mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-21 10:54:05 +00:00
Throw proper exceptions for serialize/deserialize failures
this allows them to be caught and properly reported in tests.
This commit is contained in:
parent
901a51a9dd
commit
5ce5e1d2b0
@ -188,6 +188,8 @@ final class BlockObjectToBlockStateSerializer implements BlockStateSerializer{
|
|||||||
/**
|
/**
|
||||||
* @phpstan-template TBlockType of Block
|
* @phpstan-template TBlockType of Block
|
||||||
* @phpstan-param TBlockType $blockState
|
* @phpstan-param TBlockType $blockState
|
||||||
|
*
|
||||||
|
* @throws BlockStateSerializeException
|
||||||
*/
|
*/
|
||||||
public function serializeBlock(Block $blockState) : BlockStateData{
|
public function serializeBlock(Block $blockState) : BlockStateData{
|
||||||
$typeId = $blockState->getTypeId();
|
$typeId = $blockState->getTypeId();
|
||||||
|
@ -35,7 +35,6 @@ use pocketmine\data\bedrock\EntityLegacyIds;
|
|||||||
use pocketmine\data\bedrock\item\ItemTypeIds as Ids;
|
use pocketmine\data\bedrock\item\ItemTypeIds as Ids;
|
||||||
use pocketmine\data\bedrock\item\SavedItemData as Data;
|
use pocketmine\data\bedrock\item\SavedItemData as Data;
|
||||||
use pocketmine\data\bedrock\PotionTypeIdMap;
|
use pocketmine\data\bedrock\PotionTypeIdMap;
|
||||||
use pocketmine\data\SavedDataLoadingException;
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\PotionType;
|
use pocketmine\item\PotionType;
|
||||||
use pocketmine\item\VanillaItems as Items;
|
use pocketmine\item\VanillaItems as Items;
|
||||||
@ -64,13 +63,16 @@ final class ItemDeserializer{
|
|||||||
$this->deserializers[$id] = $deserializer;
|
$this->deserializers[$id] = $deserializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws ItemTypeDeserializeException
|
||||||
|
*/
|
||||||
public function deserialize(Data $data) : Item{
|
public function deserialize(Data $data) : Item{
|
||||||
if(($blockData = $data->getBlock()) !== null){
|
if(($blockData = $data->getBlock()) !== null){
|
||||||
//TODO: this is rough duct tape; we need a better way to deal with this
|
//TODO: this is rough duct tape; we need a better way to deal with this
|
||||||
try{
|
try{
|
||||||
$block = GlobalBlockStateHandlers::getDeserializer()->deserialize($blockData);
|
$block = GlobalBlockStateHandlers::getDeserializer()->deserialize($blockData);
|
||||||
}catch(BlockStateDeserializeException $e){
|
}catch(BlockStateDeserializeException $e){
|
||||||
throw new SavedDataLoadingException("Failed to deserialize item data: " . $e->getMessage(), 0, $e);
|
throw new ItemTypeDeserializeException("Failed to deserialize item data: " . $e->getMessage(), 0, $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: worth caching this or not?
|
//TODO: worth caching this or not?
|
||||||
@ -78,7 +80,7 @@ final class ItemDeserializer{
|
|||||||
}
|
}
|
||||||
$id = $data->getName();
|
$id = $data->getName();
|
||||||
if(!isset($this->deserializers[$id])){
|
if(!isset($this->deserializers[$id])){
|
||||||
throw new SavedDataLoadingException("No deserializer found for ID $id");
|
throw new ItemTypeDeserializeException("No deserializer found for ID $id");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($this->deserializers[$id])($data);
|
return ($this->deserializers[$id])($data);
|
||||||
@ -97,7 +99,7 @@ final class ItemDeserializer{
|
|||||||
if($data->getMeta() === 0){
|
if($data->getMeta() === 0){
|
||||||
return Items::ARROW();
|
return Items::ARROW();
|
||||||
}
|
}
|
||||||
throw new SavedDataLoadingException("Tipped arrows are not implemented yet");
|
throw new ItemTypeDeserializeException("Tipped arrows are not implemented yet");
|
||||||
});
|
});
|
||||||
//TODO: minecraft:axolotl_bucket
|
//TODO: minecraft:axolotl_bucket
|
||||||
//TODO: minecraft:axolotl_spawn_egg
|
//TODO: minecraft:axolotl_spawn_egg
|
||||||
@ -107,7 +109,7 @@ final class ItemDeserializer{
|
|||||||
$meta = $data->getMeta();
|
$meta = $data->getMeta();
|
||||||
$color = DyeColorIdMap::getInstance()->fromInvertedId($meta);
|
$color = DyeColorIdMap::getInstance()->fromInvertedId($meta);
|
||||||
if($color === null){
|
if($color === null){
|
||||||
throw new SavedDataLoadingException("Unknown banner meta $meta");
|
throw new ItemTypeDeserializeException("Unknown banner meta $meta");
|
||||||
}
|
}
|
||||||
return Items::BANNER()->setColor($color);
|
return Items::BANNER()->setColor($color);
|
||||||
});
|
});
|
||||||
@ -117,7 +119,7 @@ final class ItemDeserializer{
|
|||||||
$meta = $data->getMeta();
|
$meta = $data->getMeta();
|
||||||
$color = DyeColorIdMap::getInstance()->fromId($meta);
|
$color = DyeColorIdMap::getInstance()->fromId($meta);
|
||||||
if($color === null){
|
if($color === null){
|
||||||
throw new SavedDataLoadingException("Unknown bed meta $meta");
|
throw new ItemTypeDeserializeException("Unknown bed meta $meta");
|
||||||
}
|
}
|
||||||
return Blocks::BED()->setColor($color)->asItem();
|
return Blocks::BED()->setColor($color)->asItem();
|
||||||
});
|
});
|
||||||
@ -139,7 +141,7 @@ final class ItemDeserializer{
|
|||||||
try{
|
try{
|
||||||
$treeType = TreeType::fromMagicNumber($data->getMeta());
|
$treeType = TreeType::fromMagicNumber($data->getMeta());
|
||||||
}catch(\InvalidArgumentException $e){
|
}catch(\InvalidArgumentException $e){
|
||||||
throw new SavedDataLoadingException($e->getMessage(), 0, $e);
|
throw new ItemTypeDeserializeException($e->getMessage(), 0, $e);
|
||||||
}
|
}
|
||||||
return match($treeType->id()){
|
return match($treeType->id()){
|
||||||
TreeType::OAK()->id() => Items::OAK_BOAT(),
|
TreeType::OAK()->id() => Items::OAK_BOAT(),
|
||||||
@ -229,7 +231,7 @@ final class ItemDeserializer{
|
|||||||
CompoundTypeIds::HYDROGEN_PEROXIDE => Items::CHEMICAL_HYDROGEN_PEROXIDE(),
|
CompoundTypeIds::HYDROGEN_PEROXIDE => Items::CHEMICAL_HYDROGEN_PEROXIDE(),
|
||||||
CompoundTypeIds::AMMONIA => Items::CHEMICAL_AMMONIA(),
|
CompoundTypeIds::AMMONIA => Items::CHEMICAL_AMMONIA(),
|
||||||
CompoundTypeIds::SODIUM_HYPOCHLORITE => Items::CHEMICAL_SODIUM_HYPOCHLORITE(),
|
CompoundTypeIds::SODIUM_HYPOCHLORITE => Items::CHEMICAL_SODIUM_HYPOCHLORITE(),
|
||||||
default => throw new SavedDataLoadingException("Unknown chemical meta " . $data->getMeta())
|
default => throw new ItemTypeDeserializeException("Unknown chemical meta " . $data->getMeta())
|
||||||
});
|
});
|
||||||
$this->map(Ids::COOKED_BEEF, fn() => Items::STEAK());
|
$this->map(Ids::COOKED_BEEF, fn() => Items::STEAK());
|
||||||
$this->map(Ids::COOKED_CHICKEN, fn() => Items::COOKED_CHICKEN());
|
$this->map(Ids::COOKED_CHICKEN, fn() => Items::COOKED_CHICKEN());
|
||||||
@ -284,7 +286,7 @@ final class ItemDeserializer{
|
|||||||
}
|
}
|
||||||
$dyeColor = DyeColorIdMap::getInstance()->fromInvertedId($meta);
|
$dyeColor = DyeColorIdMap::getInstance()->fromInvertedId($meta);
|
||||||
if($dyeColor === null){
|
if($dyeColor === null){
|
||||||
throw new SavedDataLoadingException("Unknown dye meta $meta");
|
throw new ItemTypeDeserializeException("Unknown dye meta $meta");
|
||||||
}
|
}
|
||||||
return match($dyeColor->id()){
|
return match($dyeColor->id()){
|
||||||
DyeColor::CYAN()->id() => Items::CYAN_DYE(),
|
DyeColor::CYAN()->id() => Items::CYAN_DYE(),
|
||||||
@ -475,7 +477,7 @@ final class ItemDeserializer{
|
|||||||
$meta = $data->getMeta();
|
$meta = $data->getMeta();
|
||||||
$potionType = PotionTypeIdMap::getInstance()->fromId($meta);
|
$potionType = PotionTypeIdMap::getInstance()->fromId($meta);
|
||||||
if($potionType === null){
|
if($potionType === null){
|
||||||
throw new SavedDataLoadingException("Unknown potion type ID $meta");
|
throw new ItemTypeDeserializeException("Unknown potion type ID $meta");
|
||||||
}
|
}
|
||||||
return match($potionType->id()){
|
return match($potionType->id()){
|
||||||
PotionType::WATER()->id() => Items::WATER_POTION(),
|
PotionType::WATER()->id() => Items::WATER_POTION(),
|
||||||
@ -520,7 +522,7 @@ final class ItemDeserializer{
|
|||||||
PotionType::STRONG_TURTLE_MASTER()->id() => Items::STRONG_TURTLE_MASTER_POTION(),
|
PotionType::STRONG_TURTLE_MASTER()->id() => Items::STRONG_TURTLE_MASTER_POTION(),
|
||||||
PotionType::SLOW_FALLING()->id() => Items::SLOW_FALLING_POTION(),
|
PotionType::SLOW_FALLING()->id() => Items::SLOW_FALLING_POTION(),
|
||||||
PotionType::LONG_SLOW_FALLING()->id() => Items::LONG_SLOW_FALLING_POTION(),
|
PotionType::LONG_SLOW_FALLING()->id() => Items::LONG_SLOW_FALLING_POTION(),
|
||||||
default => throw new SavedDataLoadingException("Unhandled potion type " . $potionType->getDisplayName())
|
default => throw new ItemTypeDeserializeException("Unhandled potion type " . $potionType->getDisplayName())
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
//TODO: minecraft:powder_snow_bucket
|
//TODO: minecraft:powder_snow_bucket
|
||||||
@ -565,7 +567,7 @@ final class ItemDeserializer{
|
|||||||
try{
|
try{
|
||||||
$skullType = SkullType::fromMagicNumber($meta);
|
$skullType = SkullType::fromMagicNumber($meta);
|
||||||
}catch(\InvalidArgumentException $e){
|
}catch(\InvalidArgumentException $e){
|
||||||
throw new SavedDataLoadingException($e->getMessage(), 0, $e);
|
throw new ItemTypeDeserializeException($e->getMessage(), 0, $e);
|
||||||
}
|
}
|
||||||
return match($skullType->id()) {
|
return match($skullType->id()) {
|
||||||
SkullType::SKELETON()->id() => Items::SKELETON_SKULL(),
|
SkullType::SKELETON()->id() => Items::SKELETON_SKULL(),
|
||||||
@ -574,7 +576,7 @@ final class ItemDeserializer{
|
|||||||
SkullType::CREEPER()->id() => Items::CREEPER_HEAD(),
|
SkullType::CREEPER()->id() => Items::CREEPER_HEAD(),
|
||||||
SkullType::PLAYER()->id() => Items::PLAYER_HEAD(),
|
SkullType::PLAYER()->id() => Items::PLAYER_HEAD(),
|
||||||
SkullType::DRAGON()->id() => Items::DRAGON_HEAD(),
|
SkullType::DRAGON()->id() => Items::DRAGON_HEAD(),
|
||||||
default => throw new SavedDataLoadingException("Unexpected skull type " . $skullType->getDisplayName())
|
default => throw new ItemTypeDeserializeException("Unexpected skull type " . $skullType->getDisplayName())
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
//TODO: minecraft:skull_banner_pattern
|
//TODO: minecraft:skull_banner_pattern
|
||||||
@ -587,7 +589,7 @@ final class ItemDeserializer{
|
|||||||
EntityLegacyIds::ZOMBIE => Items::ZOMBIE_SPAWN_EGG(),
|
EntityLegacyIds::ZOMBIE => Items::ZOMBIE_SPAWN_EGG(),
|
||||||
EntityLegacyIds::SQUID => Items::SQUID_SPAWN_EGG(),
|
EntityLegacyIds::SQUID => Items::SQUID_SPAWN_EGG(),
|
||||||
EntityLegacyIds::VILLAGER => Items::VILLAGER_SPAWN_EGG(),
|
EntityLegacyIds::VILLAGER => Items::VILLAGER_SPAWN_EGG(),
|
||||||
default => throw new SavedDataLoadingException("Unhandled spawn egg meta " . $data->getMeta())
|
default => throw new ItemTypeDeserializeException("Unhandled spawn egg meta " . $data->getMeta())
|
||||||
});
|
});
|
||||||
$this->map(Ids::SPIDER_EYE, fn() => Items::SPIDER_EYE());
|
$this->map(Ids::SPIDER_EYE, fn() => Items::SPIDER_EYE());
|
||||||
//TODO: minecraft:spider_spawn_egg
|
//TODO: minecraft:spider_spawn_egg
|
||||||
@ -595,7 +597,7 @@ final class ItemDeserializer{
|
|||||||
$meta = $data->getMeta();
|
$meta = $data->getMeta();
|
||||||
$potionType = PotionTypeIdMap::getInstance()->fromId($meta);
|
$potionType = PotionTypeIdMap::getInstance()->fromId($meta);
|
||||||
if($potionType === null){
|
if($potionType === null){
|
||||||
throw new SavedDataLoadingException("Unknown potion type ID $meta");
|
throw new ItemTypeDeserializeException("Unknown potion type ID $meta");
|
||||||
}
|
}
|
||||||
return match($potionType->id()){
|
return match($potionType->id()){
|
||||||
PotionType::WATER()->id() => Items::WATER_SPLASH_POTION(),
|
PotionType::WATER()->id() => Items::WATER_SPLASH_POTION(),
|
||||||
@ -640,7 +642,7 @@ final class ItemDeserializer{
|
|||||||
PotionType::STRONG_TURTLE_MASTER()->id() => Items::STRONG_TURTLE_MASTER_SPLASH_POTION(),
|
PotionType::STRONG_TURTLE_MASTER()->id() => Items::STRONG_TURTLE_MASTER_SPLASH_POTION(),
|
||||||
PotionType::SLOW_FALLING()->id() => Items::SLOW_FALLING_SPLASH_POTION(),
|
PotionType::SLOW_FALLING()->id() => Items::SLOW_FALLING_SPLASH_POTION(),
|
||||||
PotionType::LONG_SLOW_FALLING()->id() => Items::LONG_SLOW_FALLING_SPLASH_POTION(),
|
PotionType::LONG_SLOW_FALLING()->id() => Items::LONG_SLOW_FALLING_SPLASH_POTION(),
|
||||||
default => throw new SavedDataLoadingException("Unhandled potion type " . $potionType->getDisplayName())
|
default => throw new ItemTypeDeserializeException("Unhandled potion type " . $potionType->getDisplayName())
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
$this->map(Ids::SPRUCE_BOAT, fn() => Items::SPRUCE_BOAT());
|
$this->map(Ids::SPRUCE_BOAT, fn() => Items::SPRUCE_BOAT());
|
||||||
|
@ -27,6 +27,7 @@ use pocketmine\block\Block;
|
|||||||
use pocketmine\block\utils\DyeColor;
|
use pocketmine\block\utils\DyeColor;
|
||||||
use pocketmine\block\utils\SkullType;
|
use pocketmine\block\utils\SkullType;
|
||||||
use pocketmine\data\bedrock\BlockItemIdMap;
|
use pocketmine\data\bedrock\BlockItemIdMap;
|
||||||
|
use pocketmine\data\bedrock\blockstate\BlockStateSerializeException;
|
||||||
use pocketmine\data\bedrock\CompoundTypeIds;
|
use pocketmine\data\bedrock\CompoundTypeIds;
|
||||||
use pocketmine\data\bedrock\DyeColorIdMap;
|
use pocketmine\data\bedrock\DyeColorIdMap;
|
||||||
use pocketmine\data\bedrock\item\ItemTypeIds as Ids;
|
use pocketmine\data\bedrock\item\ItemTypeIds as Ids;
|
||||||
@ -78,6 +79,8 @@ final class ItemSerializer{
|
|||||||
/**
|
/**
|
||||||
* @phpstan-template TItemType of Item
|
* @phpstan-template TItemType of Item
|
||||||
* @phpstan-param TItemType $item
|
* @phpstan-param TItemType $item
|
||||||
|
*
|
||||||
|
* @throws ItemTypeSerializeException
|
||||||
*/
|
*/
|
||||||
public function serialize(Item $item) : Data{
|
public function serialize(Item $item) : Data{
|
||||||
if($item->isNull()){
|
if($item->isNull()){
|
||||||
@ -102,8 +105,7 @@ final class ItemSerializer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($locatedSerializer === null){
|
if($locatedSerializer === null){
|
||||||
//TODO: proper exceptions
|
throw new ItemTypeSerializeException("No serializer registered for " . get_class($item) . " " . $item->getName());
|
||||||
throw new \LogicException("No serializer registered for " . get_class($item) . " " . $item->getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,15 +121,22 @@ final class ItemSerializer{
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws ItemTypeSerializeException
|
||||||
|
*/
|
||||||
private static function standardBlock(Block $block) : Data{
|
private static function standardBlock(Block $block) : Data{
|
||||||
$blockStateData = GlobalBlockStateHandlers::getSerializer()->serialize($block->getFullId());
|
try{
|
||||||
|
$blockStateData = GlobalBlockStateHandlers::getSerializer()->serialize($block->getFullId());
|
||||||
|
}catch(BlockStateSerializeException $e){
|
||||||
|
throw new ItemTypeSerializeException($e->getMessage(), 0, $e);
|
||||||
|
}
|
||||||
|
|
||||||
$itemNameId = BlockItemIdMap::getInstance()->lookupItemId($blockStateData->getName());
|
$itemNameId = BlockItemIdMap::getInstance()->lookupItemId($blockStateData->getName());
|
||||||
if($itemNameId === null){
|
if($itemNameId === null){
|
||||||
//TODO: this might end up being a hassle for custom blocks, since it'll force providing an item
|
//TODO: this might end up being a hassle for custom blocks, since it'll force providing an item
|
||||||
//serializer for every custom block
|
//serializer for every custom block
|
||||||
//it would probably be better if we allow adding custom item <-> block ID mappings for this
|
//it would probably be better if we allow adding custom item <-> block ID mappings for this
|
||||||
throw new \LogicException("No blockitem serializer or blockitem ID mapping registered for block " . $blockStateData->getName());
|
throw new ItemTypeSerializeException("No blockitem serializer or blockitem ID mapping registered for block " . $blockStateData->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Data($itemNameId, 0, $blockStateData);
|
return new Data($itemNameId, 0, $blockStateData);
|
||||||
|
28
src/data/bedrock/item/ItemTypeDeserializeException.php
Normal file
28
src/data/bedrock/item/ItemTypeDeserializeException.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\data\bedrock\item;
|
||||||
|
|
||||||
|
final class ItemTypeDeserializeException extends \RuntimeException{
|
||||||
|
|
||||||
|
}
|
28
src/data/bedrock/item/ItemTypeSerializeException.php
Normal file
28
src/data/bedrock/item/ItemTypeSerializeException.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\data\bedrock\item;
|
||||||
|
|
||||||
|
final class ItemTypeSerializeException extends \LogicException{
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user