diff --git a/src/main/java/ac/grim/grimac/events/packets/PacketEntityReplication.java b/src/main/java/ac/grim/grimac/events/packets/PacketEntityReplication.java index 63214db7d6..9083beba27 100644 --- a/src/main/java/ac/grim/grimac/events/packets/PacketEntityReplication.java +++ b/src/main/java/ac/grim/grimac/events/packets/PacketEntityReplication.java @@ -18,6 +18,7 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.packettype.PacketType; import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.player.UserProfile; import com.github.retrooper.packetevents.protocol.potion.PotionType; import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; @@ -26,9 +27,12 @@ import java.util.ArrayList; import java.util.List; +import java.util.UUID; public class PacketEntityReplication extends Check implements PacketCheck { + private boolean hasSentPreWavePacket = true; + // Let's imagine the player is on a boat. // The player breaks this boat // If we were to despawn the boat without an extra transaction, then the boat would disappear before @@ -85,15 +89,15 @@ public void onPacketSend(PacketSendEvent event) { } if (event.getPacketType() == PacketType.Play.Server.SPAWN_LIVING_ENTITY) { WrapperPlayServerSpawnLivingEntity packetOutEntity = new WrapperPlayServerSpawnLivingEntity(event); - addEntity(packetOutEntity.getEntityId(), packetOutEntity.getEntityType(), packetOutEntity.getPosition(), packetOutEntity.getYaw(), packetOutEntity.getPitch(), packetOutEntity.getEntityMetadata(), 0); + addEntity(packetOutEntity.getEntityId(), packetOutEntity.getEntityUUID(), packetOutEntity.getEntityType(), packetOutEntity.getPosition(), packetOutEntity.getYaw(), packetOutEntity.getPitch(), packetOutEntity.getEntityMetadata(), 0); } if (event.getPacketType() == PacketType.Play.Server.SPAWN_ENTITY) { WrapperPlayServerSpawnEntity packetOutEntity = new WrapperPlayServerSpawnEntity(event); - addEntity(packetOutEntity.getEntityId(), packetOutEntity.getEntityType(), packetOutEntity.getPosition(), packetOutEntity.getYaw(), packetOutEntity.getPitch(), null, packetOutEntity.getData()); + addEntity(packetOutEntity.getEntityId(), packetOutEntity.getUUID().orElse(null), packetOutEntity.getEntityType(), packetOutEntity.getPosition(), packetOutEntity.getYaw(), packetOutEntity.getPitch(), null, packetOutEntity.getData()); } if (event.getPacketType() == PacketType.Play.Server.SPAWN_PLAYER) { WrapperPlayServerSpawnPlayer packetOutEntity = new WrapperPlayServerSpawnPlayer(event); - addEntity(packetOutEntity.getEntityId(), EntityTypes.PLAYER, packetOutEntity.getPosition(), packetOutEntity.getYaw(), packetOutEntity.getPitch(), packetOutEntity.getEntityMetadata(), 0); + addEntity(packetOutEntity.getEntityId(), packetOutEntity.getUUID(), EntityTypes.PLAYER, packetOutEntity.getPosition(), packetOutEntity.getYaw(), packetOutEntity.getPitch(), packetOutEntity.getEntityMetadata(), 0); } if (event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE) { @@ -119,6 +123,34 @@ public void onPacketSend(PacketSendEvent event) { player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> player.compensatedEntities.updateEntityMetadata(entityMetadata.getEntityId(), entityMetadata.getEntityMetadata())); } + // 1.19.3+ + if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO_UPDATE) { + WrapperPlayServerPlayerInfoUpdate info = new WrapperPlayServerPlayerInfoUpdate(event); + player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> { + for (WrapperPlayServerPlayerInfoUpdate.PlayerInfo entry : info.getEntries()) { + final UserProfile gameProfile = entry.getGameProfile(); + final UUID uuid = gameProfile.getUUID(); + player.compensatedEntities.profiles.put(uuid, gameProfile); + } + }); + } else if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO_REMOVE) { + WrapperPlayServerPlayerInfoRemove remove = new WrapperPlayServerPlayerInfoRemove(event); + player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> remove.getProfileIds().forEach(player.compensatedEntities.profiles::remove)); + } else if (event.getPacketType() == PacketType.Play.Server.PLAYER_INFO) { + WrapperPlayServerPlayerInfo info = new WrapperPlayServerPlayerInfo(event); + player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> { + if (info.getAction() == WrapperPlayServerPlayerInfo.Action.ADD_PLAYER) { + for (WrapperPlayServerPlayerInfo.PlayerData entry : info.getPlayerDataList()) { + final UserProfile gameProfile = entry.getUserProfile(); + final UUID uuid = gameProfile.getUUID(); + player.compensatedEntities.profiles.put(uuid, gameProfile); + } + } else if (info.getAction() == WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER) { + info.getPlayerDataList().forEach(profile -> player.compensatedEntities.profiles.remove(profile.getUserProfile().getUUID())); + } + }); + } + if (event.getPacketType() == PacketType.Play.Server.ENTITY_EFFECT) { WrapperPlayServerEntityEffect effect = new WrapperPlayServerEntityEffect(event); @@ -428,8 +460,10 @@ private void handleMoveEntity(PacketSendEvent event, int entityId, double deltaX xRotEntity.packetYaw = yaw; xRotEntity.steps = entity.isBoat() ? 10 : 3; } + entity.onFirstTransaction(isRelative, hasPos, deltaX, deltaY, deltaZ, player); }); + player.latencyUtils.addRealTimeTask(lastTrans + 1, () -> { PacketEntity entity = player.compensatedEntities.getEntity(entityId); if (entity == null) return; @@ -437,7 +471,7 @@ private void handleMoveEntity(PacketSendEvent event, int entityId, double deltaX }); } - public void addEntity(int entityID, EntityType type, Vector3d position, float xRot, float yRot, List entityMetadata, int extraData) { + public void addEntity(int entityID, UUID uuid, EntityType type, Vector3d position, float xRot, float yRot, List entityMetadata, int extraData) { if (despawnedEntitiesThisTransaction.contains(entityID)) { player.sendTransaction(); } @@ -445,7 +479,7 @@ public void addEntity(int entityID, EntityType type, Vector3d position, float xR player.compensatedEntities.serverPositionsMap.put(entityID, new TrackerData(position.getX(), position.getY(), position.getZ(), xRot, yRot, type, player.lastTransactionSent.get())); player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> { - player.compensatedEntities.addEntity(entityID, type, position, xRot, extraData); + player.compensatedEntities.addEntity(entityID, uuid, type, position, xRot, extraData); if (entityMetadata != null) { player.compensatedEntities.updateEntityMetadata(entityID, entityMetadata); } diff --git a/src/main/java/ac/grim/grimac/manager/CheckManager.java b/src/main/java/ac/grim/grimac/manager/CheckManager.java index 47451a29d7..486c5f713f 100644 --- a/src/main/java/ac/grim/grimac/manager/CheckManager.java +++ b/src/main/java/ac/grim/grimac/manager/CheckManager.java @@ -38,6 +38,7 @@ import ac.grim.grimac.utils.latency.CompensatedCooldown; import ac.grim.grimac.utils.latency.CompensatedFireworks; import ac.grim.grimac.utils.latency.CompensatedInventory; +import ac.grim.grimac.utils.team.TeamHandler; import com.github.retrooper.packetevents.event.PacketReceiveEvent; import com.github.retrooper.packetevents.event.PacketSendEvent; import com.google.common.collect.ClassToInstanceMap; @@ -65,6 +66,7 @@ public CheckManager(GrimPlayer player) { .put(PacketPlayerAbilities.class, new PacketPlayerAbilities(player)) .put(PacketWorldBorder.class, new PacketWorldBorder(player)) .put(ActionManager.class, player.actionManager) + .put(TeamHandler.class, new TeamHandler(player)) .put(ClientBrand.class, new ClientBrand(player)) .put(NoFallA.class, new NoFallA(player)) .put(BadPacketsO.class, new BadPacketsO(player)) diff --git a/src/main/java/ac/grim/grimac/manager/init/start/TickEndEvent.java b/src/main/java/ac/grim/grimac/manager/init/start/TickEndEvent.java index b7e7dbecc1..918324ea4f 100644 --- a/src/main/java/ac/grim/grimac/manager/init/start/TickEndEvent.java +++ b/src/main/java/ac/grim/grimac/manager/init/start/TickEndEvent.java @@ -3,11 +3,9 @@ import ac.grim.grimac.GrimAPI; import ac.grim.grimac.manager.init.Initable; import ac.grim.grimac.player.GrimPlayer; -import ac.grim.grimac.utils.anticheat.LogUtil; import ac.grim.grimac.utils.lists.HookedListWrapper; import com.github.retrooper.packetevents.util.reflection.Reflection; import io.github.retrooper.packetevents.util.SpigotReflectionUtil; -import org.bukkit.Bukkit; import sun.misc.Unsafe; import java.lang.reflect.Field; diff --git a/src/main/java/ac/grim/grimac/player/GrimPlayer.java b/src/main/java/ac/grim/grimac/player/GrimPlayer.java index 0e9f4509f2..46dc9d263f 100644 --- a/src/main/java/ac/grim/grimac/player/GrimPlayer.java +++ b/src/main/java/ac/grim/grimac/player/GrimPlayer.java @@ -122,6 +122,7 @@ public class GrimPlayer implements GrimUser { public boolean wasSneaking; public boolean isSprinting; public boolean lastSprinting; + public String teamName; // The client updates sprinting attribute at end of each tick // Don't false if the server update's the player's sprinting status public boolean lastSprintingForSpeed; diff --git a/src/main/java/ac/grim/grimac/predictionengine/movementtick/MovementTicker.java b/src/main/java/ac/grim/grimac/predictionengine/movementtick/MovementTicker.java index 9eec02f3e6..47ac37a3f5 100644 --- a/src/main/java/ac/grim/grimac/predictionengine/movementtick/MovementTicker.java +++ b/src/main/java/ac/grim/grimac/predictionengine/movementtick/MovementTicker.java @@ -10,12 +10,18 @@ import ac.grim.grimac.utils.data.packetentity.PacketEntityStrider; import ac.grim.grimac.utils.math.GrimMath; import ac.grim.grimac.utils.nmsutil.*; +import ac.grim.grimac.utils.team.EntityPredicates; +import ac.grim.grimac.utils.team.TeamHandler; +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags; 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 com.viaversion.viaversion.api.Via; +import io.github.retrooper.packetevents.util.viaversion.ViaVersionUtil; import org.bukkit.util.Vector; public class MovementTicker { @@ -27,7 +33,10 @@ public MovementTicker(GrimPlayer player) { public static void handleEntityCollisions(GrimPlayer player) { // 1.7 and 1.8 do not have player collision - if (player.getClientVersion().isOlderThan(ClientVersion.V_1_9)) return; + if (player.getClientVersion().isOlderThan(ClientVersion.V_1_9) + // Check that ViaVersion disables all collisions on a 1.8 server for 1.9+ clients + || (PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_9) + && (!ViaVersionUtil.isAvailable() || Via.getConfig().isPreventCollision()))) return; int possibleCollidingEntities = 0; @@ -35,16 +44,24 @@ public static void handleEntityCollisions(GrimPlayer player) { if (!player.compensatedEntities.getSelf().inVehicle()) { // Calculate the offset of the player to colliding other stuff SimpleCollisionBox playerBox = GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.lastX, player.lastY, player.lastZ, 0.6f, 1.8f); - SimpleCollisionBox expandedPlayerBox = playerBox.copy().expandToAbsoluteCoordinates(player.x, player.y, player.z).expand(1); + playerBox.union(GetBoundingBox.getBoundingBoxFromPosAndSize(player, player.x, player.y, player.z, 0.6f, 1.8f).expand(player.getMovementThreshold())); + playerBox.expand(0.2); + + final TeamHandler teamHandler = player.checkManager.getPacketCheck(TeamHandler.class); for (PacketEntity entity : player.compensatedEntities.entityMap.values()) { if (!entity.isPushable()) continue; + // 1.9+ player on 1.8- server with ViaVersion prevent-collision disabled. + if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9) + && !EntityPredicates.canBePushedBy(player, entity, teamHandler).test(player)) continue; + SimpleCollisionBox entityBox = entity.getPossibleCollisionBoxes(); - if (expandedPlayerBox.isCollided(entityBox)) + if (playerBox.isCollided(entityBox)) { possibleCollidingEntities++; + } } } diff --git a/src/main/java/ac/grim/grimac/predictionengine/predictions/PredictionEngine.java b/src/main/java/ac/grim/grimac/predictionengine/predictions/PredictionEngine.java index db5966b19d..d3dc910646 100644 --- a/src/main/java/ac/grim/grimac/predictionengine/predictions/PredictionEngine.java +++ b/src/main/java/ac/grim/grimac/predictionengine/predictions/PredictionEngine.java @@ -516,6 +516,7 @@ public Vector handleStartingVelocityUncertainty(GrimPlayer player, VectorData ve // // Be somewhat careful as there is an antikb (for horizontal) that relies on this lenience Vector uncertainty = new Vector(avgColliding * 0.08, additionVertical, avgColliding * 0.08); + Vector min = new Vector(player.uncertaintyHandler.xNegativeUncertainty - additionHorizontal, -bonusY + player.uncertaintyHandler.yNegativeUncertainty, player.uncertaintyHandler.zNegativeUncertainty - additionHorizontal); Vector max = new Vector(player.uncertaintyHandler.xPositiveUncertainty + additionHorizontal, bonusY + player.uncertaintyHandler.yPositiveUncertainty, player.uncertaintyHandler.zPositiveUncertainty + additionHorizontal); diff --git a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/SimpleCollisionBox.java b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/SimpleCollisionBox.java index 1d372ddee3..0c1cf2bdd2 100644 --- a/src/main/java/ac/grim/grimac/utils/collisions/datatypes/SimpleCollisionBox.java +++ b/src/main/java/ac/grim/grimac/utils/collisions/datatypes/SimpleCollisionBox.java @@ -142,6 +142,16 @@ public Vector[] corners() { return vectors; } + public SimpleCollisionBox union(SimpleCollisionBox other) { + this.minX = Math.min(this.minX, other.minX); + this.minY = Math.min(this.minY, other.minY); + this.minZ = Math.min(this.minZ, other.minZ); + this.maxX = Math.max(this.maxX, other.maxX); + this.maxY = Math.max(this.maxY, other.maxY); + this.maxZ = Math.max(this.maxZ, other.maxZ); + return this; + } + public SimpleCollisionBox expandToAbsoluteCoordinates(double x, double y, double z) { return expandToCoordinate(x - ((minX + maxX) / 2), y - ((minY + maxY) / 2), z - ((minZ + maxZ) / 2)); } diff --git a/src/main/java/ac/grim/grimac/utils/data/VectorData.java b/src/main/java/ac/grim/grimac/utils/data/VectorData.java index 7c70d9f71b..5c0f7f82b0 100644 --- a/src/main/java/ac/grim/grimac/utils/data/VectorData.java +++ b/src/main/java/ac/grim/grimac/utils/data/VectorData.java @@ -138,10 +138,10 @@ public enum VectorType { TridentJump, Trident, SlimePistonBounce, - Entity_Pushing, ZeroPointZeroThree, AttackSlow, Flip_Sneaking, - Flip_Use_Item + Flip_Use_Item, + EntityPushing } } diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntity.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntity.java index e60a234c91..b4aa6fb586 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntity.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntity.java @@ -24,16 +24,20 @@ import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.potion.PotionType; import com.github.retrooper.packetevents.util.Vector3d; +import lombok.Getter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.UUID; // You may not copy this check unless your anticheat is licensed under GPL public class PacketEntity extends TypedPacketEntity { public final TrackedPosition trackedServerPosition; + @Getter + private final UUID uuid; // NULL ON VERSIONS BELOW 1.9 public PacketEntity riding; public List passengers = new ArrayList<>(0); public boolean isDead = false; @@ -49,11 +53,13 @@ public class PacketEntity extends TypedPacketEntity { public PacketEntity(EntityType type) { super(type); + this.uuid = null; this.trackedServerPosition = new TrackedPosition(); } - public PacketEntity(GrimPlayer player, EntityType type, double x, double y, double z) { + public PacketEntity(GrimPlayer player, UUID uuid, EntityType type, double x, double y, double z) { super(type); + this.uuid = uuid; this.trackedServerPosition = new TrackedPosition(); this.trackedServerPosition.setPos(new Vector3d(x, y, z)); if (player.getClientVersion().isOlderThan(ClientVersion.V_1_9)) { // Thanks ViaVersion diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityCamel.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityCamel.java index 5ab4579d69..80375f19ac 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityCamel.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityCamel.java @@ -3,12 +3,14 @@ import ac.grim.grimac.player.GrimPlayer; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import java.util.UUID; + public class PacketEntityCamel extends PacketEntityHorse { public boolean dashing = false; //TODO: handle camel dashing - public PacketEntityCamel(GrimPlayer player, EntityType type, double x, double y, double z, float xRot) { - super(player, type, x, y, z, xRot); + public PacketEntityCamel(GrimPlayer player, UUID uuid, EntityType type, double x, double y, double z, float xRot) { + super(player, uuid, type, x, y, z, xRot); jumpStrength = 0.42F; movementSpeedAttribute = 0.09f; diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityHook.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityHook.java index 566156aff4..5378518cb0 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityHook.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityHook.java @@ -3,12 +3,14 @@ import ac.grim.grimac.player.GrimPlayer; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import java.util.UUID; + public class PacketEntityHook extends PacketEntity{ public int owner; public int attached = -1; - public PacketEntityHook(GrimPlayer player, EntityType type, double x, double y, double z, int owner) { - super(player, type, x, y, z); + public PacketEntityHook(GrimPlayer player, UUID uuid, EntityType type, double x, double y, double z, int owner) { + super(player, uuid, type, x, y, z); this.owner = owner; } } diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityHorse.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityHorse.java index e9c73a6db4..fb2ce85eba 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityHorse.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityHorse.java @@ -4,6 +4,8 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import java.util.UUID; + public class PacketEntityHorse extends PacketEntityTrackXRot { public boolean isRearing = false; public boolean hasSaddle = false; @@ -11,8 +13,8 @@ public class PacketEntityHorse extends PacketEntityTrackXRot { public double jumpStrength = 0.7; public float movementSpeedAttribute = 0.225f; - public PacketEntityHorse(GrimPlayer player, EntityType type, double x, double y, double z, float xRot) { - super(player, type, x, y, z, xRot); + public PacketEntityHorse(GrimPlayer player, UUID uuid, EntityType type, double x, double y, double z, float xRot) { + super(player, uuid, type, x, y, z, xRot); this.stepHeight = 1.0f; if (EntityTypes.isTypeInstanceOf(type, EntityTypes.CHESTED_HORSE)) { diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityRideable.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityRideable.java index 0a6a50f9c2..9054589782 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityRideable.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityRideable.java @@ -3,6 +3,8 @@ import ac.grim.grimac.player.GrimPlayer; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import java.util.UUID; + public class PacketEntityRideable extends PacketEntity { public boolean hasSaddle = false; @@ -11,8 +13,8 @@ public class PacketEntityRideable extends PacketEntity { public float movementSpeedAttribute = 0.1f; - public PacketEntityRideable(GrimPlayer player, EntityType type, double x, double y, double z) { - super(player, type, x, y, z); + public PacketEntityRideable(GrimPlayer player, UUID uuid, EntityType type, double x, double y, double z) { + super(player, uuid, type, x, y, z); this.stepHeight = 1.0f; } } diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityShulker.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityShulker.java index 67e07dbc71..44c6e4318e 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityShulker.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityShulker.java @@ -4,10 +4,12 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.world.BlockFace; +import java.util.UUID; + public class PacketEntityShulker extends PacketEntity { public BlockFace facing = BlockFace.DOWN; - public PacketEntityShulker(GrimPlayer player, EntityType type, double x, double y, double z) { - super(player, type, x, y, z); + public PacketEntityShulker(GrimPlayer player, UUID uuid, EntityType type, double x, double y, double z) { + super(player, uuid, type, x, y, z); } } diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntitySizeable.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntitySizeable.java index c070228554..dad86ef97e 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntitySizeable.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntitySizeable.java @@ -3,10 +3,12 @@ import ac.grim.grimac.player.GrimPlayer; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import java.util.UUID; + public class PacketEntitySizeable extends PacketEntity { public int size = 4; // To support entity metadata being sent after spawn, assume max size of vanilla slime - public PacketEntitySizeable(GrimPlayer player, EntityType type, double x, double y, double z) { - super(player, type, x, y, z); + public PacketEntitySizeable(GrimPlayer player, UUID uuid, EntityType type, double x, double y, double z) { + super(player, uuid, type, x, y, z); } } diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityStrider.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityStrider.java index ef5182dfea..408bd69d34 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityStrider.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityStrider.java @@ -3,10 +3,12 @@ import ac.grim.grimac.player.GrimPlayer; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import java.util.UUID; + public class PacketEntityStrider extends PacketEntityRideable { public boolean isShaking = false; - public PacketEntityStrider(GrimPlayer player, EntityType type, double x, double y, double z) { - super(player, type, x, y, z); + public PacketEntityStrider(GrimPlayer player, UUID uuid, EntityType type, double x, double y, double z) { + super(player, uuid, type, x, y, z); } } diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityTrackXRot.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityTrackXRot.java index 816deb281b..de60c2086f 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityTrackXRot.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntityTrackXRot.java @@ -3,14 +3,16 @@ import ac.grim.grimac.player.GrimPlayer; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import java.util.UUID; + // We use simple interpolation here to be "close enough" public class PacketEntityTrackXRot extends PacketEntity { public float packetYaw; public float interpYaw; public int steps = 0; - public PacketEntityTrackXRot(GrimPlayer player, EntityType type, double x, double y, double z, float xRot) { - super(player, type, x, y, z); + public PacketEntityTrackXRot(GrimPlayer player, UUID uuid, EntityType type, double x, double y, double z, float xRot) { + super(player, uuid, type, x, y, z); this.packetYaw = xRot; this.interpYaw = xRot; } diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/dragon/PacketEntityEnderDragon.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/dragon/PacketEntityEnderDragon.java index 7ac3174458..81d10eee2a 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/dragon/PacketEntityEnderDragon.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/dragon/PacketEntityEnderDragon.java @@ -7,13 +7,14 @@ import java.util.ArrayList; import java.util.List; +import java.util.UUID; public final class PacketEntityEnderDragon extends PacketEntity { private final List parts = new ArrayList<>(); - public PacketEntityEnderDragon(GrimPlayer player, int entityID, double x, double y, double z) { - super(player, EntityTypes.ENDER_DRAGON, x, y, z); + public PacketEntityEnderDragon(GrimPlayer player, UUID uuid, int entityID, double x, double y, double z) { + super(player, uuid, EntityTypes.ENDER_DRAGON, x, y, z); final Int2ObjectOpenHashMap entityMap = player.compensatedEntities.entityMap; parts.add(new PacketEntityEnderDragonPart(player, DragonPart.HEAD, x, y, z, 1.0F, 1.0F)); parts.add(new PacketEntityEnderDragonPart(player, DragonPart.NECK, x, y, z, 3.0F, 3.0F)); diff --git a/src/main/java/ac/grim/grimac/utils/data/packetentity/dragon/PacketEntityEnderDragonPart.java b/src/main/java/ac/grim/grimac/utils/data/packetentity/dragon/PacketEntityEnderDragonPart.java index 87fc3059e6..9cfec6092c 100644 --- a/src/main/java/ac/grim/grimac/utils/data/packetentity/dragon/PacketEntityEnderDragonPart.java +++ b/src/main/java/ac/grim/grimac/utils/data/packetentity/dragon/PacketEntityEnderDragonPart.java @@ -4,13 +4,15 @@ import ac.grim.grimac.utils.data.packetentity.PacketEntity; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; +import java.util.UUID; + public final class PacketEntityEnderDragonPart extends PacketEntity { private final DragonPart part; private final float width, height; public PacketEntityEnderDragonPart(GrimPlayer player, DragonPart part, double x, double y, double z, float width, float height) { - super(player, EntityTypes.ENDER_DRAGON, x, y, z); + super(player, null, EntityTypes.ENDER_DRAGON, x, y, z); this.part = part; this.width = width; this.height = height; diff --git a/src/main/java/ac/grim/grimac/utils/latency/CompensatedEntities.java b/src/main/java/ac/grim/grimac/utils/latency/CompensatedEntities.java index 330c09dd67..ba0835fb5c 100644 --- a/src/main/java/ac/grim/grimac/utils/latency/CompensatedEntities.java +++ b/src/main/java/ac/grim/grimac/utils/latency/CompensatedEntities.java @@ -15,6 +15,7 @@ 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.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; @@ -23,6 +24,7 @@ import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.bukkit.Bukkit; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import java.util.*; @@ -33,6 +35,7 @@ public class CompensatedEntities { public final Int2ObjectOpenHashMap entityMap = new Int2ObjectOpenHashMap<>(40, 0.7f); public final Int2ObjectOpenHashMap serverPositionsMap = new Int2ObjectOpenHashMap<>(40, 0.7f); + public final Object2ObjectOpenHashMap profiles = new Object2ObjectOpenHashMap<>(); public Integer serverPlayerVehicle = null; public boolean hasSprintingAttributeEnabled = false; @@ -229,33 +232,33 @@ private void tickPassenger(PacketEntity riding, PacketEntity passenger) { } } - public void addEntity(int entityID, EntityType entityType, Vector3d position, float xRot, int data) { + public void addEntity(int entityID, UUID uuid, EntityType entityType, Vector3d position, float xRot, int data) { // Dropped items are all server sided and players can't interact with them (except create them!), save the performance if (entityType == EntityTypes.ITEM) return; PacketEntity packetEntity; if (EntityTypes.CAMEL.equals(entityType)) { - packetEntity = new PacketEntityCamel(player, entityType, position.getX(), position.getY(), position.getZ(), xRot); + packetEntity = new PacketEntityCamel(player, uuid, entityType, position.getX(), position.getY(), position.getZ(), xRot); } else if (EntityTypes.isTypeInstanceOf(entityType, EntityTypes.ABSTRACT_HORSE)) { - packetEntity = new PacketEntityHorse(player, entityType, position.getX(), position.getY(), position.getZ(), xRot); + 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, entityType, position.getX(), position.getY(), position.getZ()); + packetEntity = new PacketEntitySizeable(player, uuid, entityType, position.getX(), position.getY(), position.getZ()); } else { if (EntityTypes.PIG.equals(entityType)) { - packetEntity = new PacketEntityRideable(player, entityType, position.getX(), position.getY(), position.getZ()); + packetEntity = new PacketEntityRideable(player, uuid, entityType, position.getX(), position.getY(), position.getZ()); } else if (EntityTypes.SHULKER.equals(entityType)) { - packetEntity = new PacketEntityShulker(player, entityType, position.getX(), position.getY(), position.getZ()); + packetEntity = new PacketEntityShulker(player, uuid, entityType, position.getX(), position.getY(), position.getZ()); } else if (EntityTypes.STRIDER.equals(entityType)) { - packetEntity = new PacketEntityStrider(player, entityType, position.getX(), position.getY(), position.getZ()); + 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, entityType, position.getX(), position.getY(), position.getZ(), xRot); + packetEntity = new PacketEntityTrackXRot(player, uuid, entityType, position.getX(), position.getY(), position.getZ(), xRot); } else if (EntityTypes.FISHING_BOBBER.equals(entityType)) { - packetEntity = new PacketEntityHook(player, entityType, position.getX(), position.getY(), position.getZ(), data); + packetEntity = new PacketEntityHook(player, uuid, entityType, position.getX(), position.getY(), position.getZ(), data); } else if (EntityTypes.ENDER_DRAGON.equals(entityType)) { - packetEntity = new PacketEntityEnderDragon(player, entityID, position.getX(), position.getY(), position.getZ()); + packetEntity = new PacketEntityEnderDragon(player, uuid, entityID, position.getX(), position.getY(), position.getZ()); } else { - packetEntity = new PacketEntity(player, entityType, position.getX(), position.getY(), position.getZ()); + packetEntity = new PacketEntity(player, uuid, entityType, position.getX(), position.getY(), position.getZ()); } } diff --git a/src/main/java/ac/grim/grimac/utils/team/EntityPredicates.java b/src/main/java/ac/grim/grimac/utils/team/EntityPredicates.java new file mode 100644 index 0000000000..6b548899ea --- /dev/null +++ b/src/main/java/ac/grim/grimac/utils/team/EntityPredicates.java @@ -0,0 +1,33 @@ +package ac.grim.grimac.utils.team; + +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.data.packetentity.PacketEntity; +import com.github.retrooper.packetevents.protocol.player.GameMode; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTeams; + +import java.util.function.Predicate; + +public final class EntityPredicates { + + public static Predicate canBePushedBy(GrimPlayer player, PacketEntity entity, TeamHandler teamHandler) { + if (player.gamemode == GameMode.SPECTATOR) return p -> false; + final EntityTeam entityTeam = teamHandler.getEntityTeam(entity).orElse(null); + WrapperPlayServerTeams.CollisionRule collisionRule = entityTeam == null ? WrapperPlayServerTeams.CollisionRule.ALWAYS : entityTeam.getCollisionRule(); + if (collisionRule == WrapperPlayServerTeams.CollisionRule.NEVER) return p -> false; + + return p -> { + final EntityTeam playersTeam = teamHandler.getPlayersTeam().orElse(null); + WrapperPlayServerTeams.CollisionRule collisionRule2 = playersTeam == null ? WrapperPlayServerTeams.CollisionRule.ALWAYS : playersTeam.getCollisionRule(); + if (collisionRule2 == WrapperPlayServerTeams.CollisionRule.NEVER) { + return false; + } else { + boolean bl = entityTeam != null && entityTeam.equals(playersTeam); + if ((collisionRule == WrapperPlayServerTeams.CollisionRule.PUSH_OWN_TEAM || collisionRule2 == WrapperPlayServerTeams.CollisionRule.PUSH_OWN_TEAM) && bl) { + return false; + } else { + return collisionRule != WrapperPlayServerTeams.CollisionRule.PUSH_OTHER_TEAMS && collisionRule2 != WrapperPlayServerTeams.CollisionRule.PUSH_OTHER_TEAMS || bl; + } + } + }; + } +} \ No newline at end of file diff --git a/src/main/java/ac/grim/grimac/utils/team/EntityTeam.java b/src/main/java/ac/grim/grimac/utils/team/EntityTeam.java new file mode 100644 index 0000000000..fbeffe75d1 --- /dev/null +++ b/src/main/java/ac/grim/grimac/utils/team/EntityTeam.java @@ -0,0 +1,70 @@ +package ac.grim.grimac.utils.team; + +import ac.grim.grimac.player.GrimPlayer; +import com.github.retrooper.packetevents.protocol.player.UserProfile; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTeams; +import lombok.Getter; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +public final class EntityTeam { + + private final GrimPlayer player; + @Getter private final String name; + @Getter private final Set entries = new HashSet<>(); + @Getter private WrapperPlayServerTeams.CollisionRule collisionRule; + + public EntityTeam(GrimPlayer player, String name) { + this.player = player; + this.name = name; + } + + public void update(WrapperPlayServerTeams teams) { + teams.getTeamInfo().ifPresent(info -> this.collisionRule = info.getCollisionRule()); + + final WrapperPlayServerTeams.TeamMode mode = teams.getTeamMode(); + if (mode == WrapperPlayServerTeams.TeamMode.ADD_ENTITIES || mode == WrapperPlayServerTeams.TeamMode.CREATE) { + final TeamHandler teamHandler = player.checkManager.getPacketCheck(TeamHandler.class); + for (String teamsPlayer : teams.getPlayers()) { + if (teamsPlayer.equals(player.user.getName())) { + player.teamName = name; + continue; + } + + boolean flag = false; + for (UserProfile profile : player.compensatedEntities.profiles.values()) { + if (profile.getName() != null && profile.getName().equals(teamsPlayer)) { + teamHandler.addEntityToTeam(profile.getUUID().toString(), this); + flag = true; + } + } + + if (flag) continue; + + teamHandler.addEntityToTeam(teamsPlayer, this); + } + } else if (mode == WrapperPlayServerTeams.TeamMode.REMOVE_ENTITIES) { + for (String teamsPlayer : teams.getPlayers()) { + if (teamsPlayer.equals(player.user.getName())) { + player.teamName = null; + continue; + } + entries.remove(teamsPlayer); + } + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof EntityTeam)) return false; + return Objects.equals(getName(), ((EntityTeam) o).getName()); + } + + @Override + public int hashCode() { + return Objects.hash(getName()); + } +} \ No newline at end of file diff --git a/src/main/java/ac/grim/grimac/utils/team/TeamHandler.java b/src/main/java/ac/grim/grimac/utils/team/TeamHandler.java new file mode 100644 index 0000000000..62cdded9e9 --- /dev/null +++ b/src/main/java/ac/grim/grimac/utils/team/TeamHandler.java @@ -0,0 +1,62 @@ +package ac.grim.grimac.utils.team; + +import ac.grim.grimac.checks.Check; +import ac.grim.grimac.checks.type.PacketCheck; +import ac.grim.grimac.player.GrimPlayer; +import ac.grim.grimac.utils.data.packetentity.PacketEntity; +import com.github.retrooper.packetevents.event.PacketSendEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTeams; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import java.util.Map; +import java.util.Optional; + +public class TeamHandler extends Check implements PacketCheck { + + private final Map entityTeams = new Object2ObjectOpenHashMap<>(); + private final Map entityToTeam = new Object2ObjectOpenHashMap<>(); + + public TeamHandler(GrimPlayer player) { + super(player); + } + + public void addEntityToTeam(String entityTeamRepresentation, EntityTeam team) { + entityToTeam.put(entityTeamRepresentation, team); + } + + public Optional getPlayersTeam() { + final String teamName = player.teamName; + if (teamName == null) { + return Optional.empty(); + } + return Optional.ofNullable(entityTeams.get(teamName)); + } + + public Optional getEntityTeam(PacketEntity entity) { + return Optional.ofNullable(entityToTeam.get(entity.getUuid().toString())); + } + + @Override + public void onPacketSend(PacketSendEvent event) { + if (event.getPacketType() == PacketType.Play.Server.TEAMS) { + WrapperPlayServerTeams teams = new WrapperPlayServerTeams(event); + final String teamName = teams.getTeamName(); + player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> { + switch (teams.getTeamMode()) { + case CREATE: + entityTeams.put(teamName, new EntityTeam(player, teamName)); + break; + case REMOVE: + entityTeams.remove(teamName); + break; + } + + entityTeams.computeIfPresent(teamName, (s, team) -> { + team.update(teams); + return team; + }); + }); + } + } +} \ No newline at end of file