diff --git a/src/Server.php b/src/Server.php index 546212c8a..a2ae65ef5 100644 --- a/src/Server.php +++ b/src/Server.php @@ -557,7 +557,7 @@ class Server{ $ev->call(); $class = $ev->getPlayerClass(); - if($offlinePlayerData !== null && ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString("Level", ""))) !== null){ + if($offlinePlayerData !== null && ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString(Player::TAG_LEVEL, ""))) !== null){ $playerPos = EntityDataHelper::parseLocation($offlinePlayerData, $world); $spawn = $playerPos->asVector3(); }else{ diff --git a/src/block/tile/ContainerTrait.php b/src/block/tile/ContainerTrait.php index 199d4859a..fdd050a41 100644 --- a/src/block/tile/ContainerTrait.php +++ b/src/block/tile/ContainerTrait.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace pocketmine\block\tile; +use pocketmine\data\bedrock\item\SavedItemStackData; use pocketmine\data\SavedDataLoadingException; use pocketmine\inventory\Inventory; use pocketmine\item\Item; @@ -51,7 +52,7 @@ trait ContainerTrait{ /** @var CompoundTag $itemNBT */ foreach($inventoryTag as $itemNBT){ try{ - $newContents[$itemNBT->getByte("Slot")] = Item::nbtDeserialize($itemNBT); + $newContents[$itemNBT->getByte(SavedItemStackData::TAG_SLOT)] = Item::nbtDeserialize($itemNBT); }catch(SavedDataLoadingException $e){ //TODO: not the best solution \GlobalLogger::get()->logException($e); diff --git a/src/entity/Entity.php b/src/entity/Entity.php index a8c7edd02..1397ee3a1 100644 --- a/src/entity/Entity.php +++ b/src/entity/Entity.php @@ -81,6 +81,15 @@ abstract class Entity{ public const MOTION_THRESHOLD = 0.00001; protected const STEP_CLIP_MULTIPLIER = 0.4; + private const TAG_FIRE = "Fire"; //TAG_Short + private const TAG_ON_GROUND = "OnGround"; //TAG_Byte + private const TAG_FALL_DISTANCE = "FallDistance"; //TAG_Float + private const TAG_CUSTOM_NAME = "CustomName"; //TAG_String + private const TAG_CUSTOM_NAME_VISIBLE = "CustomNameVisible"; //TAG_Byte + public const TAG_POS = "Pos"; //TAG_List|TAG_List + public const TAG_MOTION = "Motion"; //TAG_List|TAG_List + public const TAG_ROTATION = "Rotation"; //TAG_List + private static int $entityCount = 1; /** @@ -189,7 +198,7 @@ abstract class Entity{ $this->recalculateBoundingBox(); if($nbt !== null){ - $this->motion = EntityDataHelper::parseVec3($nbt, "Motion", true); + $this->motion = EntityDataHelper::parseVec3($nbt, self::TAG_MOTION, true); }else{ $this->motion = new Vector3(0, 0, 0); } @@ -437,17 +446,17 @@ abstract class Entity{ public function saveNBT() : CompoundTag{ $nbt = CompoundTag::create() - ->setTag("Pos", new ListTag([ + ->setTag(self::TAG_POS, new ListTag([ new DoubleTag($this->location->x), new DoubleTag($this->location->y), new DoubleTag($this->location->z) ])) - ->setTag("Motion", new ListTag([ + ->setTag(self::TAG_MOTION, new ListTag([ new DoubleTag($this->motion->x), new DoubleTag($this->motion->y), new DoubleTag($this->motion->z) ])) - ->setTag("Rotation", new ListTag([ + ->setTag(self::TAG_ROTATION, new ListTag([ new FloatTag($this->location->yaw), new FloatTag($this->location->pitch) ])); @@ -456,33 +465,33 @@ abstract class Entity{ EntityFactory::getInstance()->injectSaveId(get_class($this), $nbt); if($this->getNameTag() !== ""){ - $nbt->setString("CustomName", $this->getNameTag()); - $nbt->setByte("CustomNameVisible", $this->isNameTagVisible() ? 1 : 0); + $nbt->setString(self::TAG_CUSTOM_NAME, $this->getNameTag()); + $nbt->setByte(self::TAG_CUSTOM_NAME_VISIBLE, $this->isNameTagVisible() ? 1 : 0); } } - $nbt->setFloat("FallDistance", $this->fallDistance); - $nbt->setShort("Fire", $this->fireTicks); - $nbt->setByte("OnGround", $this->onGround ? 1 : 0); + $nbt->setFloat(self::TAG_FALL_DISTANCE, $this->fallDistance); + $nbt->setShort(self::TAG_FIRE, $this->fireTicks); + $nbt->setByte(self::TAG_ON_GROUND, $this->onGround ? 1 : 0); return $nbt; } protected function initEntity(CompoundTag $nbt) : void{ - $this->fireTicks = $nbt->getShort("Fire", 0); + $this->fireTicks = $nbt->getShort(self::TAG_FIRE, 0); - $this->onGround = $nbt->getByte("OnGround", 0) !== 0; + $this->onGround = $nbt->getByte(self::TAG_ON_GROUND, 0) !== 0; - $this->fallDistance = $nbt->getFloat("FallDistance", 0.0); + $this->fallDistance = $nbt->getFloat(self::TAG_FALL_DISTANCE, 0.0); - if(($customNameTag = $nbt->getTag("CustomName")) instanceof StringTag){ + if(($customNameTag = $nbt->getTag(self::TAG_CUSTOM_NAME)) instanceof StringTag){ $this->setNameTag($customNameTag->getValue()); - if(($customNameVisibleTag = $nbt->getTag("CustomNameVisible")) instanceof StringTag){ + if(($customNameVisibleTag = $nbt->getTag(self::TAG_CUSTOM_NAME_VISIBLE)) instanceof StringTag){ //Older versions incorrectly saved this as a string (see 890f72dbf23a77f294169b79590770470041adc4) $this->setNameTagVisible($customNameVisibleTag->getValue() !== ""); }else{ - $this->setNameTagVisible($nbt->getByte("CustomNameVisible", 1) !== 0); + $this->setNameTagVisible($nbt->getByte(self::TAG_CUSTOM_NAME_VISIBLE, 1) !== 0); } } } diff --git a/src/entity/EntityDataHelper.php b/src/entity/EntityDataHelper.php index 90e5e7733..1a15d7458 100644 --- a/src/entity/EntityDataHelper.php +++ b/src/entity/EntityDataHelper.php @@ -57,19 +57,19 @@ final class EntityDataHelper{ * @throws SavedDataLoadingException */ public static function parseLocation(CompoundTag $nbt, World $world) : Location{ - $pos = self::parseVec3($nbt, "Pos", false); + $pos = self::parseVec3($nbt, Entity::TAG_POS, false); - $yawPitch = $nbt->getTag("Rotation"); + $yawPitch = $nbt->getTag(Entity::TAG_ROTATION); if(!($yawPitch instanceof ListTag) || $yawPitch->getTagType() !== NBT::TAG_Float){ - throw new SavedDataLoadingException("'Rotation' should be a List"); + throw new SavedDataLoadingException("'" . Entity::TAG_ROTATION . "' should be a List"); } /** @var FloatTag[] $values */ $values = $yawPitch->getValue(); if(count($values) !== 2){ throw new SavedDataLoadingException("Expected exactly 2 entries for 'Rotation'"); } - self::validateFloat("Rotation", "yaw", $values[0]->getValue()); - self::validateFloat("Rotation", "pitch", $values[1]->getValue()); + self::validateFloat(Entity::TAG_ROTATION, "yaw", $values[0]->getValue()); + self::validateFloat(Entity::TAG_ROTATION, "pitch", $values[1]->getValue()); return Location::fromObject($pos, $world, $values[0]->getValue(), $values[1]->getValue()); } diff --git a/src/entity/EntityFactory.php b/src/entity/EntityFactory.php index fb3a1f33d..e69cfd643 100644 --- a/src/entity/EntityFactory.php +++ b/src/entity/EntityFactory.php @@ -66,6 +66,9 @@ use function reset; final class EntityFactory{ use SingletonTrait; + public const TAG_IDENTIFIER = "identifier"; //TAG_String + public const TAG_LEGACY_ID = "id"; //TAG_Int + /** * @var \Closure[] save ID => creator function * @phpstan-var array @@ -113,9 +116,9 @@ final class EntityFactory{ }, ['FallingSand', 'minecraft:falling_block'], LegacyIds::FALLING_BLOCK); $this->register(ItemEntity::class, function(World $world, CompoundTag $nbt) : ItemEntity{ - $itemTag = $nbt->getCompoundTag("Item"); + $itemTag = $nbt->getCompoundTag(ItemEntity::TAG_ITEM); if($itemTag === null){ - throw new SavedDataLoadingException("Expected \"Item\" NBT tag not found"); + throw new SavedDataLoadingException("Expected \"" . ItemEntity::TAG_ITEM . "\" NBT tag not found"); } $item = Item::nbtDeserialize($itemTag); @@ -126,14 +129,14 @@ final class EntityFactory{ }, ['Item', 'minecraft:item'], LegacyIds::ITEM); $this->register(Painting::class, function(World $world, CompoundTag $nbt) : Painting{ - $motive = PaintingMotive::getMotiveByName($nbt->getString("Motive")); + $motive = PaintingMotive::getMotiveByName($nbt->getString(Painting::TAG_MOTIVE)); if($motive === null){ throw new SavedDataLoadingException("Unknown painting motive"); } - $blockIn = new Vector3($nbt->getInt("TileX"), $nbt->getInt("TileY"), $nbt->getInt("TileZ")); - if(($directionTag = $nbt->getTag("Direction")) instanceof ByteTag){ + $blockIn = new Vector3($nbt->getInt(Painting::TAG_TILE_X), $nbt->getInt(Painting::TAG_TILE_Y), $nbt->getInt(Painting::TAG_TILE_Z)); + if(($directionTag = $nbt->getTag(Painting::TAG_DIRECTION_BE)) instanceof ByteTag){ $facing = Painting::DATA_TO_FACING[$directionTag->getValue()] ?? Facing::NORTH; - }elseif(($facingTag = $nbt->getTag("Facing")) instanceof ByteTag){ + }elseif(($facingTag = $nbt->getTag(Painting::TAG_FACING_JE)) instanceof ByteTag){ $facing = Painting::DATA_TO_FACING[$facingTag->getValue()] ?? Facing::NORTH; }else{ throw new SavedDataLoadingException("Missing facing info"); @@ -217,7 +220,7 @@ final class EntityFactory{ */ public function createFromData(World $world, CompoundTag $nbt) : ?Entity{ try{ - $saveId = $nbt->getTag("identifier") ?? $nbt->getTag("id"); + $saveId = $nbt->getTag(self::TAG_IDENTIFIER) ?? $nbt->getTag(self::TAG_LEGACY_ID); $func = null; if($saveId instanceof StringTag){ $func = $this->creationFuncs[$saveId->getValue()] ?? null; @@ -238,7 +241,7 @@ final class EntityFactory{ public function injectSaveId(string $class, CompoundTag $saveData) : void{ if(isset($this->saveNames[$class])){ - $saveData->setTag("identifier", new StringTag($this->saveNames[$class])); + $saveData->setTag(self::TAG_IDENTIFIER, new StringTag($this->saveNames[$class])); }else{ throw new \InvalidArgumentException("Entity $class is not registered"); } diff --git a/src/entity/Human.php b/src/entity/Human.php index bf68ebce2..9630f1128 100644 --- a/src/entity/Human.php +++ b/src/entity/Human.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace pocketmine\entity; +use pocketmine\data\bedrock\item\SavedItemStackData; use pocketmine\data\SavedDataLoadingException; use pocketmine\entity\animation\TotemUseAnimation; use pocketmine\entity\effect\EffectInstance; @@ -77,6 +78,26 @@ use function random_int; class Human extends Living implements ProjectileSource, InventoryHolder{ + private const TAG_INVENTORY = "Inventory"; //TAG_List + private const TAG_OFF_HAND_ITEM = "OffHandItem"; //TAG_Compound + private const TAG_ENDER_CHEST_INVENTORY = "EnderChestInventory"; //TAG_List + private const TAG_SELECTED_INVENTORY_SLOT = "SelectedInventorySlot"; //TAG_Int + private const TAG_FOOD_LEVEL = "foodLevel"; //TAG_Int + private const TAG_FOOD_EXHAUSTION_LEVEL = "foodExhaustionLevel"; //TAG_Float + private const TAG_FOOD_SATURATION_LEVEL = "foodSaturationLevel"; //TAG_Float + private const TAG_FOOD_TICK_TIMER = "foodTickTimer"; //TAG_Int + private const TAG_XP_LEVEL = "XpLevel"; //TAG_Int + private const TAG_XP_PROGRESS = "XpP"; //TAG_Float + private const TAG_LIFETIME_XP_TOTAL = "XpTotal"; //TAG_Int + private const TAG_XP_SEED = "XpSeed"; //TAG_Int + private const TAG_NAME_TAG = "NameTag"; //TAG_String + private const TAG_SKIN = "Skin"; //TAG_Compound + private const TAG_SKIN_NAME = "Name"; //TAG_String + private const TAG_SKIN_DATA = "Data"; //TAG_ByteArray + private const TAG_SKIN_CAPE_DATA = "CapeData"; //TAG_ByteArray + private const TAG_SKIN_GEOMETRY_NAME = "GeometryName"; //TAG_String + private const TAG_SKIN_GEOMETRY_DATA = "GeometryData"; //TAG_ByteArray + public static function getNetworkTypeId() : string{ return EntityIds::PLAYER; } protected PlayerInventory $inventory; @@ -104,16 +125,16 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ * @throws SavedDataLoadingException */ public static function parseSkinNBT(CompoundTag $nbt) : Skin{ - $skinTag = $nbt->getCompoundTag("Skin"); + $skinTag = $nbt->getCompoundTag(self::TAG_SKIN); if($skinTag === null){ throw new SavedDataLoadingException("Missing skin data"); } return new Skin( //this throws if the skin is invalid - $skinTag->getString("Name"), - ($skinDataTag = $skinTag->getTag("Data")) instanceof StringTag ? $skinDataTag->getValue() : $skinTag->getByteArray("Data"), //old data (this used to be saved as a StringTag in older versions of PM) - $skinTag->getByteArray("CapeData", ""), - $skinTag->getString("GeometryName", ""), - $skinTag->getByteArray("GeometryData", "") + $skinTag->getString(self::TAG_SKIN_NAME), + ($skinDataTag = $skinTag->getTag(self::TAG_SKIN_DATA)) instanceof StringTag ? $skinDataTag->getValue() : $skinTag->getByteArray(self::TAG_SKIN_DATA), //old data (this used to be saved as a StringTag in older versions of PM) + $skinTag->getByteArray(self::TAG_SKIN_CAPE_DATA, ""), + $skinTag->getString(self::TAG_SKIN_GEOMETRY_NAME, ""), + $skinTag->getByteArray(self::TAG_SKIN_GEOMETRY_DATA, "") ); } @@ -208,7 +229,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ * For Human entities which are not players, sets their properties such as nametag, skin and UUID from NBT. */ protected function initHumanData(CompoundTag $nbt) : void{ - if(($nameTagTag = $nbt->getTag("NameTag")) instanceof StringTag){ + if(($nameTagTag = $nbt->getTag(self::TAG_NAME_TAG)) instanceof StringTag){ $this->setNameTag($nameTagTag->getValue()); } @@ -257,14 +278,14 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ $this->enderInventory = new PlayerEnderInventory($this); $this->initHumanData($nbt); - $inventoryTag = $nbt->getListTag("Inventory"); + $inventoryTag = $nbt->getListTag(self::TAG_INVENTORY); if($inventoryTag !== null){ $inventoryItems = []; $armorInventoryItems = []; /** @var CompoundTag $item */ foreach($inventoryTag as $i => $item){ - $slot = $item->getByte("Slot"); + $slot = $item->getByte(SavedItemStackData::TAG_SLOT); if($slot >= 0 && $slot < 9){ //Hotbar //Old hotbar saving stuff, ignore it }elseif($slot >= 100 && $slot < 104){ //Armor @@ -277,7 +298,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ self::populateInventoryFromListTag($this->inventory, $inventoryItems); self::populateInventoryFromListTag($this->armorInventory, $armorInventoryItems); } - $offHand = $nbt->getCompoundTag("OffHandItem"); + $offHand = $nbt->getCompoundTag(self::TAG_OFF_HAND_ITEM); if($offHand !== null){ $this->offHandInventory->setItem(0, Item::nbtDeserialize($offHand)); } @@ -287,35 +308,35 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ } })); - $enderChestInventoryTag = $nbt->getListTag("EnderChestInventory"); + $enderChestInventoryTag = $nbt->getListTag(self::TAG_ENDER_CHEST_INVENTORY); if($enderChestInventoryTag !== null){ $enderChestInventoryItems = []; /** @var CompoundTag $item */ foreach($enderChestInventoryTag as $i => $item){ - $enderChestInventoryItems[$item->getByte("Slot")] = Item::nbtDeserialize($item); + $enderChestInventoryItems[$item->getByte(SavedItemStackData::TAG_SLOT)] = Item::nbtDeserialize($item); } self::populateInventoryFromListTag($this->enderInventory, $enderChestInventoryItems); } - $this->inventory->setHeldItemIndex($nbt->getInt("SelectedInventorySlot", 0)); + $this->inventory->setHeldItemIndex($nbt->getInt(self::TAG_SELECTED_INVENTORY_SLOT, 0)); $this->inventory->getHeldItemIndexChangeListeners()->add(function(int $oldIndex) : void{ foreach($this->getViewers() as $viewer){ $viewer->getNetworkSession()->onMobMainHandItemChange($this); } }); - $this->hungerManager->setFood((float) $nbt->getInt("foodLevel", (int) $this->hungerManager->getFood())); - $this->hungerManager->setExhaustion($nbt->getFloat("foodExhaustionLevel", $this->hungerManager->getExhaustion())); - $this->hungerManager->setSaturation($nbt->getFloat("foodSaturationLevel", $this->hungerManager->getSaturation())); - $this->hungerManager->setFoodTickTimer($nbt->getInt("foodTickTimer", $this->hungerManager->getFoodTickTimer())); + $this->hungerManager->setFood((float) $nbt->getInt(self::TAG_FOOD_LEVEL, (int) $this->hungerManager->getFood())); + $this->hungerManager->setExhaustion($nbt->getFloat(self::TAG_FOOD_EXHAUSTION_LEVEL, $this->hungerManager->getExhaustion())); + $this->hungerManager->setSaturation($nbt->getFloat(self::TAG_FOOD_SATURATION_LEVEL, $this->hungerManager->getSaturation())); + $this->hungerManager->setFoodTickTimer($nbt->getInt(self::TAG_FOOD_TICK_TIMER, $this->hungerManager->getFoodTickTimer())); $this->xpManager->setXpAndProgressNoEvent( - $nbt->getInt("XpLevel", 0), - $nbt->getFloat("XpP", 0.0)); - $this->xpManager->setLifetimeTotalXp($nbt->getInt("XpTotal", 0)); + $nbt->getInt(self::TAG_XP_LEVEL, 0), + $nbt->getFloat(self::TAG_XP_PROGRESS, 0.0)); + $this->xpManager->setLifetimeTotalXp($nbt->getInt(self::TAG_LIFETIME_XP_TOTAL, 0)); - if(($xpSeedTag = $nbt->getTag("XpSeed")) instanceof IntTag){ + if(($xpSeedTag = $nbt->getTag(self::TAG_XP_SEED)) instanceof IntTag){ $this->xpSeed = $xpSeedTag->getValue(); }else{ $this->xpSeed = random_int(Limits::INT32_MIN, Limits::INT32_MAX); @@ -384,18 +405,18 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ public function saveNBT() : CompoundTag{ $nbt = parent::saveNBT(); - $nbt->setInt("foodLevel", (int) $this->hungerManager->getFood()); - $nbt->setFloat("foodExhaustionLevel", $this->hungerManager->getExhaustion()); - $nbt->setFloat("foodSaturationLevel", $this->hungerManager->getSaturation()); - $nbt->setInt("foodTickTimer", $this->hungerManager->getFoodTickTimer()); + $nbt->setInt(self::TAG_FOOD_LEVEL, (int) $this->hungerManager->getFood()); + $nbt->setFloat(self::TAG_FOOD_EXHAUSTION_LEVEL, $this->hungerManager->getExhaustion()); + $nbt->setFloat(self::TAG_FOOD_SATURATION_LEVEL, $this->hungerManager->getSaturation()); + $nbt->setInt(self::TAG_FOOD_TICK_TIMER, $this->hungerManager->getFoodTickTimer()); - $nbt->setInt("XpLevel", $this->xpManager->getXpLevel()); - $nbt->setFloat("XpP", $this->xpManager->getXpProgress()); - $nbt->setInt("XpTotal", $this->xpManager->getLifetimeTotalXp()); - $nbt->setInt("XpSeed", $this->xpSeed); + $nbt->setInt(self::TAG_XP_LEVEL, $this->xpManager->getXpLevel()); + $nbt->setFloat(self::TAG_XP_PROGRESS, $this->xpManager->getXpProgress()); + $nbt->setInt(self::TAG_LIFETIME_XP_TOTAL, $this->xpManager->getLifetimeTotalXp()); + $nbt->setInt(self::TAG_XP_SEED, $this->xpSeed); $inventoryTag = new ListTag([], NBT::TAG_Compound); - $nbt->setTag("Inventory", $inventoryTag); + $nbt->setTag(self::TAG_INVENTORY, $inventoryTag); //Normal inventory $slotCount = $this->inventory->getSize() + $this->inventory->getHotbarSize(); @@ -414,11 +435,11 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ } } - $nbt->setInt("SelectedInventorySlot", $this->inventory->getHeldItemIndex()); + $nbt->setInt(self::TAG_SELECTED_INVENTORY_SLOT, $this->inventory->getHeldItemIndex()); $offHandItem = $this->offHandInventory->getItem(0); if(!$offHandItem->isNull()){ - $nbt->setTag("OffHandItem", $offHandItem->nbtSerialize()); + $nbt->setTag(self::TAG_OFF_HAND_ITEM, $offHandItem->nbtSerialize()); } /** @var CompoundTag[] $items */ @@ -432,14 +453,14 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ } } - $nbt->setTag("EnderChestInventory", new ListTag($items, NBT::TAG_Compound)); + $nbt->setTag(self::TAG_ENDER_CHEST_INVENTORY, new ListTag($items, NBT::TAG_Compound)); - $nbt->setTag("Skin", CompoundTag::create() - ->setString("Name", $this->skin->getSkinId()) - ->setByteArray("Data", $this->skin->getSkinData()) - ->setByteArray("CapeData", $this->skin->getCapeData()) - ->setString("GeometryName", $this->skin->getGeometryName()) - ->setByteArray("GeometryData", $this->skin->getGeometryData()) + $nbt->setTag(self::TAG_SKIN, CompoundTag::create() + ->setString(self::TAG_SKIN_NAME, $this->skin->getSkinId()) + ->setByteArray(self::TAG_SKIN_DATA, $this->skin->getSkinData()) + ->setByteArray(self::TAG_SKIN_CAPE_DATA, $this->skin->getCapeData()) + ->setString(self::TAG_SKIN_GEOMETRY_NAME, $this->skin->getGeometryName()) + ->setByteArray(self::TAG_SKIN_GEOMETRY_DATA, $this->skin->getGeometryData()) ); return $nbt; diff --git a/src/entity/Living.php b/src/entity/Living.php index 711c343bf..34a297578 100644 --- a/src/entity/Living.php +++ b/src/entity/Living.php @@ -77,6 +77,16 @@ use const M_PI; abstract class Living extends Entity{ protected const DEFAULT_BREATH_TICKS = 300; + private const TAG_LEGACY_HEALTH = "HealF"; //TAG_Float + private const TAG_HEALTH = "Health"; //TAG_Float + private const TAG_BREATH_TICKS = "Air"; //TAG_Short + private const TAG_ACTIVE_EFFECTS = "ActiveEffects"; //TAG_List + private const TAG_EFFECT_ID = "Id"; //TAG_Byte + private const TAG_EFFECT_DURATION = "Duration"; //TAG_Int + private const TAG_EFFECT_AMPLIFIER = "Amplifier"; //TAG_Byte + private const TAG_EFFECT_SHOW_PARTICLES = "ShowParticles"; //TAG_Byte + private const TAG_EFFECT_AMBIENT = "Ambient"; //TAG_Byte + protected int $attackTime = 0; public int $deadTicks = 0; @@ -127,9 +137,9 @@ abstract class Living extends Entity{ $health = $this->getMaxHealth(); - if(($healFTag = $nbt->getTag("HealF")) instanceof FloatTag){ + if(($healFTag = $nbt->getTag(self::TAG_LEGACY_HEALTH)) instanceof FloatTag){ $health = $healFTag->getValue(); - }elseif(($healthTag = $nbt->getTag("Health")) instanceof ShortTag){ + }elseif(($healthTag = $nbt->getTag(self::TAG_HEALTH)) instanceof ShortTag){ $health = $healthTag->getValue(); //Older versions of PocketMine-MP incorrectly saved this as a short instead of a float }elseif($healthTag instanceof FloatTag){ $health = $healthTag->getValue(); @@ -137,23 +147,23 @@ abstract class Living extends Entity{ $this->setHealth($health); - $this->setAirSupplyTicks($nbt->getShort("Air", self::DEFAULT_BREATH_TICKS)); + $this->setAirSupplyTicks($nbt->getShort(self::TAG_BREATH_TICKS, self::DEFAULT_BREATH_TICKS)); /** @var CompoundTag[]|ListTag|null $activeEffectsTag */ - $activeEffectsTag = $nbt->getListTag("ActiveEffects"); + $activeEffectsTag = $nbt->getListTag(self::TAG_ACTIVE_EFFECTS); if($activeEffectsTag !== null){ foreach($activeEffectsTag as $e){ - $effect = EffectIdMap::getInstance()->fromId($e->getByte("Id")); + $effect = EffectIdMap::getInstance()->fromId($e->getByte(self::TAG_EFFECT_ID)); if($effect === null){ continue; } $this->effectManager->add(new EffectInstance( $effect, - $e->getInt("Duration"), - Binary::unsignByte($e->getByte("Amplifier")), - $e->getByte("ShowParticles", 1) !== 0, - $e->getByte("Ambient", 0) !== 0 + $e->getInt(self::TAG_EFFECT_DURATION), + Binary::unsignByte($e->getByte(self::TAG_EFFECT_AMPLIFIER)), + $e->getByte(self::TAG_EFFECT_SHOW_PARTICLES, 1) !== 0, + $e->getByte(self::TAG_EFFECT_AMBIENT, 0) !== 0 )); } } @@ -263,22 +273,22 @@ abstract class Living extends Entity{ public function saveNBT() : CompoundTag{ $nbt = parent::saveNBT(); - $nbt->setFloat("Health", $this->getHealth()); + $nbt->setFloat(self::TAG_HEALTH, $this->getHealth()); - $nbt->setShort("Air", $this->getAirSupplyTicks()); + $nbt->setShort(self::TAG_BREATH_TICKS, $this->getAirSupplyTicks()); if(count($this->effectManager->all()) > 0){ $effects = []; foreach($this->effectManager->all() as $effect){ $effects[] = CompoundTag::create() - ->setByte("Id", EffectIdMap::getInstance()->toId($effect->getType())) - ->setByte("Amplifier", Binary::signByte($effect->getAmplifier())) - ->setInt("Duration", $effect->getDuration()) - ->setByte("Ambient", $effect->isAmbient() ? 1 : 0) - ->setByte("ShowParticles", $effect->isVisible() ? 1 : 0); + ->setByte(self::TAG_EFFECT_ID, EffectIdMap::getInstance()->toId($effect->getType())) + ->setByte(self::TAG_EFFECT_AMPLIFIER, Binary::signByte($effect->getAmplifier())) + ->setInt(self::TAG_EFFECT_DURATION, $effect->getDuration()) + ->setByte(self::TAG_EFFECT_AMBIENT, $effect->isAmbient() ? 1 : 0) + ->setByte(self::TAG_EFFECT_SHOW_PARTICLES, $effect->isVisible() ? 1 : 0); } - $nbt->setTag("ActiveEffects", new ListTag($effects)); + $nbt->setTag(self::TAG_ACTIVE_EFFECTS, new ListTag($effects)); } return $nbt; diff --git a/src/entity/Villager.php b/src/entity/Villager.php index 208ac7c77..376401a5d 100644 --- a/src/entity/Villager.php +++ b/src/entity/Villager.php @@ -36,6 +36,8 @@ class Villager extends Living implements Ageable{ public const PROFESSION_BLACKSMITH = 3; public const PROFESSION_BUTCHER = 4; + private const TAG_PROFESSION = "Profession"; //TAG_Int + public static function getNetworkTypeId() : string{ return EntityIds::VILLAGER; } private bool $baby = false; @@ -53,7 +55,7 @@ class Villager extends Living implements Ageable{ parent::initEntity($nbt); /** @var int $profession */ - $profession = $nbt->getInt("Profession", self::PROFESSION_FARMER); + $profession = $nbt->getInt(self::TAG_PROFESSION, self::PROFESSION_FARMER); if($profession > 4 || $profession < 0){ $profession = self::PROFESSION_FARMER; @@ -64,7 +66,7 @@ class Villager extends Living implements Ageable{ public function saveNBT() : CompoundTag{ $nbt = parent::saveNBT(); - $nbt->setInt("Profession", $this->getProfession()); + $nbt->setInt(self::TAG_PROFESSION, $this->getProfession()); return $nbt; } diff --git a/src/entity/object/ExperienceOrb.php b/src/entity/object/ExperienceOrb.php index c4fd4663c..ce2a766f0 100644 --- a/src/entity/object/ExperienceOrb.php +++ b/src/entity/object/ExperienceOrb.php @@ -40,6 +40,7 @@ class ExperienceOrb extends Entity{ public const TAG_VALUE_PC = "Value"; //short public const TAG_VALUE_PE = "experience value"; //int (WTF?) + private const TAG_AGE = "Age"; //TAG_Short /** Max distance an orb will follow a player across. */ public const MAX_TARGET_DISTANCE = 8.0; @@ -102,13 +103,13 @@ class ExperienceOrb extends Entity{ protected function initEntity(CompoundTag $nbt) : void{ parent::initEntity($nbt); - $this->age = $nbt->getShort("Age", 0); + $this->age = $nbt->getShort(self::TAG_AGE, 0); } public function saveNBT() : CompoundTag{ $nbt = parent::saveNBT(); - $nbt->setShort("Age", $this->age); + $nbt->setShort(self::TAG_AGE, $this->age); $nbt->setShort(self::TAG_VALUE_PC, $this->getXpValue()); $nbt->setInt(self::TAG_VALUE_PE, $this->getXpValue()); diff --git a/src/entity/object/FallingBlock.php b/src/entity/object/FallingBlock.php index 4333b8933..15b7aeac9 100644 --- a/src/entity/object/FallingBlock.php +++ b/src/entity/object/FallingBlock.php @@ -47,6 +47,9 @@ use function abs; class FallingBlock extends Entity{ private const TAG_FALLING_BLOCK = "FallingBlock"; //TAG_Compound + private const TAG_TILE_ID = "TileID"; //TAG_Int + private const TAG_TILE = "Tile"; //TAG_Byte + private const TAG_DATA = "Data"; //TAG_Byte public static function getNetworkTypeId() : string{ return EntityIds::FALLING_BLOCK; } @@ -70,14 +73,14 @@ class FallingBlock extends Entity{ if(($fallingBlockTag = $nbt->getCompoundTag(self::TAG_FALLING_BLOCK)) !== null){ $blockStateData = $blockDataUpgrader->upgradeBlockStateNbt($fallingBlockTag); }else{ - if(($tileIdTag = $nbt->getTag("TileID")) instanceof IntTag){ + if(($tileIdTag = $nbt->getTag(self::TAG_TILE_ID)) instanceof IntTag){ $blockId = $tileIdTag->getValue(); - }elseif(($tileTag = $nbt->getTag("Tile")) instanceof ByteTag){ + }elseif(($tileTag = $nbt->getTag(self::TAG_TILE)) instanceof ByteTag){ $blockId = $tileTag->getValue(); }else{ throw new SavedDataLoadingException("Missing legacy falling block info"); } - $damage = $nbt->getByte("Data", 0); + $damage = $nbt->getByte(self::TAG_DATA, 0); $blockStateData = $blockDataUpgrader->upgradeIntIdMeta($blockId, $damage); } diff --git a/src/entity/object/ItemEntity.php b/src/entity/object/ItemEntity.php index f20ec8445..97aa227f9 100644 --- a/src/entity/object/ItemEntity.php +++ b/src/entity/object/ItemEntity.php @@ -43,6 +43,13 @@ use function max; class ItemEntity extends Entity{ + private const TAG_HEALTH = "Health"; //TAG_Short + private const TAG_AGE = "Age"; //TAG_Short + private const TAG_PICKUP_DELAY = "PickupDelay"; //TAG_Short + private const TAG_OWNER = "Owner"; //TAG_String + private const TAG_THROWER = "Thrower"; //TAG_String + public const TAG_ITEM = "Item"; //TAG_Compound + public static function getNetworkTypeId() : string{ return EntityIds::ITEM; } public const MERGE_CHECK_PERIOD = 2; //0.1 seconds @@ -74,17 +81,17 @@ class ItemEntity extends Entity{ parent::initEntity($nbt); $this->setMaxHealth(5); - $this->setHealth($nbt->getShort("Health", (int) $this->getHealth())); + $this->setHealth($nbt->getShort(self::TAG_HEALTH, (int) $this->getHealth())); - $age = $nbt->getShort("Age", 0); + $age = $nbt->getShort(self::TAG_AGE, 0); if($age === -32768){ $this->despawnDelay = self::NEVER_DESPAWN; }else{ $this->despawnDelay = max(0, self::DEFAULT_DESPAWN_DELAY - $age); } - $this->pickupDelay = $nbt->getShort("PickupDelay", $this->pickupDelay); - $this->owner = $nbt->getString("Owner", $this->owner); - $this->thrower = $nbt->getString("Thrower", $this->thrower); + $this->pickupDelay = $nbt->getShort(self::TAG_PICKUP_DELAY, $this->pickupDelay); + $this->owner = $nbt->getString(self::TAG_OWNER, $this->owner); + $this->thrower = $nbt->getString(self::TAG_THROWER, $this->thrower); } protected function onFirstUpdate(int $currentTick) : void{ @@ -188,17 +195,17 @@ class ItemEntity extends Entity{ public function saveNBT() : CompoundTag{ $nbt = parent::saveNBT(); - $nbt->setTag("Item", $this->item->nbtSerialize()); - $nbt->setShort("Health", (int) $this->getHealth()); + $nbt->setTag(self::TAG_ITEM, $this->item->nbtSerialize()); + $nbt->setShort(self::TAG_HEALTH, (int) $this->getHealth()); if($this->despawnDelay === self::NEVER_DESPAWN){ $age = -32768; }else{ $age = self::DEFAULT_DESPAWN_DELAY - $this->despawnDelay; } - $nbt->setShort("Age", $age); - $nbt->setShort("PickupDelay", $this->pickupDelay); - $nbt->setString("Owner", $this->owner); - $nbt->setString("Thrower", $this->thrower); + $nbt->setShort(self::TAG_AGE, $age); + $nbt->setShort(self::TAG_PICKUP_DELAY, $this->pickupDelay); + $nbt->setString(self::TAG_OWNER, $this->owner); + $nbt->setString(self::TAG_THROWER, $this->thrower); return $nbt; } diff --git a/src/entity/object/Painting.php b/src/entity/object/Painting.php index 033c85a50..f6449883c 100644 --- a/src/entity/object/Painting.php +++ b/src/entity/object/Painting.php @@ -41,6 +41,13 @@ use pocketmine\world\World; use function ceil; class Painting extends Entity{ + public const TAG_TILE_X = "TileX"; //TAG_Int + public const TAG_TILE_Y = "TileY"; //TAG_Int + public const TAG_TILE_Z = "TileZ"; //TAG_Int + public const TAG_FACING_JE = "Facing"; //TAG_Byte + public const TAG_DIRECTION_BE = "Direction"; //TAG_Byte + public const TAG_MOTIVE = "Motive"; //TAG_String + public static function getNetworkTypeId() : string{ return EntityIds::PAINTING; } public const DATA_TO_FACING = [ @@ -84,14 +91,14 @@ class Painting extends Entity{ public function saveNBT() : CompoundTag{ $nbt = parent::saveNBT(); - $nbt->setInt("TileX", (int) $this->blockIn->x); - $nbt->setInt("TileY", (int) $this->blockIn->y); - $nbt->setInt("TileZ", (int) $this->blockIn->z); + $nbt->setInt(self::TAG_TILE_X, (int) $this->blockIn->x); + $nbt->setInt(self::TAG_TILE_Y, (int) $this->blockIn->y); + $nbt->setInt(self::TAG_TILE_Z, (int) $this->blockIn->z); - $nbt->setByte("Facing", self::FACING_TO_DATA[$this->facing]); - $nbt->setByte("Direction", self::FACING_TO_DATA[$this->facing]); //Save both for full compatibility + $nbt->setByte(self::TAG_FACING_JE, self::FACING_TO_DATA[$this->facing]); + $nbt->setByte(self::TAG_DIRECTION_BE, self::FACING_TO_DATA[$this->facing]); //Save both for full compatibility - $nbt->setString("Motive", $this->motive->getName()); + $nbt->setString(self::TAG_MOTIVE, $this->motive->getName()); return $nbt; } diff --git a/src/entity/object/PrimedTNT.php b/src/entity/object/PrimedTNT.php index 72d169d98..ec621adfb 100644 --- a/src/entity/object/PrimedTNT.php +++ b/src/entity/object/PrimedTNT.php @@ -39,6 +39,8 @@ use pocketmine\world\Position; class PrimedTNT extends Entity implements Explosive{ + private const TAG_FUSE = "Fuse"; //TAG_Short + public static function getNetworkTypeId() : string{ return EntityIds::TNT; } protected int $fuse; @@ -78,7 +80,7 @@ class PrimedTNT extends Entity implements Explosive{ protected function initEntity(CompoundTag $nbt) : void{ parent::initEntity($nbt); - $this->fuse = $nbt->getShort("Fuse", 80); + $this->fuse = $nbt->getShort(self::TAG_FUSE, 80); } public function canCollideWith(Entity $entity) : bool{ @@ -87,7 +89,7 @@ class PrimedTNT extends Entity implements Explosive{ public function saveNBT() : CompoundTag{ $nbt = parent::saveNBT(); - $nbt->setShort("Fuse", $this->fuse); + $nbt->setShort(self::TAG_FUSE, $this->fuse); return $nbt; } diff --git a/src/entity/projectile/Arrow.php b/src/entity/projectile/Arrow.php index e3b4e8a5d..e41e4ab28 100644 --- a/src/entity/projectile/Arrow.php +++ b/src/entity/projectile/Arrow.php @@ -52,6 +52,7 @@ class Arrow extends Projectile{ private const TAG_PICKUP = "pickup"; //TAG_Byte public const TAG_CRIT = "crit"; //TAG_Byte + private const TAG_LIFE = "life"; //TAG_Short protected float $damage = 2.0; protected int $pickupMode = self::PICKUP_ANY; @@ -75,14 +76,14 @@ class Arrow extends Projectile{ $this->pickupMode = $nbt->getByte(self::TAG_PICKUP, self::PICKUP_ANY); $this->critical = $nbt->getByte(self::TAG_CRIT, 0) === 1; - $this->collideTicks = $nbt->getShort("life", $this->collideTicks); + $this->collideTicks = $nbt->getShort(self::TAG_LIFE, $this->collideTicks); } public function saveNBT() : CompoundTag{ $nbt = parent::saveNBT(); $nbt->setByte(self::TAG_PICKUP, $this->pickupMode); $nbt->setByte(self::TAG_CRIT, $this->critical ? 1 : 0); - $nbt->setShort("life", $this->collideTicks); + $nbt->setShort(self::TAG_LIFE, $this->collideTicks); return $nbt; } diff --git a/src/entity/projectile/Projectile.php b/src/entity/projectile/Projectile.php index fb2410db4..ec7ad61bd 100644 --- a/src/entity/projectile/Projectile.php +++ b/src/entity/projectile/Projectile.php @@ -53,6 +53,10 @@ use const PHP_INT_MAX; abstract class Projectile extends Entity{ private const TAG_STUCK_ON_BLOCK_POS = "StuckToBlockPos"; + private const TAG_DAMAGE = "damage"; //TAG_Double + private const TAG_TILE_X = "tileX"; //TAG_Int + private const TAG_TILE_Y = "tileY"; //TAG_Int + private const TAG_TILE_Z = "tileZ"; //TAG_Int protected float $damage = 0.0; protected ?Vector3 $blockHit = null; @@ -75,7 +79,7 @@ abstract class Projectile extends Entity{ $this->setMaxHealth(1); $this->setHealth(1); - $this->damage = $nbt->getDouble("damage", $this->damage); + $this->damage = $nbt->getDouble(self::TAG_DAMAGE, $this->damage); if(($stuckOnBlockPosTag = $nbt->getListTag(self::TAG_STUCK_ON_BLOCK_POS)) !== null){ if($stuckOnBlockPosTag->getTagType() !== NBT::TAG_Int || count($stuckOnBlockPosTag) !== 3){ @@ -86,7 +90,7 @@ abstract class Projectile extends Entity{ $values = $stuckOnBlockPosTag->getValue(); $this->blockHit = new Vector3($values[0]->getValue(), $values[1]->getValue(), $values[2]->getValue()); - }elseif(($tileXTag = $nbt->getTag("tileX")) instanceof IntTag && ($tileYTag = $nbt->getTag("tileY")) instanceof IntTag && ($tileZTag = $nbt->getTag("tileZ")) instanceof IntTag){ + }elseif(($tileXTag = $nbt->getTag(self::TAG_TILE_X)) instanceof IntTag && ($tileYTag = $nbt->getTag(self::TAG_TILE_Y)) instanceof IntTag && ($tileZTag = $nbt->getTag(self::TAG_TILE_Z)) instanceof IntTag){ $this->blockHit = new Vector3($tileXTag->getValue(), $tileYTag->getValue(), $tileZTag->getValue()); } } @@ -124,7 +128,7 @@ abstract class Projectile extends Entity{ public function saveNBT() : CompoundTag{ $nbt = parent::saveNBT(); - $nbt->setDouble("damage", $this->damage); + $nbt->setDouble(self::TAG_DAMAGE, $this->damage); if($this->blockHit !== null){ $nbt->setTag(self::TAG_STUCK_ON_BLOCK_POS, new ListTag([ diff --git a/src/item/Item.php b/src/item/Item.php index 9fe3ab25b..ded0de16b 100644 --- a/src/item/Item.php +++ b/src/item/Item.php @@ -60,6 +60,9 @@ class Item implements \JsonSerializable{ use ItemEnchantmentHandlingTrait; public const TAG_ENCH = "ench"; + private const TAG_ENCH_ID = "id"; //TAG_Short + private const TAG_ENCH_LVL = "lvl"; //TAG_Short + public const TAG_DISPLAY = "display"; public const TAG_BLOCK_ENTITY_TAG = "BlockEntityTag"; @@ -68,6 +71,9 @@ class Item implements \JsonSerializable{ public const TAG_KEEP_ON_DEATH = "minecraft:keep_on_death"; + private const TAG_CAN_PLACE_ON = "CanPlaceOn"; //TAG_List + private const TAG_CAN_DESTROY = "CanDestroy"; //TAG_List + private CompoundTag $nbt; protected int $count = 1; @@ -296,8 +302,8 @@ class Item implements \JsonSerializable{ if($enchantments !== null && $enchantments->getTagType() === NBT::TAG_Compound){ /** @var CompoundTag $enchantment */ foreach($enchantments as $enchantment){ - $magicNumber = $enchantment->getShort("id", -1); - $level = $enchantment->getShort("lvl", 0); + $magicNumber = $enchantment->getShort(self::TAG_ENCH_ID, -1); + $level = $enchantment->getShort(self::TAG_ENCH_LVL, 0); if($level <= 0){ continue; } @@ -311,7 +317,7 @@ class Item implements \JsonSerializable{ $this->blockEntityTag = $tag->getCompoundTag(self::TAG_BLOCK_ENTITY_TAG); $this->canPlaceOn = []; - $canPlaceOn = $tag->getListTag("CanPlaceOn"); + $canPlaceOn = $tag->getListTag(self::TAG_CAN_PLACE_ON); if($canPlaceOn !== null && $canPlaceOn->getTagType() === NBT::TAG_String){ /** @var StringTag $entry */ foreach($canPlaceOn as $entry){ @@ -319,7 +325,7 @@ class Item implements \JsonSerializable{ } } $this->canDestroy = []; - $canDestroy = $tag->getListTag("CanDestroy"); + $canDestroy = $tag->getListTag(self::TAG_CAN_DESTROY); if($canDestroy !== null && $canDestroy->getTagType() === NBT::TAG_String){ /** @var StringTag $entry */ foreach($canDestroy as $entry){ @@ -354,8 +360,8 @@ class Item implements \JsonSerializable{ $ench = new ListTag(); foreach($this->getEnchantments() as $enchantmentInstance){ $ench->push(CompoundTag::create() - ->setShort("id", EnchantmentIdMap::getInstance()->toId($enchantmentInstance->getType())) - ->setShort("lvl", $enchantmentInstance->getLevel()) + ->setShort(self::TAG_ENCH_ID, EnchantmentIdMap::getInstance()->toId($enchantmentInstance->getType())) + ->setShort(self::TAG_ENCH_LVL, $enchantmentInstance->getLevel()) ); } $tag->setTag(self::TAG_ENCH, $ench); @@ -372,18 +378,18 @@ class Item implements \JsonSerializable{ foreach($this->canPlaceOn as $item){ $canPlaceOn->push(new StringTag($item)); } - $tag->setTag("CanPlaceOn", $canPlaceOn); + $tag->setTag(self::TAG_CAN_PLACE_ON, $canPlaceOn); }else{ - $tag->removeTag("CanPlaceOn"); + $tag->removeTag(self::TAG_CAN_PLACE_ON); } if(count($this->canDestroy) > 0){ $canDestroy = new ListTag(); foreach($this->canDestroy as $item){ $canDestroy->push(new StringTag($item)); } - $tag->setTag("CanDestroy", $canDestroy); + $tag->setTag(self::TAG_CAN_DESTROY, $canDestroy); }else{ - $tag->removeTag("CanDestroy"); + $tag->removeTag(self::TAG_CAN_DESTROY); } if($this->keepOnDeath){ diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 2b87f7ea3..592fea262 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -685,7 +685,7 @@ class NetworkSession{ //TODO: we shouldn't be loading player data here at all, but right now we don't have any choice :( $this->cachedOfflinePlayerData = $this->server->getOfflinePlayerData($this->info->getUsername()); if($checkXUID){ - $recordedXUID = $this->cachedOfflinePlayerData !== null ? $this->cachedOfflinePlayerData->getTag("LastKnownXUID") : null; + $recordedXUID = $this->cachedOfflinePlayerData !== null ? $this->cachedOfflinePlayerData->getTag(Player::TAG_LAST_KNOWN_XUID) : null; if(!($recordedXUID instanceof StringTag)){ $this->logger->debug("No previous XUID recorded, no choice but to trust this player"); }elseif(!$kickForXUIDMismatch($recordedXUID->getValue())){ diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index 3d5e01d6a..6a20a1577 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -26,6 +26,7 @@ namespace pocketmine\network\mcpe\handler; use pocketmine\block\BaseSign; use pocketmine\block\ItemFrame; use pocketmine\block\Lectern; +use pocketmine\block\tile\Sign; use pocketmine\block\utils\SignText; use pocketmine\entity\animation\ConsumingItemAnimation; use pocketmine\entity\Attribute; @@ -650,7 +651,7 @@ class InGamePacketHandler extends PacketHandler{ if(!($nbt instanceof CompoundTag)) throw new AssumptionFailedError("PHPStan should ensure this is a CompoundTag"); //for phpstorm's benefit if($block instanceof BaseSign){ - if(($textBlobTag = $nbt->getTag("Text")) instanceof StringTag){ + if(($textBlobTag = $nbt->getTag(Sign::TAG_TEXT_BLOB)) instanceof StringTag){ try{ $text = SignText::fromBlob($textBlobTag->getValue()); }catch(\InvalidArgumentException $e){ diff --git a/src/player/OfflinePlayer.php b/src/player/OfflinePlayer.php index a96df417f..0b08cf948 100644 --- a/src/player/OfflinePlayer.php +++ b/src/player/OfflinePlayer.php @@ -37,11 +37,11 @@ class OfflinePlayer implements IPlayer{ } public function getFirstPlayed() : ?int{ - return ($this->namedtag !== null && ($firstPlayedTag = $this->namedtag->getTag("firstPlayed")) instanceof LongTag) ? $firstPlayedTag->getValue() : null; + return ($this->namedtag !== null && ($firstPlayedTag = $this->namedtag->getTag(Player::TAG_FIRST_PLAYED)) instanceof LongTag) ? $firstPlayedTag->getValue() : null; } public function getLastPlayed() : ?int{ - return ($this->namedtag !== null && ($lastPlayedTag = $this->namedtag->getTag("lastPlayed")) instanceof LongTag) ? $lastPlayedTag->getValue() : null; + return ($this->namedtag !== null && ($lastPlayedTag = $this->namedtag->getTag(Player::TAG_LAST_PLAYED)) instanceof LongTag) ? $lastPlayedTag->getValue() : null; } public function hasPlayedBefore() : bool{ diff --git a/src/player/Player.php b/src/player/Player.php index a09d50f71..6025710d9 100644 --- a/src/player/Player.php +++ b/src/player/Player.php @@ -178,6 +178,16 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ private const MAX_REACH_DISTANCE_SURVIVAL = 7; private const MAX_REACH_DISTANCE_ENTITY_INTERACTION = 8; + public const TAG_FIRST_PLAYED = "firstPlayed"; //TAG_Long + public const TAG_LAST_PLAYED = "lastPlayed"; //TAG_Long + private const TAG_GAME_MODE = "playerGameType"; //TAG_Int + private const TAG_SPAWN_WORLD = "SpawnLevel"; //TAG_String + private const TAG_SPAWN_X = "SpawnX"; //TAG_Int + private const TAG_SPAWN_Y = "SpawnY"; //TAG_Int + private const TAG_SPAWN_Z = "SpawnZ"; //TAG_Int + public const TAG_LEVEL = "Level"; //TAG_String + public const TAG_LAST_KNOWN_XUID = "LastKnownXUID"; //TAG_String + /** * Validates the given username. */ @@ -346,10 +356,10 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ } )); - $this->firstPlayed = $nbt->getLong("firstPlayed", $now = (int) (microtime(true) * 1000)); - $this->lastPlayed = $nbt->getLong("lastPlayed", $now); + $this->firstPlayed = $nbt->getLong(self::TAG_FIRST_PLAYED, $now = (int) (microtime(true) * 1000)); + $this->lastPlayed = $nbt->getLong(self::TAG_LAST_PLAYED, $now); - if(!$this->server->getForceGamemode() && ($gameModeTag = $nbt->getTag("playerGameType")) instanceof IntTag){ + if(!$this->server->getForceGamemode() && ($gameModeTag = $nbt->getTag(self::TAG_GAME_MODE)) instanceof IntTag){ $this->internalSetGameMode(GameModeIdMap::getInstance()->fromId($gameModeTag->getValue()) ?? GameMode::SURVIVAL()); //TODO: bad hack here to avoid crashes on corrupted data }else{ $this->internalSetGameMode($this->server->getGamemode()); @@ -361,8 +371,8 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ $this->setNameTagAlwaysVisible(); $this->setCanClimb(); - if(($world = $this->server->getWorldManager()->getWorldByName($nbt->getString("SpawnLevel", ""))) instanceof World){ - $this->spawnPosition = new Position($nbt->getInt("SpawnX"), $nbt->getInt("SpawnY"), $nbt->getInt("SpawnZ"), $world); + if(($world = $this->server->getWorldManager()->getWorldByName($nbt->getString(self::TAG_SPAWN_WORLD, ""))) instanceof World){ + $this->spawnPosition = new Position($nbt->getInt(self::TAG_SPAWN_X), $nbt->getInt(self::TAG_SPAWN_Y), $nbt->getInt(self::TAG_SPAWN_Z), $world); } } @@ -2240,23 +2250,23 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{ public function getSaveData() : CompoundTag{ $nbt = $this->saveNBT(); - $nbt->setString("LastKnownXUID", $this->xuid); + $nbt->setString(self::TAG_LAST_KNOWN_XUID, $this->xuid); if($this->location->isValid()){ - $nbt->setString("Level", $this->getWorld()->getFolderName()); + $nbt->setString(self::TAG_LEVEL, $this->getWorld()->getFolderName()); } if($this->hasValidCustomSpawn()){ $spawn = $this->getSpawn(); - $nbt->setString("SpawnLevel", $spawn->getWorld()->getFolderName()); - $nbt->setInt("SpawnX", $spawn->getFloorX()); - $nbt->setInt("SpawnY", $spawn->getFloorY()); - $nbt->setInt("SpawnZ", $spawn->getFloorZ()); + $nbt->setString(self::TAG_SPAWN_WORLD, $spawn->getWorld()->getFolderName()); + $nbt->setInt(self::TAG_SPAWN_X, $spawn->getFloorX()); + $nbt->setInt(self::TAG_SPAWN_Y, $spawn->getFloorY()); + $nbt->setInt(self::TAG_SPAWN_Z, $spawn->getFloorZ()); } - $nbt->setInt("playerGameType", GameModeIdMap::getInstance()->toId($this->gamemode)); - $nbt->setLong("firstPlayed", $this->firstPlayed); - $nbt->setLong("lastPlayed", (int) floor(microtime(true) * 1000)); + $nbt->setInt(self::TAG_GAME_MODE, GameModeIdMap::getInstance()->toId($this->gamemode)); + $nbt->setLong(self::TAG_FIRST_PLAYED, $this->firstPlayed); + $nbt->setLong(self::TAG_LAST_PLAYED, (int) floor(microtime(true) * 1000)); return $nbt; }