From b9c808f5d996a6db07d17eba2dbea35003c39311 Mon Sep 17 00:00:00 2001 From: Goby56 <60710855+Goby56@users.noreply.github.com> Date: Wed, 1 Jan 2025 16:47:11 +0100 Subject: [PATCH] water wakes on lava --- .../com/goby56/wakes/config/WakesConfig.java | 16 +++--- .../com/goby56/wakes/duck/ProducesWake.java | 9 ++-- .../goby56/wakes/mixin/LilyPadFallMixin.java | 2 +- .../wakes/mixin/TameableTeleportMixin.java | 5 +- .../goby56/wakes/mixin/WakeSpawnerMixin.java | 51 ++++++++----------- .../particle/custom/SplashPlaneParticle.java | 4 +- .../goby56/wakes/render/enums/WakeColor.java | 23 +++------ .../com/goby56/wakes/simulation/Brick.java | 11 ++-- .../goby56/wakes/simulation/WakeHandler.java | 9 +--- .../com/goby56/wakes/simulation/WakeNode.java | 2 +- .../com/goby56/wakes/utils/WakesUtils.java | 23 +++++---- 11 files changed, 67 insertions(+), 88 deletions(-) diff --git a/src/main/java/com/goby56/wakes/config/WakesConfig.java b/src/main/java/com/goby56/wakes/config/WakesConfig.java index 2e05618..a204ec0 100644 --- a/src/main/java/com/goby56/wakes/config/WakesConfig.java +++ b/src/main/java/com/goby56/wakes/config/WakesConfig.java @@ -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 wakeColorIntervals = Lists.newArrayList(0.1f, 0.4f, 0.6f, 0.8f); + @Hidden @Entry(category = APPEARANCE) public static List 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 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; diff --git a/src/main/java/com/goby56/wakes/duck/ProducesWake.java b/src/main/java/com/goby56/wakes/duck/ProducesWake.java index 426eaa6..558d061 100644 --- a/src/main/java/com/goby56/wakes/duck/ProducesWake.java +++ b/src/main/java/com/goby56/wakes/duck/ProducesWake.java @@ -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(); diff --git a/src/main/java/com/goby56/wakes/mixin/LilyPadFallMixin.java b/src/main/java/com/goby56/wakes/mixin/LilyPadFallMixin.java index 96264fe..569c8ee 100644 --- a/src/main/java/com/goby56/wakes/mixin/LilyPadFallMixin.java +++ b/src/main/java/com/goby56/wakes/mixin/LilyPadFallMixin.java @@ -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); } } diff --git a/src/main/java/com/goby56/wakes/mixin/TameableTeleportMixin.java b/src/main/java/com/goby56/wakes/mixin/TameableTeleportMixin.java index d61cabf..05c9129 100644 --- a/src/main/java/com/goby56/wakes/mixin/TameableTeleportMixin.java +++ b/src/main/java/com/goby56/wakes/mixin/TameableTeleportMixin.java @@ -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; @@ -16,7 +13,7 @@ public class TameableTeleportMixin { @Inject(at = @At("TAIL"), method = "tryTeleportTo") private void onTeleport(int x, int y, int z, CallbackInfoReturnable cir) { if (cir.getReturnValue()) { - ((ProducesWake) this).setRecentlyTeleported(true); + ((ProducesWake) this).wakes$setRecentlyTeleported(true); } } } diff --git a/src/main/java/com/goby56/wakes/mixin/WakeSpawnerMixin.java b/src/main/java/com/goby56/wakes/mixin/WakeSpawnerMixin.java index 6efdfb1..3fdbfd7 100644 --- a/src/main/java/com/goby56/wakes/mixin/WakeSpawnerMixin.java +++ b/src/main/java/com/goby56/wakes/mixin/WakeSpawnerMixin.java @@ -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 @@ -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; @@ -77,13 +67,13 @@ 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 @@ -91,6 +81,7 @@ public abstract class WakeSpawnerMixin implements ProducesWake { this.splashPlane = particle; } + @Override public void wakes$setRecentlyTeleported(boolean b) { this.hasRecentlyTeleported = b; } @@ -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); @@ -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) { @@ -171,6 +163,7 @@ private void spawnEffects(Entity thisEntity) { } } + @Unique private Vec3d calculateVelocity(Entity thisEntity) { if (thisEntity instanceof ClientPlayerEntity) { return thisEntity.getVelocity(); diff --git a/src/main/java/com/goby56/wakes/particle/custom/SplashPlaneParticle.java b/src/main/java/com/goby56/wakes/particle/custom/SplashPlaneParticle.java index 75d6a55..6f0ee43 100644 --- a/src/main/java/com/goby56/wakes/particle/custom/SplashPlaneParticle.java +++ b/src/main/java/com/goby56/wakes/particle/custom/SplashPlaneParticle.java @@ -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); @@ -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 diff --git a/src/main/java/com/goby56/wakes/render/enums/WakeColor.java b/src/main/java/com/goby56/wakes/render/enums/WakeColor.java index 26605e6..ca83d18 100644 --- a/src/main/java/com/goby56/wakes/render/enums/WakeColor.java +++ b/src/main/java/com/goby56/wakes/render/enums/WakeColor.java @@ -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) { @@ -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) { @@ -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(); @@ -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))); diff --git a/src/main/java/com/goby56/wakes/simulation/Brick.java b/src/main/java/com/goby56/wakes/simulation/Brick.java index 8334814..683bdbf 100644 --- a/src/main/java/com/goby56/wakes/simulation/Brick.java +++ b/src/main/java/com/goby56/wakes/simulation/Brick.java @@ -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; @@ -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), @@ -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); @@ -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); } } diff --git a/src/main/java/com/goby56/wakes/simulation/WakeHandler.java b/src/main/java/com/goby56/wakes/simulation/WakeHandler.java index 54427c0..15e3a2d 100644 --- a/src/main/java/com/goby56/wakes/simulation/WakeHandler.java +++ b/src/main/java/com/goby56/wakes/simulation/WakeHandler.java @@ -107,19 +107,12 @@ public ArrayList getVisible(Frustum frustum, Class 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; diff --git a/src/main/java/com/goby56/wakes/simulation/WakeNode.java b/src/main/java/com/goby56/wakes/simulation/WakeNode.java index b03e84b..e299c2d 100644 --- a/src/main/java/com/goby56/wakes/simulation/WakeNode.java +++ b/src/main/java/com/goby56/wakes/simulation/WakeNode.java @@ -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; diff --git a/src/main/java/com/goby56/wakes/utils/WakesUtils.java b/src/main/java/com/goby56/wakes/utils/WakesUtils.java index f56341c..57127c8 100644 --- a/src/main/java/com/goby56/wakes/utils/WakesUtils.java +++ b/src/main/java/com/goby56/wakes/utils/WakesUtils.java @@ -35,7 +35,7 @@ public static void placeFallSplash(Entity entity) { WakeHandler wakeHandler = WakeHandler.getInstance().orElse(null); if (wakeHandler == null) return; - for (WakeNode node : WakeNode.Factory.splashNodes(entity, (int) Math.floor(((ProducesWake) entity).wakes$producingWaterLevel()))) { + for (WakeNode node : WakeNode.Factory.splashNodes(entity, (int) Math.floor(((ProducesWake) entity).wakes$wakeHeight()))) { wakeHandler.insert(node); } } @@ -49,7 +49,7 @@ public static void spawnPaddleSplashCloudParticle(World world, BoatEntity boat) Vec3d rot = boat.getRotationVec(1.0f); double x = boat.getX() + (i == 1 ? -rot.z : rot.z); double z = boat.getZ() + (i == 1 ? rot.x : -rot.x); - Vec3d pos = new Vec3d(x, ((ProducesWake) boat).wakes$producingWaterLevel(), z); + Vec3d pos = new Vec3d(x, ((ProducesWake) boat).wakes$wakeHeight(), z); world.addParticle(ModParticles.SPLASH_CLOUD, pos.x, pos.y, pos.z, 0, 0, 0); } } @@ -68,7 +68,7 @@ public static void placeWakeTrail(Entity entity) { ProducesWake producer = (ProducesWake) entity; double velocity = producer.wakes$getHorizontalVelocity(); - int y = (int) Math.floor(producer.wakes$producingWaterLevel()); + int y = (int) Math.floor(producer.wakes$wakeHeight()); if (entity instanceof BoatEntity boat) { for (WakeNode node : WakeNode.Factory.rowingNodes(boat, y)) { @@ -226,9 +226,13 @@ public static int rgbaArr2abgrInt(int[] arr) { return n; } - public static float getWaterLevel(World world, Entity entityInWater) { - Box box = entityInWater.getBoundingBox(); - return getWaterLevel(world, + // public static float getFluidColor() { + // return + // } + + public static float getFluidLevel(World world, Entity entityInFluid) { + Box box = entityInFluid.getBoundingBox(); + return getFluidLevel(world, MathHelper.floor(box.minX), MathHelper.ceil(box.maxX), MathHelper.floor(box.minY), MathHelper.ceil(box.maxY), MathHelper.floor(box.minZ), MathHelper.ceil(box.maxZ)); @@ -241,10 +245,9 @@ public static float getWaterLevel(World world, Entity entityInWater) { // (int) cuboidInWater.minZ, (int) cuboidInWater.maxZ); // } - private static float getWaterLevel(World world, int minX, int maxX, int minY, int maxY, int minZ, int maxZ) { - // Taken from BoatEntity$getWaterLevelBelow + private static float getFluidLevel(World world, int minX, int maxX, int minY, int maxY, int minZ, int maxZ) { + // Taken from BoatEntity$getWaterHeightBelow BlockPos.Mutable blockPos = new BlockPos.Mutable(); - yLoop: for (int y = minY; y < maxY; ++y) { float f = 0.0f; @@ -252,7 +255,7 @@ private static float getWaterLevel(World world, int minX, int maxX, int minY, in for (int z = minZ; z < maxZ; ++z) { blockPos.set(x, y, z); FluidState fluidState = world.getFluidState(blockPos); - if (fluidState.isIn(FluidTags.WATER)) { + if (fluidState.isStill()) { f = Math.max(f, fluidState.getHeight(world, blockPos)); } if (f >= 1.0f) continue yLoop;