Moved Files Around

This commit is contained in:
Cooldude2606
2019-04-18 22:24:10 +01:00
parent f6221ee68e
commit 89d52fc73b
57 changed files with 7 additions and 71 deletions

View File

@@ -1,298 +0,0 @@
--- Command system that allows middle ware and auto validation of command arguments.
-- @module ExpGamingCore.Command@4.0.0
-- @author Cooldude2606
-- @license https://github.com/explosivegaming/scenario/blob/master/LICENSE
-- @alias commands
local Game = require('FactorioStdLib.Game')
local Color = require('FactorioStdLib.Color')
--- Used as an error constant for validation
-- @field commands.error
-- @usage return commands.error, 'err message'
-- @usage return commands.error('err message')
commands.error = setmetatable({},{__call=function(...) return ... end})
commands._add_command = commands.add_command
local commandDataStore = {}
local middleware = {}
--- Used to add middle ware to the command handler, functions should return true or false
-- @tparam function callback function(player,commandName,event) should return true to allow next middle ware to run
function commands.add_middleware(callback) if not is_type(callback,'function') then error('Callback is not a function',2) return end table.insert(middleware,callback) end
--- Index of all command data
-- @field commands.data
-- @usage commands.command_name -- returns command data
-- @usage commands.data -- returns all data
-- @tparam ?string|table|event key the command that will be returned: string is the name, table is the command data, event is event from add_command
-- @treturn table the command data
setmetatable(commands,{
__index=function(tbl,key) return is_type(key,'table') and (key.command and rawget(commandDataStore,key.name) or key) or key == 'data' and commandDataStore or rawget(commandDataStore,key) end
})
--- Collection of functions that can be used to validate inputs
-- @table commands.validate
-- @usage commands.validate[type](value,event,...)
-- @tparam string type the type that the value should be
-- @param value the value that will be tested
-- @param ... any other data that can be passed to the function
-- @return[1] the validated value
-- @return[2] error constant
-- @return[2] the err message
-- @field __comment replace _ with - the ldoc did not like me using - in the names
-- @field string basically does nothing but a type filed is required
-- @field string_inf same as string but is infinite in length, must be last arg
-- @field string_len same as string but can define a max length
-- @field number converts the input into a number
-- @field number_int converts the input to a number and floors it
-- @field number_range allows a number in a range min < X <= max
-- @field number_range allows a number in a range after it has been floored min < math.floor(X) <= max
-- @field player converts the input into a valid player
-- @field player_online converts the input to a player if the player is online
-- @field player_alive converts the input to a player if the player is online and alive
-- @field player_role converts the input to a player if the player is a lower rank than the user or if the person is not admin and the user is
-- @field player_role-online converts the input to a player if the player is a lower rank than the user and online
-- @field player_role_alive converts the input to a player if the player is a lower rank than the user and online and alive
commands.validate = {
['boolean']=function(value) value = value.lower() if value == 'true' or value == 'yes' or value == 'y' or value == '1' then return true else return false end end,
['string']=function(value) return tostring(value) end,
['string-inf']=function(value) return tostring(value) end,
['string-list']=function(value,event,list)
local rtn = tostring(value) and table.includes(list,tostring(value)) and tostring(value) or nil
if not rtn then return commands.error{'expcore-commands.error-string-list',table.concat(list,', ')} end return rtn end,
['string-len']=function(value,event,max)
local rtn = tostring(value) and tostring(value):len() <= max and tostring(value) or nil
if not rtn then return commands.error{'expcore-commands.error-string-len',max} end return rtn end,
['number']=function(value)
local rtn = tonumber(value) or nil
if not rtn then return commands.error{'expcore-commands.error-number'} end return rtn end,
['number-int']=function(value)
local rtn = tonumber(value) and math.floor(tonumber(value)) or nil
if not rtn then return commands.error{'expcore-commands.error-number'} end return rtn end,
['number-range']=function(value,event,min,max)
local rtn = tonumber(value) and tonumber(value) > min and tonumber(value) <= max and tonumber(value) or nil
if not rtn then return commands.error{'expcore-commands.error-number-range',min,max} end return rtn end,
['number-range-int']=function(value,event,min,max)
local rtn = tonumber(value) and math.floor(tonumber(value)) > min and math.floor(tonumber(value)) <= max and math.floor(tonumber(value)) or nil
if not rtn then return commands.error{'expcore-commands.error-number-range',min,max} end return rtn end,
['player']=function(value)
local rtn = Game.get_player(value) or nil
if not rtn then return commands.error{'expcore-commands.error-player',value} end return rtn end,
['player-online']=function(value)
local player,err = commands.validate['player'](value)
if err then return commands.error(err) end
local rtn = player.connected and player or nil
if not rtn then return commands.error{'expcore-commands.error-player-online'} end return rtn end,
['player-alive']=function(value)
local player,err = commands.validate['player-online'](value)
if err then return commands.error(err) end
local rtn = player.character and player.character.health > 0 and player or nil
if not rtn then return commands.error{'expcore-commands.error-player-alive'} end return rtn end,
['player-rank']=function(value,event)
local player,err = commands.validate['player'](value)
if err then return commands.error(err) end
local rtn = player.admin and Game.get_player(event).admin and player or nil
if not rtn then return commands.error{'expcore-commands.error-player-rank'} end return rtn end,
['player-rank-online']=function(value)
local player,err = commands.validate['player-online'](value)
if err then return commands.error(err) end
local player,err = commands.validate['player-rank'](player)
if err then return commands.error(err) end return player end,
['player-rank-alive']=function(value)
local player,err = commands.validate['player-alive'](value)
if err then return commands.error(err) end
local player,err = commands.validate['player-rank'](player)
if err then return commands.error(err) end return player end,
}
--- Adds a function to the validation list
-- @tparam string name the name of the validation
-- @tparam function callback function(value,event) which returns either the value to be used or commands.error{'error-message'}
function commands.add_validation(name,callback) if not is_type(callback,'function') then error('Callback is not a function',2) return end commands.validate[name]=callback end
--- Returns the inputs of this command as a formated string
-- @usage commands.format_inputs('interface') -- returns <code> (if you have ExpGamingCore.Server)
-- @tparam ?string|table|event command the command to get the inputs of
-- @treturn string the formated string for the inputs
function commands.format_inputs(command)
command = commands[command]
if not is_type(command,'table') then error('Command is not valid',2) end
local rtn = ''
for name,data in pairs(command.inputs) do
if data[1] == false then rtn=rtn..string.format('[%s] ',name)
else rtn=rtn..string.format('<%s> ',name) end
end
return rtn
end
--- Used to validate the arguments of a command, will understand strings with "" as a single param else spaces divede the params
-- @usage commands.validate_args(event) -- returns args table
-- @tparam table event this is the event created by add_command not on_console_command
-- @treturn[1] table the args for this command
-- @return[2] command.error
-- @treturn string the error that happend while parsing the args
function commands.validate_args(event)
local command = commands[event.name]
if not is_type(command,'table') then error('Command not valid',2) end
local rtn = {}
local count = 0
local count_opt = 0
for _,data in pairs(command.inputs) do count = count + 1 if data[1] == false then count_opt = count_opt + 1 end end
-- checks that there is some args given if there is meant to be
if not event.parameter then
if count == count_opt then return rtn
else return commands.error('invalid-inputs') end
end
-- splits the args into words so that it can be used to assign values
local words = string.split(event.parameter,' ')
local index = 0
for _,word in pairs(words) do
index = index+1
if not word then break end
local pos, _pos = word:find('"')
local hasSecond = pos and word:find('"',pos+1) or nil
while not hasSecond and pos and pos == _pos do
local next = table.remove(words,index+1)
if not next then return commands.error('invalid-parse') end
words[index] = words[index]..' '..next
_pos = words[index]:find('"',pos+1)
end
end
-- assigns the values from the words to the args
index = 0
for name,data in pairs(command.inputs) do
index = index+1
local arg = words[index]
if not arg and data[1] then return commands.error('invalid-inputs') end
if data[2] == 'string-inf' then rtn[name] = table.concat(words,' ',index) break end
local valid = is_type(data[2],'function') and data[2] or commands.validate[data[2]] or error('Invalid validation ("'..tostring(data[2])..'") for command: "'..command.name..'/'..name..'"')
local temp_tbl = table.deepcopy(data) table.remove(temp_tbl,1) table.remove(temp_tbl,1)
local value, err = valid(arg,event,unpack(temp_tbl))
if value == commands.error then return value, err end
rtn[name] = is_type(value,'string') and value:gsub('"','') or value
end
return rtn
end
--- Used to return all the commands a player can use
-- @usage get_commands(1) -- return table of command data for each command that the player can use
-- @tparam ?index|name|player| player the player to test as
-- @treturn table a table containg all the commands the player can use
function commands.get_commands(player)
player = Game.get_player(player)
local commands = {}
if not player then return error('Invalid player',2) end
for name,data in pairs(commandDataStore) do
if #middleware > 0 then for _,callback in pairs(middleware) do
local success, err = pcall(callback,player,name,data)
if not success then error(err)
elseif err then table.insert(commands,data) end
end elseif data.default_admin_only == true and player.admin then table.insert(commands,data) end
end
return commands
end
local function logMessage(player_name,command,message,args)
game.write_file('commands.log',
game.tick
..' Player: "'..player_name..'"'
..' '..message..': "'..command.name..'"'
..' With args of: '..table.tostring(args)
..'\n'
, true, 0)
end
--- Used to call the custom commands
-- @usage You dont its an internal command
-- @tparam table command the event rasied by the command
local function run_custom_command(command)
local data = commands.data[command.name]
local player = Game.get_player(command) or SERVER
-- runs all middle ware if any, if there is no middle where then it relies on .default_admin_only
if #middleware > 0 then for _,callback in pairs(middleware) do
local success, err = pcall(callback,player,command.name,command)
if not success then error(err)
elseif not err then
player_return({'expcore-commands.command-fail',{'expcore-commands.unauthorized'}},defines.textcolor.crit)
logMessage(player.name,command,'Failed to use command (Unauthorized)',commands.validate_args(command))
game.player.play_sound{path='utility/cannot_build'}
return
end
end elseif data.default_admin_only == true and player and not player.admin then
player_return({'expcore-commands.command-fail',{'expcore-commands.unauthorized'}},defines.textcolor.crit)
logMessage(player.name,command,'Failed to use command (Unauthorized)',commands.validate_args(command))
game.player.play_sound{path='utility/cannot_build'}
return
end
-- gets the args for the command
local args, err = commands.validate_args(command)
if args == commands.error then
if is_type(err,'table') then table.insert(err,command.name) table.insert(err,commands.format_inputs(data))
player_return({'expcore-commands.command-fail',err},defines.textcolor.high) else player_return({'expcore-commands.command-fail',{'expcore-commands.invalid-inputs',command.name,commands.format_inputs(data)}},defines.textcolor.high) end
logMessage(player.name,command,'Failed to use command (Invalid Args)',args)
player.play_sound{path='utility/deconstruct_big'}
return
end
-- runs the command
local success, err = pcall(data.callback,command,args)
if not success then error(err) end
if err ~= commands.error then player_return({'expcore-commands.command-ran'},defines.textcolor.info) end
logMessage(player.name,command,'Used command',args)
end
--- Used to define commands
-- @usage --see examples in file
-- @tparam string name the name of the command
-- @tparam[opt='No Description'] string description the description of the command
-- @tparam[opt=an infinite string] table inputs a table of the inputs to be used, last index being true makes the last parameter open ended (longer than one word)
-- @tparam function callback the function to call on the event
commands.add_command = function(name, description, inputs, callback)
if commands[name] then error('That command is already registered',2) end
if not is_type(name,'string') then error('Command name has not been given') end
if not is_type(callback,'function') or not is_type(inputs,'table') then
if is_type(inputs,'function') then commands._add_command(name,description,inputs)
else error('Invalid args given to add_command') end
end
verbose('Created Command: '..name)
-- test for string and then test for locale string
description = is_type(description,'string') and description
or is_type(description,'table') and is_type(description[1],'string') and string.find(description[1],'.+[.].+') and {description,''}
or 'No Description'
inputs = is_type(inputs,'table') and inputs or {['param']={false,'string-inf'}}
commandDataStore[name] = {
name=name,
description=description,
inputs=inputs,
callback=callback,
admin_only=false
}
local help = is_type(description,'string') and commands.format_inputs(name)..'- '..description
or is_type(description,'table') and is_type(description[1],'string') and string.find(description[1],'.+[.].+') and {description,commands.format_inputs(name)..'- '}
or commands.format_inputs(name)
commandDataStore[name].help = help
commands._add_command(name,help,function(...)
local success, err = Manager.sandbox(run_custom_command,{},...)
if not success then error(err) end
end)
return commandDataStore[name]
end
return commands
--[[
command example
**locale file**
[foo]
description=__1__ this is a command
**control.lua**
commands.add_command('foo',{'foo.description'},{
['player']={true,'player'}, -- a required arg that must be a valid player
['number']={true,'number-range',0,10}, -- a required arg that must be a number 0<X<=10
['pwd']={true,function(value,event) if value == 'password123' then return true else return commands.error('Invalid Password') end} -- a required arg pwd that has custom validation
['reason']={false,'string-inf'} -- an optional arg that is and infinite length (useful for reasons)
},function(event,args)
args.player.print(args.number)
if args.reasons then args.player.print(args.reason) end
end)
]]

