ItemFactory::get() now consistently throws SavedDataLoadingException on any error, including unknown items

This commit is contained in:
Dylan K. Taylor
2022-06-27 17:14:43 +01:00
parent 2fd9b751b6
commit 541a624d48
7 changed files with 69 additions and 68 deletions

View File

@@ -38,7 +38,6 @@ use pocketmine\item\enchantment\EnchantmentInstance;
use pocketmine\math\Vector3;
use pocketmine\nbt\LittleEndianNbtSerializer;
use pocketmine\nbt\NBT;
use pocketmine\nbt\NbtDataException;
use pocketmine\nbt\NbtException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag;
@@ -606,8 +605,7 @@ class Item implements \JsonSerializable{
* Returns an Item from properties created in an array by {@link Item#jsonSerialize}
* @param mixed[] $data
*
* @throws NbtDataException
* @throws \InvalidArgumentException
* @throws SavedDataLoadingException
*/
final public static function jsonDeserialize(array $data) : Item{
$nbt = "";

View File

@@ -36,6 +36,7 @@ use pocketmine\data\bedrock\CompoundTypeIds;
use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\data\bedrock\EntityLegacyIds;
use pocketmine\data\bedrock\PotionTypeIdMap;
use pocketmine\data\SavedDataLoadingException;
use pocketmine\entity\Entity;
use pocketmine\entity\Location;
use pocketmine\entity\Squid;
@@ -50,6 +51,7 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\utils\SingletonTrait;
use pocketmine\world\format\io\GlobalBlockStateHandlers;
use pocketmine\world\World;
use function min;
/**
* Manages deserializing item types from their legacy ID/metadata.
@@ -451,26 +453,24 @@ class ItemFactory{
*
* Deserializes an item from the provided legacy ID, legacy meta, count and NBT.
*
* @throws \InvalidArgumentException
* @throws NbtException
* @throws SavedDataLoadingException
*/
public function get(int $id, int $meta = 0, int $count = 1, ?CompoundTag $tags = null) : Item{
/** @var Item|null $item */
$item = null;
if($id < -0x8000 || $id > 0x7fff){
throw new SavedDataLoadingException("Legacy ID must be in the range " . -0x8000 . " ... " . 0x7fff);
}
if($meta < 0 || $meta > 0x7ffe){ //0x7fff would cause problems with recipe wildcards
throw new \InvalidArgumentException("Meta cannot be negative or larger than " . 0x7ffe);
throw new SavedDataLoadingException("Meta cannot be negative or larger than " . 0x7ffe);
}
if(isset($this->list[$offset = self::getListOffset($id, $meta)])){
$item = clone $this->list[$offset];
}elseif(isset($this->list[$zero = self::getListOffset($id, 0)]) && $this->list[$zero] instanceof Durable){
if($meta <= $this->list[$zero]->getMaxDurability()){
$item = clone $this->list[$zero];
$item->setDamage($meta);
}else{
$item = new Item(new IID($id, $meta));
}
$item = clone $this->list[$zero];
$item->setDamage(min($meta, $this->list[$zero]->getMaxDurability()));
}elseif($id < 256){ //intentionally includes negatives, for extended block IDs
//TODO: do not assume that item IDs and block IDs are the same or related
$blockStateData = GlobalBlockStateHandlers::getUpgrader()->upgradeIntIdMeta(self::itemToBlockId($id), $meta & 0xf);
@@ -479,20 +479,22 @@ class ItemFactory{
$blockStateId = GlobalBlockStateHandlers::getDeserializer()->deserialize($blockStateData);
$item = new ItemBlock(new IID($id, $meta), BlockFactory::getInstance()->fromFullBlock($blockStateId));
}catch(BlockStateDeserializeException $e){
\GlobalLogger::get()->logException($e);
//fallthru
throw new SavedDataLoadingException("Failed to deserialize itemblock: " . $e->getMessage(), 0, $e);
}
}
}
if($item === null){
//negative damage values will fallthru to here, to avoid crazy shit with crafting wildcard hacks
$item = new Item(new IID($id, $meta));
throw new SavedDataLoadingException("No registered item is associated with this ID and meta");
}
$item->setCount($count);
if($tags !== null){
$item->setNamedTag($tags);
try{
$item->setNamedTag($tags);
}catch(NbtException $e){
throw new SavedDataLoadingException("Invalid item NBT: " . $e->getMessage(), 0, $e);
}
}
return $item;
}

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\data\SavedDataLoadingException;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\SingletonTrait;
use pocketmine\utils\Utils;
@@ -104,15 +105,16 @@ final class LegacyStringToItemParser{
$meta = 0;
}elseif(is_numeric($b[1])){
$meta = (int) $b[1];
if($meta < 0 || $meta > 0x7ffe){
throw new LegacyStringToItemParserException("Meta value $meta is outside the range 0 - " . 0x7ffe);
}
}else{
throw new LegacyStringToItemParserException("Unable to parse \"" . $b[1] . "\" from \"" . $input . "\" as a valid meta value");
}
if(isset($this->map[strtolower($b[0])])){
$item = $this->itemFactory->get($this->map[strtolower($b[0])], $meta);
try{
$item = $this->itemFactory->get($this->map[strtolower($b[0])], $meta);
}catch(SavedDataLoadingException $e){
throw new LegacyStringToItemParserException($e->getMessage(), 0, $e);
}
}else{
throw new LegacyStringToItemParserException("Unable to resolve \"" . $input . "\" to a valid item");
}