"safe" suggested the data being written survives a crash, it only
guarantees the old file is either kept or fully replaced. The new name
says what it does. No alias, plugin API breaks are allowed in minor
versions and the 2.1 migration guide lists the rename.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com>
While the host has no controller session, events between the instance
and the controller are dropped in both directions, and research_sync
only synced technologies on instance start. A technology finished during
the outage stayed unresearched on the controller and on every other
instance until the instance restarted.
On a new session the instance now runs the same technology sync as on
start, before taking the cluster queue. Contributions made while the
controller is unreachable are summed per technology and sent on connect
or resume, since progress from several instances can't be rebuilt from a
state sync that keeps the highest progress. A finish made while the
connection was dropped triggers the sync on resume too.
sync_technologies now runs while the game is running, so it skips
writing progress to a technology that finished after the dump.
Fixes#1123
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace ESLint, typescript-eslint, eslint-plugin-node and the flat
config helpers with vite-plus, which runs Oxlint for vp lint. The rules
are carried over from eslint.config.mjs by @oxlint/migrate into the lint
section of the root vite.config.ts. The formatting rules ESLint
deprecated run as @stylistic rules through Oxlint's JS plugin support,
and disable comments naming them are updated to the @stylistic names.
@stylistic understands TypeScript syntax that the core rules skipped,
so the autofix adds missing semicolons and spaces in type literals and
aliases. Leading | and & in multiline types stay where they were.
Oxlint's node/no-sync also reports identifiers ending in Sync that are
not calls. The test helper techSync is renamed and the two other names
are ignored.
Refs #1127
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace webpack and Module Federation with Vite 8. The controller build
emits one entry per shared module (lib, web_ui, typebox, antd, react,
react-dom, react-router) and lists them in manifest.json. The controller
turns that into an import map in index.html, and plugins are built as
ES modules that import the shared modules by name and are loaded with
import().
The shared Vite setup lives in @clusterio/web_ui/vite.mjs. Plugins use
clusterioPlugin(), which exposes index, package.json and web/index under
the same keys the webpack template used. The --dev and --dev-plugin
flags now run the Vite dev server in middleware mode with hot module
replacement.
Browser polyfills move from web_ui to lib, which is the code that needs
them, and lib sets the process and Buffer globals itself.
Refs #1127
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A QueueEvent arriving in the same socket read as a QueueSyncRequest reply is
applied before the reply, which then wrote the older queue over it. Skip the
reply when a QueueEvent was applied while it was in flight.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
research_queue_api is compat.version_ge("2.0.56"), named like player_sync's version checks, so it doesn't read as a
setting. Handlers check it at the top; only the three research queue events are registered behind it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Document the cluster research queue in the plugin README and the root
README. Review fixes: ipairs for queue order, event annotations on the new
Lua handlers, an IpcQueue type, a test for clearing the queue, and drop the
controller import from test/missing.js.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The last event of a tick now decides which player the queue edit is attributed to.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The save module reports queue edits on a following tile, applies the cluster
queue (dropping unknown technologies), and offers a lab-window checkbox.
All new events are gated on Factorio 2.0+.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Forward queue edits and follow requests from the save to the controller,
and apply controller broadcasts and the start-up sync to the save.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- QueueUpdateEvent, QueueEvent and QueueSyncRequest messages.
- The controller keeps one queue (max 7 names) in research_queue.json, saved with the other data.
- An update that changes the queue replaces it and is broadcast as QueueEvent; an equal update is ignored.
- QueueSyncRequest returns the queue and seeds it from the request when the queue is empty.
- A finished technology (completing contribution, advancing FinishedEvent, technology sync) drops its first queue entry without a broadcast.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The on_research_finished handler read ignore_research_finished from the
research_sync global, which is the table of RCON functions and never has that
field. The flag that sync_technologies and research_technology set lives on the
script data, so the check never returned and research that came from the
controller was sent back as newly finished. The handler now reads the flag from
the script data.
Co-authored-by: ILLISIS <jayson.harris01@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Configure the controller, host and ctl packages as optional peer
dependencies to prevent them being pulled in and installed by plugins in
environments that don't have them. This means that a host only install
with a plugin that uses both host and controller will not cause the
controller package to be installed as well.
The web_ui package is only used when building the web interface. This
only happens during development and is thus adequatly covered by the
existing entry of web_ui in the devDependencies specification.
Removing web_ui from peer dependencies prevents it from being pulled in
by npm during a regular installation. Since it's never used in a
regular installation this removed a whole lot of bloat.
Migrate the usage of CommonJS specific code and imports to ESM. Roughly
summarised this:
- Changes all require() calls to import statement or expressions.
- Changes usage of module.exports to export statements.
- Replaces require.resolve with import.meta.resolve.
- Replaces conditional imports with conditional subpath imports.
- Replaces module === require.main with import.meta.main.
- Adds the full filename with extention to all relative imports.
- Changes all usage of __dirname and __filename to their import.meta
equivalents.
- Sets "type": "module" in package.json files.
- Removes usage of "use strict".
- Adds .ts an an alias of .js for the webpack build.
Due to differences in how require and import resolves files the plugin
entrypoints will have to include the filename and extension after this
migration in order to work.
The largest source was compat.lua returning the setmetatable call
directly, which made emmylua infer the module type from the metatable
rather than the LibCompat class, hiding every field from consumers.
The remaining fixes are nil guards on gui element and character
accesses, type annotations for research_sync's script data and
player_auth's rcon arguments, casts where the api's read/write union
types are wider than the values at runtime, and scoped diagnostic
disables for the vendored json.lua and the version fallback code that
touches apis removed from the current typedefs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
These packages are obsoleted by the promises API to the built-in Node fs
module. The fs-extra package is also causing problems with broken APIs
that don't behave the same as Node's fs module, and throwing errors
without code properties on them.