View File

@@ -1,21 +0,0 @@
{
"name": "ExpGamingCore.Command",
"version": "4.0.0",
"description": "A better command handler than the base game.",
"location": "FSM_ARCHIVE",
"keywords": [
"Library",
"Lib",
"ExpGaming",
"Core",
"Commands"
],
"dependencies": {
"ExpGamingLib": "^4.0.0",
"FactorioStdLib.Table": "^0.8.0",
"FactorioStdLib.Color": "^0.8.0",
"FactorioStdLib.Game": "^0.8.0"
},
"collection": "ExpGamingCore@4.0.0",
"submodules": {}
}

View File

@@ -1,81 +0,0 @@
-- defines for groups
Group{
name='Admin',
disallow={
'edit_permission_group',
'delete_permission_group',
'add_permission_group'
}
}
Group{
name='HiMember',
disallow={
'edit_permission_group',
'delete_permission_group',
'add_permission_group'
}
}
Group{
name='Member',
disallow={
'edit_permission_group',
'delete_permission_group',
'add_permission_group',
'set_auto_launch_rocket',
'change_programmable_speaker_alert_parameters',
'drop_item'
}
}
Group{
name='User',
disallow={
'edit_permission_group',
'delete_permission_group',
'add_permission_group',
'set_auto_launch_rocket',
'change_programmable_speaker_alert_parameters',
'drop_item',
'build_terrain',
'remove_cables',
'launch_rocket',
'reset_assembling_machine',
'cancel_research'
}
}
Group{
name='Jail',
disallow={
'set_allow_commands',
'edit_permission_group',
'delete_permission_group',
'add_permission_group',
'open_character_gui',
'begin_mining',
'start_walking',
'player_leave_game',
'open_blueprint_library_gui',
'build_item',
'use_item',
'select_item',
'rotate_entity',
'open_train_gui',
'open_train_station_gui',
'open_gui',
'open_item',
'deconstruct',
'build_rail',
'cancel_research',
'start_research',
'set_train_stopped',
'select_gun',
'open_technology_gui',
'open_trains_gui',
'edit_custom_tag',
'craft',
'setup_assembling_machine',
}
}

