mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-15 18:29:46 +00:00
Eliminate remaining usages of legacy block ID+meta on disk
flower pots loaded from vanilla worlds should now correctly display the plant inside
This commit is contained in:
parent
02568bb049
commit
5c85aa6e58
@ -26,9 +26,12 @@ namespace pocketmine\block\tile;
|
||||
use pocketmine\block\Air;
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\BlockFactory;
|
||||
use pocketmine\data\bedrock\blockstate\BlockStateDeserializeException;
|
||||
use pocketmine\data\SavedDataLoadingException;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ShortTag;
|
||||
use pocketmine\world\format\io\GlobalBlockStateHandlers;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
@ -37,25 +40,35 @@ use pocketmine\nbt\tag\ShortTag;
|
||||
class FlowerPot extends Spawnable{
|
||||
private const TAG_ITEM = "item";
|
||||
private const TAG_ITEM_DATA = "mData";
|
||||
private const TAG_PLANT_BLOCK = "PlantBlock";
|
||||
|
||||
private ?Block $plant = null;
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
$blockStateData = null;
|
||||
if(($itemIdTag = $nbt->getTag(self::TAG_ITEM)) instanceof ShortTag && ($itemMetaTag = $nbt->getTag(self::TAG_ITEM_DATA)) instanceof IntTag){
|
||||
$blockStateData = GlobalBlockStateHandlers::getLegacyBlockStateMapper()->fromIntIdMeta($itemIdTag->getValue(), $itemMetaTag->getValue());
|
||||
}elseif(($plantBlockTag = $nbt->getCompoundTag(self::TAG_PLANT_BLOCK)) !== null){
|
||||
try{
|
||||
$this->setPlant(BlockFactory::getInstance()->get($itemIdTag->getValue(), $itemMetaTag->getValue()));
|
||||
}catch(\InvalidArgumentException $e){
|
||||
//noop
|
||||
$blockStateData = GlobalBlockStateHandlers::nbtToBlockStateData($plantBlockTag);
|
||||
}catch(BlockStateDeserializeException $e){
|
||||
throw new SavedDataLoadingException("Error loading " . self::TAG_PLANT_BLOCK . " tag for flower pot: " . $e->getMessage(), 0, $e);
|
||||
}
|
||||
}else{
|
||||
//TODO: new PlantBlock tag
|
||||
}
|
||||
|
||||
if($blockStateData !== null){
|
||||
try{
|
||||
$blockStateId = GlobalBlockStateHandlers::getDeserializer()->deserialize($blockStateData);
|
||||
}catch(BlockStateDeserializeException $e){
|
||||
throw new SavedDataLoadingException("Error deserializing plant for flower pot: " . $e->getMessage(), 0, $e);
|
||||
}
|
||||
$this->setPlant(BlockFactory::getInstance()->fromFullBlock($blockStateId));
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
if($this->plant !== null){
|
||||
$nbt->setShort(self::TAG_ITEM, $this->plant->getId());
|
||||
$nbt->setInt(self::TAG_ITEM_DATA, $this->plant->getMeta());
|
||||
$nbt->setTag(self::TAG_PLANT_BLOCK, GlobalBlockStateHandlers::getSerializer()->serialize($this->plant->getFullId())->toNbt());
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,8 +86,7 @@ class FlowerPot extends Spawnable{
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
if($this->plant !== null){
|
||||
$nbt->setShort(self::TAG_ITEM, $this->plant->getId());
|
||||
$nbt->setInt(self::TAG_ITEM_DATA, $this->plant->getMeta());
|
||||
$nbt->setTag(self::TAG_PLANT_BLOCK, GlobalBlockStateHandlers::getSerializer()->serialize($this->plant->getFullId())->toNbt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\entity\object;
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\BlockFactory;
|
||||
use pocketmine\block\utils\Fallable;
|
||||
use pocketmine\data\bedrock\blockstate\BlockStateDeserializeException;
|
||||
use pocketmine\data\SavedDataLoadingException;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\EntitySizeInfo;
|
||||
@ -40,9 +41,11 @@ use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\EntityIds;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection;
|
||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
||||
use pocketmine\world\format\io\GlobalBlockStateHandlers;
|
||||
use function abs;
|
||||
|
||||
class FallingBlock extends Entity{
|
||||
private const TAG_FALLING_BLOCK = "FallingBlock"; //TAG_Compound
|
||||
|
||||
public static function getNetworkTypeId() : string{ return EntityIds::FALLING_BLOCK; }
|
||||
|
||||
@ -60,22 +63,37 @@ class FallingBlock extends Entity{
|
||||
protected function getInitialGravity() : float{ return 0.04; }
|
||||
|
||||
public static function parseBlockNBT(BlockFactory $factory, CompoundTag $nbt) : Block{
|
||||
$blockId = 0;
|
||||
|
||||
//TODO: 1.8+ save format
|
||||
if(($tileIdTag = $nbt->getTag("TileID")) instanceof IntTag){
|
||||
$blockId = $tileIdTag->getValue();
|
||||
}elseif(($tileTag = $nbt->getTag("Tile")) instanceof ByteTag){
|
||||
$blockId = $tileTag->getValue();
|
||||
if(($fallingBlockTag = $nbt->getCompoundTag(self::TAG_FALLING_BLOCK)) !== null){
|
||||
try{
|
||||
$blockStateData = GlobalBlockStateHandlers::nbtToBlockStateData($fallingBlockTag);
|
||||
}catch(BlockStateDeserializeException $e){
|
||||
throw new SavedDataLoadingException($e->getMessage(), 0, $e);
|
||||
}
|
||||
}else{
|
||||
if(($tileIdTag = $nbt->getTag("TileID")) instanceof IntTag){
|
||||
$blockId = $tileIdTag->getValue();
|
||||
}elseif(($tileTag = $nbt->getTag("Tile")) instanceof ByteTag){
|
||||
$blockId = $tileTag->getValue();
|
||||
}else{
|
||||
throw new SavedDataLoadingException("Missing legacy falling block info");
|
||||
}
|
||||
$damage = $nbt->getByte("Data", 0);
|
||||
|
||||
$blockStateData = GlobalBlockStateHandlers::getLegacyBlockStateMapper()->fromIntIdMeta($blockId, $damage);
|
||||
if($blockStateData === null){
|
||||
throw new SavedDataLoadingException("Invalid legacy falling block");
|
||||
}
|
||||
}
|
||||
|
||||
if($blockId === 0){
|
||||
throw new SavedDataLoadingException("Missing block info from NBT");
|
||||
try{
|
||||
$blockStateId = GlobalBlockStateHandlers::getDeserializer()->deserialize($blockStateData);
|
||||
}catch(BlockStateDeserializeException $e){
|
||||
throw new SavedDataLoadingException($e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
$damage = $nbt->getByte("Data", 0);
|
||||
|
||||
return $factory->get($blockId, $damage);
|
||||
return $factory->fromFullBlock($blockStateId);
|
||||
}
|
||||
|
||||
public function canCollideWith(Entity $entity) : bool{
|
||||
@ -137,8 +155,7 @@ class FallingBlock extends Entity{
|
||||
|
||||
public function saveNBT() : CompoundTag{
|
||||
$nbt = parent::saveNBT();
|
||||
$nbt->setInt("TileID", $this->block->getId());
|
||||
$nbt->setByte("Data", $this->block->getMeta());
|
||||
$nbt->setTag(self::TAG_FALLING_BLOCK, GlobalBlockStateHandlers::getSerializer()->serialize($this->block->getFullId())->toNbt());
|
||||
|
||||
return $nbt;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\entity\projectile;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\BlockFactory;
|
||||
use pocketmine\data\SavedDataLoadingException;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\entity\Location;
|
||||
@ -38,21 +38,24 @@ use pocketmine\event\entity\ProjectileHitEvent;
|
||||
use pocketmine\math\RayTraceResult;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\math\VoxelRayTrace;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\timings\Timings;
|
||||
use function assert;
|
||||
use function atan2;
|
||||
use function ceil;
|
||||
use function count;
|
||||
use function sqrt;
|
||||
use const M_PI;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
abstract class Projectile extends Entity{
|
||||
private const TAG_STUCK_ON_BLOCK_POS = "StuckToBlockPos";
|
||||
|
||||
protected float $damage = 0.0;
|
||||
protected ?Block $blockHit = null;
|
||||
protected ?Vector3 $blockHit = null;
|
||||
|
||||
public function __construct(Location $location, ?Entity $shootingEntity, ?CompoundTag $nbt = null){
|
||||
parent::__construct($location, $nbt);
|
||||
@ -74,28 +77,18 @@ abstract class Projectile extends Entity{
|
||||
$this->setHealth(1);
|
||||
$this->damage = $nbt->getDouble("damage", $this->damage);
|
||||
|
||||
(function() use ($nbt) : void{
|
||||
if(($tileXTag = $nbt->getTag("tileX")) instanceof IntTag && ($tileYTag = $nbt->getTag("tileY")) instanceof IntTag && ($tileZTag = $nbt->getTag("tileZ")) instanceof IntTag){
|
||||
$blockPos = new Vector3($tileXTag->getValue(), $tileYTag->getValue(), $tileZTag->getValue());
|
||||
}else{
|
||||
return;
|
||||
if(($stuckOnBlockPosTag = $nbt->getListTag(self::TAG_STUCK_ON_BLOCK_POS)) !== null){
|
||||
if($stuckOnBlockPosTag->getTagType() !== NBT::TAG_Int || count($stuckOnBlockPosTag) !== 3){
|
||||
throw new SavedDataLoadingException(self::TAG_STUCK_ON_BLOCK_POS . " tag should be a list of 3 TAG_Int");
|
||||
}
|
||||
|
||||
if(($blockIdTag = $nbt->getTag("blockId")) instanceof IntTag){
|
||||
$blockId = $blockIdTag->getValue();
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
/** @var IntTag[] $values */
|
||||
$values = $stuckOnBlockPosTag->getValue();
|
||||
|
||||
if(($blockDataTag = $nbt->getTag("blockData")) instanceof ByteTag){
|
||||
$blockData = $blockDataTag->getValue();
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->blockHit = BlockFactory::getInstance()->get($blockId, $blockData);
|
||||
$this->blockHit->position($this->getWorld(), $blockPos->getFloorX(), $blockPos->getFloorY(), $blockPos->getFloorZ());
|
||||
})();
|
||||
$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){
|
||||
$this->blockHit = new Vector3($tileXTag->getValue(), $tileYTag->getValue(), $tileZTag->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public function canCollideWith(Entity $entity) : bool{
|
||||
@ -134,14 +127,11 @@ abstract class Projectile extends Entity{
|
||||
$nbt->setDouble("damage", $this->damage);
|
||||
|
||||
if($this->blockHit !== null){
|
||||
$pos = $this->blockHit->getPosition();
|
||||
$nbt->setInt("tileX", $pos->x);
|
||||
$nbt->setInt("tileY", $pos->y);
|
||||
$nbt->setInt("tileZ", $pos->z);
|
||||
|
||||
//we intentionally use different ones to PC because we don't have stringy IDs
|
||||
$nbt->setInt("blockId", $this->blockHit->getId());
|
||||
$nbt->setByte("blockData", $this->blockHit->getMeta());
|
||||
$nbt->setTag(self::TAG_STUCK_ON_BLOCK_POS, new ListTag([
|
||||
new IntTag($this->blockHit->getFloorX()),
|
||||
new IntTag($this->blockHit->getFloorY()),
|
||||
new IntTag($this->blockHit->getFloorZ())
|
||||
]));
|
||||
}
|
||||
|
||||
return $nbt;
|
||||
@ -152,8 +142,11 @@ abstract class Projectile extends Entity{
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->blockHit !== null && $this->getWorld()->isInLoadedTerrain($this->blockHit->getPosition()) && !$this->blockHit->isSameState($this->getWorld()->getBlock($this->blockHit->getPosition()))){
|
||||
$this->blockHit = null;
|
||||
if($this->blockHit !== null && $this->getWorld()->isInLoadedTerrain($this->blockHit)){
|
||||
$blockHit = $this->getWorld()->getBlock($this->blockHit);
|
||||
if(!$blockHit->collidesWithBB($this->getBoundingBox()->expandedCopy(0.001, 0.001, 0.001))){
|
||||
$this->blockHit = null;
|
||||
}
|
||||
}
|
||||
|
||||
parent::onNearbyBlockChange();
|
||||
@ -312,6 +305,6 @@ abstract class Projectile extends Entity{
|
||||
* Called when the projectile collides with a Block.
|
||||
*/
|
||||
protected function onHitBlock(Block $blockHit, RayTraceResult $hitResult) : void{
|
||||
$this->blockHit = clone $blockHit;
|
||||
$this->blockHit = $blockHit->getPosition()->asVector3();
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\world\format\io;
|
||||
use pocketmine\data\bedrock\blockstate\BlockStateData;
|
||||
use pocketmine\data\bedrock\blockstate\BlockStateDeserializer;
|
||||
use pocketmine\data\bedrock\blockstate\BlockStateSerializer;
|
||||
use pocketmine\data\bedrock\blockstate\BlockTypeNames;
|
||||
use pocketmine\data\bedrock\blockstate\CachingBlockStateDeserializer;
|
||||
use pocketmine\data\bedrock\blockstate\CachingBlockStateSerializer;
|
||||
use pocketmine\data\bedrock\blockstate\convert\BlockObjectToBlockStateSerializer;
|
||||
@ -36,6 +37,7 @@ use pocketmine\data\bedrock\blockstate\upgrade\LegacyBlockStateMapper;
|
||||
use pocketmine\data\bedrock\blockstate\UpgradingBlockStateDeserializer;
|
||||
use pocketmine\data\bedrock\LegacyBlockIdToStringIdMap;
|
||||
use pocketmine\errorhandler\ErrorToExceptionHandler;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use Webmozart\PathUtil\Path;
|
||||
use function file_get_contents;
|
||||
use const pocketmine\BEDROCK_BLOCK_UPGRADE_SCHEMA_PATH;
|
||||
@ -79,4 +81,23 @@ final class GlobalBlockStateHandlers{
|
||||
LegacyBlockIdToStringIdMap::getInstance()
|
||||
);
|
||||
}
|
||||
|
||||
public static function nbtToBlockStateData(CompoundTag $tag) : BlockStateData{
|
||||
if($tag->getTag("name") !== null && $tag->getTag("val") !== null){
|
||||
//Legacy (pre-1.13) blockstate - upgrade it to a version we understand
|
||||
$id = $tag->getString("name");
|
||||
$data = $tag->getShort("val");
|
||||
|
||||
$blockStateData = GlobalBlockStateHandlers::getLegacyBlockStateMapper()->fromStringIdMeta($id, $data);
|
||||
if($blockStateData === null){
|
||||
//unknown block, invalid ID
|
||||
$blockStateData = new BlockStateData(BlockTypeNames::INFO_UPDATE, CompoundTag::create(), BlockStateData::CURRENT_VERSION);
|
||||
}
|
||||
}else{
|
||||
//Modern (post-1.13) blockstate
|
||||
$blockStateData = BlockStateData::fromNbt($tag);
|
||||
}
|
||||
|
||||
return $blockStateData;
|
||||
}
|
||||
}
|
||||
|
@ -165,23 +165,9 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
||||
try{
|
||||
$offset = $stream->getOffset();
|
||||
|
||||
$tag = $nbt->read($stream->getBuffer(), $offset)->mustGetCompoundTag();
|
||||
$blockStateData = GlobalBlockStateHandlers::nbtToBlockStateData($nbt->read($stream->getBuffer(), $offset)->mustGetCompoundTag());
|
||||
$stream->setOffset($offset);
|
||||
|
||||
if($tag->getTag("name") !== null && $tag->getTag("val") !== null){
|
||||
//Legacy (pre-1.13) blockstate - upgrade it to a version we understand
|
||||
$id = $tag->getString("name");
|
||||
$data = $tag->getShort("val");
|
||||
|
||||
$blockStateData = GlobalBlockStateHandlers::getLegacyBlockStateMapper()->fromStringIdMeta($id, $data);
|
||||
if($blockStateData === null){
|
||||
$blockStateData = new BlockStateData(BlockTypeNames::INFO_UPDATE, CompoundTag::create(), BlockStateData::CURRENT_VERSION);
|
||||
}
|
||||
}else{
|
||||
//Modern (post-1.13) blockstate
|
||||
$blockStateData = BlockStateData::fromNbt($tag);
|
||||
}
|
||||
|
||||
try{
|
||||
$palette[] = $blockStateDeserializer->deserialize($blockStateData);
|
||||
}catch(BlockStateDeserializeException){
|
||||
|
Loading…
x
Reference in New Issue
Block a user