This commit is contained in:
2026-05-26 00:11:45 -04:00
commit 296c233157
41 changed files with 2829 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
# 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.