From e3a9db5d8f1416b3d4a11236fb3b79b58630c6fd Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Wed, 15 Oct 2014 11:42:58 +0200 Subject: [PATCH] Implemented saving modified chunks --- src/pocketmine/level/Level.php | 23 +++++++++++-------- src/pocketmine/level/format/FullChunk.php | 10 ++++++++ .../level/format/generic/BaseChunk.php | 7 ++++++ .../level/format/generic/BaseFullChunk.php | 19 +++++++++++++++ .../level/format/mcregion/Chunk.php | 8 +++++++ 5 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 968eba58d..8cd5bbc9f 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -677,10 +677,12 @@ class Level implements ChunkManager, Metadatable{ } public function saveChunks(){ - //TODO: only save changed chunks foreach($this->chunks as $chunk){ - $this->provider->setChunk($chunk->getX(), $chunk->getZ(), $chunk); - $this->provider->saveChunk($chunk->getX(), $chunk->getZ()); + if($chunk->hasChanged()){ + $this->provider->setChunk($chunk->getX(), $chunk->getZ(), $chunk); + $this->provider->saveChunk($chunk->getX(), $chunk->getZ()); + $chunk->setChanged(false); + } } } @@ -1545,10 +1547,8 @@ class Level implements ChunkManager, Metadatable{ public function getChunk($x, $z, $create = false){ if(isset($this->chunks[$index = "$x:$z"])){ return $this->chunks[$index]; - }elseif(($chunk = $this->provider->getChunk($x, $z, $create)) instanceof FullChunk){ - $this->chunks[$index] = $chunk; - $chunk->initChunk(); - return $chunk; + }elseif($this->loadChunk($x, $z, $create) and $this->chunks[$index] instanceof FullChunk){ + return $this->chunks[$index]; } return null; @@ -1589,6 +1589,7 @@ class Level implements ChunkManager, Metadatable{ $this->provider->setChunk($x, $z, $chunk); $this->chunks[$index] = $chunk; } + $chunk->setChanged(); } /** @@ -1805,6 +1806,7 @@ class Level implements ChunkManager, Metadatable{ $chunk = $this->provider->getChunk($x, $z, $generate); if($chunk instanceof FullChunk){ $this->chunks[$index] = $chunk; + $chunk->initChunk(); }else{ $this->timings->syncChunkLoadTimer->startTiming(); $this->provider->loadChunk($x, $z, $generate); @@ -1812,6 +1814,7 @@ class Level implements ChunkManager, Metadatable{ if(($chunk = $this->provider->getChunk($x, $z)) instanceof FullChunk){ $this->chunks[$index] = $chunk; + $chunk->initChunk(); }else{ return false; } @@ -1845,6 +1848,8 @@ class Level implements ChunkManager, Metadatable{ return false; } + $this->timings->doChunkUnload->startTiming(); + $index = "$x:$z"; $chunk = $this->getChunk($x, $z); @@ -1856,9 +1861,7 @@ class Level implements ChunkManager, Metadatable{ } } - $this->timings->doChunkUnload->startTiming(); - - if($chunk instanceof FullChunk and $this->getAutoSave()){ + if($chunk instanceof FullChunk and $chunk->hasChanged() and $this->getAutoSave()){ $this->provider->setChunk($x, $z, $chunk); $this->provider->saveChunk($x, $z); } diff --git a/src/pocketmine/level/format/FullChunk.php b/src/pocketmine/level/format/FullChunk.php index 5ecbfda97..b489e269f 100644 --- a/src/pocketmine/level/format/FullChunk.php +++ b/src/pocketmine/level/format/FullChunk.php @@ -270,6 +270,16 @@ interface FullChunk{ public function toBinary(); + /** + * @return boolean + */ + public function hasChanged(); + + /** + * @param bool $changed + */ + public function setChanged($changed = true); + /** * @param string $data * @param LevelProvider $provider diff --git a/src/pocketmine/level/format/generic/BaseChunk.php b/src/pocketmine/level/format/generic/BaseChunk.php index 68c6205ea..71d0fb0f8 100644 --- a/src/pocketmine/level/format/generic/BaseChunk.php +++ b/src/pocketmine/level/format/generic/BaseChunk.php @@ -103,6 +103,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ public function setBlock($x, $y, $z, $blockId = null, $meta = null){ try{ + $this->hasChanged = true; return $this->sections[$y >> 4]->setBlock($x, $y & 0x0f, $z, $blockId & 0xff, $meta & 0x0f); }catch(\Exception $e){ $level = $this->getProvider(); @@ -118,6 +119,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ public function setBlockId($x, $y, $z, $id){ try{ $this->sections[$y >> 4]->setBlockId($x, $y & 0x0f, $z, $id); + $this->hasChanged = true; }catch(\Exception $e){ $level = $this->getProvider(); $this->setInternalSection($Y = $y >> 4, $level::createChunkSection($Y)); @@ -132,6 +134,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ public function setBlockData($x, $y, $z, $data){ try{ $this->sections[$y >> 4]->setBlockData($x, $y & 0x0f, $z, $data); + $this->hasChanged = true; }catch(\Exception $e){ $level = $this->getProvider(); $this->setInternalSection($Y = $y >> 4, $level::createChunkSection($Y)); @@ -146,6 +149,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ public function setBlockSkyLight($x, $y, $z, $data){ try{ $this->sections[$y >> 4]->getBlockSkyLight($x, $y & 0x0f, $z, $data); + $this->hasChanged = true; }catch(\Exception $e){ $level = $this->getProvider(); $this->setInternalSection($Y = $y >> 4, $level::createChunkSection($Y)); @@ -160,6 +164,7 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ public function setBlockLight($x, $y, $z, $data){ try{ $this->sections[$y >> 4]->getBlockSkyLight($x, $y & 0x0f, $z, $data); + $this->hasChanged = true; }catch(\Exception $e){ $level = $this->getProvider(); $this->setInternalSection($Y = $y >> 4, $level::createChunkSection($Y)); @@ -217,10 +222,12 @@ abstract class BaseChunk extends BaseFullChunk implements Chunk{ }else{ $this->sections[(int) $fY] = $section; } + $this->hasChanged = true; } private function setInternalSection($fY, ChunkSection $section){ $this->sections[(int) $fY] = $section; + $this->hasChanged = true; } public function load($generate = true){ diff --git a/src/pocketmine/level/format/generic/BaseFullChunk.php b/src/pocketmine/level/format/generic/BaseFullChunk.php index 690c920fd..da2f42ed1 100644 --- a/src/pocketmine/level/format/generic/BaseFullChunk.php +++ b/src/pocketmine/level/format/generic/BaseFullChunk.php @@ -67,6 +67,8 @@ abstract class BaseFullChunk implements FullChunk{ protected $x; protected $z; + protected $hasChanged = false; + /** * @param LevelProvider $provider * @param int $x @@ -155,9 +157,12 @@ abstract class BaseFullChunk implements FullChunk{ } } } + $this->getProvider()->getLevel()->timings->syncChunkLoadTileEntitiesTimer->stopTiming(); + $this->NBTentities = null; $this->NBTtiles = null; + $this->hasChanged = false; } } @@ -202,6 +207,7 @@ abstract class BaseFullChunk implements FullChunk{ } public function setBiomeId($x, $z, $biomeId){ + $this->hasChanged = true; $this->biomeIds{($z << 4) + $x} = chr($biomeId); } @@ -212,6 +218,7 @@ abstract class BaseFullChunk implements FullChunk{ } public function setBiomeColor($x, $z, $R, $G, $B){ + $this->hasChanged = true; $this->biomeColors[($z << 4) + $x] = 0 | (($R & 0xFF) << 16) | (($G & 0xFF) << 8) | ($B & 0xFF); } @@ -228,18 +235,22 @@ abstract class BaseFullChunk implements FullChunk{ public function addEntity(Entity $entity){ $this->entities[$entity->getID()] = $entity; + $this->hasChanged = true; } public function removeEntity(Entity $entity){ unset($this->entities[$entity->getID()]); + $this->hasChanged = true; } public function addTile(Tile $tile){ $this->tiles[$tile->getID()] = $tile; + $this->hasChanged = true; } public function removeTile(Tile $tile){ unset($this->tiles[$tile->getID()]); + $this->hasChanged = true; } public function getEntities(){ @@ -310,4 +321,12 @@ abstract class BaseFullChunk implements FullChunk{ return $this->biomeColors; } + public function hasChanged(){ + return $this->hasChanged; + } + + public function setChanged($changed = true){ + $this->hasChanged = (bool) $changed; + } + } \ No newline at end of file diff --git a/src/pocketmine/level/format/mcregion/Chunk.php b/src/pocketmine/level/format/mcregion/Chunk.php index 4c2bd02c3..0bcd1ee92 100644 --- a/src/pocketmine/level/format/mcregion/Chunk.php +++ b/src/pocketmine/level/format/mcregion/Chunk.php @@ -93,6 +93,7 @@ class Chunk extends BaseFullChunk{ public function setBlockId($x, $y, $z, $id){ $this->blocks{($x << 11) + ($z << 7) + $y} = chr($id); + $this->hasChanged = true; } public function getBlockData($x, $y, $z){ @@ -112,6 +113,7 @@ class Chunk extends BaseFullChunk{ }else{ $this->data{$i} = chr((($data & 0x0f) << 4) | ($old_m & 0x0f)); } + $this->hasChanged = true; } public function getBlock($x, $y, $z, &$blockId, &$meta = null){ @@ -154,6 +156,10 @@ class Chunk extends BaseFullChunk{ } } + if($changed){ + $this->hasChanged = true; + } + return $changed; } @@ -174,6 +180,7 @@ class Chunk extends BaseFullChunk{ }else{ $this->skyLight{$i} = chr((($level & 0x0f) << 4) | ($old_sl & 0x0f)); } + $this->hasChanged = true; } public function getBlockLight($x, $y, $z){ @@ -193,6 +200,7 @@ class Chunk extends BaseFullChunk{ }else{ $this->blockLight{$i} = chr((($level & 0x0f) << 4) | ($old_l & 0x0f)); } + $this->hasChanged = true; } public function getBlockIdColumn($x, $z){