From 741e53b1c26db815cf2f6f84d494a2c6c0a0622a Mon Sep 17 00:00:00 2001 From: KdGaming0 <97355992+KdGaming0@users.noreply.github.com> Date: Thu, 14 May 2026 18:42:25 +0200 Subject: [PATCH 1/4] refactor: migrate sound settings to volume map --- README.md | 15 ++-- gradlew | 0 .../java/gg/meza/soundsbegone/Config.java | 69 +++++++++------ .../java/gg/meza/soundsbegone/ConfigData.java | 5 +- .../java/gg/meza/soundsbegone/SoundState.java | 7 -- .../soundsbegone/client/ConfigScreen.java | 85 ++++++++++++------- .../mixin/AbstractSoundInstanceMixin.java | 41 ++++++--- .../assets/soundsbegone/lang/de_de.json | 2 +- .../assets/soundsbegone/lang/en_us.json | 10 +-- .../assets/soundsbegone/lang/ru_ru.json | 2 +- .../assets/soundsbegone/lang/zh_cn.json | 2 +- versions/dependencies/1.21.11.properties | 2 +- versions/dependencies/1.21.properties | 2 +- 13 files changed, 146 insertions(+), 96 deletions(-) mode change 100644 => 100755 gradlew delete mode 100644 src/main/java/gg/meza/soundsbegone/SoundState.java diff --git a/README.md b/README.md index 26ad96f..3ee365f 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,15 @@ [![CurseForge](https://img.shields.io/curseforge/dt/874633?logo=curseforge&label=CurseForge)](https://www.curseforge.com/minecraft/mc-mods/soundsbegone) [![](https://dcbadge.limes.pink/api/server/dvg3tcQCPW)](https://discord.gg/dvg3tcQCPW) -Inspired by my own misophonia, Sounds Be Gone keeps Minecraft playable when specific noises are overwhelming. The mod passively records every sound you have heard in the past minute and lets you mute any of them permanently with a couple of clicks. Everything is client-side, so your preferences affect only your game. +Inspired by my own misophonia, Sounds Be Gone keeps Minecraft playable when specific noises are overwhelming. The mod passively records every sound you have heard in the past minute and lets you reduce the volume or mute any of them permanently with a couple of clicks. Everything is client-side, so your preferences affect only your game. ### _Fabric is supported on releases below 1.20. NeoForge builds are available for Minecraft 1.20.4 and newer._ ## Why players use Sounds Be Gone -- Instantly silence any sound event (vanilla or modded) without memorizing filenames. -- The "recently played" list removes guesswork—scroll, select, and mute. -- Keeps an audit trail so you can easily unmute later when you change your mind. +- Reduce the volume or instantly silence any sound event (vanilla or modded) without memorizing filenames. +- The "recently played" list removes guesswork—scroll, select, and adjust. +- Keeps an audit trail so you can easily readjust volumes later when you change your mind. - Built for sensory accessibility: predictable UI, reversible actions, and zero server requirements. ## Infrequent Sounds! @@ -31,13 +31,13 @@ Use **Infrequent** for sounds where silence would remove useful feedback, but no 1. When you hear an unwanted sound, press `B` (default keybind) to open the Sound Sanctuary. 2. Pick the sound(s) from the "Played in the last 60 seconds" list. -3. Toggle them off to mute permanently; the change saves immediately to your local profile. +3. Use the volume slider to turn it down, or set it to 0% to mute it permanently; the change saves immediately. ### Minecraft 1.19 and below 1. Press `ESC`, choose `MODS`, then select **Sounds Be Gone**. 2. Click the settings cog in the top-right corner to open the configuration screen. -3. Use the list of recent sounds to disable whatever is bothering you. +3. Use the list of recent sounds to turn down or disable whatever is bothering you. ## Installation @@ -58,7 +58,6 @@ Use **Infrequent** for sounds where silence would remove useful feedback, but no ## Configuration tips - Rebind the `B` key if it clashes with another mod under `Options → Controls → Key Binds → Sounds Be Gone`. -- Sounds stay muted until you manually re-enable them, even if you swap worlds or restart the client. - Mod Menu makes it easy to open the config without jumping into a world, especially on older Minecraft versions. - Keep Cloth Config up to date—new releases occasionally add UX improvements for navigating large sound lists. @@ -83,4 +82,4 @@ Thanks to all the supporters who make this project possible! Schauweg - + \ No newline at end of file diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/main/java/gg/meza/soundsbegone/Config.java b/src/main/java/gg/meza/soundsbegone/Config.java index 99e6fde..8dd0812 100644 --- a/src/main/java/gg/meza/soundsbegone/Config.java +++ b/src/main/java/gg/meza/soundsbegone/Config.java @@ -13,7 +13,9 @@ import java.lang.reflect.Type; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import static gg.meza.soundsbegone.SoundsBeGoneConfig.LOGGER; import static gg.meza.soundsbegone.SoundsBeGoneConfig.MOD_ID; @@ -41,23 +43,24 @@ public void toggleTelemetry(boolean toValue) { configData.telemetry = toValue; } - public void disableSound(String sound) { - resetSound(sound); - configData.sounds.add(sound); - } - - public void reduceSound(String sound) { - resetSound(sound); - configData.infrequent.add(sound); + public void setInfrequent(String sound, boolean value) { + if (value) { + configData.infrequent.add(sound); + } else { + configData.infrequent.remove(sound); + } } - public void resetSound(String sound) { - configData.infrequent.remove(sound); - configData.sounds.remove(sound); + public int getSoundVolume(String sound) { + return configData.soundVolumes.getOrDefault(sound, 100); } - public boolean isSoundDisabled(String sound) { - return configData.sounds.contains(sound); + public void setSoundVolume(String sound, int volume) { + if (volume == 100) { + configData.soundVolumes.remove(sound); + } else { + configData.soundVolumes.put(sound, volume); + } } public boolean isSoundInfrequent(String sound) { @@ -65,21 +68,21 @@ public boolean isSoundInfrequent(String sound) { } public Set disabledSounds() { - return configData.sounds; + return configData.soundVolumes.entrySet().stream() + .filter(e -> e.getValue() == 0) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); } - public Set infrequentSounds() { - return configData.infrequent; + public Set reducedSounds() { + return configData.soundVolumes.entrySet().stream() + .filter(e -> e.getValue() > 0 && e.getValue() < 100) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); } - public SoundState getSoundState(String sound) { - if (isSoundDisabled(sound)) { - return SoundState.DISABLED; - } else if (isSoundInfrequent(sound)) { - return SoundState.INFREQUENT; - } else { - return SoundState.ENABLED; - } + public Set infrequentSounds() { + return configData.infrequent; } public double getFrequencyPercentage() { @@ -98,7 +101,7 @@ public void initConfig() { configData = GSON.fromJson(reader, ConfigData.class); reader.close(); } catch (IOException | JsonParseException e) { - SoundsBeGoneConfig.LOGGER.error("Cause: " + e.getCause().getClass().getSimpleName()); + SoundsBeGoneConfig.LOGGER.error("Cause: {}", e.getCause().getClass().getSimpleName()); if (e.getCause().getClass() == IllegalStateException.class) { convertConfig(configPath); return; @@ -106,6 +109,7 @@ public void initConfig() { throw new SerializationException(e); } } + migrateLegacySounds(); } public void saveConfig() { @@ -142,7 +146,9 @@ private void convertConfig(Path configPath) { }.getType(); Set disabledSounds = GSON.fromJson(reader, setType); reader.close(); - this.configData.sounds = disabledSounds; + for (String sound : disabledSounds) { + this.configData.soundVolumes.put(sound, 0); + } BufferedWriter writer = Files.newBufferedWriter(configPath); GSON.toJson(configData, writer); @@ -152,4 +158,15 @@ private void convertConfig(Path configPath) { } } + private void migrateLegacySounds() { + if (configData.sounds != null && !configData.sounds.isEmpty()) { + SoundsBeGoneConfig.LOGGER.info("Migrating legacy disabled sounds to volume map"); + for (String sound : configData.sounds) { + configData.soundVolumes.put(sound, 0); + } + configData.sounds.clear(); + saveConfig(); + } + } + } diff --git a/src/main/java/gg/meza/soundsbegone/ConfigData.java b/src/main/java/gg/meza/soundsbegone/ConfigData.java index 43732e0..0461134 100644 --- a/src/main/java/gg/meza/soundsbegone/ConfigData.java +++ b/src/main/java/gg/meza/soundsbegone/ConfigData.java @@ -1,12 +1,15 @@ package gg.meza.soundsbegone; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; public class ConfigData { public String lastVersionSeen = ""; public boolean telemetry = true; public double frequencyPercentage = 10; - public Set sounds = new HashSet<>(); + public Map soundVolumes = new HashMap<>(); + public Set sounds = new HashSet<>(); // Legacy field, migrated to soundVolumes on load public Set infrequent = new HashSet<>(); } diff --git a/src/main/java/gg/meza/soundsbegone/SoundState.java b/src/main/java/gg/meza/soundsbegone/SoundState.java deleted file mode 100644 index 9c995ad..0000000 --- a/src/main/java/gg/meza/soundsbegone/SoundState.java +++ /dev/null @@ -1,7 +0,0 @@ -package gg.meza.soundsbegone; - -public enum SoundState { - ENABLED, - DISABLED, - INFREQUENT -} diff --git a/src/main/java/gg/meza/soundsbegone/client/ConfigScreen.java b/src/main/java/gg/meza/soundsbegone/client/ConfigScreen.java index 95fe884..7a981da 100644 --- a/src/main/java/gg/meza/soundsbegone/client/ConfigScreen.java +++ b/src/main/java/gg/meza/soundsbegone/client/ConfigScreen.java @@ -1,6 +1,5 @@ package gg.meza.soundsbegone.client; -import gg.meza.soundsbegone.SoundState; import gg.meza.soundsbegone.SoundsBeGoneConfig; import gg.meza.supporters.clothconfig.SupportCategory; @@ -12,6 +11,9 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +import java.util.HashSet; +import java.util.Set; + public class ConfigScreen { public static Screen getConfigScreen(Screen parent) { ConfigBuilder builder = ConfigBuilder.create() @@ -21,12 +23,11 @@ public static Screen getConfigScreen(Screen parent) { SoundsBeGoneClient.config.saveConfig(); }); ConfigCategory general = builder.getOrCreateCategory(Component.translatable("soundsbegone.config.category.latest")); - ConfigCategory disabled = builder.getOrCreateCategory(Component.translatable("soundsbegone.config.category.disabled")); - ConfigCategory infrequent = builder.getOrCreateCategory(Component.translatable("soundsbegone.config.category.infrequent")); + ConfigCategory configured = builder.getOrCreateCategory(Component.translatable("soundsbegone.config.category.configured")); ConfigCategory settings = builder.getOrCreateCategory(Component.translatable("soundsbegone.config.category.settings")); ConfigEntryBuilder entryBuilder = builder.entryBuilder(); - infrequent.addEntry( + settings.addEntry( entryBuilder.startDoubleField(Component.translatable("soundsbegone.config.infrequent.frequency.title"), SoundsBeGoneClient.config.getFrequencyPercentage()) .setMin(0.001) .setMax(99.999) @@ -62,42 +63,64 @@ public static Screen getConfigScreen(Screen parent) { SoundsBeGoneClient.SoundMap .keySet() .stream() - .filter(s -> !SoundsBeGoneClient.config.isSoundDisabled(s)) + .filter(s -> SoundsBeGoneClient.config.getSoundVolume(s) == 100 && !SoundsBeGoneClient.config.isSoundInfrequent(s)) .sorted() .forEach((key) -> general.addEntry(constructOption(entryBuilder, key))); - SoundsBeGoneClient.config.infrequentSounds().stream().sorted().forEach((key) -> infrequent.addEntry(constructOption(entryBuilder, key))); - SoundsBeGoneClient.config.disabledSounds().stream().sorted().forEach((key) -> disabled.addEntry(constructOption(entryBuilder, key))); + Set allModifiedSounds = new HashSet<>(); + allModifiedSounds.addAll(SoundsBeGoneClient.config.disabledSounds()); + allModifiedSounds.addAll(SoundsBeGoneClient.config.reducedSounds()); + allModifiedSounds.addAll(SoundsBeGoneClient.config.infrequentSounds()); + + allModifiedSounds.stream() + .sorted() + .forEach((key) -> configured.addEntry(constructOption(entryBuilder, key))); + SupportCategory.add(builder, entryBuilder); return builder.build(); } private static AbstractConfigListEntry constructOption(ConfigEntryBuilder builder, String key) { - return builder - .startEnumSelector(Component.translatable(key), SoundState.class, SoundsBeGoneClient.config.getSoundState(key)) - .setDefaultValue(SoundsBeGoneClient.config.getSoundState(key)) - .setEnumNameProvider((state) -> Component.translatable("soundsbegone.config.sound.state." + state.name().toLowerCase())) + int currentVolume = SoundsBeGoneClient.config.getSoundVolume(key); + boolean isInfrequent = SoundsBeGoneClient.config.isSoundInfrequent(key); + + SubCategoryBuilder sub = builder.startSubCategory(Component.translatable(key)); + sub.setExpanded(false); + + sub.add(builder.startIntSlider( + Component.translatable("soundsbegone.config.sound.volume"), + currentVolume, 0, 100) + .setDefaultValue(100) + .setSaveConsumer(newVolume -> { + int oldVolume = SoundsBeGoneClient.config.getSoundVolume(key); + if (oldVolume == 0 && newVolume > 0) { + SoundsBeGoneClient.telemetry.unmutedSound(key); + } else if (oldVolume > 0 && newVolume == 0) { + SoundsBeGoneClient.telemetry.mutedSound(key); + } + SoundsBeGoneClient.config.setSoundVolume(key, newVolume); + }) + .setTextGetter(value -> Component.literal(value + "%")) + .build() + ); + + sub.add(builder.startBooleanToggle( + Component.translatable("soundsbegone.config.sound.infrequent"), + isInfrequent) + .setDefaultValue(false) .setSaveConsumer(newValue -> { - boolean hasChanged = SoundsBeGoneClient.config.getSoundState(key) != newValue; - if (!hasChanged) return; - switch (newValue) { - case DISABLED -> { - SoundsBeGoneConfig.LOGGER.info("Disabling sound: " + key); - SoundsBeGoneClient.config.disableSound(key); - SoundsBeGoneClient.telemetry.mutedSound(key); - } - case INFREQUENT -> { - SoundsBeGoneConfig.LOGGER.info("Setting sound to infrequent: " + key); - SoundsBeGoneClient.config.reduceSound(key); - SoundsBeGoneClient.telemetry.setInfrequentSound(key, SoundsBeGoneClient.config.getFrequencyPercentage()); - } - case ENABLED -> { - SoundsBeGoneConfig.LOGGER.info("Enabling sound: " + key); - SoundsBeGoneClient.config.resetSound(key); - SoundsBeGoneClient.telemetry.unmutedSound(key); - } + boolean wasInfrequent = SoundsBeGoneClient.config.isSoundInfrequent(key); + SoundsBeGoneClient.config.setInfrequent(key, newValue); + if (!wasInfrequent && newValue) { + SoundsBeGoneConfig.LOGGER.info("Setting sound to infrequent: {}", key); + SoundsBeGoneClient.telemetry.setInfrequentSound(key, SoundsBeGoneClient.config.getFrequencyPercentage()); + } else if (wasInfrequent && !newValue) { + SoundsBeGoneConfig.LOGGER.info("Removing sound from infrequent: {}", key); } }) - .build(); + .build() + ); + + return sub.build(); } -} +} \ No newline at end of file diff --git a/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java b/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java index cd3f3e2..be7684f 100644 --- a/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java +++ b/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java @@ -7,6 +7,7 @@ import net.minecraft.resources.Identifier; import net.minecraft.util.RandomSource; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -17,6 +18,8 @@ @Mixin(AbstractSoundInstance.class) public class AbstractSoundInstanceMixin { + @Shadow protected float volume; + @Unique private final RandomSource random = RandomSource.create(); @Inject( @@ -24,29 +27,43 @@ public class AbstractSoundInstanceMixin { at = @At("HEAD"), cancellable = true) private void getVolume(CallbackInfoReturnable cir) { + String soundId = soundsBeGone$sound().toString(); - if (SoundsBeGoneClient.config.isSoundDisabled(soundsBeGone$sound().toString())) { - SoundsBeGoneConfig.LOGGER.debug("Disabling the sound: {}", soundsBeGone$sound()); - SoundsBeGoneClient.telemetry.blockedSound(soundsBeGone$sound().toString()); - cir.setReturnValue(0.0F); - cir.cancel(); - } else if (SoundsBeGoneClient.config.isSoundInfrequent(soundsBeGone$sound().toString())) { - double value = random.nextDouble()*100; - double weightedChance = soundEmissionRegulator.weightedChance(soundsBeGone$sound().toString(), SoundsBeGoneClient.config.getFrequencyPercentage()); + if (SoundsBeGoneClient.config.isSoundInfrequent(soundId)) { + double value = random.nextDouble() * 100; + double weightedChance = soundEmissionRegulator.weightedChance(soundId, SoundsBeGoneClient.config.getFrequencyPercentage()); boolean playSound = value < weightedChance; if (!playSound) { - SoundsBeGoneConfig.LOGGER.debug("Reducing the sound: {}", soundsBeGone$sound()); - SoundsBeGoneClient.telemetry.blockedSound(soundsBeGone$sound().toString()); + SoundsBeGoneConfig.LOGGER.debug("Reducing the sound: {}", soundId); + SoundsBeGoneClient.telemetry.blockedSound(soundId); cir.setReturnValue(0.0F); cir.cancel(); + track(soundId); + return; } } - if (Minecraft.getInstance().level != null) { - SoundsBeGoneClient.SoundMap.put(soundsBeGone$sound().toString(), new java.util.Date()); + int volumePercent = SoundsBeGoneClient.config.getSoundVolume(soundId); + if (volumePercent == 0) { + cir.setReturnValue(0.0F); + cir.cancel(); + track(soundId); + return; + } else if (volumePercent != 100) { + float newVolume = this.volume * (volumePercent / 100.0f); + cir.setReturnValue(newVolume); + cir.cancel(); } + track(soundId); + } + + @Unique + private void track(String soundId) { + if (Minecraft.getInstance().level != null) { + SoundsBeGoneClient.SoundMap.put(soundId, new java.util.Date()); + } } @Unique diff --git a/src/main/resources/assets/soundsbegone/lang/de_de.json b/src/main/resources/assets/soundsbegone/lang/de_de.json index 447fae3..cf1d9c8 100644 --- a/src/main/resources/assets/soundsbegone/lang/de_de.json +++ b/src/main/resources/assets/soundsbegone/lang/de_de.json @@ -26,4 +26,4 @@ "soundsbegone.config.telemetry.data.os": "Verwendetes Betriebssystem", "soundsbegone.config.telemetry.data.time": "Lokale Zeit", "soundsbegone.config.telemetry.data.language": "Minecraft Sprache" -} +} \ No newline at end of file diff --git a/src/main/resources/assets/soundsbegone/lang/en_us.json b/src/main/resources/assets/soundsbegone/lang/en_us.json index bdc8216..9cc635c 100644 --- a/src/main/resources/assets/soundsbegone/lang/en_us.json +++ b/src/main/resources/assets/soundsbegone/lang/en_us.json @@ -13,15 +13,13 @@ "soundsbegone.config.title" : "Sounds Be Gone Config", "soundsbegone.config.category.latest" : "Played in the last 60 seconds", - "soundsbegone.config.category.disabled" : "Disabled sounds", - "soundsbegone.config.category.infrequent" : "Infrequent sounds", + "soundsbegone.config.category.configured" : "Configured sounds", "soundsbegone.config.category.settings" : "Settings", "soundsbegone.config.infrequent.frequency.title" : "Frequency of infrequent sounds (percentage)", "soundsbegone.config.infrequent.frequency.tooltip" : "What percentage of infrequent sounds should be played? (0.001 - 99.999)", - "soundsbegone.config.sound.state.enabled" : "Enabled", - "soundsbegone.config.sound.state.disabled" : "Disabled", - "soundsbegone.config.sound.state.infrequent" : "Infrequent", + "soundsbegone.config.sound.volume" : "Volume", + "soundsbegone.config.sound.infrequent" : "Infrequent", "soundsbegone.config.telemetry.switch" : "Enable telemetry", "soundsbegone.config.telemetry.description" : "Enabling telemetry will send anonymous data to help us understand how we can make things better. We DO NOT send any data that would identify you.", @@ -37,4 +35,4 @@ "soundsbegone.config.telemetry.data.os": "Operating system used", "soundsbegone.config.telemetry.data.time": "Local time", "soundsbegone.config.telemetry.data.language": "Minecraft language" -} +} \ No newline at end of file diff --git a/src/main/resources/assets/soundsbegone/lang/ru_ru.json b/src/main/resources/assets/soundsbegone/lang/ru_ru.json index 8238cd8..f107956 100644 --- a/src/main/resources/assets/soundsbegone/lang/ru_ru.json +++ b/src/main/resources/assets/soundsbegone/lang/ru_ru.json @@ -26,4 +26,4 @@ "soundsbegone.config.telemetry.data.os": "Используемая операционная система", "soundsbegone.config.telemetry.data.time": "Местное время", "soundsbegone.config.telemetry.data.language": "Язык Minecraft" -} +} \ No newline at end of file diff --git a/src/main/resources/assets/soundsbegone/lang/zh_cn.json b/src/main/resources/assets/soundsbegone/lang/zh_cn.json index 0967ef4..9e26dfe 100644 --- a/src/main/resources/assets/soundsbegone/lang/zh_cn.json +++ b/src/main/resources/assets/soundsbegone/lang/zh_cn.json @@ -1 +1 @@ -{} +{} \ No newline at end of file diff --git a/versions/dependencies/1.21.11.properties b/versions/dependencies/1.21.11.properties index 92680ac..f9f04c3 100644 --- a/versions/dependencies/1.21.11.properties +++ b/versions/dependencies/1.21.11.properties @@ -6,6 +6,6 @@ fabric_version=0.139.5+1.21.11 neoforge_version=21.11.3-beta modmenu_version=17.0.0-alpha.1 -cloth_version=21.11.151 +cloth_version=21.11.153 meza_core_version=1.2.2 posthog_version=1.2.0 diff --git a/versions/dependencies/1.21.properties b/versions/dependencies/1.21.properties index ab701f5..afd2c5d 100644 --- a/versions/dependencies/1.21.properties +++ b/versions/dependencies/1.21.properties @@ -6,6 +6,6 @@ fabric_version=0.102.0+1.21 neoforge_version=21.0.42-beta modmenu_version=11.0.1 -cloth_version=15.0.127 +cloth_version=15.0.140 posthog_version=1.2.0 meza_core_version=1.1.2 From db0054b609a38ec2a3dda6135599a222f289fc21 Mon Sep 17 00:00:00 2001 From: KdGaming0 <97355992+KdGaming0@users.noreply.github.com> Date: Thu, 14 May 2026 19:19:00 +0200 Subject: [PATCH 2/4] chore: restore non-English lang files from main --- src/main/resources/assets/soundsbegone/lang/de_de.json | 2 +- src/main/resources/assets/soundsbegone/lang/ru_ru.json | 2 +- src/main/resources/assets/soundsbegone/lang/zh_cn.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/assets/soundsbegone/lang/de_de.json b/src/main/resources/assets/soundsbegone/lang/de_de.json index cf1d9c8..447fae3 100644 --- a/src/main/resources/assets/soundsbegone/lang/de_de.json +++ b/src/main/resources/assets/soundsbegone/lang/de_de.json @@ -26,4 +26,4 @@ "soundsbegone.config.telemetry.data.os": "Verwendetes Betriebssystem", "soundsbegone.config.telemetry.data.time": "Lokale Zeit", "soundsbegone.config.telemetry.data.language": "Minecraft Sprache" -} \ No newline at end of file +} diff --git a/src/main/resources/assets/soundsbegone/lang/ru_ru.json b/src/main/resources/assets/soundsbegone/lang/ru_ru.json index f107956..8238cd8 100644 --- a/src/main/resources/assets/soundsbegone/lang/ru_ru.json +++ b/src/main/resources/assets/soundsbegone/lang/ru_ru.json @@ -26,4 +26,4 @@ "soundsbegone.config.telemetry.data.os": "Используемая операционная система", "soundsbegone.config.telemetry.data.time": "Местное время", "soundsbegone.config.telemetry.data.language": "Язык Minecraft" -} \ No newline at end of file +} diff --git a/src/main/resources/assets/soundsbegone/lang/zh_cn.json b/src/main/resources/assets/soundsbegone/lang/zh_cn.json index 9e26dfe..0967ef4 100644 --- a/src/main/resources/assets/soundsbegone/lang/zh_cn.json +++ b/src/main/resources/assets/soundsbegone/lang/zh_cn.json @@ -1 +1 @@ -{} \ No newline at end of file +{} From bc9fdc629a9e607128492a172316eb7f1ac6c8aa Mon Sep 17 00:00:00 2001 From: KdGaming0 <97355992+KdGaming0@users.noreply.github.com> Date: Fri, 15 May 2026 08:08:08 +0200 Subject: [PATCH 3/4] fix: address telemetry gaps and config edge cases --- src/main/java/gg/meza/soundsbegone/Config.java | 11 ++++++----- .../client/mixin/AbstractSoundInstanceMixin.java | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/gg/meza/soundsbegone/Config.java b/src/main/java/gg/meza/soundsbegone/Config.java index 8dd0812..a154630 100644 --- a/src/main/java/gg/meza/soundsbegone/Config.java +++ b/src/main/java/gg/meza/soundsbegone/Config.java @@ -82,7 +82,7 @@ public Set reducedSounds() { } public Set infrequentSounds() { - return configData.infrequent; + return Set.copyOf(configData.infrequent); } public double getFrequencyPercentage() { @@ -101,8 +101,9 @@ public void initConfig() { configData = GSON.fromJson(reader, ConfigData.class); reader.close(); } catch (IOException | JsonParseException e) { - SoundsBeGoneConfig.LOGGER.error("Cause: {}", e.getCause().getClass().getSimpleName()); - if (e.getCause().getClass() == IllegalStateException.class) { + Throwable cause = e.getCause(); + SoundsBeGoneConfig.LOGGER.error("Cause: {}", cause != null ? cause.getClass().getSimpleName() : "null"); + if (cause != null && cause.getClass() == IllegalStateException.class) { convertConfig(configPath); return; } @@ -147,7 +148,7 @@ private void convertConfig(Path configPath) { Set disabledSounds = GSON.fromJson(reader, setType); reader.close(); for (String sound : disabledSounds) { - this.configData.soundVolumes.put(sound, 0); + this.configData.soundVolumes.putIfAbsent(sound, 0); } BufferedWriter writer = Files.newBufferedWriter(configPath); @@ -162,7 +163,7 @@ private void migrateLegacySounds() { if (configData.sounds != null && !configData.sounds.isEmpty()) { SoundsBeGoneConfig.LOGGER.info("Migrating legacy disabled sounds to volume map"); for (String sound : configData.sounds) { - configData.soundVolumes.put(sound, 0); + configData.soundVolumes.putIfAbsent(sound, 0); } configData.sounds.clear(); saveConfig(); diff --git a/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java b/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java index be7684f..226ca6d 100644 --- a/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java +++ b/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java @@ -46,6 +46,7 @@ private void getVolume(CallbackInfoReturnable cir) { int volumePercent = SoundsBeGoneClient.config.getSoundVolume(soundId); if (volumePercent == 0) { + SoundsBeGoneClient.telemetry.blockedSound(soundId); cir.setReturnValue(0.0F); cir.cancel(); track(soundId); From 3e924f7e90d973d30e95295c91710fe3b7bda02c Mon Sep 17 00:00:00 2001 From: KdGaming0 <97355992+KdGaming0@users.noreply.github.com> Date: Fri, 15 May 2026 08:44:36 +0200 Subject: [PATCH 4/4] fix: deduplicate telemetry and harden config migration --- src/main/java/gg/meza/soundsbegone/Config.java | 16 ++++++++-------- .../client/mixin/AbstractSoundInstanceMixin.java | 13 +++++++++++-- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/java/gg/meza/soundsbegone/Config.java b/src/main/java/gg/meza/soundsbegone/Config.java index a154630..0341b2a 100644 --- a/src/main/java/gg/meza/soundsbegone/Config.java +++ b/src/main/java/gg/meza/soundsbegone/Config.java @@ -70,15 +70,13 @@ public boolean isSoundInfrequent(String sound) { public Set disabledSounds() { return configData.soundVolumes.entrySet().stream() .filter(e -> e.getValue() == 0) - .map(Map.Entry::getKey) - .collect(Collectors.toSet()); + .map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet()); } public Set reducedSounds() { return configData.soundVolumes.entrySet().stream() .filter(e -> e.getValue() > 0 && e.getValue() < 100) - .map(Map.Entry::getKey) - .collect(Collectors.toSet()); + .map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet()); } public Set infrequentSounds() { @@ -102,7 +100,7 @@ public void initConfig() { reader.close(); } catch (IOException | JsonParseException e) { Throwable cause = e.getCause(); - SoundsBeGoneConfig.LOGGER.error("Cause: {}", cause != null ? cause.getClass().getSimpleName() : "null"); + LOGGER.error("Failed to load config", e); if (cause != null && cause.getClass() == IllegalStateException.class) { convertConfig(configPath); return; @@ -147,8 +145,10 @@ private void convertConfig(Path configPath) { }.getType(); Set disabledSounds = GSON.fromJson(reader, setType); reader.close(); - for (String sound : disabledSounds) { - this.configData.soundVolumes.putIfAbsent(sound, 0); + if (disabledSounds != null) { + for (String sound : disabledSounds) { + this.configData.soundVolumes.putIfAbsent(sound, 0); + } } BufferedWriter writer = Files.newBufferedWriter(configPath); @@ -165,7 +165,7 @@ private void migrateLegacySounds() { for (String sound : configData.sounds) { configData.soundVolumes.putIfAbsent(sound, 0); } - configData.sounds.clear(); + configData.sounds = null; saveConfig(); } } diff --git a/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java b/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java index 226ca6d..5010f58 100644 --- a/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java +++ b/src/main/java/gg/meza/soundsbegone/client/mixin/AbstractSoundInstanceMixin.java @@ -21,6 +21,8 @@ public class AbstractSoundInstanceMixin { @Shadow protected float volume; @Unique private final RandomSource random = RandomSource.create(); + @Unique + private boolean soundsBeGone$telemetryReported; @Inject( method = "getVolume()F", @@ -36,7 +38,10 @@ private void getVolume(CallbackInfoReturnable cir) { if (!playSound) { SoundsBeGoneConfig.LOGGER.debug("Reducing the sound: {}", soundId); - SoundsBeGoneClient.telemetry.blockedSound(soundId); + if (!soundsBeGone$telemetryReported) { + SoundsBeGoneClient.telemetry.blockedSound(soundId); + soundsBeGone$telemetryReported = true; + } cir.setReturnValue(0.0F); cir.cancel(); track(soundId); @@ -46,12 +51,16 @@ private void getVolume(CallbackInfoReturnable cir) { int volumePercent = SoundsBeGoneClient.config.getSoundVolume(soundId); if (volumePercent == 0) { - SoundsBeGoneClient.telemetry.blockedSound(soundId); + if (!soundsBeGone$telemetryReported) { + SoundsBeGoneClient.telemetry.blockedSound(soundId); + soundsBeGone$telemetryReported = true; + } cir.setReturnValue(0.0F); cir.cancel(); track(soundId); return; } else if (volumePercent != 100) { + track(soundId); float newVolume = this.volume * (volumePercent / 100.0f); cir.setReturnValue(newVolume); cir.cancel();