diff --git a/src/main/java/ac/grim/grimac/checks/type/BlockPlaceCheck.java b/src/main/java/ac/grim/grimac/checks/type/BlockPlaceCheck.java index e07e16a381..0247e5a14d 100644 --- a/src/main/java/ac/grim/grimac/checks/type/BlockPlaceCheck.java +++ b/src/main/java/ac/grim/grimac/checks/type/BlockPlaceCheck.java @@ -6,6 +6,7 @@ import ac.grim.grimac.utils.anticheat.update.BlockPlace; import ac.grim.grimac.utils.collisions.HitboxData; import ac.grim.grimac.utils.collisions.datatypes.CollisionBox; +import ac.grim.grimac.utils.collisions.datatypes.ComplexCollisionBox; import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox; import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags; import com.github.retrooper.packetevents.protocol.world.states.type.StateType; @@ -18,6 +19,7 @@ public class BlockPlaceCheck extends Check implements RotationCheck, PostPredictionCheck { private static final List weirdBoxes = new ArrayList<>(); private static final List buggyBoxes = new ArrayList<>(); + private final SimpleCollisionBox[] boxes = new SimpleCollisionBox[ComplexCollisionBox.DEFAULT_MAX_COLLISION_BOX_SIZE]; protected int cancelVL; @@ -69,11 +71,11 @@ protected SimpleCollisionBox getCombinedBox(final BlockPlace place) { Vector3i clicked = place.getPlacedAgainstBlockLocation(); CollisionBox placedOn = HitboxData.getBlockHitbox(player, place.getMaterial(), player.getClientVersion(), player.compensatedWorld.getWrappedBlockStateAt(clicked), clicked.getX(), clicked.getY(), clicked.getZ()); - List boxes = new ArrayList<>(); - placedOn.downCast(boxes); + int size = placedOn.downCast(boxes); SimpleCollisionBox combined = new SimpleCollisionBox(clicked.getX(), clicked.getY(), clicked.getZ()); - for (SimpleCollisionBox box : boxes) { + for (int i = 0; i < size; i++) { + SimpleCollisionBox box = boxes[i]; double minX = Math.max(box.minX, combined.minX); double minY = Math.max(box.minY, combined.minY); double minZ = Math.max(box.minZ, combined.minZ); diff --git a/src/main/java/ac/grim/grimac/predictionengine/UncertaintyHandler.java b/src/main/java/ac/grim/grimac/predictionengine/UncertaintyHandler.java index c94220b549..d96d981576 100644 --- a/src/main/java/ac/grim/grimac/predictionengine/UncertaintyHandler.java +++ b/src/main/java/ac/grim/grimac/predictionengine/UncertaintyHandler.java @@ -13,7 +13,6 @@ import com.github.retrooper.packetevents.protocol.attribute.Attributes; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.world.BlockFace; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import org.bukkit.util.Vector; import java.util.*; diff --git a/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockPlace.java b/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockPlace.java index acb2945ccb..b4583fd783 100644 --- a/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockPlace.java +++ b/src/main/java/ac/grim/grimac/utils/anticheat/update/BlockPlace.java @@ -7,6 +7,7 @@ import ac.grim.grimac.utils.collisions.CollisionData; import ac.grim.grimac.utils.collisions.blocks.DoorHandler; import ac.grim.grimac.utils.collisions.datatypes.CollisionBox; +import ac.grim.grimac.utils.collisions.datatypes.ComplexCollisionBox; import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox; import ac.grim.grimac.utils.data.HitData; import ac.grim.grimac.utils.data.packetentity.PacketEntity; @@ -37,7 +38,6 @@ import org.bukkit.util.Vector; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -72,6 +72,9 @@ public class BlockPlace { @Getter private final boolean block; + // Allocated once instead of in functions to reduce new[] calls that need to be made. Since per-instance BlockPlace is always dealt with on the same thread we can use 1 buffer array + private final SimpleCollisionBox[] collisions = new SimpleCollisionBox[ComplexCollisionBox.DEFAULT_MAX_COLLISION_BOX_SIZE]; + public BlockPlace(GrimPlayer player, InteractionHand hand, Vector3i blockPosition, int faceId, BlockFace face, ItemStack itemStack, HitData hitData) { this.player = player; this.hand = hand; @@ -200,12 +203,12 @@ public boolean isFaceFullCenter(BlockFace facing) { if (BlockTags.LEAVES.contains(data.getType())) return false; if (BlockTags.FENCE_GATES.contains(data.getType())) return false; - List collisions = new ArrayList<>(); - box.downCast(collisions); + int size = box.downCast(collisions); AxisSelect axis = AxisUtil.getAxis(facing.getOppositeFace()); - for (SimpleCollisionBox simpleBox : collisions) { + for (int i = 0; i < size; i++) { + SimpleCollisionBox simpleBox = collisions[i]; simpleBox = axis.modify(simpleBox); if (simpleBox.minX <= 7 / 16d && simpleBox.maxX >= 7 / 16d && simpleBox.minY <= 0 && simpleBox.maxY >= 10 / 16d @@ -225,12 +228,12 @@ public boolean isFaceRigid(BlockFace facing) { if (isFullFace(facing)) return true; if (BlockTags.LEAVES.contains(data.getType())) return false; - List collisions = new ArrayList<>(); - box.downCast(collisions); + int size = box.downCast(collisions); AxisSelect axis = AxisUtil.getAxis(facing.getOppositeFace()); - for (SimpleCollisionBox simpleBox : collisions) { + for (int i = 0; i < size; i++) { + SimpleCollisionBox simpleBox = collisions[i]; simpleBox = axis.modify(simpleBox); if (simpleBox.minX <= 2 / 16d && simpleBox.maxX >= 14 / 16d && simpleBox.minY <= 0 && simpleBox.maxY >= 1 @@ -289,10 +292,10 @@ public boolean isFullFace(BlockFace relative) { } } - List collisions = new ArrayList<>(); - box.downCast(collisions); + int size = box.downCast(collisions); - for (SimpleCollisionBox simpleBox : collisions) { + for (int i = 0; i < size; i++) { + SimpleCollisionBox simpleBox = collisions[i]; if (axis.modify(simpleBox).isFullBlockNoCache()) return true; } @@ -318,12 +321,12 @@ public boolean isFaceEmpty(BlockFace facing) { if (isFullFace(facing)) return true; if (BlockTags.LEAVES.contains(data.getType())) return false; - List collisions = new ArrayList<>(); - box.downCast(collisions); + int size = box.downCast(collisions); AxisSelect axis = AxisUtil.getAxis(facing.getOppositeFace()); - for (SimpleCollisionBox simpleBox : collisions) { + for (int i = 0; i < size; i++) { + SimpleCollisionBox simpleBox = collisions[i]; simpleBox = axis.modify(simpleBox); // If all sides to the box have width, there is collision. switch (facing) { diff --git a/src/main/java/ac/grim/grimac/utils/collisions/CollisionData.java b/src/main/java/ac/grim/grimac/utils/collisions/CollisionData.java index c89a83abfd..808c94a1c2 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/CollisionData.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/CollisionData.java @@ -36,7 +36,7 @@ // This is actually mean to be put into PacketEvents, but I don't like proprietary plugins stealing my code... public enum CollisionData { VINE((player, version, block, x, y, z) -> { - ComplexCollisionBox boxes = new ComplexCollisionBox(); + ComplexCollisionBox boxes = new ComplexCollisionBox(5); if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13) && block.isUp()) boxes.add(new HexCollisionBox(0.0D, 15.0D, 0.0D, 16.0D, 16.0D, 16.0D)); @@ -73,11 +73,19 @@ public enum CollisionData { BREWING_STAND((player, version, block, x, y, z) -> { int base = 0; + // maxIndex is 3 instead of 2 for legacy clients because for 1.8 players there is a very rare bug + // That we handle later in the code requiring us to add a box https://bugs.mojang.com/browse/MC-85109 For 1.8 PLAYERS + // 1.8 Brewing Stand hitbox is a fullblock until it is hit sometimes, can be caused be restarting client and joining server + int maxIndex = 3; - if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) + // Yes I know we only need maxIndex = 3 for 1.8 specifically + // No I'm not adding a special clause for which would require another if check, I'll take compute > memory any day + if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) { + maxIndex = 2; base = 1; + } - return new ComplexCollisionBox( + return new ComplexCollisionBox(maxIndex, new HexCollisionBox(base, 0, base, 16 - base, 2, 16 - base), new SimpleCollisionBox(0.4375, 0.0, 0.4375, 0.5625, 0.875, 0.5625, false)); @@ -100,7 +108,7 @@ public enum CollisionData { if (version.isOlderThanOrEquals(ClientVersion.V_1_12_2)) height = 0.3125; - return new ComplexCollisionBox( + return new ComplexCollisionBox(5, new SimpleCollisionBox(0, 0, 0, 1, height, 1, false), new SimpleCollisionBox(0, height, 0, 0.125, 1, 1, false), new SimpleCollisionBox(1 - 0.125, height, 0, 1, 1, 1, false), @@ -119,7 +127,7 @@ public enum CollisionData { // The base is 0.75×0.75, and its floor is 0.25b high. // The top is 1×0.625, and its ceiling is 0.375b low. if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) { - ComplexCollisionBox complexAnvil = new ComplexCollisionBox(); + ComplexCollisionBox complexAnvil = new ComplexCollisionBox(4); // Base of the anvil complexAnvil.add(new HexCollisionBox(2, 0, 2, 14, 4, 14)); if (face == BlockFace.NORTH || face == BlockFace.SOUTH) { @@ -188,7 +196,7 @@ public enum CollisionData { HOPPER((player, version, data, x, y, z) -> { if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) { - ComplexCollisionBox hopperBox = new ComplexCollisionBox(); + ComplexCollisionBox hopperBox = new ComplexCollisionBox(7); switch (data.getFacing()) { case DOWN: @@ -219,7 +227,7 @@ public enum CollisionData { } else { double height = 0.125 * 5; - return new ComplexCollisionBox( + return new ComplexCollisionBox(5, new SimpleCollisionBox(0, 0, 0, 1, height, 1, false), new SimpleCollisionBox(0, height, 0, 0.125, 1, 1, false), new SimpleCollisionBox(1 - 0.125, height, 0, 1, 1, 1, false), @@ -290,7 +298,7 @@ public enum CollisionData { } - ComplexCollisionBox complex = new ComplexCollisionBox( + ComplexCollisionBox complex = new ComplexCollisionBox(3, new HexCollisionBox(5.0D, 6.0D, 5.0D, 11.0D, 13.0D, 11.0D), new HexCollisionBox(4.0D, 4.0D, 4.0D, 12.0D, 6.0D, 12.0D)); @@ -324,7 +332,8 @@ public enum CollisionData { return new SimpleCollisionBox(0, 0, 0, 1, 1, 1, true); if (player.lastY > y + 1 - 1e-5 && !player.isSneaking) { - return new ComplexCollisionBox(new HexCollisionBox(0.0D, 14.0D, 0.0D, 16.0D, 16.0D, 16.0D), + return new ComplexCollisionBox(5, + new HexCollisionBox(0.0D, 14.0D, 0.0D, 16.0D, 16.0D, 16.0D), new HexCollisionBox(0.0D, 0.0D, 0.0D, 2.0D, 16.0D, 2.0D), new HexCollisionBox(14.0D, 0.0D, 0.0D, 16.0D, 16.0D, 2.0D), new HexCollisionBox(0.0D, 0.0D, 14.0D, 2.0D, 16.0D, 16.0), @@ -368,11 +377,13 @@ public enum CollisionData { return new SimpleCollisionBox(0, 0, 0, 1, 1, 1, true); if (data.isHanging()) { - return new ComplexCollisionBox(new HexCollisionBox(5.0D, 1.0D, 5.0D, 11.0D, 8.0D, 11.0D), + return new ComplexCollisionBox(2, + new HexCollisionBox(5.0D, 1.0D, 5.0D, 11.0D, 8.0D, 11.0D), new HexCollisionBox(6.0D, 8.0D, 6.0D, 10.0D, 10.0D, 10.0D)); } - return new ComplexCollisionBox(new HexCollisionBox(5.0D, 0.0D, 5.0D, 11.0D, 7.0D, 11.0D), + return new ComplexCollisionBox(2, + new HexCollisionBox(5.0D, 0.0D, 5.0D, 11.0D, 7.0D, 11.0D), new HexCollisionBox(6.0D, 7.0D, 6.0D, 10.0D, 9.0D, 10.0D)); }, StateTypes.LANTERN, StateTypes.SOUL_LANTERN), @@ -382,7 +393,7 @@ public enum CollisionData { if (version.isOlderThanOrEquals(ClientVersion.V_1_13_2)) return new SimpleCollisionBox(0, 0, 0, 1, 1, 1, true); - return new ComplexCollisionBox( + return new ComplexCollisionBox(2, new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D), // base new HexCollisionBox(4.0D, 2.0D, 4.0D, 12.0D, 14.0D, 12.0D)); // post }, StateTypes.LECTERN), @@ -411,7 +422,7 @@ public enum CollisionData { } if (version.isOlderThanOrEquals(ClientVersion.V_1_13_2)) { - ComplexCollisionBox complexAnvil = new ComplexCollisionBox(); + ComplexCollisionBox complexAnvil = new ComplexCollisionBox(4); // Base of the anvil complexAnvil.add(new HexCollisionBox(2, 0, 2, 14, 4, 14)); @@ -431,13 +442,15 @@ public enum CollisionData { Face attachment = data.getFace(); if (attachment == Face.FLOOR) { if (facing == BlockFace.NORTH || facing == BlockFace.SOUTH) { - return new ComplexCollisionBox(new HexCollisionBox(2.0D, 0.0D, 6.0D, 4.0D, 7.0D, 10.0D), + return new ComplexCollisionBox(5, + new HexCollisionBox(2.0D, 0.0D, 6.0D, 4.0D, 7.0D, 10.0D), new HexCollisionBox(12.0D, 0.0D, 6.0D, 14.0D, 7.0D, 10.0D), new HexCollisionBox(2.0D, 7.0D, 5.0D, 4.0D, 13.0D, 11.0D), new HexCollisionBox(12.0D, 7.0D, 5.0D, 14.0D, 13.0D, 11.0D), new HexCollisionBox(4.0D, 4.0D, 2.0D, 12.0D, 16.0D, 14.0D)); } else { - return new ComplexCollisionBox(new HexCollisionBox(6.0D, 0.0D, 2.0D, 10.0D, 7.0D, 4.0D), + return new ComplexCollisionBox(5, + new HexCollisionBox(6.0D, 0.0D, 2.0D, 10.0D, 7.0D, 4.0D), new HexCollisionBox(6.0D, 0.0D, 12.0D, 10.0D, 7.0D, 14.0D), new HexCollisionBox(5.0D, 7.0D, 2.0D, 11.0D, 13.0D, 4.0D), new HexCollisionBox(5.0D, 7.0D, 12.0D, 11.0D, 13.0D, 14.0D), @@ -446,25 +459,29 @@ public enum CollisionData { } else if (attachment == Face.WALL) { switch (facing) { case NORTH: - return new ComplexCollisionBox(new HexCollisionBox(2.0D, 6.0D, 7.0D, 4.0D, 10.0D, 16.0D), + return new ComplexCollisionBox(5, + new HexCollisionBox(2.0D, 6.0D, 7.0D, 4.0D, 10.0D, 16.0D), new HexCollisionBox(12.0D, 6.0D, 7.0D, 14.0D, 10.0D, 16.0D), new HexCollisionBox(2.0D, 5.0D, 3.0D, 4.0D, 11.0D, 9.0D), new HexCollisionBox(12.0D, 5.0D, 3.0D, 14.0D, 11.0D, 9.0D), new HexCollisionBox(4.0D, 2.0D, 0.0D, 12.0D, 14.0D, 12.0D)); case WEST: - return new ComplexCollisionBox(new HexCollisionBox(7.0D, 6.0D, 2.0D, 16.0D, 10.0D, 4.0D), + return new ComplexCollisionBox(5, + new HexCollisionBox(7.0D, 6.0D, 2.0D, 16.0D, 10.0D, 4.0D), new HexCollisionBox(7.0D, 6.0D, 12.0D, 16.0D, 10.0D, 14.0D), new HexCollisionBox(3.0D, 5.0D, 2.0D, 9.0D, 11.0D, 4.0D), new HexCollisionBox(3.0D, 5.0D, 12.0D, 9.0D, 11.0D, 14.0D), new HexCollisionBox(0.0D, 2.0D, 4.0D, 12.0D, 14.0D, 12.0D)); case SOUTH: - return new ComplexCollisionBox(new HexCollisionBox(2.0D, 6.0D, 0.0D, 4.0D, 10.0D, 7.0D), + return new ComplexCollisionBox(5, + new HexCollisionBox(2.0D, 6.0D, 0.0D, 4.0D, 10.0D, 7.0D), new HexCollisionBox(12.0D, 6.0D, 0.0D, 14.0D, 10.0D, 7.0D), new HexCollisionBox(2.0D, 5.0D, 7.0D, 4.0D, 11.0D, 13.0D), new HexCollisionBox(12.0D, 5.0D, 7.0D, 14.0D, 11.0D, 13.0D), new HexCollisionBox(4.0D, 2.0D, 4.0D, 12.0D, 14.0D, 16.0D)); case EAST: - return new ComplexCollisionBox(new HexCollisionBox(0.0D, 6.0D, 2.0D, 9.0D, 10.0D, 4.0D), + return new ComplexCollisionBox(5, + new HexCollisionBox(0.0D, 6.0D, 2.0D, 9.0D, 10.0D, 4.0D), new HexCollisionBox(0.0D, 6.0D, 12.0D, 9.0D, 10.0D, 14.0D), new HexCollisionBox(7.0D, 5.0D, 2.0D, 13.0D, 11.0D, 4.0D), new HexCollisionBox(7.0D, 5.0D, 12.0D, 13.0D, 11.0D, 14.0D), @@ -472,13 +489,15 @@ public enum CollisionData { } } else { if (facing == BlockFace.NORTH || facing == BlockFace.SOUTH) { - return new ComplexCollisionBox(new HexCollisionBox(2.0D, 9.0D, 6.0D, 4.0D, 16.0D, 10.0D), + return new ComplexCollisionBox(5, + new HexCollisionBox(2.0D, 9.0D, 6.0D, 4.0D, 16.0D, 10.0D), new HexCollisionBox(12.0D, 9.0D, 6.0D, 14.0D, 16.0D, 10.0D), new HexCollisionBox(2.0D, 3.0D, 5.0D, 4.0D, 9.0D, 11.0D), new HexCollisionBox(12.0D, 3.0D, 5.0D, 14.0D, 9.0D, 11.0D), new HexCollisionBox(4.0D, 0.0D, 2.0D, 12.0D, 12.0D, 14.0D)); } else { - return new ComplexCollisionBox(new HexCollisionBox(6.0D, 9.0D, 2.0D, 10.0D, 16.0D, 4.0D), + return new ComplexCollisionBox(5, + new HexCollisionBox(6.0D, 9.0D, 2.0D, 10.0D, 16.0D, 4.0D), new HexCollisionBox(6.0D, 9.0D, 12.0D, 10.0D, 16.0D, 14.0D), new HexCollisionBox(5.0D, 3.0D, 2.0D, 11.0D, 9.0D, 4.0D), new HexCollisionBox(5.0D, 3.0D, 12.0D, 11.0D, 9.0D, 14.0D), @@ -551,7 +570,7 @@ public enum CollisionData { StateTypes.ENCHANTING_TABLE), FRAME((player, version, data, x, y, z) -> { - ComplexCollisionBox complexCollisionBox = new ComplexCollisionBox(new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 13.0D, 16.0D)); + ComplexCollisionBox complexCollisionBox = new ComplexCollisionBox(2, new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 13.0D, 16.0D)); if (data.isEye()) { if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) { // 1.13 players have a 0.5x0.5 eye @@ -622,7 +641,7 @@ public enum CollisionData { if (version.isOlderThan(ClientVersion.V_1_14)) return new SimpleCollisionBox(0.0F, 0.0F, 0.0F, 1.0F, 0.5625, 1.0F, false); - ComplexCollisionBox baseBox = new ComplexCollisionBox(new HexCollisionBox(0.0D, 3.0D, 0.0D, 16.0D, 9.0D, 16.0D)); + ComplexCollisionBox baseBox = new ComplexCollisionBox(3, new HexCollisionBox(0.0D, 3.0D, 0.0D, 16.0D, 9.0D, 16.0D)); switch (data.getFacing()) { case NORTH: @@ -662,7 +681,7 @@ public enum CollisionData { CAULDRON((player, version, data, x, y, z) -> { if (version.isNewerThan(ClientVersion.getById(467))) { // changed in 19w13a, 1.14 Snapshot - return new ComplexCollisionBox( + return new ComplexCollisionBox(15, new SimpleCollisionBox(0.0, 0.0, 0.0, 0.125, 1.0, 0.25, false), new SimpleCollisionBox(0.0, 0.0, 0.75, 0.125, 1.0, 1.0, false), new SimpleCollisionBox(0.125, 0.0, 0.0, 0.25, 1.0, 0.125, false), @@ -684,7 +703,7 @@ public enum CollisionData { if (version.isOlderThan(ClientVersion.V_1_13)) height = 0.3125; - return new ComplexCollisionBox( + return new ComplexCollisionBox(5, new SimpleCollisionBox(0, 0, 0, 1, height, 1, false), new SimpleCollisionBox(0, height, 0, 0.125, 1, 1, false), new SimpleCollisionBox(1 - 0.125, height, 0, 1, 1, 1, false), @@ -834,10 +853,14 @@ public enum CollisionData { }, BlockTags.CANDLES.getStates().toArray(new StateType[0])), CANDLE_CAKE((player, version, data, x, y, z) -> { - ComplexCollisionBox cake = new ComplexCollisionBox(new HexCollisionBox(1.0, 0.0, 1.0, 15.0, 8.0, 15.0)); - if (version.isNewerThanOrEquals(ClientVersion.V_1_17)) - cake.add(new HexCollisionBox(7.0, 8.0, 7.0, 9.0, 14.0, 9.0)); - return cake; + SimpleCollisionBox cake = new HexCollisionBox(1.0, 0.0, 1.0, 15.0, 8.0, 15.0); + if (version.isOlderThan(ClientVersion.V_1_17)) { + return cake; + } else { + return new ComplexCollisionBox(2, + cake, + new HexCollisionBox(7.0, 8.0, 7.0, 9.0, 14.0, 9.0)); + } }, BlockTags.CANDLE_CAKES.getStates().toArray(new StateType[0])), SCULK_SENSOR(new HexCollisionBox(0.0, 0.0, 0.0, 16.0, 8.0, 16.0), StateTypes.SCULK_SENSOR, StateTypes.CALIBRATED_SCULK_SENSOR), @@ -914,7 +937,8 @@ public enum CollisionData { }, StateTypes.NETHER_PORTAL), AZALEA((player, version, data, x, y, z) -> { - return new ComplexCollisionBox(new HexCollisionBox(0.0, 8.0, 0.0, 16.0, 16.0, 16.0), + return new ComplexCollisionBox(2, + new HexCollisionBox(0.0, 8.0, 0.0, 16.0, 16.0, 16.0), new HexCollisionBox(6.0, 0.0, 6.0, 10.0, 8.0, 10.0)); }, StateTypes.AZALEA, StateTypes.FLOWERING_AZALEA), diff --git a/src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java b/src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java index 20ec68ebf2..012f1b1536 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java @@ -216,9 +216,11 @@ public enum HitboxData { WALL_HANGING_SIGN((player, item, version, data, x, y, z) -> { return switch (data.getFacing()) { - case NORTH, SOUTH -> new ComplexCollisionBox(new HexCollisionBox(0.0D, 14.0D, 6.0D, 16.0D, 16.0D, 10.0D), + case NORTH, SOUTH -> new ComplexCollisionBox(2, + new HexCollisionBox(0.0D, 14.0D, 6.0D, 16.0D, 16.0D, 10.0D), new HexCollisionBox(1.0D, 0.0D, 7.0D, 15.0D, 10.0D, 9.0D)); - default -> new ComplexCollisionBox(new HexCollisionBox(6.0D, 14.0D, 0.0D, 10.0D, 16.0D, 16.0D), + default -> new ComplexCollisionBox(2, + new HexCollisionBox(6.0D, 14.0D, 0.0D, 10.0D, 16.0D, 16.0D), new HexCollisionBox(7.0D, 0.0D, 1.0D, 9.0D, 10.0D, 15.0D)); }; }, BlockTags.WALL_HANGING_SIGNS.getStates().toArray(new StateType[0])), @@ -263,7 +265,7 @@ public enum HitboxData { if (version.isOlderThan(ClientVersion.V_1_13)) { return new SimpleCollisionBox(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F); } else { - return new ComplexCollisionBox( + return new ComplexCollisionBox(2, new HexCollisionBox(1.0, 0.0, 1.0, 15.0, 2.0, 15.0), new SimpleCollisionBox(0.4375, 0.0, 0.4375, 0.5625, 0.875, 0.5625, false)); } @@ -303,7 +305,8 @@ public enum HitboxData { }, StateTypes.SNOW), LECTERN_BLOCK((player, item, version, data, x, y, z) -> { - ComplexCollisionBox common = new ComplexCollisionBox(new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D), + ComplexCollisionBox common = new ComplexCollisionBox(5, + new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D), new HexCollisionBox(4.0D, 2.0D, 4.0D, 12.0D, 14.0D, 12.0D)); if (data.getFacing() == BlockFace.WEST) { @@ -329,7 +332,7 @@ public enum HitboxData { GLOW_LICHEN_SCULK_VEIN((player, item, version, data, x, y, z) -> { if (version.isNewerThan(ClientVersion.V_1_16_4)) { - ComplexCollisionBox box = new ComplexCollisionBox(); + ComplexCollisionBox box = new ComplexCollisionBox(6); if (data.isUp()) { box.add(new HexCollisionBox(0.0D, 15.0D, 0.0D, 16.0D, 16.0D, 16.0D)); @@ -491,7 +494,7 @@ public enum HitboxData { } // STABLE_SHAPE for the scaffolding - ComplexCollisionBox box = new ComplexCollisionBox( + ComplexCollisionBox box = new ComplexCollisionBox(9, new HexCollisionBox(0.0D, 14.0D, 0.0D, 16.0D, 16.0D, 16.0D), new HexCollisionBox(0.0D, 0.0D, 0.0D, 2.0D, 16.0D, 2.0D), new HexCollisionBox(14.0D, 0.0D, 0.0D, 16.0D, 16.0D, 2.0D), @@ -512,7 +515,7 @@ public enum HitboxData { if (version.isOlderThanOrEquals(ClientVersion.V_1_16_4)) return new SimpleCollisionBox(0, 0, 0, 1, 1, 1, true); - ComplexCollisionBox box = new ComplexCollisionBox(); + ComplexCollisionBox box = new ComplexCollisionBox(2); if (data.getFacing() == BlockFace.NORTH) { // Stem box.add(new HexCollisionBox(5.0D, 0.0D, 9.0D, 11.0D, 15.0D, 15.0D)); @@ -653,7 +656,7 @@ private static CollisionBox getVineCollisionBox(ClientVersion version, boolean i } } else { // Via replacement - 4 sided vine - return new ComplexCollisionBox( + return new ComplexCollisionBox(4, new HexCollisionBox(0.0D, 0.0D, 0.0D, 1.0D, 16.0D, 16.0D), new HexCollisionBox(15.0D, 0.0D, 0.0D, 16.0D, 16.0D, 16.0D), new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 16.0D, 1.0D), diff --git a/src/main/java/ac/grim/grimac/utils/collisions/blocks/DynamicChorusPlant.java b/src/main/java/ac/grim/grimac/utils/collisions/blocks/DynamicChorusPlant.java index 9703e4751e..02611d3c97 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/blocks/DynamicChorusPlant.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/blocks/DynamicChorusPlant.java @@ -31,7 +31,7 @@ private static CollisionBox[] makeShapes() { float f = 0.5F - (float) 0.3125; float f1 = 0.5F + (float) 0.3125; SimpleCollisionBox baseShape = new SimpleCollisionBox(f, f, f, f1, f1, f1, false); - CollisionBox[] avoxelshape = new CollisionBox[directions.length]; + SimpleCollisionBox[] avoxelshape = new SimpleCollisionBox[directions.length]; for (int i = 0; i < directions.length; ++i) { BlockFace direction = directions[i]; @@ -41,7 +41,7 @@ private static CollisionBox[] makeShapes() { CollisionBox[] avoxelshape1 = new CollisionBox[64]; for (int k = 0; k < 64; ++k) { - ComplexCollisionBox directionalShape = new ComplexCollisionBox(baseShape); + ComplexCollisionBox directionalShape = new ComplexCollisionBox(7, baseShape); // how big is this one?? for (int j = 0; j < directions.length; ++j) { if ((k & 1 << j) != 0) { diff --git a/src/main/java/ac/grim/grimac/utils/collisions/blocks/DynamicStair.java b/src/main/java/ac/grim/grimac/utils/collisions/blocks/DynamicStair.java index 34daed22a6..9b5878a982 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/blocks/DynamicStair.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/blocks/DynamicStair.java @@ -1,10 +1,7 @@ package ac.grim.grimac.utils.collisions.blocks; import ac.grim.grimac.player.GrimPlayer; -import ac.grim.grimac.utils.collisions.datatypes.CollisionBox; -import ac.grim.grimac.utils.collisions.datatypes.CollisionFactory; -import ac.grim.grimac.utils.collisions.datatypes.ComplexCollisionBox; -import ac.grim.grimac.utils.collisions.datatypes.HexCollisionBox; +import ac.grim.grimac.utils.collisions.datatypes.*; import ac.grim.grimac.utils.nmsutil.Materials; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; @@ -18,16 +15,16 @@ import java.util.stream.IntStream; public class DynamicStair implements CollisionFactory { - protected static final CollisionBox TOP_AABB = new HexCollisionBox(0, 8, 0, 16, 16, 16); - protected static final CollisionBox BOTTOM_AABB = new HexCollisionBox(0, 0, 0, 16, 8, 16); - protected static final CollisionBox OCTET_NNN = new HexCollisionBox(0.0D, 0.0D, 0.0D, 8.0D, 8.0D, 8.0D); - protected static final CollisionBox OCTET_NNP = new HexCollisionBox(0.0D, 0.0D, 8.0D, 8.0D, 8.0D, 16.0D); - protected static final CollisionBox OCTET_NPN = new HexCollisionBox(0.0D, 8.0D, 0.0D, 8.0D, 16.0D, 8.0D); - protected static final CollisionBox OCTET_NPP = new HexCollisionBox(0.0D, 8.0D, 8.0D, 8.0D, 16.0D, 16.0D); - protected static final CollisionBox OCTET_PNN = new HexCollisionBox(8.0D, 0.0D, 0.0D, 16.0D, 8.0D, 8.0D); - protected static final CollisionBox OCTET_PNP = new HexCollisionBox(8.0D, 0.0D, 8.0D, 16.0D, 8.0D, 16.0D); - protected static final CollisionBox OCTET_PPN = new HexCollisionBox(8.0D, 8.0D, 0.0D, 16.0D, 16.0D, 8.0D); - protected static final CollisionBox OCTET_PPP = new HexCollisionBox(8.0D, 8.0D, 8.0D, 16.0D, 16.0D, 16.0D); + protected static final SimpleCollisionBox TOP_AABB = new HexCollisionBox(0, 8, 0, 16, 16, 16); + protected static final SimpleCollisionBox BOTTOM_AABB = new HexCollisionBox(0, 0, 0, 16, 8, 16); + protected static final SimpleCollisionBox OCTET_NNN = new HexCollisionBox(0.0D, 0.0D, 0.0D, 8.0D, 8.0D, 8.0D); + protected static final SimpleCollisionBox OCTET_NNP = new HexCollisionBox(0.0D, 0.0D, 8.0D, 8.0D, 8.0D, 16.0D); + protected static final SimpleCollisionBox OCTET_NPN = new HexCollisionBox(0.0D, 8.0D, 0.0D, 8.0D, 16.0D, 8.0D); + protected static final SimpleCollisionBox OCTET_NPP = new HexCollisionBox(0.0D, 8.0D, 8.0D, 8.0D, 16.0D, 16.0D); + protected static final SimpleCollisionBox OCTET_PNN = new HexCollisionBox(8.0D, 0.0D, 0.0D, 16.0D, 8.0D, 8.0D); + protected static final SimpleCollisionBox OCTET_PNP = new HexCollisionBox(8.0D, 0.0D, 8.0D, 16.0D, 8.0D, 16.0D); + protected static final SimpleCollisionBox OCTET_PPN = new HexCollisionBox(8.0D, 8.0D, 0.0D, 16.0D, 16.0D, 8.0D); + protected static final SimpleCollisionBox OCTET_PPP = new HexCollisionBox(8.0D, 8.0D, 8.0D, 16.0D, 16.0D, 16.0D); protected static final CollisionBox[] TOP_SHAPES = makeShapes(TOP_AABB, OCTET_NNN, OCTET_PNN, OCTET_NNP, OCTET_PNP); protected static final CollisionBox[] BOTTOM_SHAPES = makeShapes(BOTTOM_AABB, OCTET_NPN, OCTET_PPN, OCTET_NPP, OCTET_PPP); private static final int[] SHAPE_BY_STATE = new int[]{12, 5, 3, 10, 14, 13, 7, 11, 13, 7, 11, 14, 8, 4, 1, 2, 4, 1, 2, 8}; @@ -85,12 +82,12 @@ private static BlockFace rotateYCCW(BlockFace face) { }; } - private static CollisionBox[] makeShapes(CollisionBox p_199779_0_, CollisionBox p_199779_1_, CollisionBox p_199779_2_, CollisionBox p_199779_3_, CollisionBox p_199779_4_) { + private static CollisionBox[] makeShapes(SimpleCollisionBox p_199779_0_, SimpleCollisionBox p_199779_1_, SimpleCollisionBox p_199779_2_, SimpleCollisionBox p_199779_3_, SimpleCollisionBox p_199779_4_) { return IntStream.range(0, 16).mapToObj((p_199780_5_) -> makeStairShape(p_199780_5_, p_199779_0_, p_199779_1_, p_199779_2_, p_199779_3_, p_199779_4_)).toArray(CollisionBox[]::new); } - private static CollisionBox makeStairShape(int p_199781_0_, CollisionBox p_199781_1_, CollisionBox p_199781_2_, CollisionBox p_199781_3_, CollisionBox p_199781_4_, CollisionBox p_199781_5_) { - ComplexCollisionBox voxelshape = new ComplexCollisionBox(p_199781_1_); + private static CollisionBox makeStairShape(int p_199781_0_, SimpleCollisionBox p_199781_1_, SimpleCollisionBox p_199781_2_, SimpleCollisionBox p_199781_3_, SimpleCollisionBox p_199781_4_, SimpleCollisionBox p_199781_5_) { + ComplexCollisionBox voxelshape = new ComplexCollisionBox(5, p_199781_1_); // can we do better than 5? if ((p_199781_0_ & 1) != 0) { voxelshape.add(p_199781_2_); } diff --git a/src/main/java/ac/grim/grimac/utils/collisions/blocks/PistonHeadCollision.java b/src/main/java/ac/grim/grimac/utils/collisions/blocks/PistonHeadCollision.java index 82d999b942..43c55d7c50 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/blocks/PistonHeadCollision.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/blocks/PistonHeadCollision.java @@ -39,33 +39,41 @@ public CollisionBox fetch(GrimPlayer player, ClientVersion version, WrappedBlock return switch (block.getFacing()) { - case UP -> new ComplexCollisionBox(new HexCollisionBox(0, 12, 0, 16, 16, 16), + case UP -> new ComplexCollisionBox(2, + new HexCollisionBox(0, 12, 0, 16, 16, 16), new HexCollisionBox(6, 0 - longAmount, 6, 10, 12, 10)); - case NORTH -> new ComplexCollisionBox(new HexCollisionBox(0, 0, 0, 16, 16, 4), + case NORTH -> new ComplexCollisionBox(2, + new HexCollisionBox(0, 0, 0, 16, 16, 4), new HexCollisionBox(6, 6, 4, 10, 10, 16 + longAmount)); case SOUTH -> { // SOUTH piston is glitched in 1.7 and 1.8, fixed in 1.9 // Don't bother with short piston boxes as 1.7/1.8 clients don't have them if (version.isOlderThanOrEquals(ClientVersion.V_1_8)) - yield new ComplexCollisionBox(new HexCollisionBox(0, 0, 12, 16, 16, 16), + yield new ComplexCollisionBox(2, + new HexCollisionBox(0, 0, 12, 16, 16, 16), new HexCollisionBox(4, 6, 0, 12, 10, 12)); - yield new ComplexCollisionBox(new HexCollisionBox(0, 0, 12, 16, 16, 16), + yield new ComplexCollisionBox(2, + new HexCollisionBox(0, 0, 12, 16, 16, 16), new HexCollisionBox(6, 6, 0 - longAmount, 10, 10, 12)); } case WEST -> { // WEST piston is glitched in 1.7 and 1.8, fixed in 1.9 // Don't bother with short piston boxes as 1.7/1.8 clients don't have them if (version.isOlderThanOrEquals(ClientVersion.V_1_8)) - yield new ComplexCollisionBox(new HexCollisionBox(0, 0, 0, 4, 16, 16), + yield new ComplexCollisionBox(2, + new HexCollisionBox(0, 0, 0, 4, 16, 16), new HexCollisionBox(6, 4, 4, 10, 12, 16)); - yield new ComplexCollisionBox(new HexCollisionBox(0, 0, 0, 4, 16, 16), + yield new ComplexCollisionBox(2, + new HexCollisionBox(0, 0, 0, 4, 16, 16), new HexCollisionBox(4, 6, 6, 16 + longAmount, 10, 10)); } - case EAST -> new ComplexCollisionBox(new HexCollisionBox(12, 0, 0, 16, 16, 16), + case EAST -> new ComplexCollisionBox(2, + new HexCollisionBox(12, 0, 0, 16, 16, 16), new HexCollisionBox(0 - longAmount, 6, 4, 12, 10, 12)); - default -> new ComplexCollisionBox(new HexCollisionBox(0, 0, 0, 16, 4, 16), + default -> new ComplexCollisionBox(2, + new HexCollisionBox(0, 0, 0, 16, 4, 16), new HexCollisionBox(6, 4, 6, 10, 16 + longAmount, 10)); }; } diff --git a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionFence.java b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionFence.java index dc4aa58c3e..2da9a7d239 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionFence.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionFence.java @@ -18,7 +18,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; public class DynamicCollisionFence extends DynamicConnecting implements CollisionFactory { - private static final CollisionBox[] COLLISION_BOXES = makeShapes(2.0F, 2.0F, 24.0F, 0.0F, 24.0F, true); + private static final CollisionBox[] COLLISION_BOXES = makeShapes(2.0F, 2.0F, 24.0F, 0.0F, 24.0F, true, 1); @Override public CollisionBox fetch(GrimPlayer player, ClientVersion version, WrappedBlockState block, int x, int y, int z) { diff --git a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionPane.java b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionPane.java index 22590282b1..fd49dbc570 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionPane.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionPane.java @@ -21,7 +21,7 @@ public class DynamicCollisionPane extends DynamicConnecting implements CollisionFactory { - private static final CollisionBox[] COLLISION_BOXES = makeShapes(1.0F, 1.0F, 16.0F, 0.0F, 16.0F, true); + private static final CollisionBox[] COLLISION_BOXES = makeShapes(1.0F, 1.0F, 16.0F, 0.0F, 16.0F, true, 1); @Override public CollisionBox fetch(GrimPlayer player, ClientVersion version, WrappedBlockState block, int x, int y, int z) { @@ -52,7 +52,7 @@ public CollisionBox fetch(GrimPlayer player, ClientVersion version, WrappedBlock if (version.isNewerThanOrEquals(ClientVersion.V_1_9)) { return COLLISION_BOXES[getAABBIndex(north, east, south, west)].copy(); } else { // 1.8 and below clients have pane bounding boxes one pixel less - ComplexCollisionBox boxes = new ComplexCollisionBox(); + ComplexCollisionBox boxes = new ComplexCollisionBox(2); if ((!west || !east) && (west || east || north || south)) { if (west) { boxes.add(new SimpleCollisionBox(0.0F, 0.0F, 0.4375F, 0.5F, 1.0F, 0.5625F)); diff --git a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionWall.java b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionWall.java index 179494f0f8..ab533afb68 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionWall.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicCollisionWall.java @@ -16,10 +16,9 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateType; public class DynamicCollisionWall extends DynamicConnecting implements CollisionFactory { - public static final CollisionBox[] BOXES = makeShapes(4.0F, 3.0F, 16.0F, 0.0F, 16.0F, false); // https://bugs.mojang.com/browse/MC-9565 // https://bugs.mojang.com/browse/MC-94016 - private static final CollisionBox[] COLLISION_BOXES = makeShapes(4.0F, 3.0F, 24.0F, 0.0F, 24.0F, false); + private static final CollisionBox[] COLLISION_BOXES = makeShapes(4.0F, 3.0F, 24.0F, 0.0F, 24.0F, false, 1); /** * @deprecated use DynamicHitboxWall @@ -53,12 +52,11 @@ public CollisionBox fetchRegularBox(GrimPlayer player, WrappedBlockState state, // On 1.13+ clients the bounding box is much more complicated if (version.isNewerThanOrEquals(ClientVersion.V_1_13)) { - ComplexCollisionBox box = new ComplexCollisionBox(); + ComplexCollisionBox box = new ComplexCollisionBox(5); // Proper and faster way would be to compute all this beforehand if (up == 1) { box.add(new HexCollisionBox(4, 0, 4, 12, 16, 12)); - return box; } if (north == 1) { @@ -81,6 +79,7 @@ public CollisionBox fetchRegularBox(GrimPlayer player, WrappedBlockState state, } else if (east == 2) { box.add(new HexCollisionBox(5, 0, 5, 16, 16, 11)); } + return box; } // Magic 1.8 code for walls that I copied over, 1.12 below uses this mess @@ -143,9 +142,7 @@ public CollisionBox fetch(GrimPlayer player, ClientVersion version, WrappedBlock if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13)) { // Proper and faster way would be to compute all this beforehand if (up) { - ComplexCollisionBox box = new ComplexCollisionBox(COLLISION_BOXES[getAABBIndex(north, east, south, west)].copy()); - box.add(new HexCollisionBox(4, 0, 4, 12, 24, 12)); - return box; + return COLLISION_BOXES[getAABBIndex(north, east, south, west)].copy().union(new HexCollisionBox(4, 0, 4, 12, 24, 12)); } return COLLISION_BOXES[getAABBIndex(north, east, south, west)].copy(); diff --git a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicConnecting.java b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicConnecting.java index 0c387cc274..ed339eceda 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicConnecting.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicConnecting.java @@ -18,7 +18,7 @@ public class DynamicConnecting { - public static CollisionBox[] makeShapes(float p_196408_1_, float p_196408_2_, float p_196408_3_, float p_196408_4_, float p_196408_5_, boolean includeCenter) { + public static CollisionBox[] makeShapes(float p_196408_1_, float p_196408_2_, float p_196408_3_, float p_196408_4_, float p_196408_5_, boolean includeCenter, int additionalMaxIndex) { float middleMin = 8.0F - p_196408_1_; float middleMax = 8.0F + p_196408_1_; float f2 = 8.0F - p_196408_2_; @@ -29,14 +29,21 @@ public static CollisionBox[] makeShapes(float p_196408_1_, float p_196408_2_, fl SimpleCollisionBox voxelshape3 = new HexCollisionBox(0.0D, p_196408_4_, f2, f3, p_196408_5_, f3); SimpleCollisionBox voxelshape4 = new HexCollisionBox(f2, p_196408_4_, f2, 16.0D, p_196408_5_, f3); - ComplexCollisionBox voxelshape5 = new ComplexCollisionBox(voxelshape1, voxelshape4); - ComplexCollisionBox voxelshape6 = new ComplexCollisionBox(voxelshape2, voxelshape3); + ComplexCollisionBox voxelshape5 = new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape1, voxelshape4); + ComplexCollisionBox voxelshape6 = new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape2, voxelshape3); - CollisionBox[] avoxelshape = new CollisionBox[]{NoCollisionBox.INSTANCE, voxelshape2, voxelshape3, voxelshape6, voxelshape1, new ComplexCollisionBox(voxelshape2, voxelshape1), new ComplexCollisionBox(voxelshape3, voxelshape1), new ComplexCollisionBox(voxelshape6, voxelshape1), voxelshape4, new ComplexCollisionBox(voxelshape2, voxelshape4), new ComplexCollisionBox(voxelshape3, voxelshape4), new ComplexCollisionBox(voxelshape6, voxelshape4), voxelshape5, new ComplexCollisionBox(voxelshape2, voxelshape5), new ComplexCollisionBox(voxelshape3, voxelshape5), new ComplexCollisionBox(voxelshape6, voxelshape5)}; + CollisionBox[] avoxelshape = new CollisionBox[]{ + NoCollisionBox.INSTANCE, voxelshape2, voxelshape3, voxelshape6, voxelshape1, + new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape2, voxelshape1), new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape3, voxelshape1), + new ComplexCollisionBox(3 + additionalMaxIndex, voxelshape2, voxelshape3, voxelshape1), voxelshape4, + new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape2, voxelshape4), new ComplexCollisionBox(2 + additionalMaxIndex, voxelshape3, voxelshape4), + new ComplexCollisionBox(3 + additionalMaxIndex, voxelshape2, voxelshape3, voxelshape4), voxelshape5, + new ComplexCollisionBox(3 + additionalMaxIndex, voxelshape2, voxelshape1, voxelshape4), new ComplexCollisionBox(3 + additionalMaxIndex, voxelshape3, voxelshape1, voxelshape4), + new ComplexCollisionBox(4 + additionalMaxIndex, voxelshape1, voxelshape2, voxelshape3, voxelshape4)}; if (includeCenter) { for (int i = 0; i < 16; ++i) { - avoxelshape[i] = new ComplexCollisionBox(up, avoxelshape[i]); + avoxelshape[i] = avoxelshape[i].union(up); } } diff --git a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxFence.java b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxFence.java index 4d4ed8a51f..0a543ae06b 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxFence.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxFence.java @@ -16,27 +16,30 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateType; import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; -import java.util.ArrayList; -import java.util.List; public class DynamicHitboxFence extends DynamicConnecting implements HitBoxFactory { - private static final CollisionBox[] MODERN_HITBOXES = makeShapes(2.0F, 2.0F, 24.0F, 0.0F, 24.0F, true); + private static final CollisionBox[] MODERN_HITBOXES = makeShapes(2.0F, 2.0F, 24.0F, 0.0F, 24.0F, true, 1); public static SimpleCollisionBox[] LEGACY_HITBOXES = new SimpleCollisionBox[] {new SimpleCollisionBox(0.375D, 0.0D, 0.375D, 0.625D, 1.0D, 0.625D), new SimpleCollisionBox(0.375D, 0.0D, 0.375D, 0.625D, 1.0D, 1.0D), new SimpleCollisionBox(0.0D, 0.0D, 0.375D, 0.625D, 1.0D, 0.625D), new SimpleCollisionBox(0.0D, 0.0D, 0.375D, 0.625D, 1.0D, 1.0D), new SimpleCollisionBox(0.375D, 0.0D, 0.0D, 0.625D, 1.0D, 0.625D), new SimpleCollisionBox(0.375D, 0.0D, 0.0D, 0.625D, 1.0D, 1.0D), new SimpleCollisionBox(0.0D, 0.0D, 0.0D, 0.625D, 1.0D, 0.625D), new SimpleCollisionBox(0.0D, 0.0D, 0.0D, 0.625D, 1.0D, 1.0D), new SimpleCollisionBox(0.375D, 0.0D, 0.375D, 1.0D, 1.0D, 0.625D), new SimpleCollisionBox(0.375D, 0.0D, 0.375D, 1.0D, 1.0D, 1.0D), new SimpleCollisionBox(0.0D, 0.0D, 0.375D, 1.0D, 1.0D, 0.625D), new SimpleCollisionBox(0.0D, 0.0D, 0.375D, 1.0D, 1.0D, 1.0D), new SimpleCollisionBox(0.375D, 0.0D, 0.0D, 1.0D, 1.0D, 0.625D), new SimpleCollisionBox(0.375D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D), new SimpleCollisionBox(0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 0.625D), new SimpleCollisionBox(0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D)}; + // no ComplexCollisionBox produced by makeShapes is every larger than 5 SimpleCollisionBoxes + private static final int MAX_MODERN_HITBOX_COMPLEX_COLLISION_BOX_SIZE = 5; + static { - for (int i = 0; i < MODERN_HITBOXES.length; i++) { + SimpleCollisionBox[] boxes = new SimpleCollisionBox[MAX_MODERN_HITBOX_COMPLEX_COLLISION_BOX_SIZE]; + + // we start from one because MODERN_HITBOXES[0] is a NoCollisionBox + for (int i = 1; i < MODERN_HITBOXES.length; i++) { CollisionBox collisionBox = MODERN_HITBOXES[i]; - List boxes = new ArrayList<>(); - collisionBox.downCast(boxes); + int size = collisionBox.downCast(boxes); - for (SimpleCollisionBox box : boxes) { - if (box.maxY > 1) { - box.maxY = 1; + for (int j = 0; j < size; j++) { + if (boxes[j].maxY > 1) { + boxes[j].maxY = 1; } } - MODERN_HITBOXES[i] = new ComplexCollisionBox(boxes.toArray(new SimpleCollisionBox[0])); + MODERN_HITBOXES[i] = size == 1 ? boxes[0] : new ComplexCollisionBox(size, boxes); } } diff --git a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxPane.java b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxPane.java index 39226ed407..b8c98a1d93 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxPane.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxPane.java @@ -15,7 +15,7 @@ public class DynamicHitboxPane extends DynamicConnecting implements HitBoxFactory { - private static final CollisionBox[] COLLISION_BOXES = makeShapes(1.0F, 1.0F, 16.0F, 0.0F, 16.0F, true); + private static final CollisionBox[] COLLISION_BOXES = makeShapes(1.0F, 1.0F, 16.0F, 0.0F, 16.0F, true, 1); @Override public CollisionBox fetch(GrimPlayer player, StateType item, ClientVersion version, WrappedBlockState block, int x, int y, int z) { diff --git a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxWall.java b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxWall.java index d633c45c9b..4c3f1fc3d9 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxWall.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxWall.java @@ -13,8 +13,6 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateType; public class DynamicHitboxWall extends DynamicConnecting implements HitBoxFactory { - private static final CollisionBox[] HIT_BOXES = makeShapes(4.0F, 3.0F, 16.0F, 0.0F, 16.0F, false); - @Override public CollisionBox fetch(GrimPlayer player, StateType heldItem, ClientVersion version, WrappedBlockState state, int x, int y, int z) { int[] connections = getConnections(player, version, state, x, y, z); @@ -60,7 +58,7 @@ private int getConnectionValue(Enum direction, boolean sixteen) { } private CollisionBox getModernHitBox(int north, int south, int west, int east, int up) { - ComplexCollisionBox box = new ComplexCollisionBox(); + ComplexCollisionBox box = new ComplexCollisionBox(5); if (up == 1) { box.add(new HexCollisionBox(4, 0, 4, 12, 16, 12)); } diff --git a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/CollisionBox.java b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/CollisionBox.java index 0b4e363132..74d6664179 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/CollisionBox.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/CollisionBox.java @@ -17,6 +17,13 @@ public interface CollisionBox { void downCast(List list); + /** + * @param list - A list that will contain all of the SimpleCollisionBoxes representing the CollisionBox. + * @return - int representing the size of elements in the array that belong to this downcast. + * The contents of elements starting from list[size] and above are undefined and should not be iterated over. + */ + int downCast(SimpleCollisionBox[] list); + boolean isNull(); boolean isFullBlock(); diff --git a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/ComplexCollisionBox.java b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/ComplexCollisionBox.java index 340f2cf533..c87d76b82e 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/ComplexCollisionBox.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/ComplexCollisionBox.java @@ -1,19 +1,33 @@ package ac.grim.grimac.utils.collisions.datatypes; -import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; import java.util.List; public class ComplexCollisionBox implements CollisionBox { - private final List boxes = new ArrayList<>(); + // Most complex shape is the Modern MC Cauldron which is made up of 15 boxes + public static int DEFAULT_MAX_COLLISION_BOX_SIZE = 15; // increase if we somehow have a shape made of more than 15 parts. + private final SimpleCollisionBox[] boxes; + private int currentLength; - public ComplexCollisionBox(CollisionBox... boxes) { - Collections.addAll(this.boxes, boxes); + public ComplexCollisionBox(SimpleCollisionBox... boxes) { + this(DEFAULT_MAX_COLLISION_BOX_SIZE, boxes); } - public boolean add(CollisionBox collisionBox) { - return boxes.add(collisionBox); + public ComplexCollisionBox(int maxIndex) { + this.boxes = new SimpleCollisionBox[maxIndex]; + } + + public ComplexCollisionBox(int maxIndex, SimpleCollisionBox... boxes) { + this.boxes = new SimpleCollisionBox[maxIndex]; + System.arraycopy(boxes, 0, this.boxes, 0, Math.min(maxIndex, boxes.length)); + currentLength = boxes.length; + } + + public boolean add(SimpleCollisionBox collisionBox) { + boxes[currentLength] = collisionBox; + currentLength++; + return currentLength <= boxes.length; } @Override @@ -24,47 +38,54 @@ public CollisionBox union(SimpleCollisionBox other) { @Override public boolean isCollided(SimpleCollisionBox other) { - for (CollisionBox box : boxes) { - if (box.isCollided(other)) return true; + for (int i = 0; i < currentLength; i++) { + if (boxes[i].isCollided(other)) return true; } return false; } @Override public boolean isIntersected(SimpleCollisionBox other) { - for (CollisionBox box : boxes) { - if (box.isIntersected(other)) - return true; + for (int i = 0; i < currentLength; i++) { + if (boxes[i].isIntersected(other)) return true; } return false; } @Override public CollisionBox copy() { - ComplexCollisionBox cc = new ComplexCollisionBox(); - for (CollisionBox b : boxes) - cc.boxes.add(b.copy()); - return cc; + ComplexCollisionBox copy = new ComplexCollisionBox(boxes.length); + for (int i = 0; i < currentLength; i++) { + copy.boxes[i] = boxes[i].copy(); + } + copy.currentLength = this.currentLength; + return copy; } @Override public CollisionBox offset(double x, double y, double z) { - for (CollisionBox b : boxes) - b.offset(x, y, z); + for (int i = 0; i < currentLength; i++) { + boxes[i].offset(x, y ,z); + } return this; } @Override public void downCast(List list) { - for (CollisionBox box : boxes) - box.downCast(list); + list.addAll(Arrays.asList(boxes).subList(0, currentLength)); + } + + @Override + public int downCast(SimpleCollisionBox[] list) { + System.arraycopy(boxes, 0, list, 0, currentLength); + return currentLength; } @Override public boolean isNull() { - for (CollisionBox box : boxes) - if (!box.isNull()) - return false; + for (int i = 0; i < currentLength; i++) { + if (!boxes[i].isNull()) return false; + } return true; } diff --git a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/DynamicCollisionBox.java b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/DynamicCollisionBox.java index 24d65b3a20..61c958ef7a 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/DynamicCollisionBox.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/DynamicCollisionBox.java @@ -52,6 +52,11 @@ public CollisionBox offset(double x, double y, double z) { return this; } + @Override + public int downCast(SimpleCollisionBox[] list) { + return box.fetch(player, version, block, x, y, z).offset(x, y, z).downCast(list); + } + @Override public void downCast(List list) { box.fetch(player, version, block, x, y, z).offset(x, y, z).downCast(list); diff --git a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/NoCollisionBox.java b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/NoCollisionBox.java index 7914037c1a..68a2afbba7 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/NoCollisionBox.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/NoCollisionBox.java @@ -32,6 +32,9 @@ public CollisionBox offset(double x, double y, double z) { @Override public void downCast(List list) { /**/ } + @Override + public int downCast(SimpleCollisionBox[] list) { return 0; } + @Override public boolean isNull() { return true; diff --git a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/SimpleCollisionBox.java b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/SimpleCollisionBox.java index bd483dc90d..80606a72bc 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/SimpleCollisionBox.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/SimpleCollisionBox.java @@ -10,7 +10,6 @@ import org.bukkit.Location; import org.bukkit.util.Vector; -import java.util.ArrayList; import java.util.List; public class SimpleCollisionBox implements CollisionBox { @@ -20,6 +19,8 @@ public class SimpleCollisionBox implements CollisionBox { public double minX, minY, minZ, maxX, maxY, maxZ; private boolean isFullBlock = false; + SimpleCollisionBox[] boxes = new SimpleCollisionBox[ComplexCollisionBox.DEFAULT_MAX_COLLISION_BOX_SIZE]; + public SimpleCollisionBox() { this(0, 0, 0, 0, 0, 0, false); } @@ -233,11 +234,10 @@ public boolean isIntersected(CollisionBox other) { return isIntersected((SimpleCollisionBox) other); } - List boxes = new ArrayList<>(); - other.downCast(boxes); + int size = other.downCast(boxes); - for (SimpleCollisionBox box : boxes) { - if (isIntersected(box)) return true; + for (int i = 0; i < size; i++) { + if (isIntersected(boxes[i])) return true; } return false; @@ -268,6 +268,12 @@ public void downCast(List list) { list.add(this); } + @Override + public int downCast(SimpleCollisionBox[] list) { + list[0] = this; + return 1; + } + @Override public boolean isNull() { return false; diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntity.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntity.java index bd65dd30a4..7f8b9df081 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntity.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntity.java @@ -32,7 +32,6 @@ import lombok.Getter; import java.util.ArrayList; -import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; import java.util.OptionalInt; diff --git a/src/main/java/ac/grim/grimac/utils/lists/RunningMode.java b/src/main/java/ac/grim/grimac/utils/lists/RunningMode.java index 6726c7d6e7..146a365415 100644 --- a/src/main/java/ac/grim/grimac/utils/lists/RunningMode.java +++ b/src/main/java/ac/grim/grimac/utils/lists/RunningMode.java @@ -4,8 +4,6 @@ import it.unimi.dsi.fastutil.doubles.Double2IntMap; import it.unimi.dsi.fastutil.doubles.Double2IntOpenHashMap; -import java.util.HashMap; -import java.util.Map; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue;