From 3172a5e197c8bffa780366247ab984ff4eac4a6c Mon Sep 17 00:00:00 2001 From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com> Date: Sun, 27 Sep 2026 12:20:13 +0200 Subject: [PATCH] fix(sound): resolve shared Bedrock sounds by event Bedrock uses the same sound name for opposite trapdoor, button, and block actions while Java exposes distinct sound events. Load explicit Java overrides for each Bedrock event and sound pair, leaving the source sound mappings unchanged for other packet types. Validate the override entries against the loaded Bedrock events and Java sound registry so stale mappings fail during startup. --- .../protocol/data/BedrockMappingData.java | 38 +++++++++++++++++++ .../protocol/packet/WorldEffectPackets.java | 2 +- .../data/custom/sound_event_overrides.json | 17 +++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/assets/viabedrock/data/custom/sound_event_overrides.json diff --git a/src/main/java/net/raphimc/viabedrock/protocol/data/BedrockMappingData.java b/src/main/java/net/raphimc/viabedrock/protocol/data/BedrockMappingData.java index 98d435ad8..2c532d856 100644 --- a/src/main/java/net/raphimc/viabedrock/protocol/data/BedrockMappingData.java +++ b/src/main/java/net/raphimc/viabedrock/protocol/data/BedrockMappingData.java @@ -143,6 +143,7 @@ public class BedrockMappingData extends MappingDataBase { private Map> bedrockLevelSoundEvents; private Map bedrockNoteBlockInstrumentSounds; private Map bedrockToJavaSounds; + private Map> bedrockLevelSoundEventOverrides; private Map bedrockToJavaParticles; private Map bedrockToJavaLevelEvents; private Map bedrockToJavaLevelEventParticles; @@ -857,6 +858,32 @@ public void load() { } } + final JsonObject soundEventOverridesJson = this.readJson("custom/sound_event_overrides.json"); + this.bedrockLevelSoundEventOverrides = new HashMap<>(soundEventOverridesJson.size()); + for (Map.Entry eventEntry : soundEventOverridesJson.entrySet()) { + final String soundEvent = eventEntry.getKey(); + final Map eventSounds = this.bedrockLevelSoundEvents.get(soundEvent); + if (eventSounds == null) { + throw new IllegalStateException("Unknown bedrock level sound event: " + soundEvent); + } + final JsonObject overridesJson = eventEntry.getValue().getAsJsonObject(); + final Map overrides = new HashMap<>(overridesJson.size()); + for (Map.Entry overrideEntry : overridesJson.entrySet()) { + final String bedrockSound = overrideEntry.getKey(); + if (eventSounds.values().stream().noneMatch(sound -> sound.sound().equals(bedrockSound))) { + throw new IllegalStateException("Sound " + bedrockSound + " is not used by level sound event " + soundEvent); + } + final String javaIdentifier = overrideEntry.getValue().getAsString(); + final Integer javaSoundId = this.javaSounds.get(javaIdentifier); + if (javaSoundId == null) { + throw new IllegalStateException("Unknown java sound: " + javaIdentifier); + } + final JavaSound defaultSound = this.bedrockToJavaSounds.get(bedrockSound); + overrides.put(bedrockSound, new JavaSound(javaSoundId, javaIdentifier, defaultSound.category())); + } + this.bedrockLevelSoundEventOverrides.put(soundEvent, overrides); + } + final JsonArray bedrockParticlesJson = this.readJson("bedrock/particles.json", JsonArray.class); final List bedrockParticles = new ArrayList<>(bedrockParticlesJson.size()); for (JsonElement particleJson : bedrockParticlesJson) { @@ -1366,6 +1393,17 @@ public Map getBedrockToJavaSounds() { return this.bedrockToJavaSounds; } + public JavaSound getJavaSoundForLevelSoundEvent(final String soundEvent, final String bedrockSound) { + final Map overrides = this.bedrockLevelSoundEventOverrides.get(soundEvent); + if (overrides != null) { + final JavaSound override = overrides.get(bedrockSound); + if (override != null) { + return override; + } + } + return this.bedrockToJavaSounds.get(bedrockSound); + } + public Map getBedrockToJavaParticles() { return this.bedrockToJavaParticles; } diff --git a/src/main/java/net/raphimc/viabedrock/protocol/packet/WorldEffectPackets.java b/src/main/java/net/raphimc/viabedrock/protocol/packet/WorldEffectPackets.java index 2539fa126..4bb95275b 100644 --- a/src/main/java/net/raphimc/viabedrock/protocol/packet/WorldEffectPackets.java +++ b/src/main/java/net/raphimc/viabedrock/protocol/packet/WorldEffectPackets.java @@ -249,7 +249,7 @@ public static void register(final BedrockProtocol protocol) { } } } - final BedrockMappingData.JavaSound javaSound = BedrockProtocol.MAPPINGS.getBedrockToJavaSounds().get(configuredSound.sound()); + final BedrockMappingData.JavaSound javaSound = BedrockProtocol.MAPPINGS.getJavaSoundForLevelSoundEvent(soundEvent, configuredSound.sound()); if (javaSound == null) { ViaBedrock.getPlatform().getLogger().log(Level.WARNING, "Unknown bedrock sound: " + configuredSound.sound()); wrapper.cancel(); diff --git a/src/main/resources/assets/viabedrock/data/custom/sound_event_overrides.json b/src/main/resources/assets/viabedrock/data/custom/sound_event_overrides.json new file mode 100644 index 000000000..e5ccdb412 --- /dev/null +++ b/src/main/resources/assets/viabedrock/data/custom/sound_event_overrides.json @@ -0,0 +1,17 @@ +{ + "break": { + "place.tuff": "minecraft:block.tuff.break", + "place.tuff_bricks": "minecraft:block.tuff_bricks.break" + }, + "button.click_off": { + "random.stone_click": "minecraft:block.stone_button.click_off", + "random.wood_click": "minecraft:block.wooden_button.click_off" + }, + "power.off": { + "random.stone_click": "minecraft:block.stone_button.click_off", + "random.wood_click": "minecraft:block.wooden_button.click_off" + }, + "trapdoor.close": { + "open_trapdoor.copper": "minecraft:block.copper_trapdoor.close" + } +}