Compare commits

..
Author SHA1 Message Date
Axionize 328e031c1b Fix 1.8 Villager and Modern Slime {Size: 0} hitboxes 2025-02-26 18:39:43 -05:00
Axionize 0bc781f390 Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/commands/GrimSpectate.java
2025-02-26 14:46:57 -05:00
Axionize c7f4bd15d2 Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	.github/workflows/gradle-publish.yml
#	build.gradle.kts
2025-02-19 03:33:51 -05:00
Axionize 9af7a7267e Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/utils/nmsutil/BukkitNMS.java
2025-02-13 23:45:31 -05:00
Axionize 3ff9e774cd Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/utils/data/packetentity/PacketEntity.java
#	src/main/java/ac/grim/grimac/utils/nmsutil/GetBoundingBox.java
2025-02-13 13:24:10 -05:00
Axionize 36e5eb9304 Attempt to fix HitboxEntity/Block AssertionError & some more AirLiquidPlace falses 2025-02-13 11:53:14 -05:00
Axionize 0d2940c34a Make painting hitbox code 1.19+ 2025-02-12 15:01:05 -05:00
Axionize a793912337 Get rid of debugging prints 2025-02-12 14:17:31 -05:00
Axionize d1194223ab Temporary workaround to NPE if paintingVariant registry doesn't have paintings for client version 2025-02-12 14:16:30 -05:00
Axionize 0624b117b5 Attempt to fix adventure shading issue with PE in lite mode 2025-02-12 14:15:27 -05:00
Axionize 5f4ec6a1a7 Fix modeling hitbox of Paintings in 1.21 2025-02-11 07:48:20 -05:00
Axionize 3c400f1eeb Dirty hack to fix calculating hitboxes for paintings 2025-02-10 15:04:38 -05:00
Axionize f6dba5ee8e Fix modeling hitbox of Falling Blocks 2025-02-10 12:58:41 -05:00
Axionize 8b3cbab3ad Fix thread exception when accessing bukkit methods from netty threads 2025-02-10 12:50:09 -05:00
Axionize c0e6ae7ec6 Make PacketEventsInit version check use NEWEST_UNSUPPORTED_PE_VERSION instead of hard coding it 2025-02-09 06:26:11 -05:00
Axionize 71d6d9e33f Fix build script 2025-02-09 06:08:27 -05:00
Axionize 0508bd98ba Fix build script 2025-02-09 05:57:50 -05:00
Axionize 5b9efc0ea5 Fix build script 2025-02-09 05:53:11 -05:00
Axionize a3812b2546 Exempt recently changed blocks as a temporary hack for HitboxBlocks 2025-02-09 05:47:41 -05:00
Axionize 05fb233f0e Build two jars, one with PE one ewithout 2025-02-09 04:53:14 -05:00
Axionize e15277d58d Add support for building Grim without shading PE as a build option 2025-02-09 03:45:54 -05:00
Axionize 177ae4cbfa Fix Remy's build mistakes #1 2025-02-09 00:51:33 -05:00
Axionize c1db1479b6 Fix merge issues with updating SprintC 2025-02-08 13:18:12 -05:00
RejomyandRejomy 86f89c010d Fix github actions failing due to incorrect path to the jar. (#53)
Co-authored-by: Rejomy <gg@gg.gg>
2025-02-07 17:41:17 -05:00
Axionize 5de92f28de Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/sprint/SprintC.java
2025-02-07 17:38:10 -05:00
Axionize 96ab0c3bdf Fix updating upstream 2025-02-05 14:30:17 -05:00
Axionize a4a1397b87 Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/manager/init/start/CommandRegister.java
#	src/main/java/ac/grim/grimac/player/GrimPlayer.java
#	src/main/resources/config/zh.yml
2025-02-05 13:01:59 -05:00
Axionize 4b5cf2a9a1 Reduce number of rays required to be traced with new getPossibleLookVectors() function 2025-02-05 12:15:48 -05:00
Axionize fa86c87693 Fix HitboxEntity and HitboxReach not working on large custom reach distances 2025-02-05 11:46:41 -05:00
You 6b639048b9 Fix historical reach teleport reach modeling 2025-02-03 11:16:51 -05:00
Axionize 5413484c2a Merge branch 'feat/fix-Folia-LatencyUtils-CME' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/utils/latency/LatencyUtils.java
2025-02-03 10:18:26 -05:00
Axionize 6d6b27dfe2 Merge remote-tracking branch 'origin/2.0' into merge-dev 2025-02-03 02:17:48 -05:00
Axionize fde5efa31f Fix new entity modeling to handle riding entities 2025-02-01 00:04:40 -05:00
Axionize cccc0194d6 Fix upstream Java 8 compatability issue 2025-01-31 22:06:17 -05:00
Axionize d8e7bc8f3e Fix Java 8 compatability break from upstream 2025-01-31 22:02:58 -05:00
Axionize dd37d3407b Enable HitboxEntities by default 2025-01-31 17:38:21 -05:00
Axionize c0c19d1a2d Merge remote-tracking branch 'origin/2.0' into merge-dev 2025-01-31 17:32:10 -05:00
Axionize 59eb669c17 Fix a rare CME in LatencyUtils 2025-01-30 12:46:26 -05:00
Axionize 86cb4af960 Refactor hitbox debugging code 2025-01-30 02:41:12 -05:00
Axionize 056b9f0486 Fix merge conflicts 2025-01-30 02:18:46 -05:00
Axionize afe483c0ad Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/manager/CheckManager.java
2025-01-30 02:02:38 -05:00
Axionize 5d4c8f6f85 Fix HitboxEntities falses 2025-01-30 01:45:49 -05:00
Axionize a08963e1dc Patches to handling non-target minimum entitiy hitboxes 2025-01-29 08:10:21 -05:00
Axionize 50a2b3af95 Update README.md to note that Java 8 is supported 2025-01-28 23:14:00 -05:00
Axionize 01cd47a6b6 Merge branch 'feat/debug-hitboxes' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/combat/Reach.java
#	src/main/java/ac/grim/grimac/checks/impl/prediction/DebugHandler.java
#	src/main/java/ac/grim/grimac/utils/nmsutil/BlockRayTrace.java
2025-01-28 06:00:06 -05:00
Axionize 7494b995bc Fix checking permission for inventory setbacks 2025-01-28 05:03:22 -05:00
Axionize e4ef877188 Port new Reach modeling to handle generating smallest possible hitboxes 2025-01-25 22:02:24 -05:00
Axionize efa8b750e7 Merge branch 'feat/more-accurate-position-reach-modeling' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/utils/data/ReachInterpolationData.java
2025-01-25 21:51:10 -05:00
Axionize 21d21d2509 Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/combat/Reach.java
#	src/main/java/ac/grim/grimac/checks/impl/scaffolding/RotationPlace.java
#	src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
#	src/main/java/ac/grim/grimac/predictionengine/PlayerBaseTick.java
#	src/main/java/ac/grim/grimac/predictionengine/UncertaintyHandler.java
#	src/main/java/ac/grim/grimac/predictionengine/predictions/PredictionEngine.java
#	src/main/java/ac/grim/grimac/predictionengine/predictions/rideable/PredictionEngineRideableUtils.java
#	src/main/java/ac/grim/grimac/utils/data/KnownInput.java
#	src/main/java/ac/grim/grimac/utils/data/VectorData.java
#	src/main/java/ac/grim/grimac/utils/nmsutil/BlockProperties.java
2025-01-25 21:34:12 -05:00
Axionize 44011acca2 Make Inventory checks support/respect nosetback permissions 2025-01-25 21:12:53 -05:00
Axionize 71791a1020 Update documentation formatting 2025-01-25 12:44:37 -05:00
Axionize 665a43bd4c Merge remote-tracking branch 'origin/2.0' into feat/more-accurate-position-reach-modeling
# Conflicts:
#	src/main/java/ac/grim/grimac/utils/data/ReachInterpolationData.java
2025-01-25 12:34:44 -05:00
Axionize 5ce81e0fe4 Add documention explaining getPossibleLocationCombined() and getPossibleHitboxCombined() 2025-01-25 12:23:46 -05:00
Axionize 29b6e12cb8 Seperate getting possible locations and possible hitbox to reduce how often expandNonRelative() needs to be called 2025-01-25 12:10:08 -05:00
Axionize 014c5f7670 Mark LineOfSightPlace as experimental cehck 2025-01-25 10:26:32 -05:00
Axionize 9c9316e224 Merge remote-tracking branch 'origin/2.0' into merge-dev 2025-01-23 18:32:51 -05:00
Axionize 9e296cbf5a Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsX.java
#	src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java
#	src/main/resources/config/en.yml
#	src/main/resources/config/es.yml
#	src/main/resources/config/fr.yml
#	src/main/resources/config/it.yml
#	src/main/resources/config/nl.yml
#	src/main/resources/config/pt.yml
#	src/main/resources/config/ru.yml
#	src/main/resources/config/tr.yml
#	src/main/resources/config/zh.yml
2025-01-22 03:20:55 -05:00
Axionize 0af47a1266 Stop using server-side tracked position when attempting to account for teleports not always moving entity client side; expand from client area instead 2025-01-22 00:50:05 -05:00
Axionize 8e6219c597 Stop using server-side tracked position; expand from client area instead 2025-01-20 03:55:57 -05:00
Axionize 9aa555ff78 Fix logic error in new brewing stand hitbox code and optimize CCB size 2025-01-20 02:34:20 -05:00
Axionize 21c0833769 Adapt RaycastData and BlockRayTrace classes to accommodate new HitboxData.getBlockHitbox() parameters format. 2025-01-20 01:44:39 -05:00
Axionize 450642d888 Refactor HitboxData.getBlockHitbox() to include isTargetBlock as parameter
Also fixes a rare NPE
2025-01-20 01:40:38 -05:00
Axionize 4fa3ef68e2 Java 8 compatability fixes 2025-01-15 22:38:17 -05:00
Axionize f477ba4c62 Merge remote-tracking branch 'origin/2.0' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsP.java
#	src/main/java/ac/grim/grimac/checks/impl/sprint/SprintB.java
#	src/main/java/ac/grim/grimac/manager/init/start/CommandRegister.java
#	src/main/java/ac/grim/grimac/utils/latency/CompensatedEntities.java
#	src/main/resources/messages/de.yml
#	src/main/resources/punishments/de.yml
#	src/main/resources/punishments/en.yml
#	src/main/resources/punishments/es.yml
#	src/main/resources/punishments/fr.yml
#	src/main/resources/punishments/it.yml
#	src/main/resources/punishments/ja.yml
#	src/main/resources/punishments/nl.yml
#	src/main/resources/punishments/pt.yml
#	src/main/resources/punishments/ru.yml
#	src/main/resources/punishments/tr.yml
#	src/main/resources/punishments/zh.yml
2025-01-15 22:01:06 -05:00
Axionize 4ac58782ac Fix legacy Elder Guardian hitbox 2025-01-05 08:17:53 -05:00
Axionize 2f6242027b Fix calling PacketGuardianEntity constructor and updating metadata; document wiki's errors 2025-01-05 08:17:27 -05:00
Axionize d8c0aef8cc add PacketEntityGuardian for hitbox modeling 2025-01-05 07:48:30 -05:00
Axionize 3f1b4d8472 Merge branch 'merge-dev' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/commands/GrimDump.java
#	src/main/java/ac/grim/grimac/commands/GrimLog.java
#	src/main/java/ac/grim/grimac/commands/GrimVersion.java
#	src/main/java/ac/grim/grimac/manager/init/start/PlaceholderAPIExpansion.java
#	src/main/java/ac/grim/grimac/utils/nmsutil/BlockRayTrace.java
2025-01-02 22:20:51 -05:00
Axionize 0adc332d14 Fix Java 8 Compatability issues 2025-01-01 23:52:56 -05:00
Axionize cda6af1f34 Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsX.java
#	src/main/java/ac/grim/grimac/checks/impl/combat/Reach.java
#	src/main/java/ac/grim/grimac/checks/impl/misc/TransactionOrder.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderB.java
#	src/main/java/ac/grim/grimac/checks/impl/scaffolding/AirLiquidPlace.java
#	src/main/java/ac/grim/grimac/checks/impl/scaffolding/PositionPlace.java
#	src/main/java/ac/grim/grimac/checks/impl/sprint/SprintB.java
#	src/main/java/ac/grim/grimac/commands/GrimVersion.java
#	src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
#	src/main/java/ac/grim/grimac/events/packets/PacketPlayerDigging.java
#	src/main/java/ac/grim/grimac/manager/CheckManager.java
#	src/main/java/ac/grim/grimac/manager/SpectateManager.java
#	src/main/java/ac/grim/grimac/predictionengine/PlayerBaseTick.java
#	src/main/java/ac/grim/grimac/utils/change/PlayerBlockHistory.java
#	src/main/java/ac/grim/grimac/utils/latency/CompensatedInventory.java
#	src/main/java/ac/grim/grimac/utils/math/GrimMath.java
#	src/main/java/ac/grim/grimac/utils/nmsutil/BlockBreakSpeed.java
#	src/main/java/ac/grim/grimac/utils/nmsutil/BoundingBoxSize.java
#	src/main/resources/punishments/de.yml
#	src/main/resources/punishments/en.yml
#	src/main/resources/punishments/es.yml
#	src/main/resources/punishments/fr.yml
#	src/main/resources/punishments/it.yml
#	src/main/resources/punishments/ja.yml
#	src/main/resources/punishments/nl.yml
#	src/main/resources/punishments/pt.yml
#	src/main/resources/punishments/ru.yml
#	src/main/resources/punishments/tr.yml
#	src/main/resources/punishments/zh.yml
2024-12-31 01:16:58 -05:00
Axionize 237f3744d4 Stash debugging code and new hitbox calculation (still wrong?) 2024-12-31 00:26:35 -05:00
Axionize 99b309a0b3 Hitbox Debug Protocol Version Update #1 2024-12-30 18:34:42 -05:00
Axionize ad68a43b83 Style fix 2024-12-28 16:21:06 -05:00
Axionize e7abaf8523 Update upstream more and add debug logging for null hitboxes and PacketOrder 2024-12-28 16:20:22 -05:00
Axionize a508002c48 Update upstream more and add debug logging for null hitboxes 2024-12-28 16:20:05 -05:00
Axionize 259696710f Merge remote-tracking branch 'maninmyvan/packetorder' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderA.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderE.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderF.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderG.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderH.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderI.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderJ.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderK.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderL.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderM.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderN.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderProcessor.java
#	src/main/java/ac/grim/grimac/manager/CheckManager.java
#	src/main/java/ac/grim/grimac/manager/init/start/CommandRegister.java
#	src/main/java/ac/grim/grimac/player/GrimPlayer.java
#	src/main/resources/punishments/de.yml
#	src/main/resources/punishments/en.yml
#	src/main/resources/punishments/es.yml
#	src/main/resources/punishments/fr.yml
#	src/main/resources/punishments/it.yml
#	src/main/resources/punishments/nl.yml
#	src/main/resources/punishments/pt.yml
#	src/main/resources/punishments/ru.yml
#	src/main/resources/punishments/zh.yml
2024-12-28 15:44:17 -05:00
ManInMyVan a47a34e9f9 include more information in verbose 2024-12-28 13:29:53 -07:00
Axionize 4eb5ad4e87 Temporary debugging change + limit used lookVecs 2024-12-28 13:51:24 -05:00
Axionize 46e616107e Fix baby entity hitboxes with dirty hardcoded hack 2024-12-27 22:06:15 -05:00
Axionize dcb72a9efd Complete initial server-side debugging implementation 2024-12-27 21:47:04 -05:00
Axionize b939ba5921 Fix modeling sculk vein hitbox and make SyncedTags compile on Java 8 2024-12-27 18:45:51 -05:00
Axionize 786611aeec Fix modeling sculk vein hitbox 2024-12-27 18:40:56 -05:00
Axionize 44eba3b446 Stash Reach debugging checks 2024-12-27 18:40:32 -05:00
ManInMyVan 0f11cb74b8 don't check the same value twice 2024-12-27 16:24:47 -07:00
ManInMyVan 1cff3e526f fix 1.21.2+ PacketOrderH false 2024-12-26 15:34:32 -07:00
ManInMyVan a09093ee5b don't register PacketOrderProcessor twice 2024-12-26 15:34:32 -07:00
ManInMyVan c1db9edd7d 1.21.2 2024-12-26 15:34:32 -07:00
ManInMyVan 9ac2b4fbb6 fix wrongly resolved merge conflict 2024-12-26 15:32:37 -07:00
ManInMyVan 0b9ba69afc fix falses 2024-12-26 15:32:37 -07:00
ManInMyVan b326c7b961 remove PacketOrderO
depends on too many factors
2024-12-26 15:32:37 -07:00
ManInMyVan f1243073f2 fix more falses 2024-12-26 15:32:37 -07:00
ManInMyVan 4e4f23479a fix falses 2024-12-26 15:32:37 -07:00
ManInMyVan c7a4eeec94 fix false when swapping offhand items 2024-12-26 15:32:37 -07:00
ManInMyVan d1a2dbf6aa fix false when dropping items 2024-12-26 15:32:37 -07:00
ManInMyVan c67258ac13 only setback on item use 2024-12-26 15:32:37 -07:00
ManInMyVan ca7da355f7 remove invalid variable default 2024-12-26 15:32:37 -07:00
ManInMyVan 2a452c7d85 add remaining entity actions to PacketOrderProcessor 2024-12-26 15:32:37 -07:00
ManInMyVan 66776e8163 rename invalidSlots to invalid 2024-12-26 15:32:36 -07:00
ManInMyVan 3089036d43 add PacketOrderO and PacketOrderP 2024-12-26 15:32:36 -07:00
ManInMyVan 447ce3466d add PacketOrderN 2024-12-26 15:32:36 -07:00
ManInMyVan 244113714e Add PacketOrderM 2024-12-26 15:32:36 -07:00
ManInMyVan ae1c47d21f fix a noslow 2024-12-26 15:32:36 -07:00
ManInMyVan 241525c2c2 rename exempt-digging to exempt-placing-while-digging in PacketOrderI
and make it work
2024-12-26 15:32:36 -07:00
ManInMyVan d2b529aceb rename PacketOrderM to PacketOrderA 2024-12-26 15:32:36 -07:00
ManInMyVan 89f0aefe22 add PacketOrderM 2024-12-26 15:32:36 -07:00
ManInMyVan 8d8499d6fc use PacketOrderProcessor in PacketOrderK 2024-12-26 15:32:36 -07:00
ManInMyVan 3bd1673e67 rewrite 2024-12-26 15:32:36 -07:00
ManInMyVan 2ee47a23ea fix falses 2024-12-26 15:32:35 -07:00
ManInMyVan 734d227175 don't cancel the tick 2024-12-26 15:32:35 -07:00
ManInMyVan 1377747bec more PacketOrderC stuff 2024-12-26 15:32:35 -07:00
ManInMyVan 210a9266a4 fixes 2024-12-26 15:32:35 -07:00
ManInMyVan 616c46d97e oops 2024-12-26 15:32:35 -07:00
ManInMyVan aa69b6f69f fix falses 2024-12-26 15:32:35 -07:00
ManInMyVan fae66e9039 Add PacketOrderK 2024-12-26 15:32:35 -07:00
ManInMyVan fb05fcb1fa make PacketOrderE setback
https://github.com/CCBlueX/LiquidBounce/blob/nextgen/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/noslow/modes/blocking/NoSlowBlockingSwitch.kt
2024-12-26 15:32:35 -07:00
ManInMyVan acdcfe8f71 exemptBreaking option in PacketOrdlerL 2024-12-26 15:32:35 -07:00
ManInMyVan e3f5db6f19 fix some PacketOrderF falses 2024-12-26 15:32:34 -07:00
ManInMyVan be48c35eda Add PacketOrderL 2024-12-26 15:32:34 -07:00
ManInMyVan 2ea1d29da5 Check entity in PacketOrderC 2024-12-26 15:32:34 -07:00
ManInMyVan c49e531853 Add PacketOrderJ 2024-12-26 15:32:34 -07:00
ManInMyVan 2eebcfd056 Add PacketOrderI 2024-12-26 15:32:34 -07:00
ManInMyVan f1988e66be Add PacketOrderH 2024-12-26 15:32:34 -07:00
ManInMyVan d7474db60d these are already packet checks 2024-12-26 15:32:34 -07:00
ManInMyVan 97b3781f49 Add PacketOrderG 2024-12-26 15:32:34 -07:00
ManInMyVan a99e0e4947 add PacketOrderF 2024-12-26 15:32:34 -07:00
ManInMyVan ec88893d52 add PacketOrderE 2024-12-26 15:32:33 -07:00
ManInMyVan c1670a7f4e PacketOrder check catagory 2024-12-26 15:32:28 -07:00
Axionize 3e185b6e1e Initial server-side impementation for debugging Hitboxes 2024-12-25 23:05:20 -05:00
Axionize d714211fe6 Merge branch 'merge' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
2024-12-25 19:14:22 -05:00
Axionize 71d524aad0 Fix more Java 8 compatability issues introduced by upstream 2024-12-24 22:58:48 -05:00
Axionize 9bf8eed3d1 - Temporarily undo entity map and iteration order changes in attempt to fix HitboxMiss and HitboxBlock? falses
- Update upstream
- Make PacketOrderC (formerly BadPacketsM) no longer experimental
2024-12-24 22:48:17 -05:00
Axionize 74c8c5ff01 Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderC.java
#	src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
#	src/main/java/ac/grim/grimac/utils/anticheat/MessageUtil.java
2024-12-24 22:38:12 -05:00
Axionize 935b26ca0c Fix Java 8 Compatability in miniMessage() 2024-12-24 22:19:05 -05:00
Axionize 5e2f889550 Revert entity iteration mapping changes (attempt to fix HitboxMiss and HitboxBlocK? falses) 2024-12-24 22:17:39 -05:00
Axionize b003ec799b Fix Java 8 Compatability in miniMessage() 2024-12-23 22:44:19 -05:00
Axionize 11037cdc85 Fix 1.8 Hitbox modeling for close non-relative teleports 2024-12-23 22:41:16 -05:00
Axionize fffae61f8a Merge branch 'feat/1.8-missed-hitbox-fix' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/events/packets/PacketEntityReplication.java
2024-12-23 22:39:29 -05:00
Axionize 6a56b9bbf0 Merge branch 'merge' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/predictionengine/predictions/rideable/PredictionEngineRideableUtils.java
#	src/main/java/ac/grim/grimac/utils/anticheat/MessageUtil.java
2024-12-23 22:38:28 -05:00
Axionize 4c13a0adec Fix 1.8 Hitbox modeling for close non-relative teleports 2024-12-23 22:06:49 -05:00
Axionize 0932b7062d Merge upstream changes up to commit 1f93dff26c 2024-12-23 21:33:36 -05:00
Axionize 7f61d19f55 Merge remote-tracking branch 'origin/2.0' into merge-dev
# Conflicts:
#	build.gradle.kts
#	src/main/java/ac/grim/grimac/checks/impl/scaffolding/AirLiquidPlace.java
#	src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
#	src/main/java/ac/grim/grimac/manager/CheckManager.java
#	src/main/java/ac/grim/grimac/player/GrimPlayer.java
#	src/main/java/ac/grim/grimac/utils/change/BlockModification.java
#	src/main/java/ac/grim/grimac/utils/change/PlayerBlockHistory.java
2024-12-23 21:12:40 -05:00
Axionize 31396cdd73 Fix NPE that can occur in HitboxEntities check 2024-12-22 21:34:33 -05:00
Axionize ceb6e7932b Merge branch 'merge' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/utils/change/PlayerBlockHistory.java
2024-12-22 21:33:35 -05:00
Axionize 82a755d739 Fix NPE that can occur if there is no hitbox overlap on entity move in reach-entities-check 2024-12-22 21:32:04 -05:00
Axionize 631217a7f4 Fix very rare CME; investigate cause later 2024-12-20 21:35:59 -05:00
Axionize b880f51fbc BadPacketsX, PacketOrder, and LineOfSightPlace improvements
* Refactor and improve numerous PacketOrder checks
* Fix some BadPacketsX falses
* Fix some LineOfSightPlace falses
2024-12-18 16:17:23 -05:00
Axionize 2a86ff4e5f BadPacketsX, and LOSP false fixes 2024-12-18 16:09:59 -05:00
Axionize 3d3a17eea9 Merge remote-tracking branch 'maninmyvan/packetorder' into merge-dev
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderA.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderE.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderF.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderG.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderH.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderI.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderJ.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderK.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderL.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderM.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderN.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderO.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderProcessor.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/TransactionOrder.java
#	src/main/java/ac/grim/grimac/manager/CheckManager.java
#	src/main/java/ac/grim/grimac/player/GrimPlayer.java
#	src/main/resources/punishments/de.yml
#	src/main/resources/punishments/en.yml
#	src/main/resources/punishments/es.yml
#	src/main/resources/punishments/fr.yml
#	src/main/resources/punishments/it.yml
#	src/main/resources/punishments/nl.yml
#	src/main/resources/punishments/pt.yml
#	src/main/resources/punishments/ru.yml
#	src/main/resources/punishments/zh.yml
2024-12-18 14:45:58 -05:00
Axionize ac2607d6cd Merge branch 'merge' into merge-dev 2024-12-18 14:21:57 -05:00
Axionize b4820b5f19 Update punishment files for logging 2024-12-17 19:57:07 -05:00
Axionize 79c70572a8 Code cleanup; re-add grim.verbose.enable-on-join permission 2024-12-17 19:11:55 -05:00
Axionize ced56218d9 Update punishment files for non-en langauges for reach refactor 2024-12-17 19:02:31 -05:00
Axionize 6243fdf605 Refactor and split Reach into 4 checks. Fix some HitboxEntity falses. (#25)
* Temporary hack to fix rapidly changing blocks causing falses
* Refactor reach to flag seperate checks
* Fix verbose double toggling
* Fix check annotations
* Temporary fix
* Temporarily disable removing extra eyeHeight reach iterations; also fix Pink Petals Box
* Stash sectioned entity map
* Replicate vanilla iteration order, primarily for performing entity hitbox blocking checks
2024-12-17 18:53:35 -05:00
AbdisKioskandManInMyVan b40deaa620 Add / grim history (#24)
* Add option to log violations

* Add /grim history command

* Follow coventions

Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>

* Remove unused getters

* Make messages configurable

* make entries per page configurable

* fix subcommand alias

* add command to messages

* synchronize writes to avoid sqlite_misuse error

* add history messages to all lang files

* add mysql compatability to violation database

* add mysql compatability to violation database

* add grim history in help command for all languages

* change colorcodes from § to & for grim history strings

* avoid sync usage of Bukkit.getOfflinePlayer(string)

* add tab completion for online players in grim history

* remove test

* Follow coventions

Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>

* revert file permission change in gradlew

* add 'server' field to grim history

---------

Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-12-17 11:41:19 -05:00
ManInMyVan 571ae73fc5 fix PacketOrderI falses with tick skipping 2024-12-15 12:55:16 -07:00
Axionize 8d2d33f1ea Fixed InventoryD not working due to upstream changes to simulation engine movement data.
ver: 2.3.69-B37
2024-12-15 14:31:52 -05:00
Axionize 738cd44ab9 Fix inventoryD breaking due to new engine changes 2024-12-15 14:30:11 -05:00
ManInMyVan b800699cbf fix 1.21.2+ PacketOrderH false 2024-12-15 12:19:41 -07:00
Axionize d3c82a326a Fix automatically enabling verbose when joining 2024-12-14 20:36:02 -05:00
Axionize e40ba62e5a Merge remote-tracking branch 'origin/2.0' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/movement/NoSlowC.java
#	src/main/java/ac/grim/grimac/checks/impl/movement/NoSlowD.java
#	src/main/java/ac/grim/grimac/checks/impl/movement/NoSlowE.java
#	src/main/java/ac/grim/grimac/checks/impl/post/Post.java
#	src/main/java/ac/grim/grimac/checks/impl/scaffolding/RotationPlace.java
#	src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
#	src/main/java/ac/grim/grimac/manager/CheckManager.java
2024-12-14 19:59:35 -05:00
ManInMyVan bcc9e9be13 don't register PacketOrderProcessor twice 2024-12-13 13:12:47 -07:00
ManInMyVan 40918c9988 remove unused imports 2024-12-13 13:11:58 -07:00
ManInMyVan f493fe3005 1.21.2 2024-12-13 12:38:30 -07:00
ManInMyVan c5dc6d4050 fix wrongly resolved merge conflict 2024-12-12 22:39:31 -07:00
ManInMyVan db8aad3c00 fix falses 2024-12-12 19:52:28 -07:00
ManInMyVan 12cdd2f380 remove PacketOrderO
depends on too many factors
2024-12-12 19:51:17 -07:00
ManInMyVan 6c3657ae40 fix more falses 2024-12-12 19:49:59 -07:00
ManInMyVan ffa21f6f3e fix falses 2024-12-12 19:49:59 -07:00
ManInMyVan 7ce0e2f9ec fix false when swapping offhand items 2024-12-12 19:49:59 -07:00
ManInMyVan 1c3c6a8879 fix false when dropping items 2024-12-12 19:49:59 -07:00
ManInMyVan 75aa7d8f71 only setback on item use 2024-12-12 19:49:59 -07:00
ManInMyVan 33c96893d7 remove invalid variable default 2024-12-12 19:49:59 -07:00
ManInMyVan c3f6fd5c65 add remaining entity actions to PacketOrderProcessor 2024-12-12 19:49:59 -07:00
ManInMyVan 616f3076c9 rename invalidSlots to invalid 2024-12-12 19:49:59 -07:00
ManInMyVan 0898a94104 add PacketOrderO and PacketOrderP 2024-12-12 19:49:59 -07:00
ManInMyVan 48a371dc66 add PacketOrderN 2024-12-12 19:49:39 -07:00
ManInMyVan 5e7fef1572 Add PacketOrderM 2024-12-12 19:49:39 -07:00
ManInMyVan 8701f12f6a fix a noslow 2024-12-12 19:49:39 -07:00
ManInMyVan cbdd5a7a14 rename exempt-digging to exempt-placing-while-digging in PacketOrderI
and make it work
2024-12-12 19:49:39 -07:00
ManInMyVan 48ba546a40 rename PacketOrderM to PacketOrderA 2024-12-12 19:49:39 -07:00
ManInMyVan cdbe983d22 add PacketOrderM 2024-12-12 19:49:39 -07:00
ManInMyVan e2ad24e604 use PacketOrderProcessor in PacketOrderK 2024-12-12 19:49:39 -07:00
ManInMyVan d954784e74 rewrite 2024-12-12 19:49:39 -07:00
ManInMyVan dd0e338588 fix falses 2024-12-12 19:49:39 -07:00
ManInMyVan 73d591907d don't cancel the tick 2024-12-12 19:49:38 -07:00
ManInMyVan 806a13ea25 more PacketOrderC stuff 2024-12-12 19:49:38 -07:00
ManInMyVan 38d64e2cff fixes 2024-12-12 19:49:38 -07:00
ManInMyVan c666d98a9e oops 2024-12-12 19:49:38 -07:00
ManInMyVan c270105c09 fix falses 2024-12-12 19:49:38 -07:00
ManInMyVan 36776a488b Add PacketOrderK 2024-12-12 19:49:38 -07:00
ManInMyVan 5d6c77851a make PacketOrderE setback
https://github.com/CCBlueX/LiquidBounce/blob/nextgen/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/noslow/modes/blocking/NoSlowBlockingSwitch.kt
2024-12-12 19:49:38 -07:00
ManInMyVan 8bb5be493d exemptBreaking option in PacketOrdlerL 2024-12-12 19:49:38 -07:00
ManInMyVan c681a12176 fix some PacketOrderF falses 2024-12-12 19:39:58 -07:00
ManInMyVan ea614f7336 Add PacketOrderL 2024-12-12 19:39:58 -07:00
ManInMyVan fa985fe4fa Check entity in PacketOrderC 2024-12-12 19:39:58 -07:00
ManInMyVan f485b70cbf Add PacketOrderJ 2024-12-12 19:39:58 -07:00
ManInMyVan 36e0974fcf Add PacketOrderI 2024-12-12 19:39:58 -07:00
ManInMyVan a4ee272641 Add PacketOrderH 2024-12-12 19:39:58 -07:00
ManInMyVan fd8507610b these are already packet checks 2024-12-12 19:39:57 -07:00
ManInMyVan 4428af4acc Add PacketOrderG 2024-12-12 19:39:57 -07:00
ManInMyVan a4031c4862 add PacketOrderF 2024-12-12 19:39:57 -07:00
ManInMyVan 7abb8d61b0 add PacketOrderE 2024-12-12 19:39:57 -07:00
ManInMyVan 0b76452fbb PacketOrder check catagory 2024-12-12 19:34:23 -07:00
Axionize 0c8b4c2f3a Update PacketEvents for 1.21.4 support and shadow colors 2024-12-07 03:42:06 -05:00
Axionize 42af76a9ea Merge remote-tracking branch 'origin/2.0' into merge 2024-12-07 02:45:54 -05:00
Axionize 7a0f2b1227 Merge remote-tracking branch 'origin/2.0' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/combat/Reach.java
#	src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
#	src/main/java/ac/grim/grimac/predictionengine/predictions/PredictionEngine.java
2024-12-05 12:36:31 -05:00
Axionize 1789912e14 Improve performance; replace concurrent with nonconcurrent queue 2024-12-05 00:23:56 -05:00
Axionize 6cbedf1f26 Fix Java 8 Compatability 2024-12-04 23:18:17 -05:00
Axionize 2c42a96c3c Merge branch '2.0' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
#	src/main/java/ac/grim/grimac/utils/latency/CompensatedEntities.java
2024-12-03 20:12:24 -05:00
Axionize bc1ab00c3f Merge remote-tracking branch 'origin/2.0' into 2.3.69-b30
# Conflicts:
#	src/main/java/ac/grim/grimac/utils/data/Pair.java
2024-11-30 02:23:24 -05:00
Axionize 34fde514fd Revert "exempt 1.14.2+ clients in NoSlowC and NoSlowD"
This reverts commit f6ef1df29d.
2024-11-30 02:22:24 -05:00
Axionize 26d5d9d9d2 Merge remote-tracking branch 'maninmyvan/multiactions' into 2.3.69-b30
# Conflicts:
#	src/main/java/ac/grim/grimac/manager/CheckManager.java
2024-11-30 02:14:27 -05:00
Axionize f755f2d670 Fix config issue where skip-block-check: true and skip-entity-check: false would cause numerous block falses 2024-11-29 16:23:30 -05:00
Axionize 3004390528 Make LOSP use same direction calculations as Reach check; could fix some falses 2024-11-29 02:01:50 -05:00
Axionize af141e35d3 Put -Dpaper.explicit-flush=true in quotes 2024-11-29 01:07:24 -05:00
Axionize 3a33be168f Warn players who want extra reach accuracy that they need to add paper.explicit-flush=true 2024-11-29 01:07:17 -05:00
Axionize 30994d1279 Shrink blocks for 0.03/0.002 2024-11-29 01:06:06 -05:00
Axionize 9b716b5c58 Add block and reach check skip options 2024-11-29 00:57:01 -05:00
Axionize 714549f79c Merge branch 'reach-check-entities' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/scaffolding/LineOfSightPlace.java
#	src/main/java/ac/grim/grimac/utils/anticheat/update/BlockPlace.java
#	src/main/java/ac/grim/grimac/utils/data/HitData.java
#	src/main/java/ac/grim/grimac/utils/latency/CompensatedEntities.java
#	src/main/java/ac/grim/grimac/utils/nmsutil/BlockRayTrace.java
2024-11-29 00:20:45 -05:00
Axionize d0fcf33255 Fix Armorstand index on 1.13.2 for PacketEntity 2024-11-29 00:09:17 -05:00
Axionize 02553f332f Fix Bow NoSlow 2024-11-28 23:29:24 -05:00
Axionize 1eb12bafd4 Fix evicting queue for riptide entities 2024-11-28 21:17:09 -05:00
Axionize 88883caca8 Fix riptide trident attacks on entiies that are non-pushable or the same team as the attacker 2024-11-28 17:10:32 -05:00
Axionize 5a8e8b320a Add permission to enable verbose on join 2024-11-27 23:45:49 -05:00
Axionize 3723581dc2 split union() in SCB into union() and new encompass() method; fixes Simulation false on walls 2024-11-27 21:48:19 -05:00
Axionize 7ea0d4d24c Make var type in ExploitC explicitly String 2024-11-27 21:47:14 -05:00
Axionize dff5361934 Merge remote-tracking branch 'origin/2.0' into merge 2024-11-27 01:37:11 -05:00
Axionize cd032a51ab Merge remote-tracking branch 'origin/2.0' into merge 2024-11-26 03:41:30 -05:00
Axionize 379fc6601d Merge remote-tracking branch 'origin/2.0' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/manager/init/start/BStats.java
2024-11-25 00:28:02 -05:00
Axionize dd490aa8c2 Merge branch 'fix-modern-cient-legacy-server-walls' into merge 2024-11-25 00:08:31 -05:00
Axionize 42094cbddc Merge branch 'fix-airliquidplace' into merge 2024-11-24 23:49:52 -05:00
Axionize d0562de1e1 Cleanup 2024-11-24 22:22:12 -05:00
Axionize d85979d3ab Merge branch 'fix-airliquidplace' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/badpackets/BadPacketsX.java
#	src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
#	src/main/java/ac/grim/grimac/manager/TickManager.java
#	src/main/java/ac/grim/grimac/utils/collisions/CollisionData.java
#	src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java
#	src/main/java/ac/grim/grimac/utils/collisions/blocks/PistonHeadCollision.java
2024-11-24 22:04:35 -05:00
Axionize 3809aed146 Finish documenting all edge cases that can false AirLiquidPlace and fixing them 2024-11-24 22:02:21 -05:00
Axionize 06210f03ba Remove debug messages 2024-11-24 21:02:05 -05:00
Axionize 97afbd8d77 Move clearing updated blocks logic into an async loop; new ClearRecentlyUpdatedBlocks() class 2024-11-24 20:29:48 -05:00
Axionize df89d15aa6 Cleanup AirLiquidPlace 2024-11-24 20:25:22 -05:00
Axionize 12864dccc5 Only check first value in iterator() in AirLiquidPlace() 2024-11-24 20:17:01 -05:00
Axionize 4c9b07612d Fix AirLiquidPlace false 2024-11-24 20:12:59 -05:00
Axionize 026c2417c9 Add new Data classes to see recently modified blocks 2024-11-24 20:12:34 -05:00
Axionize 9621add16e Fix CCB constructor for DynamicHitboxFence 2024-11-24 02:41:12 -05:00
Axionize 7bd3af3eca Use movementThreshold() instead of 0.03 where appropiate 2024-11-24 01:34:05 -05:00
Axionize dd9d14e195 Style fix 2024-11-24 00:29:24 -05:00
Axionize 8d01e90f11 Mark BadPacketsZ as no longer experimental 2024-11-24 00:03:02 -05:00
Axionize 6ed64d3730 Mark BadPacketsX as no longer experimental 2024-11-23 23:56:22 -05:00
Axionize 8660ff0f60 Fix BadPacketsX falses 2024-11-23 23:56:02 -05:00
Axionize fd889bd26a Merge remote-tracking branch 'maninmyvan/packetorder' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderA.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderE.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderF.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderG.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderH.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderI.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderJ.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderK.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderL.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderM.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderN.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderO.java
#	src/main/java/ac/grim/grimac/checks/impl/packetorder/PacketOrderProcessor.java
#	src/main/java/ac/grim/grimac/manager/CheckManager.java
2024-11-23 11:34:23 -05:00
Axionize 1a7949a477 Revert "Fix rapidly breaking/placing instabreak blocks and lighting tnt falses; currently LOSP no longer stops any illegal placements just flags. Will fix later"
This reverts commit 9f09fcd1
2024-11-22 22:23:10 -05:00
Axionize 0a26d37728 Revert "New buffer system"
This reverts commit ef45df9e
2024-11-22 22:21:37 -05:00
Axionize 73597d9524 Make whether or not to relocate deps read from project properties -> environment variable"
Prevents having to modify build.gradle.kts when disabling relocating.
2024-11-22 21:24:35 -05:00
ManInMyVan 1799a56072 fix falses 2024-11-22 14:28:02 -07:00
ManInMyVan 56e4fa75bf cleanup imports 2024-11-22 14:13:32 -07:00
ManInMyVan b535b28661 rename PacketOrderP to PacketOrderO 2024-11-22 13:46:43 -07:00
ManInMyVan 43634772c7 remove PacketOrderO
depends on too many factors
2024-11-22 13:46:43 -07:00
ManInMyVan aea66feb33 fix more falses 2024-11-22 13:46:43 -07:00
ManInMyVan 11d856ce08 fix falses 2024-11-22 13:46:43 -07:00
ManInMyVan 30a346bd3f fix a noslow 2024-11-22 13:46:43 -07:00
ManInMyVan 5254a376c4 fix false when swapping offhand items 2024-11-22 13:46:43 -07:00
ManInMyVan f79e8c12a5 fix false when dropping items 2024-11-22 13:46:42 -07:00
ManInMyVan af580c4d48 only setback on item use 2024-11-22 13:46:42 -07:00
ManInMyVan be65dc5e51 remove invalid variable default 2024-11-22 13:46:42 -07:00
ManInMyVan 93c1c7b480 remove sent variable 2024-11-22 13:46:42 -07:00
ManInMyVan b0a5dbd07f and use them 2024-11-22 13:46:42 -07:00
ManInMyVan 74cca86bb6 add remaining entity actions to PacketOrderProcessor 2024-11-22 13:46:42 -07:00
ManInMyVan fe4e60c80c rename invalidSlots to invalid 2024-11-22 13:46:42 -07:00
ManInMyVan 22dd134196 add PacketOrderO and PacketOrderP 2024-11-22 13:46:42 -07:00
ManInMyVan e971604565 add PacketOrderN 2024-11-22 13:46:42 -07:00
ManInMyVan 90c59ad4df Add PacketOrderM 2024-11-22 13:46:42 -07:00
ManInMyVan c888256b38 remove unused method 2024-11-22 13:46:41 -07:00
ManInMyVan 72a0ad53dd rename exempt-digging to exempt-placing-while-digging in PAcketOrderI
and make it work
2024-11-22 13:46:41 -07:00
ManInMyVan 2fc13af09d rename PacketOrderM to PacketOrderA 2024-11-22 13:46:41 -07:00
ManInMyVan 57ccbe753e revert renaming post 2024-11-22 13:46:41 -07:00
ManInMyVan d14916c590 add PacketOrderM 2024-11-22 13:46:41 -07:00
ManInMyVan 5b8741ca46 use PacketOrderProcessor in PacketOrderK 2024-11-22 13:46:41 -07:00
ManInMyVan cfcf52f337 rewrite 2024-11-22 13:46:41 -07:00
ManInMyVan ab32f24dc1 fix falses 2024-11-22 13:46:40 -07:00
ManInMyVan a653e17f3c don't cancel the tick 2024-11-22 13:46:40 -07:00
ManInMyVan 809d26307f more PacketOrderC stuff 2024-11-22 13:46:40 -07:00
ManInMyVan d35d326595 fixes 2024-11-22 13:46:40 -07:00
ManInMyVan 81c550e834 oops 2024-11-22 13:46:40 -07:00
ManInMyVan b27cea2385 register PacketOrderL 2024-11-22 13:46:40 -07:00
ManInMyVan 79f1d65713 fix falses 2024-11-22 13:46:40 -07:00
ManInMyVan 737e6c4cfb exemptBreaking -> exempt-breaking 2024-11-22 13:46:40 -07:00
ManInMyVan 44f68a3266 Add PacketOrderK 2024-11-22 13:46:40 -07:00
ManInMyVan 4e69adc548 exemptBreaking option in PacketOrdlerL 2024-11-22 13:46:39 -07:00
ManInMyVan 93d0c38393 make PacketOrderE setback
https://github.com/CCBlueX/LiquidBounce/blob/nextgen/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/noslow/modes/blocking/NoSlowBlockingSwitch.kt
2024-11-22 13:46:39 -07:00
ManInMyVan 81aa8b8d31 check ENTITY_ACTION packets in PacketOrderL 2024-11-22 13:46:39 -07:00
ManInMyVan ce28bb689a fix some PacketOrderF falses 2024-11-22 13:46:39 -07:00
ManInMyVan 487ce68ef6 Add PacketOrderL 2024-11-22 13:46:39 -07:00
ManInMyVan a29f7a2807 nvm it is valid on 1.8 2024-11-22 13:46:39 -07:00
ManInMyVan 80d33f0f11 this packet order is only valid in 1.7 client 2024-11-22 13:46:39 -07:00
ManInMyVan 0bd57102d5 Check entity in PacketOrderC 2024-11-22 13:46:39 -07:00
ManInMyVan c701b22098 these are already packet checks 2024-11-22 13:46:39 -07:00
ManInMyVan 0ad3c58496 Check digging packets in PacketOrderF 2024-11-22 13:46:39 -07:00
ManInMyVan 99e06d6b3b Update PacketOrderI.java 2024-11-22 13:46:39 -07:00
ManInMyVan 4785482543 Add PacketOrderJ 2024-11-22 13:46:38 -07:00
ManInMyVan c06beba53b Add PacketOrderI 2024-11-22 13:46:38 -07:00
ManInMyVan 4b989a15b6 Add PacketOrderH 2024-11-22 13:46:38 -07:00
ManInMyVan 0f10d48519 Add PacketOrderG 2024-11-22 13:46:38 -07:00
ManInMyVan 2e7454de84 add PacketOrderF 2024-11-22 13:46:38 -07:00
ManInMyVan 5faad6b3ba add PacketOrderE 2024-11-22 13:46:38 -07:00
ManInMyVan 75b0f5c344 PacketOrder check catagory 2024-11-22 13:46:38 -07:00
Axionize d0b94bbda5 Merge remote-tracking branch 'origin/update/1.21.3' into merge 2024-11-22 12:15:58 -05:00
Axionize 6f18622643 Merge branch 'flatten-complexcollisionboxes' into merge 2024-11-22 09:14:08 -05:00
Axionize 6b863655f1 Merge remote-tracking branch 'origin/2.0' into flatten-complexcollisionboxes
# Conflicts:
#	src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java
2024-11-22 09:13:17 -05:00
Axionize 631be06ec2 Remove unused calls to makeShapes() 2024-11-22 09:11:04 -05:00
Axionize 1c4361f2c6 Make makeShapes() CCD extra maxIndex explicit; Fix DynamicCollisionWall error 2024-11-22 09:10:04 -05:00
Cristian Milani 2b5016442b Fix race condition and exception when registering check permissions during rapid consecutive player joins on server start 2024-11-21 20:21:59 -05:00
Axionize e389e4b5e1 Fix Pink Petals Hitbox (Coral Fan) for > 1.12.2 and =< 1.19.3 players 2024-11-21 19:21:28 -05:00
Axionize 7d9cdb91b0 Merge branch 'flatten-complexcollisionboxes' into merge 2024-11-21 18:43:20 -05:00
Axionize 83e06bce77 Make CCD length private var 2024-11-21 18:32:33 -05:00
Axionize 42fd3e1cc7 Rename variable for clarity 2024-11-21 17:14:13 -05:00
Axionize 26a771e4da Fix copying CCBs in edge case 2024-11-21 17:12:38 -05:00
Axionize fad1eb5736 Merge branch 'flatten-complexcollisionboxes' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/utils/collisions/CollisionData.java
#	src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java
#	src/main/java/ac/grim/grimac/utils/collisions/blocks/DynamicStair.java
#	src/main/java/ac/grim/grimac/utils/collisions/blocks/PistonHeadCollision.java
#	src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicConnecting.java
#	src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxFence.java
#	src/main/java/ac/grim/grimac/utils/collisions/datatypes/ComplexCollisionBox.java
2024-11-21 12:18:11 -05:00
Axionize 1dc4361938 Remove debug print statement 2024-11-21 12:06:03 -05:00
Axionize 3d5491de4f Fix logic error again in CCB constructor 2024-11-21 12:04:04 -05:00
Axionize 75ff92c326 Optimize DynamicHitboxFence 2024-11-21 11:59:19 -05:00
Axionize c530dcfa17 Fix logic error in CCB constructor 2024-11-21 11:58:04 -05:00
Axionize d720b8864f Fix new downCast() for SimpleCollisionBox 2024-11-21 11:41:52 -05:00
Axionize 3e3dbf0f30 Manually size ComplexCollisionBoxes Pt. 2 2024-11-21 11:38:32 -05:00
Axionize 0bd154974b Manually size ComplexCollisionBoxes Pt. 1 2024-11-21 10:28:34 -05:00
Axionize 3f57026960 implement new downCast() API for Dynamic, Simple, and No Collision Boxes 2024-11-21 10:26:46 -05:00
Axionize be9841fb9f Port everything to new internal .downCast() API besides getCollisionBoxes 2024-11-20 12:37:52 -05:00
Axionize d8b529e837 Optimize ComplexCollisionBoxes by using primitives internally; Make new more efficient constructors available 2024-11-20 12:37:01 -05:00
Axionize d01805ad13 Merge remote-tracking branch 'machinebreaker/inventory-checks' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/inventory/InventoryD.java
#	src/main/java/ac/grim/grimac/checks/impl/inventory/InventoryG.java
2024-11-20 12:23:05 -05:00
Axionize f638772c5f Merge remote-tracking branch 'maninmyvan/packetorder' into merge 2024-11-20 12:21:54 -05:00
Axionize b84b21a68f Revert "Remove old .downCast() method for CollisionBoxes"
This reverts commit c91ef450
2024-11-20 12:14:16 -05:00
Axionize da230781e3 Port everything to new internal .downCast() API besides getCollisionBoxes 2024-11-20 12:01:02 -05:00
Axionize c91ef45062 Remove old .downCast() method for CollisionBoxes 2024-11-20 11:23:28 -05:00
Axionize 9a87329618 Optimize ComplexCollisionBoxes by using primitives internally; Make new more efficient constructors available 2024-11-20 11:15:53 -05:00
Axionize 24ee315c0b Merge remote-tracking branch 'origin/2.0' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/combat/Reach.java
2024-11-19 20:15:21 -05:00
ManInMyVan a4decb57f8 fix more falses 2024-11-17 18:03:13 -07:00
ManInMyVan 81feb5be3f fix falses 2024-11-17 17:25:57 -07:00
MachineBreaker 2253fd0ec3 Use correct operator in InventoryF 2024-11-17 19:46:08 -04:00
MachineBreaker db4ad8e16d Remove InventoryG millis check 2024-11-17 19:41:53 -04:00
MachineBreaker 11571a2b8a Implement inventory desync status 2024-11-17 19:40:28 -04:00
MachineBreaker c615c98d09 Clean imports 2024-11-17 19:24:53 -04:00
MachineBreaker 922b134467 Fix more false positives 2024-11-17 19:20:56 -04:00
Axionize 6650e0cece Fix entity metadata parsing for armorstands on 1.14.4 2024-11-17 14:56:18 -05:00
MachineBreaker 8714e0e5a9 Merge remote-tracking branch 'origin/inventory-checks' into inventory-checks 2024-11-17 13:53:44 -04:00
MachineBreaker 24570aa658 Update config version 2024-11-17 13:53:35 -04:00
Axionize 743a2d9cdb Ensure ComplexCollisionBoxes can only contain SimpleCollisionBoxes 2024-11-17 11:45:55 -05:00
Axionize 4b28aa7604 Ensure ComplexCollisionBoxes can only contain SimpleCollisionBoxes 2024-11-17 11:36:10 -05:00
Axionize 50425ada16 Remove debug print statement 2024-11-17 10:34:45 -05:00
MachineBreaker 6d4f3650cc Merge branch 'GrimAnticheat:2.0' into inventory-checks 2024-11-17 10:22:07 -04:00
Axionize de7a5358d2 Armorstand entity metadata in older versions 2024-11-17 08:02:01 -05:00
Axionize 9a0f3a4dd1 Fix hitboxes for armor stands (including small ones) 2024-11-17 07:46:48 -05:00
Axionize bfbde9d8fc Fix falses due to marker armor stands 2024-11-17 07:19:29 -05:00
MachineBreaker a5ced59a35 Clean imports 2024-11-17 08:13:07 -04:00
MachineBreaker e9c6fac17a Apply suggested changes 2024-11-17 08:11:54 -04:00
Axionize 2bc467ac82 Optimize if else in updateEntityMetaData() 2024-11-17 07:05:26 -05:00
Axionize c68f7bd5f8 Finish merging new inventory checks and packetorder checks; backport to Java 8 2024-11-17 05:36:08 -05:00
Axionize 7015a9efa2 Merge remote-tracking branch 'maninmyvan/packetorder' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/manager/CheckManager.java
2024-11-17 05:19:11 -05:00
ManInMyVan 06bd96fcae fix a noslow 2024-11-16 18:29:05 -07:00
ManInMyVan db7bbef9b5 fix false when swapping offhand items 2024-11-16 18:14:50 -07:00
ManInMyVan fa0d147e04 fix false when dropping items 2024-11-16 18:14:31 -07:00
ManInMyVan 39e7cbe9ca only setback on item use 2024-11-16 18:14:04 -07:00
ManInMyVan 84a1641968 remove invalid variable default 2024-11-16 18:13:45 -07:00
ManInMyVan 26acd7b3a5 remove sent variable 2024-11-16 18:13:15 -07:00
ManInMyVan f51e5e4eae and use them 2024-11-16 18:12:40 -07:00
ManInMyVan 636eaf3d5d add remaining entity actions to PacketOrderProcessor 2024-11-16 18:10:13 -07:00
ManInMyVan 5b9fdd00c8 rename invalidSlots to invalid 2024-11-16 16:45:53 -07:00
MachineBreaker bc42035866 Fix some false positives 2024-11-16 19:32:50 -04:00
Axionize 917eb371c8 Merge remote-tracking branch 'machinebreaker/inventory-checks' into inventory-checks 2024-11-16 18:09:23 -05:00
Axionize ef45df9ea3 New buffer system 2024-11-16 16:44:39 -05:00
Axionize 24965108b2 Fix for entities that players can hit through blocking reach/attack ray trace 2024-11-16 16:00:27 -05:00
Axionize 9f09fcd103 Fix rapidly breaking/placing instabreak blocks and lighting tnt falses; currently LOSP no longer stops any illegal placements just flags. Will fix later 2024-11-16 14:41:03 -05:00
MachineBreaker e1baecd32e Resync InventoryE 2024-11-16 15:31:41 -04:00
MachineBreaker 44d66e0e5b Requested changes 2024-11-16 15:26:45 -04:00
MachineBreaker 0368f930b8 Woops change check name 2024-11-16 13:12:40 -04:00
MachineBreaker a83a0c8579 Implement experimental entity action while inventory is open check 2024-11-16 13:07:17 -04:00
MachineBreaker 92b1ad28c2 Fix 1.8 clients never letting 1.9+ server know about their inventory status
(Via hack)
2024-11-16 12:59:15 -04:00
MachineBreaker 5302f15b9d Implement experimental 1.8 click window while inventory not open check 2024-11-16 12:50:09 -04:00
Axionize 6a3eec1960 Add optional success field to HitData used to indicate if raytrace hit intended target 2024-11-16 11:44:38 -05:00
Axionize 11425840ad Add getBlockPlaceCheck() method 2024-11-16 11:21:39 -05:00
Axionize 8515df8224 Early exit optimiztion 2024-11-16 11:08:47 -05:00
Axionize fe5d6e34f2 Initial work to eliminate final LOSP falses by tracking recently changed blocks; improve performance by using primitive array for SimpleCollisionBox 2024-11-16 10:56:37 -05:00
MachineBreaker e3e797e19a Woops fix compilation 2024-11-16 11:55:32 -04:00
MachineBreaker 2293092048 Make an inventory check type 2024-11-16 11:54:58 -04:00
MachineBreaker 147081ccc5 Clean 2024-11-16 11:09:47 -04:00
MachineBreaker b924f65f91 Implement held item change while inventory is open check
Also add verbose for the other inventory checks
2024-11-16 11:01:02 -04:00
MachineBreaker 259dd72f87 Use packets to close player inventory 2024-11-16 10:53:40 -04:00
MachineBreaker ab726bda78 Fix conflicts 2024-11-16 10:47:34 -04:00
MachineBreaker 163bbd7b0e Merge remote-tracking branch 'origin/2.0' into inventory-checks
# Conflicts:
#	src/main/java/ac/grim/grimac/manager/CheckManager.java
#	src/main/resources/config/zh.yml
2024-11-16 10:40:51 -04:00
Axionize 205e169754 Initial work to make Reach raytrace check also check for entities 2024-11-16 08:03:49 -05:00
Axionize 35f7914249 More robust hitData handling of new EntityHitData type in CheckManagerListener 2024-11-16 08:02:10 -05:00
Axionize 31b7fd462f Initial Entity Blocking Hit Checks 2024-11-16 06:55:52 -05:00
Axionize b9812ba2b6 Add better temporary logging to see if new HitData types are used in CheckManagerListener 2024-11-16 05:08:52 -05:00
Axionize fc1d5ff3ae Add new EntityHitData constructors 2024-11-16 01:33:56 -05:00
Axionize 2f983ad316 Refactor HitData in preperation for supporting EntityHitResults 2024-11-15 07:32:20 -05:00
Axionize db23910195 Document why we trace longer than player hit distance on reach ray trace 2024-11-15 06:23:03 -05:00
Axionize 968e166bde Fix Button hitboxes for pre-1.13 players 2024-11-15 03:13:01 -05:00
Axionize efe729c4d1 Add new Reach config option to skip checks against non-player-entities 2024-11-15 01:43:47 -05:00
Axionize d40d19d6e3 Bump packetevents back to 2.6.1 (custom) to fix bugs 2024-11-15 01:06:48 -05:00
Axionize b476b143f4 Spotless changes 2024-11-15 01:06:35 -05:00
Axionize bb54697d9c Make switch cases Java 8 compatible 2024-11-15 01:05:39 -05:00
Axionize 24102c15e6 Bump version number back to 2.3.69 2024-11-15 00:46:20 -05:00
Axionize 5100ef06c8 Build with Java 8 compatibility instead of Java 17 2024-11-15 00:44:54 -05:00
Axionize 9b892eab85 Revert "Java 17 update"
This reverts commit 5a6f87fe
2024-11-15 00:43:05 -05:00
Axionize eab5ca7f6d Merge remote-tracking branch 'origin/2.0' into merge
# Conflicts:
#	build.gradle.kts
#	src/main/java/ac/grim/grimac/checks/impl/scaffolding/RotationPlace.java
#	src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
#	src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java
#	src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxPane.java
#	src/main/java/ac/grim/grimac/utils/collisions/blocks/connecting/DynamicHitboxWall.java
2024-11-15 00:40:09 -05:00
Axionize fd055c163e Use new packetevents metrics class 2024-11-15 00:32:03 -05:00
Axionize ea78d2ff40 Update packetevents (built locally using custom changes) to fix #3 2024-11-15 00:22:52 -05:00
SamB440 6f074513f2 Merge pull request #1787 from Onako2/2.0
Update dependencies so it works on 1.21.3
2024-11-14 16:18:42 +00:00
ManInMyVan 0719c5bdc6 add PacketOrderO and PacketOrderP 2024-11-11 19:19:41 -07:00
ManInMyVan 36a394d142 add PacketOrderN 2024-11-11 19:19:41 -07:00
ManInMyVan 0e08dbc6f2 Add PacketOrderM 2024-11-11 19:19:41 -07:00
ManInMyVan 003aa67a41 remove unused method 2024-11-11 19:19:41 -07:00
ManInMyVan be45a43524 rename exempt-digging to exempt-placing-while-digging in PAcketOrderI
and make it work
2024-11-11 19:19:41 -07:00
ManInMyVan 0d700848f8 rename PacketOrderM to PacketOrderA 2024-11-11 19:19:41 -07:00
ManInMyVan 1ff402036d revert renaming post 2024-11-11 19:19:40 -07:00
ManInMyVan 9d36dbd2b8 add PacketOrderM 2024-11-11 19:19:40 -07:00
ManInMyVan c53c4378d8 use PacketOrderProcessor in PacketOrderK 2024-11-11 19:19:40 -07:00
ManInMyVan eacf176f88 rewrite 2024-11-11 19:19:40 -07:00
ManInMyVan 13afb067bb fix falses 2024-11-11 19:19:39 -07:00
ManInMyVan 7af2f4b2e2 don't cancel the tick 2024-11-11 19:19:39 -07:00
ManInMyVan a1d8bfa6a1 more PacketOrderC stuff 2024-11-11 19:19:39 -07:00
ManInMyVan 47b3fe9ca2 fixes 2024-11-11 19:19:39 -07:00
ManInMyVan 0ce52ea107 oops 2024-11-11 19:19:39 -07:00
ManInMyVan d98fe31412 register PacketOrderL 2024-11-11 19:19:39 -07:00
ManInMyVan d8f338aada fix falses 2024-11-11 19:19:39 -07:00
ManInMyVan f5965c48b3 exemptBreaking -> exempt-breaking 2024-11-11 19:19:39 -07:00
ManInMyVan 0df7077ddb Add PacketOrderK 2024-11-11 19:19:38 -07:00
ManInMyVan 222a9341bf exemptBreaking option in PacketOrdlerL 2024-11-11 19:19:38 -07:00
ManInMyVan 35f6f7870a make PacketOrderE setback
https://github.com/CCBlueX/LiquidBounce/blob/nextgen/src/main/kotlin/net/ccbluex/liquidbounce/features/module/modules/movement/noslow/modes/blocking/NoSlowBlockingSwitch.kt
2024-11-11 19:19:38 -07:00
ManInMyVan 15b6e0ba27 check ENTITY_ACTION packets in PacketOrderL 2024-11-11 19:19:38 -07:00
ManInMyVan 968754efe0 fix some PacketOrderF falses 2024-11-11 19:19:38 -07:00
ManInMyVan a03c9e0194 Add PacketOrderL 2024-11-11 19:19:38 -07:00
ManInMyVan 734e7cbae8 nvm it is valid on 1.8 2024-11-11 19:19:38 -07:00
ManInMyVan 52fe6691ac this packet order is only valid in 1.7 client 2024-11-11 19:19:38 -07:00
ManInMyVan acd8d1192c Check entity in PacketOrderC 2024-11-11 19:19:38 -07:00
ManInMyVan 8fc309cb76 these are already packet checks 2024-11-11 19:19:37 -07:00
ManInMyVan 45f16ec10f Check digging packets in PacketOrderF 2024-11-11 19:19:37 -07:00
ManInMyVan 5ff8cb21c8 Update PacketOrderI.java 2024-11-11 19:19:37 -07:00
ManInMyVan f8997b8739 Add PacketOrderJ 2024-11-11 19:19:37 -07:00
ManInMyVan ed21464c3a Add PacketOrderI 2024-11-11 19:19:37 -07:00
ManInMyVan 7954575216 Add PacketOrderH 2024-11-11 19:19:37 -07:00
ManInMyVan 1a11d3e733 Add PacketOrderG 2024-11-11 19:19:37 -07:00
ManInMyVan 487aa45a27 add PacketOrderF 2024-11-11 19:19:37 -07:00
ManInMyVan b7f9aeab06 add PacketOrderE 2024-11-11 19:19:36 -07:00
ManInMyVan 6aaee382a6 PacketOrder check catagory 2024-11-11 19:19:30 -07:00
Onako2 8c84c506bf Update dependencies for 1.21.3 support 2024-11-11 22:03:35 +01:00
Axionize 0622f92cf1 Revert "Remove unncessary NO_COLLISION entry for torchcrop"
This reverts commit e149ca6be8.
2024-11-03 18:14:12 -05:00
Axionize a8f81c141a Revert "Remove unncessary NO_COLLISION entries"
This reverts commit 1761d853de.
2024-11-03 18:14:11 -05:00
Axionize efffceb9f2 Fix scaffolding hitbox for pre-1.14 clients 2024-11-03 07:05:40 -05:00
Axionize 75d1fc32c8 Enable checks against scaffolding 2024-11-03 06:58:37 -05:00
Axionize e087e93e2a Fix Weeping Vines and Vine Plant for all versions; Fix Weeping + Twisted for pre 1.16 players 2024-11-03 06:34:04 -05:00
Axionize e83c9967b4 Fix pitcher crop for pre-1.20 players 2024-11-03 05:51:34 -05:00
Axionize 2b1896020d Fix sniffer egg for pre 1.20 players 2024-11-03 05:46:06 -05:00
Axionize 61b17907ee Fix frogspawn for pre-1.19 players 2024-11-03 05:45:50 -05:00
Axionize 339fb42f37 Fix Sculk Shrieker hit box for all versions and collision box for pre 1.18.2 2024-11-03 05:33:50 -05:00
Axionize 7985275697 Fix Spore Blossom hitbox on < 1.17 2024-11-03 05:18:42 -05:00
Axionize 661b60d07c Fix glow lichen and sculk vein boxes 2024-11-03 05:15:31 -05:00
Axionize d4f647e18b Fix Cauldron Hit/Collision Box 2024-11-03 03:51:39 -05:00
Axionize 1761d853de Remove unncessary NO_COLLISION entries 2024-11-03 02:59:10 -05:00
Axionize 42a6543f9b Fix Pink Petals Boxes 2024-11-03 02:51:23 -05:00
Axionize 9356c6c323 Add new union() function to collision boxes 2024-11-03 02:41:27 -05:00
Axionize a7a92f7e10 Fix Coral Fan Collision box 2024-11-03 01:44:04 -04:00
Axionize e149ca6be8 Remove unncessary NO_COLLISION entry for torchcrop 2024-11-03 01:17:36 -04:00
Axionize d44493743d Cleanup and documnet why 2nd rayTrace in getNearestReachHitResult is intentionally non-optimal 2024-11-03 00:48:51 -04:00
Axionize 7eb030de7d Remove unsued getFacing() from vector code 2024-11-02 22:34:03 -04:00
Axionize 8fd4a4a87d Fix falses on blocks with 'insides/internal walls' (different Raycast block placement shape then HitBox shape) like Cauldrons, Hoppers, and Composters 2024-11-02 22:33:08 -04:00
Axionize 8f71a427fd Annotate LOSP functions 2024-11-02 04:36:56 -04:00
Axionize 8b9bc356f2 Merge remote-tracking branch 'origin/2.0' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/scaffolding/RotationPlace.java
#	src/main/java/ac/grim/grimac/player/GrimPlayer.java
2024-11-01 21:31:23 -04:00
Axionize 89b6c8306e Fix falses on dead corals 2024-11-01 21:25:08 -04:00
Axionize 32a09aa36b Merge remote-tracking branch 'origin/2.0' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/player/GrimPlayer.java
2024-10-27 04:31:43 -04:00
Axionize 3ea716c580 Merge remote-tracking branch 'origin/2.0' into merge 2024-10-20 03:01:42 -04:00
Axionize 328d347845 Merge remote-tracking branch 'origin/2.0' into merge 2024-10-14 13:05:26 -04:00
Axionize d394c3d67c Revert Java 17 changes 2024-10-10 23:59:36 -04:00
Axionize 17b6b8a4e7 Merge branch 'los-containers' into merge 2024-10-10 23:54:56 -04:00
Axionize 980226fab9 Update LOSP to work with new grim config 2024-10-10 23:54:19 -04:00
Axionize 0f726a0f34 Merge remote-tracking branch 'origin/2.0' into los-containers 2024-10-10 23:53:39 -04:00
Axionize 91ee057f4a Merge remote-tracking branch 'origin/2.0' into merge
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/combat/Reach.java
2024-10-10 23:38:40 -04:00
Axionize c26afbc0af Merge branch 'GrimAnticheat:2.0' into merge 2024-10-08 00:08:05 -04:00
Axionize be56e28009 Merge branch 'fix-attribute-clamp' into merge 2024-10-05 17:35:57 -04:00
Axionize 0697c425ca Document SimpleCollisionBox and HexCollisionBox with Javadoc 2024-10-03 03:40:32 -04:00
Axionize ca0ca471fb Document SimpleCollisionBox and HexCollisionBox with Javadoc 2024-10-03 03:38:58 -04:00
Axionize 7b2aac3874 Version Bump 2024-10-03 02:25:59 -04:00
Axionize fbe8376ca0 Remove experimental check flag from Reach 2024-10-03 02:15:33 -04:00
Axionize 22bc18859b Modernize reach check 2024-10-03 01:29:18 -04:00
Axionize 25f9608d58 Merge branch 'reach-wall-hit' into LOSP-reach-wall-check
# Conflicts:
#	src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
#	src/main/java/ac/grim/grimac/utils/nmsutil/BlockRayTrace.java
2024-10-03 01:26:45 -04:00
Axionize 428f213e15 Migrate reach-related functions to new BlockRayTrace util class 2024-10-03 01:23:39 -04:00
AxionizeandManInMyVan 593d48a6e6 Button Styling Change
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:15 -04:00
AxionizeandManInMyVan 3dcf3c931a Sapling Styling Change
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:15 -04:00
AxionizeandManInMyVan 8cc45ddba3 TALL_FLOWER Styling Change
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:14 -04:00
AxionizeandManInMyVan 6f23122657 Redstone Wire Comment Styling
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:14 -04:00
AxionizeandManInMyVan c0b0759ed0 Inline Hitbox Calculation
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:14 -04:00
AxionizeandManInMyVan 00252f3b97 getPropaguleMinHeight Spacing
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:13 -04:00
AxionizeandManInMyVan 531c49011b Small Flower Line Spacing/Styling
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:13 -04:00
AxionizeandManInMyVan dea22454f7 Coral Fan Line Spacing/Styling
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:13 -04:00
AxionizeandManInMyVan 12bda63785 Banner Line Spacing/Styling
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:12 -04:00
AxionizeandManInMyVan c65e17cf0c Simplify TALL_FLOWERS handling
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:12 -04:00
AxionizeandManInMyVan 753ca0e6ad Rails Styling
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:12 -04:00
AxionizeandManInMyVan 8b85e1711d Mark function as Deprecated
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-10-03 00:10:12 -04:00
Axionize 12b0dfd19d Fix spelling mistake 2024-10-03 00:07:51 -04:00
Axionize 8c05d41423 Replace RuntimeException in HitBox.java with IllegalStateException 2024-10-03 00:07:26 -04:00
Axionize c5ab0f5440 Merge remote-tracking branch 'origin/2.0' into los-containers
# Conflicts:
#	src/main/java/ac/grim/grimac/utils/collisions/CollisionData.java
2024-10-02 21:01:12 -04:00
ManInMyVan d92f5ef375 fix chains for pre-1.16 players 2024-10-02 21:00:18 -04:00
Axionize c313d6203a Compact all NO_COLLISION states together 2024-10-02 20:51:10 -04:00
Axionize 070f92aea2 Fix 1.11 Ascending rails hitboxes 2024-09-28 01:53:38 -04:00
Axionize 4e3c5894b5 Fix HitBox of ascending powered rail on 1.9 2024-09-28 01:37:43 -04:00
Axionize 8cfb9f0f17 Fix HitBox of ascending powered rails on 1.7.10 2024-09-28 01:14:49 -04:00
Axionize 4e135e3f92 Make result player.getPossibleEyeHeights() of final in checks and remove unused imports 2024-09-28 00:21:33 -04:00
Axionize 938522974b Replace RotationPlace with LOSP in Turkish config 2024-09-26 21:23:08 -04:00
Axionize 6994975387 Merge remote-tracking branch 'origin/2.0' into los-containers
# Conflicts:
#	src/main/java/ac/grim/grimac/checks/impl/scaffolding/RotationPlace.java
2024-09-26 21:20:07 -04:00
Axionize 6d3a172466 Removing unneeded special case handling 2024-09-26 17:12:07 -04:00
Axionize 3aaa185617 Readability/documentation improvements 2024-09-25 00:51:50 -04:00
Axionize 980cd92333 1.8 Players 2024-09-25 00:28:59 -04:00
Axionize 89da2942c7 Handle player joining on new version -> scale changing -> old version 2024-09-25 00:01:52 -04:00
Axionize 8ea905e053 Optimize returned array for crawling 2024-09-25 00:01:09 -04:00
Axionize 885e959cdb fix conditionall check 2024-09-24 23:22:22 -04:00
Axionize 02904a3dce Only rewrite player possibleEyeHeights when player scale changes 2024-09-24 23:03:10 -04:00
Axionize e8d4bb2376 Don't bother updating scale attribute if no change is made 2024-09-23 21:16:24 -04:00
Axionize 7695167578 Fix intializing array 2024-09-23 20:34:50 -04:00
Axionize 94e5f63a65 Simplify logic and handle caching even when scale changes 2024-09-23 20:19:05 -04:00
Axionize 9fa0f773d5 Cache eyeHeights where possible 2024-09-22 17:41:54 -04:00
Axionize 88111e6f7e make getPossibleEyeHeights return most likely heights 2024-09-22 17:17:25 -04:00
Axionize 9a5c16fe6a Merge branch '2.0' into los-containers 2024-09-21 23:04:16 -04:00
Axionize 4efaf8d497 Fix Array matching error and block
The lower level ArraySupport.mismatch() function doesn't work on Java 8 and requires access modification in modern Java. Repalced with Arrays.equals()

The removal of checking if hitdata.getSecond() == expectedBlockFace during iteration (added in Fix 1.8 Brewing Stand bug - 4a9d8627d3) eliminates cases where a block inbetween the target block has a different blockface intercept.

Ideally we should only check the blockface once we've reached the target block as future optimization.
2024-09-21 22:46:48 -04:00
Axionize 07881da451 More minor optimizations 2024-09-21 21:40:40 -04:00
Axionize bd6c2524e7 Optimize iteration order 2024-09-21 20:19:19 -04:00
Axionize b096e02b9b Optimize getPossibleEyeHeights() 2024-09-21 20:18:55 -04:00
Axionize ad6b24345b Minor Dynamic Fence cleanup 2024-09-20 03:43:41 -04:00
Axionize 9694b756b5 Inline lever hitboxes 2024-09-20 03:35:47 -04:00
Axionize 6b5786be9d Fix legacy hitboxes for versions up to 1.12.2 and make fence hitbox generation static 2024-09-20 03:29:00 -04:00
AxionizeandCyramek 1f49ab2551 Update src/main/java/ac/grim/grimac/player/GrimPlayer.java
Co-authored-by: Cyramek <xcyramek@gmail.com>
2024-09-20 03:21:28 -04:00
Axionize b18a5bec8e Fix fences on legacy servers 2024-09-20 03:20:01 -04:00
Axionize d741459e2f Fix levers and buttons for < 1.13 2024-09-17 23:01:42 -04:00
Axionize 7007722aca Fix cactuses for pre-1.13 2024-09-17 22:48:53 -04:00
Axionize 05e7b3c1e5 Exit conditions early and remove unnccessary if statement 2024-09-17 22:27:43 -04:00
Axionize 13554546eb Deobfuscate and document purpose of misunderstood code in traverseBlocks() 2024-09-17 19:38:38 -04:00
Axionize e2f3722b52 Minor cleanup 2024-09-17 19:21:40 -04:00
AxionizeandManInMyVan 1b75734046 Update src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-09-16 21:55:53 -04:00
Axionize 61d9609328 More minor optimizations 2024-09-16 01:55:13 -04:00
Axionize 4cff51c89f More minor optimizations 2024-09-16 01:32:27 -04:00
Axionize ace5178e99 Minor optimizations 2024-09-16 01:10:44 -04:00
Axionize 4a9d8627d3 Fix 1.8 Brewing Stand bug 2024-09-16 00:26:25 -04:00
Axionize fc89b932dd Cleanup exit conditions 2024-09-15 22:38:42 -04:00
Axionize 0852ac8326 Fix ascending rails on 1.8.9 2024-09-15 22:23:15 -04:00
Axionize 87194d7f1b Fix legacy walls 2024-09-15 22:19:07 -04:00
Axionize 31fa689a98 Fix modern walls 2024-09-15 22:12:40 -04:00
Axionize 5d366e742c Fix rails 2024-09-15 18:44:07 -04:00
Axionize 7cc3c8f5ef Fix blockface false flags 2024-09-15 17:58:14 -04:00
Axionize 7215dfcf60 Add scoring system for most likely blockface 2024-09-15 17:49:15 -04:00
Axionize 5c709c1c54 Check 0.03/0.002 and non-expanded hitbox (for blockfaces) 2024-09-15 17:20:55 -04:00
Axionize 1e5ad65c9f Fix null exception 2024-09-15 14:06:48 -04:00
Axionize f6aeffb264 Quick and dirty button patch 2024-09-15 04:33:14 -04:00
Axionize 4593f3077c Quick and dirty lever fix 2024-09-15 04:29:17 -04:00
Axionize b92c8726de End portals 2024-09-15 04:16:11 -04:00
Axionize c560539a16 Brewing stands (excluding 1.8-1.8.9) 2024-09-15 04:02:53 -04:00
Axionize 9cba7a95f7 Fix cactus 2024-09-15 03:54:00 -04:00
Axionize d6d86ef04d Fix rails 2024-09-15 03:38:03 -04:00
Axionize ed643f3481 legacy pane hitbox faces, still falses because different face? 2024-09-15 03:23:04 -04:00
Axionize d8c2f77a0b Pane fix outline 2024-09-15 02:23:41 -04:00
Axionize 6cfda647f7 Fix flower and short grass offsets for older versions 2024-09-15 01:43:07 -04:00
Axionize fc58fcc721 Fix Wall Banners and Banner Simulation falses 2024-09-15 00:31:30 -04:00
Axionize 5f0707956a Also check blockfaces 2024-09-14 21:37:21 -04:00
Axionize 528712e931 Fix Wall Banners and Banner Simulation falses 2024-09-14 21:13:03 -04:00
Axionize 8fe609452b Bypass check when player near moving shulkers, pistons 2024-09-14 18:52:20 -04:00
Axionize 3afd2c4ac9 Skip post on pre 2024-09-14 18:27:51 -04:00
Axionize 5793d7b678 Merge branch '2.0' into los-containers 2024-09-14 05:13:00 -04:00
Axionize 569a8b4c4d 'Fix' 0.03 for 1.8-1.18.1 2024-09-14 05:11:17 -04:00
Axionize 9cab8f7469 Fix flower offset being visual in 1.8 + bamboo sim 2024-09-09 01:42:07 -04:00
Axionize 1ac0b2efbe Fix Bamboo HitBox & Collision Box 2024-09-08 23:19:34 -04:00
Axionize b78a36f1c2 accidentally added bamboo to No Collision 2024-09-08 22:58:35 -04:00
Axionize e23d191cb8 Merge branch '2.0' into los-containers 2024-09-08 22:50:26 -04:00
Axionize 8854b00b46 Support for buttons in 1.7 2024-09-05 21:03:12 -04:00
Axionize 4be835de07 Skip redstone wires 2024-09-05 20:38:05 -04:00
Axionize b8f59fa99c Fix Pointed Dripstone 2024-09-02 14:40:28 -04:00
Axionize 2236efea4f Fix Small Dripleaf 2024-09-02 14:34:17 -04:00
Axionize 344ba4138d Fix Hanging Roots hit/collision box 2024-09-02 14:23:31 -04:00
Axionize ba0fa7a869 Refactor Bamboo to use OffsetCollisionBox; Fix Bamboo Sapling Hit & Collision Box 2024-09-02 14:16:47 -04:00
Axionize 21668a63fd Fix Tall Grass & Large Ferns 2024-09-02 14:10:45 -04:00
Axionize 2f6f9bcbc5 Fix Tall Seagrass hitbox 2024-09-02 03:25:02 -04:00
Axionize 86d19de452 Reorder HitboxData - Groups Before Individual StateTypes so individual statetypes can override group settings (mangrove and saplings) 2024-09-02 03:18:44 -04:00
Axionize d4986449f1 Fix Mangrove Propagule, add HexOffsetCollisionBox 2024-09-02 03:09:38 -04:00
Axionize 3fc366bf1a Fix Tall Flower Hit and Collision boxes 2024-09-02 02:00:32 -04:00
Axionize 9d192b215e Add OffsetCollisionBox; Document all OffSetBlocks and quirks 2024-09-02 01:54:03 -04:00
AxionizeandCyramek b4ea4517e9 Update src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java
Co-authored-by: Cyramek <xcyramek@gmail.com>
2024-09-01 23:25:07 -04:00
AxionizeandManInMyVan 07ad12a16f Update src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java
Whitespace

Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-09-01 22:46:16 -04:00
Axionize f7529a18df Remove Fence Hack; Fix Lever South Wall Hitbox; Initial Work for Flower Hitbox 2024-09-01 22:34:11 -04:00
Axionize c66522cb47 Move Blocks with NoCollision but a Outline/Hitbox into HitboxData 2024-09-01 21:36:34 -04:00
Axionize 94a31f77ff Fix Sweet Berry Collision + HitBox 2024-09-01 19:57:51 -04:00
Axionize c0630f9f6d Crop Collision Box Overhaul
Add Crop Hitboxes
- NetherWart
- Carrot
- Wheat
- Beetroot
- Potatoes
- COCOA

Replace CollisionBoxes with NoCollisionBox
- NetherWart
- Carrot
- Wheat
- Beatroot
- Pumpkin Stem
- Melon Stem

Added new CollisionBox and set to NoCollisionBox for
- Potatoes
2024-08-31 21:05:24 -04:00
Axionize 3a145cb615 Fix banners 2024-08-31 20:03:34 -04:00
Axionize 837516ea86 Fix syntax error 2024-08-31 14:57:07 -04:00
Axionize 66228f59be Add lever hitboxes and fix banner hitboxes 2024-08-31 14:55:33 -04:00
Axionize 800c79a898 Document Hex vs Simple CollisionBox purpose 2024-08-31 14:55:16 -04:00
Axionize 2177b12bcf Print out target block when flagged - help find falses from constant flagging on non-standard blocks 2024-08-30 14:44:22 -04:00
Axionize 050c22ce27 Clean up 2024-08-29 17:02:29 -04:00
Axionize ded614f30f MVP commit 2024-08-29 17:02:28 -04:00
Axionize 88e439ebfd Improve temporary fix - delete unncessary code 2024-08-29 02:55:40 -04:00
AxionizeandManInMyVan a027355c7d Update src/main/java/ac/grim/grimac/events/packets/CheckManagerListener.java
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-08-29 02:53:48 -04:00
AxionizeandManInMyVan 8a351ec928 Update src/main/java/ac/grim/grimac/utils/collisions/datatypes/ComplexCollisionBox.java
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-08-29 02:52:53 -04:00
AxionizeandManInMyVan b2fa4974ef Update src/main/java/ac/grim/grimac/utils/collisions/HitboxData.java
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2024-08-29 02:52:29 -04:00
Axionize 9c2a034b43 Temporary Hacky Fix to demonstrate cause of fence false flag 2024-08-29 02:35:29 -04:00
Axionize 45ba746300 Comment cleanup 2024-08-26 01:22:07 -04:00
Axionize 483f317f83 Remove unneeded entry in punishments.yml 2024-08-26 01:16:26 -04:00
Axionize dee3268bce Make variables private 2024-08-26 01:14:30 -04:00
Axionize 2a88d3eef4 Account for player being inside of target block 2024-08-26 00:39:00 -04:00
Axionize 2898fed15a 1.9+ tick behind and 1.7 ticking behaviour compensation 2024-08-26 00:20:40 -04:00
Axionize d2721077c9 Remove print statements and cleanup comments 2024-08-26 00:13:54 -04:00
Axionize dd7bb81b46 Rework whitelist to use HashSet 2024-08-26 00:13:04 -04:00
Axionize 4515d21023 Seperate LOS-block-place checks from Sam's LOS reach checks 2024-08-26 00:01:14 -04:00
Axionize 3315e3c148 Revert "Merge reach wall hit check"
This reverts commit b5990080
2024-08-25 23:58:36 -04:00
Axionize 2b552680a7 Fix styling 2024-08-25 13:44:26 -04:00
Axionize f78c80f04d Temporarily comment out system.out.println 2024-08-25 03:18:17 -04:00
Axionize bc239a7994 Fix block whitelist 2024-08-25 03:15:00 -04:00
Axionize a508ec2279 0.03/0.0002 changes, cleanup code, add comments 2024-08-24 23:15:46 -04:00
Axionize cccecbacbc Remove RotationPlace, replacec with LineOfSightPlace 2024-08-24 23:09:06 -04:00
Axionize 177a8b0527 Add config options for check and enable it by adding to punishments 2024-08-24 23:08:41 -04:00
Axionize d869ff959f Add config options for check and enable it by adding to punishments 2024-08-24 23:05:04 -04:00
Axionize 772ba562e6 Rename check 2024-08-24 23:04:50 -04:00
Axionize 1786360d7c Clean up Code and add code for blockTypeWhitelist to BlockLOS checks for performance. 2024-08-24 22:24:23 -04:00
Axionize 328596f01f Expand hitbox of target block by 0.03/0.0002 to account for known MC bug 2024-08-24 19:18:43 -04:00
Axionize 6a13c9f822 Expand hitbox of target block by 0.03/0.0002 to account for known MC bug 2024-08-24 19:18:41 -04:00
Axionize 3c78a63719 Workable check 2024-08-24 19:18:41 -04:00
Axionize 8b645b75df Stash commits - loop alternate possible scenarios 2024-08-24 19:18:41 -04:00
Axionize ae3ea30c92 Stash commits - compensated everything 2024-08-24 19:18:40 -04:00
Axionize 01bd2c0c11 Stash commits - compensated world 2024-08-24 19:18:40 -04:00
Axionize e91721299a Container LOS initial commit 2024-08-24 19:18:39 -04:00
Axionize 4e08ec9fca Deobfuscate and document purpose of misunderstood code in traverseBlocks() 2024-08-24 19:18:39 -04:00
Axionize b599008040 Merge reach wall hit check
(cherry picked from commit 335c33b109)
2024-08-24 19:18:39 -04:00
SamB440 831f68b00c Check for hitting through walls 2024-06-29 18:11:05 +01:00
MachineBreaker bccda6cb9e Merge branch 'GrimAnticheat:2.0' into inventory-checks 2023-11-04 00:17:56 -04:00
MachineBreaker d0e77d2959 InventoryD: Exempt last block place use item if < 50L 2023-11-03 09:06:48 -04:00
MachineBreaker 441ff72e1e Merge branch 'GrimAnticheat:2.0' into inventory-checks 2023-11-03 09:05:45 -04:00
MachineBreaker aff131394e Don't handle InventoryD predictions if slowed down by a item. 2023-10-17 04:25:06 -04:00
MachineBreaker 7a6f758853 Merge branch 'GrimAnticheat:2.0' into inventory-checks 2023-10-17 04:24:24 -04:00
MachineBreaker eef8f538bc Merge branch 'GrimAnticheat:2.0' into inventory-checks 2023-09-25 19:55:46 -04:00
MachineBreaker 42d79ea01f Exempt teleports for InventoryD
Fixes a false positive
2023-09-18 17:42:08 -04:00
MachineBreaker df2c92555f Update fr.yml 2023-09-18 17:40:42 -04:00
MachineBreaker 380f6b5581 Update fr.yml 2023-09-18 17:40:12 -04:00
MachineBreaker fb6450fb72 Merge branch '2.0' into inventory-checks 2023-09-18 17:38:59 -04:00
Alejandro Martinez bb01c25605 Close inventory synchronously 2023-05-25 19:32:55 -04:00
Alejandro Martinez d812e7dd8b Don't setback for inventory checks 2023-05-21 13:20:28 -04:00
Alejandro Martinez 60f3a765f3 Fix section typo 2023-05-21 11:26:10 -04:00
Alejandro Martinez 31d6bd3664 Bump config version & add missing config upgrade 2023-05-21 11:24:49 -04:00
MachineBreaker 4c0018b04c Merge branch 'GrimAnticheat:2.0' into inventory-checks 2023-05-21 10:49:06 -04:00
MachineBreaker 4b0b3df9d2 Merge pull request #2 from UserNugget/inventory-checks-hotfix
Make transaction id "NONE" really impossible
2023-04-05 06:05:47 -06:00
UserNugget f699be1a65 Make transaction id "NONE" really impossible 2023-04-05 14:39:43 +03:00
MachineBreaker b6496b31f0 Merge pull request #1 from UserNugget/inventory-checks
InventoryWalk check
2023-04-05 05:17:56 -06:00
UserNugget 1e601c3de9 Remove pointless optimization 2023-04-05 10:57:39 +03:00
MachineBreaker 00b39fec38 Merge branch 'GrimAnticheat:2.0' into inventory-checks 2023-04-04 20:50:49 -06:00
UserNugget 9224ab8a76 Correct some comments 2023-04-05 05:03:29 +03:00
UserNugget 5307aebbf5 Some small fixes 2023-04-04 23:00:34 +03:00
UserNugget e7d8d613aa Most likely fixed false flags 2023-04-04 22:56:22 +03:00
UserNugget f469b08505 Close inventory to prevent infinity setbacks 2023-04-04 22:34:48 +03:00
UserNugget 60b2a07659 Initial InventoryD rewrite 2023-04-04 15:28:46 +03:00
MachineBreaker 8d6d448073 Merge branch 'GrimAnticheat:2.0' into inventory-checks 2023-04-02 17:17:22 -06:00
Alejandro Martinez 798156fedc Merge branch 'inventory-checks' of https://github.com/MachineBreaker/Grim into inventory-checks
 Conflicts:
	src/main/java/ac/grim/grimac/utils/latency/CompensatedInventory.java
2023-03-19 08:23:30 -06:00
MachineBreaker e18510fc6b Merge branch 'GrimAnticheat:2.0' into inventory-checks 2023-03-19 08:23:09 -06:00
Alejandro Martinez 0fe96bf32d Implement InventoryD (Clicking inventory while moving) 2023-03-19 08:22:04 -06:00
noobi 6d1f491b80 Fix InventoryC missing setback vls 2023-03-19 00:27:49 +01:00
noobi 07ac8b99f0 Implement InventoryC (Placing while inventory is open) 2023-03-19 00:16:05 +01:00
Alejandro Martinez 622c35e935 Implement InventoryB (Digging while inventory is open) 2023-03-18 17:03:00 -06:00
Alejandro Martinez c6adad5992 Make code more readable 2023-03-18 16:24:23 -06:00
Alejandro Martinez 211722a8a7 Properly exempt beacon inventory 2023-03-18 16:22:51 -06:00
Alejandro Martinez a0082a4ce7 Merge remote-tracking branch 'origin/inventory-checks' into inventory-checks 2023-03-18 16:17:42 -06:00
Alejandro Martinez a4eb540d23 Implement InventoryA (Attack while inventory is open) 2023-03-18 16:16:51 -06:00
MachineBreaker 2d427d6c47 Merge branch 'GrimAnticheat:2.0' into inventory-checks 2023-03-18 14:19:25 -06:00
Alejandro Martinez 0d00168aaf Initial work of Inventory Checks 2023-03-17 04:25:35 -06:00
826 changed files with 17103 additions and 29812 deletions

No files matched your search

-2
View File
@@ -7,8 +7,6 @@ indent_style = space
insert_final_newline = true
max_line_length = 100
tab_width = 4
end_of_line = crlf
trim_trailing_whitespace = true
# intellij specific configuration
ij_continuation_indent_size = 8
+2 -10
View File
@@ -30,19 +30,11 @@ body:
validations:
required: true
- type: input
attributes:
label: Client version
description: |
Provide the version of your Minecraft client.
validations:
required: true
- type: textarea
attributes:
label: Plugins
description: |
List all plugins or mods running on your server. To list plugins on bukkit, run `/plugins`.
List all plugins running on your server. To list plugins, run `/plugins`.
If your server is behind a proxy such as Bungeecord, you should list the proxy's plugins as well.
validations:
required: true
required: true
-1
View File
@@ -1 +0,0 @@
blank_issues_enabled: false
+3 -15
View File
@@ -39,23 +39,11 @@ body:
validations:
required: true
- type: dropdown
id: type
attributes:
label: Affected Platform(s)
description: Which platforms does this issue affect? If you aren't sure, select both.
options:
- "Bukkit"
- "Fabric"
multiple: true
validations:
required: true
- type: textarea
attributes:
label: Plugins/mods
label: Plugins
description: |
List all plugins or mods running on your server. To list plugins on bukkit, run `/plugins`.
List all plugins running on your server. To list plugins, run `/plugins`.
If your server is behind a proxy such as Bungeecord, you should list the proxy's plugins as well.
validations:
required: true
required: true
+2 -2
View File
@@ -46,7 +46,7 @@ body:
attributes:
label: Plugins
description: |
List all plugins or mods running on your server. To list plugins on bukkit, run `/plugins`.
List all plugins running on your server. To list plugins, run `/plugins`.
If your server is behind a proxy such as Bungeecord, you should list the proxy's plugins as well.
validations:
required: true
required: true
+4 -16
View File
@@ -1,5 +1,5 @@
name: Plugin/mod incompatibility or other bug
description: Report a bug or plugin/mod incompatibility here
name: Plugin incompatibility or other bug
description: Report a bug or plugin incompatibility here
labels: ["bug"]
body:
- type: textarea
@@ -30,23 +30,11 @@ body:
validations:
required: true
- type: dropdown
id: type
attributes:
label: Affected Platform(s)
description: Which platforms does this issue affect? If you aren't sure, select both.
options:
- "Bukkit"
- "Fabric"
multiple: true
validations:
required: true
- type: textarea
attributes:
label: Plugins
description: |
List all plugins or mods running on your server. To list plugins on bukkit, run `/plugins`.
List all plugins running on your server. To list plugins, run `/plugins`.
If your server is behind a proxy such as Bungeecord, you should list the proxy's plugins as well.
validations:
required: true
required: true
@@ -45,7 +45,7 @@ body:
attributes:
label: Plugins
description: |
List all plugins or mods running on your server. To list plugins on bukkit, run `/plugins`.
List all plugins running on your server. To list plugins, run `/plugins`.
If your server is behind a proxy such as Bungeecord, you should list the proxy's plugins as well.
validations:
required: true
required: true
-229
View File
@@ -1,229 +0,0 @@
name: Reusable Build and Publish
on:
workflow_call:
inputs:
is-release-build:
description: 'True if this is a release build, which affects versioning and publishing.'
required: true
type: boolean
release-version-type:
description: 'The version type for Modrinth (e.g., release, beta, alpha).'
required: true
type: string
release-changelog:
description: 'The changelog content for the release.'
required: false
type: string
default: ''
run-build-scan:
description: 'Whether to enable Develocity build scan'
required: true
type: boolean
publish-artifacts:
description: 'If true, uploads artifacts to Modrinth and other distribution sites.'
required: true
type: boolean
secrets:
MODRINTH_ID:
required: false
MODRINTH_TOKEN:
required: false
BUILD_UPDATE_TOKEN:
required: true
BUILD_UPDATE_URL:
required: true
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
env:
MODRINTH_ID: ${{ secrets.MODRINTH_ID }}
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
GRIM_MAIN_BRANCH: ${{ github.event.repository.default_branch }}
BUILD_UPDATE_TOKEN: ${{ secrets.BUILD_UPDATE_TOKEN }}
steps:
- name: Checkout repository with full history
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 200
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
server-id: github
settings-path: ${{ github.workspace }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
cache-read-only: ${{ github.ref_name != github.event.repository.default_branch && github.ref_name != 'dev' }}
- name: Cache Gradle Loom Cache
uses: actions/cache@v4
with:
path: .gradle/loom-cache
key: loom-cache-${{ runner.os }}-${{ hashFiles('**/libs.versions.toml', 'fabric/**/build.gradle.kts') }}
restore-keys: |
loom-cache-${{ runner.os }}
- name: Set Git Environment Variables
run: |
echo "GRIM_GIT_REPO=${{ github.event.repository.name }}" >> $GITHUB_ENV
echo "GRIM_GIT_ORG=${{ github.repository_owner }}" >> $GITHUB_ENV
- name: Compute version and Build with Gradle
id: build_with_version
run: |
# If any command in a pipeline fails, treat the pipeline as failed.
set -o pipefail
BUILD_ARGS="build"
if [[ "${{ inputs.is-release-build }}" == "true" ]]; then
BUILD_ARGS="$BUILD_ARGS -Prelease=true"
fi
# Conditionally add the --scan flag
if [[ "${{ inputs.run-build-scan }}" == "true" ]]; then
BUILD_ARGS="$BUILD_ARGS --scan"
fi
echo "Running: ./gradlew printVersion $BUILD_ARGS"
# Use 'tee' to both display the output live and save it to a file for parsing
VERSION=$(./gradlew printVersion $BUILD_ARGS | tee build-output.log | grep '^VERSION=' | tail -n1 | cut -d'=' -f2)
echo "build_version=$VERSION" >> $GITHUB_OUTPUT
echo "BUILD_VERSION=$VERSION" >> $GITHUB_ENV
echo "Build version: $VERSION"
- name: Publish Build Scan URL
# Only run this step if a scan was requested
if: ${{ inputs.run-build-scan == true }}
run: |
# Search the log file for the build scan URL and extract it
SCAN_URL=$(grep -o 'https://gradle.com/s/[^ ]*' build-output.log | head -n 1 || true)
if [[ -n "$SCAN_URL" ]]; then
echo "Found build scan URL: $SCAN_URL"
# Post a highly visible link to the Job Summary page
echo "### Gradle Build Scan" >> $GITHUB_STEP_SUMMARY
echo "A public build scan has been published and is available for inspection." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "[**View Build Scan →**]($SCAN_URL)" >> $GITHUB_STEP_SUMMARY
else
echo "Could not find build scan URL in build-output.log" >> $GITHUB_STEP_SUMMARY
fi
- name: Upload Bukkit Artifact
uses: actions/upload-artifact@v4
with:
name: grimac-bukkit
path: ${{ github.workspace }}/bukkit/build/libs/grimac-bukkit-${{ env.BUILD_VERSION }}.jar
if-no-files-found: error
- name: Upload Fabric Artifact
uses: actions/upload-artifact@v4
with:
name: grimac-fabric
path: ${{ github.workspace }}/fabric/build/libs/grimac-fabric-${{ env.BUILD_VERSION }}.jar
if-no-files-found: error
#------------------------------------------------------------------
# Generate/Prepare Changelog
#------------------------------------------------------------------
- name: Generate Changelog with git-cliff (for Dev Builds)
if: ${{ !inputs.is-release-build }}
id: git-cliff
uses: orhun/git-cliff-action@v4
with:
config: cliff.toml
args: --verbose ${{ github.event.before }}..${{ github.event.after }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # git-cliff needs a token
- name: Prepare Final Changelog
id: changelog
# Add this 'env' block to safely load the changelogs as environment variables
env:
RELEASE_NOTES: ${{ inputs.release-changelog }}
DEV_NOTES: ${{ steps.git-cliff.outputs.content }}
run: |
NOTES=""
if [[ "${{ inputs.is-release-build }}" == "true" ]]; then
# Use the environment variable for the release changelog.
# The double quotes are critical to preserve newlines!
NOTES="$RELEASE_NOTES"
else
# Use the environment variable for the dev changelog.
NOTES="$DEV_NOTES"
fi
if [ -z "$NOTES" ]; then
NOTES="* No new code changes in this build."
fi
# This is the correct way to set a multi-line output variable in Actions
{
echo "notes<<EOF"
echo "$NOTES"
echo "EOF"
} >> "$GITHUB_OUTPUT"
#------------------------------------------------------------------
# Publish to Modrinth & API
#------------------------------------------------------------------
- name: Publish Bukkit to Modrinth
if: ${{ inputs.publish-artifacts == true && env.MODRINTH_ID != '' && env.MODRINTH_TOKEN != '' }}
uses: Kir-Antipov/mc-publish@v3.3
with:
modrinth-id: ${{ secrets.MODRINTH_ID }}
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
modrinth-featured: ${{ inputs.is-release-build }} # Only feature release builds
files: bukkit/build/libs/grimac-bukkit-${{ env.BUILD_VERSION }}.jar
name: Grim Anticheat (Bukkit) ${{ env.BUILD_VERSION }}
version: ${{ env.BUILD_VERSION }}
version-type: ${{ inputs.release-version-type }}
changelog: ${{ steps.changelog.outputs.notes }}
loaders: |
bukkit
spigot
paper
folia
purpur
game-versions: '>=1.7 <=1.21.8'
- name: Publish Fabric to Modrinth
if: ${{ inputs.publish-artifacts == true && env.MODRINTH_ID != '' && env.MODRINTH_TOKEN != '' }}
uses: Kir-Antipov/mc-publish@v3.3
with:
modrinth-id: ${{ secrets.MODRINTH_ID }}
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
modrinth-featured: ${{ inputs.is-release-build }} # Only feature release builds
files: fabric/build/libs/grimac-fabric-${{ env.BUILD_VERSION }}.jar
name: Grim Anticheat (Fabric) ${{ env.BUILD_VERSION }}
version: ${{ env.BUILD_VERSION }}
version-type: ${{ inputs.release-version-type }}
changelog: ${{ steps.changelog.outputs.notes }}
loaders: |
fabric
game-versions: '>=1.16.1 <=1.21.8'
dependencies: 'fabric-api'
- name: Publish to API
if: ${{ inputs.publish-artifacts == true && env.BUILD_UPDATE_TOKEN != '' }}
run: |
curl -X POST \
-H "Content-Type: application/json" \
-H "User-Agent: GrimACBuilder/v1" \
-H "Authorization: Bearer ${{ secrets.BUILD_UPDATE_TOKEN }}" \
-d '{"org": "${{ github.repository_owner }}", "repository": "${{ github.event.repository.name }}", "branch": "${{ github.ref_name }}", "version": "${{ env.BUILD_VERSION }}"}' \
"${{ secrets.BUILD_UPDATE_URL }}"
+8 -12
View File
@@ -12,9 +12,13 @@
name: "CodeQL"
on:
workflow_dispatch:
push:
branches: [ dev ]
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '30 15 * * 2'
jobs:
analyze:
@@ -28,14 +32,14 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'java-kotlin' ]
language: [ 'java' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
@@ -47,14 +51,6 @@ jobs:
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
+95 -40
View File
@@ -1,44 +1,99 @@
name: Gradle Package (Development)
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle
name: Gradle Package
on:
workflow_dispatch:
inputs:
run-build-scan:
description: 'Run with public build scan (adds --scan)'
required: true
type: boolean
default: false
publish-artifacts:
description: 'Upload to Modrinth & API? (Uncheck for a dry run)'
type: boolean
default: true
push:
branches:
- 'main'
- '2.0'
- 'dev'
- 'release'
- 'release/**'
paths:
- '.github/workflows/**'
- 'buildSrc/**'
- 'bukkit/**'
- 'common/**'
- 'fabric/**'
- '**.java'
- '**.kt'
- '**.kts'
- '**.toml'
[push, workflow_dispatch]
jobs:
call-build-workflow:
uses: ./.github/workflows/build-and-publish.yml
build:
runs-on: ubuntu-latest
permissions:
contents: write # Allows the workflow to create or update references (tags)
packages: write
actions: write
steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
is-release-build: false
release-version-type: alpha # Dev builds are always 'alpha'
run-build-scan: ${{ github.event.inputs.run-build-scan == 'true' }}
publish-artifacts: ${{ github.event.inputs.publish-artifacts != 'false' }}
secrets:
MODRINTH_ID: ${{ secrets.MODRINTH_ID }}
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
BUILD_UPDATE_TOKEN: ${{ secrets.BUILD_UPDATE_TOKEN }}
BUILD_UPDATE_URL: ${{ secrets.BUILD_UPDATE_URL }}
java-version: '21'
distribution: 'temurin'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: Extract Version from build.gradle.kts
id: extract-version
run: |
# Extract the version from build.gradle.kts using grep and sed
VERSION=$(grep "^version\s*=" build.gradle.kts | sed 's/version\s*=\s*"\(.*\)"/\1/')
echo "VERSION: $VERSION"
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Build Lite Jar with Gradle
uses: gradle/actions/setup-gradle@v3
with:
arguments: build -PshadePE=false
- name: Upload Lite Artifact
uses: actions/upload-artifact@v4
with:
name: grimac-lite
path: ${{ github.workspace }}/build/libs/grimac-${{ env.VERSION }}-lite.jar
- name: Build Main Jar with Gradle
uses: gradle/actions/setup-gradle@v3
with:
arguments: build
- name: Upload Main Artifact
uses: actions/upload-artifact@v4
with:
name: grimac-main
path: ${{ github.workspace }}/build/libs/grimac-${{ env.VERSION }}.jar
- name: Generate build number
if: contains(fromJSON('["merge", "release", "main"]'), github.ref_name)
id: buildnumber
uses: onyxmueller/build-tag-number@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to Modrinth
if: contains(fromJSON('["merge", "release", "main"]'), github.ref_name)
uses: Kir-Antipov/mc-publish@v3.3
with:
modrinth-id: ${{ vars.MODRINTH_ID }}
modrinth-featured: true
modrinth-unfeature-mode: subset
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
files: |
${{ github.workspace }}/build/libs/grimac-${{ env.VERSION }}.jar
${{ github.workspace }}/build/libs/grimac-${{ env.VERSION }}-lite.jar
name: Lightning Grim Anticheat ${{ env.VERSION }}-b${{ steps.buildnumber.outputs.build_number }}
version: ${{ env.VERSION }}-b${{ steps.buildnumber.outputs.build_number }}
version-type: release
loaders: |
bukkit
spigot
paper
folia
purpur
game-versions: |
>=1.7
retry-attempts: 2
retry-delay: 10000
fail-mode: fail
-21
View File
@@ -1,21 +0,0 @@
name: Publish Release
on:
release:
types: [published]
jobs:
call-release-workflow:
uses: ./.github/workflows/build-and-publish.yml
with:
is-release-build: true
release-version-type: release # Official releases are 'release'
# Use the body of the GitHub Release as the changelog
release-changelog: ${{ github.event.release.body }}
run-build-scan: false
publish-artifacts: true
secrets:
MODRINTH_ID: ${{ secrets.MODRINTH_ID }}
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
BUILD_UPDATE_TOKEN: ${{ secrets.BUILD_UPDATE_TOKEN }}
BUILD_UPDATE_URL: ${{ secrets.BUILD_UPDATE_URL }}
+1 -8
View File
@@ -19,7 +19,6 @@ build/
.gradletasknamecache
gradle-app.setting
!gradle-wrapper.jar
buildSrc/.kotlin
##############################
## IntelliJ
@@ -66,10 +65,4 @@ nb-configuration.xml
##############################
## OS X
##############################
.DS_Store
##############################
## Fabric
##############################
run/
fabric/run/
.DS_Store
-40
View File
@@ -1,40 +0,0 @@
# Contributing to GrimAC
Thank you for your interest in contributing to GrimAC. This document outlines the guidelines for
making pull
requests to the project. *We're usually pretty lenient with pull requests, but this guide will help
make the process go more smoothly.*
### Pull Request Guidelines
- **Compatibility**
- Any changes must be compatible with
the [supported environments](https://github.com/GrimAnticheat/Grim/wiki/Supported-environments) (Spigot, Paper, Folia, Fabric, etc.)
- The plugin must be compatible with minecraft versions 1.8 and higher. Exempting checks from specific versions is acceptable.
- The plugin must be able to run on Java 17 or higher. Changes that don't support Java 17 at runtime will not be accepted.
- **Non-acceptable pull requests**
- Heuristic-based checks will not be accepted; however, basic rate limiting such as blocking attacks based on CPS is acceptable.
- Checks that can be easily circumvented that don't block packets or fix anything are likely to not be accepted.
- Checks or features that are too specific to a single environment or minecraft version are likely to not be accepted.
- Changes that require large or unnecessary dependencies will likely not be accepted.
- **Pull request formatting**
- Create a new branch for your feature or fix when forking the repository.
- Reference related issues in your pull request description if applicable.
- Write clear and descriptive commit messages.
- **Code styling**
- Add code comments for complex logic or significant changes.
- Try to keep your code clean and avoid duplication.
- Thoroughly test your changes before submitting your pull request.
### Development Notes
- GrimAC is built using [Gradle](https://gradle.org/) kotlin scripts.
- Java 21 is currently required to build the project. A minimum of Java 17 is required to run it.
### Questions & Support
- Join our [Discord](https://discord.grim.ac) if you have questions or need assistance.
- Refer to the [Wiki](https://github.com/GrimAnticheat/Grim/wiki) for project documentation.
+27 -67
View File
@@ -1,88 +1,49 @@
<div align="center">
<h1>GrimAC</h1>
# GrimAC
<div>
<a href="https://github.com/GrimAnticheat/Grim/actions/workflows/gradle-publish.yml">
<img alt="Workflow" src="https://img.shields.io/github/actions/workflow/status/GrimAnticheat/Grim/gradle-publish.yml?style=flat&logo=github"/>
</a>&nbsp;&nbsp;
<a href="https://modrinth.com/plugin/grimac">
<img alt="Modrinth" src="https://img.shields.io/modrinth/v/LJNGWSvH?style=flat&label=version&logo=modrinth">
</a>&nbsp;&nbsp;
<a href="https://modrinth.com/plugin/grimac#download">
<img alt="Downloads" src="https://img.shields.io/modrinth/dt/LJNGWSvH?style=flat&logo=modrinth&label=downloads&link=https%3A%2F%2Fmodrinth.com%2Fplugin%2Fgrimac%23download">
</a>&nbsp;&nbsp;
<a href="https://discord.grim.ac">
<img alt="Discord" src="https://img.shields.io/discord/811396969670901800?style=flat&label=discord&logo=discord">
</a>
</div>
<br>
</div>
GrimAC is an open source Minecraft anticheat designed for 1.21 and supports 1.8-1.21. It is free while in beta. It will eventually become paid and/or will include offering additional subscription based paid checks. Geyser players are fully exempt.
GrimAC is an open source Minecraft anticheat designed to support the latest versions of Minecraft.
It currently supports minecraft versions 1.8–1.21. Geyser players are fully exempt from the anticheat to prevent false positives.
This project is considered feature-complete for the 2.0 (open-source) branch. If you would like a bug fix or enhancement and cannot sponsor the work, pull requests are welcome.
A premium version is planned, which will offer additional subscription-based paid checks, such as heuristics.
This project is considered feature complete for the 2.0 (open-source) branch of this project. If you would like a bugfix or enhancement and cannot sponsor the work, pull requests are welcome.
## Downloads
- [Modrinth](https://modrinth.com/plugin/grimac)
- [Hangar](https://hangar.papermc.io/GrimAnticheat/GrimAnticheat)
- [SpigotMC](https://www.spigotmc.org/resources/grim-anticheat.99923/)
- *For bleeding edge builds use* [Github artifacts](https://nightly.link/GrimAnticheat/Grim/workflows/gradle-publish/2.0/artifact.zip)
- Latest updates:
- **[Modrinth](https://modrinth.com/plugin/grimac)** *(recommended)*
- GitHub
artifacts: [Bukkit](https://nightly.link/GrimAnticheat/Grim/workflows/gradle-publish/2.0/grimac-bukkit.zip), [Fabric](https://nightly.link/GrimAnticheat/Grim/workflows/gradle-publish/2.0/grimac-fabric.zip) *(bleeding edge)*
- Major releases only:
- ~~[Hangar](https://hangar.papermc.io/GrimAnticheat/GrimAnticheat)~~
- ~~[SpigotMC](https://www.spigotmc.org/resources/grim-anticheat.99923/)~~
## Installation notes
- Java 8 is fully supported.
- Paper, Spigot, and Folia are currently supported.
- If you use Geyser, place Floodgate on the backend server so grim can exempt bedrock players. Grim cannot access the Floodgate API if it is on the proxy.
- If you use ViaVersion, it should be on the backend server as movement is highly dependent on client version.
## Resources
## Support & wiki information
- Support & discussion: [Discord](https://discord.com/invite/kqQAhTmkUF)
- Report issues: [Issues](https://github.com/GrimAnticheat/Grim/issues/new/choose)
- Wiki & examples: [Wiki](https://github.com/GrimAnticheat/Grim/wiki)
- For documentation and examples visit the [Wiki](https://github.com/GrimAnticheat/Grim/wiki).
- For answers to commonly asked questions visit the [FAQ](https://github.com/GrimAnticheat/Grim/wiki/FAQ).
- For community support and project discussion join our [Discord](https://discord.grim.ac).
## Developer API
Grim's API allows you to integrate Grim into your own plugins.
- API repository: [GrimAPI](https://github.com/GrimAnticheat/GrimAPI)
- Wiki info: [Wiki](https://github.com/GrimAnticheat/GrimAPI)
## Pull Requests
See [Contributing](CONTRIBUTING.md) for more information about contributing and what our guidelines
are.
## Requirements & Installation
- Java 17 or higher. *For more details
see [Updating-to-Java-17](https://github.com/GrimAnticheat/Grim/wiki/Updating-to-Java-17).*
- A Spigot, Paper, Folia, or Fabric server environment. *For more details
see [Supported-environments](https://github.com/GrimAnticheat/Grim/wiki/Supported-environments).*
- If you use Geyser, place Floodgate on the backend server so grim can exempt bedrock players. Grim
cannot access the Floodgate API if it is on the proxy.
- If you use ViaVersion, it should be on the backend server as movement is highly dependent on
client version.
## Developer Plugin API
Grim's plugin API allows you to integrate Grim into your own plugins. Visit
the [plugin API repository](https://github.com/GrimAnticheat/GrimAPI) for the source code and more
information.
## Compiling From Source
## How to compile
1. `git clone https://github.com/GrimAnticheat/Grim.git`
2. `cd Grim`
3. `./gradlew build`
4. The final jars will compile into the `<platform>/build/libs` folders
4. The final jar will compile into the build/libs folder
## Grim Supremacy
## Grim supremacy
What makes Grim stand out against other anticheats?
### Movement Simulation Engine
* We have a 1:1 replication of the player's possible movements
* This covers everything from basic walking, swimming, knockback, cobwebs, to bubble columns
* It even covers riding entities from boats to pigs to striders
* This covers everything from basic walking, swimming, knockback, cobwebs, to bubble columns
* It even covers riding entities from boats to pigs to striders
* Built upon covering edge cases to confirm accuracy
* 1.13+ clients on 1.13+ servers, 1.12- clients on 1.13+ servers, 1.13+ clients on 1.12- servers,
and 1.12- clients on 1.12- servers are all supported regardless of the large technical changes
between these versions.
* 1.13+ clients on 1.13+ servers, 1.12- clients on 1.13+ servers, 1.13+ clients on 1.12- servers, and 1.12- clients on 1.12- servers are all supported regardless of the large technical changes between these versions.
* The order of collisions depends on the client version and is correct
* Accounts for minor bounding box differences between versions, for example:
* Single glass panes will be a + shape for 1.7-1.8 players and * for 1.9+ players
@@ -109,8 +70,7 @@ What makes Grim stand out against other anticheats?
* Per player, the cache allows for multithreaded design
* Sending players fake blocks with packets is safe and does not lead to falses
* The world is recreated for each player to allow lag compensation
* Client sided blocks cause no issues with packet based blocks. Block glitching does not false the
anticheat.
* Client sided blocks cause no issues with packet based blocks. Block glitching does not false the anticheat.
### Latency compensation
+226 -37
View File
@@ -1,49 +1,238 @@
/**
* GrimAC Build Configuration
*
* Build Flags:
* -PshadePE=true - Enables 'lite' mode
* -Prelocate=false - Adds 'no_relocate' modifier
* -Prelease=true - Removes commit/modifiers for release build
*
* Logic in: buildSrc/versioning/BuildConfig.kt & VersionUtil.kt
*/
import net.minecrell.pluginyml.bukkit.BukkitPluginDescription.Permission
import versioning.BuildConfig
import versioning.VersionUtil
plugins {
id("java")
id("maven-publish")
id("com.gradleup.shadow") version "9.0.0-beta6"
id("io.freefair.lombok") version "8.6"
id("net.minecrell.plugin-yml.bukkit") version "0.6.0"
id("com.diffplug.spotless") version "6.25.0"
}
BuildConfig.init(project)
spotless {
java {
endWithNewline()
indentWithSpaces(4)
removeUnusedImports()
trimTrailingWhitespace()
targetExclude("build/generated/**/*")
}
kotlinGradle {
endWithNewline()
indentWithSpaces(4)
trimTrailingWhitespace()
}
}
val baseVersion = "2.3.73"
group = "ac.grim.grimac"
version = VersionUtil.computeVersion(baseVersion)
description = "Libre simulation anticheat designed for 1.21 with 1.8–1.21 support, powered by PacketEvents 2.0."
version = "2.3.71"
description = "Libre simulation anticheat designed for 1.21 with 1.8-1.21 support, powered by PacketEvents 2.0."
java.sourceCompatibility = JavaVersion.VERSION_1_8
java.targetCompatibility = JavaVersion.VERSION_1_8
ext["timestamp"] = System.currentTimeMillis().toString()
ext["git_branch"] = VersionUtil.getGitBranch(true)
ext["git_commit"] = VersionUtil.getGitCommitHash(true)
ext["git_org"] = System.getenv("GRIM_GIT_ORG") ?: VersionUtil.getGitUser()
ext["git_repo"] = System.getenv("GRIM_GIT_REPO") ?: "Grim"
// Set to false for debug builds
// You cannot live reload classes if the jar relocates dependencies
// Checks Project properties -> environment variable -> defaults true
val relocate: Boolean = project.findProperty("relocate")?.toString()?.toBoolean()
?: System.getenv("RELOCATE_JAR")?.toBoolean()
?: true
println("Build configuration:")
println(" shadePE = ${BuildConfig.shadePE}")
println(" relocate = ${BuildConfig.relocate}")
println(" mavenLocalOverride = ${BuildConfig.mavenLocalOverride}")
println(" release = ${BuildConfig.release}")
println(" version = $version")
// Whether or not to shade PE into the jar, some servers may not want this if they use other plugins
// With PE; this prevents duplicate listening and reduces RAM usage by ~80-100 MB
val shadePE: Boolean = project.findProperty("shadePE")?.toString()?.toBoolean()
?: System.getenv("SHADE_PE")?.toBoolean()
?: true
tasks.register("printVersion") {
group = "versioning"
description = "Prints the computed project version"
doLast {
println("VERSION=$version")
repositories {
mavenLocal()
maven {
name = "papermc"
url = uri("https://repo.papermc.io/repository/maven-public/")
}
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") // Spigot
maven("https://jitpack.io/") { // Grim API
content {
includeGroup("com.github.grimanticheat")
}
}
maven("https://repo.viaversion.com") // ViaVersion
maven("https://repo.aikar.co/content/groups/aikar/") // ACF
maven("https://nexus.scarsz.me/content/repositories/releases") // Configuralize
maven("https://repo.opencollab.dev/maven-snapshots/") // Floodgate
maven("https://repo.opencollab.dev/maven-releases/") // Cumulus (for Floodgate)
maven("https://repo.codemc.io/repository/maven-releases/") // PacketEvents
maven("https://repo.codemc.io/repository/maven-snapshots/")
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") // placeholderapi
mavenCentral()
// FastUtil, Discord-Webhooks
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.20.6-R0.1-SNAPSHOT")
// PE dependency is now conditional
if (shadePE) {
implementation("com.github.retrooper:packetevents-spigot:2.7.1-SNAPSHOT")
} else {
compileOnly("com.github.retrooper:packetevents-spigot:2.7.1-SNAPSHOT")
}
implementation("co.aikar:acf-paper:0.5.1-SNAPSHOT")
implementation("club.minnced:discord-webhooks:0.8.0") // Newer versions include kotlin-stdlib, which leads to incompatibility with plugins that use Kotlin
implementation("it.unimi.dsi:fastutil:8.5.15")
implementation("github.scarsz:configuralize:1.4.0")
implementation("com.zaxxer:HikariCP:4.0.3")
// Used for local testing:
//implementation("ac.grim.grimac:GrimAPI:1.0")
implementation("com.github.grimanticheat:grimapi:05e31d62f2")
implementation("net.kyori:adventure-text-minimessage:4.17.0")
implementation("net.kyori:adventure-platform-bukkit:4.3.4")
implementation("org.jetbrains:annotations:24.1.0")
compileOnly("org.geysermc.floodgate:api:2.0-SNAPSHOT")
compileOnly("com.viaversion:viaversion-api:5.0.4-SNAPSHOT")
compileOnly("me.clip:placeholderapi:2.11.6")
compileOnly("io.netty:netty-all:4.1.85.Final")
}
bukkit {
name = "GrimAC"
author = "GrimAC"
main = "ac.grim.grimac.GrimAC"
website = "https://grim.ac/"
apiVersion = "1.13"
foliaSupported = true
if (!shadePE) {
depend = listOf("packetevents") + (depend ?: emptyList())
}
softDepend = listOf(
"ProtocolLib",
"ProtocolSupport",
"Essentials",
"ViaVersion",
"ViaBackwards",
"ViaRewind",
"Geyser-Spigot",
"floodgate",
"FastLogin",
"PlaceholderAPI",
)
permissions {
register("grim.alerts") {
description = "Receive alerts for violations"
default = Permission.Default.OP
}
register("grim.alerts.enable-on-join") {
description = "Enable alerts on join"
default = Permission.Default.OP
}
register("grim.performance") {
description = "Check performance metrics"
default = Permission.Default.OP
}
register("grim.profile") {
description = "Check user profile"
default = Permission.Default.OP
}
register("grim.brand") {
description = "Show client brands on join"
default = Permission.Default.OP
}
register("grim.brand.enable-on-join") {
description = "Enable showing client brands on join"
default = Permission.Default.OP
}
register("grim.sendalert") {
description = "Send cheater alert"
default = Permission.Default.OP
}
register("grim.nosetback") {
description = "Disable setback"
default = Permission.Default.FALSE
}
register("grim.nomodifypacket") {
description = "Disable modifying packets"
default = Permission.Default.FALSE
}
register("grim.exempt") {
description = "Exempt from all checks"
default = Permission.Default.FALSE
}
register("grim.verbose") {
description = "Receive verbose alerts for violations. Requires grim.alerts"
default = Permission.Default.OP
}
register("grim.verbose.enable-on-join") {
description = "Enable verbose alerts on join. Requires grim.alerts and grim.alerts.enable-on-join"
default = Permission.Default.FALSE
}
}
}
// ---------- Java Compile Optimization ----------
subprojects {
tasks.withType<JavaCompile>().configureEach {
options.isFork = true
options.isIncremental = true
tasks.build {
dependsOn(tasks.shadowJar)
dependsOn(tasks.spotlessApply)
}
tasks.withType<JavaCompile> {
options.encoding = "UTF-8"
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
disableAutoTargetJvm()
}
publishing.publications.create<MavenPublication>("maven") {
artifact(tasks["shadowJar"])
}
tasks.shadowJar {
manifest {
attributes["paperweight-mappings-namespace"] = "mojang"
}
minimize()
archiveFileName.set("${project.name}-${project.version}${if (shadePE) "" else "-lite"}.jar")
if (relocate) {
// Only relocate PE if we're shading it
if (shadePE) {
relocate("io.github.retrooper.packetevents", "ac.grim.grimac.shaded.io.github.retrooper.packetevents")
relocate("com.github.retrooper.packetevents", "ac.grim.grimac.shaded.com.github.retrooper.packetevents")
relocate("net.kyori", "ac.grim.grimac.shaded.kyori") // use PE's built-in adventure instead when not shading
}
relocate("co.aikar.commands", "ac.grim.grimac.shaded.acf")
relocate("co.aikar.locale", "ac.grim.grimac.shaded.locale")
relocate("club.minnced", "ac.grim.grimac.shaded.discord-webhooks")
relocate("github.scarsz.configuralize", "ac.grim.grimac.shaded.configuralize")
relocate("com.github.puregero", "ac.grim.grimac.shaded.com.github.puregero")
relocate("com.google.code.gson", "ac.grim.grimac.shaded.gson")
relocate("alexh", "ac.grim.grimac.shaded.maps")
relocate("it.unimi.dsi.fastutil", "ac.grim.grimac.shaded.fastutil")
relocate("okhttp3", "ac.grim.grimac.shaded.okhttp3")
relocate("okio", "ac.grim.grimac.shaded.okio")
relocate("org.yaml.snakeyaml", "ac.grim.grimac.shaded.snakeyaml")
relocate("org.json", "ac.grim.grimac.shaded.json")
relocate("org.intellij", "ac.grim.grimac.shaded.intellij")
relocate("org.jetbrains", "ac.grim.grimac.shaded.jetbrains")
relocate("com.zaxxer", "ac.grim.gimac.shaded.zaxxer")
}
}
-15
View File
@@ -1,15 +0,0 @@
plugins {
`kotlin-dsl`
kotlin("plugin.serialization") version "1.9.0" // Use the same Kotlin version as your main project
}
repositories {
mavenCentral()
}
dependencies {
implementation(libs.spotless)
implementation(libs.lombok)
implementation(libs.shadow)
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
}
-7
View File
@@ -1,7 +0,0 @@
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../libs.versions.toml"))
}
}
}
@@ -1,90 +0,0 @@
import versioning.BuildConfig
plugins {
`java-library`
id("io.freefair.lombok")
id("com.diffplug.spotless")
}
group = rootProject.group
version = rootProject.version
description = rootProject.description
// Java compilation settings
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
disableAutoTargetJvm()
withSourcesJar()
withJavadocJar()
}
// Spotless configuration
spotless {
java {
endWithNewline()
indentWithSpaces(4)
removeUnusedImports()
trimTrailingWhitespace()
targetExclude("build/generated/**/*")
}
kotlinGradle {
endWithNewline()
indentWithSpaces(4)
trimTrailingWhitespace()
}
}
tasks {
withType<JavaCompile>().configureEach {
options.encoding = "UTF-8"
options.release.set(17)
}
build {
// Ensure spotlessApply runs before build
dependsOn(tasks.named("spotlessApply"))
}
// Process resources (e.g., for plugin metadata files)
processResources {
val properties = mapOf(
"timestamp" to rootProject.ext["timestamp"],
"version" to project.version.toString(),
"git_commit" to rootProject.ext["git_commit"],
"git_branch" to rootProject.ext["git_branch"],
"git_repo" to rootProject.ext["git_repo"],
"git_org" to rootProject.ext["git_org"],
"build_shade_pe" to BuildConfig.shadePE,
"build_relocate" to BuildConfig.relocate,
"build_release" to BuildConfig.release,
)
properties.forEach { (key, value) -> inputs.property(key, value) }
filesMatching(
listOf(
"bungee.yml",
"velocity-plugin.json",
"fabric.mod.json",
"grimac.properties"
)
) {
expand(properties)
}
}
javadoc {
title = "${rootProject.name}-${project.name} v${rootProject.version}"
options.encoding = "UTF-8"
options.overview =
rootProject.file("buildSrc/src/main/resources/javadoc-overview.html").toString()
setDestinationDir(file("${project.layout.buildDirectory.asFile.get()}/docs/javadoc"))
options {
(this as CoreJavadocOptions).addBooleanOption("Xdoclint:none", true)
}
}
}
// Default tasks
defaultTasks("build")
@@ -1,407 +0,0 @@
import kotlinx.serialization.json.*
import java.util.jar.JarFile
import java.util.zip.ZipEntry
plugins {
`java-library`
}
val jijDependencies: Configuration by project.configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
extendsFrom(project.configurations.getByName("implementation"))
project.configurations.findByName("modImplementation")?.let { extendsFrom(it) }
}
data class DependencyIdentifier(
val group: String,
val name: String,
val version: String,
val classifier: String = "" // Add classifier field, default to empty string
) {
override fun toString() = "$group:$name:$version${if (classifier.isNotEmpty()) ":$classifier" else ""}"
}
// Does not support extracting classifiers but while the fabric standard is ambiguous on whether they can be included
// It does not appear dependency classifiers are in use by any mod I am aware of or can find
fun parseFabricModJson(jarFile: File, project: Project): Set<DependencyIdentifier> {
val nestedJars = mutableSetOf<DependencyIdentifier>()
try {
JarFile(jarFile).use { jar ->
val fabricModJsonEntry: ZipEntry? = jar.getEntry("fabric.mod.json")
if (fabricModJsonEntry != null) {
jar.getInputStream(fabricModJsonEntry).bufferedReader().use { reader ->
val jsonContent = reader.readText()
val jsonElement = Json.parseToJsonElement(jsonContent)
val jsonObject = jsonElement.jsonObject
val jarsArray = jsonObject["jars"]?.jsonArray ?: return@use
jarsArray.forEach { jarEntry: JsonElement ->
val filePath =
jarEntry.jsonObject["file"]?.jsonPrimitive?.content ?: return@forEach
project.logger.debug(
"Found nested JAR in fabric.mod.json: {} in {}",
filePath,
jarFile
)
val jarName = filePath.substringAfterLast("/")
val parts = jarName.removeSuffix(".jar").split("-")
if (parts.size >= 2) {
val inferredName = parts.dropLast(1).joinToString("-")
val inferredVersion = parts.last()
nestedJars.add(DependencyIdentifier("", inferredName, inferredVersion))
project.logger.debug("Inferred nested dependency from fabric.mod.json: :$inferredName:$inferredVersion")
}
}
}
}
}
} catch (e: Exception) {
project.logger.error("Failed to parse fabric.mod.json in $jarFile: ${e.message}")
}
return nestedJars
}
fun extractEmbeddedJars(jarFile: File, project: Project): Set<DependencyIdentifier> {
val embeddedJars = mutableSetOf<DependencyIdentifier>()
embeddedJars.addAll(parseFabricModJson(jarFile, project)) // Retain existing logic for top-level fabric.mod.json parsing
try {
JarFile(jarFile).use { jar ->
val entries = jar.entries()
while (entries.hasMoreElements()) {
val entry = entries.nextElement()
val entryName = entry.name
if (entryName.endsWith(".jar") && (entryName.startsWith("META-INF/jarjar/") || entryName.startsWith(
"libs/"
) || entryName.startsWith("META-INF/jars/"))
) {
project.logger.debug("Found embedded JAR: {} in {}", entryName, jarFile)
val tempFile = File.createTempFile("embedded-", ".jar")
tempFile.deleteOnExit()
jar.getInputStream(entry).use { input ->
tempFile.outputStream().use { output ->
input.copyTo(output)
}
}
JarFile(tempFile).use { embeddedJar ->
val fabricModJsonEntry: ZipEntry? = embeddedJar.getEntry("fabric.mod.json")
if (fabricModJsonEntry != null) {
embeddedJar.getInputStream(fabricModJsonEntry).bufferedReader().use { reader ->
val jsonContent = reader.readText()
val jsonElement = Json.parseToJsonElement(jsonContent)
val jsonObject = jsonElement.jsonObject
// Extract id and parse into group
val id = jsonObject["id"]?.jsonPrimitive?.content
?: throw IllegalStateException("Missing 'id' in fabric.mod.json of embedded JAR: $entryName")
val idWithDots = id.replace("_", ".")
val lastDotIndex = idWithDots.lastIndexOf(".")
val group = if (lastDotIndex != -1) idWithDots.take(lastDotIndex) else ""
// Extract name and version from the JAR filename
val jarName = entryName.substringAfterLast("/").removeSuffix(".jar")
val (name, version) = parseNameAndVersionFromJarName(jarName)
?: throw IllegalStateException("Could not parse name and version from JAR filename: $jarName")
// Create DependencyIdentifier (classifier is empty for now)
val depId = DependencyIdentifier(group, name, version)
embeddedJars.add(depId)
project.logger.debug("Identified embedded dependency from fabric.mod.json and filename: {}", depId)
}
} else {
project.logger.error("No fabric.mod.json found in embedded JAR: {}. Skipping.", entryName)
}
}
}
}
}
} catch (e: Exception) {
project.logger.error("Failed to analyze JAR file $jarFile for embedded JARs: ${e.message}")
}
return embeddedJars
}
fun parseNameAndVersionFromJarName(jarName: String): Pair<String, String>? {
val versionStartRegex = Regex("-(?=\\d)")
// Use regex to find the position of the hyphen followed by a digit
val versionStartMatch = versionStartRegex.find(jarName) ?: return null
val versionStartIndex = versionStartMatch.range.first
// Split the JAR name into name and version at the version start index
val name = jarName.take(versionStartIndex)
val version = jarName.substring(versionStartIndex + 1) // Skip the hyphen
return if (name.isNotEmpty() && version.isNotEmpty()) {
Pair(name, version)
} else {
null
}
}
fun shouldExcludeDependency(
dependency: ResolvedDependency,
allEmbeddedDependencies: Set<DependencyIdentifier>,
actuallyIncludedDependencies: Set<DependencyIdentifier>,
project: Project
): Boolean {
val group = dependency.moduleGroup
val name = dependency.moduleName
val version = dependency.moduleVersion
// Extract classifier from resolved dependency (if available)
val classifier = dependency.moduleArtifacts.firstOrNull()?.classifier ?: ""
val depId = DependencyIdentifier(group, name, version, classifier)
if (group.startsWith("net.minecraft") ||
group.startsWith("net.fabricmc") ||
name == "minecraft" ||
name == "fabric-loader" ||
name == "fastutil" ||
name.startsWith("fabric_") ||
name.startsWith("fabric-api")
) {
project.logger.debug("Excluding platform dependency: {}", depId)
return true
}
if (name.endsWith("-bom") || name.contains("_bom")) {
project.logger.debug("Excluding BOM file: {}", depId)
return true
}
if (allEmbeddedDependencies.any { it.name == name && it.version == version && it.classifier == classifier }) {
project.logger.debug("Excluding dependency already embedded in another JAR: {}", depId)
return true
}
if (actuallyIncludedDependencies.any { it.name == name && it.version == version && it.classifier == classifier }) {
project.logger.debug("Excluding duplicate dependency: {}", depId)
return true
}
return false
}
fun isJijTarget(
dependency: ResolvedDependency,
allEmbeddedDependencies: Set<DependencyIdentifier>,
actuallyIncludedDependencies: Set<DependencyIdentifier>,
project: Project
): Boolean {
val classifier = dependency.moduleArtifacts.firstOrNull()?.classifier ?: ""
project.logger.debug(
"Checking JIJ target: {}",
DependencyIdentifier(
dependency.moduleGroup,
dependency.moduleName,
dependency.moduleVersion,
classifier
)
)
return !shouldExcludeDependency(
dependency,
allEmbeddedDependencies,
actuallyIncludedDependencies,
project
)
}
fun includeDependencyWithExclusions(
depId: DependencyIdentifier,
project: Project,
actuallyIncludedDependencies: MutableSet<DependencyIdentifier>,
allEmbeddedDependencies: Set<DependencyIdentifier>
) {
project.logger.debug("Including external dependency as JIJ with dynamic exclusions: {}", depId)
project.dependencies {
// Include dependency with classifier (if present)
"include"("${depId.group}:${depId.name}:${depId.version}${if (depId.classifier.isNotEmpty()) ":${depId.classifier}" else ""}") {
allEmbeddedDependencies.forEach { embeddedDep ->
if (embeddedDep.group.isNotEmpty()) {
exclude(group = embeddedDep.group, module = embeddedDep.name)
} else {
exclude(module = embeddedDep.name)
}
project.logger.debug("Excluding embedded transitive dependency: ${embeddedDep.name}:${embeddedDep.version}${if (embeddedDep.classifier.isNotEmpty()) ":${embeddedDep.classifier}" else ""}")
}
}
}
actuallyIncludedDependencies.add(depId)
}
fun processDependencies(
dependencies: Set<ResolvedDependency>,
processed: MutableSet<String>,
allEmbeddedDependencies: MutableMap<DependencyIdentifier, File>,
actuallyIncludedDependencies: MutableSet<DependencyIdentifier>,
project: Project
) {
dependencies.forEach { dep: ResolvedDependency ->
val classifier = dep.moduleArtifacts.firstOrNull()?.classifier ?: ""
val depKey = "${dep.moduleGroup}:${dep.moduleName}:${dep.moduleVersion}${if (classifier.isNotEmpty()) ":$classifier" else ""}"
val depId = DependencyIdentifier(dep.moduleGroup, dep.moduleName, dep.moduleVersion, classifier)
if (!processed.contains(depKey)) {
processed.add(depKey)
project.logger.debug("Resolved dependency: {}", depId)
val jarFile = dep.moduleArtifacts.firstOrNull()?.file
if (jarFile != null && jarFile.exists()) {
val embeddedJars = extractEmbeddedJars(jarFile, project)
embeddedJars.forEach { embeddedDep ->
allEmbeddedDependencies[embeddedDep] = jarFile
}
}
if (isJijTarget(
dep,
allEmbeddedDependencies.keys,
actuallyIncludedDependencies,
project
)
) {
project.logger.debug("Processing JIJ dependency: {}", depId)
val isProjectDependency = project.rootProject.allprojects.any { subproject ->
subproject.name == dep.moduleName && (subproject.group == dep.moduleGroup || dep.moduleGroup.isEmpty())
}
if (isProjectDependency) {
val projectPath = project.rootProject.allprojects.find { subproject ->
subproject.name == dep.moduleName && (subproject.group == dep.moduleGroup || dep.moduleGroup.isEmpty())
}?.path
?: throw IllegalStateException("Project dependency not found: ${dep.moduleName}")
project.logger.debug("Including project dependency as JIJ: $projectPath")
project.dependencies {
"include"(project.project(projectPath))
}
actuallyIncludedDependencies.add(depId)
} else {
includeDependencyWithExclusions(
depId,
project,
actuallyIncludedDependencies,
allEmbeddedDependencies.keys
)
}
}
processDependencies(
dep.children,
processed,
allEmbeddedDependencies,
actuallyIncludedDependencies,
project
)
}
}
}
project.afterEvaluate {
project.logger.debug("Resolving jijDependencies configuration")
val resolvedDependencies = jijDependencies.resolvedConfiguration.firstLevelModuleDependencies
val processed = mutableSetOf<String>()
val allEmbeddedDependencies = mutableMapOf<DependencyIdentifier, File>()
val actuallyIncludedDependencies = mutableSetOf<DependencyIdentifier>()
fun collectAllEmbeddedDependenciesForAfterEvaluate(dependencies: Set<ResolvedDependency>) {
dependencies.forEach { dep ->
val classifier = dep.moduleArtifacts.firstOrNull()?.classifier ?: ""
val depKey = "${dep.moduleGroup}:${dep.moduleName}:${dep.moduleVersion}${if (classifier.isNotEmpty()) ":$classifier" else ""}"
if (!processed.contains(depKey)) {
processed.add(depKey)
val jarFile = dep.moduleArtifacts.firstOrNull()?.file
if (jarFile != null && jarFile.exists()) {
val embeddedJars = extractEmbeddedJars(jarFile, project)
embeddedJars.forEach { embeddedDep ->
allEmbeddedDependencies[embeddedDep] = jarFile
project.logger.debug(
"Collected embedded dependency: {} from {}",
embeddedDep,
jarFile
)
}
}
collectAllEmbeddedDependenciesForAfterEvaluate(dep.children)
}
}
}
processed.clear()
collectAllEmbeddedDependenciesForAfterEvaluate(resolvedDependencies)
processed.clear()
processDependencies(
resolvedDependencies,
processed,
allEmbeddedDependencies,
actuallyIncludedDependencies,
project
)
}
tasks.withType<Jar>().configureEach {
doFirst {
project.logger.debug("Resolving JIJ dependencies for JAR inclusion")
val resolvedDependencies =
jijDependencies.resolvedConfiguration.firstLevelModuleDependencies
val processed = mutableSetOf<String>()
val allEmbeddedDependencies = mutableMapOf<DependencyIdentifier, File>()
val actuallyIncludedDependencies = mutableSetOf<DependencyIdentifier>()
fun collectAllEmbeddedDependenciesForJar(dependencies: Set<ResolvedDependency>) {
dependencies.forEach { dep ->
val depKey = "${dep.moduleGroup}:${dep.moduleName}:${dep.moduleVersion}"
if (!processed.contains(depKey)) {
processed.add(depKey)
val jarFile = dep.moduleArtifacts.firstOrNull()?.file
if (jarFile != null && jarFile.exists()) {
val embeddedJars = extractEmbeddedJars(jarFile, project)
embeddedJars.forEach { embeddedDep ->
allEmbeddedDependencies[embeddedDep] = jarFile
project.logger.debug(
"Collected embedded dependency for JAR: {} from {}",
embeddedDep,
jarFile
)
}
}
collectAllEmbeddedDependenciesForJar(dep.children)
}
}
}
processed.clear()
collectAllEmbeddedDependenciesForJar(resolvedDependencies)
processed.clear()
fun logDependencies(dependencies: Set<ResolvedDependency>) {
dependencies.forEach { dep ->
val depKey = "${dep.moduleGroup}:${dep.moduleName}:${dep.moduleVersion}"
val depId = DependencyIdentifier(dep.moduleGroup, dep.moduleName, dep.moduleVersion)
if (!processed.contains(depKey)) {
processed.add(depKey)
project.logger.debug("Resolved JIJ dependency for JAR: {}", depId)
val jarFile = dep.moduleArtifacts.firstOrNull()?.file
if (jarFile != null && jarFile.exists()) {
val embeddedJars = extractEmbeddedJars(jarFile, project)
embeddedJars.forEach { embeddedDep ->
allEmbeddedDependencies[embeddedDep] = jarFile
}
}
if (isJijTarget(
dep,
allEmbeddedDependencies.keys,
actuallyIncludedDependencies,
project
)
) {
project.logger.debug("Including JIJ dependency in JAR: {}", depId)
actuallyIncludedDependencies.add(depId)
}
logDependencies(dep.children)
}
}
}
logDependencies(resolvedDependencies)
}
}
@@ -1,41 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import versioning.BuildConfig
plugins {
id("com.gradleup.shadow")
}
tasks.named<ShadowJar>("shadowJar") {
minimize()
archiveFileName = "${rootProject.name}-${project.name}-${rootProject.version}.jar"
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
if (BuildConfig.relocate) {
if (BuildConfig.shadePE) {
relocate("io.github.retrooper.packetevents", "ac.grim.grimac.shaded.io.github.retrooper.packetevents")
relocate("com.github.retrooper.packetevents", "ac.grim.grimac.shaded.com.github.retrooper.packetevents")
relocate("net.kyori", "ac.grim.grimac.shaded.kyori") // use PE's built-in adventure instead when not shading PE
}
relocate("club.minnced", "ac.grim.grimac.shaded.discord-webhooks")
relocate("org.slf4j", "ac.grim.grimac.shaded.slf4j") // Required by discord-webhooks
relocate("github.scarsz.configuralize", "ac.grim.grimac.shaded.configuralize")
relocate("com.github.puregero", "ac.grim.grimac.shaded.com.github.puregero")
relocate("com.google.code.gson", "ac.grim.grimac.shaded.gson")
relocate("alexh", "ac.grim.grimac.shaded.maps")
relocate("it.unimi.dsi.fastutil", "ac.grim.grimac.shaded.fastutil")
relocate("okhttp3", "ac.grim.grimac.shaded.okhttp3")
relocate("okio", "ac.grim.grimac.shaded.okio")
relocate("org.yaml.snakeyaml", "ac.grim.grimac.shaded.snakeyaml")
relocate("org.json", "ac.grim.grimac.shaded.json")
relocate("org.intellij", "ac.grim.grimac.shaded.intellij")
relocate("org.jetbrains", "ac.grim.grimac.shaded.jetbrains")
relocate("org.incendo", "ac.grim.grimac.shaded.incendo")
relocate("io.leangen.geantyref", "ac.grim.grimac.shaded.geantyref") // Required by cloud
relocate("com.zaxxer", "ac.grim.grimac.shaded.zaxxer") // Database history
}
mergeServiceFiles()
}
tasks.named("assemble") {
dependsOn(tasks.named("shadowJar"))
}
@@ -1,96 +0,0 @@
package versioning
import org.gradle.api.Project
import org.gradle.internal.extensions.stdlib.toDefaultLowerCase
import versioning.BuildConfig.init
import versioning.BuildConfig.mavenLocalOverride
import versioning.BuildConfig.release
import versioning.BuildConfig.relocate
import versioning.BuildConfig.shadePE
/**
* BuildConfig provides access to user-defined build flags that control how a Grim
* build is assembled. These flags are resolved once at configuration time using
* [init], and are then exposed as fast, memoized values.
*
* Flags can be defined in three ways:
*
* 1. JVM system properties (-Dflag=value)
* 2. Gradle project properties (-Pflag=value or in gradle.properties)
* 3. Environment variables (FLAG=value)
*
* You can use these to enable/disable features like shading, relocation, or release mode.
*
* Examples:
*
* Using Gradle -P properties:
* ```
* ./gradlew build -PshadePE=true -Prelocate=false -Prelease=true
* ```
*
* Using environment variables:
* ```
* SHADE_PE=true RELOCATE_JAR=false RELEASE=true ./gradlew build
* ```
*
* Using JVM system properties:
* ```
* ./gradlew build -DshadePE=true -Drelease=true
* ```
*
* @property shadePE If true, shades PacketEvents into the jar. Default: true.
* @property relocate If true, relocates shaded dependencies to avoid conflicts. Default: true.
* @property release If true, omits commit hash and modifiers from version string. Default: false.
* @property mavenLocalOverride If true, will make artifacts in mavenLocal() will be used instead of their remote counterparts for this build. Default: false
*/
object BuildConfig {
/**
* Must be called once from your root build script to initialize the flags.
* Example (in build.gradle.kts):
* ```
* BuildConfig.init(project)
* ```
*/
fun init(project: Project) {
_shadePE = resolveBool(project, "shadePE", altKey = "SHADE_PE", default = true)
_relocate = resolveBool(project, "relocate", altKey = "RELOCATE_JAR", default = true)
_release = resolveBool(project, "release", default = false)
_mavenLocalOverride = resolveBool(project, "mavenLocalOverride", default = false)
}
// Unified resolution logic (System > Gradle > Env)
private fun resolveRaw(project: Project, key: String): String? =
System.getProperty(key) // 1. JVM (-Dkey=value)
?: project.findProperty(key)?.toString() // 2. Gradle (-Pkey=value or gradle.properties)
?: System.getenv(key.uppercase()) // 3. ENV (KEY=value)
private fun resolveBool(project: Project, key: String, altKey: String? = null, default: Boolean): Boolean {
return resolveRaw(project, key)?.toDefaultLowerCase()?.toBooleanStrictOrNull()
?: altKey?.let {
resolveRaw(project, it)?.toDefaultLowerCase()?.toBooleanStrictOrNull()
} ?: default
}
// Private backing vars (nullable because we can't use lateinit with primitives)
private var _shadePE: Boolean? = null
private var _relocate: Boolean? = null
private var _release: Boolean? = null
private var _mavenLocalOverride: Boolean? = null
/** If true, shades PacketEvents into the jar. Default: true. */
val shadePE: Boolean get() = _shadePE
?: error("BuildConfig.shadePE accessed before init() was called")
/** If true, relocates shaded dependencies to avoid conflicts. Default: true. */
val relocate: Boolean get() = _relocate
?: error("BuildConfig.relocate accessed before init() was called")
/** If true, omits commit hash and modifiers from version string. Default: false. */
val release: Boolean get() = _release
?: error("BuildConfig.release accessed before init() was called")
val mavenLocalOverride: Boolean get() = _mavenLocalOverride
?: error("BuildConfig.release accessed before init() was called")
}
@@ -1,113 +0,0 @@
package versioning
import java.io.ByteArrayOutputStream
/**
* Utility for computing the version string of GrimAC artifacts.
*
* The version string is constructed based on:
* - A base semantic version (e.g., "2.3.72")
* - Git commit hash (unless in release mode)
* - Git branch name (unless in release mode or main)
* - Modifiers (e.g., lite, no_relocate) for non-default build configurations
*
* Example outputs:
* - `2.3.72` (release build)
* - `2.3.72-a4f8b21+lite` (preview build without PE shading)
* - `2.3.72-feature_branch-a4f8b21+lite-no_relocate`
*
* @see BuildConfig for controlling the release/modifier behavior
*/
object VersionUtil {
/**
* Computes the full version string for the build.
*
* @param baseVersion The base semantic version (e.g., "2.3.72")
* @return Full version string including commit hash, branch, and modifiers if applicable
*/
fun computeVersion(baseVersion: String): String {
if (BuildConfig.release) {
return baseVersion
}
val commitHash = getGitCommitHash()
val branch = getGitBranch()
val modifiers = buildList {
if (!BuildConfig.shadePE) add("lite")
if (!BuildConfig.relocate) add("no_relocate")
}.joinToString("-").takeIf { it.isNotEmpty() }
return buildString {
append(baseVersion)
append("-")
branch?.let { append("$it-") }
append(commitHash)
modifiers?.let { append("+$it") }
}
}
/**
* Retrieves the current Git commit
*/
fun getGitCommitHash(full: Boolean = false): String {
val stdout = ByteArrayOutputStream()
val command = listOfNotNull("git", "rev-parse", if (full) null else "--short", "HEAD")
ProcessBuilder(command)
.redirectErrorStream(true)
.start()
.apply { waitFor() }
.inputStream
.use { stdout.writeBytes(it.readAllBytes()) }
val fullCommit = stdout.toString().trim()
return fullCommit.take(minOf(fullCommit.length, 7))
}
/**
* Returns the current Git branch, sanitised for use in file names.
* If the branch is "main" or "2.0", returns null.
*
* Any slash (/) in the branch name is replaced with an underscore (_)
* to avoid filesystem issues.
*/
fun getGitBranch(raw: Boolean = false): String? {
val stdout = ByteArrayOutputStream()
ProcessBuilder("git", "rev-parse", "--abbrev-ref", "HEAD")
.redirectErrorStream(true)
.start()
.apply { waitFor() }
.inputStream.use { stdout.writeBytes(it.readAllBytes()) }
if (raw) return stdout.toString().trim()
val branch = stdout.toString().trim()
.replace(Regex("[^a-zA-Z0-9_.-]+"), "_")
.replace(Regex("_{2,}"), "_")
.trim(' ', '.', '_', '-')
.removePrefix("heads_")
val mainBranch = System.getenv("GRIM_MAIN_BRANCH") ?: "2.0"
return when (branch) {
"main", mainBranch -> null // ← ignore these branches
else -> branch
}
}
fun getGitUser(): String {
try {
val stdout = ByteArrayOutputStream()
ProcessBuilder("git", "config", "user.name")
.redirectErrorStream(true)
.start()
.apply { waitFor() }
.inputStream.use { stdout.writeBytes(it.readAllBytes()) }
return stdout.toString().trim()
} catch (_: Exception) {
return "unknown"
}
}
}
-206
View File
@@ -1,206 +0,0 @@
import net.minecrell.pluginyml.bukkit.BukkitPluginDescription.Permission
import versioning.BuildConfig
plugins {
`maven-publish`
grim.`base-conventions`
grim.`shadow-conventions`
id("de.eldoria.plugin-yml.bukkit") version "0.8.0"
id("xyz.jpenilla.run-paper") version "3.0.0-beta.1"
}
repositories {
if (BuildConfig.mavenLocalOverride) {
mavenLocal()
}
// For paper-api
exclusiveContent {
forRepository {
maven {
name = "papermc"
url = uri("https://repo.papermc.io/repository/maven-public/")
}
}
filter {
includeGroup("io.papermc.paper")
includeGroup("net.md-5")
}
}
exclusiveContent {
forRepository {
maven("https://libraries.minecraft.net") { // Brigadier
mavenContent { releasesOnly() }
}
}
filter {
includeModule("com.mojang", "brigadier")
}
}
// For placeholderapi
exclusiveContent {
forRepository {
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/")
}
filter {
includeGroup("me.clip")
}
}
// For GrimAPI and PacketEvents (transitive from :common, direct in :bukkit)
exclusiveContent {
forRepository {
maven("https://repo.grim.ac/snapshots")
}
filter {
includeGroup("ac.grim.grimac")
includeGroup("com.github.retrooper")
}
}
// For Configuralize (transitive from :common)
exclusiveContent {
forRepository {
maven("https://nexus.scarsz.me/content/repositories/releases") {
mavenContent { releasesOnly() }
}
}
filter {
includeGroup("github.scarsz")
}
}
// Maven Central Fallback
mavenCentral()
}
dependencies {
compileOnly(libs.paper.api)
compileOnly(libs.placeholderapi)
if (BuildConfig.shadePE) {
implementation(libs.packetevents.spigot)
} else {
compileOnly(libs.packetevents.spigot)
}
implementation(libs.cloud.paper)
implementation(libs.adventure.platform.bukkit)
implementation(project(":common"))
shadow(project(":common"))
}
bukkit {
name = "GrimAC"
author = "GrimAC"
main = "ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin"
website = "https://grim.ac/"
apiVersion = "1.13"
foliaSupported = true
if (!BuildConfig.shadePE) {
depend = listOf("packetevents")
}
softDepend = listOf(
"ProtocolLib",
"ProtocolSupport",
"Essentials",
"ViaVersion",
"ViaBackwards",
"ViaRewind",
"Geyser-Spigot",
"floodgate",
"FastLogin",
"PlaceholderAPI",
)
permissions {
register("grim.alerts") {
description = "Receive alerts for violations"
default = Permission.Default.OP
}
register("grim.alerts.enable-on-join") {
description = "Enable alerts on join"
default = Permission.Default.OP
}
register("grim.performance") {
description = "Check performance metrics"
default = Permission.Default.OP
}
register("grim.profile") {
description = "Check user profile"
default = Permission.Default.OP
}
register("grim.brand") {
description = "Show client brands on join"
default = Permission.Default.OP
}
register("grim.brand.enable-on-join") {
description = "Enable showing client brands on join"
default = Permission.Default.OP
}
register("grim.sendalert") {
description = "Send cheater alert"
default = Permission.Default.OP
}
register("grim.nosetback") {
description = "Disable setback"
default = Permission.Default.FALSE
}
register("grim.nomodifypacket") {
description = "Disable modifying packets"
default = Permission.Default.FALSE
}
register("grim.exempt") {
description = "Exempt from all checks"
default = Permission.Default.FALSE
}
register("grim.verbose") {
description = "Receive verbose alerts for violations"
default = Permission.Default.OP
}
register("grim.verbose.enable-on-join") {
description =
"Enable verbose alerts on join"
default = Permission.Default.FALSE
}
register("grim.list") {
description =
"Shows lists of specific data"
default = Permission.Default.FALSE
}
}
}
publishing.publications.create<MavenPublication>("maven") {
artifact(tasks["shadowJar"])
}
tasks {
runServer {
minecraftVersion("1.21.4")
}
shadowJar {
manifest {
attributes["paperweight-mappings-namespace"] = "mojang"
}
}
}
@@ -1,28 +0,0 @@
package ac.grim.grimac.platform.bukkit;
import ac.grim.grimac.platform.api.PlatformPlugin;
import org.bukkit.plugin.Plugin;
public class BukkitPlatformPlugin implements PlatformPlugin {
private final Plugin plugin;
public BukkitPlatformPlugin(Plugin plugin) {
this.plugin = plugin;
}
@Override
public boolean isEnabled() {
return plugin.isEnabled();
}
@Override
public String getName() {
return plugin.getName();
}
@SuppressWarnings("deprecation")
@Override
public String getVersion() {
return plugin.getDescription().getVersion();
}
}
@@ -1,37 +0,0 @@
package ac.grim.grimac.platform.bukkit;
import ac.grim.grimac.platform.api.PlatformServer;
import ac.grim.grimac.platform.api.sender.Sender;
import io.github.retrooper.packetevents.util.SpigotReflectionUtil;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
public class BukkitPlatformServer implements PlatformServer {
@Override
public String getPlatformImplementationString() {
return Bukkit.getVersion();
}
@Override
public void dispatchCommand(Sender sender, String command) {
CommandSender commandSender = GrimACBukkitLoaderPlugin.LOADER.getBukkitSenderFactory().reverse(sender);
Bukkit.dispatchCommand(commandSender, command);
}
@Override
public Sender getConsoleSender() {
return GrimACBukkitLoaderPlugin.LOADER.getBukkitSenderFactory().map(Bukkit.getConsoleSender());
}
@Override
public void registerOutgoingPluginChannel(String name) {
GrimACBukkitLoaderPlugin.LOADER.getServer().getMessenger().registerOutgoingPluginChannel(GrimACBukkitLoaderPlugin.LOADER, name);
}
@Override
public double getTPS() {
return SpigotReflectionUtil.getTPS();
}
}
@@ -1,163 +0,0 @@
package ac.grim.grimac.platform.bukkit;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.GrimAPIProvider;
import ac.grim.grimac.api.GrimAbstractAPI;
import ac.grim.grimac.api.plugin.GrimPlugin;
import ac.grim.grimac.events.GrimExtensionManager;
import ac.grim.grimac.manager.init.Initable;
import ac.grim.grimac.manager.init.start.ExemptOnlinePlayersOnReload;
import ac.grim.grimac.manager.init.start.StartableInitable;
import ac.grim.grimac.platform.api.Platform;
import ac.grim.grimac.platform.api.PlatformLoader;
import ac.grim.grimac.platform.api.PlatformServer;
import ac.grim.grimac.platform.api.manager.ItemResetHandler;
import ac.grim.grimac.platform.api.manager.MessagePlaceHolderManager;
import ac.grim.grimac.platform.api.manager.CommandAdapter;
import ac.grim.grimac.platform.api.manager.PlatformPluginManager;
import ac.grim.grimac.platform.api.player.PlatformPlayerFactory;
import ac.grim.grimac.platform.api.scheduler.PlatformScheduler;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.platform.api.sender.SenderFactory;
import ac.grim.grimac.platform.bukkit.initables.BukkitBStats;
import ac.grim.grimac.platform.bukkit.initables.BukkitEventManager;
import ac.grim.grimac.platform.bukkit.initables.BukkitTickEndEvent;
import ac.grim.grimac.platform.bukkit.manager.BukkitItemResetHandler;
import ac.grim.grimac.platform.bukkit.manager.BukkitMessagePlaceHolderManager;
import ac.grim.grimac.platform.bukkit.manager.BukkitParserDescriptorFactory;
import ac.grim.grimac.platform.bukkit.manager.BukkitPermissionRegistrationManager;
import ac.grim.grimac.platform.bukkit.manager.BukkitPlatformPluginManager;
import ac.grim.grimac.platform.bukkit.player.BukkitPlatformPlayerFactory;
import ac.grim.grimac.platform.bukkit.resolver.BukkitResolverRegistrar;
import ac.grim.grimac.platform.bukkit.scheduler.bukkit.BukkitPlatformScheduler;
import ac.grim.grimac.platform.bukkit.scheduler.folia.FoliaPlatformScheduler;
import ac.grim.grimac.platform.bukkit.sender.BukkitSenderFactory;
import ac.grim.grimac.platform.bukkit.utils.placeholder.PlaceholderAPIExpansion;
import ac.grim.grimac.utils.lazy.LazyHolder;
import com.github.retrooper.packetevents.PacketEventsAPI;
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.brigadier.BrigadierSetting;
import org.incendo.cloud.brigadier.CloudBrigadierManager;
import org.incendo.cloud.bukkit.CloudBukkitCapabilities;
import org.incendo.cloud.execution.ExecutionCoordinator;
import org.incendo.cloud.paper.LegacyPaperCommandManager;
import org.incendo.cloud.setting.Configurable;
public final class GrimACBukkitLoaderPlugin extends JavaPlugin implements PlatformLoader {
public static GrimACBukkitLoaderPlugin LOADER;
private final LazyHolder<PlatformScheduler> scheduler = LazyHolder.simple(this::createScheduler);
private final LazyHolder<PacketEventsAPI<?>> packetEvents = LazyHolder.simple(() -> SpigotPacketEventsBuilder.build(this));
private final LazyHolder<BukkitSenderFactory> senderFactory = LazyHolder.simple(BukkitSenderFactory::new);
private final LazyHolder<CommandManager<Sender>> commandManager = LazyHolder.simple(this::createCommandManager);
private final LazyHolder<ItemResetHandler> itemResetHandler = LazyHolder.simple(BukkitItemResetHandler::new);
@Getter private final PlatformPlayerFactory platformPlayerFactory = new BukkitPlatformPlayerFactory();
@Getter private final CommandAdapter commandAdapter = new BukkitParserDescriptorFactory();
@Getter private final PlatformPluginManager pluginManager = new BukkitPlatformPluginManager();
@Getter private final GrimPlugin plugin;
@Getter private final PlatformServer platformServer = new BukkitPlatformServer();
@Getter private final MessagePlaceHolderManager messagePlaceHolderManager = new BukkitMessagePlaceHolderManager();
@Getter private final BukkitPermissionRegistrationManager permissionManager = new BukkitPermissionRegistrationManager();
public GrimACBukkitLoaderPlugin() {
GrimExtensionManager extensionManager = GrimAPI.INSTANCE.getExtensionManager();
BukkitResolverRegistrar registrar = new BukkitResolverRegistrar(extensionManager);
registrar.registerAll();
this.plugin = registrar.resolvePlugin(this);
}
@Override
public void onLoad() {
LOADER = this;
GrimAPI.INSTANCE.load(this, this.getBukkitInitTasks());
}
private Initable[] getBukkitInitTasks() {
return new Initable[] {
new ExemptOnlinePlayersOnReload(),
new BukkitEventManager(),
new BukkitTickEndEvent(),
new BukkitBStats(),
(StartableInitable) () -> {
if (BukkitMessagePlaceHolderManager.hasPlaceholderAPI) {
new PlaceholderAPIExpansion().register();
}
}
};
}
@Override
public void onEnable() {
GrimAPI.INSTANCE.start();
}
@Override
public void onDisable() {
GrimAPI.INSTANCE.stop();
}
@Override
public PlatformScheduler getScheduler() {
return scheduler.get();
}
@Override
public PacketEventsAPI<?> getPacketEvents() {
return packetEvents.get();
}
@Override
public CommandManager<Sender> getCommandManager() {
return commandManager.get();
}
@Override
public ItemResetHandler getItemResetHandler() {
return itemResetHandler.get();
}
@Override
public SenderFactory<CommandSender> getSenderFactory() {
return senderFactory.get();
}
@Override
public void registerAPIService() {
GrimAPIProvider.init(GrimAPI.INSTANCE.getExternalAPI());
Bukkit.getServicesManager().register(GrimAbstractAPI.class, GrimAPI.INSTANCE.getExternalAPI(), GrimACBukkitLoaderPlugin.LOADER, ServicePriority.Normal);
}
private PlatformScheduler createScheduler() {
return GrimAPI.INSTANCE.getPlatform() == Platform.FOLIA ? new FoliaPlatformScheduler() : new BukkitPlatformScheduler();
}
private CommandManager<Sender> createCommandManager() {
LegacyPaperCommandManager<Sender> manager = new LegacyPaperCommandManager<>(
this,
ExecutionCoordinator.simpleCoordinator(),
senderFactory.get()
);
if (manager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
manager.registerBrigadier();
CloudBrigadierManager<Sender, ?> cbm = manager.brigadierManager();
Configurable<BrigadierSetting> settings = cbm.settings();
settings.set(BrigadierSetting.FORCE_EXECUTABLE, true);
} else if (manager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
manager.registerAsynchronousCompletions();
}
return manager;
}
public BukkitSenderFactory getBukkitSenderFactory() {
return LOADER.senderFactory.get();
}
}
@@ -1,36 +0,0 @@
package ac.grim.grimac.platform.bukkit.command;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.platform.api.command.PlayerSelector;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.platform.bukkit.sender.BukkitSenderFactory;
import lombok.RequiredArgsConstructor;
import org.incendo.cloud.bukkit.data.SinglePlayerSelector;
import java.util.Collection;
import java.util.Collections;
@RequiredArgsConstructor
public class BukkitPlayerSelectorAdapter implements PlayerSelector {
private final SinglePlayerSelector bukkitSelector;
@Override
public boolean isSingle() {
return true;
}
@Override
public Sender getSinglePlayer() {
return ((BukkitSenderFactory) GrimAPI.INSTANCE.getSenderFactory()).map(bukkitSelector.single());
}
@Override
public Collection<Sender> getPlayers() {
return Collections.singletonList(((BukkitSenderFactory) GrimAPI.INSTANCE.getSenderFactory()).map(bukkitSelector.single()));
}
@Override
public String inputString() {
return bukkitSelector.inputString();
}
}
@@ -1,28 +0,0 @@
package ac.grim.grimac.platform.bukkit.command;
import ac.grim.grimac.platform.api.command.AbstractPlayerSelectorParser;
import ac.grim.grimac.platform.api.command.PlayerSelector;
import org.incendo.cloud.bukkit.parser.selector.SinglePlayerSelectorParser;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.parser.ParserDescriptor;
import java.util.concurrent.CompletableFuture;
public class BukkitPlayerSelectorParser<C> extends AbstractPlayerSelectorParser<C> {
@Override
public ParserDescriptor<C, PlayerSelector> descriptor() {
return super.createDescriptor();
}
@Override
protected ParserDescriptor<C, ?> getPlatformSpecificDescriptor() {
return SinglePlayerSelectorParser.singlePlayerSelectorParser();
}
@Override
protected CompletableFuture<PlayerSelector> adaptToCommonSelector(CommandContext<C> context, Object platformSpecificSelector) {
return CompletableFuture.completedFuture(new BukkitPlayerSelectorAdapter((org.incendo.cloud.bukkit.data.SinglePlayerSelector) platformSpecificSelector));
}
}
@@ -1,78 +0,0 @@
package ac.grim.grimac.platform.bukkit.entity;
import ac.grim.grimac.platform.api.entity.GrimEntity;
import ac.grim.grimac.platform.api.world.PlatformWorld;
import ac.grim.grimac.platform.bukkit.utils.convert.BukkitConversionUtils;
import ac.grim.grimac.platform.bukkit.utils.reflection.PaperUtils;
import ac.grim.grimac.platform.bukkit.world.BukkitPlatformWorld;
import ac.grim.grimac.utils.math.Location;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class BukkitGrimEntity implements GrimEntity {
private final Entity entity;
private BukkitPlatformWorld bukkitPlatformWorld;
public BukkitGrimEntity(Entity entity) {
this.entity = Objects.requireNonNull(entity);
}
public Entity getBukkitEntity() {
return this.entity;
}
@Override
public UUID getUniqueId() {
return entity.getUniqueId();
}
@Override
public boolean eject() {
return entity.eject();
}
@Override
public CompletableFuture<Boolean> teleportAsync(Location location) {
org.bukkit.Location bLoc = BukkitConversionUtils.toBukkitLocation(location);
return PaperUtils.teleportAsync(this.entity, bLoc);
}
@Override
@NotNull
public Entity getNative() {
return entity;
}
@Override
public boolean isDead() {
return this.entity.isDead();
}
// TODO replace with PlayerWorldChangeEvent listener instead of checking for equality for better performance
@Override
public PlatformWorld getWorld() {
if (bukkitPlatformWorld == null || !bukkitPlatformWorld.getBukkitWorld().equals(entity.getWorld())) {
bukkitPlatformWorld = new BukkitPlatformWorld(entity.getWorld());
}
return bukkitPlatformWorld;
}
@Override
public Location getLocation() {
org.bukkit.Location location = this.entity.getLocation();
return new Location(
this.getWorld(),
location.getX(),
location.getY(),
location.getZ(),
location.getYaw(),
location.getPitch()
);
}
}
@@ -1,15 +0,0 @@
package ac.grim.grimac.platform.bukkit.initables;
import ac.grim.grimac.manager.init.start.StartableInitable;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import ac.grim.grimac.utils.anticheat.Constants;
import io.github.retrooper.packetevents.bstats.bukkit.Metrics;
public class BukkitBStats implements StartableInitable {
@Override
public void start() {
try {
new Metrics(GrimACBukkitLoaderPlugin.LOADER, Constants.BSTATS_PLUGIN_ID);
} catch (Exception ignored) {}
}
}
@@ -1,15 +0,0 @@
package ac.grim.grimac.platform.bukkit.initables;
import ac.grim.grimac.manager.init.start.StartableInitable;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import ac.grim.grimac.platform.bukkit.events.PistonEvent;
import ac.grim.grimac.utils.anticheat.LogUtil;
import org.bukkit.Bukkit;
public class BukkitEventManager implements StartableInitable {
public void start() {
LogUtil.info("Registering singular bukkit event... (PistonEvent)");
Bukkit.getPluginManager().registerEvents(new PistonEvent(), GrimACBukkitLoaderPlugin.LOADER);
}
}
@@ -1,212 +0,0 @@
package ac.grim.grimac.platform.bukkit.manager;
import ac.grim.grimac.platform.api.manager.ItemResetHandler;
import ac.grim.grimac.platform.api.player.PlatformPlayer;
import ac.grim.grimac.platform.bukkit.utils.reflection.PaperUtils;
import ac.grim.grimac.utils.reflection.ReflectionUtils;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
import org.bukkit.Bukkit;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
public class BukkitItemResetHandler implements ItemResetHandler {
private static final Consumer<Player> resetItemUsage;
private static final Predicate<Player> isUsingItem;
private static final Function<Player, InteractionHand> getItemUsageHand;
@Override
public void resetItemUsage(@Nullable PlatformPlayer player) {
if (player != null) resetItemUsage.accept((Player) player.getNative());
}
@Override
public @Nullable InteractionHand getItemUsageHand(@Nullable PlatformPlayer player) {
return player == null ? null : getItemUsageHand.apply((Player) player.getNative());
}
@Override
public boolean isUsingItem(@Nullable PlatformPlayer player) {
return player != null && isUsingItem.test((Player) player.getNative());
}
static {
final ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
boolean legacy = version.isOlderThanOrEquals(ServerVersion.V_1_8_8);
try {
Method getHandle_ = null;
if (PaperUtils.PAPER && version.isNewerThanOrEquals(ServerVersion.V_1_20_5)) {
Class<?> cls = ReflectionUtils.getClass("org.bukkit.craftbukkit.entity.CraftLivingEntity");
if (cls != null) getHandle_ = cls.getMethod("getHandle");
}
boolean obfuscated = getHandle_ == null;
String nmsPackage = obfuscated ? Bukkit.getServer().getClass().getPackageName().split("\\.")[3] : null;
if (obfuscated) {
String clazzName = legacy ? "CraftHumanEntity" : "CraftLivingEntity";
getHandle_ = Class.forName("org.bukkit.craftbukkit." + nmsPackage + ".entity." + clazzName).getMethod("getHandle");
}
final Method getHandle = getHandle_;
Class<?> clazz = getHandle_.getReturnType();
if (version.isNewerThanOrEquals(ServerVersion.V_1_10)) {
isUsingItem = Player::isHandRaised;
} else {
Method method = clazz.getMethod(switch (Objects.requireNonNull(nmsPackage)) {
case "v1_8_R3" -> "bS";
case "v1_9_R1" -> "cs";
case "v1_9_R2" -> "ct";
default -> throw new IllegalStateException("You are using an unsupported server version! (" + version.getReleaseName() + ")");
});
isUsingItem = player -> {
try {
return (boolean) method.invoke(getHandle.invoke(player));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
}
if (legacy) {
getItemUsageHand = player -> isUsingItem.test(player) ? InteractionHand.MAIN_HAND : null;
} else if (PaperUtils.PAPER && version.isNewerThanOrEquals(ServerVersion.V_1_16_5)) {
getItemUsageHand = player -> player.isHandRaised()
? player.getHandRaised() == EquipmentSlot.OFF_HAND
? InteractionHand.OFF_HAND
: InteractionHand.MAIN_HAND
: null;
} else {
Method method = clazz.getMethod(switch (Objects.requireNonNull(nmsPackage)) {
case "v1_9_R1" -> "ct";
case "v1_9_R2" -> "cu";
case "v1_10_R1" -> "cy";
case "v1_11_R1" -> "cz";
case "v1_12_R1" -> "cH";
case "v1_13_R1", "v1_13_R2", "v1_14_R1" -> "cU";
case "v1_15_R1", "v1_16_R1", "v1_16_R2", "v1_16_R3", "v1_17_R1" -> "getRaisedHand";
case "v1_18_R1" -> "eM";
case "v1_18_R2" -> "eN";
case "v1_19_R1" -> "eU";
case "v1_19_R2" -> "fa";
case "v1_19_R3" -> "ff";
case "v1_20_R1" -> "fj";
case "v1_20_R2" -> "fn";
case "v1_20_R3" -> "fo";
case "v1_20_R4" -> "fw";
case "v1_21_R1" -> "fs";
case "v1_21_R2", "v1_21_R3", "v1_21_R4" -> "fA";
case "v1_21_R5" -> "fH";
case "v1_21_R6" -> "fP";
default -> throw new IllegalStateException("You are using an unsupported server version! (" + version.getReleaseName() + ")");
});
getItemUsageHand = player -> {
try {
return isUsingItem.test(player)
? ((Enum<?>) method.invoke(getHandle.invoke(player))).ordinal() == 0
? InteractionHand.MAIN_HAND
: InteractionHand.OFF_HAND
: null;
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
}
Method setLivingEntityFlag;
if (version.isNewerThanOrEquals(ServerVersion.V_1_19)) {
String name = obfuscated ? "c" : "setLivingEntityFlag";
setLivingEntityFlag = clazz.getDeclaredMethod(name, int.class, boolean.class);
setLivingEntityFlag.setAccessible(true);
} else {
setLivingEntityFlag = null;
}
if (PaperUtils.PAPER && version.isNewerThan(ServerVersion.V_1_17)) {
resetItemUsage = setLivingEntityFlag == null ? LivingEntity::clearActiveItem : player -> {
try {
setLivingEntityFlag.invoke(getHandle.invoke(player), 1, false);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
player.clearActiveItem();
};
} else {
Method method = clazz.getMethod(switch (Objects.requireNonNull(nmsPackage)) {
case "v1_8_R3" -> "bV";
case "v1_9_R1" -> "cz";
case "v1_9_R2" -> "cA";
case "v1_10_R1" -> "cE";
case "v1_11_R1" -> "cF";
case "v1_12_R1" -> "cN";
case "v1_13_R1", "v1_13_R2" -> "da";
case "v1_14_R1" -> "dp";
case "v1_15_R1" -> "dH";
case "v1_16_R1", "v1_16_R2", "v1_16_R3", "v1_17_R1" -> "clearActiveItem";
case "v1_18_R1" -> "eR";
case "v1_18_R2" -> "eS";
case "v1_19_R1" -> "eZ";
case "v1_19_R2" -> "ff";
case "v1_19_R3" -> "fk";
case "v1_20_R1" -> "fo";
case "v1_20_R2" -> "fs";
case "v1_20_R3" -> "ft";
case "v1_20_R4" -> "fB";
case "v1_21_R1" -> "fx";
case "v1_21_R2", "v1_21_R3", "v1_21_R4" -> "fF";
case "v1_21_R5" -> "fM";
case "v1_21_R6" -> "fU";
default -> throw new IllegalStateException("You are using an unsupported server version! (" + version.getReleaseName() + ")");
});
if (legacy) { // 1.8.8
resetItemUsage = player -> {
try {
// in 1.8 we need to resync item usage manually,
// only do so if the player is using an item
if (isUsingItem.test(player)) player.updateInventory();
method.invoke(getHandle.invoke(player));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
} else if (setLivingEntityFlag == null) { // 1.9-1.18.2
resetItemUsage = player -> {
try {
method.invoke(getHandle.invoke(player));
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
} else { // 1.19+
resetItemUsage = player -> {
try {
Object handle = getHandle.invoke(player);
setLivingEntityFlag.invoke(handle, 1, false);
method.invoke(handle);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
}
}
} catch (Throwable t) {
throw t instanceof RuntimeException e ? e : new RuntimeException(t);
}
}
}
@@ -1,19 +0,0 @@
package ac.grim.grimac.platform.bukkit.manager;
import ac.grim.grimac.platform.api.manager.MessagePlaceHolderManager;
import ac.grim.grimac.platform.api.player.PlatformPlayer;
import ac.grim.grimac.platform.bukkit.player.BukkitPlatformPlayer;
import com.github.retrooper.packetevents.util.reflection.Reflection;
import me.clip.placeholderapi.PlaceholderAPI;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class BukkitMessagePlaceHolderManager implements MessagePlaceHolderManager {
public static final boolean hasPlaceholderAPI = Reflection.getClassByNameWithoutException("me.clip.placeholderapi.PlaceholderAPI") != null;
@Override
public @NotNull String replacePlaceholders(@Nullable PlatformPlayer player, @NotNull String string) {
if (!hasPlaceholderAPI) return string;
return PlaceholderAPI.setPlaceholders(player instanceof BukkitPlatformPlayer bukkitPlatformPlayer ? bukkitPlatformPlayer.getBukkitPlayer() : null, string);
}
}
@@ -1,45 +0,0 @@
package ac.grim.grimac.platform.bukkit.manager;
import ac.grim.grimac.platform.api.command.PlayerSelector;
import ac.grim.grimac.platform.api.manager.CommandAdapter;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.platform.bukkit.command.BukkitPlayerSelectorParser;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.incendo.cloud.bukkit.BukkitCommandContextKeys;
import org.incendo.cloud.parser.ParserDescriptor;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class BukkitParserDescriptorFactory implements CommandAdapter {
// Parser is kept as a field because its stateless
private final BukkitPlayerSelectorParser<Sender> bukkitPlayerSelectorParser = new BukkitPlayerSelectorParser<>();
@Override
public ParserDescriptor<Sender, PlayerSelector> singlePlayerSelectorParser() {
return bukkitPlayerSelectorParser.descriptor();
}
// TODO (Cross-platform) better + brigadier suggestions
@Override
public SuggestionProvider<Sender> onlinePlayerSuggestions() {
return (context, input) -> {
List<Suggestion> suggestions = new ArrayList<>();
for(Player player : Bukkit.getOnlinePlayers()) {
CommandSender bukkit = context.get(BukkitCommandContextKeys.BUKKIT_COMMAND_SENDER);
if (!(bukkit instanceof Player) || ((Player)bukkit).canSee(player)) {
suggestions.add(Suggestion.suggestion(player.getName()));
}
}
return CompletableFuture.completedFuture(suggestions);
};
}
}
@@ -1,33 +0,0 @@
package ac.grim.grimac.platform.bukkit.manager;
import ac.grim.grimac.platform.api.manager.PermissionRegistrationManager;
import ac.grim.grimac.platform.api.permissions.PermissionDefaultValue;
import ac.grim.grimac.platform.bukkit.utils.convert.BukkitConversionUtils;
import org.bukkit.Bukkit;
import org.bukkit.permissions.Permission;
public class BukkitPermissionRegistrationManager implements PermissionRegistrationManager {
/**
* Registers a permission with the specified default value on Bukkit.
* This method is only called for dynamic permissions (e.g., check-specific permissions
* like "grim.exempt.checkname") that are generated at runtime. Most other static permissions
* (e.g., "grim.exempt", "grim.alerts.enable-on-join") are registered with their defaults
* in the `plugin.yml` file, which is defined in the Bukkit Gradle build script.
*
* <p>Dynamic permissions are registered here to ensure they are available for autocomplete
* and permission checks immediately on startup. If the permission already exists, its default
* value is updated to match the specified value.</p>
*
* @param name The permission node to register (e.g., "grim.exempt.checkname").
* @param defaultValue The default value for the permission.
*/
@Override
public void registerPermission(String name, PermissionDefaultValue defaultValue) {
final Permission bukkitPermission = Bukkit.getPluginManager().getPermission(name);
if (bukkitPermission == null) {
Bukkit.getPluginManager().addPermission(new Permission(name, BukkitConversionUtils.toBukkitPermissionDefault(defaultValue)));
} else {
bukkitPermission.setDefault(BukkitConversionUtils.toBukkitPermissionDefault(defaultValue));
}
}
}
@@ -1,29 +0,0 @@
package ac.grim.grimac.platform.bukkit.manager;
import ac.grim.grimac.platform.api.PlatformPlugin;
import ac.grim.grimac.platform.api.manager.PlatformPluginManager;
import ac.grim.grimac.platform.bukkit.BukkitPlatformPlugin;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.Nullable;
public class BukkitPlatformPluginManager implements PlatformPluginManager {
@Override
public PlatformPlugin[] getPlugins() {
Plugin[] bukkitPlugins = Bukkit.getPluginManager().getPlugins();
PlatformPlugin[] plugins = new PlatformPlugin[bukkitPlugins.length];
for (int i = 0; i < bukkitPlugins.length; i++) {
plugins[i] = new BukkitPlatformPlugin(bukkitPlugins[i]);
}
return plugins;
}
@Override
public @Nullable PlatformPlugin getPlugin(String pluginName) {
Plugin bukkitPlugin = Bukkit.getPluginManager().getPlugin(pluginName);
return bukkitPlugin == null ? null : new BukkitPlatformPlugin(bukkitPlugin);
}
}
@@ -1,34 +0,0 @@
package ac.grim.grimac.platform.bukkit.player;
import ac.grim.grimac.platform.api.player.OfflinePlatformPlayer;
import lombok.RequiredArgsConstructor;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import java.util.UUID;
@RequiredArgsConstructor
public class BukkitOfflinePlatformPlayer implements OfflinePlatformPlayer {
private final OfflinePlayer offlinePlayer;
@Override
public boolean isOnline() {
return offlinePlayer.isOnline();
}
@Override
public @NotNull String getName() {
return Objects.requireNonNull(offlinePlayer.getName());
}
@Override
public @NotNull UUID getUniqueId() {
return offlinePlayer.getUniqueId();
}
@Override
public boolean equals(Object o) {
return o instanceof OfflinePlatformPlayer player && this.getUniqueId().equals(player.getUniqueId());
}
}
@@ -1,64 +0,0 @@
package ac.grim.grimac.platform.bukkit.player;
import ac.grim.grimac.platform.api.player.PlatformInventory;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import lombok.RequiredArgsConstructor;
import org.bukkit.entity.Player;
@RequiredArgsConstructor
public class BukkitPlatformInventory implements PlatformInventory {
private final Player bukkitPlayer;
@Override
public ItemStack getItemInHand() {
return SpigotConversionUtil.fromBukkitItemStack(bukkitPlayer.getInventory().getItemInHand());
}
@Override
public ItemStack getItemInOffHand() {
return SpigotConversionUtil.fromBukkitItemStack(bukkitPlayer.getInventory().getItemInOffHand());
}
@Override
public ItemStack getStack(int bukkitSlot, int vanillaSlot) {
return SpigotConversionUtil.fromBukkitItemStack(bukkitPlayer.getInventory().getItem(bukkitSlot));
}
@Override
public ItemStack getHelmet() {
return SpigotConversionUtil.fromBukkitItemStack(bukkitPlayer.getInventory().getHelmet());
}
@Override
public ItemStack getChestplate() {
return SpigotConversionUtil.fromBukkitItemStack(bukkitPlayer.getInventory().getChestplate());
}
@Override
public ItemStack getLeggings() {
return SpigotConversionUtil.fromBukkitItemStack(bukkitPlayer.getInventory().getLeggings());
}
@Override
public ItemStack getBoots() {
return SpigotConversionUtil.fromBukkitItemStack(bukkitPlayer.getInventory().getBoots());
}
@Override
public ItemStack[] getContents() {
org.bukkit.inventory.ItemStack[] bukkitItems = bukkitPlayer.getInventory().getContents();
ItemStack[] items = new ItemStack[bukkitItems.length];
for (int i = 0; i < bukkitItems.length; i++) {
if (bukkitItems[i] == null) continue;
items[i] = SpigotConversionUtil.fromBukkitItemStack(bukkitItems[i]);
}
return items;
}
@Override
public String getOpenInventoryKey() {
return bukkitPlayer.getOpenInventory().getType().toString();
}
}
@@ -1,174 +0,0 @@
package ac.grim.grimac.platform.bukkit.player;
import ac.grim.grimac.platform.api.entity.GrimEntity;
import ac.grim.grimac.platform.api.player.PlatformInventory;
import ac.grim.grimac.platform.api.player.PlatformPlayer;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import ac.grim.grimac.platform.bukkit.entity.BukkitGrimEntity;
import ac.grim.grimac.platform.bukkit.utils.anticheat.MultiLibUtil;
import ac.grim.grimac.platform.bukkit.utils.convert.BukkitConversionUtils;
import ac.grim.grimac.platform.bukkit.utils.reflection.PaperUtils;
import ac.grim.grimac.utils.common.arguments.CommonGrimArguments;
import ac.grim.grimac.utils.math.Location;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.player.GameMode;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.util.Vector3d;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import lombok.Getter;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.Component;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class BukkitPlatformPlayer extends BukkitGrimEntity implements PlatformPlayer {
private static final BukkitAudiences audiences = BukkitAudiences.create(GrimACBukkitLoaderPlugin.LOADER);
@Getter
private final Player bukkitPlayer;
@Getter
private final PlatformInventory inventory;
private final @Nullable User user;
public BukkitPlatformPlayer(Player bukkitPlayer) {
super(bukkitPlayer);
this.bukkitPlayer = bukkitPlayer;
this.inventory = new BukkitPlatformInventory(bukkitPlayer);
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value()) {
Object channel = PacketEvents.getAPI().getProtocolManager().getChannel(bukkitPlayer.getUniqueId());
this.user = PacketEvents.getAPI().getProtocolManager().getUser(channel);
} else {
this.user = null;
}
}
@Override
public void kickPlayer(String textReason) {
bukkitPlayer.kickPlayer(textReason);
}
@Override
public boolean hasPermission(String s) {
return bukkitPlayer.hasPermission(s);
}
@Override
public boolean hasPermission(String s, boolean defaultIfUnset) {
return this.bukkitPlayer.hasPermission(new Permission(s, defaultIfUnset ? PermissionDefault.TRUE : PermissionDefault.FALSE));
}
@Override
public boolean isSneaking() {
return bukkitPlayer.isSneaking();
}
@Override
public void setSneaking(boolean isSneaking) {
bukkitPlayer.setSneaking(isSneaking);
}
@Override
public void sendMessage(String message) {
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value() && user != null) {
user.sendMessage(message);
} else {
bukkitPlayer.sendMessage(message);
}
}
@Override
public void sendMessage(Component message) {
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value() && user != null) {
user.sendMessage(message);
} else {
audiences.player(bukkitPlayer).sendMessage(message);
}
}
@Override
public boolean isOnline() {
return bukkitPlayer.isOnline();
}
@Override
public String getName() {
return bukkitPlayer.getName();
}
@Override
public void updateInventory() {
bukkitPlayer.updateInventory();
}
@Override
public Vector3d getPosition() {
org.bukkit.Location location = this.bukkitPlayer.getLocation();
return new Vector3d(location.getX(), location.getY(), location.getZ());
}
@Override
public @Nullable GrimEntity getVehicle() {
return bukkitPlayer.getVehicle() == null ? null : new BukkitGrimEntity(bukkitPlayer.getVehicle());
}
@Override
public GameMode getGameMode() {
return SpigotConversionUtil.fromBukkitGameMode(bukkitPlayer.getGameMode());
}
@Override
public void setGameMode(GameMode gameMode) {
bukkitPlayer.setGameMode(SpigotConversionUtil.toBukkitGameMode(gameMode));
}
public World getBukkitWorld() {
return bukkitPlayer.getWorld();
}
@Override
public UUID getUniqueId() {
return bukkitPlayer.getUniqueId();
}
@Override
public boolean eject() {
return bukkitPlayer.eject();
}
@Override
public CompletableFuture<Boolean> teleportAsync(Location location) {
org.bukkit.Location bLoc = BukkitConversionUtils.toBukkitLocation(location);
return PaperUtils.teleportAsync(this.bukkitPlayer, bLoc);
}
@Override
public boolean isExternalPlayer() {
return MultiLibUtil.isExternalPlayer(this.bukkitPlayer);
}
@Override
public void sendPluginMessage(String channelName, byte[] byteArray) {
this.bukkitPlayer.sendPluginMessage(GrimACBukkitLoaderPlugin.LOADER, channelName, byteArray);
}
@Override
public Sender getSender() {
return GrimACBukkitLoaderPlugin.LOADER.getBukkitSenderFactory().map(this.bukkitPlayer);
}
@Override
@NotNull
public Player getNative() {
return this.bukkitPlayer;
}
}
@@ -1,57 +0,0 @@
package ac.grim.grimac.platform.bukkit.player;
import ac.grim.grimac.platform.api.player.AbstractPlatformPlayerFactory;
import ac.grim.grimac.platform.api.player.OfflinePlatformPlayer;
import ac.grim.grimac.platform.api.player.PlatformPlayer;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.UUID;
public class BukkitPlatformPlayerFactory extends AbstractPlatformPlayerFactory<Player> {
@Override
protected Player getNativePlayer(@NotNull UUID uuid) {
return Bukkit.getPlayer(uuid);
}
@Override
protected Player getNativePlayer(@NotNull String name) {
return Bukkit.getPlayer(name);
}
@Override
protected PlatformPlayer createPlatformPlayer(@NotNull Player nativePlayer) {
return new BukkitPlatformPlayer(nativePlayer);
}
@Override
protected UUID getPlayerUUID(@NotNull Player nativePlayer) {
return nativePlayer.getUniqueId();
}
// The cast is safe because Bukkit.getOnlinePlayers() is guaranteed to contain Player or its subtypes,
// and we're only reading from it.
@Override
@SuppressWarnings("unchecked")
protected Collection<Player> getNativeOnlinePlayers() {
// Cast Collection<? extends Player> to Collection<Player>
return (Collection<Player>) Bukkit.getOnlinePlayers();
}
@Override
public OfflinePlatformPlayer getOfflineFromUUID(@NotNull UUID uuid) {
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid);
return new BukkitOfflinePlatformPlayer(offlinePlayer);
}
@Override
public OfflinePlatformPlayer getOfflineFromName(@NotNull String name) {
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(name);
return new BukkitOfflinePlatformPlayer(offlinePlayer);
}
}
@@ -1,111 +0,0 @@
package ac.grim.grimac.platform.bukkit.resolver;
import ac.grim.grimac.api.plugin.BasicGrimPlugin;
import ac.grim.grimac.api.plugin.GrimPlugin;
import ac.grim.grimac.events.GrimExtensionManager;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Manages the registration of Bukkit-specific resolvers with the GrimExtensionManager.
* This class is designed to be instantiated once during plugin startup.
*/
public final class BukkitResolverRegistrar {
private final GrimExtensionManager extensionManager;
// Cache to ensure we only create one GrimPlugin wrapper per Bukkit Plugin instance.
private final Map<Plugin, GrimPlugin> pluginCache = new ConcurrentHashMap<>();
public BukkitResolverRegistrar(GrimExtensionManager extensionManager) {
this.extensionManager = extensionManager;
}
/**
* Registers all the Bukkit-specific resolvers in order of performance (fastest to slowest).
*/
public void registerAll() {
extensionManager.setFailureHandler(this::createFailureException);
extensionManager.registerResolver(this::resolvePluginInstance);
extensionManager.registerResolver(this::resolveStringName);
extensionManager.registerResolver(this::resolveClass);
}
/**
* The core logic for converting a Bukkit Plugin into a GrimPlugin, with caching.
*/
public GrimPlugin resolvePlugin(Plugin bukkitPlugin) {
return pluginCache.computeIfAbsent(bukkitPlugin, plugin -> {
PluginDescriptionFile desc = plugin.getDescription();
return new BasicGrimPlugin(
plugin.getLogger(),
plugin.getDataFolder(),
desc.getVersion(),
desc.getDescription(),
desc.getAuthors()
);
});
}
/**
* 1. Resolver for raw Plugin instances (the most common case).
*/
private GrimPlugin resolvePluginInstance(Object context) {
if (context instanceof Plugin bukkitPlugin) {
return resolvePlugin(bukkitPlugin);
}
return null;
}
/**
* 2. Resolver for String plugin names.
*/
private GrimPlugin resolveStringName(Object context) {
if (context instanceof String pluginName) {
// Use the Bukkit API to look up the plugin by name. This returns null if not found.
Plugin bukkitPlugin = Bukkit.getPluginManager().getPlugin(pluginName);
// We must check for null before applying the logic to avoid a NullPointerException.
return (bukkitPlugin != null) ? resolvePlugin(bukkitPlugin) : null;
}
return null;
}
/**
* 3. Resolver for Class objects.
*/
private GrimPlugin resolveClass(Object context) {
if (context instanceof Class) {
try {
// First, resolve the Class to a Plugin instance.
JavaPlugin providingPlugin = JavaPlugin.getProvidingPlugin((Class<?>) context);
// Then, use our shared logic directly to get the GrimPlugin wrapper.
return resolvePlugin(providingPlugin);
} catch (IllegalArgumentException | IllegalStateException e) {
// This is an expected failure if the class is not from a plugin
// or is called from a static initializer. We simply indicate that
// this resolver cannot handle this context.
return null;
}
}
// This resolver only handles Classes.
return null;
}
private RuntimeException createFailureException(Object failedContext) {
String message = """
Failed to resolve GrimPlugin context from the provided object of type '%s'.
Please ensure you are passing one of the following:
- The main instance of your plugin (e.g., 'this' from your class extending JavaPlugin).
- The plugin name as a String (e.g., "MyPluginName").
- Any Class from your plugin's JAR file (e.g., MyListener.class).
- A pre-existing GrimPlugin instance.
""".formatted(failedContext.getClass().getName());
return new IllegalArgumentException(message);
}
}
@@ -1,56 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.bukkit;
import ac.grim.grimac.api.plugin.GrimPlugin;
import ac.grim.grimac.platform.api.scheduler.AsyncScheduler;
import ac.grim.grimac.platform.api.scheduler.PlatformScheduler;
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitScheduler;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.TimeUnit;
public class BukkitAsyncScheduler implements AsyncScheduler {
private final BukkitScheduler bukkitScheduler = Bukkit.getScheduler();
@Override
public TaskHandle runNow(@NotNull GrimPlugin plugin, @NotNull Runnable task) {
return new BukkitTaskHandle(bukkitScheduler.runTaskAsynchronously(GrimACBukkitLoaderPlugin.LOADER, task));
}
@Override
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay, @NotNull TimeUnit timeUnit) {
return new BukkitTaskHandle(bukkitScheduler.runTaskLaterAsynchronously(
GrimACBukkitLoaderPlugin.LOADER,
task,
PlatformScheduler.convertTimeToTicks(delay, timeUnit)
));
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay, long period, @NotNull TimeUnit timeUnit) {
return new BukkitTaskHandle(bukkitScheduler.runTaskTimerAsynchronously(
GrimACBukkitLoaderPlugin.LOADER,
task,
PlatformScheduler.convertTimeToTicks(delay, timeUnit),
PlatformScheduler.convertTimeToTicks(period, timeUnit)
));
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
return new BukkitTaskHandle(bukkitScheduler.runTaskTimerAsynchronously(
GrimACBukkitLoaderPlugin.LOADER,
task,
initialDelayTicks,
periodTicks
));
}
@Override
public void cancel(@NotNull GrimPlugin plugin) {
bukkitScheduler.cancelTasks(GrimACBukkitLoaderPlugin.LOADER);
}
}
@@ -1,35 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.bukkit;
import ac.grim.grimac.api.plugin.GrimPlugin;
import ac.grim.grimac.platform.api.entity.GrimEntity;
import ac.grim.grimac.platform.api.scheduler.EntityScheduler;
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitScheduler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class BukkitEntityScheduler implements EntityScheduler {
private final BukkitScheduler scheduler = Bukkit.getScheduler();
@Override
public void execute(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable run, @Nullable Runnable retired, long delay) {
scheduler.runTaskLater(GrimACBukkitLoaderPlugin.LOADER, run, delay);
}
@Override
public TaskHandle run(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired) {
return new BukkitTaskHandle(scheduler.runTask(GrimACBukkitLoaderPlugin.LOADER, task));
}
@Override
public TaskHandle runDelayed(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired, long delayTicks) {
return new BukkitTaskHandle(scheduler.runTaskLater(GrimACBukkitLoaderPlugin.LOADER, task, delayTicks));
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired, long initialDelayTicks, long periodTicks) {
return new BukkitTaskHandle(scheduler.runTaskTimer(GrimACBukkitLoaderPlugin.LOADER, task, initialDelayTicks, periodTicks));
}
}
@@ -1,39 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.bukkit;
import ac.grim.grimac.api.plugin.GrimPlugin;
import ac.grim.grimac.platform.api.scheduler.GlobalRegionScheduler;
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitScheduler;
import org.jetbrains.annotations.NotNull;
public class BukkitGlobalRegionScheduler implements GlobalRegionScheduler {
private final BukkitScheduler bukkitScheduler = Bukkit.getScheduler();
@Override
public void execute(@NotNull GrimPlugin plugin, @NotNull Runnable task) {
bukkitScheduler.runTask(GrimACBukkitLoaderPlugin.LOADER, task);
}
@Override
public TaskHandle run(@NotNull GrimPlugin plugin, @NotNull Runnable task) {
return new BukkitTaskHandle(bukkitScheduler.runTask(GrimACBukkitLoaderPlugin.LOADER, task));
}
@Override
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay) {
return new BukkitTaskHandle(bukkitScheduler.runTaskLater(GrimACBukkitLoaderPlugin.LOADER, task, delay));
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
return new BukkitTaskHandle(bukkitScheduler.runTaskTimer(GrimACBukkitLoaderPlugin.LOADER, task, initialDelayTicks, periodTicks));
}
@Override
public void cancel(@NotNull GrimPlugin plugin) {
bukkitScheduler.cancelTasks(GrimACBukkitLoaderPlugin.LOADER);
}
}
@@ -1,13 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.bukkit;
import ac.grim.grimac.platform.api.scheduler.PlatformScheduler;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
@Getter
public class BukkitPlatformScheduler implements PlatformScheduler {
private final @NotNull BukkitAsyncScheduler asyncScheduler = new BukkitAsyncScheduler();
private final @NotNull BukkitGlobalRegionScheduler globalRegionScheduler = new BukkitGlobalRegionScheduler();
private final @NotNull BukkitEntityScheduler entityScheduler = new BukkitEntityScheduler();
private final @NotNull BukkitRegionScheduler regionScheduler = new BukkitRegionScheduler();
}
@@ -1,56 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.bukkit;
import ac.grim.grimac.api.plugin.GrimPlugin;
import ac.grim.grimac.platform.api.scheduler.RegionScheduler;
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
import ac.grim.grimac.platform.api.world.PlatformWorld;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import ac.grim.grimac.utils.math.Location;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitScheduler;
import org.jetbrains.annotations.NotNull;
public class BukkitRegionScheduler implements RegionScheduler {
private final BukkitScheduler bukkitScheduler = Bukkit.getScheduler();
@Override
public void execute(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable task) {
bukkitScheduler.runTask(GrimACBukkitLoaderPlugin.LOADER, task);
}
@Override
public void execute(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable task) {
bukkitScheduler.runTask(GrimACBukkitLoaderPlugin.LOADER, task);
}
@Override
public TaskHandle run(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable task) {
return new BukkitTaskHandle(bukkitScheduler.runTask(GrimACBukkitLoaderPlugin.LOADER, task));
}
@Override
public TaskHandle run(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable task) {
return new BukkitTaskHandle(bukkitScheduler.runTask(GrimACBukkitLoaderPlugin.LOADER, task));
}
@Override
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable task, long delayTicks) {
return new BukkitTaskHandle(bukkitScheduler.runTaskLater(GrimACBukkitLoaderPlugin.LOADER, task, delayTicks));
}
@Override
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable task, long delayTicks) {
return new BukkitTaskHandle(bukkitScheduler.runTaskLater(GrimACBukkitLoaderPlugin.LOADER, task, delayTicks));
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
return new BukkitTaskHandle(bukkitScheduler.runTaskTimer(GrimACBukkitLoaderPlugin.LOADER, task, initialDelayTicks, periodTicks));
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
return new BukkitTaskHandle(bukkitScheduler.runTaskTimer(GrimACBukkitLoaderPlugin.LOADER, task, initialDelayTicks, periodTicks));
}
}
@@ -1,33 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.bukkit;
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class BukkitTaskHandle implements TaskHandle {
private final @NotNull BukkitTask task;
@Contract(pure = true)
public BukkitTaskHandle(@NotNull BukkitTask task) {
this.task = Objects.requireNonNull(task);
}
@Override
public boolean isSync() {
return task.isSync();
}
@Override
public boolean isCancelled() {
return task.isCancelled();
}
@Override
public void cancel() {
task.cancel();
}
}
@@ -1,57 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.folia;
import ac.grim.grimac.api.plugin.GrimPlugin;
import ac.grim.grimac.platform.api.scheduler.AsyncScheduler;
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.TimeUnit;
public class FoliaAsyncScheduler implements AsyncScheduler {
private final io.papermc.paper.threadedregions.scheduler.AsyncScheduler scheduler = Bukkit.getAsyncScheduler();
@Override
public TaskHandle runNow(@NotNull GrimPlugin plugin, @NotNull Runnable task) {
return new FoliaTaskHandle(scheduler.runNow(GrimACBukkitLoaderPlugin.LOADER, ignored -> task.run()));
}
@Override
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay, @NotNull TimeUnit timeUnit) {
return new FoliaTaskHandle(scheduler.runDelayed(
GrimACBukkitLoaderPlugin.LOADER,
ignored -> task.run(),
delay,
timeUnit
));
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay, long period, @NotNull TimeUnit timeUnit) {
return new FoliaTaskHandle(scheduler.runAtFixedRate(
GrimACBukkitLoaderPlugin.LOADER,
ignored -> task.run(),
delay,
period,
timeUnit
));
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
return new FoliaTaskHandle(scheduler.runAtFixedRate(
GrimACBukkitLoaderPlugin.LOADER,
ignored -> task.run(),
initialDelayTicks * 50,
periodTicks * 50,
TimeUnit.MILLISECONDS
));
}
@Override
public void cancel(@NotNull GrimPlugin plugin) {
scheduler.cancelTasks(GrimACBukkitLoaderPlugin.LOADER);
}
}
@@ -1,55 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.folia;
import ac.grim.grimac.api.plugin.GrimPlugin;
import ac.grim.grimac.platform.api.entity.GrimEntity;
import ac.grim.grimac.platform.api.scheduler.EntityScheduler;
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import ac.grim.grimac.platform.bukkit.entity.BukkitGrimEntity;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class FoliaEntityScheduler implements EntityScheduler {
@Override
public void execute(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired, long delay) {
((BukkitGrimEntity) entity).getBukkitEntity().getScheduler().execute(GrimACBukkitLoaderPlugin.LOADER, task, retired, delay);
}
@Override
public TaskHandle run(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired) {
ScheduledTask scheduled = ((BukkitGrimEntity) entity).getBukkitEntity().getScheduler().run(
GrimACBukkitLoaderPlugin.LOADER,
ignored -> task.run(),
retired
);
return scheduled == null ? null : new FoliaTaskHandle(scheduled);
}
@Override
public TaskHandle runDelayed(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired, long delayTicks) {
ScheduledTask scheduled = ((BukkitGrimEntity) entity).getBukkitEntity().getScheduler().runDelayed(
GrimACBukkitLoaderPlugin.LOADER,
ignored -> task.run(),
retired,
delayTicks
);
return scheduled == null ? null : new FoliaTaskHandle(scheduled);
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimEntity entity, @NotNull GrimPlugin plugin, @NotNull Runnable task, @Nullable Runnable retired, long initialDelayTicks, long periodTicks) {
ScheduledTask scheduled = ((BukkitGrimEntity) entity).getBukkitEntity().getScheduler().runAtFixedRate(
GrimACBukkitLoaderPlugin.LOADER,
ignored -> task.run(),
retired,
initialDelayTicks,
periodTicks
);
return scheduled == null ? null : new FoliaTaskHandle(scheduled);
}
}
@@ -1,38 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.folia;
import ac.grim.grimac.api.plugin.GrimPlugin;
import ac.grim.grimac.platform.api.scheduler.GlobalRegionScheduler;
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
private final io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler globalRegionScheduler = Bukkit.getGlobalRegionScheduler();
@Override
public void execute(@NotNull GrimPlugin plugin, @NotNull Runnable task) {
globalRegionScheduler.execute(GrimACBukkitLoaderPlugin.LOADER, task);
}
@Override
public TaskHandle run(@NotNull GrimPlugin plugin, @NotNull Runnable task) {
return new FoliaTaskHandle(globalRegionScheduler.run(GrimACBukkitLoaderPlugin.LOADER, ignored -> task.run()));
}
@Override
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull Runnable task, long delay) {
return new FoliaTaskHandle(globalRegionScheduler.runDelayed(GrimACBukkitLoaderPlugin.LOADER, ignored -> task.run(), delay));
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
return new FoliaTaskHandle(globalRegionScheduler.runAtFixedRate(GrimACBukkitLoaderPlugin.LOADER, ignored -> task.run(), initialDelayTicks, periodTicks));
}
@Override
public void cancel(@NotNull GrimPlugin plugin) {
globalRegionScheduler.cancelTasks(GrimACBukkitLoaderPlugin.LOADER);
}
}
@@ -1,13 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.folia;
import ac.grim.grimac.platform.api.scheduler.PlatformScheduler;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
@Getter
public class FoliaPlatformScheduler implements PlatformScheduler {
private final @NotNull FoliaAsyncScheduler asyncScheduler = new FoliaAsyncScheduler();
private final @NotNull FoliaGlobalRegionScheduler globalRegionScheduler = new FoliaGlobalRegionScheduler();
private final @NotNull FoliaEntityScheduler entityScheduler = new FoliaEntityScheduler();
private final @NotNull FoliaRegionScheduler regionScheduler = new FoliaRegionScheduler();
}
@@ -1,85 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.folia;
import ac.grim.grimac.api.plugin.GrimPlugin;
import ac.grim.grimac.platform.api.scheduler.RegionScheduler;
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
import ac.grim.grimac.platform.api.world.PlatformWorld;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import ac.grim.grimac.platform.bukkit.world.BukkitPlatformWorld;
import ac.grim.grimac.utils.math.Location;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
public class FoliaRegionScheduler implements RegionScheduler {
private final io.papermc.paper.threadedregions.scheduler.RegionScheduler regionScheduler = Bukkit.getRegionScheduler();
@Override
public void execute(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable task) {
regionScheduler.execute(GrimACBukkitLoaderPlugin.LOADER, ((BukkitPlatformWorld) world).getBukkitWorld(), chunkX, chunkZ, task);
}
@Override
public void execute(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable task) {
execute(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task);
}
@Override
public TaskHandle run(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable task) {
return new FoliaTaskHandle(regionScheduler.run(
GrimACBukkitLoaderPlugin.LOADER,
((BukkitPlatformWorld) world).getBukkitWorld(),
chunkX,
chunkZ,
ignored -> task.run()
));
}
@Override
public TaskHandle run(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable task) {
return run(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task);
}
@Override
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable task, long delayTicks) {
return new FoliaTaskHandle(regionScheduler.runDelayed(
GrimACBukkitLoaderPlugin.LOADER,
((BukkitPlatformWorld) world).getBukkitWorld(),
chunkX,
chunkZ,
ignored -> task.run(),
delayTicks
));
}
@Override
public TaskHandle runDelayed(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable task, long delayTicks) {
return runDelayed(plugin, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4, task, delayTicks);
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull PlatformWorld world, int chunkX, int chunkZ, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
return new FoliaTaskHandle(regionScheduler.runAtFixedRate(
GrimACBukkitLoaderPlugin.LOADER,
((BukkitPlatformWorld) world).getBukkitWorld(),
chunkX,
chunkZ,
ignored -> task.run(),
initialDelayTicks,
periodTicks
));
}
@Override
public TaskHandle runAtFixedRate(@NotNull GrimPlugin plugin, @NotNull Location location, @NotNull Runnable task, long initialDelayTicks, long periodTicks) {
return runAtFixedRate(
plugin,
location.getWorld(),
location.getBlockX() >> 4,
location.getBlockZ() >> 4,
task,
initialDelayTicks,
periodTicks
);
}
}
@@ -1,33 +0,0 @@
package ac.grim.grimac.platform.bukkit.scheduler.folia;
import ac.grim.grimac.platform.api.scheduler.TaskHandle;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class FoliaTaskHandle implements TaskHandle {
private final @NotNull ScheduledTask task;
@Contract(pure = true)
public FoliaTaskHandle(@NotNull ScheduledTask task) {
this.task = Objects.requireNonNull(task);
}
@Override
public boolean isSync() {
return false;
}
@Override
public boolean isCancelled() {
return task.isCancelled();
}
@Override
public void cancel() {
task.cancel();
}
}
@@ -1,89 +0,0 @@
package ac.grim.grimac.platform.bukkit.sender;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.platform.api.sender.SenderFactory;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.RemoteConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.incendo.cloud.SenderMapper;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class BukkitSenderFactory extends SenderFactory<CommandSender> implements SenderMapper<CommandSender, Sender> {
private final BukkitAudiences audiences;
public BukkitSenderFactory() {
this.audiences = BukkitAudiences.create(GrimACBukkitLoaderPlugin.LOADER);
}
@Override
protected String getName(CommandSender sender) {
return sender instanceof Player ? sender.getName() : Sender.CONSOLE_NAME;
}
@Override
protected UUID getUniqueId(CommandSender sender) {
return sender instanceof Player player ? player.getUniqueId() : Sender.CONSOLE_UUID;
}
@Override
protected void sendMessage(CommandSender sender, String message) {
sender.sendMessage(message);
}
@Override
protected void sendMessage(CommandSender sender, Component message) {
// we can safely send async for players and the console - otherwise, send it sync
if (sender instanceof Player || sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender) {
this.audiences.sender(sender).sendMessage(message);
} else {
GrimAPI.INSTANCE.getScheduler().getGlobalRegionScheduler().run(
GrimAPI.INSTANCE.getGrimPlugin(),
() -> this.audiences.sender(sender).sendMessage(message)
);
}
}
@Override
protected boolean hasPermission(CommandSender sender, String node) {
return sender.hasPermission(node);
}
@Override
protected boolean hasPermission(CommandSender sender, String node, boolean defaultIfUnset) {
return sender.hasPermission(new Permission(node, defaultIfUnset ? PermissionDefault.TRUE : PermissionDefault.FALSE));
}
@Override
protected void performCommand(CommandSender sender, String command) {
throw new UnsupportedOperationException();
}
@Override
protected boolean isConsole(CommandSender sender) {
return sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender;
}
@Override
protected boolean isPlayer(CommandSender sender) {
return sender instanceof Player;
}
@Override
public @NotNull Sender map(@NotNull CommandSender base) {
return this.wrap(base);
}
@Override
public @NotNull CommandSender reverse(@NotNull Sender mapped) {
return this.unwrap(mapped);
}
}
@@ -1,26 +0,0 @@
package ac.grim.grimac.platform.bukkit.utils.anticheat;
import ac.grim.grimac.utils.anticheat.LogUtil;
import ac.grim.grimac.utils.reflection.ReflectionUtils;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import org.bukkit.entity.Player;
import java.lang.reflect.Method;
public class MultiLibUtil {
public final static Method externalPlayerMethod = ReflectionUtils.getMethod(Player.class, "isExternalPlayer");
private static final boolean IS_PRE_1_18 = PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_18);
// TODO: cache external players for better performance, but this only matters for people using multi-lib
public static boolean isExternalPlayer(Player player) {
if (externalPlayerMethod == null || IS_PRE_1_18) return false;
try {
return (boolean) externalPlayerMethod.invoke(player);
} catch (Exception e) {
LogUtil.error("Failed to invoke external player method", e);
return false;
}
}
}
@@ -1,45 +0,0 @@
package ac.grim.grimac.platform.bukkit.utils.convert;
import ac.grim.grimac.platform.api.permissions.PermissionDefaultValue;
import ac.grim.grimac.platform.bukkit.world.BukkitPlatformWorld;
import ac.grim.grimac.utils.math.Location;
import com.github.retrooper.packetevents.protocol.world.BlockFace;
import org.bukkit.permissions.PermissionDefault;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
public class BukkitConversionUtils {
@Contract("null -> null; !null -> new")
public static org.bukkit.Location toBukkitLocation(Location location) {
if (location == null) return null;
return new org.bukkit.Location(((BukkitPlatformWorld) location.getWorld()).getBukkitWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
}
/**
* Converts this enum to a Bukkit PermissionDefault.
*
* @return The corresponding Bukkit PermissionDefault.
*/
@Contract(value = "null -> null; !null -> !null", pure = true)
public static @Nullable PermissionDefault toBukkitPermissionDefault(@Nullable PermissionDefaultValue permissionDefaultValue) {
if (permissionDefaultValue == null) return null;
return switch (permissionDefaultValue) {
case TRUE -> PermissionDefault.TRUE;
case FALSE -> PermissionDefault.FALSE;
case OP -> PermissionDefault.OP;
case NOT_OP -> PermissionDefault.NOT_OP;
};
}
public static BlockFace fromBukkitFace(org.bukkit.block.BlockFace face) {
return switch (face) {
case NORTH -> BlockFace.NORTH;
case SOUTH -> BlockFace.SOUTH;
case WEST -> BlockFace.WEST;
case EAST -> BlockFace.EAST;
case UP -> BlockFace.UP;
case DOWN -> BlockFace.DOWN;
default -> BlockFace.OTHER;
};
}
}
@@ -1,40 +0,0 @@
package ac.grim.grimac.platform.bukkit.utils.reflection;
import ac.grim.grimac.platform.bukkit.GrimACBukkitLoaderPlugin;
import ac.grim.grimac.utils.anticheat.LogUtil;
import ac.grim.grimac.utils.reflection.ReflectionUtils;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import java.util.concurrent.CompletableFuture;
public class PaperUtils {
public static final boolean PAPER = ReflectionUtils.hasClass("com.destroystokyo.paper.PaperConfig")
|| ReflectionUtils.hasClass("io.papermc.paper.configuration.Configuration");
public static CompletableFuture<Boolean> teleportAsync(final Entity entity, final Location location) {
return PAPER ? entity.teleportAsync(location) : CompletableFuture.completedFuture(entity.teleport(location));
}
@SuppressWarnings("unchecked")
public static boolean registerTickEndEvent(Listener listener, Runnable runnable) {
try {
Class<?> clazz = ReflectionUtils.getClass("com.destroystokyo.paper.event.server.ServerTickEndEvent");
if (clazz == null) return false;
GrimACBukkitLoaderPlugin.LOADER.getServer().getPluginManager().registerEvent(
(Class<? extends Event>) clazz,
listener,
EventPriority.NORMAL,
(l, event) -> runnable.run(),
GrimACBukkitLoaderPlugin.LOADER
);
return true;
} catch (Exception e) {
LogUtil.error("Failed to register tick end event", e);
}
return false;
}
}
@@ -1,38 +0,0 @@
package ac.grim.grimac.platform.bukkit.world;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.platform.api.Platform;
import ac.grim.grimac.platform.api.world.PlatformChunk;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
import lombok.RequiredArgsConstructor;
import org.bukkit.Chunk;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@RequiredArgsConstructor
public class BukkitPlatformChunk implements PlatformChunk {
private static final Map<BlockData, Integer> blockDataToId = GrimAPI.INSTANCE.getPlatform() == Platform.FOLIA ? new ConcurrentHashMap<>() : new HashMap<>();
private static final boolean isFlat = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_13);
private final @NotNull Chunk chunk;
@Override
public int getBlockID(int x, int y, int z) {
Block block = chunk.getBlock(x, y, z);
return isFlat // Cache blockDataToID because Strings are expensive
? blockDataToId.computeIfAbsent(block.getBlockData(), data -> WrappedBlockState.getByString(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), data.getAsString(false)).getGlobalId())
: getLegacyBlockID(block);
}
@SuppressWarnings({ "deprecation", "UnstableApiUsage" })
private static int getLegacyBlockID(@NotNull Block block) {
return (block.getType().getId() << 4) | block.getData();
}
}
@@ -1,62 +0,0 @@
package ac.grim.grimac.platform.bukkit.world;
import ac.grim.grimac.platform.api.world.PlatformChunk;
import ac.grim.grimac.platform.api.world.PlatformWorld;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
@Getter
@RequiredArgsConstructor
public class BukkitPlatformWorld implements PlatformWorld {
private static final boolean LEGACY_SERVER_VERSION = PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_12_2);
private final @NotNull World bukkitWorld;
@Override
public boolean isChunkLoaded(int chunkX, int chunkZ) {
return bukkitWorld.isChunkLoaded(chunkX, chunkZ);
}
@Override
public WrappedBlockState getBlockAt(int x, int y, int z) {
if (LEGACY_SERVER_VERSION) {
Block block = bukkitWorld.getBlockAt(x, y, z);
@SuppressWarnings({"deprecation", "UnstableApiUsage"})
int blockId = (block.getType().getId() << 4) | block.getData();
return WrappedBlockState.getByGlobalId(blockId);
} else {
return SpigotConversionUtil.fromBukkitBlockData(bukkitWorld.getBlockAt(x, y, z).getBlockData());
}
}
@Override
public String getName() {
return bukkitWorld.getName();
}
@Override
public @Nullable UUID getUID() {
return this.bukkitWorld.getUID();
}
@Override
public PlatformChunk getChunkAt(int currChunkX, int currChunkZ) {
return new BukkitPlatformChunk(bukkitWorld.getChunkAt(currChunkX, currChunkZ));
}
@Override
public boolean isLoaded() {
return Bukkit.getWorld(bukkitWorld.getUID()) != null;
}
}
-47
View File
@@ -1,47 +0,0 @@
# cliff.toml - DEV BUILDS - Now with Author Info
[changelog]
body = """
## Changes in this Build (since previous push)
{%- for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | upper_first }}
{%- for commit in commits %}
- {{ commit.message | upper_first }} - *by {{ commit.author.name }}* {% if commit.breaking %}**[BREAKING]**{% endif %} \
{%- if commit.remote and commit.remote.url -%}
([`{{ commit.id | truncate(length=7, end="") }}`]({{ commit.remote.url }}/commit/{{- commit.id -}}))
{%- else -%}
(`{{ commit.id | truncate(length=7, end="") }}`)
{%- endif -%}
{% endfor %}
{% endfor %}
"""
trim = true
[git]
# Your previous settings here are perfect, no changes needed
filter_unconventional = false
skip_unconventional = false
remote = "https://github.com/GrimAnticheat/Grim"
commit_parsers = [
{ message = "^feat", group = "🚀 Features" },
{ message = "^fix", group = "🐛 Fixes" },
{ message = "^perf", group = "⚡️ Performance" },
{ message = "^refactor", group = "♻️ Refactoring" },
{ message = "^docs", group = "📖 Documentation" },
{ message = "^test", group = "✅ Tests" },
{ message = "^chore", group = "🤖 Maintenance & CI" },
{ body = ".*BREAKING CHANGE.*", group = "🚨 Breaking Changes" },
{ message = ".*", group = "Miscellaneous" } # CHANGED THIS LINE
]
commit_preprocessors = [
{ pattern = 'src/main/java/ac/grim/grimac/checks/.*', group = "✔️ Checks" },
{ pattern = 'src/main/java/ac/grim/grimac/api/.*', group = "🔌 API" },
{ pattern = 'src/main/java/ac/grim/grimac/platform/.*', group = "🏗️ Platform" },
{ pattern = 'src/main/java/ac/grim/grimac/engine/.*', group = "⚙️ Core Engine" },
{ pattern = 'src/main/java/ac/grim/grimac/config/.*', group = "⚙️ Configuration" },
{ pattern = 'pom.xml', group = "🤖 Maintenance & CI" },
{ pattern = '.github/.*', group = "🤖 Maintenance & CI" },
{ pattern = 'build.gradle.kts', group = "🤖 Maintenance & CI" },
{ pattern = 'src/.*', group = "⚙️ Core Engine" },
]
sort_commits = "oldest"
-107
View File
@@ -1,107 +0,0 @@
import versioning.BuildConfig
plugins {
`maven-publish`
grim.`base-conventions`
}
repositories {
if (BuildConfig.mavenLocalOverride) {
mavenLocal()
}
exclusiveContent {
forRepository {
maven("https://repo.grim.ac/snapshots") // Grim API
}
filter {
includeGroup("ac.grim.grimac")
includeGroup("com.github.retrooper")
}
}
exclusiveContent {
forRepository {
maven("https://repo.viaversion.com") { // ViaVersion
mavenContent { releasesOnly() }
}
}
filter {
includeGroup("com.viaversion")
}
}
exclusiveContent {
forRepository {
maven("https://nexus.scarsz.me/content/repositories/releases") { // Configuralize
mavenContent { releasesOnly() }
}
}
filter {
includeGroup("github.scarsz")
}
}
exclusiveContent {
forRepository {
maven("https://repo.opencollab.dev/maven-releases/") { // Cumulus (for Floodgate)
mavenContent { releasesOnly() }
}
}
filter {
includeGroup("org.geysermc.api")
}
}
exclusiveContent {
forRepository {
maven("https://repo.opencollab.dev/maven-snapshots/") { // Floodgate
mavenContent { snapshotsOnly() }
}
}
filter {
includeGroup("org.geysermc.floodgate")
includeGroup("org.geysermc.cumulus")
includeModule("org.geysermc", "common")
includeModule("org.geysermc", "geyser-parent")
}
}
mavenCentral()
}
dependencies {
if (BuildConfig.shadePE) {
api(libs.packetevents.api)
} else {
compileOnly(libs.packetevents.api)
}
api(libs.cloud.core)
api(libs.cloud.processors.requirements)
api(libs.configuralize) {
artifact {
classifier = "slim"
}
exclude(group = "org.yaml", module = "snakeyaml")
}
// Bump snakeyaml (transitive dep of configuralize) 1.29 -> 2.2+ for geyser-fabric
api(libs.snakeyaml)
api(libs.fastutil)
api(libs.adventure.text.minimessage)
api(libs.jetbrains.annotations)
api(libs.hikaricp)
api(libs.grim.api)
compileOnly(libs.geyser.base.api) {
isTransitive = false // messes with guava otherwise
}
compileOnly(libs.floodgate.api)
compileOnly(libs.viaversion)
compileOnly(libs.netty)
}
publishing.publications.create<MavenPublication>("maven") {
from(components["java"])
}
@@ -1,149 +0,0 @@
package ac.grim.grimac;
import ac.grim.grimac.api.event.EventBus;
import ac.grim.grimac.api.plugin.GrimPlugin;
import ac.grim.grimac.events.GrimExtensionManager;
import ac.grim.grimac.events.OptimizedEventBus;
import ac.grim.grimac.manager.AlertManagerImpl;
import ac.grim.grimac.manager.DiscordManager;
import ac.grim.grimac.manager.InitManager;
import ac.grim.grimac.manager.SpectateManager;
import ac.grim.grimac.manager.TickManager;
import ac.grim.grimac.manager.config.BaseConfigManager;
import ac.grim.grimac.manager.init.Initable;
import ac.grim.grimac.manager.violationdatabase.ViolationDatabaseManager;
import ac.grim.grimac.platform.api.Platform;
import ac.grim.grimac.platform.api.PlatformLoader;
import ac.grim.grimac.platform.api.PlatformServer;
import ac.grim.grimac.platform.api.manager.ItemResetHandler;
import ac.grim.grimac.platform.api.manager.MessagePlaceHolderManager;
import ac.grim.grimac.platform.api.manager.CommandAdapter;
import ac.grim.grimac.platform.api.manager.PermissionRegistrationManager;
import ac.grim.grimac.platform.api.manager.PlatformPluginManager;
import ac.grim.grimac.platform.api.player.PlatformPlayerFactory;
import ac.grim.grimac.platform.api.scheduler.PlatformScheduler;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.platform.api.sender.SenderFactory;
import ac.grim.grimac.utils.anticheat.PlayerDataManager;
import ac.grim.grimac.utils.common.arguments.CommonGrimArguments;
import ac.grim.grimac.utils.reflection.ReflectionUtils;
import lombok.Getter;
import org.incendo.cloud.CommandManager;
import org.jetbrains.annotations.NotNull;
@Getter
public final class GrimAPI {
public static final GrimAPI INSTANCE = new GrimAPI();
@Getter
private final Platform platform = detectPlatform();
private final BaseConfigManager configManager;
private final AlertManagerImpl alertManager;
private final SpectateManager spectateManager;
private final DiscordManager discordManager;
private final PlayerDataManager playerDataManager;
private final TickManager tickManager;
private final GrimExtensionManager extensionManager;
private final EventBus eventBus;
private final GrimExternalAPI externalAPI;
private ViolationDatabaseManager violationDatabaseManager;
private PlatformLoader loader;
@Getter
private InitManager initManager;
private boolean initialized = false;
private GrimAPI() {
this.configManager = new BaseConfigManager();
this.alertManager = new AlertManagerImpl();
this.spectateManager = new SpectateManager();
this.discordManager = new DiscordManager();
this.playerDataManager = new PlayerDataManager();
this.tickManager = new TickManager();
this.extensionManager = new GrimExtensionManager();
this.eventBus = new OptimizedEventBus(extensionManager);
this.externalAPI = new GrimExternalAPI(this);
}
// the order matters
private static Platform detectPlatform() {
Platform override = CommonGrimArguments.PLATFORM_OVERRIDE.value();
if (override != null) return override;
if (ReflectionUtils.hasClass("io.papermc.paper.threadedregions.RegionizedServer")) return Platform.FOLIA;
if (ReflectionUtils.hasClass("org.bukkit.Bukkit")) return Platform.BUKKIT;
if (ReflectionUtils.hasClass("net.fabricmc.loader.api.FabricLoader")) return Platform.FABRIC;
throw new IllegalStateException("Unknown platform!");
}
public void load(PlatformLoader platformLoader, Initable... platformSpecificInitables) {
this.loader = platformLoader;
this.violationDatabaseManager = new ViolationDatabaseManager(getGrimPlugin());
this.initManager = new InitManager(loader.getPacketEvents(), loader::getCommandManager, platformSpecificInitables);
this.initManager.load();
this.initialized = true;
}
public void start() {
checkInitialized();
initManager.start();
}
public void stop() {
checkInitialized();
initManager.stop();
}
public PlatformScheduler getScheduler() {
return loader.getScheduler();
}
public PlatformPlayerFactory getPlatformPlayerFactory() {
return loader.getPlatformPlayerFactory();
}
public CommandAdapter getCommandAdapter() {
return loader.getCommandAdapter();
}
public GrimPlugin getGrimPlugin() {
return loader.getPlugin();
}
public SenderFactory<?> getSenderFactory() {
return loader.getSenderFactory();
}
public ItemResetHandler getItemResetHandler() {
return loader.getItemResetHandler();
}
public PlatformPluginManager getPluginManager() {
return loader.getPluginManager();
}
public PlatformServer getPlatformServer() {
return loader.getPlatformServer();
}
public @NotNull MessagePlaceHolderManager getMessagePlaceHolderManager() {
return loader.getMessagePlaceHolderManager();
}
public CommandManager<Sender> getCommandManager() {
return loader.getCommandManager();
}
private void checkInitialized() {
if (!initialized) {
throw new IllegalStateException("GrimAPI has not been initialized!");
}
}
public PermissionRegistrationManager getPermissionManager() {
return loader.getPermissionManager();
}
public GrimExtensionManager getExtensionManager() {
return extensionManager;
}
}
@@ -1,14 +0,0 @@
package ac.grim.grimac.checks.debug;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.player.GrimPlayer;
public abstract class AbstractDebugHandler extends Check {
public AbstractDebugHandler(GrimPlayer player) {
super(player);
}
public abstract void toggleListener(GrimPlayer player);
public abstract boolean toggleConsoleOutput();
}
@@ -1,32 +0,0 @@
package ac.grim.grimac.checks.impl.badpackets;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
import ac.grim.grimac.player.GrimPlayer;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
@CheckData(name = "BadPacketsB", description = "Ignored set rotation packet")
public class BadPacketsB extends Check implements PacketCheck {
public BadPacketsB(final GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (isTransaction(event.getPacketType())) {
player.pendingRotations.removeIf(data -> {
if (player.getLastTransactionReceived() > data.getTransaction()) {
if (!data.isAccepted()) {
flagAndAlert();
}
return true;
}
return false;
});
}
}
}
@@ -1,67 +0,0 @@
package ac.grim.grimac.checks.impl.badpackets;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.BlockPlaceCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.update.BlockBreak;
import ac.grim.grimac.utils.anticheat.update.BlockPlace;
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;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientUseItem;
@CheckData(name = "BadPacketsH", description = "Sent unexpected sequence id", experimental = true)
public class BadPacketsH extends BlockPlaceCheck {
private int lastSequence;
private final boolean isSupportedVersion = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_19) && PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_19);
public BadPacketsH(final GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.USE_ITEM
&& shouldCancel(new WrapperPlayClientUseItem(event).getSequence())) {
event.setCancelled(true);
player.onPacketCancel();
}
}
@Override
public void onBlockPlace(BlockPlace place) {
if (shouldCancel(place.sequence) && shouldCancel()) {
place.resync();
}
}
@Override
public void onBlockBreak(BlockBreak blockBreak) {
switch (blockBreak.action) {
case START_DIGGING, FINISHED_DIGGING -> {
if (shouldCancel(blockBreak.sequence)) {
blockBreak.cancel();
}
}
case CANCELLED_DIGGING -> { // other actions will be checked by BadPacketsL
if (blockBreak.sequence != 0 && flagAndAlert("expected=0, id=" + blockBreak.sequence) && shouldModifyPackets()) {
blockBreak.cancel();
}
}
}
}
public boolean shouldCancel(int sequence) {
int expected = lastSequence + 1;
lastSequence = sequence;
return isSupportedVersion && sequence != expected
&& flagAndAlert("expected=" + expected + ", id=" + sequence)
&& shouldModifyPackets();
}
public void onWorldChange() {
lastSequence = 0;
}
}
@@ -1,59 +0,0 @@
package ac.grim.grimac.checks.impl.badpackets;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.data.HeadRotation;
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;
import com.github.retrooper.packetevents.protocol.player.GameMode;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientUseItem;
import java.util.ArrayList;
import java.util.List;
@CheckData(name = "BadPacketsJ", description = "Rotation in use item packet did not match tick rotation")
public class BadPacketsJ extends Check implements PacketCheck {
private final List<HeadRotation> rotations = new ArrayList<>();
public BadPacketsJ(GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (player.gamemode == GameMode.SPECTATOR) {
rotations.clear();
return;
}
if (event.getPacketType() == PacketType.Play.Client.USE_ITEM && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21)
&& PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_21)) {
WrapperPlayClientUseItem packet = new WrapperPlayClientUseItem(event);
rotations.add(new HeadRotation(packet.getYaw(), packet.getPitch()));
}
if (isTickPacket(event.getPacketType())) {
// due to tick skipping, the rotations sent could be last tick's
boolean allowLast = player.canSkipTicks() && (event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION || event.getPacketType() == PacketType.Play.Client.PLAYER_ROTATION);
for (HeadRotation rotation : rotations) {
if (rotation.yaw() == player.yaw && rotation.pitch() == player.pitch) {
allowLast = false;
continue;
}
if (rotation.yaw() == player.lastYaw && rotation.pitch() == player.lastPitch && allowLast) {
continue;
}
flagAndAlert();
}
rotations.clear();
}
}
}
@@ -1,64 +0,0 @@
package ac.grim.grimac.checks.impl.badpackets;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
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;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.Combat;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientClientStatus;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerChangeGameState;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerCombatEvent;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDeathCombatEvent;
@CheckData(name = "BadPacketsM", description = "Tried to respawn while alive", experimental = true)
public class BadPacketsM extends Check implements PacketCheck {
public BadPacketsM(final GrimPlayer player) {
super(player);
}
// not a boolean because the server could send packets that cause
// the client to send a respawn packet before it receives the first
private int exempt;
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.CLIENT_STATUS && new WrapperPlayClientClientStatus(event).getAction() == WrapperPlayClientClientStatus.Action.PERFORM_RESPAWN) {
if (exempt > 0) {
exempt--;
return;
}
if (!player.compensatedEntities.self.isDead) {
if (flagAndAlert() && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
}
}
@Override
public void onPacketSend(PacketSendEvent event) {
if (event.getPacketType() == PacketType.Play.Server.CHANGE_GAME_STATE && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)
&& new WrapperPlayServerChangeGameState(event).getReason() == WrapperPlayServerChangeGameState.Reason.WIN_GAME) {
player.addRealTimeTaskNow(() -> exempt++);
}
if (event.getPacketType() == PacketType.Play.Server.DEATH_COMBAT_EVENT && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) {
if (new WrapperPlayServerDeathCombatEvent(event).getPlayerId() == player.entityID) {
player.addRealTimeTaskNow(() -> exempt++);
}
}
if (event.getPacketType() == PacketType.Play.Server.COMBAT_EVENT && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) {
WrapperPlayServerCombatEvent packet = new WrapperPlayServerCombatEvent(event);
if (packet.getCombat() == Combat.ENTITY_DEAD && packet.getPlayerId() == player.entityID) {
player.addRealTimeTaskNow(() -> exempt++);
}
}
}
}
@@ -1,26 +0,0 @@
package ac.grim.grimac.checks.impl.badpackets;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
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.WrapperPlayClientWindowConfirmation;
@CheckData(name = "BadPacketsS")
public class BadPacketsS extends Check implements PacketCheck {
public BadPacketsS(GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.WINDOW_CONFIRMATION
&& !new WrapperPlayClientWindowConfirmation(event).isAccepted()
&& flagAndAlert() && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
}
@@ -1,62 +0,0 @@
package ac.grim.grimac.checks.impl.chat;
import ac.grim.grimac.api.config.ConfigManager;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.impl.multiactions.MultiActionsC;
import ac.grim.grimac.checks.type.PacketCheck;
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.WrapperPlayClientChatCommand;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientChatCommandUnsigned;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientChatMessage;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
import java.util.regex.Pattern;
@CheckData(name = "ChatC", description = "Moving while chatting", experimental = true)
public class ChatC extends Check implements PacketCheck {
public ChatC(GrimPlayer player) {
super(player);
}
// optionally allow cheats like autogg
private @Nullable Predicate<String> exemptRegex;
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.CHAT_MESSAGE) {
// TODO make previa after making wrapper parse by client version instead of server version
check(new WrapperPlayClientChatMessage(event).getMessage(), event);
}
if (event.getPacketType() == PacketType.Play.Client.CHAT_COMMAND_UNSIGNED) {
check("/" + new WrapperPlayClientChatCommandUnsigned(event).getCommand(), event);
}
if (event.getPacketType() == PacketType.Play.Client.CHAT_COMMAND) {
// TODO make previa after making wrapper parse by client version instead of server version
check("/" + new WrapperPlayClientChatCommand(event).getCommand(), event);
}
}
private void check(String message, PacketReceiveEvent event) {
if (exemptRegex != null && exemptRegex.test(message)) {
return;
}
String verbose = MultiActionsC.getVerbose(player);
if (!verbose.isEmpty() && flagAndAlert(verbose) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
@Override
public void onReload(ConfigManager config) {
String regexString = config.getStringElse(getConfigName() + ".exempt-regex", null);
exemptRegex = regexString == null ? null : Pattern.compile(regexString).asMatchPredicate();
}
}
@@ -1,35 +0,0 @@
package ac.grim.grimac.checks.impl.chat;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
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.common.client.WrapperCommonClientSettings;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientSettings;
@CheckData(name = "ChatD", description = "Chatting while chat is hidden", experimental = true)
public class ChatD extends Check implements PacketCheck {
private boolean hidden;
public ChatD(GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.CHAT_MESSAGE
|| event.getPacketType() == PacketType.Play.Client.CHAT_COMMAND_UNSIGNED
|| event.getPacketType() == PacketType.Play.Client.CHAT_COMMAND) {
if (hidden && flagAndAlert() && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
if (event.getPacketType() == PacketType.Play.Client.CLIENT_SETTINGS || event.getPacketType() == PacketType.Configuration.Client.CLIENT_SETTINGS) {
hidden = new WrapperPlayClientSettings(event).getChatVisibility() == WrapperCommonClientSettings.ChatVisibility.HIDDEN;
}
}
}
@@ -1,12 +0,0 @@
package ac.grim.grimac.checks.impl.combat;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.player.GrimPlayer;
@CheckData(name = "Hitboxes", setback = 10)
public class Hitboxes extends Check {
public Hitboxes(GrimPlayer player) {
super(player);
}
}
@@ -1,271 +0,0 @@
// This file was designed and is an original check for GrimAC
// Copyright (C) 2021 DefineOutside
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package ac.grim.grimac.checks.impl.combat;
import ac.grim.grimac.api.config.ConfigManager;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
import ac.grim.grimac.utils.data.packetentity.PacketEntity;
import ac.grim.grimac.utils.data.packetentity.dragon.PacketEntityEnderDragonPart;
import ac.grim.grimac.utils.math.Vector3dm;
import ac.grim.grimac.utils.nmsutil.ReachUtils;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
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.GameMode;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
// You may not copy the check unless you are licensed under GPL
@CheckData(name = "Reach", setback = 10)
public class Reach extends Check implements PacketCheck {
private static final List<EntityType> blacklisted = Arrays.asList(
EntityTypes.BOAT,
EntityTypes.CHEST_BOAT,
EntityTypes.SHULKER);
private static final CheckResult NONE = new CheckResult(ResultType.NONE, "");
// Only one flag per reach attack, per entity, per tick.
// We store position because lastX isn't reliable on teleports.
private final Int2ObjectMap<Vector3d> playerAttackQueue = new Int2ObjectOpenHashMap<>();
private boolean cancelImpossibleHits;
private double threshold;
private double cancelBuffer; // For the next 4 hits after using reach, we aggressively cancel reach
public Reach(GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(final PacketReceiveEvent event) {
if (!player.disableGrim && event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
WrapperPlayClientInteractEntity action = new WrapperPlayClientInteractEntity(event);
// Don't let the player teleport to bypass reach
if (player.getSetbackTeleportUtil().shouldBlockMovement()) {
event.setCancelled(true);
player.onPacketCancel();
return;
}
PacketEntity entity = player.compensatedEntities.entityMap.get(action.getEntityId());
// Stop people from freezing transactions before an entity spawns to bypass reach
// TODO: implement dragon parts?
if (entity == null || entity instanceof PacketEntityEnderDragonPart) {
// Only cancel if and only if we are tracking this entity
// This is because we don't track paintings.
if (shouldModifyPackets() && player.compensatedEntities.serverPositionsMap.containsKey(action.getEntityId())) {
event.setCancelled(true);
player.onPacketCancel();
}
return;
}
// Dead entities cause false flags (https://github.com/GrimAnticheat/Grim/issues/546)
if (entity.isDead) return;
// TODO: Remove when in front of via
if (entity.type == EntityTypes.ARMOR_STAND && player.getClientVersion().isOlderThan(ClientVersion.V_1_8))
return;
if (player.gamemode == GameMode.CREATIVE || player.gamemode == GameMode.SPECTATOR)
return;
if (player.inVehicle()) return;
if (entity.riding != null) return;
boolean tooManyAttacks = playerAttackQueue.size() > 10;
if (!tooManyAttacks) {
playerAttackQueue.put(action.getEntityId(), new Vector3d(player.x, player.y, player.z)); // Queue for next tick for very precise check
}
boolean knownInvalid = isKnownInvalid(entity);
if ((shouldModifyPackets() && cancelImpossibleHits && knownInvalid) || tooManyAttacks) {
event.setCancelled(true);
player.onPacketCancel();
}
}
// If the player set their look, or we know they have a new tick
if (isUpdate(event.getPacketType())) {
tickBetterReachCheckWithAngle();
}
}
// This method finds the most optimal point at which the user should be aiming at
// and then measures the distance between the player's eyes and this target point
//
// It will not cancel every invalid attack but should cancel 3.05+ or so in real-time
// Let the post look check measure the distance, as it will always return equal or higher
// than this method. If this method flags, the other method WILL flag.
//
// Meaning that the other check should be the only one that flags.
private boolean isKnownInvalid(PacketEntity reachEntity) {
// If the entity doesn't exist, or if it is exempt, or if it is dead
if ((blacklisted.contains(reachEntity.type) || !reachEntity.isLivingEntity) && reachEntity.type != EntityTypes.END_CRYSTAL)
return false; // exempt
if (player.gamemode == GameMode.CREATIVE || player.gamemode == GameMode.SPECTATOR)
return false;
if (player.inVehicle()) return false;
// Filter out what we assume to be cheats
if (cancelBuffer != 0) {
CheckResult result = checkReach(reachEntity, new Vector3d(player.x, player.y, player.z), true);
return result.isFlag(); // If they flagged
} else {
SimpleCollisionBox targetBox = reachEntity.getPossibleCollisionBoxes();
if (reachEntity.type == EntityTypes.END_CRYSTAL) {
targetBox = new SimpleCollisionBox(reachEntity.trackedServerPosition.getPos().subtract(1, 0, 1), reachEntity.trackedServerPosition.getPos().add(1, 2, 1));
}
return ReachUtils.getMinReachToBox(player, targetBox) > player.compensatedEntities.self.getAttributeValue(Attributes.ENTITY_INTERACTION_RANGE);
}
}
private void tickBetterReachCheckWithAngle() {
for (Int2ObjectMap.Entry<Vector3d> attack : playerAttackQueue.int2ObjectEntrySet()) {
PacketEntity reachEntity = player.compensatedEntities.entityMap.get(attack.getIntKey());
if (reachEntity == null) continue;
CheckResult result = checkReach(reachEntity, attack.getValue(), false);
switch (result.type()) {
case REACH -> {
String added = ", type=" + reachEntity.type.getName().getKey();
flagAndAlert(result.verbose() + added);
}
case HITBOX -> {
String added = "type=" + reachEntity.type.getName().getKey();
player.checkManager.getCheck(Hitboxes.class).flagAndAlert(result.verbose() + added);
}
}
}
playerAttackQueue.clear();
}
@NotNull
private CheckResult checkReach(PacketEntity reachEntity, Vector3d from, boolean isPrediction) {
SimpleCollisionBox targetBox = reachEntity.getPossibleCollisionBoxes();
if (reachEntity.type == EntityTypes.END_CRYSTAL) { // Hardcode end crystal box
targetBox = new SimpleCollisionBox(reachEntity.trackedServerPosition.getPos().subtract(1, 0, 1), reachEntity.trackedServerPosition.getPos().add(1, 2, 1));
}
// 1.7 and 1.8 players get a bit of extra hitbox (this is why you should use 1.8 on cross version servers)
// Yes, this is vanilla and not uncertainty. All reach checks have this or they are wrong.
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_9)) {
targetBox.expand(0.1f);
}
targetBox.expand(threshold);
// This is better than adding to the reach, as 0.03 can cause a player to miss their target
// Adds some more than 0.03 uncertainty in some cases, but a good trade off for simplicity
//
// Just give the uncertainty on 1.9+ clients as we have no way of knowing whether they had 0.03 movement
// However, on 1.21.2+ we do know if they had 0.03 movement
if (!player.packetStateData.didLastLastMovementIncludePosition || player.canSkipTicks())
targetBox.expand(player.getMovementThreshold());
double minDistance = Double.MAX_VALUE;
// https://bugs.mojang.com/browse/MC-67665
List<Vector3dm> possibleLookDirs = new ArrayList<>(Collections.singletonList(ReachUtils.getLook(player, player.yaw, player.pitch)));
// If we are a tick behind, we don't know their next look so don't bother doing this
if (!isPrediction) {
possibleLookDirs.add(ReachUtils.getLook(player, player.lastYaw, player.pitch));
// 1.9+ players could be a tick behind because we don't get skipped ticks
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9)) {
possibleLookDirs.add(ReachUtils.getLook(player, player.lastYaw, player.lastPitch));
}
// 1.7 players do not have any of these issues! They are always on the latest look vector
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_8)) {
possibleLookDirs = Collections.singletonList(ReachUtils.getLook(player, player.yaw, player.pitch));
}
}
final double maxReach = player.compensatedEntities.self.getAttributeValue(Attributes.ENTITY_INTERACTION_RANGE);
// +3 would be 3 + 3 = 6, which is the pre-1.20.5 behaviour, preventing "Missed Hitbox"
final double distance = maxReach + 3;
final double[] possibleEyeHeights = player.getPossibleEyeHeights();
final Vector3dm eyePos = new Vector3dm(from.getX(), 0, from.getZ());
for (Vector3dm lookVec : possibleLookDirs) {
for (double eye : possibleEyeHeights) {
eyePos.setY(from.getY() + eye);
Vector3dm endReachPos = eyePos.clone().add(new Vector3dm(lookVec.getX() * distance, lookVec.getY() * distance, lookVec.getZ() * distance));
Vector3dm intercept = ReachUtils.calculateIntercept(targetBox, eyePos, endReachPos).first();
if (ReachUtils.isVecInside(targetBox, eyePos)) {
minDistance = 0;
break;
}
if (intercept != null) {
minDistance = Math.min(eyePos.distance(intercept), minDistance);
}
}
}
// if the entity is not exempt and the entity is alive
if ((!blacklisted.contains(reachEntity.type) && reachEntity.isLivingEntity) || reachEntity.type == EntityTypes.END_CRYSTAL) {
if (minDistance == Double.MAX_VALUE) {
cancelBuffer = 1;
return new CheckResult(ResultType.HITBOX, "");
} else if (minDistance > maxReach) {
cancelBuffer = 1;
return new CheckResult(ResultType.REACH, String.format("%.5f", minDistance) + " blocks");
} else {
cancelBuffer = Math.max(0, cancelBuffer - 0.25);
}
}
return NONE;
}
@Override
public void onReload(ConfigManager config) {
this.cancelImpossibleHits = config.getBooleanElse("Reach.block-impossible-hits", true);
this.threshold = config.getDoubleElse("Reach.threshold", 0.0005);
}
private enum ResultType {
REACH, HITBOX, NONE
}
private record CheckResult(ResultType type, String verbose) {
public boolean isFlag() {
return type != ResultType.NONE;
}
}
}
@@ -1,39 +0,0 @@
package ac.grim.grimac.checks.impl.crash;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
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.WrapperPlayClientSelectBundleItem;
@CheckData(name = "CrashI")
public class CrashI extends Check implements PacketCheck {
public CrashI(GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.SELECT_BUNDLE_ITEM) {
int selectedItemIndex;
try {
selectedItemIndex = new WrapperPlayClientSelectBundleItem(event).getSelectedItemIndex();
} catch (IllegalArgumentException e) {
// thanks packetevents!
if (e.getMessage().startsWith("Invalid selectedItemIndex: ")) {
selectedItemIndex = Integer.parseInt(e.getMessage().substring(27));
} else {
throw e;
}
}
if (selectedItemIndex < -1) {
flagAndAlert("selectedItemIndex=" + selectedItemIndex);
event.setCancelled(true);
player.onPacketCancel();
}
}
}
}
@@ -1,49 +0,0 @@
package ac.grim.grimac.checks.impl.exploit;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.payload.PayloadItemName;
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;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientNameItem;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPluginMessage;
import org.jetbrains.annotations.NotNull;
@CheckData(name = "ExploitA", description = "Too long item name in anvil")
public class ExploitA extends Check implements PacketCheck {
public ExploitA(GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.NAME_ITEM) {
check(new WrapperPlayClientNameItem(event).getItemName(), event);
}
if (event.getPacketType() == PacketType.Play.Client.PLUGIN_MESSAGE && PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_13)) {
WrapperPlayClientPluginMessage wrapper = new WrapperPlayClientPluginMessage(event);
if (wrapper.getChannelName().equals("MC|ItemName")) {
check(PayloadItemName.CODEC.read(wrapper.getData()).itemName(), event);
}
}
}
private void check(@NotNull String name, PacketReceiveEvent event) {
int limit = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_17) ? 50
: player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_12) ? 35
: player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_11_1) ? 31 : 30;
if (name.length() > limit) {
if (flagAndAlert("name=" + name) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
}
}
@@ -1,323 +0,0 @@
package ac.grim.grimac.checks.impl.exploit;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.payload.PayloadBookEdit;
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.component.ComponentTypes;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.nbt.NBT;
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEditBook;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerBlockPlacement;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPluginMessage;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientUseItem;
import com.google.gson.JsonSyntaxException;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@CheckData(name = "ExploitB", description = "Invalid book edit")
public class ExploitB extends Check implements PacketCheck {
private static final boolean IS_1_8 = PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_8_8);
private ItemStack oldBook;
private InteractionHand hand;
public ExploitB(GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (IS_1_8 ? event.getPacketType() == PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT
&& new WrapperPlayClientPlayerBlockPlacement(event).getFaceId() == 255
: event.getPacketType() == PacketType.Play.Client.USE_ITEM) {
hand = IS_1_8 ? InteractionHand.MAIN_HAND : new WrapperPlayClientUseItem(event).getHand();
oldBook = player.inventory.getItemInHand(hand).copy();
}
if (event.getPacketType() == PacketType.Play.Client.EDIT_BOOK) {
checkEditBook(new WrapperPlayClientEditBook(event), event);
oldBook = null;
}
// 1.13-
if (event.getPacketType() == PacketType.Play.Client.PLUGIN_MESSAGE && PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_13)) {
WrapperPlayClientPluginMessage wrapper = new WrapperPlayClientPluginMessage(event);
boolean signing;
switch (wrapper.getChannelName()) {
case "MC|BSign" -> signing = true;
case "MC|BEdit" -> signing = false;
default -> {
return;
}
}
ItemStack newBook = PayloadBookEdit.CODEC.read(wrapper.getData()).itemStack();
checkItemStack(newBook, signing, event);
oldBook = null;
}
}
private void checkEditBook(WrapperPlayClientEditBook wrapper, PacketReceiveEvent event) {
if (checkEditingBook(event)) return;
int expectedSlot = hand == InteractionHand.OFF_HAND ? 40 : player.packetStateData.lastSlotSelected;
if (wrapper.getSlot() != expectedSlot) {
if (flagAndAlert("expectedSlot=" + expectedSlot + ", slot=" + wrapper.getSlot()) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return;
}
if (wrapper.getSigning() == null) { // 1.17+
if (wrapper.getTitle() != null && checkTitle(wrapper.getTitle(), event)) return;
List<String> pages = wrapper.getPages();
if (!pages.isEmpty() && checkEmptyLastPage(pages.get(pages.size() - 1), event)) return;
if (checkTooManyPages(pages.size(), event)) return;
for (String page : pages) {
if (checkPage(page, event)) return;
}
} else { // 1.13 - 1.16.5
checkItemStack(wrapper.getItemStack(), wrapper.getSigning(), event);
}
}
private void checkItemStack(ItemStack newBook, boolean signing, PacketReceiveEvent event) {
if (checkEditingBook(event)) return;
ItemType expectedType = signing && IS_1_8 ? ItemTypes.WRITTEN_BOOK : ItemTypes.WRITABLE_BOOK;
if (!newBook.is(expectedType)) {
if (flagAndAlert("expectedType=" + expectedType.getName().getKey() + ", type=" + newBook.getType().getName().getKey()) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return;
}
if (newBook.getAmount() != oldBook.getAmount()) {
if (flagAndAlert("expectedAmount=" + oldBook.getAmount() + ", amount=" + newBook.getAmount()) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return;
}
if (newBook.getLegacyData() != oldBook.getLegacyData()) {
if (flagAndAlert("expectedMeta=" + oldBook.getLegacyData() + ", meta=" + newBook.getLegacyData()) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return;
}
NBTCompound newBookNBT = newBook.getNBT();
if (newBookNBT == null) {
if (flagAndAlert("no nbt") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return;
}
NBTList<@NotNull NBTString> newPagesNBT = newBookNBT.getStringListTagOrNull("pages");
if (newPagesNBT == null) {
if (flagAndAlert("no pages") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return;
}
if (checkTooManyPages(newPagesNBT.size(), event)) return;
if (signing) {
String title = newBookNBT.getStringTagValueOrNull("title");
if (title == null) {
if (flagAndAlert("no title") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return;
}
if (checkTitle(title, event)) return;
String author = newBookNBT.getStringTagValueOrNull("author");
if (!player.getName().equals(author)) {
if (flagAndAlert("expectedAuthor=" + player.getName() + ", author=" + author) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return;
}
}
String last = null;
for (NBTString string : newPagesNBT.getTags()) {
if (IS_1_8 && signing) {
try {
JsonReader reader = new JsonReader(new StringReader(string.getValue()));
if (reader.peek() != JsonToken.BEGIN_OBJECT) throw new JsonSyntaxException("");
reader.beginObject();
if (reader.peek() != JsonToken.NAME || !reader.nextName().equals("text")
|| reader.peek() != JsonToken.STRING) throw new JsonSyntaxException("");
last = reader.nextString();
if (reader.peek() != JsonToken.END_OBJECT) throw new JsonSyntaxException("");
} catch (JsonSyntaxException e) {
if (flagAndAlert("invalid page") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return;
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
last = string.getValue();
}
if (checkPage(last, event)) return;
}
if (last != null && checkEmptyLastPage(last, event)) {
return;
}
Set<Map.Entry<String, NBT>> newNBT = newBookNBT.getTags().entrySet();
HashMap<String, NBT> oldNBT = oldBook.getNBT() == null ? new HashMap<>() : new HashMap<>(oldBook.getNBT().getTags());
oldNBT.remove("pages");
oldNBT.remove("title");
oldNBT.remove("author");
for (var entry : newNBT) {
if (!entry.getKey().equals("pages") && !entry.getKey().equals("title") && !entry.getKey().equals("author")) {
NBT nbt = oldNBT.remove(entry.getKey());
if (nbt == null || !nbt.equals(entry.getValue())) {
if (flagAndAlert("modified nbt") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return;
}
}
}
if (!oldNBT.isEmpty()) {
if (flagAndAlert("modified nbt") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
}
private boolean checkTitle(@NotNull String title, PacketReceiveEvent event) {
if (title.length() > (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_16) ? 15 : 16)) {
if (flagAndAlert("title too long") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return true;
} else if (title.isEmpty() || !title.trim().equals(title) || containsInvalidCharacters(title, false)) {
if (flagAndAlert("invalid title '" + title + "'") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return true;
}
return false;
}
private boolean checkEditingBook(PacketReceiveEvent event) {
if (oldBook == null || !oldBook.is(ItemTypes.WRITABLE_BOOK)) {
if (flagAndAlert("not editing book") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return true;
}
return false;
}
private boolean checkTooManyPages(int pages, PacketReceiveEvent event) {
NBTList<@NotNull NBTString> oldPagesNBT;
int oldPages = oldBook.getVersion().isNewerThanOrEquals(ClientVersion.V_1_20_5)
? oldBook.getComponent(ComponentTypes.WRITABLE_BOOK_CONTENT).map(content -> content.getPages().size()).orElse(0)
: oldBook.getNBT() != null && (oldPagesNBT = oldBook.getNBT().getStringListTagOrNull("pages")) != null
? oldPagesNBT.size() : 0;
if (pages > oldPages && pages > (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_14) ? 100 : 50)) {
if (flagAndAlert("too many pages") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return true;
}
return false;
}
private boolean checkPage(String page, PacketReceiveEvent event) {
if (page.length() > 256) {
if (flagAndAlert("page too long") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return true;
}
if (containsInvalidCharacters(page, true)) {
if (flagAndAlert("invalid page characters") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return true;
}
return false;
}
private boolean checkEmptyLastPage(String page, PacketReceiveEvent event) {
if (page.isEmpty()) {
if (flagAndAlert("empty last page") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
return true;
}
return false;
}
private static boolean containsInvalidCharacters(@NotNull String string, boolean allowLineBreak) {
for (int i = 0; i < string.length(); ++i) {
char character = string.charAt(i);
if (character == 167 || character < 32 && (!allowLineBreak || character != 10) || character == 127) {
return true;
}
}
return false;
}
}
@@ -1,30 +0,0 @@
package ac.grim.grimac.checks.impl.multiactions;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.BlockBreakCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.update.BlockBreak;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
@CheckData(name = "MultiActionsB", description = "Breaking blocks while using an item", experimental = true)
public class MultiActionsB extends Check implements BlockBreakCheck {
public MultiActionsB(GrimPlayer player) {
super(player);
}
@Override
public void onBlockBreak(BlockBreak blockBreak) {
if (player.packetStateData.isSlowedByUsingItem() && (player.packetStateData.lastSlotSelected == player.packetStateData.getSlowedByUsingItemSlot() || player.packetStateData.itemInUseHand == InteractionHand.OFF_HAND)) {
// this is vanilla on 1.7
if (player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_7_10)) {
return;
}
if (flagAndAlert() && shouldModifyPackets()) {
blockBreak.cancel();
}
}
}
}
@@ -1,49 +0,0 @@
package ac.grim.grimac.checks.impl.multiactions;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
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.protocol.player.ClientVersion;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.StringJoiner;
@CheckData(name = "MultiActionsC", description = "Clicked in inventory while moving", experimental = true)
public class MultiActionsC extends Check implements PacketCheck {
public MultiActionsC(GrimPlayer player) {
super(player);
}
@Contract(pure = true)
public static String getVerbose(@NotNull GrimPlayer player) {
StringJoiner verbose = new StringJoiner(", ");
if (player.isSprinting && (!player.isSwimming || !player.clientClaimsLastOnGround)) {
verbose.add("sprinting");
}
if (player.isSneaking && player.getClientVersion().isOlderThan(ClientVersion.V_1_15)) {
verbose.add("sneaking");
}
if (player.supportsEndTick() && player.packetStateData.knownInput.moving()) {
verbose.add("input");
}
return verbose.toString();
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.CLICK_WINDOW && !player.serverOpenedInventoryThisTick) {
String verbose = getVerbose(player);
if (!verbose.isEmpty() && flagAndAlert(verbose) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
}
}
@@ -1,46 +0,0 @@
package ac.grim.grimac.checks.impl.multiactions;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.BlockPlaceCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.update.BlockPlace;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
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.world.BlockFace;
@CheckData(name = "MultiActionsG", description = "Attacking or using items while rowing a boat", experimental = true)
public class MultiActionsG extends BlockPlaceCheck {
public MultiActionsG(GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY && isCheckActive()
&& flagAndAlert("interact") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
if (event.getPacketType() == PacketType.Play.Client.USE_ITEM && isCheckActive()
&& flagAndAlert("use") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
@Override
public void onBlockPlace(BlockPlace place) {
if (isCheckActive() && flagAndAlert(place.getFace() == BlockFace.OTHER ? "use" : "place") && shouldModifyPackets() && shouldCancel()) {
place.resync();
}
}
public boolean isCheckActive() {
return player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9) && !player.vehicleData.wasVehicleSwitch // one tick off?
&& player.inVehicle() && player.compensatedEntities.self.getRiding().type.isInstanceOf(EntityTypes.BOAT)
&& (player.vehicleData.nextVehicleForward != 0 || player.vehicleData.nextVehicleHorizontal != 0);
}
}
@@ -1,81 +0,0 @@
package ac.grim.grimac.checks.impl.packetorder;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
import ac.grim.grimac.player.GrimPlayer;
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;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
@CheckData(name = "PacketOrderB", description = "Did not swing for attack")
public class PacketOrderB extends Check implements PacketCheck {
// 1.9 packet order: INTERACT -> ANIMATION
// 1.8 packet order: ANIMATION -> INTERACT
// I personally think 1.8 made much more sense. You swing and THEN you hit!
private final boolean is1_9 = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_9);
// There is a "bug" in ViaRewind
// 1.8 packet order: ANIMATION -> INTERACT
// 1.9 packet order: INTERACT -> ANIMATION
// ViaRewind, on 1.9+ servers, delays a 1.8 client's ANIMATION to be after INTERACT (but before flying).
// Which means we see 1.9 packet order for 1.8 clients
// Due to ViaRewind also delaying the swings, we then see packet order above 20CPS like:
// INTERACT -> INTERACT -> ANIMATION -> ANIMATION
// I will simply disable this check for 1.8- clients on 1.9+ servers as I can't be bothered to find a way around this.
// Stop supporting such old clients on modern servers!
private final boolean exempt = player.getClientVersion().isOlderThan(ClientVersion.V_1_9)
&& PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9);
private boolean sentAnimationSinceLastAttack = player.getClientVersion().isNewerThan(ClientVersion.V_1_8);
private boolean sentAttack, sentAnimation, sentSlotSwitch;
public PacketOrderB(final GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (exempt) return;
if (event.getPacketType() == PacketType.Play.Client.ANIMATION) {
sentAnimationSinceLastAttack = sentAnimation = true;
sentAttack = sentSlotSwitch = false;
return;
}
if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event);
if (packet.getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) {
sentAttack = true;
if (is1_9 ? !sentAnimationSinceLastAttack : !sentAnimation) {
sentAttack = false; // don't flag twice
if (flagAndAlert("pre-attack") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
sentAnimationSinceLastAttack = sentAnimation = sentSlotSwitch = false;
return;
}
}
if (event.getPacketType() == PacketType.Play.Client.HELD_ITEM_CHANGE && !is1_9 && !sentSlotSwitch) {
sentSlotSwitch = true;
return; // do not set sentAnimation to false
}
if (!isAsync(event.getPacketType())) {
if (sentAttack && is1_9) {
flagAndAlert("post-attack");
}
sentAttack = sentAnimation = sentSlotSwitch = false;
}
}
}
@@ -1,43 +0,0 @@
package ac.grim.grimac.checks.impl.packetorder;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
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;
import static com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying.isFlying;
@CheckData(name = "PacketOrderO", experimental = true)
public class PacketOrderO extends Check implements PacketCheck {
public PacketOrderO(final GrimPlayer player) {
super(player);
}
private boolean flying;
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.CLIENT_TICK_END) {
flying = false;
}
if (isFlying(event.getPacketType()) && player.supportsEndTick() && !player.packetStateData.lastPacketWasTeleport) {
flying = true;
return;
}
if (flying && !isAsync(event.getPacketType()) && event.getPacketType() != PacketType.Play.Client.VEHICLE_MOVE) {
if (player.inVehicle() && event.getPacketType() == PacketType.Play.Client.ENTITY_ACTION) {
WrapperPlayClientEntityAction.Action action = new WrapperPlayClientEntityAction(event).getAction();
if (action == WrapperPlayClientEntityAction.Action.START_SPRINTING || action == WrapperPlayClientEntityAction.Action.STOP_SPRINTING) {
return;
}
}
flagAndAlert("type=" + event.getPacketType());
}
}
}
@@ -1,54 +0,0 @@
package ac.grim.grimac.checks.impl.packetorder;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
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;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerBundle;
import it.unimi.dsi.fastutil.ints.IntArrayList;
@CheckData(name = "PacketOrderP", experimental = true)
public class PacketOrderP extends Check implements PacketCheck {
public PacketOrderP(final GrimPlayer player) {
super(player);
}
private byte trimTimer; // let the list shrink eventually
private final IntArrayList transactions = new IntArrayList(0);
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.CHUNK_BATCH_ACK) {
if (!transactions.rem(player.getLastTransactionReceived())) {
flagAndAlert("invalid response");
}
} else if (!isAsync(event.getPacketType()) && !isTransaction(event.getPacketType())) {
if (transactions.rem(player.getLastTransactionReceived())) {
flagAndAlert("skipped response, type=" + event.getPacketType());
}
}
}
public void onPacketSend(PacketSendEvent event) {
if (event.getPacketType() == PacketType.Play.Server.CHUNK_BATCH_END) {
boolean sendingBundlePacket = player.packetStateData.sendingBundlePacket;
if (!sendingBundlePacket) player.user.sendPacket(new WrapperPlayServerBundle());
player.sendTransaction();
int transaction = player.getLastTransactionSent();
transactions.add(transaction);
if (++trimTimer == 0) transactions.trim();
player.addRealTimeTaskNext(() -> {
if (transactions.rem(transaction))
flagAndAlert("skipped response, type=TRANSACTION");
});
if (!sendingBundlePacket) {
event.getTasksAfterSend().add(() -> player.user.sendPacket(new WrapperPlayServerBundle()));
}
}
}
}
@@ -1,145 +0,0 @@
package ac.grim.grimac.checks.impl.prediction;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.checks.debug.AbstractDebugHandler;
import ac.grim.grimac.checks.type.PostPredictionCheck;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.update.PredictionComplete;
import ac.grim.grimac.utils.lists.EvictingQueue;
import ac.grim.grimac.utils.math.Vector3dm;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.minimessage.MiniMessage;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public class DebugHandler extends AbstractDebugHandler implements PostPredictionCheck {
private static final Component GRAY_ARROW = MiniMessage.miniMessage().deserialize("<gray>→0.03→</gray>");
private static final Component P_PREFIX = MiniMessage.miniMessage().deserialize("<reset>P: </reset>");
private static final Component A_PREFIX = MiniMessage.miniMessage().deserialize("<reset>A: </reset>");
private static final Component O_PREFIX = MiniMessage.miniMessage().deserialize("<reset>O: </reset>");
private final Set<GrimPlayer> listeners = new CopyOnWriteArraySet<>(new HashSet<>());
private boolean outputToConsole = false;
private boolean enabledFlags = false;
private boolean lastMovementIsFlag = false;
private final EvictingQueue<Component> predicted = new EvictingQueue<>(5);
private final EvictingQueue<Component> actually = new EvictingQueue<>(5);
private final EvictingQueue<Component> offset = new EvictingQueue<>(5);
public DebugHandler(GrimPlayer player) {
super(player);
}
@Override
public void onPredictionComplete(final PredictionComplete predictionComplete) {
if (!predictionComplete.isChecked()) return;
double offset = predictionComplete.getOffset();
if (listeners.isEmpty() && !outputToConsole) return;
if (player.predictedVelocity.vector.lengthSquared() == 0 && offset == 0) return;
String color = pickColor(offset, offset);
Vector3dm predicted = player.predictedVelocity.vector;
Vector3dm actually = player.actualMovement;
String xColor = pickColor(Math.abs(predicted.getX() - actually.getX()), offset);
String yColor = pickColor(Math.abs(predicted.getY() - actually.getY()), offset);
String zColor = pickColor(Math.abs(predicted.getZ() - actually.getZ()), offset);
Component p = Component.empty()
.append(P_PREFIX.color(NamedTextColor.NAMES.value(color)))
.append(Component.text(predicted.getX()).color(NamedTextColor.NAMES.value(xColor)))
.append(Component.space())
.append(Component.text(predicted.getY()).color(NamedTextColor.NAMES.value(yColor)))
.append(Component.space())
.append(Component.text(predicted.getZ()).color(NamedTextColor.NAMES.value(zColor)));
Component a = Component.empty()
.append(A_PREFIX.color(NamedTextColor.NAMES.value(color)))
.append(Component.text(actually.getX()).color(NamedTextColor.NAMES.value(xColor)))
.append(Component.space())
.append(Component.text(actually.getY()).color(NamedTextColor.NAMES.value(yColor)))
.append(Component.space())
.append(Component.text(actually.getZ()).color(NamedTextColor.NAMES.value(zColor)));
String canSkipTick = (player.couldSkipTick + " ").substring(0, 1);
String actualMovementSkip = (player.skippedTickInActualMovement + "").charAt(0) + " ";
Component o = Component.empty()
.append(Component.text(canSkipTick).color(NamedTextColor.GRAY))
.append(GRAY_ARROW)
.append(Component.text(actualMovementSkip).color(NamedTextColor.GRAY))
.append(O_PREFIX.color(NamedTextColor.NAMES.value(color)))
.append(Component.text(offset));
String prefix = player.platformPlayer == null ? "null" : player.platformPlayer.getName() + " ";
Component prefixComponent = Component.text(prefix);
boolean thisFlag = !color.equals("gray") && !color.equals("green");
if (enabledFlags) {
if (lastMovementIsFlag) {
this.predicted.clear();
this.actually.clear();
this.offset.clear();
}
this.predicted.add(p);
this.actually.add(a);
this.offset.add(o);
lastMovementIsFlag = thisFlag;
}
if (thisFlag) {
for (int i = 0; i < this.predicted.size(); i++) {
player.user.sendMessage(this.predicted.get(i));
player.user.sendMessage(this.actually.get(i));
player.user.sendMessage(this.offset.get(i));
}
}
for (GrimPlayer listener : listeners) {
Component listenerPrefix = listener == getPlayer() ? Component.empty() : prefixComponent;
listener.sendMessage(listenerPrefix.append(p));
listener.sendMessage(listenerPrefix.append(a));
listener.sendMessage(listenerPrefix.append(o));
}
listeners.removeIf(player -> player.platformPlayer != null && !player.platformPlayer.isOnline());
if (outputToConsole) {
Sender consoleSender = GrimAPI.INSTANCE.getPlatformServer().getConsoleSender();
consoleSender.sendMessage(p);
consoleSender.sendMessage(a);
consoleSender.sendMessage(o);
}
}
private String pickColor(double offset, double totalOffset) {
if (player.getSetbackTeleportUtil().blockOffsets) return "gray";
if (offset <= 0 || totalOffset <= 0) {
return "gray";
} else if (offset < 0.0001) {
return "green";
} else if (offset < 0.01) {
return "yellow";
} else {
return "red";
}
}
@Override
public void toggleListener(GrimPlayer player) {
if (!listeners.remove(player)) listeners.add(player);
}
@Override
public boolean toggleConsoleOutput() {
this.outputToConsole = !outputToConsole;
return this.outputToConsole;
}
}
@@ -1,28 +0,0 @@
package ac.grim.grimac.checks.impl.sprint;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PostPredictionCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.update.PredictionComplete;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
@CheckData(name = "SprintG", description = "Sprinting while in water", experimental = true)
public class SprintG extends Check implements PostPredictionCheck {
public SprintG(GrimPlayer player) {
super(player);
}
@Override
public void onPredictionComplete(final PredictionComplete predictionComplete) {
if (player.wasTouchingWater && (player.wasWasTouchingWater || player.getClientVersion() == ClientVersion.V_1_21_4)
&& !player.wasEyeInWater && player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_13)
&& player.wasLastPredictionCompleteChecked && predictionComplete.isChecked()) {
if (player.isSprinting && !player.isSwimming) {
flagAndAlertWithSetback();
} else {
reward();
}
}
}
}
@@ -1,55 +0,0 @@
package ac.grim.grimac.checks.impl.timer;
import ac.grim.grimac.api.config.ConfigManager;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.player.GrimPlayer;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
// This works around 1.3 timer, to prevent too high abuse - maybe there's a better solution?
@CheckData(name = "TimerLimit", setback = 10)
public class TimerLimit extends Timer {
// At what ping should we start to limit the balance advantage? (nanos)
private long limitAbuseOverPing;
public TimerLimit(GrimPlayer player) {
super(player);
}
@Override
public void doCheck(final PacketReceiveEvent event) {
// 1:1 with Timer minus cancelling the packet
if (timerBalanceRealTime > System.nanoTime()) {
// If timer check already flagged, don't flag.
if (!event.isCancelled()) {
if (flagAndAlert() && shouldSetback()) {
player.getSetbackTeleportUtil().executeNonSimulatingSetback();
}
}
// Reset the violation by 1 movement
timerBalanceRealTime -= 50e6;
}
limitFallBehind();
}
@Override
protected void limitFallBehind() {
// Limit using transaction ping if over 1000ms (default)
long playerClock = lastMovementPlayerClock;
if (limitAbuseOverPing != -1 && System.nanoTime() - playerClock > limitAbuseOverPing) {
playerClock = System.nanoTime() - limitAbuseOverPing;
}
timerBalanceRealTime = Math.max(timerBalanceRealTime, playerClock - clockDrift);
}
@Override
public void onReload(ConfigManager config) {
super.onReload(config);
limitAbuseOverPing = config.getLongElse(getConfigName() + ".ping-abuse-limit-threshold", 1000L);
if (limitAbuseOverPing != -1) {
limitAbuseOverPing *= (long) 1e6;
}
}
}
@@ -1,31 +0,0 @@
package ac.grim.grimac.checks.impl.vehicle;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
import ac.grim.grimac.player.GrimPlayer;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
@CheckData(name = "VehicleE", experimental = true, description = "Sent boat paddle states while not in a boat")
public class VehicleE extends Check implements PacketCheck {
public VehicleE(GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(final PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.STEER_BOAT) {
final EntityType vehicle = player.getVehicleType();
if (!EntityTypes.isTypeInstanceOf(vehicle, EntityTypes.BOAT)) {
if (flagAndAlert("vehicle=" + (vehicle == null ? "null" : vehicle.getName().getKey().toLowerCase())) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
}
}
}
@@ -1,59 +0,0 @@
package ac.grim.grimac.checks.impl.vehicle;
import ac.grim.grimac.checks.Check;
import ac.grim.grimac.checks.CheckData;
import ac.grim.grimac.checks.type.PacketCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.data.KnownInput;
import ac.grim.grimac.utils.data.packetentity.PacketEntity;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientSteerBoat;
@CheckData(name = "VehicleF", experimental = true, description = "Sent incorrect boat paddle states")
public class VehicleF extends Check implements PacketCheck {
public VehicleF(GrimPlayer player) {
super(player);
}
private PacketEntity lastTickVehicle;
@Override
public void onPacketReceive(final PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.STEER_BOAT) {
// lastVehicleSwitch isn't updated by this time.
if (lastTickVehicle != player.getVehicle()) return;
WrapperPlayClientSteerBoat packet = new WrapperPlayClientSteerBoat(event);
boolean expectedLeft;
boolean expectedRight;
if (player.supportsEndTick()) {
KnownInput input = player.packetStateData.knownInput;
expectedLeft = input.forward() || !input.left() && input.right();
expectedRight = input.forward() || input.left() && !input.right();
} else {
expectedLeft = player.vehicleData.nextVehicleForward > 0 || player.vehicleData.nextVehicleHorizontal < 0;
expectedRight = player.vehicleData.nextVehicleForward > 0 || player.vehicleData.nextVehicleHorizontal > 0;
if (player.vehicleData.nextVehicleForward == 0 && packet.isLeftPaddleTurning() && packet.isRightPaddleTurning()) {
return; // the player is pressing forward and backward
}
}
if (packet.isLeftPaddleTurning() != expectedLeft || packet.isRightPaddleTurning() != expectedRight) {
if (flagAndAlert("sent=(" + packet.isLeftPaddleTurning() + ", " + packet.isRightPaddleTurning() + "), expected=(" + expectedLeft + ", " + expectedRight + ")")
&& shouldModifyPackets()) {
packet.setLeftPaddleTurning(expectedLeft);
packet.setRightPaddleTurning(expectedRight);
event.markForReEncode(true);
}
}
}
if (isTickPacket(event.getPacketType())) {
lastTickVehicle = player.getVehicle();
}
}
}
@@ -1,51 +0,0 @@
package ac.grim.grimac.checks.impl.velocity;
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.util.LpVector3d;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import io.netty.buffer.Unpooled;
import lombok.experimental.UtilityClass;
@UtilityClass
public class VectorPrecisionConverter {
private static final ServerVersion SERVER_VERSION = PacketEvents.getAPI().getServerManager().getVersion();
public static Vector3d convert(ClientVersion version, Vector3d vector) {
if (version.isNewerThanOrEquals(ClientVersion.V_1_21_9) && SERVER_VERSION.isOlderThanOrEquals(ServerVersion.V_1_21_8)) {
return VectorPrecisionConverter.legacyToLp(vector);
} else if (version.isOlderThanOrEquals(ClientVersion.V_1_21_7) && SERVER_VERSION.isNewerThanOrEquals(ServerVersion.V_1_21_9)) {
return VectorPrecisionConverter.lpToLegacy(vector);
}
return vector;
}
public static Vector3d legacyToLp(Vector3d legacy) {
PacketWrapper<?> wrapper = PacketWrapper.createUniversalPacketWrapper(Unpooled.buffer());
LpVector3d.write(wrapper, legacy);
return LpVector3d.read(wrapper);
}
private static final double PRECISION_LOSS_FIX = 1e-11d;
public static Vector3d lpToLegacy(Vector3d lp) {
int xi = (int) (lp.x * 8000d + Math.copySign(PRECISION_LOSS_FIX, lp.x));
int yi = (int) (lp.y * 8000d + Math.copySign(PRECISION_LOSS_FIX, lp.y));
int zi = (int) (lp.z * 8000d + Math.copySign(PRECISION_LOSS_FIX, lp.z));
short x = (short) xi;
short y = (short) yi;
short z = (short) zi;
return new Vector3d(
x / 8000d,
y / 8000d,
z / 8000d
);
}
}
@@ -1,8 +0,0 @@
package ac.grim.grimac.command;
import ac.grim.grimac.platform.api.sender.Sender;
import org.incendo.cloud.CommandManager;
public interface BuildableCommand {
void register(CommandManager<Sender> manager);
}
@@ -1,36 +0,0 @@
package ac.grim.grimac.command;
import ac.grim.grimac.platform.api.sender.Sender;
import lombok.RequiredArgsConstructor;
import lombok.experimental.UtilityClass;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.context.CommandInput;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@UtilityClass
public class CommandUtils {
@Contract("_ -> new")
public static @NotNull SuggestionProvider<Sender> fromStrings(@NotNull String @NotNull ... strings) {
List<Suggestion> suggestions = new ArrayList<>(strings.length);
for (String s : strings) suggestions.add(Suggestion.suggestion(s));
return new SenderSuggestionProvider(Collections.unmodifiableList(suggestions));
}
@RequiredArgsConstructor
private class SenderSuggestionProvider implements SuggestionProvider<Sender> {
private final List<Suggestion> suggestions;
@Override
public @NotNull CompletableFuture<? extends @NotNull Iterable<? extends @NotNull Suggestion>> suggestionsFuture(@NotNull CommandContext context, @NotNull CommandInput input) {
return CompletableFuture.completedFuture(suggestions);
}
}
}
@@ -1,10 +0,0 @@
package ac.grim.grimac.command;
import ac.grim.grimac.platform.api.sender.Sender;
import net.kyori.adventure.text.Component;
import org.incendo.cloud.processors.requirements.Requirement;
import org.jetbrains.annotations.NotNull;
public interface SenderRequirement extends Requirement<Sender, SenderRequirement> {
@NotNull Component errorMessage(Sender sender);
}
@@ -1,33 +0,0 @@
package ac.grim.grimac.command.commands;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.command.BuildableCommand;
import ac.grim.grimac.platform.api.sender.Sender;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.description.Description;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class GrimAlerts implements BuildableCommand {
@Override
public void register(CommandManager<Sender> commandManager) {
commandManager.command(
commandManager.commandBuilder("grim", "grimac")
.literal("alerts", Description.of("Toggle alerts for the sender"))
.permission("grim.alerts")
.handler(this::handleAlerts)
);
}
// Suppress warning as we've already checked sender is not console
private void handleAlerts(@NotNull CommandContext<Sender> context) {
Sender sender = context.sender();
if (sender.isPlayer()) {
GrimAPI.INSTANCE.getAlertManager().toggleAlerts(Objects.requireNonNull(context.sender().getPlatformPlayer()), false);
} else if (sender.isConsole()) {
GrimAPI.INSTANCE.getAlertManager().toggleConsoleAlerts();
}
}
}
@@ -1,32 +0,0 @@
package ac.grim.grimac.command.commands;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.command.BuildableCommand;
import ac.grim.grimac.platform.api.sender.Sender;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.description.Description;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class GrimBrands implements BuildableCommand {
@Override
public void register(CommandManager<Sender> commandManager) {
commandManager.command(
commandManager.commandBuilder("grim", "grimac")
.literal("brands", Description.of("Toggle brands for the sender"))
.permission("grim.brand")
.handler(this::handleBrands)
);
}
private void handleBrands(@NotNull CommandContext<Sender> context) {
Sender sender = context.sender();
if (sender.isPlayer()) {
GrimAPI.INSTANCE.getAlertManager().toggleBrands(Objects.requireNonNull(context.sender().getPlatformPlayer()), false);
} else if (sender.isConsole()) {
GrimAPI.INSTANCE.getAlertManager().toggleConsoleBrands();
}
}
}
@@ -1,115 +0,0 @@
package ac.grim.grimac.command.commands;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.command.BuildableCommand;
import ac.grim.grimac.platform.api.command.PlayerSelector;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.MessageUtil;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.player.User;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.description.Description;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class GrimDebug implements BuildableCommand {
public void register(CommandManager<Sender> commandManager) {
Command.Builder<Sender> grimCommand = commandManager.commandBuilder("grim", "grimac");
// Register "debug" subcommand
Command.Builder<Sender> debugCommand = grimCommand
.literal("debug", Description.of("Toggle debug output for a player"))
.permission("grim.debug")
.optional("target", GrimAPI.INSTANCE.getCommandAdapter().singlePlayerSelectorParser())
.handler(this::handleDebug);
// Register "consoledebug" subcommand
Command.Builder<Sender> consoleDebugCommand = grimCommand
.literal("consoledebug", Description.of("Toggle console debug output for a player"))
.permission("grim.consoledebug")
.required("target", GrimAPI.INSTANCE.getCommandAdapter().singlePlayerSelectorParser())
.handler(this::handleConsoleDebug);
// Register command
commandManager.command(debugCommand);
commandManager.command(consoleDebugCommand);
}
private void handleDebug(@NotNull CommandContext<Sender> context) {
Sender sender = context.sender();
PlayerSelector playerSelector = context.getOrDefault("target", null);
GrimPlayer targetGrimPlayer = parseTarget(sender, playerSelector == null ? sender : playerSelector.getSinglePlayer());
if (targetGrimPlayer == null) {
sender.sendMessage(MessageUtil.getParsedComponent(sender, "player-not-found", "%prefix% &cPlayer is exempt or offline!"));
return;
}
if (sender.isConsole()) {
targetGrimPlayer.checkManager.getDebugHandler().toggleConsoleOutput();
} else if (sender.isPlayer()) {
GrimPlayer senderGrimPlayer = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(sender.getUniqueId());
if (senderGrimPlayer == null) {
sender.sendMessage(MessageUtil.getParsedComponent(sender, "sender-not-found", "%prefix% &cYou cannot be exempt to use this command!"));
return;
}
targetGrimPlayer.checkManager.getDebugHandler().toggleListener(senderGrimPlayer);
} else {
sender.sendMessage(MessageUtil.getParsedComponent(sender,
"run-as-player-or-console",
"%prefix% &cThis command can only be used by players or the console!")
);
}
}
private void handleConsoleDebug(@NotNull CommandContext<Sender> context) {
Sender sender = context.sender();
PlayerSelector targetName = context.getOrDefault("target", null);
GrimPlayer grimPlayer = parseTarget(sender, targetName.getSinglePlayer());
if (grimPlayer == null) return;
boolean isOutput = grimPlayer.checkManager.getDebugHandler().toggleConsoleOutput();
String playerName = grimPlayer.user.getProfile().getName(); // Use user profile for name
Component message = Component.text()
.append(Component.text("Console output for ", NamedTextColor.GRAY))
.append(Component.text(playerName, NamedTextColor.WHITE))
.append(Component.text(" is now ", NamedTextColor.GRAY))
.append(Component.text(isOutput ? "enabled" : "disabled", NamedTextColor.WHITE))
.build();
sender.sendMessage(message);
}
private @Nullable GrimPlayer parseTarget(@NotNull Sender sender, @Nullable Sender t) {
if (sender.isConsole() && t == null) {
sender.sendMessage(MessageUtil.getParsedComponent(sender, "console-specify-target", "%prefix% &cYou must specify a target as the console!"));
return null;
}
Sender target = t == null ? sender : t;
GrimPlayer grimPlayer = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(target.getUniqueId());
if (grimPlayer == null) {
User user = PacketEvents.getAPI().getPlayerManager().getUser(sender.getPlatformPlayer().getNative());
sender.sendMessage(MessageUtil.getParsedComponent(sender, "player-not-found", "%prefix% &cPlayer is exempt or offline!"));
if (user == null) {
sender.sendMessage(Component.text("Unknown PacketEvents user", NamedTextColor.RED));
} else {
boolean isExempt = GrimAPI.INSTANCE.getPlayerDataManager().shouldCheck(user);
if (!isExempt) {
sender.sendMessage(Component.text("User connection state: " + user.getConnectionState(), NamedTextColor.RED));
}
}
}
return grimPlayer;
}
}
@@ -1,114 +0,0 @@
package ac.grim.grimac.command.commands;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.command.BuildableCommand;
import ac.grim.grimac.platform.api.PlatformPlugin;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.utils.anticheat.MessageUtil;
import ac.grim.grimac.utils.common.PropertiesUtil;
import ac.grim.grimac.utils.reflection.ReflectionUtils;
import ac.grim.grimac.utils.reflection.ViaVersionUtil;
import com.github.retrooper.packetevents.PacketEvents;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.description.Description;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.Properties;
public class GrimDump implements BuildableCommand {
private static final boolean PAPER = ReflectionUtils.hasClass("com.destroystokyo.paper.PaperConfig")
|| ReflectionUtils.hasClass("io.papermc.paper.configuration.Configuration");
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
private String link = null; // these links should not expire for a while
@Override
public void register(CommandManager<Sender> commandManager) {
commandManager.command(
commandManager.commandBuilder("grim", "grimac")
.literal("dump", Description.of("Generate a debug dump"))
.permission("grim.dump")
.handler(this::handleDump)
);
}
private void handleDump(@NotNull CommandContext<Sender> context) {
Sender sender = context.sender();
if (link != null) {
sender.sendMessage(MessageUtil.miniMessage(GrimAPI.INSTANCE.getConfigManager().getConfig()
.getStringElse("upload-log", "%prefix% &fUploaded debug to: %url%")
.replace("%url%", link)));
return;
}
// TODO: change this back to application/json once allowed
GrimLog.sendLogAsync(sender, generateDump(), string -> link = string, "text/yaml");
}
public static JsonObject getBasicInfo(String type) {
JsonObject base = new JsonObject();
base.addProperty("type", type);
base.addProperty("timestamp", System.currentTimeMillis());
// versions
JsonObject versions = new JsonObject();
base.add("versions", versions);
versions.addProperty("grim", GrimAPI.INSTANCE.getExternalAPI().getGrimVersion());
versions.addProperty("packetevents", PacketEvents.getAPI().getVersion().toString());
versions.addProperty("server", PacketEvents.getAPI().getServerManager().getVersion().getReleaseName());
versions.addProperty("implementation", GrimAPI.INSTANCE.getPlatformServer().getPlatformImplementationString());
// state of different properties
JsonObject states = new JsonObject();
base.add("states", states);
if (GrimAPI.INSTANCE.isInitialized()) states.addProperty("platform", GrimAPI.INSTANCE.getPlatform().toString());
if (ViaVersionUtil.isAvailable) states.addProperty("has_viaversion", true);
if (PAPER) states.addProperty("has_paper", true);
// system
JsonObject system = new JsonObject();
base.add("system", system);
system.addProperty("os_name", System.getProperty("os.name"));
system.addProperty("java_version", System.getProperty("java.version"));
system.addProperty("user_language", System.getProperty("user.language"));
// build
JsonObject build = new JsonObject();
base.add("build", getBuildInfo());
return base;
}
private static JsonObject getBuildInfo() {
JsonObject object = new JsonObject();
try {
Properties properties = PropertiesUtil.readProperties(GrimAPI.INSTANCE.getClass(), "grimac.properties");
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
object.addProperty(entry.getKey().toString(), entry.getValue().toString());
}
} catch (Exception ignored) {}
return object;
}
/**
* Generates a diagnostic dump in JSON format that contains various metadata
* about the system, platform, and plugins. This dump is primarily used for
* debugging and finding potential issues with the environment.
* @return A JSON-formatted string containing the diagnostic dump.
*/
private String generateDump() {
JsonObject base = getBasicInfo("dump");
// plugins
JsonArray plugins = new JsonArray();
base.add("plugins", plugins);
for (PlatformPlugin plugin : GrimAPI.INSTANCE.getPluginManager().getPlugins()) {
JsonObject pluginJson = new JsonObject();
pluginJson.addProperty("enabled", plugin.isEnabled());
pluginJson.addProperty("name", plugin.getName());
pluginJson.addProperty("version", plugin.getVersion());
plugins.add(pluginJson);
}
return gson.toJson(base);
}
}
@@ -1,32 +0,0 @@
package ac.grim.grimac.command.commands;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.command.BuildableCommand;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.utils.anticheat.MessageUtil;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.description.Description;
import org.jetbrains.annotations.NotNull;
public class GrimHelp implements BuildableCommand {
@Override
public void register(CommandManager<Sender> commandManager) {
commandManager.command(
commandManager.commandBuilder("grim", "grimac")
.literal("help", Description.of("Display help information"))
.permission("grim.help")
.handler(this::handleHelp)
);
}
private void handleHelp(@NotNull CommandContext<Sender> context) {
Sender sender = context.sender();
for (String string : GrimAPI.INSTANCE.getConfigManager().getConfig().getStringList("help")) {
if (string == null) continue;
string = MessageUtil.replacePlaceholders(sender, string);
sender.sendMessage(MessageUtil.miniMessage(string));
}
}
}
@@ -1,124 +0,0 @@
package ac.grim.grimac.command.commands;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.command.BuildableCommand;
import ac.grim.grimac.manager.violationdatabase.Violation;
import ac.grim.grimac.manager.violationdatabase.ViolationDatabaseManager;
import ac.grim.grimac.platform.api.player.OfflinePlatformPlayer;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.utils.anticheat.MessageUtil;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.parser.standard.IntegerParser;
import org.incendo.cloud.parser.standard.StringParser;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class GrimHistory implements BuildableCommand {
@Override
public void register(CommandManager<Sender> commandManager) {
commandManager.command(
commandManager.commandBuilder("grim", "grimac")
.literal("history", "hist")
.permission("grim.help")
.required("target", StringParser.stringParser(), GrimAPI.INSTANCE.getCommandAdapter().onlinePlayerSuggestions())
.optional("page", IntegerParser.integerParser())
.permission("grim.history")
.handler(this::handleHistory)
);
}
private void handleHistory(CommandContext<Sender> context) {
Sender sender = context.sender();
String target = context.get("target");
Integer page = context.getOrDefault("page", 1);
if (!GrimAPI.INSTANCE.getViolationDatabaseManager().isEnabled()) {
String msg = GrimAPI.INSTANCE.getConfigManager().getConfig()
.getStringElse("grim-history-disabled",
"%prefix% &cHistory subsystem is disabled!");
sender.sendMessage(MessageUtil.miniMessage(msg));
return;
} else if (!GrimAPI.INSTANCE.getViolationDatabaseManager().isLoaded()) {
String msg = GrimAPI.INSTANCE.getConfigManager().getConfig()
.getStringElse("grim-history-load-failure",
"%prefix% &cHistory subsystem failed to load! Check server console for errors.");
sender.sendMessage(MessageUtil.miniMessage(msg));
return;
}
GrimAPI.INSTANCE.getScheduler().getAsyncScheduler().runNow(GrimAPI.INSTANCE.getGrimPlugin(), () -> {
int entriesPerPage = GrimAPI.INSTANCE.getConfigManager().getConfig().getIntElse("history.entries-per-page", 15);
String header = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("grim-history-header",
"%prefix% &bShowing logs for &f%player% (&f%page%&b/&f%maxPages%&f)");
String logFormat = GrimAPI.INSTANCE.getConfigManager().getConfig().getStringElse("grim-history-entry",
"%prefix% &8[&f%server%&8] &bFailed &f%check% (x&c%vl%&f) &7%verbose% (&b%timeago% ago&7)");
OfflinePlatformPlayer targetPlayer = GrimAPI.INSTANCE.getPlatformPlayerFactory().getOfflineFromName(target);
ViolationDatabaseManager violations = GrimAPI.INSTANCE.getViolationDatabaseManager();
int logCount = violations.getLogCount(targetPlayer.getUniqueId());
List<Violation> logs = violations.getViolations(targetPlayer.getUniqueId(), page, entriesPerPage);
int maxPages = (int) Math.ceil((float) logCount / entriesPerPage);
sender.sendMessage(MessageUtil.miniMessage(MessageUtil.replacePlaceholders(sender, header
.replace("%player%", targetPlayer.getName())
.replace("%page%", String.valueOf(page))
.replace("%maxPages%", String.valueOf(maxPages))
)));
for (int i = logs.size() - 1; i >= 0; i--) {
Violation log = logs.get(i);
sender.sendMessage(MessageUtil.miniMessage(MessageUtil.replacePlaceholders(sender, logFormat
.replace("%player%", targetPlayer.getName())
.replace("%grim_version%", log.grimVersion())
.replace("%client_brand%", log.clientBrand())
.replace("%client_version%", log.clientVersion())
.replace("%server_version%", log.serverVersion())
.replace("%check%", log.checkName())
.replace("%verbose%", log.verbose())
.replace("%vl%", String.valueOf(log.vl()))
.replace("%timeago%", getTimeAgo(log.createdAt()))
.replace("%server%", log.server())
)));
}
});
}
/**
* Calculates the time elapsed since a given timestamp in a human-readable format.
*
* @param timestamp The timestamp in milliseconds since epoch (e.g., from System.currentTimeMillis()).
* @return A string representing the time elapsed (e.g., "5d 3h 10m").
*/
private String getTimeAgo(long timestamp) {
// Calculate duration directly from current time and the provided timestamp
long durationMillis = System.currentTimeMillis() - timestamp;
// Ensure duration is non-negative, though for "time ago" it should be.
if (durationMillis < 0) {
return "0s"; // Or handle as an error/future time
}
long days = TimeUnit.MILLISECONDS.toDays(durationMillis);
durationMillis -= TimeUnit.DAYS.toMillis(days);
long hours = TimeUnit.MILLISECONDS.toHours(durationMillis);
durationMillis -= TimeUnit.HOURS.toMillis(hours);
long minutes = TimeUnit.MILLISECONDS.toMinutes(durationMillis);
durationMillis -= TimeUnit.MINUTES.toMillis(minutes);
long seconds = TimeUnit.MILLISECONDS.toSeconds(durationMillis);
StringBuilder result = new StringBuilder();
if (days > 0) result.append(days).append("d ");
if (hours > 0) result.append(hours).append("h ");
if (minutes > 0) result.append(minutes).append("m ");
if (seconds > 0 || result.isEmpty()) result.append(seconds).append("s"); // Always show seconds if nothing else, or if it's 0s.
return result.toString().trim();
}
}
@@ -1,120 +0,0 @@
package ac.grim.grimac.command.commands;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.GrimIdentity;
import ac.grim.grimac.command.BuildableCommand;
import ac.grim.grimac.command.CommandUtils;
import ac.grim.grimac.platform.api.player.PlatformPlayer;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.player.GrimPlayer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.parser.standard.StringParser;
import org.incendo.cloud.suggestion.SuggestionProvider;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
public class GrimList implements BuildableCommand {
// Mainly for debugging purposes. Useful for seeing which players are exempt or not.
@Override
public void register(CommandManager<Sender> commandManager) {
commandManager.command(commandManager.commandBuilder("grim", "grimac")
.literal("list")
.permission("grim.list")
.required("list", StringParser.stringParser(), SUGGESTIONS)
.handler(commandContext -> handleList(commandContext.sender(), commandContext.getOrDefault("list", "?").toLowerCase()))
.build());
}
private final SuggestionProvider<Sender> SUGGESTIONS = CommandUtils.fromStrings("players");
private void handleList(Sender sender, String id) {
switch (id) {
case "players" -> handleListPlayers(sender);
default -> sender.sendMessage(Component.text()
.append(Component.text("Invalid argument: ", NamedTextColor.GRAY))
.append(Component.text(id, NamedTextColor.RED))
.build());
}
}
private Component playerComponent(String name, UUID uuid, boolean online, boolean exempt) {
return Component.text(name)
.color(exempt ? (online ? NamedTextColor.GRAY : NamedTextColor.DARK_GRAY)
: (online ? NamedTextColor.WHITE : NamedTextColor.RED))
.clickEvent(ClickEvent.copyToClipboard(name))
.hoverEvent(HoverEvent.showText(playerHoverComponent(uuid, online, exempt, true)));
}
private Component playerHoverComponent(UUID uuid, boolean online, boolean exempt, boolean registered) {
var builder = Component.text();
builder.append(Component.text()
.append(Component.text("UUID: ").color(NamedTextColor.GRAY))
.append(Component.text(uuid + "").color(NamedTextColor.WHITE))
.append(Component.newline())
.append(Component.text("Status: ").color(NamedTextColor.GRAY))
.append(online ? Component.text("Online").color(NamedTextColor.GREEN)
: Component.text("Offline").color(NamedTextColor.RED)));
if (exempt) {
builder.append(Component.newline());
builder.append(Component.text("Is Exempt").color(NamedTextColor.LIGHT_PURPLE));
}
if (!registered) {
builder.append(Component.newline());
builder.append(Component.text("Not Registered").color(NamedTextColor.RED));
}
return builder.build();
}
private void handleListPlayers(Sender sender) {
final TextComponent.Builder builder = Component.text();
final Map<UUID, PlatformPlayer> onlinePlayers = GrimAPI.INSTANCE.getPlatformPlayerFactory().getOnlinePlayers()
.stream().collect(Collectors.toMap(GrimIdentity::getUniqueId, Function.identity()));
//
final Set<PlatformPlayer> unregisteredPlayers = new HashSet<>(onlinePlayers.values());
boolean after = false;
builder.append(Component.text("Players = [", NamedTextColor.GRAY));
//
for (GrimPlayer entry : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
if (after) {
builder.append(Component.text(", ").color(NamedTextColor.GRAY));
} else {
after = true;
}
PlatformPlayer platformPlayer = onlinePlayers.get(entry.getUniqueId());
if (platformPlayer != null) unregisteredPlayers.remove(platformPlayer);
boolean online = platformPlayer != null && platformPlayer.isOnline();
boolean exempt = !GrimAPI.INSTANCE.getPlayerDataManager().shouldCheck(entry.user);
builder.append(playerComponent(entry.getName(), entry.getUniqueId(), online, exempt));
}
//
for (PlatformPlayer platformPlayer : unregisteredPlayers) {
if (after) {
builder.append(Component.text(", ").color(NamedTextColor.GRAY));
} else {
after = true;
}
builder.append(Component.text(platformPlayer.getName()).color(NamedTextColor.LIGHT_PURPLE)
.clickEvent(ClickEvent.suggestCommand(platformPlayer.getName()))
.hoverEvent(HoverEvent.showText(playerHoverComponent(platformPlayer.getUniqueId(), platformPlayer.isOnline(), false, false)))
);
}
// close and send
builder.append(Component.text("]", NamedTextColor.GRAY));
sender.sendMessage(builder.build());
}
}
@@ -1,44 +0,0 @@
package ac.grim.grimac.command.commands;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.predictionengine.MovementCheckRunner;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.context.CommandContext;
import org.jetbrains.annotations.NotNull;
public class GrimPerf {
public void register(CommandManager<Sender> commandManager) {
Command.Builder<Sender> grimCommand = commandManager.commandBuilder("grim", "grimac");
Command.Builder<Sender> configuredBuilder = grimCommand
.literal("perf", "performance")
.permission("grim.performance")
.handler(this::handlePerformance);
commandManager.command(configuredBuilder);
}
private void handlePerformance(@NotNull CommandContext<Sender> context) {
Sender sender = context.sender();
double millis = MovementCheckRunner.predictionNanos / 1000000;
double longMillis = MovementCheckRunner.longPredictionNanos / 1000000;
Component message1 = Component.text()
.append(Component.text("Milliseconds per prediction (avg. 500): ", NamedTextColor.GRAY))
.append(Component.text(millis, NamedTextColor.WHITE))
.build();
Component message2 = Component.text()
.append(Component.text("Milliseconds per prediction (avg. 20k): ", NamedTextColor.GRAY))
.append(Component.text(longMillis, NamedTextColor.WHITE))
.build();
sender.sendMessage(message1);
sender.sendMessage(message2);
}
}
@@ -1,50 +0,0 @@
package ac.grim.grimac.command.commands;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.command.BuildableCommand;
import ac.grim.grimac.platform.api.command.PlayerSelector;
import ac.grim.grimac.platform.api.player.PlatformPlayer;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.MessageUtil;
import net.kyori.adventure.text.Component;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.context.CommandContext;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class GrimProfile implements BuildableCommand {
@Override
public void register(CommandManager<Sender> commandManager) {
commandManager.command(
commandManager.commandBuilder("grim", "grimac")
.literal("profile")
.permission("grim.profile")
.required("target", GrimAPI.INSTANCE.getCommandAdapter().singlePlayerSelectorParser())
.handler(this::handleProfile)
);
}
private void handleProfile(@NotNull CommandContext<Sender> context) {
Sender sender = context.sender();
PlayerSelector target = context.get("target");
PlatformPlayer targetPlatformPlayer = target.getSinglePlayer().getPlatformPlayer();
if (Objects.requireNonNull(targetPlatformPlayer).isExternalPlayer()) {
sender.sendMessage(MessageUtil.getParsedComponent(sender,"player-not-this-server", "%prefix% &cThis player isn't on this server!"));
return;
}
GrimPlayer grimPlayer = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(targetPlatformPlayer.getUniqueId());
if (grimPlayer == null) {
sender.sendMessage(MessageUtil.getParsedComponent(sender, "player-not-found", "%prefix% &cPlayer is exempt or offline!"));
return;
}
for (String message : GrimAPI.INSTANCE.getConfigManager().getConfig().getStringList("profile")) {
final Component component = MessageUtil.miniMessage(message);
sender.sendMessage(MessageUtil.replacePlaceholders(grimPlayer, component));
}
}
}
@@ -1,37 +0,0 @@
package ac.grim.grimac.command.commands;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.command.BuildableCommand;
import ac.grim.grimac.platform.api.sender.Sender;
import ac.grim.grimac.utils.anticheat.MessageUtil;
import net.kyori.adventure.text.Component;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.context.CommandContext;
import org.jetbrains.annotations.NotNull;
public class GrimReload implements BuildableCommand {
@Override
public void register(CommandManager<Sender> commandManager) {
commandManager.command(
commandManager.commandBuilder("grim", "grimac")
.literal("reload")
.permission("grim.reload")
.handler(this::handleReload)
);
}
private void handleReload(@NotNull CommandContext<Sender> context) {
Sender sender = context.sender();
// reload config
sender.sendMessage(MessageUtil.getParsedComponent(sender, "reloading", "%prefix% &7Reloading config..."));
GrimAPI.INSTANCE.getExternalAPI().reloadAsync().exceptionally(throwable -> false)
.thenAccept(bool -> {
Component message = bool
? MessageUtil.getParsedComponent(sender, "reloaded", "%prefix% &fConfig has been reloaded.")
: MessageUtil.getParsedComponent(sender, "reload-failed", "%prefix% &cFailed to reload config.");
sender.sendMessage(message);
});
}
}
Loaded 100 of 826 files, more files were not shown because too many files have changed in this diff. Show more