Compare commits

..
Author SHA1 Message Date
Axionize bf80d63c4a Address code review concerns 2025-10-31 14:14:55 -04:00
Axionize 540fc454b9 Minor code review changes 2025-10-31 07:54:56 -04:00
Axionize cad28d6342 Merge remote-tracking branch 'origin/2.0' into optimize/vector-objects
# Conflicts:
#	common/src/main/java/ac/grim/grimac/utils/data/ReachInterpolationData.java
2025-10-30 13:29:09 -04:00
Axionize 978cbb293c Address more code review concerns 2025-10-30 13:27:43 -04:00
Axionize 42ce2122a8 Apply code review suggestions for Reachutils, BlockModifications, and CheckManagerListener 2025-10-30 13:18:59 -04:00
Axionize 096b01213c Fix code review concerns for break checks 2025-10-30 13:15:07 -04:00
SamB440 f8a5315fff We do not need high bound if player ticks reliably. 2025-10-28 13:27:54 +00:00
Axionize 22e9a649c5 Make input Vec2d 2025-10-27 17:02:48 -04:00
Axionize 8e470d82bc Primitivify inputs 2025-10-27 17:02:48 -04:00
Axionize de083b7b84 Make VectorData vector use primitives 2025-10-27 17:02:48 -04:00
Axionize 3f86a097de More TeleportData conversions 2025-10-27 17:02:48 -04:00
Axionize 1b3b3d7b1d Optimize Collisions forEach predicates 2025-10-27 17:02:48 -04:00
Axionize 40aa1eadbe Primitize more vehicle teleport code 2025-10-27 17:02:48 -04:00
Axionize fac7d98530 use more primitives for teleports 2025-10-27 17:02:48 -04:00
Axionize b9f16762f1 Make BlockBreak object use primitives 2025-10-27 17:02:48 -04:00
Axionize 441af405b7 Optimize usage of vector3i.getSerializedPosition() 2025-10-27 17:02:48 -04:00
Axionize 71fb934a7e Improve performance of updateBlock() 2025-10-27 17:02:48 -04:00
Axionize fe1d3b2b93 Fix minor bug and cleanup primitiiveify ReachInterpolationData 2025-10-27 17:02:48 -04:00
Axionize a408946c0e De Vector-ify TrackedPosition 2025-10-27 17:02:48 -04:00
Axionize f1192069ae Optimize MainSupportingBlockPosFinder 2025-10-27 17:02:48 -04:00
Axionize 09139062c6 Optimize VehiclePositionUpdate, PositionUpdate, and some VectorUtils usage 2025-10-27 17:02:48 -04:00
Axionize 813551a093 Optimize TeleportData 2025-10-27 17:02:47 -04:00
Axionize 3028b4d274 Improve Vector allocations in Reach, BlockPos, ReachUtils 2025-10-27 17:02:47 -04:00
Axionize 7daaca95eb More vector optimizations 2025-10-27 17:02:47 -04:00
AnnotationVisitor 102b5842e7 Add copper golem statue, shelf collision boxes and other missing 1.21.10 stuff (#2315)
* add copper golem statue

* Include ViaVersion substitution

* add shelves

* also add copper armor

* add mannequin box sizes

* Add copper golem size
2025-10-27 11:17:09 -06:00
ManInMyVan a76bf9ce09 add copper golem statue collision box 2025-10-26 19:01:29 -06:00
ManInMyVan 4f3e715f94 add shelf collision box 2025-10-26 18:41:25 -06:00
ManInMyVan 1b47e31776 allow up to one PLAYER_INPUT per tick (#2306) 2025-10-26 11:54:15 -06:00
BT (calcastor/mame) b69906f809 Clear active item before updating inventory on legacy (#2317)
* Apply spotless

* Clear active item before updating inventory on legacy
2025-10-23 22:56:12 -06:00
ManInMyVan 9ba4052c35 possibly fix build 2025-10-23 00:51:27 -06:00
ManInMyVan a86bf57a39 mark MultiActionsD as stable 2025-10-23 00:49:50 -06:00
ManInMyVan a82f2b888a mark MultiActionsC as stable 2025-10-23 00:49:23 -06:00
ManInMyVan 89cf181772 mark PositionBreakB as stable 2025-10-23 00:43:47 -06:00
ManInMyVan 6e5ec332dd remove double space in ChatB 2025-10-23 00:40:59 -06:00
ManInMyVan 79bf7e4fd1 mark ElytraF as stable 2025-10-23 00:39:32 -06:00
ManInMyVan d0aafdd9f7 mark ElytraA as stable 2025-10-22 18:06:48 -06:00
ManInMyVan 3f19abc859 mark ElytraC as stable 2025-10-22 18:06:29 -06:00
ManInMyVan 8a6863b9d3 mark ElytraB as stable 2025-10-22 17:47:05 -06:00
Axionize 26492fd8e3 Optimize new Vector3dm() multiply calls 2025-10-20 23:23:39 -04:00
Axionize 15e809835b Optimize new object creation on vector add() calls 2025-10-20 23:15:23 -04:00
Axionize 1eae5484c7 Micro optimize DefaultResyncHandler 2025-10-20 22:56:11 -04:00
Axionize 90036e2bf2 Optimize Messages (#2309)
* Optimize MessageUtil.replacePlaceHolders()

* Send user messages at packet level bypassing backend server for performance

* Stash temporary changes

* Make Grim send fast chat messages bypasses platform by default
2025-10-20 22:16:21 -04:00
Axionize faf2fb3afb Refactor Grim startup/system args handling 2025-10-20 21:48:49 -04:00
cyramek 7461aca13f fix offground precision loss <= 1.20.4
we're now in 1e-15 average
2025-10-20 19:26:05 +02:00
AoElite f381805cad add translations for the sender-not-found message 2025-10-20 12:25:34 -04:00
AoElite 2fa022eb00 fix GrimDebug command exception if the sender is exempt or not found 2025-10-20 12:25:10 -04:00
cyramek 44900e584b support copper variants of chains 2025-10-20 10:06:45 +02:00
cyramek a2f4dc1979 get rid of a buffer in vector format conversion 2025-10-19 09:18:29 +02:00
Cyramek 0237f956ff [1.21.10] Rewrite block effects, LpVector support, partially implemented collision boxes (#2300) 2025-10-18 11:24:15 +02:00
ManInMyVan e222df8e87 check if we're already sending a bundle packet 2025-10-15 16:50:39 -06:00
ManInMyVan bbab7e222c require CHUNK_BATCH_ACK be sent only when it's supposed to be sent 2025-10-15 15:26:40 -06:00
Axionize 41c7e41a0e Fix Fabric Auto JiJ script 2025-10-15 12:44:15 -04:00
Axionize 5551ef68e1 More fastutil micro optimizations 2025-10-14 19:40:14 -04:00
Axionize ca6e83de4d Use FastUtil Map for violations 2025-10-14 19:37:00 -04:00
Axionize 4d6ac75c73 Fix ClassNotFoundException with new ChatB Via rewriter hook 2025-10-14 17:52:00 -04:00
ManInMyVan 1317ae0bb4 add 2 more rules to .editorconfig 2025-10-14 13:40:20 -06:00
ManInMyVan d538c59a79 CHUNK_BATCH_ACK is async 2025-10-12 15:43:52 -06:00
ManInMyVan 6a223a30c7 don't specify baby scale factor twice 2025-10-12 12:58:00 -06:00
cyramek 2e1c79b4e3 correct bounding box calculations for baby turtles, happy ghasts, dolphins, armadillos, and camels 2025-10-12 20:21:58 +02:00
SamB440 bb143d7993 cancelLerp fixed in 1.21.9, apparently 2025-10-12 17:58:14 +01:00
SamB440 322d2567c0 Bump Gradle to 9.1.0 2025-10-12 17:44:58 +01:00
AoElite 8d7a4cce87 ignore unhittable entities for block placements 2025-10-12 01:21:02 -04:00
ManInMyVan 832194a1e9 fix #2294 2025-10-11 18:46:37 -06:00
ManInMyVan 0321e0bceb fix some warnings 2025-10-11 12:32:57 -06:00
ManInMyVan 63854605b6 slightly more configurable webhook embed 2025-10-11 12:11:03 -06:00
AoElite 5c4602188e allow the embed images to be customizable and show grim's version in the footer 2025-10-11 08:55:29 -04:00
AoElite 163e120f00 any 200 status codes are acceptable 2025-10-11 08:22:32 -04:00
AoElite ce6e1d3e9f ensure the short commit is used 2025-10-11 08:22:02 -04:00
Axionize f6024a4308 build(workflow) Fix not attempting to push to Grim publishing API on fork build 2025-10-10 18:33:08 -04:00
Axionize b4d031c81e build(workflow) Fix changelog generation 2025-10-10 18:30:32 -04:00
Axionize d7cb4aa4e3 Allow builds to run in forks without attempting to publish to modrinth 2025-10-10 18:16:35 -04:00
Axionize b85c65d623 Improve build performance by explicitly specifying repositories 2025-10-10 18:01:29 -04:00
ManInMyVan c208824b16 rewrite BukkitItemResetHandler & add isUsingItem() & docs 2025-10-10 13:50:38 -06:00
ManInMyVan 7f6b7d0bfa forgot 1.21.9/10 2025-10-10 10:00:29 -06:00
ManInMyVan a56e99e3e2 support latest spigot in BukkitItemResetHandler 2025-10-10 09:55:17 -06:00
SamB440 9e7dabea34 Now fix geyser dependency 2025-10-10 15:34:12 +01:00
SamB440 42c6d08ff1 Fix silent failing on build 2025-10-10 15:27:53 +01:00
SamB440 0bbf472c55 Split version compute and build steps 2025-10-10 15:16:56 +01:00
Axionize d9e279a949 Undisable fabric by accident and minor cleanup 2025-10-10 02:41:38 -04:00
Axionize cccc5fdfb6 Optimize Bukkit dependency fetching 2025-10-10 02:40:20 -04:00
Axionize a7bdc869d4 Improve performance and cleaniness of downloading dependencies 2025-10-10 02:33:10 -04:00
Axionize 513633c645 Bump dependencies 2025-10-10 01:31:00 -04:00
ManInMyVan c3eb0e4196 allow multiple instances of TridentItem 2025-10-09 16:24:46 -06:00
ManInMyVan 7137b36d62 remove unnecessary parenthesis on folia scheduler tasks 2025-10-09 16:23:45 -06:00
ManInMyVan 2c0b4a2a60 make MovementTickerLivingVehicle#movementInput protected 2025-10-09 16:11:07 -06:00
ManInMyVan 8f437d6bec clean up some comments and spacing 2025-10-09 16:10:20 -06:00
ManInMyVan c0bd2dd685 make FabricPermissionRegistrationManager#fabricSenderFactory private 2025-10-09 16:08:16 -06:00
ManInMyVan 258d94b525 make LastInstance#lastInstance private 2025-10-09 16:07:53 -06:00
ManInMyVan 6a02c93204 use GrimMath.radians instead of manual conversion 2025-10-09 16:07:33 -06:00
ManInMyVan 0c86d017ac deobf some methods in PredictionEngineBoat 2025-10-09 16:06:05 -06:00
ManInMyVan 6d3aa4784d move bstats plugin id to a constants class 2025-10-09 16:05:40 -06:00
ManInMyVan cec4a85454 make BlockPlaceSnapshot a record 2025-10-09 16:05:07 -06:00
ManInMyVan 438e1accf9 fix build 2025-10-09 16:04:04 -06:00
ManInMyVan f9fff4ee0c make VehiclePositionUpdate a record 2025-10-09 16:02:52 -06:00
ManInMyVan b102afb8c8 undeprecate BukkitConversionUtils#fromBukkitFace(BlockFace) 2025-10-09 16:01:27 -06:00
ManInMyVan ef0ea352ad don't use Preconditions for null-checking 2025-10-09 16:00:53 -06:00
ManInMyVan e36e61987d remove unused class TaskWrapperHandle 2025-10-09 15:59:45 -06:00
ManInMyVan 3cf06bf00b use lombok in some places 2025-10-09 15:59:02 -06:00
ManInMyVan 7b243d3a44 use jetbrains nullability annotations 2025-10-09 13:59:48 -06:00
ManInMyVan d24726c7df less messy build script 2025-10-09 13:44:41 -06:00
ManInMyVan 1bb95e796d slight cleanup (mostly weakening package-private) 2025-10-09 13:33:49 -06:00
SamB440 642e580e61 Fix BLOCK_INTERACTION_RANGE creative mode on < 1.20.5 2025-10-09 20:14:31 +01:00
ManInMyVan 8884b0a126 bump version 2025-10-09 10:40:02 -06:00
ManInMyVan 7c5aae956e fix 1.9 sloped rail height 2025-10-07 22:15:56 -06:00
ManInMyVan 0e6d116ec6 nullability annotations & deobfing 2025-10-07 15:35:30 -06:00
ManInMyVan 141ccae1c2 deobf getNearestLookingDirections() 2025-10-07 14:51:12 -06:00
ManInMyVan 662d02cc2a xRot & yRot -> yaw & pitch 2025-10-07 14:10:37 -06:00
ManInMyVan c42217375b fix a few warns 2025-10-07 14:03:28 -06:00
ManInMyVan 258ef064ba make ExplosionHandler#firstBreadMap private 2025-10-07 14:03:12 -06:00
Axionize 12e79a1ea0 Implement API v1.2.0: Improve EventBus usability and fix reflection bugs
This update contains numerous fixes and improvements to the API, focusing on developer experience and robustness.

feat(api): Simplify EventBus registration with context resolvers
- Removes the requirement for developers to manually construct a GrimPlugin instance to use the EventBus.
- The new GrimExtensionManager uses platform-specific resolvers to automatically determine the context from common object types, reducing boilerplate.
    - On Bukkit, developers can now pass:
      - A `Plugin` instance (e.g., `this` from their main plugin class)
      - Any `Class` from the plugin's JAR (e.g., `MyListener.class`)
      - The plugin's name as a `String`

    - On Fabric, developers can now pass:
      - A mod's entrypoint instance (e.g., `this` from an Initializer)
      - The mod ID as a `String`
      - A `ModContainer` instance
      - Any `Class` from the mod's JAR

fix(api): Correctly invoke reflected event listeners
- Fixes a critical bug causing a `ClassCastException` for listeners registered via `registerAnnotatedListeners`. Listeners are now correctly fired only for their declared event type. `subscribe()` remains the recommended registration method.

perf(api): Optimize invocation of reflected listeners
- Slightly improves performance of reflected listeners by removing a redundant runtime null-check from the hot path of every event call.

refactor(core): Moved concrete EventBus implementation from API to common module
- The `OptimizedEventBus` implementation has been relocated to the `common` module to better separate the public API contract from its internal logic.
2025-10-06 06:26:16 -04:00
Axionize e0093897dc Make devvelocity build scan integration only run on --scan being applied; Update foojay resolver convention; 2025-10-06 06:26:06 -04:00
ManInMyVan 8d1ee003d9 small cleanup (mostly making things private & final) 2025-10-05 12:41:18 -06:00
ManInMyVan aa4c6e0f1d add reset-item-usage-on-item-use 2025-10-04 12:38:32 -06:00
Axionize 0fd2a96aca Even more robust sanitization 2025-10-03 02:12:13 -04:00
Axionize d15a2dd23a Buildscript patches 2025-10-03 01:18:33 -04:00
Axionize 0095f8acc1 Fix using secrets for MODRINTH_ID in workflows again 2025-10-03 01:06:02 -04:00
Axionize b824ce107d Fix using secrets for MODRINTH_ID in workflows 2025-10-03 00:51:19 -04:00
Axionize 50f3d84207 Use secrets for MODRINTH_ID 2025-10-02 07:28:52 -04:00
Axionize a26951cc95 Fix escpaing some stings in preparing final changelog 2025-10-02 07:16:37 -04:00
Axionize b72485da7e Print out build scan url not found when --scan enabled and url not found 2025-10-02 06:05:26 -04:00
Axionize 2f8a4738b3 Remove -q from printVersion so when --scan is applied logs print out 2025-10-02 06:03:46 -04:00
Axionize a74e10e888 Build script fix 2025-10-02 05:38:27 -04:00
Axionize dda13325cf Bugfix 2025-10-02 05:22:42 -04:00
Axionize 2df4c23bf2 Update buildscript to be more flexible; add support for gradle build scans 2025-10-02 05:18:00 -04:00
Axionize 8f785564d7 Run workflow on .github/workflows/** update 2025-10-02 04:48:40 -04:00
Axionize cbc2f51a0c Update new release/alpha build workflow 2025-10-02 04:43:56 -04:00
Axionize 3ac26d0601 Modify grim startup update check failure message 2025-10-01 01:02:24 -04:00
ManInMyVan cc10288e0d fix segmented hitboxes 2025-09-30 15:27:03 -06:00
ManInMyVan c10e74cd72 fix leaf litter hitbox 2025-09-29 18:02:20 -06:00
AoElite fb926ab0fb specify java version fpr codeql 2025-09-28 11:50:30 -04:00
AoElite 4be254939d update readme 2025-09-28 11:15:10 -04:00
AoElite 40a4c081c7 fix repo property including org 2025-09-28 10:27:05 -04:00
AoElite 1f16d7b0de correct formatting for conditional checks in gradle-publish workflow 2025-09-28 10:21:29 -04:00
AoElite 8d25519ace add build properties to dump 2025-09-28 10:11:58 -04:00
AoElite fefaa57044 fix workflow 2025-09-28 10:11:50 -04:00
AoElite 01ff3ecea7 exclude pull requests 2025-09-28 09:59:11 -04:00
AoElite f54ceb6531 remove unused mainBranch property from BuildConfig 2025-09-28 09:55:18 -04:00
AoElite 18d1602b3a use GitHub's default branch instead of assuming 2.0 2025-09-28 09:54:56 -04:00
AoElite c90d7ab941 fixed some minor build warnings 2025-09-28 09:02:41 -04:00
AoElite c428bf65be add a build properties file to include more details about the build 2025-09-28 08:25:57 -04:00
AoElite 088621faff simplify version extraction 2025-09-28 05:12:04 -04:00
AoElite 2a5979cc3c use different approach in Gradle version extraction in the publishing workflow 2025-09-28 04:49:32 -04:00
AoElite 9618912072 bump lombok plugin to 9.0.0 2025-09-28 04:39:13 -04:00
AoElite a0bd388109 update the checkout action to v5 in CodeQL workflow 2025-09-28 04:36:41 -04:00
AoElite 2403bc5df7 update gradle publishing actions, remove action dependency requirement, disabled building and publishing of lite 2025-09-28 04:36:01 -04:00
AoElite 9b2b080d1e enable parallel building 2025-09-28 04:33:37 -04:00
AoElite b70abbe6cd disable CodeQL workflow schedule 2025-09-28 04:25:38 -04:00
Axionize 293f6ea8b1 Add repo.grim.ac for 1.16.1 so fabric-permissions-api will be downloaded 2025-09-18 15:52:40 -04:00
Pablo Herrera fe7a263b01 Optimize away entity collision check in 1.8 (#2269) 2025-09-17 15:26:59 -06:00
SamB440andcyramek cb13221b8d Revert pre via (#2280)
* revert pre-via part 1

* don't register checks multiple times

* revert pre-via part 1

* don't register checks multiple times

* fix merge conflicts

---------

Co-authored-by: cyramek <xcyramek@gmail.com>
2025-09-17 18:07:34 +01:00
AoElite c2a07bd6f1 add back workflow paths 2025-09-16 11:45:33 -04:00
AoElite 184050bfc6 remove secret requirement 2025-09-16 11:17:47 -04:00
AoElite e368bc88ad tweak workflow 2025-09-16 11:14:22 -04:00
AoElite becbba3647 remove workflow paths 2025-09-16 11:07:47 -04:00
AoElite db92c6587e update workflow 2025-09-16 11:02:18 -04:00
AoElite a02f49ef87 update packetevents 2025-09-16 05:45:02 -04:00
AoElite 846e9ad4ed ensure fabric uses our packetevents fork 2025-09-16 03:20:04 -04:00
EternalHuman 57a9f8f432 Fix FastBreak falses white riding entity (#2273) 2025-09-08 23:11:00 -06:00
cyramek b7c5837305 only do NoSlow checks if trident is not enchanted with Riptide
This is not vanilla, but this is what the legacy handler does. To implement this properly, we would need to track biomes AND skylight, which is very memory-expensive.

fix: https://github.com/GrimAnticheat/Grim/issues/2259
2025-09-07 22:42:27 +02:00
ManInMyVan f739b1e396 remove unused imports 2025-09-05 10:24:25 -06:00
ManInMyVan 070116b037 PacketServerTeleport/PLAYER_POSITION_AND_LOOK: read event after getting player 2025-09-04 17:58:41 -06:00
ManInMyVan a8693c300e PacketServerTeleport/VEHICLE_MOVE: read event after getting player 2025-09-04 17:45:12 -06:00
Ayou 0586ea5bf6 Fix riptide velocity (#2262) 2025-09-04 07:50:13 -06:00
ManInMyVan bd4cd314c6 remove GrimPlayer#getInventory() 2025-09-03 22:53:57 -06:00
ManInMyVan 0bf3a21677 protected -> private in final class 2025-09-03 16:56:54 -06:00
ManInMyVan dc030603c8 deobf FluidFallingAdjustedMovement.getFluidFallingAdjustedMovement(...) 2025-09-03 16:52:08 -06:00
ManInMyVan 4e1320f032 remove GrimPlayer#isEyeInFluid(FluidTag) 2025-09-03 16:44:55 -06:00
ManInMyVan 9f4c321f44 make Dripstone.update(...) void 2025-09-03 16:42:08 -06:00
ManInMyVan 2b037554fb use GrimMath.radians in JumpPower 2025-09-03 16:39:39 -06:00
ManInMyVan 64ebdf21b2 make MainSupportingBlockData a record 2025-09-03 16:39:25 -06:00
ManInMyVan e26cf0f73d clean up EntityPredicates 2025-09-03 16:32:27 -06:00
ManInMyVan 42d247b641 simplify ViaVersionUtil 2025-09-03 16:20:55 -06:00
ManInMyVan ea5ed0610c move ComprensatedInventory instance to GrimPlayer 2025-09-03 16:08:11 -06:00
ManInMyVan 3f1755722c replace ChannelHelper.runInEventLoop with GrimPlayer#runSafely 2025-09-03 15:37:49 -06:00
ManInMyVan d2a8dceb2d don't use deprecated method ItemStack.getEnchantmentLevel(EnchantmentType, ClientVersion) 2025-09-02 17:45:55 -06:00
ManInMyVan f87a077e23 make Ray fields final 2025-09-02 17:36:41 -06:00
ManInMyVan 9ea389bc6a fix RunningMode field modifiers 2025-09-02 17:33:07 -06:00
ManInMyVan 566dc9bf3b mark GrimMath methods as pure 2025-09-02 17:28:51 -06:00
ManInMyVan b44dd89136 normalize trighandler param names 2025-09-02 17:26:31 -06:00
ManInMyVan eddb14b92c cache default input value; reduce memory usage for pre-1.21.2 players 2025-09-02 16:58:12 -06:00
ManInMyVan 21ef46a291 reduce runnables with world borders 2025-09-02 16:51:09 -06:00
ManInMyVan cecf5fbab2 make PacketStateData.isSlowedByUsingItem() based on slowedByUsingItemSlot
the slowedByUsingItem is redundant
2025-09-02 16:31:29 -06:00
ManInMyVan b37393c75d PacketStateData.eatingHand -> itemInUseHand 2025-09-02 16:28:44 -06:00
ManInMyVan aab6908da0 only set NoSlow.didSlotChangeLastTick if the slot actually changed 2025-09-02 16:26:29 -06:00
ManInMyVan d71239bb22 use getItemInHand in PacketPlayerDigging 2025-09-02 16:24:27 -06:00
ManInMyVan 345502b43c fix deprecated method call ItemStack.getEnchantmentLevel(EnchantmentType, ClientVersion) 2025-09-02 16:20:38 -06:00
ManInMyVan a7f8c7790e get item in PacketPlayerDigging.handleUseItem instead of it being passed 2025-09-02 16:17:39 -06:00
ManInMyVan ff9af985bf don't allow sending OFF_HAND in USE_ITEM to bypass noslow 2025-09-02 16:13:38 -06:00
AoElite dbac8bc43e add GrimList command for debugging exemptions 2025-08-31 12:41:14 -04:00
AoElite 4702add980 reduce the number of tasks for updating permissions 2025-08-31 10:21:09 -04:00
AoElite 090d1a843b add some utilities 2025-08-31 10:12:29 -04:00
AoElite 8f1e993913 fix CrashH false 2025-08-31 03:04:46 -04:00
SamB440 17a8d3b3c9 Add support for SET_PLAYER_INVENTORY packet 2025-08-28 19:58:52 +01:00
ManInMyVan 1c46546c15 remove unused imports in ChatA/B 2025-08-27 17:56:21 -06:00
ManInMyVan 97c1bddc16 make PacketPlayerDigging pre-via: fix #2250
also move it before PreViaCheckManagerListener
2025-08-27 17:56:08 -06:00
AoElite b997b6b10f allow platform to be configured via system argument 2025-08-22 23:04:06 -04:00
ManInMyVan 28d83206c1 more readable PredictionEngineElytra.applyInputsToVelocityPossibilities 2025-08-16 17:24:05 -06:00
ManInMyVan 6320fa68ce fix(PredictionEngineElytra): use stuckSpeedMultiplier instead of 0.99, 0.98, 0.99 2025-08-16 17:10:16 -06:00
ManInMyVan 0340e07547 fix(PredictionEngineElytra): shitmath look vector 2025-08-16 17:01:25 -06:00
cyramek fd59498b9b limit 1.21.5+ sprint attribute desync to minecarts 2025-08-16 20:12:33 +02:00
AoElite c0b96ea512 update README.md and CONTRIBUTING.md 2025-08-16 04:47:48 -04:00
ManInMyVan 38ccc559eb fix ChatA/ChatB falses from 31107ec4b 2025-08-14 17:38:51 -06:00
ManInMyVan 0dec74390f add force-slow-movement and force-stuck-speed (intended for anarchy servers) 2025-08-14 17:35:42 -06:00
ManInMyVan a953f501cd roll up shitmath bruteforce in PredictionEngineElytra 2025-08-14 17:05:44 -06:00
ManInMyVan 03e15141d7 cleaner stuckSpeedMultiplier constants 2025-08-14 17:00:38 -06:00
ManInMyVan 57618963e7 ExploitB: allow line break in pages 2025-08-14 15:37:14 -06:00
ManInMyVan 8cb4189554 remove unused import in BlockFaceHelper 2025-08-14 15:37:10 -06:00
Axionize 94813c0566 Fix typo in help: section of en messages.yml causing error message on /grim help. Also make /grim help handle null lines 2025-08-13 01:53:39 -04:00
Axionize b0906d936f chore(ci): Fix supported versions for Bukkit in Modrinth upload and Fabric dependences 2025-08-11 17:50:35 -04:00
ManInMyVan 6ce610e0b5 remove Killaura from punishments.yml + add Interact in japanese punishments.yml 2025-08-11 15:13:26 -06:00
Axionize ba305cf224 chore(ci): Fix escaping characters in changelog generation 2025-08-11 17:07:04 -04:00
ManInMyVan a3108c7850 merge FloodgateUtil & GeyserUtil 2025-08-11 14:51:19 -06:00
ManInMyVan 1ba072fe80 rewrite GeyserUtil to not use reflection
except once
2025-08-11 14:51:19 -06:00
ManInMyVan 376e7a9344 don't use deprecated method ItemStack.getEnchantmentLevel(EnchantmentType, ClientVersion) in Riptide 2025-08-11 14:51:18 -06:00
ManInMyVan 380e3d9094 mark many utility classes as UtilityClass 2025-08-11 14:51:18 -06:00
ManInMyVan 796a573ca1 remove unused method BlockFaceHelper.offset 2025-08-11 14:51:18 -06:00
ManInMyVan e433652ca3 don't use deprecated method ItemStack.getEnchantmentLevel(EnchantmentType, ClientVersion) in TridentItem 2025-08-11 14:51:18 -06:00
ManInMyVan 7376468701 use Math.PI in VanillaMath instead of the literal 2025-08-11 14:51:18 -06:00
ManInMyVan d2df1b76d2 simplify FloodgateUtil 2025-08-11 14:51:18 -06:00
ManInMyVan 6787d1bcd1 split isJumping and lastJumping into separate declarations 2025-08-11 14:51:18 -06:00
ManInMyVan 0a4a6cd7ef make Check.isTransaction static 2025-08-11 14:51:18 -06:00
ManInMyVan be120f062f remove Check.isFlying 2025-08-11 14:51:18 -06:00
Axionize 2bf1260a22 chore(ci): Fix generating changelog content in GitHub Actions 2025-08-11 16:25:54 -04:00
ManInMyVan 2e625e260c validate STEER_BOAT values (Add VehicleF) 2025-08-10 18:47:40 -06:00
ManInMyVan 4287f62cd7 fix PacketOrderO falses in vehicles 2025-08-10 14:13:10 -06:00
ManInMyVan b5c14f47ff check if a player is in a boat when sending STEER_BOAT (Add VehicleE) 2025-08-10 13:59:37 -06:00
ManInMyVan 647b13c083 add getVehicle() and getVehicleType() in GrimPlayer 2025-08-10 13:57:53 -06:00
AoElite cd8d78dd5d recode grim version command to use new api 2025-08-10 10:11:40 -04:00
AoElite a9a203466c allow all functional urls to be changeable, move all grim system property usage to a dedicated class 2025-08-10 10:11:04 -04:00
AoElite a695dac39b Refactor GrimDump: extract basic info generation to reusable getBasicInfo method 2025-08-10 10:07:34 -04:00
Axionize 5183ad8631 chore(ci): Replace vars.MODRINTH_ID with secrets.MODRINTH_ID to match repository Actions' settings 2025-08-08 21:58:01 -04:00
Axionize 0374b8c345 chore(ci): Create GitHub Actions script for auto-building lite version and publishing to Modrinth w/changelog 2025-08-08 21:51:46 -04:00
Axionize a2395606de chore(ci): Add cliff.toml file for defining git-cliff formatting of changelogs 2025-08-08 21:51:39 -04:00
SamB440 61f7ad8f71 [ci skip] Add client version to bypass issue template 2025-08-08 13:16:27 +01:00
SamB440 1136936ba1 Disallow step after setback 2025-08-07 15:20:29 +01:00
SamB440 25b0582074 Zero point zero three 2025-08-07 15:18:44 +01:00
SamB440 cec0738e32 [ci skip] Bump run-paper version 2025-08-06 18:28:11 +01:00
Axionize 31107ec4b5 Make ChatC and ChatB postViaChecks as temporary workaround to PE parsing limitations. 2025-08-06 10:59:09 -04:00
Axionize 4b514e7098 Fix FastBreak falses with 1.20.5+ custom tool rules. 2025-08-04 21:38:22 -04:00
Axionize 527c87e4cf Amend previous Reach false fix to only apply in versions > 1.14.4 2025-07-31 13:48:30 -04:00
Axionize 3875a6b238 Fix very rare Reach false for versions < 1.20.2 and > 1.21.4 involving rot only packets. See https://bugs.mojang.com/browse/MC/issues/MC-255263 2025-07-31 12:44:18 -04:00
Zongle Wang 5a4471c585 Shadow 9.0.0-rc2 (#2229)
```
OLD: grimac-bukkit-2.3.72-shadow-9-ba4bbef66-before.jar
NEW: grimac-bukkit-2.3.72-shadow-9-a14b4044a-after.jar

 JAR   │ old      │ new      │ diff
───────┼──────────┼──────────┼──────
 class │ 20.9 MiB │ 20.9 MiB │  0 B
 other │  1.5 MiB │  1.5 MiB │  0 B
───────┼──────────┼──────────┼──────
 total │ 22.4 MiB │ 22.4 MiB │  0 B

 CLASSES │ old   │ new   │ diff
─────────┼───────┼───────┼───────────
 classes │  4603 │  4603 │ 0 (+0 -0)
 methods │ 53656 │ 53656 │ 0 (+0 -0)
  fields │ 22173 │ 22173 │ 0 (+0 -0)

=================
====   JAR   ====
=================

 size │ diff │ path
──────┼──────┼─────────────────────────────────────────────────────────────────
  0 B │  0 B │ + META-INF/versions/9/ac/grim/grimac/shaded/snakeyaml/internal/
  0 B │  0 B │ + META-INF/versions/9/ac/grim/grimac/shaded/snakeyaml/
      │  0 B │ - META-INF/versions/9/org/yaml/snakeyaml/internal/
  0 B │  0 B │ + META-INF/versions/9/ac/grim/grimac/shaded/
      │  0 B │ - META-INF/versions/9/org/yaml/snakeyaml/
  0 B │  0 B │ + META-INF/versions/9/ac/grim/grimac/
      │  0 B │ - META-INF/versions/9/org/yaml/
  0 B │  0 B │ + META-INF/versions/9/ac/grim/
      │  0 B │ - META-INF/versions/9/org/
  0 B │  0 B │ + META-INF/versions/9/ac/
  0 B │  0 B │ + META-INF/services/
──────┼──────┼─────────────────────────────────────────────────────────────────
  0 B │  0 B │ (total)
```
2025-07-30 12:49:15 -04:00
Axionize ba4bbef66f Add mavenCentral() to repositsories to download me.lucko:fabric-permissions-api:0.1-SNAPSHOT for Fabric 1.16.1 2025-07-30 00:45:05 -04:00
Axionize 29e0c6e42c Bump PacketEvents 2025-07-30 00:17:32 -04:00
ManInMyVan 2528ff525d Revert "temp revert pre-via"
This reverts commit 77c165cfa8.
2025-07-24 08:54:57 -06:00
ManInMyVan 77c165cfa8 temp revert pre-via 2025-07-24 08:54:38 -06:00
ManInMyVan fe1c6bf3dd fix #2221 2025-07-24 08:01:11 -06:00
ManInMyVan 3de670eb1c fix exception 2025-07-23 15:32:29 -06:00
LokiandManInMyVan 533ae70f05 Hardcode more 1.21.4+ hand harvestables (#2213)
* Hardcode more 1.21.4+ Hand Harvestables

Fixes issue #2117 temporarily until PacketEvents resolves their api shortcoming (https://github.com/retrooper/packetevents/issues/1217)

* Adjust variable name

* Cleanup spacing in BlockBreakSpeed util

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

---------

Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2025-07-23 10:51:56 -04:00
cyramek b88dfa717a fix getting block jump factor in older versions 2025-07-23 04:11:00 +02:00
SamB440 933f6c7454 Add option to disable cancelling pong packets 2025-07-20 15:09:39 +01:00
Ayou e2cf0fa25b fix NPE in BlockPlaceCheck#getCombinedBox (#2215) 2025-07-20 15:10:57 +02:00
ManInMyVan d8b719daf8 more cleanup 2025-07-19 19:08:06 -06:00
ManInMyVan 95b080ae6e more small changes 2025-07-19 17:30:23 -06:00
ManInMyVan 1f052f6107 small stuff 2025-07-19 16:56:32 -06:00
ManInMyVan 02426ad592 these don't need to implement anything 2025-07-19 15:25:47 -06:00
ManInMyVan 85acf78db6 and it was not a teleport 2025-07-18 23:09:40 -06:00
ManInMyVan 354216f9b0 BadPacketsO optimizations 2025-07-18 14:53:59 -06:00
ManInMyVan 408c7d5773 pre-via block break checks 2025-07-18 14:37:53 -06:00
ManInMyVan 2e01399c13 PacketOrderO 2025-07-18 13:29:33 -06:00
Axionize 2ad98188f6 Temporary fix for BadPacketsE not working on vehicles 2025-07-17 23:55:22 -04:00
ManInMyVan ac2c9eafcb HOW DID I FORGET 2025-07-17 20:22:29 -06:00
ManInMyVan 2a7403be62 small cleanup 2025-07-17 20:22:23 -06:00
ManInMyVan 51bbb3162b pre-via chat checks 2025-07-17 20:10:41 -06:00
ManInMyVan d90de8fcca more pre-via
hopefully I didn't miss any getter changes
2025-07-17 20:08:09 -06:00
ManInMyVan 1b62b1dfb0 don't use ordinal for WindowClickType in CrashF 2025-07-17 19:57:04 -06:00
ManInMyVan c7fbc4b0b2 remove some empty lines 2025-07-17 19:55:30 -06:00
ManInMyVan 39b74b29f3 packet cancelling in VehicleD 2025-07-17 19:55:03 -06:00
ManInMyVan ed727cc923 SprintA verbose 2025-07-17 19:54:45 -06:00
ManInMyVan 9da9c30d9a there is no more via here 2025-07-17 19:38:37 -06:00
ManInMyVan 8d3e77f492 no it shouldn't 2025-07-17 11:33:16 -06:00
ManInMyVan 6e58e8c9c5 this should now be usable 2025-07-17 11:32:20 -06:00
ManInMyVan 9ab2f2e5ed fix #2211 2025-07-17 11:31:12 -06:00
Axionize 4942401c08 1.21.8 Server Support - Bump PE 2025-07-17 11:07:11 -04:00
Axionize 6e28434692 Downgrade from shadow 9.0.0-rc1 to 9.0.0-beta8 to fix jar inflation bug with shading fastutil 2025-07-17 10:58:54 -04:00
Axionize bbc1bee14d Bump Dependencies
gradlew-wrapper 8.13 -> 8.14.3
adventure 4.21.0 -> 4.23.0
adventure-platform-bukkit 4.3.4 -> 4.4.0
cloud-paper 2.0.0.-beta.10 -> 2.0.0.-beta.11
cloud-fabric 2.0.0.-beta.10 -> 2.0.0.-beta.11
packetevents 2.9.0-SNAPSHOT -> 2.9.2-SNAPSHOT
fabric-loader 0.16.10 -> 0.16.14
fabric-loom 1.10.5 -> 1.11.4
shadow 9.0.0-beta6 -> 9.0.0-rc1
2025-07-17 09:06:42 -04:00
cyramek c37a79bf9e fix: https://github.com/GrimAnticheat/Grim/issues/2209 2025-07-16 19:33:52 +02:00
ManInMyVan 2e9b086829 make some checks run before via 2025-07-15 12:03:00 -06:00
cyramek c66de10b10 fix HappyGhast false positives when holding space
fix: https://github.com/GrimAnticheat/Grim/issues/2203
2025-07-14 17:57:35 +02:00
Cyramek 4156768cae fix vehicle relative teleport/vehicle 1.12.2+ teleport system (#2200)
* fix vehicle relative teleport/vehicle 1.12.2+ teleport system

* only mark teleports for re-encoding if we’re actually rewriting them
2025-07-13 12:08:47 +02:00
Axionize 3e9b53e77e Add /grim history (#2201)
* Add /grim history command to see historical alerts

- Add basic runtime reloading support.
  - Will only actually reload if current database is different/has different setting than the one requested in config.

- Added [log] statements matching [alert] statements

* Add more detailed error message if Grim history subsystem fails to load.

* Refactor /grim history code; Fix autocomplete of online player names in /grim history

* Fix error swapping checkName and verbose in SQLite implementation

* Refactor /grim history to use more efficient long-term storage with compact UUIDs and string deduplication.

Grim old grim history data will not be migrated!

* Replace %version% with grim version in /grim history entry output

* Add support for %grim_version% %client_brand% %client_version% %server_version% substtuions in grim-history-entry
2025-07-13 05:59:52 -04:00
ManInMyVan 7b82060921 add include-timestamp to discord.yml 2025-07-09 15:35:52 -06:00
ManInMyVan e16979b09c finish ExploitC, replaces ExploitB 2025-07-09 15:20:32 -06:00
ManInMyVan 0ccd03a669 ExploitC fail-fast page parsing 2025-07-09 12:49:12 -06:00
ManInMyVan 3b76ded044 BadPacketsJ should be stable 2025-07-09 10:06:30 -06:00
ManInMyVan ba18d4c358 add missing return 2025-07-08 23:01:47 -06:00
ManInMyVan 18f0a2af31 fix ExploitC on 1.9-1.12 servers 2025-07-08 22:58:37 -06:00
ManInMyVan 8a2ca76e69 this took too long 2025-07-08 20:00:30 -06:00
ManInMyVan 1a6b6fc59f payload system 2025-07-08 17:32:59 -06:00
ManInMyVan 2518ced135 fix ExploitB false on pre 1.16 clients 2025-07-08 17:32:44 -06:00
ManInMyVan 4b53457851 validate anvil item name length 2025-07-07 16:55:14 -06:00
ManInMyVan df31a39e2b descriptions for almost every place check 2025-07-07 13:53:50 -06:00
ManInMyVan 4992cf67dc check if chat is hidden 2025-07-07 13:41:30 -06:00
ManInMyVan b4714b019d add Chat and Exploit to punishments 2025-07-07 12:22:22 -06:00
ManInMyVan 135c90c251 check for moving while chatting 2025-07-07 12:07:53 -06:00
ManInMyVan d1b0f4ddf6 remove whitespace in EquipmentType 2025-07-07 11:57:48 -06:00
ManInMyVan 0844fc646e playerData -> player 2025-07-07 11:57:31 -06:00
ManInMyVan 5fb8cd92be add KnownInput#moving 2025-07-07 11:39:28 -06:00
ManInMyVan b563792fa6 move ExploitA & C to chat category 2025-07-07 11:36:28 -06:00
Cyramek 978364a683 fix various vehicle issues [1.21.2] (#2185)
* fix happyghast step, collisions with fluids
warn about viabackwards compatibility

* fix 1.21.2+ riding without control

* use known input sneaking status if server support that

* fix fluid current pushing logic for happyghasts

* actually fix fluid pushing for happyghast

* fix vehicle input calculations for <=1.21.1 servers

* fix elytra inputs

* Revert 'fix elytra inputs'

* use pre-via listeners for sneaking

* remove warnings for sneaking issues on newer server versions

* fix float/double error causing 1e-8 imprecision when jumping on a horse

* workaround false positives when jumping on a horse

* add camel entity type

* only do this for 1.21.2+ client on 1.21.2+ servers

* build with new Grim PacketEvents fork snapshot with support for pre-via injection on Fabric
2025-07-06 23:38:15 -04:00
ManInMyVan 38a2ea4ccd slightly change ignore-duplicate-packet-rotation logic 2025-07-06 20:16:41 -06:00
ManInMyVan af2a53ac65 Merge pull request #2193 from Ayouuuu/2.0
Add ItemTypes.TURTLE_HELMET
2025-07-04 20:52:14 -06:00
Ayou d657aec5c2 Add ItemTypes.TURTLE_HELMET 2025-07-05 10:23:27 +08:00
ManInMyVan d8353143c9 fix more SprintE falses 2025-07-04 16:08:46 -06:00
ManInMyVan bb7ba08c29 fix #2190 2025-07-04 15:11:10 -06:00
SamB440 ddcc5a2dd9 Merge pull request #2188 from Cyramek/fix-vehicle-soft-collisions
fix soft collisions for vehicles
2025-07-04 15:09:59 +01:00
cyramek c4a18a50cc fix elytra inputs 2025-07-04 14:48:32 +02:00
cyramek fec88069f4 fix soft collisions for vehicles 2025-07-04 14:38:33 +02:00
ManInMyVan b8e70b89b4 fix build 2025-07-03 18:55:26 -06:00
ManInMyVan d59a9faa62 fix #2181 2025-07-03 18:49:02 -06:00
ManInMyVan d2913b3680 a bit more cleanup 2025-07-03 18:48:40 -06:00
ManInMyVan 3c562353df normalize PredictionEngine class names 2025-07-03 17:51:57 -06:00
ManInMyVan 9a22a282d4 fix NPE 2025-07-03 17:51:03 -06:00
ManInMyVan 1bfef2e580 minor cleanup 2025-07-03 17:18:19 -06:00
ManInMyVan c30be94875 why does this only not affect 1.21.4 2025-07-03 15:57:33 -06:00
ManInMyVan 0f54849351 SprintE on 1.18.2+ 2025-07-03 15:55:00 -06:00
ManInMyVan 1ab7f9f47f fix #2180 2025-07-02 16:03:55 -06:00
Cyramek c8df737498 implement HappyGhast movement simulation (#2182)
* implement happyghast movement simulation

* use grim movement input calculations for happy ghast

* remove unused jump possibilities method from HappyGhastPredictionEngine
2025-07-02 20:12:17 +01:00
SamB440 710d614c33 Check for any menu that isn't the player's 2025-07-02 14:03:35 +01:00
ManInMyVan dea9659da6 fix vine hitbox on pre-1.13 clients 2025-07-01 14:01:34 -06:00
SamB440 b8013d64fc Fix issue with server sending player inventory slot updates whilst in an unsupported inventory 2025-07-01 20:54:34 +01:00
SamB440 56130ed8c8 Add run-paper so I can debug easily 2025-07-01 19:03:54 +01:00
Axionize 8c64b48433 Fix minor spelling mistake in comment 2025-07-01 00:27:46 -04:00
Axionize 0fb2e00d96 Fix DRIED_GHAST CollisionBox for 1.7.10-1.21.5 2025-07-01 00:13:22 -04:00
cyramek 06dc5a54af properly support hasSaddle 2025-06-30 21:16:06 +02:00
Cyramek aaeded18c7 1.21.5/.6/.7 (#2079)
* 1.21.5 partial changes

* leftover

* cleanup

* check if player is in vehicle

* 1;1 input transformation

* forgot to push that

* notes

* i hate mutability

* not the case

* this is the right way

* note

* java style

* initial block collisions support

* incorrect fix for powder snow issues (1.21.4)

* support 1.18.2+ horizontal collision detection

* support elytra changes

* point three

* readability

* missed that

* fix merge conflicts

* support minecraft:blocks_attacks

* minecraft:blocks_attacks can override minecraft:food

* remove debug

* rewrite data consumable components support

* simplify consumable component handling

* as always, I forgot to remove this

* note things todo

* one more thing

* POC item behaviour

* workaround https://github.com/retrooper/packetevents/pull/1255

* 1.21.6 initial support

* fix .5/.6 riding issues

* create happy ghast entity

* todo list

* remove workarounds

* properly fix riding issues

* only use item behaviour system on reliable data component server

* replace happy ghast checks

* fix jumping on honey blocks, implement dried ghast block

* partially implement dried ghast ViaVersion replacement

* update sneaking behavior for newer client versions

* things pointed out in review

* reduce movement buffer size

* rename that field

* little refactor

* don't duplicate code

* leave it as what it was

* rename SERVER_USE_INPUT_FOR_SNEAKING to SERVER_USES_INPUT_FOR_SNEAKING

* grim's packetevents fork is here!

* simplify isHappyGhast type check
2025-06-30 08:18:49 -04:00
Axionize fcc78519a6 Include fabric-permissions-api:0.4.0 for Fabric 1.21.6 2025-06-30 04:07:25 -04:00
Axionize 4ade97a08f 1.21.6 MVP
Changes from https://github.com/GrimAnticheat/Grim/pull/2079 remain unmerged. New movement, entity, and attribute fixes have not been accounted for. This merely allows Grim to boot on 1.21.6/1.21.7-rc2 servers and 1.21.6/1.21.7-rc2 players to join.
2025-06-30 03:44:53 -04:00
ManInMyVan 0ac0a788b0 reduce object creation on fabric servers 2025-06-25 17:04:20 -06:00
ManInMyVan 6c79bafde8 a bit more cleanup 2025-06-25 15:53:54 -06:00
ManInMyVan d3e3b5877c cleanup 2025-06-25 15:38:21 -06:00
ManInMyVan bc258de6fb slight optimization 2025-06-25 14:24:41 -06:00
SamB440 b6e481dff5 Check if entityId is an active firework before adding to removal set 2025-06-22 14:13:08 +01:00
ManInMyVan d190e42b71 fix #2156 2025-06-19 11:19:45 -06:00
ManInMyVan 5de34f52f3 support reobf folia jars 2025-06-17 19:10:44 -06:00
ManInMyVan 9484870e8c fire can't be placed in liquids 2025-06-16 12:00:10 -06:00
ManInMyVan e81716acff iron trapdoors can only be opened in 1.7 2025-06-16 11:38:02 -06:00
ManInMyVan ea848fa919 fix #2149 2025-06-15 20:24:02 -06:00
SamB440 5e5fbe6283 Support plugins updating ATTACK_DAMAGE (fixes #2159) 2025-06-14 12:30:15 +01:00
ManInMyVan 984cfeecbe fix skinsrestorer compat 2025-06-07 20:12:57 -06:00
ManInMyVan 983872a585 patch #2140 2025-06-04 18:24:49 -06:00
AoElite 63f2c054a6 Merge pull request #2143 from Souipi/fix/ka-ping-method-cce
Fix GrimPlayer#getKeepAlivePing() method throwing a CCE.
2025-06-03 01:04:40 -04:00
Souipi b821f12503 fix: Fix GrimPlayer#getKeepAlivePing() method throwing a CCE. 2025-06-02 23:26:52 +02:00
ManInMyVan d22f8d8a76 fix swift sneak on pre-1.20.5 clients on 1.20.5+ servers 2025-06-01 10:52:47 -06:00
AoElite ee2ccc5708 add CONTRIBUTING.md and improve the README.md 2025-06-01 11:06:26 -04:00
AoElite 6ad8050923 improve piston performance 2025-06-01 07:15:10 -04:00
ManInMyVan 9786f0ddbf fix false with ender dragon attack slowdown 2025-05-30 20:33:04 -06:00
ManInMyVan 0d6d4daaaa minor refactor 2025-05-30 20:28:47 -06:00
ManInMyVan 32d778dd80 remove unused import 2025-05-30 18:47:03 -06:00
ManInMyVan 485f2672a7 wtf mojang 2025-05-30 18:37:47 -06:00
ManInMyVan b8600bc167 exempt ElytraC for 1 tick on respawn 2025-05-29 19:59:47 -06:00
ManInMyVan 3d68d2652a remove unused import 2025-05-29 19:33:06 -06:00
ManInMyVan e6a75183d9 probably fix #2134 2025-05-29 19:25:13 -06:00
ManInMyVan ef195ea941 fix potential false in MultiActionsE 2025-05-29 14:06:28 -06:00
ManInMyVan 5308c35c63 make MultiActionsB a BlockBreakCheck 2025-05-29 14:06:12 -06:00
ManInMyVan ee2e198335 check sneaking in MultiActionsC/D 2025-05-28 18:27:45 -06:00
ManInMyVan 76a262d592 update MultiActionsC/D description 2025-05-28 17:52:37 -06:00
Axionize 0c52c208cf Revert "Remove Unused legacy calls to event.setLastUsedWrapper(null) predating PE re-encode by default and markForReEncode()"
This reverts commit 4798903fb1.
2025-05-28 11:34:49 -04:00
ManInMyVan 438b0a5890 check knownInput in MultiActionsC/D 2025-05-27 20:05:16 -06:00
ManInMyVan 781d019dcd make MultiActionsC/D slightly more strict 2025-05-27 19:10:32 -06:00
ManInMyVan 3664b77910 BadPacketsP description 2025-05-27 19:05:12 -06:00
ManInMyVan a470d849ec maybe fix the folia BukkitItemResetHandler "issue" 2025-05-27 16:30:44 -06:00
Axionize 4798903fb1 Remove Unused legacy calls to event.setLastUsedWrapper(null) predating PE re-encode by default and markForReEncode() 2025-05-27 18:09:47 -04:00
Axionize 5a0783dbc4 Temporary fix for 1.16.5 Dirt Path/Grass Path Simulation errors 2025-05-26 21:23:11 -04:00
Axionize 8d0bb8fe19 Remove inaccurate comment 2025-05-26 21:23:11 -04:00
ManInMyVan 4442231626 don't pollData() if they don't exist 2025-05-26 18:29:44 -06:00
Axionize 895936b4b4 Optimize ViaVersionUtil
Tested on
* PandaSpigot (1.8) Java 17
* PaperSpigot (1.21.4) Java 21
* Fabric (1.21.5) Java 21

Tested-by: Axionize <154778082+axionize@users.noreply.github.com>
2025-05-26 18:51:43 -04:00
Axionize 493666537c Update PacketEvents version to new grim/2.0 branch state 2025-05-25 21:32:15 -04:00
ManInMyVan 062fe8c3eb maybe fix the disconnect.timeout issue 2025-05-25 13:24:25 -06:00
ManInMyVan 8dee1a5f84 Merge pull request #2135 from RegotlyLong/2.0
Add Chinese Translation ---- Update zh.yml
2025-05-25 12:49:30 -06:00
Ty_Regotly 20e6546d54 Update zh.yml 2025-05-25 14:52:06 +08:00
Ty_Regotly 7429cd9210 Merge branch 'GrimAnticheat:2.0' into 2.0 2025-05-25 14:47:45 +08:00
polymorphicengine b9e858d025 Add config option to disable/enable the recently added Forge blacklist (#2131)
* add config option to disable forge blacklist

* change the formatting

* Add the config setting to the rest of the languages.

* Include the comment in all available languages.

* Minor formatting changes.
2025-05-24 17:06:32 +01:00
ManInMyVan 9c8900bd3c fix BadPacketsH false when changing worlds with same dimension 2025-05-23 16:13:31 -06:00
ManInMyVan af4f8a6ddb and for pre-1.17 servers 2025-05-23 14:58:49 -06:00
ManInMyVan 815406b7b8 fix #2132 2025-05-23 14:34:15 -06:00
ManInMyVan ce39a84470 fix going into end portals in the end falsing badpacketsm 2025-05-23 14:00:14 -06:00
ManInMyVan 192b5f3818 remove unused imports 2025-05-23 13:59:28 -06:00
ManInMyVan fd8c9bb6e6 fix IndexOutOfBoundsException 2025-05-20 21:11:49 -06:00
ManInMyVan 1d0b3a856f move exploit and non-movement crash checks to packetChecks 2025-05-20 18:11:00 -06:00
ManInMyVan 415a88f007 move BadPacketsS handling to BadPacketsS class 2025-05-20 18:10:57 -06:00
ManInMyVan 008cb466e0 move BadPacketsO to be alphabetically 2025-05-20 18:09:28 -06:00
ManInMyVan 44cdd860df make BadPacketsJ a PacketCheck 2025-05-20 18:09:27 -06:00
AoElite f7670d8a9b Create config.yml 2025-05-20 17:23:17 -04:00
Axionize 2a8f2d504a Fix CME with accessing blockDataToId on Folia 2025-05-19 23:27:37 -04:00
Axionize 58128122fc Optimize BukkitPlatformWorld.getBlockAt() for legacy servers 2025-05-19 23:25:43 -04:00
Axionize 0cc819fea9 Revert incorrect Folia patch for ClassNotFoundException causing inadvertent firing of BlockReceiveGameEvent 2025-05-19 23:06:34 -04:00
ManInMyVan ab7ad0be98 reset server item usage on WINDOW_ITEMS
also check hand and item
2025-05-19 12:20:02 -06:00
SamB440 69c291de9a Blacklist forge 1.18.2-1.19.3.
Also added packet error key to language files.
2025-05-17 16:56:04 +01:00
SamB440 24f95fd0b9 Fix being able to use an elytra when it is in broken state 2025-05-17 14:50:08 +01:00
ManInMyVan 05d96aeaa1 Merge pull request #2122 from Cyramek/legacy-block-at
fix legacy BukkitPlatformWorld#getBlockAt
2025-05-16 20:44:49 -06:00
cyramek 0ab93d3fb2 fix legacy BukkitPlatformWorld#getBlockAt 2025-05-17 04:43:18 +02:00
ManInMyVan 1a39f97e22 check for respawning while alive 2025-05-16 17:01:02 -06:00
ManInMyVan f69e244363 move Post class to misc 2025-05-16 15:02:04 -06:00
ManInMyVan 740b9fe35a Timer - Vehicle -> VehicleTimer 2025-05-16 14:48:46 -06:00
ManInMyVan 829084c564 bruh 2025-05-16 13:49:59 -06:00
ManInMyVan b6e9eb0944 players don't tick in unloaded chunks 2025-05-15 20:14:38 -06:00
ManInMyVan 7555e2422b this just stops pre from flagging on 1.9 2025-05-14 16:16:57 -06:00
ManInMyVan 82f8bbf89f check the hand the player is using the item in 2025-05-14 15:48:12 -06:00
SamB440 537739095c Fix disabling threshold (it shouldn't have been working before either) 2025-05-14 17:20:08 +01:00
SamB440 60ff6d7a18 Split ping-abuse-limit-threshold into a separate check 2025-05-14 17:17:33 +01:00
SamB440 077ad7690b We do need to throw for this to work 2025-05-14 16:25:15 +01:00
ManInMyVan 9144638ef5 make PacketOrderB stricter 2025-05-13 16:06:43 -06:00
ManInMyVan 463189c35e make badpacketse stricter 2025-05-12 19:42:10 -06:00
AoElite 9099764f10 handle discord formatting better 2025-05-12 09:39:47 -04:00
AoElite 025e4dee4f handle error logging more appropriately 2025-05-12 07:35:13 -04:00
AoElite e56778d1c2 dump command changes: renamed the properties field to states, added detected platform, renamed system field names 2025-05-12 07:12:34 -04:00
AoElite 460d4db6cf fix item reset usage error with folia 2025-05-12 06:49:19 -04:00
AoElite 2514bba15b fixed folia not being detected 2025-05-12 06:48:38 -04:00
ManInMyVan c0d388548c remove exempt players from the alert manager on disconnect 2025-05-11 16:00:14 -06:00
ManInMyVan 9f0990d412 fix /gl 2025-05-11 13:15:22 -06:00
ManInMyVan e3d5b7d7a9 bubble columns were added in 1.13
still falses
2025-05-11 13:05:53 -06:00
ManInMyVan 544f3bc732 fix #2116 2025-05-10 16:00:30 -06:00
ManInMyVan d547e8b010 fix build 2025-05-09 22:18:54 -06:00
ManInMyVan bff54163db slight cleanup 2025-05-09 21:43:15 -06:00
ManInMyVan d9d08e6930 Merge pull request #2112 from PartialEq/PartialEq-patch-2
Always include entity type in reach
2025-05-09 15:15:25 -06:00
ManInMyVan 6cfc07897d actually tie verbose state to alert state this time 2025-05-09 15:08:27 -06:00
ManInMyVan 6505975c7b don't send alerts twice with verbose and alerts enabled 2025-05-09 14:06:46 -06:00
ManInMyVan 05df3f9267 tie verbose state to alert state with console alerts + abstraction 2025-05-09 13:22:43 -06:00
Axionize d4efa59ac5 Print out all BuildFlags, reformat BuildFlags print 2025-05-09 10:28:09 -04:00
Axionize 27f94db349 BuildConfig updates to make mavenLocalUse a flag 2025-05-09 10:23:15 -04:00
PartialEq 686b0efdb7 Always include entity type in reach
easier for plugins to parse
2025-05-08 13:20:27 +01:00
ManInMyVan 49a1e82d06 fix MultiActionsD false 2025-05-07 18:45:55 -06:00
Axionize c950b5e648 Fix HitboxData for Leaf Litter <= 1.21.5. Refactor HitboxData for Leaf Litter, Wild Flowers, and Cactus Flowers. 2025-05-07 11:28:43 -04:00
Axionize 8c5f803b59 Fix Leaf Litter and Wild Flowers HitboxData for <=1.21.4 2025-05-07 03:28:05 -04:00
ManInMyVan cfafff1c15 only reset sequence id if world changed 2025-05-06 18:31:40 -06:00
ManInMyVan bff3223e58 include verbose in Simulation flags
fixes #2048
2025-05-06 18:20:03 -06:00
ManInMyVan 96426b332c why 2025-05-06 17:47:03 -06:00
ManInMyVan 79e5a4d4d0 call onBlockPlace if the player is in a vehicle
fixes a BadPacketsH false
2025-05-05 19:00:28 -06:00
ManInMyVan bf6b141e3d bruh 2025-05-05 18:16:31 -06:00
ManInMyVan 32dc1db701 remove duplicated hitbox data entries 2025-05-05 12:16:32 -06:00
ManInMyVan f5d3b4ad1f Merge pull request #2106 from Bram1903/fix/BadPacketsH-NullPointerException
Fixed: NullPointerException in BadPacketsH
2025-05-05 06:18:39 -06:00
Bram 5947b086ec Fixed: NullPointerException being thrown in the BadPacketsH check upon the server sending a respawn packet 2025-05-05 10:59:17 +02:00
Axionize aac0c8b30a Fix HitboxData for new 1.21.4 & 1.21.5 blocks
- Pale Hanging Moss
- Bush
- Short Dry Grass
- Tall Dry Grass
- Leaf Litter
- Wild Flower
- Cactus Flower
- Refactor and optimize allocations in Pink Petal handler, reuse for Wild Flowers and Leaf Litters
- Remove code for getting horizontalID now merged into PE.
2025-05-04 23:23:19 -04:00
Axionize b67527564e Mark Text Displays as un-hittable entities 2025-05-04 20:43:26 -04:00
ManInMyVan 90447f2da9 delete unused ConversionUtil class 2025-05-04 17:08:16 -06:00
ManInMyVan b410b752bd make CollisionData implement CollisionFactory 2025-05-04 15:26:48 -06:00
ManInMyVan 945e055915 add pale hanging moss hitbox 2025-05-04 15:10:51 -06:00
ManInMyVan 9acc8a9b00 make HitboxData implement HitboxyFactory 2025-05-04 15:10:40 -06:00
ManInMyVan 20e2f00d84 add BadPacketsJ 2025-05-04 13:53:33 -06:00
ManInMyVan 02a47d1c35 oops 2025-05-04 12:57:12 -06:00
ManInMyVan ba1ee9b08b don't let people create ghost blocks by intentionally flagging 2025-05-04 11:55:54 -06:00
ManInMyVan 5e3280ea77 make BlockPlaceCheck implement BlockBreakCheck 2025-05-04 11:06:20 -06:00
ManInMyVan da45c99b0a add sequence to BlockBreak 2025-05-04 11:03:32 -06:00
ManInMyVan 08386bb4b2 add sequence to BlockPlace 2025-05-04 10:56:41 -06:00
Axionize 35811fe551 Mark expierence orb as unhittable entity 2025-05-04 12:37:47 -04:00
ManInMyVan efbb66c8d8 add MultiActionsG 2025-05-03 20:03:04 -06:00
ManInMyVan 0a853cb1fd forgot to check this 2025-05-03 19:03:46 -06:00
ManInMyVan 844b976826 make BadPacketsH not handle action digging packets
BadPacketsL flags them already
2025-05-03 18:44:46 -06:00
ManInMyVan a37d85c6ae fix a SprintB false 2025-05-03 15:45:40 -06:00
ManInMyVan e9109fcc11 enforce sequence id order 2025-05-03 15:39:14 -06:00
ManInMyVan b67e40da02 patch bundle crash 2025-05-03 14:19:00 -06:00
ManInMyVan c8848f0c37 always parse grim placeholders if possible 2025-05-02 16:17:32 -06:00
ManInMyVan 8ab2e3b237 slight cleanup 2025-05-02 15:49:28 -06:00
ManInMyVan 6a2677e89e tie verbose state to alert state 2025-05-02 15:37:08 -06:00
ManInMyVan b2673aa763 use an enum for alert type instead of a string
hopefully I didn't break anything
2025-05-02 15:33:03 -06:00
ManInMyVan cd43b44576 Merge pull request #2099 from Krymonota/feature/check-server-version-placement-rotation
Check server version before complaining about ViaVersion placement rotation
2025-05-02 07:37:47 -06:00
SamB440 5f65bf084c Merge pull request #2101 from mikheilkozlovi/2.0
Correct grammar
2025-05-02 12:38:27 +01:00
MISHA 930bb9096a Correct grammar 2025-05-02 12:40:18 +04:00
Axionize 3f0eaf3ac2 Fix fastbreak false with Brewing Stands for clients >=1.21.4 when not using tool; Will revert when PE fixes issue 2025-05-01 15:08:15 -04:00
Axionize 0d497d017b Make logging on Fabric use native libs and native formatting 2025-05-01 12:08:00 -04:00
Axionize d40e74c2d3 Fix NPE accessing player.getClienetVersion() after final field refactor in GrimPlayer 2025-05-01 07:49:20 -04:00
Axionize cda248ac25 Revert "this got closed"
This reverts commit ab3390c818.
2025-05-01 07:36:36 -04:00
ManInMyVan 5dd64fd414 bump adventure 2025-04-30 23:54:19 -06:00
ManInMyVan 9d76a6dadf fix possible npe in getViaTranslatedClientBlockID 2025-04-30 17:36:27 -06:00
ManInMyVan 3b2c08add3 a bit more cleanup 2025-04-30 17:36:17 -06:00
ManInMyVan e8416baf7f inline ver in getClientVersion() 2025-04-30 17:17:11 -06:00
ManInMyVan c29a422b48 GrimPlayer: use final fields where possible
also initialize some in the declaration
2025-04-30 17:16:57 -06:00
ManInMyVan ab3390c818 this got closed 2025-04-30 17:16:10 -06:00
ManInMyVan bbb49e57aa use lombok for resyncHandler getter/setter 2025-04-30 17:06:27 -06:00
ManInMyVan 77c57387cf move 2 UncertaintyHandler init lines to UncertaintyHandler
why were these not in the constructor
2025-04-30 17:06:27 -06:00
ManInMyVan b6e87def02 GrimPlayer: use Objects.requireNonNull() instead of Preconditions.checkArgument()
also use jetbrains NotNull for player variable
2025-04-30 17:06:27 -06:00
ManInMyVan 405d97d051 TaskHandle: getCancelled() -> isCancelled()
also use lombok in FabricTaskHandle
2025-04-30 17:06:25 -06:00
ManInMyVan febe34c990 actually use retired in folia entity scheduler 2025-04-30 17:05:31 -06:00
Axionize 91261e9563 Write sync boolean to FabricTasks 2025-04-30 19:01:18 -04:00
Axionize f3d9af34b1 You can't hit Lightning bolts or experince bottles 2025-04-30 15:50:10 -04:00
Axionize acffaa7a7d Mark block displays as Unhittable 2025-04-30 15:32:43 -04:00
Axionize f05e6639fd Fix punishment manager removing violations too quickly after lombok refactor 2025-04-30 14:18:33 -04:00
Axionize 54809f8c71 Fix canHit() modeling with dead entities 2025-04-30 13:26:22 -04:00
Axionize 1a7a43641e Minor Iteration optimizations; move some checks with no listeners into their own category 2025-04-30 12:51:36 -04:00
Axionize bc452fcce6 Refactor debugging to extract AbstractDebugHandler 2025-04-30 12:24:19 -04:00
Axionize 12b121f6bd Fix 1.21.5 Inventory creative check crash on Fabric 2025-04-30 11:51:40 -04:00
Niklas Gerstner 9165f2bfaa Check server version before logging error regarding ViaVersion placement rotation
ViaVersion's `fix-1_21-placement-rotation` option only applies to 1.21+ clients on servers older than 1.21. Ref:
- https://github.com/ViaVersion/ViaVersion/blob/e597d8faaa69f1e0246999b14c1e021129031e97/api/src/main/java/com/viaversion/viaversion/api/configuration/ViaVersionConfig.java#L483
- https://github.com/ViaVersion/ViaVersion/blob/e597d8faaa69f1e0246999b14c1e021129031e97/common/src/main/java/com/viaversion/viaversion/protocols/v1_20_5to1_21/rewriter/EntityPacketRewriter1_21.java#L114

I got annoyed by the error message because it doesn't apply to my server version, and it could be misleading for other server owners, so let's check the server version before complaining.
2025-04-30 16:38:56 +02:00
ManInMyVan 9063631dfe don't allow placeholders in placeholders 2025-04-29 16:19:47 -06:00
ManInMyVan 5028db35bb move hasPlaceholderAPI to BukkitMessagePlaceHolderManager 2025-04-29 15:44:39 -06:00
Axionize 1108f38440 Fix typo in BukkitPlatformInventory grabbing helmet when calling getChestplate() 2025-04-29 09:24:23 -04:00
Axionize 60c681b8cd Support ViaVersion translated blocks in Fastbreak check 2025-04-29 09:24:23 -04:00
ManInMyVan 439140d326 Merge pull request #2096 from 483378/fix/cobweb-0.03-false-setback
Fix cobweb 0.03 false setback
2025-04-29 01:30:05 -06:00
ManInMyVan 908fa71c6a make replacePlaceholders GrimPlayer nullable 2025-04-28 19:38:27 -06:00
ManInMyVan 64fdd885ae use the param 2025-04-28 19:01:41 -06:00
Axionize a20e5b8dc7 Add alternate names to re-add support for old enviornment variable exmaples, fix building bukkit plugin.yml in lite+no_relocate modes 2025-04-28 18:08:29 -04:00
483378 7d74c7f6dc Fix cobweb 0.03 false setback 2025-04-28 22:12:31 +02:00
ManInMyVan d6d8062498 fix placeholderapi expansion tab complete 2025-04-27 16:03:20 -06:00
SamB440 0750bedb49 Update issue templates to reflect platform independence 2025-04-27 21:23:11 +01:00
SamB440 0c8e51a16e Fix addNonEffectiveAI on 1.21.5 (#2090) 2025-04-27 21:09:51 +01:00
ManInMyVan b4d4942bf3 escape minimessage in verbose 2025-04-27 14:07:36 -06:00
ManInMyVan b89419e972 don't parse placeholders in verbose 2025-04-27 13:19:26 -06:00
ManInMyVan e7dde99aa1 why was this like that? 2025-04-27 12:44:46 -06:00
ManInMyVan 50bf3c1141 slight cleanup 2025-04-27 12:37:40 -06:00
ManInMyVan ab7b1e3d56 lombok 2025-04-27 12:28:32 -06:00
Axionize 897a73e823 Fix build error with shadePE flag not working and -Pflag specifiations not working 2025-04-27 10:16:57 -04:00
Axionize 65ca915e79 Translations for PacketOrderI config 2025-04-27 10:16:57 -04:00
Axionize 70a0bbccbc Refactor traverseBlocks and getNearestBlockHitResult into WorldRayTrace.jav 2025-04-27 10:16:57 -04:00
ManInMyVan 5faba02091 why was it like this 2025-04-26 20:39:45 -06:00
ManInMyVan 68739cd78b Merge pull request #1678 from ManInMyVan/packetorder
Add PacketOrder checks
2025-04-26 16:02:27 -06:00
ManInMyVan 7311e65cdf merge fixes 2025-04-26 15:07:08 -06:00
ManInMyVan f0176901dd Merge remote-tracking branch 'refs/remotes/upstream/2.0' into packetorder 2025-04-26 15:03:34 -06:00
Axionize 3902561418 Refactor names of BadPacketsH & BadPacketsM -> PacketOrderB & PacketOrderC respectively 2025-04-26 11:27:10 -04:00
Axionize 78c96b3e83 Allow /grim brands, verbose, alerts to be executed by console, cleanup code for sending and processing brands, verbose, alerts 2025-04-26 11:03:36 -04:00
Axionize cc3308243b Update API 2025-04-26 10:28:07 -04:00
Axionize e8700bf60f Add silent flag for toggling alerts/verbose/brands and implement new AlertManager API 2025-04-26 10:18:30 -04:00
Axionize 843cfe20f4 Fix rare issue with vehicles on Bukkit in SetbackUtil 2025-04-26 10:09:00 -04:00
Axionize f4e0dadf2b Bump gradle wrapper; only configure compile optimizations for subprojects 2025-04-26 07:42:53 -04:00
Axionize a57e4984b7 Minor Build Optimizations 2025-04-26 07:40:03 -04:00
Axionize 0f607ba729 Fix getting TPS on Fabric returning average tick time instead 2025-04-26 03:11:01 -04:00
Axionize a50621b16f Fix :fabric:mc1161 submodule not loading properly since 3 commits ago 2025-04-26 00:56:14 -04:00
Axionize 4227baa87a Fix :fabric:mc1171 submodule not loading properly since 2 commits ago 2025-04-26 00:46:06 -04:00
Axionize f254d8467f Ignore temporary buildSrc/.kotlin folder in .gitignore 2025-04-26 00:25:11 -04:00
Axionize f8595ca1ac Fabric package consistency fixes 2025-04-26 00:24:41 -04:00
Axionize a1001963d0 Fix erorr with setting gamemode on 1.17-1.20.1 with previous commit 2025-04-26 00:13:30 -04:00
Axionize 0b97c55679 Fix setting gamemode on Fabric breaking in 1.17+ 2025-04-26 00:05:46 -04:00
ManInMyVan 079486e4dc update readme for platform independence changes 2025-04-25 18:40:21 -06:00
AoElite 50b360dd09 use our own packetevents repo 2025-04-25 03:53:54 -04:00
a45917c9d2 Platform Independence (future Sponge, Fabric, Neoforge, Velocity, etc... support) (#2024)
* 1.21.5 partial changes

* leftover

* cleanup

* check if player is in vehicle

* 1;1 input transformation

* forgot to push that

* notes

* i hate mutability

* not the case

* this is the right way

* note

* java style

* initial block collisions support

* incorrect fix for powder snow issues (1.21.4)

* support 1.18.2+ horizontal collision detection

* Seperated/Abstracted:
- Thread Management
- GrimEntity/PlatformPlayer + PlatformInventory
- PlatformWorld, PlatformChunk, Location
- Removed many bukkit dependencies
- Migrated Bukkit Events to own code section

- Disabled BStats temporarily

* Refactor Part 2:
- Replace Vectors
- Replace ChatColor.translateColorCodes()

* Stash code

* Almost there; just events and bukkit extensions left

* Fix plugin compilation and exeution of commands

* Refactor Part 3:
Checkpoint
Need to implement:
- Fix PlaceHolderAPI and ManInMyVan's MessageUtil logic error
- Add BStats back
- Add platform independent Permissions
- Make TickEndEvent handling platform independent

Need to Test:
- ProxyAlertMessenger
- Commands

* Platform Independence Achieved!

* Multi-module project init setup

* Complete multi-module project setup

* Fabric Support MVP
- Registering permissions likely incomplete
- Building jar incomplete; only works in Debug mode
- Exempting on reload not done
- Plugin Channels not implemented

* Platform loading fixes

* Refactor resyncPosition() internally; may move to platformPlayer in future

* Beta Fabric Support Complete + General Bug Fixes:
- Generate autocompletions for permissions
- Make OP, and enable-on-join permissions false by default even for ops

- Fixed usage of isWorldLoaded() in pre-migration codebase from breaking 1.8 support
- Numerous command loader bugs fixed
- A lot more

* Fix Fabric execution and shutdown; Initial Fabric build script

* Finish Fabric buildscript; now builds runnable jar

* Fix Actions workflow

* Build against new Grim API instead of locally

* Temporarily build against my fork to fix PacketEvent's broken Fabric support

* Fix scheduler hierachy issue

* Moderate refactoring and codebase cleanup

Fixed GitHub actions

Note that Fabric platform is missing:
- Pistons
- Providing an instance of GrimExternalAPI for other plugins/mods to get
- and more

* PE datatype refactor; Fix Folia support

* Fix endTick on Folia

* Refactor Fabric to support 1.21.4, 1.21.1, and (soon) 1.16.1

* Add 1.20.1 support (once PE is fixed)

* Actuallly commit 1.20.4 support

* Fix Legacy (< 1.16.5) Big DripLeaf CollisionBox modeling

* Fix project build issues and fix 1.20.1 support

* Configure builds to use shared lib versions files; push for rebuild with updated PE; (Working 1.20.1)

* Code cleanup

* Minor code cleanup

* Bump Fabric loom version; trigger rebuild on updated PE fork with Fabric fixes

* Fix 1.8 support using non-existent inventory method

* Fix running fabric in IDE and dev mode

Credit: @Bawnorton

* Hopefully Fix inventory errors

* Cleanup Fabric buildscript

* Fix rare preconditions error with checking for null platformPlayer

* Fix Build error from rebasing https://github.com/GrimAnticheat/Grim/commit/aab710dd8b55bc6fbe88f0f4c79aa214527a20dd

* Code cleanup to address code review concerns

* Fix build issues with relocation on bukkit; force rebuild for fabric registry fix with PE

* Fix library relocation typo

* Bump snakeyaml version for Fabric support

* Build against slim configuralize for fabric support

* Fix Geyser-Fabric compatability

* Initable refactor; support multiple types of initables as one object; shutdown fabric bstats

* Fix updating native ServerPlayerEntity reference; Refactor @NonNull annotations

* Translation parity (and more/better) with pre-platform-independence port

* Make Grim rely on JiJed and loaded PE API; Transition PacketPlayerDigging to be cross-platform from upstream

* Add support for Spigot 1.17 - 1.18.2 itemUsageReset()

- Also decrease allocated via gradle.properties
- Forces rebuild with new PE which will fix Geyser detection

* Only include fabricAPI modules we use, reuse dependency code for multiple projects

* New API refactor with getEventBus()

* Minor Build optimization

* Bump RAM allocation to Gradle in root gradle.properties

* Fix build issues with downloading Conditional Mixin library for PE Fabric

* Partially fix lack of suggestions in cloud commands when incorrect command/typo is typed (only works when required arguments missing in a command on modern brigadier servers due to cloud bug, will fix later)

- Also force rebuild with new PE

* Fix build errors from rebasing

* Add explicit dependency for parent mod on packetevents

* Refactor to use new API with better EventBus and consolidate event-bus related code to be non-platform specific

* Fix error with teleporting between dimensions

* Update Loom; Buildscript consolidation and improvements

* Initial 1.21.5 Support

* Significantly reduce Fabric jar size

* Fix 1.21.5 Support breaking with new Chunk format

* Improve performance of underlying Collection used for exemptUsers

* Update API; Add support for overriding player.resyncPosition(x, y, z, sequence)

* Minor Annotation Style changes

* Execute piston updates from Bukkit Event in player netty channel.
- This fixes a rare race condition with pistons. https://github.com/GrimAnticheat/Grim/issues/2031
- Reduces load on main thread (we check for isChunkLoaded() and do processing in netty channel helper now)

* Fix 1.21.5 support and entity metadata
- Fixed 1.21.5 Pig Variant entity metadata handling
- Read Strider isShaking value from entity metadata
- (Hopefully) Fix 1.8 horse saddle modeling

* Fix working with cooldown groups

* Fix 1.21.5 Inventory compatability issues

* Improve performance of internal sendAlert command invocations

* Fix PlaceholderAPI replacements

* Address code review styling concerns. Fix errors from rebasing on 2.0.

* Fully replace underlying native inventory and player objects when reset on death.
- Fixes fastbreak issues after dying with keepInventory off

* Fix rebase on top of more 1.21.5 and other movement fixes.

* Implement new versioning scheme: https://github.com/GrimAnticheat/Grim/wiki/Versions-and-Versioning

* Rewrite Fabric multi-version support
 - handles 1.16.1 - 1.21.5 (currently only 1.19.3+ works due to Cloud command library limitations)
 - Java 21 -> Java 17 requirement for Fabric on older versions that didn't require Java 21

* Startup time optimization

* Fix Fabric Inventory from multi-version refactor

* Fix update checker by fixing version parsing for new version schema

* Complete translations

* Improve Reach and Hitboxes config

* Fix Entity Modeling
- Save data for what mobs can be hit for future hit-un-hittable-entity-check
- Fix bounding boxes and modeling sizes for some entities (firework rocket, falling block, guardians, armor stands)
- Fix modeling of numerous types of baby mobs

* Add support for Fastbreak on blocks that don't exist in client version

* Fix error when kicking player on Fabric 1.20.2+

* Fix Fabric PlatformEntity and PlatformInventory loader issue

* Fix executing commands in Fabric 1.20.3+

* Build 1.17 module against 1.17.1; Fix loader naming inconsistencies

* Fix logic error with FabricAsyncScheduler's runAtFixedRate()

* use our own webhook system

* Fix build issues with compileOnly exports and RotationData/BadPacketsB imports

* Fix issue with running some commands on 1.21.2+

* update GrimAPI used in build script

* Fix building with new API

---------

Co-authored-by: cyramek <xcyramek@gmail.com>
Co-authored-by: ManInMyVan <113963219+ManInMyVan@users.noreply.github.com>
2025-04-25 02:47:26 -04:00
ManInMyVan 858d00cf89 fix BadPacketsE false 2025-04-23 15:10:51 -06:00
ManInMyVan 7190444988 I'm a genius 2025-04-23 15:05:05 -06:00
ManInMyVan c9dfb30cab how did I miss that 2025-04-23 15:03:26 -06:00
ManInMyVan 7618b1fb27 that's definitely wrong 2025-04-23 14:51:29 -06:00
ManInMyVan fb725dc4ec handle PLAYER_ROTATION packets
causes simulation falses for some reason, but this is better than it was before
2025-04-23 14:26:30 -06:00
SamB440 d5fbbbffb0 Workflows are fun! 2025-04-17 21:17:16 +01:00
SamB440 9b04d8ba1b Fix deprecation... 2025-04-17 21:13:36 +01:00
SamB440 8d2f51dc1a Bump setup-gradle to v4 2025-04-17 21:11:00 +01:00
SamB440 401abad5fd Bump version 2025-04-17 18:52:54 +01:00
SamB440 3f67b339ba Update Gradle wrapper and add validation workflow step 2025-04-17 17:38:56 +01:00
ManInMyVan c083cbabed fix 1.18+ world reader 2025-04-13 20:20:22 -06:00
ManInMyVan 23f7c11512 fix build 2025-04-13 11:16:54 -06:00
SamB440 12d5f752af Merge pull request #2078 from Packsolite/2.0
Fix possible NullPointerException introduced with #2076
2025-04-13 16:07:04 +01:00
Packsolite be23df3313 Fix NullPointerException 2025-04-13 14:54:44 +02:00
ManInMyVan fb9d6e48f8 bump packetevents 2025-04-12 22:50:18 -06:00
ManInMyVan 459032943b remove misleading comment 2025-04-12 21:53:33 -06:00
ManInMyVan 404dad8d89 Merge pull request #2076 from Packsolite/2.0
Fix vehicle desync when demounting too fast
2025-04-12 20:30:36 -06:00
Packsolite 27297942f3 Fix vehicle desync when demounting too fast 2025-04-11 22:13:16 +02:00
ManInMyVan 0d32a9e610 fix &0 2025-04-10 08:19:39 -06:00
ManInMyVan 046628a7e3 fix brand detection with legacy servers and modern clients 2025-04-08 19:37:17 -06:00
ManInMyVan 07af49e6db forgot reset would reset non-decorations 2025-04-08 17:48:24 -06:00
ManInMyVan 13f08afaf5 fix reset-item-usage-on-item-update breaking vanilla behavior 2025-04-08 15:44:33 -06:00
ManInMyVan 3d57122eaf fix legacy color codes not resetting formatting 2025-04-07 17:43:45 -06:00
ManInMyVan 3f13807e87 bump minimessage 2025-04-07 17:41:45 -06:00
Cyramek ce8cdba97f Merge pull request #2058 from Cyramek/consumable
handle consumable component [1.21.2+]
2025-04-07 13:33:25 +01:00
ManInMyVan d975986196 remove temp fix for trial spawners 2025-04-01 17:00:22 -06:00
ManInMyVan b82f46beb4 flag invalid click types 2025-03-30 20:34:24 -06:00
SamB440 c947b868ba Fix teleports on 1.21.4, fixes #1923 2025-03-30 16:45:15 +01:00
AoElite 32c75c78b0 Merge pull request #2038 from 483378/fix/copper-door-falses
Fix copper door falses
2025-03-23 08:35:18 -04:00
Axionize b71c11882a Fix rare AirLiquidBreak NPE 2025-03-23 00:52:38 -04:00
ManInMyVan 990efdd6d2 fix a noslow 2025-03-22 15:31:21 -06:00
ManInMyVan 3c89193fff rename mitigate-autoblock and mitigate-desync-noslow 2025-03-22 15:25:49 -06:00
SamB440 aff9dc3c25 Merge pull request #2030 from Dream23322/patch-1
Update README.md
2025-03-22 18:43:15 +00:00
ManInMyVan 6b17d5fd0e fix spectate command 2025-03-19 16:06:07 -06:00
SamB440 319dca27ae Use single runnable for multi block changes 2025-03-19 14:24:27 +00:00
SamB440 5d20372645 Fix 1.21.2+ item cooldown
How to make simple feature more complex?
2025-03-14 18:26:39 +00:00
ManInMyVan 74108a2088 fix #1962 2025-03-14 11:56:23 -06:00
Cyramek aab710dd8b Fix Block Collisions [1.21.2+] (#2015) 2025-03-11 08:51:52 -04:00
483378 4a65251817 Fix copper door falses 2025-03-04 22:29:29 +01:00
SamB440 1fb1a73060 Fix teleport check 2025-03-02 20:37:41 +00:00
ManInMyVan 6811bc71fc Merge pull request #2033 from 483378/2.0
AimModulo360: fix horse false flag <= 1.13
2025-03-02 11:18:14 -07:00
SamB440 6205a23edd Merge pull request #2034 from 483378/Add-Hitboxes-to-punishments-config
Add Hitboxes to punishments config
2025-03-02 13:33:44 +00:00
483378 2f844bc56e Add Hitboxes to punishments config 2025-03-02 11:59:17 +01:00
483378 5ca4082675 AimModulo360: fix horse false flag <= 1.13 2025-03-02 10:59:51 +01:00
ManInMyVan 078bc139f7 revert changes from 68a04d05 and 45da02e7
it could be bypassed
2025-03-01 12:49:11 -07:00
Me. 37d07d3b03 Update README.md 2025-03-01 11:01:31 +10:00
SamB440 5bccfe831d Fix not reencoding stupidity packet 2025-02-28 14:31:41 +00:00
ManInMyVan 3fbaa0a0e6 why does OnlinePlayer exist 2025-02-23 10:42:20 -07:00
SamB440 931d26569c Don't need to throw 2025-02-23 12:42:05 +00:00
SamB440 b207fe233e Add option to debug packet cancelling 2025-02-22 20:40:23 +00:00
SamB440 0cc0910455 Merge pull request #2019 from Cyramek/water-push-fix
fix water flow push [1.21.4]
2025-02-22 19:25:09 +00:00
cyramek b5acee4911 fix water flow push 2025-02-22 20:04:57 +01:00
ManInMyVan ccada109b1 include "ms" in fastbreak verbose 2025-02-21 17:30:59 -07:00
ManInMyVan 16c0d37b54 include block type in fastbreak verbose 2025-02-21 17:30:16 -07:00
ManInMyVan f6c16ea567 make fastbreak verbose case consistent 2025-02-21 17:29:33 -07:00
ManInMyVan b9934f5130 same with tridents and debug sticks 2025-02-21 17:18:05 -07:00
ManInMyVan 3c48b6edab creative mode players cannot mine with a mace 2025-02-21 17:10:14 -07:00
ManInMyVan fdf8bc26a5 very minor changes 2025-02-21 16:07:00 -07:00
AoElite 900cbed5fa update api 2025-02-19 07:06:28 -05:00
SamB440 233cd2a7d7 Fix TAB server version check 2025-02-17 21:00:46 +00:00
AoElite 0c8b60018a build with Java 21 2025-02-14 03:14:54 -05:00
AoElite a54787152d bump deepsource runtime version to 17 2025-02-14 03:11:19 -05:00
AoElite 2932f0a40c handle end tick support for folia better & try to use paper's end tick event if reflection fails 2025-02-14 03:08:37 -05:00
AoElite 94d47391af correct wrong method name 2025-02-14 02:55:08 -05:00
AoElite 9964478ce1 added a better way to log exceptions 2025-02-14 02:33:38 -05:00
AoElite d3667e1add use teleportAsync when possible, this also should fix the spectating command not working on folia 2025-02-14 02:28:17 -05:00
ManInMyVan 04e1459d9e Merge pull request #2006 from ManInMyVan/fix/item-reset-exceptions
fix exceptions caused by resetting item usage async
2025-02-13 12:09:15 -07:00
ManInMyVan e99855bdc5 inline the class field 2025-02-12 15:54:59 -07:00
ManInMyVan 028a526c51 fix exceptions caused by resetting item usage async 2025-02-12 12:10:22 -07:00
SamB440 9650cdb4f2 Entity pushing fixes and performance improvement 2025-02-12 16:03:24 +00:00
GigaZelensky 5326845c7a Add Custom Setback Violation Threshold (#2001)
* Add Custom Setback Violation Threshold

This change introduces a configurable threshold for setbacks, allowing more flexibility in how violations are handled. It can be useful in multiple scenarios, such as integrating Grim with other anti-cheat systems like Vulcan. By delaying setbacks, more obvious cheats (e.g., flying) can be detected and handled by other systems first, preventing unnecessary interference that might limit their effectiveness.

Additionally, this feature helps reduce the impact of small false positives or minor violations on legitimate players, ensuring that occasional detection inaccuracies don’t result in unnecessary movement corrections.

The option is set to 1 by default to maintain the existing behavior, but it can be adjusted in the config for more customized handling.

* Update en.yml

* Update config to match custom Setback Violation Threshold

* Update config to match custom Setback Violation Threshold

* Update config to match custom Setback Violation Threshold

* Update config to match custom Setback Violation Threshold

* Update config to match custom Setback Violation Threshold

* Update config to match custom Setback Violation Threshold

* Update ja.yml

* Update config to match custom Setback Violation Threshold

* Update config to match custom Setback Violation Threshold

* Update tr.yml

* Update config to match custom Setback Violation Threshold

* Update config to match custom Setback Violation Threshold

* Update config to match custom Setback Violation Threshold
2025-02-12 15:09:01 +00:00
Axionize 7646df0563 Fix a rare CME in LatencyUtils (#1984) 2025-02-08 12:53:02 -05:00
Axionize 23369cf1d6 Fix modeling teleport packets for entities on clients < 1.16.2 (#1985)
* Fix modeling teleport packets for entities on clients < 1.16.2
* Fix new entity modeling to handle riding entities
* Fix merge issues from backporting
2025-02-08 12:52:24 -05:00
ManInMyVan 864e9de3e8 fix #1948 2025-02-05 16:57:46 -07:00
ManInMyVan 68b4fa7805 fix SprintE false 2025-02-05 16:43:38 -07:00
ManInMyVan c7e1fda7bb correct checking water for in sprint checks 2025-02-05 16:20:25 -07:00
ManInMyVan 6c42bdcd4e MC152728 was unfixed 2025-02-05 15:31:29 -07:00
Ty_Regotly bdd8225d7c Merge branch 'GrimAnticheat:2.0' into 2.0 2025-02-05 19:41:43 +08:00
Ty_Regotly 439cbc6db3 Correct some translation errors, and update the time (#1996)
* Update de.yml

* Update en.yml

* Update es.yml

* Update fr.yml

* Update it.yml

* Update ja.yml

* Update nl.yml

* Update pt.yml

* Update ru.yml

* Update tr.yml

* Update zh.yml
2025-02-05 11:35:21 +00:00
Ty_Regotly d6a36fcea7 Merge branch '2.0' into 2.0 2025-02-05 15:31:35 +08:00
ManInMyVan 652b66202d Merge pull request #1997 from TrollsterCooleg/2.0
Make the placeholders persist
2025-02-04 21:03:11 -07:00
TrollsterCooleg 9f031e638a Make the placeholders persist 2025-02-04 21:54:30 -06:00
ManInMyVan 45da02e7c0 check slot 2025-02-04 20:21:12 -07:00
ManInMyVan 68a04d05f8 hopefuly fix errors with mitigate-desync-noslow 2025-02-04 17:29:08 -07:00
Ty_Regotly dce77cfdba Update zh.yml 2025-02-04 08:34:46 +08:00
Ty_Regotly 31444ef010 Update tr.yml 2025-02-04 08:15:16 +08:00
Ty_Regotly f5c3fe6669 Update ru.yml 2025-02-04 08:15:08 +08:00
Ty_Regotly 8a75b40695 Update pt.yml 2025-02-04 08:14:56 +08:00
Ty_Regotly 210d756a2d Update nl.yml 2025-02-04 08:14:47 +08:00
Ty_Regotly cc65b3cc2c Update ja.yml 2025-02-04 08:14:34 +08:00
Ty_Regotly d77b073b10 Update it.yml 2025-02-04 08:14:25 +08:00
Ty_Regotly 421acef99a Update fr.yml 2025-02-04 08:14:16 +08:00
Ty_Regotly 9af21596ef Update es.yml 2025-02-04 08:14:06 +08:00
Ty_Regotly 0603c72c89 Update en.yml 2025-02-04 08:13:51 +08:00
Ty_Regotly 106a1d2f6a Update de.yml 2025-02-04 08:13:41 +08:00
ManInMyVan e329171b11 add check-for-updates to all config files 2025-02-03 15:15:46 -07:00
SamB440 b8121543ee Add setting for checking for updates on startup (implements #1995) 2025-02-03 19:42:49 +00:00
SamB440 70cf56fad6 Stop paper taking 10 years to remap the plugin 2025-02-03 19:33:20 +00:00
SamB440 f88a114e0e Bump version 2025-02-01 15:17:30 +00:00
SamB440 ff888f8c73 Kick players if a transaction error occurs 2025-01-31 20:28:14 +00:00
SamB440 66a250eb9e Maybe fix flint and steel prediction (fixes #1991) 2025-01-31 20:06:57 +00:00
SamB440 3c56ba9880 Support creaking hitbox (fixes #1986) 2025-01-31 19:08:43 +00:00
SamB440 514a48e508 Update Gradle wrapper 2025-01-31 19:05:53 +00:00
SamB440 32b66cb4ff Fix checking for elytra on servers older than 1.21.2 2025-01-31 19:01:59 +00:00
SamB440 057de4d4e2 Update shadow plugin 2025-01-31 18:48:31 +00:00
ManInMyVan 081e2d3b2b fix resin hitbox
closes #1982
2025-01-30 19:17:28 -07:00
SamB440 856a51e574 Bump version 2025-01-30 21:35:29 +00:00
SamB440 a4786a16c0 Exempt TRIAL_SPAWNER on fastbreak (#1962) as temp-fix 2025-01-30 21:22:43 +00:00
SamB440 c904f14c7b Use Component instead of String 2025-01-30 21:19:54 +00:00
ManInMyVan 896cf12b71 patch civ 2025-01-29 16:02:04 -07:00
ManInMyVan 1506c97ffc fix comment 2025-01-29 07:56:20 -07:00
ManInMyVan 9107586fc1 assume cooldown is full on 1.8 servers 2025-01-28 19:44:24 -07:00
ManInMyVan bc96460eb3 RotationBreak
closes #1196
2025-01-28 17:12:53 -07:00
ManInMyVan 94705fcd09 why are we ticking velocity on duplicates? 2025-01-28 12:47:27 -07:00
Axionize 7ae935f5e3 Revert "More Accurate Position Reach Modeling for MC clients < 1.16.2 (#1964)" (#1980)
This reverts commit 6d06b9b559.
2025-01-28 05:55:36 -05:00
Axionize 6d06b9b559 More Accurate Position Reach Modeling for MC clients < 1.16.2 (#1964)
* Stop using server-side tracked position when attempting to account for teleports not always moving entity client side; expand from client area instead

* Seperate getting possible locations and possible hitbox to reduce how often expandNonRelative() needs to be called

* Add documention explaining getPossibleLocationCombined() and getPossibleHitboxCombined()

* Update documentation formatting
2025-01-28 05:47:59 -05:00
SamB440 bae421ff27 Merge pull request #1976 from Packsolite/project/add-editorconfig
Add .editorconfig
2025-01-27 18:38:46 +00:00
ManInMyVan f81743e07f Merge pull request #1975 from Packsolite/config/ignore-laby-mod-brand
Ignore labymod client brand by default
2025-01-27 09:17:54 -07:00
Packsolite b0e4693f2b Add .editorconfig 2025-01-27 16:55:54 +01:00
Packsolite e569483f63 Ignore labymod client brand 2025-01-27 16:18:18 +01:00
ManInMyVan 164d16dce9 fix warns from TrackerData 2025-01-26 15:50:56 -07:00
SamB440 a504b8f595 Fix viaversion respawn metadata handling (fixes #1965) 2025-01-26 19:45:22 +00:00
ManInMyVan 0a9ea97aa6 cleanup 2025-01-25 14:34:54 -07:00
ManInMyVan 91e281514b remove random newline 2025-01-25 14:22:45 -07:00
ManInMyVan a03c8bbdbd support placeholderapi placeholders in custom kick messages 2025-01-25 14:21:23 -07:00
ManInMyVan 22074dc228 revert renaming compensatedWorld and compensatedEntities 2025-01-25 14:17:15 -07:00
ManInMyVan 3a40ba8b29 "small" refactor 2025-01-25 12:34:22 -07:00
ManInMyVan 0d84b4e958 patch drop noslow 2025-01-24 19:16:06 -07:00
ManInMyVan 098399f754 don't allow negative kb on 1.9+ 2025-01-24 19:12:30 -07:00
ManInMyVan 334a356446 some keepsprint patch fixes 2025-01-24 17:59:05 -07:00
SamB440 acac69e750 Account for new 1.21.2 collision requirement 2025-01-24 19:53:13 +00:00
SamB440 f8aa54855d Update compatibility notice 2025-01-24 19:48:22 +00:00
ManInMyVan 7d928d581f patch keepsprint 2025-01-23 17:59:46 -07:00
SamB440 31394f472f Fix listening to brands on modern clients 2025-01-23 16:07:24 +00:00
SamB440 f721b1850c Fix the plugin not loading lol 2025-01-23 16:02:56 +00:00
ManInMyVan 4419646f11 customizable disconnect messages 2025-01-22 19:50:40 -07:00
Axionize 40bbd2eb2e Stop using server-side tracked position when attempting to account for teleports not always moving entity client side; expand from client area instead (#1902) 2025-01-22 01:27:16 -05:00
Axionize 6cfe71da9b Refactor HitboxData.getBlockHitbox() to include isTargetBlock as parameter (#1957)
Also fixes a rare NPE in LOSP
2025-01-22 00:45:27 -05:00
ManInMyVan 393357d9f6 revert recent BadPacketsN changes 2025-01-20 17:26:20 -07:00
ManInMyVan dcf0c73005 refactoring 2025-01-20 15:57:23 -07:00
ManInMyVan 856ec6c655 remove DebugHandler check name
I don't this is used
2025-01-20 15:42:08 -07:00
ManInMyVan 54a10f77db remove (Prediction) from NoSlow 2025-01-20 15:41:28 -07:00
ManInMyVan 0f50bde4db Merge pull request #1959 from spring-dependency-management/explosion-fix
Fix explosion false when dead
2025-01-20 15:25:33 -07:00
spring-dependency-management d7368ceba6 Fix explosion false when dead 2025-01-20 22:24:02 +00:00
ManInMyVan 1e8fc587af always poll 2025-01-20 12:27:52 -07:00
ManInMyVan 75bcac7a49 don't check item usage in MultiActionsC/D 2025-01-19 14:30:33 -07:00
ManInMyVan 111cc7aafd finally use that util I added a while ago 2025-01-19 12:45:11 -07:00
AoElite 924dcf9014 update elytra feature & use switches 2025-01-19 03:03:31 -05:00
AoElite 63aa1ed632 update feature manager 2025-01-19 03:00:35 -05:00
ManInMyVan eda4dc7236 actually fix it 2025-01-18 20:21:32 -07:00
ManInMyVan acfef61eac actually fix it this time 2025-01-18 19:53:39 -07:00
ManInMyVan 85e1e20e41 fix BadPacketsX false 2025-01-18 19:12:28 -07:00
ManInMyVan fe09db6636 I hate vehicles 2025-01-18 19:05:23 -07:00
ManInMyVan b6a79b74b6 this also applies to horses 2025-01-18 18:45:39 -07:00
ManInMyVan 9f305370f8 don't register PacketOrderD twice 2025-01-18 18:37:59 -07:00
ManInMyVan b0df15cab0 fixes 2025-01-18 18:31:56 -07:00
ManInMyVan 316711f796 rename PacketOrderO to PacketOrderD 2025-01-18 18:31:29 -07:00
ManInMyVan 8718a7e140 add missing PacketOrder entries 2025-01-18 18:31:29 -07:00
ManInMyVan 9930adb2a8 revert renaming TransactionOrder 2025-01-18 18:31:29 -07:00
ManInMyVan 8d7abe318e spectator mode is dumb 2025-01-18 18:31:29 -07:00
ManInMyVan 23547bd4ab include more information in verbose 2025-01-18 18:31:29 -07:00
ManInMyVan 02378b9385 don't check the same value twice 2025-01-18 18:31:29 -07:00
ManInMyVan f818e59021 fix 1.21.2+ PacketOrderH false 2025-01-18 18:31:29 -07:00
ManInMyVan 1c8a91b027 don't register PacketOrderProcessor twice 2025-01-18 18:31:28 -07:00
ManInMyVan cf37307bcb 1.21.2 2025-01-18 18:31:28 -07:00
ManInMyVan cd243008cd fix wrongly resolved merge conflict 2025-01-18 18:31:28 -07:00
ManInMyVan 9b63c5117e fix falses 2025-01-18 18:31:28 -07:00
ManInMyVan 1ed1c70070 remove PacketOrderO
depends on too many factors
2025-01-18 18:31:28 -07:00
ManInMyVan 24d7cfeff9 fix more falses 2025-01-18 18:31:28 -07:00
ManInMyVan 5c149495e0 fix falses 2025-01-18 18:31:28 -07:00
ManInMyVan 4a78268389 fix false when swapping offhand items 2025-01-18 18:31:28 -07:00
ManInMyVan 367941a418 fix false when dropping items 2025-01-18 18:31:27 -07:00
ManInMyVan f1aa07fae3 only setback on item use 2025-01-18 18:31:27 -07:00
ManInMyVan b21e1432d1 remove invalid variable default 2025-01-18 18:31:27 -07:00
ManInMyVan a259ae5dc3 add remaining entity actions to PacketOrderProcessor 2025-01-18 18:31:27 -07:00
ManInMyVan 98dbc8f6dd rename invalidSlots to invalid 2025-01-18 18:31:27 -07:00
ManInMyVan dfc3c6eafe add PacketOrderO and PacketOrderP 2025-01-18 18:31:27 -07:00
ManInMyVan 85ed4bac2e add PacketOrderN 2025-01-18 18:31:27 -07:00
ManInMyVan 75c7103cb5 Add PacketOrderM 2025-01-18 18:31:26 -07:00
ManInMyVan 3163e5e8e8 fix a noslow 2025-01-18 18:31:26 -07:00
ManInMyVan efcae7bea5 rename exempt-digging to exempt-placing-while-digging in PacketOrderI
and make it work
2025-01-18 18:31:26 -07:00
ManInMyVan 563ec57e66 rename PacketOrderM to PacketOrderA 2025-01-18 18:31:26 -07:00
ManInMyVan 8993b77374 add PacketOrderM 2025-01-18 18:31:26 -07:00
ManInMyVan af1c592266 use PacketOrderProcessor in PacketOrderK 2025-01-18 18:31:26 -07:00
ManInMyVan 910ea942fb rewrite 2025-01-18 18:31:21 -07:00
ManInMyVan 2e45b1f74b fix falses 2025-01-18 18:28:45 -07:00
ManInMyVan 7b7a3f0d60 don't cancel the tick 2025-01-18 18:28:45 -07:00
ManInMyVan d94a3f6e86 more PacketOrderC stuff 2025-01-18 18:28:45 -07:00
ManInMyVan 51ac086ce7 fixes 2025-01-18 18:28:45 -07:00
ManInMyVan 92cc9a32b4 oops 2025-01-18 18:28:45 -07:00
ManInMyVan 6b0708ed80 fix falses 2025-01-18 18:28:45 -07:00
ManInMyVan 5de181ccad Add PacketOrderK 2025-01-18 18:28:45 -07:00
ManInMyVan ae71e204d8 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
2025-01-18 18:28:44 -07:00
ManInMyVan 554063f82b exemptBreaking option in PacketOrdlerL 2025-01-18 18:28:40 -07:00
ManInMyVan 56df4e122f fix some PacketOrderF falses 2025-01-18 18:27:27 -07:00
ManInMyVan 3715591e37 Add PacketOrderL 2025-01-18 18:27:27 -07:00
ManInMyVan f5a67a48ea Check entity in PacketOrderC 2025-01-18 18:27:27 -07:00
ManInMyVan 95830492c4 Add PacketOrderJ 2025-01-18 18:27:27 -07:00
ManInMyVan 850e1da3d4 Add PacketOrderI 2025-01-18 18:27:27 -07:00
ManInMyVan 8b27dcbb52 Add PacketOrderH 2025-01-18 18:27:27 -07:00
ManInMyVan 73a688b6f1 these are already packet checks 2025-01-18 18:27:26 -07:00
ManInMyVan 26a8ec8cf1 Add PacketOrderG 2025-01-18 18:27:26 -07:00
ManInMyVan 83d20afa12 add PacketOrderF 2025-01-18 18:27:26 -07:00
ManInMyVan 165a6a591c add PacketOrderE 2025-01-18 18:27:26 -07:00
ManInMyVan 26367a5eb9 PacketOrder check catagory 2025-01-18 18:27:26 -07:00
SamB440 783240c06f Merge pull request #1952 from Cyramek/fix-fastbreak
account for fastbreak flag cancellation
2025-01-18 17:36:49 +00:00
cyramek fbcad3e605 account for fastbreak flag cancellation 2025-01-18 18:35:52 +01:00
SamB440 10c1a1350c Warn about plugin incompatibility 2025-01-18 14:50:04 +00:00
ManInMyVan 69875008c3 exempt 1.8 players from elytra checks 2025-01-16 19:37:52 -07:00
ManInMyVan e39eb89f59 fix possible BadPacketsQ npe 2025-01-16 19:35:15 -07:00
ManInMyVan 71015ec3c7 Add VehicleD 2025-01-16 17:10:12 -07:00
ManInMyVan 09b8071f5b make VehicleC a PacketCheck 2025-01-16 16:49:45 -07:00
ManInMyVan e011b2dbbd Vehicle check catagory 2025-01-16 16:37:21 -07:00
ManInMyVan 7208842b0c perf 2025-01-16 16:24:50 -07:00
ManInMyVan 2830856812 per check nosetback and nomodifypacket permissions 2025-01-16 16:24:34 -07:00
ManInMyVan 50f9b6ecbd fix ElytraH name 2025-01-15 21:55:02 -07:00
ManInMyVan f31182419f fix pose desync 2025-01-15 18:58:31 -07:00
ManInMyVan 918dbf28ce ElytraF to I 2025-01-15 18:08:24 -07:00
ManInMyVan 5c73e7d0f1 BadPacketsD description 2025-01-15 17:05:34 -07:00
ManInMyVan 950d7a7a86 add ElytraE 2025-01-15 16:46:39 -07:00
ManInMyVan 0f068c763f add ElytraD 2025-01-15 16:46:25 -07:00
ManInMyVan 32b799735a add ElytraC 2025-01-15 16:36:54 -07:00
ManInMyVan fba015809f fix #1932 2025-01-13 19:39:43 -07:00
ManInMyVan 917d115a54 |= is a thing 2025-01-13 19:21:16 -07:00
ManInMyVan bf2de308ed fix #1949 2025-01-13 19:02:32 -07:00
ManInMyVan 0d278ed756 Merge pull request #1950 from twcult/patch-1
Update CrashH.java
2025-01-13 15:21:58 -07:00
twcult 99cab0a346 Update CrashH.java 2025-01-14 01:04:17 +03:00
SamB440 b83c04ddca Count invalid packets in TickTimer 2025-01-13 20:55:47 +00:00
SamB440 83fba052a5 Fix AimModulo360 falses when entering vehicle (fixes #1942) 2025-01-13 17:33:00 +00:00
SamB440 66438dd0c0 Fix 1.9+ server check for BadPacketsH, fixes #1946 2025-01-13 17:21:09 +00:00
SamB440 470776e49e Don't alert for BadPacketsR 2025-01-12 13:03:01 +00:00
ManInMyVan c1e02d5731 support glider component 2025-01-11 19:06:58 -07:00
ManInMyVan 9303ca77bb &= is a thing 2025-01-11 17:47:55 -07:00
ManInMyVan f2043ff12e check for releasing jump in ElytraB 2025-01-11 17:45:44 -07:00
ManInMyVan 9fc6e2f696 fix WrongBreak false 2025-01-10 20:39:14 -07:00
ManInMyVan 6fb84703d0 use flagAndAlert 2025-01-10 20:37:01 -07:00
ManInMyVan 35ca5dcfe9 SprintF 2025-01-10 20:34:56 -07:00
ManInMyVan 77d07fb444 patch sideways sprint 2025-01-10 19:57:42 -07:00
ManInMyVan dbce0b70e5 patch spigot antispam bypass 2025-01-10 19:35:33 -07:00
ManInMyVan 83bb7eaf64 Merge pull request #1938 from twcult/2.0
Remove method `canSkipTicks()` inlining
2025-01-10 18:59:31 -07:00
twcult ec0b723ae9 Update Reach.java 2025-01-11 04:52:42 +03:00
ManInMyVan e2049c7998 exempt redstone in PositionBreakA 2025-01-10 16:30:55 -07:00
ManInMyVan 8968acf214 pass verbose to flag() 2025-01-10 07:56:57 -07:00
ManInMyVan 405b679d68 Merge pull request #1937 from MatrixU5er/patch-1
Better Chinese translation
2025-01-09 19:34:01 -07:00
ManInMyVan dcc134ef37 add elytra to punishments config 2025-01-09 19:30:05 -07:00
MatrixU5er b356c1d162 Better Chinese translation
Added new Chinese translations and made some changes to make them easier to understand
2025-01-10 09:59:04 +08:00
ManInMyVan c4f224f406 add 2 elytra checks 2025-01-09 18:37:59 -07:00
SamB440 10ff3cefb5 Merge pull request #1936 from Penguin285/Penguin285-patch-1
Fixed Client Brands not sending properly
2025-01-09 16:30:42 +00:00
Penguin285 5c80e28c7d Fixed Client Brands not sending properly
The previous code was checking if the player had verbose enabled, instead of checking if they had brands enabled
2025-01-09 16:09:08 +00:00
AoElite bdb1330706 bump api 2025-01-08 00:37:44 -05:00
AoElite b30f4e18da Merge pull request #1930 from spring-dependency-management/badpacketsc-spectator-false
Fix badpacketsC false when in spectator
2025-01-07 22:45:41 -05:00
spring-dependency-management 7563b53fa1 Fix spectator false 2025-01-08 02:54:52 +00:00
AoElite f852f16c9c implement sendMessage 2025-01-07 11:54:34 -05:00
AoElite de730d73c0 implement more new API additions 2025-01-07 11:27:44 -05:00
AoElite dbe72a7fbf update API implementation 2025-01-07 06:21:56 -05:00
SamB440 c1225cb920 Brand handling improvements 2025-01-04 17:19:09 +00:00
ManInMyVan 17927c11bf remove grim.brand.exempt because it causes npes 2025-01-04 10:13:41 -07:00
SamB440 66f6bd72d0 More Jabba 17 cleanup 2025-01-03 18:29:54 +00:00
ManInMyVan 6816df7a93 fix #1921 2025-01-03 10:53:17 -07:00
SamB440 7e0699d1bb Merge pull request #1903 from matsu1213/fix-bpn-setbacks
Fix BadPacketsN setbacks for relative teleports
2025-01-03 14:58:41 +00:00
ManInMyVan 1ce5a530ff small optimization for older servers 2025-01-02 12:53:21 -07:00
ManInMyVan 61e506437b add methods for nms item usage 2025-01-02 12:41:57 -07:00
ManInMyVan a23e1a10f4 add /grim brand and grim.brand.enable-on-join 2025-01-02 11:46:16 -07:00
ManInMyVan d1f6a47519 add verbose toggle messages to messages.yml 2025-01-02 11:46:04 -07:00
ManInMyVan 4cb6de2cb1 remove unused import 2025-01-02 11:44:52 -07:00
ManInMyVan 000758e7f1 include action in invalidbreak verbose 2025-01-02 11:12:34 -07:00
ManInMyVan 57157d068e add grim.brand.exempt 2025-01-02 11:04:22 -07:00
ManInMyVan 368db15026 make BadPacketsL stricter 2025-01-02 11:00:23 -07:00
ManInMyVan a0b1d290b5 Merge pull request #1919 from calcastor/invalidbreak-1.7
Exempt block face id 255 for 1.7.10- players in InvalidBreak
2025-01-02 10:56:53 -07:00
ManInMyVan e75b987a6e check action 2025-01-02 10:56:40 -07:00
ManInMyVan 7955563931 make PositionBreakB stricter for 1.7 2025-01-02 10:54:37 -07:00
matsu1213 cd9e22aad4 Use getMask 2025-01-02 23:17:24 +09:00
BT (calcastor/mame) cf66554afe Exempt block face id 255 for 1.7.10- players in InvalidBreak 2025-01-02 00:33:09 -08:00
ManInMyVan a179f3e625 fix #1918 2025-01-01 19:15:36 -07:00
ManInMyVan fe96f848ad import DiggingAction 2025-01-01 13:36:28 -07:00
ManInMyVan 37b12ac56b fix PositionBreakA falses 2025-01-01 13:10:12 -07:00
ManInMyVan 6846e2d6a3 small refactor 2024-12-31 11:46:10 -07:00
ManInMyVan 5da77e2aa5 Merge pull request #1917 from 483378/2.0
BadPacketsV: fix >= 1.21.2 false flag
2024-12-31 11:01:02 -07:00
483378 7ac3d4104f BadPacketsV: make check stricter again for 1.8 players 2024-12-31 18:58:05 +01:00
SamB440 1c1f1d7031 Fix redstone wall torch powered state 2024-12-31 17:40:11 +00:00
SamB440 47a26f86dc Merge pull request #1909 from caneeeeee/adjust-german-translation
Adjust German translation
2024-12-31 17:02:30 +00:00
483378 9e054c2b6c BadPacketsV: fix >= 1.21.2 false flag 2024-12-31 17:34:40 +01:00
ManInMyVan c685c47d16 exempt spectators in FarPlace and FarBreak 2024-12-30 20:21:53 -07:00
ManInMyVan b968bd98f3 add PositionBreakB 2024-12-30 18:36:34 -07:00
ManInMyVan 5902fec4a8 add PositionBreak 2024-12-30 18:32:50 -07:00
ManInMyVan 2171a57757 Merge pull request #1916 from jonesdevelopment/feat/remove-log4j-checks
Remove ExploitA since it's useless and broken
2024-12-30 17:11:03 -07:00
Jones 882990fe84 Remove ExploitA since it's useless and broken 2024-12-31 00:54:22 +01:00
ManInMyVan c1e070e7ba decrease movement threshold leniency for 1.21.2+ 2024-12-30 16:09:20 -07:00
ManInMyVan 7e879aab9d add InvalidBreak 2024-12-30 15:59:43 -07:00
ManInMyVan 08a73ba2c6 add AirLiquidBreak description 2024-12-30 15:53:31 -07:00
ManInMyVan 411d3577e8 add description for NoSwingBreak 2024-12-30 15:51:44 -07:00
ManInMyVan a24f6ac26c add FarBreak 2024-12-30 15:51:12 -07:00
ManInMyVan 58e05442fe add NoSwingBreak 2024-12-30 15:41:07 -07:00
ManInMyVan c79928a8c8 Add MultiBreak 2024-12-30 15:30:32 -07:00
ManInMyVan 994990e4df Merge pull request #1530 from ManInMyVan/bp3
Add BadPacketsX
2024-12-30 14:39:38 -07:00
ManInMyVan f6b55d3ca5 Add BadPacketsX 2024-12-30 14:37:30 -07:00
ManInMyVan 649ffe0f71 add description for BadPacketsH 2024-12-30 14:07:27 -07:00
ManInMyVan f861181959 Merge pull request #1915 from AbdisKiosk/fix-nosuchmethoderror
Fix nosuchmethoderror in grimversion in old minecraft versions
2024-12-30 14:05:43 -07:00
ManInMyVan bc2ebf7222 rename BadPacketsX to AirLiquidBreak 2024-12-30 14:04:30 -07:00
ManInMyVan ac204c99b2 rename BadPacketsZ to WrongBreak 2024-12-30 14:02:55 -07:00
ManInMyVan 606a89ea61 make "FastBreak" "Break" in punishments.yml 2024-12-30 13:59:56 -07:00
ManInMyVan 4340962786 fix sprint check names 2024-12-30 13:27:08 -07:00
ManInMyVan e2f22682bd move sprint checks to their own package 2024-12-30 13:22:35 -07:00
ManInMyVan f4ab6de6af move timer checks to their own package 2024-12-30 13:22:01 -07:00
ManInMyVan 7bb1f01f28 cleanup 2024-12-30 13:17:21 -07:00
SamB440 8d7217439f Make PlayerBaseTick static to reduce allocations, make Column a record 2024-12-30 17:59:50 +00:00
SamB440 3308b4d7e3 Let TickTimer setback 2024-12-30 17:17:36 +00:00
SamB440 f6513b5537 Reduce reach uncertainty for 1.21.2+ end tick 2024-12-30 17:07:23 +00:00
SamB440 20217fd40b Avoid an allocation here 2024-12-30 17:05:40 +00:00
SamB440 6c5ff42045 Fix Reach verbose 2024-12-30 17:02:41 +00:00
SamB440 1e1a176b73 Split reach missed hitbox into hitboxes 2024-12-30 16:57:45 +00:00
SamB440 ba85055e5a Code cleanup 2024-12-30 16:00:57 +00:00
AbdisKiosk caed9e1850 Fix nosuchmethoderror in grimversion 2024-12-30 15:20:29 +01:00
SamB440 5acbb1d514 Fix inside block epsilon thing 2024-12-30 01:15:19 +00:00
ManInMyVan 5532ae0c34 fix falses 2024-12-29 15:59:53 -07:00
ManInMyVan bc276d0ca9 fix #1801 2024-12-29 14:39:53 -07:00
SamB440 251f1c13a9 revert this because im an idiot and didn't notice it's changing a different velocity 2024-12-29 21:27:09 +00:00
SamB440 9322d5d7b4 refactor and mention mojang broke movement here 2024-12-29 21:25:31 +00:00
ManInMyVan cf8f2d04f6 fix more falses on legacy versions 2024-12-29 14:08:45 -07:00
ManInMyVan dc8329e2cd fix clicking on trapdoors with blocks causing falses on legacy version 2024-12-29 13:34:16 -07:00
ManInMyVan 4351fb0531 fix falses in spectator mode 2024-12-29 12:57:07 -07:00
ManInMyVan 3b9fcefae0 tiny cleanup 2024-12-29 12:40:01 -07:00
ManInMyVan e90601f2b9 use canSkipTicks in BadPacketsV 2024-12-29 12:14:23 -07:00
ManInMyVan 5fbbabadf7 don't count stop sprinting as a start sprinting packet 2024-12-28 19:48:46 -07:00
ManInMyVan 105f0eceab small cleanup 2024-12-28 19:41:32 -07:00
ManInMyVan 8c15640a44 move FastBreak to breaking package 2024-12-28 19:39:42 -07:00
ManInMyVan 51b6141f91 Merge pull request #1485 from ManInMyVan/BadPackets1
Add BadPacketsV
2024-12-28 19:36:56 -07:00
ManInMyVan a4624f6907 add BadPacketsV description 2024-12-28 19:36:26 -07:00
ManInMyVan 3ac459d42c get offset after checking isChecked 2024-12-28 18:10:55 -07:00
ManInMyVan 726f6f84bf use flagAndAlert in ExplosionHandler 2024-12-28 18:02:43 -07:00
ManInMyVan c880dbb4ce use flagAndAlert a bit more 2024-12-28 17:58:39 -07:00
ManInMyVan 097b471aed add SprintE 2024-12-28 15:14:12 -07:00
ManInMyVan 069c503bda rename NoSlowB-E to SprintA-D
they aren't really "NoSlow" cheats
2024-12-28 13:42:13 -07:00
ManInMyVan b7c8ca1683 add MultiActions to tr.yml and ja.yml 2024-12-28 13:40:20 -07:00
ManInMyVan 27f4f34b16 fix falses 2024-12-28 12:44:18 -07:00
caneeeeee d388d3f5db Adjust German translation: preserve placeholders and improve contextual accuracy 2024-12-28 15:14:29 +01:00
ManInMyVan 744be32389 Merge pull request #1908 from GrimAnticheat/fix/sculk-vein-hitbox
Fix Sculk Vein hitbox
2024-12-27 19:53:27 -07:00
You 8c97274929 Fix Sculk Vein hitbox 2024-12-27 21:40:42 -05:00
AoElite a630dbe028 Added /grim dump. A command that dumps useful debugging information into a link. 2024-12-26 01:54:51 -05:00
ManInMyVan 3e42fe9d5e remove random comment 2024-12-25 22:42:12 -07:00
AoElite 06fad2ecaf Added /grim version command. Uses Modrinth API to check if Grim is up to date. 2024-12-26 00:36:31 -05:00
ManInMyVan 3ddc1e846a allow usage of grim variables outside of grim (PAPI expansion)) 2024-12-25 20:08:25 -07:00
ManInMyVan af6c859b16 support for &x&r&r&g&g&b&b hex codes 2024-12-24 19:30:42 -07:00
ManInMyVan d138d0d602 remove inaccurate messages.yml header 2024-12-24 19:23:44 -07:00
ManInMyVan 70d0fa96c2 fix hex codes 2024-12-24 19:11:09 -07:00
ManInMyVan 133e7dc490 this is also stable 2024-12-24 18:38:16 -07:00
ManInMyVan 4cb0a46797 this is stable 2024-12-24 18:37:10 -07:00
ManInMyVan 4298031d3f fix fluid hitbox for pre 1.13 players 2024-12-24 14:41:53 -07:00
ManInMyVan f4c43735f7 fix getEyeHeight() for 1.8 players 2024-12-24 14:39:33 -07:00
ManInMyVan 61f90fe721 fix reach for lily pads and buckets 2024-12-24 14:19:08 -07:00
ManInMyVan 431200c855 fix viaversion snow 2024-12-24 12:45:12 -07:00
ManInMyVan 481a115ba1 fix fluid placement distance 2024-12-24 11:39:32 -07:00
SamB440 b0f6e49109 Remove useless semicolon 2024-12-24 18:30:12 +00:00
SamB440 122ad4a93c Make hasSentPreWavePacket atomic 2024-12-24 18:29:19 +00:00
ManInMyVan 464e61b6b0 fix some issues with fluid placements on pre-1.13 2024-12-24 10:36:27 -07:00
matsu1213 1405faa391 Fix BadPacketsN setbacks for relative teleports 2024-12-24 12:46:37 +09:00
SamB440 1f93dff26c Update Gradle wrapper 2024-12-23 17:22:42 +00:00
ManInMyVan 002b027e2b don't apply changes to tags that don't exist in the player's version 2024-12-22 20:25:01 -07:00
ManInMyVan 2a5b25e927 oops 2024-12-22 19:33:46 -07:00
ManInMyVan 597e3ba820 Check lastVehicleSwitch in isTickingReliablyFor (#1876) 2024-12-22 21:01:26 -05:00
SamB440 20234319e6 Update Gradle wrapper 2024-12-22 17:26:53 +00:00
ManInMyVan 8b76fd36d7 fix falses with custom mining tags 2024-12-20 17:10:04 -07:00
ManInMyVan 6ca375ff61 Merge pull request #1895 from jonesdevelopment/fix/variable-replacements
Fix variables never actually updating
2024-12-20 13:53:47 -07:00
Jones 1836b14d5d The Grim version is also static 2024-12-20 21:49:49 +01:00
Jones 618b6aca24 Only change static variables 2024-12-20 21:49:22 +01:00
ManInMyVan 4a45918971 fix pale moss carpets 2024-12-20 13:02:48 -07:00
ManInMyVan f8af107a1a Merge pull request #1896 from ManInMyVan/fix/snow
fix snow collisions
2024-12-20 12:19:24 -07:00
ManInMyVan 94491d293b fix snow collisions 2024-12-20 12:11:44 -07:00
Jones 49debf6cd0 Fix variables never actually updating 2024-12-20 18:21:37 +01:00
ManInMyVan c87ae3af8b rename NoFallA and NoFallB classes to match check name 2024-12-19 18:00:34 -07:00
ManInMyVan 423f2d0711 remove redundant configName declarations 2024-12-19 17:54:36 -07:00
AoElite 9a0ec5d010 update grim api 2024-12-19 04:46:36 -05:00
ManInMyVan 60ed674228 Merge pull request #1894 from ManInMyVan/bump-packetevents
bump packetevents
2024-12-18 23:19:45 -07:00
ManInMyVan 8bec79abc6 bump packetevents 2024-12-18 23:09:04 -07:00
ManInMyVan 0ee4b2551f Merge pull request #1893 from ManInMyVan/fix/autoblock
patch autoblock in 1.8
2024-12-18 20:43:13 -07:00
Axionize ad3cbd739a Fix AirLiquidPlace falses (and BadPacketsX false) (#1822)
* Add new Data classes to see recently modified blocks
* Fix AirLiquidPlace false
* Cleanup AirLiquidPlace
* Finish documenting all edge cases that can false AirLiquidPlace and fixing them
* Apply Style Changes From Code Review
2024-12-18 22:21:53 -05:00
ManInMyVan d9718b308f patch autoblock in 1.8 2024-12-18 17:48:01 -07:00
AoElite 4b03892c86 Update README.md
fix typo
2024-12-18 01:52:52 -05:00
AoElite 7668ddb6d6 Update README.md
add Java 17 warning
2024-12-17 15:43:48 -05:00
AoElite 33582cd417 Update README.md
add installation notes
2024-12-17 14:59:47 -05:00
AoElite 2474c550cc Update README.md 2024-12-17 14:49:52 -05:00
SamB440 4f8357f5a1 Bump version (2.3.69) 2024-12-17 17:59:58 +00:00
SamB440 b4ac002779 Warn about viabackwards and promote placement config warn to error 2024-12-17 16:01:46 +00:00
SamB440 f04cadb38d Fix BadPacketsE with viabackwards 2024-12-17 15:35:21 +00:00
ManInMyVan 79ec178845 Merge pull request #1887 from ManInMyVan/localized-desciptions
allow localizing check descriptions
2024-12-16 16:10:47 -07:00
ManInMyVan a8da7dde72 allow localizing check descriptions 2024-12-16 15:49:18 -07:00
ManInMyVan 576a67502b Merge pull request #1621 from ManInMyVan/minimessage
Add MiniMessage And PlaceHolderAPI Support
2024-12-16 15:35:01 -07:00
SamB440 eb72a7c86d Add Camel simulation support 2024-12-16 21:40:31 +00:00
Axionize 5d486a5707 Merge pull request #1824 from Axionize/fix-modern-client-legacy-server-walls
Fix Modern Client + Legacy Server Walls
2024-12-15 17:12:06 -05:00
Axionize 9975d1a6bf Merge pull request #1886 from Axionize/fix/pink-petals-ccb-size
Fix IndexOutofBoundsException when interacting with Pink Petals with 3 or more flowers
2024-12-15 17:02:35 -05:00
Axionize dd74dc9737 Fix IndexOutofBoundsException when interacting with Pink Petals with 3 or more flowers 2024-12-15 16:52:02 -05:00
SamB440 bf37add382 Merge pull request #1880 from Currypan1229/maint/yml-cu-853275982
Fix namespace of punishments.yml for japanese
2024-12-15 19:09:48 +00:00
Currypan1229 432a0aed02 Fix namespace of punishments.yml for japanese 2024-12-16 04:07:30 +09:00
ManInMyVan 6a1a5f81ed add UNKNOWN branch to BadPacketsP 2024-12-13 13:59:05 -07:00
ManInMyVan a620149a93 Merge pull request #1860 from ManInMyVan/bpP
show click type name and use enhanced switch statements in BadPacketsP
2024-12-13 13:04:46 -07:00
ManInMyVan 4c21c11484 Merge pull request #1842 from ManInMyVan/descriptions
Add descriptions to checks
2024-12-12 18:39:15 -07:00
ManInMyVan ca72cd5997 Add descriptions to some checks 2024-12-12 18:36:26 -07:00
ManInMyVan 3952600032 Merge pull request #1875 from ManInMyVan/don't-check-skippedTickInActualMovement
don't check skippedTickInActualMovement when handling slot changes
2024-12-11 22:11:41 -07:00
ManInMyVan d42bc4bec7 Merge pull request #1879 from ManInMyVan/deprecations
fix some deprecation warnings
2024-12-11 19:34:27 -07:00
ManInMyVan 30a6e7c336 Merge pull request #1878 from ManInMyVan/use-new-java-features
use new java features more
2024-12-11 15:25:13 -07:00
ManInMyVan d82b168cd6 use new java features more 2024-12-10 18:44:02 -07:00
ManInMyVan 284effc237 fix some deprecation warnings 2024-12-09 17:58:30 -07:00
ManInMyVan e97566cd5f and check client version 2024-12-09 16:36:07 -07:00
ManInMyVan 8c2b87f472 don't check skippedTickInActualMovement when handling slot changes 2024-12-09 16:14:33 -07:00
ManInMyVan f3433f3011 Merge pull request #1874 from ManInMyVan/postcheck-to-post
rename PostCheck to Post
2024-12-08 23:13:52 -07:00
ManInMyVan 587b317cb6 rename PostCheck to Post 2024-12-08 20:23:10 -07:00
ManInMyVan febe00e950 Add MiniMessage and PlaceHolderAPI Support 2024-12-08 20:09:59 -07:00
AoElite c7445019f9 Merge pull request #1847 from ManInMyVan/blockbreakcheck
BlockBreakCheck
2024-12-08 21:54:37 -05:00
SamB440 ff1c3043b3 Merge pull request #1871 from ManInMyVan/noslowc&d-1.21.4
check 1.21.4 players in NoSlowC and NoSlowD
2024-12-08 11:35:11 +00:00
ManInMyVan 0b038d38e9 check 1.21.4 players in NoSlowC and NoSlowD 2024-12-07 13:58:56 -07:00
SamB440 b0790af3e1 Update packetevents 2024-12-07 19:42:47 +00:00
SamB440 912939a5f4 Another 1.21.2 fix 2024-12-07 19:33:33 +00:00
SamB440 7d30183af3 Use an identity hash set for synced tags 2024-12-06 20:00:33 +00:00
SamB440 2ac8a86d4f Update ExplosionHandler to account for 1.21.2 changes 2024-12-06 14:57:37 +00:00
AoElite d598ae0057 Merge pull request #1863 from ManInMyVan/fix/multiactionsc-false
fix MultiActionsC false with server opened inventories
2024-12-05 21:25:25 -05:00
ManInMyVan d3fde8025a fix MultiActionsC false with server opened inventories 2024-12-05 17:31:56 -07:00
ManInMyVan 7fe146db05 show click type name and use enhanced switch statements in BadPacketsP 2024-12-04 19:49:53 -07:00
ManInMyVan 227458a633 BlockBreakCheck 2024-12-04 17:30:05 -07:00
ManInMyVan e61fb9b3e4 Add BadPacketsV 2024-12-04 17:25:58 -07:00
AoElite 97abaaf8ad Merge pull request #1846 from Axionize/remove-use-of-var
Remove Usage of Var
2024-12-04 15:36:17 -05:00
SamB440 1f3ac2a174 Merge pull request #1831 from GrimAnticheat/update/1.21.3
1.21.3 update
2024-12-04 13:37:52 +00:00
SamB440 ff0629d0b7 Merging really sucks 2024-12-04 13:36:17 +00:00
SamB440 9936984534 Merge branch '2.0' into update/1.21.3 2024-12-04 13:34:06 +00:00
SamB440 ca56975136 Revert BadPacketsE changes 2024-12-04 13:31:49 +00:00
AoElite 348daf6a52 Merge pull request #1850 from SergioK29/fix-missing-should-cancel-packets
Fix missing shouldModifyPackets
2024-12-04 08:05:46 -05:00
AoElite d67b470ff6 better BadPackets E & R support for 1.21.2+ 2024-12-04 08:00:12 -05:00
SamB440 130f9e1023 Merge pull request #1597 from ManInMyVan/multiactions
Add MultiActions Checks
2024-12-03 22:13:59 +00:00
SamB440 eaac8ad908 Merge pull request #1835 from Axionize/fix-riptide-teams-and-non-pushable
Fix riptide trident attacks on entities that are non-pushable or the same team as the attacker
2024-12-03 21:12:19 +00:00
SamB440 89f8696d88 Merge pull request #1715 from ManInMyVan/elytra-fly
Allow exempting elytras
2024-12-03 18:01:08 +00:00
AoElite 940a1f819f punishment manager performance improvements 2024-12-03 12:07:33 -05:00
AoElite 3f01edba9d fixed paintings not being registered 2024-12-03 11:37:58 -05:00
SergioK29 24409a5771 Fix missing shouldModifyPackets 2024-12-03 14:00:27 +00:00
ManInMyVan 88e0f98241 fix swimming false 2024-12-02 18:11:48 -07:00
SamB440 fde99a7cbf Remove fastutil usage from CorrectingPlayerInventoryStorage 2024-12-02 13:54:46 +00:00
Axionize 1c3929834a Remove usage of var 2024-12-01 17:08:01 -05:00
ManInMyVan 3a839d7240 add parenthesis 2024-12-01 12:51:19 -07:00
SamB440 7737337a86 Don't let setbacks bypass stuck speed 2024-12-01 18:34:52 +00:00
MachineBreaker 88dc6a42a9 Merge pull request #1832 from Axionize/replace-var-with-explicit-types
Make var type in ExploitC explicitly String
2024-12-01 14:34:09 -04:00
MachineBreaker bcc93aab4a Merge pull request #1804 from GrimAnticheat/2.0-optimise-menu-type
Optimise MenuType#getMenuType
2024-12-01 14:30:33 -04:00
SamB440 b88561284c Disable verbose enable-on-join by default even for OPs 2024-12-01 17:38:41 +00:00
SamB440 5fd8230884 Fix timer ping-abuse-limit-threshold 2024-12-01 17:37:19 +00:00
SamB440 ca0fa88a77 Merge pull request #932 from SamB440/fix/BadPacketsG
Reimplement BadPacketsG
2024-12-01 15:01:56 +00:00
SamB440 cbb3c1cc0f Fix BadPacketsG falses & a sneak desync 2024-12-01 14:59:02 +00:00
SamB440 519968b85a Fix BadPacketsG teleport status 2024-12-01 14:58:38 +00:00
SamB440 6314b78e47 Merge pull request #1837 from ManInMyVan/cleanup/packetcheck
remove unused method from PacketCheck
2024-12-01 14:49:25 +00:00
SamB440 b791897dbc Merge pull request #1833 from Axionize/verbose-on-join
Add permission to enable verbose on join
2024-12-01 14:46:53 +00:00
SamB440 61af1d1e72 Merge pull request #1830 from ManInMyVan/blockbreak-class
add BlockBreak class
2024-12-01 14:42:08 +00:00
SamB440 bf3fc94d92 More big changes 2024-12-01 14:14:07 +00:00
Axionize 4887415912 Add verbose to appropiate places; makes sure player have alert for auto activation of verbose 2024-11-29 22:50:29 -05:00
SamB440 7f0838832d Merge pull request #1839 from Cyramek/limit-jump-possibilities
[1.21.3] Limit jump possibilities
2024-11-29 18:06:24 +00:00
cyramek 336efafbd3 limit jump possibilities 2024-11-29 18:46:47 +01:00
SamB440 782f8f8a09 Big changes 2024-11-29 17:15:37 +00:00
SamB440 c1858e49d8 Merge pull request #1815 from Axionize/explicit-flush-detection
Warn users who want extra reach accuracy that they need to add paper.explicit-flush=true
2024-11-29 12:24:00 +00:00
SamB440 7dce3a7a12 Merge pull request #1836 from ManInMyVan/cleanup/pair
cleanup Pair class
2024-11-29 12:22:22 +00:00
Axionize 7786da7296 Fix evicting queue for riptide entities 2024-11-28 21:46:43 -05:00
ManInMyVan bc365176b1 remove unused method from PacketCheck 2024-11-28 17:29:45 -07:00
ManInMyVan 7fe224c206 cleanup Pair class 2024-11-28 17:27:32 -07:00
Axionize 48e5f54341 Fix riptide trident attacks on entities that are non-pushable or the same team as the attacker 2024-11-28 17:14:56 -05:00
SamB440 5edf92f124 Merge pull request #1834 from Cyramek/fix-known-input
[1.21.3] fix looping through invalid values caused by known input
2024-11-28 14:33:13 +00:00
cyramek 1c3e938f0f fix looping through invalid values caused by known input 2024-11-28 15:09:54 +01:00
Axionize ec71581eae Add permission to enable verbose on join 2024-11-27 23:46:10 -05:00
Axionize 0904b61df0 Make var type in ExploitC explicitly String 2024-11-27 22:04:50 -05:00
Axionize c9e082257c Put -Dpaper.explicit-flush=true in quotes 2024-11-27 22:01:27 -05:00
Axionize 53dd27e95d split union() in SCB into union() and new encompass() method; fixes Simulation false on walls 2024-11-27 21:59:56 -05:00
SamB440 8875bbf991 Re-encode this 2024-11-27 17:53:49 +00:00
SamB440 e933186d2e determineCanSkipTick idle for 1.21.2+ 2024-11-27 16:53:50 +00:00
SamB440 89bec80b34 Fix 1.21.2+ jump false 2024-11-27 16:07:11 +00:00
SamB440 cc78eca02f Fix offground precision loss to make us consistent 1E-15 offset 2024-11-27 16:06:58 +00:00
SamB440 77a91ec627 1.21.3 update 2024-11-27 16:06:07 +00:00
ManInMyVan 1036563b24 add BlockBreak class 2024-11-26 17:48:45 -07:00
AoElite dd5ea74ae4 update fastutils 2024-11-26 12:43:55 -05:00
AoElite aa7a4dc155 Merge pull request #1828 from ManInMyVan/paper-dupe-patch
patch paper dupe
2024-11-25 21:49:57 -05:00
ManInMyVan 3387365732 remove unused import 2024-11-25 17:55:25 -07:00
ManInMyVan 411aa4f2b2 patch paper dupe 2024-11-25 17:48:30 -07:00
SamB440 63a8e394a9 Merge pull request #1827 from ItsClairton/fix/cauldron
fix: Legacy cauldron collision box.
2024-11-26 00:02:59 +00:00
Clairton Santos 9804b8b62f fix: Legacy cauldron collision box. 2024-11-25 20:44:55 -03:00
Axionize f59279ad51 Comment cleanup 2024-11-25 16:20:32 -05:00
SamB440 f82cce32f6 Merge pull request #1724 from K-Lqrs/2.0
[Improved] Add full Japanese translations for all GrimAC configuration files
2024-11-25 15:29:13 +00:00
AoElite 474ae7dd27 small ResyncWorldUtil refactor 2024-11-25 07:16:47 -05:00
SamB440 d85c1d267b Merge pull request #1825 from Cyramek/fix-reach
fix wrongly ported reach changes from grim 3.0
2024-11-25 09:02:36 +00:00
cyramek 6ce2bcb9e9 fix wrongly ported changes from grim 3.0 2024-11-25 09:30:21 +01:00
AoElite 48eff610c3 fixed BadPackets E & R falsing on 1.21.2+ players in vehicles 2024-11-25 00:04:00 -05:00
AoElite 677dd044ff refactor bstats for packetevents 2024-11-25 00:02:34 -05:00
AoElite 87f30eea37 added a todo 2024-11-25 00:02:02 -05:00
AoElite 370da407ce update packetevents 2024-11-25 00:01:54 -05:00
Axionize 43e4c29f2c Document current state 2024-11-24 23:54:39 -05:00
Axionize 7924107b00 Finish faster equivalent impl 2024-11-24 23:54:39 -05:00
SamB440 1ef4b4eec9 Merge pull request #1821 from Axionize/fix-complex-fence-boxes
Fix CCB constructor for DynamicHitboxFence
2024-11-24 14:00:36 +00:00
AoElite 954eb8b51c Merge pull request #1783 from ManInMyVan/track-paintings
track paintings
2024-11-24 06:52:30 -05:00
AoElite 84ceaa29dc Merge pull request #1797 from ManInMyVan/stopspectating-here-permission
add permission for /grim stopspectating here
2024-11-24 06:49:33 -05:00
AoElite 6974d61b9d Merge pull request #1817 from Axionize/badpacketsx
Fix BadPacketsX false and mark it as no longer experimental
2024-11-24 06:46:58 -05:00
AoElite d9a3a890c8 Merge pull request #1818 from Axionize/badpacketsz
Mark BadPacketsZ as no longer experimental
2024-11-24 06:46:29 -05:00
AoElite c4495d995a Merge pull request #1820 from Axionize/use-movement-threshold
Use movementThreshold() instead of 0.03 where appropiate
2024-11-24 06:42:44 -05:00
Axionize 9bd5c2db0b Fix CCB constructor for DynamicHitboxFence 2024-11-24 02:38:55 -05:00
Axionize 2518b23f8b Use movementThreshold() instead of 0.03 where appropiate 2024-11-24 01:37:53 -05:00
Axionize bd2ceeeed4 Style fix 2024-11-24 00:28:46 -05:00
Axionize a6d082b355 Mark BadPacketsX as no longer experimental 2024-11-24 00:00:47 -05:00
Axionize 3fedd558d6 Fix BadPacketsX falses 2024-11-23 23:58:02 -05:00
Axionize 547a2965dd Warn players who want extra reach accuracy that they need to add paper.explicit-flush=true 2024-11-23 22:31:31 -05:00
ManInMyVan c19914e83f fix MutliActionsF false 2024-11-23 16:37:45 -07:00
ManInMyVan 6c14faa51d fix MutliActionsF falses 2024-11-23 16:37:06 -07:00
ManInMyVan 6b4060e0c4 fix MultiActionsF false 2024-11-23 16:37:06 -07:00
ManInMyVan 483706151b check sprinting in MultiActionsC and MultiActionsD 2024-11-23 16:37:06 -07:00
ManInMyVan 9dc128cc1d add MultiActionsF 2024-11-23 16:37:06 -07:00
ManInMyVan 50b7e84f58 offhand 2024-11-23 16:37:06 -07:00
ManInMyVan a77067ffe5 Add MultiActionsE 2024-11-23 16:37:06 -07:00
ManInMyVan 2a49635497 Add MutliActionsD 2024-11-23 16:37:05 -07:00
ManInMyVan a158019d66 Add MultiActions Checks 2024-11-23 16:37:05 -07:00
MachineBreaker 93f14a5b40 Optimise MenuType#getMenuType 2024-11-17 11:15:07 -04:00
ManInMyVan 2de0f49af9 add permission for /grim stopspectating here 2024-11-15 15:04:04 -07:00
ManInMyVan 39a53db067 track paintings 2024-11-09 17:08:10 -07:00
Lars 9bfc7d7d9b わずかな間違いを修正・2 2024-11-02 23:41:34 +13:00
Lars 7c93eda985 わずかな間違いを修正 2024-11-02 19:13:51 +13:00
Lars 1e7a858aa0 Japanese向けの翻訳を修正 2024-11-02 19:10:17 +13:00
Lars 11fba1b6bd configのja.ymlを修正済み 2024-11-02 19:06:11 +13:00
ManInMyVan ce9d66c199 Allow exempting elytras 2024-10-27 12:51:33 -06:00
Ruxy 330a9782bc Add full Japanese translations for all GrimAC configuration files 2024-09-17 10:31:53 +12:00
820 changed files with 36868 additions and 13190 deletions

No files matched your search

+1 -1
View File
@@ -5,4 +5,4 @@ name = "java"
enabled = true
[analyzers.meta]
runtime_version = "16"
runtime_version = "17"
+19
View File
@@ -0,0 +1,19 @@
root = true
[*]
charset = utf-8
indent_size = 4
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
ij_formatter_off_tag = @formatter:off
ij_formatter_on_tag = @formatter:on
ij_formatter_tags_enabled = false
ij_smart_tabs = false
ij_wrap_on_typing = false
+10 -2
View File
@@ -30,11 +30,19 @@ 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 running on your server. To list plugins, run `/plugins`.
List all plugins or mods running on your server. To list plugins on bukkit, 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
@@ -0,0 +1 @@
blank_issues_enabled: false
+15 -3
View File
@@ -39,11 +39,23 @@ 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
label: Plugins/mods
description: |
List all plugins running on your server. To list plugins, run `/plugins`.
List all plugins or mods running on your server. To list plugins on bukkit, 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 running on your server. To list plugins, run `/plugins`.
List all plugins or mods running on your server. To list plugins on bukkit, 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
+16 -4
View File
@@ -1,5 +1,5 @@
name: Plugin incompatibility or other bug
description: Report a bug or plugin incompatibility here
name: Plugin/mod incompatibility or other bug
description: Report a bug or plugin/mod incompatibility here
labels: ["bug"]
body:
- type: textarea
@@ -30,11 +30,23 @@ 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 running on your server. To list plugins, run `/plugins`.
List all plugins or mods running on your server. To list plugins on bukkit, 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 running on your server. To list plugins, run `/plugins`.
List all plugins or mods running on your server. To list plugins on bukkit, 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
@@ -0,0 +1,229 @@
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 }}"
+12 -8
View File
@@ -12,13 +12,9 @@
name: "CodeQL"
on:
workflow_dispatch:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '30 15 * * 2'
branches: [ dev ]
jobs:
analyze:
@@ -32,14 +28,14 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
language: [ 'java-kotlin' ]
# 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@v4
uses: actions/checkout@v5
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
@@ -51,6 +47,14 @@ 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
+41 -35
View File
@@ -1,38 +1,44 @@
# 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
name: Gradle Package (Development)
on:
[push, workflow_dispatch]
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'
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
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: Build with Gradle
uses: gradle/actions/setup-gradle@v3
with:
arguments: build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v4
with:
path: /home/runner/work/Grim/Grim/build/libs/**.jar
call-build-workflow:
uses: ./.github/workflows/build-and-publish.yml
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 }}
+21
View File
@@ -0,0 +1,21 @@
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 }}
+8 -1
View File
@@ -19,6 +19,7 @@ build/
.gradletasknamecache
gradle-app.setting
!gradle-wrapper.jar
buildSrc/.kotlin
##############################
## IntelliJ
@@ -65,4 +66,10 @@ nb-configuration.xml
##############################
## OS X
##############################
.DS_Store
.DS_Store
##############################
## Fabric
##############################
run/
fabric/run/
+40
View File
@@ -0,0 +1,40 @@
# 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.
+76 -16
View File
@@ -1,29 +1,88 @@
# GrimAC
<div align="center">
<h1>GrimAC</h1>
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. You can join the [discord](https://discord.com/invite/kqQAhTmkUF) for jar releases & changelogs.
<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.
### Compiling through terminal/command prompt
1. git clone https://github.com/GrimAnticheat/Grim.git (or click the green code button, download ZIP, then unzip it.)
2. cd Grim
3. ./gradlew build
4. The final jar is located in build/libs
## Downloads
### API Information
Grim's API allows you to integrate Grim into your own plugins. For more information, check out the API's GitHub repository [here](https://github.com/GrimAnticheat/GrimAPI).
- 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/)~~
## Grim supremacy
## Resources
Here are the main cores that make Grim stand out against other anticheats
- 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).
## 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
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
## 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
@@ -50,7 +109,8 @@ Here are the main cores that make 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
+37 -172
View File
@@ -1,184 +1,49 @@
import net.minecrell.pluginyml.bukkit.BukkitPluginDescription.Permission
/**
* 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
*/
plugins {
id("java")
id("maven-publish")
id("com.github.johnrengelman.shadow") version "8.1.1"
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"
}
import versioning.BuildConfig
import versioning.VersionUtil
spotless {
java {
endWithNewline()
indentWithSpaces(4)
removeUnusedImports()
trimTrailingWhitespace()
targetExclude("build/generated/**/*")
}
kotlinGradle {
endWithNewline()
indentWithSpaces(4)
trimTrailingWhitespace()
}
}
BuildConfig.init(project)
val baseVersion = "2.3.73"
group = "ac.grim.grimac"
version = "2.3.68"
description = "Libre simulation anticheat designed for 1.21 with 1.8-1.21 support, powered by PacketEvents 2.0."
version = VersionUtil.computeVersion(baseVersion)
description = "Libre simulation anticheat designed for 1.21 with 1.8–1.21 support, powered by PacketEvents 2.0."
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
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")
repositories {
mavenLocal()
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/")
mavenCentral()
// FastUtil, Discord-Webhooks
}
dependencies {
implementation("com.github.retrooper:packetevents-spigot:2.5.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.13")
implementation("github.scarsz:configuralize:1.4.0")
//implementation("com.github.grimanticheat:grimapi:1193c4fa41")
// Used for local testing: implementation("ac.grim.grimac:GRIMAPI:1.0")
implementation("com.github.grimanticheat:grimapi:fc5634e444")
implementation("org.jetbrains:annotations:24.1.0")
compileOnly("org.geysermc.floodgate:api:2.0-SNAPSHOT")
compileOnly("org.spigotmc:spigot-api:1.18.2-R0.1-SNAPSHOT")
compileOnly("com.viaversion:viaversion-api:5.0.4-SNAPSHOT")
//
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
softDepend = listOf(
"ProtocolLib",
"ProtocolSupport",
"Essentials",
"ViaVersion",
"ViaBackwards",
"ViaRewind",
"Geyser-Spigot",
"floodgate",
"FastLogin"
)
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.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
}
tasks.register("printVersion") {
group = "versioning"
description = "Prints the computed project version"
doLast {
println("VERSION=$version")
}
}
tasks.build {
dependsOn(tasks.shadowJar)
dependsOn(tasks.spotlessApply)
}
tasks.withType<JavaCompile> {
options.encoding = "UTF-8"
}
publishing.publications.create<MavenPublication>("maven") {
artifact(tasks["shadowJar"])
}
tasks.shadowJar {
minimize()
archiveFileName.set("${project.name}-${project.version}.jar")
if (relocate) {
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("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("net.kyori", "ac.grim.grimac.shaded.kyori")
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")
// ---------- Java Compile Optimization ----------
subprojects {
tasks.withType<JavaCompile>().configureEach {
options.isFork = true
options.isIncremental = true
}
}
+15
View File
@@ -0,0 +1,15 @@
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
@@ -0,0 +1,7 @@
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../libs.versions.toml"))
}
}
}
@@ -0,0 +1,90 @@
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")
@@ -0,0 +1,407 @@
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)
}
}
@@ -0,0 +1,41 @@
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"))
}
@@ -0,0 +1,96 @@
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")
}
@@ -0,0 +1,113 @@
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
@@ -0,0 +1,206 @@
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"
}
}
}
@@ -0,0 +1,28 @@
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();
}
}
@@ -0,0 +1,37 @@
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();
}
}
@@ -0,0 +1,163 @@
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();
}
}
@@ -0,0 +1,36 @@
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();
}
}
@@ -0,0 +1,28 @@
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));
}
}
@@ -0,0 +1,104 @@
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 com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
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 {
protected static final boolean CAN_USE_DIRECT_GETTERS = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_20_1) && PaperUtils.PAPER;
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()
);
}
@Override
public double distanceSquared(double oX, double oY, double oZ) {
if (CAN_USE_DIRECT_GETTERS) {
double x = this.entity.getX();
double y = this.entity.getY();
double z = this.entity.getZ();
double distX = (x - oX) * (x - oX);
double distY = (y - oY) * (y - oY);
double distZ = (z - oZ) * (z - oZ);
return distX + distY + distZ;
} else {
org.bukkit.Location location = this.entity.getLocation();
double x = location.getX();
double y = location.getY();
double z = location.getZ();
double distX = (x - oX) * (x - oX);
double distY = (y - oY) * (y - oY);
double distZ = (z - oZ) * (z - oZ);
return distX + distY + distZ;
}
}
}
@@ -1,10 +1,11 @@
package ac.grim.grimac.events.bukkit;
package ac.grim.grimac.platform.bukkit.events;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.platform.bukkit.utils.convert.BukkitConversionUtils;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.blockstate.helper.BlockFaceHelper;
import ac.grim.grimac.utils.collisions.datatypes.SimpleCollisionBox;
import ac.grim.grimac.utils.data.PistonData;
import ac.grim.grimac.utils.data.TrackedPosition;
import com.github.retrooper.packetevents.protocol.world.BlockFace;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -18,8 +19,20 @@ import java.util.ArrayList;
import java.util.List;
public class PistonEvent implements Listener {
Material SLIME_BLOCK = Material.getMaterial("SLIME_BLOCK");
Material HONEY_BLOCK = Material.getMaterial("HONEY_BLOCK");
private final Material SLIME_BLOCK = Material.getMaterial("SLIME_BLOCK");
private final Material HONEY_BLOCK = Material.getMaterial("HONEY_BLOCK");
private static final double MAX_HORIZONTAL_DISTANCE = 24.0;
private static final double MAX_VERTICAL_DISTANCE = 64.0;
// accuracy isn't that important, it's close enough and performant
private static boolean isCloseEnough(final int aX, final int aY, final int aZ,
final double bX, final double bY, final double bZ) {
return Math.abs(aX - bX) <= MAX_HORIZONTAL_DISTANCE
&& Math.abs(aY - bY) <= MAX_VERTICAL_DISTANCE
&& Math.abs(aZ - bZ) <= MAX_HORIZONTAL_DISTANCE;
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPistonPushEvent(BlockPistonExtendEvent event) {
@@ -55,10 +68,19 @@ public class PistonEvent implements Listener {
piston.getY() + event.getDirection().getModY(),
piston.getZ() + event.getDirection().getModZ()));
final int chunkX = event.getBlock().getX() >> 4;
final int chunkZ = event.getBlock().getZ() >> 4;
final BlockFace blockFace = BukkitConversionUtils.fromBukkitFace(event.getDirection());
final int sourceX = piston.getX();
final int sourceY = piston.getY();
final int sourceZ = piston.getZ();
for (GrimPlayer player : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
if (player.compensatedWorld.isChunkLoaded(event.getBlock().getX() >> 4, event.getBlock().getZ() >> 4)) {
PistonData data = new PistonData(BlockFaceHelper.fromBukkitFace(event.getDirection()), boxes, player.lastTransactionSent.get(), true, hasSlimeBlock, hasHoneyBlock);
player.latencyUtils.addRealTimeTaskAsync(player.lastTransactionSent.get(), () -> player.compensatedWorld.activePistons.add(data));
TrackedPosition position = player.compensatedEntities.self.trackedServerPosition;
if (player.compensatedWorld.isChunkLoaded(chunkX, chunkZ) && isCloseEnough(sourceX, sourceY, sourceZ, position.getX(), position.getY(), position.getZ())) {
final int lastTrans = player.lastTransactionSent.get();
PistonData data = new PistonData(blockFace, boxes, lastTrans, true, hasSlimeBlock, hasHoneyBlock);
player.latencyUtils.addRealTimeTaskAsync(lastTrans, () -> player.compensatedWorld.activePistons.add(data));
}
}
}
@@ -79,7 +101,7 @@ public class PistonEvent implements Listener {
boolean hasHoneyBlock = false;
List<SimpleCollisionBox> boxes = new ArrayList<>();
BlockFace face = BlockFaceHelper.fromBukkitFace(event.getDirection());
BlockFace face = BukkitConversionUtils.fromBukkitFace(event.getDirection());
// The event was called without blocks and is therefore in the right direction
if (event.getBlocks().isEmpty()) {
@@ -108,10 +130,19 @@ public class PistonEvent implements Listener {
}
}
final Block block = event.getBlock();
final int chunkX = block.getX() >> 4;
final int chunkZ = block.getZ() >> 4;
final int sourceX = block.getX();
final int sourceY = block.getY();
final int sourceZ = block.getZ();
for (GrimPlayer player : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
if (player.compensatedWorld.isChunkLoaded(event.getBlock().getX() >> 4, event.getBlock().getZ() >> 4)) {
PistonData data = new PistonData(BlockFaceHelper.fromBukkitFace(event.getDirection()), boxes, player.lastTransactionSent.get(), false, hasSlimeBlock, hasHoneyBlock);
player.latencyUtils.addRealTimeTaskAsync(player.lastTransactionSent.get(), () -> player.compensatedWorld.activePistons.add(data));
TrackedPosition position = player.compensatedEntities.self.trackedServerPosition;
if (player.compensatedWorld.isChunkLoaded(chunkX, chunkZ) && isCloseEnough(sourceX, sourceY, sourceZ, position.getX(), position.getY(), position.getZ())) {
int lastTrans = player.lastTransactionSent.get();
PistonData data = new PistonData(face, boxes, lastTrans, false, hasSlimeBlock, hasHoneyBlock);
player.latencyUtils.addRealTimeTaskAsync(lastTrans, () -> player.compensatedWorld.activePistons.add(data));
}
}
}
@@ -0,0 +1,15 @@
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) {}
}
}
@@ -0,0 +1,15 @@
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);
}
}
@@ -0,0 +1,94 @@
package ac.grim.grimac.platform.bukkit.initables;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.manager.init.start.AbstractTickEndEvent;
import ac.grim.grimac.platform.api.Platform;
import ac.grim.grimac.platform.bukkit.player.BukkitPlatformPlayer;
import ac.grim.grimac.platform.bukkit.utils.reflection.PaperUtils;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.LogUtil;
import ac.grim.grimac.utils.lists.HookedListWrapper;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.util.reflection.Reflection;
import io.github.retrooper.packetevents.util.SpigotReflectionUtil;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
// Copied from: https://github.com/ThomasOM/Pledge/blob/master/src/main/java/dev/thomazz/pledge/inject/ServerInjector.java
@SuppressWarnings(value = {"unchecked", "deprecated"})
public class BukkitTickEndEvent extends AbstractTickEndEvent implements Listener {
@Override
public void start() {
if (!super.shouldInjectEndTick()) {
return;
}
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThan(ServerVersion.V_1_11_2) && !Boolean.getBoolean("paper.explicit-flush")) {
LogUtil.warn("Reach.enable-post-packet=true but paper.explicit-flush=false, add \"-Dpaper.explicit-flush=true\" to your server's startup flags for fully functional extra reach accuracy.");
}
// this is necessary for folia
if (GrimAPI.INSTANCE.getPlatform() == Platform.FOLIA) {
PaperUtils.registerTickEndEvent(this, this::tickAllFoliaPlayers);
return;
}
// if it fails to inject, try to use paper's event
if (!injectWithReflection() && !PaperUtils.registerTickEndEvent(this, this::tickAllPlayers)) {
LogUtil.error("Failed to inject into the end of tick event!");
}
}
private void tickAllPlayers() {
for (GrimPlayer player : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
if (player.disableGrim) continue;
super.onEndOfTick(player);
}
}
private void tickAllFoliaPlayers() {
for (GrimPlayer player : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
if (player.disableGrim) continue;
if (player.platformPlayer == null) continue;
Player p = ((BukkitPlatformPlayer) player.platformPlayer).getNative();
if (!Bukkit.isOwnedByCurrentRegion(p)) continue;
super.onEndOfTick(player);
}
}
private boolean injectWithReflection() {
// Inject so we can add the final transaction pre-flush event
try {
Object connection = SpigotReflectionUtil.getMinecraftServerConnectionInstance();
Field connectionsList = Reflection.getField(connection.getClass(), List.class, 1);
List<Object> endOfTickObject = (List<Object>) connectionsList.get(connection);
// Use a list wrapper to check when the size method is called
// Unsure why synchronized is needed because the object itself gets synchronized
// but whatever. At least plugins can't break it, I guess.
//
// Pledge injects into another list, so we should be safe injecting into this one
List<?> wrapper = Collections.synchronizedList(new HookedListWrapper<>(endOfTickObject) {
@Override
public void onIterator() {
tickAllPlayers();
}
});
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
unsafe.putObject(connection, unsafe.objectFieldOffset(connectionsList), wrapper);
} catch (NoSuchFieldException | IllegalAccessException e) {
LogUtil.error("Failed to inject into the end of tick event via reflection", e);
return false;
}
return true;
}
}
@@ -0,0 +1,213 @@
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 {
method.invoke(getHandle.invoke(player));
// 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();
} 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);
}
}
}
@@ -0,0 +1,19 @@
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);
}
}
@@ -0,0 +1,45 @@
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);
};
}
}
@@ -0,0 +1,33 @@
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));
}
}
}
@@ -0,0 +1,29 @@
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);
}
}
@@ -0,0 +1,34 @@
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());
}
}
@@ -0,0 +1,64 @@
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();
}
}
@@ -0,0 +1,178 @@
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() {
if (CAN_USE_DIRECT_GETTERS) {
return new Vector3d(this.bukkitPlayer.getX(), this.bukkitPlayer.getY(), this.bukkitPlayer.getZ());
} else {
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;
}
}
@@ -0,0 +1,57 @@
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);
}
}
@@ -0,0 +1,111 @@
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);
}
}
@@ -0,0 +1,56 @@
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);
}
}
@@ -0,0 +1,35 @@
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));
}
}
@@ -0,0 +1,39 @@
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);
}
}
@@ -0,0 +1,13 @@
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();
}
@@ -0,0 +1,56 @@
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));
}
}
@@ -0,0 +1,33 @@
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();
}
}
@@ -0,0 +1,57 @@
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);
}
}
@@ -0,0 +1,55 @@
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);
}
}
@@ -0,0 +1,38 @@
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);
}
}
@@ -0,0 +1,13 @@
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();
}
@@ -0,0 +1,85 @@
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
);
}
}
@@ -0,0 +1,33 @@
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();
}
}
@@ -0,0 +1,89 @@
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);
}
}
@@ -0,0 +1,26 @@
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;
}
}
}
@@ -0,0 +1,45 @@
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;
};
}
}
@@ -0,0 +1,79 @@
package ac.grim.grimac.platform.bukkit.utils.placeholder;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.GrimUser;
import ac.grim.grimac.player.GrimPlayer;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
public class PlaceholderAPIExpansion extends PlaceholderExpansion {
@Override
public @NotNull String getIdentifier() {
return "grim";
}
public @NotNull String getAuthor() {
return String.join(", ", GrimAPI.INSTANCE.getGrimPlugin().getDescription().getAuthors());
}
@Override
public @NotNull String getVersion() {
return GrimAPI.INSTANCE.getExternalAPI().getGrimVersion();
}
@Override
public boolean persist() {
return true;
}
@Override
public @NotNull List<String> getPlaceholders() {
Set<String> staticReplacements = GrimAPI.INSTANCE.getExternalAPI().getStaticReplacements().keySet();
Set<String> variableReplacements = GrimAPI.INSTANCE.getExternalAPI().getVariableReplacements().keySet();
ArrayList<String> placeholders = new ArrayList<>(staticReplacements.size() + variableReplacements.size());
for (String s : staticReplacements) {
placeholders.add(s.equals("%grim_version%") ? s : "%grim_" + s.replaceAll("%", "") + "%");
}
for (String s : variableReplacements) {
placeholders.add(s.equals("%player%") ? "%grim_player%" : "%grim_player_" + s.replaceAll("%", "") + "%");
}
return placeholders;
}
@Override
public String onRequest(OfflinePlayer offlinePlayer, @NotNull String params) {
for (Map.Entry<String, String> entry : GrimAPI.INSTANCE.getExternalAPI().getStaticReplacements().entrySet()) {
String key = entry.getKey().equals("%grim_version%")
? "version"
: entry.getKey().replaceAll("%", "");
if (params.equalsIgnoreCase(key)) {
return entry.getValue();
}
}
if (offlinePlayer instanceof Player player) {
GrimPlayer grimPlayer = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(player.getUniqueId());
if (grimPlayer == null) return null;
for (Map.Entry<String, Function<GrimUser, String>> entry : GrimAPI.INSTANCE.getExternalAPI().getVariableReplacements().entrySet()) {
String key = entry.getKey().equals("%player%")
? "player"
: "player_" + entry.getKey().replaceAll("%", "");
if (params.equalsIgnoreCase(key)) {
return entry.getValue().apply(grimPlayer);
}
}
}
return null;
}
}
@@ -0,0 +1,40 @@
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;
}
}
@@ -0,0 +1,38 @@
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();
}
}
@@ -0,0 +1,62 @@
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
@@ -0,0 +1,47 @@
# 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
@@ -0,0 +1,107 @@
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"])
}
@@ -0,0 +1,149 @@
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;
}
}
@@ -4,64 +4,50 @@ import ac.grim.grimac.api.GrimAbstractAPI;
import ac.grim.grimac.api.GrimUser;
import ac.grim.grimac.api.alerts.AlertManager;
import ac.grim.grimac.api.config.ConfigManager;
import ac.grim.grimac.api.events.GrimReloadEvent;
import ac.grim.grimac.api.event.EventBus;
import ac.grim.grimac.api.event.events.GrimReloadEvent;
import ac.grim.grimac.manager.config.ConfigManagerFileImpl;
import ac.grim.grimac.manager.init.Initable;
import ac.grim.grimac.manager.init.start.StartableInitable;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.LogUtil;
import ac.grim.grimac.utils.anticheat.MessageUtil;
import ac.grim.grimac.utils.common.ConfigReloadObserver;
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
import io.github.retrooper.packetevents.util.SpigotReflectionUtil;
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.ServicePriority;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
//This is used for grim's external API. It has its own class just for organization.
public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, Initable {
public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, StartableInitable {
private final GrimAPI api;
@Getter
private final Map<String, Function<GrimUser, String>> variableReplacements = new ConcurrentHashMap<>();
@Getter
private final Map<String, String> staticReplacements = new ConcurrentHashMap<>();
private final Map<String, Function<Object, Object>> functions = new ConcurrentHashMap<>();
private final ConfigManagerFileImpl configManagerFile = new ConfigManagerFileImpl();
private ConfigManager configManager = null;
private boolean started = false;
public GrimExternalAPI(GrimAPI api) {
this.api = api;
}
@Nullable
@Override
public GrimUser getGrimUser(Player player) {
return api.getPlayerDataManager().getPlayer(player);
public @NotNull EventBus getEventBus() {
return api.getEventBus();
}
@Override
public void setServerName(String name) {
variableReplacements.put("%server%", user -> name);
}
@Getter
private final Map<String, Function<GrimUser, String>> variableReplacements = new ConcurrentHashMap<>();
@Getter
private final Map<String, String> staticReplacements = new ConcurrentHashMap<>();
public String replaceVariables(GrimUser user, String content, boolean colors) {
if (colors) content = ChatColor.translateAlternateColorCodes('&', content);
for (Map.Entry<String, String> entry : staticReplacements.entrySet()) {
content = content.replace(entry.getKey(), entry.getValue());
}
for (Map.Entry<String, Function<GrimUser, String>> entry : variableReplacements.entrySet()) {
content = content.replace(entry.getKey(), entry.getValue().apply(user));
}
return content;
public @Nullable GrimUser getGrimUser(UUID uuid) {
return api.getPlayerDataManager().getPlayer(uuid);
}
@Override
@@ -84,12 +70,9 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
@Override
public String getGrimVersion() {
PluginDescriptionFile description = GrimAPI.INSTANCE.getPlugin().getDescription();
return description.getVersion();
return api.getGrimPlugin().getDescription().getVersion();
}
private final Map<String, Function<Object, Object>> functions = new ConcurrentHashMap<>();
@Override
public void registerFunction(String key, Function<Object, Object> function) {
if (function == null) {
@@ -114,14 +97,20 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
return configManager;
}
private ConfigManager configManager = null;
private final ConfigManagerFileImpl configManagerFile = new ConfigManagerFileImpl();
private boolean started = false;
@Override
public boolean hasStarted() {
return started;
}
@Override
public int getCurrentTick() {
return GrimAPI.INSTANCE.getTickManager().currentTick;
}
// on load, load the config & register the service
public void load() {
reload(configManagerFile);
Bukkit.getServicesManager().register(GrimAbstractAPI.class, this, GrimAPI.INSTANCE.getPlugin(), ServicePriority.Normal);
api.getLoader().registerAPIService();
}
// handles any config loading that's needed to be done after load
@@ -131,15 +120,15 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
try {
GrimAPI.INSTANCE.getConfigManager().start();
} catch (Exception e) {
e.printStackTrace();
LogUtil.error("Failed to start config manager.", e);
}
}
@Override
public void reload(ConfigManager config) {
if (config.isLoadedAsync() && started) {
FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
o -> successfulReload(config));
GrimAPI.INSTANCE.getScheduler().getAsyncScheduler().runNow(GrimAPI.INSTANCE.getGrimPlugin(),
() -> successfulReload(config));
} else {
successfulReload(config);
}
@@ -149,8 +138,8 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
public CompletableFuture<Boolean> reloadAsync(ConfigManager config) {
if (config.isLoadedAsync() && started) {
CompletableFuture<Boolean> future = new CompletableFuture<>();
FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
o -> future.complete(successfulReload(config)));
GrimAPI.INSTANCE.getScheduler().getAsyncScheduler().runNow(GrimAPI.INSTANCE.getGrimPlugin(),
() -> future.complete(successfulReload(config)));
return future;
}
return CompletableFuture.completedFuture(successfulReload(config));
@@ -162,14 +151,16 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
GrimAPI.INSTANCE.getConfigManager().load(config);
if (started) GrimAPI.INSTANCE.getConfigManager().start();
onReload(config);
if (started) FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
o -> Bukkit.getPluginManager().callEvent(new GrimReloadEvent(true)));
if (started)
GrimAPI.INSTANCE.getScheduler().getAsyncScheduler().runNow(GrimAPI.INSTANCE.getGrimPlugin(),
() -> GrimAPI.INSTANCE.getEventBus().post(new GrimReloadEvent(true)));
return true;
} catch (Exception e) {
e.printStackTrace();
LogUtil.error("Failed to reload config", e);
}
if (started) FoliaScheduler.getAsyncScheduler().runNow(GrimAPI.INSTANCE.getPlugin(),
o -> Bukkit.getPluginManager().callEvent(new GrimReloadEvent(false)));
if (started)
GrimAPI.INSTANCE.getScheduler().getAsyncScheduler().runNow(GrimAPI.INSTANCE.getGrimPlugin(),
() -> GrimAPI.INSTANCE.getEventBus().post(new GrimReloadEvent(false)));
return false;
}
@@ -184,16 +175,15 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
// Update variables
updateVariables();
// Restart
GrimAPI.INSTANCE.getDiscordManager().start();
GrimAPI.INSTANCE.getSpectateManager().start();
GrimAPI.INSTANCE.getAlertManager().reload(configManager);
GrimAPI.INSTANCE.getDiscordManager().reload();
GrimAPI.INSTANCE.getSpectateManager().reload();
GrimAPI.INSTANCE.getViolationDatabaseManager().reload();
// Don't reload players if the plugin hasn't started yet
if (!started) return;
// Reload checks for all players
for (GrimPlayer grimPlayer : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
ChannelHelper.runInEventLoop(grimPlayer.user.getChannel(), () -> {
grimPlayer.updatePermissions();
grimPlayer.reload(configManager);
});
for (GrimPlayer player : GrimAPI.INSTANCE.getPlayerDataManager().getEntries()) {
player.runSafely(() -> player.reload(configManager));
}
}
@@ -205,11 +195,10 @@ public class GrimExternalAPI implements GrimAbstractAPI, ConfigReloadObserver, I
variableReplacements.putIfAbsent("%h_sensitivity%", user -> ((int) Math.round(user.getHorizontalSensitivity() * 200)) + "");
variableReplacements.putIfAbsent("%v_sensitivity%", user -> ((int) Math.round(user.getVerticalSensitivity() * 200)) + "");
variableReplacements.putIfAbsent("%fast_math%", user -> !user.isVanillaMath() + "");
variableReplacements.putIfAbsent("%tps%", user -> String.format("%.2f", SpigotReflectionUtil.getTPS()));
variableReplacements.putIfAbsent("%tps%", user -> String.format("%.2f", GrimAPI.INSTANCE.getPlatformServer().getTPS()));
variableReplacements.putIfAbsent("%version%", GrimUser::getVersionName);
// static variables
staticReplacements.putIfAbsent("%prefix%", ChatColor.translateAlternateColorCodes('&', GrimAPI.INSTANCE.getConfigManager().getPrefix()));
staticReplacements.put("%prefix%", MessageUtil.translateAlternateColorCodes('&', GrimAPI.INSTANCE.getConfigManager().getPrefix()));
staticReplacements.putIfAbsent("%grim_version%", getGrimVersion());
}
}
@@ -0,0 +1,205 @@
package ac.grim.grimac.checks;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.AbstractCheck;
import ac.grim.grimac.api.config.ConfigManager;
import ac.grim.grimac.api.event.events.FlagEvent;
import ac.grim.grimac.player.GrimPlayer;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import lombok.Getter;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import static com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying.isFlying;
// Class from https://github.com/Tecnio/AntiCheatBase/blob/master/src/main/java/me/tecnio/anticheat/check/Check.java
@Getter
public class Check extends GrimProcessor implements AbstractCheck {
protected @NotNull final GrimPlayer player;
public double violations;
private double decay;
private double setbackVL;
private String checkName;
private String configName;
private String alternativeName;
private String displayName;
private String description;
private boolean experimental;
private @Setter boolean isEnabled;
private boolean exemptPermission;
private boolean noSetbackPermission;
private boolean noModifyPacketPermission;
private long lastViolationTime;
public Check(final @NotNull GrimPlayer player) {
this.player = Objects.requireNonNull(player);
final CheckData checkData = this.getClass().getAnnotation(CheckData.class);
if (checkData != null) {
this.checkName = checkData.name();
this.configName = checkData.configName();
// Fall back to check name
if (this.configName.equals("DEFAULT")) this.configName = this.checkName;
this.decay = checkData.decay();
this.setbackVL = checkData.setback();
this.alternativeName = checkData.alternativeName();
this.experimental = checkData.experimental();
this.description = checkData.description();
this.displayName = this.checkName;
}
reload();
}
public boolean shouldModifyPackets() {
return isEnabled && !player.disableGrim && !player.noModifyPacketPermission && !exemptPermission;
}
public final void updatePermissions() {
if (configName == null || player.platformPlayer == null) return;
final String id = configName.toLowerCase();
exemptPermission = player.platformPlayer.hasPermission("grim.exempt." + id);
noSetbackPermission = player.platformPlayer.hasPermission("grim.nosetback." + id);
noModifyPacketPermission = player.platformPlayer.hasPermission("grim.nomodifypacket." + id);
}
public final boolean flagAndAlert(String verbose) {
if (flag(verbose)) {
alert(verbose);
return true;
}
return false;
}
public final boolean flagAndAlert() {
return flagAndAlert("");
}
public final boolean flag() {
return flag("");
}
public final boolean flag(String verbose) {
if (player.disableGrim || (experimental && !player.isExperimentalChecks()) || exemptPermission)
return false; // Avoid calling event if disabled
FlagEvent event = new FlagEvent(player, this, verbose);
GrimAPI.INSTANCE.getEventBus().post(event);
if (event.isCancelled()) return false;
player.punishmentManager.handleViolation(this);
lastViolationTime = System.currentTimeMillis();
violations++;
return true;
}
public final boolean flagWithSetback() {
return flagWithSetback("");
}
public final boolean flagWithSetback(String verbose) {
if (flag(verbose)) {
setbackIfAboveSetbackVL();
return true;
}
return false;
}
public final boolean flagAndAlertWithSetback() {
return flagAndAlertWithSetback("");
}
public final boolean flagAndAlertWithSetback(String verbose) {
if (flagAndAlert(verbose)) {
setbackIfAboveSetbackVL();
return true;
}
return false;
}
public final void reward() {
violations = Math.max(0, violations - decay);
}
@Override
public final void reload(ConfigManager configuration) {
decay = configuration.getDoubleElse(configName + ".decay", decay);
setbackVL = configuration.getDoubleElse(configName + ".setbackvl", setbackVL);
displayName = configuration.getStringElse(configName + ".displayname", checkName);
description = configuration.getStringElse(configName + ".description", description);
if (setbackVL == -1) setbackVL = Double.MAX_VALUE;
onReload(configuration);
}
@Override
public void onReload(ConfigManager config) {
}
public boolean alert(String verbose) {
return player.punishmentManager.handleAlert(player, verbose, this);
}
public boolean setbackIfAboveSetbackVL() {
if (shouldSetback()) {
return player.getSetbackTeleportUtil().executeViolationSetback();
}
return false;
}
public boolean shouldSetback() {
return !noSetbackPermission && violations > setbackVL;
}
public String formatOffset(double offset) {
return offset > 0.001 ? String.format("%.5f", offset) : String.format("%.2E", offset);
}
public static boolean isTransaction(PacketTypeCommon packetType) {
return packetType == PacketType.Play.Client.PONG ||
packetType == PacketType.Play.Client.WINDOW_CONFIRMATION;
}
public static boolean isAsync(PacketTypeCommon packetType) {
return packetType == PacketType.Play.Client.KEEP_ALIVE;
}
public boolean isUpdate(PacketTypeCommon packetType) {
return isFlying(packetType)
|| packetType == PacketType.Play.Client.CLIENT_TICK_END
|| isTransaction(packetType);
}
public boolean isTickPacket(PacketTypeCommon packetType) {
if (isTickPacketIncludingNonMovement(packetType)) {
if (isFlying(packetType)) {
return !player.packetStateData.lastPacketWasTeleport && !player.packetStateData.lastPacketWasOnePointSeventeenDuplicate;
}
return true;
}
return false;
}
public boolean isTickPacketIncludingNonMovement(PacketTypeCommon packetType) {
// On 1.21.2+ fall back to the TICK_END packet IF the player did not send a movement packet for their tick
// TickTimer checks to see if player did not send a tick end packet before new flying packet is sent
if (player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_2)
&& !player.packetStateData.didSendMovementBeforeTickEnd) {
if (packetType == PacketType.Play.Client.CLIENT_TICK_END) {
return true;
}
}
return isFlying(packetType);
}
}
@@ -0,0 +1,17 @@
package ac.grim.grimac.checks;
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.AbstractProcessor;
import ac.grim.grimac.api.config.ConfigReloadable;
import ac.grim.grimac.utils.common.ConfigReloadObserver;
public abstract class GrimProcessor implements AbstractProcessor, ConfigReloadable, ConfigReloadObserver {
// Not everything has to be a check for it to process packets & be configurable
@Override
public void reload() {
reload(GrimAPI.INSTANCE.getConfigManager().getConfig());
}
}
@@ -0,0 +1,14 @@
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();
}
@@ -8,15 +8,15 @@ import ac.grim.grimac.utils.anticheat.update.RotationUpdate;
@CheckData(name = "AimDuplicateLook")
public class AimDuplicateLook extends Check implements RotationCheck {
private boolean exempt;
public AimDuplicateLook(GrimPlayer playerData) {
super(playerData);
}
boolean exempt = false;
@Override
public void process(final RotationUpdate rotationUpdate) {
if (player.packetStateData.lastPacketWasTeleport || player.packetStateData.lastPacketWasOnePointSeventeenDuplicate || player.compensatedEntities.getSelf().getRiding() != null) {
if (player.packetStateData.lastPacketWasTeleport || player.packetStateData.lastPacketWasOnePointSeventeenDuplicate || player.compensatedEntities.self.getRiding() != null) {
exempt = true;
return;
}
@@ -20,12 +20,15 @@ public class AimModulo360 extends Check implements RotationCheck {
@Override
public void process(final RotationUpdate rotationUpdate) {
if (player.packetStateData.lastPacketWasTeleport) {
// Exempt for teleport, entering a vehicle due to rotation reset or
// after forced, client-sided rotation change after interacting with a horse (not necessarily mounting it)
if (player.packetStateData.lastPacketWasTeleport || player.vehicleData.wasVehicleSwitch
|| player.packetStateData.horseInteractCausedForcedRotation) {
lastDeltaYaw = rotationUpdate.getDeltaXRot();
return;
}
if (player.xRot < 360 && player.xRot > -360 && Math.abs(rotationUpdate.getDeltaXRot()) > 320 && Math.abs(lastDeltaYaw) < 30) {
if (player.yaw < 360 && player.yaw > -360 && Math.abs(rotationUpdate.getDeltaXRot()) > 320 && Math.abs(lastDeltaYaw) < 30) {
flagAndAlert();
} else {
reward();
@@ -8,37 +8,35 @@ import ac.grim.grimac.utils.data.Pair;
import ac.grim.grimac.utils.lists.RunningMode;
import ac.grim.grimac.utils.math.GrimMath;
public class AimProcessor extends Check implements RotationCheck {
private static final int SIGNIFICANT_SAMPLES_THRESHOLD = 15;
private static final int TOTAL_SAMPLES_THRESHOLD = 80;
public double sensitivityX;
public double sensitivityY;
public double divisorX;
public double divisorY;
public double modeX, modeY;
public double deltaDotsX, deltaDotsY;
private final RunningMode xRotMode = new RunningMode(TOTAL_SAMPLES_THRESHOLD);
private final RunningMode yRotMode = new RunningMode(TOTAL_SAMPLES_THRESHOLD);
private float lastXRot;
private float lastYRot;
public AimProcessor(GrimPlayer playerData) {
super(playerData);
}
RunningMode xRotMode = new RunningMode(TOTAL_SAMPLES_THRESHOLD);
RunningMode yRotMode = new RunningMode(TOTAL_SAMPLES_THRESHOLD);
float lastXRot;
float lastYRot;
public double sensitivityX;
public double sensitivityY;
public double divisorX;
public double divisorY;
public double modeX, modeY;
public double deltaDotsX, deltaDotsY;
public static double convertToSensitivity(double var13) {
double var11 = var13 / 0.15F / 8.0D;
double var9 = Math.cbrt(var11);
return (var9 - 0.2f) / 0.6f;
}
@Override
public void process(final RotationUpdate rotationUpdate) {
rotationUpdate.setProcessor(this);
float deltaXRot = rotationUpdate.getDeltaXRotABS();
this.divisorX = GrimMath.gcd(deltaXRot, lastXRot);
@@ -47,7 +45,6 @@ public class AimProcessor extends Check implements RotationCheck {
this.lastXRot = deltaXRot;
}
float deltaYRot = rotationUpdate.getDeltaYRotABS();
this.divisorY = GrimMath.gcd(deltaYRot, lastYRot);
@@ -75,10 +72,4 @@ public class AimProcessor extends Check implements RotationCheck {
this.deltaDotsX = deltaXRot / modeX;
this.deltaDotsY = deltaYRot / modeY;
}
public static double convertToSensitivity(double var13) {
double var11 = var13 / 0.15F / 8.0D;
double var9 = Math.cbrt(var11);
return (var9 - 0.2f) / 0.6f;
}
}
@@ -8,9 +8,9 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientHeldItemChange;
@CheckData(name = "BadPacketsA")
@CheckData(name = "BadPacketsA", description = "Sent duplicate slot id")
public class BadPacketsA extends Check implements PacketCheck {
int lastSlot = -1;
private int lastSlot = -1;
public BadPacketsA(final GrimPlayer player) {
super(player);
@@ -0,0 +1,32 @@
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;
});
}
}
}
@@ -6,9 +6,10 @@ 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.GameMode;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
@CheckData(name = "BadPacketsC")
@CheckData(name = "BadPacketsC", description = "Interacted with self")
public class BadPacketsC extends Check implements PacketCheck {
public BadPacketsC(GrimPlayer player) {
super(player);
@@ -17,6 +18,7 @@ public class BadPacketsC extends Check implements PacketCheck {
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.INTERACT_ENTITY) {
if (player.gamemode == GameMode.SPECTATOR) return;
if (new WrapperPlayClientInteractEntity(event).getEntityId() == player.entityID) {
// Instant ban
if (flagAndAlert() && shouldModifyPackets()) {
@@ -8,7 +8,7 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
@CheckData(name = "BadPacketsD")
@CheckData(name = "BadPacketsD", description = "Impossible pitch")
public class BadPacketsD extends Check implements PacketCheck {
public BadPacketsD(GrimPlayer player) {
super(player);
@@ -22,15 +22,13 @@ public class BadPacketsD extends Check implements PacketCheck {
final float pitch = new WrapperPlayClientPlayerFlying(event).getLocation().getPitch();
if (pitch > 90 || pitch < -90) {
// Ban.
if (flagAndAlert("pitch=" + pitch)) {
if (shouldModifyPackets()) {
// prevent other checks from using an invalid pitch
if (player.yRot > 90) player.yRot = 90;
if (player.yRot < -90) player.yRot = -90;
if (flagAndAlert("pitch=" + pitch) && shouldModifyPackets()) {
// prevent other checks from using an invalid pitch
if (player.pitch > 90) player.pitch = 90;
if (player.pitch < -90) player.pitch = -90;
event.setCancelled(true);
player.onPacketCancel();
}
event.setCancelled(true);
player.onPacketCancel();
}
}
}
@@ -4,13 +4,18 @@ 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.WrapperPlayClientPlayerFlying;
@CheckData(name = "BadPacketsE")
public class BadPacketsE extends Check implements PacketCheck {
private int noReminderTicks;
private final int maxNoReminderTicks = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8) ? 20 : 19;
private final boolean isViaPleaseStopUsingProtocolHacksOnYourServer = player.getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_2) || PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_21_2);
public BadPacketsE(GrimPlayer player) {
super(player);
@@ -21,15 +26,14 @@ public class BadPacketsE extends Check implements PacketCheck {
if (event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION ||
event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION) {
noReminderTicks = 0;
} else if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType())) {
noReminderTicks++;
} else if (event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE) {
} else if (WrapperPlayClientPlayerFlying.isFlying(event.getPacketType()) && !player.packetStateData.lastPacketWasTeleport) {
if (++noReminderTicks > maxNoReminderTicks) {
flagAndAlert("ticks=" + noReminderTicks);
}
} else if (event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE
|| (isViaPleaseStopUsingProtocolHacksOnYourServer && player.inVehicle())) {
noReminderTicks = 0; // Exempt vehicles
}
if (noReminderTicks > 20) {
flagAndAlert("ticks=" + noReminderTicks); // ban? I don't know how this would false
}
}
public void handleRespawn() {
@@ -8,7 +8,7 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction;
@CheckData(name = "BadPacketsF")
@CheckData(name = "BadPacketsF", description = "Sent duplicate sprinting status")
public class BadPacketsF extends Check implements PacketCheck {
public boolean lastSprinting;
public boolean exemptNext = true; // Support 1.14+ clients starting on either true or false sprinting, we don't know
@@ -8,10 +8,9 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction;
@CheckData(name = "BadPacketsG")
@CheckData(name = "BadPacketsG", description = "Sent duplicate sneaking status")
public class BadPacketsG extends Check implements PacketCheck {
boolean wasTeleport;
boolean lastSneaking;
private boolean lastSneaking, respawn;
public BadPacketsG(GrimPlayer player) {
super(player);
@@ -19,13 +18,12 @@ public class BadPacketsG extends Check implements PacketCheck {
@Override
public void onPacketReceive(PacketReceiveEvent event) {
wasTeleport = player.packetStateData.lastPacketWasTeleport || wasTeleport;
if (event.getPacketType() == PacketType.Play.Client.ENTITY_ACTION) {
WrapperPlayClientEntityAction packet = new WrapperPlayClientEntityAction(event);
if (packet.getAction() == WrapperPlayClientEntityAction.Action.START_SNEAKING) {
if (lastSneaking && !wasTeleport) {
// The player may send two START_SNEAKING packets if they respawned
if (lastSneaking && !respawn) {
if (flagAndAlert("state=true") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
@@ -33,8 +31,9 @@ public class BadPacketsG extends Check implements PacketCheck {
} else {
lastSneaking = true;
}
respawn = false;
} else if (packet.getAction() == WrapperPlayClientEntityAction.Action.STOP_SNEAKING) {
if (!lastSneaking && !wasTeleport) {
if (!lastSneaking && !respawn) {
if (flagAndAlert("state=false") && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
@@ -42,7 +41,13 @@ public class BadPacketsG extends Check implements PacketCheck {
} else {
lastSneaking = false;
}
respawn = false;
}
}
}
public void handleRespawn() {
// Clients could potentially not send a STOP_SNEAKING packet when they die, so we need to track it
respawn = true;
}
}
@@ -0,0 +1,67 @@
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;
}
}
@@ -8,7 +8,7 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerAbilities;
@CheckData(name = "BadPacketsI")
@CheckData(name = "BadPacketsI", description = "Claimed to be flying while unable to fly")
public class BadPacketsI extends Check implements PacketCheck {
public BadPacketsI(GrimPlayer player) {
super(player);
@@ -16,13 +16,11 @@ public class BadPacketsI extends Check implements PacketCheck {
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.PLAYER_ABILITIES) {
if (new WrapperPlayClientPlayerAbilities(event).isFlying() && !player.canFly) {
if (flagAndAlert() && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
if (event.getPacketType() == PacketType.Play.Client.PLAYER_ABILITIES
&& new WrapperPlayClientPlayerAbilities(event).isFlying() && !player.canFly
&& flagAndAlert() && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
}
@@ -0,0 +1,59 @@
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();
}
}
}
@@ -8,7 +8,7 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.player.GameMode;
@CheckData(name = "BadPacketsK")
@CheckData(name = "BadPacketsK", description = "Sent spectate packets while not in spectator mode")
public class BadPacketsK extends Check implements PacketCheck {
public BadPacketsK(GrimPlayer player) {
super(player);
@@ -16,13 +16,11 @@ public class BadPacketsK extends Check implements PacketCheck {
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.SPECTATE) {
if (player.gamemode != GameMode.SPECTATOR) {
if (flagAndAlert() && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
if (event.getPacketType() == PacketType.Play.Client.SPECTATE
&& player.gamemode != GameMode.SPECTATOR
&& flagAndAlert() && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
}
@@ -8,13 +8,11 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
import com.github.retrooper.packetevents.protocol.world.BlockFace;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging;
import java.util.Locale;
// checks for impossible dig packets
@CheckData(name = "BadPacketsL")
@CheckData(name = "BadPacketsL", description = "Sent impossible dig packet")
public class BadPacketsL extends Check implements PacketCheck {
public BadPacketsL(GrimPlayer player) {
@@ -26,23 +24,25 @@ public class BadPacketsL extends Check implements PacketCheck {
if (event.getPacketType() == PacketType.Play.Client.PLAYER_DIGGING) {
final WrapperPlayClientPlayerDigging packet = new WrapperPlayClientPlayerDigging(event);
if (packet.getAction() == DiggingAction.START_DIGGING || packet.getAction() == DiggingAction.FINISHED_DIGGING || packet.getAction() == DiggingAction.CANCELLED_DIGGING) return;
if (packet.getAction() == DiggingAction.START_DIGGING || packet.getAction() == DiggingAction.FINISHED_DIGGING || packet.getAction() == DiggingAction.CANCELLED_DIGGING)
return;
// 1.8 and above clients always send digging packets that aren't used for digging at 0, 0, 0, facing DOWN
// 1.7 and below clients do the same, except use SOUTH for RELEASE_USE_ITEM
final BlockFace expectedFace = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_7_10) && packet.getAction() == DiggingAction.RELEASE_USE_ITEM
? BlockFace.SOUTH : BlockFace.DOWN;
final int expectedFace = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_7_10) && packet.getAction() == DiggingAction.RELEASE_USE_ITEM
? 255 : 0;
if (packet.getBlockFace() != expectedFace
if (packet.getBlockFaceId() != expectedFace
|| packet.getBlockPosition().getX() != 0
|| packet.getBlockPosition().getY() != 0
|| packet.getBlockPosition().getZ() != 0
|| packet.getSequence() != 0
) {
if (flagAndAlert("xyzF="
+ packet.getBlockPosition().getX() + ", " + packet.getBlockPosition().getY() + ", " + packet.getBlockPosition().getZ() + ", " + packet.getBlockFace()
if (flagAndAlert("pos="
+ packet.getBlockPosition().getX() + ", " + packet.getBlockPosition().getY() + ", " + packet.getBlockPosition().getZ()
+ ", face=" + packet.getBlockFace()
+ ", sequence=" + packet.getSequence()
+ ", action=" + packet.getAction().toString().toLowerCase(Locale.ROOT).replace("_", " ") + " v" + player.getVersionName()
+ ", action=" + packet.getAction().toString().toLowerCase(Locale.ROOT)
) && shouldModifyPackets() && packet.getAction() != DiggingAction.RELEASE_USE_ITEM) {
event.setCancelled(true);
player.onPacketCancel();
@@ -0,0 +1,64 @@
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++);
}
}
}
}
@@ -2,11 +2,10 @@ 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;
@CheckData(name = "BadPacketsN")
public class BadPacketsN extends Check implements PacketCheck {
@CheckData(name = "BadPacketsN", setback = 0)
public class BadPacketsN extends Check {
public BadPacketsN(final GrimPlayer player) {
super(player);
}
@@ -4,7 +4,6 @@ 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.Pair;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
@@ -12,11 +11,10 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientKe
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerKeepAlive;
import java.util.LinkedList;
import java.util.Queue;
@CheckData(name = "BadPacketsO")
public class BadPacketsO extends Check implements PacketCheck {
Queue<Pair<Long, Long>> keepaliveMap = new LinkedList<>();
private final LinkedList<Long> keepalives = new LinkedList<>();
public BadPacketsO(GrimPlayer player) {
super(player);
@@ -25,37 +23,30 @@ public class BadPacketsO extends Check implements PacketCheck {
@Override
public void onPacketSend(PacketSendEvent event) {
if (event.getPacketType() == PacketType.Play.Server.KEEP_ALIVE) {
WrapperPlayServerKeepAlive packet = new WrapperPlayServerKeepAlive(event);
keepaliveMap.add(new Pair<>(packet.getId(), System.nanoTime()));
keepalives.add(new WrapperPlayServerKeepAlive(event).getId());
}
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.KEEP_ALIVE) {
WrapperPlayClientKeepAlive packet = new WrapperPlayClientKeepAlive(event);
final long id = new WrapperPlayClientKeepAlive(event).getId();
long id = packet.getId();
boolean hasID = false;
for (long keepalive : keepalives) {
if (keepalive == id) {
// Found the ID, remove stuff until we get to it (to stop very slow memory leaks)
Long data;
do {
data = keepalives.poll();
} while (data != null && data != id);
for (Pair<Long, Long> iterator : keepaliveMap) {
if (iterator.first() == id) {
hasID = true;
break;
return;
}
}
if (!hasID) {
if (flagAndAlert("id=" + id) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
} else { // Found the ID, remove stuff until we get to it (to stop very slow memory leaks)
Pair<Long, Long> data;
do {
data = keepaliveMap.poll();
if (data == null) break;
} while (data.first() != id);
if (flagAndAlert("id=" + id) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
}
}
@@ -8,18 +8,19 @@ 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.client.WrapperPlayClientClickWindow;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientClickWindow.WindowClickType;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerOpenWindow;
@CheckData(name = "BadPacketsP", experimental = true)
@CheckData(name = "BadPacketsP", description = "Invalid click packets", experimental = true)
public class BadPacketsP extends Check implements PacketCheck {
private int containerType = -1;
private int containerId = -1;
public BadPacketsP(GrimPlayer playerData) {
super(playerData);
}
private int containerType = -1;
private int containerId = -1;
@Override
public void onPacketSend(final PacketSendEvent event) {
if (event.getPacketType() == PacketType.Play.Server.OPEN_WINDOW) {
@@ -33,35 +34,22 @@ public class BadPacketsP extends Check implements PacketCheck {
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.CLICK_WINDOW) {
WrapperPlayClientClickWindow wrapper = new WrapperPlayClientClickWindow(event);
int clickType = wrapper.getWindowClickType().ordinal();
WindowClickType clickType = wrapper.getWindowClickType();
int button = wrapper.getButton();
boolean flag = false;
// TODO: Adjust for containers
boolean flag = switch (clickType) {
case PICKUP, QUICK_MOVE, CLONE -> button > 2 || button < 0;
case SWAP -> (button > 8 || button < 0) && button != 40;
case THROW -> button != 0 && button != 1;
case QUICK_CRAFT -> button == 3 || button == 7 || button > 10 || button < 0;
case PICKUP_ALL -> button != 0;
case UNKNOWN -> true;
};
//TODO: Adjust for containers
switch (clickType) {
case 0:
case 1:
case 4:
if (button != 0 && button != 1) flag = true;
break;
case 2:
if ((button > 8 || button < 0) && button != 40) flag = true;
break;
case 3:
if (button != 2) flag = true;
break;
case 5:
if (button == 3 || button == 7 || button > 10 || button < 0) flag = true;
break;
case 6:
if (button != 0) flag = true;
break;
}
//Allowing this to false flag to debug and find issues faster
// Allowing this to false flag to debug and find issues faster
if (flag) {
if (flagAndAlert("clickType=" + clickType + " button=" + button + (wrapper.getWindowId() == containerId ? " container=" + containerType : "")) && shouldModifyPackets()) {
if (flagAndAlert("clickType=" + clickType.toString().toLowerCase() + ", button=" + button + (wrapper.getWindowId() == containerId ? ", container=" + containerType : "")) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
@@ -19,8 +19,10 @@ public class BadPacketsQ extends Check implements PacketCheck {
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == Client.ENTITY_ACTION) {
WrapperPlayClientEntityAction wrapper = new WrapperPlayClientEntityAction(event);
if (wrapper.getJumpBoost() < 0 || wrapper.getJumpBoost() > 100 || wrapper.getEntityId() != player.entityID || (wrapper.getAction() != Action.START_JUMPING_WITH_HORSE && wrapper.getJumpBoost() != 0)) {
// you are able to send negative jump boost, how and why!?
if (Math.abs(wrapper.getJumpBoost()) > 100
|| wrapper.getEntityId() != player.entityID
|| wrapper.getAction() != Action.START_JUMPING_WITH_HORSE && wrapper.getJumpBoost() != 0) {
if (flagAndAlert("boost=" + wrapper.getJumpBoost() + ", action=" + wrapper.getAction() + ", entity=" + wrapper.getEntityId()) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
@@ -10,26 +10,27 @@ import com.github.retrooper.packetevents.protocol.player.GameMode;
@CheckData(name = "BadPacketsR", decay = 0.25, experimental = true)
public class BadPacketsR extends Check implements PacketCheck {
public BadPacketsR(final GrimPlayer player) {
super(player);
}
private int positions = 0;
private long clock = 0;
private long lastTransTime;
private int oldTransId = 0;
public BadPacketsR(final GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(final PacketReceiveEvent event) {
if (isTransaction(event.getPacketType()) && player.packetStateData.lastTransactionPacketWasValid) {
long ms = (player.getPlayerClockAtLeast() - clock) / 1000000L;
long diff = (System.currentTimeMillis() - lastTransTime);
if (diff > 2000 && ms > 2000) {
if (positions == 0 && clock != 0 && player.gamemode != GameMode.SPECTATOR && !player.compensatedEntities.getSelf().isDead) {
flagAndAlert("time=" + ms + "ms, " + "lst=" + diff + "ms, positions=" + positions);
if (positions == 0 && clock != 0 && player.gamemode != GameMode.SPECTATOR && !player.compensatedEntities.self.isDead) {
flag("time=" + ms + "ms, " + "lst=" + diff + "ms, positions=" + positions);
} else {
reward();
}
player.compensatedEntities.entitiesRemovedThisTick.clear();
player.compensatedWorld.removeInvalidPistonLikeStuff(oldTransId);
positions = 0;
clock = player.getPlayerClockAtLeast();
@@ -39,9 +40,10 @@ public class BadPacketsR extends Check implements PacketCheck {
}
//
if ((event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION ||
event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION) && !player.compensatedEntities.getSelf().inVehicle()) {
event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION) && !player.inVehicle()) {
positions++;
} else if (event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE && player.compensatedEntities.getSelf().inVehicle()) {
} else if ((event.getPacketType() == PacketType.Play.Client.STEER_VEHICLE || event.getPacketType() == PacketType.Play.Client.VEHICLE_MOVE)
&& player.inVehicle()) {
positions++;
}
}
@@ -0,0 +1,26 @@
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();
}
}
}
@@ -14,18 +14,22 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientIn
@CheckData(name = "BadPacketsT")
public class BadPacketsT extends Check implements PacketCheck {
private final double maxHorizontalDisplacement;
private final double minVerticalDisplacement;
private final double maxVerticalDisplacement;
public BadPacketsT(final GrimPlayer player) {
super(player);
// 1.7 and 1.8 seem to have different hitbox "expansion" values than 1.9+
// https://github.com/GrimAnticheat/Grim/pull/1274#issuecomment-1872458702
// https://github.com/GrimAnticheat/Grim/pull/1274#issuecomment-1872533497
double expansion = player.getClientVersion().isOlderThan(ClientVersion.V_1_9) ? 0.1 : 0;
maxHorizontalDisplacement = 0.3001 + expansion;
minVerticalDisplacement = -0.0001 - expansion;
maxVerticalDisplacement = 1.8001 + expansion;
}
// 1.7 and 1.8 seem to have different hitbox "expansion" values than 1.9+
// https://github.com/GrimAnticheat/Grim/pull/1274#issuecomment-1872458702
// https://github.com/GrimAnticheat/Grim/pull/1274#issuecomment-1872533497
private final boolean hasLegacyExpansion = player.getClientVersion().isOlderThan(ClientVersion.V_1_9);
private final double maxHorizontalDisplacement = 0.3001 + (hasLegacyExpansion ? 0.1 : 0);
private final double minVerticalDisplacement = -0.0001 - (hasLegacyExpansion ? 0.1 : 0);
private final double maxVerticalDisplacement = 1.8001 + (hasLegacyExpansion ? 0.1 : 0);
@Override
public void onPacketReceive(final PacketReceiveEvent event) {
if (event.getPacketType().equals(PacketType.Play.Client.INTERACT_ENTITY)) {
@@ -39,7 +43,7 @@ public class BadPacketsT extends Check implements PacketCheck {
}
// Make sure our target entity is actually a player (Player NPCs work too)
if (!EntityTypes.PLAYER.equals(packetEntity.getType())) {
if (!EntityTypes.PLAYER.equals(packetEntity.type)) {
// We can't check for any entity that is not a player
return;
}
@@ -49,7 +53,7 @@ public class BadPacketsT extends Check implements PacketCheck {
// 27/12/2023 - Dynamic values for more than just one entity type?
// 28/12/2023 - Player-only is fine
// 30/12/2023 - Expansions differ in 1.9+
final float scale = (float) packetEntity.getAttributeValue(Attributes.GENERIC_SCALE);
final float scale = (float) packetEntity.getAttributeValue(Attributes.SCALE);
if (targetVector.y > (minVerticalDisplacement * scale) && targetVector.y < (maxVerticalDisplacement * scale)
&& Math.abs(targetVector.x) < (maxHorizontalDisplacement * scale)
&& Math.abs(targetVector.z) < (maxHorizontalDisplacement * scale)) {
@@ -14,7 +14,7 @@ import com.github.retrooper.packetevents.util.Vector3f;
import com.github.retrooper.packetevents.util.Vector3i;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerBlockPlacement;
@CheckData(name = "BadPacketsU", experimental = true)
@CheckData(name = "BadPacketsU", description = "Sent impossible use item packet")
public class BadPacketsU extends Check implements PacketCheck {
public BadPacketsU(GrimPlayer player) {
super(player);
@@ -0,0 +1,41 @@
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.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
@CheckData(name = "BadPacketsV", description = "Did not move far enough", experimental = true)
public class BadPacketsV extends Check implements PacketCheck {
private int noReminderTicks;
public BadPacketsV(GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (!player.canSkipTicks() && isTickPacket(event.getPacketType())) {
if (event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION || event.getPacketType() == PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION) {
int positionAtLeastEveryNTicks = player.getClientVersion().isOlderThanOrEquals(ClientVersion.V_1_8) ? 20 : 19;
if (noReminderTicks < positionAtLeastEveryNTicks && !player.uncertaintyHandler.lastTeleportTicks.hasOccurredSince(1)) {
final double deltaSq = new WrapperPlayClientPlayerFlying(event).getLocation().getPosition()
.distanceSquared(new Vector3d(player.lastX, player.lastY, player.lastZ));
if (deltaSq <= player.getMovementThreshold() * player.getMovementThreshold()) {
flagAndAlert("delta=" + Math.sqrt(deltaSq));
}
}
noReminderTicks = 0;
} else {
noReminderTicks++;
}
}
}
}
@@ -2,11 +2,10 @@ 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;
@CheckData(name = "BadPacketsW", experimental = true)
public class BadPacketsW extends Check implements PacketCheck {
@CheckData(name = "BadPacketsW", description = "Interacted with non-existent entity", experimental = true)
public class BadPacketsW extends Check {
public BadPacketsW(GrimPlayer player) {
super(player);
}
@@ -0,0 +1,77 @@
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.PostPredictionCheck;
import ac.grim.grimac.player.GrimPlayer;
import ac.grim.grimac.utils.anticheat.update.PredictionComplete;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.player.GameMode;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEntityAction;
@CheckData(name = "BadPacketsX", experimental = true)
public class BadPacketsX extends Check implements PostPredictionCheck {
private boolean sprint;
private boolean sneak;
private int flags;
public BadPacketsX(GrimPlayer player) {
super(player);
}
@Override
public void onPredictionComplete(final PredictionComplete predictionComplete) {
if (!player.canSkipTicks()) {
if (flags > 0) {
setbackIfAboveSetbackVL();
}
flags = 0;
return;
}
if (player.isTickingReliablyFor(3)) {
for (; flags > 0; flags--) {
flagAndAlertWithSetback();
}
}
flags = 0;
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (player.gamemode == GameMode.SPECTATOR || isTickPacket(event.getPacketType())) {
sprint = sneak = false;
return;
}
if (event.getPacketType() == PacketType.Play.Client.ENTITY_ACTION) {
switch (new WrapperPlayClientEntityAction(event).getAction()) {
case START_SNEAKING, STOP_SNEAKING -> {
if (sneak) {
if (player.canSkipTicks() || flagAndAlert()) {
flags++;
}
}
sneak = true;
}
case START_SPRINTING, STOP_SPRINTING -> {
if (player.inVehicle()) {
return;
}
if (sprint) {
if (player.canSkipTicks() || flagAndAlert()) {
flags++;
}
}
sprint = true;
}
}
}
}
}
@@ -8,10 +8,7 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientHeldItemChange;
/**
* Checks for out of bounds slot changes
*/
@CheckData(name = "BadPacketsY")
@CheckData(name = "BadPacketsY", description = "Sent out of bounds slot id")
public class BadPacketsY extends Check implements PacketCheck {
public BadPacketsY(GrimPlayer player) {
super(player);
@@ -22,7 +19,7 @@ public class BadPacketsY extends Check implements PacketCheck {
if (event.getPacketType() == PacketType.Play.Client.HELD_ITEM_CHANGE) {
final int slot = new WrapperPlayClientHeldItemChange(event).getSlot();
if (slot > 8 || slot < 0) { // ban
if (flagAndAlert("slot="+slot) && shouldModifyPackets()) {
if (flagAndAlert("slot=" + slot) && shouldModifyPackets()) {
event.setCancelled(true);
player.onPacketCancel();
}
@@ -0,0 +1,32 @@
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;
@CheckData(name = "BadPacketsZ", experimental = true)
public class BadPacketsZ extends Check implements PacketCheck {
private boolean sent;
public BadPacketsZ(GrimPlayer player) {
super(player);
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() == PacketType.Play.Client.CLIENT_TICK_END) {
sent = false;
}
if (event.getPacketType() == PacketType.Play.Client.PLAYER_INPUT) {
if (sent) {
flagAndAlert();
}
sent = true;
}
}
}
Loaded 100 of 820 files, more files were not shown because too many files have changed in this diff. Show more