Files
2026-05-26 00:11:45 -04:00

3.2 KiB

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:

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:

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.