Add exp_roles plugin and scenario permissions - #448
Open
bbassie wants to merge 3 commits into
Open
Conversation
The role system is moving onto clusterio's own roles and permissions, which requires every in game action to exist as a real permission rather than a bare string held only by the lua config. Adds a permission for each of the 104 actions and 7 flags used by the legacy role config. Names are derived from the legacy action by a deterministic transform, exported so the lua side can apply the same mapping and keep existing call sites working. Command descriptions are taken from the existing locale entries so they match what players already see. Actions held by the Guest role are marked grantByDefault, since the in game default role and clusterio's default role are the same concept. Role management actions have no scenario permission; they map onto core.user.update_roles and core.role.list instead. Also corrects the /unjail description, which was a copy of /jail. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Clusterio already stores roles, the permissions they grant, and which user holds which role, along with a web UI for all three. What it does not have is the properties a role only needs in game, or a way for an instance to learn about any of it, since role and user updates are only sent to control connections. This plugin fills both gaps. The controller keeps a record per role holding the order, priority, short hand, tag, colour and auto assign threshold, created automatically for any role which does not have one. It then rebroadcasts roles and assignments on its own events so instances can follow them. The lua module presents the same interface the legacy expcore.roles module did, so the call sites can be moved over without being rewritten. Permission checks translate the legacy action strings using the same mapping exp_scenario defines. Two things replace features the legacy system had: - Priority replaces disallow. Only the roles with the highest priority a player holds are considered, so Jail can suppress every other role including the default one, without needing to take roles away first. - Assignments made in game are applied locally and then sent to the controller, which keeps assign_player synchronous for callers. A role which should never leave this map, such as one earned from time on the map, is assigned with assign_player_local instead. Roles earned from online time across the cluster are granted by the controller from the threshold on the role, using the online time clusterio already tracks. Nothing requires this plugin yet; moving the call sites off expcore.roles and removing the legacy config is left for a follow up. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Checked with the same LuaLS version and factorio library CI uses. The module now reports no findings; the 279 which remain are all pre-existing and main is already failing on them. Most were annotations rather than behaviour. Two are worth noting: - The role prototype is now its own class which the role inherits, since defining methods on a table annotated as the role counted as injecting fields into it. - The role change message is built from a literal locale key per branch. Building the key by concatenation gives a plain string where a localised string is wanted, which is the same finding the legacy module reports. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
Author
|
On the red lint check: it is pre-existing, not from this branch. The repo currently reports 279 findings across 51 files. This branch contributes zero — I ran the same LuaLS 3.18.2 and FMTK factorio library the workflow uses and fixed all 17 the new module initially had. Happy to leave it, or to fix the pre-existing ones in a separate PR if that would be useful — |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces the role storage half of
exp_legacy/expcore/roles.luawith clusterio's own roles and permissions. Clusterio already stores roles, the permissions they grant, and which user holds which role, plus a web UI for all three — so this adds only what it is missing, rather than reimplementing any of it.This does not yet move the call sites off
expcore.roles; nothing depends on the new plugin. That is deliberate, see "What is left" below.exp_scenario: permissions for the in game actionsThe role config held 105 action strings and 7 flags that only existed as bare strings in lua. Each is now a real clusterio permission, so it appears on the role page and can be granted like any other.
Names come from a deterministic transform, exported so the lua side derives exactly the same name and existing call sites keep working untouched:
Flags become permissions too —
player_has_flagandplayer_allowedare the same lookup, the only difference being that flags have change triggers, which stay in lua.Command descriptions are taken from the existing locale entries rather than written fresh, so they match what players already see in
/commands. Two permissions were referenced in code but missing from the role config (command/give-warning,command/collectdata); both are now defined.The 21 actions the Guest role granted are marked
grantByDefault, since the in game default role and clusterio's default role are the same concept.Three actions have no scenario permission — they map onto core ones instead:
command/assign-rolecore.user.update_rolescommand/unassign-rolecore.user.update_rolescommand/get-rolescore.role.listexp_roles: the sync pluginRoleUpdatesEventandUserUpdatesEventare bothdst: "control", so instances cannot subscribe to them. The controller plugin rebroadcasts on its own events, the same shapeexp_groupsuses.It stores one record per role for the properties clusterio's role does not carry — order, priority, short hand, tag, colour, auto assign threshold, block auto assign — created automatically for any role without one and removed when the role is deleted. These are edited on the core role page through a
componentExtra, so there is no second place to manage roles.There is no
default_role_idorroot_role_idsetting: the default role iscontroller.default_role_id, and root iscore.admin, which already short circuits every permission check.exp_roles.sync_modeisdisabled/enabled/bidirectional, matchingexp_groups.Priority replaces
disallowOnly the roles with the highest priority a player holds are considered, and those union as normal. Jail sits above everything else, so holding it suppresses every other role including the implicit default — which is what
disallow(default.allowed)was reaching for. It never worked, as the field isallowed_actions, notallowed, so it was passing nil.This means jail lives on the cluster like any other role, and
Jail.old_rolesis no longer needed: jailing becomes "add one role", unjailing "remove one role", with no stashing and restoring.Local assignments
Assignments made in game are applied locally first and then sent up, so
assign_playerstays synchronous for callers and nothing downstream has to learn about the round trip. Once the controller confirms, the role moves out of the local overlay. If it is refused, the instance rolls the change back.The same overlay carries assignments which should never leave the map —
assign_player_local, for roles earned from time on this map.Auto assign
Roles earned from online time across the cluster are granted by the controller from the threshold on the role, using the online time clusterio already tracks. Per map conditions stay in lua as local assignments. This drops the legacy
MapsPlayed/AfkTimeconditions in favour of online time alone.Verification
No factorio server was involved, so the lua was exercised directly under a stubbed environment:
config.playersview.What is left
Follow ups, kept separate because they are the risky part and deserve their own review:
require("modules.exp_legacy.expcore.roles"), simplify jail, delete the legacy module and config.override_player_rolesis not migrated, and there is no automatic export of live save data —Storage.registerkeys ondebug.getinfoshort_src and asserts it is not at runtime, so an rcon helper would register under the wrong name. A manual_exporttaking the table as an argument can be added if it turns out to be wanted.Also
One unrelated one line fix:
exp-commands_unjail.descriptionwas a copy of the/jailtext.🤖 Generated with Claude Code