From f6bf48546fe1fa43b464be526e39b9337095be0f Mon Sep 17 00:00:00 2001 From: You Date: Wed, 18 Dec 2024 21:02:28 -0500 Subject: [PATCH 1/9] Add unloaded check behaviour --- .../ac/grim/grimac/api/AbstractCheck.java | 2 ++ .../api/dynamic/DefaultUnloadedBehavior.java | 23 +++++++++++++++++++ .../grimac/api/dynamic/UnloadedBehavior.java | 7 ++++++ 3 files changed, 32 insertions(+) create mode 100644 src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java create mode 100644 src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java diff --git a/src/main/java/ac/grim/grimac/api/AbstractCheck.java b/src/main/java/ac/grim/grimac/api/AbstractCheck.java index 0ab72fd..9cf16b5 100644 --- a/src/main/java/ac/grim/grimac/api/AbstractCheck.java +++ b/src/main/java/ac/grim/grimac/api/AbstractCheck.java @@ -1,6 +1,7 @@ package ac.grim.grimac.api; import ac.grim.grimac.api.common.BasicStatus; +import ac.grim.grimac.api.dynamic.UnloadedBehavior; public interface AbstractCheck extends AbstractProcessor, BasicStatus { @@ -18,4 +19,5 @@ default String getAlternativeName() { boolean isExperimental(); + UnloadedBehavior getUnloadedBehavior(); } diff --git a/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java b/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java new file mode 100644 index 0000000..3f93a2d --- /dev/null +++ b/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java @@ -0,0 +1,23 @@ +package ac.grim.grimac.api.dynamic; + +import java.lang.reflect.Method; + +// Default implementations +public class DefaultUnloadedBehavior implements UnloadedBehavior { + public static final UnloadedBehavior INSTANCE = new DefaultUnloadedBehavior(); + + @Override + public Object handleUnloadedCall(Method method, Object[] args) { + Class returnType = method.getReturnType(); + if (returnType == boolean.class) { + return false; + } + if (returnType == int.class) { + return 0; + } + if (returnType == void.class) { + return null; + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java b/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java new file mode 100644 index 0000000..83e41d9 --- /dev/null +++ b/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java @@ -0,0 +1,7 @@ +package ac.grim.grimac.api.dynamic; + +import java.lang.reflect.Method; + +public interface UnloadedBehavior { + Object handleUnloadedCall(Method method, Object[] args); +} \ No newline at end of file From 959e9e797d478718ef4d32910be778f46649e1f7 Mon Sep 17 00:00:00 2001 From: You Date: Wed, 18 Dec 2024 21:07:22 -0500 Subject: [PATCH 2/9] Document code and UnloadedBehaviour --- .../ac/grim/grimac/api/AbstractCheck.java | 38 ++++++++++++++++++- .../api/dynamic/DefaultUnloadedBehavior.java | 34 ++++++++--------- .../grimac/api/dynamic/UnloadedBehavior.java | 11 ++++++ 3 files changed, 65 insertions(+), 18 deletions(-) diff --git a/src/main/java/ac/grim/grimac/api/AbstractCheck.java b/src/main/java/ac/grim/grimac/api/AbstractCheck.java index 9cf16b5..3d98b42 100644 --- a/src/main/java/ac/grim/grimac/api/AbstractCheck.java +++ b/src/main/java/ac/grim/grimac/api/AbstractCheck.java @@ -3,21 +3,57 @@ import ac.grim.grimac.api.common.BasicStatus; import ac.grim.grimac.api.dynamic.UnloadedBehavior; +/** + * Base interface for all anti-cheat checks. Checks are modular components that detect specific + * types of cheating behavior. This interface defines the very core functionality that all checks + * must implement. + */ public interface AbstractCheck extends AbstractProcessor, BasicStatus { - + /** + * Gets the name of this check, used for identification and permissions. + * @return The check's name + */ String getCheckName(); + /** + * Gets an alternative name for this check, defaults to the check name. + * Useful for checks that may have multiple names or variants (IE AntiKB and AntiKnockback) + * @return The alternative check name + */ default String getAlternativeName() { return getCheckName(); } + /** + * Gets the current violation level for this check. + * @return Number of violations accumulated + */ double getViolations(); + /** + * Gets the rate at which violations decay over time. + * @return The violation decay rate + */ double getDecay(); + /** + * Gets the violation level at which a setback/punishment should occur. + * @return The setback threshold + */ double getSetbackVL(); + /** + * Whether this check is experimental/in testing. + * @return true if experimental, false if stable + */ boolean isExperimental(); + /** + * Defines how this check should behave when unloaded. + * This allows checks to specify custom behavior when they are disabled + * rather than using the default no-op behavior. + * + * @return The UnloadedBehavior implementation for this check + */ UnloadedBehavior getUnloadedBehavior(); } diff --git a/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java b/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java index 3f93a2d..be6ebe6 100644 --- a/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java +++ b/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java @@ -2,22 +2,22 @@ import java.lang.reflect.Method; -// Default implementations +/** + * Default implementation that returns safe "no-op" values for unloaded checks. + * - boolean methods return false + * - numeric methods return 0 + * - void methods do nothing + * - object methods return null + */ public class DefaultUnloadedBehavior implements UnloadedBehavior { - public static final UnloadedBehavior INSTANCE = new DefaultUnloadedBehavior(); - - @Override - public Object handleUnloadedCall(Method method, Object[] args) { - Class returnType = method.getReturnType(); - if (returnType == boolean.class) { - return false; - } - if (returnType == int.class) { - return 0; - } - if (returnType == void.class) { - return null; - } - return null; - } + public static final UnloadedBehavior INSTANCE = new DefaultUnloadedBehavior(); + + @Override + public Object handleUnloadedCall(Method method, Object[] args) { + Class returnType = method.getReturnType(); + if (returnType == boolean.class) return false; + if (returnType == int.class) return 0; + if (returnType == void.class) return null; + return null; + } } \ No newline at end of file diff --git a/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java b/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java index 83e41d9..6e29d28 100644 --- a/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java +++ b/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java @@ -2,6 +2,17 @@ import java.lang.reflect.Method; +/** + * Defines how an unloaded check should behave when its methods are called. + * This allows for graceful degradation when checks are disabled/unloaded. + */ public interface UnloadedBehavior { + /** + * Handle a method call on an unloaded check + * + * @param method The method being called + * @param args The arguments passed to the method + * @return The value to return from the method call + */ Object handleUnloadedCall(Method method, Object[] args); } \ No newline at end of file From e152ebfad5e14e8513be0b41786d1c676fb579ee Mon Sep 17 00:00:00 2001 From: You Date: Wed, 18 Dec 2024 22:20:32 -0500 Subject: [PATCH 3/9] Add support to get dependency information for checks --- .../ac/grim/grimac/api/AbstractCheck.java | 53 +++++++++++++++++++ .../java/ac/grim/grimac/api/CheckType.java | 30 +++++++++++ .../grimac/api/dynamic/UnloadedBehavior.java | 1 + 3 files changed, 84 insertions(+) create mode 100644 src/main/java/ac/grim/grimac/api/CheckType.java diff --git a/src/main/java/ac/grim/grimac/api/AbstractCheck.java b/src/main/java/ac/grim/grimac/api/AbstractCheck.java index 3d98b42..3a14c56 100644 --- a/src/main/java/ac/grim/grimac/api/AbstractCheck.java +++ b/src/main/java/ac/grim/grimac/api/AbstractCheck.java @@ -2,6 +2,10 @@ import ac.grim.grimac.api.common.BasicStatus; import ac.grim.grimac.api.dynamic.UnloadedBehavior; +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Base interface for all anti-cheat checks. Checks are modular components that detect specific @@ -56,4 +60,53 @@ default String getAlternativeName() { * @return The UnloadedBehavior implementation for this check */ UnloadedBehavior getUnloadedBehavior(); + + /** + * @return Set of check classes that must be loaded along with this check to run + */ + default Set> getDependencies() { + return Stream.concat(getLoadAfter().stream(), getLoadBefore().stream()) + .collect(Collectors.toSet()); + } + + /** + * @return Set of check classes that must run after this check + */ + default Set> getLoadAfter() { + return Collections.emptySet(); + } + + /** + * @return Set of check classes that must run before this check + */ + default Set> getLoadBefore() { + return Collections.emptySet(); + } + + /** + * Called when check is being loaded + * @return true if loaded successfully + */ + default boolean onLoad() { + return true; + } + + /** + * Called when check is being unloaded + */ + default void onUnload() {} + + /** + * @return Bit mask representing all check types this check implements + */ + int getCheckMask(); + + /** + * Test if this check is of a specific type + * @param type The check type to test for + * @return true if this check handles the given type + */ + default boolean isCheckType(CheckType type) { + return (getCheckMask() & type.getMask()) != 0; + } } diff --git a/src/main/java/ac/grim/grimac/api/CheckType.java b/src/main/java/ac/grim/grimac/api/CheckType.java new file mode 100644 index 0000000..7fa979c --- /dev/null +++ b/src/main/java/ac/grim/grimac/api/CheckType.java @@ -0,0 +1,30 @@ +package ac.grim.grimac.api; + +/** + * Represents different types of checks that can be performed + */ +public enum CheckType { + PACKET(0), + POSITION(1), + ROTATION(2), + VEHICLE(3), + PRE_PREDICTION(4), + BLOCK_BREAK(5), + BLOCK_PLACE(6), + POST_PREDICTION(7); + + private final int bitPosition; + private final int mask; + + CheckType(int bitPosition) { + if (bitPosition >= 32) { + throw new IllegalArgumentException("Cannot have more than 32 check types"); + } + this.bitPosition = bitPosition; + this.mask = 1 << bitPosition; + } + + public int getMask() { + return mask; + } +} \ No newline at end of file diff --git a/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java b/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java index 6e29d28..1f5df58 100644 --- a/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java +++ b/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java @@ -5,6 +5,7 @@ /** * Defines how an unloaded check should behave when its methods are called. * This allows for graceful degradation when checks are disabled/unloaded. + * */ public interface UnloadedBehavior { /** From 3500c6a40466ff05c6a524e08eef03d53da44d3f Mon Sep 17 00:00:00 2001 From: You Date: Fri, 20 Dec 2024 20:34:40 -0500 Subject: [PATCH 4/9] Address code review changes in AbstractCheck * isCheckType(CheckType type) -> is(CheckType type) * getCheckMask() -> getMask() * make getUnloadedBehaviour() default to return the default unloaded behaviour instance --- src/main/java/ac/grim/grimac/api/AbstractCheck.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/ac/grim/grimac/api/AbstractCheck.java b/src/main/java/ac/grim/grimac/api/AbstractCheck.java index 3a14c56..7c08d4b 100644 --- a/src/main/java/ac/grim/grimac/api/AbstractCheck.java +++ b/src/main/java/ac/grim/grimac/api/AbstractCheck.java @@ -1,6 +1,7 @@ package ac.grim.grimac.api; import ac.grim.grimac.api.common.BasicStatus; +import ac.grim.grimac.api.dynamic.DefaultUnloadedBehavior; import ac.grim.grimac.api.dynamic.UnloadedBehavior; import java.util.Collections; import java.util.Set; @@ -59,7 +60,9 @@ default String getAlternativeName() { * * @return The UnloadedBehavior implementation for this check */ - UnloadedBehavior getUnloadedBehavior(); + default UnloadedBehavior getUnloadedBehavior() { + return DefaultUnloadedBehavior.INSTANCE; + } /** * @return Set of check classes that must be loaded along with this check to run @@ -99,14 +102,14 @@ default void onUnload() {} /** * @return Bit mask representing all check types this check implements */ - int getCheckMask(); + int getMask(); /** * Test if this check is of a specific type * @param type The check type to test for * @return true if this check handles the given type */ - default boolean isCheckType(CheckType type) { - return (getCheckMask() & type.getMask()) != 0; + default boolean is(CheckType type) { + return (getMask() & type.getMask()) != 0; } } From aaea77044e280ec9792bd559ad288dc85343fb8d Mon Sep 17 00:00:00 2001 From: You Date: Fri, 20 Dec 2024 22:37:58 -0500 Subject: [PATCH 5/9] Add new function to API for checking if a check supports being run against a player --- src/main/java/ac/grim/grimac/api/AbstractCheck.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/ac/grim/grimac/api/AbstractCheck.java b/src/main/java/ac/grim/grimac/api/AbstractCheck.java index 7c08d4b..1913b4b 100644 --- a/src/main/java/ac/grim/grimac/api/AbstractCheck.java +++ b/src/main/java/ac/grim/grimac/api/AbstractCheck.java @@ -112,4 +112,15 @@ default void onUnload() {} default boolean is(CheckType type) { return (getMask() & type.getMask()) != 0; } + /** + * Determines if this check supports/is compatible with the given player. + * This can be used to disable checks for players on certain versions, + * with specific conditions, or other compatibility requirements. + * + * @param player The {@link GrimUser} to check compatibility for + * @return true if the check supports this player, false otherwise + */ + default boolean supportsPlayer(GrimUser player) { + return true; + } } From 97505bb7faa591029615f6625f3f9405cddd82f3 Mon Sep 17 00:00:00 2001 From: Axionize <154778082+Axionize@users.noreply.github.com> Date: Sat, 21 Dec 2024 20:51:11 -0500 Subject: [PATCH 6/9] Apply minor style changes from code review Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com> --- src/main/java/ac/grim/grimac/api/AbstractCheck.java | 3 ++- src/main/java/ac/grim/grimac/api/CheckType.java | 2 +- .../ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java | 2 +- src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java | 3 +-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/ac/grim/grimac/api/AbstractCheck.java b/src/main/java/ac/grim/grimac/api/AbstractCheck.java index 1913b4b..384f76f 100644 --- a/src/main/java/ac/grim/grimac/api/AbstractCheck.java +++ b/src/main/java/ac/grim/grimac/api/AbstractCheck.java @@ -22,7 +22,7 @@ public interface AbstractCheck extends AbstractProcessor, BasicStatus { /** * Gets an alternative name for this check, defaults to the check name. - * Useful for checks that may have multiple names or variants (IE AntiKB and AntiKnockback) + * Useful for checks that may have multiple names or variants (ie AntiKB and AntiKnockback) * @return The alternative check name */ default String getAlternativeName() { @@ -112,6 +112,7 @@ default void onUnload() {} default boolean is(CheckType type) { return (getMask() & type.getMask()) != 0; } + /** * Determines if this check supports/is compatible with the given player. * This can be used to disable checks for players on certain versions, diff --git a/src/main/java/ac/grim/grimac/api/CheckType.java b/src/main/java/ac/grim/grimac/api/CheckType.java index 7fa979c..8baff03 100644 --- a/src/main/java/ac/grim/grimac/api/CheckType.java +++ b/src/main/java/ac/grim/grimac/api/CheckType.java @@ -27,4 +27,4 @@ public enum CheckType { public int getMask() { return mask; } -} \ No newline at end of file +} diff --git a/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java b/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java index be6ebe6..654e4f3 100644 --- a/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java +++ b/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java @@ -20,4 +20,4 @@ public Object handleUnloadedCall(Method method, Object[] args) { if (returnType == void.class) return null; return null; } -} \ No newline at end of file +} diff --git a/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java b/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java index 1f5df58..98f756a 100644 --- a/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java +++ b/src/main/java/ac/grim/grimac/api/dynamic/UnloadedBehavior.java @@ -5,7 +5,6 @@ /** * Defines how an unloaded check should behave when its methods are called. * This allows for graceful degradation when checks are disabled/unloaded. - * */ public interface UnloadedBehavior { /** @@ -16,4 +15,4 @@ public interface UnloadedBehavior { * @return The value to return from the method call */ Object handleUnloadedCall(Method method, Object[] args); -} \ No newline at end of file +} From d140895535e376699e0385b7e1718ad2c4600b43 Mon Sep 17 00:00:00 2001 From: You Date: Sat, 21 Dec 2024 20:55:17 -0500 Subject: [PATCH 7/9] Remove bitPosition; use ordinal() instead --- src/main/java/ac/grim/grimac/api/CheckType.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/ac/grim/grimac/api/CheckType.java b/src/main/java/ac/grim/grimac/api/CheckType.java index 8baff03..6f105a4 100644 --- a/src/main/java/ac/grim/grimac/api/CheckType.java +++ b/src/main/java/ac/grim/grimac/api/CheckType.java @@ -13,14 +13,12 @@ public enum CheckType { BLOCK_PLACE(6), POST_PREDICTION(7); - private final int bitPosition; private final int mask; CheckType(int bitPosition) { if (bitPosition >= 32) { throw new IllegalArgumentException("Cannot have more than 32 check types"); } - this.bitPosition = bitPosition; this.mask = 1 << bitPosition; } From 8d082daeb60cd2443b5b725991735f030fefa2e4 Mon Sep 17 00:00:00 2001 From: You Date: Sat, 21 Dec 2024 20:55:35 -0500 Subject: [PATCH 8/9] Use 4 line indents on DefaultUnloadedBehaviour --- .../api/dynamic/DefaultUnloadedBehavior.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java b/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java index 654e4f3..17ecbfc 100644 --- a/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java +++ b/src/main/java/ac/grim/grimac/api/dynamic/DefaultUnloadedBehavior.java @@ -10,14 +10,14 @@ * - object methods return null */ public class DefaultUnloadedBehavior implements UnloadedBehavior { - public static final UnloadedBehavior INSTANCE = new DefaultUnloadedBehavior(); + public static final UnloadedBehavior INSTANCE = new DefaultUnloadedBehavior(); - @Override - public Object handleUnloadedCall(Method method, Object[] args) { - Class returnType = method.getReturnType(); - if (returnType == boolean.class) return false; - if (returnType == int.class) return 0; - if (returnType == void.class) return null; - return null; - } + @Override + public Object handleUnloadedCall(Method method, Object[] args) { + Class returnType = method.getReturnType(); + if (returnType == boolean.class) return false; + if (returnType == int.class) return 0; + if (returnType == void.class) return null; + return null; + } } From e05a14cf857282f9de526f3818e6e1d4038fd71a Mon Sep 17 00:00:00 2001 From: Axionize <154778082+Axionize@users.noreply.github.com> Date: Sat, 21 Dec 2024 22:26:34 -0500 Subject: [PATCH 9/9] New None CheckType and basic checktype documentation --- .../java/ac/grim/grimac/api/CheckType.java | 67 +++++++++++++++---- 1 file changed, 53 insertions(+), 14 deletions(-) diff --git a/src/main/java/ac/grim/grimac/api/CheckType.java b/src/main/java/ac/grim/grimac/api/CheckType.java index 6f105a4..9bf721d 100644 --- a/src/main/java/ac/grim/grimac/api/CheckType.java +++ b/src/main/java/ac/grim/grimac/api/CheckType.java @@ -1,28 +1,67 @@ package ac.grim.grimac.api; /** - * Represents different types of checks that can be performed + * Represents the types of events a check can listen to. + * Checks can listen to multiple event types simultaneously via bitmasks. + * For example, a check could listen to both POSITION and ROTATION events + * by combining their respective masks. */ public enum CheckType { - PACKET(0), - POSITION(1), - ROTATION(2), - VEHICLE(3), - PRE_PREDICTION(4), - BLOCK_BREAK(5), - BLOCK_PLACE(6), - POST_PREDICTION(7); + /** + * For checks without any event listeners + */ + NONE(0), + + /** + * Packet analysis events + */ + PACKET(1), + + /** + * Player movement events + */ + POSITION(2), + + /** + * Player rotation events + */ + ROTATION(3), + + /** + * Vehicle-related events + */ + VEHICLE(4), + + /** + * Pre-prediction calculation events + */ + PRE_PREDICTION(5), + + /** + * Block breaking events + */ + BLOCK_BREAK(6), + + /** + * Block placement events + */ + BLOCK_PLACE(7), + + /** + * Post-prediction calculation events + */ + POST_PREDICTION(8); private final int mask; - + CheckType(int bitPosition) { - if (bitPosition >= 32) { + if (bitPosition > 0 && bitPosition >= 32) { throw new IllegalArgumentException("Cannot have more than 32 check types"); } - this.mask = 1 << bitPosition; + this.mask = bitPosition == 0 ? 0 : 1 << (bitPosition - 1); } - + public int getMask() { return mask; } -} +} \ No newline at end of file