mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-22 00:33:59 +00:00
Chunks no longer exist in un-generated state
a non-generated chunk is now always represented by NULL. This forces the case of ungenerated chunks to be handled by all code, which is necessary because ungenerated chunks cannot be interacted with or modified in any meaningful way.
This commit is contained in:
parent
05ab44f768
commit
b9cd633cee
@ -936,7 +936,6 @@ class World implements ChunkManager{
|
||||
$hash = World::chunkHash($dx + $chunkX, $dz + $chunkZ);
|
||||
if(!isset($chunkTickList[$hash]) and isset($this->chunks[$hash])){
|
||||
if(
|
||||
!$this->chunks[$hash]->isGenerated() ||
|
||||
!$this->chunks[$hash]->isPopulated() ||
|
||||
$this->isChunkLocked($dx + $chunkX, $dz + $chunkZ)
|
||||
){
|
||||
@ -1025,7 +1024,7 @@ class World implements ChunkManager{
|
||||
$this->timings->syncChunkSaveTimer->startTiming();
|
||||
try{
|
||||
foreach($this->chunks as $chunkHash => $chunk){
|
||||
if($chunk->isDirty() and $chunk->isGenerated()){
|
||||
if($chunk->isDirty()){
|
||||
self::getXZ($chunkHash, $chunkX, $chunkZ);
|
||||
$this->provider->saveChunk($chunkX, $chunkZ, $chunk);
|
||||
$chunk->clearDirtyFlags();
|
||||
@ -2085,8 +2084,7 @@ class World implements ChunkManager{
|
||||
}
|
||||
|
||||
public function isChunkGenerated(int $x, int $z) : bool{
|
||||
$chunk = $this->loadChunk($x, $z);
|
||||
return $chunk !== null ? $chunk->isGenerated() : false;
|
||||
return $this->loadChunk($x, $z) !== null;
|
||||
}
|
||||
|
||||
public function isChunkPopulated(int $x, int $z) : bool{
|
||||
@ -2337,7 +2335,7 @@ class World implements ChunkManager{
|
||||
return false;
|
||||
}
|
||||
|
||||
if($trySave and $this->getAutoSave() and $chunk->isGenerated() and $chunk->isDirty()){
|
||||
if($trySave and $this->getAutoSave() and $chunk->isDirty()){
|
||||
$this->timings->syncChunkSaveTimer->startTiming();
|
||||
try{
|
||||
$this->provider->saveChunk($x, $z, $chunk);
|
||||
@ -2384,7 +2382,7 @@ class World implements ChunkManager{
|
||||
$max = $this->worldHeight;
|
||||
$v = $spawn->floor();
|
||||
$chunk = $this->getOrLoadChunkAtPosition($v);
|
||||
if($chunk === null || !$chunk->isGenerated()){
|
||||
if($chunk === null){
|
||||
throw new WorldException("Cannot find a safe spawn point in non-generated terrain");
|
||||
}
|
||||
$x = (int) $v->x;
|
||||
|
@ -51,8 +51,6 @@ class Chunk{
|
||||
/** @var bool|null */
|
||||
protected $lightPopulated = false;
|
||||
/** @var bool */
|
||||
protected $terrainGenerated = false;
|
||||
/** @var bool */
|
||||
protected $terrainPopulated = false;
|
||||
|
||||
/**
|
||||
@ -207,15 +205,6 @@ class Chunk{
|
||||
$this->dirtyFlags |= self::DIRTY_FLAG_TERRAIN;
|
||||
}
|
||||
|
||||
public function isGenerated() : bool{
|
||||
return $this->terrainGenerated;
|
||||
}
|
||||
|
||||
public function setGenerated(bool $value = true) : void{
|
||||
$this->terrainGenerated = $value;
|
||||
$this->dirtyFlags |= self::DIRTY_FLAG_TERRAIN;
|
||||
}
|
||||
|
||||
public function addEntity(Entity $entity) : void{
|
||||
if($entity->isClosed()){
|
||||
throw new \InvalidArgumentException("Attempted to add a garbage closed Entity to a chunk");
|
||||
|
@ -67,9 +67,6 @@ abstract class BaseWorldProvider implements WorldProvider{
|
||||
}
|
||||
|
||||
public function saveChunk(int $chunkX, int $chunkZ, Chunk $chunk) : void{
|
||||
if(!$chunk->isGenerated()){
|
||||
throw new \InvalidStateException("Cannot save un-generated chunk");
|
||||
}
|
||||
$this->writeChunk($chunkX, $chunkZ, $chunk);
|
||||
}
|
||||
|
||||
|
@ -63,44 +63,42 @@ final class FastChunkSerializer{
|
||||
$stream = new BinaryStream();
|
||||
$stream->putByte(
|
||||
($includeLight ? self::FLAG_HAS_LIGHT : 0) |
|
||||
($chunk->isPopulated() ? self::FLAG_POPULATED : 0) |
|
||||
($chunk->isGenerated() ? self::FLAG_GENERATED : 0)
|
||||
($chunk->isPopulated() ? self::FLAG_POPULATED : 0)
|
||||
);
|
||||
if($chunk->isGenerated()){
|
||||
//subchunks
|
||||
$subChunks = $chunk->getSubChunks();
|
||||
$count = $subChunks->count();
|
||||
$stream->putByte($count);
|
||||
|
||||
foreach($subChunks as $y => $subChunk){
|
||||
$stream->putByte($y);
|
||||
$stream->putInt($subChunk->getEmptyBlockId());
|
||||
$layers = $subChunk->getBlockLayers();
|
||||
$stream->putByte(count($layers));
|
||||
foreach($layers as $blocks){
|
||||
$wordArray = $blocks->getWordArray();
|
||||
$palette = $blocks->getPalette();
|
||||
//subchunks
|
||||
$subChunks = $chunk->getSubChunks();
|
||||
$count = $subChunks->count();
|
||||
$stream->putByte($count);
|
||||
|
||||
$stream->putByte($blocks->getBitsPerBlock());
|
||||
$stream->put($wordArray);
|
||||
$serialPalette = pack("L*", ...$palette);
|
||||
$stream->putInt(strlen($serialPalette));
|
||||
$stream->put($serialPalette);
|
||||
}
|
||||
foreach($subChunks as $y => $subChunk){
|
||||
$stream->putByte($y);
|
||||
$stream->putInt($subChunk->getEmptyBlockId());
|
||||
$layers = $subChunk->getBlockLayers();
|
||||
$stream->putByte(count($layers));
|
||||
foreach($layers as $blocks){
|
||||
$wordArray = $blocks->getWordArray();
|
||||
$palette = $blocks->getPalette();
|
||||
|
||||
if($includeLight){
|
||||
$stream->put($subChunk->getBlockSkyLightArray()->getData());
|
||||
$stream->put($subChunk->getBlockLightArray()->getData());
|
||||
}
|
||||
$stream->putByte($blocks->getBitsPerBlock());
|
||||
$stream->put($wordArray);
|
||||
$serialPalette = pack("L*", ...$palette);
|
||||
$stream->putInt(strlen($serialPalette));
|
||||
$stream->put($serialPalette);
|
||||
}
|
||||
|
||||
//biomes
|
||||
$stream->put($chunk->getBiomeIdArray());
|
||||
if($includeLight){
|
||||
$stream->put(pack("S*", ...$chunk->getHeightMapArray()));
|
||||
$stream->put($subChunk->getBlockSkyLightArray()->getData());
|
||||
$stream->put($subChunk->getBlockLightArray()->getData());
|
||||
}
|
||||
}
|
||||
|
||||
//biomes
|
||||
$stream->put($chunk->getBiomeIdArray());
|
||||
if($includeLight){
|
||||
$stream->put(pack("S*", ...$chunk->getHeightMapArray()));
|
||||
}
|
||||
|
||||
return $stream->getBuffer();
|
||||
}
|
||||
|
||||
@ -113,39 +111,36 @@ final class FastChunkSerializer{
|
||||
$flags = $stream->getByte();
|
||||
$lightPopulated = (bool) ($flags & self::FLAG_HAS_LIGHT);
|
||||
$terrainPopulated = (bool) ($flags & self::FLAG_POPULATED);
|
||||
$terrainGenerated = (bool) ($flags & self::FLAG_GENERATED);
|
||||
|
||||
$subChunks = [];
|
||||
$biomeIds = null;
|
||||
$heightMap = null;
|
||||
if($terrainGenerated){
|
||||
$count = $stream->getByte();
|
||||
for($subCount = 0; $subCount < $count; ++$subCount){
|
||||
$y = $stream->getByte();
|
||||
$airBlockId = $stream->getInt();
|
||||
|
||||
/** @var PalettedBlockArray[] $layers */
|
||||
$layers = [];
|
||||
for($i = 0, $layerCount = $stream->getByte(); $i < $layerCount; ++$i){
|
||||
$bitsPerBlock = $stream->getByte();
|
||||
$words = $stream->get(PalettedBlockArray::getExpectedWordArraySize($bitsPerBlock));
|
||||
$palette = array_values(unpack("L*", $stream->get($stream->getInt())));
|
||||
$count = $stream->getByte();
|
||||
for($subCount = 0; $subCount < $count; ++$subCount){
|
||||
$y = $stream->getByte();
|
||||
$airBlockId = $stream->getInt();
|
||||
|
||||
$layers[] = PalettedBlockArray::fromData($bitsPerBlock, $words, $palette);
|
||||
}
|
||||
$subChunks[$y] = new SubChunk(
|
||||
$airBlockId, $layers, $lightPopulated ? new LightArray($stream->get(2048)) : null, $lightPopulated ? new LightArray($stream->get(2048)) : null
|
||||
);
|
||||
/** @var PalettedBlockArray[] $layers */
|
||||
$layers = [];
|
||||
for($i = 0, $layerCount = $stream->getByte(); $i < $layerCount; ++$i){
|
||||
$bitsPerBlock = $stream->getByte();
|
||||
$words = $stream->get(PalettedBlockArray::getExpectedWordArraySize($bitsPerBlock));
|
||||
$palette = array_values(unpack("L*", $stream->get($stream->getInt())));
|
||||
|
||||
$layers[] = PalettedBlockArray::fromData($bitsPerBlock, $words, $palette);
|
||||
}
|
||||
$subChunks[$y] = new SubChunk(
|
||||
$airBlockId, $layers, $lightPopulated ? new LightArray($stream->get(2048)) : null, $lightPopulated ? new LightArray($stream->get(2048)) : null
|
||||
);
|
||||
}
|
||||
|
||||
$biomeIds = new BiomeArray($stream->get(256));
|
||||
if($lightPopulated){
|
||||
$heightMap = new HeightArray(array_values(unpack("S*", $stream->get(512))));
|
||||
}
|
||||
$biomeIds = new BiomeArray($stream->get(256));
|
||||
if($lightPopulated){
|
||||
$heightMap = new HeightArray(array_values(unpack("S*", $stream->get(512))));
|
||||
}
|
||||
|
||||
$chunk = new Chunk($subChunks, null, null, $biomeIds, $heightMap);
|
||||
$chunk->setGenerated($terrainGenerated);
|
||||
$chunk->setPopulated($terrainPopulated);
|
||||
$chunk->setLightPopulated($lightPopulated);
|
||||
$chunk->clearDirtyFlags();
|
||||
|
@ -406,7 +406,6 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
||||
|
||||
//TODO: tile ticks, biome states (?)
|
||||
|
||||
$chunk->setGenerated();
|
||||
$chunk->setPopulated();
|
||||
if($hasBeenUpgraded){
|
||||
$chunk->setDirty(); //trigger rewriting chunk to disk if it was converted from an older format
|
||||
|
@ -99,7 +99,6 @@ trait LegacyAnvilChunkTrait{
|
||||
$biomeArray
|
||||
);
|
||||
$result->setPopulated($chunk->getByte("TerrainPopulated", 0) !== 0);
|
||||
$result->setGenerated();
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,6 @@ class McRegion extends RegionWorldProvider{
|
||||
$biomeIds
|
||||
);
|
||||
$result->setPopulated($chunk->getByte("TerrainPopulated", 0) !== 0);
|
||||
$result->setGenerated(true);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,6 @@ class Flat extends Generator{
|
||||
|
||||
protected function generateBaseChunk() : void{
|
||||
$this->chunk = new Chunk();
|
||||
$this->chunk->setGenerated();
|
||||
|
||||
for($Z = 0; $Z < 16; ++$Z){
|
||||
for($X = 0; $X < 16; ++$X){
|
||||
|
@ -91,7 +91,7 @@ class PopulationTask extends AsyncTask{
|
||||
/** @var Chunk[] $chunks */
|
||||
$chunks = [];
|
||||
|
||||
$chunk = $this->chunk !== null ? FastChunkSerializer::deserialize($this->chunk) : new Chunk();
|
||||
$chunk = $this->chunk !== null ? FastChunkSerializer::deserialize($this->chunk) : null;
|
||||
|
||||
for($i = 0; $i < 9; ++$i){
|
||||
if($i === 4){
|
||||
@ -99,27 +99,29 @@ class PopulationTask extends AsyncTask{
|
||||
}
|
||||
$ck = $this->{"chunk$i"};
|
||||
if($ck === null){
|
||||
$chunks[$i] = new Chunk();
|
||||
$chunks[$i] = null;
|
||||
}else{
|
||||
$chunks[$i] = FastChunkSerializer::deserialize($ck);
|
||||
}
|
||||
}
|
||||
|
||||
$manager->setChunk($this->chunkX, $this->chunkZ, $chunk);
|
||||
if(!$chunk->isGenerated()){
|
||||
if($chunk === null){
|
||||
$generator->generateChunk($manager, $this->chunkX, $this->chunkZ);
|
||||
$chunk = $manager->getChunk($this->chunkX, $this->chunkZ);
|
||||
$chunk->setGenerated();
|
||||
$chunk->setDirtyFlag(Chunk::DIRTY_FLAG_TERRAIN, true);
|
||||
$chunk->setDirtyFlag(Chunk::DIRTY_FLAG_BIOMES, true);
|
||||
}
|
||||
|
||||
foreach($chunks as $i => $c){
|
||||
$cX = (-1 + $i % 3) + $this->chunkX;
|
||||
$cZ = (-1 + intdiv($i, 3)) + $this->chunkZ;
|
||||
$manager->setChunk($cX, $cZ, $c);
|
||||
if(!$c->isGenerated()){
|
||||
if($c === null){
|
||||
$generator->generateChunk($manager, $cX, $cZ);
|
||||
$chunks[$i] = $manager->getChunk($cX, $cZ);
|
||||
$chunks[$i]->setGenerated();
|
||||
$chunks[$i]->setDirtyFlag(Chunk::DIRTY_FLAG_TERRAIN, true);
|
||||
$chunks[$i]->setDirtyFlag(Chunk::DIRTY_FLAG_BIOMES, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,16 +535,6 @@ parameters:
|
||||
count: 3
|
||||
path: ../../../src/world/World.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method isPopulated\\(\\) on pocketmine\\\\world\\\\format\\\\Chunk\\|null\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/world/World.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$chunk of class pocketmine\\\\world\\\\generator\\\\PopulationTask constructor expects pocketmine\\\\world\\\\format\\\\Chunk, pocketmine\\\\world\\\\format\\\\Chunk\\|null given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/world/World.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\world\\\\biome\\\\BiomeRegistry\\:\\:getBiome\\(\\) should return pocketmine\\\\world\\\\biome\\\\Biome but returns pocketmine\\\\world\\\\biome\\\\Biome\\|null\\.$#"
|
||||
count: 1
|
||||
@ -591,13 +581,8 @@ parameters:
|
||||
path: ../../../src/world/generator/PopulationTask.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method setGenerated\\(\\) on pocketmine\\\\world\\\\format\\\\Chunk\\|null\\.$#"
|
||||
count: 2
|
||||
path: ../../../src/world/generator/PopulationTask.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method isGenerated\\(\\) on pocketmine\\\\world\\\\format\\\\Chunk\\|null\\.$#"
|
||||
count: 1
|
||||
message: "#^Cannot call method setDirtyFlag\\(\\) on pocketmine\\\\world\\\\format\\\\Chunk\\|null\\.$#"
|
||||
count: 4
|
||||
path: ../../../src/world/generator/PopulationTask.php
|
||||
|
||||
-
|
||||
|
Loading…
x
Reference in New Issue
Block a user