Skip to content

Commit

Permalink
Fix earmuff behavior for long-running sounds
Browse files Browse the repository at this point in the history
Previously the earmuffs would only affect sounds when they started, i.e.
a sound started before putting on earmuffs would never get attenuated
while a sound started while wearing earmuffs would be attenuated
forever.
  • Loading branch information
malte0811 committed Feb 4, 2024
1 parent 456323a commit eb30ab1
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 174 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@
import blusunrize.immersiveengineering.common.register.IEPotions;
import blusunrize.immersiveengineering.common.util.ItemNBTHelper;
import blusunrize.immersiveengineering.common.util.Utils;
import blusunrize.immersiveengineering.common.util.sound.IEMuffledSound;
import blusunrize.immersiveengineering.common.util.sound.IEMuffledTickableSound;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.platform.Lighting;
import com.mojang.blaze3d.systems.RenderSystem;
Expand All @@ -65,7 +63,6 @@
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.client.resources.sounds.TickableSoundInstance;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
Expand Down Expand Up @@ -98,7 +95,6 @@
import net.neoforged.neoforge.capabilities.Capabilities.EnergyStorage;
import net.neoforged.neoforge.client.event.*;
import net.neoforged.neoforge.client.event.InputEvent.MouseScrollingEvent;
import net.neoforged.neoforge.client.event.sound.PlaySoundEvent;
import net.neoforged.neoforge.client.gui.overlay.ExtendedGui;
import net.neoforged.neoforge.client.gui.overlay.VanillaGuiOverlay;
import net.neoforged.neoforge.energy.IEnergyStorage;
Expand Down Expand Up @@ -263,32 +259,6 @@ public void onItemTooltip(ItemTooltipEvent event)
)));
}

@SubscribeEvent
public void onPlaySound(PlaySoundEvent event)
{
if(event.getSound()==null)
return;
else
event.getSound().getSource();
if(!EarmuffsItem.affectedSoundCategories.contains(event.getSound().getSource().getName()))
return;
if(ClientUtils.mc().player!=null)
{
ItemStack earmuffs = EarmuffsItem.EARMUFF_GETTERS.getFrom(ClientUtils.mc().player);
if(!earmuffs.isEmpty()&&
!ItemNBTHelper.getBoolean(earmuffs, "IE:Earmuffs:Cat_"+event.getSound().getSource().getName()))
{
for(String blacklist : IEClientConfig.earDefenders_SoundBlacklist.get())
if(blacklist!=null&&blacklist.equalsIgnoreCase(event.getSound().getLocation().toString()))
return;
if(event.getSound() instanceof TickableSoundInstance)
event.setSound(new IEMuffledTickableSound((TickableSoundInstance)event.getSound(), EarmuffsItem.getVolumeMod(earmuffs)));
else
event.setSound(new IEMuffledSound(event.getSound(), EarmuffsItem.getVolumeMod(earmuffs)));
}
}
}

@SubscribeEvent
public void onRenderItemFrame(RenderItemInFrameEvent event)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* BluSunrize
* Copyright (c) 2024
*
* This code is licensed under "Blu's License of Common Sense"
* Details can be found in the license file in the root folder of this project
*/

package blusunrize.immersiveengineering.client;

import blusunrize.immersiveengineering.api.Lib;
import blusunrize.immersiveengineering.common.config.IEClientConfig;
import blusunrize.immersiveengineering.common.items.EarmuffsItem;
import blusunrize.immersiveengineering.common.util.ItemNBTHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.sounds.SoundInstance;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.item.ItemStack;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod.EventBusSubscriber;
import net.neoforged.fml.common.Mod.EventBusSubscriber.Bus;
import net.neoforged.neoforge.event.TickEvent.ClientTickEvent;
import net.neoforged.neoforge.event.TickEvent.Phase;

