mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-25 12:23:48 +00:00
BaseWorldProvider: don't crash the server when encountering an unknown block
This commit is contained in:
parent
f6c9bf5cd1
commit
bedf79e2cd
@ -23,8 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\world\format\io;
|
namespace pocketmine\world\format\io;
|
||||||
|
|
||||||
use pocketmine\data\bedrock\block\BlockStateData;
|
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
|
||||||
use pocketmine\data\bedrock\block\BlockTypeNames;
|
|
||||||
use pocketmine\world\format\io\exception\CorruptedWorldException;
|
use pocketmine\world\format\io\exception\CorruptedWorldException;
|
||||||
use pocketmine\world\format\io\exception\UnsupportedWorldFormatException;
|
use pocketmine\world\format\io\exception\UnsupportedWorldFormatException;
|
||||||
use pocketmine\world\format\PalettedBlockArray;
|
use pocketmine\world\format\PalettedBlockArray;
|
||||||
@ -62,10 +61,16 @@ abstract class BaseWorldProvider implements WorldProvider{
|
|||||||
$newStateData = $blockDataUpgrader->upgradeIntIdMeta($legacyIdMeta >> 4, $legacyIdMeta & 0xf);
|
$newStateData = $blockDataUpgrader->upgradeIntIdMeta($legacyIdMeta >> 4, $legacyIdMeta & 0xf);
|
||||||
if($newStateData === null){
|
if($newStateData === null){
|
||||||
//TODO: remember data for unknown states so we can implement them later
|
//TODO: remember data for unknown states so we can implement them later
|
||||||
$newStateData = new BlockStateData(BlockTypeNames::INFO_UPDATE, [], BlockStateData::CURRENT_VERSION);
|
$newStateData = GlobalBlockStateHandlers::getUnknownBlockStateData();
|
||||||
}
|
}
|
||||||
|
|
||||||
$newPalette[$k] = $blockStateDeserializer->deserialize($newStateData);
|
try{
|
||||||
|
$newPalette[$k] = $blockStateDeserializer->deserialize($newStateData);
|
||||||
|
}catch(BlockStateDeserializeException){
|
||||||
|
//TODO: this needs to be logged
|
||||||
|
//TODO: maybe we can remember unknown states for later saving instead of discarding them and destroying maps...
|
||||||
|
$newPalette[$k] = $blockStateDeserializer->deserialize(GlobalBlockStateHandlers::getUnknownBlockStateData());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: this is sub-optimal since it reallocates the offset table multiple times
|
//TODO: this is sub-optimal since it reallocates the offset table multiple times
|
||||||
|
@ -26,6 +26,7 @@ namespace pocketmine\world\format\io;
|
|||||||
use pocketmine\data\bedrock\block\BlockStateData;
|
use pocketmine\data\bedrock\block\BlockStateData;
|
||||||
use pocketmine\data\bedrock\block\BlockStateDeserializer;
|
use pocketmine\data\bedrock\block\BlockStateDeserializer;
|
||||||
use pocketmine\data\bedrock\block\BlockStateSerializer;
|
use pocketmine\data\bedrock\block\BlockStateSerializer;
|
||||||
|
use pocketmine\data\bedrock\block\BlockTypeNames;
|
||||||
use pocketmine\data\bedrock\block\CachingBlockStateDeserializer;
|
use pocketmine\data\bedrock\block\CachingBlockStateDeserializer;
|
||||||
use pocketmine\data\bedrock\block\CachingBlockStateSerializer;
|
use pocketmine\data\bedrock\block\CachingBlockStateSerializer;
|
||||||
use pocketmine\data\bedrock\block\convert\BlockObjectToBlockStateSerializer;
|
use pocketmine\data\bedrock\block\convert\BlockObjectToBlockStateSerializer;
|
||||||
@ -54,6 +55,8 @@ final class GlobalBlockStateHandlers{
|
|||||||
|
|
||||||
private static ?BlockDataUpgrader $blockDataUpgrader = null;
|
private static ?BlockDataUpgrader $blockDataUpgrader = null;
|
||||||
|
|
||||||
|
private static ?BlockStateData $unknownBlockStateData = null;
|
||||||
|
|
||||||
public static function getDeserializer() : BlockStateDeserializer{
|
public static function getDeserializer() : BlockStateDeserializer{
|
||||||
return self::$blockStateDeserializer ??= new CachingBlockStateDeserializer(new BlockStateToBlockObjectDeserializer());
|
return self::$blockStateDeserializer ??= new CachingBlockStateDeserializer(new BlockStateToBlockObjectDeserializer());
|
||||||
}
|
}
|
||||||
@ -83,4 +86,8 @@ final class GlobalBlockStateHandlers{
|
|||||||
|
|
||||||
return self::$blockDataUpgrader;
|
return self::$blockDataUpgrader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getUnknownBlockStateData() : BlockStateData{
|
||||||
|
return self::$unknownBlockStateData ??= new BlockStateData(BlockTypeNames::INFO_UPDATE, [], BlockStateData::CURRENT_VERSION);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,7 @@ namespace pocketmine\world\format\io\leveldb;
|
|||||||
use pocketmine\block\Block;
|
use pocketmine\block\Block;
|
||||||
use pocketmine\block\BlockTypeIds;
|
use pocketmine\block\BlockTypeIds;
|
||||||
use pocketmine\data\bedrock\BiomeIds;
|
use pocketmine\data\bedrock\BiomeIds;
|
||||||
use pocketmine\data\bedrock\block\BlockStateData;
|
|
||||||
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
|
use pocketmine\data\bedrock\block\BlockStateDeserializeException;
|
||||||
use pocketmine\data\bedrock\block\BlockTypeNames;
|
|
||||||
use pocketmine\nbt\LittleEndianNbtSerializer;
|
use pocketmine\nbt\LittleEndianNbtSerializer;
|
||||||
use pocketmine\nbt\NbtDataException;
|
use pocketmine\nbt\NbtDataException;
|
||||||
use pocketmine\nbt\NbtException;
|
use pocketmine\nbt\NbtException;
|
||||||
@ -178,9 +176,8 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
|
|||||||
$palette[] = $blockStateDeserializer->deserialize($blockStateData);
|
$palette[] = $blockStateDeserializer->deserialize($blockStateData);
|
||||||
}catch(BlockStateDeserializeException){
|
}catch(BlockStateDeserializeException){
|
||||||
//TODO: remember data for unknown states so we can implement them later
|
//TODO: remember data for unknown states so we can implement them later
|
||||||
//TODO: this is slow; we need to cache this
|
|
||||||
//TODO: log this
|
//TODO: log this
|
||||||
$palette[] = $blockStateDeserializer->deserialize(new BlockStateData(BlockTypeNames::INFO_UPDATE, [], BlockStateData::CURRENT_VERSION));
|
$palette[] = $blockStateDeserializer->deserialize(GlobalBlockStateHandlers::getUnknownBlockStateData());
|
||||||
}
|
}
|
||||||
}catch(NbtException | BlockStateDeserializeException $e){
|
}catch(NbtException | BlockStateDeserializeException $e){
|
||||||
throw new CorruptedChunkException("Invalid blockstate NBT at offset $i in paletted storage: " . $e->getMessage(), 0, $e);
|
throw new CorruptedChunkException("Invalid blockstate NBT at offset $i in paletted storage: " . $e->getMessage(), 0, $e);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user