Merge pull request #169 from Cooldude2606/feature/role-core-fix

Fixed issue with add_player and remove_player
This commit is contained in:
Cooldude2606
2020-08-01 01:05:00 +01:00
committed by GitHub

View File

@@ -119,15 +119,15 @@ local write_json = _C.write_json --- @dep expcore.common
local Roles = { local Roles = {
_prototype={}, _prototype={},
config={ config={
order={}, -- Contains the order of the roles, lower index is better order = {}, -- Contains the order of the roles, lower index is better
roles={}, -- Contains the raw info for the roles, indexed by role name 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 flags = {}, -- Contains functions that run when a flag is added/removed from a player
internal={}, -- Contains all internally accessed roles, such as root, default internal = {}, -- Contains all internally accessed roles, such as root, default
players={} -- Contains the roles that players have players = {} -- Contains the roles that players have
}, },
events = { events = {
on_role_assigned=script.generate_event_name(), on_role_assigned = script.generate_event_name(),
on_role_unassigned=script.generate_event_name(), on_role_unassigned = script.generate_event_name(),
} }
} }
@@ -145,7 +145,7 @@ end)
-- there is a second half called role_update which triggers after the event call, it also is called when a player joins -- 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)
by_player_name = game.player and game.player.name or by_player_name or '<server>' by_player_name = game.player and game.player.name or by_player_name or '<server>'
local by_player = Game.get_player_from_any(by_player_name) local by_player = game.players[by_player_name]
local by_player_index = by_player and by_player.index or 0 local by_player_index = by_player and by_player.index or 0
-- get the event id from the type of emit -- get the event id from the type of emit
local event = Roles.events.on_role_assigned local event = Roles.events.on_role_assigned
@@ -153,12 +153,13 @@ local function emit_player_roles_updated(player, type, roles, by_player_name, sk
event = Roles.events.on_role_unassigned event = Roles.events.on_role_unassigned
end end
-- convert the roles to objects and get the names of the roles -- convert the roles to objects and get the names of the roles
local role_names = {} local index, role_names, valid_roles = 0, {}, {}
for index, role in pairs(roles) do for _, role in ipairs(roles) do
role = Roles.get_role_from_any(role) role = Roles.get_role_from_any(role)
if role then if role then
roles[index] = role index = index + 1
table.insert(role_names, role.name) valid_roles[index] = role
role_names[index] = role.name
end end
end end
-- output to all the different locations: game print, player sound, event trigger and role log -- output to all the different locations: game print, player sound, event trigger and role log
@@ -175,7 +176,7 @@ local function emit_player_roles_updated(player, type, roles, by_player_name, sk
tick=game.tick, tick=game.tick,
player_index=player.index, player_index=player.index,
by_player_index=by_player_index, by_player_index=by_player_index,
roles=roles roles=valid_roles
}) })
write_json('log/roles.log', { write_json('log/roles.log', {
player_name=player.name, player_name=player.name,
@@ -194,7 +195,7 @@ game.player.print(Roles.debug())
]] ]]
function Roles.debug() function Roles.debug()
local output = '' local output = ''
for index, role_name in pairs(Roles.config.order) do for index, role_name in ipairs(Roles.config.order) do
local role = Roles.config.roles[role_name] local role = Roles.config.roles[role_name]
local color = role.custom_color or Colours.white local color = role.custom_color or Colours.white
color = string.format('[color=%d, %d, %d]', color.r, color.g, color.b) color = string.format('[color=%d, %d, %d]', color.r, color.g, color.b)
@@ -212,7 +213,7 @@ Roles.print_to_roles({'Administrator', 'Moderator'}, 'Hello, World!')
]] ]]
function Roles.print_to_roles(roles, message) function Roles.print_to_roles(roles, message)
for _, role in pairs(roles) do for _, role in ipairs(roles) do
role = Roles.get_role_from_any(role) role = Roles.get_role_from_any(role)
if role then role:print(message) end if role then role:print(message) end
end end
@@ -230,9 +231,9 @@ function Roles.print_to_roles_higher(role, message)
role = Roles.get_role_from_any(role) role = Roles.get_role_from_any(role)
if not role then return end if not role then return end
local roles = {} local roles = {}
for index, role_name in pairs(Roles.config.order) do for index, role_name in ipairs(Roles.config.order) do
if index <= role.index and role_name ~= Roles.config.internal.default then if index <= role.index and role_name ~= Roles.config.internal.default then
table.insert(roles, role_name) roles[#roles+1] = role_name
end end
end end
Roles.print_to_roles(roles, message) Roles.print_to_roles(roles, message)
@@ -250,9 +251,9 @@ function Roles.print_to_roles_lower(role, message)
role = Roles.get_role_from_any(role) role = Roles.get_role_from_any(role)
if not role then return end if not role then return end
local roles = {} local roles = {}
for index, role_name in pairs(Roles.config.order) do for index, role_name in ipairs(Roles.config.order) do
if index >= role.index and role_name ~= Roles.config.internal.default then if index >= role.index and role_name ~= Roles.config.internal.default then
table.insert(roles, role_name) roles[#roles+1] = role_name
end end
end end
Roles.print_to_roles(roles, message) Roles.print_to_roles(roles, message)
@@ -318,8 +319,8 @@ function Roles.get_player_roles(player)
local roles = Roles.config.players[player.name] or {} local roles = Roles.config.players[player.name] or {}
local default = Roles.config.roles[Roles.config.internal.default] local default = Roles.config.roles[Roles.config.internal.default]
local rtn = {default} local rtn = {default}
for _, role_name in pairs(roles) do for index, role_name in ipairs(roles) do
table.insert(rtn, Roles.config.roles[role_name]) rtn[index+1] = Roles.config.roles[role_name]
end end
return rtn return rtn
end end
@@ -336,7 +337,7 @@ function Roles.get_player_highest_role(player)
local roles = Roles.get_player_roles(player) local roles = Roles.get_player_roles(player)
if not roles then return end if not roles then return end
local highest local highest
for _, role in pairs(roles) do for _, role in ipairs(roles) do
if not highest or role.index < highest.index then if not highest or role.index < highest.index then
highest = role highest = role
end end
@@ -344,9 +345,9 @@ function Roles.get_player_highest_role(player)
return highest return highest
end end
--- Assinment. --- Assignment.
-- Functions for changing player's roles -- Functions for changing player's roles
-- @section assinment -- @section assignment
--[[-- Gives a player the given role(s) with an option to pass a by player name used in the log --[[-- Gives a player the given role(s) with an option to pass a by player name used in the log
@tparam LuaPlayer player the player that will be assigned the roles @tparam LuaPlayer player the player that will be assigned the roles
@@ -365,10 +366,11 @@ Roles.assign_player('Cooldude2606', 'Moderator', nil, true)
function Roles.assign_player(player, roles, by_player_name, skip_checks, silent) function Roles.assign_player(player, roles, by_player_name, skip_checks, silent)
local valid_player = Game.get_player_from_any(player) local valid_player = Game.get_player_from_any(player)
if not skip_checks and not valid_player then return end 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 if type(roles) ~= 'table' or roles.name then
roles = {roles} roles = {roles}
end end
for _, role in pairs(roles) do for _, role in ipairs(roles) do
role = Roles.get_role_from_any(role) role = Roles.get_role_from_any(role)
if role then if role then
role:add_player(valid_player or player, valid_player == nil, true) role:add_player(valid_player or player, valid_player == nil, true)
@@ -400,7 +402,7 @@ function Roles.unassign_player(player, roles, by_player_name, skip_checks, silen
if type(roles) ~= 'table' or roles.name then if type(roles) ~= 'table' or roles.name then
roles = {roles} roles = {roles}
end end
for _, role in pairs(roles) do for _, role in ipairs(roles) do
role = Roles.get_role_from_any(role) role = Roles.get_role_from_any(role)
if role then if role then
role:remove_player(valid_player or player, valid_player == nil, true) role:remove_player(valid_player or player, valid_player == nil, true)
@@ -453,7 +455,7 @@ function Roles.player_has_role(player, search_role)
if not roles then return end if not roles then return end
search_role = Roles.get_role_from_any(search_role) search_role = Roles.get_role_from_any(search_role)
if not search_role then return end if not search_role then return end
for _, role in pairs(roles) do for _, role in ipairs(roles) do
if role.name == search_role.name then return true end if role.name == search_role.name then return true end
end end
return false return false
@@ -471,7 +473,7 @@ local has_flag = Roles.player_has_flag(game.player, 'is_donator')
function Roles.player_has_flag(player, flag_name) function Roles.player_has_flag(player, flag_name)
local roles = Roles.get_player_roles(player) local roles = Roles.get_player_roles(player)
if not roles then return end if not roles then return end
for _, role in pairs(roles) do for _, role in ipairs(roles) do
if role:has_flag(flag_name) then if role:has_flag(flag_name) then
return true return true
end end
@@ -491,7 +493,7 @@ local has_flag = Roles.player_has_flag(game.player, 'is_donator')
function Roles.player_allowed(player, action) function Roles.player_allowed(player, action)
local roles = Roles.get_player_roles(player) local roles = Roles.get_player_roles(player)
if not roles then return end if not roles then return end
for _, role in pairs(roles) do for _, role in ipairs(roles) do
if role:is_allowed(action) then if role:is_allowed(action) then
return true return true
end end
@@ -499,7 +501,7 @@ function Roles.player_allowed(player, action)
return false return false
end end
--- Definations. --- Definitions.
-- Functions which are used to define roles -- Functions which are used to define roles
-- @section checks -- @section checks
@@ -522,17 +524,17 @@ function Roles.define_role_order(order)
_C.error_if_runtime() _C.error_if_runtime()
Roles.config.order = {} Roles.config.order = {}
local done = {} local done = {}
for _, role in ipairs(order) do for index, role in ipairs(order) do
if type(role) == 'table' and role.name then if type(role) == 'table' and role.name then
done[role.name] = true done[role.name] = true
table.insert(Roles.config.order, role.name) Roles.config.order[index] = role.name
else else
done[role] = true done[role] = true
table.insert(Roles.config.order, role) Roles.config.order[index] = role
end end
end end
-- Check no roles were missed -- Check no roles were missed
for role_name, _ in pairs(Roles.config.roles) do for role_name in pairs(Roles.config.roles) do
if not done[role_name] then if not done[role_name] then
error('Role missing '..role_name..' from role order, all defined roles must be included.', 2) error('Role missing '..role_name..' from role order, all defined roles must be included.', 2)
end end
@@ -555,7 +557,7 @@ end
@tparam string name the name of the flag which the roles will have @tparam string name the name of the flag which the roles will have
@tparam function callback the function that is called when roles are assigned @tparam function callback the function that is called when roles are assigned
@usage-- Defineing a flag trigger @usage-- Defining a flag trigger
Roles.define_flag_trigger('is_donator', function(player, state) Roles.define_flag_trigger('is_donator', function(player, state)
player.character_running_speed_modifier = state and 1.5 or 1 player.character_running_speed_modifier = state and 1.5 or 1
end) end)
@@ -598,7 +600,7 @@ end
@tparam[opt=name] string short_hand the shortened version of the name @tparam[opt=name] string short_hand the shortened version of the name
@treturn Roles._prototype the start of the config chain for this role @treturn Roles._prototype the start of the config chain for this role
@usage-- Defineing a new role @usage-- Defining a new role
local role = Roles.new_role('Moderator', 'Mod') local role = Roles.new_role('Moderator', 'Mod')
]] ]]
@@ -649,7 +651,7 @@ function Roles._prototype:allow(actions)
if type(actions) ~= 'table' then if type(actions) ~= 'table' then
actions = {actions} actions = {actions}
end end
for _, action in pairs(actions) do for _, action in ipairs(actions) do
self.allowed_actions[action]=true self.allowed_actions[action]=true
end end
return self return self
@@ -659,7 +661,7 @@ end
@tparam table actions indexed with numbers and is an array of action names, order has no effect @tparam table actions indexed with numbers and is an array of action names, order has no effect
@treturn Roles._prototype allows chaining @treturn Roles._prototype allows chaining
@usage-- Disalow an action for a role, useful if inherit an action from a parent @usage-- Disallow an action for a role, useful if inherit an action from a parent
role:disallow{ role:disallow{
'command/kill', 'command/kill',
'gui/game settings' 'gui/game settings'
@@ -670,7 +672,7 @@ function Roles._prototype:disallow(actions)
if type(actions) ~= 'table' then if type(actions) ~= 'table' then
actions = {actions} actions = {actions}
end end
for _, action in pairs(actions) do for _, action in ipairs(actions) do
self.allowed_actions[action]=false self.allowed_actions[action]=false
end end
return self return self
@@ -733,7 +735,7 @@ function Roles._prototype:has_flag(name)
end end
--- Role Properties. --- Role Properties.
-- Functions for chaning other proerties -- Functions for changing other properties
-- @section properties -- @section properties
--[[-- Sets a custom player tag for the role, can be accessed by other code --[[-- Sets a custom player tag for the role, can be accessed by other code
@@ -850,30 +852,31 @@ role:add_player(game.player)
]] ]]
function Roles._prototype:add_player(player, skip_check, skip_event) function Roles._prototype:add_player(player, skip_check, skip_event)
player = Game.get_player_from_any(player) local valid_player = Game.get_player_from_any(player)
-- Default role cant have players added or removed -- Default role cant have players added or removed
if self.name == Roles.config.internal.default then return end if self.name == Roles.config.internal.default then return end
-- Check the player is valid, can be skipped but a name must be given -- Check the player is valid, can be skipped but a name must be given
if not player then local player_name
if skip_check then if valid_player then
player = {name=player} player_name = valid_player.name
else elseif skip_check then
return false player_name = player
end else
return false
end end
-- Add the role name to the player's roles -- Add the role name to the player's roles
local player_roles = Roles.config.players[player.name] local player_roles = Roles.config.players[player_name]
if player_roles then if player_roles then
for _, role_name in pairs(player_roles) do for _, role_name in ipairs(player_roles) do
if role_name == self.name then return false end if role_name == self.name then return false end
end end
table.insert(player_roles, self.name) player_roles[#player_roles+1] = self.name
else else
Roles.config.players[player.name] = {self.name} Roles.config.players[player_name] = {self.name}
end end
-- Emits event if required -- Emits event if required
if not skip_event then if valid_player and not skip_event then
emit_player_roles_updated(player, 'assign', {self}) emit_player_roles_updated(valid_player, 'assign', {self})
end end
return true return true
end end
@@ -889,37 +892,39 @@ role:remove_player(game.player)
]] ]]
function Roles._prototype:remove_player(player, skip_check, skip_event) function Roles._prototype:remove_player(player, skip_check, skip_event)
player = Game.get_player_from_any(player) local valid_player = Game.get_player_from_any(player)
-- Default role cant have players added or removed -- Default role cant have players added or removed
if self.name == Roles.config.internal.default then return end if self.name == Roles.config.internal.default then return end
-- Check the player is valid, can be skipped but a name must be given -- Check the player is valid, can be skipped but a name must be given
if not player then local player_name
if skip_check then if valid_player then
player = {name=player} player_name = valid_player.name
else elseif skip_check then
return false player_name = player
end else
return false
end end
-- Remove the role from the players roles -- Remove the role from the players roles
local player_roles = Roles.config.players[player.name] local player_roles = Roles.config.players[player_name]
local rtn = false local found = false
if player_roles then if player_roles then
for index, role_name in pairs(player_roles) do for index, role_name in ipairs(player_roles) do
if role_name == self.name then if role_name == self.name then
table.remove(player_roles, index) player_roles[index] = player_roles[#player_roles]
rtn = true player_roles[#player_roles] = nil
found = true
break break
end end
end end
if #player_roles == 0 then if #player_roles == 0 then
Roles.config.players[player.name] = nil Roles.config.players[player_name] = nil
end end
end end
-- Emits event if required -- Emits event if required
if not skip_event then if valid_player and not skip_event then
emit_player_roles_updated(player, 'unassign', {self}) emit_player_roles_updated(valid_player, 'unassign', {self})
end end
return rtn return found
end end
--[[-- Returns an array of all the players who have this role, can be filtered by online status --[[-- Returns an array of all the players who have this role, can be filtered by online status
@@ -935,30 +940,20 @@ local players = role:get_players(true)
]] ]]
function Roles._prototype:get_players(online) function Roles._prototype:get_players(online)
local players = {} local players = {}
-- Gets all players that have this role -- Search all players to check if they have this role
for player_name, player_roles in pairs(Roles.config.players) do for player_name, player_roles in pairs(Roles.config.players) do
for _, role_name in pairs(player_roles) do for _, role_name in ipairs(player_roles) do
if role_name == self.name then if role_name == self.name then
table.insert(players, player_name) local player = game.players[player_name]
-- Filter by online state if required
if online == nil or player.connected == online then
players[#players+1] = player
end
break
end end
end end
end end
-- Convert the player names to LuaPlayer return players
for index, player_name in pairs(players) do
players[index] = Game.get_player_from_any(player_name)
end
-- Filter by online if param is defined
if online == nil then
return players
else
local filtered = {}
for _, player in pairs(players) do
if player.connected == online then
table.insert(filtered, player)
end
end
return filtered
end
end end
--[[-- Will print a message to all players with this role --[[-- Will print a message to all players with this role
@@ -971,7 +966,7 @@ role:print('Hello, World!')
]] ]]
function Roles._prototype:print(message) function Roles._prototype:print(message)
local players = self:get_players(true) local players = self:get_players(true)
for _, player in pairs(players) do for _, player in ipairs(players) do
player.print(message) player.print(message)
end end
return #players return #players
@@ -979,7 +974,7 @@ end
--- Used internally to be the first trigger on an event change, would be messy to include this in 4 different places --- Used internally to be the first trigger on an event change, would be messy to include this in 4 different places
local function role_update(event) local function role_update(event)
local player = Game.get_player_by_index(event.player_index) local player = game.players[event.player_index]
-- Updates flags given to the player -- Updates flags given to the player
for flag, async_token in pairs(Roles.config.flags) do for flag, async_token in pairs(Roles.config.flags) do
local state = Roles.player_has_flag(player, flag) local state = Roles.player_has_flag(player, flag)
@@ -1006,8 +1001,8 @@ Event.add(defines.events.on_player_joined_game, role_update)
-- Every 60 seconds the auto promote check is preformed -- Every 60 seconds the auto promote check is preformed
Event.on_nth_tick(3600, function() Event.on_nth_tick(3600, function()
local promotes = {} local promotes = {}
for _, player in pairs(game.connected_players) do for _, player in ipairs(game.connected_players) do
for _, role in pairs(Roles.config.roles) do for _, role in ipairs(Roles.config.roles) do
if role.auto_promote_condition then if role.auto_promote_condition then
local success, err = pcall(role.auto_promote_condition, player) local success, err = pcall(role.auto_promote_condition, player)
if not success then if not success then