View File

@@ -1,189 +0,0 @@
--- Adds a system to manage and auto-create permission groups.
-- @module ExpGamingCore@Group
-- @author Cooldude2606
-- @license https://github.com/explosivegaming/scenario/blob/master/LICENSE
-- @alias Group
-- Module Require
local Game = require('FactorioStdLib.Game')
-- Module Define
local module_verbose = false
--- Used as an interface for factorio permissions groups
-- @type Group
-- @field _prototype the prototype of this class
-- @field groups a table of all groups, includes auto complete on the indexing
local _GroupSelfRef
local Group = {
_prototype = {},
groups = setmetatable({},{
__index=table.autokey,
__newindex=function(tbl,key,value)
rawset(tbl,key,_GroupSelfRef.define(value))
end
}),
on_init = function()
if loaded_modules['ExpGamingCore.Server'] then require('ExpGamingCore.Server') end
end,
on_post = function(self)
-- creates a root role that the server can use
self{name='Root',disallow={}}
-- loads the groups in config
require(module_path..'/config',{Group=self})
end
}
_GroupSelfRef=Group
-- Function Define
--- Defines a new instance of a group
-- @usage Group.define{name='foo',disallow={'edit_permission_group','delete_permission_group','add_permission_group'}} -- returns new group
-- @usage Group{name='foo',disallow={'edit_permission_group','delete_permission_group','add_permission_group'}} -- returns new group
-- @tparam table obj contains string name and table disallow of defines.input_action
-- @treturn Group the group which has been made
function Group.define(obj)
if not type_error(game,nil,'Cant define Group during runtime.') then return end
if not type_error(obj.name,'string','Group creation is invalid: group.name is not a string') then return end
if not type_error(obj.disallow,'table','Group creation is invalid: group.disallow is not a table') then return end
verbose('Created Group: '..obj.name)
setmetatable(obj,{__index=function(tbl,key) return Group._prototype[key] or game and game.permissions.get_group(tbl.name)[key] or nil end})
obj.connected_players = setmetatable({self=obj},Group._prototype.connected_players_mt)
rawset(Group.groups,obj.name,obj)
return obj
end
--- Used to get the group of a player or the group by name
-- @usage Group.get('foo') -- returns group foo
-- @usage Group.get(player) -- returns group of player
-- @tparam ?LuaPlayer|pointerToPlayer|string mixed can either be the name or raw group of a group or a player indenifier
-- @treturn table the group which was found or nil
function Group.get(mixed)
if is_type(mixed,'table') and mixed.name then mixed = mixed.name end
if game and Game.get_player(mixed) then mixed = Game.get_player(mixed).permission_group.name end
local rtn = Group.groups[mixed]
if not rtn and game and is_type(mixed,'string') and game.permissions.get_group(mixed) then
rtn = setmetatable({disallow={},name=mixed},{
__index=function(tbl,key) return Group._prototype[key] or game and game.permissions.get_group(tbl.name)[key] or nil end
})
rtn.connected_players = setmetatable({self=rtn},Group._prototype.connected_players_mt)
end
return rtn
end
--- Used to place a player into a group
-- @usage Group.assign(player,group)
-- @tparam ?LuaPlayer|pointerToPlayer player the player to assign the group to
-- @tparam ?string|LuaPermissionGroup the group to add the player to
-- @treturn boolean was the player assigned
function Group.assign(player,group)
player = Game.get_player(player)
if not player then error('Invalid player #1 given to Group.assign.',2) return end
group = Group.get(group)
if not group then error('Invalid group #2 given to Group.assign.',2) return end
return group:add_player(player)
end
--- Used to get the factorio permission group linked to this group
-- @usage group:get_raw() -- returns LuaPermissionGroup of this group
-- @treturn LuaPermissionGroup the factorio group linked to this group
function Group._prototype:get_raw()
if not self_test(self,'group','get_raw') then return end
local _group = game.permissions.get_group(self.name)
if not _group or _group.valid == false then error('No permissions group found, please to not remove groups with /permissions',2) return end
return setmetatable({},{__index=_group})
end
--- Used to add a player to this group
-- @usage group:add_player(player) -- returns true if added
-- @tparam ?LuaPlayer|pointerToPlayer player the player to add to the group
-- @treturn boolean if the player was added
function Group._prototype:add_player(player)
if not self_test(self,'group','add_player') then return end
player = Game.get_player(player)
if not player then error('Invalid player #1 given to group.add_player.',2) return end
local raw_group = self:get_raw()
return raw_group.add_player(player)
end
--- Used to remove a player from this group
-- @usage group:remove_player(player) -- returns true if removed
-- @tparam ?LuaPlayer|pointerToPlayer player the player to remove from the group
-- @treturn boolean if the player was removed
function Group._prototype:remove_player(player)
if not self_test(self,'group','remove_player') then return end
player = Game.get_player(player)
if not player then error('Invalid player #1 given to group.remove_player.',2) return end
local raw_group = self:get_raw()
return raw_group.remove_player(player)
end
--- Gets all players in this group
-- @usage group:get_players() -- returns table of players
-- @usage group.players -- returns table of players
-- @usage group.connected_players -- returns table of online players
-- @tparam[opt=false] boolean online if true returns only online players
-- @treturn table table of players
function Group._prototype:get_players(online)
if not self_test(self,'group','get_players') then return end
if online and not type_error(online,'boolean','Invalid argument #1 to group:get_players, online is not a boolean.') then return end
local raw_group = self:get_raw()
local rtn = {}
if online then for _,player in pairs(raw_group.players) do if player.connected then table.insert(rtn,player) end end end
return online and rtn or raw_group.players
end
-- this is used to create a connected_players table
Group._prototype.connected_players_mt = {
__call=function(tbl) return tbl.self:get_players(true) end,
__pairs=function(self)
local players = self.self:get_players(true)
local function next_pair(tbl,key)
local k, v = next(players, key)
if v then return k,v end
end
return next_pair, players, nil
end,
__ipairs=function(self)
local players = self.self:get_players(true)
local function next_pair(tbl,key)
local k, v = next(players, key)
if v then return k,v end
end
return next_pair, players, nil
end
}
--- Prints a message or value to all online players in this group
-- @usage group.print('Hello, World!')
-- @param rtn any value you wish to print, string not required
-- @param colour the colour to print the message in
-- @treturn number the number of players who received the message
function Group._prototype:print(rtn,colour)
if not self_test(self,'group','print') then return end
if colour and not type_error(colour,'table','Invalid argument #2 to group:print, colour is not a table.') then return end
local players = self:get_players()
local ctn = 0
for _,player in pairs(players) do if player.connected then player_return(rtn,colour,player) ctn=ctn+1 end end
return ctn
end
-- Event Handlers Define
-- creates all permission groups and links them
Event.add('on_init',function()
for name,group in pairs(Group.groups) do
local _group = game.permissions.create_group(name)
verbose('Created Permission Group: '..name)
local count = 0
for _,to_remove in pairs(group.disallow) do
count=count+1
_group.set_allows_action(defines.input_action[to_remove],false)
end
verbose('Disalowed '..count..' input actions.')
end
end)
-- Module Return
-- calling will attempt to define a new group
return setmetatable(Group,{__call=function(tbl,...) tbl.define(...) end})

