mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-03 08:39:53 +00:00
LevelDB: Added conversion of legacy extradata -> 4D subchunk block layers
This commit is contained in:
parent
f7a9da4e92
commit
0f398bbe66
@ -183,6 +183,47 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
return PalettedBlockArray::fromData($bitsPerBlock, $words, $palette);
|
return PalettedBlockArray::fromData($bitsPerBlock, $words, $palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static function deserializeExtraDataKey(int $chunkVersion, int $key, ?int &$x, ?int &$y, ?int &$z) : void{
|
||||||
|
if($chunkVersion >= 3){
|
||||||
|
$x = ($key >> 12) & 0xf;
|
||||||
|
$z = ($key >> 8) & 0xf;
|
||||||
|
$y = $key & 0xff;
|
||||||
|
}else{ //pre-1.0, 7 bits were used because the build height limit was lower
|
||||||
|
$x = ($key >> 11) & 0xf;
|
||||||
|
$z = ($key >> 7) & 0xf;
|
||||||
|
$y = $key & 0x7f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function deserializeLegacyExtraData(string $index, int $chunkVersion) : array{
|
||||||
|
if(($extraRawData = $this->db->get($index . self::TAG_BLOCK_EXTRA_DATA)) === false or $extraRawData === ""){
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var PalettedBlockArray[] $extraDataLayers */
|
||||||
|
$extraDataLayers = [];
|
||||||
|
$binaryStream = new BinaryStream($extraRawData);
|
||||||
|
$count = $binaryStream->getLInt();
|
||||||
|
for($i = 0; $i < $count; ++$i){
|
||||||
|
$key = $binaryStream->getLInt();
|
||||||
|
$value = $binaryStream->getLShort();
|
||||||
|
|
||||||
|
self::deserializeExtraDataKey($chunkVersion, $key, $x, $fullY, $z);
|
||||||
|
|
||||||
|
$ySub = ($fullY >> 4) & 0xf;
|
||||||
|
$y = $key & 0xf;
|
||||||
|
|
||||||
|
$blockId = $value & 0xff;
|
||||||
|
$blockData = ($value >> 8) & 0xf;
|
||||||
|
if(!isset($extraDataLayers[$ySub])){
|
||||||
|
$extraDataLayers[$ySub] = new PalettedBlockArray(BlockLegacyIds::AIR << 4);
|
||||||
|
}
|
||||||
|
$extraDataLayers[$ySub]->set($x, $y, $z, ($blockId << 4) | $blockData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $extraDataLayers;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $chunkX
|
* @param int $chunkX
|
||||||
* @param int $chunkZ
|
* @param int $chunkZ
|
||||||
@ -216,6 +257,9 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
case 4: //MCPE 1.1
|
case 4: //MCPE 1.1
|
||||||
//TODO: check beds
|
//TODO: check beds
|
||||||
case 3: //MCPE 1.0
|
case 3: //MCPE 1.0
|
||||||
|
/** @var PalettedBlockArray[] $convertedLegacyExtraData */
|
||||||
|
$convertedLegacyExtraData = $this->deserializeLegacyExtraData($index, $chunkVersion);
|
||||||
|
|
||||||
for($y = 0; $y < Chunk::MAX_SUBCHUNKS; ++$y){
|
for($y = 0; $y < Chunk::MAX_SUBCHUNKS; ++$y){
|
||||||
if(($data = $this->db->get($index . self::TAG_SUBCHUNK_PREFIX . chr($y))) === false){
|
if(($data = $this->db->get($index . self::TAG_SUBCHUNK_PREFIX . chr($y))) === false){
|
||||||
continue;
|
continue;
|
||||||
@ -250,17 +294,31 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
throw new CorruptedChunkException($e->getMessage(), 0, $e);
|
throw new CorruptedChunkException($e->getMessage(), 0, $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
$subChunks[$y] = new SubChunk([SubChunkConverter::convertSubChunkXZY($blocks, $blockData)]);
|
$storages = [SubChunkConverter::convertSubChunkXZY($blocks, $blockData)];
|
||||||
|
if(isset($convertedLegacyExtraData[$y])){
|
||||||
|
$storages[] = $convertedLegacyExtraData[$y];
|
||||||
|
}
|
||||||
|
|
||||||
|
$subChunks[$y] = new SubChunk($storages);
|
||||||
break;
|
break;
|
||||||
case 1: //paletted v1, has a single blockstorage
|
case 1: //paletted v1, has a single blockstorage
|
||||||
$subChunks[$y] = new SubChunk([$this->deserializePaletted($binaryStream)]);
|
$storages = [$this->deserializePaletted($binaryStream)];
|
||||||
|
if(isset($convertedLegacyExtraData[$y])){
|
||||||
|
$storages[] = $convertedLegacyExtraData[$y];
|
||||||
|
}
|
||||||
|
$subChunks[$y] = new SubChunk($storages);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
|
//legacy extradata layers intentionally ignored because they aren't supposed to exist in v8
|
||||||
|
$storageCount = $binaryStream->getByte();
|
||||||
|
if($storageCount > 0){
|
||||||
$storages = [];
|
$storages = [];
|
||||||
for($k = 0, $storageCount = $binaryStream->getByte(); $k < $storageCount; ++$k){
|
|
||||||
|
for($k = 0; $k < $storageCount; ++$k){
|
||||||
$storages[] = $this->deserializePaletted($binaryStream);
|
$storages[] = $this->deserializePaletted($binaryStream);
|
||||||
}
|
}
|
||||||
$subChunks[$y] = new SubChunk($storages);
|
$subChunks[$y] = new SubChunk($storages);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//TODO: set chunks read-only so the version on disk doesn't get overwritten
|
//TODO: set chunks read-only so the version on disk doesn't get overwritten
|
||||||
@ -280,6 +338,9 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: // < MCPE 1.0
|
case 2: // < MCPE 1.0
|
||||||
|
/** @var PalettedBlockArray[] $extraDataLayers */
|
||||||
|
$convertedLegacyExtraData = $this->deserializeLegacyExtraData($index, $chunkVersion);
|
||||||
|
|
||||||
$legacyTerrain = $this->db->get($index . self::TAG_LEGACY_TERRAIN);
|
$legacyTerrain = $this->db->get($index . self::TAG_LEGACY_TERRAIN);
|
||||||
if($legacyTerrain === false){
|
if($legacyTerrain === false){
|
||||||
throw new CorruptedChunkException("Missing expected LEGACY_TERRAIN tag for format version $chunkVersion");
|
throw new CorruptedChunkException("Missing expected LEGACY_TERRAIN tag for format version $chunkVersion");
|
||||||
@ -294,7 +355,11 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
}
|
}
|
||||||
|
|
||||||
for($yy = 0; $yy < 8; ++$yy){
|
for($yy = 0; $yy < 8; ++$yy){
|
||||||
$subChunks[$yy] = new SubChunk([SubChunkConverter::convertSubChunkFromLegacyColumn($fullIds, $fullData, $yy)]);
|
$storages = [SubChunkConverter::convertSubChunkFromLegacyColumn($fullIds, $fullData, $yy)];
|
||||||
|
if(isset($convertedLegacyExtraData[$yy])){
|
||||||
|
$storages[] = $convertedLegacyExtraData[$yy];
|
||||||
|
}
|
||||||
|
$subChunks[$yy] = new SubChunk($storages);
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
@ -331,19 +396,6 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: extra data should be converted into blockstorage layers (first they need to be implemented!)
|
|
||||||
/*
|
|
||||||
$extraData = [];
|
|
||||||
if(($extraRawData = $this->db->get($index . self::TAG_BLOCK_EXTRA_DATA)) !== false and $extraRawData !== ""){
|
|
||||||
$binaryStream->setBuffer($extraRawData, 0);
|
|
||||||
$count = $binaryStream->getLInt();
|
|
||||||
for($i = 0; $i < $count; ++$i){
|
|
||||||
$key = $binaryStream->getLInt();
|
|
||||||
$value = $binaryStream->getLShort();
|
|
||||||
$extraData[$key] = $value;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
$chunk = new Chunk(
|
$chunk = new Chunk(
|
||||||
$chunkX,
|
$chunkX,
|
||||||
$chunkZ,
|
$chunkZ,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user