-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Scope
- HyperFactions should integrate with HyCitizens (v1.6.0+) to enforce zone protection flags on citizen NPC interactions
- When a player interacts with a HyCitizens NPC inside a protected zone where
NPC_INTERACTis denied, the interaction should be blocked with a protection denial message - Integration should use the same reflection-based, fail-open pattern as the existing KyuubiSoft Core integration (
KyuubiSoftIntegration.java) - Integration should be optional — HyperFactions compiles and runs without HyCitizens present
- NPC role names (
HyCitizens_*,Citizen_*) should be added toisTameableCreatureRole()blocklist so citizens are classified as interactive NPCs, not tameable creatures - Admin status command (
/f admin integration) should show HyCitizens detection status
Developer API
HyCitizens provides a public developer API with documented event listeners and cancellable events:
- Entry point:
HyCitizensPlugin.get().getCitizensManager() - Listener registration:
manager.addCitizenInteractListener(event -> { ... }) - Event:
CitizenInteractEvent—getCitizen(),getPlayerRef(),setCancelled(true) - Cancellation: blocks all downstream processing (messages, commands, animations)
- Docs: API Overview | Events | Full Example
The API is stable and documented. We use reflection to access it (avoiding a compile-time dependency on HyCitizens), but the target classes and methods are part of the public API contract.
Implementation Details
Integration Path (reflection against public API)
The following reflection path targets HyCitizens' documented public API (v1.6.0+):
// 1. Get plugin instance (documented entry point)
Class<?> pluginClass = Class.forName("com.electro.hycitizens.HyCitizensPlugin");
Object plugin = pluginClass.getMethod("get").invoke(null);
// 2. Get CitizensManager (documented API surface)
Object manager = pluginClass.getMethod("getCitizensManager").invoke(plugin);
// 3. Load listener interface (public API)
Class<?> listenerClass = Class.forName("com.electro.hycitizens.events.CitizenInteractListener");
// 4. Create proxy that checks zone protection
Object proxy = Proxy.newProxyInstance(listenerClass.getClassLoader(),
new Class<?>[]{ listenerClass }, (p, method, args) -> {
if ("onCitizenInteract".equals(method.getName())) {
Object event = args[0]; // CitizenInteractEvent
// event.getPlayerRef() → PlayerRef
// event.getCitizen() → CitizenData (has position, world)
// Check ProtectionChecker.canInteract() at citizen position
// If blocked: event.setCancelled(true) + send denial message
}
return null;
});
// 5. Register listener (documented method)
manager.getClass().getMethod("addCitizenInteractListener", listenerClass)
.invoke(manager, proxy);Key Differences from KyuubiSoft Integration
| Aspect | KyuubiSoft | HyCitizens |
|---|---|---|
| API entry | CoreAPI.getInstance() |
HyCitizensPlugin.get().getCitizensManager() |
| API docs | Minimal | Full docs site |
| Interceptor type | CitizenDialogInterceptor (return true to block) |
CitizenInteractListener (setCancelled to block) |
| Position source | Player position | Citizen position (from CitizenData) |
| Interaction types | Dialog only | F-key + left-click |
| Cleanup | removeDialogInterceptor() |
removeCitizenInteractListener() |
NPC Role Classification
Add to isTameableCreatureRole() blocklist in ProtectionChecker.java:
HyCitizens_prefix — all dynamically generated citizen rolesCitizen_prefix — all 48 bundled fallback roles
Suggested File Structure
HyCitizensIntegration.java— new file, mirrorsKyuubiSoftIntegration.javapatternProtectionChecker.java— addHyCitizens_andCitizen_to role blocklistAdminIntegrationHandler.java— add HyCitizens status to integration display
Risks and Alternatives
-
PacketWatcher bypasses mixin interception — HyCitizens uses raw
PacketWatcher(SyncInteractionChainspackets) instead of Hytale's interaction event system. HyperProtect-Mixin'sSimpleInstantInteractionGatewill never fire for citizen interactions. The listener-based approach via the public API is the correct integration path. -
Position source — KyuubiSoft checks the player's position for zone lookup. HyCitizens provides both the player position (via
getPlayerRef()) and the citizen position (viaCitizenData). The citizen position is more appropriate since the NPC is the entity being interacted with. -
Plugin load order — if HyCitizens initializes after HyperFactions,
HyCitizensPlugin.get()may return null. Need to handle late registration, similar to the KyuubiSoft pattern. -
Alternative: PacketWatcher-level interception — register our own
PacketWatcherto interceptSyncInteractionChainsbefore HyCitizens processes them. Not recommended:PacketAdapters.registerInboundhas no priority system, making execution order unpredictable. The public API is the correct approach.
References and Media
- HyCitizens Developer API: https://hycitizens.com/docs/api/
- HyCitizens Events: https://hycitizens.com/docs/api/events
- HyCitizens Full Example: https://hycitizens.com/docs/api/full-example
- Existing KyuubiSoft integration (reference):
KyuubiSoftIntegration.java - HyCitizens decompiled analysis:
resources/docs/HyCitizens/(local documentation from v1.6.0 inspection) - HyCitizens GitHub: https://github.com/ElectroGamesDev/HyCitizens
Metadata
Metadata
Assignees
Labels
Type
Projects
Status