Skip to content

Commit

Permalink
Merge pull request #1560 from GrimAnticheat/update/1.21
Browse files Browse the repository at this point in the history
1.21 update
  • Loading branch information
SamB440 authored Jun 26, 2024
2 parents b8a3971 + f698cc9 commit d8a8468
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,9 @@ private static void handleBlockPlaceOrUseItem(PacketWrapper packet, GrimPlayer p
}

private boolean isMojangStupid(GrimPlayer player, WrapperPlayClientPlayerFlying flying) {
// Mojang has become less stupid!
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21)) return false;

final Location location = flying.getLocation();
final double threshold = player.getMovementThreshold();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import ac.grim.grimac.utils.latency.CompensatedEntities;
import ac.grim.grimac.utils.math.GrimMath;
import ac.grim.grimac.utils.nmsutil.*;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.world.BlockFace;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
Expand Down Expand Up @@ -142,7 +144,7 @@ public void updatePowderSnow() {
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_16_4)) return;

// The client first desync's this attribute
player.compensatedEntities.getSelf().playerSpeed.getModifiers().removeIf(modifier -> modifier.getUUID().equals(CompensatedEntities.SNOW_MODIFIER_UUID));
player.compensatedEntities.getSelf().playerSpeed.getModifiers().removeIf(modifier -> modifier.getUUID().equals(CompensatedEntities.SNOW_MODIFIER_UUID) || modifier.getName().getKey().equals("powder_snow"));

// And then re-adds it using purely what the server has sent it
StateType type = BlockProperties.getOnPos(player, player.mainSupportingBlockData, new Vector3d(player.x, player.y, player.z));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;

