mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-12 00:39:45 +00:00
Discard light information from disk storage
this makes world conversion faster and offers the opportunity to correct age-old lighting bugs.
This commit is contained in:
parent
6e00ab2069
commit
1bb9b3d3ab
@ -2663,7 +2663,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
|
||||
(new ChunkLoadEvent($this, $chunk, !$chunk->isGenerated()))->call();
|
||||
|
||||
if(!$chunk->isLightPopulated() and $chunk->isPopulated() and $this->getServer()->getProperty("chunk-ticking.light-updates", false)){
|
||||
if($chunk->isPopulated() and $this->getServer()->getProperty("chunk-ticking.light-updates", false)){
|
||||
$this->getServer()->getAsyncPool()->submitTask(new LightPopulationTask($this, $chunk));
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ use function file_exists;
|
||||
use function is_dir;
|
||||
use function mkdir;
|
||||
use function ord;
|
||||
use function pack;
|
||||
use function str_repeat;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
use function unpack;
|
||||
@ -146,14 +146,9 @@ class LevelDB extends BaseLevelProvider{
|
||||
/** @var SubChunk[] $subChunks */
|
||||
$subChunks = [];
|
||||
|
||||
/** @var int[] $heightMap */
|
||||
$heightMap = [];
|
||||
/** @var string $biomeIds */
|
||||
$biomeIds = "";
|
||||
|
||||
/** @var bool $lightPopulated */
|
||||
$lightPopulated = true;
|
||||
|
||||
$chunkVersion = ord($this->db->get($index . self::TAG_VERSION));
|
||||
|
||||
$binaryStream = new BinaryStream();
|
||||
@ -179,20 +174,15 @@ class LevelDB extends BaseLevelProvider{
|
||||
try{
|
||||
$blocks = $binaryStream->get(4096);
|
||||
$blockData = $binaryStream->get(2048);
|
||||
|
||||
if($chunkVersion < 4){
|
||||
$blockSkyLight = $binaryStream->get(2048);
|
||||
$blockLight = $binaryStream->get(2048);
|
||||
}else{
|
||||
//Mojang didn't bother changing the subchunk version when they stopped saving sky light -_-
|
||||
$blockSkyLight = "";
|
||||
$blockLight = "";
|
||||
$lightPopulated = false;
|
||||
$binaryStream->get(4096); //legacy light info, discard it
|
||||
}
|
||||
}catch(BinaryDataException $e){
|
||||
throw new CorruptedChunkException($e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
$subChunks[$y] = new SubChunk($blocks, $blockData, $blockSkyLight, $blockLight);
|
||||
$subChunks[$y] = new SubChunk($blocks, $blockData);
|
||||
break;
|
||||
default:
|
||||
//TODO: set chunks read-only so the version on disk doesn't get overwritten
|
||||
@ -204,7 +194,7 @@ class LevelDB extends BaseLevelProvider{
|
||||
$binaryStream->setBuffer($maps2d);
|
||||
|
||||
try{
|
||||
$heightMap = array_values(unpack("v*", $binaryStream->get(512)));
|
||||
$binaryStream->get(512); //heightmap, discard it
|
||||
$biomeIds = $binaryStream->get(256);
|
||||
}catch(BinaryDataException $e){
|
||||
throw new CorruptedChunkException($e->getMessage(), 0, $e);
|
||||
@ -220,8 +210,7 @@ class LevelDB extends BaseLevelProvider{
|
||||
try{
|
||||
$fullIds = $binaryStream->get(32768);
|
||||
$fullData = $binaryStream->get(16384);
|
||||
$fullSkyLight = $binaryStream->get(16384);
|
||||
$fullBlockLight = $binaryStream->get(16384);
|
||||
$binaryStream->get(32768); //legacy light info, discard it
|
||||
}catch(BinaryDataException $e){
|
||||
throw new CorruptedChunkException($e->getMessage(), 0, $e);
|
||||
}
|
||||
@ -239,23 +228,12 @@ class LevelDB extends BaseLevelProvider{
|
||||
$data .= substr($fullData, $subOffset, 8);
|
||||
$subOffset += 64;
|
||||
}
|
||||
$skyLight = "";
|
||||
$subOffset = ($yy << 3);
|
||||
for($i = 0; $i < 256; ++$i){
|
||||
$skyLight .= substr($fullSkyLight, $subOffset, 8);
|
||||
$subOffset += 64;
|
||||
}
|
||||
$blockLight = "";
|
||||
$subOffset = ($yy << 3);
|
||||
for($i = 0; $i < 256; ++$i){
|
||||
$blockLight .= substr($fullBlockLight, $subOffset, 8);
|
||||
$subOffset += 64;
|
||||
}
|
||||
$subChunks[$yy] = new SubChunk($ids, $data, $skyLight, $blockLight);
|
||||
|
||||
$subChunks[$yy] = new SubChunk($ids, $data);
|
||||
}
|
||||
|
||||
try{
|
||||
$heightMap = array_values(unpack("C*", $binaryStream->get(256)));
|
||||
$binaryStream->get(256); //heightmap, discard it
|
||||
$biomeIds = ChunkUtils::convertBiomeColors(array_values(unpack("N*", $binaryStream->get(1024))));
|
||||
}catch(BinaryDataException $e){
|
||||
throw new CorruptedChunkException($e->getMessage(), 0, $e);
|
||||
@ -307,15 +285,13 @@ class LevelDB extends BaseLevelProvider{
|
||||
$subChunks,
|
||||
$entities,
|
||||
$tiles,
|
||||
$biomeIds,
|
||||
$heightMap
|
||||
$biomeIds
|
||||
);
|
||||
|
||||
//TODO: tile ticks, biome states (?)
|
||||
|
||||
$chunk->setGenerated(true);
|
||||
$chunk->setPopulated(true);
|
||||
$chunk->setLightPopulated($lightPopulated);
|
||||
$chunk->setGenerated();
|
||||
$chunk->setPopulated();
|
||||
|
||||
return $chunk;
|
||||
}
|
||||
@ -338,7 +314,7 @@ class LevelDB extends BaseLevelProvider{
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->put($index . self::TAG_DATA_2D, pack("v*", ...$chunk->getHeightMapArray()) . $chunk->getBiomeIdArray());
|
||||
$this->db->put($index . self::TAG_DATA_2D, str_repeat("\x00", 512) . $chunk->getBiomeIdArray());
|
||||
|
||||
//TODO: use this properly
|
||||
$this->db->put($index . self::TAG_STATE_FINALISATION, chr(self::FINALISATION_DONE));
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\level\format\io\ChunkUtils;
|
||||
use pocketmine\level\format\SubChunk;
|
||||
use pocketmine\nbt\tag\ByteArrayTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use function str_repeat;
|
||||
|
||||
class Anvil extends RegionLevelProvider{
|
||||
use LegacyAnvilChunkTrait;
|
||||
@ -35,17 +36,16 @@ class Anvil extends RegionLevelProvider{
|
||||
return new CompoundTag("", [
|
||||
new ByteArrayTag("Blocks", ChunkUtils::reorderByteArray($subChunk->getBlockIdArray())), //Generic in-memory chunks are currently always XZY
|
||||
new ByteArrayTag("Data", ChunkUtils::reorderNibbleArray($subChunk->getBlockDataArray())),
|
||||
new ByteArrayTag("SkyLight", ChunkUtils::reorderNibbleArray($subChunk->getBlockSkyLightArray(), "\xff")),
|
||||
new ByteArrayTag("BlockLight", ChunkUtils::reorderNibbleArray($subChunk->getBlockLightArray()))
|
||||
new ByteArrayTag("SkyLight", str_repeat("\x00", 2048)),
|
||||
new ByteArrayTag("BlockLight", str_repeat("\x00", 2048))
|
||||
]);
|
||||
}
|
||||
|
||||
protected function deserializeSubChunk(CompoundTag $subChunk) : SubChunk{
|
||||
return new SubChunk(
|
||||
ChunkUtils::reorderByteArray($subChunk->getByteArray("Blocks")),
|
||||
ChunkUtils::reorderNibbleArray($subChunk->getByteArray("Data")),
|
||||
ChunkUtils::reorderNibbleArray($subChunk->getByteArray("SkyLight"), "\xff"),
|
||||
ChunkUtils::reorderNibbleArray($subChunk->getByteArray("BlockLight"))
|
||||
ChunkUtils::reorderNibbleArray($subChunk->getByteArray("Data"))
|
||||
//ignore legacy light information
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ use pocketmine\nbt\NbtDataException;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntArrayTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use function array_fill;
|
||||
|
||||
/**
|
||||
* Trait containing I/O methods for handling legacy Anvil-style chunks.
|
||||
@ -56,7 +57,7 @@ trait LegacyAnvilChunkTrait{
|
||||
$nbt->setLong("LastUpdate", 0); //TODO
|
||||
$nbt->setLong("InhabitedTime", 0); //TODO
|
||||
$nbt->setByte("TerrainPopulated", $chunk->isPopulated() ? 1 : 0);
|
||||
$nbt->setByte("LightPopulated", $chunk->isLightPopulated() ? 1 : 0);
|
||||
$nbt->setByte("LightPopulated", 0);
|
||||
|
||||
$subChunks = [];
|
||||
foreach($chunk->getSubChunks() as $y => $subChunk){
|
||||
@ -71,7 +72,7 @@ trait LegacyAnvilChunkTrait{
|
||||
$nbt->setTag(new ListTag("Sections", $subChunks, NBT::TAG_Compound));
|
||||
|
||||
$nbt->setByteArray("Biomes", $chunk->getBiomeIdArray());
|
||||
$nbt->setIntArray("HeightMap", $chunk->getHeightMapArray());
|
||||
$nbt->setIntArray("HeightMap", array_fill(0, 256, 0));
|
||||
|
||||
$nbt->setTag(new ListTag("Entities", $chunk->getNBTentities(), NBT::TAG_Compound));
|
||||
$nbt->setTag(new ListTag("TileEntities", $chunk->getNBTtiles(), NBT::TAG_Compound));
|
||||
@ -123,10 +124,8 @@ trait LegacyAnvilChunkTrait{
|
||||
$subChunks,
|
||||
$chunk->hasTag("Entities", ListTag::class) ? $chunk->getListTag("Entities")->getValue() : [],
|
||||
$chunk->hasTag("TileEntities", ListTag::class) ? $chunk->getListTag("TileEntities")->getValue() : [],
|
||||
$biomeIds,
|
||||
$chunk->getIntArray("HeightMap", [])
|
||||
$biomeIds
|
||||
);
|
||||
$result->setLightPopulated($chunk->getByte("LightPopulated", 0) !== 0);
|
||||
$result->setPopulated($chunk->getByte("TerrainPopulated", 0) !== 0);
|
||||
$result->setGenerated();
|
||||
return $result;
|
||||
|
@ -34,11 +34,8 @@ use pocketmine\nbt\tag\ByteArrayTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntArrayTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use function array_values;
|
||||
use function pack;
|
||||
use function str_repeat;
|
||||
use function substr;
|
||||
use function unpack;
|
||||
|
||||
class McRegion extends RegionLevelProvider{
|
||||
|
||||
@ -54,12 +51,10 @@ class McRegion extends RegionLevelProvider{
|
||||
|
||||
$nbt->setLong("LastUpdate", 0); //TODO
|
||||
$nbt->setByte("TerrainPopulated", $chunk->isPopulated() ? 1 : 0);
|
||||
$nbt->setByte("LightPopulated", $chunk->isLightPopulated() ? 1 : 0);
|
||||
$nbt->setByte("LightPopulated", 0);
|
||||
|
||||
$ids = "";
|
||||
$data = "";
|
||||
$skyLight = "";
|
||||
$blockLight = "";
|
||||
$subChunks = $chunk->getSubChunks();
|
||||
for($x = 0; $x < 16; ++$x){
|
||||
for($z = 0; $z < 16; ++$z){
|
||||
@ -67,19 +62,17 @@ class McRegion extends RegionLevelProvider{
|
||||
$subChunk = $subChunks[$y];
|
||||
$ids .= substr($subChunk->getBlockIdArray(), ($x << 8) | ($z << 4), 16);
|
||||
$data .= substr($subChunk->getBlockDataArray(), ($x << 7) | ($z << 3), 8);
|
||||
$skyLight .= substr($subChunk->getBlockSkyLightArray(), ($x << 7) | ($z << 3), 8);
|
||||
$blockLight .= substr($subChunk->getBlockLightArray(), ($x << 7) | ($z << 3), 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$nbt->setByteArray("Blocks", $ids);
|
||||
$nbt->setByteArray("Data", $data);
|
||||
$nbt->setByteArray("SkyLight", $skyLight);
|
||||
$nbt->setByteArray("BlockLight", $blockLight);
|
||||
$nbt->setByteArray("SkyLight", str_repeat("\x00", 16384));
|
||||
$nbt->setByteArray("BlockLight", str_repeat("\x00", 16384));
|
||||
|
||||
$nbt->setByteArray("Biomes", $chunk->getBiomeIdArray()); //doesn't exist in regular McRegion, this is here for PocketMine-MP only
|
||||
$nbt->setByteArray("HeightMap", pack("C*", ...$chunk->getHeightMapArray())); //this is ByteArray in McRegion, but IntArray in Anvil (due to raised build height)
|
||||
$nbt->setByteArray("HeightMap", str_repeat("\x00", 256)); //this is ByteArray in McRegion, but IntArray in Anvil (due to raised build height)
|
||||
|
||||
$nbt->setTag(new ListTag("Entities", $chunk->getNBTentities(), NBT::TAG_Compound));
|
||||
$nbt->setTag(new ListTag("TileEntities", $chunk->getNBTtiles(), NBT::TAG_Compound));
|
||||
@ -110,8 +103,6 @@ class McRegion extends RegionLevelProvider{
|
||||
$subChunks = [];
|
||||
$fullIds = $chunk->hasTag("Blocks", ByteArrayTag::class) ? $chunk->getByteArray("Blocks") : str_repeat("\x00", 32768);
|
||||
$fullData = $chunk->hasTag("Data", ByteArrayTag::class) ? $chunk->getByteArray("Data") : str_repeat("\x00", 16384);
|
||||
$fullSkyLight = $chunk->hasTag("SkyLight", ByteArrayTag::class) ? $chunk->getByteArray("SkyLight") : str_repeat("\xff", 16384);
|
||||
$fullBlockLight = $chunk->hasTag("BlockLight", ByteArrayTag::class) ? $chunk->getByteArray("BlockLight") : str_repeat("\x00", 16384);
|
||||
|
||||
for($y = 0; $y < 8; ++$y){
|
||||
$offset = ($y << 4);
|
||||
@ -126,19 +117,7 @@ class McRegion extends RegionLevelProvider{
|
||||
$data .= substr($fullData, $offset, 8);
|
||||
$offset += 64;
|
||||
}
|
||||
$skyLight = "";
|
||||
$offset = ($y << 3);
|
||||
for($i = 0; $i < 256; ++$i){
|
||||
$skyLight .= substr($fullSkyLight, $offset, 8);
|
||||
$offset += 64;
|
||||
}
|
||||
$blockLight = "";
|
||||
$offset = ($y << 3);
|
||||
for($i = 0; $i < 256; ++$i){
|
||||
$blockLight .= substr($fullBlockLight, $offset, 8);
|
||||
$offset += 64;
|
||||
}
|
||||
$subChunks[$y] = new SubChunk($ids, $data, $skyLight, $blockLight);
|
||||
$subChunks[$y] = new SubChunk($ids, $data);
|
||||
}
|
||||
|
||||
if($chunk->hasTag("BiomeColors", IntArrayTag::class)){
|
||||
@ -149,23 +128,14 @@ class McRegion extends RegionLevelProvider{
|
||||
$biomeIds = "";
|
||||
}
|
||||
|
||||
$heightMap = [];
|
||||
if($chunk->hasTag("HeightMap", ByteArrayTag::class)){
|
||||
$heightMap = array_values(unpack("C*", $chunk->getByteArray("HeightMap")));
|
||||
}elseif($chunk->hasTag("HeightMap", IntArrayTag::class)){
|
||||
$heightMap = $chunk->getIntArray("HeightMap"); #blameshoghicp
|
||||
}
|
||||
|
||||
$result = new Chunk(
|
||||
$chunk->getInt("xPos"),
|
||||
$chunk->getInt("zPos"),
|
||||
$subChunks,
|
||||
$chunk->hasTag("Entities", ListTag::class) ? $chunk->getListTag("Entities")->getValue() : [],
|
||||
$chunk->hasTag("TileEntities", ListTag::class) ? $chunk->getListTag("TileEntities")->getValue() : [],
|
||||
$biomeIds,
|
||||
$heightMap
|
||||
$biomeIds
|
||||
);
|
||||
$result->setLightPopulated($chunk->getByte("LightPopulated", 0) !== 0);
|
||||
$result->setPopulated($chunk->getByte("TerrainPopulated", 0) !== 0);
|
||||
$result->setGenerated(true);
|
||||
return $result;
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\level\format\io\region;
|
||||
use pocketmine\level\format\SubChunk;
|
||||
use pocketmine\nbt\tag\ByteArrayTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use function str_repeat;
|
||||
|
||||
/**
|
||||
* This format is exactly the same as the PC Anvil format, with the only difference being that the stored data order
|
||||
@ -38,17 +39,15 @@ class PMAnvil extends RegionLevelProvider{
|
||||
return new CompoundTag("", [
|
||||
new ByteArrayTag("Blocks", $subChunk->getBlockIdArray()),
|
||||
new ByteArrayTag("Data", $subChunk->getBlockDataArray()),
|
||||
new ByteArrayTag("SkyLight", $subChunk->getBlockSkyLightArray()),
|
||||
new ByteArrayTag("BlockLight", $subChunk->getBlockLightArray())
|
||||
new ByteArrayTag("SkyLight", str_repeat("\x00", 2048)),
|
||||
new ByteArrayTag("BlockLight", str_repeat("\x00", 2048))
|
||||
]);
|
||||
}
|
||||
|
||||
protected function deserializeSubChunk(CompoundTag $subChunk) : SubChunk{
|
||||
return new SubChunk(
|
||||
$subChunk->getByteArray("Blocks"),
|
||||
$subChunk->getByteArray("Data"),
|
||||
$subChunk->getByteArray("SkyLight"),
|
||||
$subChunk->getByteArray("BlockLight")
|
||||
$subChunk->getByteArray("Data")
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user