From ceca8fbf00c9bcd3b9745fcaadda44bee111e5b4 Mon Sep 17 00:00:00 2001 From: oof2win2 Date: Sat, 12 Nov 2022 22:28:06 +0100 Subject: [PATCH 1/8] fix: set roles after jailing --- expcore/roles.lua | 11 ++++++++++- modules/control/jail.lua | 20 ++++++++++++++++---- modules/control/jail_old_role.lua | 13 +++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 modules/control/jail_old_role.lua diff --git a/expcore/roles.lua b/expcore/roles.lua index 2028cd23..b6d1000d 100644 --- a/expcore/roles.lua +++ b/expcore/roles.lua @@ -115,6 +115,7 @@ local Groups = require 'expcore.permission_groups' --- @dep expcore.permission_g local Async = require 'expcore.async' --- @dep expcore.async local Colours = require 'utils.color_presets' --- @dep utils.color_presets local write_json = _C.write_json --- @dep expcore.common +local JailOldRole = require 'modules.control.jail_old_role' --- @dep modules.control.jail local Roles = { _prototype={}, @@ -368,7 +369,15 @@ function Roles.assign_player(player, roles, by_player_name, skip_checks, silent) if not skip_checks and not valid_player then return end if not player then return end if type(roles) ~= 'table' or roles.name then - roles = {roles} + roles = { roles } + end + if Roles.player_has_role(player, "Jail") then + local to_assign = JailOldRole.old_roles[valid_player.name] or {} + for _, role in ipairs(roles) do + table.insert(to_assign, role) + end + JailOldRole.old_roles[valid_player.name] = to_assign + return end for _, role in ipairs(roles) do role = Roles.get_role_from_any(role) diff --git a/modules/control/jail.lua b/modules/control/jail.lua index 1e37fbfa..93a02734 100644 --- a/modules/control/jail.lua +++ b/modules/control/jail.lua @@ -19,6 +19,7 @@ local Roles = require 'expcore.roles' --- @dep expcore.roles local Game = require 'utils.game' --- @dep utils.game local Global = require 'utils.global' --- @dep utils.global +local JailOldRole = require 'modules.control.jail_old_role' --- @dep modules.control.jail_old_role local valid_player = Game.get_player_from_any local assign_roles = Roles.assign_player @@ -89,7 +90,7 @@ function Jail.jail_player(player, by_player_name, reason) if has_role(player, 'Jail') then return end local roles = get_roles(player) - old_roles[player.name] = roles + JailOldRole.old_roles[player.name] = roles player.walking_state = { walking = false } player.riding_state = { acceleration = defines.riding.acceleration.nothing, direction = player.riding_state.direction } @@ -116,14 +117,25 @@ function Jail.unjail_player(player, by_player_name) if not by_player_name then return end if not has_role(player, 'Jail') then return end - local roles = old_roles[player.name] or {} + local roles = JailOldRole.old_roles[player.name] or {} - assign_roles(player, roles, by_player_name, nil, true) unassign_roles(player, 'Jail', by_player_name, nil, true) + assign_roles(player, roles, by_player_name, nil, true) event_emit(Jail.events.on_player_unjailed, player, by_player_name) return true end -return Jail \ No newline at end of file +function Jail.add_old_role(player, to_assign) + player = valid_player(player) + if not player then return end + + if not has_role(player, 'Jail') then return end + local roles = JailOldRole.old_roles[player.name] + if not roles then return end + + table.insert(roles, to_assign) +end + +return Jail diff --git a/modules/control/jail_old_role.lua b/modules/control/jail_old_role.lua new file mode 100644 index 00000000..0bf5d836 --- /dev/null +++ b/modules/control/jail_old_role.lua @@ -0,0 +1,13 @@ +local Global = require 'utils.global' --- @dep utils.global + +local Jail = { + old_roles = {} +} + +local old_roles = Jail.old_roles +Global.register(old_roles, function(tbl) + Jail.old_roles = tbl + old_roles = tbl +end) + +return Jail From 2d9cfd8e11e3be3f0d84a86cfe1bb66eb7bb6b4e Mon Sep 17 00:00:00 2001 From: oof2win2 Date: Sat, 12 Nov 2022 22:31:36 +0100 Subject: [PATCH 2/8] feat: change future to assign roles to table --- expcore/roles.lua | 4 +++- modules/control/jail.lua | 21 ++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/expcore/roles.lua b/expcore/roles.lua index b6d1000d..a7ec1a9e 100644 --- a/expcore/roles.lua +++ b/expcore/roles.lua @@ -374,7 +374,9 @@ function Roles.assign_player(player, roles, by_player_name, skip_checks, silent) if Roles.player_has_role(player, "Jail") then local to_assign = JailOldRole.old_roles[valid_player.name] or {} for _, role in ipairs(roles) do - table.insert(to_assign, role) + if not to_assign[role] then + to_assign[role] = 1 + end end JailOldRole.old_roles[valid_player.name] = to_assign return diff --git a/modules/control/jail.lua b/modules/control/jail.lua index 93a02734..120ad2c8 100644 --- a/modules/control/jail.lua +++ b/modules/control/jail.lua @@ -18,11 +18,10 @@ local Roles = require 'expcore.roles' --- @dep expcore.roles local Game = require 'utils.game' --- @dep utils.game -local Global = require 'utils.global' --- @dep utils.global local JailOldRole = require 'modules.control.jail_old_role' --- @dep modules.control.jail_old_role local valid_player = Game.get_player_from_any -local assign_roles = Roles.assign_player +local assign_role = Roles.assign_player local unassign_roles = Roles.unassign_player local has_role = Roles.player_has_role local get_roles = Roles.get_player_roles @@ -44,12 +43,6 @@ local Jail = { } } -local old_roles = Jail.old_roles -Global.register(old_roles, function(tbl) - Jail.old_roles = tbl - old_roles = tbl -end) - --- Used to emit the jail related events -- @tparam number event the name of the event that will be emited -- @tparam LuaPlayer player the player who is being acted on @@ -90,7 +83,11 @@ function Jail.jail_player(player, by_player_name, reason) if has_role(player, 'Jail') then return end local roles = get_roles(player) - JailOldRole.old_roles[player.name] = roles + local old_roles = {} + for _, role in ipairs(roles) do + old_roles[role.name] = 1 + end + JailOldRole.old_roles[player.name] = old_roles player.walking_state = { walking = false } player.riding_state = { acceleration = defines.riding.acceleration.nothing, direction = player.riding_state.direction } @@ -99,7 +96,7 @@ function Jail.jail_player(player, by_player_name, reason) player.picking_state = false player.repair_state = { repairing = false } - assign_roles(player, 'Jail', by_player_name, nil, true) + assign_role(player, 'Jail', by_player_name, nil, true) unassign_roles(player, roles, by_player_name, nil, true) event_emit(Jail.events.on_player_jailed, player, by_player_name, reason) @@ -120,7 +117,9 @@ function Jail.unjail_player(player, by_player_name) local roles = JailOldRole.old_roles[player.name] or {} unassign_roles(player, 'Jail', by_player_name, nil, true) - assign_roles(player, roles, by_player_name, nil, true) + for role, _ in pairs(roles) do + assign_role(player, role, by_player_name, nil, true) + end event_emit(Jail.events.on_player_unjailed, player, by_player_name) From 3f42681ddc1b8e6289fce243b37debf106f9887a Mon Sep 17 00:00:00 2001 From: oof2win2 Date: Sun, 13 Nov 2022 08:42:18 +0100 Subject: [PATCH 3/8] feat: role deference in Roles module itself --- config/expcore/roles.lua | 1 + expcore/roles.lua | 56 ++++++++++++++++++++++--------- modules/control/jail.lua | 26 ++------------ modules/control/jail_old_role.lua | 13 ------- 4 files changed, 44 insertions(+), 52 deletions(-) delete mode 100644 modules/control/jail_old_role.lua diff --git a/config/expcore/roles.lua b/config/expcore/roles.lua index 3f6dd512..20feeb14 100644 --- a/config/expcore/roles.lua +++ b/config/expcore/roles.lua @@ -267,6 +267,7 @@ Roles.new_role('Jail') :set_permission_group('Restricted') :set_custom_color{r=50,g=50,b=50} :set_block_auto_assign(true) +:set_flag("defer_role_changes") :disallow(default.allowed) --- System defaults which are required to be set diff --git a/expcore/roles.lua b/expcore/roles.lua index a7ec1a9e..acbf9b28 100644 --- a/expcore/roles.lua +++ b/expcore/roles.lua @@ -115,17 +115,17 @@ local Groups = require 'expcore.permission_groups' --- @dep expcore.permission_g local Async = require 'expcore.async' --- @dep expcore.async local Colours = require 'utils.color_presets' --- @dep utils.color_presets local write_json = _C.write_json --- @dep expcore.common -local JailOldRole = require 'modules.control.jail_old_role' --- @dep modules.control.jail local Roles = { - _prototype={}, - config={ - order = {}, -- Contains the order of the roles, lower index is better - roles = {}, -- Contains the raw info for the roles, indexed by role name - flags = {}, -- Contains functions that run when a flag is added/removed from a player - internal = {}, -- Contains all internally accessed roles, such as root, default - players = {}, -- Contains the roles that players have - auto_assign = {} -- Contains references to all roles which have auto assign conditions + _prototype = {}, + config = { + order = {}, -- Contains the order of the roles, lower index is better + roles = {}, -- Contains the raw info for the roles, indexed by role name + flags = {}, -- Contains functions that run when a flag is added/removed from a player + internal = {}, -- Contains all internally accessed roles, such as root, default + players = {}, -- Contains the roles that players have + auto_assign = {}, -- Contains references to all roles which have auto assign conditions + deferred_roles = {}, -- Contains the roles that are to be assigned to players when they are unjailed }, events = { on_role_assigned = script.generate_event_name(), @@ -137,6 +137,9 @@ local Roles = { Global.register(Roles.config.players, function(tbl) Roles.config.players = tbl end) +Global.register(Roles.config.deferred_roles, function(tbl) + Roles.config.deferred_roles = tbl +end) --- Getter. -- Functions which get roles @@ -371,16 +374,17 @@ function Roles.assign_player(player, roles, by_player_name, skip_checks, silent) if type(roles) ~= 'table' or roles.name then roles = { roles } end - if Roles.player_has_role(player, "Jail") then - local to_assign = JailOldRole.old_roles[valid_player.name] or {} + + -- if the player has a role that needs to defer the role changes, save the roles that need to be assigned later into a table + if valid_player and Roles.player_has_flag(player, "defer_role_changes") then + local assign_later = Roles.config.deferred_roles[valid_player.name] or {} for _, role in ipairs(roles) do - if not to_assign[role] then - to_assign[role] = 1 - end + assign_later[role] = 1 end - JailOldRole.old_roles[valid_player.name] = to_assign + Roles.config.deferred_roles[valid_player.name] = assign_later return end + for _, role in ipairs(roles) do role = Roles.get_role_from_any(role) if role then @@ -411,14 +415,34 @@ function Roles.unassign_player(player, roles, by_player_name, skip_checks, silen if not skip_checks and not valid_player then return end if not player then return end if type(roles) ~= 'table' or roles.name then - roles = {roles} + roles = { roles } end + + local had_deferred_changes = false + for _, role in ipairs(roles) do role = Roles.get_role_from_any(role) if role then + if role:has_flag("defer_role_changes") then + had_deferred_changes = true + end role:remove_player(valid_player or player, valid_player == nil, true) end end + + + -- if there are deferred role changes, apply them now + if had_deferred_changes then + local assign_later = Roles.config.deferred_roles[player.name] or {} + log(serpent.line(assign_later)) + for role_name, _ in pairs(assign_later) do + local role = Roles.get_role_from_any(role_name) + if role then + role:add_player(valid_player or player, valid_player == nil, true) + end + end + end + if valid_player then emit_player_roles_updated(valid_player, 'unassign', roles, by_player_name, silent) end diff --git a/modules/control/jail.lua b/modules/control/jail.lua index 120ad2c8..b5bf7df4 100644 --- a/modules/control/jail.lua +++ b/modules/control/jail.lua @@ -18,10 +18,9 @@ local Roles = require 'expcore.roles' --- @dep expcore.roles local Game = require 'utils.game' --- @dep utils.game -local JailOldRole = require 'modules.control.jail_old_role' --- @dep modules.control.jail_old_role local valid_player = Game.get_player_from_any -local assign_role = Roles.assign_player +local assign_roles = Roles.assign_player local unassign_roles = Roles.unassign_player local has_role = Roles.player_has_role local get_roles = Roles.get_player_roles @@ -83,11 +82,6 @@ function Jail.jail_player(player, by_player_name, reason) if has_role(player, 'Jail') then return end local roles = get_roles(player) - local old_roles = {} - for _, role in ipairs(roles) do - old_roles[role.name] = 1 - end - JailOldRole.old_roles[player.name] = old_roles player.walking_state = { walking = false } player.riding_state = { acceleration = defines.riding.acceleration.nothing, direction = player.riding_state.direction } @@ -96,8 +90,9 @@ function Jail.jail_player(player, by_player_name, reason) player.picking_state = false player.repair_state = { repairing = false } - assign_role(player, 'Jail', by_player_name, nil, true) unassign_roles(player, roles, by_player_name, nil, true) + assign_roles(player, 'Jail', by_player_name, nil, true) + assign_roles(player, roles, by_player_name, nil, true) event_emit(Jail.events.on_player_jailed, player, by_player_name, reason) @@ -114,27 +109,12 @@ function Jail.unjail_player(player, by_player_name) if not by_player_name then return end if not has_role(player, 'Jail') then return end - local roles = JailOldRole.old_roles[player.name] or {} unassign_roles(player, 'Jail', by_player_name, nil, true) - for role, _ in pairs(roles) do - assign_role(player, role, by_player_name, nil, true) - end event_emit(Jail.events.on_player_unjailed, player, by_player_name) return true end -function Jail.add_old_role(player, to_assign) - player = valid_player(player) - if not player then return end - - if not has_role(player, 'Jail') then return end - local roles = JailOldRole.old_roles[player.name] - if not roles then return end - - table.insert(roles, to_assign) -end - return Jail diff --git a/modules/control/jail_old_role.lua b/modules/control/jail_old_role.lua deleted file mode 100644 index 0bf5d836..00000000 --- a/modules/control/jail_old_role.lua +++ /dev/null @@ -1,13 +0,0 @@ -local Global = require 'utils.global' --- @dep utils.global - -local Jail = { - old_roles = {} -} - -local old_roles = Jail.old_roles -Global.register(old_roles, function(tbl) - Jail.old_roles = tbl - old_roles = tbl -end) - -return Jail From c42613e63c2a78b383aac4fb76fa671c7d53565d Mon Sep 17 00:00:00 2001 From: oof2win2 Date: Sun, 13 Nov 2022 08:49:06 +0100 Subject: [PATCH 4/8] fix(debug): remove log --- expcore/roles.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/expcore/roles.lua b/expcore/roles.lua index acbf9b28..28ba0b80 100644 --- a/expcore/roles.lua +++ b/expcore/roles.lua @@ -434,7 +434,6 @@ function Roles.unassign_player(player, roles, by_player_name, skip_checks, silen -- if there are deferred role changes, apply them now if had_deferred_changes then local assign_later = Roles.config.deferred_roles[player.name] or {} - log(serpent.line(assign_later)) for role_name, _ in pairs(assign_later) do local role = Roles.get_role_from_any(role_name) if role then From 7b2a35259dd7bfef168405d1de80ff7f5f082902 Mon Sep 17 00:00:00 2001 From: oof2win2 Date: Sun, 13 Nov 2022 09:27:33 +0100 Subject: [PATCH 5/8] feat(roles): deferred role assignment message --- expcore/roles.lua | 17 ++++++++++++++--- locale/en/expcore.cfg | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/expcore/roles.lua b/expcore/roles.lua index 28ba0b80..0dcaa2ac 100644 --- a/expcore/roles.lua +++ b/expcore/roles.lua @@ -148,7 +148,7 @@ end) --- Internal function used to trigger a few different things when roles are changed -- this is the raw internal trigger as the other function is called at other times -- there is a second half called role_update which triggers after the event call, it also is called when a player joins -local function emit_player_roles_updated(player, type, roles, by_player_name, skip_game_print) +local function emit_player_roles_updated(player, type, roles, by_player_name, skip_game_print, deferred) by_player_name = game.player and game.player.name or by_player_name or '' local by_player = game.players[by_player_name] local by_player_index = by_player and by_player.index or 0 @@ -168,7 +168,11 @@ local function emit_player_roles_updated(player, type, roles, by_player_name, sk end -- output to all the different locations: game print, player sound, event trigger and role log if not skip_game_print then - game.print({'expcore-roles.game-message-'..type, player.name, table.concat(role_names, ', '), by_player_name}, Colours.cyan) + if deferred then + game.print({'expcore-roles.game-message-deferred-'..type, player.name, table.concat(role_names, ', '), by_player_name}, Colours.cyan) + else + game.print({'expcore-roles.game-message-'..type, player.name, table.concat(role_names, ', '), by_player_name}, Colours.cyan) + end end if type == 'assign' then player.play_sound{path='utility/achievement_unlocked'} @@ -378,10 +382,17 @@ function Roles.assign_player(player, roles, by_player_name, skip_checks, silent) -- if the player has a role that needs to defer the role changes, save the roles that need to be assigned later into a table if valid_player and Roles.player_has_flag(player, "defer_role_changes") then local assign_later = Roles.config.deferred_roles[valid_player.name] or {} + local were_changes = false for _, role in ipairs(roles) do - assign_later[role] = 1 + if not assign_later[role] then + assign_later[role] = 1 + were_changes = true + end end Roles.config.deferred_roles[valid_player.name] = assign_later + if were_changes then + emit_player_roles_updated(valid_player, 'assign', roles, by_player_name, silent, true) + end return end diff --git a/locale/en/expcore.cfg b/locale/en/expcore.cfg index bdc4907d..3bfb6828 100644 --- a/locale/en/expcore.cfg +++ b/locale/en/expcore.cfg @@ -29,6 +29,7 @@ error-log-format-flag=[ERROR] roleFlag/__1__ :: __2__ error-log-format-assign=[ERROR] rolePromote/__1__ :: __2__ game-message-assign=__1__ has been assigned to __2__ by __3__ game-message-unassign=__1__ has been unassigned from __2__ by __3__ +game-message-deferred-assign=__1__ will been assigned to __2__ by __3__ reject-role=Invalid Role Name. reject-player-role=Player has a higher role. From e8e5f963a1986cadf56e2141ff53baa9d734de17 Mon Sep 17 00:00:00 2001 From: oof2win2 Date: Thu, 17 Nov 2022 07:58:48 +0100 Subject: [PATCH 6/8] feat: review changes --- expcore/roles.lua | 54 +++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/expcore/roles.lua b/expcore/roles.lua index 0dcaa2ac..cbaa2395 100644 --- a/expcore/roles.lua +++ b/expcore/roles.lua @@ -134,11 +134,9 @@ local Roles = { } --- When global is loaded it will have the metatable re-assigned to the roles -Global.register(Roles.config.players, function(tbl) - Roles.config.players = tbl -end) -Global.register(Roles.config.deferred_roles, function(tbl) - Roles.config.deferred_roles = tbl +Global.register({ Roles.config.players, Roles.config.deferred_roles }, function(tbl) + Roles.config.players = tbl[1] + Roles.config.deferred_roles = tbl[2] end) --- Getter. @@ -382,17 +380,17 @@ function Roles.assign_player(player, roles, by_player_name, skip_checks, silent) -- if the player has a role that needs to defer the role changes, save the roles that need to be assigned later into a table if valid_player and Roles.player_has_flag(player, "defer_role_changes") then local assign_later = Roles.config.deferred_roles[valid_player.name] or {} - local were_changes = false + local were_changes = false for _, role in ipairs(roles) do - if not assign_later[role] then - assign_later[role] = 1 - were_changes = true - end + if assign_later[role] ~= 1 then + assign_later[role] = 1 + were_changes = true + end end Roles.config.deferred_roles[valid_player.name] = assign_later - if were_changes then - emit_player_roles_updated(valid_player, 'assign', roles, by_player_name, silent, true) - end + if were_changes then + emit_player_roles_updated(valid_player, 'assign', roles, by_player_name, silent, true) + end return end @@ -429,26 +427,42 @@ function Roles.unassign_player(player, roles, by_player_name, skip_checks, silen roles = { roles } end - local had_deferred_changes = false + -- if the player has a role that needs to defer the role changes, save the roles that need to be unassigned later into a table + if Roles.player_has_flag(player, "defer_role_changes") then + local assign_later = Roles.config.deferred_roles[valid_player.name] or {} + local were_changes = false + for _, role in ipairs(roles) do + if assign_later[role] ~= -1 then + assign_later[role] = -1 + were_changes = true + end + end + Roles.config.deferred_roles[valid_player.name] = assign_later + if were_changes then + emit_player_roles_updated(valid_player, 'unassign', roles, by_player_name, silent, true) + end + return + end for _, role in ipairs(roles) do role = Roles.get_role_from_any(role) if role then - if role:has_flag("defer_role_changes") then - had_deferred_changes = true - end role:remove_player(valid_player or player, valid_player == nil, true) end end -- if there are deferred role changes, apply them now - if had_deferred_changes then + if Roles.player_has_flag(valid_player, "defer_role_changes") then local assign_later = Roles.config.deferred_roles[player.name] or {} - for role_name, _ in pairs(assign_later) do + for role_name, assign in pairs(assign_later) do local role = Roles.get_role_from_any(role_name) if role then - role:add_player(valid_player or player, valid_player == nil, true) + if assign == 1 then + role:add_player(valid_player or player, valid_player == nil, true) + elseif assign == -1 then + role:remove_player(valid_player or player, valid_player == nil, true) + end end end end From fce01baf1c1d4e84606dfdbe3d296eaacf343d5c Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 18 Feb 2023 19:17:15 +0000 Subject: [PATCH 7/8] Fixed assignment logic edge cases --- expcore/roles.lua | 133 +++++++++++++++++++++++++----------------- locale/en/expcore.cfg | 1 - 2 files changed, 81 insertions(+), 53 deletions(-) diff --git a/expcore/roles.lua b/expcore/roles.lua index cbaa2395..cedbd016 100644 --- a/expcore/roles.lua +++ b/expcore/roles.lua @@ -146,8 +146,8 @@ end) --- Internal function used to trigger a few different things when roles are changed -- this is the raw internal trigger as the other function is called at other times -- there is a second half called role_update which triggers after the event call, it also is called when a player joins -local function emit_player_roles_updated(player, type, roles, by_player_name, skip_game_print, deferred) - by_player_name = game.player and game.player.name or by_player_name or '' +local function emit_player_roles_updated(player, type, roles, by_player_name, skip_game_print) + by_player_name = by_player_name or game.player and game.player.name or '' local by_player = game.players[by_player_name] local by_player_index = by_player and by_player.index or 0 -- get the event id from the type of emit @@ -155,22 +155,14 @@ local function emit_player_roles_updated(player, type, roles, by_player_name, sk if type == 'unassign' then event = Roles.events.on_role_unassigned end - -- convert the roles to objects and get the names of the roles - local index, role_names = 0, {} - for _, role in ipairs(roles) do - role = Roles.get_role_from_any(role) - if role then - index = index + 1 - role_names[index] = role.name - end + -- Get the names of the roles + local role_names = {} + for index, role in ipairs(roles) do + role_names[index] = role.name end -- output to all the different locations: game print, player sound, event trigger and role log if not skip_game_print then - if deferred then - game.print({'expcore-roles.game-message-deferred-'..type, player.name, table.concat(role_names, ', '), by_player_name}, Colours.cyan) - else - game.print({'expcore-roles.game-message-'..type, player.name, table.concat(role_names, ', '), by_player_name}, Colours.cyan) - end + game.print({'expcore-roles.game-message-'..type, player.name, table.concat(role_names, ', '), by_player_name}, Colours.cyan) end if type == 'assign' then player.play_sound{path='utility/achievement_unlocked'} @@ -373,35 +365,46 @@ function Roles.assign_player(player, roles, by_player_name, skip_checks, silent) local valid_player = Game.get_player_from_any(player) if not skip_checks and not valid_player then return end if not player then return end + + -- Convert the roles into a table (allows for optional array) if type(roles) ~= 'table' or roles.name then roles = { roles } end - -- if the player has a role that needs to defer the role changes, save the roles that need to be assigned later into a table + -- Convert to role objects + local role_objects = {} + for _, role in ipairs(roles) do + local role_object = Roles.get_role_from_any(role) + if role_object then table.insert(role_objects, role_object) end + end + + -- If the player has a role that needs to defer the role changes, save the roles that need to be assigned later into a table if valid_player and Roles.player_has_flag(player, "defer_role_changes") then local assign_later = Roles.config.deferred_roles[valid_player.name] or {} - local were_changes = false - for _, role in ipairs(roles) do - if assign_later[role] ~= 1 then - assign_later[role] = 1 - were_changes = true + for _, role in ipairs(role_objects) do + local role_change = assign_later[role.name] + if role_change then + role_change.count = role_change.count + 1 + if role_change.count == 1 then + role_change.by_player_name = by_player_name or "" + role_change.silent = silent + end + else + assign_later[role.name] = { + count = 1, by_player_name = by_player_name or "", silent = silent + } end end Roles.config.deferred_roles[valid_player.name] = assign_later - if were_changes then - emit_player_roles_updated(valid_player, 'assign', roles, by_player_name, silent, true) - end return end - for _, role in ipairs(roles) do - role = Roles.get_role_from_any(role) - if role then - role:add_player(valid_player or player, valid_player == nil, true) - end + for _, role in ipairs(role_objects) do + role:add_player(valid_player or player, valid_player == nil, true) end + if valid_player then - emit_player_roles_updated(valid_player, 'assign', roles, by_player_name, silent) + emit_player_roles_updated(valid_player, 'assign', role_objects, by_player_name, silent) end end @@ -423,52 +426,78 @@ function Roles.unassign_player(player, roles, by_player_name, skip_checks, silen local valid_player = Game.get_player_from_any(player) if not skip_checks and not valid_player then return end if not player then return end + + -- Convert the roles into a table (allows for optional array) if type(roles) ~= 'table' or roles.name then roles = { roles } end - -- if the player has a role that needs to defer the role changes, save the roles that need to be unassigned later into a table - if Roles.player_has_flag(player, "defer_role_changes") then + -- Convert to role objects + local role_objects = {} + for _, role in ipairs(roles) do + local role_object = Roles.get_role_from_any(role) + if role_object then table.insert(role_objects, role_object) end + end + + -- If the player has a role that needs to defer the role changes, save the roles that need to be unassigned later into a table + local defer_changes = Roles.player_has_flag(player, "defer_role_changes") + if defer_changes then local assign_later = Roles.config.deferred_roles[valid_player.name] or {} - local were_changes = false - for _, role in ipairs(roles) do - if assign_later[role] ~= -1 then - assign_later[role] = -1 - were_changes = true + for _, role in ipairs(role_objects) do + local role_change = assign_later[role.name] + if role_change then + role_change.count = role_change.count - 1 + if role_change.count == -1 then + role_change.by_player_name = by_player_name or "" + role_change.silent = silent + end + else + assign_later[role.name] = { + count = -1, by_player_name = by_player_name or "", silent = silent + } end end Roles.config.deferred_roles[valid_player.name] = assign_later - if were_changes then - emit_player_roles_updated(valid_player, 'unassign', roles, by_player_name, silent, true) - end - return end - for _, role in ipairs(roles) do - role = Roles.get_role_from_any(role) - if role then + -- Remove the player from roles + local role_changes = {} + for _, role in ipairs(role_objects) do + if not defer_changes or role:has_flag("defer_role_changes") then role:remove_player(valid_player or player, valid_player == nil, true) + table.insert(role_changes, role) end end - - -- if there are deferred role changes, apply them now - if Roles.player_has_flag(valid_player, "defer_role_changes") then + -- If there are deferred role changes, apply them now + if defer_changes and not Roles.player_has_flag(valid_player, "defer_role_changes") then local assign_later = Roles.config.deferred_roles[player.name] or {} - for role_name, assign in pairs(assign_later) do + local assigns, unassigns = {}, {} + for role_name, details in pairs(assign_later) do local role = Roles.get_role_from_any(role_name) if role then - if assign == 1 then + if details.count > 0 then role:add_player(valid_player or player, valid_player == nil, true) - elseif assign == -1 then + if not assigns[details.by_player_name] then assigns[details.by_player_name] = {} end + if not details.silent then table.insert(assigns[details.by_player_name], role) end + elseif details.count < 0 then role:remove_player(valid_player or player, valid_player == nil, true) + if not unassigns[details.by_player_name] then unassigns[details.by_player_name] = {} end + if not details.silent then table.insert(unassigns[details.by_player_name], role) end end end end + for assign_by_player_name, assign_roles in pairs(assigns) do + if #assign_roles > 0 then emit_player_roles_updated(valid_player, 'assign', assign_roles, assign_by_player_name) end + end + for unassign_by_player_name, unassign_roles in pairs(unassigns) do + if #unassign_roles > 0 then emit_player_roles_updated(valid_player, 'unassign', unassign_roles, unassign_by_player_name) end + end + Roles.config.deferred_roles[player.name] = nil end - if valid_player then - emit_player_roles_updated(valid_player, 'unassign', roles, by_player_name, silent) + if valid_player and #role_changes > 0 then + emit_player_roles_updated(valid_player, 'unassign', role_changes, by_player_name, silent) end end diff --git a/locale/en/expcore.cfg b/locale/en/expcore.cfg index 3bfb6828..bdc4907d 100644 --- a/locale/en/expcore.cfg +++ b/locale/en/expcore.cfg @@ -29,7 +29,6 @@ error-log-format-flag=[ERROR] roleFlag/__1__ :: __2__ error-log-format-assign=[ERROR] rolePromote/__1__ :: __2__ game-message-assign=__1__ has been assigned to __2__ by __3__ game-message-unassign=__1__ has been unassigned from __2__ by __3__ -game-message-deferred-assign=__1__ will been assigned to __2__ by __3__ reject-role=Invalid Role Name. reject-player-role=Player has a higher role. From 19ad8838a65dc62668ea3d4f1f325116757ea530 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Sat, 25 Feb 2023 15:32:49 +0000 Subject: [PATCH 8/8] Fixed Indentation --- expcore/roles.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/expcore/roles.lua b/expcore/roles.lua index cedbd016..b895897b 100644 --- a/expcore/roles.lua +++ b/expcore/roles.lua @@ -162,7 +162,7 @@ local function emit_player_roles_updated(player, type, roles, by_player_name, sk end -- output to all the different locations: game print, player sound, event trigger and role log if not skip_game_print then - game.print({'expcore-roles.game-message-'..type, player.name, table.concat(role_names, ', '), by_player_name}, Colours.cyan) + game.print({'expcore-roles.game-message-'..type, player.name, table.concat(role_names, ', '), by_player_name}, Colours.cyan) end if type == 'assign' then player.play_sound{path='utility/achievement_unlocked'}