Completed logic for ExpGamingCore.Role

This commit is contained in:
Cooldude2606
2018-09-28 19:44:26 +01:00
parent f6e5ea08be
commit 34d966e5c8
2 changed files with 174 additions and 48 deletions

View File

@@ -44,6 +44,7 @@ function Group.define(obj)
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 rawget(tbl,'_raw_group') and rawget(tbl,'_raw_group')[key] or nil end})
obj.connected_players = setmetatable({self=obj},Group._prototype.connected_players_mt)
rawset(Group.groups,obj.name,obj)
return obj
end
@@ -54,13 +55,17 @@ end
-- @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)
local player = game and Game.get_player(mixed)
if is_type(mixed,'table') and mixed._raw_group then return mixed end
if player then mixed = player.permission_group.name end
if is_type(mixed,'table') and not mixed.__self and mixed._raw_group then return mixed end
if is_type(mixed,'table') and mixed.__self and mixed.name then mixed = mixed.name end
return Group.groups[mixed] or game.permissions.get_group(mixed) and setmetatable({disallow={},name=mixed,_raw_group=game.permissions.get_group(mixed)},{
__index=function(tbl,key) return Group._prototype[key] or rawget(tbl,'_raw_group') and rawget(tbl,'_raw_group')[key] or nil end
})
if game and game.players[mixed] then mixed = game.players[mixed].permission_group.name end
local rtn = Group.groups[mixed]
if not rtn and game.permissions.get_group(mixed) then
rtn = setmetatable({disallow={},name=mixed,_raw_group=game.permissions.get_group(mixed)},{
__index=function(tbl,key) return Group._prototype[key] or rawget(tbl,'_raw_group') and rawget(tbl,'_raw_group')[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
@@ -110,7 +115,9 @@ function Group._prototype:remove_player(player)
end
--- Gets all players in this group
-- @usage group:get_players(true) -- returns all online players
-- @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)
@@ -122,6 +129,27 @@ function Group._prototype:get_players(online)
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(tbl)
local players = tbl.self:get_players(true)
local function next_pair(tbl,k)
k, v = next(players, k)
if v then return k,v end
end
return next_pair, players, nil
end,
__ipairs=function(tbl)
local players = tbl.self:get_players(true)
local function next_pair(tbl,k)
k, v = next(players, k)
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

View File

@@ -9,7 +9,7 @@ local Group = require('ExpGamingCore.Group@^4.0.0')
local Game = require('FactorioStdLib.Game@^0.8.0')
-- Local Varibles
local role_change_event_id = script.generate_event_name()
local role_change_event_id = script.generate_event_name('on_role_change')
-- Module Define
local module_verbose = false
@@ -48,6 +48,7 @@ local Role = {
-- Global Define
local global = global{
change_chache_length=15,
changes={},
players={},
roles={}
@@ -55,7 +56,11 @@ local global = global{
-- Function Define
-- creates role object
--- 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
@@ -68,12 +73,18 @@ function Role.define(obj)
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
-- gets all roles of a user or a role by name
--- 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 indenifier
-- @treturn table the group which was found or nil
function Role.get(mixed)
local player = game and Game.get_player(mixed)
if player then
@@ -85,45 +96,62 @@ function Role.get(mixed)
elseif is_type(mixed,'string') then return Role.roles[mixed] end
end
-- gives a player a role by name or a table of roles
function Role.assign(player,role,no_log)
--- 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 recursly though the table
-- @tparam[opt='<server>'] ?LuaPlayer|pointerToPlayer by_player the player who assigned the roles to the player
-- @tparam[opt] boolean when true the assign will not be loged to the change chache
-- @treturn boolean was the player assigned the roles
function Role.assign(player,role,by_player,no_log)
local player = Game.get_player(player)
if not player then error('Invalid player #1 given to Role.assign.',2) return end
-- this loops over a table of role if given; will return if ipairs returns, else will asume it was ment to be a role and error
if is_type(role,'table') and not role.name then
local ctn = 0
for _,_role in ipairs(role) do ctn=ctn+1 Role.assign(player,_role,true) end
if ctn > 0 then if not no_log then table.insert(global.changes[player.index],{'assign',role.name}) end return end
for _,_role in ipairs(role) do ctn=ctn+1 Role.assign(player,_role,by_player,true) end
if ctn > 0 then if not no_log then table.insert(global.changes[player.index],{'assign',role}) end return end
end
local 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 provent the global table getting too full
if not global.changes[player.index] then global.changes[player.index]={} end
if #global.changes[player.index] > 20 then table.remove(global.changes[player.index],1) end
if #global.changes[player.index] > global.change_chache_length then table.remove(global.changes[player.index],1) end
if not no_log then table.insert(global.changes[player.index],{'assign',role.name}) end
return role:add_player(player)
return role:add_player(player,by_player)
end
-- removes a player from a role by name or a table of roles
function Role.unassign(player,role,no_log)
--- 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 recursly though the table
-- @tparam[opt='<server>'] ?LuaPlayer|pointerToPlayer by_player the player who unassigned the roles from the player
-- @tparam[opt] boolean no_log when true the assign will not be loged to the change chache
-- @treturn boolean was the player unassigned the roles
function Role.unassign(player,role,by_player,no_log)
local player = Game.get_player(player)
if not player then error('Invalid player #1 given to Role.unassign.',2) return end
-- this loops over a table of role if given; will return if ipairs returns, else will asume it was ment to be a role and error
if is_type(role,'table') and not role.name then
local ctn = 0
for _,_role in ipairs(role) do ctn=ctn+1 Role.unassign(player,_role,true) end
if ctn > 0 then if not no_log then table.insert(global.changes[player.index],{'unassign',role.name}) end return end
for _,_role in ipairs(role) do ctn=ctn+1 Role.unassign(player,_role,by_player,true) end
if ctn > 0 then if not no_log then table.insert(global.changes[player.index],{'unassign',role}) end return end
end
local 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 provent the global table getting too full
if #global.changes[player.index] > 20 then table.remove(global.changes[player.index],1) end
if #global.changes[player.index] > global.change_chache_length then table.remove(global.changes[player.index],1) end
if not no_log then table.insert(global.changes[player.index],{'unassign',role.name}) end
return role:remove_player(player)
return role:remove_player(player,by_player)
end
-- gets the highest role from a set of options; player can be passed
--- 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'} -- retuns 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
@@ -138,8 +166,13 @@ function Role.get_highest(options)
return highest
end
-- reverts the last change to a user's roles
function Role.revert(player,count)
--- Uses the change chache 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 proformed the role revert
-- @tparam[opt=1] count the number of reverts to do, if 0 all changes chached are reverted
-- @treturn number the number of changes that occured
function Role.revert(player,by_player,count)
local 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
@@ -147,20 +180,21 @@ function Role.revert(player,count)
if #changes == 0 then error('Player has no role changes logged, can not revert.') end
local count = count or 1
local ctn = 0
if count > #changes then count = #changes end
if count > #changes or count == 0 then count = #changes end
for i = 1,count do
local change = table.remove(changes,1)
local change = table.remove(changes)
if not change then break end
if change[1] == 'assign' then Role.unassign(player,change[2],true) end
if change[1] == 'unassign' then Role.assign(player,change[2],true) end
if change[1] == 'assign' then Role.unassign(player,change[2],by_player,true) end
if change[1] == 'unassign' then Role.assign(player,change[2],by_player,true) end
ctn=ctn+1
end
return ctn
end
-- when a role has the given flag the callback is called, params: player, state
-- all the flags a player has are combined with true as pirority
-- example Role.add_flag('is_admin',function(player,state) player.admin = state 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 falg 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
@@ -168,7 +202,11 @@ function Role.add_flag(flag,callback)
Role.flags[flag] = callback or true
end
-- tests if mixed (either player or role) has the requested flag
--- Checks if a player or role has the requested flag, if player all roles of player are checked (true has pirortiy)
-- @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)
@@ -179,15 +217,20 @@ function Role.has_flag(mixed,flag)
return false
end
-- allows a table to be made that includes all possible actions and thus can test who is allowed
-- used purly as a way to loop over all actions
--- 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
-- returns if mixed (either player or role) is allowed to do this action
--- Checks if a player or role is allowed the requested action, if player all roles of player are checked (true has pirortiy)
-- @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)
@@ -198,7 +241,13 @@ function Role.allowed(mixed,action)
return false
end
-- prints to this role and all below it or above if inv
--- 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 recived 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 recived the message
function Role.print(role,rtn,colour,inv)
local role = Role.get(role)
if not type_error(role,'table','Invalid argument #1 to Role.print, role is invalid.') then return end
@@ -213,7 +262,9 @@ function Role.print(role,rtn,colour,inv)
return ctn
end
-- outputs all roles for debug purposes
--- Prints all registed roles and there important infomation (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)
local player = Game.get_player(player) or game.player
if not player then error('Invalid player #2 given to Role.debug_output.',2) return end
@@ -230,21 +281,31 @@ function Role.debug_output(role,player)
else for index,_role in pairs(Role.roles) do _output(_role) end end
end
-- returns true if this role has this flag set
--- 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
-- returns true if the rank is allowed, indexing with metatables for inheraitance
--- 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
return self.allow[action] or self.is_root or false -- still include is_root exception flag
end
-- gets the players in this role and online only if online is true
--- 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
@@ -257,7 +318,33 @@ function Role._prototype:get_players(online)
return rtn
end
-- prints a message to all players with this role
-- 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,k)
k, v = next(players, k)
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,k)
k, v = next(players, k)
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!') -- retuns number of players who recived 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 recived 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
@@ -266,7 +353,9 @@ function Role._prototype:print(rtn,colour)
return ctn
end
-- runs though Role.actions and returns a list of which this role can do
--- Returns a table that describes all the permissions and which this role is allowed
-- @usage role:get_permissions() -- retuns table of permissions
-- @treturn table a table of permisions, 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 = {}
@@ -274,7 +363,10 @@ function Role._prototype:get_permissions()
return rtn
end
-- adds a player to this role
--- 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
function Role._prototype:add_player(player,by_player)
if not self_test(self,'role','add_player') then return end
local player = Game.get_player(player)
@@ -297,7 +389,10 @@ function Role._prototype:add_player(player,by_player)
})
end
-- removes a player from this role
--- 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
function Role._prototype:remove_player(player,by_player)
if not self_test(self,'role','add_player') then return end
local player = Game.get_player(player)
@@ -310,7 +405,7 @@ function Role._prototype:remove_player(player,by_player)
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.insert(global.players[player.index],index)
table.remove(global.players[player.index],index)
script.raise_event(role_change_event_id,{
name=role_change_event_id,
tick=game.tick,
@@ -328,9 +423,12 @@ script.on_event(role_change_event_id,function(event)
local player = Game.get_player(event)
local by_player = Game.get_player(event.by_player_index) or {name='<server>',index=0}
local role = Role.get(event.role_name)
local highest = Role.get_highest(player)
local highest = Role.get_highest(player) or {__faild=true,tag='',name='None'}
-- gets the falgs 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)
if highest.__faild then Group.get(player):remove_player(player)
else Group.assign(player,highest.group) end
player.tag = highest.tag
-- play a sound to the player
if event.effect == 'assign' and not role.is_jail then player.play_sound{path='utility/achievement_unlocked'}