View File

@@ -1,22 +0,0 @@
{
"name": "ExpGamingCore.Group",
"version": "4.0.0",
"description": "Adds a system to manage and auto-create permission groups.",
"location": "FSM_ARCHIVE",
"keywords": [
"Groups",
"ExpGaming",
"System",
"Management",
"Manage",
"Permissions"
],
"dependencies": {
"FactorioStdLib": "^0.8.0",
"ExpGamingCore.Server": "?^4.0.0",
"ExpGamingLib": "^4.0.0",
"FactorioStdLib.Game": "^0.8.0"
},
"collection": "ExpGamingCore@4.0.0",
"submodules": {}
}

View File

@@ -1,284 +0,0 @@
-- the two below are used internally by the role system and should not be REMOVED, name must be kept the same and used at least once
Role.add_flag('is_default') -- this must be included in at least one role
Role.add_flag('is_root',function(player,state)
if state then game.print('--- !!!ALERT!!! --- '..player.name..' has been given a role with ROOT ACCESS --- !!!ALERT!!! ---') end
if player.character then player.character.destructible = not state end
end) -- the SERVER role will have root but you may assign this to other roles
-- the two below are ised internally by the role system and should not be RENAMED, name must be kept the same but does not need to be used
Role.add_flag('block_auto_promote') -- is not required but name is used internally to block time based promotions
Role.add_flag('is_antiroot',function(player,state) if player.character then player.character.destructible = not state end end) -- not required but setting true will disallow everything for that role
-- all below are not required and are not used internally
Role.add_flag('is_admin',function(player,state) player.admin = state end) -- highly recommenced but not required
Role.add_flag('is_spectator',function(player,state) player.spectator = state end)
Role.add_flag('is_jail',function(player,state) if player.character then player.character.active = not state end end)
Role.add_flag('allow_afk_kick')
Role.add_flag('is_donator')
Role.add_flag('is_timed')
Role.add_flag('is_verified')
Role.add_flag('not_reportable')
-- Root
Role{
name='Root',
short_hand='Root',
tag='[Root]',
group='Root',
colour={r=255,b=255,g=255},
is_root=true,
is_admin=true,
is_spectator=true,
not_reportable=true,
allow={}
}
Role{
name='Community Manager',
short_hand='Com Mngr',
tag='[Com Mngr]',
group='Root',
colour={r=150,g=68,b=161},
is_admin=true,
is_spectator=true,
is_donator=true,
not_reportable=true,
allow={}
}
Role{
name='Developer',
short_hand='Dev',
tag='[Dev]',
group='Root',
colour={r=179,g=125,b=46},
is_admin=true,
is_spectator=true,
is_donator=true,
not_reportable=true,
allow={
['interface']=true,
['cheat-mode']=true
}
}
-- Admin
Role{
name='Administrator',
short_hand='Admin',
tag='[Admin]',
group='Admin',
colour={r=233,g=63,b=233},
is_admin=true,
is_spectator=true,
is_verified=true,
not_reportable=true,
allow={
['game-settings']=true,
['always-warp']=true,
['admin-items']=true
}
}
Role{
name='Moderator',
short_hand='Mod',
tag='[Mod]',
group='Admin',
colour={r=0,g=170,b=0},
is_admin=true,
is_spectator=true,
is_verified=true,
not_reportable=true,
allow={
['set-home']=true,
['home']=true,
['return']=true,
['bonus']=true,
['announcements']=true,
['rank-changer']=true,
}
}
Role{
name='Trainee',
short_hand='TrMod',
tag='[TrMod]',
group='Admin',
colour={r=0,g=196,b=137},
is_spectator=true,
is_verified=true,
not_reportable=true,
allow={
['go-to']=true,
['bring']=true,
['set-home']=false,
['home']=false,
['return']=false,
['bonus']=false,
['admin-commands']=true,
['warn']=true,
['temp-ban']=true,
['clear-warnings']=true,
['clear-reports']=true,
['clear-all']=true,
['clear-inv']=true,
}
}
-- High Member
Role{
name='Sponsor',
short_hand='Spon',
tag='[Sponsor]',
group='HiMember',
colour={r=247,g=246,b=54},
is_spectator=true,
is_donator=true,
allow={}
}
Role{
name='Pay to Win',
short_hand='P2W',
tag='[P2W]',
group='HiMember',
colour={r=238,g=172,b=44},
is_donator=true,
allow={
['jail']=true,
['unjail']=true,
['bonus']=true,
['bonus-respawn']=true
}
}
Role{
name='Donator',
short_hand='Don',
tag='[Donator]',
group='HiMember',
colour={r=230,g=99,b=34},
is_donator=true,
allow_afk_kick=true,
allow={
['set-home']=true,
['home']=true,
['return']=true,
}
}
Role{
name='Partner',
short_hand='Part',
tag='[Partner]',
group='HiMember',
colour={r=140,g=120,b=200},
allow_afk_kick=false,
is_spectator=true,
allow={
['global-chat']=true,
}
}
Role{
name='Veteran',
short_hand='Vet',
tag='[Veteran]',
group='HiMember',
colour={r=140,g=120,b=200},
is_timed=true,
is_verified=true,
allow_afk_kick=true,
time=600, -- 10 hours
allow={
['tree-decon']=true,
['create-poll']=true,
['repair']=true
}
}
-- Member
Role{
name='Member',
short_hand='Mem',
tag='[Member]',
group='Member',
colour={r=24,g=172,b=188},
is_verified=true,
allow_afk_kick=true,
allow={
['edit-tasklist']=true,
['make-warp']=true,
['nuke']=true,
['verified']=true
}
}
Role{
name='Regular',
short_hand='Reg',
tag='[Regular]',
group='Member',
colour={r=79,g=155,b=163},
allow_afk_kick=true,
is_timed=true,
time=180, -- 3 hours
allow={
['kill']=true,
['decon']=true,
['capsules']=true
}
}
-- Guest
Role{
name='Guest',
short_hand='',
tag='',
group='User',
colour={r=185,g=187,b=160},
allow_afk_kick=true,
is_default=true,
allow={
['player-list']=true,
['readme']=true,
['rockets']=true,
['science']=true,
['tasklist']=true,
['report']=true,
['warp-list']=true,
['polls']=true,
['tag']=true,
['tag-clear']=true,
['report']=true
}
}
-- Jail
Role{
name='Jail',
short_hand='Jail',
tag='[Jail]',
group='Jail',
colour={r=50,g=50,b=50},
is_jail=true,
is_antiroot=true,
block_auto_promote=true,
allow={}
}
Role.order = {
'Root',
'Community Manager',
'Developer',
'Administrator',
'Moderator',
'Trainee',
'Sponsor',
'Pay to Win',
'Donator',
'Partner',
'Veteran',
'Member',
'Regular',
'Guest',
'Jail'
}
Role.set_preassign{
["cooldude2606"]={"Developer","Admin","Mod"},
["aldldl"]={"Sponsor","Admin","Donator","Sponsor","Member","Mod"},
["arty714"]={"Admin","Community Manager","Member","Mod"},
["drahc_pro"]={"Admin","Member","Mod"},
["mark9064"]={"Admin","Member","Mod"}
}

