VonixGuardian — Developer API & Architecture
VonixGuardian is architected around a pure-Java engine decoupled from Minecraft internal classes, surrounded by thin loader-specific event bridges.
1. Engine Layering & Architecture
Section titled “1. Engine Layering & Architecture”┌─────────────────────────────────────────────────────────────┐│ Third-Party Mods ││ (Soft-dep via Reflection or PreLogEvent) │└──────────────────────────────┬──────────────────────────────┘ │┌──────────────────────────────▼──────────────────────────────┐│ mc-<ver>/{fabric, forge, neoforge} Loader Glue ││ (Event handlers, Mixins, WorldMutator, OpLevelFallback) │└──────────────────────────────┬──────────────────────────────┘ │┌──────────────────────────────▼──────────────────────────────┐│ mc-<ver>/common Module ││ (Mojmap command tree, NBT codecs, EntitySentinel) │└──────────────────────────────┬──────────────────────────────┘ │┌──────────────────────────────▼──────────────────────────────┐│ core/ Pure-Java Engine ││ (JDBC DAO, Ring-buffer Queue, QueryParser, Rollback) ││ *Zero Minecraft or Loader Dependencies* │└─────────────────────────────────────────────────────────────┘core/: Pure-Java engine containing the JDBC connection manager, ring-buffer queue, audit logger, filter parser, and rollback mathematics. Contains zero Minecraft imports.mc-<ver>/common/: Minecraft-specific code shared across all loaders for a given MC version. Uses official Mojang mappings (Mojmap).mc-<ver>/{loader}/: Thin glue modules (~30–50 LOC per loader) that register loader event hooks and mixins.
2. Public Java API Surface
Section titled “2. Public Java API Surface”Integrations interact through the public API package: network.vonix.guardian.core.api.
Key Interfaces
Section titled “Key Interfaces”network.vonix.guardian.core.Guardian— Primary runtime singleton. ImplementsEventSubmitterand exposes theGuardianDao.network.vonix.guardian.core.api.VonixGuardianAPI— Helper interface offering typed convenience lookups:hasPlaced(world, x, y, z, timeWindow)hasRemoved(world, x, y, z, timeWindow)queueLookup(filter, callback)logPlacement(player, blockState, world, x, y, z)logRemoval(player, blockState, world, x, y, z)logChat(player, message)logCommand(player, commandString)
Typed Lookup Result Classes
Section titled “Typed Lookup Result Classes”Query results are returned as strongly-typed result records:
BlockLookupResultContainerLookupResultItemLookupResultInventoryLookupResultSessionLookupResultUsernameLookupResultMessageLookupResultSignLookupResult
3. Recommended Soft-Dependency Pattern
Section titled “3. Recommended Soft-Dependency Pattern”To avoid creating a hard crash when VonixGuardian is not installed on a user’s server, interact via reflection:
package com.example.mymod.compat;
import java.lang.reflect.Method;import java.util.UUID;
public final class GuardianCompat { private static final boolean AVAILABLE; private static Object GUARDIAN_INSTANCE; private static Method SUBMIT_KILL_METHOD;
static { boolean ok = false; try { // Check loader accessor (Fabric example) Class<?> loaderCls = Class.forName("network.vonix.guardian.fabric.VonixGuardianFabric"); GUARDIAN_INSTANCE = loaderCls.getMethod("guardian").invoke(null); if (GUARDIAN_INSTANCE != null) { Class<?> submitterCls = Class.forName("network.vonix.guardian.core.event.EventSubmitter"); SUBMIT_KILL_METHOD = submitterCls.getMethod("submitEntityKill", UUID.class, String.class, String.class, int.class, int.class, int.class, String.class, String.class); ok = true; } } catch (Throwable ignored) { // VonixGuardian not installed or still booting } AVAILABLE = ok; }
public static boolean isAvailable() { return AVAILABLE; }
public static void logCustomKill(UUID killer, String killerName, String world, int x, int y, int z, String victim, String tag) { if (!AVAILABLE) return; try { SUBMIT_KILL_METHOD.invoke(GUARDIAN_INSTANCE, killer, killerName, world, x, y, z, victim, tag); } catch (Throwable t) { // Never allow an audit failure to interrupt game logic } }}4. PreLogEvent Extensibility
Section titled “4. PreLogEvent Extensibility”Third-party mods can intercept, modify, or cancel audit actions before they are enqueued into the writer pipeline.
- Fabric: Subscribed via
PreLogCallback.EVENT.register((action) -> { ... }). - Forge / NeoForge: Standard
@SubscribeEventlistener onPreLogEvent.
// Example: Cancel logging for a custom mini-game arena@SubscribeEventpublic void onPreLog(PreLogEvent event) { if (event.getAction().getWorldKey().equals("minigame:spleef_arena")) { event.setCanceled(true); // Action dropped before reaching queue }}5. Universal Griefing Attribution Chain
Section titled “5. Universal Griefing Attribution Chain”When an entity causes damage or modifies blocks, the loader’s AttributionResolver walks this hierarchy to extract the true responsible player UUID:
- Direct Player: Source entity is already a
ServerPlayer. - Controlling Passenger: Inspects
entity.getControllingPassenger(). Blames the player riding a dragon, horse, or vehicle. TamableAnimalOwner: Inspectsanimal.getOwnerUUID(). Catches modded tamed creatures.OwnableEntityOwner: Broad vanilla interface implemented by custom projectiles and summons.ProjectileShooter: Recursively walksprojectile.getOwner()until a living source is found.- Recent Interactor: Inspects the entity’s latest interaction cache.
The originating entity ID is stored in source_tag (e.g. #mob:dragonmounts:fire_dragon), while the discovered player UUID is stored in actor_uuid.