Eliminate usages of BaseNbtSerializer->readCompressed() and BaseNbtSerializer->writeCompressed()

This commit is contained in:
Dylan K. Taylor 2020-06-17 14:31:56 +01:00
parent 3cdf808da1
commit 506f98efc4
4 changed files with 48 additions and 9 deletions

View File

@ -141,10 +141,14 @@ use function time;
use function touch;
use function trim;
use function yaml_parse;
use function zlib_decode;
use function zlib_encode;
use const DIRECTORY_SEPARATOR;
use const PHP_EOL;
use const PHP_INT_MAX;
use const PTHREADS_INHERIT_NONE;
use const ZLIB_ENCODING_DEFLATE;
use const ZLIB_ENCODING_GZIP;
/**
* The class that manages everything
@ -511,16 +515,34 @@ class Server{
return file_exists($this->getPlayerDataPath($name));
}
private function handleCorruptedPlayerData(string $name) : void{
$path = $this->getPlayerDataPath($name);
rename($path, $path . '.bak');
$this->logger->error($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
}
public function getOfflinePlayerData(string $name) : ?CompoundTag{
$name = strtolower($name);
$path = $this->getPlayerDataPath($name);
if(file_exists($path)){
$contents = @file_get_contents($path);
if($contents === false){
throw new \RuntimeException("Failed to read player data file \"$path\" (permission denied?)");
}
$decompressed = @zlib_decode($contents);
if($decompressed === false){
$this->logger->debug("Failed to decompress raw player data for \"$name\"");
$this->handleCorruptedPlayerData($name);
return null;
}
try{
return (new BigEndianNbtSerializer())->readCompressed(file_get_contents($path))->mustGetCompoundTag();
return (new BigEndianNbtSerializer())->read($decompressed)->mustGetCompoundTag();
}catch(NbtDataException $e){ //zlib decode error / corrupt data
rename($path, $path . '.bak');
$this->logger->error($this->getLanguage()->translateString("pocketmine.data.playerCorrupted", [$name]));
$this->logger->debug("Failed to decode NBT data for \"$name\": " . $e->getMessage());
$this->handleCorruptedPlayerData($name);
return null;
}
}
return null;
@ -535,7 +557,7 @@ class Server{
if(!$ev->isCancelled()){
$nbt = new BigEndianNbtSerializer();
try{
file_put_contents($this->getPlayerDataPath($name), $nbt->writeCompressed(new TreeRoot($ev->getSaveData())));
file_put_contents($this->getPlayerDataPath($name), zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP));
}catch(\ErrorException $e){
$this->logger->critical($this->getLanguage()->translateString("pocketmine.data.saveError", [$name, $e->getMessage()]));
$this->logger->logException($e);

View File

@ -38,6 +38,9 @@ use function ceil;
use function file_get_contents;
use function file_put_contents;
use function microtime;
use function zlib_decode;
use function zlib_encode;
use const ZLIB_ENCODING_GZIP;
class JavaWorldData extends BaseNbtWorldData{
@ -70,7 +73,7 @@ class JavaWorldData extends BaseNbtWorldData{
->setTag("GameRules", new CompoundTag());
$nbt = new BigEndianNbtSerializer();
$buffer = $nbt->writeCompressed(new TreeRoot(CompoundTag::create()->setTag("Data", $worldData)));
$buffer = zlib_encode($nbt->write(new TreeRoot(CompoundTag::create()->setTag("Data", $worldData))), ZLIB_ENCODING_GZIP);
file_put_contents($path . "level.dat", $buffer);
}
@ -80,8 +83,12 @@ class JavaWorldData extends BaseNbtWorldData{
throw new CorruptedWorldException("Failed to read level.dat (permission denied or doesn't exist)");
}
$nbt = new BigEndianNbtSerializer();
$decompressed = @zlib_decode($rawLevelData);
if($decompressed === false){
throw new CorruptedWorldException("Failed to decompress level.dat contents");
}
try{
$worldData = $nbt->readCompressed($rawLevelData)->mustGetCompoundTag();
$worldData = $nbt->read($decompressed)->mustGetCompoundTag();
}catch(NbtDataException $e){
throw new CorruptedWorldException($e->getMessage(), 0, $e);
}
@ -106,7 +113,7 @@ class JavaWorldData extends BaseNbtWorldData{
public function save() : void{
$nbt = new BigEndianNbtSerializer();
$buffer = $nbt->writeCompressed(new TreeRoot(CompoundTag::create()->setTag("Data", $this->compoundTag)));
$buffer = zlib_encode($nbt->write(new TreeRoot(CompoundTag::create()->setTag("Data", $this->compoundTag))), ZLIB_ENCODING_GZIP);
file_put_contents($this->dataPath, $buffer);
}

View File

@ -34,6 +34,7 @@ use pocketmine\world\format\Chunk;
use pocketmine\world\format\io\ChunkUtils;
use pocketmine\world\format\io\exception\CorruptedChunkException;
use pocketmine\world\format\SubChunk;
use function zlib_decode;
/**
* Trait containing I/O methods for handling legacy Anvil-style chunks.
@ -54,9 +55,13 @@ trait LegacyAnvilChunkTrait{
* @throws CorruptedChunkException
*/
protected function deserializeChunk(string $data) : Chunk{
$decompressed = @zlib_decode($data);
if($decompressed === false){
throw new CorruptedChunkException("Failed to decompress chunk NBT");
}
$nbt = new BigEndianNbtSerializer();
try{
$chunk = $nbt->readCompressed($data)->mustGetCompoundTag();
$chunk = $nbt->read($decompressed)->mustGetCompoundTag();
}catch(NbtDataException $e){
throw new CorruptedChunkException($e->getMessage(), 0, $e);
}

View File

@ -36,6 +36,7 @@ use pocketmine\world\format\io\exception\CorruptedChunkException;
use pocketmine\world\format\io\SubChunkConverter;
use pocketmine\world\format\SubChunk;
use function str_repeat;
use function zlib_decode;
class McRegion extends RegionWorldProvider{
@ -50,9 +51,13 @@ class McRegion extends RegionWorldProvider{
* @throws CorruptedChunkException
*/
protected function deserializeChunk(string $data) : Chunk{
$decompressed = @zlib_decode($data);
if($decompressed === false){
throw new CorruptedChunkException("Failed to decompress chunk NBT");
}
$nbt = new BigEndianNbtSerializer();
try{
$chunk = $nbt->readCompressed($data)->mustGetCompoundTag();
$chunk = $nbt->read($decompressed)->mustGetCompoundTag();
}catch(NbtDataException $e){
throw new CorruptedChunkException($e->getMessage(), 0, $e);
}