diff --git a/src/pocketmine/level/format/io/region/RegionLoader.php b/src/pocketmine/level/format/io/region/RegionLoader.php index decb9c1c5..042852c65 100644 --- a/src/pocketmine/level/format/io/region/RegionLoader.php +++ b/src/pocketmine/level/format/io/region/RegionLoader.php @@ -142,13 +142,13 @@ class RegionLoader{ if($length >= self::MAX_SECTOR_LENGTH){ $this->locationTable[$index][0] = ++$this->lastSector; $this->locationTable[$index][1] = 1; - throw new CorruptedChunkException("Corrupted chunk header detected (sector count larger than max)"); + throw new CorruptedChunkException("Corrupted chunk header detected (sector count $length larger than max " . self::MAX_SECTOR_LENGTH . ")"); } return null; } if($length > ($this->locationTable[$index][1] << 12)){ //Invalid chunk, bigger than defined number of sectors - MainLogger::getLogger()->error("Corrupted bigger chunk detected (bigger than number of sectors given in header)"); + MainLogger::getLogger()->error("Chunk x=$x,z=$z length mismatch (expected " . ($this->locationTable[$index][1] << 12) . " sectors, got $length sectors)"); $this->locationTable[$index][1] = $length >> 12; $this->writeLocationIndex($index); } @@ -240,6 +240,16 @@ class RegionLoader{ return $x | ($z << 5); } + /** + * @param int $offset + * @param int &$x + * @param int &$z + */ + protected static function getChunkCoords(int $offset, ?int &$x, ?int &$z) : void{ + $x = $offset & 0x1f; + $z = ($offset >> 5) & 0x1f; + } + /** * Writes the region header and closes the file * @@ -265,18 +275,23 @@ class RegionLoader{ } $data = unpack("N*", $headerRaw); + /** @var int[] $usedOffsets */ $usedOffsets = []; for($i = 0; $i < 1024; ++$i){ $index = $data[$i + 1]; $offset = $index >> 8; if($offset !== 0){ - fseek($this->filePointer, $offset << 12); + self::getChunkCoords($i, $x, $z); + $fileOffset = $offset << 12; + + fseek($this->filePointer, $fileOffset); if(fgetc($this->filePointer) === false){ //Try and read from the location - throw new CorruptedRegionException("Region file location offset points to invalid location"); + throw new CorruptedRegionException("Region file location offset x=$x,z=$z points to invalid file location $fileOffset"); }elseif(isset($usedOffsets[$offset])){ - throw new CorruptedRegionException("Found two chunk offsets pointing to the same location"); + self::getChunkCoords($usedOffsets[$offset], $existingX, $existingZ); + throw new CorruptedRegionException("Found two chunk offsets (chunk1: x=$existingX,z=$existingZ, chunk2: x=$x,z=$z) pointing to the file location $fileOffset"); }else{ - $usedOffsets[$offset] = true; + $usedOffsets[$offset] = $i; } }