Merge pull request #235 from oof2win2/bugfix/jail

fix: set roles after jailing
This commit is contained in:
Cooldude2606
2023-02-25 15:41:04 +00:00
committed by GitHub
3 changed files with 122 additions and 42 deletions

View File

@@ -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

View File

@@ -117,14 +117,15 @@ local Colours = require 'utils.color_presets' --- @dep utils.color_presets
local write_json = _C.write_json --- @dep expcore.common
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(),
@@ -133,8 +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
Global.register({ Roles.config.players, Roles.config.deferred_roles }, function(tbl)
Roles.config.players = tbl[1]
Roles.config.deferred_roles = tbl[2]
end)
--- Getter.
@@ -145,7 +147,7 @@ end)
-- 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)
by_player_name = game.player and game.player.name or by_player_name or '<server>'
by_player_name = by_player_name or game.player and game.player.name or '<server>'
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
@@ -153,14 +155,10 @@ 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
@@ -367,17 +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}
roles = { roles }
end
-- Convert to role objects
local role_objects = {}
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
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 {}
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 "<server>"
role_change.silent = silent
end
else
assign_later[role.name] = {
count = 1, by_player_name = by_player_name or "<server>", silent = silent
}
end
end
Roles.config.deferred_roles[valid_player.name] = assign_later
return
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
@@ -399,17 +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}
roles = { roles }
end
-- Convert to role objects
local role_objects = {}
for _, role in ipairs(roles) do
role = Roles.get_role_from_any(role)
if role then
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 {}
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 "<server>"
role_change.silent = silent
end
else
assign_later[role.name] = {
count = -1, by_player_name = by_player_name or "<server>", silent = silent
}
end
end
Roles.config.deferred_roles[valid_player.name] = assign_later
end
-- 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 valid_player then
emit_player_roles_updated(valid_player, 'unassign', roles, by_player_name, silent)
-- 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 {}
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 details.count > 0 then
role:add_player(valid_player or player, valid_player == nil, true)
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 and #role_changes > 0 then
emit_player_roles_updated(valid_player, 'unassign', role_changes, by_player_name, silent)
end
end

View File

@@ -18,7 +18,6 @@
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 valid_player = Game.get_player_from_any
local assign_roles = Roles.assign_player
@@ -43,12 +42,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
@@ -89,7 +82,6 @@ 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
player.walking_state = { walking = false }
player.riding_state = { acceleration = defines.riding.acceleration.nothing, direction = player.riding_state.direction }
@@ -98,8 +90,9 @@ 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)
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)
@@ -116,9 +109,7 @@ 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 {}
assign_roles(player, roles, by_player_name, nil, true)
unassign_roles(player, 'Jail', by_player_name, nil, true)
event_emit(Jail.events.on_player_unjailed, player, by_player_name)
@@ -126,4 +117,4 @@ function Jail.unjail_player(player, by_player_name)
return true
end
return Jail
return Jail