Level: Avoid chunk sending bugs caused by duplicate chunks with wrong coordinates

If the same chunk is set into multiple different places in the world, the chunk's position is no longer able to be relied on, because it will have the position of the last place it was set. This results in chunks not getting sent correctly when the same chunk is set in multiple places.

This avoids the bug by using known valid coordinates (using chunk hashes) to establish the real coordinates, and also adds an assert to notify developers should they unintentionally set a duplicate chunk by mistake.
This commit is contained in:
Dylan K. Taylor 2018-06-09 11:25:45 +01:00
parent c327b3d2c4
commit d04991feb6
2 changed files with 5 additions and 4 deletions

View File

@ -2487,8 +2487,9 @@ class Level implements ChunkManager, Metadatable{
if(!($chunk instanceof Chunk)){
throw new ChunkException("Invalid Chunk sent");
}
assert($chunk->getX() === $x and $chunk->getZ() === $z, "Chunk coordinate mismatch: expected $x $z, but chunk has coordinates " . $chunk->getX() . " " . $chunk->getZ() . ", did you forget to clone a chunk before setting?");
$this->server->getAsyncPool()->submitTask(new ChunkRequestTask($this, $chunk));
$this->server->getAsyncPool()->submitTask(new ChunkRequestTask($this, $x, $z, $chunk));
$this->timings->syncChunkSendPrepareTimer->stopTiming();
}

View File

@ -43,13 +43,13 @@ class ChunkRequestTask extends AsyncTask{
protected $compressionLevel;
public function __construct(Level $level, Chunk $chunk){
public function __construct(Level $level, int $chunkX, int $chunkZ, Chunk $chunk){
$this->levelId = $level->getId();
$this->compressionLevel = $level->getServer()->networkCompressionLevel;
$this->chunk = $chunk->fastSerialize();
$this->chunkX = $chunk->getX();
$this->chunkZ = $chunk->getZ();
$this->chunkX = $chunkX;
$this->chunkZ = $chunkZ;
//TODO: serialize tiles with chunks
$tiles = "";