mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-21 08:17:34 +00:00
ÂInsert PM data version into blockstates, chunks, entities, tiles and level.dat
this information will allow us to correct for any bugs introduced by past versions. however, we still need to propagate this information to permit actually using it when loading data.
This commit is contained in:
parent
7f1550ef04
commit
f5a1a0c9cb
@ -35,6 +35,21 @@ final class VersionInfo{
|
||||
public const IS_DEVELOPMENT_BUILD = true;
|
||||
public const BUILD_CHANNEL = "beta";
|
||||
|
||||
/**
|
||||
* PocketMine-MP-specific version ID for world data. Used to determine what fixes need to be applied to old world
|
||||
* data (e.g. stuff saved wrongly by past versions).
|
||||
* This version supplements the Minecraft vanilla world version.
|
||||
*
|
||||
* This should be bumped if any **non-Mojang** BC-breaking change or bug fix is made to world save data of any kind
|
||||
* (entities, tiles, blocks, biomes etc.). For example, if PM accidentally saved a block with its facing value
|
||||
* swapped, we would bump this, but not if Mojang did the same change.
|
||||
*/
|
||||
public const WORLD_DATA_VERSION = 1;
|
||||
/**
|
||||
* Name of the NBT tag used to store the world data version.
|
||||
*/
|
||||
public const TAG_WORLD_DATA_VERSION = "PMMPDataVersion"; //TAG_Long
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ use pocketmine\nbt\NbtDataException;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
use pocketmine\VersionInfo;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\World;
|
||||
use function get_class;
|
||||
@ -71,7 +72,8 @@ abstract class Tile{
|
||||
->setString(self::TAG_ID, TileFactory::getInstance()->getSaveId(get_class($this)))
|
||||
->setInt(self::TAG_X, $this->position->getFloorX())
|
||||
->setInt(self::TAG_Y, $this->position->getFloorY())
|
||||
->setInt(self::TAG_Z, $this->position->getFloorZ());
|
||||
->setInt(self::TAG_Z, $this->position->getFloorZ())
|
||||
->setLong(VersionInfo::TAG_WORLD_DATA_VERSION, VersionInfo::WORLD_DATA_VERSION);
|
||||
$this->writeSaveData($nbt);
|
||||
|
||||
return $nbt;
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\nbt\NbtException;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\Tag;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\VersionInfo;
|
||||
use function array_keys;
|
||||
use function count;
|
||||
use function implode;
|
||||
@ -96,12 +97,13 @@ final class BlockStateData{
|
||||
$name = $nbt->getString(self::TAG_NAME);
|
||||
$states = $nbt->getCompoundTag(self::TAG_STATES) ?? throw new BlockStateDeserializeException("Missing tag \"" . self::TAG_STATES . "\"");
|
||||
$version = $nbt->getInt(self::TAG_VERSION, 0);
|
||||
//TODO: read version from VersionInfo::TAG_WORLD_DATA_VERSION - we may need it to fix up old blockstates
|
||||
}catch(NbtException $e){
|
||||
throw new BlockStateDeserializeException($e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
$allKeys = $nbt->getValue();
|
||||
unset($allKeys[self::TAG_NAME], $allKeys[self::TAG_STATES], $allKeys[self::TAG_VERSION]);
|
||||
unset($allKeys[self::TAG_NAME], $allKeys[self::TAG_STATES], $allKeys[self::TAG_VERSION], $allKeys[VersionInfo::TAG_WORLD_DATA_VERSION]);
|
||||
if(count($allKeys) !== 0){
|
||||
throw new BlockStateDeserializeException("Unexpected extra keys: " . implode(", ", array_keys($allKeys)));
|
||||
}
|
||||
@ -117,7 +119,8 @@ final class BlockStateData{
|
||||
return CompoundTag::create()
|
||||
->setString(self::TAG_NAME, $this->name)
|
||||
->setInt(self::TAG_VERSION, $this->version)
|
||||
->setTag(self::TAG_STATES, $statesTag);
|
||||
->setTag(self::TAG_STATES, $statesTag)
|
||||
->setLong(VersionInfo::TAG_WORLD_DATA_VERSION, VersionInfo::WORLD_DATA_VERSION);
|
||||
}
|
||||
|
||||
public function equals(self $that) : bool{
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\data\bedrock\item;
|
||||
|
||||
use pocketmine\data\bedrock\block\BlockStateData;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\VersionInfo;
|
||||
|
||||
final class SavedItemData{
|
||||
|
||||
@ -59,6 +60,7 @@ final class SavedItemData{
|
||||
if($this->tag !== null){
|
||||
$result->setTag(self::TAG_TAG, $this->tag);
|
||||
}
|
||||
$result->setLong(VersionInfo::TAG_WORLD_DATA_VERSION, VersionInfo::WORLD_DATA_VERSION);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
@ -149,6 +149,7 @@ final class ItemDataUpgrader{
|
||||
[$newNameId, $newMeta] = $this->idMetaUpgrader->upgrade($rawNameId, $meta);
|
||||
|
||||
//TODO: this won't account for spawn eggs from before 1.16.100 - perhaps we're lucky and they just left the meta in there anyway?
|
||||
//TODO: read version from VersionInfo::TAG_WORLD_DATA_VERSION - we may need it to fix up old items
|
||||
|
||||
return new SavedItemData($newNameId, $newMeta, $blockStateData, $tag->getCompoundTag(SavedItemData::TAG_TAG));
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ use pocketmine\Server;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\VersionInfo;
|
||||
use pocketmine\world\format\Chunk;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\sound\Sound;
|
||||
@ -489,6 +490,8 @@ abstract class Entity{
|
||||
$nbt->setShort(self::TAG_FIRE, $this->fireTicks);
|
||||
$nbt->setByte(self::TAG_ON_GROUND, $this->onGround ? 1 : 0);
|
||||
|
||||
$nbt->setLong(VersionInfo::TAG_WORLD_DATA_VERSION, VersionInfo::WORLD_DATA_VERSION);
|
||||
|
||||
return $nbt;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ use pocketmine\nbt\TreeRoot;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\Filesystem;
|
||||
use pocketmine\utils\Limits;
|
||||
use pocketmine\VersionInfo;
|
||||
use pocketmine\world\format\io\exception\CorruptedWorldException;
|
||||
use pocketmine\world\format\io\exception\UnsupportedWorldFormatException;
|
||||
use pocketmine\world\generator\Flat;
|
||||
@ -201,6 +202,7 @@ class BedrockWorldData extends BaseNbtWorldData{
|
||||
$this->compoundTag->setInt(self::TAG_NETWORK_VERSION, self::CURRENT_STORAGE_NETWORK_VERSION);
|
||||
$this->compoundTag->setInt(self::TAG_STORAGE_VERSION, self::CURRENT_STORAGE_VERSION);
|
||||
$this->compoundTag->setTag(self::TAG_LAST_OPENED_WITH_VERSION, new ListTag(array_map(fn(int $v) => new IntTag($v), self::CURRENT_CLIENT_VERSION_TARGET)));
|
||||
$this->compoundTag->setLong(VersionInfo::TAG_WORLD_DATA_VERSION, VersionInfo::WORLD_DATA_VERSION);
|
||||
|
||||
$nbt = new LittleEndianNbtSerializer();
|
||||
$buffer = $nbt->write(new TreeRoot($this->compoundTag));
|
||||
|
@ -30,6 +30,7 @@ use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\nbt\TreeRoot;
|
||||
use pocketmine\utils\Filesystem;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\VersionInfo;
|
||||
use pocketmine\world\format\io\exception\CorruptedWorldException;
|
||||
use pocketmine\world\generator\GeneratorManager;
|
||||
use pocketmine\world\World;
|
||||
@ -126,6 +127,8 @@ class JavaWorldData extends BaseNbtWorldData{
|
||||
}
|
||||
|
||||
public function save() : void{
|
||||
$this->compoundTag->setLong(VersionInfo::TAG_WORLD_DATA_VERSION, VersionInfo::WORLD_DATA_VERSION);
|
||||
|
||||
$nbt = new BigEndianNbtSerializer();
|
||||
$buffer = Utils::assumeNotFalse(zlib_encode($nbt->write(new TreeRoot(CompoundTag::create()->setTag(self::TAG_ROOT_DATA, $this->compoundTag))), ZLIB_ENCODING_GZIP));
|
||||
Filesystem::safeFilePutContents($this->dataPath, $buffer);
|
||||
|
@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\world\format\io\leveldb;
|
||||
|
||||
use pocketmine\VersionInfo;
|
||||
|
||||
final class ChunkDataKey{
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
@ -50,4 +52,6 @@ final class ChunkDataKey{
|
||||
|
||||
public const OLD_VERSION = "\x76";
|
||||
|
||||
public const PM_DATA_VERSION = VersionInfo::TAG_WORLD_DATA_VERSION;
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ use pocketmine\nbt\TreeRoot;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\BinaryDataException;
|
||||
use pocketmine\utils\BinaryStream;
|
||||
use pocketmine\VersionInfo;
|
||||
use pocketmine\world\format\Chunk;
|
||||
use pocketmine\world\format\io\BaseWorldProvider;
|
||||
use pocketmine\world\format\io\ChunkData;
|
||||
@ -601,6 +602,8 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
||||
return null;
|
||||
}
|
||||
|
||||
//TODO: read PM_DATA_VERSION - we'll need it to fix up old chunks
|
||||
|
||||
$logger = new \PrefixedLogger($this->logger, "Loading chunk x=$chunkX z=$chunkZ v$chunkVersion");
|
||||
|
||||
$hasBeenUpgraded = $chunkVersion < self::CURRENT_LEVEL_CHUNK_VERSION;
|
||||
@ -710,6 +713,7 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
||||
$write = new \LevelDBWriteBatch();
|
||||
|
||||
$write->put($index . ChunkDataKey::NEW_VERSION, chr(self::CURRENT_LEVEL_CHUNK_VERSION));
|
||||
$write->put($index . ChunkDataKey::PM_DATA_VERSION, Binary::writeLLong(VersionInfo::WORLD_DATA_VERSION));
|
||||
|
||||
$chunk = $chunkData->getChunk();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user