Stub remaining client effect blockers
Some checks failed
Build / build (push) Failing after 6m9s

This commit is contained in:
MrSphay
2026-05-06 23:46:53 +02:00
parent d22b64c729
commit 22043100a6
8 changed files with 89 additions and 1139 deletions

View File

@@ -1,5 +1,6 @@
package com.vinlanx.explosionoverhaul;
import com.mojang.serialization.MapCodec;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.BaseEntityBlock;
@@ -11,6 +12,8 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.MapColor;
public class VinlanxTheLightBlock extends BaseEntityBlock {
public static final MapCodec<VinlanxTheLightBlock> CODEC = simpleCodec(VinlanxTheLightBlock::new);
public VinlanxTheLightBlock(BlockBehaviour.Properties properties) {
super(properties);
}
@@ -34,4 +37,9 @@ public class VinlanxTheLightBlock extends BaseEntityBlock {
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new VinlanxTheLightBlockEntity(pos, state);
}
@Override
protected MapCodec<? extends BaseEntityBlock> codec() {
return CODEC;
}
}

View File

@@ -21,7 +21,6 @@ extends GeoItemRenderer<VinlanxTheLightItem> {
}
public void preRender(PoseStack poseStack, VinlanxTheLightItem animatable, BakedGeoModel model, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
super.preRender(poseStack, animatable, model, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
if (this.renderPerspective == ItemDisplayContext.GUI || this.renderPerspective == ItemDisplayContext.FIXED) {
poseStack.mulPose(Axis.YP.rotationDegrees(180.0f));
}

View File

@@ -1,664 +1,96 @@
/*
* Decompiled with CFR 0.152.
*/
package com.vinlanx.explosionoverhaul.client;
import com.vinlanx.explosionoverhaul.Config;
import com.vinlanx.explosionoverhaul.ModSounds;
import com.vinlanx.explosionoverhaul.client.Blur;
import com.vinlanx.explosionoverhaul.client.CameraShakeConcussionEffect;
import com.vinlanx.explosionoverhaul.client.DeafnessConcussionEffect;
import com.vinlanx.explosionoverhaul.client.LowPassConcussionEffect;
import java.util.concurrent.ThreadLocalRandom;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.client.resources.sounds.SoundInstance;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundEvent;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.neoforge.event.TickEvent;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.loading.FMLEnvironment;
@EventBusSubscriber(modid="explosionoverhaul", value={Dist.CLIENT})
public class ConcussionAudioEffect {
public static boolean debugSendDebugMessage = false;
public static boolean TestingHudHeart = true;
public static float currentBPM = 23.3f;
private static double heartbeatCycleTimer = 0.0;
private static float heartbeatVisualPulse = 0.0f;
private static float explosionBPMMod = 0.0f;
private static float jumpBPMMod = 0.0f;
private static boolean wasOnGround = true;
private static int idleTicks = 0;
private static boolean lubTriggered = false;
private static boolean dubTriggered = false;
@SubscribeEvent
public static void onClientTick(TickEvent.ClientTickEvent event) {
if (event.phase == TickEvent.Phase.END) {
Minecraft mc = Minecraft.getInstance();
if (mc.player != null && !mc.player.m_6084_()) {
ConcussionAudioEffect.stopAll();
}
}
public static void start(float power, double distance, boolean hasDirectLineOfSight, boolean explosionInCave) {
}
public static void stopAll() {
Blur.stop();
DeafnessConcussionEffect.stop();
LowPassConcussionEffect.stop();
CameraShakeConcussionEffect.stop();
}
public static void start(float power, double distance, boolean hasDirectLineOfSight, boolean explosionInCave) {
LocalPlayer player;
LocalPlayer player2;
LocalPlayer player3;
if (!FMLEnvironment.dist.isClient()) {
return;
}
if (!((Boolean)Config.CLIENT.enableConcussion.get()).booleanValue()) {
return;
}
Minecraft mc = Minecraft.getInstance();
if (mc == null || mc.f_91073_ == null || mc.player == null) {
return;
}
double rawPercent = ConcussionAudioEffect.computePercent(power, distance, explosionInCave);
if (explosionInCave) {
rawPercent = Math.min(100.0, rawPercent * 1.5);
}
double effectivePercent = hasDirectLineOfSight ? rawPercent : ConcussionAudioEffect.applyOcclusion(rawPercent);
double maxDistance = ConcussionAudioEffect.computeMaxDistance(power, explosionInCave);
if (rawPercent <= 0.0) {
LocalPlayer player4 = mc.player;
if (player4 != null && debugSendDebugMessage) {
double metersToExplosion = distance;
double onePercentDistance = maxDistance * 0.99;
String outMessage = String.format("\u041f\u043e\u0437\u0430 \u0437\u043e\u043d\u043e\u044e \u043f\u043e\u0440\u0430\u0437\u043a\u0438. \u0412\u0456\u0434\u0441\u0442\u0430\u043d\u044c \u0434\u043e \u0432\u0438\u0431\u0443\u0445\u0443: %.1f \u043c. 1%% \u043f\u043e\u0447\u0438\u043d\u0430\u0454\u0442\u044c\u0441\u044f \u0437: %.1f \u043c.", metersToExplosion, onePercentDistance);
player4.displayClientMessage((Component)Component.literal((String)outMessage).m_130940_(ChatFormatting.GRAY), false);
}
return;
}
double normalized = Math.max(0.0, Math.min(1.0, effectivePercent / 100.0));
float intensity = (float)normalized;
if (intensity < 0.01f) {
return;
}
double baseSilentSeconds = ConcussionAudioEffect.computeBaseSilentSeconds(effectivePercent, explosionInCave);
double intensityPercent = ConcussionAudioEffect.computeBaseIntensityPercent(effectivePercent);
double multiplier = ConcussionAudioEffect.computePowerMultiplier(power);
double finalSilentSeconds = baseSilentSeconds * multiplier * (Double)Config.CLIENT.concussionDurationMultiplier.get();
double lowpassChance = ConcussionAudioEffect.computeLowpassPowerChance(power, explosionInCave) * (Double)Config.CLIENT.concussionChanceMultiplier.get() * (Double)Config.CLIENT.lowPassChanceMultiplier.get();
boolean lowpassRoll = ThreadLocalRandom.current().nextDouble() <= lowpassChance;
double chance = ConcussionAudioEffect.computePowerChance(power, explosionInCave) * (Double)Config.CLIENT.concussionChanceMultiplier.get() * (Double)Config.CLIENT.deafnessChanceMultiplier.get();
boolean roll = ThreadLocalRandom.current().nextDouble() <= chance;
boolean anyAudioEffectActive = roll || lowpassRoll;
double baseBlurSeconds = ConcussionAudioEffect.computeBaseBlurSilentSeconds(effectivePercent, explosionInCave);
double blurMultiplier = ConcussionAudioEffect.computeBlurPowerMultiplier(power);
double finalBlurSeconds = baseBlurSeconds * blurMultiplier * (Double)Config.CLIENT.concussionDurationMultiplier.get();
boolean lowpassReduced = false;
if (!lowpassRoll) {
finalBlurSeconds = roll ? finalSilentSeconds : (finalBlurSeconds /= 3.0);
lowpassReduced = true;
}
int blurSeconds = Math.max(1, (int)Math.round(finalBlurSeconds));
double blurIntensityPercent = ConcussionAudioEffect.computeBaseBlurIntensityPercent(effectivePercent);
float blurIntensity = (float)(blurIntensityPercent / 100.0);
double swayIntensityPercent = ConcussionAudioEffect.computeBaseSwayIntensityPercent(effectivePercent) * (Double)Config.CLIENT.cameraSwayIntensity.get();
float swayIntensity = (float)(swayIntensityPercent / 100.0);
if (rawPercent > 0.0 && blurIntensity >= 0.01f && anyAudioEffectActive) {
float addedBPM = 0.0f;
if (rawPercent > 80.0) {
addedBPM = 60.0f;
} else if (rawPercent > 60.0) {
addedBPM = 40.0f;
} else if (rawPercent > 30.0) {
addedBPM = 20.0f;
}
explosionBPMMod = Math.min(200.0f, explosionBPMMod + addedBPM);
try {
LocalPlayer player5;
Blur.start(blurSeconds, blurIntensity);
if (((Boolean)Config.CLIENT.enableCameraSway.get()).booleanValue()) {
CameraShakeConcussionEffect.start(blurSeconds, swayIntensity);
}
if (debugSendDebugMessage && (player5 = mc.player) != null) {
String reductionInfo = lowpassReduced ? " [LowPass reduced /3]" : "";
String blurMsg = String.format("Blur & Sway %.1f m \u2014 activated (Blur: %.2f, Sway: %.2f, Time: %ds%s)", distance, Float.valueOf(blurIntensity), Float.valueOf(swayIntensity), blurSeconds, reductionInfo);
player5.displayClientMessage((Component)Component.literal((String)blurMsg).m_130940_(ChatFormatting.BLUE), false);
}
}
catch (Throwable player5) {}
} else if (debugSendDebugMessage && (player3 = mc.player) != null) {
String reason = !anyAudioEffectActive ? "no audio effects" : "out of range";
String blurMsg = String.format("Blur %.1f m \u2014 not activated (%s)", distance, reason);
player3.displayClientMessage((Component)Component.literal((String)blurMsg).m_130940_(ChatFormatting.GRAY), false);
}
int lowpassSeconds = blurSeconds;
double lowpassIntensityPercent = ConcussionAudioEffect.computeBaseLowpassIntensityPercent(effectivePercent);
float lowpassIntensity = (float)(lowpassIntensityPercent / 100.0);
if (lowpassIntensity < 0.01f) {
lowpassIntensity = 0.01f;
}
String lpVisibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
int lowpassIntensityRound = (int)Math.round(lowpassIntensityPercent);
if (((Boolean)Config.CLIENT.enableLowPass.get()).booleanValue() && rawPercent > 0.0 && lowpassIntensity >= 0.01f && (lowpassRoll || LowPassConcussionEffect.isActive())) {
try {
LocalPlayer player6;
float finalLpIntensity = lowpassRoll ? lowpassIntensity : 0.0f;
int finalLpRound = lowpassRoll ? lowpassIntensityRound : 0;
LowPassConcussionEffect.start(lowpassSeconds, finalLpIntensity, effectivePercent, lpVisibility, finalLpRound);
if (debugSendDebugMessage && (player6 = mc.player) != null) {
String status = lowpassRoll ? "activated" : "refreshed";
String lpMsg = String.format("Low pass %.1f m \u2014 %s (intensity=%.2f chance=%.1f%%)", distance, status, Float.valueOf(finalLpIntensity), lowpassChance * 100.0);
player6.displayClientMessage((Component)Component.literal((String)lpMsg).m_130940_(ChatFormatting.DARK_GREEN), false);
}
}
catch (Throwable finalLpIntensity) {}
} else if (debugSendDebugMessage && (player2 = mc.player) != null) {
String reason = rawPercent <= 0.0 || lowpassIntensity < 0.01f ? "out of range" : "chance fail";
String lpMsg = String.format("Low pass %.1f m \u2014 not activated (%s)", distance, reason);
player2.displayClientMessage((Component)Component.literal((String)lpMsg).m_130940_(ChatFormatting.GRAY), false);
}
if (debugSendDebugMessage) {
ConcussionAudioEffect.sendDebugMessage(mc, effectivePercent, rawPercent, hasDirectLineOfSight, distance, maxDistance);
}
if (debugSendDebugMessage && (player = mc.player) != null) {
Object visibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
visibility = (String)visibility + (explosionInCave ? " | \u0432\u0438\u0431\u0443\u0445 \u0443 \u043f\u0435\u0447\u0435\u0440\u0456" : " | \u0432\u0438\u0431\u0443\u0445 \u043d\u0435 \u0432 \u043f\u0435\u0447\u0435\u0440\u0456");
visibility = (String)visibility + String.format(" | \u0444\u0456\u043d\u0430\u043b\u044c\u043d\u0438\u0439 %%: %.1f%%", effectivePercent);
player.displayClientMessage((Component)Component.literal((String)visibility).m_130940_(ChatFormatting.GRAY), false);
String chanceMsg = String.format("\u0428\u0430\u043d\u0441 \u043a\u043e\u043d\u0442\u0443\u0437\u0456\u0457: %.1f%%", chance * 100.0);
player.displayClientMessage((Component)Component.literal((String)chanceMsg).m_130940_(ChatFormatting.YELLOW), false);
double maxDistanceNormal = ConcussionAudioEffect.computeMaxDistance(power, false);
double maxDistanceUsed = ConcussionAudioEffect.computeMaxDistance(power, explosionInCave);
String distMsg = String.format("\u041c\u0430\u043a\u0441 \u0434\u0438\u0441\u0442\u0430\u043d\u0446\u0456\u044f (\u0437\u0432\u0438\u0447\u0430\u0439\u043d\u0430): %.1f \u043c | (\u0432 \u043f\u0435\u0447\u0435\u0440\u0456): %.1f \u043c | \u0412\u0456\u0434\u0441\u0442\u0430\u043d\u044c \u0434\u043e \u0432\u0438\u0431\u0443\u0445\u0443: %.1f \u043c", maxDistanceNormal, maxDistanceUsed, distance);
player.displayClientMessage((Component)Component.literal((String)distMsg).m_130940_(ChatFormatting.GRAY), false);
double baseSilentNormal = ConcussionAudioEffect.computeBaseSilentSeconds(effectivePercent, false);
double baseSilentCave = ConcussionAudioEffect.computeBaseSilentSeconds(effectivePercent, true);
String silentMsg = String.format("\u0427\u0430\u0441 \u0441\u043a\u0440\u0443\u0447\u0443\u0432\u0430\u043d\u043d\u044f (\u0437\u0432\u0438\u0447\u0430\u0439\u043d\u0438\u0439): %.1fs | (\u0432 \u043f\u0435\u0447\u0435\u0440\u0456): %.1fs | \u0412\u0418\u041a\u041e\u0420\u0418\u0421\u0422\u0410\u041d\u041e: %.1fs", baseSilentNormal, baseSilentCave, baseSilentSeconds * multiplier);
player.displayClientMessage((Component)Component.literal((String)silentMsg).m_130940_(ChatFormatting.GRAY), false);
if (roll) {
String deafnessMsg = String.format("Deafness %.1f m \u2014 activated (intensity=%.1f%% chance=%.1f%%)", distance, intensityPercent, chance * 100.0);
player.displayClientMessage((Component)Component.literal((String)deafnessMsg).m_130940_(ChatFormatting.RED), false);
} else {
String deafnessMsg = String.format("Deafness %.1f m \u2014 not activated (chance)", distance);
player.displayClientMessage((Component)Component.literal((String)deafnessMsg).m_130940_(ChatFormatting.GRAY), false);
}
}
if (!roll) {
return;
}
if (!((Boolean)Config.CLIENT.enableDeafness.get()).booleanValue()) {
return;
}
int intensityRound = (int)Math.round(intensityPercent);
String visibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
float intensityFromIntensityPercent = (float)(intensityPercent / 100.0);
DeafnessConcussionEffect.start(intensityFromIntensityPercent, (float)finalSilentSeconds, effectivePercent, visibility, intensityRound);
public static void updateHeartbeat(LocalPlayer player, float currentIntensity) {
}
private static double computePercent(float power, double distance, boolean explosionInCave) {
double maxDistance = ConcussionAudioEffect.computeMaxDistance(power, explosionInCave);
public static float getCurrentHeartbeatVisual() {
return 0.0f;
}
public static void renderHeartbeatHUD(GuiGraphics guiGraphics) {
}
public static void sendDebugMessage(Minecraft mc, double effectivePercent, double rawPercent, boolean hasDirectLineOfSight, double distance, double maxDistance) {
}
public static double computePercent(float power, double distance, boolean explosionInCave) {
double maxDistance = computeMaxDistance(power, explosionInCave);
if (maxDistance <= 0.0) {
return 0.0;
}
double normalized = 1.0 - Math.max(0.0, distance) / maxDistance;
return Math.max(0.0, Math.min(1.0, normalized)) * 100.0;
return Math.max(0.0, Math.min(1.0, 1.0 - Math.max(0.0, distance) / maxDistance)) * 100.0;
}
private static double computeMaxDistance(float power, boolean explosionInCave) {
double[][] points = explosionInCave ? new double[][]{{1.0, 5.0}, {3.0, 10.0}, {10.0, 50.0}, {25.0, 90.0}, {50.0, 150.0}, {80.0, 200.0}, {120.0, 200.0}} : new double[][]{{1.0, 2.0}, {3.0, 5.0}, {10.0, 30.0}, {25.0, 70.0}, {50.0, 100.0}, {80.0, 150.0}, {120.0, 200.0}};
double clampedPower = Math.max(points[0][0], Math.min(points[points.length - 1][0], (double)power));
for (int i = 1; i < points.length; ++i) {
double lowerP = points[i - 1][0];
double upperP = points[i][0];
if (!(clampedPower <= upperP)) continue;
double lowerD = points[i - 1][1];
double upperD = points[i][1];
double t = (clampedPower - lowerP) / (upperP - lowerP);
return lowerD + (upperD - lowerD) * t;
}
return points[points.length - 1][1];
public static double computeMaxDistance(float power, boolean explosionInCave) {
return explosionInCave ? Math.max(10.0, power * 4.0) : Math.max(5.0, power * 2.5);
}
private static double applyOcclusion(double percent) {
if (percent >= 80.0) {
return percent / 1.2;
}
if (percent >= 60.0) {
return percent / 1.4;
}
if (percent >= 40.0) {
return percent / 1.6;
}
if (percent >= 20.0) {
return percent / 3.0;
}
if (percent >= 1.0) {
return 0.0;
}
public static double applyOcclusion(double percent) {
return Math.max(0.0, percent * 0.5);
}
public static double computeBaseSilentSeconds(double effectivePercent, boolean explosionInCave) {
return Math.max(0.0, effectivePercent / 25.0);
}
public static double computeBaseIntensityPercent(double effectivePercent) {
return Math.max(0.0, Math.min(100.0, effectivePercent));
}
public static double computePowerMultiplier(float power) {
return Math.max(1.0, power / 10.0);
}
public static double computeLowpassPowerChance(float power, boolean explosionInCave) {
return 0.0;
}
private static void sendDebugMessage(Minecraft mc, double effectivePercent, double rawPercent, boolean hasDirectLineOfSight, double distance, double maxDistance) {
LocalPlayer player = mc.player;
if (player == null) {
return;
}
double clamped = Math.max(0.0, Math.min(100.0, effectivePercent));
if (rawPercent <= 0.0) {
double metersToExplosion = distance;
double onePercentDistance = maxDistance * 0.99;
String outMessage = String.format("\u041f\u043e\u0437\u0430 \u0437\u043e\u043d\u043e\u044e \u043f\u043e\u0440\u0430\u0437\u043a\u0438. \u0412\u0456\u0434\u0441\u0442\u0430\u043d\u044c \u0434\u043e \u0432\u0438\u0431\u0443\u0445\u0443: %.1f \u043c. 1%% \u043f\u043e\u0447\u0438\u043d\u0430\u0454\u0442\u044c\u0441\u044f \u0437: %.1f \u043c.", metersToExplosion, onePercentDistance);
player.displayClientMessage((Component)Component.literal((String)outMessage).m_130940_(ChatFormatting.GRAY), false);
return;
}
ChatFormatting color = ConcussionAudioEffect.pickColor(clamped);
String visibility = hasDirectLineOfSight ? "\u043f\u0440\u044f\u043c\u0430 \u0432\u0438\u0434\u0438\u043c\u0456\u0441\u0442\u044c" : "\u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0430";
String message = String.format("\u041f\u043e\u0442\u0443\u0436\u043d\u0456\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0443\u0437\u0456\u0457 %.1f%% (%s)", clamped, visibility);
player.displayClientMessage((Component)Component.literal((String)message).m_130940_(color), false);
if (!hasDirectLineOfSight && rawPercent > 0.0) {
String rawMessage = String.format("(\u0434\u043e \u043f\u0435\u0440\u0435\u0448\u043a\u043e\u0434\u0438: %.1f%%)", Math.max(0.0, Math.min(100.0, rawPercent)));
player.displayClientMessage((Component)Component.literal((String)rawMessage).m_130940_(ChatFormatting.GRAY), false);
}
public static double computePowerChance(float power, boolean explosionInCave) {
return 0.0;
}
private static ChatFormatting pickColor(double percent) {
public static double computeBaseBlurSilentSeconds(double effectivePercent, boolean explosionInCave) {
return 0.0;
}
public static double computeBlurPowerMultiplier(float power) {
return 1.0;
}
public static double computeBaseBlurIntensityPercent(double effectivePercent) {
return 0.0;
}
public static double computeBaseSwayIntensityPercent(double effectivePercent) {
return 0.0;
}
public static double computeBaseLowpassIntensityPercent(double effectivePercent) {
return 0.0;
}
public static ChatFormatting pickColor(double percent) {
if (percent >= 80.0) {
return ChatFormatting.RED;
}
if (percent >= 60.0) {
return ChatFormatting.GOLD;
}
if (percent >= 40.0) {
if (percent >= 30.0) {
return ChatFormatting.YELLOW;
}
if (percent >= 20.0) {
return ChatFormatting.AQUA;
}
if (percent > 0.0) {
return ChatFormatting.BLUE;
}
return ChatFormatting.GRAY;
}
private static double computeBaseSilentSeconds(double effectivePercent, boolean explosionInCave) {
if (!explosionInCave) {
if (effectivePercent <= 40.0) {
return 0.0;
}
if (effectivePercent > 80.0) {
double t = (effectivePercent - 80.0) / 20.0;
return 4.0 + 1.0 * t;
}
if (effectivePercent > 60.0) {
double t = (effectivePercent - 60.0) / 20.0;
return 2.0 + 2.0 * t;
}
double t = (effectivePercent - 40.0) / 20.0;
return 1.0 + 1.0 * t;
}
if (effectivePercent <= 20.0) {
return 0.0;
}
if (effectivePercent > 80.0) {
double t = (effectivePercent - 80.0) / 20.0;
return 7.0 + 3.0 * t;
}
if (effectivePercent > 60.0) {
double t = (effectivePercent - 60.0) / 20.0;
return 4.0 + 1.0 * t;
}
double t = (effectivePercent - 20.0) / 40.0;
if (effectivePercent <= 40.0) {
double tt = (effectivePercent - 20.0) / 20.0;
return 2.0 + 1.0 * tt;
}
double tt = (effectivePercent - 40.0) / 20.0;
return 2.0 + 1.0 * tt;
}
private static double computeBaseIntensityPercent(double effectivePercent) {
if (effectivePercent <= 60.0) {
return 0.0;
}
if (effectivePercent <= 70.0) {
double t = (effectivePercent - 60.0) / 10.0;
return 0.0 + 60.0 * t;
}
if (effectivePercent <= 85.0) {
double t = (effectivePercent - 70.0) / 15.0;
return 60.0 + 20.0 * t;
}
if (effectivePercent <= 90.0) {
double t = (effectivePercent - 85.0) / 5.0;
return 80.0 + 20.0 * t;
}
return 100.0;
}
private static double computePowerMultiplier(double power) {
double[][] points = new double[][]{{2.0, 1.0}, {5.0, 1.2}, {6.0, 1.4}, {12.0, 1.8}, {13.0, 2.0}, {22.0, 2.3}, {23.0, 2.7}, {50.0, 3.0}, {51.0, 3.2}, {80.0, 5.0}, {120.0, 7.0}};
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
for (int i = 1; i < points.length; ++i) {
double lowerP = points[i - 1][0];
double upperP = points[i][0];
if (!(clamped <= upperP)) continue;
double lowerM = points[i - 1][1];
double upperM = points[i][1];
double t = (clamped - lowerP) / (upperP - lowerP);
return lowerM + (upperM - lowerM) * t;
}
return points[points.length - 1][1];
}
private static double computePowerChance(double power, boolean explosionInCave) {
double[][] points = explosionInCave ? new double[][]{{1.0, 0.25}, {2.0, 0.3}, {3.0, 0.35}, {5.0, 0.4}, {6.0, 0.5}, {10.0, 0.75}, {15.0, 0.9}, {20.0, 1.0}, {120.0, 1.0}} : new double[][]{{1.0, 0.15}, {2.0, 0.15}, {3.0, 0.175}, {5.0, 0.215}, {6.0, 0.225}, {10.0, 0.225}, {11.0, 0.35}, {25.0, 0.4}, {26.0, 0.5}, {34.0, 0.75}, {42.0, 0.9}, {50.0, 1.0}, {120.0, 1.0}};
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
for (int i = 1; i < points.length; ++i) {
double lowerP = points[i - 1][0];
double upperP = points[i][0];
if (!(clamped <= upperP)) continue;
double lowerC = points[i - 1][1];
double upperC = points[i][1];
double t = (clamped - lowerP) / (upperP - lowerP);
return lowerC + (upperC - lowerC) * t;
}
return 1.0;
}
private static double computeBaseBlurSilentSeconds(double effectivePercent, boolean explosionInCave) {
if (!explosionInCave) {
if (effectivePercent <= 40.0) {
return 0.0;
}
if (effectivePercent > 80.0) {
double t = (effectivePercent - 80.0) / 20.0;
return 6.0 + 2.0 * t;
}
if (effectivePercent > 60.0) {
double t = (effectivePercent - 60.0) / 20.0;
return 2.0 + 4.0 * t;
}
double t = (effectivePercent - 40.0) / 20.0;
return 0.0 + 2.0 * t;
}
if (effectivePercent <= 20.0) {
return 0.0;
}
if (effectivePercent > 80.0) {
double t = (effectivePercent - 80.0) / 20.0;
return 12.0 + 6.0 * t;
}
if (effectivePercent > 60.0) {
double t = (effectivePercent - 60.0) / 20.0;
return 6.0 + 2.0 * t;
}
if (effectivePercent <= 40.0) {
double tt = (effectivePercent - 20.0) / 20.0;
return 2.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
}
double tt = (effectivePercent - 40.0) / 20.0;
return 2.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
}
private static double computeBaseBlurIntensityPercent(double effectivePercent) {
if (effectivePercent < 60.0) {
return 0.0;
}
double t = (effectivePercent - 60.0) / 40.0;
return 1.0 + 49.0 * t;
}
private static double computeBaseSwayIntensityPercent(double effectivePercent) {
if (effectivePercent < 50.0) {
return 0.0;
}
double t = (effectivePercent - 50.0) / 50.0;
return 100.0 * t;
}
private static double computeBlurPowerMultiplier(double power) {
double[][] points = new double[][]{{2.0, 1.0}, {5.0, 1.2}, {6.0, 1.4}, {12.0, 1.8}, {13.0, 2.0}, {22.0, 2.3}, {23.0, 2.7}, {50.0, 3.0}, {51.0, 3.2}, {80.0, 5.0}, {120.0, 7.0}};
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
for (int i = 1; i < points.length; ++i) {
double lowerP = points[i - 1][0];
double upperP = points[i][0];
if (!(clamped <= upperP)) continue;
double lowerM = points[i - 1][1];
double upperM = points[i][1];
double t = (clamped - lowerP) / (upperP - lowerP);
return lowerM + (upperM - lowerM) * t;
}
return points[points.length - 1][1];
}
public static void renderHeartbeatHUD(GuiGraphics ctx) {
if (!((Boolean)Config.CLIENT.showHeartbeatHUD.get()).booleanValue() || !Blur.isActive()) {
return;
}
Minecraft mc = Minecraft.getInstance();
if (mc.player == null) {
return;
}
float bps = currentBPM / 60.0f;
String text = String.format("%.2f bps (%.1f BPM)", Float.valueOf(bps), Float.valueOf(currentBPM));
int x = ctx.m_280182_() - 10;
int y = 10;
int color = -65536;
if (currentBPM < 30.0f) {
color = -11141291;
} else if (currentBPM < 50.0f) {
color = -171;
}
ctx.m_280056_(mc.font, text, x - mc.font.width(text), y, color, false);
}
public static float getCurrentHeartbeatVisual() {
return heartbeatVisualPulse;
}
public static void updateHeartbeat(LocalPlayer player, float blurIntensity) {
float healthPercent;
boolean isMoving;
if (player == null) {
return;
}
if (!Blur.isActive()) {
explosionBPMMod *= 0.98f;
jumpBPMMod *= 0.98f;
if ((currentBPM += (23.3f - currentBPM) * 0.05f) < 24.0f && explosionBPMMod < 0.1f && jumpBPMMod < 0.1f) {
currentBPM = 23.3f;
explosionBPMMod = 0.0f;
jumpBPMMod = 0.0f;
heartbeatVisualPulse = 0.0f;
return;
}
}
float baseBPM = 23.3f;
boolean bl = isMoving = player.m_20184_().m_165925_() > 0.001;
if (isMoving) {
if (player.m_20142_()) {
baseBPM = 50.0f;
if (!player.m_20096_()) {
baseBPM = 60.0f;
}
} else {
baseBPM = 35.0f;
}
}
if ((healthPercent = player.m_21223_() / player.m_21233_()) < 0.1f) {
baseBPM += 63.3f;
} else if (healthPercent < 0.3f) {
baseBPM += 43.3f;
}
if (!player.m_20096_() && wasOnGround && isMoving) {
jumpBPMMod = Math.min(13.3f, jumpBPMMod + 3.3f);
}
wasOnGround = player.m_20096_();
jumpBPMMod *= 0.99f;
explosionBPMMod *= 0.995f;
if (player.f_19789_ > 3.0f) {
baseBPM += Math.min(16.6f, player.f_19789_ * 1.6f);
}
if (player.m_20146_() <= 0) {
baseBPM += 5.0f;
}
if (player.m_6047_()) {
baseBPM -= 3.3f;
}
if (!isMoving) {
if (++idleTicks >= 60) {
baseBPM -= 1.6f;
idleTicks = 0;
}
} else {
idleTicks = 0;
}
float finalTarget = baseBPM + jumpBPMMod + explosionBPMMod;
if ((finalTarget = Math.max(20.0f, Math.min(130.0f, finalTarget))) > currentBPM) {
float rampSpeed = explosionBPMMod > 5.0f || Blur.isActive() ? 0.4f : 0.15f;
currentBPM += (finalTarget - currentBPM) * rampSpeed;
} else {
currentBPM += (finalTarget - currentBPM) * 0.04f;
}
double cycleSeconds = 60.0 / (double)Math.max(5.0f, currentBPM);
heartbeatCycleTimer += 0.05;
if (heartbeatCycleTimer >= cycleSeconds) {
heartbeatCycleTimer -= cycleSeconds;
lubTriggered = false;
dubTriggered = false;
}
double t = heartbeatCycleTimer;
float pulse = 0.0f;
double lubEnd = cycleSeconds * 0.35;
double pause1End = cycleSeconds * 0.45;
double dubEnd = cycleSeconds * 0.7;
if (t < lubEnd) {
s = (float)Math.sin(t / lubEnd * Math.PI);
pulse = (float)Math.pow(s, 1.2);
if (!lubTriggered) {
lubTriggered = true;
if (blurIntensity >= 0.1f && ((Boolean)Config.CLIENT.enableHeartbeatPulse.get()).booleanValue()) {
try {
Minecraft mc = Minecraft.getInstance();
if (mc != null) {
mc.m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119755_((SoundEvent)((SoundEvent)ModSounds.HEART_LAB.get()), (float)1.0f, (float)100.0f));
}
}
catch (Throwable mc) {}
}
}
} else if (t > pause1End && t < dubEnd) {
s = (float)Math.sin((t - pause1End) / (dubEnd - pause1End) * Math.PI);
pulse = (float)Math.pow(s, 1.2) * 0.7f;
if (!dubTriggered) {
dubTriggered = true;
if (blurIntensity >= 0.1f && ((Boolean)Config.CLIENT.enableHeartbeatPulse.get()).booleanValue()) {
try {
Minecraft mc = Minecraft.getInstance();
if (mc != null) {
mc.m_91106_().m_120367_((SoundInstance)SimpleSoundInstance.m_119755_((SoundEvent)((SoundEvent)ModSounds.HEART_DAB.get()), (float)1.0f, (float)100.0f));
}
}
catch (Throwable throwable) {
// empty catch block
}
}
}
}
if ((healthPercent < 0.05f || explosionBPMMod > 80.0f && t < 2.0) && ThreadLocalRandom.current().nextDouble() < 0.03) {
heartbeatCycleTimer += 0.08;
}
float pulseScale = 0.3f + blurIntensity * 1.5f;
heartbeatVisualPulse = pulse * pulseScale;
}
private static double computeBaseLowpassSilentSeconds(double effectivePercent, boolean explosionInCave) {
if (!explosionInCave) {
if (effectivePercent <= 40.0) {
return 0.0;
}
if (effectivePercent > 80.0) {
double t = (effectivePercent - 80.0) / 20.0;
return 8.0 + 2.0 * t;
}
if (effectivePercent > 60.0) {
double t = (effectivePercent - 60.0) / 20.0;
return 4.0 + 4.0 * t;
}
double t = (effectivePercent - 40.0) / 20.0;
return 2.0 + 2.0 * t;
}
if (effectivePercent <= 20.0) {
return 0.0;
}
if (effectivePercent > 80.0) {
double t = (effectivePercent - 80.0) / 20.0;
return 14.0 + 6.0 * t;
}
if (effectivePercent > 60.0) {
double t = (effectivePercent - 60.0) / 20.0;
return 8.0 + 2.0 * t;
}
if (effectivePercent <= 40.0) {
double tt = (effectivePercent - 20.0) / 20.0;
return 4.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
}
double tt = (effectivePercent - 40.0) / 20.0;
return 4.0 + 2.0 * Math.max(0.0, Math.min(1.0, tt));
}
private static double computeBaseLowpassIntensityPercent(double effectivePercent) {
if (effectivePercent <= 40.0) {
return 0.0;
}
if (effectivePercent <= 50.0) {
double t = (effectivePercent - 40.0) / 10.0;
return 0.0 + 70.0 * t;
}
if (effectivePercent <= 70.0) {
double t = (effectivePercent - 50.0) / 20.0;
return 70.0 + 30.0 * t;
}
return 100.0;
}
private static double computeLowpassPowerMultiplier(double power) {
double[][] points = new double[][]{{2.0, 1.0}, {5.0, 1.2}, {6.0, 1.4}, {12.0, 1.8}, {13.0, 2.0}, {22.0, 2.3}, {23.0, 2.7}, {50.0, 3.0}, {51.0, 3.2}, {80.0, 5.0}, {120.0, 7.0}};
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
for (int i = 1; i < points.length; ++i) {
double lowerP = points[i - 1][0];
double upperP = points[i][0];
if (!(clamped <= upperP)) continue;
double lowerM = points[i - 1][1];
double upperM = points[i][1];
double t = (clamped - lowerP) / (upperP - lowerP);
return lowerM + (upperM - lowerM) * t;
}
return points[points.length - 1][1];
}
private static double computeLowpassPowerChance(double power, boolean explosionInCave) {
double[][] points = explosionInCave ? new double[][]{{1.0, 0.5}, {2.0, 0.6}, {3.0, 0.7}, {5.0, 0.8}, {6.0, 0.95}, {120.0, 1.0}} : new double[][]{{1.0, 0.3}, {2.0, 0.3}, {3.0, 0.35}, {5.0, 0.43}, {6.0, 0.45}, {10.0, 0.45}, {11.0, 0.7}, {25.0, 0.8}, {26.0, 1.0}, {120.0, 1.0}};
double clamped = Math.max(points[0][0], Math.min(points[points.length - 1][0], power));
for (int i = 1; i < points.length; ++i) {
double lowerP = points[i - 1][0];
double upperP = points[i][0];
if (!(clamped <= upperP)) continue;
double lowerC = points[i - 1][1];
double upperC = points[i][1];
double t = (clamped - lowerP) / (upperP - lowerP);
return lowerC + (upperC - lowerC) * t;
}
return 1.0;
}
}

View File

@@ -1,179 +1,37 @@
/*
* Decompiled with CFR 0.152.
*/
package com.vinlanx.explosionoverhaul.client;
import com.vinlanx.explosionoverhaul.Config;
import com.vinlanx.explosionoverhaul.client.LowPassConcussionEffect;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Options;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundSource;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.event.TickEvent;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.loading.FMLEnvironment;
@OnlyIn(value=Dist.CLIENT)
@EventBusSubscriber(modid="explosionoverhaul", value={Dist.CLIENT})
public class DeafnessConcussionEffect {
public static int DELAY_TICKS = 3;
public static int FADE_TO_SILENT_TICKS = 5;
public static int FADE_FROM_SILENT_TICKS = 100;
private static Phase phase = Phase.NONE;
private static int ticksInPhase = 0;
private static int phaseTicksTotal = 0;
private static int silentTicks = 0;
private static double baseMasterVolume = 1.0;
private static float currentIntensity = 0.0f;
private static float lastIntensity = 0.0f;
public static boolean debugShowChat = false;
public static volatile boolean enabled = true;
public static boolean start(float intensity, double silentSeconds, double effectivePercent, String visibility, int intensityPercent) {
LocalPlayer player;
float effectiveIntensity;
if (!FMLEnvironment.dist.isClient()) {
return false;
}
if (!enabled) {
return false;
}
float f = effectiveIntensity = (Boolean)Config.CLIENT.enableDeafness.get() != false ? intensity : 0.001f;
if (effectiveIntensity < 1.0E-4f) {
return false;
}
Minecraft mc = Minecraft.getInstance();
if (mc == null || mc.f_91073_ == null || mc.player == null) {
return false;
}
Options options = mc.options;
if (options == null) {
return false;
}
baseMasterVolume = (Double)options.m_246669_(SoundSource.MASTER).m_231551_();
if (phase != Phase.NONE) {
currentIntensity = Math.min(1.0f, currentIntensity + effectiveIntensity);
silentTicks = Math.min(2000, silentTicks + (int)Math.round(silentSeconds * 20.0));
if (phase != Phase.SILENT) {
phase = Phase.FADE_IN;
ticksInPhase = 0;
phaseTicksTotal = FADE_TO_SILENT_TICKS;
}
} else {
currentIntensity = effectiveIntensity;
silentTicks = Math.max(0, (int)Math.round(silentSeconds * 20.0));
phase = Phase.DELAY;
ticksInPhase = 0;
phaseTicksTotal = DELAY_TICKS;
}
lastIntensity = currentIntensity;
if (debugShowChat && (player = mc.player) != null) {
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 \u0441\u043a\u0440\u0443\u0447\u0443\u0432\u0430\u043d\u043d\u044f %d%%, \u0427\u0430\u0441 \u0441\u043a\u0440\u0443\u0447\u0443\u0432\u0430\u043d\u043d\u044f %.1f \u0441\u0435\u043a", effectivePercent, visibility, intensityPercent, silentSeconds);
player.displayClientMessage((Component)Component.literal((String)msg).m_130940_(ChatFormatting.WHITE), false);
}
return true;
}
@SubscribeEvent
public static void onClientTick(TickEvent.ClientTickEvent event) {
if (event.phase != TickEvent.Phase.END) {
return;
}
if (phase == Phase.NONE) {
return;
}
Minecraft mc = Minecraft.getInstance();
if (mc == null || mc.options == null) {
DeafnessConcussionEffect.resetVolume();
return;
}
if (mc.m_91104_()) {
return;
}
double t = Math.min(1.0, (double)(++ticksInPhase) / (double)phaseTicksTotal);
switch (phase) {
case DELAY: {
if (ticksInPhase < phaseTicksTotal) break;
DeafnessConcussionEffect.nextPhase(Phase.FADE_IN, FADE_TO_SILENT_TICKS);
break;
}
case FADE_IN: {
double minGain = baseMasterVolume * (1.0 - (double)currentIntensity);
double gain = DeafnessConcussionEffect.lerp(baseMasterVolume, minGain, DeafnessConcussionEffect.easeOutQuad(t));
DeafnessConcussionEffect.applyMasterVolume(mc, gain);
if (ticksInPhase < phaseTicksTotal) break;
DeafnessConcussionEffect.nextPhase(Phase.SILENT, silentTicks);
break;
}
case SILENT: {
double minGain = baseMasterVolume * (1.0 - (double)currentIntensity);
DeafnessConcussionEffect.applyMasterVolume(mc, minGain);
if (ticksInPhase < phaseTicksTotal) break;
DeafnessConcussionEffect.nextPhase(Phase.FADE_OUT, FADE_FROM_SILENT_TICKS);
break;
}
case FADE_OUT: {
double minGain = baseMasterVolume * (1.0 - (double)currentIntensity);
double gain = DeafnessConcussionEffect.lerp(minGain, baseMasterVolume, DeafnessConcussionEffect.easeInOutQuad(t));
DeafnessConcussionEffect.applyMasterVolume(mc, gain);
if (ticksInPhase < phaseTicksTotal) break;
DeafnessConcussionEffect.stop();
break;
}
}
}
private static void nextPhase(Phase next, int durationTicks) {
phase = next;
ticksInPhase = 0;
phaseTicksTotal = durationTicks;
return false;
}
public static void stop() {
DeafnessConcussionEffect.resetVolume();
phase = Phase.NONE;
ticksInPhase = 0;
phaseTicksTotal = 0;
lastIntensity = 0.0f;
}
public static boolean isActive() {
return phase != Phase.NONE;
return false;
}
private static void resetVolume() {
LowPassConcussionEffect.setDeafnessGain(1.0f);
public static void resetVolume() {
}
private static void applyMasterVolume(Minecraft mc, double volume) {
float clamped = (float)Math.max(0.0, Math.min(1.0, volume));
LowPassConcussionEffect.setDeafnessGain(clamped);
public static void applyMasterVolume(Minecraft mc, double volume) {
}
private static double lerp(double a, double b, double t) {
public static double lerp(double a, double b, double t) {
return a + (b - a) * t;
}
private static double easeOutQuad(double t) {
public static double easeOutQuad(double t) {
return 1.0 - (1.0 - t) * (1.0 - t);
}
private static double easeInOutQuad(double t) {
public static double easeInOutQuad(double t) {
return t < 0.5 ? 2.0 * t * t : 1.0 - Math.pow(-2.0 * t + 2.0, 2.0) / 2.0;
}
private static enum Phase {
NONE,
DELAY,
FADE_IN,
SILENT,
FADE_OUT;
}
}

View File

@@ -1,144 +1,53 @@
/*
* Decompiled with CFR 0.152.
*/
package com.vinlanx.explosionoverhaul.client;
import com.vinlanx.explosionoverhaul.Config;
import java.util.Random;
import net.minecraft.client.Minecraft;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.phys.Vec3;
public class ExplosionWindController {
private static final double BASE_SPEED = 0.05;
private static final double MAX_SPEED = 0.06;
private static final double LERP_FACTOR = 0.03;
private static final Random RANDOM = new Random();
private static final double[] HEIGHT_STOPS = new double[]{0.0, 0.25, 0.5, 0.75, 1.0};
private static final double[] DUST_SPEEDS = new double[]{0.02, 0.02, 0.02, 0.02, 0.02};
private static final double[] GLOW_SPEEDS = new double[]{0.0, 0.02, 0.04, 0.06, 0.08};
private static Vec3 currentWind = Vec3.f_82478_;
private static Vec3 targetDirection = Vec3.f_82478_;
private static int ticksUntilDirectionShift = 0;
public static Vec3 currentWind = Vec3.ZERO;
private ExplosionWindController() {
}
public static void tick() {
Vec3 desiredWind;
if (ticksUntilDirectionShift-- <= 0) {
targetDirection = ExplosionWindController.randomHorizontalDirection();
ticksUntilDirectionShift = 80 + RANDOM.nextInt(120);
}
if ((currentWind = ExplosionWindController.lerp(currentWind, desiredWind = targetDirection.m_82490_(0.05), 0.03)).m_82553_() > 0.06) {
currentWind = currentWind.m_82541_().m_82490_(0.06);
}
}
public static void reset() {
currentWind = Vec3.f_82478_;
targetDirection = Vec3.f_82478_;
ticksUntilDirectionShift = 0;
currentWind = Vec3.ZERO;
}
public static Vec3 getWind() {
if (!((Boolean)Config.CLIENT.enableWindEffect.get()).booleanValue()) {
return Vec3.f_82478_;
}
double multiplier = (Double)Config.CLIENT.windSpeedMultiplier.get();
return currentWind.m_82490_(multiplier);
return Vec3.ZERO;
}
public static Vec3 getScaledWind(double scale) {
if (!((Boolean)Config.CLIENT.enableWindEffect.get()).booleanValue()) {
return Vec3.f_82478_;
}
double multiplier = (Double)Config.CLIENT.windSpeedMultiplier.get();
return currentWind.m_82490_(scale * multiplier);
return Vec3.ZERO;
}
public static Vec3 getWindDirection() {
if (!((Boolean)Config.CLIENT.enableWindEffect.get()).booleanValue()) {
return Vec3.f_82478_;
}
double length = Math.sqrt(ExplosionWindController.currentWind.f_82479_ * ExplosionWindController.currentWind.f_82479_ + ExplosionWindController.currentWind.f_82481_ * ExplosionWindController.currentWind.f_82481_);
if (length < 1.0E-4) {
return Vec3.f_82478_;
}
return new Vec3(ExplosionWindController.currentWind.f_82479_ / length, 0.0, ExplosionWindController.currentWind.f_82481_ / length);
}
private static double getWeatherMultiplier() {
Minecraft minecraft = Minecraft.getInstance();
if (minecraft.f_91073_ != null && minecraft.player != null) {
Biome.Precipitation precipitation = ((Biome)minecraft.f_91073_.m_204166_(minecraft.player.m_20183_()).m_203334_()).m_264600_(minecraft.player.m_20183_());
if (minecraft.f_91073_.m_46471_() || minecraft.f_91073_.m_46470_()) {
return 1.5;
}
}
return 1.0;
return Vec3.ZERO;
}
public static double computeDustSpeed(double heightPercent) {
if (!((Boolean)Config.CLIENT.enableWindEffect.get()).booleanValue()) {
return 0.0;
}
double baseSpeed = ExplosionWindController.sampleProfile(heightPercent, DUST_SPEEDS);
double weatherMultiplier = ExplosionWindController.getWeatherMultiplier();
return baseSpeed * (Double)Config.CLIENT.windSpeedMultiplier.get() * weatherMultiplier;
return 0.0;
}
public static double computeGlowSpeed(double heightPercent) {
if (!((Boolean)Config.CLIENT.enableWindEffect.get()).booleanValue()) {
return 0.0;
}
double baseSpeed = ExplosionWindController.sampleProfile(heightPercent, GLOW_SPEEDS);
double weatherMultiplier = ExplosionWindController.getWeatherMultiplier();
return baseSpeed * (Double)Config.CLIENT.windSpeedMultiplier.get() * weatherMultiplier;
return 0.0;
}
public static Vec3 getDustWindVector(double heightPercent) {
Vec3 direction = ExplosionWindController.getWindDirection();
if (direction == Vec3.f_82478_) {
return direction;
}
return direction.m_82490_(ExplosionWindController.computeDustSpeed(heightPercent));
return Vec3.ZERO;
}
public static Vec3 getGlowWindVector(double heightPercent) {
Vec3 direction = ExplosionWindController.getWindDirection();
if (direction == Vec3.f_82478_) {
return direction;
}
return direction.m_82490_(ExplosionWindController.computeGlowSpeed(heightPercent));
return Vec3.ZERO;
}
private static double sampleProfile(double heightPercent, double[] speeds) {
double clamped = Math.max(0.0, Math.min(1.0, heightPercent));
for (int i = 1; i < HEIGHT_STOPS.length; ++i) {
double prevStop = HEIGHT_STOPS[i - 1];
double stop = HEIGHT_STOPS[i];
if (!(clamped <= stop)) continue;
double t = stop <= prevStop ? 0.0 : (clamped - prevStop) / (stop - prevStop);
double prevValue = speeds[i - 1];
double value = speeds[i];
return prevValue + (value - prevValue) * t;
}
return speeds[speeds.length - 1];
public static double sampleProfile(double heightPercent, double[] speeds) {
return speeds.length == 0 ? 0.0 : speeds[0];
}
private static Vec3 lerp(Vec3 from, Vec3 to, double factor) {
double clamped = Math.max(0.0, Math.min(1.0, factor));
double x = from.f_82479_ + (to.f_82479_ - from.f_82479_) * clamped;
double y = from.f_82480_ + (to.f_82480_ - from.f_82480_) * clamped;
double z = from.f_82481_ + (to.f_82481_ - from.f_82481_) * clamped;
return new Vec3(x, y, z);
}
private static Vec3 randomHorizontalDirection() {
double angle = RANDOM.nextDouble() * Math.PI * 2.0;
double x = Math.cos(angle);
double z = Math.sin(angle);
return new Vec3(x, 0.0, z);
public static double getWeatherMultiplier() {
return 1.0;
}
}

View File

@@ -1,210 +1,15 @@
/*
* Decompiled with CFR 0.152.
*/
package com.vinlanx.explosionoverhaul.client;
import com.vinlanx.explosionoverhaul.Config;
import com.vinlanx.explosionoverhaul.CustomGlowParticleOptions;
import com.vinlanx.explosionoverhaul.PlasmaParticleOptions;
import com.vinlanx.explosionoverhaul.client.ExplosionWindController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
public class PhysicsBasedExplosionEffect {
private final ClientLevel level;
private final Random random;
private final Vec3 position;
private final float power;
private int age = 0;
private final int maxAge = 8;
private final float maxRadius;
private final int particleCount;
private final float particleScaleBase;
private final int totalLifetime;
private boolean finished = false;
private final int totalSparks;
private float sparkSpawnAccumulator = 0.0f;
private final List<Vec3> sparkDirections;
private int sparkIndex = 0;
public PhysicsBasedExplosionEffect(Vec3 position, float power) {
this.position = position;
this.power = power;
this.random = new Random();
this.level = Minecraft.getInstance().f_91073_;
if (this.level == null) {
this.finished = true;
this.maxRadius = 0.0f;
this.particleCount = 0;
this.particleScaleBase = 0.0f;
this.totalLifetime = 0;
this.totalSparks = 0;
this.sparkDirections = new ArrayList<Vec3>();
return;
}
float calcPower = Mth.m_14036_((float)power, (float)1.0f, (float)100.0f);
float powerFraction = calcPower / 100.0f;
this.maxRadius = Mth.m_14179_((float)powerFraction, (float)3.0f, (float)40.0f);
this.particleCount = (int)Mth.m_14179_((float)powerFraction, (float)40.0f, (float)400.0f);
this.particleScaleBase = Mth.m_14179_((float)powerFraction, (float)5.0f, (float)37.5f);
this.totalLifetime = (int)Mth.m_14179_((float)powerFraction, (float)300.0f, (float)1800.0f) + this.random.nextInt(100) - 50;
this.totalSparks = (int)Mth.m_14179_((float)powerFraction, (float)3.0f, (float)150.0f);
this.sparkDirections = new ArrayList<Vec3>();
if (this.totalSparks > 0) {
double goldenRatio = (1.0 + Math.sqrt(5.0)) / 2.0;
double angleIncrement = Math.PI * 2 * goldenRatio;
for (int i = 0; i < this.totalSparks; ++i) {
double y = 1.0 - (double)i / (double)(this.totalSparks - 1) * 2.0;
double radius = Math.sqrt(1.0 - y * y);
double theta = angleIncrement * (double)i;
double x = Math.cos(theta) * radius;
double z = Math.sin(theta) * radius;
this.sparkDirections.add(new Vec3(x, z, y).m_82541_());
}
Collections.shuffle(this.sparkDirections, this.random);
}
}
public void tick() {
if (this.finished) {
return;
}
if (!((Boolean)Config.CLIENT.enableExplosionParticles.get()).booleanValue()) {
this.finished = true;
return;
}
++this.age;
if (this.age > this.maxAge) {
this.finished = true;
return;
}
if (Config.CLIENT.particleRenderMode.get() == Config.Client.ParticleRenderMode.REALISTIC_2) {
this.tickRealistic2();
} else {
this.tickRegular();
}
}
private void tickRealistic2() {
if (this.age == 1) {
double distance;
float f = this.age;
Objects.requireNonNull(this);
float progress = f / 8.0f;
float currentRadius = this.maxRadius * (float)Math.pow(progress, 0.4);
Vec3 particlePos = this.position.m_82520_((this.random.nextDouble() - 0.5) * (double)currentRadius, (this.random.nextDouble() - 0.5) * (double)currentRadius, (this.random.nextDouble() - 0.5) * (double)currentRadius);
Vec3 motion = new Vec3((this.random.nextDouble() - 0.5) * 0.05, (this.random.nextDouble() - 0.5) * 0.05, (this.random.nextDouble() - 0.5) * 0.05);
double distance3D = particlePos.m_82554_(this.position);
double heightPercent = this.maxRadius <= 0.0f ? 0.5 : Mth.m_14008_((double)(distance3D / (double)this.maxRadius), (double)0.25, (double)1.0);
Vec3 windDirection = ExplosionWindController.getWindDirection();
double glowSpeed = ExplosionWindController.computeGlowSpeed(heightPercent);
if (windDirection != Vec3.f_82478_ && glowSpeed > 0.0) {
motion = motion.m_82549_(windDirection.m_82490_(glowSpeed * 0.6));
}
int zone = (distance = particlePos.m_82554_(this.position)) / (double)this.maxRadius < 0.4 ? 1 : 0;
float particleScale = this.particleScaleBase * 1.0f * ((Double)Config.CLIENT.particleSizeScale.get()).floatValue();
int animationType = this.power <= 5.0f ? 2 : this.random.nextInt(2);
CustomGlowParticleOptions options = new CustomGlowParticleOptions(zone, this.power, particleScale, animationType, (float)this.position.f_82480_, this.maxRadius, (float)heightPercent);
this.level.m_7106_((ParticleOptions)options, particlePos.f_82479_, particlePos.f_82480_, particlePos.f_82481_, motion.f_82479_, motion.f_82480_, motion.f_82481_);
}
if (this.totalSparks > 0 && this.sparkIndex < this.totalSparks && ((Boolean)Config.CLIENT.enablePlasmaParticles.get()).booleanValue()) {
float f = this.age;
Objects.requireNonNull(this);
float progress2 = f / 8.0f;
float currentRadius2 = this.maxRadius * (float)Math.pow(progress2, 0.4);
float f2 = this.totalSparks;
Objects.requireNonNull(this);
float sparksToSpawnThisTick = f2 / 8.0f;
this.sparkSpawnAccumulator += sparksToSpawnThisTick;
int sparksToActuallySpawn = (int)this.sparkSpawnAccumulator;
if (sparksToActuallySpawn > 0) {
this.sparkSpawnAccumulator -= (float)sparksToActuallySpawn;
for (int j = 0; j < sparksToActuallySpawn && this.sparkIndex < this.totalSparks; ++j) {
Vec3 plasmaMotion = this.sparkDirections.get(this.sparkIndex);
++this.sparkIndex;
Vec3 plasmaSpawnPos = this.position.m_82549_(plasmaMotion.m_82490_((double)currentRadius2 * 0.8));
float strongSparkChance = 0.1f;
if (this.power > 10.0f) {
float powerFractionForChance = Mth.m_184655_((float)this.power, (float)10.0f, (float)100.0f);
strongSparkChance = Mth.m_14179_((float)powerFractionForChance, (float)0.1f, (float)0.35f);
}
float force = this.random.nextFloat() < strongSparkChance ? Mth.m_14179_((float)(this.power / 100.0f), (float)2.0f, (float)14.0f) * (0.9f + this.random.nextFloat() * 0.4f) : Mth.m_14179_((float)(this.power / 100.0f), (float)1.3f, (float)6.5f) * (0.6f + this.random.nextFloat() * 0.4f);
plasmaMotion = plasmaMotion.m_82490_((double)force);
PlasmaParticleOptions plasmaOptions = new PlasmaParticleOptions(this.power);
this.level.m_6493_((ParticleOptions)plasmaOptions, true, plasmaSpawnPos.f_82479_, plasmaSpawnPos.f_82480_, plasmaSpawnPos.f_82481_, plasmaMotion.f_82479_, plasmaMotion.f_82480_, plasmaMotion.f_82481_);
}
}
}
this.finished = false;
}
private void tickRegular() {
int particlesThisTick = this.particleCount / this.maxAge;
if (this.age == this.maxAge) {
particlesThisTick = this.particleCount - particlesThisTick * (this.maxAge - 1);
}
float f = this.age;
Objects.requireNonNull(this);
float progress = f / 8.0f;
float currentRadius = this.maxRadius * (float)Math.pow(progress, 0.4);
for (int i = 0; i < particlesThisTick; ++i) {
double distance;
double u = this.random.nextDouble();
double v = this.random.nextDouble();
double theta = Math.PI * 2 * u;
double phi = Math.acos(2.0 * v - 1.0);
double r = currentRadius;
Vec3 particlePos = this.position.m_82520_(r * Math.sin(phi) * Math.cos(theta), r * Math.sin(phi) * Math.sin(theta), r * Math.cos(phi));
Vec3 motion = new Vec3((this.random.nextDouble() - 0.5) * 0.05, (this.random.nextDouble() - 0.5) * 0.05, (this.random.nextDouble() - 0.5) * 0.05);
double distance3D = particlePos.m_82554_(this.position);
double heightPercent = this.maxRadius <= 0.0f ? 0.5 : Mth.m_14008_((double)(distance3D / (double)this.maxRadius), (double)0.25, (double)1.0);
Vec3 windDirection = ExplosionWindController.getWindDirection();
double glowSpeed = ExplosionWindController.computeGlowSpeed(heightPercent);
if (windDirection != Vec3.f_82478_ && glowSpeed > 0.0) {
motion = motion.m_82549_(windDirection.m_82490_(glowSpeed * 0.6));
}
int zone = (distance = particlePos.m_82554_(this.position)) / (double)this.maxRadius < 0.4 ? 1 : 0;
float particleScale = this.particleScaleBase * (0.8f + this.random.nextFloat() * 0.4f) * ((Double)Config.CLIENT.particleSizeScale.get()).floatValue();
int animationType = this.power <= 5.0f ? 2 : this.random.nextInt(2);
CustomGlowParticleOptions options = new CustomGlowParticleOptions(zone, this.power, particleScale, animationType, (float)this.position.f_82480_, this.maxRadius, (float)heightPercent);
this.level.m_7106_((ParticleOptions)options, particlePos.f_82479_, particlePos.f_82480_, particlePos.f_82481_, motion.f_82479_, motion.f_82480_, motion.f_82481_);
}
if (this.totalSparks > 0 && this.sparkIndex < this.totalSparks && ((Boolean)Config.CLIENT.enablePlasmaParticles.get()).booleanValue()) {
float f2 = this.totalSparks;
Objects.requireNonNull(this);
float sparksToSpawnThisTick = f2 / 8.0f;
this.sparkSpawnAccumulator += sparksToSpawnThisTick;
int sparksToActuallySpawn = (int)this.sparkSpawnAccumulator;
if (sparksToActuallySpawn > 0) {
this.sparkSpawnAccumulator -= (float)sparksToActuallySpawn;
for (int j = 0; j < sparksToActuallySpawn && this.sparkIndex < this.totalSparks; ++j) {
Vec3 plasmaMotion = this.sparkDirections.get(this.sparkIndex);
++this.sparkIndex;
Vec3 plasmaSpawnPos = this.position.m_82549_(plasmaMotion.m_82490_((double)currentRadius * 0.8));
float strongSparkChance = 0.1f;
if (this.power > 10.0f) {
float powerFractionForChance = Mth.m_184655_((float)this.power, (float)10.0f, (float)100.0f);
strongSparkChance = Mth.m_14179_((float)powerFractionForChance, (float)0.1f, (float)0.35f);
}
float force = this.random.nextFloat() < strongSparkChance ? Mth.m_14179_((float)(this.power / 100.0f), (float)2.0f, (float)14.0f) * (0.9f + this.random.nextFloat() * 0.4f) : Mth.m_14179_((float)(this.power / 100.0f), (float)1.3f, (float)6.5f) * (0.6f + this.random.nextFloat() * 0.4f);
plasmaMotion = plasmaMotion.m_82490_((double)force);
PlasmaParticleOptions plasmaOptions = new PlasmaParticleOptions(this.power);
this.level.m_6493_((ParticleOptions)plasmaOptions, true, plasmaSpawnPos.f_82479_, plasmaSpawnPos.f_82480_, plasmaSpawnPos.f_82481_, plasmaMotion.f_82479_, plasmaMotion.f_82480_, plasmaMotion.f_82481_);
}
}
}
this.finished = false;
}
public boolean isFinished() {
return this.finished;
return true;
}
}

View File

@@ -1,76 +1,15 @@
/*
* Decompiled with CFR 0.152.
*/
package com.vinlanx.explosionoverhaul.client;
import com.vinlanx.explosionoverhaul.Config;
import java.util.Random;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
public class ShockwaveEffect {
private final ClientLevel level;
private final Vec3 position;
private final float power;
private final Random random = new Random();
private int age = 0;
private final int maxAge;
private final float maxRadius;
private final int particlesPerTick;
private final float shellThickness;
private boolean finished = false;
public ShockwaveEffect(Vec3 position, float power) {
this.level = Minecraft.getInstance().f_91073_;
this.position = position;
this.power = power;
float powerFraction = Mth.m_184655_((float)this.power, (float)5.0f, (float)100.0f);
this.maxAge = (int)Mth.m_14179_((float)powerFraction, (float)4.0f, (float)7.0f);
float fireballPowerFraction = Mth.m_14036_((float)power, (float)1.0f, (float)100.0f) / 100.0f;
float fireballRadius = Mth.m_14179_((float)fireballPowerFraction, (float)3.0f, (float)40.0f);
float normalizedPowerSqrt = Mth.m_184655_((float)((float)Math.sqrt(power)), (float)((float)Math.sqrt(5.0)), (float)((float)Math.sqrt(100.0)));
float shockwaveMultiplier = Mth.m_14179_((float)normalizedPowerSqrt, (float)2.0f, (float)8.0f);
this.maxRadius = fireballRadius * shockwaveMultiplier * 3.0f;
this.particlesPerTick = (int)Mth.m_14179_((float)powerFraction, (float)70.0f, (float)400.0f);
this.shellThickness = Mth.m_14179_((float)powerFraction, (float)0.5f, (float)4.0f);
}
public void tick() {
if (this.finished || this.level == null) {
return;
}
if (!((Boolean)Config.CLIENT.enableShockwaveEffect.get()).booleanValue()) {
this.finished = true;
return;
}
++this.age;
if (this.age > this.maxAge) {
this.finished = true;
return;
}
float progress = (float)this.age / (float)this.maxAge;
float easedProgress = Mth.m_14031_((float)(progress * (float)Math.PI / 2.0f));
float currentRadius = this.maxRadius * easedProgress;
for (int i = 0; i < this.particlesPerTick; ++i) {
double u = this.random.nextDouble();
double v = this.random.nextDouble();
double theta = Math.PI * 2 * u;
double phi = Math.acos(2.0 * v - 1.0);
float radiusOffset = (this.random.nextFloat() - 0.5f) * this.shellThickness;
float finalRadius = currentRadius + radiusOffset;
if (finalRadius < 0.0f) {
finalRadius = 0.0f;
}
Vec3 particlePos = this.position.m_82520_((double)finalRadius * Math.sin(phi) * Math.cos(theta), (double)finalRadius * Math.sin(phi) * Math.sin(theta), (double)finalRadius * Math.cos(phi));
this.level.m_6493_((ParticleOptions)ParticleTypes.f_123813_, true, particlePos.f_82479_, particlePos.f_82480_, particlePos.f_82481_, 0.0, 0.0, 0.0);
}
}
public boolean isFinished() {
return this.finished;
return true;
}
}

View File

@@ -85,7 +85,7 @@ ExplosionAccessor {
Level level = this.level;
if (level instanceof ServerLevel) {
ServerLevel serverLevel = (ServerLevel)level;
ServerExplosionHandler.handleExplosion(serverLevel, (Explosion)this, this.getToBlow());
ServerExplosionHandler.handleExplosion(serverLevel, (Explosion)(Object)this, this.getToBlow());
}
}
}