public class ComplexCollisionBox implements CollisionBox {

private final List<CollisionBox> boxes = new ArrayList<>();

public ComplexCollisionBox(CollisionBox... boxes) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ac.grim.grimac.utils.collisions.datatypes;

public class HexCollisionBox extends SimpleCollisionBox {

public HexCollisionBox(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
this.minX = minX / 16d;
this.minY = minY / 16d;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@
import com.github.retrooper.packetevents.protocol.world.BlockFace;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.util.Vector3i;
import it.unimi.dsi.fastutil.doubles.AbstractDoubleList;
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
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 {

public static final double COLLISION_EPSILON = 1.0E-7;

public double minX, minY, minZ, maxX, maxY, maxZ;
boolean isFullBlock = false;
private boolean isFullBlock = false;

public SimpleCollisionBox() {
this(0, 0, 0, 0, 0, 0, false);
Expand Down Expand Up @@ -425,6 +430,55 @@ public Vector min() {
return new Vector(minX, minY, minZ);
}

public DoubleList getYPointPositions() {
return create(minX, minY, minZ, maxX, maxY, maxZ);
}

private DoubleList create(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
if (!(maxX - minX < 1.0E-7) && !(maxY - minY < 1.0E-7) && !(maxZ - minZ < 1.0E-7)) {
int i = findBits(minX, maxX);
int j = findBits(minY, maxY);
int k = findBits(minZ, maxZ);
if (i < 0 || j < 0 || k < 0) {
return DoubleArrayList.wrap(new double[]{minY, maxY});
} else if (i == 0 && j == 0 && k == 0) {
return DoubleArrayList.wrap(new double[]{0, 1});
} else {
int m = 1 << j;

return new AbstractDoubleList() {
@Override
public double getDouble(int index) {
return (double) index / (double) m;
}

@Override
public int size() {
return m + 1;
}
};
}
} else {
return DoubleArrayList.of();
}
}

private int findBits(double min, double max) {
if (!(min < -COLLISION_EPSILON) && !(max > 1.0000001)) {
for (int i = 0; i <= 3; i++) {
int j = 1 << i;
double d = min * (double)j;
double e = max * (double)j;
boolean bl = Math.abs(d - (double)Math.round(d)) < COLLISION_EPSILON * (double)j;
boolean bl2 = Math.abs(e - (double)Math.round(e)) < COLLISION_EPSILON * (double)j;
if (bl && bl2) {
return i;
}
}
}
return -1;
}

@Override
public String toString() {
return "SimpleCollisionBox{" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,27 @@
import ac.grim.grimac.utils.nmsutil.WatchableIndexUtil;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
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.resources.ResourceLocation;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.bukkit.Bukkit;

import java.util.*;

public class CompensatedEntities {

private static final UUID SPRINTING_MODIFIER_UUID = UUID.fromString("662A6B8D-DA3E-4C1C-8813-96EA6097278D");
public static final UUID SNOW_MODIFIER_UUID = UUID.fromString("1eaf83ff-7207-4596-b37a-d7a07b3ec4ce");

public final Int2ObjectOpenHashMap<PacketEntity> entityMap = new Int2ObjectOpenHashMap<>(40, 0.7f);
public final Int2ObjectOpenHashMap<TrackerData> serverPositionsMap = new Int2ObjectOpenHashMap<>(40, 0.7f);
public Integer serverPlayerVehicle = null;
Expand Down Expand Up @@ -108,12 +113,12 @@ public double getPlayerMovementSpeed() {
public void updateAttributes(int entityID, List<WrapperPlayServerUpdateAttributes.Property> objects) {
if (entityID == player.entityID) {
for (WrapperPlayServerUpdateAttributes.Property snapshotWrapper : objects) {
final String key = snapshotWrapper.getKey();
if (key.toUpperCase().contains("MOVEMENT")) {
if (snapshotWrapper.getAttribute() == Attributes.GENERIC_MOVEMENT_SPEED) {
boolean found = false;
List<WrapperPlayServerUpdateAttributes.PropertyModifier> modifiers = snapshotWrapper.getModifiers();
for (WrapperPlayServerUpdateAttributes.PropertyModifier modifier : modifiers) {
if (modifier.getUUID().equals(SPRINTING_MODIFIER_UUID)) {
final ResourceLocation name = modifier.getName();
if (name.getKey().equals(SPRINTING_MODIFIER_UUID.toString()) || name.getKey().equals("sprinting")) {
found = true;
break;
}
Expand All @@ -125,6 +130,8 @@ public void updateAttributes(int entityID, List<WrapperPlayServerUpdateAttribute
continue;
}

// TODO recode our attribute handling
final String key = snapshotWrapper.getKey();
// Attribute limits defined by https://minecraft.wiki/w/Attribute
// These seem to be clamped on the client, but not the server
switch (key) {
Expand Down Expand Up @@ -188,7 +195,7 @@ private double calculateAttribute(WrapperPlayServerUpdateAttributes.Property sna
double d0 = snapshotWrapper.getValue();

List<WrapperPlayServerUpdateAttributes.PropertyModifier> modifiers = snapshotWrapper.getModifiers();
modifiers.removeIf(modifier -> modifier.getUUID().equals(SPRINTING_MODIFIER_UUID));
modifiers.removeIf(modifier -> modifier.getUUID().equals(SPRINTING_MODIFIER_UUID) || modifier.getName().getKey().equals("sprinting"));

for (WrapperPlayServerUpdateAttributes.PropertyModifier attributemodifier : modifiers) {
if (attributemodifier.getOperation() == WrapperPlayServerUpdateAttributes.PropertyModifier.Operation.ADDITION)
Expand Down
73 changes: 60 additions & 13 deletions src/main/java/ac/grim/grimac/utils/nmsutil/Collisions.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3d;
import it.unimi.dsi.fastutil.floats.FloatArraySet;
import it.unimi.dsi.fastutil.floats.FloatArrays;
import it.unimi.dsi.fastutil.floats.FloatSet;
import org.bukkit.Location;
import org.bukkit.util.Vector;

Expand Down Expand Up @@ -109,27 +112,50 @@ public static Vector collide(GrimPlayer player, double desiredX, double desiredY

// While running up stairs and holding space, the player activates the "lastOnGround" part without otherwise being able to step
// 0.03 movement must compensate for stepping elsewhere. Too much of a hack to include in this met5hod.
boolean movingIntoGround = (player.lastOnGround || (collisionResult.getY() != desiredY && (desiredY < 0 || clientVelY < 0))) || player.pointThreeEstimator.closeEnoughToGroundToStepWithPointThree(data, clientVelY);
boolean movingIntoGroundReal = player.pointThreeEstimator.closeEnoughToGroundToStepWithPointThree(data, clientVelY) || collisionResult.getY() != desiredY && (desiredY < 0 || clientVelY < 0);
boolean movingIntoGround = player.lastOnGround || movingIntoGroundReal;

// If the player has x or z collision, is going in the downwards direction in the last or this tick, and can step up
// If not, just return the collisions without stepping up that we calculated earlier
if (stepUpHeight > 0.0F && movingIntoGround && (collisionResult.getX() != desiredX || collisionResult.getZ() != desiredZ)) {
player.uncertaintyHandler.isStepMovement = true;
Vector regularStepUp = collideBoundingBoxLegacy(new Vector(desiredX, stepUpHeight, desiredZ), player.boundingBox, desiredMovementCollisionBoxes, order);

// 1.7 clients do not have this stepping bug fix
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8)) {
Vector stepUpBugFix = collideBoundingBoxLegacy(new Vector(0, stepUpHeight, 0), player.boundingBox.copy().expandToCoordinate(desiredX, 0, desiredZ), desiredMovementCollisionBoxes, order);
if (stepUpBugFix.getY() < stepUpHeight) {
Vector stepUpBugFixResult = collideBoundingBoxLegacy(new Vector(desiredX, 0, desiredZ), player.boundingBox.copy().offset(0, stepUpBugFix.getY(), 0), desiredMovementCollisionBoxes, order).add(stepUpBugFix);
if (getHorizontalDistanceSqr(stepUpBugFixResult) > getHorizontalDistanceSqr(regularStepUp)) {
regularStepUp = stepUpBugFixResult;
// 1.21 significantly refactored this
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21)) {
SimpleCollisionBox box2 = movingIntoGroundReal ? player.boundingBox.copy().offset(0.0, collisionResult.getY(), 0.0) : player.boundingBox.copy();
SimpleCollisionBox box3 = box2.copy().expandToCoordinate(desiredX, stepUpHeight, desiredZ);
if (!movingIntoGroundReal) {
box3 = box3.copy().expandToCoordinate(0.0, -1.0E-5F, 0.0);
}

final List<SimpleCollisionBox> list2 = new ArrayList<>();
getCollisionBoxes(player, box3, list2, false);
final float[] stepHeights = collectStepHeights(box2, list2, (float) stepUpHeight, (float) collisionResult.getY());

for (float stepHeight : stepHeights) {
Vector vec3d2 = collideBoundingBoxLegacy(new Vector(desiredX, stepHeight, desiredZ), box2, list2, order);
if (getHorizontalDistanceSqr(vec3d2) > getHorizontalDistanceSqr(collisionResult)) {
final double d = player.boundingBox.minY - box2.minY;
collisionResult = vec3d2.add(new Vector(0.0, -d, 0.0));
break;
}
}
} else {
Vector regularStepUp = collideBoundingBoxLegacy(new Vector(desiredX, stepUpHeight, desiredZ), player.boundingBox, desiredMovementCollisionBoxes, order);

// 1.7 clients do not have this stepping bug fix
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_8)) {
Vector stepUpBugFix = collideBoundingBoxLegacy(new Vector(0, stepUpHeight, 0), player.boundingBox.copy().expandToCoordinate(desiredX, 0, desiredZ), desiredMovementCollisionBoxes, order);
if (stepUpBugFix.getY() < stepUpHeight) {
Vector stepUpBugFixResult = collideBoundingBoxLegacy(new Vector(desiredX, 0, desiredZ), player.boundingBox.copy().offset(0, stepUpBugFix.getY(), 0), desiredMovementCollisionBoxes, order).add(stepUpBugFix);
if (getHorizontalDistanceSqr(stepUpBugFixResult) > getHorizontalDistanceSqr(regularStepUp)) {
regularStepUp = stepUpBugFixResult;
}
}
}
}

if (getHorizontalDistanceSqr(regularStepUp) > getHorizontalDistanceSqr(collisionResult)) {
collisionResult = regularStepUp.add(collideBoundingBoxLegacy(new Vector(0, -regularStepUp.getY() + (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14) ? desiredY : 0), 0), player.boundingBox.copy().offset(regularStepUp.getX(), regularStepUp.getY(), regularStepUp.getZ()), desiredMovementCollisionBoxes, order));
if (getHorizontalDistanceSqr(regularStepUp) > getHorizontalDistanceSqr(collisionResult)) {
collisionResult = regularStepUp.add(collideBoundingBoxLegacy(new Vector(0, -regularStepUp.getY() + (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14) ? desiredY : 0), 0), player.boundingBox.copy().offset(regularStepUp.getX(), regularStepUp.getY(), regularStepUp.getZ()), desiredMovementCollisionBoxes, order));
}
}
}

Expand All @@ -151,6 +177,27 @@ public static Vector collide(GrimPlayer player, double desiredX, double desiredY
return bestOrderResult;
}

private static float[] collectStepHeights(SimpleCollisionBox collisionBox, List<SimpleCollisionBox> collisions, float stepHeight, float collideY) {
final FloatSet floatSet = new FloatArraySet(4);

for (SimpleCollisionBox blockBox : collisions) {
for (double possibleStepY : blockBox.getYPointPositions()) {
float yDiff = (float) (possibleStepY - collisionBox.minY);
if (!(yDiff < 0.0F) && yDiff != collideY) {
if (yDiff > stepHeight) {
break;
}

floatSet.add(yDiff);
}
}
}

float[] fs = floatSet.toFloatArray();
FloatArrays.unstableSort(fs);
return fs;
}

public static boolean addWorldBorder(GrimPlayer player, SimpleCollisionBox wantedBB, List<SimpleCollisionBox> listOfBlocks, boolean onlyCheckCollide) {
// Worldborders were added in 1.8
// Don't add to border unless the player is colliding with it and is near it
Expand Down

0 comments on commit d8a8468

Please sign in to comment.