### Integration Example: Listening to Flag Events
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/events.md
A complete plugin example demonstrating how to enable the plugin, get the event bus, listen for FlagEvents, and handle violations by logging and kicking players.
```java
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.event.EventBus;
import ac.grim.grimac.api.event.events.FlagEvent;
import ac.grim.grimac.api.plugin.GrimPlugin;
import org.bukkit.plugin.java.JavaPlugin;
public class MyAntiCheatPlugin extends JavaPlugin {
@Override
public void onEnable() {
EventBus bus = GrimAPI.INSTANCE.getEventBus();
FlagEvent.Channel flagChannel = bus.get(FlagEvent.class);
// Listen to violations
flagChannel.listen((player, check, verbose) -> {
handleViolation(player, check, verbose);
});
getLogger().info("Listening to GrimAC violations");
}
private void handleViolation(GrimPlayer player, Check check, String verbose) {
String name = player.getName();
String checkName = check.getCheckName();
double vl = check.getViolations();
getLogger().info(name + " flagged by " + checkName + " (VL: " + vl + ")");
// Perform custom action
if (vl > 100) {
player.getPlayer().kickPlayer("Suspected cheating");
}
}
}
```
--------------------------------
### Example Check Configuration
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/configuration.md
An example demonstrating the configuration for a specific check, 'badpackets.a'.
```yaml
badpackets:
a:
decay: 0.05
setbackvl: 25.0
displayname: "BadPackets A"
description: "Checks for invalid packet sequences"
```
--------------------------------
### GrimAPI Initialization
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimAPI.md
Methods for initializing, starting, and stopping the GrimAPI. Ensure `load()` is called before `start()` or `stop()`.
```APIDOC
## GrimAPI Initialization
### `void load(PlatformLoader platformLoader, Initable... platformSpecificInitables)`
Initialize GrimAPI with platform-specific loader and modules.
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Parameters
- `platformLoader` (PlatformLoader) - Required - Platform implementation (Bukkit, Fabric, or Folia)
- `platformSpecificInitables` (Initable[]) - Optional - Platform-specific initialization modules
### Returns
`void`
### Throws
- `IllegalStateException` — If called more than once
### Request Example
```java
PlatformLoader loader = new BukkitPlatformLoader(plugin);
GrimAPI.INSTANCE.load(loader);
GrimAPI.INSTANCE.start();
```
### `void start()`
Start all managers and begin anticheat processing. Must call `load()` first.
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Returns
`void`
### Throws
- `IllegalStateException` — If `load()` was not called
### Request Example
```java
GrimAPI.INSTANCE.start();
```
### `void stop()`
Stop all managers and shut down anticheat. Server shutdown or plugin unload.
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Returns
`void`
### Throws
- `IllegalStateException` — If `load()` was not called
```
--------------------------------
### Custom Configuration Implementation
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/configuration.md
Shows how to implement a custom configuration manager, for example, loading from a database.
```java
public class DatabaseConfig implements ConfigManager {
@Override
public void reload() throws Exception {
// Load from database
}
@Override
public String getString(String key, String def) {
// Query database
}
// ... implement other methods
}
// Register
ConfigManager config = new DatabaseConfig();
GrimAPI.INSTANCE.getExternalAPI().reload(config);
```
--------------------------------
### GrimAPI Plugin Integration Example
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/types.md
Example of how a plugin can integrate with GrimAC using the GrimAPI to access event buses and player data.
```java
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.GrimUser;
import ac.grim.grimac.api.event.EventBus;
import ac.grim.grimac.api.event.events.FlagEvent;
public class MyPlugin {
public void onEnable() {
// Access API
var api = GrimAPI.INSTANCE.getExternalAPI();
var bus = api.getEventBus();
// Listen to flag events
FlagEvent.Channel flagChannel = bus.get(FlagEvent.class);
flagChannel.listen((player, check, verbose) -> {
System.out.println(player.getName() + " flagged " + check.getCheckName());
});
// Get player
GrimUser user = api.getGrimUser(uuid);
if (user != null) {
System.out.println(user.getName() + " ping: " + user.getTransactionPing());
}
}
}
```
--------------------------------
### Example: Listen to Flag Events
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/events.md
Register a listener to the FlagEvent channel to receive notifications about player flags. This example demonstrates how to access player, check, and verbose information, and react to specific check types.
```java
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.event.EventBus;
import ac.grim.grimac.api.event.events.FlagEvent;
import ac.grim.grimac.checks.impl.badpackets.BadPacketsA;
public class MyPlugin {
public void onLoad() {
EventBus bus = GrimAPI.INSTANCE.getEventBus();
FlagEvent.Channel flagChannel = bus.get(FlagEvent.class);
// Listen to all flags
flagChannel.listen((player, check, verbose) -> {
String checkName = check.getCheckName();
double vl = check.getViolations();
System.out.println(player.getName() + " flagged by " + checkName +
" (VL: " + vl + ") - " + verbose);
// React to specific checks
if (check instanceof BadPacketsA) {
System.out.println("BadPackets A detected!");
}
});
}
}
```
--------------------------------
### Initialize GrimAPI Before Use
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/errors.md
Avoid calling GrimAPI methods before initialization. Ensure GrimAPI.INSTANCE.load() is called during plugin setup.
```java
// WRONG - GrimAPI not loaded yet
GrimAPI.INSTANCE.getScheduler(); // Throws IllegalStateException
// CORRECT - After load()
GrimAPI.INSTANCE.load(platformLoader);
GrimAPI.INSTANCE.start();
GrimAPI.INSTANCE.getScheduler(); // Works
```
--------------------------------
### Integration Patterns
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/INDEX.md
Examples and guidance on integrating Grim Anticheat with other plugins or systems.
```APIDOC
## Integration Examples
This section provides documented integration patterns for Grim Anticheat.
### Available Patterns:
- Listen to violations
- Access player data
- Manage alerts
- Schedule async tasks
- Reload configuration
- Register message variables
- Custom config managers
- Event listener best practices
```
--------------------------------
### SQLite Initialization Log Example
Source: https://github.com/grimanticheat/grim/wiki/Database
This log message confirms that Grim has initialized using the SQLite backend and is employing its modern dialect.
```text
[grim-datastore] SQLite engine 3.49.1 - using modern dialect
```
--------------------------------
### Access Configuration Manager
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimAPI.md
Get the BaseConfigManager to access configuration settings. This example shows how to retrieve a double value with a default.
```java
double decay = GrimAPI.INSTANCE.getConfigManager()
.getDoubleElse("badpackets.a.decay", 0.05);
```
--------------------------------
### MariaDB Startup Log Example
Source: https://github.com/grimanticheat/grim/wiki/Database
This log message indicates that Grim has successfully connected to a MariaDB server and is using its specific dialect for operations.
```text
[grim-datastore] MariaDB engine 10.11.16-MariaDB-... - using MariaDB dialect
```
--------------------------------
### Initialize GrimAPI
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimAPI.md
Load GrimAPI with a platform loader and optional platform-specific modules. This method must be called before start() and can only be called once.
```java
PlatformLoader loader = new BukkitPlatformLoader(plugin);
GrimAPI.INSTANCE.load(loader);
GrimAPI.INSTANCE.start();
```
--------------------------------
### Gradle Setup for GrimAPI
Source: https://github.com/grimanticheat/grim/wiki/Developer-API
Add GrimAC's snapshot repository and compileOnly dependency for GrimAPI in your Gradle build file.
```kotlin
repositories {
maven {
name = "grimacSnapshots"
url = uri("https://repo.grim.ac/snapshots")
}
}
dependencies {
compileOnly("ac.grim.grimac:GrimAPI:1.3.2.1")
}
```
--------------------------------
### Accessing Server Information and Commands
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/QUICK-REFERENCE.md
Get server TPS, platform implementation details, and dispatch commands.
```java
PlatformServer server = GrimAPI.INSTANCE.getPlatformServer();
double tps = server.getTPS();
String impl = server.getPlatformImplementationString();
server.dispatchCommand(sender, "command");
Sender console = server.getConsoleSender();
```
--------------------------------
### Start GrimAPI Processing
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimAPI.md
Initiate all managers and anticheat processing. Ensure load() has been called prior to invoking this method.
```java
GrimAPI.INSTANCE.start();
```
--------------------------------
### Custom Check Configuration Example
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Check.md
Demonstrates how checks can be configured via YAML. This allows overriding default values like decay, setback thresholds, and display names.
```yaml
badpackets:
a:
decay: 0.05 # Override default decay
setbackvl: 25 # Override default setback threshold
displayname: "Suspicious Packets" # Custom alert name
description: "Detects invalid packet patterns"
```
--------------------------------
### Access Event Bus
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimAPI.md
Retrieve the EventBus for subscribing to and publishing events. This example demonstrates listening for FlagEvents.
```java
EventBus bus = GrimAPI.INSTANCE.getEventBus();
FlagEvent.Channel flagChannel = bus.get(FlagEvent.class);
flagChannel.listen((player, check, verbose) -> {
// Handle flag event
});
```
--------------------------------
### Clone Grim Repository
Source: https://github.com/grimanticheat/grim/blob/2.0/README.md
Clone the GrimAC repository from GitHub to start compiling from source. Navigate into the cloned directory.
```bash
git clone https://github.com/GrimAnticheat/Grim.git
cd Grim
```
--------------------------------
### Example: Listen to GrimReloadEvent
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/events.md
Register a listener for GrimReloadEvents to be informed about configuration reload status. The listener receives a boolean indicating success or failure.
```java
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.event.EventBus;
import ac.grim.grimac.api.event.events.GrimReloadEvent;
public class MyPlugin {
public void onLoad() {
EventBus bus = GrimAPI.INSTANCE.getEventBus();
GrimReloadEvent.Channel reloadChannel = bus.get(GrimReloadEvent.class);
// Listen to config reloads
reloadChannel.listen(success -> {
if (success) {
System.out.println("GrimAC config reloaded successfully");
} else {
System.out.println("GrimAC config reload failed");
}
});
}
}
```
--------------------------------
### Get Data Storage Providers
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/QUICK-REFERENCE.md
Retrieve DataStoreProvider instances for MySQL and SQLite. Providers are configured via config.yml.
```java
BackendRegistry registry = GrimAPI.INSTANCE
.getBackendRegistry();
DataStoreProvider mysql = registry.getProvider("mysql");
DataStoreProvider sqlite = registry.getProvider("sqlite");
// Providers are configured via config.yml
```
--------------------------------
### Platform Enumeration
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/types.md
Enumerates supported server platforms like Fabric, Bukkit, and Folia. Includes a method to get the platform name.
```java
public enum Platform {
FABRIC("fabric"), // Fabric loader
BUKKIT("bukkit"), // Bukkit/Paper/Spigot
FOLIA("folia") // Paper Folia (multi-threaded)
}
```
--------------------------------
### Maven Setup for GrimAPI
Source: https://github.com/grimanticheat/grim/wiki/Developer-API
Configure the GrimAC snapshot repository and add the provided scope dependency for GrimAPI in your Maven pom.xml.
```xml
grimac-snapshots
GrimAC's Maven Repository
https://repo.grim.ac/snapshots
ac.grim.grimac
GrimAPI
1.3.2.1
provided
```
--------------------------------
### Logging Undefined Message Placeholder
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/errors.md
Example showing how an undefined variable placeholder in a message template results in the placeholder being left as-is in the output.
```text
%player% = "Steve"
%undefined_var% = "%undefined_var%"
// Output: "Steve flagged - undefined: %undefined_var%"
```
--------------------------------
### Retrieve Configuration Values with Defaults
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/errors.md
Safely get configuration values, falling back to a default if a key is missing. This method never throws an exception for missing keys.
```java
// If "badpackets.a.decay" missing, uses default 0.05
double decay = config.getDoubleElse("badpackets.a.decay", 0.05);
```
--------------------------------
### Fabric Bootstrap for Grim Hooks
Source: https://github.com/grimanticheat/grim/wiki/Developer-API
Example of how to call the shared GrimHooks.register method from a Fabric mod's ModInitializer.
```java
import net.fabricmc.api.ModInitializer;
public final class MyFabricMod implements ModInitializer {
@Override
public void onInitialize() {
GrimHooks.register(this);
// GrimHooks.register("my-mod-id") also works when a mod id is easier.
}
}
```
--------------------------------
### Bukkit/Paper Bootstrap for Grim Hooks
Source: https://github.com/grimanticheat/grim/wiki/Developer-API
Example of how to call the shared GrimHooks.register method from a Bukkit/Paper plugin's onEnable method.
```java
public final class MyBukkitPlugin extends JavaPlugin {
@Override
public void onEnable() {
GrimHooks.register(this);
}
}
```
--------------------------------
### Access Platform Scheduler
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimAPI.md
Obtain the PlatformScheduler for scheduling asynchronous and synchronous tasks with platform abstraction. This example shows running a task asynchronously.
```java
GrimAPI.INSTANCE.getScheduler().getAsyncScheduler()
.runNow(plugin, () -> {
// Async task
});
```
--------------------------------
### Database Backend Configuration Failure
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/errors.md
Example of a YAML configuration where the database host is unreachable, causing the storage to fall back to in-memory mode.
```yaml
storage:
type: mysql
host: unreachable.host
# Connection fails at startup, falls back to in-memory
```
--------------------------------
### Punishment Configuration for Webhooks
Source: https://github.com/grimanticheat/grim/wiki/Discord-webhooks
Configure punishment rules and associated commands, including webhook alerts. This example sends a webhook alert for every 20 violations of 'Knockback' or 'Explosion' checks.
```yaml
Punishments:
Knockback:
remove-violations-after: 300
checks:
- "Knockback"
- "Explosion"
commands:
- "5:5 [alert]"
- "20:20 [webhook]"
```
--------------------------------
### Get Grim Version and Tick Info
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/QUICK-REFERENCE.md
Retrieve the current Grim version, the current tick count, and check if the API has started.
```java
String version = GrimAPI.INSTANCE.getExternalAPI()
.getGrimVersion();
int tick = GrimAPI.INSTANCE.getExternalAPI()
.getCurrentTick();
boolean started = GrimAPI.INSTANCE.getExternalAPI()
.hasStarted();
```
--------------------------------
### Access Platform Player Factory
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimAPI.md
Get the PlatformPlayerFactory to convert UUIDs or names into platform-specific player objects. This example retrieves a player from a UUID.
```java
PlatformPlayer player = GrimAPI.INSTANCE.getPlatformPlayerFactory()
.getFromUUID(uuid);
```
--------------------------------
### Example Log Output for Newer SQLite Engine
Source: https://github.com/grimanticheat/grim/wiki/Database
Log messages indicating that the minecraft-sqlite-jdbc holder is newer than the bundled SQLite engine and that JDBC connections are being routed through the holder's classloader.
```text
[grim-datastore] minecraft-sqlite-jdbc holder is newer than bundled
(holder=3.53.0, bundled=3.21.0); routing JDBC through holder's child-first classloader
[grim-datastore] SQLite engine 3.53.0 - using modern dialect
```
--------------------------------
### Get GrimUser by UUID
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/README.md
Retrieve a GrimUser object using a player's UUID. This is a common starting point for accessing player-specific data within GrimAC.
```java
GrimUser user = GrimAPI.INSTANCE.getExternalAPI()
.getGrimUser(uuid);
```
--------------------------------
### GrimAPI - Main Entry Point
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/INDEX.md
The GrimAPI class serves as the main singleton entry point for interacting with the GrimAnticheat system. It provides access to core functionalities, lifecycle management, and platform detection.
```APIDOC
## GrimAPI
### Description
The main singleton entry point for the GrimAnticheat system. Provides access to all getter methods, lifecycle management functions, and platform detection capabilities.
### Class
GrimAPI
### Methods
- **getters**: Access to various system states and configurations.
- **lifecycle management**: Functions to start, stop, and manage the anticheat service.
- **platform detection**: Methods to identify the current operating environment.
### File
api-reference/GrimAPI.md
```
--------------------------------
### GrimAPI Initialization with Class Reference
Source: https://github.com/grimanticheat/grim/wiki/Developer-API
Alternative method for GrimAPI initialization when a direct platform instance is unavailable, using a class reference from the plugin.
```java
GrimPlugin grim = GrimAPIProvider.get().getGrimPlugin(GrimHooks.class);
```
--------------------------------
### Access Data Storage Backend Registry
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimExternalAPI.md
Get the registry for data storage backends, allowing access to providers like MySQL or NoSQL. This is the entry point for managing data persistence.
```java
BackendRegistry registry = GrimAPI.INSTANCE.getExternalAPI()
.getBackendRegistry();
DataStoreProvider mysql = registry.getProvider("mysql");
```
--------------------------------
### Get All Online Players
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Platform-APIs.md
Retrieves a collection of all currently connected players.
```Java
Collection getOnlinePlayers()
```
--------------------------------
### Get Online PlatformPlayer by UUID
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Platform-APIs.md
Retrieves an online player by their UUID.
```Java
PlatformPlayer getFromUUID(UUID uuid)
```
--------------------------------
### Get All Offline Players
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Platform-APIs.md
Retrieves a collection of all known offline players.
```Java
Collection getOfflinePlayers()
```
--------------------------------
### Method Signature Convention
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/README.md
Illustrates the documentation convention for method signatures, showing parameter types, names, and return types.
```plaintext
methodName(paramType paramName): returnType
```
--------------------------------
### MiniMessage Style Codes
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/configuration.md
Examples of using MiniMessage format for text styles.
```plaintext
Bold
Italic
Underlined
Strikethrough
```
--------------------------------
### hasStarted
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimExternalAPI.md
Checks if the GrimAC system has been initialized and is currently active.
```APIDOC
## hasStarted
### Description
Checks if GrimAC has started and is active.
### Method
`boolean hasStarted()`
### Response
#### Success Response
- **boolean** - True if GrimAC is active, false otherwise.
### Request Example
```java
if (GrimAPI.INSTANCE.getExternalAPI().hasStarted()) {
// Grim is running
}
```
```
--------------------------------
### MiniMessage Color Codes
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/configuration.md
Examples of using MiniMessage format for color codes in messages.
```plaintext
Red text
Green text
Blue text
Yellow text
Gold text
Cyan text
Magenta text
White text
Black text
Dark gray text
Gray text
```
--------------------------------
### Build Grim Anticheat from Source
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/OVERVIEW.md
Clone the Grim Anticheat repository and build the project using Gradle. The compiled artifacts will be located in the /build/libs directory.
```bash
git clone https://github.com/GrimAnticheat/Grim.git
cd Grim
./gradlew build
# Artifacts in /build/libs
```
--------------------------------
### Accessing the GrimAPI Instance
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/QUICK-REFERENCE.md
Obtain the main entry point for the GrimAPI and its external plugin API.
```java
// Main entry point
GrimAPI api = GrimAPI.INSTANCE;
// External plugin API
GrimExternalAPI external = api.getExternalAPI();
```
--------------------------------
### Get Online PlatformPlayer by Name
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Platform-APIs.md
Retrieves an online player by their name. The lookup is case-insensitive.
```Java
PlatformPlayer getFromName(String name)
```
--------------------------------
### PlatformLoader
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Platform-APIs.md
Handles the bootstrapping of platform implementations.
```APIDOC
## PlatformLoader
Platform implementation bootstrap.
```java
public interface PlatformLoader
```
### Methods
All return values from platform initialization. Called during `GrimAPI.load()`.
#### `PlatformScheduler getScheduler()`
Get async/sync task scheduler.
**Returns:** `PlatformScheduler` - See [PlatformScheduler](#platformscheduler) below
#### `PlatformPlayerFactory getPlatformPlayerFactory()`
Get player lookup factory.
**Returns:** `PlatformPlayerFactory` - See [PlatformPlayerFactory](#platformplayerfactory) below
#### `PacketEventsAPI> getPacketEvents()`
Get PacketEvents API for packet handling.
**Returns:** `PacketEventsAPI` - Packet interceptor
#### `ItemResetHandler getItemResetHandler()`
Get item reset utility for setbacks.
**Returns:** `ItemResetHandler` - Reset inventory items
#### `CommandService getCommandService()`
Get command registration.
**Returns:** `CommandService` - Register commands
#### `SenderFactory> getSenderFactory()`
Get message sender factory.
**Returns:** `SenderFactory` - Create message senders
#### `GrimPlugin getPlugin()`
Get Grim plugin instance.
**Returns:** `GrimPlugin` - Plugin metadata
#### `PlatformPluginManager getPluginManager()`
Get plugin queries.
**Returns:** `PlatformPluginManager` - Check plugin state
#### `PlatformServer getPlatformServer()`
Get server instance.
**Returns:** `PlatformServer` - Server operations
#### `MessagePlaceHolderManager getMessagePlaceHolderManager()`
Get placeholder processor.
**Returns:** `MessagePlaceHolderManager` - PlaceholderAPI (Bukkit)
#### `PermissionRegistrationManager getPermissionManager()`
Get permission registration.
**Returns:** `PermissionRegistrationManager` - Register permissions
#### `void registerAPIService()`
Initialize platform-specific API service.
**Returns:** `void`
**Called:** During `InitManager.load()`
```
--------------------------------
### Get PlatformPlayer from Native Player Object
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Platform-APIs.md
Converts a Bukkit or Fabric player object into a PlatformPlayer representation.
```Java
PlatformPlayer getFromNativePlayerType(Object playerObject)
```
--------------------------------
### Enable Debug Mode via System Property
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/configuration.md
Demonstrates how to enable GrimAC debug mode by setting a Java system property.
```bash
java -Dgrim.debug=true ...
```
--------------------------------
### Get Server TPS
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimAPI.md
Retrieve the server's Transactions Per Second (TPS) using the GrimAPI.
```java
double tps = GrimAPI.INSTANCE.getPlatformServer().getTPS();
```
--------------------------------
### MiniMessage Legacy Ampersand Codes
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/configuration.md
Examples of legacy ampersand color and style codes converted to MiniMessage format.
```plaintext
&c =
&a =
&9 =
&e =
&6 =
&b =
&d =
&f =
&l =
&o =
```
--------------------------------
### MiniMessage Component Creation and Sending
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/types.md
Demonstrates creating a colored text component using the Adventure library and sending it to a player.
```java
// Create component
Component component = Component.text("Player flagged")
.color(NamedTextColor.RED);
// Send to player
platformPlayer.sendMessage(component);
```
--------------------------------
### Gradle Build Command with Custom Options
Source: https://github.com/grimanticheat/grim/wiki/Versions-and-Versioning
Custom build options like disabling shading and relocation can be passed to Gradle.
```bash
./gradlew build -PshadePE=false -Prelocate=false
```
--------------------------------
### getPlatformServer
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimAPI.md
Obtains the server instance and utilities, including TPS, console access, and command execution.
```APIDOC
## getPlatformServer
### Description
Get server instance and utilities.
### Returns
`PlatformServer` - TPS, console, commands
### Example
```java
double tps = GrimAPI.INSTANCE.getPlatformServer().getTPS();
```
```
--------------------------------
### Get GrimAC Build Version
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimExternalAPI.md
Retrieve the current build version of GrimAC. This is useful for logging or compatibility checks.
```java
String version = GrimAPI.INSTANCE.getExternalAPI().getGrimVersion();
System.out.println("Grim version: " + version);
```
--------------------------------
### Configuration and Error Handling
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/INDEX.md
Documentation for configuring Grim Anticheat and understanding its error handling mechanisms.
```APIDOC
## Configuration and Error Handling
This section outlines how to configure Grim Anticheat and manage potential errors.
### Configuration
- **configuration.md**: Provides details on all configuration options available for Grim Anticheat.
### Error Handling
- **errors.md**: Documents error messages and their meanings, aiding in troubleshooting.
```
--------------------------------
### Default Configuration Settings
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/configuration.md
Illustrates the default settings for GrimAC checks when no configuration is provided.
```yaml
# All checks enabled with default settings
# Decay: 0.05 per tick
# Setback threshold: 25 VL
# Prefix: "[Grim] "
# Alerts: console enabled, verbose disabled
```
--------------------------------
### Gradle Build Command with System Property
Source: https://github.com/grimanticheat/grim/wiki/Versions-and-Versioning
The release flag can also be set as a JVM system property.
```bash
./gradlew build -Drelease=true
```
--------------------------------
### Get AlertManager
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimExternalAPI.md
Access the AlertManager to control alert settings and query alert history. Allows enabling/disabling console alerts.
```java
AlertManager alerts = GrimAPI.INSTANCE.getExternalAPI().getAlertManager();
alerts.setConsoleAlertsEnabled(true);
```
--------------------------------
### Reload Configuration via API
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/configuration.md
Demonstrates how to reload the GrimAC configuration using the provided Java API.
```java
ConfigManager config = GrimAPI.INSTANCE.getExternalAPI()
.getConfigManager();
GrimAPI.INSTANCE.getExternalAPI().reload(config);
```
--------------------------------
### Get ConfigManager
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimExternalAPI.md
Retrieve the current configuration manager to access and modify GrimAC settings. Handles file-based and custom configurations.
```java
ConfigManager config = GrimAPI.INSTANCE.getExternalAPI().getConfigManager();
if (config != null) {
double decay = config.getDoubleElse("badpackets.a.decay", 0.05);
}
```
--------------------------------
### PlatformLoader Interface
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Platform-APIs.md
Defines the bootstrap process for platform implementations.
```java
public interface PlatformLoader
```
--------------------------------
### Get OfflinePlatformPlayer by Name
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Platform-APIs.md
Retrieves an offline player's data using their name. The player may not be currently loaded.
```Java
OfflinePlatformPlayer getOfflineFromName(String name)
```
--------------------------------
### Get OfflinePlatformPlayer by UUID
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Platform-APIs.md
Retrieves an offline player's data using their UUID. The player may not be currently loaded.
```Java
OfflinePlatformPlayer getOfflineFromUUID(UUID uuid)
```
--------------------------------
### General Datastore Settings Configuration
Source: https://github.com/grimanticheat/grim/wiki/Database
Configuration for session reconstruction, write path, data retention, migration, name resolution, and history paging. 'write-path.queue-capacity' must be a power of two.
```yaml
database:
session:
gap-ms: 600000
scope-per-server: true
heartbeat-interval-ms: 30000
write-path:
queue-capacity: 16384
batch-size: 256
flush-interval-ms: 1000
warn-rate-ms: 10000
shutdown-drain-timeout-ms: 5000
wait-strategy: BLOCKING
retention:
session:
enabled: true
max-age-days: 90
violation:
enabled: true
max-age-days: 365
player-identity:
enabled: false
setting:
enabled: false
blob:
enabled: true
max-age-days: 30
migration:
skip: false
max-duration-ms: 0
name-resolution:
chain: [local-cache, offline-mode-uuid]
history:
entries-per-page: 15
group-interval-ms: 30000
server-name: "Prison"
```
--------------------------------
### Access Backend Registry
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimAPI.md
Get the BackendRegistry to access data storage backend providers like SQL, MongoDB, or Redis.
```java
GrimAPI.INSTANCE.getBackendRegistry();
```
--------------------------------
### Source File Reference Convention
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/README.md
Demonstrates the standard format for referencing source files within the documentation, including the file path and line numbers.
```plaintext
path/to/File.java:line-numbers
```
--------------------------------
### Check GrimAPI Initialization
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/README.md
Verify if the GrimAPI has been successfully initialized before proceeding with its usage. This is a crucial step for ensuring proper integration.
```java
GrimAPI.INSTANCE.getExternalAPI().hasStarted()
```
--------------------------------
### Bukkit/Paper Plugin GrimAPI Initialization
Source: https://github.com/grimanticheat/grim/wiki/Developer-API
Initialize GrimAPI and obtain the GrimPlugin instance for your Bukkit/Paper plugin. This should be done in onEnable.
```java
import ac.grim.grimac.api.GrimAPIProvider;
import ac.grim.grimac.api.GrimAbstractAPI;
import ac.grim.grimac.api.plugin.GrimPlugin;
import org.bukkit.plugin.java.JavaPlugin;
public final class MyPlugin extends JavaPlugin {
private GrimPlugin grimPlugin;
@Override
public void onEnable() {
GrimAbstractAPI api = GrimAPIProvider.get();
this.grimPlugin = api.getGrimPlugin(this);
}
}
```
--------------------------------
### GrimAPI Provider and Plugin Registration
Source: https://github.com/grimanticheat/grim/wiki/Developer-API
Demonstrates how to obtain the GrimAPI instance and register your plugin for event handling. This is the primary method for interacting with Grim's features.
```APIDOC
## GrimAPIProvider.get()
### Description
Retrieves the singleton instance of the GrimAbstractAPI, which is the entry point for all Grim API functionalities.
### Method
`GrimAbstractAPI GrimAPIProvider.get()`
### Endpoint
N/A (Java method call)
### Parameters
None
### Request Example
```java
import ac.grim.grimac.api.GrimAPIProvider;
import ac.grim.grimac.api.GrimAbstractAPI;
// ...
GrimAbstractAPI api = GrimAPIProvider.get();
```
### Response
#### Success Response
- **api** (GrimAbstractAPI) - The singleton instance of the Grim API.
### Response Example
```java
// GrimAbstractAPI instance is returned
```
## GrimAPI.getGrimPlugin(Object platformOwner)
### Description
Resolves and returns a `GrimPlugin` wrapper for your platform-specific plugin or mod. This wrapper is used for Grim-specific registrations, such as event handlers.
### Method
`GrimPlugin GrimAbstractAPI.getGrimPlugin(Object platformOwner)`
### Endpoint
N/A (Java method call)
### Parameters
- **platformOwner** (Object) - Required - The native platform object representing your plugin/mod (e.g., Bukkit `Plugin` instance, Fabric `ModInitializer`, or your mod id string). A `Class>` belonging to your plugin also works.
### Request Example
```java
import ac.grim.grimac.api.GrimAPIProvider;
import ac.grim.grimac.api.GrimAbstractAPI;
import ac.grim.grimac.api.plugin.GrimPlugin;
// ...
GrimAbstractAPI api = GrimAPIProvider.get();
Object myPluginInstance = this; // For Bukkit/Paper plugins
GrimPlugin grim = api.getGrimPlugin(myPluginInstance);
```
### Response
#### Success Response
- **grim** (GrimPlugin) - A Grim-specific wrapper for your plugin.
#### Response Example
```java
// GrimPlugin instance is returned
```
## EventBus.get(Class eventClass)
### Description
Retrieves the event bus instance, which allows you to subscribe to and handle Grim-specific events.
### Method
`EventBus EventBus.get()`
### Endpoint
N/A (Java method call)
### Parameters
None
### Request Example
```java
import ac.grim.grimac.api.GrimAPIProvider;
import ac.grim.grimac.api.event.EventBus;
// ...
GrimAbstractAPI api = GrimAPIProvider.get();
EventBus bus = api.getEventBus();
```
### Response
#### Success Response
- **bus** (EventBus) - The event bus instance.
#### Response Example
```java
// EventBus instance is returned
```
## EventBus.get(Class eventClass).onFlag(GrimPlugin plugin, FlagCallback callback)
### Description
Registers a callback to be executed when a `FlagEvent` occurs. This allows you to react to player flagging events within Grim.
### Method
`void EventBus.get(FlagEvent.class).onFlag(GrimPlugin plugin, FlagCallback callback)`
### Endpoint
N/A (Java method call)
### Parameters
- **plugin** (GrimPlugin) - Required - The `GrimPlugin` instance representing your plugin.
- **callback** (FlagCallback) - Required - An interface with a method `onFlag` that will be executed when the event is triggered. The callback receives `user`, `check`, `verbose`, and `cancelled` parameters.
### Request Example
```java
import ac.grim.grimac.api.GrimAPIProvider;
import ac.grim.grimac.api.event.EventBus;
import ac.grim.grimac.api.event.events.FlagEvent;
import ac.grim.grimac.api.plugin.GrimPlugin;
// Assuming 'grim' is your GrimPlugin instance and 'bus' is your EventBus instance
bus.get(FlagEvent.class).onFlag(grim, (user, check, verbose, cancelled) -> {
grim.getLogger().info(user.getName() + " flagged " + check.getCheckName());
return cancelled; // Return true to cancel the flag, false otherwise
});
```
### Response
#### Success Response
This method returns `void` and does not produce a direct response. The callback is registered.
#### Response Example
N/A
```
--------------------------------
### Check if GrimAC Has Started
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimExternalAPI.md
Determine if GrimAC is currently active and running on the server. Use this to ensure operations are performed only when the system is ready.
```java
if (GrimAPI.INSTANCE.getExternalAPI().hasStarted()) {
// Grim is running
}
```
--------------------------------
### Build GrimAC from Source
Source: https://github.com/grimanticheat/grim/blob/2.0/README.md
Compile the GrimAC project using Gradle. The resulting JAR files will be located in the platform-specific build/libs directories.
```bash
./gradlew build
```
--------------------------------
### Listen to and Fire FlagEvent using EventBus
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Managers.md
Demonstrates how to obtain the Channel for FlagEvent from the EventBus, register a listener, and fire the event. Requires an instance of EventBus.
```java
EventBus bus = GrimAPI.INSTANCE.getEventBus();
FlagEvent.Channel flagChannel = bus.get(FlagEvent.class);
flagChannel.listen((player, check, verbose) -> {
System.out.println(player.getName() + " flagged " + check.getCheckName());
});
// Later: fire event
flagChannel.fire(player, check, "verbose reason");
```
--------------------------------
### Retrieve Player Information
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/README.md
Get detailed information about a player using their UUID. This includes their name, client version, ping, and location.
```java
GrimUser user = GrimAPI.INSTANCE.getExternalAPI()
.getGrimUser(uuid);
if (user != null) {
System.out.println("Name: " + user.getName());
System.out.println("Version: " + user.getVersionName());
System.out.println("Ping: " + user.getTransactionPing());
System.out.println("Location: " + user.getLocation());
}
```
--------------------------------
### File Statistics Overview
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/INDEX.md
Displays a breakdown of file sizes and types within the Grim Anticheat project repository. Useful for understanding project structure and content distribution.
```text
README.md 1,227 lines (master index)
OVERVIEW.md 823 lines (architecture)
QUICK-REFERENCE.md 597 lines (examples)
CHECK-CATEGORIES.md 698 lines (all checks)
types.md 450 lines (data types)
events.md 540 lines (event system)
configuration.md 596 lines (config)
errors.md 487 lines (error handling)
api-reference/GrimAPI.md 156 lines
api-reference/GrimExternalAPI.md 252 lines
api-reference/GrimUser.md 350 lines
api-reference/Check.md 221 lines
api-reference/Managers.md 548 lines
api-reference/Platform-APIs.md 588 lines
Total: 5,879 lines
```
--------------------------------
### Gradle Build Command with Release Flag
Source: https://github.com/grimanticheat/grim/wiki/Versions-and-Versioning
Builds can be triggered with a release flag using Gradle.
```bash
./gradlew build -Prelease=true
```
--------------------------------
### Customize Configuration
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/OVERVIEW.md
Implement a custom configuration manager to override default settings. This snippet shows how to create a CustomConfig class that fetches string values from a database.
```java
public class CustomConfig implements ConfigManager {
@Override
public String getString(String key, String def) {
return database.query(key, def);
}
}
GrimAPI.INSTANCE.getExternalAPI()
.reload(new CustomConfig());
```
--------------------------------
### Access FlagEvent Channel
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/events.md
Get the specific channel for FlagEvents from the event bus. This channel is used to register listeners for player flag events.
```java
FlagEvent.Channel channel = GrimAPI.INSTANCE.getEventBus()
.get(FlagEvent.class);
```
--------------------------------
### Routing Setting to MySQL with Other Categories
Source: https://github.com/grimanticheat/grim/wiki/Database-Settings
Routes 'setting' and other specified categories to MySQL, enabling shared user choices across Grim instances.
```yaml
database:
routing:
violation: mysql
session: mysql
player-identity: mysql
setting: mysql
blob: none
```
--------------------------------
### Get GrimUser by UUID
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimExternalAPI.md
Retrieves the GrimUser object associated with a player's UUID. This is a blocking lookup. Returns null if the player is not tracked.
```java
GrimUser user = GrimAPI.INSTANCE.getExternalAPI().getGrimUser(uuid);
```
--------------------------------
### Get EntityScheduler
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Platform-APIs.md
Retrieves a scheduler tied to a specific entity. On Folia, this uses the entity-owning thread; on Bukkit/Fabric, it uses the main thread synchronously.
```Java
EntityScheduler getEntityScheduler()
```
--------------------------------
### Get RegionScheduler
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Platform-APIs.md
Retrieves a scheduler tied to the current region. On Folia, this uses the region-owning thread; on Bukkit/Fabric, it uses the main thread synchronously.
```Java
RegionScheduler getRegionScheduler()
```
--------------------------------
### PostgreSQL Database Configuration
Source: https://github.com/grimanticheat/grim/wiki/Database
Configuration for connecting to a PostgreSQL database. Ensure the 'postgres' section in 'databases/postgres.yml' is correctly set up.
```yaml
postgres:
host: "localhost"
port: 5432
database: "grim"
user: "postgres"
password: ""
extra-jdbc-params: ""
batch-flush-cap: 256
tables:
meta: grim_meta
checks: grim_checks
players: grim_players
sessions: grim_sessions
violations: grim_violations
settings: grim_settings
```
--------------------------------
### GrimAC Check Class Definition
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/OVERVIEW.md
Example of a custom check class definition in Java, extending the base Check class and using annotations for configuration.
```java
@CheckData(
name = "BadPackets A",
configName = "badpackets.a",
stableKey = "badpackets.duplicate_slot"
)
public class BadPacketsA extends Check {
@Override
public void onReload(ConfigManager config) { }
}
```
--------------------------------
### Get GrimPlugin Instance
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimExternalAPI.md
Retrieve the GrimPlugin metadata associated with a given plugin or extension instance. This is used for interacting with GrimAC's plugin system.
```java
GrimPlugin grimPlugin = GrimAPI.INSTANCE.getExternalAPI()
.getGrimPlugin(myPlugin);
```
--------------------------------
### Inspect Player Status with GrimAPI
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimUser.md
Demonstrates how to retrieve and display various status information for a player using the GrimAPI. Ensure GrimAPI and GrimUser are imported.
```java
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.GrimUser;
import java.util.UUID;
public class CheckPlayerStatus {
public void inspectPlayer(UUID uuid) {
GrimUser user = GrimAPI.INSTANCE.getExternalAPI()
.getGrimUser(uuid);
if (user == null) {
System.out.println("Player not tracked by Grim");
return;
}
System.out.println("Player: " + user.getName());
System.out.println("Version: " + user.getVersionName());
System.out.println("Ping: " + user.getTransactionPing() + "ms");
System.out.println("Location: " + user.getLocation());
System.out.println("Velocity: " + user.getVelocity());
System.out.println("On ground: " + user.isOnGround());
System.out.println("In water: " + user.isInWater());
System.out.println("Game mode: " + user.getGameMode());
}
}
```
--------------------------------
### Access Tick Manager
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimAPI.md
Get the TickManager to access the current server tick count. The server typically runs at 20 ticks per second.
```java
int currentTick = GrimAPI.INSTANCE.getTickManager().currentTick;
```
--------------------------------
### Get Player Data by UUID
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/Managers.md
Retrieve a tracked player object using their unique identifier (UUID). This is useful for accessing player-specific data and checks.
```java
GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager()
.getPlayer(uuid);
if (player != null) {
double violations = player.checkManager
.allChecks.get(BadPacketsA.class).violations;
}
```
--------------------------------
### Default Setting Routing to SQLite
Source: https://github.com/grimanticheat/grim/wiki/Database-Settings
Configures the 'setting' category to use SQLite as its default backend.
```yaml
database:
routing:
setting: sqlite
```
--------------------------------
### Integrate with GrimAC API
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/OVERVIEW.md
This snippet shows how to enable your plugin, verify GrimAC is loaded, and access the GrimAPI to listen for FlagEvents. Ensure GrimAC is a dependency in your plugin.yml.
```java
import ac.grim.grimac.GrimAPI;
import ac.grim.grimac.api.event.events.FlagEvent;
import org.bukkit.plugin.java.JavaPlugin;
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
// Verify Grim is loaded
if (!getServer().getPluginManager().isPluginEnabled("GrimAnticheat")) {
getLogger().severe("GrimAC not found!");
setEnabled(false);
return;
}
// Access API
GrimAPI api = GrimAPI.INSTANCE;
// Listen to violations
api.getEventBus().get(FlagEvent.class)
.listen((player, check, verbose) -> {
getLogger().info(player.getName() + " flagged by " +
check.getCheckName());
});
}
}
```
--------------------------------
### Listen to Flag Event Channel
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/OVERVIEW.md
Subscribe to the FlagEvent channel to receive notifications about player violations. This example shows how to cast the user to GrimPlayer for additional access.
```java
FlagEvent.Channel channel = bus.get(FlagEvent.class);
channel.listen((player, check, verbose) -> {
// Handle violation
// user instanceof GrimPlayer = true for casting
});
```
--------------------------------
### Detecting the Server Platform
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/QUICK-REFERENCE.md
Identify the current server platform (e.g., Folia, Bukkit, Fabric) to adapt behavior.
```java
Platform platform = GrimAPI.INSTANCE.getPlatform();
if (platform == Platform.FOLIA) {
// Advanced threading available
}
if (platform == Platform.BUKKIT) {
// Single-threaded
}
if (platform == Platform.FABRIC) {
// Fabric mods available
}
```
--------------------------------
### Get Current Server Tick
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/api-reference/GrimExternalAPI.md
Obtain the current server tick count. This can be used for time-sensitive operations, as the server runs at 20 ticks per second.
```java
int tick = GrimAPI.INSTANCE.getExternalAPI().getCurrentTick();
```
--------------------------------
### Access Player Data
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/OVERVIEW.md
Retrieve and display data for a specific player using their UUID. This snippet shows how to get a GrimUser object and access their name and location.
```java
GrimUser user = GrimAPI.INSTANCE.getExternalAPI()
.getGrimUser(uuid);
if (user != null) {
System.out.println(user.getName() + " at " + user.getLocation());
}
```
--------------------------------
### Multiple Event Listeners
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/events.md
Demonstrates registering multiple listeners for the same event channel, each handling different aspects like logging, alerting, or custom actions.
```java
FlagEvent.Channel flagChannel = bus.get(FlagEvent.class);
// Listener 1: Log all flags
flagChannel.listen((p, c, v) -> log(p, c));
// Listener 2: Alert on high VL
flagChannel.listen((p, c, v) -> {
if (c.getViolations() > 100) alert(p);
});
// Listener 3: Custom punishment
flagChannel.listen((p, c, v) -> {
if (isProbableCheat(c)) punish(p);
});
```
--------------------------------
### TaskHandle Usage for Task Management
Source: https://github.com/grimanticheat/grim/blob/2.0/_autodocs/types.md
Shows how to schedule an asynchronous task and manage its execution using TaskHandle, including cancellation.
```java
TaskHandle handle = GrimAPI.INSTANCE.getScheduler()
.getAsyncScheduler()
.runNow(plugin, () -> {
// Do work
});
// Later, cancel if needed
if (!handle.isCancelled()) {
handle.cancel();
}
```