diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSoundEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSoundEntityTranslator.java
new file mode 100644
index 000000000..11a047805
--- /dev/null
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/JavaSoundEntityTranslator.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2019-2022 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.geyser.translator.protocol.java.entity;
+
+import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSoundEntityPacket;
+import org.geysermc.geyser.entity.type.Entity;
+import org.geysermc.geyser.session.GeyserSession;
+import org.geysermc.geyser.translator.protocol.PacketTranslator;
+import org.geysermc.geyser.translator.protocol.Translator;
+import org.geysermc.geyser.util.SoundUtils;
+
+@Translator(packet = ClientboundSoundEntityPacket.class)
+public class JavaSoundEntityTranslator extends PacketTranslator<ClientboundSoundEntityPacket> {
+    @Override
+    public void translate(GeyserSession session, ClientboundSoundEntityPacket packet) {
+        Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
+        if (entity == null) {
+            return;
+        }
+        SoundUtils.playBuiltinSound(session, packet.getSound(), entity.getPosition(), packet.getPitch());
+    }
+}
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCustomSoundTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCustomSoundTranslator.java
index 63da6710c..00894bd8b 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCustomSoundTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaCustomSoundTranslator.java
@@ -25,45 +25,21 @@
 
 package org.geysermc.geyser.translator.protocol.java.level;
 
-import com.github.steveice10.mc.protocol.data.game.level.sound.BuiltinSound;
-import com.github.steveice10.mc.protocol.data.game.level.sound.CustomSound;
 import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundCustomSoundPacket;
 import com.nukkitx.math.vector.Vector3f;
-import com.nukkitx.protocol.bedrock.packet.*;
+import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.protocol.PacketTranslator;
 import org.geysermc.geyser.translator.protocol.Translator;
-import org.geysermc.geyser.registry.Registries;
-import org.geysermc.geyser.registry.type.SoundMapping;
+import org.geysermc.geyser.util.SoundUtils;
 
 @Translator(packet = ClientboundCustomSoundPacket.class)
 public class JavaCustomSoundTranslator extends PacketTranslator<ClientboundCustomSoundPacket> {
 
     @Override
     public void translate(GeyserSession session, ClientboundCustomSoundPacket packet) {
-        String packetSound;
-        if (packet.getSound() instanceof BuiltinSound) {
-            packetSound = ((BuiltinSound) packet.getSound()).getName();
-        } else if (packet.getSound() instanceof CustomSound) {
-            packetSound = ((CustomSound) packet.getSound()).getName();
-        } else {
-            session.getGeyser().getLogger().debug("Unknown sound packet, we were unable to map this. " + packet.toString());
-            return;
-        }
-
-        SoundMapping soundMapping = Registries.SOUNDS.get(packetSound.replace("minecraft:", ""));
-        String playsound;
-        if (soundMapping == null || soundMapping.getPlaysound() == null) {
-            // no mapping
-            session.getGeyser().getLogger()
-                    .debug("[PlaySound] Defaulting to sound server gave us for " + packet.toString());
-            playsound = packetSound.replace("minecraft:", "");
-        } else {
-            playsound = soundMapping.getPlaysound();
-        }
-
         PlaySoundPacket playSoundPacket = new PlaySoundPacket();
-        playSoundPacket.setSound(playsound);
+        playSoundPacket.setSound(SoundUtils.translatePlaySound(packet.getSound()));
         playSoundPacket.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));
         playSoundPacket.setVolume(packet.getVolume());
         playSoundPacket.setPitch(packet.getPitch());
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSoundTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSoundTranslator.java
index 60e7907e2..626c4527c 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSoundTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSoundTranslator.java
@@ -27,75 +27,17 @@ package org.geysermc.geyser.translator.protocol.java.level;
 
 import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundSoundPacket;
 import com.nukkitx.math.vector.Vector3f;
-import com.nukkitx.protocol.bedrock.data.LevelEventType;
-import com.nukkitx.protocol.bedrock.data.SoundEvent;
-import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
-import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.protocol.PacketTranslator;
 import org.geysermc.geyser.translator.protocol.Translator;
