-
-
Notifications
You must be signed in to change notification settings - Fork 825
More efficient multi block updates #6307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
95a0f31
6aecb95
638673a
ef4faf3
5a5c2c0
6f3154a
fdce150
0763298
a0f8ea0
346178c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,19 +25,105 @@ | |
|
|
||
| package org.geysermc.geyser.translator.protocol.java.level; | ||
|
|
||
| import org.cloudburstmc.math.vector.Vector3i; | ||
| import org.cloudburstmc.protocol.bedrock.data.BlockChangeEntry.MessageType; | ||
| import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; | ||
| import org.cloudburstmc.protocol.bedrock.packet.UpdateSubChunkBlocksPacket; | ||
| import org.geysermc.geyser.entity.type.ItemFrameEntity; | ||
| import org.geysermc.geyser.level.block.Blocks; | ||
| import org.geysermc.geyser.level.block.type.Block; | ||
| import org.geysermc.geyser.level.block.type.BlockState; | ||
| import org.geysermc.geyser.registry.BlockRegistries; | ||
| import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette; | ||
| import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockChangeEntry; | ||
| import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundSectionBlocksUpdatePacket; | ||
| import org.geysermc.geyser.session.GeyserSession; | ||
| import org.geysermc.geyser.translator.protocol.PacketTranslator; | ||
| import org.geysermc.geyser.translator.protocol.Translator; | ||
|
|
||
| import java.util.BitSet; | ||
| import java.util.Objects; | ||
|
|
||
| @Translator(packet = ClientboundSectionBlocksUpdatePacket.class) | ||
| public class JavaSectionBlocksUpdateTranslator extends PacketTranslator<ClientboundSectionBlocksUpdatePacket> { | ||
|
|
||
| private static final int FLAG_ALL = 1 << UpdateBlockPacket.Flag.NEIGHBORS.ordinal() | 1 << UpdateBlockPacket.Flag.NETWORK.ordinal(); | ||
|
|
||
| @Override | ||
| public void translate(GeyserSession session, ClientboundSectionBlocksUpdatePacket packet) { | ||
| DataPalette palette = null; | ||
| if (session.getChunkCache().isCache()) { | ||
| palette = session.getChunkCache().getChunkSection(packet.getChunkX(), packet.getChunkY(), packet.getChunkZ(), true); | ||
| if (palette == null) { | ||
|
valaphee marked this conversation as resolved.
|
||
| return; | ||
| } | ||
|
valaphee marked this conversation as resolved.
valaphee marked this conversation as resolved.
|
||
| } | ||
|
valaphee marked this conversation as resolved.
|
||
|
|
||
| Vector3i clientBreakPos = session.getBlockBreakHandler().getCurrentBlockPos(); | ||
| BitSet waterlogged = BlockRegistries.WATERLOGGED.get(); | ||
|
|
||
| UpdateSubChunkBlocksPacket updateSubChunkBlocksPacket = new UpdateSubChunkBlocksPacket(); | ||
|
|
||
| for (BlockChangeEntry entry : packet.getEntries()) { | ||
| session.getWorldCache().updateServerCorrectBlockState(entry.getPosition(), entry.getBlock()); | ||
| session.getWorldCache().removePrediction(entry.getPosition()); | ||
|
|
||
| // Hack to avoid looking up blockstates for the currently broken position each tick | ||
| if (clientBreakPos != null && Objects.equals(clientBreakPos, entry.getPosition())) { | ||
| session.getBlockBreakHandler().setUpdatedServerBlockStateId(entry.getBlock()); | ||
| } | ||
|
|
||
| int oldBlock = palette != null | ||
| ? palette.get(entry.getPosition().getX() & 0xF, entry.getPosition().getY() & 0xF, entry.getPosition().getZ() & 0xF) | ||
| : session.getGeyser().getWorldManager().getBlockAt(session, entry.getPosition()); | ||
| if (entry.getBlock() == oldBlock) { | ||
|
valaphee marked this conversation as resolved.
|
||
| // Skip unchanged blocks which may occur with older versions of Minecraft | ||
| continue; | ||
| } | ||
|
valaphee marked this conversation as resolved.
valaphee marked this conversation as resolved.
|
||
|
|
||
| if (palette != null) { | ||
| palette.set(entry.getPosition().getX() & 0xF, entry.getPosition().getY() & 0xF, entry.getPosition().getZ() & 0xF, entry.getBlock()); | ||
| } | ||
|
onebeastchris marked this conversation as resolved.
|
||
|
|
||
| BlockState blockState = BlockState.of(entry.getBlock()); | ||
| if (blockState.is(Blocks.AIR)) { | ||
| ItemFrameEntity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, entry.getPosition()); | ||
| if (itemFrameEntity != null) { // Item frame is still present and no block overrides that; refresh it | ||
| itemFrameEntity.updateBlock(true); | ||
| continue; | ||
| } | ||
| } | ||
|
|
||
| // Some block may have special handling, keep it that way | ||
| if (!(blockState.block().getClass().equals(Block.class))) { | ||
| blockState.block().updateBlock(session, blockState, entry.getPosition()); | ||
| continue; | ||
|
Comment on lines
+96
to
+99
|
||
| } | ||
|
valaphee marked this conversation as resolved.
|
||
|
|
||
| // Skull is gone | ||
| session.getSkullCache().removeSkull(entry.getPosition()); | ||
|
Comment on lines
+87
to
+103
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand why you didn't use
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea its only called if its specialized, for anything else we would have to check both locations, could add comments
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd be fine with a comment in Block#updateBlock like: any changes you do here, add them to this translator too. |
||
|
|
||
| updateSubChunkBlocksPacket.getStandardBlocks().add(new org.cloudburstmc.protocol.bedrock.data.BlockChangeEntry( | ||
| entry.getPosition(), | ||
| session.getBlockMappings().getBedrockBlock(blockState), | ||
| FLAG_ALL, | ||
| -1, | ||
| MessageType.NONE | ||
| )); | ||
|
valaphee marked this conversation as resolved.
valaphee marked this conversation as resolved.
|
||
|
|
||
| boolean isWaterlogged = waterlogged.get(entry.getBlock()); | ||
| if (waterlogged.get(oldBlock) != isWaterlogged) { | ||
| updateSubChunkBlocksPacket.getExtraBlocks().add(new org.cloudburstmc.protocol.bedrock.data.BlockChangeEntry( | ||
| entry.getPosition(), | ||
| isWaterlogged ? session.getBlockMappings().getBedrockWater() : session.getBlockMappings().getBedrockAir(), | ||
| 0, | ||
| -1, | ||
| MessageType.NONE | ||
| )); | ||
| } | ||
| } | ||
|
|
||
|
valaphee marked this conversation as resolved.
|
||
| if (!updateSubChunkBlocksPacket.getStandardBlocks().isEmpty()) { | ||
| session.sendUpstreamPacket(updateSubChunkBlocksPacket); | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.