View File

@@ -1,532 +0,0 @@
--- Adds roles where a player can have more than one role
-- @module ExpGamingCore.Role@4.0.0
-- @author Cooldude2606
-- @license https://github.com/explosivegaming/scenario/blob/master/LICENSE
-- @alias Role
-- Module Require
local Group = require('ExpGamingCore.Group')
local Game = require('FactorioStdLib.Game')
-- Local Variables
local role_change_event_id = script.generate_event_name('on_role_change')
local RoleGlobal
-- Module Define
local _RoleSelfReference
local module_verbose = false
local Role = {
_prototype={},
order={},
flags={},
actions={},
preassign={},
meta={times={},groups={},count=0},
roles=setmetatable({},{
__index=table.autokey,
__newindex=function(tbl,key,value)
rawset(tbl,key,_RoleSelfReference.define(value))
end
}),
on_init=function(self)
if loaded_modules['ExpGamingCore.Server'] then require('ExpGamingCore.Server').add_module_to_interface('Role','ExpGamingCore.Role') end
if loaded_modules['ExpGamingCore.Command'] then require(module_path..'/src/commands',{self=self}) end
if loaded_modules['ExpGamingCore.Sync'] then require(module_path..'/src/sync',{self=self,RoleGlobal=RoleGlobal}) end
end,
on_post=function(self)
-- creates a server role with root access
self.meta.server = self{name='SERVER',group='Root',is_root=true,allow={}}
-- loads the roles in config
require(module_path..'/config',{Role=self})
self.order[0] = 'SERVER'
-- joins role allows into a chain
local previous
for index,role_name in pairs(self.order) do
local role = self.get(role_name)
if not role then error('Invalid role name in order listing: '..role_name) return end
if role.is_default then self.meta.default = role end
if role.is_timed then self.meta.times[role.name] = {index,role.time*3600} end
if not self.meta.groups[role.group.name] then self.meta.groups[role.group.name] = {lowest=index,highest=index} end
if self.meta.groups[role.group.name].highest > index then self.meta.groups[role.group.name].highest = index end
if self.meta.groups[role.group.name].lowest < index then self.meta.groups[role.group.name].lowest = index end
if previous then setmetatable(previous.allow,{__index=role.allow}) end
self.meta.count = self.meta.count+1
role.index = index
previous = role
end
if previous then setmetatable(previous.allow,{__index=function(tbl,key) return false end})
else error('Invalid roles, no roles to load.') end
end
}
_RoleSelfReference=Role
-- Global Define
local global = {
change_cache_length=15,
changes={},
latest_change={},
preassign={},
players={},
roles={}
}
Global.register(global,function(tbl) RoleGlobal = tbl end)
-- Function Define
--- Used to set default roles for players who join
-- @usage Role.set_preassign{name={roles}}
function Role.set_preassign(tbl) if game then global.preassign = tbl else Role.preassign = tbl end end
--- Defines a new instance of a role
-- @usage Role.define{name='Root',short_hand='Root',tag='[Root]',group='Root',colour={r=255,b=255,g=255},is_root=true,allow={}} -- returns new role
-- @usage Role{name='Root',short_hand='Root',tag='[Root]',group='Root',colour={r=255,b=255,g=255},is_root=true,allow={}} -- returns new role
-- @tparam table obj contains the strings: name,short_hand,tag a table called allow a table called colour and a pointer to a permission group
-- @treturn Role the role which has been made
function Role.define(obj)
if not type_error(game,nil,'Cant define Role during runtime.') then return end
if not type_error(obj.name,'string','Role creation is invalid: role.name is not a string') then return end
if not is_type(obj.short_hand,'string') then obj.short_hand = obj.name:sub(1,3) end
if not is_type(obj.tag,'string') then obj.tag = '['..obj.short_hand..']' end
if not is_type(obj.colour,'table') then obj.colour = {r=255,b=255,g=255} end
if not type_error(obj.allow,'table','Role creation is invalid: role.allow is not a table') then return end
obj.group = Group.get(obj.group)
if not type_error(obj.group,'table','Role creation is invalid: role.group is invalid') then return end
if obj.time and not type_error(obj.time,'number','Role creation is invalid: role.time is not a number') then return end
verbose('Created Role: '..obj.name)
setmetatable(obj,{__index=Role._prototype})
obj.connected_players = setmetatable({self=obj,connected=true},Role._prototype.players_mt)
obj.players = setmetatable({self=obj},Role._prototype.players_mt)
rawset(Role.roles,obj.name,obj)
table.insert(Role.order,obj.name)
return obj
end
--- Used to get the role of a player or the role by name
-- @usage Role.get('foo') -- returns group foo
-- @usage Role.get(player) -- returns group of player
-- @tparam ?LuaPlayer|pointerToPlayer|string mixed can either be the name of the role or a player identifier
-- @treturn table the group which was found or nil
function Role.get(mixed,forceIsRole)
local player = game and Game.get_player(mixed)
if player == SERVER then return {Role.meta.server} end
if not forceIsRole and player then
local rtn = {}
if not global.players[player.index] then return Role.meta.default and {Role.meta.default} or {} end
for _,role in pairs(global.players[player.index]) do table.insert(rtn,Role.get(role)) end
return rtn
elseif is_type(mixed,'table') and mixed.group then return mixed
elseif is_type(mixed,'string') then return Role.roles[mixed]
elseif is_type(mixed,'number') then
for _,role in pairs(Role.roles) do
if role.index == mixed then return role end
end
end
end
--- Used to place a player into a role(s)
-- @usage Role.assign(player,'Root')
-- @usage Role.assign(player,{'Root','Foo'})
-- @tparam ?LuaPlayer|pointerToPlayer player the player to assign the role to
-- @tparam ?string|role|table the role to add the player to, if its a table then it will act recursively though the table
-- @tparam[opt='<server>'] ?LuaPlayer|pointerToPlayer by_player the player who assigned the roles to the player
-- @tparam[opt] table batch this is used internally to prevent multiple event calls, contains {role_index_in_batch,batch}
-- @treturn boolean was the player assigned the roles
function Role.assign(player,role,by_player,batch)
player = Game.get_player(player)
if not player then error('Invalid player #1 given to Role.assign.',2) return end
verbose('Assigning Roles: '..serpent.line(role)..' to: '..player.name)
-- this loops over a table of role if given; will return if ipairs returns, else will assume it was meant to be a role and error
if is_type(role,'table') and not role.name then
local ctn = 0
for n,_role in ipairs(role) do ctn=ctn+1 Role.assign(player,_role,by_player,{n,role}) end
if ctn > 0 then if not batch then table.insert(global.changes[player.index],{'assign',role}) global.latest_change = {player.index,'assign',role} end return end
end
role = Role.get(role)
if not role then error('Invalid role #2 given to Role.assign.',2) return end
-- this acts as a way to prevent the global table getting too full
if not global.changes[player.index] then global.changes[player.index]={} end
if #global.changes[player.index] > global.change_cache_length then table.remove(global.changes[player.index],1) end
if not batch then table.insert(global.changes[player.index],{'assign',role.name}) global.latest_change = {player.index,'assign',role.name} end
return role:add_player(player,by_player,batch)
end
--- Used to remove a player from a role(s)
-- @usage Role.unassign(player,'Root')
-- @tparam ?LuaPlayer|pointerToPlayer player the player to unassign the role to
-- @tparam ?string|role|table role the role to remove the player from, if its a table then it will act recursively though the table
-- @tparam[opt='<server>'] ?LuaPlayer|pointerToPlayer by_player the player who unassigned the roles from the player
-- @tparam[opt] table batch this is used internally to prevent multiple event calls
-- @treturn boolean was the player unassigned the roles
function Role.unassign(player,role,by_player,batch)
player = Game.get_player(player)
if not player then error('Invalid player #1 given to Role.unassign.',2) return end
verbose('Assigning Roles: '..serpent.line(role)..' to: '..player.name)
-- this loops over a table of role if given; will return if ipairs returns, else will assume it was meant to be a role and error
if is_type(role,'table') and not role.name then
local ctn = 0
for n,_role in ipairs(role) do ctn=ctn+1 Role.unassign(player,_role,by_player,{n,role}) end
if ctn > 0 then if not batch then table.insert(global.changes[player.index],{'unassign',role}) global.latest_change = {player.index,'unassign',role} end return end
end
role = Role.get(role)
if not role then error('Invalid role #2 given to Role.unassign.',2) return end
if not global.changes[player.index] then global.changes[player.index]={} end
-- this acts as a way to prevent the global table getting too full
if #global.changes[player.index] > global.change_cache_length then table.remove(global.changes[player.index],1) end
if not batch then table.insert(global.changes[player.index],{'unassign',role.name}) global.latest_change = {player.index,'unassign',role.name} end
return role:remove_player(player,by_player,batch)
end
--- Returns the highest role given in a list, if a player is passed then it returns the highest role of the player
-- @usage Role.get_highest{'Root','Admin','Mod'} -- returns Root (given that root is highest)
-- @usage Role.get_highest(player) -- returns the players highest role
-- @tparam ?table|LuaPlayer|pointerToPlayer options table of options or a player
-- @treturn role the highest role given in the options
function Role.get_highest(options)
local player = Game.get_player(options)
if player then options = Role.get(player) end
if not type_error(options,'table','Invalid argument #1 to Role.get_highest, options is not a table of roles.') then return end
local highest_index = -1
local highest
for _,role_name in pairs(options) do
local role = Role.get(role_name)
if not role then error('Invalid role inside options: '..serpent.line(role_name)) return end
if highest_index == -1 or role.index < highest_index then highest_index,highest = role.index,role end
end
return highest
end
--- Uses the change cache to revert changes to players roles
-- @usage Role.revert(player) -- reverts the last change to the players roles
-- @tparam ?LuaPlayer|pointerToPlayer player the player to revert the changes of
-- @tparam[opt] ?LuaPlayer|pointerToPlayer the player who preformed the role revert
-- @tparam[opt=1] count the number of reverts to do, if 0 all changes cached are reverted
-- @treturn number the number of changes that occurred
function Role.revert(player,by_player,count)
player = Game.get_player(player)
if not player then error('Invalid player #1 given to Role.revert.',2) return end
if count and not type_error(count,'number','Invalid argument #2 to Role.revert, count is not a number.') then return end
local changes = global.changes[player.index] or {}
if #changes == 0 then error('Player has no role changes logged, can not revert.') end
count = count or 1
local ctn = 0
if count > #changes or count == 0 then count = #changes end
for i = 1,count do
local change = table.remove(changes)
if not change then break end
local batch = is_type(change[2],'table') and change[2] or {change[2]}
if change[1] == 'assign' then Role.unassign(player,change[2],by_player,batch) end
if change[1] == 'unassign' then Role.assign(player,change[2],by_player,batch) end
ctn=ctn+1
end
return ctn
end
--- Adds a flag which can be set on roles; these flags act as a quick way to access general role changes
-- @usage Role.add_flag('is_admin',function(player,state) player.admin = state end) -- the function is passed player and if the flag is true or false
-- @tparam string flag the name of the flag that is being added
-- @tparam[opt] function callback the function(player,state) which is called when a player loses or gains a flag, if nil no function is called
function Role.add_flag(flag,callback)
if not type_error(flag,'string','Invalid argument #1 to Role.add_flag, flag is not a string.') then return end
if callback and not type_error(callback,'function','Invalid argument #2 to Role.add_flag, callback is not a function.') then return end
verbose('Added flag: '..flag)
Role.flags[flag] = callback or true
end
--- Checks if a player or role has the requested flag, if player all roles of player are checked (true has priority)
-- @usage Role.has_flag(role,'is_admin') -- returns true if this role has is_admin set
-- @tparam role|LuaPlayer|pointerToPlayer mixed the player or role that will be tested
-- @tparam string flag the flag to test for
-- @treturn boolean if the flag was true or false, false if nil
function Role.has_flag(mixed,flag)
if not type_error(flag,'string','Invalid argument #2 to Role.has_flag, flag is not a string.') then return end
local roles = Role.get(mixed)
if not type_error(roles,'table','Invalid argument #1 to Role.has_flag, mixed is not a role or player.') then return end
if #roles > 0 then for _,role in pairs(roles) do
if role:has_flag(flag) then return true end
end elseif roles:has_flag(flag) then return true end
return false
end
--- Adds a action to be used by the role system
-- @usage Role.add_action('foo')
-- @tparam string action the name of the action that will be added
function Role.add_action(action)
if not type_error(action,'string','Invalid argument #1 to Role.add_action, action is not a string.') then return end
verbose('Added action: '..action)
table.insert(Role.actions,action)
end
--- Checks if a player or role is allowed the requested action, if player all roles of player are checked (true has priority)
-- @usage Role.allowed(role,'foo') -- returns true if this role is allowed 'foo'
-- @tparam ?role|LuaPlayer|pointerToPlayer mixed the player or role that will be tested
-- @tparam string action the action to test for
-- @treturn boolean if the action is allowed for the player or role
function Role.allowed(mixed,action)
if not type_error(action,'string','Invalid argument #2 to Role.allowed, action is not a string.') then return end
local roles = Role.get(mixed)
if not type_error(roles,'table','Invalid argument #1 to Role.allowed, mixed is not a role or player.') then return end
if #roles > 0 then for _,role in pairs(roles) do
if role:allowed(action) then return true end
end elseif roles:allowed(action) then return true end
return false
end
--- Prints to all roles and players of those roles which are greater than the given role (or if inv then all below)
-- @usage Role.print('Admin','Hello, World!') -- returns the number of players who received the message
-- @tparam ?role|string role the role which acts as the turning point of the print (always included regardless of inv value)
-- @param rtn the value that will be returned to the players
-- @tparam[opt] table colour the colour that you want the message printed in
-- @tparam[opt=false] boolean inv true to print to roles below, false to print to roles above
-- @treturn number the number of players who received the message
function Role.print(role,rtn,colour,inv)
role = Role.get(role,true)
if not type_error(role,'table','Invalid argument #1 to Role.print, role is invalid.') then return end
if colour and not type_error(colour,'table','Invalid argument #3 to Role.print, colour is not a table.') then return end
if inv and not type_error(inv,'boolean','Invalid argument #4 to Role.print, inv is not a boolean.') then return end
local message = inv and {'ExpGamingCore-Role.default-print',rtn} or {'ExpGamingCore-Role.print',role.name,rtn}
local change = inv and 1 or -1
local ctn = 0
local i = role.index
while true do
local _role = Role.get(i,true)
if not _role then break end
ctn=ctn+_role:print(message,colour)
i=i+change
end
return ctn
end
--- Prints all registered roles and there important information (debug)
-- @tparam[opt] ?role|string the role to print the info of, if nil then all roles are printed in order of power
-- @tparam[opt=game.player] ?LuaPlayer|pointerToPlayer the player to print the info to, default the player who ran command
function Role.debug_output(role,player)
player = Game.get_player(player) or game.player
if not player then error('Invalid player #2 given to Role.debug_output.',2) return end
local function _output(_role)
local flags = {};for flag in pairs(Role.flags) do if _role:has_flag(flag) then table.insert(flags,flag) end end
local rtn = string.format('%s) %q-%q || Tag: %s Short Hand: %q Time: %s Flags: %s',
_role.index,_role.group.name,_role.name,_role.tag,_role.short_hand,tostring(_role.time),table.concat(flags,', '))
player_return(rtn,_role.colour,player)
end
if role then
role = Role.get(role)
if not type_error(role,'table','Invalid argument #1 to Role.print, role is invalid.') then return end
_output(role)
else for index,_role in pairs(Role.roles) do _output(_role) end end
end
--- Used to test if a role has a flag set
-- @usage role:has_flag('is_admin') -- returns true if the role has the flag 'is_admin'
-- @tparam string flag the flag to test for
-- @treturn boolean true if the flag is set else false
function Role._prototype:has_flag(flag)
if not self_test(self,'role','has_flag') then return end
if not type_error(flag,'string','Invalid argument #1 to role:has_flag, flag is not a string.') then return end
return self[flag] or false
end
--- Used to test if a role is allowed an action
-- @usage role:allowed('foo') -- returns true if the role is allowed 'foo'
-- @tparam string action the action to test for
-- @treturn boolean true if the action is allowed else false
function Role._prototype:allowed(action)
if not self_test(self,'role','allowed') then return end
if not type_error(action,'string','Invalid argument #1 to role:allowed, action is not a string.') then return end
if self.is_antiroot then return false end
return self.allow[action] or self.is_root or false -- still include is_root exception flag
end
--- Returns the players who have this role
-- @usage role:get_player() -- returns table of players
-- @usage role.players -- returns table of players
-- @usage role.connected_players -- returns table of online players
-- @tparam[opt] boolean online if true only returns online players
function Role._prototype:get_players(online)
if not self_test(self,'role','get_players') then return end
if online and not type_error(online,'boolean','Invalid argument #1 to role:get_players, online is not a boolean.') then return end
if not global.roles[self.name] then global.roles[self.name] = {} end
if self.is_default then if online then return game.connected_players else return game.players end end
local rtn = {}
for _,player_index in pairs(global.roles[self.name]) do
local player = game.players[player_index]
if player and not online or player.connected then table.insert(rtn,player) end
end
return rtn
end
-- this is used to create a connected_players table
Role._prototype.players_mt = {
__call=function(tbl) return tbl.self:get_players(tbl.connected) end,
__pairs=function(tbl)
local players = tbl.self:get_players(tbl.connected)
local function next_pair(tbl,key)
local k, v = next(players, key)
if v then return k,v end
end
return next_pair, players, nil
end,
__ipairs=function(tbl)
local players = tbl.self:get_players(tbl.connected)
local function next_pair(tbl,key)
local k, v = next(players, key)
if v then return k,v end
end
return next_pair, players, nil
end
}
--- Prints a message to all players who have this role
-- @usage role:print('Hello, World!') -- returns number of players who received the message
-- @param rtn the message to print to the players
-- @tparam[opt] table colour the colour to print the message in
-- @treturn number the number of players who received the message
function Role._prototype:print(rtn,colour)
if not self_test(self,'role','print') then return end
if colour and not type_error(colour,'table','Invalid argument #2 to Role.print, colour is not a table.') then return end
local ctn = 0
for _,player in pairs(self:get_players(true)) do ctn=ctn+1 player_return(rtn,colour,player) end
return ctn
end
--- Returns a table that describes all the permissions and which this role is allowed
-- @usage role:get_permissions() -- returns table of permissions
-- @treturn table a table of permissions, only includes ones which were defined with Role.add_action
function Role._prototype:get_permissions()
if not self_test(self,'role','get_permissions') then return end
local rtn = {}
for _,action in pairs(Role.actions) do rtn[action] = self:allowed(action) end
return rtn
end
--- Adds a player to this role (players can have more than one role)
-- @usage role:add_player(player)
-- @tparam ?LuaPlayer|PointerToPlayer player the player to add
-- @tparam[opt] ?LuaPlayer|PointerToPlayer by_player the player who ran the command
-- @tparam[opt] table batch this is used internally to prevent multiple event calls
function Role._prototype:add_player(player,by_player,batch)
if not self_test(self,'role','add_player') then return end
player = Game.get_player(player)
if not player then error('Invalid player #1 given to role:add_player.',2) return end
by_player = Game.get_player(by_player) or SERVER
if not global.roles[self.name] then global.roles[self.name] = {} end
if not global.players[player.index] then global.players[player.index] = {} end
local highest = Role.get_highest(player) or Role.meta.default
for _,player_index in pairs(global.roles[self.name]) do if player_index == player.index then return end end
table.insert(global.roles[self.name],player.index)
table.insert(global.players[player.index],self.name)
script.raise_event(role_change_event_id,{
name=role_change_event_id,
tick=game.tick,
player_index=player.index,
by_player_index=by_player.index,
old_highest=highest.name,
role_name=self.name,
batch=batch and batch[2] or {self.name},
batch_index=batch and batch[1] or 1,
effect='assign'
})
end
--- Removes a player from this role (players can have more than one role)
-- @usage role:remove_player(player)
-- @tparam ?LuaPlayer|PointerToPlayer player the player to remove
-- @tparam[opt] ?LuaPlayer|PointerToPlayer by_player the player who ran the command
-- @tparam[opt] table batch this is used internally to prevent multiple event calls
function Role._prototype:remove_player(player,by_player,batch)
if not self_test(self,'role','add_player') then return end
player = Game.get_player(player)
if not player then error('Invalid player #1 given to role:remove_player.',2) return end
by_player = Game.get_player(by_player) or SERVER
if not global.roles[self.name] then global.roles[self.name] = {} end
if not global.players[player.index] then global.players[player.index] = {} end
local highest = Role.get_highest(player) or Role.meta.default
local index = 0
for _index,player_index in pairs(global.roles[self.name]) do if player_index == player.index then index=_index break end end
table.remove(global.roles[self.name],index)
for _index,role_name in pairs(global.players[player.index]) do if role_name == self.name then index=_index break end end
table.remove(global.players[player.index],index)
script.raise_event(role_change_event_id,{
name=role_change_event_id,
tick=game.tick,
player_index=player.index,
by_player_index=by_player.index,
old_highest=highest.name,
role_name=self.name,
batch=batch and batch[2] or {self.name},
batch_index=batch and batch[1] or 1,
effect='unassign'
})
end
-- Event Handlers Define
Event.add(role_change_event_id,function(event)
-- variable init
local player = Game.get_player(event)
local by_player = Game.get_player(event.by_player_index) or SERVER
local role = Role.get(event.role_name)
local highest = Role.get_highest(player)
if not highest then Role.meta.default:add_player(player) highest = Role.meta.default end
-- gets the flags the player currently has
for flag,callback in pairs(Role.flags) do if is_type(callback,'function') then callback(player,Role.has_flag(player,flag)) end end
-- assign new tag and group of highest role
Group.assign(player,highest.group)
local old_highest_tag = Role.get(event.old_highest).tag or ''
local start, _end = string.find(player.tag,old_highest_tag,1,true)
if start and old_highest_tag ~= highest.tag then player.tag = string.sub(player.tag,0,start-1)..highest.tag..string.sub(player.tag,_end+1) end
if not start then player.tag = highest.tag player_return({'ExpGamingCore-Role.tag-reset'},nil,player) end
if player.online_time > 60 then
-- send a message to other players
if event.batch_index == 1 then
local names = {}
for _,name in pairs(event.batch) do local next_role = Role.get(name) if next_role then table.insert(names,next_role.name) end end
if event.effect == 'assign' then
if not role.is_jail then player.play_sound{path='utility/achievement_unlocked'} end
game.print{'ExpGamingCore-Role.default-print',{'ExpGamingCore-Role.assign',player.name,table.concat(names,', '),by_player.name}}
else
player.play_sound{path='utility/game_lost'}
game.print{'ExpGamingCore-Role.default-print',{'ExpGamingCore-Role.unassign',player.name,table.concat(names,', '),by_player.name}}
end
end
-- log change to file
game.write_file('role-change.json',
table.json({
tick=game.tick,
effect=event.effect,
role_name=role.name,
player_name=player.name,
by_player_name=by_player.name,
play_time=player.online_time,
highest_role_name=highest.name,
old_highest=event.highest,
batch_count=#event.batch,
batch_index=event.batch_index
})..'\n'
, true, 0)
end
end)
Event.add(defines.events.on_player_created,function(event)
local player = Game.get_player(event)
local highest = Role.get_highest(player) or Role.meta.default
Group.assign(player,highest.group)
player.tag=highest.tag
if global.preassign[player.name:lower()] then Role.assign(player,global.preassign[player.name:lower()]) end
if Role.preassign[player.name:lower()] then Role.assign(player,Role.preassign[player.name:lower()]) end
end)
Event.add(defines.events.on_tick,function(event)
if game.tick%(3600*5) ~= 0 then return end -- every 5 minutes
for _,player in pairs(game.connected_players) do
if not Role.has_flag(player,'block_auto_promote') then
local highest = Role.get_highest(player)
for role_name, time in pairs(Role.meta.times) do
if highest.index > time[1] and (player.online_time) > time[2] then Role.assign(player,role_name) end
end
end
end
end)
-- Module Return
-- calling will attempt to define a new role
return setmetatable(Role,{__call=function(tbl,...) return tbl.define(...) end})