-import org.geysermc.geyser.level.block.BlockStateValues;
-import org.geysermc.geyser.registry.BlockRegistries;
 import org.geysermc.geyser.util.SoundUtils;
-import org.geysermc.geyser.registry.Registries;
-import org.geysermc.geyser.registry.type.SoundMapping;
 
 @Translator(packet = ClientboundSoundPacket.class)
 public class JavaSoundTranslator extends PacketTranslator<ClientboundSoundPacket> {
 
     @Override
     public void translate(GeyserSession session, ClientboundSoundPacket packet) {
-        String packetSound = packet.getSound().getName();
-
-        SoundMapping soundMapping = Registries.SOUNDS.get(packetSound);
-        if (soundMapping == null) {
-            session.getGeyser().getLogger().debug("[Builtin] Sound mapping " + packetSound + " not found - " + packet.toString());
-            return;
-        }
-
-        if (soundMapping.isLevelEvent()) {
-            LevelEventPacket levelEventPacket = new LevelEventPacket();
-            levelEventPacket.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));
-            levelEventPacket.setData(0);
-            levelEventPacket.setType(LevelEventType.valueOf(soundMapping.getBedrock()));
-            session.sendUpstreamPacket(levelEventPacket);
-            return;
-        }
-        LevelSoundEventPacket soundPacket = new LevelSoundEventPacket();
-        SoundEvent sound = SoundUtils.toSoundEvent(soundMapping.getBedrock());
-        if (sound == null) {
-            sound = SoundUtils.toSoundEvent(packetSound);
-        }
-        if (sound == null) {
-            session.getGeyser().getLogger().debug("[Builtin] Sound for original " + packetSound + " to mappings " + soundPacket
-                            + " was not a playable level sound, or has yet to be mapped to an enum in "
-                            + "NukkitX SoundEvent ");
-            return;
-        }
-
-        soundPacket.setSound(sound);
-        soundPacket.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));
-        soundPacket.setIdentifier(soundMapping.getIdentifier());
-        if (sound == SoundEvent.NOTE) {
-            // Minecraft Wiki: 2^(x/12) = Java pitch where x is -12 to 12
-            // Java sends the note value as above starting with -12 and ending at 12
-            // Bedrock has a number for each type of note, then proceeds up the scale by adding to that number
-            soundPacket.setExtraData(soundMapping.getExtraData() + (int)(Math.round((Math.log10(packet.getPitch()) / Math.log10(2)) * 12)) + 12);
-        } else if (sound == SoundEvent.PLACE && soundMapping.getExtraData() == -1) {
-            if (!soundMapping.getIdentifier().equals(":")) {
-                soundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(
-                        BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(soundMapping.getIdentifier(), BlockStateValues.JAVA_AIR_ID)));
-            } else {
-                session.getGeyser().getLogger().debug("PLACE sound mapping identifier was invalid! Please report: " + packet.toString());
-            }
-            soundPacket.setIdentifier(":");
-        } else {
-            soundPacket.setExtraData(soundMapping.getExtraData());
-        }
-
-
-        soundPacket.setBabySound(false); // might need to adjust this in the future
-        soundPacket.setRelativeVolumeDisabled(false);
-        session.sendUpstreamPacket(soundPacket);
+        Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
+        SoundUtils.playBuiltinSound(session, packet.getSound(), position, packet.getPitch());
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaStopSoundTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaStopSoundTranslator.java
index d9750ad7e..e5bc7999f 100644
--- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaStopSoundTranslator.java
+++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaStopSoundTranslator.java
@@ -25,15 +25,12 @@
 
 package org.geysermc.geyser.translator.protocol.java.level;
 
-import com.github.steveice10.mc.protocol.data.game.level.sound.BuiltinSound;
-import com.github.steveice10.mc.protocol.data.game.level.sound.CustomSound;
 import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundStopSoundPacket;
 import com.nukkitx.protocol.bedrock.packet.StopSoundPacket;
 import org.geysermc.geyser.session.GeyserSession;
 import org.geysermc.geyser.translator.protocol.PacketTranslator;
 import org.geysermc.geyser.translator.protocol.Translator;
