mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-13 05:15:13 +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[]
|
* @return int[]|null
|
||||||
* @phpstan-return array{int, int}
|
* @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){
|
if($internalMeta === -1){
|
||||||
$internalMeta = 0x7fff;
|
$internalMeta = 0x7fff;
|
||||||
}
|
}
|
||||||
@ -156,7 +156,16 @@ final class ItemTranslator{
|
|||||||
return [$this->simpleCoreToNetMapping[$internalId], $internalMeta];
|
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 = "Damage"; //TAG_Int
|
||||||
private const DAMAGE_TAG_CONFLICT_RESOLUTION = "___Damage_ProtocolCollisionResolution___";
|
private const DAMAGE_TAG_CONFLICT_RESOLUTION = "___Damage_ProtocolCollisionResolution___";
|
||||||
|
private const PM_ID_TAG = "___Id___";
|
||||||
private const PM_META_TAG = "___Meta___";
|
private const PM_META_TAG = "___Meta___";
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
@ -143,26 +144,40 @@ class TypeConverter{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$isBlockItem = $itemStack->getId() < 256;
|
$isBlockItem = $itemStack->getId() < 256;
|
||||||
if($itemStack instanceof Durable and $itemStack->getDamage() > 0){
|
|
||||||
if($nbt !== null){
|
$idMeta = ItemTranslator::getInstance()->toNetworkIdQuiet($itemStack->getId(), $itemStack->getMeta());
|
||||||
if(($existing = $nbt->getTag(self::DAMAGE_TAG)) !== null){
|
if($idMeta === null){
|
||||||
$nbt->removeTag(self::DAMAGE_TAG);
|
//Display unmapped items as INFO_UPDATE, but stick something in their NBT to make sure they don't stack with
|
||||||
$nbt->setTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION, $existing);
|
//other unmapped items.
|
||||||
}
|
[$id, $meta] = ItemTranslator::getInstance()->toNetworkId(ItemIds::INFO_UPDATE, 0);
|
||||||
}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){
|
if($nbt === null){
|
||||||
$nbt = new CompoundTag();
|
$nbt = new CompoundTag();
|
||||||
}
|
}
|
||||||
|
$nbt->setInt(self::PM_ID_TAG, $itemStack->getId());
|
||||||
$nbt->setInt(self::PM_META_TAG, $itemStack->getMeta());
|
$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;
|
$blockRuntimeId = 0;
|
||||||
if($isBlockItem){
|
if($isBlockItem){
|
||||||
@ -197,6 +212,13 @@ class TypeConverter{
|
|||||||
|
|
||||||
if($compound !== null){
|
if($compound !== null){
|
||||||
$compound = clone $compound;
|
$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){
|
if(($damageTag = $compound->getTag(self::DAMAGE_TAG)) instanceof IntTag){
|
||||||
$meta = $damageTag->getValue();
|
$meta = $damageTag->getValue();
|
||||||
$compound->removeTag(self::DAMAGE_TAG);
|
$compound->removeTag(self::DAMAGE_TAG);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user