View File

@@ -1,6 +0,0 @@
[ExpGamingCore-Role]
default-print=[Everyone]: __1__
print=[__1__]: __2__
assign=__1__ was assigned to __2__ by __3__
unassign=__1__ was unassigned from __2__ by __3__
tag-reset=Your Tag was reset due to a role change

View File

@@ -1,24 +0,0 @@
{
"name": "ExpGamingCore.Role",
"version": "4.0.0",
"description": "Adds roles where a player can have more than one role",
"location": "FSM_ARCHIVE",
"keywords": [
"Role",
"Ranks",
"Permissions",
"Alowed",
"Admin"
],
"dependencies": {
"ExpGamingLib": "^4.0.0",
"FactorioStdLib.Table": "^0.8.0",
"FactorioStdLib.Game": "^0.8.0",
"ExpGamingCore.Group": "^4.0.0",
"ExpGamingCore.Server": "?^4.0.0",
"ExpGamingCore.Command": "?^4.0.0",
"ExpGamingCore.Sync": "?^4.0.0"
},
"collection": "ExpGamingCore@4.0.0",
"submodules": {}
}

View File

@@ -1,28 +0,0 @@
local Role = self
commands.add_validation('player-rank',function(value,event)
local player,err = commands.validate['player'](value)
if err then return commands.error(err) end
local rtn = Role.get_highest(player).index > Role.get_highest(event).index and player or player.index == event.player_index and player or nil
if not rtn then return commands.error{'ExpGamingCore_Command.error-player-rank'} end return rtn
end)
commands.add_validation('player-rank-online',function(value,event)
local player,err = commands.validate['player-online'](value)
if err then return commands.error(err) end
local player,err = commands.validate['player-rank'](player)
if err then return commands.error(err) end
return player
end)
commands.add_validation('player-rank-alive',function(value,event)
local player,err = commands.validate['player-alive'](value)
if err then return commands.error(err) end
local player,err = commands.validate['player-rank'](player,event)
if err then return commands.error(err) end
return player
end)
commands.add_middleware(function(player,command_name,event)
return Role.allowed(player,command_name)
end)

