Files
Explosion-Overhaul/src/main/java/com/vinlanx/explosionoverhaul/client/GroundDustEffect.java
MrSphay 8584bf771f
Some checks failed
Build / build (push) Failing after 6m33s
Restore original explosion visuals
2026-05-09 19:04:09 +02:00

190 lines
7.8 KiB
Java

package com.vinlanx.explosionoverhaul.client;
import com.vinlanx.explosionoverhaul.Config;
import com.vinlanx.explosionoverhaul.SmokeParticleOptions;
import java.awt.Color;
import java.util.Random;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.Mth;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.MapColor;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
public class GroundDustEffect {
private final ClientLevel level;
private final Vec3 center;
private final float maxRadius;
private final int particlesPerTick;
private final int maxAge;
private final float particleBaseSize;
private final Random random = new Random();
private final int raycastFrequency;
private Color currentDustColor = new Color(128, 128, 128);
private int age;
private boolean finished;
public GroundDustEffect(Vec3 position, float power) {
this.level = Minecraft.getInstance().level;
this.center = position;
float quality = Config.CLIENT.groundDustQuality.get().floatValue();
this.raycastFrequency = Math.max(1, Config.CLIENT.groundDustRaycastFrequency.get());
float powerFraction = Mth.clamp(power / 100.0f, 0.0f, 1.0f);
this.particlesPerTick = Math.max(1, (int)(Mth.lerp(powerFraction, 40.0f, 200.0f) * quality));
this.maxAge = Math.max(1, (int)(Mth.lerp(powerFraction, 30.0f, 70.0f) * quality));
this.maxRadius = power * this.calculateRadiusMultiplier(power);
this.particleBaseSize = Mth.lerp(powerFraction, 1.0f, 12.0f);
if (this.level == null || quality <= 0.0f) {
this.finished = true;
}
}
public void tick() {
if (this.finished || this.level == null) {
return;
}
if (!Config.CLIENT.enableGroundDustEffect.get()) {
this.finished = true;
return;
}
if (++this.age > this.maxAge) {
this.finished = true;
return;
}
float progress = this.age / (float)this.maxAge;
float easedProgress = 1.0f - (float)Math.pow(1.0f - progress, 3.0);
float currentRadius = this.maxRadius * easedProgress;
if (this.age % 10 == 0) {
double checkAngle = this.random.nextDouble() * Math.PI * 2.0;
double checkX = this.center.x + Math.cos(checkAngle) * currentRadius;
double checkZ = this.center.z + Math.sin(checkAngle) * currentRadius;
BlockHitResult hit = this.level.clip(new ClipContext(
new Vec3(checkX, this.center.y + 15.0, checkZ),
new Vec3(checkX, this.center.y - 15.0, checkZ),
ClipContext.Block.COLLIDER,
ClipContext.Fluid.NONE,
null));
if (hit.getType() == HitResult.Type.BLOCK) {
Color color = getDustColorForState(this.level.getBlockState(hit.getBlockPos()));
if (color != null) {
this.currentDustColor = color;
}
}
}
double cachedY = this.center.y;
for (int i = 0; i < this.particlesPerTick; ++i) {
double angle = i / (double)this.particlesPerTick * Math.PI * 2.0 + (this.random.nextDouble() - 0.5) * 0.1;
double radiusFrac = this.random.nextDouble();
double spawnRadius = currentRadius * (0.6 + radiusFrac * 0.4);
double x = this.center.x + Math.cos(angle) * spawnRadius;
double z = this.center.z + Math.sin(angle) * spawnRadius;
if (i % this.raycastFrequency == 0) {
BlockHitResult hit = this.level.clip(new ClipContext(
new Vec3(x, this.center.y + 15.0, z),
new Vec3(x, this.center.y - 15.0, z),
ClipContext.Block.COLLIDER,
ClipContext.Fluid.NONE,
null));
if (hit.getType() != HitResult.Type.BLOCK) {
continue;
}
cachedY = hit.getLocation().y;
}
double spawnY = cachedY;
Vec3 direction = new Vec3(x - this.center.x, 0.0, z - this.center.z).normalize();
double motionStrength = Mth.lerp(1.0f - progress, 0.05f, 0.45f);
double motionX = direction.x * motionStrength + (this.random.nextDouble() - 0.5) * 0.05;
double motionZ = direction.z * motionStrength + (this.random.nextDouble() - 0.5) * 0.05;
double motionY = (this.random.nextDouble() - 0.5) * 0.02;
Vec3 windDirection = ExplosionWindController.getWindDirection();
double windSpeed = ExplosionWindController.computeDustSpeed(0.0);
if (windDirection.lengthSqr() > 1.0E-4 && windSpeed > 0.0) {
motionX += windDirection.x * windSpeed * 0.65;
motionZ += windDirection.z * windSpeed * 0.65;
}
float red;
float green;
float blue;
float alpha;
float scale;
if (radiusFrac <= 0.2) {
red = 0.2f;
green = 0.2f;
blue = 0.2f;
alpha = 0.9f;
scale = this.particleBaseSize * 0.5f;
} else if (radiusFrac <= 0.65) {
red = 0.4f;
green = 0.4f;
blue = 0.4f;
alpha = 0.6f;
scale = this.particleBaseSize * 0.75f;
} else {
red = this.currentDustColor.getRed() / 255.0f;
green = this.currentDustColor.getGreen() / 255.0f;
blue = this.currentDustColor.getBlue() / 255.0f;
alpha = 0.35f;
scale = this.particleBaseSize;
}
SmokeParticleOptions options = new SmokeParticleOptions(
scale * (0.8f + this.random.nextFloat() * 0.4f),
100 + this.random.nextInt(60),
red,
green,
blue,
alpha,
false,
(float)windSpeed,
0.0f,
null);
this.level.addParticle(options, true, x, spawnY + 0.2, z, motionX, motionY, motionZ);
}
}
public boolean isFinished() {
return this.finished;
}
private Color getDustColorForState(BlockState state) {
if (state.is(BlockTags.WOOL) || state.getMapColor((BlockGetter)this.level, BlockPos.ZERO) == MapColor.NONE) {
return null;
}
if (state.is(Blocks.GRASS_BLOCK)) {
return new Color(Blocks.DIRT.defaultBlockState().getMapColor((BlockGetter)this.level, BlockPos.ZERO).col);
}
if (state.is(Blocks.STONE) || state.is(Blocks.COBBLESTONE)) {
return new Color(Blocks.COBBLESTONE.defaultBlockState().getMapColor((BlockGetter)this.level, BlockPos.ZERO).col);
}
return new Color(state.getMapColor((BlockGetter)this.level, BlockPos.ZERO).col);
}
private float calculateRadiusMultiplier(float power) {
if (power <= 5.0f) {
return 2.0f;
}
if (power <= 40.0f) {
return Mth.lerp((power - 5.0f) / 35.0f, 2.0f, 4.0f);
}
if (power <= 80.0f) {
return Mth.lerp((power - 40.0f) / 40.0f, 4.0f, 5.0f);
}
if (power <= 100.0f) {
return Mth.lerp((power - 80.0f) / 20.0f, 5.0f, 7.0f);
}
return 7.0f;
}
}