clusterio logs "using deprecated class export" for every node entrypoint
that exports a Base*Plugin subclass, and the web UI logs "using deprecated
class hooks" for WebPlugin classes. Every entrypoint now has a default
export function, like exp_auto_restart and the exp_roles web plugin.
The classes stay where they hold state, but no longer extend the base
classes. The constructor takes the load context and init() attaches the
hooks the base class used to attach from the on* methods, so the tests can
still call those methods directly. exp_server_ups sends its RCON command
through instance.sendRcon with the plugin name, which is what the removed
BaseInstancePlugin.sendRcon did.
The instance entrypoints of exp_commands, exp_gui, exp_legacy, exp_util
and exp_scenario were empty classes, kept only so the host loads the
plugin and patches its module into the save. An empty function does the
same.
The exp_groups web components read the subscriptions through exported
useGroups, useAssignments and useRoleMappings hooks instead of looking
the plugin up in control.plugins, which only holds class plugins.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clusterio #984 converted its packages to ESM, so a CommonJS plugin can
no longer import @clusterio/lib and plugin entrypoints must name the
full file. Every package gets "type": "module", entrypoints and relative
imports carry the .js extension, and the webpack configs become .cjs as
webpack-cli loads them with require. tsconfig.node.json moves from
node16 to nodenext to match clusterio, which needs it for the JSON
import attributes in its sources.
The tap tests and the shared test helpers use import and
import.meta.dirname. The test scripts pass --type-strip-only so tap
leaves lib's .ts subpath imports to Node's own type stripping, as its
TypeScript loader compiled them without a default export. The lua
runner resolves fengari from the test file it is given, since a bare
import from the shared test directory does not reach the plugin's
devDependencies.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every call site of expcore.roles now uses exp_roles, and the legacy module,
its config, and the glue which refreshed guis on role events are deleted.
Where a file only renamed the require and the permission strings the change is
mechanical; the rest:
- Jail is now "give the Jail role" and unjail "take it away". The role has a
higher priority than every other so holding it suppresses them, which is
what stashing and restoring the roles was for.
- The command role authority derives exp_scenario.command.<name> from the
command name, and the role parsers use player_outranks rather than comparing
indexes with their own root check.
- The admin and spectator triggers, and the gui refresh on role changes, live
in exp_scenario/control/roles.lua; the system commands trigger stays with
the command authority.
- The player list warn button is keyed on create_warning, the permission
the command behind it already required, and report on create_report. Both
were keyed on names no role held, so only root ever saw them.
- The warps and tasks configs say exp_roles where they said expcore.roles.
- The role tables the readme and player list read are replaced by
get_player_names and get_roles.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
emmylua only parses the inline cast as `--[[@as T]]`, the spaced form
`--[[ @as T ]]` is treated as a plain comment, so all 149 of them were
doing nothing.
LuaGuiElement.style is a union because a style name can be assigned to
it, so reading it back needs the cast.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Refactor server ups
* Use catalogs
* Move to own plugin
* Use web config
* Remove External.get_server_ups
* Update workspace version requirement
* Remove need for storage
* Add locale
* Fix CI