# Overview ## What NetworkCore is A single Hytale plugin that every other KweebecNet plugin depends on. It owns three concerns that don't belong in any individual gamemode or feature plugin: 1. **Metrics** - counters, gauges, and timers exposed over a Prometheus-compatible HTTP endpoint 2. **Cross-server messaging** - Redis pub/sub with a small JSON envelope, plus a request/response RPC layer on top 3. **Server presence** - every server in the network heartbeats to Redis, every other server learns about it within a few seconds and is notified via local Hytale events ## Why it's split out If every gamemode plugin opened its own Redis connection, registered its own metrics, and rolled its own service-discovery, you'd have N copies of the same logic, N config blocks to keep in sync, and N places to add TLS when the time comes. Putting it in one plugin means: - Plugins don't carry Redis as a dependency. They depend on NetworkCore's `MessageBus` interface. - A single config file owns Redis + network secrets. - When we add TLS, an audit log, or a different backend, only NetworkCore changes. ## What lives in NetworkCore (and what doesn't) **In:** - The MessageBus, ServerRegistry, MetricsService, RpcClient - Auth-token verification on inbound messages - The /networkcore admin command - Built-in metrics (player count, JVM memory) **Out:** - Player profiles, stats, currency - those belong in a separate plugin (probably backed by MySQL) - Chat, parties, queues - separate plugins that *use* the MessageBus - World/match management - the existing MinigameCore-style plugins keep that role The rule of thumb: if it's something every plugin should be able to use, it's in NetworkCore. If it's a feature you'd ship to players, it's its own plugin. ## How plugins use it Two access patterns, both backed by the same internal service registry: ```java NetworkCore core = NetworkCore.getInstance(); // Convenience getters for the bundled services core.getMetrics().counter("matches_started", Map.of("game", "bridge_duel")).inc(); core.getMessageBus().publish("party.invite", invite); // Generic lookup for anything (including services other plugins contribute) MetricsService metrics = core.getService(MetricsService.class); ``` A plugin that wants to contribute its own service to the registry can do: ```java core.registerService(MyPartyService.class, new MyPartyServiceImpl()); ``` Other plugins then resolve it via `core.getService(MyPartyService.class)`. No DI framework, just a typed map. ## Lifecycle NetworkCore uses the standard Hytale plugin lifecycle: - `setup()` - load config, generate or read the server id, register the admin command, register MetricsService (built-ins included). Singleton becomes available here. - `start()` - open the Redis connection, bind the Prometheus HTTP server, start the heartbeat, publish a hello to the network. - `shutdown()` - publish a goodbye, stop the heartbeat, close Redis and the HTTP server. Dependent plugins should resolve services in their own `start()`, not `setup()`. Hytale's dependency ordering guarantees we finish `setup()` before any dependent plugin's `start()` runs, but it does not guarantee we finish `start()` first - so a `getMessageBus()` call from another plugin's `setup()` may return null.