-import org.geysermc.geyser.registry.Registries;
-import org.geysermc.geyser.registry.type.SoundMapping;
+import org.geysermc.geyser.util.SoundUtils;
 
 @Translator(packet = ClientboundStopSoundPacket.class)
 public class JavaStopSoundTranslator extends PacketTranslator<ClientboundStopSoundPacket> {
@@ -49,36 +46,11 @@ public class JavaStopSoundTranslator extends PacketTranslator<ClientboundStopSou
             return;
         }
 
-        String packetSound;
-        if (packet.getSound() instanceof BuiltinSound) {
-            packetSound = ((BuiltinSound) packet.getSound()).getName();
-        } else if (packet.getSound() instanceof CustomSound) {
-            packetSound = ((CustomSound) packet.getSound()).getName();
-        } else {
-            session.getGeyser().getLogger().debug("Unknown sound packet, we were unable to map this. " + packet.toString());
-            return;
-        }
-        SoundMapping soundMapping = Registries.SOUNDS.get(packetSound.replace("minecraft:", ""));
-        session.getGeyser().getLogger()
-                .debug("[StopSound] Sound mapping " + packetSound + " -> "
-                        + soundMapping + (soundMapping == null ? "[not found]" : "")
-                        + " - " + packet.toString());
-        String playsound;
-        if (soundMapping == null || soundMapping.getPlaysound() == null) {
-            // no mapping
-            session.getGeyser().getLogger()
-                    .debug("[StopSound] Defaulting to sound server gave us.");
-            playsound = packetSound;
-        } else {
-            playsound = soundMapping.getPlaysound();
-        }
-
         StopSoundPacket stopSoundPacket = new StopSoundPacket();
-        stopSoundPacket.setSoundName(playsound);
-        // packet not mapped in the library
+        stopSoundPacket.setSoundName(SoundUtils.translatePlaySound(packet.getSound()));
         stopSoundPacket.setStoppingAllSound(false);
 
         session.sendUpstreamPacket(stopSoundPacket);
-        session.getGeyser().getLogger().debug("[StopSound] Packet sent - " + packet.toString() + " --> " + stopSoundPacket);
+        session.getGeyser().getLogger().debug("[StopSound] Stopped " + packet.getSound() + " -> " + stopSoundPacket.getSoundName());
     }
 }
diff --git a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java
index d2675f13e..44ec06244 100644
--- a/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java
+++ b/core/src/main/java/org/geysermc/geyser/util/SoundUtils.java
@@ -25,7 +25,20 @@
 
 package org.geysermc.geyser.util;
 
+import com.github.steveice10.mc.protocol.data.game.level.sound.BuiltinSound;
+import com.github.steveice10.mc.protocol.data.game.level.sound.CustomSound;
+import com.github.steveice10.mc.protocol.data.game.level.sound.Sound;
+import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.LevelEventType;
 import com.nukkitx.protocol.bedrock.data.SoundEvent;
