mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-21 08:17:34 +00:00
TypeConverter: account for items without properly mapped IDs
fixes #4459
This commit is contained in:
parent
19a66a8d03
commit
8ac16345a3
@ -142,10 +142,10 @@ final class ItemTranslator{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
* @phpstan-return array{int, int}
|
||||
* @return int[]|null
|
||||
* @phpstan-return array{int, int}|null
|
||||
*/
|
||||
public function toNetworkId(int $internalId, int $internalMeta) : array{
|
||||
public function toNetworkIdQuiet(int $internalId, int $internalMeta) : ?array{
|
||||
if($internalMeta === -1){
|
||||
$internalMeta = 0x7fff;
|
||||
}
|
||||
@ -156,7 +156,16 @@ final class ItemTranslator{
|
||||
return [$this->simpleCoreToNetMapping[$internalId], $internalMeta];
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("Unmapped ID/metadata combination $internalId:$internalMeta");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
* @phpstan-return array{int, int}
|
||||
*/
|
||||
public function toNetworkId(int $internalId, int $internalMeta) : array{
|
||||
return $this->toNetworkIdQuiet($internalId, $internalMeta) ??
|
||||
throw new \InvalidArgumentException("Unmapped ID/metadata combination $internalId:$internalMeta");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,6 +58,7 @@ class TypeConverter{
|
||||
|
||||
private const DAMAGE_TAG = "Damage"; //TAG_Int
|
||||
private const DAMAGE_TAG_CONFLICT_RESOLUTION = "___Damage_ProtocolCollisionResolution___";
|
||||
private const PM_ID_TAG = "___Id___";
|
||||
private const PM_META_TAG = "___Meta___";
|
||||
|
||||
/** @var int */
|
||||
@ -143,26 +144,40 @@ class TypeConverter{
|
||||
}
|
||||
|
||||
$isBlockItem = $itemStack->getId() < 256;
|
||||
if($itemStack instanceof Durable and $itemStack->getDamage() > 0){
|
||||
if($nbt !== null){
|
||||
if(($existing = $nbt->getTag(self::DAMAGE_TAG)) !== null){
|
||||
$nbt->removeTag(self::DAMAGE_TAG);
|
||||
$nbt->setTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION, $existing);
|
||||
}
|
||||
}else{
|
||||
$nbt = new CompoundTag();
|
||||
}
|
||||
$nbt->setInt(self::DAMAGE_TAG, $itemStack->getDamage());
|
||||
}elseif($isBlockItem && $itemStack->getMeta() !== 0){
|
||||
//TODO HACK: This foul-smelling code ensures that we can correctly deserialize an item when the
|
||||
//client sends it back to us, because as of 1.16.220, blockitems quietly discard their metadata
|
||||
//client-side. Aside from being very annoying, this also breaks various server-side behaviours.
|
||||
|
||||
$idMeta = ItemTranslator::getInstance()->toNetworkIdQuiet($itemStack->getId(), $itemStack->getMeta());
|
||||
if($idMeta === null){
|
||||
//Display unmapped items as INFO_UPDATE, but stick something in their NBT to make sure they don't stack with
|
||||
//other unmapped items.
|
||||
[$id, $meta] = ItemTranslator::getInstance()->toNetworkId(ItemIds::INFO_UPDATE, 0);
|
||||
if($nbt === null){
|
||||
$nbt = new CompoundTag();
|
||||
}
|
||||
$nbt->setInt(self::PM_ID_TAG, $itemStack->getId());
|
||||
$nbt->setInt(self::PM_META_TAG, $itemStack->getMeta());
|
||||
}else{
|
||||
[$id, $meta] = $idMeta;
|
||||
|
||||
if($itemStack instanceof Durable and $itemStack->getDamage() > 0){
|
||||
if($nbt !== null){
|
||||
if(($existing = $nbt->getTag(self::DAMAGE_TAG)) !== null){
|
||||
$nbt->removeTag(self::DAMAGE_TAG);
|
||||
$nbt->setTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION, $existing);
|
||||
}
|
||||
}else{
|
||||
$nbt = new CompoundTag();
|
||||
}
|
||||
$nbt->setInt(self::DAMAGE_TAG, $itemStack->getDamage());
|
||||
}elseif($isBlockItem && $itemStack->getMeta() !== 0){
|
||||
//TODO HACK: This foul-smelling code ensures that we can correctly deserialize an item when the
|
||||
//client sends it back to us, because as of 1.16.220, blockitems quietly discard their metadata
|
||||
//client-side. Aside from being very annoying, this also breaks various server-side behaviours.
|
||||
if($nbt === null){
|
||||
$nbt = new CompoundTag();
|
||||
}
|
||||
$nbt->setInt(self::PM_META_TAG, $itemStack->getMeta());
|
||||
}
|
||||
}
|
||||
[$id, $meta] = ItemTranslator::getInstance()->toNetworkId($itemStack->getId(), $itemStack->getMeta());
|
||||
|
||||
$blockRuntimeId = 0;
|
||||
if($isBlockItem){
|
||||
@ -197,6 +212,13 @@ class TypeConverter{
|
||||
|
||||
if($compound !== null){
|
||||
$compound = clone $compound;
|
||||
if(($idTag = $compound->getTag(self::PM_ID_TAG)) instanceof IntTag){
|
||||
$id = $idTag->getValue();
|
||||
$compound->removeTag(self::PM_ID_TAG);
|
||||
if($compound->count() === 0){
|
||||
$compound = null;
|
||||
}
|
||||
}
|
||||
if(($damageTag = $compound->getTag(self::DAMAGE_TAG)) instanceof IntTag){
|
||||
$meta = $damageTag->getValue();
|
||||
$compound->removeTag(self::DAMAGE_TAG);
|
||||
|
Loading…
x
Reference in New Issue
Block a user