mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2026-07-26 18:36:23 +09:00
Add instance plugin
This commit is contained in:
+148
-1
@@ -1,6 +1,153 @@
|
|||||||
import * as lib from "@clusterio/lib";
|
|
||||||
import { BaseInstancePlugin } from "@clusterio/host";
|
import { BaseInstancePlugin } from "@clusterio/host";
|
||||||
|
import * as lib from "@clusterio/lib";
|
||||||
|
import * as messages from "./messages";
|
||||||
|
|
||||||
|
export type IpcGroupUpdated = {
|
||||||
|
group_name: string,
|
||||||
|
group_id: number | undefined,
|
||||||
|
permissions: { is_blacklist: boolean, permissions: string[] },
|
||||||
|
};
|
||||||
|
|
||||||
|
export type IpcGroupDeleted = {
|
||||||
|
group_name: string,
|
||||||
|
group_id: number | undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type IpcPlayerAssignments = {
|
||||||
|
assignments: Record<string, number>,
|
||||||
|
};
|
||||||
|
|
||||||
export class InstancePlugin extends BaseInstancePlugin {
|
export class InstancePlugin extends BaseInstancePlugin {
|
||||||
|
async init() {
|
||||||
|
this.instance.handle(messages.GroupUpdatedEvent, this.handleGroupUpdatedEvent.bind(this));
|
||||||
|
this.instance.handle(messages.AssignmentUpdatedEvent, this.handleAssignmentUpdatedEvent.bind(this));
|
||||||
|
this.instance.server.handle(`exp_group:group_updated`, this.handleGroupUpdatedIPC.bind(this))
|
||||||
|
this.instance.server.handle(`exp_group:group_deleted`, this.handleGroupDeletedIPC.bind(this))
|
||||||
|
this.instance.server.handle(`exp_group:player_assignments`, this.handlePlayerAssignmentsIPC.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
async onInstanceConfigFieldChanged(field: string, curr: unknown, prev: unknown) {
|
||||||
|
switch(field) {
|
||||||
|
case "exp_groups.sync_mode":
|
||||||
|
await this.luaSetEmitEvents(curr == "bidirectional")
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async onStart() {
|
||||||
|
await this.instance.sendTo("controller", new lib.SubscriptionRequest(
|
||||||
|
`exp_groups:${messages.GroupUpdatedEvent.name}`, true
|
||||||
|
));
|
||||||
|
const groups = await this.instance.sendTo("controller", new messages.GroupListRequest())
|
||||||
|
await this.luaSendInitialGroups(groups);
|
||||||
|
await this.luaSetEmitEvents(this.instance.config.get("exp_groups.sync_mode") == "bidirectional")
|
||||||
|
}
|
||||||
|
|
||||||
|
async onPlayerEvent(event: lib.PlayerEvent) {
|
||||||
|
switch(event.type) {
|
||||||
|
case "join":
|
||||||
|
this.handlePlayerJoin(event.name);
|
||||||
|
break;
|
||||||
|
case "leave":
|
||||||
|
this.handlePlayerLeave(event.name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async handlePlayerJoin(playerName: string) {
|
||||||
|
await this.subscribePlayerAssignment(playerName);
|
||||||
|
await this.requestPlayerAssignment(playerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handlePlayerLeave(playerName: string) {
|
||||||
|
await this.unsubscribePlayerAssignment(playerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleGroupUpdatedEvent(event: messages.GroupUpdatedEvent) {
|
||||||
|
for (const group of event.updates) {
|
||||||
|
await this.luaSendGroupUpdate(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleAssignmentUpdatedEvent(event: messages.AssignmentUpdatedEvent) {
|
||||||
|
for (const assignment of event.updates) {
|
||||||
|
await this.luaSendAssignmentUpdate(assignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleGroupUpdatedIPC(event: IpcGroupUpdated) {
|
||||||
|
const permissions = new messages.GroupPermissions(
|
||||||
|
event.permissions.is_blacklist,
|
||||||
|
event.permissions.permissions,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (event.group_id === undefined) {
|
||||||
|
await this.instance.sendTo("controller",
|
||||||
|
new messages.GroupCreateRequest(event.group_name, permissions),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await this.instance.sendTo("controller", new messages.GroupUpdateRequest(
|
||||||
|
new messages.GroupRecord(event.group_id, event.group_name, permissions),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleGroupDeletedIPC(event: IpcGroupDeleted) {
|
||||||
|
if (event.group_id === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.instance.sendTo("controller", new messages.GroupDeleteRequest(event.group_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
async handlePlayerAssignmentsIPC(event: IpcPlayerAssignments) {
|
||||||
|
await Promise.all(
|
||||||
|
Object.entries(event.assignments).map(([playerName, groupId]) =>
|
||||||
|
this.instance.sendTo("controller",
|
||||||
|
new messages.AssignmentUpdateRequest(new messages.AssignmentRecord(playerName, groupId)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async subscribePlayerAssignment(playerName: string) {
|
||||||
|
await this.instance.sendTo("controller", new lib.SubscriptionRequest(
|
||||||
|
`exp_groups:${messages.AssignmentUpdatedEvent.name}`, true, 0, playerName
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
async unsubscribePlayerAssignment(playerName: string) {
|
||||||
|
await this.instance.sendTo("controller", new lib.SubscriptionRequest(
|
||||||
|
`exp_groups:${messages.AssignmentUpdatedEvent.name}`, false, 0, playerName
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
async requestPlayerAssignment(playerName: string) {
|
||||||
|
const assignment = await this.instance.sendTo("controller", new messages.AssignmentGetRequest(playerName));
|
||||||
|
await this.luaSendAssignmentUpdate(assignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
async luaSendInitialGroups(groups: messages.GroupRecord[]) {
|
||||||
|
if (this.instance.config.get("exp_groups.sync_mode") == "disabled") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.instance.sendRcon(`/sc exp_groups.initialise_groups(helpers.json_to_table${JSON.stringify(groups)})`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async luaSendGroupUpdate(group: messages.GroupRecord) {
|
||||||
|
if (this.instance.config.get("exp_groups.sync_mode") == "disabled") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.instance.sendRcon(`/sc exp_groups.receive_group_update(helpers.json_to_table${JSON.stringify(group)})`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async luaSendAssignmentUpdate(assignment: messages.AssignmentRecord) {
|
||||||
|
if (this.instance.config.get("exp_groups.sync_mode") == "disabled") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.instance.sendRcon(`/sc exp_groups.initialise_groups(helpers.receive_assignment_update${JSON.stringify(assignment)})`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async luaSetEmitEvents(emitEvents: boolean) {
|
||||||
|
await this.instance.sendRcon(`/sc exp_groups.set_emit_events(${emitEvents})`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--[[-- Exp Permission Groups
|
--[[-- ExpGroups
|
||||||
Adds permission group syncing to clusterio
|
Adds permission group syncing to clusterio
|
||||||
]]
|
]]
|
||||||
|
|
||||||
@@ -6,18 +6,18 @@ local clusterio_api = require("modules/clusterio/api")
|
|||||||
local compat = require("modules/clusterio/compat")
|
local compat = require("modules/clusterio/compat")
|
||||||
|
|
||||||
--- Top level module table, contains event handlers and public methods
|
--- Top level module table, contains event handlers and public methods
|
||||||
--- @class ExpPermissionGroups
|
--- @class ExpGroups
|
||||||
local ExpPermissionGroups = {}
|
local ExpGroups = {}
|
||||||
|
|
||||||
--- @class ExpPermissionGroups.GroupPermissions
|
--- @class ExpPermissionGroups.GroupPermissions
|
||||||
--- @field [1] boolean -- is_blacklist, true means action names is a backlist
|
--- @field is_blacklist boolean
|
||||||
--- @field [2] string[] -- action_names, the actions to allow or disallow
|
--- @field permissions string[]
|
||||||
|
|
||||||
--- @class ExpPermissionGroups.GroupRecord
|
--- @class ExpPermissionGroups.GroupRecord
|
||||||
--- @field id number
|
--- @field id number
|
||||||
--- @field name string
|
--- @field name string
|
||||||
--- @field permissions ExpPermissionGroups.GroupPermissions?
|
--- @field permissions ExpPermissionGroups.GroupPermissions?
|
||||||
--- @field isDeleted boolean
|
--- @field is_deleted boolean
|
||||||
|
|
||||||
--- @class ExpPermissionGroups.AssignmentRecord
|
--- @class ExpPermissionGroups.AssignmentRecord
|
||||||
--- @field name string
|
--- @field name string
|
||||||
@@ -44,7 +44,7 @@ local function setup_script_data()
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
ExpPermissionGroups.on_load()
|
ExpGroups.on_load()
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -71,17 +71,15 @@ end
|
|||||||
--- @param group LuaPermissionGroup
|
--- @param group LuaPermissionGroup
|
||||||
--- @param permissions ExpPermissionGroups.GroupPermissions
|
--- @param permissions ExpPermissionGroups.GroupPermissions
|
||||||
local function decode_group_permissions(group, permissions)
|
local function decode_group_permissions(group, permissions)
|
||||||
local is_blacklist = permissions[1]
|
|
||||||
local actions_names = permissions[2]
|
|
||||||
local action_allowed = not is_blacklist
|
|
||||||
|
|
||||||
-- Construct a hash map for faster lookup
|
-- Construct a hash map for faster lookup
|
||||||
local action_map = {}
|
local action_map = {}
|
||||||
for _, input_action_name in pairs(actions_names) do
|
for _, input_action_name in pairs(permissions.permissions) do
|
||||||
action_map[input_action_name] = true
|
action_map[input_action_name] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Apply the whitelist / backlist to the group
|
-- Apply the whitelist / backlist to the group
|
||||||
|
local is_blacklist = permissions.is_blacklist
|
||||||
|
local action_allowed = not is_blacklist
|
||||||
for input_action_name, input_action in pairs(defines.input_action) do
|
for input_action_name, input_action in pairs(defines.input_action) do
|
||||||
if action_map[input_action_name] then
|
if action_map[input_action_name] then
|
||||||
group.set_allows_action(input_action, action_allowed)
|
group.set_allows_action(input_action, action_allowed)
|
||||||
@@ -114,11 +112,11 @@ local function encode_group_permissions(group)
|
|||||||
|
|
||||||
-- Return the whitelist if it is smaller
|
-- Return the whitelist if it is smaller
|
||||||
if blacklist_index > whitelist_index then
|
if blacklist_index > whitelist_index then
|
||||||
return { false, whitelist }
|
return { is_blacklist = false, permissions = whitelist }
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Otherwise return the blacklist as it is smaller
|
-- Otherwise return the blacklist as it is smaller
|
||||||
return { true, blacklist }
|
return { is_blacklist = true, permissions = blacklist }
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -128,7 +126,7 @@ end
|
|||||||
--- Update the factorio permission group
|
--- Update the factorio permission group
|
||||||
--- @param group_record ExpPermissionGroups.GroupRecord
|
--- @param group_record ExpPermissionGroups.GroupRecord
|
||||||
local function update_group(group_record)
|
local function update_group(group_record)
|
||||||
assert(not group_record.isDeleted)
|
assert(not group_record.is_deleted)
|
||||||
|
|
||||||
-- Try find the group by id and then then name
|
-- Try find the group by id and then then name
|
||||||
local group = script_data.clusterio_id_to_group[group_record.id]
|
local group = script_data.clusterio_id_to_group[group_record.id]
|
||||||
@@ -156,7 +154,7 @@ end
|
|||||||
--- Delete the factorio permission group
|
--- Delete the factorio permission group
|
||||||
--- @param group_record ExpPermissionGroups.GroupRecord
|
--- @param group_record ExpPermissionGroups.GroupRecord
|
||||||
local function delete_group(group_record)
|
local function delete_group(group_record)
|
||||||
assert(group_record.isDeleted)
|
assert(group_record.is_deleted)
|
||||||
|
|
||||||
local default_group = get_default_group()
|
local default_group = get_default_group()
|
||||||
local group = script_data.clusterio_id_to_group[group_record.id]
|
local group = script_data.clusterio_id_to_group[group_record.id]
|
||||||
@@ -193,19 +191,19 @@ end
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
--- Restore local references to persistent script data after load
|
--- Restore local references to persistent script data after load
|
||||||
function ExpPermissionGroups.on_load()
|
function ExpGroups.on_load()
|
||||||
script_data = compat.script_data["exp_groups"]
|
script_data = compat.script_data["exp_groups"]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Enable or disable emitting lua changes back to the instance plugin
|
--- Enable or disable emitting lua changes back to the instance plugin
|
||||||
--- @param enabled boolean?
|
--- @param enabled boolean?
|
||||||
function ExpPermissionGroups.set_emit_events(enabled)
|
function ExpGroups.set_emit_events(enabled)
|
||||||
script_data.emit_updates = enabled ~= false
|
script_data.emit_updates = enabled ~= false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Replace local state with expected controller state on startup
|
--- Replace local state with expected controller state on startup
|
||||||
--- @param group_records ExpPermissionGroups.GroupRecord[]
|
--- @param group_records ExpPermissionGroups.GroupRecord[]
|
||||||
function ExpPermissionGroups.initialise_groups(group_records)
|
function ExpGroups.initialise_groups(group_records)
|
||||||
local _emit_events = script_data.emit_updates
|
local _emit_events = script_data.emit_updates
|
||||||
script_data.emit_updates = false
|
script_data.emit_updates = false
|
||||||
|
|
||||||
@@ -241,11 +239,11 @@ end
|
|||||||
|
|
||||||
--- Receive an updated version of a group record
|
--- Receive an updated version of a group record
|
||||||
--- @param group_record ExpPermissionGroups.GroupRecord
|
--- @param group_record ExpPermissionGroups.GroupRecord
|
||||||
function ExpPermissionGroups.receive_group_update(group_record)
|
function ExpGroups.receive_group_update(group_record)
|
||||||
local _emit_events = script_data.emit_updates
|
local _emit_events = script_data.emit_updates
|
||||||
script_data.emit_updates = false
|
script_data.emit_updates = false
|
||||||
|
|
||||||
if group_record.isDeleted then
|
if group_record.is_deleted then
|
||||||
delete_group(group_record)
|
delete_group(group_record)
|
||||||
else
|
else
|
||||||
update_group(group_record)
|
update_group(group_record)
|
||||||
@@ -256,7 +254,7 @@ end
|
|||||||
|
|
||||||
--- Receive an updated version of a assignment record
|
--- Receive an updated version of a assignment record
|
||||||
--- @param assignment_record ExpPermissionGroups.AssignmentRecord
|
--- @param assignment_record ExpPermissionGroups.AssignmentRecord
|
||||||
function ExpPermissionGroups.receive_assignment_update(assignment_record)
|
function ExpGroups.receive_assignment_update(assignment_record)
|
||||||
local _emit_events = script_data.emit_updates
|
local _emit_events = script_data.emit_updates
|
||||||
script_data.emit_updates = false
|
script_data.emit_updates = false
|
||||||
|
|
||||||
@@ -271,7 +269,7 @@ end
|
|||||||
|
|
||||||
--- Get the current script data for debugging purposes
|
--- Get the current script data for debugging purposes
|
||||||
--- @package
|
--- @package
|
||||||
function ExpPermissionGroups._script_data()
|
function ExpGroups._script_data()
|
||||||
return script_data
|
return script_data
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -332,7 +330,6 @@ local function flush_group_updates()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Get all the groups and emit their updates
|
-- Get all the groups and emit their updates
|
||||||
local get_group = game.permissions.get_group
|
|
||||||
for _, group in pairs(script_data.dirty_groups) do
|
for _, group in pairs(script_data.dirty_groups) do
|
||||||
if group.valid then
|
if group.valid then
|
||||||
emit_group_update(group)
|
emit_group_update(group)
|
||||||
@@ -431,6 +428,6 @@ local on_nth_tick = {
|
|||||||
[300] = on_nth_tick_flush,
|
[300] = on_nth_tick_flush,
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpPermissionGroups.events = events --- @package
|
ExpGroups.events = events --- @package
|
||||||
ExpPermissionGroups.on_nth_tick = on_nth_tick --- @package
|
ExpGroups.on_nth_tick = on_nth_tick --- @package
|
||||||
return ExpPermissionGroups
|
return ExpGroups
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
--[[
|
||||||
|
It is best practice to not expose any globals because all modules share a global environment
|
||||||
|
However, sometimes you need globals, for example to access functions within rcon commands
|
||||||
|
Therefore, we advise that this should be the only file in your module to expose globals
|
||||||
|
Typically this would be your control file as shown in the example below
|
||||||
|
]]
|
||||||
|
|
||||||
|
-- Access using `/sc exp_groups.foo()`
|
||||||
|
exp_groups = require("modules/exp_groups/control")
|
||||||
Reference in New Issue
Block a user