Start work on entity sounds, other misc implementations/fixes

This commit is contained in:
RednedEpic 2020-05-02 01:06:22 -05:00
parent f057edb526
commit ff26dcad0d
16 changed files with 342 additions and 76 deletions

View File

@ -50,6 +50,7 @@ import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.network.translators.Translators;
import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.ItemTranslator;
import org.geysermc.connector.network.translators.sound.EntitySoundInteractionHandler;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.utils.InventoryUtils;
@ -160,6 +161,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
InteractAction.INTERACT_AT, vector.getX(), vector.getY(), vector.getZ(), Hand.MAIN_HAND);
session.getDownstream().getSession().send(interactPacket);
session.getDownstream().getSession().send(interactAtPacket);
EntitySoundInteractionHandler.handleEntityInteraction(session, vector, entity);
break;
case 1: //Attack
ClientPlayerInteractEntityPacket attackPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),

View File

@ -32,7 +32,7 @@ import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.network.translators.sound.SoundInteractionHandler;
import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHandler;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.utils.ChunkUtils;
@ -103,6 +103,6 @@ public class JavaBlockChangeTranslator extends PacketTranslator<ServerBlockChang
String identifier = BlockTranslator.getJavaIdBlockMap().inverse().get(packet.getRecord().getBlock());
session.setInteracting(false);
session.setLastInteractionPosition(null);
SoundInteractionHandler.handleBlockInteraction(session, lastInteractPos.toFloat(), identifier);
BlockSoundInteractionHandler.handleBlockInteraction(session, lastInteractPos.toFloat(), identifier);
}
}

View File

@ -81,6 +81,16 @@ public class JavaPlayEffectTranslator extends PacketTranslator<ServerPlayEffectP
// Might need to be SHOOT
effect.setType(LevelEventType.PARTICLE_SMOKE);
break;
case BLOCK_LAVA_EXTINGUISH:
LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket();
soundEventPacket.setSound(SoundEvent.EXTINGUISH_FIRE);
soundEventPacket.setPosition(Vector3f.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()));
soundEventPacket.setIdentifier(":");
soundEventPacket.setExtraData(-1);
soundEventPacket.setBabySound(false);
soundEventPacket.setRelativeVolumeDisabled(false);
session.getUpstream().sendPacket(soundEventPacket);
return;
default:
GeyserConnector.getInstance().getLogger().debug("No effect handling for particle effect: " + packet.getEffect());
}

View File