View File

@@ -1,82 +0,0 @@
local Role = self
local RoleGlobal = RoleGlobal
local Sync = require('ExpGamingCore.Sync')
local Game = require('FactorioStdLib.Game')
local Color = require('FactorioStdLib.Color')
-- just to hard reset the role sync
function Sync.set_roles(...)
Role.set_preassign(...)
end
-- used to assign the role if the player is online, or add to the the preassign
function Sync.assign_role(player_name,roles,by_player_name)
if not game then return end
local preassign = RoleGlobal.preassign
local player_roles = preassign[player_name]
if Game.get_player(player_name) then Role.assign(player_name,roles,by_player_name)
else
if not is_type(roles,'table') then roles = {roles} end
if not player_roles then preassign[player_name] = roles return end
for _,role_name in pairs(roles) do
if not table.includes(player_roles,role_name) then table.insert(player_roles,role_name) end
end
end
end
-- used to unassign the role if the player is online, or removes the preassign
function Sync.unassign_role(player_name,roles,by_player_name)
if not game then return end
local preassign = RoleGlobal.preassign
local player_roles = preassign[player_name]
if Game.get_player(player_name) then Role.unassign(player_name,roles,by_player_name)
else
if not is_type(roles,'table') then roles = {roles} end
if not player_roles then preassign[player_name] = nil return end
for _,role_name in pairs(roles) do
local index = table.index(player_roles,role_name)
if index then table.remove(player_roles,index) end
end
end
end
Sync.add_update('roles',function()
if not game then return {'Offline'} end
local _rtn = {}
for _,role in pairs(Role.roles) do
local players = role:get_players()
local _players = {}
for k,player in pairs(players) do _players[k] = player.name end
local online = role:get_players(true)
local _online = {}
for k,player in pairs(online) do _online[k] = player.name end
_rtn[role.name] = {players=_players,online=_online,n_players=#_players,n_online=#_online}
end
return _rtn
end)
-- Adds a caption to the info gui that shows the rank given to the player
if Sync.add_to_gui then
Sync.add_to_gui(function(player)
local names = {}
for _,role in pairs(Role.get(player)) do table.insert(names,role.name) end
return 'You have been assigned the roles: '..table.concat(names,', ')
end)
end
-- adds a discord emit for rank changing
Event.add('on_role_change',function(event)
local role = Role.get(event.role_name)
local player = Game.get_player(event)
local by_player = Game.get_player(event.by_player_index) or SERVER
if role.is_jail and RoleGlobal.last_change[1] ~= player.index then
Sync.emit_embedded{
title='Player Jail',
color=Color.to_hex(defines.textcolor.med),
description='There was a player jailed.',
['Player:']='<<inline>>'..player.name,
['By:']='<<inline>>'..by_player.name,
['Reason:']='No Reason'
}
end
end)