diff --git a/src/main/java/g_mungus/wakes_compat/DynamicWakeSize.java b/src/main/java/g_mungus/wakes_compat/DynamicWakeSize.java index 12f6813..23d0736 100644 --- a/src/main/java/g_mungus/wakes_compat/DynamicWakeSize.java +++ b/src/main/java/g_mungus/wakes_compat/DynamicWakeSize.java @@ -1,6 +1,7 @@ package g_mungus.wakes_compat; import net.minecraft.util.math.Vec3d; +import org.joml.Vector3d; public interface DynamicWakeSize { @@ -10,5 +11,5 @@ public interface DynamicWakeSize { public Vec3d vs_wakes_compat_template_1_20_1$getPos(); - public void vs_wakes_compat_template_1_20_1$setOffset(Vec3d pos); + public void vs_wakes_compat_template_1_20_1$setOffset(Vector3d pos); } diff --git a/src/main/java/g_mungus/wakes_compat/ShipWake.java b/src/main/java/g_mungus/wakes_compat/ShipWake.java index 2f507eb..7e2610d 100644 --- a/src/main/java/g_mungus/wakes_compat/ShipWake.java +++ b/src/main/java/g_mungus/wakes_compat/ShipWake.java @@ -9,23 +9,17 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.Vec3i; import net.minecraft.world.World; import org.joml.Vector3d; import org.joml.Vector3dc; import org.joml.Vector3i; -import org.joml.primitives.AABBdc; -import org.joml.primitives.AABBic; import org.valkyrienskies.core.api.ships.Ship; import org.valkyrienskies.core.api.world.LevelYRange; import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; +import java.util.*; -import static g_mungus.wakes_compat.Util.approximateDirection; -import static g_mungus.wakes_compat.Util.getYaw; +import static g_mungus.wakes_compat.Util.*; public class ShipWake { @@ -40,15 +34,22 @@ public static void placeWakeTrail(Ship ship) { Vec3d prevPos = producer.getPrevPos(); - AABBdc aabb = ship.getWorldAABB(); - AABBic saabb = ship.getShipAABB(); +// AABBdc aabb = ship.getWorldAABB(); +// AABBic saabb = ship.getShipAABB(); if (prevPos != null) { - assert saabb != null; - float xwidth = saabb.maxX() - saabb.minX(); - float zwidth = saabb.maxZ() - saabb.minZ(); - float width = Math.min(xwidth, zwidth); +// assert saabb != null; +// float xwidth = saabb.maxX() - saabb.minX(); +// float zwidth = saabb.maxZ() - saabb.minZ(); +// float width = Math.min(xwidth, zwidth); - var7 = WakeNode.Factory.thickNodeTrail(prevPos.x, prevPos.z, (aabb.maxX() + aabb.minX())/2, (aabb.maxZ() + aabb.minZ())/2, height, (float) WakesClient.CONFIG_INSTANCE.initialStrength, velocity, width).iterator(); + float width = ((DynamicWakeSize)ship).vs_wakes_compat_template_1_20_1$getWidth(); + double toX = ((DynamicWakeSize)ship).vs_wakes_compat_template_1_20_1$getPos().x; + double toY = ((DynamicWakeSize)ship).vs_wakes_compat_template_1_20_1$getPos().z; + +// assert MinecraftClient.getInstance().player != null; +// MinecraftClient.getInstance().player.sendMessage(Text.of("WAKE_COORDS: " + toX + ", " + toY)); + + var7 = WakeNode.Factory.thickNodeTrail(prevPos.x, prevPos.z, toX, toY, height, (float) WakesClient.CONFIG_INSTANCE.initialStrength, velocity, width).iterator(); while(var7.hasNext()) { node = (WakeNode)var7.next(); @@ -96,25 +97,11 @@ public static void checkShipSize(Ship s) { s.getActiveChunksSet().getMinMaxWorldPos(minWorldPos, maxWorldPos, new LevelYRange(minY, maxY)); - float width = 0; - Vec3d offset; - - //floodfill stuff - - - offset = Vec3d.ZERO; - - ((DynamicWakeSize) s).vs_wakes_compat_template_1_20_1$setWidth(width); - ((DynamicWakeSize) s).vs_wakes_compat_template_1_20_1$setOffset(offset); - - - assert MinecraftClient.getInstance().player != null; - MinecraftClient.getInstance().player.sendMessage(Text.of(String.valueOf(minWorldPos) + String.valueOf(maxWorldPos))); + calculateShipWidthAndOffset(world, minWorldPos, maxWorldPos, blockYLevelShip, direction, s); } - // Helper method to calculate ship's width and offset private static void calculateShipWidthAndOffset(World world, Vector3i minWorldPos, Vector3i maxWorldPos, int blockYLevelShip, Direction direction, Ship s) { // Axis variables to abstract x-axis or z-axis iterations @@ -126,95 +113,80 @@ private static void calculateShipWidthAndOffset(World world, Vector3i minWorldPo int secondaryMax = isZAxis ? maxWorldPos.x() : maxWorldPos.z(); // Max for the secondary axis boolean isNegativeDirection = (direction == Direction.NORTH || direction == Direction.WEST); // Reverse iteration? - // Variables to track the row index and bounds - boolean foundFirstNonAirBlock = false; - int rowsChecked = 0; + List> rows = new ArrayList<>(); - RowWithBlocks widestRow = null; - Vec3d boundsCenter = new Vec3d((minWorldPos.x() + maxWorldPos.x()) / 2.0, blockYLevelShip, - (minWorldPos.z() + maxWorldPos.z()) / 2.0); - - // Iterate based on primary axis (either x or z depending on direction) for (int primary = isNegativeDirection ? primaryMax : primaryMin; isNegativeDirection ? primary >= primaryMin : primary <= primaryMax; primary += isNegativeDirection ? -1 : 1) { - List blockPositions = new ArrayList<>(); - int minInRow = secondaryMax; - int maxInRow = secondaryMin; - boolean foundNonAirBlockInRow = false; + LinkedList blockPositions = new LinkedList<>(); + - // Iterate over the secondary axis (either z or x depending on direction) for (int secondary = secondaryMin; secondary <= secondaryMax; secondary++) { int x = isZAxis ? secondary : primary; // Set x for BlockPos int z = isZAxis ? primary : secondary; // Set z for BlockPos if (!world.getBlockState(new BlockPos(x, blockYLevelShip, z)).isAir()) { - foundNonAirBlockInRow = true; + blockPositions.add(new BlockPos(x, blockYLevelShip, z)); - minInRow = Math.min(minInRow, secondary); - maxInRow = Math.max(maxInRow, secondary); } } + if (!blockPositions.isEmpty()) { + rows.add(blockPositions); + } + if (rows.size() >= 5) break; + } - if (foundNonAirBlockInRow) { - if (!foundFirstNonAirBlock) { - foundFirstNonAirBlock = true; - } - rowsChecked++; - - // Create a new RowWithBlocks instance for this row - RowWithBlocks currentRow = new RowWithBlocks(rowsChecked, blockPositions, minInRow, maxInRow, Util.getCentre((AABBdc) s.getShipAABB())); + // Use the widest row to calculate the final width and offset + float width = 0; + Vector3d offset = new Vector3d(); - // Update widestRow if this row is wider - if (widestRow == null || currentRow.getWidth() > widestRow.getWidth()) { - widestRow = currentRow; - } - // Stop after 5 rows checked - if (rowsChecked >= 5) break; + for(LinkedList row : rows) { + float rowWidth = getWidth(row); + if (rowWidth > width) { + width = rowWidth; + offset = getOffset(row); + offset = new Vector3d(offset.x, 0, offset.z); } } - // Use the widest row to calculate the final width and offset - if (widestRow != null) { - float width = widestRow.getWidth(); - Vec3d offset = widestRow.getOffset(); - - ((DynamicWakeSize) s).vs_wakes_compat_template_1_20_1$setWidth(width); - ((DynamicWakeSize) s).vs_wakes_compat_template_1_20_1$setOffset(offset); - - assert MinecraftClient.getInstance().player != null; - MinecraftClient.getInstance().player.sendMessage(Text.of("Width: " + width + ", Offset: " + offset)); - } else { - ((DynamicWakeSize) s).vs_wakes_compat_template_1_20_1$setWidth(0); - ((DynamicWakeSize) s).vs_wakes_compat_template_1_20_1$setOffset(Vec3d.ZERO); - } - } + ((DynamicWakeSize) s).vs_wakes_compat_template_1_20_1$setWidth(width); - private static class RowWithBlocks { - int index; - List blockPositions; - int width; - Vec3d offset; + Vector3d offsetReal; - public RowWithBlocks(int index, List blockPositions, int minPos, int maxPos, Vec3d boundsCenter) { - this.index = index; - this.blockPositions = blockPositions; - this.width = maxPos - minPos; - // Offset is calculated as the center between min and max non-air blocks - this.offset = new Vec3d((minPos + maxPos) / 2.0, boundsCenter.y, boundsCenter.z); + if (!offset.equals(0,0,0)) { + Vector3d shipCentre = Util.getCentre(Objects.requireNonNull(s.getShipAABB())); + offsetReal = new Vector3d(shipCentre.x, 0, shipCentre.z).sub(offset); + ((DynamicWakeSize) s).vs_wakes_compat_template_1_20_1$setOffset(offsetReal.negate()); } - public int getWidth() { - return this.width; - } - public Vec3d getOffset() { - return this.offset; - } + + + +// assert MinecraftClient.getInstance().player != null; +// MinecraftClient.getInstance().player.sendMessage(Text.of("Offset: " + offsetReal)); } + + private static int getWidth(LinkedList blockPositions) { + if(blockPositions.isEmpty()) return 0; + + return blockPositions.getFirst().getManhattanDistance(blockPositions.getLast()) + 1; + } + + private static Vector3d getOffset(LinkedList blockPositions) { + if (blockPositions.isEmpty()) return new Vector3d(); + + Vec3d first = Vec3d.ofCenter(blockPositions.getFirst()); + Vec3d last = Vec3d.ofCenter(blockPositions.getLast()); + + return averageVec(first, last); + } + + + } diff --git a/src/main/java/g_mungus/wakes_compat/Util.java b/src/main/java/g_mungus/wakes_compat/Util.java index 1e9a49f..95237c1 100644 --- a/src/main/java/g_mungus/wakes_compat/Util.java +++ b/src/main/java/g_mungus/wakes_compat/Util.java @@ -1,20 +1,12 @@ package g_mungus.wakes_compat; -import com.goby56.wakes.WakesClient; -import com.goby56.wakes.duck.ProducesWake; -import com.goby56.wakes.simulation.WakeHandler; -import com.goby56.wakes.simulation.WakeNode; -import net.minecraft.entity.Entity; -import net.minecraft.entity.vehicle.BoatEntity; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import org.joml.Quaterniondc; +import org.joml.Vector3d; import org.joml.primitives.AABBdc; import org.joml.primitives.AABBic; -import org.valkyrienskies.core.api.ships.Ship; -import org.valkyrienskies.mod.common.VSGameUtilsKt; - -import java.util.Iterator; public class Util { @@ -24,6 +16,12 @@ public static Vec3d getCentre (AABBdc aabb) { return new Vec3d(centreX, aabb.minY(), centreZ); } + public static Vector3d getCentre (AABBic aabb) { + double centreX = (double) (aabb.maxX() + aabb.minX()) /2; + double centreZ = (double) (aabb.maxZ() + aabb.minZ()) /2; + return new Vector3d(centreX, aabb.minY(), centreZ); + } + public static double getYaw(Quaterniondc quaternion) { double w = quaternion.w(); @@ -51,4 +49,12 @@ public static Direction approximateDirection (Double degrees) { return Direction.NORTH; } } + + public static Vector3d averageVec(Vec3d vec1, Vec3d vec2) { + double avgX = (vec1.getX() + vec2.getX()) / 2d; + double avgY = (vec1.getY() + vec2.getY()) / 2d; + double avgZ = (vec1.getZ() + vec2.getZ()) / 2d; + + return new Vector3d(avgX, avgY, avgZ); + } } diff --git a/src/main/java/g_mungus/wakes_compat/mixin/ShipObjectClientMixin.java b/src/main/java/g_mungus/wakes_compat/mixin/ShipObjectClientMixin.java index 077d3ef..9a3fa2f 100644 --- a/src/main/java/g_mungus/wakes_compat/mixin/ShipObjectClientMixin.java +++ b/src/main/java/g_mungus/wakes_compat/mixin/ShipObjectClientMixin.java @@ -5,8 +5,7 @@ import g_mungus.wakes_compat.DynamicWakeSize; import g_mungus.wakes_compat.Util; import net.minecraft.util.math.Vec3d; -import org.joml.Vector3d; -import org.joml.Vector3dc; +import org.joml.*; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -14,7 +13,7 @@ import org.valkyrienskies.core.impl.game.ships.ShipObjectClient; import org.valkyrienskies.mod.common.util.VectorConversionsMCKt; -@Mixin(ShipObjectClient.class) +@Mixin(value = ShipObjectClient.class, remap = false) public abstract class ShipObjectClientMixin implements ProducesWake, DynamicWakeSize { @Unique @@ -55,13 +54,19 @@ public Vec3d getPrevPos() { @Override public Vec3d vs_wakes_compat_template_1_20_1$getPos() { - Ship ship = (Ship)(Object)this; - return Util.getCentre(ship.getWorldAABB()).add(offset.rotateY((float) Util.getYaw(ship.getTransform().getShipToWorldRotation()))); + + return Util.getCentre(((Ship)(Object)this).getWorldAABB()).add(offset); } @Override - public void vs_wakes_compat_template_1_20_1$setOffset(Vec3d vec3d) { - this.offset = vec3d; + public void vs_wakes_compat_template_1_20_1$setOffset(Vector3d vec) { + + + Ship ship = (Ship)(Object)this; + Quaterniondc mat = ship.getTransform().getShipToWorldRotation(); + + + this.offset = VectorConversionsMCKt.toMinecraft(vec.rotate(mat)); }