Compare commits
32
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72b8616ffe | ||
|
|
f82cce32f6 | ||
|
|
474ae7dd27 | ||
|
|
d85c1d267b | ||
|
|
6ce2bcb9e9 | ||
|
|
48eff610c3 | ||
|
|
677dd044ff | ||
|
|
87f30eea37 | ||
|
|
370da407ce | ||
|
|
1ef4b4eec9 | ||
|
|
954eb8b51c | ||
|
|
84ceaa29dc | ||
|
|
6974d61b9d | ||
|
|
d9a3a890c8 | ||
|
|
c4495d995a | ||
|
|
9bd5c2db0b | ||
|
|
2518b23f8b | ||
|
|
8af0dbc46d | ||
|
|
5f7d296b4d | ||
|
|
c4cd8136bf | ||
|
|
dbc0c11795 | ||
|
|
d30b024bd3 | ||
|
|
a3e979abc8 | ||
|
|
0f3bf60549 | ||
|
|
deb2628f77 | ||
|
|
2de0f49af9 | ||
|
|
39a53db067 | ||
|
|
9bfc7d7d9b | ||
|
|
7c93eda985 | ||
|
|
1e7a858aa0 | ||
|
|
11fba1b6bd | ||
|
|
330a9782bc |
No files matched your search
+5
-2
@@ -35,7 +35,10 @@ java {
|
||||
|
||||
// Set to false for debug builds
|
||||
// You cannot live reload classes if the jar relocates dependencies
|
||||
var relocate = true;
|
||||
// Checks Project properties -> environment variable -> defaults true
|
||||
val relocate: Boolean = project.findProperty("relocate")?.toString()?.toBoolean()
|
||||
?: System.getenv("RELOCATE_JAR")?.toBoolean()
|
||||
?: true
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
@@ -57,7 +60,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.github.retrooper:packetevents-spigot:2.5.1-SNAPSHOT")
|
||||
implementation("com.github.retrooper:packetevents-spigot:2.6.1-SNAPSHOT")
|
||||
implementation("co.aikar:acf-paper:0.5.1-SNAPSHOT")
|
||||
implementation("club.minnced:discord-webhooks:0.8.0") // Newer versions include kotlin-stdlib, which leads to incompatibility with plugins that use Kotlin
|
||||
implementation("it.unimi.dsi:fastutil:8.5.13")
|
||||
|
||||
@@ -23,7 +23,8 @@ public class BadPacketsE extends Check implements PacketCheck {
|
||||
noReminderTicks = 0;
|
||||
} else if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
|
||||
noReminderTicks++;
|
||||
} else if (event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE) {
|
||||
} else if (event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE ||
|
||||
event.getPacketType() == PacketType.Play.Client.VEHICLE_MOVE) {
|
||||
noReminderTicks = 0; // Exempt vehicles
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,9 @@ public class BadPacketsR extends Check implements PacketCheck {
|
||||
if ((event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION ||
|
||||
event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION) && !player.compensatedEntities.getSelf().inVehicle()) {
|
||||
positions++;
|
||||
} else if (event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE && player.compensatedEntities.getSelf().inVehicle()) {
|
||||
} else if ((event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE ||
|
||||
event.getPacketType() == PacketType.Play.Client.VEHICLE_MOVE)
|
||||
&& player.compensatedEntities.getSelf().inVehicle()) {
|
||||
positions++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPl
|
||||
import static ac.grim.grimac.events.packets.patch.ResyncWorldUtil.resyncPosition;
|
||||
import static ac.grim.grimac.utils.nmsutil.BlockBreakSpeed.getBlockDamage;
|
||||
|
||||
@CheckData(name = "BadPacketsZ", experimental = true)
|
||||
@CheckData(name = "BadPacketsZ")
|
||||
public class BadPacketsZ extends Check implements PacketCheck {
|
||||
public BadPacketsZ(final GrimPlayer player) {
|
||||
super(player);
|
||||
|
||||
@@ -59,7 +59,7 @@ public class MultiInteractA extends Check implements PostPredictionCheck {
|
||||
// we don't need to check pre-1.9 players here (no tick skipping)
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
if (player.isTickingReliablyFor(3) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
for (String verbose : flags) {
|
||||
flagAndAlert(verbose);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class MultiInteractB extends Check implements PostPredictionCheck {
|
||||
// we don't need to check pre-1.9 players here (no tick skipping)
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) return;
|
||||
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
if (player.isTickingReliablyFor(3) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
for (String verbose : flags) {
|
||||
flagAndAlert(verbose);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public class PostCheck extends Check implements PacketCheck, PostPredictionCheck
|
||||
// Okay, the user might be cheating, let's double check
|
||||
// 1.8 clients have the idle packet, and this shouldn't false on 1.8 clients
|
||||
// 1.9+ clients have predictions, which will determine if hidden tick skipping occurred
|
||||
if (player.isTickingReliablyFor(3)) {
|
||||
if (player.isTickingReliablyFor(3) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
for (String flag : flags) {
|
||||
flagAndAlert(flag);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class MultiPlace extends BlockPlaceCheck {
|
||||
|
||||
@Override
|
||||
public void onPredictionComplete(PredictionComplete predictionComplete) {
|
||||
if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && player.isTickingReliablyFor(3)) {
|
||||
if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8) && player.isTickingReliablyFor(3) && !player.uncertaintyHandler.lastVehicleSwitch.hasOccurredSince(0)) {
|
||||
for (String verbose : flags) {
|
||||
flagAndAlert(verbose);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import ac.grim.grimac.player.GrimPlayer;
|
||||
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 @@ import java.util.List;
|
||||
public class BlockPlaceCheck extends Check implements RotationCheck, PostPredictionCheck {
|
||||
private static final List<StateType> weirdBoxes = new ArrayList<>();
|
||||
private static final List<StateType> buggyBoxes = new ArrayList<>();
|
||||
private final SimpleCollisionBox[] boxes = new SimpleCollisionBox[ComplexCollisionBox.DEFAULT_MAX_COLLISION_BOX_SIZE];
|
||||
|
||||
protected int cancelVL;
|
||||
|
||||
@@ -69,11 +71,11 @@ public class BlockPlaceCheck extends Check implements RotationCheck, PostPredict
|
||||
Vector3i clicked = place.getPlacedAgainstBlockLocation();
|
||||
CollisionBox placedOn = HitboxData.getBlockHitbox(player, place.getMaterial(), player.getClientVersion(), player.compensatedWorld.getWrappedBlockStateAt(clicked), clicked.getX(), clicked.getY(), clicked.getZ());
|
||||
|
||||
List<SimpleCollisionBox> 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);
|
||||
|
||||
@@ -3,6 +3,8 @@ package ac.grim.grimac.commands;
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.utils.anticheat.MessageUtil;
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import co.aikar.commands.BukkitCommandCompletionContext;
|
||||
import co.aikar.commands.CommandCompletions.CommandCompletionHandler;
|
||||
import co.aikar.commands.annotation.CommandAlias;
|
||||
import co.aikar.commands.annotation.CommandCompletion;
|
||||
import co.aikar.commands.annotation.CommandPermission;
|
||||
@@ -10,16 +12,21 @@ import co.aikar.commands.annotation.Subcommand;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@CommandAlias("grim|grimac")
|
||||
public class GrimStopSpectating extends BaseCommand {
|
||||
public static final CommandCompletionHandler<BukkitCommandCompletionContext> completionHandler = context -> context.getSender().hasPermission("grim.spectate.stophere") ? List.of("here") : List.of();
|
||||
|
||||
@Subcommand("stopspectating")
|
||||
@CommandPermission("grim.spectate")
|
||||
@CommandCompletion("here")
|
||||
@CommandCompletion("@stopspectating")
|
||||
public void onStopSpectate(CommandSender sender, String[] args) {
|
||||
String string = args.length > 0 ? args[0] : null;
|
||||
if (!(sender instanceof Player player)) return;
|
||||
if (!(sender instanceof Player)) return;
|
||||
Player player = (Player) sender;
|
||||
if (GrimAPI.INSTANCE.getSpectateManager().isSpectating(player.getUniqueId())) {
|
||||
boolean teleportBack = string == null || !string.equalsIgnoreCase("here");
|
||||
boolean teleportBack = string == null || !string.equalsIgnoreCase("here") || !sender.hasPermission("grim.spectate.stophere");
|
||||
GrimAPI.INSTANCE.getSpectateManager().disable(player, teleportBack);
|
||||
} else {
|
||||
String message = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("cannot-spectate-return", "%prefix% &cYou can only do this after spectating a player.");
|
||||
|
||||
@@ -98,6 +98,10 @@ public class PacketEntityReplication extends Check implements PacketCheck {
|
||||
WrapperPlayServerSpawnPlayer packetOutEntity = new WrapperPlayServerSpawnPlayer(event);
|
||||
addEntity(packetOutEntity.getEntityId(), packetOutEntity.getUUID(), EntityTypes.PLAYER, packetOutEntity.getPosition(), packetOutEntity.getYaw(), packetOutEntity.getPitch(), packetOutEntity.getEntityMetadata(), 0);
|
||||
}
|
||||
if (event.getPacketType() == PacketType.Play.Server.SPAWN_PAINTING) {
|
||||
WrapperPlayServerSpawnPainting packetOutEntity = new WrapperPlayServerSpawnPainting(event);
|
||||
addEntity(packetOutEntity.getEntityId(), packetOutEntity.getUUID(), EntityTypes.PAINTING, packetOutEntity.getPosition().toVector3d(), packetOutEntity.getDirection().getHorizontalIndex(), 0f, null, packetOutEntity.getType().isPresent() ? packetOutEntity.getType().get().getId() : -1);
|
||||
}
|
||||
|
||||
if (event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE) {
|
||||
WrapperPlayServerEntityRelativeMove move = new WrapperPlayServerEntityRelativeMove(event);
|
||||
|
||||
@@ -22,7 +22,7 @@ public class PacketPlayerSteer extends PacketListenerAbstract {
|
||||
|
||||
@Override
|
||||
public void onPacketReceive(PacketReceiveEvent event) {
|
||||
|
||||
//TODO: add support for 1.21.2 with new vehicle move packet
|
||||
if (event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE) {
|
||||
WrapperPlayClientSteerVehicle steer = new WrapperPlayClientSteerVehicle(event);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.github.retrooper.packetevents.util.Vector3i;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerMultiBlockChange;
|
||||
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
@@ -35,19 +36,20 @@ public class ResyncWorldUtil {
|
||||
|| !player.compensatedWorld.isChunkLoaded(maxBlockX >> 4, minBlockZ >> 4) || !player.compensatedWorld.isChunkLoaded(maxBlockX >> 4, maxBlockZ >> 4))
|
||||
return;
|
||||
|
||||
if (player.bukkitPlayer == null) return;
|
||||
World world = player.bukkitPlayer.getWorld();
|
||||
|
||||
// Takes 0.15ms or so to complete. Not bad IMO. Unsure how I could improve this other than sending packets async.
|
||||
// But that's on PacketEvents.
|
||||
FoliaScheduler.getRegionScheduler().execute(GrimAPI.INSTANCE.getPlugin(), player.bukkitPlayer.getWorld(),
|
||||
FoliaScheduler.getRegionScheduler().execute(GrimAPI.INSTANCE.getPlugin(), world,
|
||||
minBlockX >> 4, minBlockZ >> 4, () -> {
|
||||
boolean flat = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13);
|
||||
|
||||
if (player.bukkitPlayer == null) return;
|
||||
// Player hasn't spawned, don't spam packets
|
||||
if (!player.getSetbackTeleportUtil().hasAcceptedSpawnTeleport) return;
|
||||
|
||||
// Check the 4 corners of the BB for loaded chunks, don't freeze main thread to load chunks.
|
||||
if (!player.bukkitPlayer.getWorld().isChunkLoaded(minBlockX >> 4, minBlockZ >> 4) || !player.bukkitPlayer.getWorld().isChunkLoaded(minBlockX >> 4, maxBlockZ >> 4)
|
||||
|| !player.bukkitPlayer.getWorld().isChunkLoaded(maxBlockX >> 4, minBlockZ >> 4) || !player.bukkitPlayer.getWorld().isChunkLoaded(maxBlockX >> 4, maxBlockZ >> 4))
|
||||
if (!world.isChunkLoaded(minBlockX >> 4, minBlockZ >> 4) || !world.isChunkLoaded(minBlockX >> 4, maxBlockZ >> 4)
|
||||
|| !world.isChunkLoaded(maxBlockX >> 4, minBlockZ >> 4) || !world.isChunkLoaded(maxBlockX >> 4, maxBlockZ >> 4))
|
||||
return;
|
||||
|
||||
// This is based on Tuinity's code, thanks leaf. Now merged into paper.
|
||||
@@ -76,7 +78,7 @@ public class ResyncWorldUtil {
|
||||
int minX = currChunkX == minChunkX ? minBlockX & 15 : 0; // coordinate in chunk
|
||||
int maxX = currChunkX == maxChunkX ? maxBlockX & 15 : 15; // coordinate in chunk
|
||||
|
||||
Chunk chunk = player.bukkitPlayer.getWorld().getChunkAt(currChunkX, currChunkZ);
|
||||
Chunk chunk = world.getChunkAt(currChunkX, currChunkZ);
|
||||
|
||||
for (int currChunkY = minChunkY; currChunkY <= maxChunkY; ++currChunkY) {
|
||||
int minY = currChunkY == minChunkY ? minBlockY & 15 : 0; // coordinate in chunk
|
||||
|
||||
@@ -2,13 +2,14 @@ package ac.grim.grimac.manager.init.start;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.manager.init.Initable;
|
||||
import io.github.retrooper.packetevents.bstats.bukkit.Metrics;
|
||||
|
||||
public class BStats implements Initable {
|
||||
@Override
|
||||
public void start() {
|
||||
int pluginId = 12820; // <-- Replace with the id of your plugin!
|
||||
try {
|
||||
new io.github.retrooper.packetevents.bstats.Metrics(GrimAPI.INSTANCE.getPlugin(), pluginId);
|
||||
new Metrics(GrimAPI.INSTANCE.getPlugin(), pluginId);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,5 +23,7 @@ public class CommandRegister implements Initable {
|
||||
commandManager.registerCommand(new GrimStopSpectating());
|
||||
commandManager.registerCommand(new GrimLog());
|
||||
commandManager.registerCommand(new GrimVerbose());
|
||||
|
||||
commandManager.getCommandCompletions().registerCompletion("stopspectating", GrimStopSpectating.completionHandler);
|
||||
}
|
||||
}
|
||||
@@ -347,7 +347,7 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
player.packetStateData.lastRiptide = currentTime;
|
||||
}
|
||||
|
||||
SimpleCollisionBox steppingOnBB = GetBoundingBox.getCollisionBoxForPlayer(player, player.x, player.y, player.z).expand(0.03).offset(0, -1, 0);
|
||||
SimpleCollisionBox steppingOnBB = GetBoundingBox.getCollisionBoxForPlayer(player, player.x, player.y, player.z).expand(player.getMovementThreshold()).offset(0, -1, 0);
|
||||
Collisions.hasMaterial(player, steppingOnBB, (pair) -> {
|
||||
WrappedBlockState data = pair.first();
|
||||
if (data.getType() == StateTypes.SLIME_BLOCK && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8)) {
|
||||
@@ -411,8 +411,8 @@ public class MovementCheckRunner extends Check implements PositionCheck {
|
||||
player.uncertaintyHandler.lastUnderwaterFlyingHack.reset();
|
||||
}
|
||||
|
||||
boolean couldBeStuckSpeed = Collisions.checkStuckSpeed(player, 0.03);
|
||||
boolean couldLeaveStuckSpeed = player.isPointThree() && Collisions.checkStuckSpeed(player, -0.03);
|
||||
boolean couldBeStuckSpeed = Collisions.checkStuckSpeed(player, player.getMovementThreshold());
|
||||
boolean couldLeaveStuckSpeed = player.isPointThree() && Collisions.checkStuckSpeed(player, -player.getMovementThreshold());
|
||||
player.uncertaintyHandler.claimingLeftStuckSpeed = !player.compensatedEntities.getSelf().inVehicle() && player.stuckSpeedMultiplier.getX() < 1 && !couldLeaveStuckSpeed;
|
||||
|
||||
if (couldBeStuckSpeed) {
|
||||
|
||||
@@ -268,13 +268,14 @@ public class PlayerBaseTick {
|
||||
|
||||
|
||||
private void moveTowardsClosestSpace(double xPosition, double zPosition) {
|
||||
player.boundingBox = player.boundingBox.expand(0.03, 0, 0.03); // 0.03... thanks mojang!
|
||||
double movementThreshold = player.getMovementThreshold();
|
||||
player.boundingBox = player.boundingBox.expand(movementThreshold, 0, movementThreshold); // 0.03... thanks mojang!
|
||||
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14)) {
|
||||
moveTowardsClosestSpaceModern(xPosition, zPosition);
|
||||
} else {
|
||||
moveTowardsClosestSpaceLegacy(xPosition, zPosition);
|
||||
}
|
||||
player.boundingBox = player.boundingBox.expand(-0.03, 0, -0.03);
|
||||
player.boundingBox = player.boundingBox.expand(-movementThreshold, 0, -movementThreshold);
|
||||
}
|
||||
|
||||
// Mojang is incompetent and this will push the player out a lot when using elytras
|
||||
|
||||
@@ -127,12 +127,13 @@ public class PointThreeEstimator {
|
||||
|
||||
// Calculate head hitters. Take a shortcut by checking if the player doesn't intersect with this block, but does
|
||||
// when the player vertically moves upwards by 0.03! This is equivalent to the move method, but MUCH faster.
|
||||
SimpleCollisionBox slightlyExpanded = normalBox.copy().expand(0.03, 0, 0.03);
|
||||
if (!slightlyExpanded.isIntersected(data) && slightlyExpanded.offset(0, 0.03, 0).isIntersected(data)) {
|
||||
double movementThreshold = player.getMovementThreshold();
|
||||
SimpleCollisionBox slightlyExpanded = normalBox.copy().expand(movementThreshold, 0, movementThreshold);
|
||||
if (!slightlyExpanded.isIntersected(data) && slightlyExpanded.offset(0, movementThreshold, 0).isIntersected(data)) {
|
||||
headHitter = true;
|
||||
}
|
||||
|
||||
SimpleCollisionBox pointThreeBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y - 0.03, player.z, 0.66f, 1.86f);
|
||||
SimpleCollisionBox pointThreeBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y - movementThreshold, player.z, 0.66f, 1.86f);
|
||||
if ((Materials.isWater(player.getClientVersion(), state) || stateType == StateTypes.LAVA) &&
|
||||
pointThreeBox.isIntersected(new SimpleCollisionBox(x, y, z))) {
|
||||
|
||||
@@ -212,7 +213,8 @@ public class PointThreeEstimator {
|
||||
}
|
||||
|
||||
public void endOfTickTick() {
|
||||
SimpleCollisionBox pointThreeBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y - 0.03, player.z, 0.66f, 1.86f);
|
||||
double movementThreshold = player.getMovementThreshold();
|
||||
SimpleCollisionBox pointThreeBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y - movementThreshold, player.z, 0.66f, 1.86f);
|
||||
|
||||
// Determine the head hitter using the current Y position
|
||||
SimpleCollisionBox oldBB = player.boundingBox;
|
||||
@@ -222,7 +224,7 @@ public class PointThreeEstimator {
|
||||
for (float sizes : (player.skippedTickInActualMovement ? new float[]{0.6f, 1.5f, 1.8f} : new float[]{player.pose.height})) {
|
||||
// Try to limit collisions to be as small as possible, for maximum performance
|
||||
player.boundingBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y + (sizes - 0.01f), player.z, 0.6f, 0.01f);
|
||||
headHitter = headHitter || Collisions.collide(player, 0, 0.03, 0).getY() != 0.03;
|
||||
headHitter = headHitter || Collisions.collide(player, 0, movementThreshold, 0).getY() != movementThreshold;
|
||||
}
|
||||
|
||||
player.boundingBox = oldBB;
|
||||
|
||||
@@ -13,7 +13,6 @@ import ac.grim.grimac.utils.nmsutil.ReachUtils;
|
||||
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.*;
|
||||
|
||||
@@ -7,6 +7,7 @@ import ac.grim.grimac.utils.collisions.AxisUtil;
|
||||
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 lombok.Setter;
|
||||
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 class BlockPlace {
|
||||
if (BlockTags.LEAVES.contains(data.getType())) return false;
|
||||
if (BlockTags.FENCE_GATES.contains(data.getType())) return false;
|
||||
|
||||
List<SimpleCollisionBox> 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 class BlockPlace {
|
||||
if (isFullFace(facing)) return true;
|
||||
if (BlockTags.LEAVES.contains(data.getType())) return false;
|
||||
|
||||
List<SimpleCollisionBox> 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 class BlockPlace {
|
||||
}
|
||||
}
|
||||
|
||||
List<SimpleCollisionBox> 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 class BlockPlace {
|
||||
if (isFullFace(facing)) return true;
|
||||
if (BlockTags.LEAVES.contains(data.getType())) return false;
|
||||
|
||||
List<SimpleCollisionBox> 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) {
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.util.stream.Stream;
|
||||
// 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),
|
||||
|
||||
|
||||
@@ -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 @@ public enum HitboxData {
|
||||
}
|
||||
} 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),
|
||||
|
||||
@@ -31,7 +31,7 @@ public class DynamicChorusPlant implements CollisionFactory {
|
||||
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 @@ public class DynamicChorusPlant implements CollisionFactory {
|
||||
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) {
|
||||
|
||||
@@ -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 com.github.retrooper.packetevents.protocol.world.states.enums.Shape;
|
||||
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 @@ public class DynamicStair implements CollisionFactory {
|
||||
};
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
@@ -39,33 +39,41 @@ public class PistonHeadCollision implements CollisionFactory {
|
||||
|
||||
|
||||
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));
|
||||
};
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
|
||||
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) {
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
|
||||
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 class DynamicCollisionPane extends DynamicConnecting implements Collision
|
||||
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));
|
||||
|
||||
+4
-7
@@ -16,10 +16,9 @@ import com.github.retrooper.packetevents.protocol.world.states.enums.West;
|
||||
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 class DynamicCollisionWall extends DynamicConnecting implements Collision
|
||||
|
||||
// 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 class DynamicCollisionWall extends DynamicConnecting implements Collision
|
||||
} 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 class DynamicCollisionWall extends DynamicConnecting implements Collision
|
||||
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();
|
||||
|
||||
+12
-5
@@ -18,7 +18,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
|
||||
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 class DynamicConnecting {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-13
@@ -16,27 +16,29 @@ import com.github.retrooper.packetevents.protocol.world.states.enums.*;
|
||||
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)};
|
||||
|
||||
static {
|
||||
for (int i = 0; i < MODERN_HITBOXES.length; i++) {
|
||||
CollisionBox collisionBox = MODERN_HITBOXES[i];
|
||||
List<SimpleCollisionBox> boxes = new ArrayList<>();
|
||||
collisionBox.downCast(boxes);
|
||||
// no ComplexCollisionBox produced by makeShapes is every larger than 5 SimpleCollisionBoxes
|
||||
private static final int MAX_MODERN_HITBOX_COMPLEX_COLLISION_BOX_SIZE = 5;
|
||||
|
||||
for (SimpleCollisionBox box : boxes) {
|
||||
if (box.maxY > 1) {
|
||||
box.maxY = 1;
|
||||
static {
|
||||
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];
|
||||
int size = collisionBox.downCast(boxes);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||
|
||||
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) {
|
||||
|
||||
+1
-3
@@ -13,8 +13,6 @@ import com.github.retrooper.packetevents.protocol.world.states.enums.*;
|
||||
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 @@ public class DynamicHitboxWall extends DynamicConnecting implements HitBoxFactor
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -17,6 +17,13 @@ public interface CollisionBox {
|
||||
|
||||
void downCast(List<SimpleCollisionBox> 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();
|
||||
|
||||
@@ -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<CollisionBox> 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];
|
||||
currentLength = Math.min(maxIndex, boxes.length);
|
||||
System.arraycopy(boxes, 0, this.boxes, 0, this.currentLength);
|
||||
}
|
||||
|
||||
public boolean add(SimpleCollisionBox collisionBox) {
|
||||
boxes[currentLength] = collisionBox;
|
||||
currentLength++;
|
||||
return currentLength <= boxes.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -24,47 +38,54 @@ public class ComplexCollisionBox implements CollisionBox {
|
||||
|
||||
@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<SimpleCollisionBox> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,11 @@ public class DynamicCollisionBox implements CollisionBox {
|
||||
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<SimpleCollisionBox> list) {
|
||||
box.fetch(player, version, block, x, y, z).offset(x, y, z).downCast(list);
|
||||
|
||||
@@ -32,6 +32,9 @@ public class NoCollisionBox implements CollisionBox {
|
||||
@Override
|
||||
public void downCast(List<SimpleCollisionBox> list) { /**/ }
|
||||
|
||||
@Override
|
||||
public int downCast(SimpleCollisionBox[] list) { return 0; }
|
||||
|
||||
@Override
|
||||
public boolean isNull() {
|
||||
return true;
|
||||
|
||||
@@ -10,7 +10,6 @@ import it.unimi.dsi.fastutil.doubles.DoubleList;
|
||||
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 class SimpleCollisionBox implements CollisionBox {
|
||||
return isIntersected((SimpleCollisionBox) other);
|
||||
}
|
||||
|
||||
List<SimpleCollisionBox> 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 class SimpleCollisionBox implements CollisionBox {
|
||||
list.add(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int downCast(SimpleCollisionBox[] list) {
|
||||
list[0] = this;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNull() {
|
||||
return false;
|
||||
|
||||
@@ -32,7 +32,6 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package ac.grim.grimac.utils.data.packetentity;
|
||||
|
||||
import ac.grim.grimac.player.GrimPlayer;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
import com.github.retrooper.packetevents.protocol.world.Direction;
|
||||
import com.github.retrooper.packetevents.protocol.world.PaintingType;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
public class PacketEntityPainting extends PacketEntity {
|
||||
|
||||
private final @Nullable PaintingType paintingType;
|
||||
private final Direction direction;
|
||||
|
||||
public PacketEntityPainting(GrimPlayer player, UUID uuid, double x, double y, double z, @Nullable PaintingType paintingType, Direction direction) {
|
||||
super(player, uuid, EntityTypes.PAINTING, x, y, z);
|
||||
this.paintingType = paintingType;
|
||||
this.direction = direction;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,8 @@ import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionType;
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionTypes;
|
||||
import com.github.retrooper.packetevents.protocol.world.BlockFace;
|
||||
import com.github.retrooper.packetevents.protocol.world.Direction;
|
||||
import com.github.retrooper.packetevents.protocol.world.PaintingType;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
|
||||
@@ -168,22 +170,22 @@ public class CompensatedEntities {
|
||||
packetEntity = new PacketEntityHorse(player, uuid, entityType, position.getX(), position.getY(), position.getZ(), xRot);
|
||||
} else if (entityType == EntityTypes.SLIME || entityType == EntityTypes.MAGMA_CUBE || entityType == EntityTypes.PHANTOM) {
|
||||
packetEntity = new PacketEntitySizeable(player, uuid, entityType, position.getX(), position.getY(), position.getZ());
|
||||
} else if (EntityTypes.PIG.equals(entityType)) {
|
||||
packetEntity = new PacketEntityRideable(player, uuid, entityType, position.getX(), position.getY(), position.getZ());
|
||||
} else if (EntityTypes.SHULKER.equals(entityType)) {
|
||||
packetEntity = new PacketEntityShulker(player, uuid, entityType, position.getX(), position.getY(), position.getZ());
|
||||
} else if (EntityTypes.STRIDER.equals(entityType)) {
|
||||
packetEntity = new PacketEntityStrider(player, uuid, entityType, position.getX(), position.getY(), position.getZ());
|
||||
} else if (EntityTypes.isTypeInstanceOf(entityType, EntityTypes.BOAT) || EntityTypes.CHICKEN.equals(entityType)) {
|
||||
packetEntity = new PacketEntityTrackXRot(player, uuid, entityType, position.getX(), position.getY(), position.getZ(), xRot);
|
||||
} else if (EntityTypes.FISHING_BOBBER.equals(entityType)) {
|
||||
packetEntity = new PacketEntityHook(player, uuid, entityType, position.getX(), position.getY(), position.getZ(), data);
|
||||
} else if (EntityTypes.ENDER_DRAGON.equals(entityType)) {
|
||||
packetEntity = new PacketEntityEnderDragon(player, uuid, entityID, position.getX(), position.getY(), position.getZ());
|
||||
} else if (entityType == EntityTypes.PAINTING) {
|
||||
packetEntity = new PacketEntityPainting(player, uuid, position.x, position.y, position.z, data == -1 ? null : PaintingType.getById(data), Direction.getByHorizontalIndex((int) xRot));
|
||||
} else {
|
||||
if (EntityTypes.PIG.equals(entityType)) {
|
||||
packetEntity = new PacketEntityRideable(player, uuid, entityType, position.getX(), position.getY(), position.getZ());
|
||||
} else if (EntityTypes.SHULKER.equals(entityType)) {
|
||||
packetEntity = new PacketEntityShulker(player, uuid, entityType, position.getX(), position.getY(), position.getZ());
|
||||
} else if (EntityTypes.STRIDER.equals(entityType)) {
|
||||
packetEntity = new PacketEntityStrider(player, uuid, entityType, position.getX(), position.getY(), position.getZ());
|
||||
} else if (EntityTypes.isTypeInstanceOf(entityType, EntityTypes.BOAT) || EntityTypes.CHICKEN.equals(entityType)) {
|
||||
packetEntity = new PacketEntityTrackXRot(player, uuid, entityType, position.getX(), position.getY(), position.getZ(), xRot);
|
||||
} else if (EntityTypes.FISHING_BOBBER.equals(entityType)) {
|
||||
packetEntity = new PacketEntityHook(player, uuid, entityType, position.getX(), position.getY(), position.getZ(), data);
|
||||
} else if (EntityTypes.ENDER_DRAGON.equals(entityType)) {
|
||||
packetEntity = new PacketEntityEnderDragon(player, uuid, entityID, position.getX(), position.getY(), position.getZ());
|
||||
} else {
|
||||
packetEntity = new PacketEntity(player, uuid, entityType, position.getX(), position.getY(), position.getZ());
|
||||
}
|
||||
packetEntity = new PacketEntity(player, uuid, entityType, position.getX(), position.getY(), position.getZ());
|
||||
}
|
||||
|
||||
entityMap.put(entityID, packetEntity);
|
||||
|
||||
@@ -4,8 +4,6 @@ import ac.grim.grimac.utils.data.Pair;
|
||||
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;
|
||||
|
||||
|
||||
@@ -61,13 +61,14 @@ public class Collisions {
|
||||
SimpleCollisionBox oldBB = player.boundingBox;
|
||||
player.boundingBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, x, y, z, 0.6f, 0.06f);
|
||||
|
||||
double posXZ = Collisions.collide(player, 0.03, -0.03, 0.03).getY();
|
||||
double negXNegZ = Collisions.collide(player, -0.03, -0.03, -0.03).getY();
|
||||
double posXNegZ = Collisions.collide(player, 0.03, -0.03, -0.03).getY();
|
||||
double posZNegX = Collisions.collide(player, -0.03, -0.03, 0.03).getY();
|
||||
double movementThreshold = player.getMovementThreshold();
|
||||
double posXZ = Collisions.collide(player, movementThreshold, -movementThreshold, movementThreshold).getY();
|
||||
double negXNegZ = Collisions.collide(player, -movementThreshold, -movementThreshold, -movementThreshold).getY();
|
||||
double posXNegZ = Collisions.collide(player, movementThreshold, -movementThreshold, -movementThreshold).getY();
|
||||
double posZNegX = Collisions.collide(player, -movementThreshold, -movementThreshold, movementThreshold).getY();
|
||||
|
||||
player.boundingBox = oldBB;
|
||||
return negXNegZ != -0.03 || posXNegZ != -0.03 || posXZ != -0.03 || posZNegX != -0.03;
|
||||
return negXNegZ != -movementThreshold || posXNegZ != -movementThreshold || posXZ != -movementThreshold || posZNegX != -movementThreshold;
|
||||
}
|
||||
|
||||
// Call this when there isn't uncertainty on the Y axis
|
||||
|
||||
@@ -176,14 +176,14 @@ public class ReachUtils {
|
||||
}
|
||||
|
||||
public static double getMinReachToBox(GrimPlayer player, SimpleCollisionBox targetBox) {
|
||||
boolean giveMovementThresholdLenience = player.packetStateData.didLastMovementIncludePosition || player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9);
|
||||
boolean giveMovementThresholdLenience = !player.packetStateData.didLastMovementIncludePosition || player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9);
|
||||
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) targetBox.expand(0.1);
|
||||
|
||||
double lowest = Double.MAX_VALUE;
|
||||
|
||||
if (giveMovementThresholdLenience) targetBox.expand(player.getMovementThreshold());
|
||||
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
|
||||
for (double eyes : possibleEyeHeights) {
|
||||
if (giveMovementThresholdLenience) targetBox.expand(player.getMovementThreshold());
|
||||
Vector from = new Vector(player.x, player.y + eyes, player.z);
|
||||
Vector closestPoint = VectorUtils.cutBoxToVector(from, targetBox);
|
||||
lowest = Math.min(lowest, closestPoint.distance(from));
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
# GrimACのメイン設定
|
||||
# ソースコード: https://github.com/MWHunter/Grim
|
||||
# Copyright 2024 DefineOutside and contributors, Licensed under GPLv3.
|
||||
# 改変されたバイナリやGrimのコードをコピーしたプラグインは、私的なものとするか、
|
||||
# 購入者に追加料金なしで完全なソースコードを公開する必要があります
|
||||
|
||||
# "セットバック"は、Grimによってプレイヤーの違反が検知された際、プレイヤーを元の位置/状態に戻すことを意味します。
|
||||
|
||||
alerts:
|
||||
# アラートを、プレイヤーに送信するだけでなくコンソールにも送信するかどうか。
|
||||
print-to-console: true
|
||||
# これは、プロキシに接続された他のサーバー間でアラートが共有される方法を制御します。
|
||||
# Velocityを使用している場合は、Velocityの設定で 'bungee-plugin-message-channel' を有効にする必要があります。
|
||||
proxy:
|
||||
# プロキシに接続された他のサーバーにアラートを送信するかどうか。
|
||||
send: false
|
||||
# プロキシに接続された他のサーバーからのアラートを受信するかどうか。
|
||||
receive: false
|
||||
|
||||
verbose:
|
||||
print-to-console: false
|
||||
|
||||
client-brand:
|
||||
# プレイヤーのクライアントブランドが以下の正規表現のいずれかと一致する場合、オペレータにはそのプレイヤーの情報が送信されません。
|
||||
ignored-clients:
|
||||
- "^vanilla$"
|
||||
- "^fabric$"
|
||||
- "^lunarclient:v\\d+\\.\\d+\\.\\d+-\\d{4}$"
|
||||
- "^Feather Fabric$"
|
||||
|
||||
spectators:
|
||||
# 'grim.spectator' パーミッションを持つプレイヤーを、実際にスペクテイター状態でなくても非表示にするかどうか。
|
||||
hide-regardless: false
|
||||
# スペクテイター状態のプレイヤーを指定したワールドでのみ非表示にする。(空欄にするとすべてのワールドで有効)
|
||||
allowed-worlds:
|
||||
- ""
|
||||
|
||||
# プレイヤーがタイムアウトでKickされるまでの時間を設定します。 | デフォルト= 60(秒)
|
||||
max-transaction-time: 60
|
||||
|
||||
# 重複した移動パケットをキャンセルしますか?
|
||||
# 1.21でこの問題は修正されました。重複パケットの問題は、Mojangが「バケツの同期ズレ」を修正しようとしたことに起因するものでした。 https://bugs.mojang.com/browse/MC-12363
|
||||
# この設定は、V1.17-1.20.5クライアントが、V1.8サーバーに接続している際にのみ適用されます。
|
||||
cancel-duplicate-packet: true
|
||||
|
||||
# 重複パケットの回転を無視するかどうか。
|
||||
ignore-duplicate-packet-rotation: false
|
||||
|
||||
Simulation:
|
||||
# プレイヤーが違反をしていない場合、違反の度合いをどれだけ減らすかの倍率。
|
||||
# デフォルト設定のグラフ(x軸 = 秒, y軸 = 1/1000ブロック): https://www.desmos.com/calculator/d4ufgxrxer
|
||||
setback-decay-multiplier: 0.999
|
||||
# プレイヤーの動きが、シミュレーションからどれだけズレた場合に違反とみなすか。
|
||||
# シミュレーションされた動きからのズレをブロック単位で設定します。
|
||||
# OptifineのFastMath(計算の最適化)に対応するために計算テーブルを切り替え、0.001に下げるとFastMathによる誤検知を軽減します。
|
||||
# ただし、この補正がうまく機能しない場合、Grimがプレイヤーを不正と判断する可能性があります...
|
||||
threshold: 0.001
|
||||
# プレイヤーを即座にセットバックする前に、シミュレーションされた動きとプレイヤーの実際の動きの間にどれだけの違反が必要かを指定します。
|
||||
# -1で無効化できます。
|
||||
immediate-setback-threshold: 0.1
|
||||
# 全ティックでのシミュレーションとの累積ズレがこの値を超えたらリセットを開始します。
|
||||
# -1で無効化できます。
|
||||
max-advantage: 1
|
||||
# デフォルト設定では、50秒経過すると、プレイヤーのアドバンテージが4ブロックから1ブロックに減少します。
|
||||
# これは、プレイヤーが違反を蓄積しすぎて、違反を解消できなくなるのを防ぐためです。
|
||||
# デフォルトのアドバンテージの上限 (x軸 = 秒, y軸 = 1/1000ブロック): https://www.desmos.com/calculator/4lovswdarj
|
||||
max-ceiling: 4
|
||||
|
||||
# プレイヤーが移動中にブロックに入ったかどうかをチェックします。
|
||||
Phase:
|
||||
setbackvl: 1 # 1ブロック以上のズレがある場合に違反と判断します。
|
||||
decay: 0.005
|
||||
|
||||
AirLiquidPlace:
|
||||
cancelvl: 0
|
||||
|
||||
FabricatedPlace:
|
||||
cancelvl: 5
|
||||
|
||||
FarPlace:
|
||||
cancelvl: 5
|
||||
|
||||
PositionPlace:
|
||||
cancelvl: 5
|
||||
|
||||
RotationPlace:
|
||||
cancelvl: 5
|
||||
|
||||
# 予測に基づく「NoSlow」チェック
|
||||
# Grimは、バグのあるネットコードを考慮しており、右クリックやオフハンドボタンを連打しても誤検知が起こりにくくなっています。
|
||||
# 他のアンチチートよりも安定していますが、もし誤検知があれば報告してください。ネットコードの問題を多数修正しています。
|
||||
NoSlowA:
|
||||
# どれだけのズレが「チート」として扱われるか
|
||||
# デフォルトで他のズレ基準よりも低めに設定されています
|
||||
# NoSlow(速度低下なし)の状態では、0.03〜0.2の範囲で一貫してフラグが立ちます
|
||||
threshold: 0.001
|
||||
# NoSlowによるアドバンテージを無効化するため、最初の項目で即座にセットバックさせます
|
||||
setbackvl: 5
|
||||
# プレイヤーがアイテム使用時に速度低下が発生する場合、この値によりアドバンテージの累積が減少します
|
||||
decay: 0.05
|
||||
|
||||
Knockback:
|
||||
# プレイヤーが違反していない場合、総アドバンテージにどれだけの倍率を掛けるか
|
||||
setback-decay-multiplier: 0.999
|
||||
# プレイヤーの速度からどれだけズレたら違反とみなすか
|
||||
# 許容速度からのズレをブロック単位で測定します
|
||||
threshold: 0.001
|
||||
# プレイヤーが即座にセットバックされる前に、1ティックで発生しなければならない違反のしきい値
|
||||
# -1で無効化できます
|
||||
immediate-setback-threshold: 0.1
|
||||
# 全ティックでの累積アドバンテージがこの値を超えたらセットバックを開始します
|
||||
# -1で無効化できます
|
||||
max-advantage: 1
|
||||
# 違反が過剰に蓄積し、リセットが難しくなるのを防ぐための上限です
|
||||
max-ceiling: 4
|
||||
|
||||
Explosion:
|
||||
threshold: 0.001
|
||||
setbackvl: 3
|
||||
|
||||
TimerA:
|
||||
setbackvl: 10
|
||||
# プレイヤーがネットワーク遅延やラグの影響で操作がサーバーの予測より遅れている場合、
|
||||
# その遅れ分を後で使用できるように蓄積するためのミリ秒数を設定します。
|
||||
# この値を高く設定しすぎると、1.8版の高速使用、高速回復、高速弓などの不正な動作をバイパスできる可能性があるため、
|
||||
# 120ミリ秒がバランスの良い設定とされています。
|
||||
drift: 120
|
||||
# タイマーバランスの制限を開始し、不正利用を防止するためのPingのしきい値
|
||||
# 正当なプレイヤーであっても、このPingのしきい値を超えるとセットバックが発生する場合があります
|
||||
# -1で無効化
|
||||
ping-abuse-limit-threshold: 1000
|
||||
|
||||
NegativeTimer:
|
||||
# プレイヤーが移動中にどれだけミリ秒の遅延が発生した場合にフラグを立て始めるかを指定します
|
||||
# ここで指定した遅延量(ミリ秒)を超えると、違反として検知される可能性があります
|
||||
drift: 1200
|
||||
|
||||
# TimerAと同じチェック方法ですが、乗り物操作に適用されます
|
||||
TimerVehicle:
|
||||
# 目標タイマー値は1.005です
|
||||
setbackvl: 10
|
||||
|
||||
EntityControl:
|
||||
setbackvl: 25
|
||||
|
||||
Reach:
|
||||
# ヒットボックスをどれだけ拡大するかを設定します。0.0005に設定することで3.0005以上のリーチを検出できます
|
||||
#
|
||||
# プロトコルの変更や制限により、1.9〜1.18.1(1.18.2を除く)や
|
||||
# 一部のクライアント/サーバーの組み合わせでは、強制的に0.03の拡大が適用される場合があります。
|
||||
# このチェックは1.7/1.8クライアントが1.8サーバーに接続した際に最も効果的です。
|
||||
threshold: 0.0005
|
||||
# 不可能なヒット(距離的に届かない攻撃)をキャンセルするか
|
||||
# 3.00〜3.03のリーチによるヒットが通る場合がありますが、パケット順序の制限によりフラグが立つこともあります
|
||||
block-impossible-hits: true
|
||||
# チート検出の可能性を高めるため、各ティックの終わりに追加のパケットを送信します
|
||||
# これはサーバーの接続リストに挿入され、サーバーがフラッシュする直前に送信されます
|
||||
# 有効にすると全プレイヤーの帯域幅使用量が増加しますが、サーバーのパフォーマンスは低下しません
|
||||
# 有効にすることでさらに多くのチーターを検出できますが、
|
||||
# 無効のままでもチーターを検出でき、誤検知も発生しません
|
||||
# PvP特化の1.8サーバーでない限り、この追加パケットの有効化は推奨されません
|
||||
enable-post-packet: false
|
||||
|
||||
exploit:
|
||||
# エリトラでダッシュジャンプを行うと非常に高い速度を得られるエクスプロイト(意図しない挙動)があります。
|
||||
# この設定をfalseにすると、そのエクスプロイトを防ぎます
|
||||
# Mojangのネットコードにより、エリトラの動作は開始がクライアント側、終了がサーバー側で処理されるためにズレが生じています。
|
||||
# エリトラは水平摩擦0.99を持ち、水平速度0.2が常に追加されると非常に高速度になります。
|
||||
allow-sprint-jumping-when-using-elytra: true
|
||||
|
||||
# このオプションは、ゴーストブロックが発生したときにプレイヤーを再同期させることで、
|
||||
# ゴーストブロックへのブロック設置をできるだけ制限します
|
||||
allow-building-on-ghostblocks: true
|
||||
|
||||
# 上記の設定に基づき、ゴーストブロックのチェック距離を定義します
|
||||
# 設定可能な範囲は2から4です
|
||||
distance-to-check-if-ghostblocks: 2
|
||||
|
||||
# Nettyに参加時にプラグインが注入された場合の互換性問題をデバッグするためにログを有効にします
|
||||
debug-pipeline-on-join: false
|
||||
|
||||
# 実験的なチェックを有効にします
|
||||
experimental-checks: false
|
||||
|
||||
# Grimは "Timer" のような違反パケットをキャンセルすることがありますが、1秒間にキャンセルされたパケット数がXを超えた場合、
|
||||
# プレイヤーを強制的にキックしますか?これは、いくつかのパケットリミッターがGrimによってキャンセルされたパケットをカウントしないためです。
|
||||
packet-spam-threshold: 100
|
||||
|
||||
# Grimは、飛行状態を解除されたプレイヤーがXミリ秒以上のPingを持つことを許可しません
|
||||
# これは、現在Grimが飛行中のプレイヤーをチェックしていないためです
|
||||
# 無効にするには、-1を設定してください
|
||||
max-ping-out-of-flying: 1000
|
||||
|
||||
# プレイヤーから、ロケット花火による加速効果を削除する際の最大ピン値
|
||||
# これにより、レイテンシの高いプレイヤーが1つのロケット花火による加速でエリトラを永久に使用するのを防ぎます。
|
||||
max-ping-firework-boost: 1000
|
||||
|
||||
config-version: 9
|
||||
@@ -0,0 +1,15 @@
|
||||
# このファイルは、アラートをDiscordに送信するための設定ファイルです。
|
||||
# webhookの取得方法は、以下を参照してください
|
||||
# https://support.discord.com/hc/ja/articles/228383668-Webhooks-%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9
|
||||
enabled: false
|
||||
webhook: ""
|
||||
embed-title: "**Grim アラート**"
|
||||
embed-color: "#00FFFF"
|
||||
violation-content:
|
||||
- "**プレイヤー**: %player%"
|
||||
- "**違反項目**: %check%"
|
||||
- "**違反回数**: %violations%"
|
||||
- "**クライアントバージョン**: %version%"
|
||||
- "**ブランド**: %brand%"
|
||||
- "**Ping**: %ping%"
|
||||
- "**TPS**: %tps%"
|
||||
@@ -0,0 +1,53 @@
|
||||
# 16進数コードも使用できます。フォーマットは #FFFFFF または #ffffff です。
|
||||
|
||||
# \u00BB は » (二重 >>)です。ANSI と UTF-8 はこれを異なる方法で解釈します... 場合によっては ? と表示されることがあります。
|
||||
prefix: "&bGrim &8\u00BB"
|
||||
|
||||
alerts-enabled: "%prefix% &fアラートが有効になりました"
|
||||
alerts-disabled: "%prefix% &fアラートが無効になりました"
|
||||
client-brand-format: "%prefix% &f%player% が %brand% を使用して参加しました"
|
||||
console-specify-target: "%prefix% &cコンソールでターゲットを指定する必要があります!"
|
||||
player-not-found: "%prefix% &cプレイヤーはチェックから免除されているか、オフラインです!"
|
||||
player-not-this-server: "%prefix% &cプレイヤーはこのサーバーにいません!"
|
||||
spectate-return: "\n%prefix% &f以前の場所に戻るにはここをクリック\n"
|
||||
cannot-spectate-return: "%prefix% &c観戦しているプレイヤー以外ではこの操作はできません"
|
||||
cannot-run-on-self: "%prefix% &c自分に対してこのコマンドは使用できません!"
|
||||
upload-log: "%prefix% &fデバッグをアップロードしました: %url%"
|
||||
upload-log-start: "%prefix% &fログをアップロード中... しばらくお待ちください"
|
||||
upload-log-not-found: "%prefix% &cそのログが見つかりません"
|
||||
upload-log-upload-failure: "%prefix% &cログのアップロード中に問題が発生しました。詳細はコンソールを確認してください"
|
||||
|
||||
# 使用可能なプレースホルダー:
|
||||
# %prefix%
|
||||
# %player%
|
||||
# %check_name%
|
||||
# %description%
|
||||
# %experimental%
|
||||
# %vl% - 違反回数
|
||||
# %verbose% - チェックからの追加情報(全てのチェックが情報を追加するわけではありません)
|
||||
alerts-format: "%prefix% &f%player% が &b%check_name%%experimental% &fに失敗しました (x&c%vl%&f) &7%verbose%"
|
||||
alerts-format-proxy: "%prefix% &f[&cプロキシ&f] &f%player% が &b%check_name%%experimental% &fに失敗しました (x&c%vl%&f) &7%verbose%"
|
||||
experimental-symbol: "*"
|
||||
|
||||
profile:
|
||||
- "&7======================"
|
||||
- "%prefix% &b%player% のプロファイル"
|
||||
- "&bPing: &f%ping%"
|
||||
- "&bバージョン: &f%version%"
|
||||
- "&bクライアントブランド: &f%brand%"
|
||||
- "&b水平感度: &f%h_sensitivity%%"
|
||||
- "&b垂直感度: &f%v_sensitivity%%"
|
||||
- "&bFastMath 有効: &f%fast_math%"
|
||||
- "&7======================"
|
||||
help:
|
||||
- "&7======================"
|
||||
- "/grim alerts &f- &7アラートを切り替えます"
|
||||
- "/grim profile <player> &f- &7プレイヤー情報を表示します"
|
||||
- "/grim help &f- &7このヘルプメッセージを表示します"
|
||||
- "/grim debug <player> &f- &7開発者用の予測出力を表示します"
|
||||
- "/grim perf &f- &7開発者用のパフォーマンス (ms/予測)"
|
||||
- "/grim reload &f- &7設定をリロードします"
|
||||
- "/grim spectate <player> &f- &7プレイヤーを観戦します"
|
||||
- "/grim verbose &f- &7全てのフラグをバッファなしで表示します"
|
||||
- "/grim log [0-255] &f- &7予測フラグのデバッグログをアップロードします"
|
||||
- "&7======================"
|
||||
@@ -0,0 +1,94 @@
|
||||
# %check_name% – チェックの名前
|
||||
# %description% - チェックの説明
|
||||
# %vl% - 違反回数
|
||||
# %verbose% - 追加情報
|
||||
# %player% - プレイヤー名
|
||||
# [alert] - アラート通知を行う特別なコマンド
|
||||
# [webhook] - DiscordのWebhookに通知する特別なコマンド
|
||||
# [proxy] - プロキシに接続された他のサーバーに通知する特別なコマンド(BungeeCord/Velocity用)
|
||||
処罰:
|
||||
Simulation:
|
||||
# 何秒後に違反をリセットしますか?
|
||||
remove-violations-after: 300
|
||||
# このセクションでは、指定した名前と一致するすべてのチェックに対して処罰を設定します
|
||||
# 一部のチェックを除外するには、名前の前に「!」を付けます
|
||||
# 例: !BadPacketsN
|
||||
checks:
|
||||
- "Simulation"
|
||||
- "GroundSpoof"
|
||||
- "Timer"
|
||||
- "NoFall"
|
||||
# しきい値:間隔 コマンド
|
||||
#
|
||||
# 例: 100回の違反で「incorrect movement!」と表示しプレイヤーをキックする場合
|
||||
# commands:
|
||||
# - "100:0 kick %player% incorrect movement!"
|
||||
# 0は一度だけ実行されることを意味します
|
||||
# - "100:50 say %player% is cheating"
|
||||
# 100回違反が発生した際に実行し、その後100回以降は50回ごとに実行されます
|
||||
#
|
||||
commands:
|
||||
- "100:40 [alert]"
|
||||
- "100:100 [webhook]"
|
||||
- "100:100 [proxy]"
|
||||
Knockback:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "Knockback"
|
||||
- "Explosion"
|
||||
commands:
|
||||
- "5:5 [alert]"
|
||||
- "20:20 [webhook]"
|
||||
- "20:20 [proxy]"
|
||||
Post:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "Post"
|
||||
commands:
|
||||
- "20:20 [alert]"
|
||||
- "40:40 [webhook]"
|
||||
- "40:40 [proxy]"
|
||||
BadPackets:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "BadPackets"
|
||||
- "Crash"
|
||||
commands:
|
||||
- "20:20 [alert]"
|
||||
- "40:40 [webhook]"
|
||||
- "40:40 [proxy]"
|
||||
Reach:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "Reach"
|
||||
commands:
|
||||
- "5:5 [alert]"
|
||||
- "5:5 [webhook]"
|
||||
- "5:5 [proxy]"
|
||||
Misc:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "EntityControl"
|
||||
- "NoSlow"
|
||||
- "Place"
|
||||
- "Baritone"
|
||||
- "FastBreak"
|
||||
- "TransactionOrder"
|
||||
commands:
|
||||
- "10:5 [alert]"
|
||||
- "20:10 [webhook]"
|
||||
- "20:10 [proxy]"
|
||||
Combat:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "Killaura"
|
||||
- "Aim"
|
||||
commands:
|
||||
- "20:40 [alert]"
|
||||
# バージョン2.2.10時点では、AutoClickerのチェックはまだなく、これはプレースホルダーです。Grimは将来的にAutoClickerのチェックを追加予定です。
|
||||
Autoclicker:
|
||||
remove-violations-after: 300
|
||||
checks:
|
||||
- "Autoclicker"
|
||||
commands:
|
||||
- "20:40 [alert]"
|
||||
Reference in new issue
Block a user