@ -0,0 +1,87 @@
/*
* 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;
/**
* Sound interaction handler for when a block is right-clicked.
*/
public interface BlockSoundInteractionHandler extends SoundInteractionHandler<String> {
/**
* 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<SoundHandler, SoundInteractionHandler<?>> interactionEntry : SoundHandlerRegistry.INTERACTION_HANDLERS.entrySet()) {
if (!(interactionEntry.getValue() instanceof BlockSoundInteractionHandler)) {
continue;
}
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;
}
}
((BlockSoundInteractionHandler) interactionEntry.getValue()).handleInteraction(session, position, identifier);
}
}
}

View File

@ -0,0 +1,88 @@
/*
* 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.entity.Entity;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.Translators;
import java.util.Map;
/**
* Sound interaction handler for when an entity is right-clicked.
*/
public interface EntitySoundInteractionHandler extends SoundInteractionHandler<Entity> {
/**
* Handles the block interaction when a player
* right-clicks an entity.
*
* @param session the session interacting with the block
* @param position the position of the block
* @param entity the entity interacted with
*/
static void handleEntityInteraction(GeyserSession session, Vector3f position, Entity entity) {
for (Map.Entry<SoundHandler, SoundInteractionHandler<?>> interactionEntry : SoundHandlerRegistry.INTERACTION_HANDLERS.entrySet()) {
if (!(interactionEntry.getValue() instanceof EntitySoundInteractionHandler)) {
continue;
}
if (interactionEntry.getKey().entities().length != 0) {
boolean contains = false;
for (String entityIdentifier : interactionEntry.getKey().entities()) {
if (entity.getEntityType().name().toLowerCase().contains(entityIdentifier)) {
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;
}
}
((EntitySoundInteractionHandler) interactionEntry.getValue()).handleInteraction(session, position, entity);
}
}
}

View File

@ -38,8 +38,10 @@ public @interface SoundHandler {
/**
* The identifier(s) that the placed block must contain
* one of.
* Leave empty to ignore.
* one of. Leave empty to ignore.
*
* Only applies to interaction handlers that are an
* instance of {@link BlockSoundInteractionHandler}.
*
* @return the value the interacted block must contain
*/
@ -47,13 +49,23 @@ public @interface SoundHandler {
/**
* The identifier(s) that the player's hand item
* must contain one of.
* Leave empty to ignore.
* must contain one of. Leave empty to ignore.
*
* @return the value the item in the player's hand must contain
*/
String[] items() default {};
/**
* The identifier(s) that the interacted entity must have.
* Leave empty to ignore.
*
* Only applies to interaction handlers that are an
* instance of {@link BlockSoundInteractionHandler}.
*
* @return the value the item in the player's hand must contain
*/
String[] entities() default {};
/**
* Controls if the interaction should still be
* called even if the player is sneaking while

View File

@ -36,13 +36,13 @@ import java.util.Map;
*/
public class SoundHandlerRegistry {
static final Map<SoundHandler, SoundInteractionHandler> INTERACTION_HANDLERS = new HashMap<>();
static final Map<SoundHandler, SoundInteractionHandler<?>> 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();
SoundInteractionHandler<?> interactionHandler = (SoundInteractionHandler<?>) clazz.newInstance();
SoundHandler annotation = clazz.getAnnotation(SoundHandler.class);
INTERACTION_HANDLERS.put(annotation, interactionHandler);
} catch (InstantiationException | IllegalAccessException ex) {
@ -63,7 +63,7 @@ public class SoundHandlerRegistry {
*
* @return a map of the interaction handlers
*/
public static Map<SoundHandler, SoundInteractionHandler> getInteractionHandlers() {
public static Map<SoundHandler, SoundInteractionHandler<?>> getInteractionHandlers() {
return INTERACTION_HANDLERS;
}
}

View File

@ -26,22 +26,20 @@
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
* various objects. 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.
*
* @param <T> the value
*/
public interface SoundInteractionHandler {
public interface SoundInteractionHandler<T> {
/**
* Handles the interaction when a player
@ -49,51 +47,7 @@ public interface SoundInteractionHandler {
*
* @param session the session interacting with the block
* @param position the position of the block
* @param identifier the identifier of the block
* @param value the value
*/
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<SoundHandler, SoundInteractionHandler> 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);
}
}
void handleInteraction(GeyserSession session, Vector3f position, T value);
}

View File

@ -24,17 +24,18 @@
*
*/
package org.geysermc.connector.network.translators.sound;
package org.geysermc.connector.network.translators.sound.block;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.SoundEvent;
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.Translators;
import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHandler;
import org.geysermc.connector.network.translators.sound.SoundHandler;
@SoundHandler(items = "bucket")
public class BucketSoundInteractionHandler implements SoundInteractionHandler {
public class BucketSoundInteractionHandler implements BlockSoundInteractionHandler {
@Override
public void handleInteraction(GeyserSession session, Vector3f position, String identifier) {

View File

@ -24,16 +24,17 @@
*
*/
package org.geysermc.connector.network.translators.sound;
package org.geysermc.connector.network.translators.sound.block;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.LevelEventType;
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHandler;
import org.geysermc.connector.network.translators.sound.SoundHandler;
@SoundHandler(blocks = "door")
public class DoorSoundInteractionHandler implements SoundInteractionHandler {
public class DoorSoundInteractionHandler implements BlockSoundInteractionHandler {
@Override
public void handleInteraction(GeyserSession session, Vector3f position, String identifier) {

View File

@ -24,16 +24,17 @@
*
*/
package org.geysermc.connector.network.translators.sound;
package org.geysermc.connector.network.translators.sound.block;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.SoundEvent;
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHandler;
import org.geysermc.connector.network.translators.sound.SoundHandler;
@SoundHandler(items = "flint_and_steel", ignoreSneakingWhileHolding = true)
public class FlintAndSteelInteractionHandler implements SoundInteractionHandler {
public class FlintAndSteelInteractionHandler implements BlockSoundInteractionHandler {
@Override
public void handleInteraction(GeyserSession session, Vector3f position, String identifier) {

View File

@ -24,17 +24,18 @@
*
*/
package org.geysermc.connector.network.translators.sound;
package org.geysermc.connector.network.translators.sound.block;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.SoundEvent;
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHandler;
import org.geysermc.connector.network.translators.sound.SoundHandler;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
@SoundHandler(blocks = "grass_path", items = "shovel", ignoreSneakingWhileHolding = true)
public class GrassPathInteractionHandler implements SoundInteractionHandler {
public class GrassPathInteractionHandler implements BlockSoundInteractionHandler {
@Override
public void handleInteraction(GeyserSession session, Vector3f position, String identifier) {

View File

@ -0,0 +1,51 @@
/*
* 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.block;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.SoundEvent;
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHandler;
import org.geysermc.connector.network.translators.sound.SoundHandler;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
@SoundHandler(blocks = "farmland", items = "hoe", ignoreSneakingWhileHolding = true)
public class HoeInteractionHandler implements BlockSoundInteractionHandler {
@Override
public void handleInteraction(GeyserSession session, Vector3f position, String identifier) {
LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket();
levelSoundEventPacket.setPosition(position);
levelSoundEventPacket.setBabySound(false);
levelSoundEventPacket.setRelativeVolumeDisabled(false);
levelSoundEventPacket.setIdentifier(":");
levelSoundEventPacket.setSound(SoundEvent.ITEM_USE_ON);
levelSoundEventPacket.setExtraData(BlockTranslator.getBedrockBlockId(BlockTranslator.getJavaBlockState(identifier)));
session.getUpstream().sendPacket(levelSoundEventPacket);
}
}

View File

@ -24,15 +24,17 @@
*
*/
package org.geysermc.connector.network.translators.sound;
package org.geysermc.connector.network.translators.sound.block;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.LevelEventType;
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHandler;
import org.geysermc.connector.network.translators.sound.SoundHandler;
@SoundHandler(blocks = "lever")
public class LeverSoundInteractionHandler implements SoundInteractionHandler {
public class LeverSoundInteractionHandler implements BlockSoundInteractionHandler {
@Override
public void handleInteraction(GeyserSession session, Vector3f position, String identifier) {

View File

@ -0,0 +1,55 @@
/*
* 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.entity;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.SoundEvent;
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.Translators;
import org.geysermc.connector.network.translators.sound.EntitySoundInteractionHandler;
import org.geysermc.connector.network.translators.sound.SoundHandler;
@SoundHandler(entities = "cow", items = "bucket")
public class MilkCowSoundInteractionHandler implements EntitySoundInteractionHandler {
@Override
public void handleInteraction(GeyserSession session, Vector3f position, Entity value) {
if (!Translators.getItemTranslator().getItem(session.getInventory().getItemInHand()).getJavaIdentifier().equals("minecraft:bucket")) {
return;
}
LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket();
levelSoundEventPacket.setPosition(position);
levelSoundEventPacket.setBabySound(false);
levelSoundEventPacket.setRelativeVolumeDisabled(false);
levelSoundEventPacket.setIdentifier(":");
levelSoundEventPacket.setSound(SoundEvent.MILK);
levelSoundEventPacket.setExtraData(-1);
session.getUpstream().sendPacket(levelSoundEventPacket);
}
}

@ -1 +1 @@
Subproject commit e28b127030a81330d9fabef30efda8cbfdf4e5e3
Subproject commit 9d801ea70edf1ae36f38b91a5c17bf2245315a68