import java.util.EnumMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@EventBusSubscriber(value = Dist.CLIENT, modid = Lib.MODID, bus = Bus.FORGE)
public class EarmuffHandler
{
private static final Map<SoundSource, Float> LAST_MULTIPLIERS = makeDefaultMultipliers();
private static Set<ResourceLocation> IGNORED_SOUNDS = Set.of();

/**
* Only the volume multiplier for ticking sounds is updated tick-by-tick. For non-ticking sounds (e.g. records) we
* need to force the volume update when necessary.
*/
@SubscribeEvent
public static void updateEarmuffMultipliers(ClientTickEvent ev)
{
if(ev.phase!=Phase.START||ClientUtils.mc().player==null)
return;
Map<SoundSource, Float> newMultipliers = makeDefaultMultipliers();
ItemStack earmuffs = EarmuffsItem.EARMUFF_GETTERS.getFrom(ClientUtils.mc().player);
if(!earmuffs.isEmpty())
for(SoundSource source : SoundSource.values())
if(EarmuffsItem.affectedSoundCategories.contains(source.getName()))
if(!ItemNBTHelper.getBoolean(earmuffs, "IE:Earmuffs:Cat_"+source.getName()))
{
// The max call is just a last safeguard against overly high attenuation (see documentation on
// EarmuffsItem.MIN_MULTIPLIER). The workbench config UI should limit the attenuation by itself.
final float newMultiplier = Math.max(
EarmuffsItem.MIN_MULTIPLIER, EarmuffsItem.getVolumeMod(earmuffs)
);
newMultipliers.put(source, newMultiplier);
}
for(SoundSource source : SoundSource.values())
if(LAST_MULTIPLIERS.get(source).floatValue()!=newMultipliers.get(source))
{
LAST_MULTIPLIERS.put(source, newMultipliers.get(source));
Minecraft.getInstance().getSoundManager().updateSourceVolume(
source, Minecraft.getInstance().options.getSoundSourceVolume(source)
);
}
}

public static float getVolumeMultiplier(SoundInstance sound)
{
if(IGNORED_SOUNDS.contains(sound.getLocation()))
return 1;
else
return LAST_MULTIPLIERS.get(sound.getSource());
}

public static void onConfigUpdate()
{
IGNORED_SOUNDS = IEClientConfig.earDefenders_SoundBlacklist.get().stream()
.map(ResourceLocation::tryParse)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}

private static Map<SoundSource, Float> makeDefaultMultipliers()
{
Map<SoundSource, Float> result = new EnumMap<>(SoundSource.class);
for(SoundSource type : SoundSource.values())
result.put(type, 1f);
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import blusunrize.immersiveengineering.ImmersiveEngineering;
import blusunrize.immersiveengineering.api.Lib;
import blusunrize.immersiveengineering.api.fluid.FluidUtils;
import blusunrize.immersiveengineering.client.EarmuffHandler;
import blusunrize.immersiveengineering.common.wires.IEWireTypes.IEWireType;
import com.google.common.collect.ImmutableList;
import net.neoforged.api.distmarker.Dist;
Expand Down Expand Up @@ -122,6 +123,7 @@ public static void onConfigChange(ModConfigEvent ev)
ImmersiveEngineering.proxy.resetManual();
}
FluidUtils.enableFractionDisplay = fractionDisplay.get();
EarmuffHandler.onConfigUpdate();
}
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* BluSunrize
* Copyright (c) 2024
*
* This code is licensed under "Blu's License of Common Sense"
* Details can be found in the license file in the root folder of this project
*/

package blusunrize.immersiveengineering.mixin.coremods.client;

import blusunrize.immersiveengineering.client.EarmuffHandler;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import net.minecraft.client.resources.sounds.SoundInstance;
import net.minecraft.client.sounds.SoundEngine;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

@Mixin(SoundEngine.class)
public class SoundEngineMixin
{
@ModifyExpressionValue(
method = "play", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/sounds/SoundEngine;calculateVolume(FLnet/minecraft/sounds/SoundSource;)F")
)
public float adjustVolumeAtStart(float original, SoundInstance sound)
{
return original*EarmuffHandler.getVolumeMultiplier(sound);
}

@ModifyReturnValue(method = "calculateVolume(Lnet/minecraft/client/resources/sounds/SoundInstance;)F", at = @At("TAIL"))
public float adjustVolumeForEarmuffs(float original, SoundInstance sound)
{
return original*EarmuffHandler.getVolumeMultiplier(sound);
}
}
3 changes: 2 additions & 1 deletion src/main/resources/immersiveengineering.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
"accessors.client.WorldRendererAccess",
"coremods.client.BipedModelMixin",
"coremods.client.LevelRendererMixin",
"coremods.client.RebuildTaskMixin"
"coremods.client.RebuildTaskMixin",
"coremods.client.SoundEngineMixin"
],
"injectors": {
"defaultRequire": 1
Expand Down

0 comments on commit eb30ab1

Please sign in to comment.