/* * Decompiled with CFR 0.152. */ package com.vinlanx.explosionoverhaul.client; import com.vinlanx.explosionoverhaul.Config; import com.vinlanx.explosionoverhaul.client.SoundEngineAudioQueue; import com.vinlanx.explosionoverhaul.client.SoundPhysicsCompatibility; import java.util.concurrent.atomic.AtomicBoolean; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import org.lwjgl.openal.AL10; import org.lwjgl.openal.ALC10; import org.lwjgl.openal.EXTEfx; @OnlyIn(value=Dist.CLIENT) @Mod.EventBusSubscriber(modid="explosionoverhaul", value={Dist.CLIENT}) public class LowPassConcussionEffect { private static final float HF_MIN = 0.01f; private static final float HF_MAX = 1.0f; private static final float GAIN_MIN = 0.1f; private static final int FADE_IN_TICKS = 40; private static final int FADE_OUT_TICKS = 100; private static volatile Phase phase = Phase.IDLE; private static volatile int holdTicks = 0; private static volatile int ticksInPhase = 0; private static final AtomicBoolean efxAvailable = new AtomicBoolean(false); private static volatile int filterId = 0; private static volatile float targetHfMin = 1.0f; private static volatile float targetGainMin = 1.0f; private static volatile float currentDeafnessGain = 1.0f; public static volatile boolean enabled = true; public static volatile boolean debugShowChat = false; private static volatile boolean compatibilityMode = false; private static volatile float lastAppliedHf = 1.0f; private static volatile float lastAppliedGain = 1.0f; public static void setDeafnessGain(float gain) { currentDeafnessGain = Math.max(0.0f, Math.min(1.0f, gain)); if (phase == Phase.IDLE && currentDeafnessGain < 0.99f && !compatibilityMode) { SoundEngineAudioQueue.enqueueAudio(() -> LowPassConcussionEffect.ensureFilterExists()); } } private static void ensureFilterExists() { if (!efxAvailable.get()) { long ctx = ALC10.alcGetCurrentContext(); long dev = ALC10.alcGetContextsDevice((long)ctx); if (!ALC10.alcIsExtensionPresent((long)dev, (CharSequence)"ALC_EXT_EFX")) { efxAvailable.set(false); return; } efxAvailable.set(true); } if (filterId == 0) { filterId = EXTEfx.alGenFilters(); EXTEfx.alFilteri((int)filterId, (int)32769, (int)1); EXTEfx.alFilterf((int)filterId, (int)1, (float)1.0f); EXTEfx.alFilterf((int)filterId, (int)2, (float)1.0f); } } public static void start(int seconds, float intensity) { Minecraft mc; if (!enabled) { return; } if (seconds < 1) { seconds = 1; } if (seconds > 600) { seconds = 600; } float effectiveIntensity = (Boolean)Config.CLIENT.enableLowPass.get() != false ? intensity : 0.001f; float addedStrength = Math.max(0.0f, Math.min(1.0f, effectiveIntensity)); if (phase != Phase.IDLE) { float currentStrength = (1.0f - targetHfMin) / 0.99f; float totalStrength = Math.min(1.0f, currentStrength + addedStrength); targetHfMin = 1.0f - totalStrength * 0.99f; holdTicks = Math.min(2000, holdTicks + seconds * 20); if (phase == Phase.FADE_OUT) { phase = Phase.HOLD; ticksInPhase = 0; } } else { float totalStrength = addedStrength; targetHfMin = 1.0f - totalStrength * 0.99f; targetGainMin = 0.1f; holdTicks = seconds * 20; ticksInPhase = 0; phase = Phase.FADE_IN; } if (!compatibilityMode) { SoundEngineAudioQueue.enqueueAudio(() -> { try { LowPassConcussionEffect.ensureFilterExists(); } catch (Throwable ex) { efxAvailable.set(false); } }); SoundEngineAudioQueue.drainNow(); } if (debugShowChat && (mc = Minecraft.m_91087_()) != null && mc.f_91074_ != null) { mc.f_91074_.m_5661_((Component)Component.m_237113_((String)("Low pass test queued for " + seconds + "s (strength=" + addedStrength + ")")), false); } } public static void start(int seconds, float intensity, double effectivePercent, String visibility, int intensityPercent) { Minecraft mc; if (debugShowChat && (mc = Minecraft.m_91087_()) != null && mc.f_91074_ != null) { mc.f_91074_.m_5661_((Component)Component.m_237113_((String)"__________________________________________"), false); String msg = String.format("\u041f\u043e\u0442\u0443\u0436\u043d\u0456\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0443\u0437\u0456\u0457 %.1f%% (%s) \u2014 \u0421\u0438\u043b\u0430 \u043f\u0440\u0438\u0433\u043b\u0443\u0448\u0435\u043d\u043d\u044f %d%%, \u0427\u0430\u0441 \u043f\u0440\u0438\u0433\u043b\u0443\u0448\u0435\u043d\u043d\u044f %.1f \u0441\u0435\u043a", effectivePercent, visibility, intensityPercent, (double)seconds); mc.f_91074_.m_5661_((Component)Component.m_237113_((String)msg).m_130940_(ChatFormatting.WHITE), false); mc.f_91074_.m_5661_((Component)Component.m_237113_((String)"__________________________________________"), false); } LowPassConcussionEffect.start(seconds, intensity); } public static void stop() { phase = Phase.IDLE; ticksInPhase = 0; lastAppliedHf = 1.0f; lastAppliedGain = 1.0f; targetGainMin = 1.0f; if (compatibilityMode) { SoundEngineAudioQueue.enqueueAudio(SoundPhysicsCompatibility::reapplyDirectFilterParameters); } SoundEngineAudioQueue.enqueueAudio(() -> { if (filterId != 0) { try { EXTEfx.alFilterf((int)filterId, (int)2, (float)1.0f); EXTEfx.alFilterf((int)filterId, (int)1, (float)1.0f); } catch (Throwable throwable) { // empty catch block } } }); } public static boolean isActive() { return phase != Phase.IDLE || currentDeafnessGain < 0.99f; } public static int getFilterId() { return filterId; } @SubscribeEvent public static void onClientTick(TickEvent.ClientTickEvent event) { if (event.phase == TickEvent.Phase.END) { LowPassConcussionEffect.onClientTick(); } } public static void onClientTick() { Minecraft mc = Minecraft.m_91087_(); if (mc != null && mc.m_91104_()) { return; } if (currentDeafnessGain < 0.99f || phase != Phase.IDLE) { float hf = 1.0f; float gainInterp = 1.0f; if (phase != Phase.IDLE) { ++ticksInPhase; switch (phase) { case FADE_IN: { float t = Math.min(1.0f, (float)ticksInPhase / 40.0f); hf = LowPassConcussionEffect.lerp(1.0f, targetHfMin, LowPassConcussionEffect.easeOutQuad(t)); gainInterp = LowPassConcussionEffect.lerp(1.0f, targetGainMin, LowPassConcussionEffect.easeOutQuad(t)); if (ticksInPhase < 40) break; phase = Phase.HOLD; ticksInPhase = 0; hf = targetHfMin; gainInterp = targetGainMin; break; } case HOLD: { hf = targetHfMin; gainInterp = targetGainMin; if (ticksInPhase < holdTicks) break; phase = Phase.FADE_OUT; ticksInPhase = 0; break; } case FADE_OUT: { float t = Math.min(1.0f, (float)ticksInPhase / 100.0f); hf = LowPassConcussionEffect.lerp(targetHfMin, 1.0f, LowPassConcussionEffect.easeInQuad(t)); gainInterp = LowPassConcussionEffect.lerp(targetGainMin, 1.0f, LowPassConcussionEffect.easeInQuad(t)); if (ticksInPhase < 100) break; LowPassConcussionEffect.stop(); hf = 1.0f; gainInterp = 1.0f; } } } float combinedGain = Math.max(0.0f, Math.min(1.0f, gainInterp * currentDeafnessGain)); LowPassConcussionEffect.applyFilterParamsOnAudioThread(hf, combinedGain); } } private static void applyFilterParamsOnAudioThread(float hf, float gain) { float clampedHf = Math.max(0.01f, Math.min(1.0f, hf)); float clampedGain = Math.max(0.0f, Math.min(1.0f, gain)); lastAppliedHf = clampedHf; lastAppliedGain = clampedGain; if (compatibilityMode) { SoundEngineAudioQueue.enqueueAudio(SoundPhysicsCompatibility::reapplyDirectFilterParameters); } if (!efxAvailable.get()) { return; } int fid = filterId; if (fid == 0) { return; } SoundEngineAudioQueue.enqueueAudio(() -> { try { EXTEfx.alFilterf((int)fid, (int)2, (float)clampedHf); EXTEfx.alFilterf((int)fid, (int)1, (float)clampedGain); } catch (Throwable throwable) { // empty catch block } }); } private static float lerp(float a, float b, float t) { return a + (b - a) * t; } private static float easeOutQuad(float t) { return 1.0f - (1.0f - t) * (1.0f - t); } private static float easeInQuad(float t) { return t * t; } private static String alErrorName(int err) { return switch (err) { case 0 -> "AL_NO_ERROR"; case 40961 -> "AL_INVALID_NAME"; case 40962 -> "AL_INVALID_ENUM"; case 40963 -> "AL_INVALID_VALUE"; case 40964 -> "AL_INVALID_OPERATION"; case 40965 -> "AL_OUT_OF_MEMORY"; default -> "AL_UNKNOWN_ERROR"; }; } public static void setCompatibilityMode(boolean compatibilityActive) { compatibilityMode = compatibilityActive; } public static float getCurrentHfMultiplier() { return Math.max(0.01f, Math.min(1.0f, lastAppliedHf)); } public static float getCurrentGainMultiplier() { return Math.max(0.0f, Math.min(1.0f, lastAppliedGain)); } public static void attachFilterToSource(int sourceId) { if (sourceId <= 0) { return; } if (!efxAvailable.get() || filterId == 0) { return; } try { if (!AL10.alIsSource((int)sourceId)) { return; } if (AL10.alGetSourcei((int)sourceId, (int)514) == 1) { return; } AL10.alSourcei((int)sourceId, (int)131077, (int)filterId); } catch (Throwable throwable) { // empty catch block } } public static void detachFilterFromSource(int sourceId) { try { if (AL10.alIsSource((int)sourceId)) { AL10.alSourcei((int)sourceId, (int)131077, (int)0); } } catch (Throwable throwable) { // empty catch block } } private static enum Phase { IDLE, FADE_IN, HOLD, FADE_OUT; } }