Skip to content

Commit

Permalink
water wakes on lava
Browse files Browse the repository at this point in the history
  • Loading branch information
Goby56 committed Jan 1, 2025
1 parent c0fa5f2 commit b9c808f
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 88 deletions.
16 changes: 10 additions & 6 deletions src/main/java/com/goby56/wakes/config/WakesConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,17 @@ public class WakesConfig extends MidnightConfig {
@Entry(category = APPEARANCE) public static float maxSplashPlaneVelocity = 0.5f;
@Entry(category = APPEARANCE) public static float splashPlaneScale = 0.8f;

@Hidden @Entry(category = APPEARANCE) public static List<Float> wakeColorIntervals = Lists.newArrayList(0.1f, 0.4f, 0.6f, 0.8f);
@Hidden @Entry(category = APPEARANCE) public static List<Float> wakeColorIntervals = Lists.newArrayList(0.05f, 0.15f, 0.2f, 0.35f, 0.52f, 0.6f, 0.7f, 0.9f);
@Hidden @Entry(selectionMode = 1, category = APPEARANCE, isColor = true) public static List<String> wakeColors = Lists.newArrayList(
"#ffff00ff",
"#ffff00ff",
"#ffff00ff",
"#ffff00ff",
"#ffff00ff"
"#00000000", // TRANSPARENT
"#289399a6", // DARK GRAY
"#649ea5b0", // GRAY
"#b4c4cad1", // LIGHT GRAY
"#00000000", // TRANSPARENT
"#b4c4cad1", // LIGHT GRAY
"#ffffffff", // WHITE
"#b4c4cad1", // LIGHT GRAY
"#649ea5b0" // GRAY
);

@Entry(category = DEBUG) public static boolean debugColors = false;
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/com/goby56/wakes/duck/ProducesWake.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@
import net.minecraft.util.math.Vec3d;

public interface ProducesWake {
boolean wakes$onWaterSurface();
Float wakes$producingWaterLevel();
void wakes$setProducingHeight(float h);
boolean wakes$onFluidSurface();
Float wakes$wakeHeight();
void wakes$setWakeHeight(float h);
Vec3d wakes$getPrevPos();
void wakes$setPrevPos(Vec3d pos);
Vec3d wakes$getNumericalVelocity();
double wakes$getHorizontalVelocity();
double wakes$getVerticalVelocity();
void wakes$setSplashPlane(SplashPlaneParticle particle);

void setRecentlyTeleported(boolean b);
void wakes$setRecentlyTeleported(boolean b);

SplashPlaneParticle wakes$getSplashPlane();

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/goby56/wakes/mixin/LilyPadFallMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void onLandedUpon(World world, BlockState state, BlockPos pos, Entity ent
EffectSpawningRule rule = WakesUtils.getEffectRuleFromSource(entity);
ProducesWake wakeProducer = (ProducesWake) entity;
if (rule.simulateWakes) {
wakeProducer.wakes$setProducingHeight(pos.getY() + WakeNode.WATER_OFFSET);
wakeProducer.wakes$setWakeHeight(pos.getY() + WakeNode.WATER_OFFSET);
WakesUtils.placeFallSplash(entity);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package com.goby56.wakes.mixin;

import com.goby56.wakes.duck.ProducesWake;
import net.minecraft.entity.ai.goal.FollowOwnerGoal;
import net.minecraft.entity.passive.TameableEntity;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
Expand All @@ -16,7 +13,7 @@ public class TameableTeleportMixin {
@Inject(at = @At("TAIL"), method = "tryTeleportTo")
private void onTeleport(int x, int y, int z, CallbackInfoReturnable<Boolean> cir) {
if (cir.getReturnValue()) {
((ProducesWake) this).setRecentlyTeleported(true);
((ProducesWake) this).wakes$setRecentlyTeleported(true);
}
}
}
51 changes: 22 additions & 29 deletions src/main/java/com/goby56/wakes/mixin/WakeSpawnerMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,34 +22,29 @@
@Mixin(Entity.class)
public abstract class WakeSpawnerMixin implements ProducesWake {

@Shadow public abstract boolean isSubmergedInWater();
@Shadow public abstract String toString();
@Shadow public abstract boolean isTouchingWater();
@Shadow private Vec3d pos;
@Shadow private World world;

@Shadow public abstract float getYaw(float tickDelta);

@Shadow public abstract float getYaw();

@Shadow public abstract double getX();

@Shadow public abstract Box getBoundingBox();

@Shadow public abstract double getZ();

@Unique private boolean onWaterSurface = false;
@Shadow public abstract boolean isInFluid();

@Unique private boolean onFluidSurface = false;
@Unique private Vec3d prevPosOnSurface = null;
@Unique private Vec3d numericalVelocity = Vec3d.ZERO;
@Unique private double horizontalNumericalVelocity = 0;
@Unique private double verticalNumericalVelocity = 0;
@Unique private Float producingWaterLevel = null;
@Unique private Float wakeHeight = null;
@Unique private SplashPlaneParticle splashPlane;
@Unique private boolean hasRecentlyTeleported = false;

@Override
public boolean wakes$onWaterSurface() {
return this.onWaterSurface;
public boolean wakes$onFluidSurface() {
return this.onFluidSurface;
}

@Override
Expand All @@ -61,11 +56,6 @@ public abstract class WakeSpawnerMixin implements ProducesWake {
return this.horizontalNumericalVelocity;
}

@Override
public double wakes$getVerticalVelocity() {
return this.verticalNumericalVelocity;
}

@Override
public Vec3d wakes$getPrevPos() {
return this.prevPosOnSurface;
Expand All @@ -77,20 +67,21 @@ public abstract class WakeSpawnerMixin implements ProducesWake {
}

@Override
public Float wakes$producingWaterLevel() {
return this.producingWaterLevel;
public Float wakes$wakeHeight() {
return this.wakeHeight;
}

@Override
public void wakes$setProducingHeight(float h) {
this.producingWaterLevel = h;
public void wakes$setWakeHeight(float h) {
this.wakeHeight = h;
}

@Override
public void wakes$setSplashPlane(SplashPlaneParticle particle) {
this.splashPlane = particle;
}

@Override
public void wakes$setRecentlyTeleported(boolean b) {
this.hasRecentlyTeleported = b;
}
Expand All @@ -107,37 +98,37 @@ public abstract class WakeSpawnerMixin implements ProducesWake {
// System.out.printf("%s wants to teleport\n", this);
// }

@Unique
private boolean onFluidSurface() {
double hitboxMaxY = this.getBoundingBox().maxY;
BlockPos blockPos = BlockPos.ofFloored(this.getX(), hitboxMaxY, this.getZ());
FluidState fluidState = this.world.getFluidState(blockPos);
double fluidHeight = (float)blockPos.getY() + fluidState.getHeight(this.world, blockPos);
return this.isTouchingWater() && hitboxMaxY > fluidHeight;
return this.isInFluid() && hitboxMaxY > fluidHeight;
}

@Inject(at = @At("TAIL"), method = "tick")
private void tick(CallbackInfo info) {
this.onWaterSurface = onFluidSurface();
this.onFluidSurface = onFluidSurface();
Entity thisEntity = ((Entity) (Object) this);
Vec3d vel = this.calculateVelocity(thisEntity);
this.numericalVelocity = vel;
this.horizontalNumericalVelocity = vel.horizontalLength();
this.verticalNumericalVelocity = vel.y;

if (WakesConfig.disableMod) {
return;
}

if (this.onWaterSurface && !this.hasRecentlyTeleported) {
this.producingWaterLevel = WakesUtils.getWaterLevel(this.world, thisEntity);
if (this.onFluidSurface && !this.hasRecentlyTeleported) {
this.wakeHeight = WakesUtils.getFluidLevel(this.world, thisEntity);

Vec3d currPos = new Vec3d(thisEntity.getX(), this.producingWaterLevel, thisEntity.getZ());
Vec3d currPos = new Vec3d(thisEntity.getX(), this.wakeHeight, thisEntity.getZ());

this.spawnEffects(thisEntity);

this.wakes$setPrevPos(currPos);
} else {
this.producingWaterLevel = null;
this.wakeHeight = null;
this.prevPosOnSurface = null;
}
this.wakes$setRecentlyTeleported(false);
Expand All @@ -152,13 +143,14 @@ private void onSwimmingStart(CallbackInfo ci) {

EffectSpawningRule rule = WakesUtils.getEffectRuleFromSource(thisEntity);
if (rule.simulateWakes) {
if (this.producingWaterLevel == null)
this.producingWaterLevel = WakesUtils.getWaterLevel(this.world, thisEntity);
if (this.wakeHeight == null)
this.wakeHeight = WakesUtils.getFluidLevel(this.world, thisEntity);
WakesUtils.placeFallSplash(((Entity) (Object) this));
}
// TODO ADD WAKE WHEN GETTING OUT OF WATER
}

@Unique
private void spawnEffects(Entity thisEntity) {
EffectSpawningRule rule = WakesUtils.getEffectRuleFromSource(thisEntity);
if (rule.simulateWakes) {
Expand All @@ -171,6 +163,7 @@ private void spawnEffects(Entity thisEntity) {
}
}

@Unique
private Vec3d calculateVelocity(Entity thisEntity) {
if (thisEntity instanceof ClientPlayerEntity) {
return thisEntity.getVelocity();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void tick() {
this.prevYaw = this.yaw;

if (this.owner instanceof ProducesWake wakeOwner) {
if (this.owner.isRemoved() || !wakeOwner.wakes$onWaterSurface() || wakeOwner.wakes$getHorizontalVelocity() < 1e-2) {
if (this.owner.isRemoved() || !wakeOwner.wakes$onFluidSurface() || wakeOwner.wakes$getHorizontalVelocity() < 1e-2) {
this.markDead();
} else {
this.aliveTick(wakeOwner);
Expand All @@ -76,7 +76,7 @@ private void aliveTick(ProducesWake wakeProducer) {
this.direction = Vec3d.fromPolar(0, -this.yaw);
Vec3d planeOffset = direction.multiply(this.owner.getWidth() + WakesConfig.splashPlaneOffset);
Vec3d planePos = this.owner.getPos().add(planeOffset);
this.setPos(planePos.x, wakeProducer.wakes$producingWaterLevel(), planePos.z);
this.setPos(planePos.x, wakeProducer.wakes$wakeHeight(), planePos.z);
}

@Override
Expand Down
23 changes: 7 additions & 16 deletions src/main/java/com/goby56/wakes/render/enums/WakeColor.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public class WakeColor {
public final float h;
public final float s;
public final float v;
public boolean isHighlight;


public WakeColor(int argb) {
Expand All @@ -34,7 +33,6 @@ public WakeColor(int red, int green, int blue, int alpha) {
this.h = hsv[0];
this.s = hsv[1];
this.v = hsv[2];
this.isHighlight = false;
}

public WakeColor(float hue, float saturation, float value, float opacity) {
Expand All @@ -49,18 +47,13 @@ public String toHex() {
return "#" + Integer.toHexString(a << 24 | r << 16 | g << 8 | b);
}

public WakeColor isHighlight(boolean b) {
this.isHighlight = b;
return this;
}

private static double invertedLogisticCurve(float x) {
float k = WakesConfig.shaderLightPassthrough;
return WakesClient.areShadersEnabled ? k * (4 * Math.pow(x - 0.5f, 3) + 0.5f) : x;
}

public static int sampleColor(float waveEqAvg, int waterColor, int lightColor, float opacity) {
WakeColor tint = new WakeColor(waterColor);
public static int sampleColor(float waveEqAvg, int fluidCol, int lightColor, float opacity) {
WakeColor tint = new WakeColor(fluidCol);
double clampedRange = 1 / (1 + Math.exp(-0.1 * waveEqAvg));
var ranges = WakesConfig.wakeColorIntervals;
int returnIndex = ranges.size();
Expand All @@ -70,19 +63,17 @@ public static int sampleColor(float waveEqAvg, int waterColor, int lightColor, f
break;
}
}
WakeColor color = WakesConfig.getWakeColor(returnIndex).isHighlight(false); // .isHighlight(returnIndex == WakesConfig.highlightIndex);
WakeColor color = WakesConfig.getWakeColor(returnIndex);
return color.blend(tint, lightColor, opacity).abgr;
}

public WakeColor blend(WakeColor tint, int lightColor, float opacity) {
float srcA = this.a / 255f;
int a = (int) (opacity * 255 * srcA);
int r = 255, g = 255, b = 255;
if (!this.isHighlight) {
r = (int) ((this.r) * (srcA) + (tint.r) * (1 - srcA));
g = (int) ((this.g) * (srcA) + (tint.g) * (1 - srcA));
b = (int) ((this.b) * (srcA) + (tint.b) * (1 - srcA));
}
int r = (int) ((this.r) * (srcA) + (tint.r) * (1 - srcA));
int g = (int) ((this.g) * (srcA) + (tint.g) * (1 - srcA));
int b = (int) ((this.b) * (srcA) + (tint.b) * (1 - srcA));

r = (int) ((r * invertedLogisticCurve((lightColor & 0xFF) / 255f)));
g = (int) ((g * invertedLogisticCurve((lightColor >> 8 & 0xFF) / 255f)));
b = (int) ((b * invertedLogisticCurve((lightColor >> 16 & 0xFF) / 255f)));
Expand Down
11 changes: 5 additions & 6 deletions src/main/java/com/goby56/wakes/simulation/Brick.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.goby56.wakes.simulation;

import com.goby56.wakes.WakesClient;
import com.goby56.wakes.config.WakesConfig;
import com.goby56.wakes.render.enums.WakeColor;
import com.goby56.wakes.debug.WakesDebugInfo;
Expand Down Expand Up @@ -172,10 +171,10 @@ public void populatePixels() {
for (int x = 0; x < dim; x++) {
WakeNode node = this.get(x, z);
int lightCol = LightmapTextureManager.MAX_LIGHT_COORDINATE;
int waterCol = 0;
int fluidColor = 0;
float opacity = 0;
if (node != null) {
waterCol = BiomeColors.getWaterColor(world, node.blockPos());
fluidColor = BiomeColors.getWaterColor(world, node.blockPos());
int lightCoordinate = WorldRenderer.getLightmapCoordinates(world, node.blockPos());
lightCol = MinecraftClient.getInstance().gameRenderer.getLightmapTextureManager().image.getColor(
LightmapTextureManager.getBlockLightCoordinates(lightCoordinate),
Expand All @@ -193,7 +192,7 @@ public void populatePixels() {
if (node != null) {
// TODO USE SHADERS TO COLOR THE WAKES?
float avg = (node.u[0][r + 1][c + 1] + node.u[1][r + 1][c + 1] + node.u[2][r + 1][c + 1]) / 3;
color = getPixelColor(avg, waterCol, lightCol, opacity);
color = getPixelColor(avg, fluidColor, lightCol, opacity);
}
long pixelOffset = 4L * (((long) r * dim * texRes) + c);
MemoryUtil.memPutInt(imgPtr + nodeOffset + pixelOffset, color);
Expand All @@ -204,11 +203,11 @@ public void populatePixels() {
hasPopulatedPixels = true;
}

private static int getPixelColor(float waveEqAvg, int waterCol, int lightCol, float opacity) {
private static int getPixelColor(float waveEqAvg, int fluidCol, int lightCol, float opacity) {
if (WakesConfig.debugColors) {
int clampedRange = (int) (255 * (2 / (1 + Math.exp(-0.1 * waveEqAvg)) - 1));
return new WakeColor(Math.max(-clampedRange, 0), Math.max(clampedRange, 0), 0, 255).abgr;
}
return WakeColor.sampleColor(waveEqAvg, waterCol, lightCol, opacity);
return WakeColor.sampleColor(waveEqAvg, fluidCol, lightCol, opacity);
}
}
9 changes: 1 addition & 8 deletions src/main/java/com/goby56/wakes/simulation/WakeHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,12 @@ public <T> ArrayList<T> getVisible(Frustum frustum, Class<T> type) {
}

private int getArrayIndex(int y) {
if (y < this.minY || y > this.maxY) {
if (y < this.minY || y >= this.maxY) {
return -1;
}
return y - this.minY;
}

private int getYLevel(int i) {
if (i < 0 || i > this.maxY - this.minY) {
throw new IndexOutOfBoundsException();
}
return i + this.minY;
}

public static void scheduleResolutionChange(Resolution newRes) {
WakesConfig.wakeResolution = newRes;
resolutionResetScheduled = true;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/goby56/wakes/simulation/WakeNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public void updateFloodLevel(int newLevel) {
public boolean validPos(World world) {
FluidState fluidState = world.getFluidState(this.blockPos());
FluidState fluidStateAbove = world.getFluidState(this.blockPos().up());
if (fluidState.isOf(Fluids.WATER) && fluidStateAbove.isEmpty()) {
if (fluidState.isStill() && fluidStateAbove.isEmpty()) {
return fluidState.isStill();
}
return false;
Expand Down
Loading

0 comments on commit b9c808f

Please sign in to comment.