From ad596cdccb55f7479180373ef341ca85889ed25f Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Thu, 30 Apr 2020 00:21:02 -0500 Subject: [PATCH] Add sound handlers for block interaction These sound handlers had to be added since on Minecraft: Java Edition, these sounds are handled clientside whilst Minecraft: Bedrock Edition expects something from the server. To counter this, we emulate the sounds of that on Minecraft: Java Edition within Geyser and send it to the client. The code may seem a tadredundant, but there is not much of an alternative unfortunately. --- .../network/session/GeyserSession.java | 10 ++ .../bedrock/BedrockActionTranslator.java | 2 + ...BedrockInventoryTransactionTranslator.java | 2 + .../java/world/JavaBlockChangeTranslator.java | 33 ++++++- .../java/world/JavaPlayEffectTranslator.java | 4 +- .../sound/BucketSoundInteractionHandler.java | 72 ++++++++++++++ .../sound/DoorSoundInteractionHandler.java | 46 +++++++++ .../FlintAndSteelInteractionHandler.java | 49 +++++++++ .../sound/GrassPathInteractionHandler.java | 50 ++++++++++ .../sound/LeverSoundInteractionHandler.java | 46 +++++++++ .../translators/sound/SoundHandler.java | 66 +++++++++++++ .../sound/SoundHandlerRegistry.java | 69 +++++++++++++ .../sound/SoundInteractionHandler.java | 99 +++++++++++++++++++ connector/src/main/resources/mappings | 2 +- 14 files changed, 542 insertions(+), 8 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/BucketSoundInteractionHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/DoorSoundInteractionHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/FlintAndSteelInteractionHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/GrassPathInteractionHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/LeverSoundInteractionHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandlerRegistry.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 70574032..e9b0e472 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -118,6 +118,10 @@ public class GeyserSession implements CommandSender { private GameMode gameMode = GameMode.SURVIVAL; private final AtomicInteger pendingDimSwitches = new AtomicInteger(0); + + @Setter + private boolean sneaking; + @Setter private boolean sprinting; @@ -133,6 +137,12 @@ public class GeyserSession implements CommandSender { @Setter private String lastBlockPlacedId; + @Setter + private boolean interacting; + + @Setter + private Vector3i lastInteractionPosition; + @Setter private boolean switchingDimension = false; private boolean manyDimPackets = false; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java index 1c8159cf..d7248aa3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java @@ -78,10 +78,12 @@ public class BedrockActionTranslator extends PacketTranslator INTERACTION_HANDLERS = new HashMap<>(); + + static { + Reflections ref = new Reflections("org.geysermc.connector.network.translators.sound"); + for (Class clazz : ref.getTypesAnnotatedWith(SoundHandler.class)) { + try { + SoundInteractionHandler interactionHandler = (SoundInteractionHandler) clazz.newInstance(); + SoundHandler annotation = clazz.getAnnotation(SoundHandler.class); + INTERACTION_HANDLERS.put(annotation, interactionHandler); + } catch (InstantiationException | IllegalAccessException ex) { + ex.printStackTrace(); + } + } + } + + private SoundHandlerRegistry() { + } + + public static void init() { + // no-op + } + + /** + * Returns a map of the interaction handlers + * + * @return a map of the interaction handlers + */ + public static Map getInteractionHandlers() { + return INTERACTION_HANDLERS; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java new file mode 100644 index 00000000..364b93b8 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + * + */ + +package org.geysermc.connector.network.translators.sound; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.nukkitx.math.vector.Vector3f; + +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.Translators; + +import java.util.Map; + +/** + * Handler for playing sounds when right-clicking + * blocks. Due to Minecraft: Bedrock Edition + * expecting interaction sounds to be played serverside + * and Minecraft: Java Edition handling them clientside, + * this had to be made to handle scenarios like that. + */ +public interface SoundInteractionHandler { + + /** + * Handles the interaction when a player + * right-clicks a block. + * + * @param session the session interacting with the block + * @param position the position of the block + * @param identifier the identifier of the block + */ + void handleInteraction(GeyserSession session, Vector3f position, String identifier); + + /** + * Handles the block interaction when a player + * right-clicks a block. + * + * @param session the session interacting with the block + * @param position the position of the block + * @param identifier the identifier of the block + */ + static void handleBlockInteraction(GeyserSession session, Vector3f position, String identifier) { + for (Map.Entry interactionEntry : SoundHandlerRegistry.INTERACTION_HANDLERS.entrySet()) { + if (interactionEntry.getKey().blocks().length != 0) { + boolean contains = false; + for (String blockIdentifier : interactionEntry.getKey().blocks()) { + if (identifier.contains(blockIdentifier)) { + contains = true; + break; + } + } + if (!contains) continue; + } + ItemStack itemInHand = session.getInventory().getItemInHand(); + if (interactionEntry.getKey().items().length != 0) { + if (itemInHand == null || itemInHand.getId() == 0) { + continue; + } + String handIdentifier = Translators.getItemTranslator().getItem(session.getInventory().getItemInHand()).getJavaIdentifier(); + boolean contains = false; + for (String itemIdentifier : interactionEntry.getKey().items()) { + if (handIdentifier.contains(itemIdentifier)) { + contains = true; + break; + } + } + if (!contains) continue; + } + if (session.isSneaking() && !interactionEntry.getKey().ignoreSneakingWhileHolding()) { + if (session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() != 0) { + continue; + } + } + interactionEntry.getValue().handleInteraction(session, position, identifier); + } + } +} diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index 4d53e24f..e28b1270 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 4d53e24f92d20e51909ee48ac28ed17f92cb819e +Subproject commit e28b127030a81330d9fabef30efda8cbfdf4e5e3