From 74861ac60190c76e847dc0a929a6374742727a14 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Sun, 2 Feb 2025 22:03:56 +0800 Subject: [PATCH 01/12] feat: init work --- .../java/org/allaymc/api/math/MathUtils.java | 58 ++++++++++++++----- .../allaymc/api/math/location/Location3d.java | 7 +++ 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/api/src/main/java/org/allaymc/api/math/MathUtils.java b/api/src/main/java/org/allaymc/api/math/MathUtils.java index f48822c8c..1275af28d 100644 --- a/api/src/main/java/org/allaymc/api/math/MathUtils.java +++ b/api/src/main/java/org/allaymc/api/math/MathUtils.java @@ -3,6 +3,7 @@ import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.math.location.Location3fc; import org.joml.*; +import org.joml.primitives.AABBd; import org.joml.primitives.AABBf; import java.lang.Math; @@ -16,11 +17,11 @@ */ public final class MathUtils { - private static final float[] SIN_LOOK_UP_TABLE = new float[65536]; + private static final double[] SIN_LOOK_UP_TABLE = new double[65536]; static { for (int i = 0; i < 65536; i++) { - SIN_LOOK_UP_TABLE[i] = (float) Math.sin(i * Math.PI * 2.0D / 65536.0d); + SIN_LOOK_UP_TABLE[i] = Math.sin(i * Math.PI * 2.0D / 65536.0d); } } @@ -145,8 +146,8 @@ public static Vector3i ceil(Vector3fc vector3f) { * * @return the centered vector. */ - public static Vector3f center(Vector3ic vector3i) { - return new Vector3f(vector3i.x() + 0.5f, vector3i.y() + 0.5f, vector3i.z() + 0.5f); + public static Vector3d center(Vector3ic vector3i) { + return new Vector3d(vector3i.x() + 0.5, vector3i.y() + 0.5, vector3i.z() + 0.5); } /** @@ -203,7 +204,7 @@ public static double fastDoubleInverseSqrt(double x) { * * @return {@code true} if the value is in the range, otherwise {@code false}. */ - public static boolean isInRange(float l, float value, float r) { + public static boolean isInRange(double l, double value, double r) { return l <= value && value <= r; } @@ -215,13 +216,13 @@ public static boolean isInRange(float l, float value, float r) { * * @return the direction vector. */ - public static Vector3f getDirectionVector(double yaw, double pitch) { + public static Vector3d getDirectionVector(double yaw, double pitch) { var pitch0 = toRadians(pitch + 90); var yaw0 = toRadians(yaw + 90); var x = sin(pitch0) * cos(yaw0); var z = sin(pitch0) * sin(yaw0); var y = cos(pitch0); - return new Vector3f((float) x, (float) y, (float) z).normalize(); + return new Vector3d(x, y, z).normalize(); } /** @@ -231,7 +232,7 @@ public static Vector3f getDirectionVector(double yaw, double pitch) { * * @return the yaw. */ - public static double getYawFromVector(Vector3fc vector) { + public static double getYawFromVector(Vector3dc vector) { double length = vector.x() * vector.x() + vector.z() * vector.z(); // Prevent NAN if (length == 0) { @@ -248,7 +249,7 @@ public static double getYawFromVector(Vector3fc vector) { * * @return the pitch. */ - public static double getPitchFromVector(Vector3fc vector) { + public static double getPitchFromVector(Vector3dc vector) { double length = vector.x() * vector.x() + vector.z() * vector.z() + @@ -268,7 +269,7 @@ public static double getPitchFromVector(Vector3fc vector) { * * @return the sin value. */ - public static float fastSin(float radian) { + public static double fastSin(float radian) { return SIN_LOOK_UP_TABLE[((int) (radian * 10430.378F) & 0xFFFF)]; } @@ -279,7 +280,7 @@ public static float fastSin(float radian) { * * @return the sin value. */ - public static float fastSin(double radian) { + public static double fastSin(double radian) { return SIN_LOOK_UP_TABLE[((int) (radian * 10430.378F) & 0xFFFF)]; } @@ -290,7 +291,7 @@ public static float fastSin(double radian) { * * @return the cos value. */ - public static float fastCos(float radian) { + public static double fastCos(float radian) { return SIN_LOOK_UP_TABLE[((int) (radian * 10430.378F + 16384.0F) & 0xFFFF)]; } @@ -301,7 +302,7 @@ public static float fastCos(float radian) { * * @return the cos value. */ - public static float fastCos(double radian) { + public static double fastCos(double radian) { return SIN_LOOK_UP_TABLE[((int) (radian * 10430.378F + 16384.0F) & 0xFFFF)]; } @@ -364,6 +365,19 @@ public static Vector3f normalizeIfNotZero(Vector3f v) { return v.lengthSquared() > 0 ? v.normalize(v) : v; } + /** + * Normalize the vector if it is not zero. + *

+ * If the vector is zero, it can't be normalized, otherwise a vector with three NaN values will be produced. + * + * @param v the vector. + * + * @return the normalized vector. + */ + public static Vector3d normalizeIfNotZero(Vector3d v) { + return v.lengthSquared() > 0 ? v.normalize(v) : v; + } + /** * Grow an AABB by a certain amount. * @@ -381,4 +395,22 @@ public static AABBf grow(AABBf aabb, float growth) { aabb.maxZ += growth; return aabb; } + + /** + * Grow an AABB by a certain amount. + * + * @param aabb the AABB to grow. + * @param growth the amount to grow by. + * + * @return the grown AABB. + */ + public static AABBd grow(AABBd aabb, double growth) { + aabb.minX -= growth; + aabb.minY -= growth; + aabb.minZ -= growth; + aabb.maxX += growth; + aabb.maxY += growth; + aabb.maxZ += growth; + return aabb; + } } diff --git a/api/src/main/java/org/allaymc/api/math/location/Location3d.java b/api/src/main/java/org/allaymc/api/math/location/Location3d.java index f5e0b4ad1..2c305b99e 100644 --- a/api/src/main/java/org/allaymc/api/math/location/Location3d.java +++ b/api/src/main/java/org/allaymc/api/math/location/Location3d.java @@ -30,6 +30,13 @@ public Location3d(Location3dc l) { this.headYaw = l.headYaw(); } + public Location3d(Location3ic l) { + super(l.x(), l.y(), l.z(), l.dimension()); + this.pitch = l.pitch(); + this.yaw = l.yaw(); + this.headYaw = l.headYaw(); + } + public Location3d(double x, double y, double z, Dimension dimension) { super(x, y, z, dimension); } From 2bd71c634e38e5e8949e66d4fab439e2772feafd Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Tue, 4 Feb 2025 05:34:18 +0800 Subject: [PATCH 02/12] feat: complete most of the things --- .../block/component/data/BlockStateData.java | 28 ++- .../org/allaymc/api/block/data/BlockFace.java | 26 +-- .../api/client/storage/PlayerData.java | 2 +- .../allaymc/api/command/CommandSender.java | 4 +- .../allaymc/api/command/NPCCommandSender.java | 4 +- .../args/CachedFilterSelectorArgument.java | 6 +- .../args/CachedSimpleSelectorArgument.java | 8 +- .../selector/args/SelectorArgument.java | 8 +- .../entity/component/EntityBaseComponent.java | 112 +++++----- .../player/EntityPlayerBaseComponent.java | 16 +- .../api/entity/initinfo/EntityInitInfo.java | 22 +- .../api/entity/interfaces/EntityPlayer.java | 4 +- .../event/entity/EntityFallEvent.java | 4 +- .../event/entity/EntityMoveEvent.java | 8 +- .../event/entity/EntityTeleportEvent.java | 10 +- .../event/player/PlayerMoveEvent.java | 8 +- .../java/org/allaymc/api/math/MathUtils.java | 10 + .../allaymc/api/math/position/Position3d.java | 5 + .../api/math/voxelshape/VoxelShape.java | 192 +++++++++--------- .../java/org/allaymc/api/world/Dimension.java | 166 +++++++-------- .../java/org/allaymc/api/world/Explosion.java | 156 +++++++------- .../java/org/allaymc/api/world/WorldPool.java | 14 -- .../allaymc/api/world/chunk/ChunkLoader.java | 4 +- .../world/service/EntityPhysicsService.java | 8 +- .../allaymc/api/world/service/HasAABB.java | 6 +- .../org/allaymc/server/AABBTreeJMHTest.java | 42 ++-- .../java/org/allaymc/server/AllayServer.java | 8 +- .../component/BlockBaseComponentImpl.java | 4 +- .../BlockJukeboxBaseComponentImpl.java | 4 +- .../BlockLiquidBaseComponentImpl.java | 6 +- .../component/BlockTntBaseComponentImpl.java | 6 +- .../BlockWetSpongeBaseComponentImpl.java | 3 +- ...ockEntityContainerHolderComponentImpl.java | 10 +- .../BlockEntityJukeboxBaseComponentImpl.java | 10 +- .../BlockEntityFurnaceBaseComponentImpl.java | 12 +- .../server/command/ProxyCommandSender.java | 6 +- .../command/defaults/ExecuteCommand.java | 16 +- .../server/command/defaults/FillCommand.java | 6 +- .../command/defaults/GameTestCommand.java | 22 +- .../command/defaults/SetBlockCommand.java | 4 +- .../defaults/SetWorldSpawnCommand.java | 4 +- .../command/defaults/SpawnPointCommand.java | 6 +- .../command/defaults/StructureCommand.java | 8 +- .../command/defaults/SummonCommand.java | 8 +- .../command/defaults/TeleportCommand.java | 20 +- .../server/command/defaults/WorldCommand.java | 4 +- .../selector/AllayEntitySelectorAPI.java | 8 +- .../server/command/selector/ParseUtils.java | 20 ++ .../server/command/selector/args/C.java | 4 +- .../server/command/selector/args/DX.java | 4 +- .../server/command/selector/args/DY.java | 4 +- .../server/command/selector/args/DZ.java | 4 +- .../server/command/selector/args/L.java | 4 +- .../server/command/selector/args/LM.java | 4 +- .../server/command/selector/args/M.java | 4 +- .../server/command/selector/args/Name.java | 4 +- .../server/command/selector/args/R.java | 4 +- .../server/command/selector/args/RM.java | 4 +- .../server/command/selector/args/RX.java | 4 +- .../server/command/selector/args/RXM.java | 4 +- .../server/command/selector/args/RY.java | 4 +- .../server/command/selector/args/RYM.java | 4 +- .../server/command/selector/args/Scores.java | 4 +- .../server/command/selector/args/Tag.java | 4 +- .../server/command/selector/args/Type.java | 4 +- .../server/command/selector/args/X.java | 6 +- .../server/command/selector/args/Y.java | 6 +- .../server/command/selector/args/Z.java | 6 +- .../server/command/tree/node/PosNode.java | 8 +- .../server/datastruct/aabb/AABBTree.java | 30 +-- .../aabb/AABBTreeHeuristicFunction.java | 4 +- .../server/datastruct/aabb/AABBTreeNode.java | 8 +- .../server/datastruct/aabb/AABBUtils.java | 24 +-- .../aabb/AreaAABBHeuristicFunction.java | 6 +- .../component/EntityBaseComponentImpl.java | 115 +++++------ .../EntityContainerHolderComponentImpl.java | 18 +- .../component/EntityDamageComponentImpl.java | 2 +- .../EntityFallingBlockBaseComponentImpl.java | 16 +- .../EntityItemBaseComponentImpl.java | 14 +- .../EntityPickableBaseComponentImpl.java | 4 +- .../component/EntityTntBaseComponentImpl.java | 16 +- .../EntityXpOrbBaseComponentImpl.java | 8 +- .../component/event/CEntityFallEvent.java | 2 +- .../component/event/CPlayerMoveEvent.java | 4 +- .../player/EntityPlayerBaseComponentImpl.java | 56 ++--- .../EntityPlayerNetworkComponentImpl.java | 4 +- .../ItemSpawnEggBaseComponentImpl.java | 13 +- .../ItemChorusFruitBaseComponentImpl.java | 4 +- .../ingame/PlayerActionPacketProcessor.java | 6 +- .../PlayerAuthInputPacketProcessor.java | 9 +- .../org/allaymc/server/world/AllayWorld.java | 8 +- .../service/AllayEntityPhysicsService.java | 108 +++++----- .../allaymc/api/block/data/BlockFaceTest.java | 14 +- .../api/math/voxelshape/VoxelShapeTest.java | 98 ++++----- .../server/block/BlockStateDataTest.java | 12 +- .../server/command/CommandTreeTest.java | 20 +- .../command/selector/ParseUtilsTest.java | 11 + .../datastruct/aabbtree/AABBTreeTest.java | 92 ++++----- .../datastruct/aabbtree/TestEntity.java | 24 +-- .../entity/type/AllayEntityTypeTest.java | 4 +- .../server/world/service/TestChunkLoader.java | 6 +- 101 files changed, 972 insertions(+), 950 deletions(-) diff --git a/api/src/main/java/org/allaymc/api/block/component/data/BlockStateData.java b/api/src/main/java/org/allaymc/api/block/component/data/BlockStateData.java index 160f237e5..23327543d 100644 --- a/api/src/main/java/org/allaymc/api/block/component/data/BlockStateData.java +++ b/api/src/main/java/org/allaymc/api/block/component/data/BlockStateData.java @@ -10,9 +10,9 @@ import lombok.ToString; import lombok.experimental.Accessors; import org.allaymc.api.math.voxelshape.VoxelShape; -import org.joml.Vector3fc; +import org.joml.Vector3dc; import org.joml.Vector3ic; -import org.joml.primitives.AABBf; +import org.joml.primitives.AABBd; import java.awt.*; @@ -36,18 +36,16 @@ public class BlockStateData { protected static Gson SERIALIZER = new GsonBuilder() .registerTypeAdapter(VoxelShape.class, (JsonDeserializer) (json, typeOfT, context) -> { var array = json.getAsJsonArray(); - var minX = array.get(0).getAsFloat(); - var minY = array.get(1).getAsFloat(); - var minZ = array.get(2).getAsFloat(); - var maxX = array.get(3).getAsFloat(); - var maxY = array.get(4).getAsFloat(); - var maxZ = array.get(5).getAsFloat(); + var minX = array.get(0).getAsDouble(); + var minY = array.get(1).getAsDouble(); + var minZ = array.get(2).getAsDouble(); + var maxX = array.get(3).getAsDouble(); + var maxY = array.get(4).getAsDouble(); + var maxZ = array.get(5).getAsDouble(); if (minX == 0 && minY == 0 && minZ == 0 && maxX == 0 && maxY == 0 && maxZ == 0) { return VoxelShape.EMPTY; } - return VoxelShape.builder().solid( - new AABBf(minX, minY, minZ, maxX, maxY, maxZ) - ).build(); + return VoxelShape.builder().solid(new AABBd(minX, minY, minZ, maxX, maxY, maxZ)).build(); }) .registerTypeAdapter(Color.class, (JsonDeserializer) (json, typeOfT, context) -> { // Example: #4c4c4cff @@ -167,11 +165,11 @@ public boolean hasCollision() { return !collisionShape.getSolids().isEmpty(); } - public VoxelShape computeOffsetCollisionShape(float x, float y, float z) { + public VoxelShape computeOffsetCollisionShape(double x, double y, double z) { return collisionShape.translate(x, y, z); } - public VoxelShape computeOffsetCollisionShape(Vector3fc vector) { + public VoxelShape computeOffsetCollisionShape(Vector3dc vector) { return computeOffsetCollisionShape(vector.x(), vector.y(), vector.z()); } @@ -179,11 +177,11 @@ public VoxelShape computeOffsetCollisionShape(Vector3ic vector) { return computeOffsetCollisionShape(vector.x(), vector.y(), vector.z()); } - public VoxelShape computeOffsetShape(float x, float y, float z) { + public VoxelShape computeOffsetShape(double x, double y, double z) { return shape.translate(x, y, z); } - public VoxelShape computeOffsetShape(Vector3fc vector) { + public VoxelShape computeOffsetShape(Vector3dc vector) { return computeOffsetShape(vector.x(), vector.y(), vector.z()); } diff --git a/api/src/main/java/org/allaymc/api/block/data/BlockFace.java b/api/src/main/java/org/allaymc/api/block/data/BlockFace.java index 0ff8ea4f8..572e106e0 100644 --- a/api/src/main/java/org/allaymc/api/block/data/BlockFace.java +++ b/api/src/main/java/org/allaymc/api/block/data/BlockFace.java @@ -4,12 +4,12 @@ import lombok.Getter; import org.allaymc.api.block.property.enums.MinecraftCardinalDirection; import org.jetbrains.annotations.ApiStatus; -import org.joml.Vector3f; -import org.joml.Vector3fc; +import org.joml.Vector3d; +import org.joml.Vector3dc; import org.joml.Vector3i; import org.joml.Vector3ic; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; import static java.lang.Math.max; import static java.lang.Math.min; @@ -103,12 +103,12 @@ public Vector3ic offsetPos(Vector3ic pos) { * * @return the rotated AABB. */ - public AABBf rotateAABB(AABBfc aabb) { - var c1 = new Vector3f(aabb.minX(), aabb.minY(), aabb.minZ()); - var c2 = new Vector3f(aabb.maxX(), aabb.maxY(), aabb.maxZ()); + public AABBd rotateAABB(AABBdc aabb) { + var c1 = new Vector3d(aabb.minX(), aabb.minY(), aabb.minZ()); + var c2 = new Vector3d(aabb.maxX(), aabb.maxY(), aabb.maxZ()); var nc1 = rotateVector(c1); var nc2 = rotateVector(c2); - return new AABBf( + return new AABBd( min(nc1.x, nc2.x), min(nc1.y, nc2.y), min(nc1.z, nc2.z), @@ -126,12 +126,12 @@ public AABBf rotateAABB(AABBfc aabb) { * @return the rotated vector. */ @SuppressWarnings("SuspiciousNameCombination") - public Vector3f rotateVector(Vector3fc vec) { - Vector3f result = new Vector3f(vec); + public Vector3d rotateVector(Vector3dc vec) { + Vector3d result = new Vector3d(vec); // Translate to rotation point (0.5, 0.5, 0.5) - result.sub(0.5f, 0.5f, 0.5f); + result.sub(0.5, 0.5, 0.5); - float temp; + double temp; switch (this) { case EAST -> { // No rotation needed as EAST is the default orientation @@ -163,7 +163,7 @@ public Vector3f rotateVector(Vector3fc vec) { } // Translate back to original point - result.add(0.5f, 0.5f, 0.5f); + result.add(0.5, 0.5, 0.5); return result; } diff --git a/api/src/main/java/org/allaymc/api/client/storage/PlayerData.java b/api/src/main/java/org/allaymc/api/client/storage/PlayerData.java index 59bf1b1e6..0a0a119ef 100644 --- a/api/src/main/java/org/allaymc/api/client/storage/PlayerData.java +++ b/api/src/main/java/org/allaymc/api/client/storage/PlayerData.java @@ -29,7 +29,7 @@ public static PlayerData createEmpty() { var server = Server.getInstance(); var globalSpawnPoint = server.getWorldPool().getGlobalSpawnPoint(); var builder = NbtMap.builder(); - writeVector3f(builder, "Pos", server.getWorldPool().getGlobalSpawnPointVec3f()); + writeVector3f(builder, "Pos", globalSpawnPoint.x(), globalSpawnPoint.y(), globalSpawnPoint.z()); var worldName = globalSpawnPoint.dimension().getWorld().getWorldData().getDisplayName(); var dimId = globalSpawnPoint.dimension().getDimensionInfo().dimensionId(); return builder() diff --git a/api/src/main/java/org/allaymc/api/command/CommandSender.java b/api/src/main/java/org/allaymc/api/command/CommandSender.java index 71ab11b2b..6d6590427 100644 --- a/api/src/main/java/org/allaymc/api/command/CommandSender.java +++ b/api/src/main/java/org/allaymc/api/command/CommandSender.java @@ -4,7 +4,7 @@ import org.allaymc.api.entity.interfaces.EntityPlayer; import org.allaymc.api.i18n.TextReceiver; import org.allaymc.api.i18n.TrContainer; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.permission.Permissible; import org.allaymc.api.server.Server; import org.allaymc.api.world.gamerule.GameRule; @@ -35,7 +35,7 @@ public interface CommandSender extends TextReceiver, Permissible { * * @return The location where the command was executed. */ - Location3fc getCmdExecuteLocation(); + Location3dc getCmdExecuteLocation(); /** * Handle the result of the command execution. diff --git a/api/src/main/java/org/allaymc/api/command/NPCCommandSender.java b/api/src/main/java/org/allaymc/api/command/NPCCommandSender.java index 31222bd33..f8192479e 100644 --- a/api/src/main/java/org/allaymc/api/command/NPCCommandSender.java +++ b/api/src/main/java/org/allaymc/api/command/NPCCommandSender.java @@ -5,7 +5,7 @@ import org.allaymc.api.entity.interfaces.EntityNpc; import org.allaymc.api.entity.interfaces.EntityPlayer; import org.allaymc.api.i18n.TrContainer; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.permission.DefaultPermissions; import org.allaymc.api.permission.tree.PermissionTree; import org.cloudburstmc.protocol.bedrock.data.command.CommandOriginData; @@ -35,7 +35,7 @@ public CommandOriginData getCommandOriginData() { } @Override - public Location3fc getCmdExecuteLocation() { + public Location3dc getCmdExecuteLocation() { return npc.getLocation(); } diff --git a/api/src/main/java/org/allaymc/api/command/selector/args/CachedFilterSelectorArgument.java b/api/src/main/java/org/allaymc/api/command/selector/args/CachedFilterSelectorArgument.java index 616d15eea..76dddd9a2 100644 --- a/api/src/main/java/org/allaymc/api/command/selector/args/CachedFilterSelectorArgument.java +++ b/api/src/main/java/org/allaymc/api/command/selector/args/CachedFilterSelectorArgument.java @@ -7,7 +7,7 @@ import org.allaymc.api.command.selector.SelectorSyntaxException; import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import java.util.List; import java.util.Set; @@ -27,7 +27,7 @@ public CachedFilterSelectorArgument() { } @Override - public Function, List> getFilter(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException { + public Function, List> getFilter(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException { var value = cache.getIfPresent(Sets.newHashSet(arguments)); if (value == null) { value = cache(selectorType, sender, basePos, arguments); @@ -56,7 +56,7 @@ public boolean isFilter() { * * @throws SelectorSyntaxException if there is an error parsing the arguments. */ - protected abstract Function, List> cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException; + protected abstract Function, List> cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException; /** * Provides the cache service used to store filter functions. diff --git a/api/src/main/java/org/allaymc/api/command/selector/args/CachedSimpleSelectorArgument.java b/api/src/main/java/org/allaymc/api/command/selector/args/CachedSimpleSelectorArgument.java index ccb41715b..cc268698c 100644 --- a/api/src/main/java/org/allaymc/api/command/selector/args/CachedSimpleSelectorArgument.java +++ b/api/src/main/java/org/allaymc/api/command/selector/args/CachedSimpleSelectorArgument.java @@ -7,8 +7,8 @@ import org.allaymc.api.command.selector.SelectorSyntaxException; import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3f; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3d; +import org.allaymc.api.math.location.Location3dc; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -27,7 +27,7 @@ public CachedSimpleSelectorArgument() { } @Override - public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3f basePos, String... arguments) throws SelectorSyntaxException { + public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3d basePos, String... arguments) throws SelectorSyntaxException { var value = cache.getIfPresent(Sets.newHashSet(arguments)); if (value == null) { value = cache(selectorType, sender, basePos, arguments); @@ -50,7 +50,7 @@ public Predicate getPredicate(SelectorType selectorType, CommandSender s * * @throws SelectorSyntaxException if the arguments cannot be parsed. */ - protected abstract Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException; + protected abstract Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException; /** * Provides the cache service used to store predicates. diff --git a/api/src/main/java/org/allaymc/api/command/selector/args/SelectorArgument.java b/api/src/main/java/org/allaymc/api/command/selector/args/SelectorArgument.java index 9d071806f..21351ed4f 100644 --- a/api/src/main/java/org/allaymc/api/command/selector/args/SelectorArgument.java +++ b/api/src/main/java/org/allaymc/api/command/selector/args/SelectorArgument.java @@ -4,8 +4,8 @@ import org.allaymc.api.command.selector.SelectorSyntaxException; import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3f; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3d; +import org.allaymc.api.math.location.Location3dc; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -33,7 +33,7 @@ public interface SelectorArgument extends Comparable { * * @throws SelectorSyntaxException if an error occurs while parsing the arguments. */ - default Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3f basePos, String... arguments) throws SelectorSyntaxException { + default Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3d basePos, String... arguments) throws SelectorSyntaxException { return null; } @@ -52,7 +52,7 @@ default Predicate getPredicate(SelectorType selectorType, CommandSender * * @throws SelectorSyntaxException if an error occurs while parsing the arguments. */ - default Function, List> getFilter(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException { + default Function, List> getFilter(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException { return null; } diff --git a/api/src/main/java/org/allaymc/api/entity/component/EntityBaseComponent.java b/api/src/main/java/org/allaymc/api/entity/component/EntityBaseComponent.java index e883238ff..cb2ef05a9 100644 --- a/api/src/main/java/org/allaymc/api/entity/component/EntityBaseComponent.java +++ b/api/src/main/java/org/allaymc/api/entity/component/EntityBaseComponent.java @@ -15,8 +15,8 @@ import org.allaymc.api.eventbus.event.entity.EntityTeleportEvent; import org.allaymc.api.item.ItemStack; import org.allaymc.api.math.MathUtils; -import org.allaymc.api.math.location.Location3f; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3d; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.math.location.Location3ic; import org.allaymc.api.math.position.Position3i; import org.allaymc.api.math.position.Position3ic; @@ -35,10 +35,10 @@ import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.UnmodifiableView; -import org.joml.Vector3f; -import org.joml.Vector3fc; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; +import org.joml.Vector3d; +import org.joml.Vector3dc; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; import java.util.Map; import java.util.Set; @@ -48,12 +48,12 @@ */ public interface EntityBaseComponent extends EntityComponent, CommandSender, HasAABB, HasLongId { - float SPRINTING_MOVEMENT_FACTOR = 1.3f; - float WALKING_MOVEMENT_FACTOR = 1f; - float SNEAKING_MOVEMENT_FACTOR = 0.3f; - float STOP_MOVEMENT_FACTOR = 0f; - float DEFAULT_PUSH_SPEED_REDUCTION = 1f; - float DEFAULT_KNOCKBACK = 0.4f; + double SPRINTING_MOVEMENT_FACTOR = 1.3; + double WALKING_MOVEMENT_FACTOR = 1; + double SNEAKING_MOVEMENT_FACTOR = 0.3; + double STOP_MOVEMENT_FACTOR = 0; + double DEFAULT_PUSH_SPEED_REDUCTION = 1; + double DEFAULT_KNOCKBACK = 0.4; /** * Gets the type of this entity. @@ -106,7 +106,7 @@ default void clearNameTag() { * * @return the location of this entity. */ - Location3fc getLocation(); + Location3dc getLocation(); /** * Set the location before the entity is spawned. @@ -118,7 +118,7 @@ default void clearNameTag() { * * @throws IllegalStateException if the entity is already spawned. */ - void setLocationBeforeSpawn(Location3fc location); + void setLocationBeforeSpawn(Location3dc location); /** * Gets the dimension of this entity. @@ -185,7 +185,7 @@ default boolean isAlive() { * * @param location the location to teleport the entity to. */ - default void teleport(Location3fc location) { + default void teleport(Location3dc location) { teleport(location, EntityTeleportEvent.Reason.UNKNOWN); } @@ -195,7 +195,7 @@ default void teleport(Location3fc location) { * @param location the location to teleport the entity to. * @param reason the reason of the teleport. */ - void teleport(Location3fc location, EntityTeleportEvent.Reason reason); + void teleport(Location3dc location, EntityTeleportEvent.Reason reason); /** * Teleport the entity to the specified location asynchronously. @@ -204,7 +204,7 @@ default void teleport(Location3fc location) { * * @param location the location to teleport the entity to. */ - default void teleportAsync(Location3fc location) { + default void teleportAsync(Location3dc location) { Thread.ofVirtual().start(() -> teleport(location)); } @@ -214,7 +214,7 @@ default void teleportAsync(Location3fc location) { * @param location the location to teleport the entity to. */ default void teleport(Location3ic location) { - teleport(new Location3f(location)); + teleport(new Location3d(location)); } /** @@ -225,7 +225,7 @@ default void teleport(Location3ic location) { * @param location the location to teleport the entity to. */ default void teleportAsync(Location3ic location) { - teleportAsync(new Location3f(location)); + teleportAsync(new Location3d(location)); } /** @@ -293,15 +293,15 @@ default void setAndSendEntityFlag(EntityFlag flag, boolean value) { * * @return the aabb of this entity. */ - AABBfc getAABB(); + AABBdc getAABB(); /** * Get the offset aabb of this entity. * * @return the offset aabb of this entity. */ - default AABBf getOffsetAABB() { - return getAABB().translate(getLocation(), new AABBf()); + default AABBd getOffsetAABB() { + return getAABB().translate(getLocation(), new AABBd()); } /** @@ -370,14 +370,14 @@ default void onCollideWith(Entity other) {} * * @return the motion of this entity. */ - Vector3fc getMotion(); + Vector3dc getMotion(); /** * Set the motion of this entity. * * @param motion the motion to set. */ - void setMotion(Vector3fc motion); + void setMotion(Vector3dc motion); /** * Set the motion of this entity. @@ -386,8 +386,8 @@ default void onCollideWith(Entity other) {} * @param my the motion y to set. * @param mz the motion z to set. */ - default void setMotion(float mx, float my, float mz) { - setMotion(new Vector3f(mx, my, mz)); + default void setMotion(double mx, double my, double mz) { + setMotion(new Vector3d(mx, my, mz)); } /** @@ -395,8 +395,8 @@ default void setMotion(float mx, float my, float mz) { * * @param add the motion to add. */ - default void addMotion(Vector3fc add) { - setMotion(getMotion().add(add, new Vector3f())); + default void addMotion(Vector3dc add) { + setMotion(getMotion().add(add, new Vector3d())); } /** @@ -406,8 +406,8 @@ default void addMotion(Vector3fc add) { * @param my the motion y to add. * @param mz the motion z to add. */ - default void addMotion(float mx, float my, float mz) { - setMotion(getMotion().add(mx, my, mz, new Vector3f())); + default void addMotion(double mx, double my, double mz) { + setMotion(getMotion().add(mx, my, mz, new Vector3d())); } /** @@ -415,7 +415,7 @@ default void addMotion(float mx, float my, float mz) { * * @return the last motion of this entity. */ - Vector3fc getLastMotion(); + Vector3dc getLastMotion(); /** * Check if the entity is on the ground. @@ -512,7 +512,7 @@ default NbtMap saveNBTWithoutPos() { * * @return the fall distance of this entity. */ - float getFallDistance(); + double getFallDistance(); /** * Called when the entity falls. @@ -585,7 +585,7 @@ default boolean enableHeadYaw() { * @return the base offset of this entity. */ default float getNetworkOffset() { - return 0f; + return 0; } /** @@ -602,8 +602,8 @@ default boolean computeMovementServerSide() { * * @return the step height of this entity. */ - default float getStepHeight() { - return 0.6f; + default double getStepHeight() { + return 0.6; } /** @@ -611,8 +611,8 @@ default float getStepHeight() { * * @return the gravity of this entity. */ - default float getGravity() { - return 0.08f; + default double getGravity() { + return 0.08; } /** @@ -623,8 +623,8 @@ default float getGravity() { * * @return the drag factor when on ground of this entity. */ - default float getDragFactorOnGround() { - return 0.1f; + default double getDragFactorOnGround() { + return 0.1; } /** @@ -636,8 +636,8 @@ default float getDragFactorOnGround() { * * @return the drag factor when in air of this entity. */ - default float getDragFactorInAir() { - return 0.02f; + default double getDragFactorInAir() { + return 0.02; } /** @@ -663,8 +663,8 @@ default void setHasGravity(boolean hasGravity) { * * @return the eye height of this entity. */ - default float getEyeHeight() { - return (getAABB().maxY() - getAABB().minY()) * 0.9f; + default double getEyeHeight() { + return (getAABB().maxY() - getAABB().minY()) * 0.9; } /** @@ -676,7 +676,7 @@ default float getEyeHeight() { * * @see Horizontal Movement Formulas */ - default float getMovementFactor() { + default double getMovementFactor() { return STOP_MOVEMENT_FACTOR; } @@ -685,7 +685,7 @@ default float getMovementFactor() { * * @return the push speed reduction of this entity. */ - default float getPushSpeedReduction() { + default double getPushSpeedReduction() { return DEFAULT_PUSH_SPEED_REDUCTION; } @@ -753,23 +753,23 @@ default BlockFace getHorizontalFace() { } /** - * @see #knockback(Vector3fc, float, boolean, float) + * @see #knockback(Vector3dc, double, boolean, double) */ - default void knockback(Vector3fc source) { + default void knockback(Vector3dc source) { knockback(source, DEFAULT_KNOCKBACK); } /** - * @see #knockback(Vector3fc, float, boolean, float) + * @see #knockback(Vector3dc, double, boolean, double) */ - default void knockback(Vector3fc source, float kb) { + default void knockback(Vector3dc source, double kb) { knockback(source, kb, false); } /** - * @see #knockback(Vector3fc, float, boolean, float) + * @see #knockback(Vector3dc, double, boolean, double) */ - default void knockback(Vector3fc source, float kb, boolean ignoreKnockbackResistance) { + default void knockback(Vector3dc source, double kb, boolean ignoreKnockbackResistance) { knockback(source, kb, ignoreKnockbackResistance, kb); } @@ -781,7 +781,7 @@ default void knockback(Vector3fc source, float kb, boolean ignoreKnockbackResist * @param ignoreKnockbackResistance {@code true} if the knockback resistance should be ignored. * @param kby the knockback strength in y-axis. */ - void knockback(Vector3fc source, float kb, boolean ignoreKnockbackResistance, float kby); + void knockback(Vector3dc source, double kb, boolean ignoreKnockbackResistance, double kby); /** * Apply the entity event to the entity. @@ -812,11 +812,11 @@ default void applyAction(AnimatePacket.Action action) { * @param action the action of the action. * @param rowingTime the rowing time of the action. */ - default void applyAction(AnimatePacket.Action action, float rowingTime) { + default void applyAction(AnimatePacket.Action action, double rowingTime) { var pk = new AnimatePacket(); pk.setRuntimeEntityId(getRuntimeId()); pk.setAction(action); - pk.setRowingTime(rowingTime); + pk.setRowingTime((float) rowingTime); sendPacketToViewers(pk); } @@ -871,7 +871,7 @@ default boolean canCriticalAttack() { */ default boolean isEyesInWater() { var dim = getDimension(); - var eyeLoc = getLocation().add(0, getEyeHeight(), 0, new Vector3f()); + var eyeLoc = getLocation().add(0, getEyeHeight(), 0, new Vector3d()); var eyesBlockState = dim.getBlockState(eyeLoc); return eyesBlockState.getBlockType().hasBlockTag(BlockTags.WATER) && @@ -971,7 +971,7 @@ default boolean canStandSafely(int x, int y, int z, Dimension dimension) { if (!blockUnder.getBlockStateData().isSolid()) { return false; } - var aabb = getAABB().translate(x + 0.5f, y + 0.5f, z + 0.5f, new AABBf()); + var aabb = getAABB().translate(x + 0.5, y + 0.5, z + 0.5, new AABBd()); return dimension.getCollidingBlockStates(aabb) == null; } } diff --git a/api/src/main/java/org/allaymc/api/entity/component/player/EntityPlayerBaseComponent.java b/api/src/main/java/org/allaymc/api/entity/component/player/EntityPlayerBaseComponent.java index 7e8190939..b95859dbb 100644 --- a/api/src/main/java/org/allaymc/api/entity/component/player/EntityPlayerBaseComponent.java +++ b/api/src/main/java/org/allaymc/api/entity/component/player/EntityPlayerBaseComponent.java @@ -14,8 +14,8 @@ import org.cloudburstmc.protocol.bedrock.data.GameType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.jetbrains.annotations.UnmodifiableView; -import org.joml.Vector3f; -import org.joml.Vector3fc; +import org.joml.Vector3d; +import org.joml.Vector3dc; import org.joml.Vector3ic; import java.util.Map; @@ -395,7 +395,7 @@ default boolean canReachBlock(Vector3ic pos) { * * @return Whether the player can reach the point. */ - default boolean canReach(Vector3fc pos) { + default boolean canReach(Vector3dc pos) { return canReach(pos.x(), pos.y(), pos.z()); } @@ -408,19 +408,19 @@ default boolean canReach(Vector3fc pos) { * * @return Whether the player can reach the point. */ - default boolean canReach(float x, float y, float z) { + default boolean canReach(double x, double y, double z) { if (isDead()) return false; var maxDistance = getMaxInteractDistance(); // Check whether there is a point that inside of the player's AABB // And can reach the provided pos var aabb = getOffsetAABB(); - float[] aabbXs = new float[]{aabb.minX(), aabb.maxX()}; - float[] aabbYs = new float[]{aabb.minY(), aabb.maxY()}; - float[] aabbZs = new float[]{aabb.minZ(), aabb.maxZ()}; + double[] aabbXs = new double[]{aabb.minX(), aabb.maxX()}; + double[] aabbYs = new double[]{aabb.minY(), aabb.maxY()}; + double[] aabbZs = new double[]{aabb.minZ(), aabb.maxZ()}; for (var aabbX : aabbXs) { for (var aabbY : aabbYs) { for (var aabbZ : aabbZs) { - if (new Vector3f(aabbX, aabbY, aabbZ).distanceSquared(x, y, z) <= maxDistance * maxDistance) { + if (new Vector3d(aabbX, aabbY, aabbZ).distanceSquared(x, y, z) <= maxDistance * maxDistance) { return true; } } diff --git a/api/src/main/java/org/allaymc/api/entity/initinfo/EntityInitInfo.java b/api/src/main/java/org/allaymc/api/entity/initinfo/EntityInitInfo.java index 032a6fb40..eae345c4e 100644 --- a/api/src/main/java/org/allaymc/api/entity/initinfo/EntityInitInfo.java +++ b/api/src/main/java/org/allaymc/api/entity/initinfo/EntityInitInfo.java @@ -4,12 +4,12 @@ import lombok.Setter; import org.allaymc.api.component.interfaces.ComponentInitInfo; import org.allaymc.api.entity.type.EntityType; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.world.Dimension; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; -import org.joml.Vector3fc; +import org.joml.Vector3dc; /** * Represents the initialization information for an entity. @@ -59,33 +59,33 @@ public Builder dimension(Dimension dimension) { return this; } - public Builder loc(Location3fc loc) { + public Builder loc(Location3dc loc) { pos(loc.x(), loc.y(), loc.z()); rot((float) loc.yaw(), (float) loc.pitch()); this.dimension = loc.dimension(); return this; } - public Builder pos(Vector3fc pos) { + public Builder pos(Vector3dc pos) { return pos(pos.x(), pos.y(), pos.z()); } - public Builder pos(float x, float y, float z) { - nbtBuilder.putList("Pos", NbtType.FLOAT, x, y, z); + public Builder pos(double x, double y, double z) { + nbtBuilder.putList("Pos", NbtType.FLOAT, (float) x, (float) y, (float) z); return this; } - public Builder rot(float yaw, float pitch) { - nbtBuilder.putList("Rotation", NbtType.FLOAT, yaw, pitch); + public Builder rot(double yaw, double pitch) { + nbtBuilder.putList("Rotation", NbtType.FLOAT, (float) yaw, (float) pitch); return this; } - public Builder motion(float dx, float dy, float dz) { - nbtBuilder.putList("Motion", NbtType.FLOAT, dx, dy, dz); + public Builder motion(double dx, double dy, double dz) { + nbtBuilder.putList("Motion", NbtType.FLOAT, (float) dx, (float) dy, (float) dz); return this; } - public Builder motion(Vector3fc m) { + public Builder motion(Vector3dc m) { return motion(m.x(), m.y(), m.z()); } diff --git a/api/src/main/java/org/allaymc/api/entity/interfaces/EntityPlayer.java b/api/src/main/java/org/allaymc/api/entity/interfaces/EntityPlayer.java index c1f613343..696302670 100644 --- a/api/src/main/java/org/allaymc/api/entity/interfaces/EntityPlayer.java +++ b/api/src/main/java/org/allaymc/api/entity/interfaces/EntityPlayer.java @@ -16,7 +16,7 @@ import org.cloudburstmc.protocol.bedrock.data.GameType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket; -import org.joml.Vector3f; +import org.joml.Vector3d; import static org.allaymc.api.item.type.ItemTypes.AIR; @@ -88,7 +88,7 @@ default void dropItemInPlayerPos(ItemStack itemStack) { var dimension = playerLoc.dimension(); dimension.dropItem( itemStack, - playerLoc.add(0, this.getEyeHeight() - 0.4f, 0, new Vector3f()), + playerLoc.add(0, this.getEyeHeight() - 0.4f, 0, new Vector3d()), MathUtils.getDirectionVector(playerLoc.yaw(), playerLoc.pitch()).mul(0.4f), 40 ); diff --git a/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityFallEvent.java b/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityFallEvent.java index ee731a0bc..7e75ff41b 100644 --- a/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityFallEvent.java +++ b/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityFallEvent.java @@ -11,9 +11,9 @@ @Getter @Setter public class EntityFallEvent extends EntityEvent implements CancellableEvent { - protected float fallDistance; + protected double fallDistance; - public EntityFallEvent(Entity entity, float fallDistance) { + public EntityFallEvent(Entity entity, double fallDistance) { super(entity); this.fallDistance = fallDistance; } diff --git a/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityMoveEvent.java b/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityMoveEvent.java index c6f4ed90e..15290a267 100644 --- a/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityMoveEvent.java +++ b/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityMoveEvent.java @@ -3,18 +3,18 @@ import lombok.Getter; import lombok.Setter; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; /** * @author daoge_cmd */ @Getter public class EntityMoveEvent extends EntityEvent { - protected Location3fc from; + protected Location3dc from; @Setter - protected Location3fc to; + protected Location3dc to; - public EntityMoveEvent(Entity entity, Location3fc from, Location3fc to) { + public EntityMoveEvent(Entity entity, Location3dc from, Location3dc to) { super(entity); this.from = from; this.to = to; diff --git a/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityTeleportEvent.java b/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityTeleportEvent.java index ff326087c..d53b7cd75 100644 --- a/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityTeleportEvent.java +++ b/api/src/main/java/org/allaymc/api/eventbus/event/entity/EntityTeleportEvent.java @@ -5,21 +5,21 @@ import lombok.Setter; import org.allaymc.api.entity.Entity; import org.allaymc.api.eventbus.event.CancellableEvent; -import org.allaymc.api.math.location.Location3f; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3d; +import org.allaymc.api.math.location.Location3dc; /** * @author daoge_cmd */ @Getter public class EntityTeleportEvent extends EntityEvent implements CancellableEvent { - protected Location3fc from; + protected Location3dc from; @Setter - protected Location3f to; + protected Location3d to; @Getter protected Reason reason; - public EntityTeleportEvent(Entity entity, Location3fc from, Location3f to, Reason reason) { + public EntityTeleportEvent(Entity entity, Location3dc from, Location3d to, Reason reason) { super(entity); this.from = from; this.to = to; diff --git a/api/src/main/java/org/allaymc/api/eventbus/event/player/PlayerMoveEvent.java b/api/src/main/java/org/allaymc/api/eventbus/event/player/PlayerMoveEvent.java index 3d689fb6a..e23b0dc37 100644 --- a/api/src/main/java/org/allaymc/api/eventbus/event/player/PlayerMoveEvent.java +++ b/api/src/main/java/org/allaymc/api/eventbus/event/player/PlayerMoveEvent.java @@ -3,17 +3,17 @@ import lombok.Getter; import org.allaymc.api.entity.interfaces.EntityPlayer; import org.allaymc.api.eventbus.event.CancellableEvent; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; /** * @author daoge_cmd | Dhaiven */ @Getter public class PlayerMoveEvent extends PlayerEvent implements CancellableEvent { - protected Location3fc from; - protected Location3fc to; + protected Location3dc from; + protected Location3dc to; - public PlayerMoveEvent(EntityPlayer player, Location3fc from, Location3fc to) { + public PlayerMoveEvent(EntityPlayer player, Location3dc from, Location3dc to) { super(player); this.from = from; this.to = to; diff --git a/api/src/main/java/org/allaymc/api/math/MathUtils.java b/api/src/main/java/org/allaymc/api/math/MathUtils.java index 1275af28d..190ff8027 100644 --- a/api/src/main/java/org/allaymc/api/math/MathUtils.java +++ b/api/src/main/java/org/allaymc/api/math/MathUtils.java @@ -4,6 +4,7 @@ import org.allaymc.api.math.location.Location3fc; import org.joml.*; import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; import org.joml.primitives.AABBf; import java.lang.Math; @@ -413,4 +414,13 @@ public static AABBd grow(AABBd aabb, double growth) { aabb.maxZ += growth; return aabb; } + + /** + * NOTICE: This is a temporary method due to a bug in JOML-primitives, and will be removed after + * this pr got merged. + */ + public static boolean intersectsAABB(AABBdc aabb1, AABBdc aabb2) { + return aabb1.maxX() > aabb2.minX() && aabb1.maxY() > aabb2.minY() && aabb1.maxZ() > aabb2.minZ() && + aabb1.minX() < aabb2.maxX() && aabb1.minY() < aabb2.maxY() && aabb1.minZ() < aabb2.maxZ(); + } } diff --git a/api/src/main/java/org/allaymc/api/math/position/Position3d.java b/api/src/main/java/org/allaymc/api/math/position/Position3d.java index cfe44b455..e51a3c050 100644 --- a/api/src/main/java/org/allaymc/api/math/position/Position3d.java +++ b/api/src/main/java/org/allaymc/api/math/position/Position3d.java @@ -20,6 +20,11 @@ public class Position3d extends Vector3d implements Position3dc { public WeakReference dimension; + public Position3d(Position3ic p) { + super(p); + this.dimension = new WeakReference<>(p.dimension()); + } + public Position3d(Position3dc p) { super(p); this.dimension = new WeakReference<>(p.dimension()); diff --git a/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java b/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java index 5ef1a3839..0b3cdca6c 100644 --- a/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java +++ b/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java @@ -4,12 +4,13 @@ import lombok.AllArgsConstructor; import lombok.Getter; import org.allaymc.api.block.data.BlockFace; -import org.joml.Vector2f; -import org.joml.Vector3f; -import org.joml.Vector3fc; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; -import org.joml.primitives.Rayf; +import org.allaymc.api.math.MathUtils; +import org.joml.Vector2d; +import org.joml.Vector3d; +import org.joml.Vector3dc; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; +import org.joml.primitives.Rayd; import java.util.*; import java.util.stream.Collectors; @@ -28,8 +29,8 @@ public final class VoxelShape { public static final VoxelShape EMPTY = new VoxelShape(Collections.emptySet(), Collections.emptySet()); - private final Set solids; - private final Set vacancies; + private final Set solids; + private final Set vacancies; public static VoxelShapeBuilder builder() { return new VoxelShapeBuilder(); @@ -40,15 +41,15 @@ public static VoxelShapeBuilder builder() { * * @return the minimum AABB that can contain this voxel shape. */ - public AABBf unionAABB() { - float - minX = Float.MAX_VALUE, - minY = Float.MAX_VALUE, - minZ = Float.MAX_VALUE; - float - maxX = -Float.MAX_VALUE, - maxY = -Float.MAX_VALUE, - maxZ = -Float.MAX_VALUE; + public AABBd unionAABB() { + double + minX = Double.MAX_VALUE, + minY = Double.MAX_VALUE, + minZ = Double.MAX_VALUE; + double + maxX = -Double.MAX_VALUE, + maxY = -Double.MAX_VALUE, + maxZ = -Double.MAX_VALUE; for (var solid : solids) { if (solid.minX() < minX) minX = solid.minX(); if (solid.minY() < minY) minY = solid.minY(); @@ -57,7 +58,7 @@ public AABBf unionAABB() { if (solid.maxY() > maxY) maxY = solid.maxY(); if (solid.maxZ() > maxZ) maxZ = solid.maxZ(); } - return new AABBf( + return new AABBd( minX, minY, minZ, maxX, maxY, maxZ ); @@ -71,10 +72,10 @@ public AABBf unionAABB() { * @return the rotated voxel shape. */ public VoxelShape rotate(BlockFace face) { - Set newSolids = solids.stream() + Set newSolids = solids.stream() .map(face::rotateAABB) .collect(Collectors.toSet()); - Set newVacancies = vacancies.stream() + Set newVacancies = vacancies.stream() .map(face::rotateAABB) .collect(Collectors.toSet()); return new VoxelShape(newSolids, newVacancies); @@ -89,12 +90,12 @@ public VoxelShape rotate(BlockFace face) { * * @return the translated voxel shape. */ - public VoxelShape translate(float x, float y, float z) { - Set newSolids = solids.stream() - .map(solid -> solid.translate(x, y, z, new AABBf())) + public VoxelShape translate(double x, double y, double z) { + Set newSolids = solids.stream() + .map(solid -> solid.translate(x, y, z, new AABBd())) .collect(Collectors.toSet()); - Set newVacancies = vacancies.stream() - .map(vacancy -> vacancy.translate(x, y, z, new AABBf())) + Set newVacancies = vacancies.stream() + .map(vacancy -> vacancy.translate(x, y, z, new AABBd())) .collect(Collectors.toSet()); return new VoxelShape(newSolids, newVacancies); } @@ -106,20 +107,20 @@ public VoxelShape translate(float x, float y, float z) { * * @return the translated voxel shape. */ - public VoxelShape translate(Vector3fc vec) { + public VoxelShape translate(Vector3dc vec) { // This method is frequently called in physics calculation, // So performance in mind // Set the size of the set as we know that how many entries // will be put into this set to speed up. - var newSolids = new HashSet(solids.size()); + var newSolids = new HashSet(solids.size()); // Simply use for-each instead of stream to get better performance for (var solid : solids) { - newSolids.add(solid.translate(vec, new AABBf())); + newSolids.add(solid.translate(vec, new AABBd())); } - var newVacancies = new HashSet(vacancies.size()); + var newVacancies = new HashSet(vacancies.size()); for (var vacancy : vacancies) { - newVacancies.add(vacancy.translate(vec, new AABBf())); + newVacancies.add(vacancy.translate(vec, new AABBd())); } return new VoxelShape(newSolids, newVacancies); } @@ -131,9 +132,10 @@ public VoxelShape translate(Vector3fc vec) { * * @return true if this voxel shape intersects with the specified AABB, otherwise false. */ - public boolean intersectsAABB(AABBfc other) { + public boolean intersectsAABB(AABBdc other) { var aabb = unionAABB(); - if (!aabb.intersectsAABB(other)) return false; + // TODO: This is a bug in JOML-primitives + if (!MathUtils.intersectsAABB(aabb, other)) return false; other.intersection(aabb, aabb); if (vacancies.stream().anyMatch(vacancy -> vacancy.containsAABB(aabb))) return false; @@ -147,7 +149,7 @@ public boolean intersectsAABB(AABBfc other) { * * @return {@code true} if this voxel shape intersects with the specified point, otherwise {@code false}. */ - public boolean intersectsPoint(Vector3fc vec) { + public boolean intersectsPoint(Vector3dc vec) { if (vacancies.stream().anyMatch(vacancy -> vacancy.containsPoint(vec))) return false; return solids.stream().anyMatch(solid -> solid.containsPoint(vec)); } @@ -161,7 +163,7 @@ public boolean intersectsPoint(Vector3fc vec) { * * @return {@code true} if this voxel shape intersects with the specified point, otherwise {@code false}. */ - public boolean intersectsPoint(float x, float y, float z) { + public boolean intersectsPoint(double x, double y, double z) { if (vacancies.stream().anyMatch(vacancy -> vacancy.containsPoint(x, y, z))) return false; return solids.stream().anyMatch(solid -> solid.containsPoint(x, y, z)); } @@ -175,23 +177,23 @@ public boolean intersectsPoint(float x, float y, float z) { */ public boolean isFull(BlockFace face) { // Check if vacancies cause any gaps on the face - for (AABBfc vacancy : vacancies) { + for (AABBdc vacancy : vacancies) { if (isAlignedWithFace(vacancy, face)) { - float[] uvMinMax = getUVMinMax(vacancy, face); + double[] uvMinMax = getUVMinMax(vacancy, face); // As long as there is any gap, the face is incomplete - if (uvMinMax[0] < 1f || uvMinMax[1] > 0f || uvMinMax[2] < 1f || uvMinMax[3] > 0f) { + if (uvMinMax[0] < 1 || uvMinMax[1] > 0f || uvMinMax[2] < 1 || uvMinMax[3] > 0f) { return false; } } } - float minU = Float.MAX_VALUE, maxU = -Float.MAX_VALUE; - float minV = Float.MAX_VALUE, maxV = -Float.MAX_VALUE; + double minU = Double.MAX_VALUE, maxU = -Double.MAX_VALUE; + double minV = Double.MAX_VALUE, maxV = -Double.MAX_VALUE; // Calculate the range covered by solids - for (AABBfc solid : solids) { + for (AABBdc solid : solids) { if (isAlignedWithFace(solid, face)) { - float[] uvMinMax = getUVMinMax(solid, face); + double[] uvMinMax = getUVMinMax(solid, face); minU = Math.min(minU, uvMinMax[0]); maxU = Math.max(maxU, uvMinMax[1]); minV = Math.min(minV, uvMinMax[2]); @@ -201,7 +203,7 @@ public boolean isFull(BlockFace face) { // If the solids do not completely cover the face, return false // If the face is fully covered by solids with no gaps, return true - return minU == 0f && maxU == 1f && minV == 0f && maxV == 1f; + return minU == 0 && maxU == 1 && minV == 0 && maxV == 1; } /** @@ -213,14 +215,14 @@ public boolean isFull(BlockFace face) { */ public boolean isCenterFull(BlockFace face) { // The boundaries of the center region, from 3/8 to 5/8 - float centerMinUV = (float) 3 / 8; - float centerMaxUV = (float) 5 / 8; + double centerMinUV = (double) 3 / 8; + double centerMaxUV = (double) 5 / 8; // First, check if any vacancy affects the center region boolean vacancyAffectsCenter = vacancies.stream() .filter(vacancy -> isAlignedWithFace(vacancy, face)) .anyMatch(vacancy -> { - float[] uvMinMax = getUVMinMax(vacancy, face); + double[] uvMinMax = getUVMinMax(vacancy, face); return uvMinMax[0] < centerMaxUV && uvMinMax[1] > centerMinUV && uvMinMax[2] < centerMaxUV && uvMinMax[3] > centerMinUV; }); @@ -234,7 +236,7 @@ public boolean isCenterFull(BlockFace face) { return solids.stream() .filter(solid -> isAlignedWithFace(solid, face)) .anyMatch(solid -> { - float[] uvMinMax = getUVMinMax(solid, face); + double[] uvMinMax = getUVMinMax(solid, face); return uvMinMax[0] <= centerMinUV && uvMinMax[1] >= centerMaxUV && uvMinMax[2] <= centerMinUV && uvMinMax[3] >= centerMaxUV; }); @@ -260,10 +262,10 @@ public boolean isFullBlock() { */ public boolean isEdgeFull(BlockFace face) { // Define the width of the edge region - float edgeWidth = 0.125f; + double edgeWidth = 0.125; // Get the boundaries of all edge regions - List edgeRegions = getEdgeRegions(face, edgeWidth); + List edgeRegions = getEdgeRegions(face, edgeWidth); // Check if any vacancy affects any edge region boolean vacancyAffectsEdge = vacancies.stream() @@ -276,7 +278,7 @@ public boolean isEdgeFull(BlockFace face) { } // Check if any solid fully covers each edge region - for (float[] edge : edgeRegions) { + for (double[] edge : edgeRegions) { boolean edgeCovered = solids.stream() .filter(solid -> isAlignedWithFace(solid, face)) .anyMatch(solid -> isRegionFullyCovered(solid, face, edge[0], edge[1], edge[2], edge[3])); @@ -290,10 +292,10 @@ public boolean isEdgeFull(BlockFace face) { } /** - * @see #intersectsRay(Vector3fc, Vector3fc) + * @see #intersectsRay(Vector3dc, Vector3dc) */ - public boolean intersectsRay(float sx, float sy, float sz, float ex, float ey, float ez) { - return intersectsRay(new Vector3f(sx, sy, sz), new Vector3f(ex, ey, ez)); + public boolean intersectsRay(double sx, double sy, double sz, double ex, double ey, double ez) { + return intersectsRay(new Vector3d(sx, sy, sz), new Vector3d(ex, ey, ez)); } /** @@ -304,8 +306,8 @@ public boolean intersectsRay(float sx, float sy, float sz, float ex, float ey, f * * @return {@code true} if the ray intersects this voxel shape, otherwise {@code false}. */ - public boolean intersectsRay(Vector3fc start, Vector3fc end) { - var ray = new Rayf(start, end.sub(start, new Vector3f())); + public boolean intersectsRay(Vector3dc start, Vector3dc end) { + var ray = new Rayd(start, end.sub(start, new Vector3d())); if (vacancies.isEmpty()) { // This would be quicker if no vacancy exists @@ -317,7 +319,7 @@ public boolean intersectsRay(Vector3fc start, Vector3fc end) { // For each solid intervals, check if they can be fully covered by vacancy intervals for (var solidInterval : solidIntervals) { - float currentStart = solidInterval.x; + double currentStart = solidInterval.x; boolean isCovered = false; for (var vacancyInterval : vacancyIntervals) { @@ -342,16 +344,16 @@ public boolean intersectsRay(Vector3fc start, Vector3fc end) { return false; } - private List mergeIntervals(List intervals) { + private List mergeIntervals(List intervals) { // Sort by interval starting point - intervals.sort((a, b) -> Float.compare(a.x, b.x)); - List merged = new ArrayList<>(); + intervals.sort((a, b) -> Double.compare(a.x, b.x)); + List merged = new ArrayList<>(); - for (Vector2f interval : intervals) { + for (Vector2d interval : intervals) { // If merged is empty or the current interval does not overlap with the previous merged interval if (merged.isEmpty() || merged.getLast().y < interval.x) { // Add current interval - merged.add(new Vector2f(interval)); + merged.add(new Vector2d(interval)); } else { // Merge interval merged.getLast().y = Math.max(merged.getLast().y, interval.y); @@ -361,10 +363,10 @@ private List mergeIntervals(List intervals) { return merged; } - private List intersectsRay(Set aabbs, Rayf ray) { - var set = new ArrayList(); + private List intersectsRay(Set aabbs, Rayd ray) { + var set = new ArrayList(); for (var aabb : aabbs) { - var result = new Vector2f(); + var result = new Vector2d(); if (aabb.intersectsRay(ray, result)) { set.add(order(result)); } @@ -373,9 +375,9 @@ private List intersectsRay(Set aabbs, Rayf ray) { return set; } - private Vector2f order(Vector2f vec) { + private Vector2d order(Vector2d vec) { if (vec.x > vec.y) { - float temp = vec.x; + double temp = vec.x; vec.x = vec.y; vec.y = temp; } @@ -383,11 +385,11 @@ private Vector2f order(Vector2f vec) { return vec; } - private List getEdgeRegions(BlockFace face, float edgeWidth) { - List edgeRegions = new ArrayList<>(); + private List getEdgeRegions(BlockFace face, double edgeWidth) { + List edgeRegions = new ArrayList<>(); // Define templates for the four edge regions - float[][] templateEdges = { + double[][] templateEdges = { {0, edgeWidth, 0, 1}, // First edge {1 - edgeWidth, 1, 0, 1}, // Corresponding opposite edge {edgeWidth, 1 - edgeWidth, 0, edgeWidth}, // Third edge @@ -400,14 +402,14 @@ private List getEdgeRegions(BlockFace face, float edgeWidth) { case UP, DOWN -> edgeRegions.addAll(Arrays.asList(templateEdges)); case NORTH, SOUTH -> { // X-Y plane, swap V and U - for (float[] edge : templateEdges) { - edgeRegions.add(new float[]{edge[0], edge[1], edge[2], edge[3]}); + for (double[] edge : templateEdges) { + edgeRegions.add(new double[]{edge[0], edge[1], edge[2], edge[3]}); } } case WEST, EAST -> { // Y-Z plane, swap U and V - for (float[] edge : templateEdges) { - edgeRegions.add(new float[]{edge[2], edge[3], edge[0], edge[1]}); + for (double[] edge : templateEdges) { + edgeRegions.add(new double[]{edge[2], edge[3], edge[0], edge[1]}); } } } @@ -415,40 +417,40 @@ private List getEdgeRegions(BlockFace face, float edgeWidth) { return edgeRegions; } - private boolean intersectsRegion(AABBfc aabb, BlockFace face, float minU, float maxU, float minV, float maxV) { - float[] uvMinMax = getUVMinMax(aabb, face); + private boolean intersectsRegion(AABBdc aabb, BlockFace face, double minU, double maxU, double minV, double maxV) { + double[] uvMinMax = getUVMinMax(aabb, face); return uvMinMax[0] < maxU && uvMinMax[1] > minU && uvMinMax[2] < maxV && uvMinMax[3] > minV; } - private boolean isRegionFullyCovered(AABBfc aabb, BlockFace face, float minU, float maxU, float minV, float maxV) { - float[] uvMinMax = getUVMinMax(aabb, face); + private boolean isRegionFullyCovered(AABBdc aabb, BlockFace face, double minU, double maxU, double minV, double maxV) { + double[] uvMinMax = getUVMinMax(aabb, face); return uvMinMax[0] <= minU && uvMinMax[1] >= maxU && uvMinMax[2] <= minV && uvMinMax[3] >= maxV; } - private boolean isAlignedWithFace(AABBfc solid, BlockFace face) { + private boolean isAlignedWithFace(AABBdc solid, BlockFace face) { return switch (face) { - case UP -> solid.maxY() == 1f; - case DOWN -> solid.minY() == 0f; - case NORTH -> solid.minZ() == 0f; - case SOUTH -> solid.maxZ() == 1f; - case WEST -> solid.minX() == 0f; - case EAST -> solid.maxX() == 1f; + case UP -> solid.maxY() == 1; + case DOWN -> solid.minY() == 0; + case NORTH -> solid.minZ() == 0; + case SOUTH -> solid.maxZ() == 1; + case WEST -> solid.minX() == 0; + case EAST -> solid.maxX() == 1; }; } - private float[] getUVMinMax(AABBfc solid, BlockFace face) { + private double[] getUVMinMax(AABBdc solid, BlockFace face) { return switch (face) { - case UP, DOWN -> new float[]{solid.minX(), solid.maxX(), solid.minZ(), solid.maxZ()}; - case NORTH, SOUTH -> new float[]{solid.minX(), solid.maxX(), solid.minY(), solid.maxY()}; - case WEST, EAST -> new float[]{solid.minZ(), solid.maxZ(), solid.minY(), solid.maxY()}; + case UP, DOWN -> new double[]{solid.minX(), solid.maxX(), solid.minZ(), solid.maxZ()}; + case NORTH, SOUTH -> new double[]{solid.minX(), solid.maxX(), solid.minY(), solid.maxY()}; + case WEST, EAST -> new double[]{solid.minZ(), solid.maxZ(), solid.minY(), solid.maxY()}; }; } public static class VoxelShapeBuilder { - private final Set solids = new HashSet<>(); - private final Set vacancies = new HashSet<>(); + private final Set solids = new HashSet<>(); + private final Set vacancies = new HashSet<>(); /** * Add a solid area to the voxel shape. @@ -457,7 +459,7 @@ public static class VoxelShapeBuilder { * * @return this builder. */ - public VoxelShapeBuilder solid(AABBfc solid) { + public VoxelShapeBuilder solid(AABBdc solid) { solids.add(solid); return this; } @@ -474,8 +476,8 @@ public VoxelShapeBuilder solid(AABBfc solid) { * * @return this builder. */ - public VoxelShapeBuilder solid(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - return solid(new AABBf(minX, minY, minZ, maxX, maxY, maxZ)); + public VoxelShapeBuilder solid(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { + return solid(new AABBd(minX, minY, minZ, maxX, maxY, maxZ)); } /** @@ -485,7 +487,7 @@ public VoxelShapeBuilder solid(float minX, float minY, float minZ, float maxX, f * * @return this builder. */ - public VoxelShapeBuilder vacancy(AABBfc vacancy) { + public VoxelShapeBuilder vacancy(AABBdc vacancy) { vacancies.add(vacancy); return this; } @@ -502,8 +504,8 @@ public VoxelShapeBuilder vacancy(AABBfc vacancy) { * * @return this builder. */ - public VoxelShapeBuilder vacancy(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { - return vacancy(new AABBf(minX, minY, minZ, maxX, maxY, maxZ)); + public VoxelShapeBuilder vacancy(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { + return vacancy(new AABBd(minX, minY, minZ, maxX, maxY, maxZ)); } /** diff --git a/api/src/main/java/org/allaymc/api/world/Dimension.java b/api/src/main/java/org/allaymc/api/world/Dimension.java index 3f68e19ff..9e649fbc6 100644 --- a/api/src/main/java/org/allaymc/api/world/Dimension.java +++ b/api/src/main/java/org/allaymc/api/world/Dimension.java @@ -33,11 +33,11 @@ import org.jetbrains.annotations.Range; import org.jetbrains.annotations.Unmodifiable; import org.jetbrains.annotations.UnmodifiableView; -import org.joml.Vector3f; -import org.joml.Vector3fc; +import org.joml.Vector3d; +import org.joml.Vector3dc; import org.joml.Vector3i; import org.joml.Vector3ic; -import org.joml.primitives.AABBfc; +import org.joml.primitives.AABBdc; import java.util.*; import java.util.concurrent.ThreadLocalRandom; @@ -205,29 +205,29 @@ default void removePlayer(EntityPlayer player) { /** * @see #setBlockState(int, int, int, BlockState, int, boolean, boolean, boolean, PlayerInteractInfo) */ - default void setBlockState(Vector3fc pos, BlockState blockState) { + default void setBlockState(Vector3dc pos, BlockState blockState) { setBlockState(pos, blockState, 0); } /** * @see #setBlockState(int, int, int, BlockState, int, boolean, boolean, boolean, PlayerInteractInfo) */ - default void setBlockState(Vector3fc pos, BlockState blockState, int layer) { - pos = pos.floor(new Vector3f()); + default void setBlockState(Vector3dc pos, BlockState blockState, int layer) { + pos = pos.floor(new Vector3d()); setBlockState((int) pos.x(), (int) pos.y(), (int) pos.z(), blockState, layer); } /** * @see #setBlockState(int, int, int, BlockState, int, boolean, boolean, boolean, PlayerInteractInfo) */ - default void setBlockState(float x, float y, float z, BlockState blockState) { + default void setBlockState(double x, double y, double z, BlockState blockState) { setBlockState(x, y, z, blockState, 0); } /** * @see #setBlockState(int, int, int, BlockState, int, boolean, boolean, boolean, PlayerInteractInfo) */ - default void setBlockState(float x, float y, float z, BlockState blockState, int layer) { + default void setBlockState(double x, double y, double z, BlockState blockState, int layer) { setBlockState((int) Math.floor(x), (int) Math.floor(y), (int) Math.floor(z), blockState, layer); } @@ -362,29 +362,29 @@ default void sendBlockUpdateTo(BlockState blockState, int x, int y, int z, int l /** * @see #getBlockState(int, int, int, int) */ - default BlockState getBlockState(Vector3fc pos) { + default BlockState getBlockState(Vector3dc pos) { return getBlockState(pos, 0); } /** * @see #getBlockState(int, int, int, int) */ - default BlockState getBlockState(Vector3fc pos, int layer) { - pos = pos.floor(new Vector3f()); + default BlockState getBlockState(Vector3dc pos, int layer) { + pos = pos.floor(new Vector3d()); return getBlockState((int) pos.x(), (int) pos.y(), (int) pos.z(), layer); } /** * @see #getBlockState(int, int, int, int) */ - default BlockState getBlockState(float x, float y, float z) { + default BlockState getBlockState(double x, double y, double z) { return getBlockState(x, y, z, 0); } /** * @see #getBlockState(int, int, int, int) */ - default BlockState getBlockState(float x, float y, float z, int layer) { + default BlockState getBlockState(double x, double y, double z, int layer) { return getBlockState((int) Math.floor(x), (int) Math.floor(y), (int) Math.floor(z), layer); } @@ -456,7 +456,7 @@ default BlockState[][][] getBlockStates(int x, int y, int z, int sizeX, int size /** * @see #forEachBlockStates(int, int, int, int, int, int, int, PosAndBlockStateConsumer) */ - default void forEachBlockStates(AABBfc aabb, int layer, PosAndBlockStateConsumer blockStateConsumer) { + default void forEachBlockStates(AABBdc aabb, int layer, PosAndBlockStateConsumer blockStateConsumer) { var maxX = (int) Math.ceil(aabb.maxX()); var maxY = (int) Math.ceil(aabb.maxY()); var maxZ = (int) Math.ceil(aabb.maxZ()); @@ -622,16 +622,16 @@ default void updateBlockProperty(BlockPropertyType property } /** - * @see #getCollidingBlockStates(AABBfc, int, boolean) + * @see #getCollidingBlockStates(AABBdc, int, boolean) */ - default BlockState[][][] getCollidingBlockStates(AABBfc aabb) { + default BlockState[][][] getCollidingBlockStates(AABBdc aabb) { return getCollidingBlockStates(aabb, 0); } /** - * @see #getCollidingBlockStates(AABBfc, int, boolean) + * @see #getCollidingBlockStates(AABBdc, int, boolean) */ - default BlockState[][][] getCollidingBlockStates(AABBfc aabb, int layer) { + default BlockState[][][] getCollidingBlockStates(AABBdc aabb, int layer) { return getCollidingBlockStates(aabb, layer, false); } @@ -644,7 +644,7 @@ default BlockState[][][] getCollidingBlockStates(AABBfc aabb, int layer) { * * @return the block states that collide with the specified AABB, or {@code null} if no block collides. */ - default BlockState[][][] getCollidingBlockStates(AABBfc aabb, int layer, boolean ignoreCollision) { + default BlockState[][][] getCollidingBlockStates(AABBdc aabb, int layer, boolean ignoreCollision) { var maxX = (int) Math.ceil(aabb.maxX()); var maxY = (int) Math.ceil(aabb.maxY()); var maxZ = (int) Math.ceil(aabb.maxZ()); @@ -666,37 +666,37 @@ default BlockState[][][] getCollidingBlockStates(AABBfc aabb, int layer, boolean } /** - * @see #addLevelEvent(float, float, float, LevelEventType, int) + * @see #addLevelEvent(double, double, double, LevelEventType, int) */ default void addLevelEvent(Vector3ic pos, LevelEventType eventType) { addLevelEvent(pos, eventType, 0); } /** - * @see #addLevelEvent(float, float, float, LevelEventType, int) + * @see #addLevelEvent(double, double, double, LevelEventType, int) */ default void addLevelEvent(Vector3ic pos, LevelEventType eventType, int data) { addLevelEvent(pos.x(), pos.y(), pos.z(), eventType, data); } /** - * @see #addLevelEvent(float, float, float, LevelEventType, int) + * @see #addLevelEvent(double, double, double, LevelEventType, int) */ - default void addLevelEvent(Vector3fc pos, LevelEventType eventType) { + default void addLevelEvent(Vector3dc pos, LevelEventType eventType) { addLevelEvent(pos, eventType, 0); } /** - * @see #addLevelEvent(float, float, float, LevelEventType, int) + * @see #addLevelEvent(double, double, double, LevelEventType, int) */ - default void addLevelEvent(Vector3fc pos, LevelEventType eventType, int data) { + default void addLevelEvent(Vector3dc pos, LevelEventType eventType, int data) { addLevelEvent(pos.x(), pos.y(), pos.z(), eventType, data); } /** - * @see #addLevelEvent(float, float, float, LevelEventType, int) + * @see #addLevelEvent(double, double, double, LevelEventType, int) */ - default void addLevelEvent(float x, float y, float z, LevelEventType eventType) { + default void addLevelEvent(double x, double y, double z, LevelEventType eventType) { addLevelEvent(x, y, z, eventType, 0); } @@ -709,7 +709,7 @@ default void addLevelEvent(float x, float y, float z, LevelEventType eventType) * @param eventType the level event type. * @param data the data of the level event. */ - default void addLevelEvent(float x, float y, float z, LevelEventType eventType, int data) { + default void addLevelEvent(double x, double y, double z, LevelEventType eventType, int data) { var chunk = getChunkService().getChunkByDimensionPos((int) x, (int) z); if (chunk == null) return; @@ -721,44 +721,44 @@ default void addLevelEvent(float x, float y, float z, LevelEventType eventType, } /** - * @see #addLevelSoundEvent(float, float, float, SoundEvent, int, String, boolean, boolean) + * @see #addLevelSoundEvent(double, double, double, SoundEvent, int, String, boolean, boolean) */ default void addLevelSoundEvent(Vector3ic pos, SoundEvent soundEvent) { addLevelSoundEvent(pos.x(), pos.y(), pos.z(), soundEvent); } /** - * @see #addLevelSoundEvent(float, float, float, SoundEvent, int, String, boolean, boolean) + * @see #addLevelSoundEvent(double, double, double, SoundEvent, int, String, boolean, boolean) */ default void addLevelSoundEvent(Vector3ic pos, SoundEvent soundEvent, int extraData) { addLevelSoundEvent(pos.x(), pos.y(), pos.z(), soundEvent, extraData); } /** - * @see #addLevelSoundEvent(float, float, float, SoundEvent, int, String, boolean, boolean) + * @see #addLevelSoundEvent(double, double, double, SoundEvent, int, String, boolean, boolean) */ - default void addLevelSoundEvent(Vector3fc pos, SoundEvent soundEvent) { + default void addLevelSoundEvent(Vector3dc pos, SoundEvent soundEvent) { addLevelSoundEvent(pos.x(), pos.y(), pos.z(), soundEvent); } /** - * @see #addLevelSoundEvent(float, float, float, SoundEvent, int, String, boolean, boolean) + * @see #addLevelSoundEvent(double, double, double, SoundEvent, int, String, boolean, boolean) */ - default void addLevelSoundEvent(Vector3fc pos, SoundEvent soundEvent, int extraData) { + default void addLevelSoundEvent(Vector3dc pos, SoundEvent soundEvent, int extraData) { addLevelSoundEvent(pos.x(), pos.y(), pos.z(), soundEvent, extraData); } /** - * @see #addLevelSoundEvent(float, float, float, SoundEvent, int, String, boolean, boolean) + * @see #addLevelSoundEvent(double, double, double, SoundEvent, int, String, boolean, boolean) */ - default void addLevelSoundEvent(float x, float y, float z, SoundEvent soundEvent) { + default void addLevelSoundEvent(double x, double y, double z, SoundEvent soundEvent) { addLevelSoundEvent(x, y, z, soundEvent, -1); } /** - * @see #addLevelSoundEvent(float, float, float, SoundEvent, int, String, boolean, boolean) + * @see #addLevelSoundEvent(double, double, double, SoundEvent, int, String, boolean, boolean) */ - default void addLevelSoundEvent(float x, float y, float z, SoundEvent soundEvent, int extraData) { + default void addLevelSoundEvent(double x, double y, double z, SoundEvent soundEvent, int extraData) { addLevelSoundEvent(x, y, z, soundEvent, extraData, "", false, false); } @@ -774,7 +774,7 @@ default void addLevelSoundEvent(float x, float y, float z, SoundEvent soundEvent * @param babySound whether the sound is a baby sound. * @param relativeVolumeDisabled whether the relative volume is disabled. */ - default void addLevelSoundEvent(float x, float y, float z, SoundEvent soundEvent, int extraData, String identifier, boolean babySound, boolean relativeVolumeDisabled) { + default void addLevelSoundEvent(double x, double y, double z, SoundEvent soundEvent, int extraData, String identifier, boolean babySound, boolean relativeVolumeDisabled) { var chunk = getChunkService().getChunk((int) x >> 4, (int) z >> 4); if (chunk == null) return; @@ -889,7 +889,7 @@ default BlockStateWithPos[] getNeighborsBlockState(int x, int y, int z) { * * @return {@code true} if the y coordinate is in the range of this dimension, otherwise {@code false}. */ - default boolean isYInRange(float y) { + default boolean isYInRange(double y) { return y >= getDimensionInfo().minHeight() && y <= getDimensionInfo().maxHeight(); } @@ -902,7 +902,7 @@ default boolean isYInRange(float y) { * * @return {@code true} if the pos is in a valid and loaded region, otherwise {@code false}. */ - default boolean isInWorld(float x, float y, float z) { + default boolean isInWorld(double x, double y, double z) { return isYInRange(y) && getChunkService().isChunkLoaded((int) x >> 4, (int) z >> 4); } @@ -913,7 +913,7 @@ default boolean isInWorld(float x, float y, float z) { * * @return {@code true} if the aabb is in a valid and loaded region, otherwise {@code false}. */ - default boolean isAABBInWorld(AABBfc aabb) { + default boolean isAABBInWorld(AABBdc aabb) { return isInWorld(aabb.maxX(), aabb.maxY(), aabb.maxZ()) && isInWorld(aabb.minX(), aabb.minY(), aabb.minZ()); } @@ -949,37 +949,37 @@ default int getBlockEntityCount() { } /** - * @see #addParticle(float, float, float, ParticleType, int) + * @see #addParticle(double, double, double, ParticleType, int) */ default void addParticle(Vector3ic pos, ParticleType particleType) { addParticle(pos, particleType, 0); } /** - * @see #addParticle(float, float, float, ParticleType, int) + * @see #addParticle(double, double, double, ParticleType, int) */ default void addParticle(Vector3ic pos, ParticleType particleType, int data) { addParticle(pos.x(), pos.y(), pos.z(), particleType, data); } /** - * @see #addParticle(float, float, float, ParticleType, int) + * @see #addParticle(double, double, double, ParticleType, int) */ - default void addParticle(Vector3fc pos, ParticleType particleType) { + default void addParticle(Vector3dc pos, ParticleType particleType) { addParticle(pos, particleType, 0); } /** - * @see #addParticle(float, float, float, ParticleType, int) + * @see #addParticle(double, double, double, ParticleType, int) */ - default void addParticle(Vector3fc pos, ParticleType particleType, int data) { + default void addParticle(Vector3dc pos, ParticleType particleType, int data) { addParticle(pos.x(), pos.y(), pos.z(), particleType, data); } /** - * @see #addParticle(float, float, float, ParticleType, int) + * @see #addParticle(double, double, double, ParticleType, int) */ - default void addParticle(float x, float y, float z, ParticleType particleType) { + default void addParticle(double x, double y, double z, ParticleType particleType) { this.addParticle(x, y, z, particleType, 0); } @@ -992,7 +992,7 @@ default void addParticle(float x, float y, float z, ParticleType particleType) { * @param particleType the type of the particle to be added. * @param data the data associated with the particle. */ - default void addParticle(float x, float y, float z, ParticleType particleType, int data) { + default void addParticle(double x, double y, double z, ParticleType particleType, int data) { addLevelEvent(x, y, z, particleType, data); } @@ -1006,51 +1006,51 @@ default void broadcastPacket(BedrockPacket packet) { } /** - * @see #addSound(float, float, float, String, float) + * @see #addSound(double, double, double, String, double) */ - default void addSound(Vector3fc pos, String sound) { + default void addSound(Vector3dc pos, String sound) { addSound(pos, sound, 1); } /** - * @see #addSound(float, float, float, String, float) + * @see #addSound(double, double, double, String, double) */ - default void addSound(Vector3fc pos, String sound, float volume) { + default void addSound(Vector3dc pos, String sound, double volume) { addSound(pos, sound, volume, 1); } /** - * @see #addSound(float, float, float, String, float) + * @see #addSound(double, double, double, String, double) */ - default void addSound(Vector3fc pos, String sound, float volume, float pitch) { + default void addSound(Vector3dc pos, String sound, double volume, double pitch) { addSound(pos.x(), pos.y(), pos.z(), sound, volume, pitch); } /** - * @see #addSound(float, float, float, String, float) + * @see #addSound(double, double, double, String, double) */ default void addSound(Vector3ic pos, String sound) { addSound(pos, sound, 1); } /** - * @see #addSound(float, float, float, String, float) + * @see #addSound(double, double, double, String, double) */ - default void addSound(Vector3ic pos, String sound, float volume) { + default void addSound(Vector3ic pos, String sound, double volume) { addSound(pos, sound, volume, 1); } /** - * @see #addSound(float, float, float, String, float) + * @see #addSound(double, double, double, String, double) */ - default void addSound(Vector3ic pos, String sound, float volume, float pitch) { + default void addSound(Vector3ic pos, String sound, double volume, double pitch) { addSound(pos.x(), pos.y(), pos.z(), sound, volume, pitch); } /** - * @see #addSound(float, float, float, String, float) + * @see #addSound(double, double, double, String, double) */ - default void addSound(float x, float y, float z, String sound) { + default void addSound(double x, double y, double z, String sound) { addSound(x, y, z, sound, 1); } @@ -1063,7 +1063,7 @@ default void addSound(float x, float y, float z, String sound) { * @param sound the sound. * @param volume the volume of the sound. */ - default void addSound(float x, float y, float z, String sound, float volume) { + default void addSound(double x, double y, double z, String sound, double volume) { addSound(x, y, z, sound, volume, 1); } @@ -1077,31 +1077,31 @@ default void addSound(float x, float y, float z, String sound, float volume) { * @param volume the volume of the sound. * @param pitch the pitch of the sound. */ - default void addSound(float x, float y, float z, String sound, float volume, float pitch) { + default void addSound(double x, double y, double z, String sound, double volume, double pitch) { Preconditions.checkArgument(volume >= 0 && volume <= 1, "Sound volume must be between 0 and 1"); Preconditions.checkArgument(pitch >= 0, "Sound pitch must be higher than 0"); var packet = new PlaySoundPacket(); packet.setSound(sound); - packet.setVolume(volume); - packet.setPitch(pitch); + packet.setVolume((float) volume); + packet.setPitch((float) pitch); packet.setPosition(org.cloudburstmc.math.vector.Vector3f.from(x, y, z)); getChunkService().getChunkByDimensionPos((int) x, (int) z).addChunkPacket(packet); } /** - * @see #dropItem(ItemStack, Vector3fc, Vector3fc, int) + * @see #dropItem(ItemStack, Vector3dc, Vector3dc, int) */ - default void dropItem(ItemStack itemStack, Vector3fc pos) { + default void dropItem(ItemStack itemStack, Vector3dc pos) { var rand = ThreadLocalRandom.current(); - dropItem(itemStack, pos, new Vector3f(rand.nextFloat(0.2f) - 0.1f, 0.2f, rand.nextFloat(0.2f) - 0.1f)); + dropItem(itemStack, pos, new Vector3d(rand.nextDouble(0.2) - 0.1, 0.2, rand.nextDouble(0.2) - 0.1)); } /** - * @see #dropItem(ItemStack, Vector3fc, Vector3fc, int) + * @see #dropItem(ItemStack, Vector3dc, Vector3dc, int) */ - default void dropItem(ItemStack itemStack, Vector3fc pos, Vector3fc motion) { + default void dropItem(ItemStack itemStack, Vector3dc pos, Vector3dc motion) { dropItem(itemStack, pos, motion, 10); } @@ -1113,7 +1113,7 @@ default void dropItem(ItemStack itemStack, Vector3fc pos, Vector3fc motion) { * @param motion the motion of the item entity. * @param pickupDelay the pickup delay of the item entity. */ - default void dropItem(ItemStack itemStack, Vector3fc pos, Vector3fc motion, int pickupDelay) { + default void dropItem(ItemStack itemStack, Vector3dc pos, Vector3dc motion, int pickupDelay) { var entityItem = EntityTypes.ITEM.createEntity( EntityInitInfo.builder() .dimension(this) @@ -1135,7 +1135,7 @@ default void dropItem(ItemStack itemStack, Vector3fc pos, Vector3fc motion, int * @param pos the pos to drop the xp orbs. * @param xp the amount of xp to drop. */ - default void splitAndDropXpOrb(Vector3fc pos, int xp) { + default void splitAndDropXpOrb(Vector3dc pos, int xp) { for (var split : EntityXpOrb.splitIntoOrbSizes(xp)) { dropXpOrb(pos, split); } @@ -1148,12 +1148,12 @@ default void splitAndDropXpOrb(Vector3fc pos, int xp) { * @param pos the pos to drop the xp orb. * @param xp the amount of xp to drop. */ - default void dropXpOrb(Vector3fc pos, int xp) { + default void dropXpOrb(Vector3dc pos, int xp) { var rand = ThreadLocalRandom.current(); - var motion = new Vector3f( - (rand.nextFloat() * 0.2f - 0.1f) * 2f, - rand.nextFloat() * 0.4f, - (rand.nextFloat() * 0.2f - 0.1f) * 2f + var motion = new Vector3d( + (rand.nextDouble() * 0.2 - 0.1) * 2, + rand.nextDouble() * 0.4, + (rand.nextDouble() * 0.2 - 0.1) * 2 ); dropXpOrb(pos, xp, motion); } @@ -1165,7 +1165,7 @@ default void dropXpOrb(Vector3fc pos, int xp) { * @param xp the amount of xp to drop. * @param motion the motion of the xp orb entity. */ - default void dropXpOrb(Vector3fc pos, int xp, Vector3fc motion) { + default void dropXpOrb(Vector3dc pos, int xp, Vector3dc motion) { dropXpOrb(pos, xp, motion, 10); } @@ -1177,14 +1177,14 @@ default void dropXpOrb(Vector3fc pos, int xp, Vector3fc motion) { * @param motion the motion of the xp orb entity. * @param pickupDelay the pickup delay of the xp orb entity. */ - default void dropXpOrb(Vector3fc pos, int xp, Vector3fc motion, int pickupDelay) { + default void dropXpOrb(Vector3dc pos, int xp, Vector3dc motion, int pickupDelay) { var rand = ThreadLocalRandom.current(); var entityXpOrb = EntityTypes.XP_ORB.createEntity( EntityInitInfo.builder() .dimension(this) .pos(pos) .motion(motion) - .rot(rand.nextFloat() * 360f, 0) + .rot(rand.nextDouble() * 360, 0) .build() ); entityXpOrb.setExperienceValue(xp); diff --git a/api/src/main/java/org/allaymc/api/world/Explosion.java b/api/src/main/java/org/allaymc/api/world/Explosion.java index 1fd0620dc..278276954 100644 --- a/api/src/main/java/org/allaymc/api/world/Explosion.java +++ b/api/src/main/java/org/allaymc/api/world/Explosion.java @@ -14,12 +14,12 @@ import org.allaymc.api.math.position.Position3i; import org.cloudburstmc.protocol.bedrock.data.ParticleType; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; -import org.joml.Vector3f; -import org.joml.Vector3fc; +import org.joml.Vector3d; +import org.joml.Vector3dc; import org.joml.Vector3i; import org.joml.Vector3ic; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; import java.util.ArrayList; import java.util.Arrays; @@ -42,17 +42,17 @@ @Setter public class Explosion { - protected static final Vector3fc[] RAYS = new Vector3fc[1352]; + protected static final Vector3dc[] RAYS = new Vector3dc[1352]; static { int index = 0; - for (float x = 0; x < 16; x++) { - for (float y = 0; y < 16; y++) { - for (float z = 0; z < 16; z++) { + for (double x = 0; x < 16; x++) { + for (double y = 0; y < 16; y++) { + for (double z = 0; z < 16; z++) { if (x != 0 && x != 15 && y != 0 && y != 15 && z != 0 && z != 15) { continue; } - RAYS[index++] = new Vector3f(x / 15.0f * 2 - 1, y / 15.0f * 2 - 1, z / 15.0f * 2 - 1).normalize(0.3f); + RAYS[index++] = new Vector3d(x / 15.0 * 2 - 1, y / 15.0 * 2 - 1, z / 15.0 * 2 - 1).normalize(0.3); } } } @@ -153,16 +153,16 @@ public Explosion(float size, boolean spawnFire, float itemDropChance, SoundEvent } /** - * @see #explode(Dimension, float, float, float) + * @see #explode(Dimension, double, double, double) */ public void explode(Dimension dimension, Vector3ic pos) { this.explode(dimension, pos.x(), pos.y(), pos.z()); } /** - * @see #explode(Dimension, float, float, float) + * @see #explode(Dimension, double, double, double) */ - public void explode(Dimension dimension, Vector3fc pos) { + public void explode(Dimension dimension, Vector3dc pos) { this.explode(dimension, pos.x(), pos.y(), pos.z()); } @@ -174,13 +174,13 @@ public void explode(Dimension dimension, Vector3fc pos) { * @param y the y coordinate of the explosion. * @param z the z coordinate of the explosion. */ - public void explode(Dimension dimension, float x, float y, float z) { - var explosionPos = new Vector3f(x, y, z); + public void explode(Dimension dimension, double x, double y, double z) { + var explosionPos = new Vector3d(x, y, z); var rand = ThreadLocalRandom.current(); var d = size * 2; - var aabb = new AABBf( - (float) Math.floor(x - d - 1), (float) Math.floor(y - d - 1), (float) Math.floor(z - d - 1), - (float) Math.ceil(x + d + 1), (float) Math.ceil(y + d + 1), (float) Math.ceil(z + d + 1) + var aabb = new AABBd( + (double) Math.floor(x - d - 1), (double) Math.floor(y - d - 1), (double) Math.floor(z - d - 1), + (double) Math.ceil(x + d + 1), (double) Math.ceil(y + d + 1), (double) Math.ceil(z + d + 1) ); MathUtils.grow(aabb, 2); @@ -189,45 +189,45 @@ public void explode(Dimension dimension, float x, float y, float z) { // Skip the entity that caused the explosion affectedEntities.remove(entity); var impactMap = affectedEntities.parallelStream() - .collect(Collectors.toConcurrentMap( + .collect(Collectors.toConcurrentMap( affectedEntity -> affectedEntity, affectedEntity -> { var pos = affectedEntity.getLocation(); - var dist = pos.sub(x, y, z, new Vector3f()).length(); + var dist = pos.sub(x, y, z, new Vector3d()).length(); if (dist > d || dist == 0) { - return 0.0f; + return 0.0; } // Method exposure() is slow, let's calculate it in parallel - return (1.0f - dist / d) * exposure(dimension, explosionPos, affectedEntity.getOffsetAABB()); + return (1.0 - dist / d) * exposure(dimension, explosionPos, affectedEntity.getOffsetAABB()); } )); for (var affectedEntity : affectedEntities) { var impact = impactMap.get(affectedEntity); - if (impact == 0.0f) { + if (impact == 0.0) { continue; } - var kbResistance = 0.0f; + var kbResistance = 0.0; if (affectedEntity instanceof EntityAttributeComponent attributeComponent && attributeComponent.supportAttribute(AttributeType.KNOCKBACK_RESISTANCE)) { kbResistance = attributeComponent.getAttributeValue(AttributeType.KNOCKBACK_RESISTANCE); } - var direction = affectedEntity.getLocation().sub(explosionPos, new Vector3f()); + var direction = affectedEntity.getLocation().sub(explosionPos, new Vector3d()); if (direction.lengthSquared() > 0) { - affectedEntity.addMotion(direction.normalize().mul(impact * (1.0f - kbResistance))); + affectedEntity.addMotion(direction.normalize().mul(impact * (1.0 - kbResistance))); } if (affectedEntity instanceof EntityDamageComponent damageComponent) { var m = switch (dimension.getWorld().getWorldData().getDifficulty()) { - case PEACEFUL -> 0.0f; + case PEACEFUL -> 0.0; case EASY -> 3.5f; - case NORMAL -> 7.0f; + case NORMAL -> 7.0; case HARD -> 10.5f; }; - var damage = (impact * impact + impact) * m * size / 2.0f + 1.0f; + var damage = (impact * impact + impact) * m * size / 2.0 + 1.0; if (entity == null) { - damageComponent.attack(DamageContainer.blockExplosion(damage)); + damageComponent.attack(DamageContainer.blockExplosion((float) damage)); } else { - damageComponent.attack(DamageContainer.entityExplosion(entity, damage)); + damageComponent.attack(DamageContainer.entityExplosion(entity, (float) damage)); } } } @@ -244,9 +244,9 @@ public void explode(Dimension dimension, float x, float y, float z) { var lz = z; // Get the random instance for each thread var localRand = ThreadLocalRandom.current(); - for (var blastForce = size * (0.7f + localRand.nextFloat() * 0.6f); blastForce > 0; blastForce -= 0.225f) { + for (var blastForce = size * (0.7f + localRand.nextDouble() * 0.6f); blastForce > 0; blastForce -= 0.225f) { var current = new Vector3i((int) Math.floor(lx), (int) Math.floor(ly), (int) Math.floor(lz)); - var resistance = 0.0f; + var resistance = 0.0; // Do not use getLiquid(), which is much slower. Just get the block in layer 1 and // check if it is water by comparing it with BlockTypes.WATER and BlockTypes.FLOWING_WATER var layer1 = dimension.getBlockState(current, 1).getBlockType(); @@ -259,7 +259,7 @@ public void explode(Dimension dimension, float x, float y, float z) { ly += ray.y(); lz += ray.z(); - var delta = (resistance / 5.0f + 0.3f) * 0.3f; + var delta = (resistance / 5.0 + 0.3f) * 0.3f; // resistance may be very big if the block is an unbreakable block such as // bedrock, so we should operate it carefully to avoid precision overflow if (blastForce < delta) { @@ -294,7 +294,7 @@ public void explode(Dimension dimension, float x, float y, float z) { } dimension.setBlockState(pos, BlockTypes.AIR.getDefaultState()); - if (itemDropChance > rand.nextFloat()) { + if (itemDropChance > rand.nextDouble()) { var centerPos = MathUtils.center(pos); for (var item : block.getBehavior().getDrops(new BlockStateWithPos(block, new Position3i(pos, dimension)), null, null)) { dimension.dropItem(item, centerPos); @@ -323,25 +323,25 @@ public void explode(Dimension dimension, float x, float y, float z) { /** * Calculate the exposure of an explosion to an entity, used to calculate the impact of an explosion. */ - protected float exposure(Dimension dimension, Vector3fc origin, AABBfc box) { - Vector3fc boxMin = new Vector3f(box.minX(), box.minY(), box.minZ()); - Vector3fc boxMax = new Vector3f(box.maxX(), box.maxY(), box.maxZ()); - var diff = boxMax.sub(boxMin, new Vector3f()).mul(2.0f).add(1, 1, 1); - - var step = new Vector3f(1.0f / diff.x(), 1.0f / diff.y(), 1.0f / diff.z()); - if (step.x() < 0.0f || step.y() < 0.0f || step.z() < 0.0f) { - return 0.0f; + protected double exposure(Dimension dimension, Vector3dc origin, AABBdc box) { + Vector3dc boxMin = new Vector3d(box.minX(), box.minY(), box.minZ()); + Vector3dc boxMax = new Vector3d(box.maxX(), box.maxY(), box.maxZ()); + var diff = boxMax.sub(boxMin, new Vector3d()).mul(2.0).add(1, 1, 1); + + var step = new Vector3d(1.0 / diff.x(), 1.0 / diff.y(), 1.0 / diff.z()); + if (step.x() < 0.0 || step.y() < 0.0 || step.z() < 0.0) { + return 0.0; } - float xOffset = (1.0f - (float) Math.floor(diff.x()) / diff.x()) / 2.0f; - float zOffset = (1.0f - (float) Math.floor(diff.z()) / diff.z()) / 2.0f; + double xOffset = (1.0 - Math.floor(diff.x()) / diff.x()) / 2.0; + double zOffset = (1.0 - Math.floor(diff.z()) / diff.z()) / 2.0; - float checks = 0; - float misses = 0; - for (var x = 0.0f; x <= 1.0f; x += step.x()) { - for (var y = 0.0f; y <= 1.0f; y += step.y()) { - for (var z = 0.0f; z <= 1.0f; z += step.z()) { - var point = new Vector3f( + double checks = 0; + double misses = 0; + for (var x = 0.0; x <= 1.0; x += step.x()) { + for (var y = 0.0; y <= 1.0; y += step.y()) { + for (var z = 0.0; z <= 1.0; z += step.z()) { + var point = new Vector3d( lerp(x, boxMin.x(), boxMax.x()) + xOffset, lerp(y, boxMin.y(), boxMax.y()), lerp(z, boxMin.z(), boxMax.z()) + zOffset @@ -373,13 +373,13 @@ protected float exposure(Dimension dimension, Vector3fc origin, AABBfc box) { /** * Return the linear interpolation between a and b at t. */ - protected static float lerp(float a, float b, float t) { + protected static double lerp(double a, double b, double t) { return b + a * (t - b); } - protected static void traverseBlocks(Vector3fc start, Vector3fc end, Predicate predicate) { - var dir = end.sub(start, new Vector3f()); - if (Float.compare(dir.lengthSquared(), 0.0f) == 0) { + protected static void traverseBlocks(Vector3dc start, Vector3dc end, Predicate predicate) { + var dir = end.sub(start, new Vector3d()); + if (Double.compare(dir.lengthSquared(), 0.0) == 0) { throw new IllegalArgumentException("Start and end points are the same, giving a zero direction vector"); } @@ -391,11 +391,11 @@ protected static void traverseBlocks(Vector3fc start, Vector3fc end, Predicate 0.0f) { - return 1.0f; - } else if (f < 0.0f) { - return -1.0f; + protected static double sign(double f) { + if (f > 0.0) { + return 1.0; + } else if (f < 0.0) { + return -1.0; } else { - return 0.0f; + return 0.0; } } } diff --git a/api/src/main/java/org/allaymc/api/world/WorldPool.java b/api/src/main/java/org/allaymc/api/world/WorldPool.java index 40a148e69..0c93ed05d 100644 --- a/api/src/main/java/org/allaymc/api/world/WorldPool.java +++ b/api/src/main/java/org/allaymc/api/world/WorldPool.java @@ -3,8 +3,6 @@ import org.allaymc.api.math.location.Location3i; import org.allaymc.api.math.location.Location3ic; import org.jetbrains.annotations.UnmodifiableView; -import org.joml.Vector3f; -import org.joml.Vector3fc; import java.util.Map; @@ -77,16 +75,4 @@ default Location3ic getGlobalSpawnPoint() { var vec = getDefaultWorld().getWorldData().getSpawnPoint(); return new Location3i(vec.x(), vec.y(), vec.z(), getDefaultWorld().getOverWorld()); } - - /** - * Get the global spawn point of the server. - *

- * Global spawn point is the location of the player who joins the server for the first time. - * - * @return the global spawn point of the server. - */ - default Vector3fc getGlobalSpawnPointVec3f() { - var vec = getDefaultWorld().getWorldData().getSpawnPoint(); - return new Vector3f(vec.x(), vec.y(), vec.z()); - } } diff --git a/api/src/main/java/org/allaymc/api/world/chunk/ChunkLoader.java b/api/src/main/java/org/allaymc/api/world/chunk/ChunkLoader.java index 6effca4a5..efb43bf12 100644 --- a/api/src/main/java/org/allaymc/api/world/chunk/ChunkLoader.java +++ b/api/src/main/java/org/allaymc/api/world/chunk/ChunkLoader.java @@ -1,7 +1,7 @@ package org.allaymc.api.world.chunk; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.network.PacketReceiver; import org.jetbrains.annotations.ApiStatus; @@ -19,7 +19,7 @@ public interface ChunkLoader extends PacketReceiver { * * @return the location of the chunk loader. */ - Location3fc getLocation(); + Location3dc getLocation(); /** * Check if the loader is active. diff --git a/api/src/main/java/org/allaymc/api/world/service/EntityPhysicsService.java b/api/src/main/java/org/allaymc/api/world/service/EntityPhysicsService.java index 473b9f998..6175784ae 100644 --- a/api/src/main/java/org/allaymc/api/world/service/EntityPhysicsService.java +++ b/api/src/main/java/org/allaymc/api/world/service/EntityPhysicsService.java @@ -2,7 +2,7 @@ import org.allaymc.api.entity.Entity; import org.allaymc.api.math.voxelshape.VoxelShape; -import org.joml.primitives.AABBfc; +import org.joml.primitives.AABBdc; import java.util.List; @@ -31,7 +31,7 @@ default List computeCollidingEntities(Entity entity) { * * @return The entities that are colliding with the specified aabb. */ - default List computeCollidingEntities(AABBfc aabb) { + default List computeCollidingEntities(AABBdc aabb) { return computeCollidingEntities(aabb, entity -> true); } @@ -55,7 +55,7 @@ default List computeCollidingEntities(Entity entity, boolean ignoreEntit * * @return The entities that are colliding with the specified aabb. */ - default List computeCollidingEntities(AABBfc aabb, boolean ignoreEntityHasCollision) { + default List computeCollidingEntities(AABBdc aabb, boolean ignoreEntityHasCollision) { return computeCollidingEntities(aabb, entity -> ignoreEntityHasCollision || entity.hasEntityCollision()); } @@ -67,7 +67,7 @@ default List computeCollidingEntities(AABBfc aabb, boolean ignoreEntityH * * @return The entities that are colliding with the specified aabb and pass the predicate. */ - List computeCollidingEntities(AABBfc aabb, AABBOverlapFilter predicate); + List computeCollidingEntities(AABBdc aabb, AABBOverlapFilter predicate); /** * @see #computeCollidingEntities(VoxelShape, boolean) diff --git a/api/src/main/java/org/allaymc/api/world/service/HasAABB.java b/api/src/main/java/org/allaymc/api/world/service/HasAABB.java index 731c55dcd..35c5f4b29 100644 --- a/api/src/main/java/org/allaymc/api/world/service/HasAABB.java +++ b/api/src/main/java/org/allaymc/api/world/service/HasAABB.java @@ -1,6 +1,6 @@ package org.allaymc.api.world.service; -import org.joml.primitives.AABBfc; +import org.joml.primitives.AABBdc; /** * HasAABB represents an object that has an AABB. @@ -12,10 +12,10 @@ public interface HasAABB { /** * @return the AABB of the object. */ - AABBfc getAABB(); + AABBdc getAABB(); /** * @return the offset AABB of the object. */ - AABBfc getOffsetAABB(); + AABBdc getOffsetAABB(); } diff --git a/server/src/jmh/java/org/allaymc/server/AABBTreeJMHTest.java b/server/src/jmh/java/org/allaymc/server/AABBTreeJMHTest.java index c3a48d4ab..9fc774df7 100644 --- a/server/src/jmh/java/org/allaymc/server/AABBTreeJMHTest.java +++ b/server/src/jmh/java/org/allaymc/server/AABBTreeJMHTest.java @@ -2,7 +2,7 @@ import org.allaymc.server.datastruct.aabb.AABBTree; import org.allaymc.server.datastruct.aabbtree.TestEntity; -import org.joml.primitives.AABBf; +import org.joml.primitives.AABBd; import org.openjdk.jmh.annotations.*; import java.util.ArrayList; @@ -25,8 +25,8 @@ public class AABBTreeJMHTest { private final int RANGE = 500; private AABBTree aabbTree; private TestEntity[] testEntities; - private AABBf[] testEntityAABBs; - private AABBf[] testAABBs; + private AABBd[] testEntityAABBs; + private AABBd[] testAABBs; private int indexCounter = 0; @Setup @@ -37,11 +37,11 @@ public void init() { testEntities[i] = createRandomTestEntity(i); aabbTree.add(testEntities[i]); } - testEntityAABBs = new AABBf[TEST_ENTITY_COUNT]; + testEntityAABBs = new AABBd[TEST_ENTITY_COUNT]; for (int i = 0; i < TEST_ENTITY_COUNT; i++) { - testEntityAABBs[i] = new AABBf().set(testEntities[i].getOffsetAABB()); + testEntityAABBs[i] = new AABBd().set(testEntities[i].getOffsetAABB()); } - testAABBs = new AABBf[TEST_ENTITY_COUNT]; + testAABBs = new AABBd[TEST_ENTITY_COUNT]; for (int i = 0; i < TEST_ENTITY_COUNT; i++) { testAABBs[i] = createRandomAABB(); } @@ -50,23 +50,23 @@ public void init() { public TestEntity createRandomTestEntity(int id) { return new TestEntity( id, - ThreadLocalRandom.current().nextFloat() * RANGE, - ThreadLocalRandom.current().nextFloat() * RANGE, - ThreadLocalRandom.current().nextFloat() * RANGE, - ThreadLocalRandom.current().nextFloat() * ENTITY_SIZE, - ThreadLocalRandom.current().nextFloat() * ENTITY_SIZE, - ThreadLocalRandom.current().nextFloat() * ENTITY_SIZE + ThreadLocalRandom.current().nextDouble() * RANGE, + ThreadLocalRandom.current().nextDouble() * RANGE, + ThreadLocalRandom.current().nextDouble() * RANGE, + ThreadLocalRandom.current().nextDouble() * ENTITY_SIZE, + ThreadLocalRandom.current().nextDouble() * ENTITY_SIZE, + ThreadLocalRandom.current().nextDouble() * ENTITY_SIZE ); } - public AABBf createRandomAABB() { - var x = ThreadLocalRandom.current().nextFloat() * RANGE; - var y = ThreadLocalRandom.current().nextFloat() * RANGE; - var z = ThreadLocalRandom.current().nextFloat() * RANGE; - var width = ThreadLocalRandom.current().nextFloat() * ENTITY_SIZE; - var height = ThreadLocalRandom.current().nextFloat() * ENTITY_SIZE; - var length = ThreadLocalRandom.current().nextFloat() * ENTITY_SIZE; - return new AABBf( + public AABBd createRandomAABB() { + var x = ThreadLocalRandom.current().nextDouble() * RANGE; + var y = ThreadLocalRandom.current().nextDouble() * RANGE; + var z = ThreadLocalRandom.current().nextDouble() * RANGE; + var width = ThreadLocalRandom.current().nextDouble() * ENTITY_SIZE; + var height = ThreadLocalRandom.current().nextDouble() * ENTITY_SIZE; + var length = ThreadLocalRandom.current().nextDouble() * ENTITY_SIZE; + return new AABBd( x, y, z, x + width, y + height, z + length ); @@ -99,7 +99,7 @@ public void testAABBTreeUpdate() { } } - public void forEachDetect(AABBf aabb, List result) { + public void forEachDetect(AABBd aabb, List result) { for (var entityAABB : testEntityAABBs) { if (entityAABB.intersectsAABB(aabb)) result.add(entityAABB); diff --git a/server/src/main/java/org/allaymc/server/AllayServer.java b/server/src/main/java/org/allaymc/server/AllayServer.java index 79aab21cc..8f9f0224d 100644 --- a/server/src/main/java/org/allaymc/server/AllayServer.java +++ b/server/src/main/java/org/allaymc/server/AllayServer.java @@ -22,8 +22,8 @@ import org.allaymc.api.i18n.MayContainTrKey; import org.allaymc.api.i18n.TrContainer; import org.allaymc.api.i18n.TrKeys; -import org.allaymc.api.math.location.Location3f; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3d; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.network.ClientStatus; import org.allaymc.api.network.NetworkInterface; import org.allaymc.api.permission.DefaultPermissions; @@ -530,8 +530,8 @@ public CommandOriginData getCommandOriginData() { } @Override - public Location3fc getCmdExecuteLocation() { - return new Location3f(0, 0, 0, getWorldPool().getDefaultWorld().getOverWorld()); + public Location3dc getCmdExecuteLocation() { + return new Location3d(0, 0, 0, getWorldPool().getDefaultWorld().getOverWorld()); } @Override diff --git a/server/src/main/java/org/allaymc/server/block/component/BlockBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/block/component/BlockBaseComponentImpl.java index 8a9a72f72..44aaa8e20 100644 --- a/server/src/main/java/org/allaymc/server/block/component/BlockBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/block/component/BlockBaseComponentImpl.java @@ -14,6 +14,7 @@ import org.allaymc.api.entity.interfaces.EntityPlayer; import org.allaymc.api.item.ItemStack; import org.allaymc.api.item.enchantment.type.EnchantmentTypes; +import org.allaymc.api.math.MathUtils; import org.allaymc.api.utils.Identifier; import org.allaymc.api.utils.Utils; import org.allaymc.api.world.Dimension; @@ -22,7 +23,6 @@ import org.allaymc.server.component.annotation.Manager; import org.allaymc.server.loottable.context.BreakBlockContext; import org.cloudburstmc.protocol.bedrock.data.GameType; -import org.joml.Vector3f; import org.joml.Vector3ic; import java.util.Set; @@ -122,7 +122,7 @@ public void afterNeighborLayerReplace(BlockStateWithPos currentBlockState, Block public void onBreak(BlockStateWithPos blockState, ItemStack usedItem, Entity entity) { if (!isDroppable(blockState, usedItem, entity)) return; - var dropPos = new Vector3f(blockState.pos()).add(0.5f, 0.5f, 0.5f); + var dropPos = MathUtils.center(blockState.pos()); var dimension = blockState.pos().dimension(); if (usedItem != null && usedItem.hasEnchantment(EnchantmentTypes.SILK_TOUCH)) { // Silk Touch, directly drop the block itself diff --git a/server/src/main/java/org/allaymc/server/block/component/BlockJukeboxBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/block/component/BlockJukeboxBaseComponentImpl.java index e9898ec03..f580b02d2 100644 --- a/server/src/main/java/org/allaymc/server/block/component/BlockJukeboxBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/block/component/BlockJukeboxBaseComponentImpl.java @@ -6,7 +6,7 @@ import org.allaymc.api.block.type.BlockType; import org.allaymc.api.blockentity.interfaces.BlockEntityJukebox; import org.allaymc.api.item.ItemStack; -import org.allaymc.api.math.position.Position3f; +import org.allaymc.api.math.position.Position3d; import org.allaymc.api.math.position.Position3i; import org.allaymc.api.world.Dimension; import org.allaymc.server.component.annotation.Dependency; @@ -36,7 +36,7 @@ public boolean onInteract(ItemStack itemStack, Dimension dimension, PlayerIntera jukebox.setMusicDiscItem(null); jukebox.stop(); - dimension.dropItem(musicDisc, new Position3f(blockEntity.getPosition()).add(0, 1, 0)); + dimension.dropItem(musicDisc, new Position3d(blockEntity.getPosition()).add(0, 1, 0)); } else { jukebox.setMusicDiscItem(player.getItemInHand()); player.clearItemInHand(); diff --git a/server/src/main/java/org/allaymc/server/block/component/BlockLiquidBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/block/component/BlockLiquidBaseComponentImpl.java index df6c8c138..abd5731da 100644 --- a/server/src/main/java/org/allaymc/server/block/component/BlockLiquidBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/block/component/BlockLiquidBaseComponentImpl.java @@ -16,7 +16,7 @@ import org.allaymc.api.math.MathUtils; import org.allaymc.api.math.position.Position3i; import org.allaymc.api.world.Dimension; -import org.joml.Vector3f; +import org.joml.Vector3d; import org.joml.Vector3i; import org.joml.Vector3ic; @@ -104,7 +104,7 @@ public void onScheduledUpdate(BlockStateWithPos blockStateWithPos) { /** * This method is used in {@link org.allaymc.server.world.service.AllayEntityPhysicsService} */ - public Vector3f calculateFlowVector(Dimension dimension, int x, int y, int z, BlockState current) { + public Vector3d calculateFlowVector(Dimension dimension, int x, int y, int z, BlockState current) { // TODO: cache the flow vector for better performance var vx = 0; var vy = 0; @@ -143,7 +143,7 @@ public Vector3f calculateFlowVector(Dimension dimension, int x, int y, int z, Bl vz += offset.z() * realDecay; } - var vector = new Vector3f(vx, vy, vz); + var vector = new Vector3d(vx, vy, vz); if (isFalling(current)) { for (var face : BlockFace.getHorizontalBlockFaces()) { diff --git a/server/src/main/java/org/allaymc/server/block/component/BlockTntBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/block/component/BlockTntBaseComponentImpl.java index 1d86d04df..9823c93eb 100644 --- a/server/src/main/java/org/allaymc/server/block/component/BlockTntBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/block/component/BlockTntBaseComponentImpl.java @@ -15,7 +15,7 @@ import org.allaymc.api.world.Dimension; import org.allaymc.server.entity.component.EntityTntBaseComponentImpl; import org.cloudburstmc.nbt.NbtMap; -import org.joml.Vector3f; +import org.joml.Vector3d; import java.util.concurrent.ThreadLocalRandom; @@ -54,11 +54,11 @@ public void prime(BlockStateWithPos blockStateWithPos, int fuse) { var pos = blockStateWithPos.pos(); dimension.setBlockState(pos, BlockTypes.AIR.getDefaultState()); var angle = ThreadLocalRandom.current().nextFloat() * Math.PI * 2; - var motion = new Vector3f((float) (-Math.sin(angle) * 0.02f), 0.2f, (float) (-Math.cos(angle) * 0.02f)); + var motion = new Vector3d(-Math.sin(angle) * 0.02, 0.2, -Math.cos(angle) * 0.02); var entity = EntityTypes.TNT.createEntity( EntityInitInfo.builder() .dimension(dimension) - .pos(pos.x() + 0.5f, pos.y(), pos.z() + 0.5f) + .pos(pos.x() + 0.5, pos.y(), pos.z() + 0.5) .motion(motion) .nbt(NbtMap.builder().putShort(EntityTntBaseComponentImpl.TAG_FUSE, (short) fuse).build()) .build() diff --git a/server/src/main/java/org/allaymc/server/block/component/BlockWetSpongeBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/block/component/BlockWetSpongeBaseComponentImpl.java index da1794441..8b1b80519 100644 --- a/server/src/main/java/org/allaymc/server/block/component/BlockWetSpongeBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/block/component/BlockWetSpongeBaseComponentImpl.java @@ -10,7 +10,6 @@ import org.allaymc.api.world.DimensionInfo; import org.cloudburstmc.protocol.bedrock.data.ParticleType; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; -import org.joml.Vector3f; /** * @author daoge_cmd @@ -27,7 +26,7 @@ public void afterPlaced(BlockStateWithPos oldBlockState, BlockState newBlockStat if (oldBlockState.dimension().getDimensionInfo() == DimensionInfo.NETHER) { oldBlockState.dimension().setBlockState(oldBlockState.pos(), BlockTypes.SPONGE.getDefaultState()); oldBlockState.dimension().addLevelSoundEvent(MathUtils.center(oldBlockState.pos()), SoundEvent.FIZZ); - oldBlockState.dimension().addParticle(new Vector3f(oldBlockState.pos()).add(0.5f, 1.0f, 0.5f), ParticleType.EXPLODE); + oldBlockState.dimension().addParticle(MathUtils.center(oldBlockState.pos()), ParticleType.EXPLODE); } } } diff --git a/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityContainerHolderComponentImpl.java b/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityContainerHolderComponentImpl.java index 2e6861a4d..1cd19e9d3 100644 --- a/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityContainerHolderComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityContainerHolderComponentImpl.java @@ -17,7 +17,7 @@ import org.allaymc.server.component.annotation.Dependency; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; -import org.joml.Vector3f; +import org.joml.Vector3d; import java.util.concurrent.ThreadLocalRandom; import java.util.function.Consumer; @@ -98,10 +98,10 @@ protected void onReplace(CBlockOnReplaceEvent event) { container.removeAllViewers(); for (var itemStack : container.getItemStacks()) { if (itemStack == ItemAirStack.AIR_STACK) continue; - dimension.dropItem(itemStack, new Vector3f( - pos.x() + rand.nextFloat(0.5f) + 0.25f, - pos.y() + rand.nextFloat(0.5f) + 0.25f, - pos.z() + rand.nextFloat(0.5f) + 0.25f + dimension.dropItem(itemStack, new Vector3d( + pos.x() + rand.nextDouble(0.5) + 0.25, + pos.y() + rand.nextDouble(0.5) + 0.25, + pos.z() + rand.nextDouble(0.5) + 0.25 )); } diff --git a/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityJukeboxBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityJukeboxBaseComponentImpl.java index 9eefb7121..56f57ee35 100644 --- a/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityJukeboxBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/blockentity/component/BlockEntityJukeboxBaseComponentImpl.java @@ -10,7 +10,7 @@ import org.allaymc.server.block.component.event.CBlockOnReplaceEvent; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; -import org.joml.Vector3f; +import org.joml.Vector3d; import java.util.concurrent.ThreadLocalRandom; @@ -48,10 +48,10 @@ public void onReplace(CBlockOnReplaceEvent event) { var rand = ThreadLocalRandom.current(); if (this.musicDiscItem != null) { - dimension.dropItem(this.musicDiscItem, new Vector3f( - pos.x() + rand.nextFloat(0.5f) + 0.25f, - pos.y() + rand.nextFloat(0.5f) + 0.25f, - pos.z() + rand.nextFloat(0.5f) + 0.25f + dimension.dropItem(this.musicDiscItem, new Vector3d( + pos.x() + rand.nextDouble(0.5) + 0.25, + pos.y() + rand.nextDouble(0.5) + 0.25, + pos.z() + rand.nextDouble(0.5) + 0.25 )); this.musicDiscItem = null; this.stop(); diff --git a/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityFurnaceBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityFurnaceBaseComponentImpl.java index 9ca04708c..b1226768a 100644 --- a/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityFurnaceBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/blockentity/component/furnace/BlockEntityFurnaceBaseComponentImpl.java @@ -25,7 +25,7 @@ import org.allaymc.server.component.annotation.OnInitFinish; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.packet.ContainerSetDataPacket; -import org.joml.Vector3f; +import org.joml.Vector3d; import java.util.concurrent.ThreadLocalRandom; @@ -235,12 +235,12 @@ protected boolean checkIngredient(ItemStack ingredient) { protected void tryDropStoredXP() { if (storedXP < 1) return; - var pos = new Vector3f( - position.x() + 0.5f, - position.y() + 1.5f, - position.z() + 0.5f + var pos = new Vector3d( + position.x() + 0.5, + position.y() + 1.5, + position.z() + 0.5 ); - getDimension().dropXpOrb(pos, (int) storedXP); + getDimension().dropXpOrb(pos, storedXP); storedXP = 0; } diff --git a/server/src/main/java/org/allaymc/server/command/ProxyCommandSender.java b/server/src/main/java/org/allaymc/server/command/ProxyCommandSender.java index 4ee2e9d1e..236c341ed 100644 --- a/server/src/main/java/org/allaymc/server/command/ProxyCommandSender.java +++ b/server/src/main/java/org/allaymc/server/command/ProxyCommandSender.java @@ -4,7 +4,7 @@ import lombok.Setter; import lombok.experimental.Delegate; import org.allaymc.api.command.CommandSender; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; /** * @author daoge_cmd @@ -15,14 +15,14 @@ public class ProxyCommandSender implements CommandSender { @Getter protected CommandSender origin; @Setter - protected Location3fc cmdExecuteLocation; + protected Location3dc cmdExecuteLocation; public ProxyCommandSender(CommandSender origin) { this.origin = origin; } @Override - public Location3fc getCmdExecuteLocation() { + public Location3dc getCmdExecuteLocation() { if (cmdExecuteLocation != null) { return cmdExecuteLocation; } diff --git a/server/src/main/java/org/allaymc/server/command/defaults/ExecuteCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/ExecuteCommand.java index f323ba0b0..697881096 100644 --- a/server/src/main/java/org/allaymc/server/command/defaults/ExecuteCommand.java +++ b/server/src/main/java/org/allaymc/server/command/defaults/ExecuteCommand.java @@ -5,13 +5,13 @@ import org.allaymc.api.command.tree.CommandTree; import org.allaymc.api.entity.Entity; import org.allaymc.api.i18n.TrKeys; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.api.registry.Registries; import org.allaymc.api.server.Server; import org.allaymc.api.world.DimensionInfo; import org.allaymc.server.command.ProxyCommandSender; -import org.joml.Vector3f; -import org.joml.Vector3fc; +import org.joml.Vector3d; +import org.joml.Vector3dc; import java.util.List; @@ -58,8 +58,8 @@ public void prepareCommandTree(CommandTree tree) { List remain = context.getResult(2); var proxySender = new ProxyCommandSender(context.getSender()); - var newLoc = new Location3f(context.getSender().getCmdExecuteLocation()); - var newLocFloor = newLoc.floor(new Vector3f()); + var newLoc = new Location3d(context.getSender().getCmdExecuteLocation()); + var newLocFloor = newLoc.floor(new Vector3d()); if (axes.contains("x")) { newLoc.x = newLocFloor.x; } @@ -102,12 +102,12 @@ public void prepareCommandTree(CommandTree tree) { .pos("pos") .remain("subcommand") .exec(context -> { - Vector3fc pos = context.getResult(1); + Vector3dc pos = context.getResult(1); List remain = context.getResult(2); var sender = context.getSender(); var proxySender = new ProxyCommandSender(sender); var loc = sender.getCmdExecuteLocation(); - var newLoc = new Location3f(loc); + var newLoc = new Location3d(loc); newLoc.set(pos); proxySender.setCmdExecuteLocation(newLoc); var result = tree.parse(proxySender, remain.toArray(String[]::new)); @@ -139,7 +139,7 @@ public void prepareCommandTree(CommandTree tree) { var sender = context.getSender(); var proxySender = new ProxyCommandSender(sender); var loc = sender.getCmdExecuteLocation(); - var newLoc = new Location3f(loc); + var newLoc = new Location3d(loc); newLoc.setDimension(dim); proxySender.setCmdExecuteLocation(newLoc); var result = tree.parse(proxySender, remain.toArray(String[]::new)); diff --git a/server/src/main/java/org/allaymc/server/command/defaults/FillCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/FillCommand.java index f3805b8cf..753ae9ee0 100644 --- a/server/src/main/java/org/allaymc/server/command/defaults/FillCommand.java +++ b/server/src/main/java/org/allaymc/server/command/defaults/FillCommand.java @@ -5,7 +5,7 @@ import org.allaymc.api.command.SimpleCommand; import org.allaymc.api.command.tree.CommandTree; import org.allaymc.api.i18n.TrKeys; -import org.joml.Vector3f; +import org.joml.Vector3d; import java.util.List; @@ -26,8 +26,8 @@ public void prepareCommandTree(CommandTree tree) { .blockPropertyValues("blockPropertyValues") .optional() .exec(context -> { - var from = context.getResult(0).floor(); - var to = context.getResult(1).ceil(); + var from = context.getResult(0).floor(); + var to = context.getResult(1).ceil(); var dim = context.getSender().getCmdExecuteLocation().dimension(); if (!dim.isInWorld(from.x(), from.y(), from.z()) || !dim.isInWorld(to.x(), to.y(), to.z())) { context.addError("%" + TrKeys.M_COMMANDS_FILL_OUTOFWORLD); diff --git a/server/src/main/java/org/allaymc/server/command/defaults/GameTestCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/GameTestCommand.java index 36a0cdb7b..09954e9e4 100644 --- a/server/src/main/java/org/allaymc/server/command/defaults/GameTestCommand.java +++ b/server/src/main/java/org/allaymc/server/command/defaults/GameTestCommand.java @@ -25,8 +25,8 @@ import org.allaymc.server.block.type.BlockLootTable; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.data.command.CommandData; -import org.joml.Vector3f; -import org.joml.Vector3fc; +import org.joml.Vector3d; +import org.joml.Vector3dc; import java.io.IOException; import java.io.InputStreamReader; @@ -115,7 +115,7 @@ public void prepareCommandTree(CommandTree tree) { } var loc = player.getLocation(); - var floorLoc = loc.floor(new Vector3f()); + var floorLoc = loc.floor(new Vector3d()); loc.dimension().setBlockState((int) floorLoc.x(), (int) floorLoc.y(), (int) floorLoc.z(), blockType.getDefaultState()); return context.success(); }, SenderType.PLAYER) @@ -214,7 +214,7 @@ public void prepareCommandTree(CommandTree tree) { .intNum("xp") .exec((context, player) -> { player.getDimension().splitAndDropXpOrb( - player.getLocation().add(0, -1, 0, new Vector3f()), + player.getLocation().add(0, -1, 0, new Vector3d()), context.getResult(1) ); return context.success(); @@ -229,8 +229,8 @@ public void prepareCommandTree(CommandTree tree) { .root() .key("printblockunder") .exec((context, player) -> { - player.sendText(player.getDimension().getBlockState(player.getLocation().sub(0, 1, 0, new Vector3f()), 0).toString()); - player.sendText(player.getDimension().getBlockState(player.getLocation().sub(0, 1, 0, new Vector3f()), 1).toString()); + player.sendText(player.getDimension().getBlockState(player.getLocation().sub(0, 1, 0, new Vector3d()), 0).toString()); + player.sendText(player.getDimension().getBlockState(player.getLocation().sub(0, 1, 0, new Vector3d()), 1).toString()); return context.success(); }, SenderType.PLAYER) .root() @@ -241,7 +241,7 @@ public void prepareCommandTree(CommandTree tree) { .intNum("c") .blockType("block") .exec((context, player) -> { - var pos = MathUtils.floor((Vector3fc) context.getResult(1)); + var pos = MathUtils.floor((Vector3dc) context.getResult(1)); int a = context.getResult(2); int b = context.getResult(3); int c = context.getResult(4); @@ -278,7 +278,7 @@ public void prepareCommandTree(CommandTree tree) { .root() .key("getheight") .exec((context, player) -> { - var floorLoc = player.getLocation().floor(new Vector3f()); + var floorLoc = player.getLocation().floor(new Vector3d()); player.sendText("Height is " + player.getDimension().getHeight((int) floorLoc.x, (int) floorLoc.z)); return context.success(); }, SenderType.PLAYER) @@ -286,7 +286,7 @@ public void prepareCommandTree(CommandTree tree) { .key("getlightdata") .pos("pos") .exec((context, player) -> { - var floorLoc = ((Vector3f) context.getResult(1)).floor(); + var floorLoc = ((Vector3d) context.getResult(1)).floor(); int x = (int) floorLoc.x; int y = (int) floorLoc.y; int z = (int) floorLoc.z; @@ -310,9 +310,9 @@ public void prepareCommandTree(CommandTree tree) { .bool("spawnfire").optional() .exec((context, player) -> { var explosion = new Explosion(context.getResult(2), context.getResult(3)); - Vector3f pos = context.getResult(1); + Vector3d pos = context.getResult(1); if (pos == null) { - pos = new Vector3f(context.getSender().getCmdExecuteLocation()); + pos = new Vector3d(context.getSender().getCmdExecuteLocation()); } explosion.explode(player.getDimension(), pos); return context.success(); diff --git a/server/src/main/java/org/allaymc/server/command/defaults/SetBlockCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/SetBlockCommand.java index e48b9d5cc..0ff67050e 100644 --- a/server/src/main/java/org/allaymc/server/command/defaults/SetBlockCommand.java +++ b/server/src/main/java/org/allaymc/server/command/defaults/SetBlockCommand.java @@ -6,7 +6,7 @@ import org.allaymc.api.command.SimpleCommand; import org.allaymc.api.command.tree.CommandTree; import org.allaymc.api.i18n.TrKeys; -import org.joml.Vector3f; +import org.joml.Vector3d; import java.util.List; @@ -26,7 +26,7 @@ public void prepareCommandTree(CommandTree tree) { .blockPropertyValues("blockPropertyValues") .optional() .exec((context, entity) -> { - Vector3f pos = context.getResult(0); + Vector3d pos = context.getResult(0); BlockType blockType = context.getResult(1); List> blockPropertyValues = context.getResult(2); diff --git a/server/src/main/java/org/allaymc/server/command/defaults/SetWorldSpawnCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/SetWorldSpawnCommand.java index 86ac2393d..66bff335c 100644 --- a/server/src/main/java/org/allaymc/server/command/defaults/SetWorldSpawnCommand.java +++ b/server/src/main/java/org/allaymc/server/command/defaults/SetWorldSpawnCommand.java @@ -5,7 +5,7 @@ import org.allaymc.api.command.tree.CommandTree; import org.allaymc.api.i18n.TrKeys; import org.allaymc.api.world.DimensionInfo; -import org.joml.Vector3f; +import org.joml.Vector3d; import org.joml.Vector3i; /** @@ -25,7 +25,7 @@ public void prepareCommandTree(CommandTree tree) { context.addError("%" + TrKeys.M_COMMANDS_SETWORLDSPAWN_WRONGDIMENSION); return context.fail(); } - Vector3f pos = context.getResult(0); + Vector3d pos = context.getResult(0); var newSpawnPoint = new Vector3i((int) pos.x(), (int) pos.y(), (int) pos.z()); entity.getWorld().getWorldData().setSpawnPoint(newSpawnPoint); context.addOutput(TrKeys.M_COMMANDS_SETWORLDSPAWN_SUCCESS, newSpawnPoint.x(), newSpawnPoint.y(), newSpawnPoint.z()); diff --git a/server/src/main/java/org/allaymc/server/command/defaults/SpawnPointCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/SpawnPointCommand.java index 644d37da2..fc65793d4 100644 --- a/server/src/main/java/org/allaymc/server/command/defaults/SpawnPointCommand.java +++ b/server/src/main/java/org/allaymc/server/command/defaults/SpawnPointCommand.java @@ -5,10 +5,10 @@ import org.allaymc.api.command.tree.CommandTree; import org.allaymc.api.entity.interfaces.EntityPlayer; import org.allaymc.api.i18n.TrKeys; -import org.allaymc.api.math.location.Location3i; import org.allaymc.api.math.MathUtils; +import org.allaymc.api.math.location.Location3i; import org.allaymc.api.world.DimensionInfo; -import org.joml.Vector3f; +import org.joml.Vector3d; import java.util.List; @@ -34,7 +34,7 @@ public void prepareCommandTree(CommandTree tree) { } List players = context.getResult(0); - Vector3f pos = context.getResult(1); + Vector3d pos = context.getResult(1); for (EntityPlayer player : players) { player.setSpawnPoint(new Location3i( diff --git a/server/src/main/java/org/allaymc/server/command/defaults/StructureCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/StructureCommand.java index c5f4ce158..a3c0590c1 100644 --- a/server/src/main/java/org/allaymc/server/command/defaults/StructureCommand.java +++ b/server/src/main/java/org/allaymc/server/command/defaults/StructureCommand.java @@ -6,7 +6,7 @@ import org.allaymc.api.utils.Structure; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtUtils; -import org.joml.Vector3f; +import org.joml.Vector3d; import java.io.IOException; import java.nio.file.Files; @@ -36,8 +36,8 @@ public void prepareCommandTree(CommandTree tree) { .pos("end") .exec((context, player) -> { String fileName = context.getResult(1); - Vector3f start = ((Vector3f) context.getResult(2)).floor(); - Vector3f end = ((Vector3f) context.getResult(3)).floor(); + Vector3d start = ((Vector3d) context.getResult(2)).floor(); + Vector3d end = ((Vector3d) context.getResult(3)).floor(); var sizeX = (int) (end.x - start.x + 1); var sizeY = (int) (end.y - start.y + 1); var sizeZ = (int) (end.z - start.z + 1); @@ -78,7 +78,7 @@ public void prepareCommandTree(CommandTree tree) { .pos("pos") .exec((context, player) -> { String fileName = context.getResult(1); - Vector3f pos = ((Vector3f) context.getResult(2)).floor(); + Vector3d pos = ((Vector3d) context.getResult(2)).floor(); NbtMap nbt; var filePath = STRUCTURE_DIR.resolve(fileName + STRUCTURE_FILE_EXT); diff --git a/server/src/main/java/org/allaymc/server/command/defaults/SummonCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/SummonCommand.java index 85157e73d..9ffa70bb1 100644 --- a/server/src/main/java/org/allaymc/server/command/defaults/SummonCommand.java +++ b/server/src/main/java/org/allaymc/server/command/defaults/SummonCommand.java @@ -7,8 +7,8 @@ import org.allaymc.api.entity.type.EntityType; import org.allaymc.api.entity.type.EntityTypes; import org.allaymc.api.i18n.TrKeys; -import org.joml.Vector3f; -import org.joml.Vector3fc; +import org.joml.Vector3d; +import org.joml.Vector3dc; /** * @author daoge_cmd @@ -34,11 +34,11 @@ public void prepareCommandTree(CommandTree tree) { context.addError("%" + TrKeys.M_COMMANDS_SUMMON_FAILED); return context.fail(); } - Vector3fc pos = context.getResult(1); + Vector3dc pos = context.getResult(1); if (pos == null) { pos = sender.getCmdExecuteLocation(); } - var floorPos = pos.floor(new Vector3f()); + var floorPos = pos.floor(new Vector3d()); if (dim.getChunkService().getChunkByDimensionPos((int) floorPos.x(), (int) floorPos.z()) == null) { context.addError("%" + TrKeys.M_COMMANDS_SUMMON_OUTOFWORLD); return context.fail(); diff --git a/server/src/main/java/org/allaymc/server/command/defaults/TeleportCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/TeleportCommand.java index e14c6a25a..4dbd28f2d 100644 --- a/server/src/main/java/org/allaymc/server/command/defaults/TeleportCommand.java +++ b/server/src/main/java/org/allaymc/server/command/defaults/TeleportCommand.java @@ -5,8 +5,8 @@ import org.allaymc.api.command.tree.CommandTree; import org.allaymc.api.entity.Entity; import org.allaymc.api.i18n.TrKeys; -import org.allaymc.api.math.location.Location3f; -import org.joml.Vector3f; +import org.allaymc.api.math.location.Location3d; +import org.joml.Vector3d; import java.util.List; @@ -23,18 +23,18 @@ public TeleportCommand() { public void prepareCommandTree(CommandTree tree) { tree.getRoot() .pos("pos") - .exec((context,sender) -> { - Vector3f pos = context.getResult(0); - var loc = new Location3f(pos.x, pos.y, pos.z, context.getSender().getCmdExecuteLocation().dimension()); + .exec((context, sender) -> { + Vector3d pos = context.getResult(0); + var loc = new Location3d(pos.x, pos.y, pos.z, context.getSender().getCmdExecuteLocation().dimension()); sender.teleport(loc); context.addOutput(TrKeys.M_COMMANDS_TP_SUCCESS_COORDINATES, sender.getDisplayName(), pos.x, pos.y, pos.z); return context.success(); - },SenderType.ENTITY) + }, SenderType.ENTITY) .root() .target("destination") - .exec((context,sender) -> { + .exec((context, sender) -> { List destination = context.getResult(0); if (destination.isEmpty()) { @@ -53,14 +53,14 @@ public void prepareCommandTree(CommandTree tree) { context.addOutput(TrKeys.M_COMMANDS_TP_SUCCESS, sender.getDisplayName(), destEntity.getDisplayName()); return context.success(); - },SenderType.ENTITY) + }, SenderType.ENTITY) .root() .target("victims") .pos("pos") .exec(context -> { List victims = context.getResult(0); - Vector3f pos = context.getResult(1); - var loc = new Location3f(pos.x, pos.y, pos.z, context.getSender().getCmdExecuteLocation().dimension()); + Vector3d pos = context.getResult(1); + var loc = new Location3d(pos.x, pos.y, pos.z, context.getSender().getCmdExecuteLocation().dimension()); for (Entity victim : victims) { victim.teleport(loc); context.addOutput(TrKeys.M_COMMANDS_TP_SUCCESS_COORDINATES, victim.getDisplayName(), pos.x, pos.y, pos.z); diff --git a/server/src/main/java/org/allaymc/server/command/defaults/WorldCommand.java b/server/src/main/java/org/allaymc/server/command/defaults/WorldCommand.java index 319de71ba..a2a1e01d0 100644 --- a/server/src/main/java/org/allaymc/server/command/defaults/WorldCommand.java +++ b/server/src/main/java/org/allaymc/server/command/defaults/WorldCommand.java @@ -6,7 +6,7 @@ import org.allaymc.api.form.Forms; import org.allaymc.api.i18n.I18n; import org.allaymc.api.i18n.TrKeys; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.api.registry.Registries; import org.allaymc.api.server.Server; import org.allaymc.api.utils.TextFormat; @@ -66,7 +66,7 @@ public void prepareCommandTree(CommandTree tree) { } var dim = world.getDimension(dimInfo.dimensionId()); - entity.teleport(new Location3f(0, 64, 0, dim)); + entity.teleport(new Location3d(0, 64, 0, dim)); context.addOutput(TrKeys.A_COMMAND_WORLD_TP_SUCCESS, worldName, dimName); return context.success(); }, SenderType.ENTITY) diff --git a/server/src/main/java/org/allaymc/server/command/selector/AllayEntitySelectorAPI.java b/server/src/main/java/org/allaymc/server/command/selector/AllayEntitySelectorAPI.java index e9cb2b393..e867176d6 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/AllayEntitySelectorAPI.java +++ b/server/src/main/java/org/allaymc/server/command/selector/AllayEntitySelectorAPI.java @@ -11,7 +11,7 @@ import org.allaymc.api.command.selector.args.SelectorArgument; import org.allaymc.api.entity.Entity; import org.allaymc.api.entity.interfaces.EntityPlayer; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.api.utils.AllayStringUtils; import org.allaymc.server.command.selector.args.*; @@ -92,7 +92,7 @@ public List matchEntities(CommandSender sender, String token) throws Sel } // Get the cloned location information of the executor - var senderLocation = new Location3f(sender.getCmdExecuteLocation()); + var senderLocation = new Location3d(sender.getCmdExecuteLocation()); // Get the selector type var selectorType = parseSelectorType(matcher.group(1)); // Determine the entity detection range according to the selector type first @@ -163,9 +163,9 @@ else if (arg.getDefaultValue(arguments, selectorType, sender) != null) // Select the closest player if (selectorType == NEAREST_PLAYER && entities.size() != 1) { Entity nearest = null; - var min = Float.MAX_VALUE; + var min = Double.MAX_VALUE; for (var entity : entities) { - var distanceSquared = 0f; + var distanceSquared = 0.0; if ((distanceSquared = senderLocation.distanceSquared(entity.getLocation())) < min) { min = distanceSquared; nearest = entity; diff --git a/server/src/main/java/org/allaymc/server/command/selector/ParseUtils.java b/server/src/main/java/org/allaymc/server/command/selector/ParseUtils.java index 95aa57578..32dd27cbe 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/ParseUtils.java +++ b/server/src/main/java/org/allaymc/server/command/selector/ParseUtils.java @@ -50,6 +50,26 @@ public static float parseOffsetFloat(String value, float base) throws SelectorSy } } + /** + * Parse the offset double value + * + * @param value Text + * @param base Base value + * + * @return Offset value + */ + public static double parseOffsetDouble(String value, double base) throws SelectorSyntaxException { + try { + if (value.startsWith("~")) { + return value.length() != 1 ? base + Double.parseDouble(value.substring(1)) : base; + } else { + return Double.parseDouble(value); + } + } catch (NumberFormatException e) { + throw new SelectorSyntaxException("Error parsing target selector", e); + } + } + /** * Check if the parameter is reversed * diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/C.java b/server/src/main/java/org/allaymc/server/command/selector/args/C.java index 517782068..1dbec610f 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/C.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/C.java @@ -5,7 +5,7 @@ import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.command.selector.args.CachedFilterSelectorArgument; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.server.command.selector.ParseUtils; import java.util.Collections; @@ -18,7 +18,7 @@ */ public class C extends CachedFilterSelectorArgument { @Override - public Function, List> cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException { + public Function, List> cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/DX.java b/server/src/main/java/org/allaymc/server/command/selector/args/DX.java index 78b72f8e1..974d0d4ec 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/DX.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/DX.java @@ -4,7 +4,7 @@ import org.allaymc.api.command.selector.SelectorSyntaxException; import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -14,7 +14,7 @@ */ public class DX extends ScopeArgument { @Override - public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3f basePos, String... arguments) throws SelectorSyntaxException { + public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3d basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/DY.java b/server/src/main/java/org/allaymc/server/command/selector/args/DY.java index dbb99a32c..e03b4c04d 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/DY.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/DY.java @@ -4,7 +4,7 @@ import org.allaymc.api.command.selector.SelectorSyntaxException; import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -14,7 +14,7 @@ */ public class DY extends ScopeArgument { @Override - public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3f basePos, String... arguments) throws SelectorSyntaxException { + public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3d basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/DZ.java b/server/src/main/java/org/allaymc/server/command/selector/args/DZ.java index e480c35e2..d710108d2 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/DZ.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/DZ.java @@ -4,7 +4,7 @@ import org.allaymc.api.command.selector.SelectorSyntaxException; import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -14,7 +14,7 @@ */ public class DZ extends ScopeArgument { @Override - public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3f basePos, String... arguments) throws SelectorSyntaxException { + public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3d basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/L.java b/server/src/main/java/org/allaymc/server/command/selector/args/L.java index e4d9f026d..8153051f7 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/L.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/L.java @@ -6,7 +6,7 @@ import org.allaymc.api.command.selector.args.CachedSimpleSelectorArgument; import org.allaymc.api.entity.Entity; import org.allaymc.api.entity.interfaces.EntityPlayer; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -16,7 +16,7 @@ */ public class L extends CachedSimpleSelectorArgument { @Override - protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException { + protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/LM.java b/server/src/main/java/org/allaymc/server/command/selector/args/LM.java index df6e05336..2f273d68c 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/LM.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/LM.java @@ -6,7 +6,7 @@ import org.allaymc.api.command.selector.args.CachedSimpleSelectorArgument; import org.allaymc.api.entity.Entity; import org.allaymc.api.entity.interfaces.EntityPlayer; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -16,7 +16,7 @@ */ public class LM extends CachedSimpleSelectorArgument { @Override - protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException { + protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/M.java b/server/src/main/java/org/allaymc/server/command/selector/args/M.java index f22879552..6f09badd8 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/M.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/M.java @@ -6,7 +6,7 @@ import org.allaymc.api.command.selector.args.CachedSimpleSelectorArgument; import org.allaymc.api.entity.Entity; import org.allaymc.api.entity.interfaces.EntityPlayer; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -16,7 +16,7 @@ */ public class M extends CachedSimpleSelectorArgument { @Override - protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException { + protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); var gmStr = arguments[0]; diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/Name.java b/server/src/main/java/org/allaymc/server/command/selector/args/Name.java index 856180018..0660bc349 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/Name.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/Name.java @@ -4,7 +4,7 @@ import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.command.selector.args.CachedSimpleSelectorArgument; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.server.command.selector.ParseUtils; import java.util.ArrayList; @@ -15,7 +15,7 @@ */ public class Name extends CachedSimpleSelectorArgument { @Override - protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) { + protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) { var have = new ArrayList(); var dontHave = new ArrayList(); for (var name : arguments) { diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/R.java b/server/src/main/java/org/allaymc/server/command/selector/args/R.java index cc0579b41..91ab26e11 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/R.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/R.java @@ -5,7 +5,7 @@ import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.command.selector.args.SelectorArgument; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -15,7 +15,7 @@ */ public class R implements SelectorArgument { @Override - public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3f basePos, String... arguments) throws SelectorSyntaxException { + public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3d basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/RM.java b/server/src/main/java/org/allaymc/server/command/selector/args/RM.java index cc85bb1f3..915718506 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/RM.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/RM.java @@ -5,7 +5,7 @@ import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.command.selector.args.SelectorArgument; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -15,7 +15,7 @@ */ public class RM implements SelectorArgument { @Override - public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3f basePos, String... arguments) throws SelectorSyntaxException { + public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3d basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/RX.java b/server/src/main/java/org/allaymc/server/command/selector/args/RX.java index 57eb5e40c..7b3f5be3a 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/RX.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/RX.java @@ -5,7 +5,7 @@ import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.command.selector.args.CachedSimpleSelectorArgument; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -15,7 +15,7 @@ */ public class RX extends CachedSimpleSelectorArgument { @Override - protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException { + protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/RXM.java b/server/src/main/java/org/allaymc/server/command/selector/args/RXM.java index 1ca8f68bf..a088aad51 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/RXM.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/RXM.java @@ -5,7 +5,7 @@ import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.command.selector.args.CachedSimpleSelectorArgument; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -15,7 +15,7 @@ */ public class RXM extends CachedSimpleSelectorArgument { @Override - protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException { + protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/RY.java b/server/src/main/java/org/allaymc/server/command/selector/args/RY.java index d37325bb3..90c40752a 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/RY.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/RY.java @@ -5,7 +5,7 @@ import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.command.selector.args.CachedSimpleSelectorArgument; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -15,7 +15,7 @@ */ public class RY extends CachedSimpleSelectorArgument { @Override - protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException { + protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/RYM.java b/server/src/main/java/org/allaymc/server/command/selector/args/RYM.java index 45d845aa4..6d23a14ff 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/RYM.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/RYM.java @@ -5,7 +5,7 @@ import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.command.selector.args.CachedSimpleSelectorArgument; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -15,7 +15,7 @@ */ public class RYM extends CachedSimpleSelectorArgument { @Override - protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException { + protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/Scores.java b/server/src/main/java/org/allaymc/server/command/selector/args/Scores.java index 9ea70fb9b..2149d50f5 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/Scores.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/Scores.java @@ -6,7 +6,7 @@ import org.allaymc.api.command.selector.args.CachedSimpleSelectorArgument; import org.allaymc.api.entity.Entity; import org.allaymc.api.entity.interfaces.EntityPlayer; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.scoreboard.scorer.EntityScorer; import org.allaymc.api.scoreboard.scorer.PlayerScorer; import org.allaymc.api.scoreboard.scorer.Scorer; @@ -28,7 +28,7 @@ public class Scores extends CachedSimpleSelectorArgument { protected static final String SCORE_SCOPE_SEPARATOR = ".."; @Override - protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) throws SelectorSyntaxException { + protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); List conditions = new ArrayList<>(); for (var entry : AllayStringUtils.fastSplit(SCORE_SEPARATOR, arguments[0].substring(1, arguments[0].length() - 1))) { diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/Tag.java b/server/src/main/java/org/allaymc/server/command/selector/args/Tag.java index a987f9cac..337ec92bc 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/Tag.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/Tag.java @@ -4,7 +4,7 @@ import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.command.selector.args.CachedSimpleSelectorArgument; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.server.command.selector.ParseUtils; import java.util.ArrayList; @@ -15,7 +15,7 @@ */ public class Tag extends CachedSimpleSelectorArgument { @Override - protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) { + protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) { var have = new ArrayList(); var dontHave = new ArrayList(); for (var tag : arguments) { diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/Type.java b/server/src/main/java/org/allaymc/server/command/selector/args/Type.java index 84cc6d01a..8c0bad9fe 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/Type.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/Type.java @@ -4,7 +4,7 @@ import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.command.selector.args.CachedSimpleSelectorArgument; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.server.command.selector.ParseUtils; import java.util.ArrayList; @@ -18,7 +18,7 @@ public class Type extends CachedSimpleSelectorArgument { @Override - protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3fc basePos, String... arguments) { + protected Predicate cache(SelectorType selectorType, CommandSender sender, Location3dc basePos, String... arguments) { var have = new ArrayList(); var dontHave = new ArrayList(); for (var type : arguments) { diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/X.java b/server/src/main/java/org/allaymc/server/command/selector/args/X.java index acbb83413..23ac367fb 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/X.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/X.java @@ -4,7 +4,7 @@ import org.allaymc.api.command.selector.SelectorSyntaxException; import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -14,10 +14,10 @@ */ public class X extends CoordinateArgument { @Override - public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3f basePos, String... arguments) throws SelectorSyntaxException { + public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3d basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); - basePos.x = ParseUtils.parseOffsetFloat(arguments[0], basePos.x); + basePos.x = ParseUtils.parseOffsetDouble(arguments[0], basePos.x); return null; } diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/Y.java b/server/src/main/java/org/allaymc/server/command/selector/args/Y.java index 4dfd7624c..842d947da 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/Y.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/Y.java @@ -4,7 +4,7 @@ import org.allaymc.api.command.selector.SelectorSyntaxException; import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -14,10 +14,10 @@ */ public class Y extends CoordinateArgument { @Override - public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3f basePos, String... arguments) throws SelectorSyntaxException { + public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3d basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); - basePos.y = ParseUtils.parseOffsetFloat(arguments[0], basePos.y); + basePos.y = ParseUtils.parseOffsetDouble(arguments[0], basePos.y); return null; } diff --git a/server/src/main/java/org/allaymc/server/command/selector/args/Z.java b/server/src/main/java/org/allaymc/server/command/selector/args/Z.java index 686c8d74e..b6ecc8a79 100644 --- a/server/src/main/java/org/allaymc/server/command/selector/args/Z.java +++ b/server/src/main/java/org/allaymc/server/command/selector/args/Z.java @@ -4,7 +4,7 @@ import org.allaymc.api.command.selector.SelectorSyntaxException; import org.allaymc.api.command.selector.SelectorType; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.server.command.selector.ParseUtils; import java.util.function.Predicate; @@ -14,10 +14,10 @@ */ public class Z extends CoordinateArgument { @Override - public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3f basePos, String... arguments) throws SelectorSyntaxException { + public Predicate getPredicate(SelectorType selectorType, CommandSender sender, Location3d basePos, String... arguments) throws SelectorSyntaxException { ParseUtils.singleArgument(arguments, getKeyName()); ParseUtils.cannotReversed(arguments[0]); - basePos.z = ParseUtils.parseOffsetFloat(arguments[0], basePos.z); + basePos.z = ParseUtils.parseOffsetDouble(arguments[0], basePos.z); return null; } diff --git a/server/src/main/java/org/allaymc/server/command/tree/node/PosNode.java b/server/src/main/java/org/allaymc/server/command/tree/node/PosNode.java index d56085607..cff8f1206 100644 --- a/server/src/main/java/org/allaymc/server/command/tree/node/PosNode.java +++ b/server/src/main/java/org/allaymc/server/command/tree/node/PosNode.java @@ -5,7 +5,7 @@ import org.allaymc.api.command.tree.CommandNode; import org.cloudburstmc.protocol.bedrock.data.command.CommandParam; import org.cloudburstmc.protocol.bedrock.data.command.CommandParamData; -import org.joml.Vector3f; +import org.joml.Vector3d; /** * @author daoge_cmd @@ -22,7 +22,7 @@ public boolean match(CommandContext context) { var baseY = basePos.y(); var baseZ = basePos.z(); - float x, y, z; + double x, y, z; try { var index = context.getCurrentArgIndex(); x = getRelative(context.queryArg(index), baseX); @@ -31,14 +31,14 @@ public boolean match(CommandContext context) { } catch (Exception e) { return false; } - context.putResult(new Vector3f(x, y, z)); + context.putResult(new Vector3d(x, y, z)); context.popArg(); context.popArg(); context.popArg(); return true; } - protected float getRelative(String token, float base) { + protected double getRelative(String token, double base) { if (!token.contains("~")) return Float.parseFloat(token); if (token.length() > 1) return base + Float.parseFloat(token.substring(1)); diff --git a/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTree.java b/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTree.java index d557618f3..3cff76c94 100644 --- a/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTree.java +++ b/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTree.java @@ -2,14 +2,15 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import lombok.Getter; +import org.allaymc.api.math.MathUtils; import org.allaymc.api.world.service.AABBOverlapFilter; import org.allaymc.api.world.service.HasAABB; import org.allaymc.api.world.service.HasLongId; import org.joml.FrustumIntersection; import org.joml.Matrix4fc; import org.joml.RayAabIntersection; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; import org.joml.primitives.Rayf; import java.util.*; @@ -231,13 +232,13 @@ private void insertNode(int node) { AABBTreeNode nodeToAdd = getNodeAt(node); AABBTreeNode parentNode = getNodeAt(root); - AABBf nodeToAddAABB = nodeToAdd.getAabb(); + AABBd nodeToAddAABB = nodeToAdd.getAabb(); while (!parentNode.isLeaf()) { AABBTreeNode leftChild = getNodeAt(parentNode.getLeftChild()); AABBTreeNode rightChild = getNodeAt(parentNode.getRightChild()); - AABBf aabbA = leftChild.getAabb(); - AABBf aabbB = rightChild.getAabb(); + AABBd aabbA = leftChild.getAabb(); + AABBd aabbB = rightChild.getAabb(); AABBTreeHeuristicFunction.HeuristicResult heuristicResult = insertionHeuristicFunction .getInsertionHeuristic(aabbA, aabbB, nodeToAdd.getData(), nodeToAddAABB); @@ -261,7 +262,7 @@ private void detectCollisionPairsWithNode(AABBTreeNode nodeToTest, CollisionF List> result) { Deque stack = new ArrayDeque<>(); stack.offer(root); - AABBf overlapWith = nodeToTest.getAabb(); + AABBd overlapWith = nodeToTest.getAabb(); while (!stack.isEmpty()) { int nodeIndex = stack.pop(); @@ -270,7 +271,7 @@ private void detectCollisionPairsWithNode(AABBTreeNode nodeToTest, CollisionF } AABBTreeNode node = getNodeAt(nodeIndex); - AABBf nodeAABB = node.getAabb(); + AABBd nodeAABB = node.getAabb(); if (nodeAABB.intersectsAABB(overlapWith)) { if (node.isLeaf() && node.getIndex() != nodeToTest.getIndex()) { T nodeData = node.getData(); @@ -361,12 +362,12 @@ public void remove(T object) { syncUpHierarchy(nodeGrandparent); } - public void detectOverlaps(AABBfc overlapWith, List result) { + public void detectOverlaps(AABBdc overlapWith, List result) { detectOverlaps(overlapWith, defaultAABBOverlapFilter, result); } - public void detectOverlaps(AABBfc overlapWith, AABBOverlapFilter filter, List result) { - traverseTree(aabb -> aabb.intersectsAABB(overlapWith), filter, result); + public void detectOverlaps(AABBdc overlapWith, AABBOverlapFilter filter, List result) { + traverseTree(aabb -> MathUtils.intersectsAABB(aabb, overlapWith), filter, result); } public void detectCollisionPairs(List> result) { @@ -396,19 +397,20 @@ public void detectInFrustum(Matrix4fc worldViewProjection, List result) { public void detectInFrustum(Matrix4fc worldViewProjection, AABBOverlapFilter filter, List result) { frustumIntersection.set(worldViewProjection, false); - traverseTree(aabb -> frustumIntersection.testAab(aabb.minX(), aabb.minY(), aabb.minZ(), aabb.maxX(), aabb.maxY(), aabb.maxZ()), filter, result); + traverseTree(aabb -> frustumIntersection.testAab((float) aabb.minX(), (float) aabb.minY(), (float) aabb.minZ(), (float) aabb.maxX(), (float) aabb.maxY(), (float) aabb.maxZ()), filter, result); } public void detectRayIntersection(Rayf ray, List result) { detectRayIntersection(ray, defaultAABBOverlapFilter, result); } + // TODO: Use Rayfc here public void detectRayIntersection(Rayf ray, AABBOverlapFilter filter, List result) { rayIntersection.set(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ); - traverseTree(aabb -> rayIntersection.test(aabb.minX(), aabb.minY(), aabb.minZ(), aabb.maxX(), aabb.maxY(), aabb.maxZ()), filter, result); + traverseTree(aabb -> rayIntersection.test((float) aabb.minX(), (float) aabb.minY(), (float) aabb.minZ(), (float) aabb.maxX(), (float) aabb.maxY(), (float) aabb.maxZ()), filter, result); } - private void traverseTree(Predicate nodeTest, AABBOverlapFilter filter, List result) { + private void traverseTree(Predicate nodeTest, AABBOverlapFilter filter, List result) { result.clear(); if (root == AABBTreeNode.INVALID_NODE_INDEX) { return; @@ -423,7 +425,7 @@ private void traverseTree(Predicate nodeTest, AABBOverlapFilter filte if (nodeIndex == AABBTreeNode.INVALID_NODE_INDEX) continue; AABBTreeNode node = getNodeAt(nodeIndex); - AABBf nodeAABB = node.getAabb(); + AABBd nodeAABB = node.getAabb(); if (nodeTest.test(nodeAABB)) { if (node.isLeaf()) { T nodeData = node.getData(); diff --git a/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTreeHeuristicFunction.java b/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTreeHeuristicFunction.java index 643e84cad..f6d5f206c 100644 --- a/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTreeHeuristicFunction.java +++ b/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTreeHeuristicFunction.java @@ -1,14 +1,14 @@ package org.allaymc.server.datastruct.aabb; import org.allaymc.api.world.service.HasAABB; -import org.joml.primitives.AABBf; +import org.joml.primitives.AABBd; /** * @author daoge_cmd */ @FunctionalInterface public interface AABBTreeHeuristicFunction { - HeuristicResult getInsertionHeuristic(AABBf left, AABBf right, T object, AABBf objectAABB); + HeuristicResult getInsertionHeuristic(AABBd left, AABBd right, T object, AABBd objectAABB); enum HeuristicResult { LEFT, diff --git a/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTreeNode.java b/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTreeNode.java index fc9090fbe..38a06bfd1 100644 --- a/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTreeNode.java +++ b/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTreeNode.java @@ -3,7 +3,7 @@ import lombok.Getter; import lombok.Setter; import org.allaymc.api.world.service.HasAABB; -import org.joml.primitives.AABBf; +import org.joml.primitives.AABBd; /** * @author daoge_cmd @@ -19,7 +19,7 @@ public final class AABBTreeNode { private static final int MAX_NUM_OF_CHILDREN_PER_NODE = 2; private final int[] children = new int[MAX_NUM_OF_CHILDREN_PER_NODE]; - private final AABBf aabb = new AABBf(); + private final AABBd aabb = new AABBd(); private int parent = INVALID_NODE_INDEX; private int index = INVALID_NODE_INDEX; @@ -61,8 +61,8 @@ void computeAABBWithMargin(float margin) { public void resetForReuse() { assignChildren(INVALID_NODE_INDEX, INVALID_NODE_INDEX); - aabb.setMin(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY); - aabb.setMax(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY); + aabb.setMin(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); + aabb.setMax(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); this.parent = INVALID_NODE_INDEX; this.height = 0; diff --git a/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBUtils.java b/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBUtils.java index f2f718280..84cd28334 100644 --- a/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBUtils.java +++ b/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBUtils.java @@ -1,29 +1,17 @@ package org.allaymc.server.datastruct.aabb; import lombok.experimental.UtilityClass; -import org.joml.primitives.AABBf; +import org.joml.primitives.AABBd; /** * @author daoge_cmd */ @UtilityClass public final class AABBUtils { - public static float getWidth(AABBf aabb) { - return aabb.maxX - aabb.minX; - } - - public static float getHeight(AABBf aabb) { - return aabb.maxY - aabb.minY; - } - - public static float getDepth(AABBf aabb) { - return aabb.maxZ - aabb.minZ; - } - - public static float getArea(AABBf aabb) { - var width = getWidth(aabb); - var height = getHeight(aabb); - var depth = getDepth(aabb); - return 2.0f * (width * height + width * depth + height * depth); + public static double getArea(AABBd aabb) { + var lx = aabb.lengthX(); + var ly = aabb.lengthY(); + var lz = aabb.lengthZ(); + return 2.0 * (lx * ly + lx * lz + ly * lz); } } diff --git a/server/src/main/java/org/allaymc/server/datastruct/aabb/AreaAABBHeuristicFunction.java b/server/src/main/java/org/allaymc/server/datastruct/aabb/AreaAABBHeuristicFunction.java index 26d388a68..25a8e7b39 100644 --- a/server/src/main/java/org/allaymc/server/datastruct/aabb/AreaAABBHeuristicFunction.java +++ b/server/src/main/java/org/allaymc/server/datastruct/aabb/AreaAABBHeuristicFunction.java @@ -1,7 +1,7 @@ package org.allaymc.server.datastruct.aabb; import org.allaymc.api.world.service.HasAABB; -import org.joml.primitives.AABBf; +import org.joml.primitives.AABBd; import static org.allaymc.server.datastruct.aabb.AABBUtils.getArea; @@ -9,10 +9,10 @@ * @author daoge_cmd */ public class AreaAABBHeuristicFunction implements AABBTreeHeuristicFunction { - private final AABBf temp = new AABBf(); + private final AABBd temp = new AABBd(); @Override - public HeuristicResult getInsertionHeuristic(AABBf left, AABBf right, T object, AABBf objectAABB) { + public HeuristicResult getInsertionHeuristic(AABBd left, AABBd right, T object, AABBd objectAABB) { var diffA = getArea(left.union(objectAABB, temp)) - getArea(left); var diffB = getArea(right.union(objectAABB, temp)) - getArea(right); return diffA < diffB ? HeuristicResult.LEFT : HeuristicResult.RIGHT; diff --git a/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java index 259610a80..c192575c3 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java @@ -20,8 +20,8 @@ import org.allaymc.api.eventbus.event.entity.*; import org.allaymc.api.i18n.TrContainer; import org.allaymc.api.math.MathUtils; -import org.allaymc.api.math.location.Location3f; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3d; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.math.position.Position3i; import org.allaymc.api.permission.DefaultPermissions; import org.allaymc.api.permission.tree.PermissionTree; @@ -38,6 +38,7 @@ import org.allaymc.server.world.chunk.AllayUnsafeChunk; import org.allaymc.server.world.service.AllayEntityPhysicsService; import org.cloudburstmc.math.vector.Vector2f; +import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; @@ -49,10 +50,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.*; import org.jetbrains.annotations.UnmodifiableView; -import org.joml.Vector3f; -import org.joml.Vector3fc; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; +import org.joml.Vector3d; +import org.joml.Vector3dc; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; import java.util.*; import java.util.concurrent.ThreadLocalRandom; @@ -90,8 +91,8 @@ public class EntityBaseComponentImpl implements EntityBaseComponent { private static final CommandOriginData ENTITY_COMMAND_ORIGIN_DATA = new CommandOriginData(CommandOriginType.ENTITY, UUID.randomUUID(), "", 0); @Getter - protected final Location3f location; - protected final Location3f locLastSent = new Location3f(0, 0, 0, null); + protected final Location3d location; + protected final Location3d locLastSent = new Location3d(0, 0, 0, null); @Getter protected final long runtimeId = RUNTIME_ID_COUNTER.getAndIncrement(); @Getter @@ -110,9 +111,9 @@ public class EntityBaseComponentImpl implements EntityBaseComponent { protected Map viewers = new Long2ObjectOpenHashMap<>(); protected Map effects = new HashMap<>(); @Getter - protected Vector3f motion = new Vector3f(); + protected Vector3d motion = new Vector3d(); @Getter - protected Vector3f lastMotion = new Vector3f(); + protected Vector3d lastMotion = new Vector3d(); @Getter protected boolean onGround = true; @Setter @@ -126,14 +127,14 @@ public class EntityBaseComponentImpl implements EntityBaseComponent { protected boolean dead; protected int deadTimer; @Getter - protected float fallDistance; + protected double fallDistance; @Getter @Setter protected String displayName; protected Set tags = new HashSet<>(); public EntityBaseComponentImpl(EntityInitInfo info) { - this.location = new Location3f(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, info.dimension()); + this.location = new Location3d(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, info.dimension()); this.entityType = info.getEntityType(); this.metadata = new Metadata(); setDisplayName(entityType.getIdentifier().toString()); @@ -162,9 +163,9 @@ private NbtMap buildAABBTag() { .putFloat("MinX", 0) .putFloat("MinY", 0) .putFloat("MinZ", 0) - .putFloat("MaxX", aabb.maxX() - aabb.minX()) - .putFloat("MaxY", aabb.maxY() - aabb.minY()) - .putFloat("MaxZ", aabb.maxZ() - aabb.minZ()) + .putFloat("MaxX", (float) (aabb.maxX() - aabb.minX())) + .putFloat("MaxY", (float) (aabb.maxY() - aabb.minY())) + .putFloat("MaxZ", (float) (aabb.maxZ() - aabb.minZ())) .putFloat("PivotX", 0) .putFloat("PivotY", 0) .putFloat("PivotZ", 0) @@ -274,9 +275,9 @@ protected void onDie() { protected void spawnDeadParticle() { var offsetAABB = getOffsetAABB(); - for (float x = offsetAABB.minX(); x <= offsetAABB.maxX(); x += 0.5f) { - for (float z = offsetAABB.minZ(); z <= offsetAABB.maxZ(); z += 0.5f) { - for (float y = offsetAABB.minY(); y <= offsetAABB.maxY(); y += 0.5f) { + for (double x = offsetAABB.minX(); x <= offsetAABB.maxX(); x += 0.5) { + for (double z = offsetAABB.minZ(); z <= offsetAABB.maxZ(); z += 0.5) { + for (double y = offsetAABB.minY(); y <= offsetAABB.maxY(); y += 0.5) { this.getDimension().addParticle(x, y, z, ParticleType.EXPLODE); } } @@ -284,14 +285,14 @@ protected void spawnDeadParticle() { } @Override - public void setLocationBeforeSpawn(Location3fc location) { + public void setLocationBeforeSpawn(Location3dc location) { if (!canBeSpawnedIgnoreLocation()) { throw new IllegalStateException("Trying to set location of an entity which cannot being spawned!"); } setLocation(location, false); } - protected void setLocation(Location3fc location, boolean calculateFallDistance) { + protected void setLocation(Location3dc location, boolean calculateFallDistance) { if (MathUtils.hasNaN(location)) { throw new IllegalArgumentException("Trying to set the location of entity " + runtimeId + " to a new location which contains NaN: " + location); } @@ -314,10 +315,10 @@ protected void setLocation(Location3fc location, boolean calculateFallDistance) this.location.setDimension(location.dimension()); } - private void tryResetFallDistance(Location3fc location) { + private void tryResetFallDistance(Location3dc location) { var blockState0 = location.dimension().getBlockState(location); var blockState1 = location.dimension().getBlockState(location, 1); - var newEntityAABB = getAABB().translate(location, new AABBf()); + var newEntityAABB = getAABB().translate(location, new AABBd()); if (!blockState0.getBlockStateData().hasCollision() && blockState1.getBehavior().canResetFallDamage() && @@ -365,11 +366,11 @@ public boolean willBeSpawnedNextTick() { return willBeSpawnedNextTick; } - public boolean setLocationAndCheckChunk(Location3fc newLoc) { + public boolean setLocationAndCheckChunk(Location3dc newLoc) { return setLocationAndCheckChunk(newLoc, true); } - public boolean setLocationAndCheckChunk(Location3fc newLoc, boolean calculateFallDistance) { + public boolean setLocationAndCheckChunk(Location3dc newLoc, boolean calculateFallDistance) { if (checkChunk(this.location, newLoc)) { setLocation(newLoc, calculateFallDistance); return true; @@ -377,7 +378,7 @@ public boolean setLocationAndCheckChunk(Location3fc newLoc, boolean calculateFal return false; } - protected boolean checkChunk(Location3fc oldLoc, Location3fc newLoc) { + protected boolean checkChunk(Location3dc oldLoc, Location3dc newLoc) { var oldChunkX = (int) oldLoc.x() >> 4; var oldChunkZ = (int) oldLoc.z() >> 4; var newChunkX = (int) newLoc.x() >> 4; @@ -418,7 +419,7 @@ protected boolean checkChunk(Location3fc oldLoc, Location3fc newLoc) { } @Override - public void teleport(Location3fc target, EntityTeleportEvent.Reason reason) { + public void teleport(Location3dc target, EntityTeleportEvent.Reason reason) { Objects.requireNonNull(target.dimension()); if (this.location.dimension() == null) { log.warn("Trying to teleport an entity whose dimension is null! Entity: {}", thisEntity); @@ -430,7 +431,7 @@ public void teleport(Location3fc target, EntityTeleportEvent.Reason reason) { return; } - var event = new EntityTeleportEvent(thisEntity, this.location, new Location3f(target), reason); + var event = new EntityTeleportEvent(thisEntity, this.location, new Location3d(target), reason); if (!event.call()) { return; } @@ -446,20 +447,20 @@ public void teleport(Location3fc target, EntityTeleportEvent.Reason reason) { } } - protected void beforeTeleport(Location3fc target) { + protected void beforeTeleport(Location3dc target) { this.fallDistance = 0; this.setMotion(0, 0, 0); // Ensure that the new chunk is loaded target.dimension().getChunkService().getOrLoadChunkSync((int) target.x() >> 4, (int) target.z() >> 4); } - protected void teleportInDimension(Location3fc target) { + protected void teleportInDimension(Location3dc target) { // This method should always return true because we have loaded the chunk setLocationAndCheckChunk(target, false); broadcastMoveToViewers(target, true); } - protected void teleportOverDimension(Location3fc target) { + protected void teleportOverDimension(Location3dc target) { // Teleporting to another dimension, there will be more works to be done this.location.dimension().getEntityService().removeEntity(thisEntity, () -> { setLocationBeforeSpawn(target); @@ -485,9 +486,9 @@ protected SetEntityDataPacket createSetEntityDataPacket() { } @Override - public AABBfc getAABB() { + public AABBdc getAABB() { // Default aabb is player's - return new AABBf(-0.3f, 0.0f, -0.3f, 0.3f, 1.8f, 0.3f); + return new AABBd(-0.3, 0.0, -0.3, 0.3, 1.8, 0.3); } @Override @@ -497,12 +498,12 @@ public Map getViewers() { } @Override - public void setMotion(Vector3fc motion) { + public void setMotion(Vector3dc motion) { if (MathUtils.hasNaN(motion)) { throw new IllegalArgumentException("Trying to set the motion of entity " + runtimeId + " to a new motion which contains NaN: " + motion); } this.lastMotion = this.motion; - this.motion = new Vector3f(motion); + this.motion = new Vector3d(motion); } public void setOnGround(boolean onGround) { @@ -513,13 +514,13 @@ public void setOnGround(boolean onGround) { } @Override - public void knockback(Vector3fc source, float kb, boolean ignoreKnockbackResistance, float kby) { + public void knockback(Vector3dc source, double kb, boolean ignoreKnockbackResistance, double kby) { setMotion(calculateKnockbackMotion(source, kb, ignoreKnockbackResistance, kby)); } - protected Vector3f calculateKnockbackMotion(Vector3fc source, float kb, boolean ignoreKnockbackResistance, float kby) { + protected Vector3d calculateKnockbackMotion(Vector3dc source, double kb, boolean ignoreKnockbackResistance, double kby) { if (!ignoreKnockbackResistance) { - var resistance = 0.0f; + var resistance = 0.0; if (attributeComponent != null && attributeComponent.supportAttribute(AttributeType.KNOCKBACK_RESISTANCE)) { resistance = attributeComponent.getAttributeValue(AttributeType.KNOCKBACK_RESISTANCE); } @@ -528,21 +529,21 @@ protected Vector3f calculateKnockbackMotion(Vector3fc source, float kb, boolean kby *= 1 - resistance; } } - Vector3f vec; + Vector3d vec; if (location.distanceSquared(source) <= 0.0001 /* 0.01 * 0.01 */) { // Generate a random kb direction if distance <= 0.01m var rand = ThreadLocalRandom.current(); - var rx = rand.nextFloat(1) - 0.5f; - var rz = rand.nextFloat(1) - 0.5f; - vec = MathUtils.normalizeIfNotZero(new Vector3f(rx, 0, rz)).mul(kb); + var rx = rand.nextDouble(1) - 0.5; + var rz = rand.nextDouble(1) - 0.5; + vec = MathUtils.normalizeIfNotZero(new Vector3d(rx, 0, rz)).mul(kb); } else { - vec = location.sub(source, new Vector3f()).normalize().mul(kb); + vec = location.sub(source, new Vector3d()).normalize().mul(kb); vec.y = 0; } - return new Vector3f( - motion.x / 2f + vec.x, + return new Vector3d( + motion.x / 2 + vec.x, min(motion.y / 2 + kby, kby), - motion.z / 2f + vec.z + motion.z / 2 + vec.z ); } @@ -589,14 +590,14 @@ public void sendPacketToViewersImmediately(BedrockPacket packet) { viewers.values().forEach(client -> client.sendPacketImmediately(packet)); } - public void broadcastMoveToViewers(Location3fc newLoc, boolean teleporting) { + public void broadcastMoveToViewers(Location3dc newLoc, boolean teleporting) { var movementPk = createMovePacket(newLoc, teleporting); var motionPk = createMotionPacket(); sendPacketToViewers(movementPk); sendPacketToViewers(motionPk); } - protected BedrockPacket createMovePacket(Location3fc newLoc, boolean teleporting) { + protected BedrockPacket createMovePacket(Location3dc newLoc, boolean teleporting) { return Server.SETTINGS.entitySettings().physicsEngineSettings().useDeltaMovePacket() ? createDeltaMovePacket(newLoc, teleporting) : createAbsoluteMovePacket(newLoc, teleporting); @@ -605,11 +606,11 @@ protected BedrockPacket createMovePacket(Location3fc newLoc, boolean teleporting protected BedrockPacket createMotionPacket() { var pk = new SetEntityMotionPacket(); pk.setRuntimeEntityId(getRuntimeId()); - pk.setMotion(MathUtils.JOMLVecToCBVec(motion)); + pk.setMotion(Vector3f.from(motion.x, motion.y, motion.z)); return pk; } - protected BedrockPacket createAbsoluteMovePacket(Location3fc newLoc, boolean teleporting) { + protected BedrockPacket createAbsoluteMovePacket(Location3dc newLoc, boolean teleporting) { var pk = new MoveEntityAbsolutePacket(); pk.setRuntimeEntityId(getRuntimeId()); pk.setPosition(org.cloudburstmc.math.vector.Vector3f.from(newLoc.x(), newLoc.y() + getNetworkOffset(), newLoc.z())); @@ -619,21 +620,21 @@ protected BedrockPacket createAbsoluteMovePacket(Location3fc newLoc, boolean tel return pk; } - protected BedrockPacket createDeltaMovePacket(Location3fc newLoc, boolean teleporting) { + protected BedrockPacket createDeltaMovePacket(Location3dc newLoc, boolean teleporting) { var pk = new MoveEntityDeltaPacket(); pk.setRuntimeEntityId(getRuntimeId()); var moveFlags = computeMoveFlags(newLoc); pk.getFlags().addAll(moveFlags); if (moveFlags.contains(HAS_X)) { - pk.setX(newLoc.x()); + pk.setX((float) newLoc.x()); locLastSent.x = newLoc.x(); } if (moveFlags.contains(HAS_Y)) { - pk.setY(newLoc.y()); + pk.setY((float) newLoc.y()); locLastSent.y = newLoc.y() + getNetworkOffset(); } if (moveFlags.contains(HAS_Z)) { - pk.setZ(newLoc.z()); + pk.setZ((float) newLoc.z()); locLastSent.z = newLoc.z(); } if (moveFlags.contains(HAS_PITCH)) { @@ -657,7 +658,7 @@ protected BedrockPacket createDeltaMovePacket(Location3fc newLoc, boolean telepo return pk; } - protected Set computeMoveFlags(Location3fc newLoc) { + protected Set computeMoveFlags(Location3dc newLoc) { var flags = EnumSet.noneOf(MoveEntityDeltaPacket.Flag.class); var settings = Server.SETTINGS.entitySettings().physicsEngineSettings(); var diffPositionThreshold = settings.diffPositionThreshold(); @@ -677,8 +678,8 @@ public NbtMap saveNBT() { var builder = NbtMap.builder(); builder.putString(TAG_IDENTIFIER, entityType.getIdentifier().toString()); builder.putBoolean(TAG_ON_GROUND, onGround); - AllayNbtUtils.writeVector3f(builder, TAG_POS, location); - AllayNbtUtils.writeVector3f(builder, TAG_MOTION, motion); + AllayNbtUtils.writeVector3f(builder, TAG_POS, (float) location.x, (float) location.y, (float) location.z); + AllayNbtUtils.writeVector3f(builder, TAG_MOTION, (float) motion.x, (float) motion.y, (float) motion.z); AllayNbtUtils.writeVector2f(builder, TAG_ROTATION, (float) location.yaw(), (float) location.pitch()); if (!tags.isEmpty()) { builder.putList(TAG_TAGS, NbtType.STRING, new ArrayList<>(tags)); @@ -852,7 +853,7 @@ public CommandOriginData getCommandOriginData() { } @Override - public Location3fc getCmdExecuteLocation() { + public Location3dc getCmdExecuteLocation() { return getLocation(); } diff --git a/server/src/main/java/org/allaymc/server/entity/component/EntityContainerHolderComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/EntityContainerHolderComponentImpl.java index 282c4c5f7..7df4a6d3c 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/EntityContainerHolderComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/EntityContainerHolderComponentImpl.java @@ -10,7 +10,7 @@ import org.allaymc.api.world.gamerule.GameRule; import org.allaymc.server.component.annotation.ComponentObject; import org.allaymc.server.entity.component.event.CEntityDieEvent; -import org.joml.Vector3f; +import org.joml.Vector3d; import java.util.concurrent.ThreadLocalRandom; @@ -41,15 +41,15 @@ protected void onDie(CEntityDieEvent event) { if (itemStack == ItemAirStack.AIR_STACK) continue; dimension.dropItem( itemStack, - new Vector3f( - pos.x() + rand.nextFloat(0.5f) + 0.25f, - pos.y() + rand.nextFloat(0.5f) + 0.25f, - pos.z() + rand.nextFloat(0.5f) + 0.25f + new Vector3d( + pos.x() + rand.nextDouble(0.5) + 0.25, + pos.y() + rand.nextDouble(0.5) + 0.25, + pos.z() + rand.nextDouble(0.5) + 0.25 ), - new Vector3f( - rand.nextFloat(1f) - 0.5f, - 0.5f, - rand.nextFloat(1f) - 0.5f + new Vector3d( + rand.nextDouble(1) - 0.5, + 0.5, + rand.nextDouble(1) - 0.5 ), 40 ); diff --git a/server/src/main/java/org/allaymc/server/entity/component/EntityDamageComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/EntityDamageComponentImpl.java index a755cd10f..82158a79f 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/EntityDamageComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/EntityDamageComponentImpl.java @@ -249,7 +249,7 @@ protected void onFall(CEntityFallEvent event) { } var blockStateStandingOn = thisEntity.getBlockStateStandingOn().blockState(); - float rawDamage = (event.getFallDistance() - 3) - baseComponent.getEffectLevel(EffectTypes.JUMP_BOOST); + double rawDamage = (event.getFallDistance() - 3) - baseComponent.getEffectLevel(EffectTypes.JUMP_BOOST); var damage = Math.round(rawDamage * (1 - blockStateStandingOn.getBehavior().getFallDamageReductionFactor())); if (damage > 0) { attack(DamageContainer.fall(damage)); diff --git a/server/src/main/java/org/allaymc/server/entity/component/EntityFallingBlockBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/EntityFallingBlockBaseComponentImpl.java index 498f1c272..a996dbdbf 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/EntityFallingBlockBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/EntityFallingBlockBaseComponentImpl.java @@ -12,9 +12,9 @@ import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; -import org.joml.Vector3f; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; +import org.joml.Vector3d; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; import java.util.Objects; @@ -75,7 +75,7 @@ protected void tickFalling() { return; } - var floorLoc = location.floor(new Vector3f()); + var floorLoc = location.floor(new Vector3d()); if (currentBlock.getBlockType().hasBlockTag(BlockCustomTags.REPLACEABLE)) { dimension.breakBlock((int) floorLoc.x(), (int) floorLoc.y(), (int) floorLoc.z(), null, null); } else { @@ -104,13 +104,13 @@ public void loadNBT(NbtMap nbt) { } @Override - public AABBfc getAABB() { - return new AABBf(-0.49f, 0, -0.49f, 0.49f, 0.98f, 0.49f); + public AABBdc getAABB() { + return new AABBd(-0.49, 0, -0.49, 0.49, 0.98, 0.49); } @Override - public float getGravity() { - return 0.04f; + public double getGravity() { + return 0.04; } @Override diff --git a/server/src/main/java/org/allaymc/server/entity/component/EntityItemBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/EntityItemBaseComponentImpl.java index d36db300d..a1368b3ce 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/EntityItemBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/EntityItemBaseComponentImpl.java @@ -8,12 +8,12 @@ import org.allaymc.api.entity.interfaces.EntityItem; import org.allaymc.api.entity.type.EntityTypes; import org.allaymc.api.item.ItemStack; -import org.allaymc.api.math.MathUtils; +import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.packet.AddItemEntityPacket; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; import static org.allaymc.api.item.ItemHelper.fromNBT; @@ -75,8 +75,8 @@ public void loadNBT(NbtMap nbt) { } @Override - public AABBfc getAABB() { - return new AABBf(-0.125f, 0.0f, -0.125f, 0.125f, 0.25f, 0.125f); + public AABBdc getAABB() { + return new AABBd(-0.125, 0.0, -0.125, 0.125, 0.25, 0.125); } @Override @@ -90,8 +90,8 @@ public BedrockPacket createSpawnPacket() { packet.setRuntimeEntityId(runtimeId); packet.setUniqueEntityId(runtimeId); packet.setItemInHand(itemStack.toNetworkItemData()); - packet.setPosition(MathUtils.JOMLVecToCBVec(location)); - packet.setMotion(MathUtils.JOMLVecToCBVec(motion)); + packet.setPosition(Vector3f.from(location.x, location.y, location.z)); + packet.setMotion(Vector3f.from(motion.x, motion.y, motion.z)); packet.getMetadata().putAll(metadata.getEntityDataMap()); return packet; } diff --git a/server/src/main/java/org/allaymc/server/entity/component/EntityPickableBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/EntityPickableBaseComponentImpl.java index 982b61e06..d905b640f 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/EntityPickableBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/EntityPickableBaseComponentImpl.java @@ -68,7 +68,7 @@ public NbtMap saveNBT() { } @Override - public float getGravity() { - return 0.04f; + public double getGravity() { + return 0.04; } } diff --git a/server/src/main/java/org/allaymc/server/entity/component/EntityTntBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/EntityTntBaseComponentImpl.java index cf80c096c..9f6b67b57 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/EntityTntBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/EntityTntBaseComponentImpl.java @@ -11,8 +11,8 @@ import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; /** * @author daoge_cmd @@ -83,8 +83,8 @@ public NbtMap saveNBT() { } @Override - public float getGravity() { - return 0.04f; + public double getGravity() { + return 0.04; } @Override @@ -93,14 +93,14 @@ public float getNetworkOffset() { } @Override - public AABBfc getAABB() { - return new AABBf(-0.49f, 0.0f, -0.49f, 0.49f, 0.98f, 0.49f); + public AABBdc getAABB() { + return new AABBd(-0.49, 0.0, -0.49, 0.49, 0.98, 0.49); } @Override - public float getStepHeight() { + public double getStepHeight() { // Entity tnt can't step - return 0.0f; + return 0.0; } @Override diff --git a/server/src/main/java/org/allaymc/server/entity/component/EntityXpOrbBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/EntityXpOrbBaseComponentImpl.java index 6f8188043..99489263f 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/EntityXpOrbBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/EntityXpOrbBaseComponentImpl.java @@ -11,8 +11,8 @@ import org.allaymc.server.entity.component.event.CEntityTryDamageEvent; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; /** * @author daoge_cmd @@ -100,8 +100,8 @@ public NbtMap saveNBT() { } @Override - public AABBfc getAABB() { - return new AABBf(-0.05f, 0f, -0.05f, 0.05f, 0.1f, 0.05f); + public AABBdc getAABB() { + return new AABBd(-0.05, 0, -0.05, 0.05, 0.1, 0.05); } @EventHandler diff --git a/server/src/main/java/org/allaymc/server/entity/component/event/CEntityFallEvent.java b/server/src/main/java/org/allaymc/server/entity/component/event/CEntityFallEvent.java index aa8f8ce22..7516d34c2 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/event/CEntityFallEvent.java +++ b/server/src/main/java/org/allaymc/server/entity/component/event/CEntityFallEvent.java @@ -10,5 +10,5 @@ @Getter @AllArgsConstructor public class CEntityFallEvent extends Event { - protected float fallDistance; + protected double fallDistance; } diff --git a/server/src/main/java/org/allaymc/server/entity/component/event/CPlayerMoveEvent.java b/server/src/main/java/org/allaymc/server/entity/component/event/CPlayerMoveEvent.java index 690fdc452..7b91bf501 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/event/CPlayerMoveEvent.java +++ b/server/src/main/java/org/allaymc/server/entity/component/event/CPlayerMoveEvent.java @@ -3,7 +3,7 @@ import lombok.AllArgsConstructor; import lombok.Getter; import org.allaymc.api.eventbus.event.Event; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3dc; /** * @author daoge_cmd @@ -11,5 +11,5 @@ @AllArgsConstructor @Getter public class CPlayerMoveEvent extends Event { - protected Location3fc newLoc; + protected Location3dc newLoc; } diff --git a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java index 89190d003..a42389669 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java @@ -29,9 +29,8 @@ import org.allaymc.api.form.type.Form; import org.allaymc.api.i18n.I18n; import org.allaymc.api.i18n.TrContainer; -import org.allaymc.api.math.MathUtils; -import org.allaymc.api.math.location.Location3f; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3d; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.math.location.Location3i; import org.allaymc.api.math.location.Location3ic; import org.allaymc.api.permission.tree.PermissionTree; @@ -57,6 +56,7 @@ import org.allaymc.server.entity.impl.EntityPlayerImpl; import org.allaymc.server.world.AllayWorld; import org.allaymc.server.world.gamerule.AllayGameRules; +import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; @@ -71,9 +71,9 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.*; -import org.joml.Vector3f; -import org.joml.Vector3fc; -import org.joml.primitives.AABBf; +import org.joml.Vector3d; +import org.joml.Vector3dc; +import org.joml.primitives.AABBd; import java.util.*; import java.util.concurrent.ThreadLocalRandom; @@ -142,7 +142,7 @@ public class EntityPlayerBaseComponentImpl extends EntityBaseComponentImpl imple */ @Getter @Setter - protected Vector3fc expectedTeleportPos; + protected Vector3dc expectedTeleportPos; // Set enchantment seed to a random value // and if player has enchantment seed previously, // this random value will be covered @@ -283,13 +283,13 @@ protected void tryPickUpItems() { var dimension = location.dimension(); // pick up items - var pickUpArea = new AABBf( - location.x - 1.425f, - location.y - 1.425f, - location.z - 1.425f, - location.x + 1.425f, - location.y + 1.425f, - location.z + 1.425f + var pickUpArea = new AABBd( + location.x - 1.425, + location.y - 1.425, + location.z - 1.425, + location.x + 1.425, + location.y + 1.425, + location.z + 1.425 ); var entityItems = dimension.getEntityPhysicsService().computeCollidingEntities(pickUpArea, true) .stream() @@ -321,13 +321,13 @@ protected void tryPickUpItems() { } @Override - protected void beforeTeleport(Location3fc target) { + protected void beforeTeleport(Location3dc target) { super.beforeTeleport(target); - this.expectedTeleportPos = new Vector3f(target); + this.expectedTeleportPos = new Vector3d(target); } @Override - protected void teleportInDimension(Location3fc target) { + protected void teleportInDimension(Location3dc target) { super.teleportInDimension(target); // For player, we also need to send move packet to client // However, there is no need to send motion packet as we are teleporting the player @@ -335,7 +335,7 @@ protected void teleportInDimension(Location3fc target) { } @Override - protected void teleportOverDimension(Location3fc target) { + protected void teleportOverDimension(Location3dc target) { var currentDim = location.dimension(); var targetDim = target.dimension(); if (currentDim.getWorld() != targetDim.getWorld()) { @@ -354,7 +354,7 @@ protected void teleportOverDimension(Location3fc target) { awaitingDimensionChangeACK = true; var packet = new ChangeDimensionPacket(); packet.setDimension(targetDim.getDimensionInfo().dimensionId()); - packet.setPosition(MathUtils.JOMLVecToCBVec(target)); + packet.setPosition(Vector3f.from(target.x(), target.y(), target.z())); packet.setRespawn(!thisPlayer.isAlive()); networkComponent.sendPacket(packet); } @@ -383,8 +383,8 @@ public void despawnFrom(EntityPlayer player) { } @Override - public void broadcastMoveToViewers(Location3fc newLoc, boolean teleporting) { - var loc = new Location3f(newLoc); + public void broadcastMoveToViewers(Location3dc newLoc, boolean teleporting) { + var loc = new Location3d(newLoc); // base offset seems not being used in move packet // loc.add(0, getBaseOffset(), 0f); @@ -751,11 +751,11 @@ public void applyEntityEvent(EntityEventType event, int data) { } @Override - public void applyAction(AnimatePacket.Action action, float rowingTime) { + public void applyAction(AnimatePacket.Action action, double rowingTime) { var packet = new AnimatePacket(); packet.setRuntimeEntityId(getRuntimeId()); packet.setAction(action); - packet.setRowingTime(rowingTime); + packet.setRowingTime((float) rowingTime); sendPacketToViewers(packet); // Player should also send the packet to itself networkComponent.sendPacket(packet); @@ -926,23 +926,23 @@ protected void sendMobEffectPacket(MobEffectPacket packet) { networkComponent.sendPacket(packet); } - public void setMotionValueOnly(Vector3fc motion) { - this.motion = new Vector3f(motion); + public void setMotionValueOnly(Vector3dc motion) { + this.motion = new Vector3d(motion); } @Override - public void setMotion(Vector3fc motion) { + public void setMotion(Vector3dc motion) { // For player, motion effect is calculated by the client rather than the server // We only need to send SetEntityMotionPacket to client when // we want to apply motion on a player var packet = new SetEntityMotionPacket(); - packet.setMotion(MathUtils.JOMLVecToCBVec(motion)); + packet.setMotion(Vector3f.from(motion.x(), motion.y(), motion.z())); packet.setRuntimeEntityId(runtimeId); networkComponent.sendPacket(packet); } @Override - public void setLocationBeforeSpawn(Location3fc location) { + public void setLocationBeforeSpawn(Location3dc location) { if (this.location.dimension() != null && location.dimension() == null) { // Different from normal entity, reset the dimension of player entity back to null is not allowed throw new IllegalArgumentException("Reset dimension back to null is not allowed for player!"); diff --git a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java index c571ad065..7c7b6c03d 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java @@ -19,7 +19,7 @@ import org.allaymc.api.i18n.TrKeys; import org.allaymc.api.item.ItemStack; import org.allaymc.api.item.recipe.Recipe; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.api.network.ClientStatus; import org.allaymc.api.network.ProtocolInfo; import org.allaymc.api.pack.Pack; @@ -320,7 +320,7 @@ public void initializePlayer() { // Load the current point chunk firstly so that we can add player entity into the chunk dimension.getChunkService().getOrLoadChunkSync((int) currentPos.x() >> 4, (int) currentPos.z() >> 4); - baseComponent.setLocationBeforeSpawn(new Location3f(currentPos.x(), currentPos.y(), currentPos.z(), dimension)); + baseComponent.setLocationBeforeSpawn(new Location3d(currentPos.x(), currentPos.y(), currentPos.z(), dimension)); dimension.addPlayer(thisPlayer); var startGamePacket = encodeStartGamePacket(dimension.getWorld(), playerData, dimension); diff --git a/server/src/main/java/org/allaymc/server/item/component/ItemSpawnEggBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/item/component/ItemSpawnEggBaseComponentImpl.java index 9dc9703d0..7bfa110a4 100644 --- a/server/src/main/java/org/allaymc/server/item/component/ItemSpawnEggBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/item/component/ItemSpawnEggBaseComponentImpl.java @@ -7,7 +7,6 @@ import org.allaymc.api.registry.Registries; import org.allaymc.api.utils.Identifier; import org.allaymc.api.world.Dimension; -import org.joml.Vector3f; import org.joml.Vector3ic; /** @@ -31,15 +30,15 @@ public boolean useItemOnBlock(Dimension dimension, Vector3ic placeBlockPos, Play this.customEntityId = new Identifier(identifier.toString().replace("_spawn_egg", "")); } + var clickedPos = interactInfo.clickedPos(); + var clickedBlockPos = interactInfo.clickedBlockPos(); var entity = Registries.ENTITIES.get(this.customEntityId).createEntity( EntityInitInfo.builder() .dimension(dimension) - .pos(interactInfo.clickedPos().add( - interactInfo.clickedBlockPos().x(), - interactInfo.clickedBlockPos().y(), - interactInfo.clickedBlockPos().z(), - new Vector3f() - )) + .pos( + (double) clickedPos.x() + clickedBlockPos.x(), + (double) clickedPos.y() + clickedBlockPos.y(), + (double) clickedPos.z() + clickedBlockPos.z()) .build() ); dimension.getEntityService().addEntity(entity); diff --git a/server/src/main/java/org/allaymc/server/item/component/food/ItemChorusFruitBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/item/component/food/ItemChorusFruitBaseComponentImpl.java index 6aa3fe9a4..d1c416efc 100644 --- a/server/src/main/java/org/allaymc/server/item/component/food/ItemChorusFruitBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/item/component/food/ItemChorusFruitBaseComponentImpl.java @@ -2,7 +2,7 @@ import org.allaymc.api.block.type.BlockTypes; import org.allaymc.api.entity.interfaces.EntityPlayer; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.api.math.position.Position3ic; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; @@ -24,7 +24,7 @@ public void onEaten(EntityPlayer player) { var safePos = dimension.findSuitableGroundPosAround(this::isSafeStandingPos, (int) playerLoc.x(), (int) playerLoc.z(), 8, 16); if (safePos != null) { dimension.addLevelSoundEvent(playerLoc, SoundEvent.TELEPORT); - player.teleport(new Location3f(safePos.x() + 0.5f, safePos.y(), safePos.z() + 0.5f, dimension)); + player.teleport(new Location3d(safePos.x() + 0.5, safePos.y(), safePos.z() + 0.5, dimension)); dimension.addLevelSoundEvent(playerLoc, SoundEvent.TELEPORT); } } diff --git a/server/src/main/java/org/allaymc/server/network/processor/impl/ingame/PlayerActionPacketProcessor.java b/server/src/main/java/org/allaymc/server/network/processor/impl/ingame/PlayerActionPacketProcessor.java index d0c55ca58..b2b9789a6 100644 --- a/server/src/main/java/org/allaymc/server/network/processor/impl/ingame/PlayerActionPacketProcessor.java +++ b/server/src/main/java/org/allaymc/server/network/processor/impl/ingame/PlayerActionPacketProcessor.java @@ -3,7 +3,7 @@ import lombok.extern.slf4j.Slf4j; import org.allaymc.api.entity.interfaces.EntityPlayer; import org.allaymc.api.eventbus.event.player.PlayerRespawnEvent; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.api.math.location.Location3ic; import org.allaymc.server.entity.component.player.EntityPlayerBaseComponentImpl; import org.allaymc.server.entity.impl.EntityPlayerImpl; @@ -102,13 +102,13 @@ public PacketSignal handleAsync(EntityPlayer player, PlayerActionPacket packet, private void prepareForRespawn(EntityPlayer player, Location3ic spawnPoint) { var spawnDimension = spawnPoint.dimension(); spawnDimension.getChunkService().getOrLoadChunkSync(spawnPoint.x() >> 4, spawnPoint.z() >> 4); - player.setLocationBeforeSpawn(new Location3f(spawnPoint)); + player.setLocationBeforeSpawn(new Location3d(spawnPoint)); } private void afterRespawn(EntityPlayer player, Location3ic spawnPoint) { var spawnDimension = spawnPoint.dimension(); // Teleport to prevent the player from falling into strange places - player.teleport(new Location3f(spawnPoint.x(), spawnPoint.y(), spawnPoint.z(), spawnDimension)); + player.teleport(new Location3d(spawnPoint.x(), spawnPoint.y(), spawnPoint.z(), spawnDimension)); player.setSprinting(false); player.setSneaking(false); player.removeAllEffects(); diff --git a/server/src/main/java/org/allaymc/server/network/processor/impl/ingame/PlayerAuthInputPacketProcessor.java b/server/src/main/java/org/allaymc/server/network/processor/impl/ingame/PlayerAuthInputPacketProcessor.java index 2a99f9bbe..a7eeec15e 100644 --- a/server/src/main/java/org/allaymc/server/network/processor/impl/ingame/PlayerAuthInputPacketProcessor.java +++ b/server/src/main/java/org/allaymc/server/network/processor/impl/ingame/PlayerAuthInputPacketProcessor.java @@ -5,7 +5,7 @@ import org.allaymc.api.block.type.BlockState; import org.allaymc.api.entity.interfaces.EntityPlayer; import org.allaymc.api.math.MathUtils; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.server.entity.component.player.EntityPlayerBaseComponentImpl; import org.allaymc.server.entity.component.player.EntityPlayerNetworkComponentImpl; import org.allaymc.server.entity.impl.EntityPlayerImpl; @@ -64,7 +64,7 @@ private static boolean isInvalidGameType(EntityPlayer player) { protected void handleMovement(EntityPlayer player, Vector3f newPos, Vector3f newRot) { var world = player.getLocation().dimension(); - ((AllayEntityPhysicsService) world.getEntityPhysicsService()).offerClientMove(player, new Location3f( + ((AllayEntityPhysicsService) world.getEntityPhysicsService()).offerClientMove(player, new Location3d( newPos.getX(), newPos.getY(), newPos.getZ(), newRot.getX(), newRot.getY(), newRot.getZ(), world @@ -291,7 +291,8 @@ public PacketSignal handleAsync(EntityPlayer player, PlayerAuthInputPacket packe var baseComponent = ((EntityPlayerBaseComponentImpl) ((EntityPlayerImpl) player).getBaseComponent()); if (baseComponent.isAwaitingTeleportACK()) { - var diff = baseComponent.getExpectedTeleportPos().sub(MathUtils.CBVecToJOMLVec(packet.getPosition().sub(0, player.getNetworkOffset(), 0)), new org.joml.Vector3f()).length(); + var clientPos = MathUtils.CBVecToJOMLVec(packet.getPosition().sub(0, player.getNetworkOffset(), 0)); + var diff = baseComponent.getExpectedTeleportPos().sub(clientPos.x(), clientPos.y(), clientPos.z(), new org.joml.Vector3d()).length(); if (diff > TELEPORT_ACK_DIFF_TOLERANCE) { // The player has moved before it received the teleport packet. Ignore this movement entirely and // wait for the client to sync itself back to the server. Once we get a movement that is close @@ -333,7 +334,7 @@ protected boolean validateClientLocation(EntityPlayer player, Vector3f pos, Vect protected boolean isLocationChanged(EntityPlayer player, Vector3f pos, Vector3f rot) { // The PlayerAuthInput packet is sent every tick, so don't do anything if the position and rotation were unchanged. var location = player.getLocation(); - return Float.compare(location.x(), pos.getX()) != 0 || Float.compare(location.y() + player.getNetworkOffset(), pos.getY()) != 0 || Float.compare(location.z(), pos.getZ()) != 0 || + return Double.compare(location.x(), pos.getX()) != 0 || Double.compare(location.y() + player.getNetworkOffset(), pos.getY()) != 0 || Double.compare(location.z(), pos.getZ()) != 0 || Double.compare(location.pitch(), rot.getX()) != 0 || Double.compare(location.yaw(), rot.getY()) != 0 || Double.compare(location.headYaw(), rot.getZ()) != 0; } diff --git a/server/src/main/java/org/allaymc/server/world/AllayWorld.java b/server/src/main/java/org/allaymc/server/world/AllayWorld.java index 68b052670..63a1155c3 100644 --- a/server/src/main/java/org/allaymc/server/world/AllayWorld.java +++ b/server/src/main/java/org/allaymc/server/world/AllayWorld.java @@ -13,8 +13,8 @@ import org.allaymc.api.eventbus.event.world.WorldDataSaveEvent; import org.allaymc.api.i18n.I18n; import org.allaymc.api.i18n.TrKeys; -import org.allaymc.api.math.location.Location3f; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3d; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.math.position.Position3i; import org.allaymc.api.math.position.Position3ic; import org.allaymc.api.scheduler.Scheduler; @@ -433,9 +433,9 @@ protected record PacketQueueEntry(EntityPlayer player, BedrockPacket packet, lon protected class SpawnPointChunkLoader implements ChunkLoader { @Override - public Location3fc getLocation() { + public Location3dc getLocation() { var spawnPoint = worldData.getSpawnPoint(); - return new Location3f(spawnPoint.x(), spawnPoint.y(), spawnPoint.z(), getOverWorld()); + return new Location3d(spawnPoint.x(), spawnPoint.y(), spawnPoint.z(), getOverWorld()); } @Override diff --git a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java index 56b9d6f15..049129207 100644 --- a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java +++ b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java @@ -1,7 +1,7 @@ package org.allaymc.server.world.service; import it.unimi.dsi.fastutil.Pair; -import it.unimi.dsi.fastutil.floats.FloatBooleanImmutablePair; +import it.unimi.dsi.fastutil.doubles.DoubleBooleanImmutablePair; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import lombok.extern.slf4j.Slf4j; import org.allaymc.api.block.component.BlockLiquidBaseComponent; @@ -14,8 +14,8 @@ import org.allaymc.api.eventbus.event.entity.EntityMoveEvent; import org.allaymc.api.eventbus.event.player.PlayerMoveEvent; import org.allaymc.api.math.MathUtils; -import org.allaymc.api.math.location.Location3f; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3d; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.math.voxelshape.VoxelShape; import org.allaymc.api.server.Server; import org.allaymc.api.world.Dimension; @@ -32,9 +32,9 @@ import org.allaymc.server.network.processor.impl.ingame.PlayerAuthInputPacketProcessor; import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket; import org.jctools.maps.NonBlockingHashMapLong; -import org.joml.Vector3f; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; +import org.joml.Vector3d; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -54,10 +54,10 @@ @Slf4j public class AllayEntityPhysicsService implements EntityPhysicsService { - public static final FloatBooleanImmutablePair EMPTY_FLOAT_BOOLEAN_PAIR = new FloatBooleanImmutablePair(0, false); + public static final DoubleBooleanImmutablePair EMPTY_FLOAT_BOOLEAN_PAIR = new DoubleBooleanImmutablePair(0, false); - public static final float MOTION_THRESHOLD; - public static final float BLOCK_COLLISION_MOTION; + public static final double MOTION_THRESHOLD; + public static final double BLOCK_COLLISION_MOTION; /** * When the min distance of entity to the collision shape of block is smaller than FAT_AABB_MARGIN, * the entity will be considered as collided with the block. This is used to prevent floating point @@ -66,14 +66,14 @@ public class AllayEntityPhysicsService implements EntityPhysicsService { * This value is actually the value of the y coordinate decimal point when the player stands on the * full block (such as the grass block) */ - public static final float FAT_AABB_MARGIN = 0.00001f; + public static final double FAT_AABB_MARGIN = 0.00001; - private static final float STEPPING_OFFSET = 0.05f; - private static final float MOMENTUM_FACTOR = 0.91f; + private static final double STEPPING_OFFSET = 0.05; + private static final double MOMENTUM_FACTOR = 0.91; - private static final float WATER_FLOW_MOTION = 0.014f; - private static final float LAVA_FLOW_MOTION = 0.002333333f; - private static final float LAVA_FLOW_MOTION_IN_NETHER = 0.007f; + private static final double WATER_FLOW_MOTION = 0.014; + private static final double LAVA_FLOW_MOTION = 0.002333333; + private static final double LAVA_FLOW_MOTION_IN_NETHER = 0.007; private static final int X = 0; private static final int Y = 1; @@ -120,7 +120,7 @@ public void tick() { if (entity.computeLiquidMotion()) { hasLiquidMotion = computeLiquidMotion(entity); } - entity.setMotion(checkMotionThreshold(new Vector3f(entity.getMotion()))); + entity.setMotion(checkMotionThreshold(new Vector3d(entity.getMotion()))); if (applyMotion(entity)) { updatedEntities.put(entity.getRuntimeId(), entity); } @@ -131,7 +131,7 @@ public void tick() { // 2. The entity is stuck in the block // Do not calculate other motion exclude block collision motion computeBlockCollisionMotion(entity, collidedBlocks); - entity.setMotion(checkMotionThreshold(new Vector3f(entity.getMotion()))); + entity.setMotion(checkMotionThreshold(new Vector3d(entity.getMotion()))); if (forceApplyMotion(entity)) { updatedEntities.put(entity.getRuntimeId(), entity); } @@ -168,7 +168,7 @@ protected void computeBlockCollisionMotion(Entity entity, BlockState[][][] colli var minY = (int) floor(aabb.minY()); var minZ = (int) floor(aabb.minZ()); int targetX = 0, targetY = 0, targetZ = 0; - float V = 0; + double V = 0; for (int ox = 0, blocksLength = collidedBlocks.length; ox < blocksLength; ox++) { BlockState[][] sub1 = collidedBlocks[ox]; for (int oy = 0, sub1Length = sub1.length; oy < sub1Length; oy++) { @@ -201,7 +201,7 @@ protected void computeBlockCollisionMotion(Entity entity, BlockState[][][] colli // 2. Centered on the block pos we found (1), find out the best moving direction BlockFace movingDirection = null; var values = BlockFace.values(); - float distanceSqrt = Integer.MAX_VALUE; + double distanceSqrt = Integer.MAX_VALUE; for (int i = values.length - 1; i >= 0; i--) { var blockFace = values[i]; var offsetVec = blockFace.offsetPos(targetX, targetY, targetZ); @@ -228,20 +228,20 @@ protected void computeEntityCollisionMotion(Entity entity) { var collidedEntities = getCachedEntityCollidingResult(entity); collidedEntities.removeIf(e -> !e.computeEntityCollisionMotion()); - var collisionMotion = new Vector3f(0, 0, 0); + var collisionMotion = new Vector3d(0, 0, 0); var location = entity.getLocation(); var pushSpeedReduction = entity.getPushSpeedReduction(); for (var other : collidedEntities) { // https://github.com/lovexyn0827/Discovering-Minecraft/blob/master/Minecraft%E5%AE%9E%E4%BD%93%E8%BF%90%E5%8A%A8%E7%A0%94%E7%A9%B6%E4%B8%8E%E5%BA%94%E7%94%A8/5-Chapter-5.md var ol = other.getLocation(); - var direction = MathUtils.normalizeIfNotZero(new Vector3f(entity.getLocation()).sub(other.getLocation(), new Vector3f())); + var direction = MathUtils.normalizeIfNotZero(new Vector3d(entity.getLocation()).sub(other.getLocation(), new Vector3d())); var distance = max(abs(ol.x() - location.x()), abs(ol.z() - location.z())); if (distance <= 0.01) continue; var k = 0.05f * pushSpeedReduction; if (distance <= 1) { - k *= MathUtils.fastFloatInverseSqrt(distance); + k *= MathUtils.fastDoubleInverseSqrt(distance); } else { k /= distance; } @@ -263,8 +263,8 @@ protected void computeEntityCollisionMotion(Entity entity) { protected boolean computeLiquidMotion(Entity entity) { var hasWaterMotion = new AtomicBoolean(false); var hasLavaMotion = new AtomicBoolean(false); - var waterMotion = new Vector3f(); - var lavaMotion = new Vector3f(); + var waterMotion = new Vector3d(); + var lavaMotion = new Vector3d(); var entityY = entity.getLocation().y(); dimension.forEachBlockStates(entity.getOffsetAABB(), 0, (x, y, z, block) -> { @@ -298,7 +298,7 @@ protected boolean computeLiquidMotion(Entity entity) { return false; } - var finalMotion = new Vector3f(); + var finalMotion = new Vector3d(); if (hasWaterMotion.get()) { // Multiple water flow vector may cancel each other out and let the final motion result // in zero vector, so we still need to use normalizeIfNotZero() here to prevent NaN @@ -325,7 +325,7 @@ protected void updateMotion(Entity entity, boolean hasLiquidMotion) { var speedLevel = entity.getEffectLevel(EffectTypes.SPEED); var slownessLevel = entity.getEffectLevel(EffectTypes.SLOWNESS); var effectFactor = (1f + 0.2f * speedLevel) * (1f - 0.15f * slownessLevel); - float slipperinessMultiplier = 1; + double slipperinessMultiplier = 1; if (!hasLiquidMotion) { // Entity that has liquid motion won't be affected by the friction of the block it stands on slipperinessMultiplier = blockStateStandingOn != null ? blockStateStandingOn.getBlockStateData().friction() : DEFAULT_FRICTION; @@ -337,20 +337,20 @@ protected void updateMotion(Entity entity, boolean hasLiquidMotion) { var velocityFactor = entity.isOnGround() ? entity.getDragFactorOnGround() : entity.getDragFactorInAir(); var acceleration = velocityFactor * movementFactor; if (entity.isOnGround()) { - acceleration *= (float) (effectFactor * pow(DEFAULT_FRICTION / slipperinessMultiplier, 3)); + acceleration *= effectFactor * pow(DEFAULT_FRICTION / slipperinessMultiplier, 3); } var yaw = entity.getLocation().yaw(); - var newMx = (float) (momentumMx + acceleration * sin(yaw)); - var newMz = (float) (momentumMz + acceleration * cos(yaw)); + var newMx = momentumMx + acceleration * sin(yaw); + var newMz = momentumMz + acceleration * cos(yaw); // Skip sprint jump boost because this service does not handle player's movement var newMy = (motion.y() - (entity.hasGravity() ? entity.getGravity() : 0f)) * (1 - entity.getDragFactorInAir()); - entity.setMotion(checkMotionThreshold(new Vector3f(newMx, newMy, newMz))); + entity.setMotion(checkMotionThreshold(new Vector3d(newMx, newMy, newMz))); } - protected Vector3f checkMotionThreshold(Vector3f motion) { + protected Vector3d checkMotionThreshold(Vector3d motion) { if (abs(motion.x) < MOTION_THRESHOLD) motion.x = 0; if (abs(motion.y) < MOTION_THRESHOLD) motion.y = 0; if (abs(motion.z) < MOTION_THRESHOLD) motion.z = 0; @@ -358,13 +358,13 @@ protected Vector3f checkMotionThreshold(Vector3f motion) { } protected boolean forceApplyMotion(Entity entity) { - var loc = new Location3f(entity.getLocation()); + var loc = new Location3d(entity.getLocation()); loc.add(entity.getMotion()); return updateEntityLocation(entity, loc); } protected boolean applyMotion(Entity entity) { - var pos = new Location3f(entity.getLocation()); + var pos = new Location3d(entity.getLocation()); var motion = entity.getMotion(); var mx = motion.x(); var my = motion.y(); @@ -385,7 +385,7 @@ protected boolean applyMotion(Entity entity) { mx = applyMotion0(entity.getStepHeight(), pos, mx, aabb, isOnGround, X); } - entity.setMotion(new Vector3f(mx, my, mz)); + entity.setMotion(new Vector3d(mx, my, mz)); if (!pos.equals(entity.getLocation()) && updateEntityLocation(entity, pos)) { // Update onGround status after updated entity location // to make sure that some block (for example: water) can reset @@ -408,14 +408,14 @@ protected boolean applyMotion(Entity entity) { * * @return The remaining component of the object's movement velocity along the specified axis after considering possible collisions and intersections. */ - private float applyMotion0(float stepHeight, Location3f pos, float motion, AABBf aabb, boolean enableStepping, int axis) { + private double applyMotion0(double stepHeight, Location3d pos, double motion, AABBd aabb, boolean enableStepping, int axis) { if (motion == 0) return motion; if (axis < X || axis > Z) { throw new IllegalArgumentException("Invalid axis: " + axis); } - var resultAABB = new AABBf(aabb); - var resultPos = new Vector3f(pos); + var resultAABB = new AABBd(aabb); + var resultPos = new Vector3d(pos); // The first time directly moves var result = moveAlongAxisAndStopWhenCollision(resultAABB, motion, resultPos, axis); @@ -443,18 +443,18 @@ private float applyMotion0(float stepHeight, Location3f pos, float motion, AABBf * @param recorder The vector to record the movement along the axis. * @param axis The axis along which to move the AABB. Use 0 for the X-axis, 1 for the Y-axis, and 2 for the Z-axis. * - * @return A pair containing the remaining movement distance along the axis after collision detection (Float) + * @return A pair containing the remaining movement distance along the axis after collision detection (Double) * and a boolean indicating whether a collision occurred (Boolean). * If no movement was specified (motion = 0), an empty pair is returned. * * @throws IllegalArgumentException if an invalid axis is provided. */ - private Pair moveAlongAxisAndStopWhenCollision(AABBf aabb, float motion, Vector3f recorder, int axis) { + private Pair moveAlongAxisAndStopWhenCollision(AABBd aabb, double motion, Vector3d recorder, int axis) { if (motion == 0) { return EMPTY_FLOAT_BOOLEAN_PAIR; } - var extendAxis = new AABBf(aabb); + var extendAxis = new AABBd(aabb); // Move towards the negative(motion < 0) or positive(motion > 0) axis direction var shouldTowardsNegative = motion < 0; @@ -489,7 +489,7 @@ private Pair moveAlongAxisAndStopWhenCollision(AABBf aabb, float collision = axis != Y || shouldTowardsNegative; // There is a collision - var minAxis = (float) floor(extendAxis.getMin(axis)); + var minAxis = floor(extendAxis.getMin(axis)); var maxAxis = computeMax(minAxis, axis, blocks); // Calculate the ray axis starting coordinate var coordinate = shouldTowardsNegative ? aabb.getMin(axis) : aabb.getMax(axis); @@ -516,20 +516,20 @@ private Pair moveAlongAxisAndStopWhenCollision(AABBf aabb, float // Update the coordinates recorder.setComponent(axis, recorder.get(axis) + deltaAxis); - return new FloatBooleanImmutablePair(motion, collision); + return new DoubleBooleanImmutablePair(motion, collision); } // Do not use dimension.isAABBInDimension(extendX|Y|Z) because entity should be able to move even if y > maxHeight - protected boolean notValidEntityArea(AABBf extendAABB) { + protected boolean notValidEntityArea(AABBd extendAABB) { return (extendAABB.minY < dimension.getDimensionInfo().minHeight()) && !dimension.getChunkService().isChunkLoaded((int) extendAABB.minX >> 4, (int) extendAABB.minZ >> 4) && !dimension.getChunkService().isChunkLoaded((int) extendAABB.maxX >> 4, (int) extendAABB.maxZ >> 4); } - protected boolean tryStepping(Vector3f pos, AABBf aabb, float stepHeight, boolean positive, boolean xAxis) { + protected boolean tryStepping(Vector3d pos, AABBd aabb, double stepHeight, boolean positive, boolean xAxis) { var offset = positive ? STEPPING_OFFSET : -STEPPING_OFFSET; - var offsetAABB = aabb.translate(xAxis ? offset : 0, 0, xAxis ? 0 : offset, new AABBf()); - var recorder = new Vector3f(); + var offsetAABB = aabb.translate(xAxis ? offset : 0, 0, xAxis ? 0 : offset, new AABBd()); + var recorder = new Vector3d(); moveAlongAxisAndStopWhenCollision(offsetAABB, stepHeight, recorder, Y); moveAlongAxisAndStopWhenCollision(offsetAABB, -stepHeight, recorder, Y); if (recorder.y == 0 || dimension.getCollidingBlockStates(offsetAABB) != null) { @@ -541,8 +541,8 @@ protected boolean tryStepping(Vector3f pos, AABBf aabb, float stepHeight, boolea } } - protected float computeMax(float start, int axis, BlockState[][][] blocks) { - float max = start; + protected double computeMax(double start, int axis, BlockState[][][] blocks) { + double max = start; for (int ox = 0, blocksLength = blocks.length; ox < blocksLength; ox++) { BlockState[][] sub1 = blocks[ox]; for (int oy = 0, sub1Length = sub1.length; oy < sub1Length; oy++) { @@ -550,7 +550,7 @@ protected float computeMax(float start, int axis, BlockState[][][] blocks) { for (int oz = 0, sub2Length = sub2.length; oz < sub2Length; oz++) { BlockState blockState = sub2[oz]; if (blockState == null) continue; - float current; + double current; var unionAABB = blockState.getBlockStateData().collisionShape().unionAABB(); switch (axis) { case X -> current = unionAABB.lengthX() + start + ox; @@ -592,7 +592,7 @@ protected void handleClientMoveQueue() { } // Calculate delta pos (motion) - var motion = event.getTo().sub(player.getLocation(), new Vector3f()); + var motion = event.getTo().sub(player.getLocation(), new Vector3d()); baseComponent.setMotionValueOnly(motion); if (updateEntityLocation(player, clientMove.newLoc())) { entityAABBTree.update(player); @@ -607,7 +607,7 @@ protected void handleClientMoveQueue() { } } - protected boolean updateEntityLocation(Entity entity, Location3fc newLoc) { + protected boolean updateEntityLocation(Entity entity, Location3dc newLoc) { var event = new EntityMoveEvent(entity, entity.getLocation(), newLoc); if (!event.call()) { return false; @@ -652,7 +652,7 @@ public void removeEntity(Entity entity) { * Please note that this method usually been called asynchronously

* See {@link PlayerAuthInputPacketProcessor#handleAsync(EntityPlayer, PlayerAuthInputPacket, long)} */ - public void offerClientMove(EntityPlayer player, Location3fc newLoc) { + public void offerClientMove(EntityPlayer player, Location3dc newLoc) { if (!entities.containsKey(player.getRuntimeId()) || player.getLocation().equals(newLoc)) { return; } @@ -661,7 +661,7 @@ public void offerClientMove(EntityPlayer player, Location3fc newLoc) { } @Override - public List computeCollidingEntities(AABBfc aabb, AABBOverlapFilter predicate) { + public List computeCollidingEntities(AABBdc aabb, AABBOverlapFilter predicate) { var result = new LinkedList(); entityAABBTree.detectOverlaps(aabb, predicate, result); return result; @@ -685,5 +685,5 @@ public List getCachedEntityCollidingResult(Entity entity, boolean ignore return result; } - protected record ClientMove(EntityPlayer player, Location3fc newLoc) {} + protected record ClientMove(EntityPlayer player, Location3dc newLoc) {} } diff --git a/server/src/test/java/org/allaymc/api/block/data/BlockFaceTest.java b/server/src/test/java/org/allaymc/api/block/data/BlockFaceTest.java index becae5161..b368c036d 100644 --- a/server/src/test/java/org/allaymc/api/block/data/BlockFaceTest.java +++ b/server/src/test/java/org/allaymc/api/block/data/BlockFaceTest.java @@ -1,6 +1,6 @@ package org.allaymc.api.block.data; -import org.joml.Vector3f; +import org.joml.Vector3d; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -26,12 +26,12 @@ class BlockFaceTest { */ @Test void testRotateVector() { - var vec = new Vector3f(0.1f, 0.2f, 0.3f); + var vec = new Vector3d(0.1, 0.2, 0.3); assertEquals(vec.toString(), BlockFace.EAST.rotateVector(vec).toString()); - assertEquals(new Vector3f(0.2f, 0.9f, 0.3f).toString(), BlockFace.DOWN.rotateVector(vec).toString()); - assertEquals(new Vector3f(0.8f, 0.1f, 0.3f).toString(), BlockFace.UP.rotateVector(vec).toString()); - assertEquals(new Vector3f(0.9f, 0.2f, 0.7f).toString(), BlockFace.WEST.rotateVector(vec).toString()); - assertEquals(new Vector3f(0.7f, 0.2f, 0.1f).toString(), BlockFace.SOUTH.rotateVector(vec).toString()); - assertEquals(new Vector3f(0.3f, 0.2f, 0.9f).toString(), BlockFace.NORTH.rotateVector(vec).toString()); + assertEquals(new Vector3d(0.2, 0.9, 0.3).toString(), BlockFace.DOWN.rotateVector(vec).toString()); + assertEquals(new Vector3d(0.8, 0.1, 0.3).toString(), BlockFace.UP.rotateVector(vec).toString()); + assertEquals(new Vector3d(0.9, 0.2, 0.7).toString(), BlockFace.WEST.rotateVector(vec).toString()); + assertEquals(new Vector3d(0.7, 0.2, 0.1).toString(), BlockFace.SOUTH.rotateVector(vec).toString()); + assertEquals(new Vector3d(0.3, 0.2, 0.9).toString(), BlockFace.NORTH.rotateVector(vec).toString()); } } \ No newline at end of file diff --git a/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java b/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java index 6fac2dc17..1c007d16b 100644 --- a/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java +++ b/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java @@ -1,8 +1,8 @@ package org.allaymc.api.math.voxelshape; import org.allaymc.api.block.data.BlockFace; -import org.joml.Vector3f; -import org.joml.primitives.AABBf; +import org.joml.Vector3d; +import org.joml.primitives.AABBd; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -16,17 +16,17 @@ void testStairShape() { var vs = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.5f, 0.5f, 0, 1, 1, 1) + .vacancy(0.5, 0.5, 0, 1, 1, 1) .build(); - assertFalse(vs.intersectsPoint(0.75f, 0.75f, 0.5f)); - var aabb = new AABBf(0.51f, 0.51f, 0.01f, 0.99f, 0.99f, 0.99f); + assertFalse(vs.intersectsPoint(0.75, 0.75, 0.5)); + var aabb = new AABBd(0.51, 0.51, 0.01, 0.99, 0.99, 0.99); assertFalse(vs.intersectsAABB(aabb)); var vs2 = vs.rotate(BlockFace.SOUTH); - assertFalse(vs2.intersectsPoint(0.5f, 0.75f, 0.75f)); + assertFalse(vs2.intersectsPoint(0.5, 0.75, 0.75)); var vs3 = vs.rotate(BlockFace.NORTH); - assertFalse(vs3.intersectsPoint(0.5f, 0.75f, 0.25f)); + assertFalse(vs3.intersectsPoint(0.5, 0.75, 0.25)); } @Test @@ -34,15 +34,15 @@ void testCauldronShape() { var vs = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.1f, 0.1f, 0.1f, 0.9f, 0.9f, 0.9f) + .vacancy(0.1, 0.1, 0.1, 0.9, 0.9, 0.9) .build(); - assertFalse(vs.intersectsPoint(0.5f, 0.5f, 0.5f)); - assertTrue(vs.intersectsPoint(0.5f, 0.5f, 0.05f)); - assertFalse(vs.intersectsPoint(new Vector3f(0.5f, 0.5f, 0.5f))); - assertTrue(vs.intersectsPoint(new Vector3f(0.5f, 0.5f, 0.05f))); + assertFalse(vs.intersectsPoint(0.5, 0.5, 0.5)); + assertTrue(vs.intersectsPoint(0.5, 0.5, 0.05)); + assertFalse(vs.intersectsPoint(new Vector3d(0.5, 0.5, 0.5))); + assertTrue(vs.intersectsPoint(new Vector3d(0.5, 0.5, 0.05))); - var aabb = new AABBf(0.2f, 0.2f, 0.2f, 0.8f, 0.8f, 0.8f); + var aabb = new AABBd(0.2, 0.2, 0.2, 0.8, 0.8, 0.8); assertFalse(vs.intersectsAABB(aabb)); } @@ -51,10 +51,10 @@ void testTranslate() { var vs = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.1f, 0.1f, 0.1f, 0.9f, 0.9f, 0.9f) + .vacancy(0.1, 0.1, 0.1, 0.9, 0.9, 0.9) .build(); validateTranslateResult(vs.translate(1, 1, 1)); - validateTranslateResult(vs.translate(new Vector3f(1, 1, 1))); + validateTranslateResult(vs.translate(new Vector3d(1, 1, 1))); } void validateTranslateResult(VoxelShape vs) { @@ -66,12 +66,12 @@ void validateTranslateResult(VoxelShape vs) { assertEquals(2, solid.maxY()); assertEquals(2, solid.maxZ()); var vacancy = vs.getVacancies().iterator().next(); - assertEquals(1.1f, vacancy.minX()); - assertEquals(1.1f, vacancy.minY()); - assertEquals(1.1f, vacancy.minZ()); - assertEquals(1.9f, vacancy.maxX()); - assertEquals(1.9f, vacancy.maxY()); - assertEquals(1.9f, vacancy.maxZ()); + assertEquals(1.1, vacancy.minX()); + assertEquals(1.1, vacancy.minY()); + assertEquals(1.1, vacancy.minZ()); + assertEquals(1.9, vacancy.maxX()); + assertEquals(1.9, vacancy.maxY()); + assertEquals(1.9, vacancy.maxZ()); } @Test @@ -88,7 +88,7 @@ void testIsFull() { var vs2 = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.4f, 0, 0.4f, 0.6f, 1, 0.6f) + .vacancy(0.4, 0, 0.4, 0.6, 1, 0.6) .build(); assertFalse(vs2.isFull(BlockFace.UP)); @@ -100,7 +100,7 @@ void testIsFull() { var vs3 = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.4f, 0.4f, 0.4f, 0.6f, 0.6f, 0.6f) + .vacancy(0.4, 0.4, 0.4, 0.6, 0.6, 0.6) .build(); for (var face : BlockFace.values()) { @@ -109,7 +109,7 @@ void testIsFull() { var vs4 = VoxelShape .builder() - .solid(0, 0, 0, 0.5f, 1, 1) + .solid(0, 0, 0, 0.5, 1, 1) .build(); assertFalse(vs4.isFull(BlockFace.UP)); @@ -151,7 +151,7 @@ void testIsCenterFull() { var vs2 = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.45f, 0, 0.45f, 0.55f, 1, 0.55f) + .vacancy(0.45, 0, 0.45, 0.55, 1, 0.55) .build(); assertFalse(vs2.isCenterFull(BlockFace.UP)); @@ -163,7 +163,7 @@ void testIsCenterFull() { var vs3 = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.35f, 0.35f, 0.35f, 0.65f, 0.65f, 0.65f) + .vacancy(0.35, 0.35, 0.35, 0.65, 0.65, 0.65) .build(); for (var face : BlockFace.values()) { @@ -172,7 +172,7 @@ void testIsCenterFull() { var vs4 = VoxelShape .builder() - .solid(0.375f, 0, 0.375f, 0.625f, 1, 0.625f) + .solid(0.375, 0, 0.375, 0.625, 1, 0.625) .build(); assertTrue(vs4.isCenterFull(BlockFace.UP)); @@ -195,14 +195,14 @@ void testIsFullBlock() { var vs2 = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.4f, 0, 0.4f, 0.6f, 1, 0.6f) + .vacancy(0.4, 0, 0.4, 0.6, 1, 0.6) .build(); assertFalse(vs2.isFullBlock()); // 部分支撑面不完整 var vs3 = VoxelShape .builder() - .solid(0, 0, 0, 1, 0.5f, 1) + .solid(0, 0, 0, 1, 0.5, 1) .build(); assertFalse(vs3.isFullBlock()); } @@ -220,7 +220,7 @@ void testIsEdgeFull() { var vs2 = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.0f, 0.0f, 0.0f, 0.125f, 1, 0.125f) + .vacancy(0.0, 0.0, 0.0, 0.125, 1, 0.125) .build(); for (var face : BlockFace.getVerticalBlockFaces()) { assertFalse(vs2.isEdgeFull(face)); @@ -228,7 +228,7 @@ void testIsEdgeFull() { var vs3 = VoxelShape .builder() - .solid(0, 0, 0, 0.125f, 1, 1) + .solid(0, 0, 0, 0.125, 1, 1) .build(); assertTrue(vs3.isEdgeFull(BlockFace.WEST)); assertFalse(vs3.isEdgeFull(BlockFace.EAST)); @@ -240,14 +240,14 @@ void testIsEdgeFull() { var vs4 = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.2f, 0.8f, 0.2f, 0.8f, 1, 0.8f) + .vacancy(0.2, 0.8, 0.2, 0.8, 1, 0.8) .build(); assertTrue(vs4.isEdgeFull(BlockFace.UP)); var vs5 = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.1f, 0.8f, 0.1f, 0.9f, 1, 0.9f) + .vacancy(0.1, 0.8, 0.1, 0.9, 1, 0.9) .build(); assertFalse(vs5.isEdgeFull(BlockFace.UP)); } @@ -263,16 +263,16 @@ void testIntersectsRay() { var vs2 = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.1f, 0.1f, 0.1f, 0.9f, 0.9f, 0.9f) + .vacancy(0.1, 0.1, 0.1, 0.9, 0.9, 0.9) .build(); assertTrue(vs2.intersectsRay(0, 0, 0, 1, 1, 1)); var vs3 = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.4f, 0, 0.4f, 0.6f, 1, 0.6f) + .vacancy(0.4, 0, 0.4, 0.6, 1, 0.6) .build(); - assertFalse(vs3.intersectsRay(0.5f, 0, 0.5f, 0.5f, 1, 0.5f)); + assertFalse(vs3.intersectsRay(0.5, 0, 0.5, 0.5, 1, 0.5)); var vs4 = VoxelShape .builder() @@ -284,29 +284,29 @@ void testIntersectsRay() { var vs5 = VoxelShape .builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0, 0, 0, 1, 0.4f, 1) - .vacancy(0, 0.6f, 0, 1, 1, 1) + .vacancy(0, 0, 0, 1, 0.4, 1) + .vacancy(0, 0.6, 0, 1, 1, 1) .build(); assertTrue(vs5.intersectsRay(0, 0, 0, 1, 1, 1)); var vs6 = VoxelShape .builder() - .vacancy(0, 0.4f, 0, 1, 0.6f, 1) - .solid(0, 0, 0, 1, 0.4f, 1) - .solid(0, 0.6f, 0, 1, 1, 1) + .vacancy(0, 0.4, 0, 1, 0.6, 1) + .solid(0, 0, 0, 1, 0.4, 1) + .solid(0, 0.6, 0, 1, 1, 1) .build(); assertTrue(vs6.intersectsRay(0, 0, 0, 1, 1, 1)); - assertFalse(vs6.intersectsRay(0, 0.4f, 0, 1, 0.4f, 1)); - assertFalse(vs6.intersectsRay(0, 0.41f, 0, 1, 0.41f, 1)); - assertFalse(vs6.intersectsRay(0, 0.59f, 0, 1, 0.59f, 1)); - assertFalse(vs6.intersectsRay(0, 0.6f, 0, 1, 0.6f, 1)); + assertFalse(vs6.intersectsRay(0, 0.4, 0, 1, 0.4, 1)); + assertFalse(vs6.intersectsRay(0, 0.41, 0, 1, 0.41, 1)); + assertFalse(vs6.intersectsRay(0, 0.59, 0, 1, 0.59, 1)); + assertFalse(vs6.intersectsRay(0, 0.6, 0, 1, 0.6, 1)); var vs7 = VoxelShape .builder() - .solid(0, 0, 0, 1, 0.9f, 1) - .solid(0, 0.1f, 0, 1, 1, 1) - .vacancy(0.4f, 0, 0.4f, 0.6f, 1, 0.6f) + .solid(0, 0, 0, 1, 0.9, 1) + .solid(0, 0.1, 0, 1, 1, 1) + .vacancy(0.4, 0, 0.4, 0.6, 1, 0.6) .build(); - assertFalse(vs7.intersectsRay(0.5f, 0, 0.5f, 0.5f, 1, 0.5f)); + assertFalse(vs7.intersectsRay(0.5, 0, 0.5, 0.5, 1, 0.5)); } } \ No newline at end of file diff --git a/server/src/test/java/org/allaymc/server/block/BlockStateDataTest.java b/server/src/test/java/org/allaymc/server/block/BlockStateDataTest.java index 5064d9834..d5f372f76 100644 --- a/server/src/test/java/org/allaymc/server/block/BlockStateDataTest.java +++ b/server/src/test/java/org/allaymc/server/block/BlockStateDataTest.java @@ -54,12 +54,12 @@ void testDeserialization() { assertEquals(0, blockStateData.burnOdds()); assertFalse(blockStateData.canContainLiquidSource()); var unionAABB = blockStateData.collisionShape().unionAABB(); - assertEquals(0.0005f, unionAABB.minX()); - assertEquals(0.0005f, unionAABB.minY()); - assertEquals(0.0005f, unionAABB.minZ()); - assertEquals(0.9995f, unionAABB.maxX()); - assertEquals(0.1825f, unionAABB.maxY()); - assertEquals(0.9995f, unionAABB.maxZ()); + assertEquals(0.0005, unionAABB.minX()); + assertEquals(0.0005, unionAABB.minY()); + assertEquals(0.0005, unionAABB.minZ()); + assertEquals(0.9995, unionAABB.maxX()); + assertEquals(0.1825, unionAABB.maxY()); + assertEquals(0.9995, unionAABB.maxZ()); assertEquals(1.25f, blockStateData.hardness()); assertEquals(1.25f, blockStateData.explosionResistance()); assertEquals(0, blockStateData.flameOdds()); diff --git a/server/src/test/java/org/allaymc/server/command/CommandTreeTest.java b/server/src/test/java/org/allaymc/server/command/CommandTreeTest.java index 1682ad11c..5686bfdd3 100644 --- a/server/src/test/java/org/allaymc/server/command/CommandTreeTest.java +++ b/server/src/test/java/org/allaymc/server/command/CommandTreeTest.java @@ -4,11 +4,11 @@ import org.allaymc.api.command.CommandSender; import org.allaymc.api.command.tree.CommandContext; import org.allaymc.api.command.tree.CommandNodeFactory; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.api.utils.Utils; import org.allaymc.server.command.tree.AllayCommandNodeFactory; import org.allaymc.server.command.tree.AllayCommandTree; -import org.joml.Vector3f; +import org.joml.Vector3d; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -23,7 +23,7 @@ public class CommandTreeTest { static Command mockCmd = Mockito.mock(Command.class); static CommandSender mockSender = Mockito.mock(CommandSender.class); - static Location3f cmdExecLoc = new Location3f(0, 0, 0, null); + static Location3d cmdExecLoc = new Location3d(0, 0, 0, null); @BeforeAll static void init() { @@ -158,24 +158,24 @@ void testComplexOptionalNode() { @Test void testPosNode() { var tree = AllayCommandTree.create(mockCmd); - Vector3f dest = new Vector3f(); + Vector3d dest = new Vector3d(); tree.getRoot() .pos("pos") .exec(context -> { - dest.set((Vector3f) context.getResult(0)); + dest.set((Vector3d) context.getResult(0)); return context.success(); }); tree.parse(mockSender, new String[]{"11", "45", "14"}); - assertEquals(new Vector3f(11, 45, 14), dest); + assertEquals(new Vector3d(11, 45, 14), dest); cmdExecLoc.set(19, 19, 810); tree.parse(mockSender, new String[]{"~1", "~2", "~3"}); - assertEquals(new Vector3f(19 + 1, 19 + 2, 810 + 3), dest); + assertEquals(new Vector3d(19 + 1, 19 + 2, 810 + 3), dest); tree.parse(mockSender, new String[]{"~-1", "~-2", "~-3"}); - assertEquals(new Vector3f(19 - 1, 19 - 2, 810 - 3), dest); + assertEquals(new Vector3d(19 - 1, 19 - 2, 810 - 3), dest); tree.parse(mockSender, new String[]{"~1.5", "~2.5", "~3.5"}); - assertEquals(new Vector3f(19 + 1.5f, 19 + 2.5f, 810 + 3.5f), dest); + assertEquals(new Vector3d(19 + 1.5f, 19 + 2.5f, 810 + 3.5f), dest); tree.parse(mockSender, new String[]{"19", "19", "810"}); - assertEquals(new Vector3f(19, 19, 810), dest); + assertEquals(new Vector3d(19, 19, 810), dest); } @Test diff --git a/server/src/test/java/org/allaymc/server/command/selector/ParseUtilsTest.java b/server/src/test/java/org/allaymc/server/command/selector/ParseUtilsTest.java index 13badde7c..d071a1ec1 100644 --- a/server/src/test/java/org/allaymc/server/command/selector/ParseUtilsTest.java +++ b/server/src/test/java/org/allaymc/server/command/selector/ParseUtilsTest.java @@ -33,6 +33,17 @@ void testParseOffsetFloat() { assertEquals(0.0f, parseOffsetFloat("~-1.0", base)); } + @SneakyThrows + @Test + void testParseOffsetDouble() { + var base = 1.0; + assertEquals(1.0, parseOffsetDouble("1.0", base)); + assertEquals(1.0, parseOffsetDouble("1.0", 2.0)); + assertEquals(1.0, parseOffsetDouble("~", base)); + assertEquals(2.0, parseOffsetDouble("~1.0", base)); + assertEquals(0.0, parseOffsetDouble("~-1.0", base)); + } + @Test void testCheckReversed() { assertFalse(checkReversed("xxx")); diff --git a/server/src/test/java/org/allaymc/server/datastruct/aabbtree/AABBTreeTest.java b/server/src/test/java/org/allaymc/server/datastruct/aabbtree/AABBTreeTest.java index 34efeb188..c9f15e447 100644 --- a/server/src/test/java/org/allaymc/server/datastruct/aabbtree/AABBTreeTest.java +++ b/server/src/test/java/org/allaymc/server/datastruct/aabbtree/AABBTreeTest.java @@ -3,7 +3,7 @@ import org.allaymc.server.datastruct.aabb.AABBTree; import org.allaymc.server.datastruct.aabb.AABBTreeNode; import org.allaymc.server.datastruct.aabb.CollisionPair; -import org.joml.primitives.AABBf; +import org.joml.primitives.AABBd; import org.joml.primitives.Rayf; import org.junit.jupiter.api.Test; @@ -21,7 +21,7 @@ public class AABBTreeTest { public void shouldAddAnObjectToTheTree() { // Given AABBTree tree = givenTree(); - TestEntity entity = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); // When tree.add(entity); @@ -34,7 +34,7 @@ public void shouldAddAnObjectToTheTree() { public void shouldNotAddTheSameObjectTwice() { // Given AABBTree tree = givenTree(); - TestEntity entity = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); // When tree.add(entity); @@ -51,8 +51,8 @@ public void shouldNotAddTheSameObjectTwice() { public void shouldAddTwoObjectsToTheTreeByCreatingABranch() { // Given AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); // When tree.add(entity1); @@ -70,8 +70,8 @@ public void shouldAddTwoObjectsToTheTreeByCreatingABranch() { public void shouldCorrectlyCalculateHeights() { // Given AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); // When tree.add(entity1); @@ -88,9 +88,9 @@ public void shouldCorrectlyCalculateHeights() { public void shouldCorrectlyCalculateHeightsInAMoreComplexCase() { // Given AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity3 = new TestEntity(3, 5.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); + TestEntity entity3 = new TestEntity(3, 5.0, 0.0, 10.0, 10.0); // When tree.add(entity1); @@ -113,11 +113,11 @@ public void shouldCorrectlyCalculateHeightsInAMoreComplexCase() { public void shouldCorrectlyCalculateHeightsInAnEvenMoreComplexCase() { // Given AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity3 = new TestEntity(3, 5.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity4 = new TestEntity(4, 15.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity5 = new TestEntity(5, -25.0f, 10.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); + TestEntity entity3 = new TestEntity(3, 5.0, 0.0, 10.0, 10.0); + TestEntity entity4 = new TestEntity(4, 15.0, 0.0, 10.0, 10.0); + TestEntity entity5 = new TestEntity(5, -25.0, 10.0, 10.0, 10.0); // When tree.add(entity1); @@ -146,9 +146,9 @@ public void shouldCorrectlyCalculateHeightsInAnEvenMoreComplexCase() { public void shouldCorrectlyCalculateHeightsAfterRemovingAnObject() { // Given AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity3 = new TestEntity(3, 5.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); + TestEntity entity3 = new TestEntity(3, 5.0, 0.0, 10.0, 10.0); tree.add(entity1); tree.add(entity2); tree.add(entity3); @@ -169,7 +169,7 @@ public void shouldCorrectlyCalculateHeightsAfterRemovingAnObject() { public void shouldRemoveAnObjectFromTheTree() { // Given AABBTree tree = givenTree(); - TestEntity entity = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); tree.add(entity); // When @@ -183,7 +183,7 @@ public void shouldRemoveAnObjectFromTheTree() { public void shouldRemovingAnObjectMarkANodeFree() { // Given AABBTree tree = givenTree(); - TestEntity entity = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); tree.add(entity); // When @@ -198,8 +198,8 @@ public void shouldRemovingAnObjectMarkANodeFree() { public void shouldRemovingAnObjectInAMoreComplexTreeMarkNodesFree() { // Given AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); tree.add(entity1); tree.add(entity2); @@ -216,8 +216,8 @@ public void shouldRemovingAnObjectInAMoreComplexTreeMarkNodesFree() { public void shouldContainsReturnTrueIfAnObjectIsAddedToTheTree() { // Given AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); // When tree.add(entity1); @@ -231,8 +231,8 @@ public void shouldContainsReturnTrueIfAnObjectIsAddedToTheTree() { public void shouldClearTheTree() { // Given AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); tree.add(entity1); // When @@ -249,10 +249,10 @@ public void shouldClearTheTree() { @Test public void shouldNotDetectAABBOverlaps() { // Given - AABBf testForOverlap = new AABBf(1.0f, 10.5f, 0.0f, 2.0f, 10.0f, 0.0f); + AABBd testForOverlap = new AABBd(1.0, 10.5, 0.0, 2.0, 10.0, 0.0); AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); tree.add(entity1); tree.add(entity2); @@ -267,10 +267,10 @@ public void shouldNotDetectAABBOverlaps() { @Test public void shouldDetectAABBOverlaps() { // Given - AABBf testForOverlap = new AABBf(1.0f, 5.1f, 0.0f, 2.0f, 10.0f, 0.0f); + AABBd testForOverlap = new AABBd(1.0, 5.1, 0.0, 2.0, 10.0, 0.0); AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, -20.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, -20.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); tree.add(entity1); tree.add(entity2); @@ -286,10 +286,10 @@ public void shouldDetectAABBOverlaps() { @Test public void shouldDetectAABBOverlapsWithFiltering() { // Given - AABBf testForOverlap = new AABBf(1.0f, 5.1f, 0.0f, 2.0f, 10.0f, 0.0f); + AABBd testForOverlap = new AABBd(1.0, 5.1, 0.0, 2.0, 10.0, 0.0); AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); tree.add(entity1); tree.add(entity2); @@ -309,9 +309,9 @@ public void shouldDetectAABBOverlapsWithFiltering() { public void shouldDetectCollidingPairs() { // Given AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity3 = new TestEntity(3, 11.0f, 0.0f, 10.0f, 10.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); + TestEntity entity3 = new TestEntity(3, 11.0, 0.0, 10.0, 10.0); tree.add(entity1); tree.add(entity2); tree.add(entity3); @@ -331,10 +331,10 @@ public void shouldDetectCollidingPairs() { public void shouldDetectCollidingPairsWithFiltering() { // Given AABBTree tree = givenTree(); - TestEntity entity1 = new TestEntity(1, 0.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity3 = new TestEntity(3, 11.0f, 0.0f, 10.0f, 10.0f); - TestEntity entity4 = new TestEntity(4, -6.0f, 0.0f, 3.0f, 1.0f); + TestEntity entity1 = new TestEntity(1, 0.0, 0.0, 10.0, 10.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 10.0, 10.0); + TestEntity entity3 = new TestEntity(3, 11.0, 0.0, 10.0, 10.0); + TestEntity entity4 = new TestEntity(4, -6.0, 0.0, 3.0, 1.0); tree.add(entity1); tree.add(entity2); tree.add(entity3); @@ -359,8 +359,8 @@ public void shouldDetectRayIntersection() { // Given AABBTree tree = givenTree(); Rayf ray = new Rayf(0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f); - TestEntity entity1 = new TestEntity(1, 2.0f, 0.0f, 3.0f, 3.0f); - TestEntity entity2 = new TestEntity(2, -5.0f, 0.0f, 3.0f, 2.0f); + TestEntity entity1 = new TestEntity(1, 2.0, 0.0, 3.0, 3.0); + TestEntity entity2 = new TestEntity(2, -5.0, 0.0, 3.0, 2.0); tree.add(entity1); tree.add(entity2); @@ -376,7 +376,7 @@ public void shouldDetectRayIntersection() { @Test public void shouldRestoreNodeToInitialStateOnReuse() { // Given - TestEntity entity = new TestEntity(1, 0.0f, 0.0f, 1.0f, 1.0f); + TestEntity entity = new TestEntity(1, 0.0, 0.0, 1.0, 1.0); AABBTreeNode node = new AABBTreeNode<>(); // When @@ -391,7 +391,7 @@ public void shouldRestoreNodeToInitialStateOnReuse() { // Then assertEquals(INVALID_NODE_INDEX, node.getLeftChild()); assertEquals(INVALID_NODE_INDEX, node.getRightChild()); - assertEquals(new AABBf(), node.getAabb()); + assertEquals(new AABBd(), node.getAabb()); assertEquals(INVALID_NODE_INDEX, node.getParent()); assertEquals(0, node.getHeight()); assertNull(node.getData()); diff --git a/server/src/test/java/org/allaymc/server/datastruct/aabbtree/TestEntity.java b/server/src/test/java/org/allaymc/server/datastruct/aabbtree/TestEntity.java index 552d3bdec..70ee07e9e 100644 --- a/server/src/test/java/org/allaymc/server/datastruct/aabbtree/TestEntity.java +++ b/server/src/test/java/org/allaymc/server/datastruct/aabbtree/TestEntity.java @@ -3,8 +3,8 @@ import lombok.Getter; import org.allaymc.api.world.service.HasAABB; import org.allaymc.api.world.service.HasLongId; -import org.joml.primitives.AABBf; -import org.joml.primitives.AABBfc; +import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; /** * @author daoge_cmd @@ -12,15 +12,15 @@ @Getter public class TestEntity implements HasAABB, HasLongId { - private final float x, y, z; - private final float width, height, length; + private final double x, y, z; + private final double width, height, length; private final int id; - public TestEntity(int id, float x, float y, float width, float height) { + public TestEntity(int id, double x, double y, double width, double height) { this(id, x, y, 0, width, height, 0); } - public TestEntity(int id, float x, float y, float z, float width, float height, float length) { + public TestEntity(int id, double x, double y, double z, double width, double height, double length) { this.id = id; this.x = x; this.y = y; @@ -31,18 +31,18 @@ public TestEntity(int id, float x, float y, float z, float width, float height, } @Override - public AABBfc getOffsetAABB() { - var dest = new AABBf(); + public AABBdc getOffsetAABB() { + var dest = new AABBd(); dest.setMin(x, y, z); dest.setMax(x + width, y + height, z + length); return dest; } @Override - public AABBfc getAABB() { - return new AABBf( - -width / 2f, 0, -length / 2f, - width / 2f, height, length / 2f + public AABBdc getAABB() { + return new AABBd( + -width / 2, 0, -length / 2, + width / 2, height, length / 2 ); } diff --git a/server/src/test/java/org/allaymc/server/entity/type/AllayEntityTypeTest.java b/server/src/test/java/org/allaymc/server/entity/type/AllayEntityTypeTest.java index c599cfd01..337ecaa64 100644 --- a/server/src/test/java/org/allaymc/server/entity/type/AllayEntityTypeTest.java +++ b/server/src/test/java/org/allaymc/server/entity/type/AllayEntityTypeTest.java @@ -3,7 +3,7 @@ import org.allaymc.api.entity.initinfo.EntityInitInfo; import org.allaymc.api.entity.interfaces.EntitySheep; import org.allaymc.api.entity.type.EntityTypes; -import org.allaymc.api.math.location.Location3f; +import org.allaymc.api.math.location.Location3d; import org.allaymc.api.world.Dimension; import org.allaymc.testutils.AllayTestExtension; import org.junit.jupiter.api.BeforeAll; @@ -28,6 +28,6 @@ static void init() { @Test void testCommon() { - assertEquals(new Location3f(0f, 1f, 2f, 0, 0, 0, mockDimension), sheep.getLocation()); + assertEquals(new Location3d(0f, 1f, 2f, 0, 0, 0, mockDimension), sheep.getLocation()); } } \ No newline at end of file diff --git a/server/src/test/java/org/allaymc/server/world/service/TestChunkLoader.java b/server/src/test/java/org/allaymc/server/world/service/TestChunkLoader.java index b041892f7..73a4c8d69 100644 --- a/server/src/test/java/org/allaymc/server/world/service/TestChunkLoader.java +++ b/server/src/test/java/org/allaymc/server/world/service/TestChunkLoader.java @@ -3,8 +3,8 @@ import lombok.Getter; import lombok.Setter; import org.allaymc.api.entity.Entity; -import org.allaymc.api.math.location.Location3f; -import org.allaymc.api.math.location.Location3fc; +import org.allaymc.api.math.location.Location3d; +import org.allaymc.api.math.location.Location3dc; import org.allaymc.api.world.chunk.Chunk; import org.allaymc.api.world.chunk.ChunkLoader; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; @@ -28,7 +28,7 @@ public class TestChunkLoader implements ChunkLoader { protected boolean loaderActive = true; @Getter @Setter - protected Location3fc location = new Location3f(0, 0, 0, null); + protected Location3dc location = new Location3d(0, 0, 0, null); @Override public void sendPacket(BedrockPacket packet) { From 27cdeff01b9dcabc158de6db7251f10b89158082 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Tue, 4 Feb 2025 05:52:26 +0800 Subject: [PATCH 03/12] feat: use our own joml-primitives fork --- api/src/main/java/org/allaymc/api/math/MathUtils.java | 10 ---------- .../org/allaymc/api/math/voxelshape/VoxelShape.java | 3 +-- gradle/libs.versions.toml | 2 +- .../org/allaymc/server/datastruct/aabb/AABBTree.java | 11 +++++------ 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/api/src/main/java/org/allaymc/api/math/MathUtils.java b/api/src/main/java/org/allaymc/api/math/MathUtils.java index 190ff8027..1275af28d 100644 --- a/api/src/main/java/org/allaymc/api/math/MathUtils.java +++ b/api/src/main/java/org/allaymc/api/math/MathUtils.java @@ -4,7 +4,6 @@ import org.allaymc.api.math.location.Location3fc; import org.joml.*; import org.joml.primitives.AABBd; -import org.joml.primitives.AABBdc; import org.joml.primitives.AABBf; import java.lang.Math; @@ -414,13 +413,4 @@ public static AABBd grow(AABBd aabb, double growth) { aabb.maxZ += growth; return aabb; } - - /** - * NOTICE: This is a temporary method due to a bug in JOML-primitives, and will be removed after - * this pr got merged. - */ - public static boolean intersectsAABB(AABBdc aabb1, AABBdc aabb2) { - return aabb1.maxX() > aabb2.minX() && aabb1.maxY() > aabb2.minY() && aabb1.maxZ() > aabb2.minZ() && - aabb1.minX() < aabb2.maxX() && aabb1.minY() < aabb2.maxY() && aabb1.minZ() < aabb2.maxZ(); - } } diff --git a/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java b/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java index 0b3cdca6c..afaee06cf 100644 --- a/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java +++ b/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java @@ -4,7 +4,6 @@ import lombok.AllArgsConstructor; import lombok.Getter; import org.allaymc.api.block.data.BlockFace; -import org.allaymc.api.math.MathUtils; import org.joml.Vector2d; import org.joml.Vector3d; import org.joml.Vector3dc; @@ -135,7 +134,7 @@ public VoxelShape translate(Vector3dc vec) { public boolean intersectsAABB(AABBdc other) { var aabb = unionAABB(); // TODO: This is a bug in JOML-primitives - if (!MathUtils.intersectsAABB(aabb, other)) return false; + if (!aabb.intersectsAABB(other)) return false; other.intersection(aabb, aabb); if (vacancies.stream().anyMatch(vacancy -> vacancy.containsAABB(aabb))) return false; diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index eead59122..dc84e541e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -62,7 +62,7 @@ javapoet = { module = "com.palantir.javapoet:javapoet", version = "0.6.0" } fastreflect = { group = "com.github.AllayMC", name = "fast-reflection", version = "8733a599fa" } # Math computing joml = { group = "org.joml", name = "joml", version = "1.10.8" } -joml-primitives = { group = "org.joml", name = "joml-primitives", version = "1.10.0" } +joml-primitives = { group = "org.allaymc", name = "joml-primitives", version = "404d04f6b7" } # Netty netty-epoll = { group = "io.netty", name = "netty-transport-classes-epoll", version.ref = "netty" } netty-kqueue = { group = "io.netty", name = "netty-transport-classes-kqueue", version.ref = "netty" } diff --git a/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTree.java b/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTree.java index 3cff76c94..2983dd5ae 100644 --- a/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTree.java +++ b/server/src/main/java/org/allaymc/server/datastruct/aabb/AABBTree.java @@ -2,7 +2,6 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import lombok.Getter; -import org.allaymc.api.math.MathUtils; import org.allaymc.api.world.service.AABBOverlapFilter; import org.allaymc.api.world.service.HasAABB; import org.allaymc.api.world.service.HasLongId; @@ -11,7 +10,7 @@ import org.joml.RayAabIntersection; import org.joml.primitives.AABBd; import org.joml.primitives.AABBdc; -import org.joml.primitives.Rayf; +import org.joml.primitives.Rayfc; import java.util.*; import java.util.function.Predicate; @@ -367,7 +366,7 @@ public void detectOverlaps(AABBdc overlapWith, List result) { } public void detectOverlaps(AABBdc overlapWith, AABBOverlapFilter filter, List result) { - traverseTree(aabb -> MathUtils.intersectsAABB(aabb, overlapWith), filter, result); + traverseTree(aabb -> aabb.intersectsAABB(overlapWith), filter, result); } public void detectCollisionPairs(List> result) { @@ -400,13 +399,13 @@ public void detectInFrustum(Matrix4fc worldViewProjection, AABBOverlapFilter traverseTree(aabb -> frustumIntersection.testAab((float) aabb.minX(), (float) aabb.minY(), (float) aabb.minZ(), (float) aabb.maxX(), (float) aabb.maxY(), (float) aabb.maxZ()), filter, result); } - public void detectRayIntersection(Rayf ray, List result) { + public void detectRayIntersection(Rayfc ray, List result) { detectRayIntersection(ray, defaultAABBOverlapFilter, result); } // TODO: Use Rayfc here - public void detectRayIntersection(Rayf ray, AABBOverlapFilter filter, List result) { - rayIntersection.set(ray.oX, ray.oY, ray.oZ, ray.dX, ray.dY, ray.dZ); + public void detectRayIntersection(Rayfc ray, AABBOverlapFilter filter, List result) { + rayIntersection.set(ray.oX(), ray.oY(), ray.oZ(), ray.dX(), ray.dY(), ray.dZ()); traverseTree(aabb -> rayIntersection.test((float) aabb.minX(), (float) aabb.minY(), (float) aabb.minZ(), (float) aabb.maxX(), (float) aabb.maxY(), (float) aabb.maxZ()), filter, result); } From 2bfbcd74ece14eadf1b48df3e529d60743914c08 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Tue, 4 Feb 2025 06:42:47 +0800 Subject: [PATCH 04/12] fix: fix Position3d and Location3d --- .../allaymc/api/math/location/Location3d.java | 942 +----------------- .../allaymc/api/math/position/Position3d.java | 919 ----------------- .../java/org/allaymc/api/world/Dimension.java | 12 + .../service/AllayEntityPhysicsService.java | 2 +- 4 files changed, 17 insertions(+), 1858 deletions(-) diff --git a/api/src/main/java/org/allaymc/api/math/location/Location3d.java b/api/src/main/java/org/allaymc/api/math/location/Location3d.java index 2c305b99e..421d35e5b 100644 --- a/api/src/main/java/org/allaymc/api/math/location/Location3d.java +++ b/api/src/main/java/org/allaymc/api/math/location/Location3d.java @@ -1,6 +1,7 @@ package org.allaymc.api.math.location; import com.google.common.base.Objects; +import lombok.Setter; import org.allaymc.api.math.position.Position3d; import org.allaymc.api.server.Server; import org.allaymc.api.world.Dimension; @@ -18,7 +19,9 @@ /** * @author Cool_Loong */ +@Setter public class Location3d extends Position3d implements Location3dc { + public double pitch; public double yaw; public double headYaw; @@ -154,771 +157,6 @@ public double headYaw() { return headYaw; } - public void setYaw(double yaw) { - this.yaw = yaw; - } - - public void setPitch(double pitch) { - this.pitch = pitch; - } - - public void setHeadYaw(double headYaw) { - this.headYaw = headYaw; - } - - @Override - public Location3d set(Vector3dc v) { - super.set(v); - return this; - } - - @Override - public Location3d set(Vector3ic v) { - super.set(v); - return this; - } - - @Override - public Location3d set(Vector2dc v, double z) { - super.set(v, z); - return this; - } - - @Override - public Location3d set(Vector2ic v, double z) { - super.set(v, z); - return this; - } - - @Override - public Location3d set(Vector3fc v) { - super.set(v); - return this; - } - - @Override - public Location3d set(Vector2fc v, double z) { - super.set(v, z); - return this; - } - - @Override - public Location3d set(double d) { - super.set(d); - return this; - } - - @Override - public Location3d set(double x, double y, double z) { - super.set(x, y, z); - return this; - } - - @Override - public Location3d set(double[] xyz) { - super.set(xyz); - return this; - } - - @Override - public Location3d set(float[] xyz) { - super.set(xyz); - return this; - } - - @Override - public Location3d set(ByteBuffer buffer) { - super.set(buffer); - return this; - } - - @Override - public Location3d set(int index, ByteBuffer buffer) { - super.set(index, buffer); - return this; - } - - @Override - public Location3d set(DoubleBuffer buffer) { - super.set(buffer); - return this; - } - - @Override - public Location3d set(int index, DoubleBuffer buffer) { - super.set(index, buffer); - return this; - } - - @Override - public Location3d setFromAddress(long address) { - super.setFromAddress(address); - return this; - } - - @Override - public Location3d setComponent(int component, double value) throws IllegalArgumentException { - super.setComponent(component, value); - return this; - } - - @Override - public Location3dc getToAddress(long address) { - super.getToAddress(address); - return this; - } - - @Override - public Location3d sub(Vector3dc v) { - super.sub(v); - return this; - } - - @Override - public Location3d sub(Vector3dc v, Vector3d dest) { - super.sub(v, dest); - return this; - } - - @Override - public Location3d sub(Vector3fc v) { - super.sub(v); - return this; - } - - @Override - public Location3d sub(Vector3fc v, Vector3d dest) { - super.sub(v, dest); - return this; - } - - @Override - public Location3d sub(double x, double y, double z) { - super.sub(x, y, z); - return this; - } - - @Override - public Location3d sub(double x, double y, double z, Vector3d dest) { - super.sub(x, y, z, dest); - return this; - } - - @Override - public Location3d add(Vector3dc v) { - super.add(v); - return this; - } - - @Override - public Location3d add(Vector3dc v, Vector3d dest) { - super.add(v, dest); - return this; - } - - @Override - public Location3d add(Vector3fc v) { - super.add(v); - return this; - } - - @Override - public Location3d add(Vector3fc v, Vector3d dest) { - super.add(v, dest); - return this; - } - - @Override - public Location3d add(double x, double y, double z) { - super.add(x, y, z); - return this; - } - - @Override - public Location3d add(double x, double y, double z, Vector3d dest) { - super.add(x, y, z, dest); - return this; - } - - @Override - public Location3d fma(Vector3dc a, Vector3dc b) { - super.fma(a, b); - return this; - } - - @Override - public Location3d fma(double a, Vector3dc b) { - super.fma(a, b); - return this; - } - - @Override - public Location3d fma(Vector3fc a, Vector3fc b) { - super.fma(a, b); - return this; - } - - @Override - public Location3d fma(Vector3fc a, Vector3fc b, Vector3d dest) { - super.fma(a, b, dest); - return this; - } - - @Override - public Location3d fma(double a, Vector3fc b) { - super.fma(a, b); - return this; - } - - @Override - public Location3d fma(Vector3dc a, Vector3dc b, Vector3d dest) { - super.fma(a, b, dest); - return this; - } - - @Override - public Location3d fma(double a, Vector3dc b, Vector3d dest) { - super.fma(a, b, dest); - return this; - } - - @Override - public Location3d fma(Vector3dc a, Vector3fc b, Vector3d dest) { - super.fma(a, b, dest); - return this; - } - - @Override - public Location3d fma(double a, Vector3fc b, Vector3d dest) { - super.fma(a, b, dest); - return this; - } - - @Override - public Location3d mulAdd(Vector3dc a, Vector3dc b) { - super.mulAdd(a, b); - return this; - } - - @Override - public Location3d mulAdd(double a, Vector3dc b) { - super.mulAdd(a, b); - return this; - } - - @Override - public Location3d mulAdd(Vector3dc a, Vector3dc b, Vector3d dest) { - super.mulAdd(a, b, dest); - return this; - } - - @Override - public Location3d mulAdd(double a, Vector3dc b, Vector3d dest) { - super.mulAdd(a, b, dest); - return this; - } - - @Override - public Location3d mulAdd(Vector3fc a, Vector3dc b, Vector3d dest) { - super.mulAdd(a, b, dest); - return this; - } - - @Override - public Location3d mul(Vector3dc v) { - super.mul(v); - return this; - } - - @Override - public Location3d mul(Vector3fc v) { - super.mul(v); - return this; - } - - @Override - public Location3d mul(Vector3fc v, Vector3d dest) { - super.mul(v, dest); - return this; - } - - @Override - public Location3d mul(Vector3dc v, Vector3d dest) { - super.mul(v, dest); - return this; - } - - @Override - public Location3d div(Vector3dc v) { - super.div(v); - return this; - } - - @Override - public Location3d div(Vector3fc v) { - super.div(v); - return this; - } - - @Override - public Location3d div(Vector3fc v, Vector3d dest) { - super.div(v, dest); - return this; - } - - @Override - public Location3d div(Vector3dc v, Vector3d dest) { - super.div(v, dest); - return this; - } - - @Override - public Location3d mulProject(Matrix4dc mat, double w, Vector3d dest) { - super.mulProject(mat, w, dest); - return this; - } - - @Override - public Location3d mulProject(Matrix4dc mat, Vector3d dest) { - super.mulProject(mat, dest); - return this; - } - - @Override - public Location3d mulProject(Matrix4dc mat) { - super.mulProject(mat); - return this; - } - - @Override - public Location3d mulProject(Matrix4fc mat, Vector3d dest) { - super.mulProject(mat, dest); - return this; - } - - @Override - public Location3d mulProject(Matrix4fc mat) { - super.mulProject(mat); - return this; - } - - @Override - public Location3d mul(Matrix3fc mat) { - super.mul(mat); - return this; - } - - @Override - public Location3d mul(Matrix3dc mat) { - super.mul(mat); - return this; - } - - @Override - public Location3d mul(Matrix3dc mat, Vector3d dest) { - super.mul(mat, dest); - return this; - } - - @Override - public Vector3f mul(Matrix3dc mat, Vector3f dest) { - return super.mul(mat, dest); - } - - @Override - public Location3d mul(Matrix3fc mat, Vector3d dest) { - super.mul(mat, dest); - return this; - } - - @Override - public Location3d mul(Matrix3x2dc mat) { - super.mul(mat); - return this; - } - - @Override - public Location3d mul(Matrix3x2dc mat, Vector3d dest) { - super.mul(mat, dest); - return this; - } - - @Override - public Location3d mul(Matrix3x2fc mat) { - super.mul(mat); - return this; - } - - @Override - public Location3d mul(Matrix3x2fc mat, Vector3d dest) { - super.mul(mat, dest); - return this; - } - - @Override - public Location3d mulTranspose(Matrix3dc mat) { - super.mulTranspose(mat); - return this; - } - - @Override - public Location3d mulTranspose(Matrix3dc mat, Vector3d dest) { - super.mulTranspose(mat, dest); - return this; - } - - @Override - public Location3d mulTranspose(Matrix3fc mat) { - super.mulTranspose(mat); - return this; - } - - @Override - public Location3d mulTranspose(Matrix3fc mat, Vector3d dest) { - super.mulTranspose(mat, dest); - return this; - } - - @Override - public Location3d mulPosition(Matrix4fc mat) { - super.mulPosition(mat); - return this; - } - - @Override - public Location3d mulPosition(Matrix4dc mat) { - super.mulPosition(mat); - return this; - } - - @Override - public Location3d mulPosition(Matrix4x3dc mat) { - super.mulPosition(mat); - return this; - } - - @Override - public Location3d mulPosition(Matrix4x3fc mat) { - super.mulPosition(mat); - return this; - } - - @Override - public Location3d mulPosition(Matrix4dc mat, Vector3d dest) { - super.mulPosition(mat, dest); - return this; - } - - @Override - public Location3d mulPosition(Matrix4fc mat, Vector3d dest) { - super.mulPosition(mat, dest); - return this; - } - - @Override - public Location3d mulPosition(Matrix4x3dc mat, Vector3d dest) { - super.mulPosition(mat, dest); - return this; - } - - @Override - public Location3d mulPosition(Matrix4x3fc mat, Vector3d dest) { - super.mulPosition(mat, dest); - return this; - } - - @Override - public Location3d mulTransposePosition(Matrix4dc mat) { - super.mulTransposePosition(mat); - return this; - } - - @Override - public Location3d mulTransposePosition(Matrix4dc mat, Vector3d dest) { - super.mulTransposePosition(mat, dest); - return this; - } - - @Override - public Location3d mulTransposePosition(Matrix4fc mat) { - super.mulTransposePosition(mat); - return this; - } - - @Override - public Location3d mulTransposePosition(Matrix4fc mat, Vector3d dest) { - super.mulTransposePosition(mat, dest); - return this; - } - - @Override - public Location3d mulDirection(Matrix4fc mat) { - super.mulDirection(mat); - return this; - } - - @Override - public Location3d mulDirection(Matrix4dc mat) { - super.mulDirection(mat); - return this; - } - - @Override - public Location3d mulDirection(Matrix4x3dc mat) { - super.mulDirection(mat); - return this; - } - - @Override - public Location3d mulDirection(Matrix4x3fc mat) { - super.mulDirection(mat); - return this; - } - - @Override - public Location3d mulDirection(Matrix4dc mat, Vector3d dest) { - super.mulDirection(mat, dest); - return this; - } - - @Override - public Location3d mulDirection(Matrix4fc mat, Vector3d dest) { - super.mulDirection(mat, dest); - return this; - } - - @Override - public Location3d mulDirection(Matrix4x3dc mat, Vector3d dest) { - super.mulDirection(mat, dest); - return this; - } - - @Override - public Location3d mulDirection(Matrix4x3fc mat, Vector3d dest) { - super.mulDirection(mat, dest); - return this; - } - - @Override - public Location3d mulTransposeDirection(Matrix4dc mat) { - super.mulTransposeDirection(mat); - return this; - } - - @Override - public Location3d mulTransposeDirection(Matrix4dc mat, Vector3d dest) { - super.mulTransposeDirection(mat, dest); - return this; - } - - @Override - public Location3d mulTransposeDirection(Matrix4fc mat) { - super.mulTransposeDirection(mat); - return this; - } - - @Override - public Location3d mulTransposeDirection(Matrix4fc mat, Vector3d dest) { - super.mulTransposeDirection(mat, dest); - return this; - } - - @Override - public Location3d mul(double scalar) { - super.mul(scalar); - return this; - } - - @Override - public Location3d mul(double scalar, Vector3d dest) { - super.mul(scalar, dest); - return this; - } - - @Override - public Location3d mul(double x, double y, double z) { - super.mul(x, y, z); - return this; - } - - @Override - public Location3d mul(double x, double y, double z, Vector3d dest) { - super.mul(x, y, z, dest); - return this; - } - - @Override - public Location3d rotate(Quaterniondc quat) { - super.rotate(quat); - return this; - } - - @Override - public Location3d rotate(Quaterniondc quat, Vector3d dest) { - super.rotate(quat, dest); - return this; - } - - @Override - public Quaterniond rotationTo(Vector3dc toDir, Quaterniond dest) { - return super.rotationTo(toDir, dest); - } - - @Override - public Quaterniond rotationTo(double toDirX, double toDirY, double toDirZ, Quaterniond dest) { - return super.rotationTo(toDirX, toDirY, toDirZ, dest); - } - - @Override - public Location3d rotateAxis(double angle, double x, double y, double z) { - super.rotateAxis(angle, x, y, z); - return this; - } - - @Override - public Location3d rotateAxis(double angle, double aX, double aY, double aZ, Vector3d dest) { - super.rotateAxis(angle, aX, aY, aZ, dest); - return this; - } - - @Override - public Location3d rotateX(double angle) { - super.rotateX(angle); - return this; - } - - @Override - public Location3d rotateX(double angle, Vector3d dest) { - super.rotateX(angle, dest); - return this; - } - - @Override - public Location3d rotateY(double angle) { - super.rotateY(angle); - return this; - } - - @Override - public Location3d rotateY(double angle, Vector3d dest) { - super.rotateY(angle, dest); - return this; - } - - @Override - public Location3d rotateZ(double angle) { - super.rotateZ(angle); - return this; - } - - @Override - public Location3d rotateZ(double angle, Vector3d dest) { - super.rotateZ(angle, dest); - return this; - } - - @Override - public Location3d div(double scalar) { - super.div(scalar); - return this; - } - - @Override - public Location3d div(double scalar, Vector3d dest) { - super.div(scalar, dest); - return this; - } - - @Override - public Location3d div(double x, double y, double z) { - super.div(x, y, z); - return this; - } - - @Override - public Location3d div(double x, double y, double z, Vector3d dest) { - super.div(x, y, z, dest); - return this; - } - - @Override - public Location3d normalize() { - super.normalize(); - return this; - } - - @Override - public Location3d normalize(Vector3d dest) { - super.normalize(dest); - return this; - } - - @Override - public Location3d normalize(double length) { - super.normalize(length); - return this; - } - - @Override - public Location3d normalize(double length, Vector3d dest) { - super.normalize(length, dest); - return this; - } - - @Override - public Location3d cross(Vector3dc v) { - super.cross(v); - return this; - } - - @Override - public Location3d cross(double x, double y, double z) { - super.cross(x, y, z); - return this; - } - - @Override - public Location3d cross(Vector3dc v, Vector3d dest) { - super.cross(v, dest); - return this; - } - - @Override - public Location3d cross(double x, double y, double z, Vector3d dest) { - super.cross(x, y, z, dest); - return this; - } - - @Override - public Location3d min(Vector3dc v) { - super.min(v); - return this; - } - - @Override - public Location3d min(Vector3dc v, Vector3d dest) { - super.min(v, dest); - return this; - } - - @Override - public Location3d max(Vector3dc v) { - super.max(v); - return this; - } - - @Override - public Location3d max(Vector3dc v, Vector3d dest) { - super.max(v, dest); - return this; - } - - @Override - public Location3d zero() { - super.zero(); - return this; - } - @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeDouble(x); @@ -932,7 +170,7 @@ public void writeExternal(ObjectOutput out) throws IOException { } @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + public void readExternal(ObjectInput in) throws IOException { x = in.readDouble(); y = in.readDouble(); z = in.readDouble(); @@ -942,178 +180,6 @@ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundExcept dimension = new WeakReference<>(Server.getInstance().getWorldPool().getWorld(in.readUTF()).getDimension(in.readInt())); } - @Override - public Location3d negate() { - super.negate(); - return this; - } - - @Override - public Location3d negate(Vector3d dest) { - super.negate(dest); - return this; - } - - @Override - public Location3d absolute() { - super.absolute(); - return this; - } - - @Override - public Location3d absolute(Vector3d dest) { - super.absolute(dest); - return this; - } - - @Override - public Location3d reflect(Vector3dc normal) { - super.reflect(normal); - return this; - } - - @Override - public Location3d reflect(double x, double y, double z) { - super.reflect(x, y, z); - return this; - } - - @Override - public Location3d reflect(Vector3dc normal, Vector3d dest) { - super.reflect(normal, dest); - return this; - } - - @Override - public Location3d reflect(double x, double y, double z, Vector3d dest) { - super.reflect(x, y, z, dest); - return this; - } - - @Override - public Location3d half(Vector3dc other) { - super.half(other); - return this; - } - - @Override - public Location3d half(double x, double y, double z) { - super.half(x, y, z); - return this; - } - - @Override - public Location3d half(Vector3dc other, Vector3d dest) { - super.half(other, dest); - return this; - } - - @Override - public Location3d half(double x, double y, double z, Vector3d dest) { - super.half(x, y, z, dest); - return this; - } - - @Override - public Location3d smoothStep(Vector3dc v, double t, Vector3d dest) { - super.smoothStep(v, t, dest); - return this; - } - - @Override - public Location3d hermite(Vector3dc t0, Vector3dc v1, Vector3dc t1, double t, Vector3d dest) { - super.hermite(t0, v1, t1, t, dest); - return this; - } - - @Override - public Location3d lerp(Vector3dc other, double t) { - super.lerp(other, t); - return this; - } - - @Override - public Location3d lerp(Vector3dc other, double t, Vector3d dest) { - super.lerp(other, t, dest); - return this; - } - - @Override - public Vector3i get(int mode, Vector3i dest) { - return super.get(mode, dest); - } - - @Override - public Vector3f get(Vector3f dest) { - return super.get(dest); - } - - @Override - public Location3d get(Vector3d dest) { - super.get(dest); - return this; - } - - @Override - public Location3d orthogonalize(Vector3dc v, Vector3d dest) { - super.orthogonalize(v, dest); - return this; - } - - @Override - public Location3d orthogonalize(Vector3dc v) { - super.orthogonalize(v); - return this; - } - - @Override - public Location3d orthogonalizeUnit(Vector3dc v, Vector3d dest) { - super.orthogonalizeUnit(v, dest); - return this; - } - - @Override - public Location3d orthogonalizeUnit(Vector3dc v) { - super.orthogonalizeUnit(v); - return this; - } - - @Override - public Location3d floor() { - super.floor(); - return this; - } - - @Override - public Location3d floor(Vector3d dest) { - super.floor(dest); - return this; - } - - @Override - public Location3d ceil() { - super.ceil(); - return this; - } - - @Override - public Location3d ceil(Vector3d dest) { - super.ceil(dest); - return this; - } - - @Override - public Location3d round() { - super.round(); - return this; - } - - @Override - public Location3d round(Vector3d dest) { - super.round(dest); - return this; - } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/api/src/main/java/org/allaymc/api/math/position/Position3d.java b/api/src/main/java/org/allaymc/api/math/position/Position3d.java index e51a3c050..166fdd0b8 100644 --- a/api/src/main/java/org/allaymc/api/math/position/Position3d.java +++ b/api/src/main/java/org/allaymc/api/math/position/Position3d.java @@ -114,758 +114,11 @@ public void setDimension(Dimension dimension) { this.dimension = new WeakReference<>(dimension); } - @Override - public Position3d set(Vector3dc v) { - super.set(v); - return this; - } - - @Override - public Position3d set(Vector3ic v) { - super.set(v); - return this; - } - - @Override - public Position3d set(Vector2dc v, double z) { - super.set(v, z); - return this; - } - - @Override - public Position3d set(Vector2ic v, double z) { - super.set(v, z); - return this; - } - - @Override - public Position3d set(Vector3fc v) { - super.set(v); - return this; - } - - @Override - public Position3d set(Vector2fc v, double z) { - super.set(v, z); - return this; - } - - @Override - public Position3d set(double d) { - super.set(d); - return this; - } - - @Override - public Position3d set(double x, double y, double z) { - super.set(x, y, z); - return this; - } - - @Override - public Position3d set(double[] xyz) { - super.set(xyz); - return this; - } - - @Override - public Position3d set(float[] xyz) { - super.set(xyz); - return this; - } - - @Override - public Position3d set(ByteBuffer buffer) { - super.set(buffer); - return this; - } - - @Override - public Position3d set(int index, ByteBuffer buffer) { - super.set(index, buffer); - return this; - } - - @Override - public Position3d set(DoubleBuffer buffer) { - super.set(buffer); - return this; - } - - @Override - public Position3d set(int index, DoubleBuffer buffer) { - super.set(index, buffer); - return this; - } - - @Override - public Position3d setFromAddress(long address) { - super.setFromAddress(address); - return this; - } - - @Override - public Position3d setComponent(int component, double value) throws IllegalArgumentException { - super.setComponent(component, value); - return this; - } - @Override public Position3dc getToAddress(long address) { throw new UnsupportedOperationException(); } - @Override - public Position3d sub(Vector3dc v) { - super.sub(v); - return this; - } - - @Override - public Position3d sub(Vector3dc v, Vector3d dest) { - super.sub(v, dest); - return this; - } - - @Override - public Position3d sub(Vector3fc v) { - super.sub(v); - return this; - } - - @Override - public Position3d sub(Vector3fc v, Vector3d dest) { - super.sub(v, dest); - return this; - } - - @Override - public Position3d sub(double x, double y, double z) { - super.sub(x, y, z); - return this; - } - - @Override - public Position3d sub(double x, double y, double z, Vector3d dest) { - super.sub(x, y, z, dest); - return this; - } - - @Override - public Position3d add(Vector3dc v) { - super.add(v); - return this; - } - - @Override - public Position3d add(Vector3dc v, Vector3d dest) { - super.add(v, dest); - return this; - } - - @Override - public Position3d add(Vector3fc v) { - super.add(v); - return this; - } - - @Override - public Position3d add(Vector3fc v, Vector3d dest) { - super.add(v, dest); - return this; - } - - @Override - public Position3d add(double x, double y, double z) { - super.add(x, y, z); - return this; - } - - @Override - public Position3d add(double x, double y, double z, Vector3d dest) { - super.add(x, y, z, dest); - return this; - } - - @Override - public Position3d fma(Vector3dc a, Vector3dc b) { - super.fma(a, b); - return this; - } - - @Override - public Position3d fma(double a, Vector3dc b) { - super.fma(a, b); - return this; - } - - @Override - public Position3d fma(Vector3fc a, Vector3fc b) { - super.fma(a, b); - return this; - } - - @Override - public Position3d fma(Vector3fc a, Vector3fc b, Vector3d dest) { - super.fma(a, b, dest); - return this; - } - - @Override - public Position3d fma(double a, Vector3fc b) { - super.fma(a, b); - return this; - } - - @Override - public Position3d fma(Vector3dc a, Vector3dc b, Vector3d dest) { - super.fma(a, b, dest); - return this; - } - - @Override - public Position3d fma(double a, Vector3dc b, Vector3d dest) { - super.fma(a, b, dest); - return this; - } - - @Override - public Position3d fma(Vector3dc a, Vector3fc b, Vector3d dest) { - super.fma(a, b, dest); - return this; - } - - @Override - public Position3d fma(double a, Vector3fc b, Vector3d dest) { - super.fma(a, b, dest); - return this; - } - - @Override - public Position3d mulAdd(Vector3dc a, Vector3dc b) { - super.mulAdd(a, b); - return this; - } - - @Override - public Position3d mulAdd(double a, Vector3dc b) { - super.mulAdd(a, b); - return this; - } - - @Override - public Position3d mulAdd(Vector3dc a, Vector3dc b, Vector3d dest) { - super.mulAdd(a, b, dest); - return this; - } - - @Override - public Position3d mulAdd(double a, Vector3dc b, Vector3d dest) { - super.mulAdd(a, b, dest); - return this; - } - - @Override - public Position3d mulAdd(Vector3fc a, Vector3dc b, Vector3d dest) { - super.mulAdd(a, b, dest); - return this; - } - - @Override - public Position3d mul(Vector3dc v) { - super.mul(v); - return this; - } - - @Override - public Position3d mul(Vector3fc v) { - super.mul(v); - return this; - } - - @Override - public Position3d mul(Vector3fc v, Vector3d dest) { - super.mul(v, dest); - return this; - } - - @Override - public Position3d mul(Vector3dc v, Vector3d dest) { - super.mul(v, dest); - return this; - } - - @Override - public Position3d div(Vector3dc v) { - super.div(v); - return this; - } - - @Override - public Position3d div(Vector3fc v) { - super.div(v); - return this; - } - - @Override - public Position3d div(Vector3fc v, Vector3d dest) { - super.div(v, dest); - return this; - } - - @Override - public Position3d div(Vector3dc v, Vector3d dest) { - super.div(v, dest); - return this; - } - - @Override - public Position3d mulProject(Matrix4dc mat, double w, Vector3d dest) { - super.mulProject(mat, w, dest); - return this; - } - - @Override - public Position3d mulProject(Matrix4dc mat, Vector3d dest) { - super.mulProject(mat, dest); - return this; - } - - @Override - public Position3d mulProject(Matrix4dc mat) { - super.mulProject(mat); - return this; - } - - @Override - public Position3d mulProject(Matrix4fc mat, Vector3d dest) { - super.mulProject(mat, dest); - return this; - } - - @Override - public Position3d mulProject(Matrix4fc mat) { - super.mulProject(mat); - return this; - } - - @Override - public Position3d mul(Matrix3fc mat) { - super.mul(mat); - return this; - } - - @Override - public Position3d mul(Matrix3dc mat) { - super.mul(mat); - return this; - } - - @Override - public Position3d mul(Matrix3dc mat, Vector3d dest) { - super.mul(mat, dest); - return this; - } - - @Override - public Vector3f mul(Matrix3dc mat, Vector3f dest) { - return super.mul(mat, dest); - } - - @Override - public Position3d mul(Matrix3fc mat, Vector3d dest) { - super.mul(mat, dest); - return this; - } - - @Override - public Position3d mul(Matrix3x2dc mat) { - super.mul(mat); - return this; - } - - @Override - public Position3d mul(Matrix3x2dc mat, Vector3d dest) { - super.mul(mat, dest); - return this; - } - - @Override - public Position3d mul(Matrix3x2fc mat) { - super.mul(mat); - return this; - } - - @Override - public Position3d mul(Matrix3x2fc mat, Vector3d dest) { - super.mul(mat, dest); - return this; - } - - @Override - public Position3d mulTranspose(Matrix3dc mat) { - super.mulTranspose(mat); - return this; - } - - @Override - public Position3d mulTranspose(Matrix3dc mat, Vector3d dest) { - super.mulTranspose(mat, dest); - return this; - } - - @Override - public Position3d mulTranspose(Matrix3fc mat) { - super.mulTranspose(mat); - return this; - } - - @Override - public Position3d mulTranspose(Matrix3fc mat, Vector3d dest) { - super.mulTranspose(mat, dest); - return this; - } - - @Override - public Position3d mulPosition(Matrix4fc mat) { - super.mulPosition(mat); - return this; - } - - @Override - public Position3d mulPosition(Matrix4dc mat) { - super.mulPosition(mat); - return this; - } - - @Override - public Position3d mulPosition(Matrix4x3dc mat) { - super.mulPosition(mat); - return this; - } - - @Override - public Position3d mulPosition(Matrix4x3fc mat) { - super.mulPosition(mat); - return this; - } - - @Override - public Position3d mulPosition(Matrix4dc mat, Vector3d dest) { - super.mulPosition(mat, dest); - return this; - } - - @Override - public Position3d mulPosition(Matrix4fc mat, Vector3d dest) { - super.mulPosition(mat, dest); - return this; - } - - @Override - public Position3d mulPosition(Matrix4x3dc mat, Vector3d dest) { - super.mulPosition(mat, dest); - return this; - } - - @Override - public Position3d mulPosition(Matrix4x3fc mat, Vector3d dest) { - super.mulPosition(mat, dest); - return this; - } - - @Override - public Position3d mulTransposePosition(Matrix4dc mat) { - super.mulTransposePosition(mat); - return this; - } - - @Override - public Position3d mulTransposePosition(Matrix4dc mat, Vector3d dest) { - super.mulTransposePosition(mat, dest); - return this; - } - - @Override - public Position3d mulTransposePosition(Matrix4fc mat) { - super.mulTransposePosition(mat); - return this; - } - - @Override - public Position3d mulTransposePosition(Matrix4fc mat, Vector3d dest) { - super.mulTransposePosition(mat, dest); - return this; - } - - @Override - public Position3d mulDirection(Matrix4fc mat) { - super.mulDirection(mat); - return this; - } - - @Override - public Position3d mulDirection(Matrix4dc mat) { - super.mulDirection(mat); - return this; - } - - @Override - public Position3d mulDirection(Matrix4x3dc mat) { - super.mulDirection(mat); - return this; - } - - @Override - public Position3d mulDirection(Matrix4x3fc mat) { - super.mulDirection(mat); - return this; - } - - @Override - public Position3d mulDirection(Matrix4dc mat, Vector3d dest) { - super.mulDirection(mat, dest); - return this; - } - - @Override - public Position3d mulDirection(Matrix4fc mat, Vector3d dest) { - super.mulDirection(mat, dest); - return this; - } - - @Override - public Position3d mulDirection(Matrix4x3dc mat, Vector3d dest) { - super.mulDirection(mat, dest); - return this; - } - - @Override - public Position3d mulDirection(Matrix4x3fc mat, Vector3d dest) { - super.mulDirection(mat, dest); - return this; - } - - @Override - public Position3d mulTransposeDirection(Matrix4dc mat) { - super.mulTransposeDirection(mat); - return this; - } - - @Override - public Position3d mulTransposeDirection(Matrix4dc mat, Vector3d dest) { - super.mulTransposeDirection(mat, dest); - return this; - } - - @Override - public Position3d mulTransposeDirection(Matrix4fc mat) { - super.mulTransposeDirection(mat); - return this; - } - - @Override - public Position3d mulTransposeDirection(Matrix4fc mat, Vector3d dest) { - super.mulTransposeDirection(mat, dest); - return this; - } - - @Override - public Position3d mul(double scalar) { - super.mul(scalar); - return this; - } - - @Override - public Position3d mul(double scalar, Vector3d dest) { - super.mul(scalar, dest); - return this; - } - - @Override - public Position3d mul(double x, double y, double z) { - super.mul(x, y, z); - return this; - } - - @Override - public Position3d mul(double x, double y, double z, Vector3d dest) { - super.mul(x, y, z, dest); - return this; - } - - @Override - public Position3d rotate(Quaterniondc quat) { - super.rotate(quat); - return this; - } - - @Override - public Position3d rotate(Quaterniondc quat, Vector3d dest) { - super.rotate(quat, dest); - return this; - } - - @Override - public Quaterniond rotationTo(Vector3dc toDir, Quaterniond dest) { - return super.rotationTo(toDir, dest); - } - - @Override - public Quaterniond rotationTo(double toDirX, double toDirY, double toDirZ, Quaterniond dest) { - return super.rotationTo(toDirX, toDirY, toDirZ, dest); - } - - @Override - public Position3d rotateAxis(double angle, double x, double y, double z) { - super.rotateAxis(angle, x, y, z); - return this; - } - - @Override - public Position3d rotateAxis(double angle, double aX, double aY, double aZ, Vector3d dest) { - super.rotateAxis(angle, aX, aY, aZ, dest); - return this; - } - - @Override - public Position3d rotateX(double angle) { - super.rotateX(angle); - return this; - } - - @Override - public Position3d rotateX(double angle, Vector3d dest) { - super.rotateX(angle, dest); - return this; - } - - @Override - public Position3d rotateY(double angle) { - super.rotateY(angle); - return this; - } - - @Override - public Position3d rotateY(double angle, Vector3d dest) { - super.rotateY(angle, dest); - return this; - } - - @Override - public Position3d rotateZ(double angle) { - super.rotateZ(angle); - return this; - } - - @Override - public Position3d rotateZ(double angle, Vector3d dest) { - super.rotateZ(angle, dest); - return this; - } - - @Override - public Position3d div(double scalar) { - super.div(scalar); - return this; - } - - @Override - public Position3d div(double scalar, Vector3d dest) { - super.div(scalar, dest); - return this; - } - - @Override - public Position3d div(double x, double y, double z) { - super.div(x, y, z); - return this; - } - - @Override - public Position3d div(double x, double y, double z, Vector3d dest) { - super.div(x, y, z, dest); - return this; - } - - @Override - public Position3d normalize() { - super.normalize(); - return this; - } - - @Override - public Position3d normalize(Vector3d dest) { - super.normalize(dest); - return this; - } - - @Override - public Position3d normalize(double length) { - super.normalize(length); - return this; - } - - @Override - public Position3d normalize(double length, Vector3d dest) { - super.normalize(length, dest); - return this; - } - - @Override - public Position3d cross(Vector3dc v) { - super.cross(v); - return this; - } - - @Override - public Position3d cross(double x, double y, double z) { - super.cross(x, y, z); - return this; - } - - @Override - public Position3d cross(Vector3dc v, Vector3d dest) { - super.cross(v, dest); - return this; - } - - @Override - public Position3d cross(double x, double y, double z, Vector3d dest) { - super.cross(x, y, z, dest); - return this; - } - - @Override - public Position3d min(Vector3dc v) { - super.min(v); - return this; - } - - @Override - public Position3d min(Vector3dc v, Vector3d dest) { - super.min(v, dest); - return this; - } - - @Override - public Position3d max(Vector3dc v) { - super.max(v); - return this; - } - - @Override - public Position3d max(Vector3dc v, Vector3d dest) { - super.max(v, dest); - return this; - } - - @Override - public Position3d zero() { - super.zero(); - return this; - } - @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeDouble(x); @@ -883,178 +136,6 @@ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundExcept dimension = new WeakReference<>(Server.getInstance().getWorldPool().getWorld(in.readUTF()).getDimension(in.readInt())); } - @Override - public Position3d negate() { - super.negate(); - return this; - } - - @Override - public Position3d negate(Vector3d dest) { - super.negate(dest); - return this; - } - - @Override - public Position3d absolute() { - super.absolute(); - return this; - } - - @Override - public Position3d absolute(Vector3d dest) { - super.absolute(dest); - return this; - } - - @Override - public Position3d reflect(Vector3dc normal) { - super.reflect(normal); - return this; - } - - @Override - public Position3d reflect(double x, double y, double z) { - super.reflect(x, y, z); - return this; - } - - @Override - public Position3d reflect(Vector3dc normal, Vector3d dest) { - super.reflect(normal, dest); - return this; - } - - @Override - public Position3d reflect(double x, double y, double z, Vector3d dest) { - super.reflect(x, y, z, dest); - return this; - } - - @Override - public Position3d half(Vector3dc other) { - super.half(other); - return this; - } - - @Override - public Position3d half(double x, double y, double z) { - super.half(x, y, z); - return this; - } - - @Override - public Position3d half(Vector3dc other, Vector3d dest) { - super.half(other, dest); - return this; - } - - @Override - public Position3d half(double x, double y, double z, Vector3d dest) { - super.half(x, y, z, dest); - return this; - } - - @Override - public Position3d smoothStep(Vector3dc v, double t, Vector3d dest) { - super.smoothStep(v, t, dest); - return this; - } - - @Override - public Position3d hermite(Vector3dc t0, Vector3dc v1, Vector3dc t1, double t, Vector3d dest) { - super.hermite(t0, v1, t1, t, dest); - return this; - } - - @Override - public Position3d lerp(Vector3dc other, double t) { - super.lerp(other, t); - return this; - } - - @Override - public Position3d lerp(Vector3dc other, double t, Vector3d dest) { - super.lerp(other, t, dest); - return this; - } - - @Override - public Vector3i get(int mode, Vector3i dest) { - return super.get(mode, dest); - } - - @Override - public Vector3f get(Vector3f dest) { - return super.get(dest); - } - - @Override - public Position3d get(Vector3d dest) { - super.get(dest); - return this; - } - - @Override - public Position3d orthogonalize(Vector3dc v, Vector3d dest) { - super.orthogonalize(v, dest); - return this; - } - - @Override - public Position3d orthogonalize(Vector3dc v) { - super.orthogonalize(v); - return this; - } - - @Override - public Position3d orthogonalizeUnit(Vector3dc v, Vector3d dest) { - super.orthogonalizeUnit(v, dest); - return this; - } - - @Override - public Position3d orthogonalizeUnit(Vector3dc v) { - super.orthogonalizeUnit(v); - return this; - } - - @Override - public Position3d floor() { - super.floor(); - return this; - } - - @Override - public Position3d floor(Vector3d dest) { - super.floor(dest); - return this; - } - - @Override - public Position3d ceil() { - super.ceil(); - return this; - } - - @Override - public Position3d ceil(Vector3d dest) { - super.ceil(dest); - return this; - } - - @Override - public Position3d round() { - super.round(); - return this; - } - - @Override - public Position3d round(Vector3d dest) { - super.round(dest); - return this; - } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/api/src/main/java/org/allaymc/api/world/Dimension.java b/api/src/main/java/org/allaymc/api/world/Dimension.java index 9e649fbc6..1da84d397 100644 --- a/api/src/main/java/org/allaymc/api/world/Dimension.java +++ b/api/src/main/java/org/allaymc/api/world/Dimension.java @@ -483,6 +483,8 @@ default void forEachBlockStates(int x, int y, int z, int sizeX, int sizeY, int s return; } + var dimensionInfo = getDimensionInfo(); + var startX = x >> 4; var endX = (x + sizeX - 1) >> 4; var startY = y >> 4; @@ -501,6 +503,10 @@ default void forEachBlockStates(int x, int y, int z, int sizeX, int sizeY, int s var chunk = getChunkService().getOrLoadChunkSync(chunkX, chunkZ); for (int sectionY = startY; sectionY <= endY; sectionY++) { + if (sectionY < dimensionInfo.minSectionY() || sectionY > dimensionInfo.maxSectionY()) { + continue; + } + var cY = sectionY << 4; var localStartY = Math.max(y - cY, 0); var localEndY = Math.min(y + sizeY - cY, 16); @@ -541,6 +547,8 @@ default void setBlockStates(int x, int y, int z, int sizeX, int sizeY, int sizeZ return; } + var dimensionInfo = getDimensionInfo(); + var startX = x >> 4; var endX = (x + sizeX - 1) >> 4; var startY = y >> 4; @@ -559,6 +567,10 @@ default void setBlockStates(int x, int y, int z, int sizeX, int sizeY, int sizeZ var chunk = getChunkService().getOrLoadChunkSync(chunkX, chunkZ); for (int sectionY = startY; sectionY <= endY; sectionY++) { + if (sectionY < dimensionInfo.minSectionY() || sectionY > dimensionInfo.maxSectionY()) { + continue; + } + var cY = sectionY << 4; var localStartY = Math.max(y - cY, 0); var localEndY = Math.min(y + sizeY - cY, 16); diff --git a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java index 049129207..90cf7ef5e 100644 --- a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java +++ b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java @@ -521,7 +521,7 @@ private Pair moveAlongAxisAndStopWhenCollision(AABBd aabb, doub // Do not use dimension.isAABBInDimension(extendX|Y|Z) because entity should be able to move even if y > maxHeight protected boolean notValidEntityArea(AABBd extendAABB) { - return (extendAABB.minY < dimension.getDimensionInfo().minHeight()) && + return !(extendAABB.minY >= dimension.getDimensionInfo().minHeight()) && !dimension.getChunkService().isChunkLoaded((int) extendAABB.minX >> 4, (int) extendAABB.minZ >> 4) && !dimension.getChunkService().isChunkLoaded((int) extendAABB.maxX >> 4, (int) extendAABB.maxZ >> 4); } From 7573cfebe6a75969de6bd60e8c8a914103102ff2 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Tue, 4 Feb 2025 07:42:21 +0800 Subject: [PATCH 05/12] fix: fix FAT_AABB_MARGIN usage in AllayEntityPhysicsService#moveAlongAxisAndStopWhenCollision --- .../service/AllayEntityPhysicsService.java | 68 ++++++++++++------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java index 90cf7ef5e..828107bc0 100644 --- a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java +++ b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java @@ -63,8 +63,8 @@ public class AllayEntityPhysicsService implements EntityPhysicsService { * the entity will be considered as collided with the block. This is used to prevent floating point * number overflow problem and is what the vanilla actually does. *

- * This value is actually the value of the y coordinate decimal point when the player stands on the - * full block (such as the grass block) + * This value is actually the value of the client-side y coordinate decimal point when the player + * stands on the full block (such as the grass block). */ public static final double FAT_AABB_MARGIN = 0.00001; @@ -444,7 +444,7 @@ private double applyMotion0(double stepHeight, Location3d pos, double motion, AA * @param axis The axis along which to move the AABB. Use 0 for the X-axis, 1 for the Y-axis, and 2 for the Z-axis. * * @return A pair containing the remaining movement distance along the axis after collision detection (Double) - * and a boolean indicating whether a collision occurred (Boolean). + * and a boolean indicating whether a collision occurred (Boolean) or whether the entity will be on ground (if axis == Y). * If no movement was specified (motion = 0), an empty pair is returned. * * @throws IllegalArgumentException if an invalid axis is provided. @@ -481,41 +481,58 @@ private Pair moveAlongAxisAndStopWhenCollision(AABBd aabb, doub return EMPTY_FLOAT_BOOLEAN_PAIR; } - var deltaAxis = motion; + var deltaInAxis = motion; var collision = false; var blocks = dimension.getCollidingBlockStates(extendAxis); if (blocks != null) { - collision = axis != Y || shouldTowardsNegative; + // There is a collision if `blocks` is not null + if (axis == Y) { + // When the axis is Y, `collision` indicates whether the entity will be on the ground + collision = shouldTowardsNegative; + } else { + collision = true; + } - // There is a collision - var minAxis = floor(extendAxis.getMin(axis)); - var maxAxis = computeMax(minAxis, axis, blocks); + var minInAxis = floor(extendAxis.getMin(axis)); + var maxInAxis = computeMax(minInAxis, axis, blocks); // Calculate the ray axis starting coordinate var coordinate = shouldTowardsNegative ? aabb.getMin(axis) : aabb.getMax(axis); - if (isInRange(minAxis, coordinate, maxAxis)) { - // Stuck into the block - deltaAxis = 0; + if (isInRange(minInAxis, coordinate, maxInAxis)) { + // Entity is stuck into blocks + deltaInAxis = 0; } else { - deltaAxis = min(abs(coordinate - minAxis), abs(coordinate - maxAxis)); + deltaInAxis = min(abs(coordinate - minInAxis), abs(coordinate - maxInAxis)); if (shouldTowardsNegative) { - deltaAxis = -deltaAxis; + deltaInAxis = -deltaInAxis; } - if (abs(deltaAxis) <= FAT_AABB_MARGIN) { - deltaAxis = 0; + } + + if (deltaInAxis != 0) { + // Make a certain distance (FAT_AABB_MARGIN) between the entity and the block + var signum = signum(deltaInAxis); + var deltaInAxisWithFAM = deltaInAxis + (signum > 0 ? -FAT_AABB_MARGIN : FAT_AABB_MARGIN); + if (signum != signum(deltaInAxisWithFAM)) { + deltaInAxis = 0; + } else { + deltaInAxis = deltaInAxisWithFAM; } } motion = 0; } - // Move the collision box - if (axis == X) aabb.translate(deltaAxis, 0, 0); - else if (axis == Y) aabb.translate(0, deltaAxis, 0); - else aabb.translate(0, 0, deltaAxis); + if (deltaInAxis != 0) { + // Move the collision box + switch (axis) { + case X -> aabb.translate(deltaInAxis, 0, 0); + case Y -> aabb.translate(0, deltaInAxis, 0); + default -> aabb.translate(0, 0, deltaInAxis); + } + // Update the coordinates + recorder.setComponent(axis, recorder.get(axis) + deltaInAxis); + } - // Update the coordinates - recorder.setComponent(axis, recorder.get(axis) + deltaAxis); return new DoubleBooleanImmutablePair(motion, collision); } @@ -549,7 +566,10 @@ protected double computeMax(double start, int axis, BlockState[][][] blocks) { BlockState[] sub2 = sub1[oy]; for (int oz = 0, sub2Length = sub2.length; oz < sub2Length; oz++) { BlockState blockState = sub2[oz]; - if (blockState == null) continue; + if (blockState == null) { + continue; + } + double current; var unionAABB = blockState.getBlockStateData().collisionShape().unionAABB(); switch (axis) { @@ -558,7 +578,9 @@ protected double computeMax(double start, int axis, BlockState[][][] blocks) { case Z -> current = unionAABB.lengthZ() + start + oz; default -> throw new IllegalArgumentException("Invalid axis provided"); } - if (current > max) max = current; + if (current > max) { + max = current; + } } } } From df7c4aef02ac1390c7bec0df17c104cb42a80d4b Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Fri, 7 Feb 2025 14:42:03 +0800 Subject: [PATCH 06/12] refactor: refactor VoxelShape#intersectsRay --- .../api/math/voxelshape/VoxelShape.java | 145 +++++++++++++++--- .../java/org/allaymc/api/world/Explosion.java | 2 +- .../api/math/voxelshape/VoxelShapeTest.java | 54 ++++++- 3 files changed, 169 insertions(+), 32 deletions(-) diff --git a/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java b/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java index afaee06cf..c6abc26c6 100644 --- a/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java +++ b/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java @@ -10,6 +10,7 @@ import org.joml.primitives.AABBd; import org.joml.primitives.AABBdc; import org.joml.primitives.Rayd; +import org.joml.primitives.Raydc; import java.util.*; import java.util.stream.Collectors; @@ -133,7 +134,6 @@ public VoxelShape translate(Vector3dc vec) { */ public boolean intersectsAABB(AABBdc other) { var aabb = unionAABB(); - // TODO: This is a bug in JOML-primitives if (!aabb.intersectsAABB(other)) return false; other.intersection(aabb, aabb); @@ -269,8 +269,7 @@ public boolean isEdgeFull(BlockFace face) { // Check if any vacancy affects any edge region boolean vacancyAffectsEdge = vacancies.stream() .filter(vacancy -> isAlignedWithFace(vacancy, face)) - .anyMatch(vacancy -> edgeRegions.stream() - .anyMatch(edge -> intersectsRegion(vacancy, face, edge[0], edge[1], edge[2], edge[3]))); + .anyMatch(vacancy -> edgeRegions.stream().anyMatch(edge -> intersectsRegion(vacancy, face, edge[0], edge[1], edge[2], edge[3]))); if (vacancyAffectsEdge) { return false; @@ -291,43 +290,46 @@ public boolean isEdgeFull(BlockFace face) { } /** - * @see #intersectsRay(Vector3dc, Vector3dc) + * @see #intersectsRay(Raydc) */ - public boolean intersectsRay(double sx, double sy, double sz, double ex, double ey, double ez) { - return intersectsRay(new Vector3d(sx, sy, sz), new Vector3d(ex, ey, ez)); + public boolean intersectsRay(double ox, double oy, double oz, double dx, double dy, double dz) { + return intersectsRay(new Vector3d(ox, oy, oz), new Vector3d(dx, dy, dz)); + } + + /** + * @see #intersectsRay(Raydc) + */ + public boolean intersectsRay(Vector3dc origin, Vector3dc direction) { + return intersectsRay(new Rayd(origin, direction)); } /** * Determine whether the given ray intersects this voxel shape. * - * @param start the start point of the ray. - * @param end the end point of the ray. + * @param ray the ray to check. * * @return {@code true} if the ray intersects this voxel shape, otherwise {@code false}. */ - public boolean intersectsRay(Vector3dc start, Vector3dc end) { - var ray = new Rayd(start, end.sub(start, new Vector3d())); - + public boolean intersectsRay(Raydc ray) { if (vacancies.isEmpty()) { // This would be quicker if no vacancy exists return solids.stream().anyMatch(solid -> solid.intersectsRay(ray)); } - var solidIntervals = mergeIntervals(intersectsRay(solids, ray)); - var vacancyIntervals = mergeIntervals(intersectsRay(vacancies, ray)); + var solidIntervals = mergeAndSortIntervals(intersectsRay(solids, ray)); + var vacancyIntervals = mergeAndSortIntervals(intersectsRay(vacancies, ray)); // For each solid intervals, check if they can be fully covered by vacancy intervals for (var solidInterval : solidIntervals) { - double currentStart = solidInterval.x; boolean isCovered = false; for (var vacancyInterval : vacancyIntervals) { // Check if vacancy interval cover the starting point of the currently uncovered part of solid interval - if (vacancyInterval.x <= currentStart && vacancyInterval.y >= currentStart) { + if (vacancyInterval.x <= solidInterval.x && vacancyInterval.y >= solidInterval.x) { // Update the current starting point to the end point of the vacancy interval - currentStart = Math.max(currentStart, vacancyInterval.y); + solidInterval.x = Math.max(solidInterval.x, vacancyInterval.y); // If the current starting point has exceeded the end point of the solid interval, it means it is completely covered. - if (currentStart >= solidInterval.y) { + if (solidInterval.x >= solidInterval.y) { isCovered = true; break; } @@ -343,9 +345,101 @@ public boolean intersectsRay(Vector3dc start, Vector3dc end) { return false; } - private List mergeIntervals(List intervals) { + /** + * @see #intersectsRay(Raydc, Vector2d) + */ + public boolean intersectsRay(double ox, double oy, double oz, double dx, double dy, double dz, Vector2d result) { + return intersectsRay(new Vector3d(ox, oy, oz), new Vector3d(dx, dy, dz), result); + } + + /** + * @see #intersectsRay(Raydc, Vector2d) + */ + public boolean intersectsRay(Vector3dc origin, Vector3dc direction, Vector2d result) { + return intersectsRay(new Rayd(origin, direction), result); + } + + /** + * Determine whether the given ray intersects this voxel shape. This method is similar to + * {@link #intersectsRay(Raydc)} but will save the intersection result. + * + * @param ray the ray to check. + * @param result a vector which will hold the resulting values of the parameter t in the ray equation p(t) = origin + t * dir + * of the near and far point of intersection if the ray intersects this VoxelShape. Notes that {@code result.y()} will be bigger + * than {@code result.x()}. + * + * @return {@code true} if the ray intersects this voxel shape, otherwise {@code false}. + */ + public boolean intersectsRay(Raydc ray, Vector2d result) { + if (vacancies.isEmpty()) { + // This would be quicker if no vacancy exists + result.set(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY); + var hasIntersection = false; + for (var solid : solids) { + var vec = new Vector2d(); + if (solid.intersectsRay(ray, vec)) { + order(vec); + hasIntersection = true; + if (vec.x < result.x) { + result.x = vec.x; + } + if (vec.y > result.y) { + result.y = vec.y; + } + } + } + + return hasIntersection; + } + + var solidIntervals = mergeAndSortIntervals(intersectsRay(solids, ray)); + var vacancyIntervals = mergeAndSortIntervals(intersectsRay(vacancies, ray)); + + // For each solid intervals, check if they can be fully covered by vacancy intervals + for (var iterator = solidIntervals.iterator(); iterator.hasNext(); ) { + var solidInterval = iterator.next(); + for (var vacancyInterval : vacancyIntervals) { + // Check if vacancy interval cover the starting point of the currently uncovered part of solid interval + if (vacancyInterval.x <= solidInterval.x && vacancyInterval.y >= solidInterval.x) { + // Update the current starting point to the end point of the vacancy interval + solidInterval.x = Math.max(solidInterval.x, vacancyInterval.y); + // If the current starting point has exceeded the end point of the solid interval, it means it is completely covered. + if (solidInterval.x >= solidInterval.y) { + iterator.remove(); + break; + } + } + } + } + + if (solidIntervals.isEmpty()) { + return false; + } else { + result.set(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY); + for (var solidInterval : solidIntervals) { + if (solidInterval.x < result.x) { + result.x = solidInterval.x; + } + if (solidInterval.y > result.y) { + result.y = solidInterval.y; + } + } + + return true; + } + } + + /** + * Merge overlapping intervals into a single interval. This method will also sort the merged intervals by their + * left boundary. Therefore, we guarantee that vector that has bigger index will have a bigger left boundary. + * + * @param intervals the intervals to merge. + * + * @return the merged and sorted intervals. + */ + private List mergeAndSortIntervals(List intervals) { // Sort by interval starting point - intervals.sort((a, b) -> Double.compare(a.x, b.x)); + intervals.sort(Comparator.comparingDouble(a -> a.x)); List merged = new ArrayList<>(); for (Vector2d interval : intervals) { @@ -362,7 +456,7 @@ private List mergeIntervals(List intervals) { return merged; } - private List intersectsRay(Set aabbs, Rayd ray) { + private List intersectsRay(Set aabbs, Raydc ray) { var set = new ArrayList(); for (var aabb : aabbs) { var result = new Vector2d(); @@ -375,12 +469,13 @@ private List intersectsRay(Set aabbs, Rayd ray) { } private Vector2d order(Vector2d vec) { - if (vec.x > vec.y) { - double temp = vec.x; - vec.x = vec.y; - vec.y = temp; - } + return vec.x > vec.y ? swap(vec) : vec; + } + private Vector2d swap(Vector2d vec) { + double temp = vec.x; + vec.x = vec.y; + vec.y = temp; return vec; } diff --git a/api/src/main/java/org/allaymc/api/world/Explosion.java b/api/src/main/java/org/allaymc/api/world/Explosion.java index 278276954..88db65289 100644 --- a/api/src/main/java/org/allaymc/api/world/Explosion.java +++ b/api/src/main/java/org/allaymc/api/world/Explosion.java @@ -350,7 +350,7 @@ protected double exposure(Dimension dimension, Vector3dc origin, AABBdc box) { final boolean[] collided = new boolean[1]; traverseBlocks(origin, point, pos -> { var block = dimension.getBlockState(pos); - if (block.getBlockStateData().computeOffsetCollisionShape(pos).intersectsRay(origin, point)) { + if (block.getBlockStateData().computeOffsetCollisionShape(pos).intersectsRay(origin, point.sub(origin, new Vector3d()))) { collided[0] = true; return false; } diff --git a/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java b/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java index 1c007d16b..38ecdca6d 100644 --- a/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java +++ b/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java @@ -1,6 +1,7 @@ package org.allaymc.api.math.voxelshape; import org.allaymc.api.block.data.BlockFace; +import org.joml.Vector2d; import org.joml.Vector3d; import org.joml.primitives.AABBd; import org.junit.jupiter.api.Test; @@ -272,7 +273,7 @@ void testIntersectsRay() { .solid(0, 0, 0, 1, 1, 1) .vacancy(0.4, 0, 0.4, 0.6, 1, 0.6) .build(); - assertFalse(vs3.intersectsRay(0.5, 0, 0.5, 0.5, 1, 0.5)); + assertFalse(vs3.intersectsRay(0.5, 0, 0.5, 0, 1, 0)); var vs4 = VoxelShape .builder() @@ -296,10 +297,10 @@ void testIntersectsRay() { .solid(0, 0.6, 0, 1, 1, 1) .build(); assertTrue(vs6.intersectsRay(0, 0, 0, 1, 1, 1)); - assertFalse(vs6.intersectsRay(0, 0.4, 0, 1, 0.4, 1)); - assertFalse(vs6.intersectsRay(0, 0.41, 0, 1, 0.41, 1)); - assertFalse(vs6.intersectsRay(0, 0.59, 0, 1, 0.59, 1)); - assertFalse(vs6.intersectsRay(0, 0.6, 0, 1, 0.6, 1)); + assertFalse(vs6.intersectsRay(0, 0.4, 0, 1, 0, 1)); + assertFalse(vs6.intersectsRay(0, 0.41, 0, 1, 0, 1)); + assertFalse(vs6.intersectsRay(0, 0.59, 0, 1, 0, 1)); + assertFalse(vs6.intersectsRay(0, 0.6, 0, 1, 0, 1)); var vs7 = VoxelShape .builder() @@ -307,6 +308,47 @@ void testIntersectsRay() { .solid(0, 0.1, 0, 1, 1, 1) .vacancy(0.4, 0, 0.4, 0.6, 1, 0.6) .build(); - assertFalse(vs7.intersectsRay(0.5, 0, 0.5, 0.5, 1, 0.5)); + assertFalse(vs7.intersectsRay(0.5, 0, 0.5, 0, 1, 0)); + } + + @Test + void testIntersectsRayWithResult() { + var result = new Vector2d(); + + var vs1 = VoxelShape + .builder() + .solid(0, 0, 0, 1, 1, 1) + .build(); + assertTrue(vs1.intersectsRay(0, 0, 0, 1, 1, 1, result)); + assertEquals(0, result.x); + assertEquals(1, result.y); + + var vs2 = VoxelShape + .builder() + .solid(0, 0, 0, 1, 1, 1) + .vacancy(0.1, 0.1, 0.1, 0.9, 0.9, 0.9) + .build(); + assertTrue(vs2.intersectsRay(0, 0, 0, 1, 1, 1, result)); + assertEquals(0, result.x); + assertEquals(1, result.y); + + result.set(0, 0); + var vs3 = VoxelShape + .builder() + .solid(0, 0, 0, 1, 1, 1) + .vacancy(0, 0, 0, 1, 1, 1) + .build(); + assertFalse(vs3.intersectsRay(0, 0, 0, 1, 1, 1, result)); + assertEquals(0, result.x); + assertEquals(0, result.y); + + var vs4 = VoxelShape + .builder() + .solid(0, 0.2, 0, 1, 0.8, 1) + .vacancy(0, 0.4, 0, 1, 0.6, 1) + .build(); + assertTrue(vs4.intersectsRay(0, 0, 0, 0, 1, 0, result)); + assertEquals(0.2, result.x); + assertEquals(0.8, result.y); } } \ No newline at end of file From 97b55027e4e157257fa696f729c8947562084505 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Fri, 7 Feb 2025 15:28:07 +0800 Subject: [PATCH 07/12] deps: update joml-primitives version --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dc84e541e..682270efd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -62,7 +62,7 @@ javapoet = { module = "com.palantir.javapoet:javapoet", version = "0.6.0" } fastreflect = { group = "com.github.AllayMC", name = "fast-reflection", version = "8733a599fa" } # Math computing joml = { group = "org.joml", name = "joml", version = "1.10.8" } -joml-primitives = { group = "org.allaymc", name = "joml-primitives", version = "404d04f6b7" } +joml-primitives = { group = "org.allaymc", name = "joml-primitives", version = "f4a0483f44" } # Netty netty-epoll = { group = "io.netty", name = "netty-transport-classes-epoll", version.ref = "netty" } netty-kqueue = { group = "io.netty", name = "netty-transport-classes-kqueue", version.ref = "netty" } From ac203134daebdd27e475e8cf574c09578edcd65b Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Fri, 7 Feb 2025 18:01:02 +0800 Subject: [PATCH 08/12] refactor: refactor VoxelShape --- .../api/math/voxelshape/VoxelShape.java | 403 ++++++------------ .../api/math/voxelshape/VoxelShapes.java | 8 +- .../api/math/voxelshape/VoxelShapeTest.java | 198 +++++---- 3 files changed, 228 insertions(+), 381 deletions(-) diff --git a/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java b/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java index c6abc26c6..a2f21bb1f 100644 --- a/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java +++ b/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShape.java @@ -18,7 +18,7 @@ /** * VoxelShape represents the shape of a block. *

- * Compared to aabb, voxel shape can have multiple solid and vacancy areas. which means + * Compared to aabb, voxel shape can have multiple solid areas. which means * it can represent a more complex shape (stairs, walls). * * @author daoge_cmd @@ -27,10 +27,9 @@ @AllArgsConstructor(access = AccessLevel.PRIVATE) public final class VoxelShape { - public static final VoxelShape EMPTY = new VoxelShape(Collections.emptySet(), Collections.emptySet()); + public static final VoxelShape EMPTY = new VoxelShape(Collections.emptySet()); private final Set solids; - private final Set vacancies; public static VoxelShapeBuilder builder() { return new VoxelShapeBuilder(); @@ -75,10 +74,7 @@ public VoxelShape rotate(BlockFace face) { Set newSolids = solids.stream() .map(face::rotateAABB) .collect(Collectors.toSet()); - Set newVacancies = vacancies.stream() - .map(face::rotateAABB) - .collect(Collectors.toSet()); - return new VoxelShape(newSolids, newVacancies); + return new VoxelShape(newSolids); } /** @@ -94,10 +90,7 @@ public VoxelShape translate(double x, double y, double z) { Set newSolids = solids.stream() .map(solid -> solid.translate(x, y, z, new AABBd())) .collect(Collectors.toSet()); - Set newVacancies = vacancies.stream() - .map(vacancy -> vacancy.translate(x, y, z, new AABBd())) - .collect(Collectors.toSet()); - return new VoxelShape(newSolids, newVacancies); + return new VoxelShape(newSolids); } /** @@ -118,11 +111,7 @@ public VoxelShape translate(Vector3dc vec) { for (var solid : solids) { newSolids.add(solid.translate(vec, new AABBd())); } - var newVacancies = new HashSet(vacancies.size()); - for (var vacancy : vacancies) { - newVacancies.add(vacancy.translate(vec, new AABBd())); - } - return new VoxelShape(newSolids, newVacancies); + return new VoxelShape(newSolids); } /** @@ -133,12 +122,7 @@ public VoxelShape translate(Vector3dc vec) { * @return true if this voxel shape intersects with the specified AABB, otherwise false. */ public boolean intersectsAABB(AABBdc other) { - var aabb = unionAABB(); - if (!aabb.intersectsAABB(other)) return false; - - other.intersection(aabb, aabb); - if (vacancies.stream().anyMatch(vacancy -> vacancy.containsAABB(aabb))) return false; - return solids.stream().anyMatch(solid -> solid.intersectsAABB(aabb)); + return solids.stream().anyMatch(solid -> solid.intersectsAABB(other)); } /** @@ -149,7 +133,6 @@ public boolean intersectsAABB(AABBdc other) { * @return {@code true} if this voxel shape intersects with the specified point, otherwise {@code false}. */ public boolean intersectsPoint(Vector3dc vec) { - if (vacancies.stream().anyMatch(vacancy -> vacancy.containsPoint(vec))) return false; return solids.stream().anyMatch(solid -> solid.containsPoint(vec)); } @@ -163,132 +146,147 @@ public boolean intersectsPoint(Vector3dc vec) { * @return {@code true} if this voxel shape intersects with the specified point, otherwise {@code false}. */ public boolean intersectsPoint(double x, double y, double z) { - if (vacancies.stream().anyMatch(vacancy -> vacancy.containsPoint(x, y, z))) return false; return solids.stream().anyMatch(solid -> solid.containsPoint(x, y, z)); } /** - * Check if the specified face of this voxel shape is full. + * Checks if the specified face is "full", i.e. whether the [0,1]×[0,1] region of that face + * is completely covered. * - * @param face the face to check. + * @param face the face to check * - * @return {@code true} if the specified face of this voxel shape is full, otherwise {@code false}. + * @return true if the face is completely covered; otherwise, false. */ public boolean isFull(BlockFace face) { - // Check if vacancies cause any gaps on the face - for (AABBdc vacancy : vacancies) { - if (isAlignedWithFace(vacancy, face)) { - double[] uvMinMax = getUVMinMax(vacancy, face); - // As long as there is any gap, the face is incomplete - if (uvMinMax[0] < 1 || uvMinMax[1] > 0f || uvMinMax[2] < 1 || uvMinMax[3] > 0f) { - return false; - } - } - } - - double minU = Double.MAX_VALUE, maxU = -Double.MAX_VALUE; - double minV = Double.MAX_VALUE, maxV = -Double.MAX_VALUE; - - // Calculate the range covered by solids + List uvRectangles = new ArrayList<>(); for (AABBdc solid : solids) { if (isAlignedWithFace(solid, face)) { - double[] uvMinMax = getUVMinMax(solid, face); - minU = Math.min(minU, uvMinMax[0]); - maxU = Math.max(maxU, uvMinMax[1]); - minV = Math.min(minV, uvMinMax[2]); - maxV = Math.max(maxV, uvMinMax[3]); + uvRectangles.add(getUVMinMax(solid, face)); } } - - // If the solids do not completely cover the face, return false - // If the face is fully covered by solids with no gaps, return true - return minU == 0 && maxU == 1 && minV == 0 && maxV == 1; + return isRegionFullyCovered(0.0, 1.0, 0.0, 1.0, uvRectangles); } /** - * Check if the specified face of this voxel shape is center full. + * Checks if the center of the specified face is full. The center is defined as the region + * [3/8, 5/8]×[3/8, 5/8]. * - * @param face the face to check. + * @param face the face to check * - * @return {@code true} if the specified face of this voxel shape is center full, otherwise {@code false}. + * @return true if the center region is completely covered; otherwise, false. */ public boolean isCenterFull(BlockFace face) { - // The boundaries of the center region, from 3/8 to 5/8 - double centerMinUV = (double) 3 / 8; - double centerMaxUV = (double) 5 / 8; - - // First, check if any vacancy affects the center region - boolean vacancyAffectsCenter = vacancies.stream() - .filter(vacancy -> isAlignedWithFace(vacancy, face)) - .anyMatch(vacancy -> { - double[] uvMinMax = getUVMinMax(vacancy, face); - return uvMinMax[0] < centerMaxUV && uvMinMax[1] > centerMinUV && - uvMinMax[2] < centerMaxUV && uvMinMax[3] > centerMinUV; - }); - - if (vacancyAffectsCenter) { - return false; // If a vacancy affects the center region, return false + List uvRectangles = new ArrayList<>(); + for (AABBdc solid : solids) { + if (isAlignedWithFace(solid, face)) { + uvRectangles.add(getUVMinMax(solid, face)); + } } - - // Then check if the solid fully covers the center region - // If the solid fully covers the center region, return true - return solids.stream() - .filter(solid -> isAlignedWithFace(solid, face)) - .anyMatch(solid -> { - double[] uvMinMax = getUVMinMax(solid, face); - return uvMinMax[0] <= centerMinUV && uvMinMax[1] >= centerMaxUV && - uvMinMax[2] <= centerMinUV && uvMinMax[3] >= centerMaxUV; - }); + double centerMin = 3.0 / 8.0; + double centerMax = 5.0 / 8.0; + return isRegionFullyCovered(centerMin, centerMax, centerMin, centerMax, uvRectangles); } /** - * Check if this voxel shape is full block. - *

- * Full block means that all faces of this voxel shape are full. + * Checks if the edges of the specified face are full. The edge region is defined by the given + * edgeWidth (here, 0.125). * - * @return {@code true} if this voxel shape is full block, otherwise {@code false}. + * @param face the face to check + * + * @return true if all edge regions are completely covered; otherwise, false. */ - public boolean isFullBlock() { - return Arrays.stream(BlockFace.values()).allMatch(this::isFull); + public boolean isEdgeFull(BlockFace face) { + double edgeWidth = 0.125; + List uvRectangles = new ArrayList<>(); + for (AABBdc solid : solids) { + if (isAlignedWithFace(solid, face)) { + uvRectangles.add(getUVMinMax(solid, face)); + } + } + // Retrieve the edge regions for the face (each represented as [minU, maxU, minV, maxV]) + for (double[] edge : getEdgeRegions(face, edgeWidth)) { + if (!isRegionFullyCovered(edge[0], edge[1], edge[2], edge[3], uvRectangles)) { + return false; + } + } + return true; } /** - * Check if the specified face of this voxel shape is edge full. + * Helper method: Checks whether the union of the provided UV rectangles completely covers the specified region. + * The method divides the target region into a grid using all boundary lines (from both the target region and + * the intersected rectangles) and then verifies that each cell's center is covered by at least one rectangle. * - * @param face the face to check. + * @param regionMinU the minimum U coordinate of the target region + * @param regionMaxU the maximum U coordinate of the target region + * @param regionMinV the minimum V coordinate of the target region + * @param regionMaxV the maximum V coordinate of the target region + * @param uvRectangles a list of rectangles, each represented as [minU, maxU, minV, maxV] * - * @return {@code true} if the specified face of this voxel shape is edge full, otherwise {@code false}. + * @return true if the union of the rectangles completely covers the target region; otherwise, false. */ - public boolean isEdgeFull(BlockFace face) { - // Define the width of the edge region - double edgeWidth = 0.125; - - // Get the boundaries of all edge regions - List edgeRegions = getEdgeRegions(face, edgeWidth); - - // Check if any vacancy affects any edge region - boolean vacancyAffectsEdge = vacancies.stream() - .filter(vacancy -> isAlignedWithFace(vacancy, face)) - .anyMatch(vacancy -> edgeRegions.stream().anyMatch(edge -> intersectsRegion(vacancy, face, edge[0], edge[1], edge[2], edge[3]))); - - if (vacancyAffectsEdge) { - return false; + private boolean isRegionFullyCovered(double regionMinU, double regionMaxU, + double regionMinV, double regionMaxV, + List uvRectangles) { + // Collect boundaries from the target region and the intersections with each rectangle. + TreeSet uBoundaries = new TreeSet<>(); + TreeSet vBoundaries = new TreeSet<>(); + uBoundaries.add(regionMinU); + uBoundaries.add(regionMaxU); + vBoundaries.add(regionMinV); + vBoundaries.add(regionMaxV); + for (double[] rect : uvRectangles) { + // Compute the intersection of the rectangle with the target region. + double u0 = Math.max(regionMinU, rect[0]); + double u1 = Math.min(regionMaxU, rect[1]); + double v0 = Math.max(regionMinV, rect[2]); + double v1 = Math.min(regionMaxV, rect[3]); + if (u0 < u1 && v0 < v1) { + uBoundaries.add(u0); + uBoundaries.add(u1); + vBoundaries.add(v0); + vBoundaries.add(v1); + } } - - // Check if any solid fully covers each edge region - for (double[] edge : edgeRegions) { - boolean edgeCovered = solids.stream() - .filter(solid -> isAlignedWithFace(solid, face)) - .anyMatch(solid -> isRegionFullyCovered(solid, face, edge[0], edge[1], edge[2], edge[3])); - - if (!edgeCovered) { - return false; + List uList = new ArrayList<>(uBoundaries); + List vList = new ArrayList<>(vBoundaries); + // Iterate over each sub-cell defined by adjacent boundaries. + for (int i = 0; i < uList.size() - 1; i++) { + double u0 = uList.get(i); + double u1 = uList.get(i + 1); + double uc = (u0 + u1) / 2.0; // Sample point (cell center) + for (int j = 0; j < vList.size() - 1; j++) { + double v0 = vList.get(j); + double v1 = vList.get(j + 1); + double vc = (v0 + v1) / 2.0; + // Check if the cell center is covered by any rectangle. + boolean covered = false; + for (double[] rect : uvRectangles) { + if (uc >= rect[0] && uc <= rect[1] && + vc >= rect[2] && vc <= rect[3]) { + covered = true; + break; + } + } + if (!covered) { + return false; + } } } - return true; } + /** + * Check if this voxel shape is full block. + *

+ * Full block means that all faces of this voxel shape are full. + * + * @return {@code true} if this voxel shape is full block, otherwise {@code false}. + */ + public boolean isFullBlock() { + return Arrays.stream(BlockFace.values()).allMatch(this::isFull); + } + /** * @see #intersectsRay(Raydc) */ @@ -311,38 +309,7 @@ public boolean intersectsRay(Vector3dc origin, Vector3dc direction) { * @return {@code true} if the ray intersects this voxel shape, otherwise {@code false}. */ public boolean intersectsRay(Raydc ray) { - if (vacancies.isEmpty()) { - // This would be quicker if no vacancy exists - return solids.stream().anyMatch(solid -> solid.intersectsRay(ray)); - } - - var solidIntervals = mergeAndSortIntervals(intersectsRay(solids, ray)); - var vacancyIntervals = mergeAndSortIntervals(intersectsRay(vacancies, ray)); - - // For each solid intervals, check if they can be fully covered by vacancy intervals - for (var solidInterval : solidIntervals) { - boolean isCovered = false; - - for (var vacancyInterval : vacancyIntervals) { - // Check if vacancy interval cover the starting point of the currently uncovered part of solid interval - if (vacancyInterval.x <= solidInterval.x && vacancyInterval.y >= solidInterval.x) { - // Update the current starting point to the end point of the vacancy interval - solidInterval.x = Math.max(solidInterval.x, vacancyInterval.y); - // If the current starting point has exceeded the end point of the solid interval, it means it is completely covered. - if (solidInterval.x >= solidInterval.y) { - isCovered = true; - break; - } - } - } - - if (!isCovered) { - // Return false directly if any of the solid interval is not fully covered - return true; - } - } - - return false; + return solids.stream().anyMatch(solid -> solid.intersectsRay(ray)); } /** @@ -366,106 +333,33 @@ public boolean intersectsRay(Vector3dc origin, Vector3dc direction, Vector2d res * @param ray the ray to check. * @param result a vector which will hold the resulting values of the parameter t in the ray equation p(t) = origin + t * dir * of the near and far point of intersection if the ray intersects this VoxelShape. Notes that {@code result.y()} will be bigger - * than {@code result.x()}. + * than {@code result.x()}. If the ray does not intersect this VoxelShape, the result will be {@code (Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY)}. * * @return {@code true} if the ray intersects this voxel shape, otherwise {@code false}. */ public boolean intersectsRay(Raydc ray, Vector2d result) { - if (vacancies.isEmpty()) { - // This would be quicker if no vacancy exists - result.set(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY); - var hasIntersection = false; - for (var solid : solids) { - var vec = new Vector2d(); - if (solid.intersectsRay(ray, vec)) { - order(vec); - hasIntersection = true; - if (vec.x < result.x) { - result.x = vec.x; - } - if (vec.y > result.y) { - result.y = vec.y; - } + // This would be quicker if no vacancy exists + result.set(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY); + var hasIntersection = false; + for (var solid : solids) { + var vec = new Vector2d(); + if (solid.intersectsRay(ray, vec)) { + order(vec); + hasIntersection = true; + if (vec.x < result.x) { + result.x = vec.x; } - } - - return hasIntersection; - } - - var solidIntervals = mergeAndSortIntervals(intersectsRay(solids, ray)); - var vacancyIntervals = mergeAndSortIntervals(intersectsRay(vacancies, ray)); - - // For each solid intervals, check if they can be fully covered by vacancy intervals - for (var iterator = solidIntervals.iterator(); iterator.hasNext(); ) { - var solidInterval = iterator.next(); - for (var vacancyInterval : vacancyIntervals) { - // Check if vacancy interval cover the starting point of the currently uncovered part of solid interval - if (vacancyInterval.x <= solidInterval.x && vacancyInterval.y >= solidInterval.x) { - // Update the current starting point to the end point of the vacancy interval - solidInterval.x = Math.max(solidInterval.x, vacancyInterval.y); - // If the current starting point has exceeded the end point of the solid interval, it means it is completely covered. - if (solidInterval.x >= solidInterval.y) { - iterator.remove(); - break; - } + if (vec.y > result.y) { + result.y = vec.y; } } } - if (solidIntervals.isEmpty()) { - return false; - } else { - result.set(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY); - for (var solidInterval : solidIntervals) { - if (solidInterval.x < result.x) { - result.x = solidInterval.x; - } - if (solidInterval.y > result.y) { - result.y = solidInterval.y; - } - } - - return true; + if (!hasIntersection) { + result.set(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); } - } - /** - * Merge overlapping intervals into a single interval. This method will also sort the merged intervals by their - * left boundary. Therefore, we guarantee that vector that has bigger index will have a bigger left boundary. - * - * @param intervals the intervals to merge. - * - * @return the merged and sorted intervals. - */ - private List mergeAndSortIntervals(List intervals) { - // Sort by interval starting point - intervals.sort(Comparator.comparingDouble(a -> a.x)); - List merged = new ArrayList<>(); - - for (Vector2d interval : intervals) { - // If merged is empty or the current interval does not overlap with the previous merged interval - if (merged.isEmpty() || merged.getLast().y < interval.x) { - // Add current interval - merged.add(new Vector2d(interval)); - } else { - // Merge interval - merged.getLast().y = Math.max(merged.getLast().y, interval.y); - } - } - - return merged; - } - - private List intersectsRay(Set aabbs, Raydc ray) { - var set = new ArrayList(); - for (var aabb : aabbs) { - var result = new Vector2d(); - if (aabb.intersectsRay(ray, result)) { - set.add(order(result)); - } - } - - return set; + return hasIntersection; } private Vector2d order(Vector2d vec) { @@ -511,18 +405,6 @@ private List getEdgeRegions(BlockFace face, double edgeWidth) { return edgeRegions; } - private boolean intersectsRegion(AABBdc aabb, BlockFace face, double minU, double maxU, double minV, double maxV) { - double[] uvMinMax = getUVMinMax(aabb, face); - return uvMinMax[0] < maxU && uvMinMax[1] > minU && - uvMinMax[2] < maxV && uvMinMax[3] > minV; - } - - private boolean isRegionFullyCovered(AABBdc aabb, BlockFace face, double minU, double maxU, double minV, double maxV) { - double[] uvMinMax = getUVMinMax(aabb, face); - return uvMinMax[0] <= minU && uvMinMax[1] >= maxU && - uvMinMax[2] <= minV && uvMinMax[3] >= maxV; - } - private boolean isAlignedWithFace(AABBdc solid, BlockFace face) { return switch (face) { case UP -> solid.maxY() == 1; @@ -544,7 +426,6 @@ private double[] getUVMinMax(AABBdc solid, BlockFace face) { public static class VoxelShapeBuilder { private final Set solids = new HashSet<>(); - private final Set vacancies = new HashSet<>(); /** * Add a solid area to the voxel shape. @@ -574,41 +455,13 @@ public VoxelShapeBuilder solid(double minX, double minY, double minZ, double max return solid(new AABBd(minX, minY, minZ, maxX, maxY, maxZ)); } - /** - * Add a vacancy area to the voxel shape. - * - * @param vacancy the vacancy area to add. - * - * @return this builder. - */ - public VoxelShapeBuilder vacancy(AABBdc vacancy) { - vacancies.add(vacancy); - return this; - } - - /** - * Add a vacancy area to the voxel shape. - * - * @param minX the minimum x coordinate of the vacancy area. - * @param minY the minimum y coordinate of the vacancy area. - * @param minZ the minimum z coordinate of the vacancy area. - * @param maxX the maximum x coordinate of the vacancy area. - * @param maxY the maximum y coordinate of the vacancy area. - * @param maxZ the maximum z coordinate of the vacancy area. - * - * @return this builder. - */ - public VoxelShapeBuilder vacancy(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) { - return vacancy(new AABBd(minX, minY, minZ, maxX, maxY, maxZ)); - } - /** * Build the voxel shape. * * @return the voxel shape. */ public VoxelShape build() { - return new VoxelShape(solids, vacancies); + return new VoxelShape(solids); } } } diff --git a/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShapes.java b/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShapes.java index 51828cac6..eb7e37f29 100644 --- a/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShapes.java +++ b/api/src/main/java/org/allaymc/api/math/voxelshape/VoxelShapes.java @@ -23,12 +23,12 @@ public final class VoxelShapes { private static final Map DOWNWARDS_STAIR_SHAPES = new EnumMap<>(BlockFace.class); private static final VoxelShape UPWARDS_STAIR_SHAPE = VoxelShape.builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0, 0.5f, 0, 0.5f, 1, 1) + .solid(0, 0, 0, 1, 0.5f, 1) + .solid(0.5f, 0.5f, 0, 1, 1, 1) .build(); private static final VoxelShape DOWNWARDS_STAIR_SHAPE = VoxelShape.builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0, 0, 0, 0.5f, 0.5f, 1) + .solid(0, 0.5f, 0, 1, 1, 1) + .solid(0.5f, 0, 0, 1, 0.5f, 1) .build(); static { diff --git a/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java b/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java index 38ecdca6d..c2bbfcd9d 100644 --- a/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java +++ b/server/src/test/java/org/allaymc/api/math/voxelshape/VoxelShapeTest.java @@ -4,6 +4,7 @@ import org.joml.Vector2d; import org.joml.Vector3d; import org.joml.primitives.AABBd; +import org.joml.primitives.AABBdc; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -16,8 +17,8 @@ class VoxelShapeTest { void testStairShape() { var vs = VoxelShape .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.5, 0.5, 0, 1, 1, 1) + .solid(0, 0, 0, 1, 0.5, 1) + .solid(0, 0.5, 0, 0.5, 1, 1) .build(); assertFalse(vs.intersectsPoint(0.75, 0.75, 0.5)); var aabb = new AABBd(0.51, 0.51, 0.01, 0.99, 0.99, 0.99); @@ -34,8 +35,12 @@ void testStairShape() { void testCauldronShape() { var vs = VoxelShape .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.1, 0.1, 0.1, 0.9, 0.9, 0.9) + .solid(0, 0, 0, 1, 0.1, 1) + .solid(0, 0.1, 0, 1, 0.9, 0.1) + .solid(0, 0.1, 0.9, 1, 0.9, 1) + .solid(0, 0.1, 0.1, 0.1, 0.9, 0.9) + .solid(0.9, 0.1, 0.1, 1, 0.9, 0.9) + .solid(0, 0.9, 0, 1, 1, 1) .build(); assertFalse(vs.intersectsPoint(0.5, 0.5, 0.5)); @@ -51,28 +56,24 @@ void testCauldronShape() { void testTranslate() { var vs = VoxelShape .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.1, 0.1, 0.1, 0.9, 0.9, 0.9) + .solid(0, 0, 0, 1, 0.1, 1) + .solid(0, 0.1, 0, 1, 0.9, 0.1) + .solid(0, 0.1, 0.9, 1, 0.9, 1) + .solid(0, 0.1, 0.1, 0.1, 0.9, 0.9) + .solid(0.9, 0.1, 0.1, 1, 0.9, 0.9) + .solid(0, 0.9, 0, 1, 1, 1) .build(); - validateTranslateResult(vs.translate(1, 1, 1)); - validateTranslateResult(vs.translate(new Vector3d(1, 1, 1))); + validateTranslateResult(vs.translate(1, 1, 1).unionAABB()); + validateTranslateResult(vs.translate(new Vector3d(1, 1, 1)).unionAABB()); } - void validateTranslateResult(VoxelShape vs) { - var solid = vs.getSolids().iterator().next(); + void validateTranslateResult(AABBdc solid) { assertEquals(1, solid.minX()); assertEquals(1, solid.minY()); assertEquals(1, solid.minZ()); assertEquals(2, solid.maxX()); assertEquals(2, solid.maxY()); assertEquals(2, solid.maxZ()); - var vacancy = vs.getVacancies().iterator().next(); - assertEquals(1.1, vacancy.minX()); - assertEquals(1.1, vacancy.minY()); - assertEquals(1.1, vacancy.minZ()); - assertEquals(1.9, vacancy.maxX()); - assertEquals(1.9, vacancy.maxY()); - assertEquals(1.9, vacancy.maxZ()); } @Test @@ -86,24 +87,30 @@ void testIsFull() { assertTrue(vs1.isFull(face)); } - var vs2 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.4, 0, 0.4, 0.6, 1, 0.6) + var vs2 = VoxelShape.builder() + .solid(0.0, 0.0, 0.0, 0.4, 1.0, 1.0) + .solid(0.6, 0.0, 0.0, 1.0, 1.0, 1.0) + .solid(0.4, 0.0, 0.0, 0.6, 1.0, 0.4) + .solid(0.4, 0.0, 0.6, 0.6, 1.0, 1.0) .build(); + assertFalse(vs2.isFull(BlockFace.UP)); assertFalse(vs2.isFull(BlockFace.DOWN)); for (var face : BlockFace.getHorizontalBlockFaces()) { assertTrue(vs2.isFull(face)); } - var vs3 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.4, 0.4, 0.4, 0.6, 0.6, 0.6) + var vs3 = VoxelShape.builder() + .solid(0.0, 0.0, 0.0, 1.0, 0.4, 1.0) + .solid(0.0, 0.6, 0.0, 1.0, 1.0, 1.0) + .solid(0.0, 0.4, 0.0, 0.4, 0.6, 1.0) + .solid(0.6, 0.4, 0.0, 1.0, 0.6, 1.0) + .solid(0.4, 0.4, 0.0, 0.6, 0.6, 0.4) + .solid(0.4, 0.4, 0.6, 0.6, 0.6, 1.0) .build(); + for (var face : BlockFace.values()) { assertTrue(vs3.isFull(face)); } @@ -130,7 +137,6 @@ void testIsFull() { var vs6 = VoxelShape .builder() - .vacancy(0, 0, 0, 1, 1, 1) .build(); for (var face : BlockFace.values()) { @@ -149,10 +155,11 @@ void testIsCenterFull() { assertTrue(vs1.isCenterFull(face)); } - var vs2 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.45, 0, 0.45, 0.55, 1, 0.55) + var vs2 = VoxelShape.builder() + .solid(0.0, 0.0, 0.0, 0.45, 1.0, 1.0) + .solid(0.55, 0.0, 0.0, 1.0, 1.0, 1.0) + .solid(0.45, 0.0, 0.0, 0.55, 1.0, 0.45) + .solid(0.45, 0.0, 0.55, 0.55, 1.0, 1.0) .build(); assertFalse(vs2.isCenterFull(BlockFace.UP)); @@ -161,12 +168,16 @@ void testIsCenterFull() { assertTrue(vs2.isCenterFull(face)); } - var vs3 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.35, 0.35, 0.35, 0.65, 0.65, 0.65) + var vs3 = VoxelShape.builder() + .solid(0.0, 0.0, 0.0, 1.0, 0.35, 1.0) + .solid(0.0, 0.65, 0.0, 1.0, 1.0, 1.0) + .solid(0.0, 0.35, 0.0, 0.35, 0.65, 1.0) + .solid(0.65, 0.35, 0.0, 1.0, 0.65, 1.0) + .solid(0.35, 0.35, 0.0, 0.65, 0.65, 0.35) + .solid(0.35, 0.35, 0.65, 0.65, 0.65, 1.0) .build(); + for (var face : BlockFace.values()) { assertTrue(vs3.isCenterFull(face)); } @@ -193,11 +204,13 @@ void testIsFullBlock() { assertTrue(vs1.isFullBlock()); // 不完整方块(有空缺) - var vs2 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.4, 0, 0.4, 0.6, 1, 0.6) + var vs2 = VoxelShape.builder() + .solid(0.0, 0.0, 0.0, 0.4, 1.0, 1.0) + .solid(0.6, 0.0, 0.0, 1.0, 1.0, 1.0) + .solid(0.4, 0.0, 0.0, 0.6, 1.0, 0.4) + .solid(0.4, 0.0, 0.6, 0.6, 1.0, 1.0) .build(); + assertFalse(vs2.isFullBlock()); // 部分支撑面不完整 @@ -218,11 +231,11 @@ void testIsEdgeFull() { assertTrue(vs1.isEdgeFull(face)); } - var vs2 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.0, 0.0, 0.0, 0.125, 1, 0.125) + var vs2 = VoxelShape.builder() + .solid(0.125, 0.0, 0.0, 1.0, 1.0, 1.0) + .solid(0.0, 0.0, 0.125, 0.125, 1.0, 1.0) .build(); + for (var face : BlockFace.getVerticalBlockFaces()) { assertFalse(vs2.isEdgeFull(face)); } @@ -238,18 +251,24 @@ void testIsEdgeFull() { assertFalse(vs3.isEdgeFull(BlockFace.UP)); assertFalse(vs3.isEdgeFull(BlockFace.DOWN)); - var vs4 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.2, 0.8, 0.2, 0.8, 1, 0.8) + var vs4 = VoxelShape.builder() + .solid(0.0, 0.0, 0.0, 1.0, 0.8, 1.0) + .solid(0.0, 0.8, 0.0, 0.2, 1.0, 1.0) + .solid(0.8, 0.8, 0.0, 1.0, 1.0, 1.0) + .solid(0.2, 0.8, 0.0, 0.8, 1.0, 0.2) + .solid(0.2, 0.8, 0.8, 0.8, 1.0, 1.0) .build(); + assertTrue(vs4.isEdgeFull(BlockFace.UP)); - var vs5 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.1, 0.8, 0.1, 0.9, 1, 0.9) + var vs5 = VoxelShape.builder() + .solid(0.0, 0.0, 0.0, 1.0, 0.8, 1.0) + .solid(0.0, 0.8, 0.0, 0.1, 1.0, 1.0) + .solid(0.9, 0.8, 0.0, 1.0, 1.0, 1.0) + .solid(0.1, 0.8, 0.0, 0.9, 1.0, 0.1) + .solid(0.1, 0.8, 0.9, 0.9, 1.0, 1.0) .build(); + assertFalse(vs5.isEdgeFull(BlockFace.UP)); } @@ -261,54 +280,28 @@ void testIntersectsRay() { .build(); assertTrue(vs1.intersectsRay(0, 0, 0, 1, 1, 1)); - var vs2 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.1, 0.1, 0.1, 0.9, 0.9, 0.9) + var vs2 = VoxelShape.builder() + .solid(0.0, 0.0, 0.0, 1.0, 0.1, 1.0) + .solid(0.0, 0.9, 0.0, 1.0, 1.0, 1.0) + .solid(0.0, 0.1, 0.0, 0.1, 0.9, 1.0) + .solid(0.9, 0.1, 0.0, 1.0, 0.9, 1.0) + .solid(0.1, 0.1, 0.0, 0.9, 0.9, 0.1) + .solid(0.1, 0.1, 0.9, 0.9, 0.9, 1.0) .build(); assertTrue(vs2.intersectsRay(0, 0, 0, 1, 1, 1)); - var vs3 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.4, 0, 0.4, 0.6, 1, 0.6) + var vs3 = VoxelShape.builder() + .solid(0.0, 0.0, 0.0, 0.4, 1.0, 1.0) + .solid(0.6, 0.0, 0.0, 1.0, 1.0, 1.0) + .solid(0.4, 0.0, 0.0, 0.6, 1.0, 0.4) + .solid(0.4, 0.0, 0.6, 0.6, 1.0, 1.0) .build(); assertFalse(vs3.intersectsRay(0.5, 0, 0.5, 0, 1, 0)); - var vs4 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0, 0, 0, 1, 1, 1) - .build(); - assertFalse(vs4.intersectsRay(0, 0, 0, 1, 1, 1)); - - var vs5 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0, 0, 0, 1, 0.4, 1) - .vacancy(0, 0.6, 0, 1, 1, 1) - .build(); - assertTrue(vs5.intersectsRay(0, 0, 0, 1, 1, 1)); - - var vs6 = VoxelShape - .builder() - .vacancy(0, 0.4, 0, 1, 0.6, 1) - .solid(0, 0, 0, 1, 0.4, 1) - .solid(0, 0.6, 0, 1, 1, 1) - .build(); - assertTrue(vs6.intersectsRay(0, 0, 0, 1, 1, 1)); - assertFalse(vs6.intersectsRay(0, 0.4, 0, 1, 0, 1)); - assertFalse(vs6.intersectsRay(0, 0.41, 0, 1, 0, 1)); - assertFalse(vs6.intersectsRay(0, 0.59, 0, 1, 0, 1)); - assertFalse(vs6.intersectsRay(0, 0.6, 0, 1, 0, 1)); - - var vs7 = VoxelShape - .builder() - .solid(0, 0, 0, 1, 0.9, 1) - .solid(0, 0.1, 0, 1, 1, 1) - .vacancy(0.4, 0, 0.4, 0.6, 1, 0.6) + var vs4 = VoxelShape.builder() + .solid(0, 0.4, 0, 1, 0.6, 1) .build(); - assertFalse(vs7.intersectsRay(0.5, 0, 0.5, 0, 1, 0)); + assertTrue(vs4.intersectsRay(0, 0, 0, 1, 1, 1)); } @Test @@ -323,10 +316,14 @@ void testIntersectsRayWithResult() { assertEquals(0, result.x); assertEquals(1, result.y); - var vs2 = VoxelShape - .builder() + var vs2 = VoxelShape.builder() .solid(0, 0, 0, 1, 1, 1) - .vacancy(0.1, 0.1, 0.1, 0.9, 0.9, 0.9) + .solid(0.0, 0.0, 0.0, 0.1, 1, 1) + .solid(0.9, 0.0, 0.0, 1.0, 1, 1) + .solid(0.0, 0.0, 0.0, 1.0, 0.1, 1) + .solid(0.0, 0.9, 0.0, 1.0, 1.0, 1) + .solid(0.0, 0.0, 0.0, 1.0, 1.0, 0.1) + .solid(0.0, 0.0, 0.9, 1.0, 1.0, 1) .build(); assertTrue(vs2.intersectsRay(0, 0, 0, 1, 1, 1, result)); assertEquals(0, result.x); @@ -335,17 +332,14 @@ void testIntersectsRayWithResult() { result.set(0, 0); var vs3 = VoxelShape .builder() - .solid(0, 0, 0, 1, 1, 1) - .vacancy(0, 0, 0, 1, 1, 1) .build(); assertFalse(vs3.intersectsRay(0, 0, 0, 1, 1, 1, result)); - assertEquals(0, result.x); - assertEquals(0, result.y); + assertEquals(Double.NEGATIVE_INFINITY, result.x); + assertEquals(Double.POSITIVE_INFINITY, result.y); - var vs4 = VoxelShape - .builder() - .solid(0, 0.2, 0, 1, 0.8, 1) - .vacancy(0, 0.4, 0, 1, 0.6, 1) + var vs4 = VoxelShape.builder() + .solid(0, 0.2, 0, 1, 0.4, 1) + .solid(0, 0.6, 0, 1, 0.8, 1) .build(); assertTrue(vs4.intersectsRay(0, 0, 0, 0, 1, 0, result)); assertEquals(0.2, result.x); From 2c0367f1e8b30e745e38cdfabeca17cfa467202a Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Fri, 7 Feb 2025 19:06:03 +0800 Subject: [PATCH 09/12] fix: fix several bugs in physics engine --- .../service/AllayEntityPhysicsService.java | 127 ++++++++++-------- 1 file changed, 72 insertions(+), 55 deletions(-) diff --git a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java index 828107bc0..71b6ca24d 100644 --- a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java +++ b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java @@ -32,6 +32,7 @@ import org.allaymc.server.network.processor.impl.ingame.PlayerAuthInputPacketProcessor; import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket; import org.jctools.maps.NonBlockingHashMapLong; +import org.jetbrains.annotations.Range; import org.joml.Vector3d; import org.joml.primitives.AABBd; import org.joml.primitives.AABBdc; @@ -44,7 +45,6 @@ import static java.lang.Math.*; import static org.allaymc.api.block.component.data.BlockStateData.DEFAULT_FRICTION; import static org.allaymc.api.block.type.BlockTypes.AIR; -import static org.allaymc.api.math.MathUtils.isInRange; /** * Special thanks to MCPK Wiki @@ -410,9 +410,7 @@ protected boolean applyMotion(Entity entity) { */ private double applyMotion0(double stepHeight, Location3d pos, double motion, AABBd aabb, boolean enableStepping, int axis) { if (motion == 0) return motion; - if (axis < X || axis > Z) { - throw new IllegalArgumentException("Invalid axis: " + axis); - } + checkAxis(axis); var resultAABB = new AABBd(aabb); var resultPos = new Vector3d(pos); @@ -449,42 +447,47 @@ private double applyMotion0(double stepHeight, Location3d pos, double motion, AA * * @throws IllegalArgumentException if an invalid axis is provided. */ - private Pair moveAlongAxisAndStopWhenCollision(AABBd aabb, double motion, Vector3d recorder, int axis) { + private Pair moveAlongAxisAndStopWhenCollision(AABBd aabb, double motion, Vector3d recorder, @Range(from = X, to = Z) int axis) { if (motion == 0) { return EMPTY_FLOAT_BOOLEAN_PAIR; } + checkAxis(axis); - var extendAxis = new AABBd(aabb); + // `extAABBInAxis` is the extended aabb in the axis which is used to check for block collision, + // and the direction of the axis is determined by the sign of `motion` + var extAABBInAxis = new AABBd(aabb); // Move towards the negative(motion < 0) or positive(motion > 0) axis direction var shouldTowardsNegative = motion < 0; switch (axis) { case X -> { - var lengthX = extendAxis.lengthX(); - extendAxis.minX += shouldTowardsNegative ? motion : lengthX; - extendAxis.maxX += shouldTowardsNegative ? -lengthX : motion; + var lengthX = extAABBInAxis.lengthX(); + extAABBInAxis.minX += shouldTowardsNegative ? motion : lengthX; + extAABBInAxis.maxX += shouldTowardsNegative ? -lengthX : motion; } case Y -> { - var lengthY = extendAxis.lengthY(); - extendAxis.minY += shouldTowardsNegative ? motion : lengthY; - extendAxis.maxY += shouldTowardsNegative ? -lengthY : motion; + var lengthY = extAABBInAxis.lengthY(); + extAABBInAxis.minY += shouldTowardsNegative ? motion : lengthY; + extAABBInAxis.maxY += shouldTowardsNegative ? -lengthY : motion; } case Z -> { - var lengthZ = extendAxis.lengthZ(); - extendAxis.minZ += shouldTowardsNegative ? motion : lengthZ; - extendAxis.maxZ += shouldTowardsNegative ? -lengthZ : motion; + var lengthZ = extAABBInAxis.lengthZ(); + extAABBInAxis.minZ += shouldTowardsNegative ? motion : lengthZ; + extAABBInAxis.maxZ += shouldTowardsNegative ? -lengthZ : motion; } default -> throw new IllegalArgumentException("Invalid axis provided"); } - if (notValidEntityArea(extendAxis)) { + // Do not use dimension.isAABBInDimension(extendX|Y|Z) because entity should be able to move even if y > maxHeight + if (notValidEntityArea(extAABBInAxis)) { return EMPTY_FLOAT_BOOLEAN_PAIR; } + // `deltaInAxis` is the actual movement distance along the axis direction, and if there is no collision, this distance is equal to `motion` var deltaInAxis = motion; var collision = false; - var blocks = dimension.getCollidingBlockStates(extendAxis); + var blocks = dimension.getCollidingBlockStates(extAABBInAxis); if (blocks != null) { // There is a collision if `blocks` is not null if (axis == Y) { @@ -494,29 +497,20 @@ private Pair moveAlongAxisAndStopWhenCollision(AABBd aabb, doub collision = true; } - var minInAxis = floor(extendAxis.getMin(axis)); - var maxInAxis = computeMax(minInAxis, axis, blocks); - // Calculate the ray axis starting coordinate - var coordinate = shouldTowardsNegative ? aabb.getMin(axis) : aabb.getMax(axis); - if (isInRange(minInAxis, coordinate, maxInAxis)) { - // Entity is stuck into blocks + var extAABBStartCoordinate = shouldTowardsNegative ? extAABBInAxis.getMax(axis) : extAABBInAxis.getMin(axis); + var collisionCoordinate = computeCollisionCoordinate(aabb, extAABBInAxis, blocks, axis, shouldTowardsNegative); + deltaInAxis = abs(extAABBStartCoordinate - collisionCoordinate); + + // Make a certain distance (FAT_AABB_MARGIN) between the entity and the blocks + if (deltaInAxis < FAT_AABB_MARGIN) { deltaInAxis = 0; } else { - deltaInAxis = min(abs(coordinate - minInAxis), abs(coordinate - maxInAxis)); - if (shouldTowardsNegative) { - deltaInAxis = -deltaInAxis; - } + deltaInAxis -= FAT_AABB_MARGIN; } - if (deltaInAxis != 0) { - // Make a certain distance (FAT_AABB_MARGIN) between the entity and the block - var signum = signum(deltaInAxis); - var deltaInAxisWithFAM = deltaInAxis + (signum > 0 ? -FAT_AABB_MARGIN : FAT_AABB_MARGIN); - if (signum != signum(deltaInAxisWithFAM)) { - deltaInAxis = 0; - } else { - deltaInAxis = deltaInAxisWithFAM; - } + // The actual movement distance should be negative if the entity moves towards the negative axis direction + if (shouldTowardsNegative) { + deltaInAxis = -deltaInAxis; } motion = 0; @@ -536,7 +530,12 @@ private Pair moveAlongAxisAndStopWhenCollision(AABBd aabb, doub return new DoubleBooleanImmutablePair(motion, collision); } - // Do not use dimension.isAABBInDimension(extendX|Y|Z) because entity should be able to move even if y > maxHeight + private void checkAxis(int axis) { + if (axis < X || axis > Z) { + throw new IllegalArgumentException("Invalid axis: " + axis); + } + } + protected boolean notValidEntityArea(AABBd extendAABB) { return !(extendAABB.minY >= dimension.getDimensionInfo().minHeight()) && !dimension.getChunkService().isChunkLoaded((int) extendAABB.minX >> 4, (int) extendAABB.minZ >> 4) && @@ -558,33 +557,51 @@ protected boolean tryStepping(Vector3d pos, AABBd aabb, double stepHeight, boole } } - protected double computeMax(double start, int axis, BlockState[][][] blocks) { - double max = start; - for (int ox = 0, blocksLength = blocks.length; ox < blocksLength; ox++) { - BlockState[][] sub1 = blocks[ox]; - for (int oy = 0, sub1Length = sub1.length; oy < sub1Length; oy++) { - BlockState[] sub2 = sub1[oy]; - for (int oz = 0, sub2Length = sub2.length; oz < sub2Length; oz++) { - BlockState blockState = sub2[oz]; + protected double computeCollisionCoordinate(AABBdc entityAABB, AABBdc extAABBInAxis, BlockState[][][] blocks, @Range(from = X, to = Z) int axis, boolean shouldTowardNegative) { + checkAxis(axis); + double coordinate = shouldTowardNegative ? -Double.MAX_VALUE : Double.MAX_VALUE; + + for (int ox = 0; ox < blocks.length; ox++) { + var sub1 = blocks[ox]; + for (int oy = 0; oy < sub1.length; oy++) { + var sub2 = sub1[oy]; + for (int oz = 0; oz < sub2.length; oz++) { + var blockState = sub2[oz]; if (blockState == null) { continue; } - double current; - var unionAABB = blockState.getBlockStateData().collisionShape().unionAABB(); - switch (axis) { - case X -> current = unionAABB.lengthX() + start + ox; - case Y -> current = unionAABB.lengthY() + start + oy; - case Z -> current = unionAABB.lengthZ() + start + oz; - default -> throw new IllegalArgumentException("Invalid axis provided"); + var shape = blockState.getBlockStateData().computeOffsetCollisionShape(floor(extAABBInAxis.minX()) + ox, floor(extAABBInAxis.minY()) + oy, floor(extAABBInAxis.minZ()) + oz); + if (shape.intersectsAABB(entityAABB)) { + // Ignore the blocks that collided with the entity + continue; } - if (current > max) { - max = current; + + var solids = shape.getSolids(); + for (var solid : solids) { + if (!solid.intersectsAABB(extAABBInAxis)) { + // This solid part is not intersected with `extAABBInAxis`, ignore it + continue; + } + + double current; + if (shouldTowardNegative) { + current = solid.getMax(axis); + if (current > coordinate) { + coordinate = current; + } + } else { + current = solid.getMin(axis); + if (current < coordinate) { + coordinate = current; + } + } } } } } - return max; + + return coordinate; } protected void handleClientMoveQueue() { From fbc1ae3c09128fd7a0d8f3ae6567feb55a66e921 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Fri, 7 Feb 2025 21:34:20 +0800 Subject: [PATCH 10/12] fix: fix possible client crash when moving entity --- .../server/world/service/AllayEntityPhysicsService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java index 71b6ca24d..34aaf15d5 100644 --- a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java +++ b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java @@ -499,7 +499,11 @@ private Pair moveAlongAxisAndStopWhenCollision(AABBd aabb, doub var extAABBStartCoordinate = shouldTowardsNegative ? extAABBInAxis.getMax(axis) : extAABBInAxis.getMin(axis); var collisionCoordinate = computeCollisionCoordinate(aabb, extAABBInAxis, blocks, axis, shouldTowardsNegative); - deltaInAxis = abs(extAABBStartCoordinate - collisionCoordinate); + // abs(collisionCoordinate) != Double.MAX_VALUE means that the entity is stuck into the blocks. Collision + // coordinate cannot being calculated because blocks that are intersected with the entity will be ignored + if (abs(collisionCoordinate) != Double.MAX_VALUE) { + deltaInAxis = abs(extAABBStartCoordinate - collisionCoordinate); + } // Make a certain distance (FAT_AABB_MARGIN) between the entity and the blocks if (deltaInAxis < FAT_AABB_MARGIN) { @@ -601,6 +605,7 @@ protected double computeCollisionCoordinate(AABBdc entityAABB, AABBdc extAABBInA } } + // FIXME: abs(coordinate) == Double.MAX_VALUE return coordinate; } From 1b44d990d2237cd0f6c964cde4c5a55ccb5f65f3 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Fri, 7 Feb 2025 21:44:35 +0800 Subject: [PATCH 11/12] chores: code cleanup --- .../world/service/AllayEntityPhysicsService.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java index 34aaf15d5..f8b498caf 100644 --- a/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java +++ b/server/src/main/java/org/allaymc/server/world/service/AllayEntityPhysicsService.java @@ -678,6 +678,7 @@ public void addEntity(Entity entity) { if (entities.containsKey(entity.getRuntimeId())) { throw new IllegalArgumentException("Entity " + entity.getRuntimeId() + " is already added!"); } + entities.put(entity.getRuntimeId(), entity); entityAABBTree.add(entity); } @@ -686,7 +687,10 @@ public void addEntity(Entity entity) { * Please call it before run tick()! */ public void removeEntity(Entity entity) { - if (!entities.containsKey(entity.getRuntimeId())) return; + if (!entities.containsKey(entity.getRuntimeId())) { + return; + } + entities.remove(entity.getRuntimeId()); entityAABBTree.remove(entity); entityCollisionCache.remove(entity.getRuntimeId()); @@ -723,9 +727,14 @@ public List computeCollidingEntities(VoxelShape voxelShape, boolean igno @Override public List getCachedEntityCollidingResult(Entity entity, boolean ignoreEntityHasCollision) { - if (!entity.hasEntityCollision()) return Collections.emptyList(); + if (!entity.hasEntityCollision()) { + return Collections.emptyList(); + } + var result = entityCollisionCache.getOrDefault(entity.getRuntimeId(), Collections.emptyList()); - if (!ignoreEntityHasCollision) result.removeIf(e -> !e.hasEntityCollision()); + if (!ignoreEntityHasCollision) { + result.removeIf(e -> !e.hasEntityCollision()); + } return result; } From b1943afc80fc7c227be236e7ebd52083ab54d652 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Fri, 7 Feb 2025 21:50:38 +0800 Subject: [PATCH 12/12] docs: update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20d7e6566..1fdc57b29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,8 @@ Unless otherwise specified, any version comparison below is the comparison of se ### Changed +- (API) We now used `double` instead of `float` in entity location, motion, aabb and some other classes which require high precision. + This should improve the accuracy of entity movement and collision detection. - (API) Renamed `FullContainerTypeBuilder` to `Builder`. - (API) Moved method `Chunk#isLoaded` to `UnsafeChunk#isLoaded`. - (API) Made method `Dimension#createUpdateBlockPacket` private, consider using `Dimension#sendBlockUpdateTo` method instead. @@ -55,6 +57,7 @@ Unless otherwise specified, any version comparison below is the comparison of se - (API) Replaced `Chunk#batchProcess` method with new `Chunk#applyOperation` and `Chunk#applyOperationInSection` methods. - (API) Moved inner class `ItemArmorBaseComponent#ArmorType` to package `org.allaymc.api.item.data`. - (API) Changed the default value of `ServerSettings#GenericSettings#defaultPermission` to `PlayerPermission.MEMBER`. +- (API) `VoxelShape` have being refactored. Now it doesn't allow using `vacancy`, this change is required by physics engine to fix some bugs. - Main thread will sleep a short time if gui is enabled when the server exits abnormally. This gives user time to see what goes wrong. - Server won't crash if failed to load the descriptor of a plugin now. An error message will be print to the console instead. - Server won't crash if failed to create world generator. Void world generator will be used instead. @@ -75,6 +78,7 @@ Unless otherwise specified, any version comparison below is the comparison of se - Fixed the bug that damage that smaller than 1 will never kill an entity even if the entity has only 1 health. - Fixed the bug caused by incorrect initial value of runtime id counter. The initial value should be 1 instead of 0. - Fixed the bug that `/alwaysday` command actually do the opposite thing. +- Several bugs in physics engine, including wrong collision detection and wrong movement calculation are fixed. ### Removed