From c08bde583e46078665a67828cdfa267b296b2c94 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Wed, 19 Feb 2025 18:52:53 +0100 Subject: [PATCH 1/2] Start fixing our block breaking code --- .../geyser/registry/type/ItemMappings.java | 2 +- .../geyser/session/GeyserSession.java | 11 +- .../inventory/InventoryTranslator.java | 4 +- ...BedrockInventoryTransactionTranslator.java | 1 + .../player/input/BedrockBlockActions.java | 174 +++++++++++++----- .../BedrockPlayerAuthInputTranslator.java | 54 +----- 6 files changed, 150 insertions(+), 96 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java index 4ebe11bae2c..021f6372c87 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java @@ -144,7 +144,7 @@ public ItemMapping getMapping(ItemData data) { return lightBlock; } - boolean isBlock = data.getBlockDefinition() != null; + boolean isBlock = data.getBlockDefinition() != null && data.getBlockDefinition().getRuntimeId() != 0; boolean hasDamage = data.getDamage() != 0; for (ItemMapping mapping : this.items) { diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 005e72097d8..232b53d7a07 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -401,9 +401,18 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Setter private BedrockDimension bedrockDimension = this.bedrockOverworldDimension; + /** + * Stores the blockstate of the block being currently broken. + */ @Setter private int breakingBlock; + /** + * Stores the block break position of the currently broken block. + */ + @Setter + private Vector3i blockBreakPosition; + @Setter private Vector3i lastBlockPlacePosition; @@ -1594,7 +1603,7 @@ private void startGame() { startGamePacket.setAuthoritativeMovementMode(AuthoritativeMovementMode.SERVER); startGamePacket.setRewindHistorySize(0); - startGamePacket.setServerAuthoritativeBlockBreaking(false); + startGamePacket.setServerAuthoritativeBlockBreaking(true); startGamePacket.setServerId(""); startGamePacket.setWorldId(""); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index 6394c5312dd..b6cbbfe2bae 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -534,9 +534,9 @@ public ItemStackResponse translateRequest(GeyserSession session, Inventory inven case CRAFT_RESULTS_DEPRECATED: // Tends to be called for UI inventories case CRAFT_RECIPE_OPTIONAL: // Anvils and cartography tables will handle this case CRAFT_LOOM: // Looms 1.17.40+ - case CRAFT_REPAIR_AND_DISENCHANT: { // Grindstones 1.17.40+ + case CRAFT_REPAIR_AND_DISENCHANT: // Grindstones 1.17.40+ + case MINE_BLOCK: // Server auth block breaking, confirms durability change break; - } default: return rejectRequest(request); } diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java index bfc71089a96..6f7639ba6eb 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java @@ -175,6 +175,7 @@ public void translate(GeyserSession session, InventoryTransactionPacket packet) break; case ITEM_USE: switch (packet.getActionType()) { + // Block placing case 0 -> { final Vector3i packetBlockPosition = packet.getBlockPosition(); Vector3i blockPos = BlockUtils.getBlockPosition(packetBlockPosition, packet.getBlockFace()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockBlockActions.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockBlockActions.java index 4fed313ad9e..426e7eef349 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockBlockActions.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockBlockActions.java @@ -32,7 +32,9 @@ import org.cloudburstmc.protocol.bedrock.data.PlayerBlockActionData; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.block.custom.CustomBlockState; +import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.inventory.GeyserItemStack; @@ -44,6 +46,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.translator.item.CustomItemTranslator; +import org.geysermc.geyser.translator.protocol.bedrock.BedrockInventoryTransactionTranslator; import org.geysermc.geyser.util.BlockUtils; import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; @@ -62,6 +65,7 @@ static void translate(GeyserSession session, List playerA session.getBookEditCache().checkForSend(); for (PlayerBlockActionData blockActionData : playerActions) { + GeyserImpl.getInstance().getLogger().error(blockActionData.toString()); handle(session, blockActionData); } } @@ -70,14 +74,15 @@ private static void handle(GeyserSession session, PlayerBlockActionData blockAct PlayerActionType action = blockActionData.getAction(); Vector3i vector = blockActionData.getBlockPosition(); int blockFace = blockActionData.getFace(); + switch (action) { case DROP_ITEM -> { ServerboundPlayerActionPacket dropItemPacket = new ServerboundPlayerActionPacket(PlayerAction.DROP_ITEM, vector, Direction.VALUES[blockFace], 0); session.sendDownstreamGamePacket(dropItemPacket); } - case START_BREAK -> { - // Ignore START_BREAK when the player is CREATIVE to avoid Spigot receiving 2 packets it interpets as block breaking. https://github.com/GeyserMC/Geyser/issues/4021 + case START_BREAK -> startBlockBreak(session, vector, blockFace); + case BLOCK_CONTINUE_DESTROY -> { if (session.getGameMode() == GameMode.CREATIVE) { break; } @@ -86,62 +91,26 @@ private static void handle(GeyserSession session, PlayerBlockActionData blockAct return; } - // Start the block breaking animation - int blockState = session.getGeyser().getWorldManager().getBlockAt(session, vector); - LevelEventPacket startBreak = new LevelEventPacket(); - startBreak.setType(LevelEvent.BLOCK_START_BREAK); - startBreak.setPosition(vector.toFloat()); - double breakTime = BlockUtils.getSessionBreakTimeTicks(session, BlockState.of(blockState).block()); - - // If the block is custom or the breaking item is custom, we must keep track of break time ourselves - GeyserItemStack item = session.getPlayerInventory().getItemInHand(); - ItemMapping mapping = item.getMapping(session); - ItemDefinition customItem = mapping.isTool() ? CustomItemTranslator.getCustomItem(item.getComponents(), mapping) : null; - CustomBlockState blockStateOverride = BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get(blockState); - SkullCache.Skull skull = session.getSkullCache().getSkulls().get(vector); - - session.setBlockBreakStartTime(0); - if (blockStateOverride != null || customItem != null || (skull != null && skull.getBlockDefinition() != null)) { - session.setBlockBreakStartTime(System.currentTimeMillis()); - } - startBreak.setData((int) (65535 / breakTime)); - session.setBreakingBlock(blockState); - session.sendUpstreamPacket(startBreak); - - // Account for fire - the client likes to hit the block behind. - Vector3i fireBlockPos = BlockUtils.getBlockPosition(vector, blockFace); - Block block = session.getGeyser().getWorldManager().blockAt(session, fireBlockPos).block(); Direction direction = Direction.VALUES[blockFace]; - if (block == Blocks.FIRE || block == Blocks.SOUL_FIRE) { - ServerboundPlayerActionPacket startBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.START_DIGGING, fireBlockPos, - direction, session.getWorldCache().nextPredictionSequence()); - session.sendDownstreamGamePacket(startBreakingPacket); - } - ServerboundPlayerActionPacket startBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.START_DIGGING, - vector, direction, session.getWorldCache().nextPredictionSequence()); - session.sendDownstreamGamePacket(startBreakingPacket); + // The Bedrock client won't send a new start_break packet, but just continue breaking blocks + if (!vector.equals(session.getBlockBreakPosition())) { + GeyserImpl.getInstance().getLogger().error("Invalid block break position! Expected " + session.getBlockBreakPosition() + ", got " + vector); - spawnBlockBreakParticles(session, direction, vector, BlockState.of(blockState)); - } - case CONTINUE_BREAK -> { - if (session.getGameMode() == GameMode.CREATIVE) { + // Start breaking new block + startBlockBreak(session, vector, blockFace); break; } - if (!canMine(session, vector)) { - return; - } - int breakingBlock = session.getBreakingBlock(); if (breakingBlock == -1) { + // TODO ?????? breakingBlock = Block.JAVA_AIR_ID; } Vector3f vectorFloat = vector.toFloat(); BlockState breakingBlockState = BlockState.of(breakingBlock); - Direction direction = Direction.VALUES[blockFace]; spawnBlockBreakParticles(session, direction, vector, breakingBlockState); double breakTime = BlockUtils.getSessionBreakTimeTicks(session, breakingBlockState.block()); @@ -186,6 +155,13 @@ private static void handle(GeyserSession session, PlayerBlockActionData blockAct } } + // Bedrock "confirms" that it stopped breaking blocks by sending an abort packet after breaking the block + if (session.getBlockBreakPosition() == null) { + break; + } + + session.setBlockBreakPosition(null); + ServerboundPlayerActionPacket abortBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.CANCEL_DIGGING, vector, Direction.DOWN, 0); session.sendDownstreamGamePacket(abortBreakingPacket); @@ -198,11 +174,119 @@ private static void handle(GeyserSession session, PlayerBlockActionData blockAct session.sendUpstreamPacket(stopBreak); } // Handled in BedrockInventoryTransactionTranslator - case STOP_BREAK -> { + case BLOCK_PREDICT_DESTROY -> { + breakBlock(session, vector, blockFace); } } } + private static void startBlockBreak(GeyserSession session, Vector3i vector, int blockFace) { + session.setBlockBreakPosition(vector); + + // Only send block breaking in the BLOCK_PREDICT_DESTROY case + if (session.getGameMode() == GameMode.CREATIVE) { + return; + } + + if (!canMine(session, vector)) { + return; + } + + // Start the block breaking animation + int blockState = session.getGeyser().getWorldManager().getBlockAt(session, vector); + LevelEventPacket startBreak = new LevelEventPacket(); + startBreak.setType(LevelEvent.BLOCK_START_BREAK); + startBreak.setPosition(vector.toFloat()); + double breakTime = BlockUtils.getSessionBreakTimeTicks(session, BlockState.of(blockState).block()); + + // If the block is custom or the breaking item is custom, we must keep track of break time ourselves + GeyserItemStack item = session.getPlayerInventory().getItemInHand(); + ItemMapping mapping = item.getMapping(session); + ItemDefinition customItem = mapping.isTool() ? CustomItemTranslator.getCustomItem(item.getComponents(), mapping) : null; + CustomBlockState blockStateOverride = BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get(blockState); + SkullCache.Skull skull = session.getSkullCache().getSkulls().get(vector); + + session.setBlockBreakPosition(vector); // TODO account for fire workaround + session.setBlockBreakStartTime(0); + if (blockStateOverride != null || customItem != null || (skull != null && skull.getBlockDefinition() != null)) { + session.setBlockBreakStartTime(System.currentTimeMillis()); + } + startBreak.setData((int) (65535 / breakTime)); + session.setBreakingBlock(blockState); + session.sendUpstreamPacket(startBreak); + + // Account for fire - the client likes to hit the block behind. + Vector3i fireBlockPos = BlockUtils.getBlockPosition(vector, blockFace); + Block block = session.getGeyser().getWorldManager().blockAt(session, fireBlockPos).block(); + Direction direction = Direction.VALUES[blockFace]; + if (block == Blocks.FIRE || block == Blocks.SOUL_FIRE) { + ServerboundPlayerActionPacket startBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.START_DIGGING, fireBlockPos, + direction, session.getWorldCache().nextPredictionSequence()); + session.sendDownstreamGamePacket(startBreakingPacket); + +// ServerboundPlayerActionPacket stopBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.FINISH_DIGGING, fireBlockPos, +// direction, session.getWorldCache().nextPredictionSequence()); +// session.sendDownstreamGamePacket(stopBreakingPacket); + } + + ServerboundPlayerActionPacket startBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.START_DIGGING, + vector, direction, session.getWorldCache().nextPredictionSequence()); + session.sendDownstreamGamePacket(startBreakingPacket); + + spawnBlockBreakParticles(session, direction, vector, BlockState.of(blockState)); + } + + private static void breakBlock(GeyserSession session, Vector3i vector, int blockFace) { + int blockState = session.getGameMode() == GameMode.CREATIVE ? + session.getGeyser().getWorldManager().getBlockAt(session, vector) : session.getBreakingBlock(); + + session.setLastBlockPlaced(null); + session.setLastBlockPlacePosition(null); + + // Same deal with vanilla block placing as above. + if (!session.getWorldBorder().isInsideBorderBoundaries()) { + BedrockInventoryTransactionTranslator.restoreCorrectBlock(session, vector); + return; + } + + Vector3f playerPosition = session.getPlayerEntity().getPosition(); + playerPosition = playerPosition.down(EntityDefinitions.PLAYER.offset() - session.getEyeHeight()); + + // why is this here??? move to start break + if (!BedrockInventoryTransactionTranslator.canInteractWithBlock(session, playerPosition, vector)) { + BedrockInventoryTransactionTranslator.restoreCorrectBlock(session, vector); + return; + } + + int sequence = session.getWorldCache().nextPredictionSequence(); + session.getWorldCache().markPositionInSequence(vector); + // -1 means we don't know what block they're breaking + if (blockState == -1) { + blockState = Block.JAVA_AIR_ID; + } + + LevelEventPacket blockBreakPacket = new LevelEventPacket(); + blockBreakPacket.setType(LevelEvent.PARTICLE_DESTROY_BLOCK); + blockBreakPacket.setPosition(vector.toFloat()); + blockBreakPacket.setData(session.getBlockMappings().getBedrockBlockId(blockState)); + session.sendUpstreamPacket(blockBreakPacket); + session.setBreakingBlock(-1); + session.setBlockBreakPosition(null); + + // TODO move + Entity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, vector); + if (itemFrameEntity != null) { + ServerboundInteractPacket attackPacket = new ServerboundInteractPacket(itemFrameEntity.getEntityId(), + InteractAction.ATTACK, session.isSneaking()); + session.sendDownstreamGamePacket(attackPacket); + return; + } + + PlayerAction action = session.getGameMode() == GameMode.CREATIVE ? PlayerAction.START_DIGGING : PlayerAction.FINISH_DIGGING; + ServerboundPlayerActionPacket breakPacket = new ServerboundPlayerActionPacket(action, vector, Direction.VALUES[blockFace], sequence); + session.sendDownstreamGamePacket(breakPacket); + } + private static boolean canMine(GeyserSession session, Vector3i vector) { if (session.isHandsBusy()) { session.setBreakingBlock(-1); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockPlayerAuthInputTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockPlayerAuthInputTranslator.java index 8e09c6c98b3..96b7796ab44 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockPlayerAuthInputTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockPlayerAuthInputTranslator.java @@ -30,16 +30,14 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.InputMode; -import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.PlayerActionType; import org.cloudburstmc.protocol.bedrock.data.PlayerAuthInputData; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.ItemUseTransaction; import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket; -import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; +import org.cloudburstmc.protocol.bedrock.packet.ItemStackResponsePacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerActionPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket; -import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.BoatEntity; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.ItemFrameEntity; @@ -47,22 +45,17 @@ import org.geysermc.geyser.entity.type.living.animal.horse.LlamaEntity; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; import org.geysermc.geyser.entity.vehicle.ClientVehicle; -import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; -import org.geysermc.geyser.translator.protocol.bedrock.BedrockInventoryTransactionTranslator; import org.geysermc.geyser.util.CooldownUtils; -import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.InteractAction; -import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerState; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundMoveVehiclePacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; -import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; @@ -86,6 +79,11 @@ public void translate(GeyserSession session, PlayerAuthInputPacket packet) { for (PlayerAuthInputData input : inputData) { switch (input) { case PERFORM_ITEM_INTERACTION -> processItemUseTransaction(session, packet.getItemUseTransaction()); + case PERFORM_ITEM_STACK_REQUEST -> { + ItemStackResponsePacket responsePacket = new ItemStackResponsePacket(); + responsePacket.getEntries().add(session.getInventoryTranslator().translateRequest(session, session.getPlayerInventory(), packet.getItemStackRequest())); + session.sendUpstreamPacket(responsePacket); + } case PERFORM_BLOCK_ACTIONS -> BedrockBlockActions.translate(session, packet.getPlayerActions()); case START_SPRINTING -> { if (!entity.getFlag(EntityFlag.SWIMMING)) { @@ -185,51 +183,13 @@ private static void sendPlayerGlideToggle(GeyserSession session, Entity entity) private static void processItemUseTransaction(GeyserSession session, ItemUseTransaction transaction) { if (transaction.getActionType() == 2) { - int blockState = session.getGameMode() == GameMode.CREATIVE ? - session.getGeyser().getWorldManager().getBlockAt(session, transaction.getBlockPosition()) : session.getBreakingBlock(); - - session.setLastBlockPlaced(null); - session.setLastBlockPlacePosition(null); - - // Same deal with vanilla block placing as above. - if (!session.getWorldBorder().isInsideBorderBoundaries()) { - BedrockInventoryTransactionTranslator.restoreCorrectBlock(session, transaction.getBlockPosition()); - return; - } - - Vector3f playerPosition = session.getPlayerEntity().getPosition(); - playerPosition = playerPosition.down(EntityDefinitions.PLAYER.offset() - session.getEyeHeight()); - - if (!BedrockInventoryTransactionTranslator.canInteractWithBlock(session, playerPosition, transaction.getBlockPosition())) { - BedrockInventoryTransactionTranslator.restoreCorrectBlock(session, transaction.getBlockPosition()); - return; - } - - int sequence = session.getWorldCache().nextPredictionSequence(); - session.getWorldCache().markPositionInSequence(transaction.getBlockPosition()); - // -1 means we don't know what block they're breaking - if (blockState == -1) { - blockState = Block.JAVA_AIR_ID; - } - - LevelEventPacket blockBreakPacket = new LevelEventPacket(); - blockBreakPacket.setType(LevelEvent.PARTICLE_DESTROY_BLOCK); - blockBreakPacket.setPosition(transaction.getBlockPosition().toFloat()); - blockBreakPacket.setData(session.getBlockMappings().getBedrockBlockId(blockState)); - session.sendUpstreamPacket(blockBreakPacket); - session.setBreakingBlock(-1); - + // TODO test Entity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, transaction.getBlockPosition()); if (itemFrameEntity != null) { ServerboundInteractPacket attackPacket = new ServerboundInteractPacket(itemFrameEntity.getEntityId(), InteractAction.ATTACK, session.isSneaking()); session.sendDownstreamGamePacket(attackPacket); - return; } - - PlayerAction action = session.getGameMode() == GameMode.CREATIVE ? PlayerAction.START_DIGGING : PlayerAction.FINISH_DIGGING; - ServerboundPlayerActionPacket breakPacket = new ServerboundPlayerActionPacket(action, transaction.getBlockPosition(), Direction.VALUES[transaction.getBlockFace()], sequence); - session.sendDownstreamGamePacket(breakPacket); } else { session.getGeyser().getLogger().error("Unhandled item use transaction type!"); if (session.getGeyser().getLogger().isDebug()) { From 7a4857f4a91d22d6781c36d4683428e728e4eb50 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Thu, 20 Feb 2025 15:52:11 +0100 Subject: [PATCH 2/2] use existing method to translate item stack request --- .../entity/player/input/BedrockBlockActions.java | 11 ++++++++--- .../input/BedrockPlayerAuthInputTranslator.java | 7 ++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockBlockActions.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockBlockActions.java index 426e7eef349..70967ae02e1 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockBlockActions.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockBlockActions.java @@ -95,8 +95,6 @@ private static void handle(GeyserSession session, PlayerBlockActionData blockAct // The Bedrock client won't send a new start_break packet, but just continue breaking blocks if (!vector.equals(session.getBlockBreakPosition())) { - GeyserImpl.getInstance().getLogger().error("Invalid block break position! Expected " + session.getBlockBreakPosition() + ", got " + vector); - // Start breaking new block startBlockBreak(session, vector, blockFace); break; @@ -233,7 +231,8 @@ private static void startBlockBreak(GeyserSession session, Vector3i vector, int vector, direction, session.getWorldCache().nextPredictionSequence()); session.sendDownstreamGamePacket(startBreakingPacket); - spawnBlockBreakParticles(session, direction, vector, BlockState.of(blockState)); + // TODO test + //spawnBlockBreakParticles(session, direction, vector, BlockState.of(blockState)); } private static void breakBlock(GeyserSession session, Vector3i vector, int blockFace) { @@ -265,6 +264,12 @@ private static void breakBlock(GeyserSession session, Vector3i vector, int block blockState = Block.JAVA_AIR_ID; } + LevelEventPacket breakingPacket = new LevelEventPacket(); + breakingPacket.setType(LevelEvent.BLOCK_STOP_BREAK); + breakingPacket.setPosition(vector.toFloat()); + breakingPacket.setData(0); + session.sendUpstreamPacket(breakingPacket); + LevelEventPacket blockBreakPacket = new LevelEventPacket(); blockBreakPacket.setType(LevelEvent.PARTICLE_DESTROY_BLOCK); blockBreakPacket.setPosition(vector.toFloat()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockPlayerAuthInputTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockPlayerAuthInputTranslator.java index 96b7796ab44..38e39324df9 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockPlayerAuthInputTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/input/BedrockPlayerAuthInputTranslator.java @@ -59,6 +59,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; +import java.util.List; import java.util.Set; @Translator(packet = PlayerAuthInputPacket.class) @@ -79,11 +80,7 @@ public void translate(GeyserSession session, PlayerAuthInputPacket packet) { for (PlayerAuthInputData input : inputData) { switch (input) { case PERFORM_ITEM_INTERACTION -> processItemUseTransaction(session, packet.getItemUseTransaction()); - case PERFORM_ITEM_STACK_REQUEST -> { - ItemStackResponsePacket responsePacket = new ItemStackResponsePacket(); - responsePacket.getEntries().add(session.getInventoryTranslator().translateRequest(session, session.getPlayerInventory(), packet.getItemStackRequest())); - session.sendUpstreamPacket(responsePacket); - } + case PERFORM_ITEM_STACK_REQUEST -> session.getInventoryTranslator().translateRequests(session, session.getPlayerInventory(), List.of(packet.getItemStackRequest())); case PERFORM_BLOCK_ACTIONS -> BedrockBlockActions.translate(session, packet.getPlayerActions()); case START_SPRINTING -> { if (!entity.getFlag(EntityFlag.SWIMMING)) {