Compare commits

...
Author SHA1 Message Date
Axionize 72b8616ffe Merge remote-tracking branch 'origin/2.0' into optimize-entity-packets
# Conflicts:
#	src/main/java/ac/grim/grimac/utils/latency/CompensatedEntities.java
2024-11-25 16:28:14 -05:00
SamB440 f82cce32f6 Merge pull request #1724 from K-Lqrs/2.0
[Improved] Add full Japanese translations for all GrimAC configuration files
2024-11-25 15:29:13 +00:00
AoElite 474ae7dd27 small ResyncWorldUtil refactor 2024-11-25 07:16:47 -05:00
SamB440 d85c1d267b Merge pull request #1825 from Cyramek/fix-reach
fix wrongly ported reach changes from grim 3.0
2024-11-25 09:02:36 +00:00
cyramek 6ce2bcb9e9 fix wrongly ported changes from grim 3.0 2024-11-25 09:30:21 +01:00
AoElite 48eff610c3 fixed BadPackets E & R falsing on 1.21.2+ players in vehicles 2024-11-25 00:04:00 -05:00
AoElite 677dd044ff refactor bstats for packetevents 2024-11-25 00:02:34 -05:00
AoElite 87f30eea37 added a todo 2024-11-25 00:02:02 -05:00
AoElite 370da407ce update packetevents 2024-11-25 00:01:54 -05:00
SamB440 1ef4b4eec9 Merge pull request #1821 from Axionize/fix-complex-fence-boxes
Fix CCB constructor for DynamicHitboxFence
2024-11-24 14:00:36 +00:00
AoElite 954eb8b51c Merge pull request #1783 from ManInMyVan/track-paintings
track paintings
2024-11-24 06:52:30 -05:00
AoElite 84ceaa29dc Merge pull request #1797 from ManInMyVan/stopspectating-here-permission
add permission for /grim stopspectating here
2024-11-24 06:49:33 -05:00
AoElite 6974d61b9d Merge pull request #1817 from Axionize/badpacketsx
Fix BadPacketsX false and mark it as no longer experimental
2024-11-24 06:46:58 -05:00
AoElite d9a3a890c8 Merge pull request #1818 from Axionize/badpacketsz
Mark BadPacketsZ as no longer experimental
2024-11-24 06:46:29 -05:00
AoElite c4495d995a Merge pull request #1820 from Axionize/use-movement-threshold
Use movementThreshold() instead of 0.03 where appropiate
2024-11-24 06:42:44 -05:00
Axionize 9bd5c2db0b Fix CCB constructor for DynamicHitboxFence 2024-11-24 02:38:55 -05:00
Axionize 2518b23f8b Use movementThreshold() instead of 0.03 where appropiate 2024-11-24 01:37:53 -05:00
Axionize 8af0dbc46d Mark BadPacketsZ as no longer experimental 2024-11-23 23:59:56 -05:00
SamB440 5f7d296b4d Merge pull request #1814 from Axionize/dynamically-configurable-relocate
Make relocate read from project properties --> environment variable --> default to true
2024-11-23 19:11:32 +00:00
Axionize c4cd8136bf Ensure ComplexCollisionBoxes can only contain SimpleCollisionBoxes (#1805)
* Ensure ComplexCollisionBoxes can only contain SimpleCollisionBoxes

* Optimize ComplexCollisionBoxes by using primitives internally; Make new more efficient constructors available

* Port everything to new internal .downCast() API besides getCollisionBoxes

* implement new downCast() API for Dynamic, Simple, and No Collision Boxes

* Manually size ComplexCollisionBoxes Pt. 1

* Manually size ComplexCollisionBoxes Pt. 2

* Fix new downCast() for SimpleCollisionBox

* Fix logic error in CCB constructor

* Optimize DynamicHitboxFence

* Fix logic error again in CCB constructor

* Remove debug print statement

* Fix copying CCBs in edge case

* Rename variable for clarity

* Make CCD length private var

* Make makeShapes() CCD extra maxIndex explicit; Fix DynamicCollisionWall error

* Remove unused calls to makeShapes()
2024-11-23 10:57:15 +00:00
SamB440 dbc0c11795 Merge pull request #1813 from ManInMyVan/fix/falses
fix falses
2024-11-23 10:56:35 +00:00
Axionize d30b024bd3 Make whether or not to relocate deps read from project properties -> environment variable"
Prevents having to modify build.gradle.kts when disabling relocating.
2024-11-22 21:23:12 -05:00
ManInMyVan a3e979abc8 fix falses 2024-11-22 14:33:57 -07:00
Axionize 0f3bf60549 Minor Optimization to addEntity() 2024-11-17 11:51:15 -05:00
Axionize deb2628f77 Optimize if else in updateEntityMetaData() 2024-11-17 11:50:47 -05:00
ManInMyVan 2de0f49af9 add permission for /grim stopspectating here 2024-11-15 15:04:04 -07:00
ManInMyVan 39a53db067 track paintings 2024-11-09 17:08:10 -07:00
Lars 9bfc7d7d9b わずかな間違いを修正・2 2024-11-02 23:41:34 +13:00
Lars 7c93eda985 わずかな間違いを修正 2024-11-02 19:13:51 +13:00
Lars 1e7a858aa0 Japanese向けの翻訳を修正 2024-11-02 19:10:17 +13:00
Lars 11fba1b6bd configのja.ymlを修正済み 2024-11-02 19:06:11 +13:00
Ruxy 330a9782bc Add full Japanese translations for all GrimAC configuration files 2024-09-17 10:31:53 +12:00
47 changed files with 687 additions and 197 deletions

No files matched your search

+5 -2
View File
@@ -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));
};
}
@@ -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) {
@@ -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));
@@ -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();
@@ -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);
}
}
@@ -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);
}
}
@@ -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) {
@@ -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));
+198
View File
@@ -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
+15
View File
@@ -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%"
+53
View File
@@ -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======================"
+94
View File
@@ -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]"