Skip to content

Commit

Permalink
Merge remote-tracking branch 'machinebreaker/inventory-checks' into m…
Browse files Browse the repository at this point in the history
…erge

# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/inventory/InventoryD.java
#	src/main/java/ac/grim/grimac/checks/impl/inventory/InventoryG.java
  • Loading branch information
Axionize committed Nov 20, 2024
2 parents f638772 + 2253fd0 commit d01805a
Show file tree
Hide file tree
Showing 26 changed files with 131 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity.InteractAction;

@CheckData(name = "InventoryA", setback = 3)
@CheckData(name = "InventoryA", setback = 3, description = "Attacked an entity while inventory is open")
public class InventoryA extends InventoryCheck {
public InventoryA(GrimPlayer player) {
super(player);
Expand All @@ -25,7 +25,7 @@ public void onPacketReceive(PacketReceiveEvent event) {

// Is not possible to attack while the inventory is open.
if (player.hasInventoryOpen) {
if (flagAndAlert("Attacked an entity while inventory is open")) {
if (flagAndAlert()) {
// Cancel the packet
if (shouldModifyPackets()) {
event.setCancelled(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging;

@CheckData(name = "InventoryB", setback = 3)
@CheckData(name = "InventoryB", setback = 3, description = "Started digging blocks while inventory is open")
public class InventoryB extends InventoryCheck {
public InventoryB(GrimPlayer player) {
super(player);
Expand All @@ -18,7 +18,7 @@ public void handle(PacketReceiveEvent event, WrapperPlayClientPlayerDigging wrap

// Is not possible to start digging a block while the inventory is open.
if (player.hasInventoryOpen) {
if (flagAndAlert("Started digging blocks while inventory is open")) {
if (flagAndAlert()) {
// Cancel the packet
if (shouldModifyPackets()) {
event.setCancelled(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.update.BlockPlace;

@CheckData(name = "InventoryC", setback = 3)
@CheckData(name = "InventoryC", setback = 3, description = "Placed a block while inventory is open")
public class InventoryC extends InventoryCheck {

public InventoryC(GrimPlayer player) {
Expand All @@ -15,7 +15,7 @@ public InventoryC(GrimPlayer player) {
public void onBlockPlace(final BlockPlace place) {
// It is not possible to place a block while the inventory is open
if (player.hasInventoryOpen) {
if (flagAndAlert("Placed a block while inventory is open")) {
if (flagAndAlert()) {
if (shouldModifyPackets()) {
place.resync();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import ac.grim.grimac.utils.data.VectorData;
import ac.grim.grimac.utils.data.VectorData.MoveVectorData;
import ac.grim.grimac.utils.data.VehicleData;

import java.util.StringJoiner;

@CheckData(name = "InventoryD", setback = 1, decay = 0.25)
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/ac/grim/grimac/checks/impl/inventory/InventoryE.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import ac.grim.grimac.checks.type.InventoryCheck;
import ac.grim.grimac.player.GrimPlayer;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;

@CheckData(name = "InventoryE", setback = 3)
@CheckData(name = "InventoryE", setback = 3, description = "Sent a held item change packet while inventory is open")
public class InventoryE extends InventoryCheck {
private long lastTransaction = Long.MAX_VALUE; // Impossible transaction ID

public InventoryE(GrimPlayer player) {
super(player);
Expand All @@ -21,7 +23,8 @@ public void onPacketReceive(PacketReceiveEvent event) {
// It is not possible to change hotbar slots with held item change while the inventory is open
// A container click packet would be sent instead
if (player.hasInventoryOpen) {
if (flagAndAlert("Sent a held item change packet while inventory is open")) {
if (this.lastTransaction < player.lastTransactionReceived.get()
&& flagAndAlert()) {
// Cancel the packet
if (shouldModifyPackets()) {
event.setCancelled(true);
Expand All @@ -35,4 +38,11 @@ public void onPacketReceive(PacketReceiveEvent event) {
}
}
}

@Override
public void onPacketSend(PacketSendEvent event) {
if (event.getPacketType() == PacketType.Play.Server.HELD_ITEM_CHANGE) {
this.lastTransaction = player.lastTransactionSent.get();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.InventoryCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.inventory.InventoryDesyncStatus;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;

@CheckData(name = "InventoryF", setback = 3, experimental = true)
@CheckData(name = "InventoryF", setback = 3, description = "Sent a click window packet without a open inventory", experimental = true)
public class InventoryF extends InventoryCheck {

public InventoryF(GrimPlayer player) {
Expand All @@ -26,8 +27,8 @@ public void onPacketReceive(PacketReceiveEvent event) {
super.onPacketReceive(event);

if (event.getPacketType() == PacketType.Play.Client.CLICK_WINDOW) {
if (!player.hasInventoryOpen) {
if (flagAndAlert("Sent a click window packet without a open inventory")) {
if (!player.hasInventoryOpen && player.inventoryDesyncStatus == InventoryDesyncStatus.NOT_DESYNCED) {
if (flagAndAlert()) {
// Cancel the packet
if (shouldModifyPackets()) {
event.setCancelled(true);
Expand Down
13 changes: 11 additions & 2 deletions src/main/java/ac/grim/grimac/checks/impl/inventory/InventoryG.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import ac.grim.grimac.player.GrimPlayer;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction;

@CheckData(name = "InventoryG", setback = 3, experimental = true)
@CheckData(name = "InventoryG", setback = 3, description = "Sent a entity action packet while inventory is open", experimental = true)
public class InventoryG extends InventoryCheck {

public InventoryG(GrimPlayer player) {
Expand All @@ -19,8 +20,16 @@ public void onPacketReceive(PacketReceiveEvent event) {
super.onPacketReceive(event);

if (event.getPacketType() == PacketType.Play.Client.ENTITY_ACTION) {
WrapperPlayClientEntityAction wrapper = new WrapperPlayClientEntityAction(event);
WrapperPlayClientEntityAction.Action action = wrapper.getAction();

if (action == WrapperPlayClientEntityAction.Action.STOP_SNEAKING
|| action == WrapperPlayClientEntityAction.Action.STOP_SPRINTING) {
return;
}

if (player.hasInventoryOpen) {
if (flagAndAlert("Sent a entity action packet while inventory is open")) {
if (flagAndAlert()) {
closeInventory();
}
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/ac/grim/grimac/checks/type/InventoryCheck.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientCloseWindow;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerCloseWindow;
import org.jetbrains.annotations.MustBeInvokedByOverriders;

public class InventoryCheck extends BlockPlaceCheck implements PacketCheck {
// Impossible transaction ID
Expand All @@ -18,8 +19,8 @@ public InventoryCheck(GrimPlayer player) {
super(player);
}

// IMPORTANT: When doing checks remember to call super.onPacketReceive(event)
@Override
@MustBeInvokedByOverriders
public void onPacketReceive(final PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.CLICK_WINDOW) {
// Disallow any clicks if inventory is closing
Expand Down
57 changes: 41 additions & 16 deletions src/main/java/ac/grim/grimac/events/packets/PacketPlayerWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.data.packetentity.PacketEntitySelf;
import ac.grim.grimac.utils.inventory.InventoryDesyncStatus;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
import com.github.retrooper.packetevents.event.PacketListenerPriority;
Expand All @@ -28,8 +29,8 @@ public void onPacketReceive(PacketReceiveEvent event) {
GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(event.getUser());
if (player == null) return;

if (player.hasInventoryOpen && isDesynced(player)) {
player.hasInventoryOpen = false;
if (player.hasInventoryOpen && isNearNetherPortal(player)) {
handleInventoryClose(player, InventoryDesyncStatus.NETHER_PORTAL);
}
}

Expand All @@ -41,7 +42,7 @@ public void onPacketReceive(PacketReceiveEvent event) {
GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(event.getUser());
if (player == null) return;

player.hasInventoryOpen = true;
handleInventoryOpen(player);
}
}

Expand All @@ -56,19 +57,19 @@ public void onPacketReceive(PacketReceiveEvent event) {
// This is a workaround to atleast make our inventory checks work "decently" in 1.8 clients for 1.9+ servers
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)
&& player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8)) {
player.hasInventoryOpen = true;
handleInventoryOpen(player);
}

if (player.getClientVersion().isNewerThan(ClientVersion.V_1_8)) {
player.hasInventoryOpen = true;
handleInventoryOpen(player);
}
}

if (event.getPacketType() == PacketType.Play.Client.CLOSE_WINDOW) {
GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(event.getUser());
if (player == null) return;

player.hasInventoryOpen = false;
handleInventoryClose(player, InventoryDesyncStatus.NOT_DESYNCED);
}
}

Expand All @@ -81,7 +82,7 @@ public void onPacketSend(PacketSendEvent event) {
player.sendTransaction();

player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(),
() -> player.hasInventoryOpen = false);
() -> handleInventoryClose(player, InventoryDesyncStatus.NOT_DESYNCED));
} else if (event.getPacketType() == PacketType.Play.Server.OPEN_WINDOW) {
WrapperPlayServerOpenWindow wrapper = new WrapperPlayServerOpenWindow(event);

Expand All @@ -92,39 +93,63 @@ public void onPacketSend(PacketSendEvent event) {

String legacyType = wrapper.getLegacyType();
int modernType = wrapper.getType();
InventoryDesyncStatus inventoryDesyncStatus = getContainerDesyncStatus(player, legacyType, modernType);

player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(),
() -> player.hasInventoryOpen = !isAlwaysDesynced(player, legacyType, modernType));
() -> {
if (inventoryDesyncStatus == InventoryDesyncStatus.NOT_DESYNCED) {
handleInventoryOpen(player);
} else {
handleInventoryClose(player, inventoryDesyncStatus);
}
});
} else if (event.getPacketType() == PacketType.Play.Server.OPEN_HORSE_WINDOW) {
GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(event.getUser());
if (player == null) return;

player.sendTransaction();

player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(),
() -> player.hasInventoryOpen = true);
() -> handleInventoryOpen(player));
} else if (event.getPacketType() == PacketType.Play.Server.CLOSE_WINDOW) {
GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(event.getUser());
if (player == null) return;

player.sendTransaction();

player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(),
() -> player.hasInventoryOpen = false);
() -> handleInventoryClose(player, InventoryDesyncStatus.NOT_DESYNCED));
}
}

private boolean isAlwaysDesynced(GrimPlayer player, String legacyType, int modernType) {
// Closing beacon with the cross button cause desync in 1.8
if (player.getClientVersion() == ClientVersion.V_1_8 &&
private void handleInventoryOpen(GrimPlayer player) {
if (!player.hasInventoryOpen) {
player.lastInventoryOpen = System.currentTimeMillis();
}

player.hasInventoryOpen = true;
}

private void handleInventoryClose(GrimPlayer player, InventoryDesyncStatus desyncStatus) {
player.hasInventoryOpen = false;
player.inventoryDesyncStatus = desyncStatus;
}

public InventoryDesyncStatus getContainerDesyncStatus(GrimPlayer player, String legacyType, int modernType) {
// Closing beacon with the cross button cause desync in 1.7-1.8
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8) &&
("minecraft:beacon".equals(legacyType) || modernType == 8)) {
return true;
return player.inventoryDesyncStatus = InventoryDesyncStatus.BEACON;
}

if (isNearNetherPortal(player)) {
return player.inventoryDesyncStatus = InventoryDesyncStatus.NETHER_PORTAL;
}

return isDesynced(player);
return player.inventoryDesyncStatus = InventoryDesyncStatus.NOT_DESYNCED;
}

private boolean isDesynced(GrimPlayer player) {
public boolean isNearNetherPortal(GrimPlayer player) {
// Going inside nether portal with opened inventory cause desync, fixed in 1.12.2
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_12_1) &&
player.pointThreeEstimator.isNearNetherPortal) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public void reload() {
GrimAPI.INSTANCE.getPlugin().getDataFolder().mkdirs();
if (!initialized) {
initialized = true;
upgrade();
config.addSource(GrimAC.class, "config", getConfigFile("config.yml"));
config.addSource(GrimAC.class, "messages", getConfigFile("messages.yml"));
config.addSource(GrimAC.class, "discord", getConfigFile("discord.yml"));
Expand Down Expand Up @@ -81,7 +82,7 @@ private void upgrade() {

configVersion = Integer.parseInt(configStringVersion);
// TODO: Do we have to hardcode this?
configString = configString.replaceAll("config-version: " + configStringVersion, "config-version: 9");
configString = configString.replaceAll("config-version: " + configStringVersion, "config-version: 10");
Files.write(config.toPath(), configString.getBytes());

upgradeModernConfig(config, configString, configVersion);
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/ac/grim/grimac/player/GrimPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import ac.grim.grimac.utils.data.tags.SyncedTags;
import ac.grim.grimac.utils.enums.FluidTag;
import ac.grim.grimac.utils.enums.Pose;
import ac.grim.grimac.utils.inventory.InventoryDesyncStatus;
import ac.grim.grimac.utils.latency.*;
import ac.grim.grimac.utils.math.GrimMath;
import ac.grim.grimac.utils.math.TrigHandler;
Expand Down Expand Up @@ -216,6 +217,8 @@ public void onPacketCancel() {

public int totalFlyingPacketsSent;
public boolean hasInventoryOpen;
public long lastInventoryOpen;
public InventoryDesyncStatus inventoryDesyncStatus;
public Queue<BlockPlaceSnapshot> placeUseItemPackets = new LinkedBlockingQueue<>();
// This variable is for support with test servers that want to be able to disable grim
// Grim disabler 2022 still working!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ac.grim.grimac.utils.inventory;

public enum InventoryDesyncStatus {
BEACON,
NETHER_PORTAL,
NOT_DESYNCED
}
2 changes: 1 addition & 1 deletion src/main/resources/config/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -233,4 +233,4 @@ max-ping-out-of-flying: 1000
# This prevents high latency players from being able to use 1 firework boost with an elytra forever.
max-ping-firework-boost: 1000

config-version: 9
config-version: 10
2 changes: 1 addition & 1 deletion src/main/resources/config/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -236,4 +236,4 @@ max-ping-out-of-flying: 1000
# This prevents high latency players from being able to use 1 firework boost with an elytra forever.
max-ping-firework-boost: 1000

config-version: 9
config-version: 10
2 changes: 1 addition & 1 deletion src/main/resources/config/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,4 @@ max-ping-out-of-flying: 1000
# This prevents high latency players from being able to use 1 firework boost with an elytra forever.
max-ping-firework-boost: 1000

config-version: 9
config-version: 10
2 changes: 1 addition & 1 deletion src/main/resources/config/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -232,4 +232,4 @@ max-ping-out-of-flying: 1000
# This prevents high latency players from being able to use 1 firework boost with an elytra forever.
max-ping-firework-boost: 1000

config-version: 9
config-version: 10
2 changes: 1 addition & 1 deletion src/main/resources/config/it.yml
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,4 @@ max-ping-out-of-flying: 1000
# This prevents high latency players from being able to use 1 firework boost with an elytra forever.
max-ping-firework-boost: 1000

config-version: 9
config-version: 10
2 changes: 1 addition & 1 deletion src/main/resources/config/nl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,4 @@ max-ping-out-of-flying: 1000
# This prevents high latency players from being able to use 1 firework boost with an elytra forever.
max-ping-firework-boost: 1000

config-version: 9
config-version: 10
2 changes: 1 addition & 1 deletion src/main/resources/config/pt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,4 @@ max-ping-out-of-flying: 1000
# Previne jogadores com ping alto de usarem um foguete ara voar indefinidamente.
max-ping-firework-boost: 1000

config-version: 9
config-version: 10
2 changes: 1 addition & 1 deletion src/main/resources/config/ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,4 @@ max-ping-out-of-flying: 1000
# This prevents high latency players from being able to use 1 firework boost with an elytra forever.
max-ping-firework-boost: 1000

config-version: 9
config-version: 10
Loading

0 comments on commit d01805a

Please sign in to comment.