+import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
+import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
+import org.geysermc.geyser.GeyserImpl;
+import org.geysermc.geyser.level.block.BlockStateValues;
+import org.geysermc.geyser.registry.BlockRegistries;
+import org.geysermc.geyser.registry.Registries;
+import org.geysermc.geyser.registry.type.SoundMapping;
+import org.geysermc.geyser.session.GeyserSession;
 
 public class SoundUtils {
 
@@ -38,9 +51,103 @@ public class SoundUtils {
      */
     public static SoundEvent toSoundEvent(String sound) {
         try {
-            return SoundEvent.valueOf(sound.toUpperCase().replaceAll("\\.", "_"));
+            return SoundEvent.valueOf(sound.toUpperCase().replace(".", "_"));
         } catch (Exception ex) {
             return null;
         }
     }
+
+    /**
+     * Translates a Java Custom or Builtin Sound to its Bedrock equivalent
+     *
+     * @param sound the sound to translate
+     * @return a Bedrock sound
+     */
+    public static String translatePlaySound(Sound sound) {
+        String packetSound;
+        if (sound instanceof BuiltinSound builtinSound) {
+            packetSound = builtinSound.getName();
+        } else if (sound instanceof CustomSound customSound) {
+            packetSound = customSound.getName();
+        } else {
+            GeyserImpl.getInstance().getLogger().debug("Unknown sound, we were unable to map this. " + sound);
+            return "";
+        }
+
+        // Drop the namespace
+        int colonPos = packetSound.indexOf(":");
+        if (colonPos != -1) {
+            packetSound = packetSound.substring(colonPos + 1);
+        }
+
+        SoundMapping soundMapping = Registries.SOUNDS.get(packetSound);
+        if (soundMapping == null || soundMapping.getPlaysound() == null) {
+            // no mapping
+            GeyserImpl.getInstance().getLogger().debug("[PlaySound] Defaulting to sound server gave us for " + sound);
+            return packetSound;
+        }
+        return soundMapping.getPlaysound();
+    }
+
+    /**
+     * Translates and plays a Java Builtin Sound for a Bedrock client
+     *
+     * @param session the Bedrock client session.
+     * @param javaSound the builtin sound to play
+     * @param position the position
+     * @param pitch the pitch
+     */
+    public static void playBuiltinSound(GeyserSession session, BuiltinSound javaSound, Vector3f position, float pitch) {
+        String packetSound = javaSound.getName();
+
+        SoundMapping soundMapping = Registries.SOUNDS.get(packetSound);
+        if (soundMapping == null) {
+            session.getGeyser().getLogger().debug("[Builtin] Sound mapping for " + packetSound + " not found");
+            return;
+        }
+
+        if (soundMapping.isLevelEvent()) {
+            LevelEventPacket levelEventPacket = new LevelEventPacket();
+            levelEventPacket.setPosition(position);
+            levelEventPacket.setData(0);
+            levelEventPacket.setType(LevelEventType.valueOf(soundMapping.getBedrock()));
+            session.sendUpstreamPacket(levelEventPacket);
+            return;
+        }
+
+        LevelSoundEventPacket soundPacket = new LevelSoundEventPacket();
+        SoundEvent sound = SoundUtils.toSoundEvent(soundMapping.getBedrock());
+        if (sound == null) {
+            sound = SoundUtils.toSoundEvent(packetSound);
+        }
+        if (sound == null) {
+            session.getGeyser().getLogger().debug("[Builtin] Sound for original '" + packetSound + "' to mappings '" + soundMapping.getBedrock()
+                    + "' was not a playable level sound, or has yet to be mapped to an enum in SoundEvent.");
+            return;
+        }
+
+        soundPacket.setSound(sound);
+        soundPacket.setPosition(position);
+        soundPacket.setIdentifier(soundMapping.getIdentifier());
+        if (sound == SoundEvent.NOTE) {
+            // Minecraft Wiki: 2^(x/12) = Java pitch where x is -12 to 12
+            // Java sends the note value as above starting with -12 and ending at 12
+            // Bedrock has a number for each type of note, then proceeds up the scale by adding to that number
+            soundPacket.setExtraData(soundMapping.getExtraData() + (int)(Math.round((Math.log10(pitch) / Math.log10(2)) * 12)) + 12);
+        } else if (sound == SoundEvent.PLACE && soundMapping.getExtraData() == -1) {
+            if (!soundMapping.getIdentifier().equals(":")) {
+                int javaId = BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(soundMapping.getIdentifier(), BlockStateValues.JAVA_AIR_ID);
+                soundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(javaId));
+            } else {
+                session.getGeyser().getLogger().debug("PLACE sound mapping identifier was invalid! Please report: " + soundMapping);
+            }
+            soundPacket.setIdentifier(":");
+        } else {
+            soundPacket.setExtraData(soundMapping.getExtraData());
+        }
+
+        soundPacket.setBabySound(false); // might need to adjust this in the future
+        soundPacket.setRelativeVolumeDisabled(false);
+        session.sendUpstreamPacket(soundPacket);
+    }
 }
diff --git a/core/src/main/resources/mappings b/core/src/main/resources/mappings
index f0cee51f5..7fc4ac178 160000
--- a/core/src/main/resources/mappings
+++ b/core/src/main/resources/mappings
@@ -1 +1 @@
-Subproject commit f0cee51f5868a78e18f3ac348eab52d5bbb2ac6f
+Subproject commit 7fc4ac178901f2ba2989645d0da44dcfb95575db