Added a hack to allow tiles to trigger client-side render updates on blocks without actually changing the block

Bedrock block entity updates don't directly trigger block rendering
updates. This is a problem when the block entity data affects the
block's appearance directly (e.g. cauldron water colour, flower pot
contents), because it means changing them won't directly result in a
client-side render update.

This hack allows tiles to spoof block updates without actually changing
the server-side block, keeping the internals and API clean of random
shitbox workarounds.

fixes #5174
fixes #4944
This commit is contained in:
Dylan K. Taylor
2022-07-19 17:47:41 +01:00
parent f64e306fb8
commit 87b840ff97
4 changed files with 44 additions and 2 deletions

View File

@@ -36,6 +36,7 @@ use pocketmine\block\tile\TileFactory;
use pocketmine\block\UnknownBlock;
use pocketmine\block\VanillaBlocks;
use pocketmine\data\bedrock\BiomeIds;
use pocketmine\data\bedrock\block\BlockStateData;
use pocketmine\data\SavedDataLoadingException;
use pocketmine\entity\Entity;
use pocketmine\entity\EntityFactory;
@@ -948,6 +949,22 @@ class World implements ChunkManager{
$fullBlock = $this->getBlockAt($b->x, $b->y, $b->z);
$blockPosition = BlockPosition::fromVector3($b);
$tile = $this->getTileAt($b->x, $b->y, $b->z);
if($tile instanceof Spawnable && ($fakeStateProperties = $tile->getRenderUpdateBugWorkaroundStateProperties($fullBlock)) !== null){
$originalStateData = $blockMapping->toStateData($fullBlock->getStateId());
$fakeStateData = new BlockStateData(
$originalStateData->getName(),
array_merge($originalStateData->getStates(), $fakeStateProperties),
$originalStateData->getVersion()
);
$packets[] = UpdateBlockPacket::create(
$blockPosition,
$blockMapping->getBlockStateDictionary()->lookupStateIdFromData($fakeStateData) ?? throw new AssumptionFailedError("Unmapped fake blockstate data: " . $fakeStateData->toNbt()),
UpdateBlockPacket::FLAG_NETWORK,
UpdateBlockPacket::DATA_LAYER_NORMAL
);
}
$packets[] = UpdateBlockPacket::create(
$blockPosition,
$blockMapping->toRuntimeId($fullBlock->getStateId()),
@@ -955,7 +972,6 @@ class World implements ChunkManager{
UpdateBlockPacket::DATA_LAYER_NORMAL
);
$tile = $this->getTileAt($b->x, $b->y, $b->z);
if($tile instanceof Spawnable){
$packets[] = BlockActorDataPacket::create($blockPosition, $tile->getSerializedSpawnCompound());
}