Each plugin class now has a private constructor and a static async
fromContext(context) that loads its datastores, constructs the instance
and attaches its handlers and hooks. This replaces the public constructor
followed by init(), and AutoRestart's start().
Datastores are loaded before construction and passed to the constructor,
so the definite assignment assertions on them are gone. Tests build the
plugins through fromContext and pass a wrapped logger in the context
instead of overwriting plugin.logger before init().
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- The instance sends every value of a feature, defaults included, so
update_config is one loop which sets each field and compares. The
stored table is the last set of values, and _apply is gone.
- values_equal compares table sizes before the contents.
- Protected entities are registered with register_on_object_destroyed
and forgotten in on_object_destroyed, which covers every way an
entity can go. The four removal handlers and the validity checks are
gone. Entities destroyed while the feature is disabled are swept when
it is enabled again. Saves from before the registrations table get it
through the Storage on_init callback.
- Spawn area applied the water offset twice and the pattern offset
never. The pattern tiles now move with the entities above them.
- pruneFeatureValues reads a validation result instead of catching an
error, and FeaturesPage hands its pending state and unsaved bar to
helpers.
- Shorter comments throughout.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Features can now be enabled, disabled, and configured from the web UI
while the game is running, without editing Lua files. The first five
features covered are AFK Kick, Chat Auto Reply, Death Markers, Mine
Depletion, and Station Auto Name.
Lua side: module/features.lua holds each feature's defaults, keeps the
overrides from the controller in storage, and patches them onto the
config table in place. Features.guard skips a feature's handlers while
it is disabled. The five config files move from exp_legacy into
exp_scenario/module/config and their control files now read config at
runtime instead of deciding at load which handlers to register. AFK
Kick times are now in minutes.
Controller side: features.ts lists the editable settings and their
defaults. Overrides that differ from the default are stored in
exp_scenario/features.json and guarded by the existing
exp_scenario.config.view/edit permissions. The instance plugin sends
them over rcon on start, on every change, and again after the
controller restarts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>