mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 11:35:22 +09:00
Merge branch 'release/5.3.0'
This commit is contained in:
11
config/command_auth_roles.lua
Normal file
11
config/command_auth_roles.lua
Normal file
@@ -0,0 +1,11 @@
|
||||
--- This will make commands only work if the role has been allowed it in the role config
|
||||
local Commands = require 'expcore.commands'
|
||||
local Roles = require 'expcore.roles'
|
||||
|
||||
Commands.add_authenticator(function(player,command,tags,reject)
|
||||
if Roles.player_allowed(player,'command/'..command) then
|
||||
return true
|
||||
else
|
||||
return reject()
|
||||
end
|
||||
end)
|
||||
38
config/command_parse_roles.lua
Normal file
38
config/command_parse_roles.lua
Normal file
@@ -0,0 +1,38 @@
|
||||
--- Adds some parse functions that can be used with the role system
|
||||
local Commands = require 'expcore.commands'
|
||||
local Roles = require 'expcore.roles'
|
||||
require 'config.command_parse_general'
|
||||
|
||||
Commands.add_parse('role',function(input,player,reject)
|
||||
if not input then return end
|
||||
local role = Roles.get_role_from_any(input)
|
||||
if not role then
|
||||
return reject{'expcore-role.reject-role'}
|
||||
else
|
||||
return role
|
||||
end
|
||||
end)
|
||||
|
||||
Commands.add_parse('player-role',function(input,player,reject)
|
||||
local input_player = Commands.parse('player',input,player,reject)
|
||||
if not input_player then return end -- nil check
|
||||
local player_highest = Roles.get_player_highest_role(player)
|
||||
local input_player_highest = Roles.get_player_highest_role(input_player)
|
||||
if player_highest.index < input_player_highest.index then
|
||||
return input_player
|
||||
else
|
||||
return reject{'expcore-roles.reject-player-role'}
|
||||
end
|
||||
end)
|
||||
|
||||
Commands.add_parse('player-role-online',function(input,player,reject)
|
||||
local input_player = Commands.parse('player-role',input,player,reject)
|
||||
if not input_player then return end -- nil check
|
||||
return Commands.parse('player-online',input_player,player,reject)
|
||||
end)
|
||||
|
||||
Commands.add_parse('player-role-alive',function(input,player,reject)
|
||||
local input_player = Commands.parse('player-role',input,player,reject)
|
||||
if not input_player then return end -- nil check
|
||||
return Commands.parse('player-alive',input_player,player,reject)
|
||||
end)
|
||||
@@ -14,6 +14,7 @@ return {
|
||||
'modules.commands.cheat-mode',
|
||||
'modules.commands.interface',
|
||||
'modules.commands.help',
|
||||
'modules.commands.roles',
|
||||
-- QoL Addons
|
||||
'modules.addons.chat-popups',
|
||||
'modules.addons.damage-popups',
|
||||
@@ -24,6 +25,8 @@ return {
|
||||
'modules.addons.worn-paths',
|
||||
-- Config Files
|
||||
'config.command_auth_admin', -- commands tagged with admin_only are blocked for non admins
|
||||
'config.command_auth_roles', -- commands must be allowed via the role config
|
||||
'config.command_auth_runtime_disable', -- allows commands to be enabled and disabled during runtime
|
||||
'config.permission_groups', -- loads some predefined permission groups
|
||||
'config.roles', -- loads some predefined roles
|
||||
}
|
||||
@@ -100,7 +100,7 @@ Permission_Groups.new_group('Restricted')
|
||||
:disallow_all()
|
||||
:allow('write_to_console')
|
||||
|
||||
--- These events are used until a role system is added to make it easier for our admins
|
||||
--[[ These events are used until a role system is added to make it easier for our admins
|
||||
|
||||
local trusted_time = 60*60*60*10 -- 10 hour
|
||||
local standard_time = 60*60*60*3 -- 3 hour
|
||||
@@ -137,4 +137,4 @@ Event.on_nth_tick(check_interval,function(event)
|
||||
for _,player in pairs(game.connected_players) do
|
||||
assign_group(player)
|
||||
end
|
||||
end)
|
||||
end)]]
|
||||
7
config/pollution_grading.lua
Normal file
7
config/pollution_grading.lua
Normal file
@@ -0,0 +1,7 @@
|
||||
-- This controls how pollution is viewed on the map
|
||||
return {
|
||||
reference_point = {x=0,y=0}, -- where pollution is read from
|
||||
max_scalar = 0.5, -- the scale between true max and max
|
||||
min_scalar = 0.17, -- the scale between the lowest max and min
|
||||
update_delay = 15 -- time in minutes between view updates
|
||||
}
|
||||
185
config/roles.lua
Normal file
185
config/roles.lua
Normal file
@@ -0,0 +1,185 @@
|
||||
--- This is the main config file for the role system; file includes defines for roles and role flags and default values
|
||||
local Roles = require 'expcore.roles'
|
||||
|
||||
-- Use these to adjust for ticks ie game.tick < 5*minutes
|
||||
local seconds, minutes, hours = 60, 3600, 216000
|
||||
|
||||
local function playtime(time_required)
|
||||
return function(player)
|
||||
if player.online_time > time_required then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Role flags that will run when a player changes roles
|
||||
Roles.define_flag_trigger('is_admin',function(player,state)
|
||||
player.admin = state
|
||||
end)
|
||||
Roles.define_flag_trigger('is_spectator',function(player,state)
|
||||
player.spectator = state
|
||||
end)
|
||||
Roles.define_flag_trigger('is_jail',function(player,state)
|
||||
if player.character then
|
||||
player.character.active = not state
|
||||
end
|
||||
end)
|
||||
|
||||
--- Admin Roles
|
||||
Roles.new_role('System','SYS')
|
||||
:set_permission_group('Admin')
|
||||
:set_flag('is_admin')
|
||||
:set_flag('is_spectator')
|
||||
:set_allow_all()
|
||||
|
||||
Roles.new_role('Senior Administrator','SAdmin')
|
||||
:set_permission_group('Admin')
|
||||
:set_flag('is_admin')
|
||||
:set_flag('is_spectator')
|
||||
:set_parent('Administrator')
|
||||
:allow{
|
||||
'command/interface',
|
||||
'command/toggle-cheat-mode'
|
||||
}
|
||||
|
||||
Roles.new_role('Administrator','Admin')
|
||||
:set_permission_group('Admin')
|
||||
:set_custom_color{r=233,g=63,b=233}
|
||||
:set_flag('is_admin')
|
||||
:set_flag('is_spectator')
|
||||
:set_parent('Moderator')
|
||||
:allow{
|
||||
}
|
||||
|
||||
Roles.new_role('Moderator','Mod')
|
||||
:set_permission_group('Admin')
|
||||
:set_custom_color{r=0,g=170,b=0}
|
||||
:set_flag('is_admin')
|
||||
:set_flag('is_spectator')
|
||||
:set_parent('Trainee')
|
||||
:allow{
|
||||
'command/assign-role',
|
||||
'command/unassign-role'
|
||||
}
|
||||
|
||||
Roles.new_role('Trainee','TrMod')
|
||||
:set_permission_group('Admin')
|
||||
:set_custom_color{r=0,g=170,b=0}
|
||||
:set_flag('is_admin')
|
||||
:set_flag('is_spectator')
|
||||
:set_parent('Donator')
|
||||
:allow{
|
||||
'command/admin-chat',
|
||||
'command/teleport',
|
||||
'command/bring',
|
||||
'command/goto',
|
||||
'command/kill/always',
|
||||
'command/tag-clear/always',
|
||||
}
|
||||
|
||||
--- Trusted Roles
|
||||
Roles.new_role('Sponsor','Spon')
|
||||
:set_permission_group('Trusted')
|
||||
:set_custom_color{r=247,g=246,b=54}
|
||||
:set_flag('is_spectator')
|
||||
:set_parent('Pay to Win')
|
||||
:allow{
|
||||
}
|
||||
|
||||
Roles.new_role('Pay to Win','P2W')
|
||||
:set_permission_group('Trusted')
|
||||
:set_custom_color{r=238,g=172,b=44}
|
||||
:set_flag('is_spectator')
|
||||
:set_parent('Donator')
|
||||
:allow{
|
||||
}
|
||||
|
||||
Roles.new_role('Donator','Don')
|
||||
:set_permission_group('Trusted')
|
||||
:set_custom_color{r=230,g=99,b=34}
|
||||
:set_flag('is_spectator')
|
||||
:set_parent('Veteran')
|
||||
:allow{
|
||||
}
|
||||
|
||||
Roles.new_role('Partner','Part')
|
||||
:set_permission_group('Trusted')
|
||||
:set_custom_color{r=140,g=120,b=200}
|
||||
:set_flag('is_spectator')
|
||||
:set_parent('Veteran')
|
||||
:allow{
|
||||
}
|
||||
|
||||
Roles.new_role('Veteran','Vet')
|
||||
:set_permission_group('Trusted')
|
||||
:set_custom_color{r=140,g=120,b=200}
|
||||
:set_parent('Member')
|
||||
:allow{
|
||||
}
|
||||
:set_auto_promote_condition(playtime(10*hours))
|
||||
|
||||
--- Standard User Roles
|
||||
Roles.new_role('Member','Mem')
|
||||
:set_permission_group('Standard')
|
||||
:set_custom_color{r=24,g=172,b=188}
|
||||
:set_parent('Regular')
|
||||
:allow{
|
||||
}
|
||||
|
||||
Roles.new_role('Regular','Reg')
|
||||
:set_permission_group('Standard')
|
||||
:set_custom_color{r=79,g=155,b=163}
|
||||
:set_parent('Guest')
|
||||
:allow{
|
||||
'command/kill'
|
||||
}
|
||||
:set_auto_promote_condition(playtime(3*hours))
|
||||
|
||||
--- Guest/Default role
|
||||
Roles.new_role('Guest','')
|
||||
:set_permission_group('Guest')
|
||||
:set_custom_color{r=185,g=187,b=160}
|
||||
:allow{
|
||||
'command/me',
|
||||
'command/tag',
|
||||
'command/tag-clear',
|
||||
'command/chelp',
|
||||
'command/list-roles'
|
||||
}
|
||||
|
||||
--- Jail role
|
||||
Roles.new_role('Jail')
|
||||
:set_permission_group('Restricted')
|
||||
:set_custom_color{r=50,g=50,b=50}
|
||||
:set_block_auto_promote(true)
|
||||
:allow{
|
||||
}
|
||||
|
||||
--- System defaults which are required to be set
|
||||
Roles.set_root('System')
|
||||
Roles.set_default('Guest')
|
||||
|
||||
Roles.define_role_order{
|
||||
'System',
|
||||
'Senior Administrator',
|
||||
'Administrator',
|
||||
'Moderator',
|
||||
'Trainee',
|
||||
'Sponsor',
|
||||
'Pay to Win',
|
||||
'Donator',
|
||||
'Partner',
|
||||
'Veteran',
|
||||
'Member',
|
||||
'Regular',
|
||||
'Guest',
|
||||
'Jail'
|
||||
}
|
||||
|
||||
Roles.override_player_roles{
|
||||
Cooldude2606={'Senior Administrator','Administrator','Moderator','Member'},
|
||||
arty714={'Senior Administrator','Administrator','Moderator','Member'},
|
||||
mark9064={'Administrator','Moderator','Member'},
|
||||
Drahc_pro={'Administrator','Moderator','Member'},
|
||||
aldldl={'Sponsor','Administrator','Moderator','Member'},
|
||||
}
|
||||
@@ -3,115 +3,170 @@
|
||||
-- @module Commands
|
||||
--[[
|
||||
>>>>Example Authenticator:
|
||||
The command system is most useful when you can control who can use commands; to do this would would need to
|
||||
define an authenticator which is ran every time a command is run; in this example I will show a simple one
|
||||
that requires some commands to require the user to be a game admin:
|
||||
|
||||
-- adds an admin only authenticator where if a command has the tag admin_only: true
|
||||
-- then will only allow admins to use this command
|
||||
Commands.add_authenticator(function(player,command,tags,reject)
|
||||
if tags.admin_only then -- the command has the tag admin_only set to true
|
||||
if player.admin then -- the player is an admin
|
||||
return true -- no return is needed for success but is useful to include
|
||||
else -- the player is not admin
|
||||
-- you must return to block a command, they are a few ways to do this:
|
||||
-- return false -- most basic and has no custom error message
|
||||
-- return reject -- sill no error message and is here in case people dont know its a function
|
||||
-- reject() -- rejects the player, return not needed but please return if possible
|
||||
-- return reject() -- rejects the player and has a failsafe return to block command
|
||||
-- reject('This command is for admins only!') -- reject but with custom error message, return not needed but please return if possible
|
||||
return reject('This command is for admins only!') -- reject but with custom error message and has return failsafe
|
||||
When the authenticator is called be the command handler it will be passed 4 vales:
|
||||
1) the player who used the command
|
||||
2) the name of the command that is being used
|
||||
3) any flags which have been set for this command, this is a table of values set using :set_flag(name,value)
|
||||
4) the reject function which is the preferred method to prevent execution of the command
|
||||
|
||||
For our admin only example we will set a flag to true when we want it do be admin only so when we define the
|
||||
command will will use :set_flag('admin_only',true) and then inside the authenticator we will test if the flag
|
||||
is present using: if flags.admin_only then
|
||||
|
||||
Although no return is required to allow the command to execute it is best practice to return true; we do this in
|
||||
two cases in our authenticator:
|
||||
1) when the "admin_only" flag is not set, which we take to mean any one can use it
|
||||
2) when the "admin_only" flag is set, and the player is admin
|
||||
|
||||
Now when the user is not an admin and the command requires you to be an admin then we must reject the request:
|
||||
1) return false -- this is the most basic block and should only be used while testing
|
||||
2) return reject -- returning the reject function is only an option as a fail safe, same as returning false
|
||||
3) reject() -- this will block execution without returning to allow further code to be ran in the authenticator
|
||||
4) reject('This command is for admins only!') -- Using reject as a function allows a error message to be returned
|
||||
5) return reject() -- using return on either case above is best practice as you should execute all code before rejecting
|
||||
|
||||
Example Code:
|
||||
Commands.add_authenticator(function(player,command,flags,reject)
|
||||
if flags.admin_only then -- our test for the "admin_only" flag
|
||||
if player.admin then
|
||||
return true -- true return 2
|
||||
else
|
||||
return reject('This command is for admins only!') -- reject return 5 with a custom error message
|
||||
end
|
||||
else -- command does not require admin
|
||||
return true -- no return is needed for success but is useful to include
|
||||
else
|
||||
return true -- true return 1
|
||||
end
|
||||
end)
|
||||
|
||||
>>>>Example Parse:
|
||||
Before you go making commands it is important to understand the most powerful feature of this command handler,
|
||||
when you define a command you are able to type the params and have then be parsed by an handler so before your
|
||||
command is ever executed you can be sure that all the params are valid. This module should be paired with a general
|
||||
command parse but you may want to create your own:
|
||||
|
||||
-- adds a parse that will cover numbers within the given range
|
||||
-- input, player and reject are common to all parse functions
|
||||
-- range_min and range_max are passed to the function from add_param
|
||||
For our example we will create a parse to accept only integer numbers in a given range:
|
||||
1) we will give it the name "number-range-int" this is the "type" that the input is expected to be
|
||||
2) when we define the type we will also define the min and max of the range so we can use the function more than once
|
||||
Example parse usage:
|
||||
:add_param('repeat_count',false,'number-range-int',5,10) -- range 5 to 10 inclusive
|
||||
|
||||
The command parse will be passed 3 params and any other you define, in our case:
|
||||
1) the input that has been given by the user for this param, the role of this function is to transform this value
|
||||
nb: the input is a string but can be nil if the param is marked as optional
|
||||
2) the player who is using the command, this is always present
|
||||
3) the reject function to throw an error to the user, this is always present
|
||||
4) the range min, this is user defined and has the value given when the param is defined
|
||||
5) the range max, this is user defined and has the value given when the param is defined
|
||||
|
||||
When returning from the param parse you again have a few options with how to do this:
|
||||
1) you return the new value for the param (any non nil value) this value is then passed to the command callback
|
||||
2) not returning will cause a generic invalid error and the command callback is blocked, not recommenced
|
||||
3) return reject -- this is just a failsafe in case the function is not called, same as no return
|
||||
4) return reject() -- will give a shorter error message as you pass a nil custom error
|
||||
5) return reject('Number entered is not in range: '..range_min..', '..range_max) -- returns a custom error the the user
|
||||
nb: if you do not return reject after you call it then you are still returning nil so there will be a duplicate message
|
||||
|
||||
It should be noted that if you want to expand on an existing parse you can use Commands.parse(type,input,player,reject)
|
||||
and this value will either return a new value for the input or nil, if it is nil you should return nil to prevent dobble
|
||||
messages to the user:
|
||||
input = Commands.parse('number-int',input,player,reject)
|
||||
if not input then return end -- nil check
|
||||
|
||||
Example Code:
|
||||
Commands.add_parse('number-range-int',function(input,player,reject,range_min,range_max)
|
||||
local rtn = tonumber(input) and math.floor(tonumber(input)) or nil -- converts input to number
|
||||
if not rtn or rtn < range_min or rtn > range_max then -- check if it is nil or out of the range
|
||||
-- invalid input for we will reject the input, they are a few ways to do this:
|
||||
-- dont return anything -- will print generic input error
|
||||
-- return false -- this WILL NOT reject the input as false can be a valid output
|
||||
-- return reject -- will print generic input error
|
||||
-- return reject() -- will print generic input error with no please check type message
|
||||
-- reject() -- if you do not return the value then they will be a duplicate message
|
||||
return reject('Number entered is not in range: '..range_min..', '..range_max) -- reject with custom error
|
||||
else
|
||||
return rtn -- returns the number value this will be passed to the command callback
|
||||
end
|
||||
end)
|
||||
|
||||
>>>>Example Command:
|
||||
|
||||
-- adds a command that will print the players name a given number of times
|
||||
-- and can only be used by admin to show how auth works
|
||||
Commands.new_command('repeat-name','Will repeat you name a number of times in chat.') -- creates the new command with the name "repeat-name" and a help message
|
||||
:add_param('repeat-count',false,'number-range-int',1,5) -- adds a new param called "repeat-count" that is required and is type "number_range_int" the name can be used here as add_parse was used
|
||||
:add_param('smiley',true,function(input,player,reject) -- this param is optional and has a custom parse function where add_parse was not used before hand
|
||||
if not input then return end -- when they is an optional param input may be nil, you can return a default value here, but using nil will allow add_defaults to pick a default
|
||||
if input:lower() == 'true' or input:lower() == 'yes' then
|
||||
return true -- the value is truthy so true is returned
|
||||
else
|
||||
-- it should be noted that this function will be ran even when the param is not present
|
||||
-- in this case input is nil and so a default can be returned, see above
|
||||
return false -- false is returned other wise
|
||||
end
|
||||
end)
|
||||
:add_defaults{smiley=false} -- adds false as the default for smiley
|
||||
:add_tag('admin_only',true) -- adds the tag admin_only: true which because of the above authenticator means you must be added to use this command
|
||||
:add_alias('name','rname') -- adds two aliases "name" and "rname" for this command which will work as if the ordinal name was used
|
||||
--:enable_auto_concat() -- cant be used due to optional param here, but this will make all user input params after the last expected one be added to the last expected one
|
||||
:register(function(player,repeat_count,smiley,raw) -- this registers the command to the game, notice the params are what were defined above
|
||||
-- prints the raw input to show that it can be used
|
||||
game.print(player.name..' used a command with input: '..raw)
|
||||
-- some smiley logic
|
||||
local msg
|
||||
if smiley then
|
||||
msg = ':) '..player.name
|
||||
else
|
||||
msg = ') '..player.name
|
||||
end
|
||||
-- prints your name alot
|
||||
for i = 1,repeat_count do
|
||||
Commands.print(i..msg) -- this command is an alias for ("expcore.common").player_return it will print any value to the player/server not just strings
|
||||
end
|
||||
-- if you wanted to you can return some values here
|
||||
-- no return -- only success message is printed
|
||||
-- Commands.error('optional message here') -- prints an error message
|
||||
-- return Commands.error('optional message here') -- prints an error message, and stops success message being printed
|
||||
-- Commands.success('optional message here') -- same as below but success message is printed twice DONT DO this
|
||||
-- return Commands.success('optional message here') -- prints your message and then the success message
|
||||
end)
|
||||
|
||||
>>>>Examples With No Comments (for example formatting):
|
||||
|
||||
Commands.add_authenticator(function(player,command,tags,reject)
|
||||
if tags.admin_only then
|
||||
if player.admin then
|
||||
return true
|
||||
else
|
||||
return reject('This command is for admins only!')
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
Commands.add_parse('number_range_int',function(input,player,reject,range_min,range_max)
|
||||
local rtn = tonumber(input) and math.floor(tonumber(input)) or nil
|
||||
if not rtn or rtn < range_min or rtn > range_max then
|
||||
-- the input is either not a number or is outside the range
|
||||
return reject('Number entered is not in range: '..range_min..', '..range_max)
|
||||
else
|
||||
-- returns the input as a number value rather than a string, thus the param is now the correct type
|
||||
return rtn
|
||||
end
|
||||
end)
|
||||
|
||||
>>>>Example Command:
|
||||
How for the fun part making the commands, the commands can be set up with any number of params and flags that you want,
|
||||
you can add aliases for the commands and set default values for optional params and of course register your command callback
|
||||
in our example we will just have a command that will repeat the users name in chat X amount of times and only allow admins to use it.
|
||||
|
||||
First we create the new command, nb this will not register the command to the game this is done at the end, we will call
|
||||
the command "repeat-name" and set the help message as follows:
|
||||
Commands.new_command('repeat-name','Will repeat you name a number of times in chat.')
|
||||
:add_param('repeat-count',false,'number_range_int',1,5)
|
||||
|
||||
Now for our first param we will call "repeat-count" and it will be a required value between 1 and 5 inclusive:
|
||||
:add_param('repeat-count',false,'number-range-int',1,5)
|
||||
|
||||
Our second param we need a custom parse for but we have not defined it, this is an option for when it is unlikely for
|
||||
any other command to use the same input type; however in our case it will just be a boolean which should be noted as being
|
||||
included in the general command parse config. As for the param its self it will be called "smiley" and will be optional with
|
||||
a default value of false:
|
||||
:add_param('smiley',true,function(input,player,reject)
|
||||
-- since it is optional the input can be nil, in which case we just return
|
||||
if not input then return end
|
||||
-- if it is not nil then we check for a truthy value
|
||||
if input:lower() == 'true' or input:lower() == 'yes' then
|
||||
return true
|
||||
else
|
||||
-- note that because we did not return nil or reject then false will be passed to command callback, see example parse
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
Once all params are defined you can now define some default values if you have optional params, the default value will be used only
|
||||
when no value is given as input, if an invalid value is given then the command will still fail and this value will not be used, the
|
||||
default can also be a function which is passed the player using the command and returns a value. Here we set the default for "smiley" to false:
|
||||
:set_defaults{smiley=false}
|
||||
|
||||
Another example of defaults if we have: item, amount[opt], player[opt]
|
||||
:set_defaults{
|
||||
amount = 50, -- more than one value can be set at a time
|
||||
player = function(player)
|
||||
return player -- default is the player using the command
|
||||
end
|
||||
}
|
||||
|
||||
Now the params are set up we can alter how the command works, we can set auth flags, add aliases to this command or enable "auto concat"
|
||||
which is when you want all extra words to be concatenated onto the end of the last param, useful for reason or messages:
|
||||
:set_flag('admin_only',true) -- in our case we want "admin_only" to be set to true so only admins can use the command
|
||||
:add_alias('name','rname') -- we also add two aliases here: "name" and "rname" which point to this command
|
||||
-- :enable_auto_concat() we do not use this in our case but this can also be used to enable the "auto concat" feature
|
||||
|
||||
And finally we want to register a callback to this command, the callback is what defines what the command does, can be as complex as you
|
||||
want it to be to as simple as our example; the command receives two params plus all that you have defines:
|
||||
1) the player who used the command
|
||||
2) in our case repeat_count which will be a number
|
||||
3) in our case smiley which will be a boolean
|
||||
4) the raw input; this param is always last as is always present as a catch all
|
||||
:register(function(player,repeat_count,smiley,raw)
|
||||
-- this is to show the value for raw as this is an example command, the log file will also show this
|
||||
game.print(player.name..' used a command with input: '..raw)
|
||||
local msg = ') '..player.name
|
||||
if smiley then
|
||||
-- this is where that smiley param is used
|
||||
msg = ':'..msg
|
||||
end
|
||||
for 1 = 1,repeat_count do
|
||||
-- this print function will return ANY value to the user in a desync safe manor, this includes if the command was used through rcon
|
||||
Command.print(1..msg)
|
||||
end
|
||||
-- see below for what else can be used here
|
||||
end)
|
||||
|
||||
Some other useful functions that can be used are:
|
||||
Commands.print(any,colour[opt]) -- this will return any value value to the user including if it is ran through rcon console
|
||||
Commands.error(message[opt]) -- this returns a warning to the user, aka an error that does not prevent execution of the command
|
||||
return Commands.error(message[opt]) -- this returns an error to the user, and will halt the command execution, ie no success message is returned
|
||||
Commands.success(message[opt]) -- used to return a success message however dont use this method see below
|
||||
return Commands.success(message[opt]) -- will return the success message to the user and your given message, halts execution
|
||||
|
||||
Example Code:
|
||||
Commands.new_command('repeat-name','Will repeat you name a number of times in chat.')
|
||||
:add_param('repeat-count',false,'number-range-int',1,5) -- required int in range 1 to 5 inclusive
|
||||
:add_param('smiley',true,function(input,player,reject) -- optional boolean default false
|
||||
if not input then return end
|
||||
if input:lower() == 'true' or input:lower() == 'yes' then
|
||||
return true
|
||||
@@ -119,17 +174,17 @@
|
||||
return false
|
||||
end
|
||||
end)
|
||||
:add_defaults{smiley=false}
|
||||
:add_tag('admin_only',true)
|
||||
:add_alias('name','rname')
|
||||
:set_defaults{smiley=false}
|
||||
:set_flag('admin_only',true) -- command is admin only
|
||||
:add_alias('name','rname') -- allow alias: name and rname
|
||||
:register(function(player,repeat_count,smiley,raw)
|
||||
game.print(player.name..' used a command with input: '..raw)
|
||||
local msg = ') '..player.name
|
||||
if smiley then
|
||||
msg = ':'..msg
|
||||
end
|
||||
for i = 1,repeat_count do
|
||||
Commands.print(i..msg)
|
||||
for 1 = 1,repeat_count do
|
||||
Command.print(1..msg)
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -147,8 +202,8 @@
|
||||
|
||||
Commands.add_command(name,help) --- Creates a new command object to added details to, note this does not register the command to the game
|
||||
Commands._prototype:add_param(name,optional,parse,...) --- Adds a new param to the command this will be displayed in the help and used to parse the input
|
||||
Commands._prototype:add_defaults(defaults) --- Adds default values to params only matters if the param is optional
|
||||
Commands._prototype:add_tag(name,value) --- Adds a tag to the command which is passed via the tags param to the authenticators, can be used to assign command roles or type
|
||||
Commands._prototype:set_defaults(defaults) --- Adds default values to params only matters if the param is optional
|
||||
Commands._prototype:set_flag(name,value) --- Adds a tag to the command which is passed via the flags param to the authenticators, can be used to assign command roles or type
|
||||
Commands._prototype:add_alias(...) --- Adds an alias or multiple that will also be registered with the same callback, eg /teleport can be /tp with both working
|
||||
Commands._prototype:enable_auto_concat() --- Enables auto concatenation of any params on the end so quotes are not needed for last param
|
||||
Commands._prototype:register(callback) --- Adds the callback to the command and registers all aliases, params and help message with the game
|
||||
@@ -183,7 +238,7 @@ local Commands = {
|
||||
-- @tparam callback function the callback you want to register as an authenticator
|
||||
-- callback param - player: LuaPlayer - the player who is trying to use the command
|
||||
-- callback param - command: string - the name of the command which is being used
|
||||
-- callback param - tags: table - any tags which have been set for the command
|
||||
-- callback param - flags: table - any flags which have been set for the command
|
||||
-- callback param - reject: function(error_message?: string) - call to fail authorize with optional error message
|
||||
-- @treturn number the index it was inserted at use to remove the callback, if anon function used
|
||||
function Commands.add_authenticator(callback)
|
||||
@@ -241,8 +296,8 @@ function Commands.authorize(player,command_name)
|
||||
|
||||
-- loops over each authorization callback if any return false or unauthorized command will fail
|
||||
for _,callback in pairs(Commands.authorization) do
|
||||
-- callback(player: LuaPlayer, command: string, tags: table, reject: function(error_message?: string))
|
||||
local success, rtn = pcall(callback,player,command_name,command_data.tags,auth_fail)
|
||||
-- callback(player: LuaPlayer, command: string, flags: table, reject: function(error_message?: string))
|
||||
local success, rtn = pcall(callback,player,command_name,command_data.flags,auth_fail)
|
||||
-- error handler
|
||||
if not success then
|
||||
-- the callback failed to run
|
||||
@@ -360,7 +415,7 @@ function Commands.new_command(name,help)
|
||||
auto_concat=false,
|
||||
min_param_count=0,
|
||||
max_param_count=0,
|
||||
tags={}, -- stores tags that can be used by auth
|
||||
flags={}, -- stores flags that can be used by auth
|
||||
aliases={}, -- n = name: string
|
||||
params={}, -- [param_name] = {optional: boolean, default: any, parse: function, parse_args: table}
|
||||
}, {
|
||||
@@ -399,7 +454,7 @@ end
|
||||
-- @tparam defaults table a table keyed by the name of the param with the value as the default value {paramName=defaultValue}
|
||||
-- callback param - player: LuaPlayer - the player using the command, default value does not need to be a function callback
|
||||
-- @treturn Commands._prototype pass through to allow more functions to be called
|
||||
function Commands._prototype:add_defaults(defaults)
|
||||
function Commands._prototype:set_defaults(defaults)
|
||||
for name,value in pairs(defaults) do
|
||||
if self.params[name] then
|
||||
self.params[name].default = value
|
||||
@@ -408,18 +463,18 @@ function Commands._prototype:add_defaults(defaults)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Adds a tag to the command which is passed via the tags param to the authenticators, can be used to assign command roles or type
|
||||
-- @tparam name string the name of the tag to be added; used to keep tags separate
|
||||
--- Adds a tag to the command which is passed via the flags param to the authenticators, can be used to assign command roles or type
|
||||
-- @tparam name string the name of the tag to be added; used to keep flags separate
|
||||
-- @tparam value any the tag that you want can be anything that the authenticators are expecting
|
||||
-- nb: if value is nil then name will be assumed as the value and added at a numbered index
|
||||
-- @treturn Commands._prototype pass through to allow more functions to be called
|
||||
function Commands._prototype:add_tag(name,value)
|
||||
function Commands._prototype:set_flag(name,value)
|
||||
if not value then
|
||||
-- value not given so name is the value
|
||||
table.insert(self.tags,name)
|
||||
table.insert(self.flags,name)
|
||||
else
|
||||
-- name is given so its key: value
|
||||
self.tags[name] = value
|
||||
self.flags[name] = value
|
||||
end
|
||||
return self
|
||||
end
|
||||
@@ -516,7 +571,7 @@ end
|
||||
-- @tparam[opt] value any the value to return to the player, if nil then only success message returned
|
||||
-- @treturn Commands.defines.success return this to the command handler to prevent two success messages
|
||||
function Commands.success(value)
|
||||
if value then player_return(value) end
|
||||
if value ~= nil then player_return(value) end
|
||||
player_return({'expcore-commands.command-ran'},'cyan')
|
||||
return Commands.defines.success
|
||||
end
|
||||
@@ -643,7 +698,7 @@ function Commands.run_command(command_event)
|
||||
if Commands.internal_error(success,command_data.name,param_parsed) then
|
||||
return command_log(player,command_data,'Internal Error: Param Parse Fail',params,command_event.parameter,param_parsed)
|
||||
end
|
||||
if param_data.optional == true and param_parsed == nil then
|
||||
if param_data.optional == true and raw_params[index] == nil then
|
||||
-- if it is optional and param is nil then it is set to default
|
||||
param_parsed = param_data.default
|
||||
if type(param_parsed) == 'function' then
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
time-symbol-days-short=__1__d
|
||||
|
||||
[expcore-commands]
|
||||
unauthorized=Unauthorized, Access is denied due to invalid credentials
|
||||
reject-string-options=Invalid Option, Must be one of: __1__
|
||||
reject-string-max-length=Invalid Length, Max: __1__
|
||||
reject-number=Invalid Number
|
||||
reject-number=Invalid Number.
|
||||
reject-number-range=Invalid Range, Min (inclusive): __1__, Max (inclusive): __2__
|
||||
reject-player=Invaild Player Name, __1__ ,try using tab key to auto-complete the name
|
||||
reject-player-online=Player is offline.
|
||||
reject-player-alive=Player is dead.
|
||||
reject-force=Invaild Force Name
|
||||
reject-surface=Invaild surface Name
|
||||
reject-force=Invaild Force Name.
|
||||
reject-surface=Invaild Surface Name.
|
||||
invalid-inputs=Invalid Input, /__1__ __2__
|
||||
invalid-param=Invalid Param "__1__"; __2__
|
||||
command-help=__1__ - __2__
|
||||
command-ran=Command Complete
|
||||
command-fail=Command failed to run: __1__
|
||||
command-error-log-format=[ERROR] command/__1__ :: __2__
|
||||
command-error-log-format=[ERROR] command/__1__ :: __2__
|
||||
|
||||
[expcore-roles]
|
||||
error-log-format-flag=[ERROR] roleFlag/__1__ :: __2__
|
||||
error-log-format-promote=[ERROR] rolePromote/__1__ :: __2__
|
||||
game-message-assign=__1__ has been assigned to __2__ by __3__
|
||||
game-message-unassign=__1__ has been unassigned from __2__ by __3__
|
||||
reject-role=Invalid Role Name.
|
||||
reject-player-role=Player has a higher role.
|
||||
745
expcore/roles.lua
Normal file
745
expcore/roles.lua
Normal file
@@ -0,0 +1,745 @@
|
||||
--- Factorio role system to manage custom permissions
|
||||
-- @author Cooldude2606
|
||||
-- @module Commands
|
||||
--[[
|
||||
>>>>Using Role System (Frontend):
|
||||
When a map first starts you will want to define on mass all the players you expect to join and the roles to give them:
|
||||
Roles.override_player_roles{
|
||||
Cooldude2606 = {'Owner','Admin','Member'},
|
||||
NotCooldude2606 = {'Member'}
|
||||
}
|
||||
|
||||
Once the game is running you still want to be able to give role and remove them which is when you would use:
|
||||
Roles.assign_player(player,'Admin',by_player_name) -- this will give the "Admin" role to the player
|
||||
Roles.unassign_player(player,{'Admin','Moderator'},by_player_name) -- this will remove "Admin" and "Moderator" role in one go
|
||||
|
||||
>>>>Using Role System (Backend):
|
||||
To comparer two players you can comparer the index of they highest roles, can be used when you want to allow a "write" down type system:
|
||||
Roles.get_player_highest_role(playerOne).index < Roles.get_player_highest_role(playerTwo).index -- remember that less means a higher role
|
||||
|
||||
Listing all of a players roles can also be useful which is when you would want to use:
|
||||
Roles.get_player_roles(player) -- the return is an array that can be looped over however this is not in particular order
|
||||
|
||||
Finally you may want to test if a player has a certain role, flag or action allowed which is when you would use:
|
||||
Roles.player_has_role(player,'Admin') -- you can provide a role name if you only want a name based system
|
||||
Roles.player_has_flag(player,'is_donator') -- your roles can be grouped together with flags such as is_donator
|
||||
Roles.player_allowed(player,'game modifiers') -- or you can have an action based system where each action is something the player can do
|
||||
|
||||
>>>>Example Flag Define:
|
||||
Flags can be used to group multiple roles and actions under one catch all, for example if you want a piece of code to only
|
||||
be active for your donators then you would add a "is_donator" flag to all your donator roles and then in the code test if
|
||||
a player has that tag present:
|
||||
|
||||
-- give you donators a speed boost when they join; these functions aren't required but can be useful
|
||||
Roles.define_flag_trigger('is_donator',function(player,state)
|
||||
if state then
|
||||
player.character_running_speed_modifier = 1.5
|
||||
else
|
||||
player.character_running_speed_modifier = 1
|
||||
end
|
||||
end)
|
||||
|
||||
-- then on all your donator roles you would add
|
||||
Roles.new_role('Donator')
|
||||
:set_flag('is_donator')
|
||||
|
||||
-- and in your code you would test for
|
||||
if Roles.player_has_flag(player,'is_donator') then
|
||||
-- some donator only code
|
||||
end
|
||||
|
||||
>>>>Example Role Define:
|
||||
You can't use a role system without any roles so first you must define your roles; each role has a minimum of a name with
|
||||
the option for a shorthand:
|
||||
Roles.new_role('Administrator','Admin')
|
||||
|
||||
Next you will want to add any extras you want to have, such as a tag, colour, permission group or any custom flags:
|
||||
Roles.new_role('Administrator','Admin')
|
||||
:set_custom_tag('[Admin]')
|
||||
:set_custom_color('red') -- this can be {r=0,g=0,b=0} or a predefined value
|
||||
:set_permission_group('Staff') -- a second argument can be added if you have not used the custom permission group config
|
||||
:set_flag('is_admin')
|
||||
|
||||
You will then want to decide if you want to allow all actions, this should of course be used sparely:
|
||||
Roles.new_role('Administrator','Admin')
|
||||
...extras...
|
||||
:set_allow_all()
|
||||
|
||||
If you dont do this want this as i would advise you do then you will want to define what the role can do; this comes with
|
||||
an optional inheritance system if you like those sort of things in which case disallow may also be of some use to you:
|
||||
Roles.new_role('Administrator','Admin')
|
||||
...extras...
|
||||
:set_parent('Moderator') -- the admin can do anything that a moderator can do
|
||||
:allow{ -- these actions can be anything just try to keep them without conflicts
|
||||
'command/kill',
|
||||
'gui/game settings'
|
||||
}
|
||||
|
||||
Here is what the finished admin role would look like:
|
||||
Roles.new_role('Administrator','Admin')
|
||||
:set_custom_tag('[Admin]')
|
||||
:set_custom_color('red')
|
||||
:set_permission_group('Staff')
|
||||
:set_flag('is_admin')
|
||||
:set_parent('Moderator')
|
||||
:allow{
|
||||
'command/kill',
|
||||
'gui/game settings'
|
||||
}
|
||||
|
||||
>>>>Example System Define:
|
||||
Once all roles are defined these steps must be done to ensure the system is ready to use, this includes setting a default
|
||||
role, assigning a root (all permission) role that the server/system will use and the linier order that the roles fall into:
|
||||
|
||||
Roles.set_default('Guest')
|
||||
Roles.set_root('System')
|
||||
|
||||
Roles.define_role_order{
|
||||
'System',
|
||||
'Administrator',
|
||||
'Moderator',
|
||||
'Donator',
|
||||
'Guest'
|
||||
}
|
||||
|
||||
Just remember that in this example all these roles have not been defined; so make sure all your roles that are used are defined
|
||||
before hand; a config file on load is useful for this to ensure that its loaded before the first player even joins.
|
||||
|
||||
>>>>Functions List (see function for more detail):
|
||||
Roles.debug() --- Returns a string which contains all roles in index order displaying all data for them
|
||||
|
||||
Roles.get_role_by_name(name) --- Get a role for the given name
|
||||
Roles.get_role_by_order(index) --- Get a role with the given order index
|
||||
Roles.get_role_from_any(any) --- Gets a role from a name,index or role object (where it is just returned)
|
||||
Roles.get_player_roles(player) --- Gets all the roles of the given player, this will always contain the default role
|
||||
Roles.get_player_highest_role(player) --- Gets the highest role which the player has, can be used to compeer one player to another
|
||||
|
||||
Roles.assign_player(player,roles,by_player_name) --- Gives a player the given role(s) with an option to pass a by player name used in the log
|
||||
Roles.unassign_player(player,roles,by_player_name) --- Removes a player from the given role(s) with an option to pass a by player name used in the log
|
||||
Roles.override_player_roles(roles) --- Overrides all player roles with the given table of roles, useful to mass set roles on game start
|
||||
|
||||
Roles.player_has_role(player,search_role) --- A test for weather a player has the given role
|
||||
Roles.player_has_flag(player,flag_name) --- A test for weather a player has the given flag true for at least one of they roles
|
||||
Roles.player_allowed(player,action) --- A test for weather a player has at least one role which is allowed the given action
|
||||
|
||||
Roles.define_role_order(order) --- Used to set the role order, higher in the list is better, must be called at least once in config
|
||||
Roles.define_flag_trigger(name,callback) --- Defines a new trigger for when a tag is added or removed from a player
|
||||
Roles.set_default(name) --- Sets the default role which every player will have, this needs to be called at least once
|
||||
Roles.set_root(name) --- Sets the root role which will always have all permissions, any server actions act from this role
|
||||
|
||||
Roles.new_role(name,short_hand) --- Defines a new role and returns the prototype to allow configuration
|
||||
|
||||
Roles._prototype:set_allow_all(state) --- Sets the default allow state of the role, true will allow all actions
|
||||
Roles._prototype:allow(actions) --- Sets the allow actions for this role, actions in this list will be allowed for this role
|
||||
Roles._prototype:disallow(actions) --- Sets the disallow actions for this role, will prevent actions from being allowed regardless of inheritance
|
||||
Roles._prototype:is_allowed(action) --- Test for if a role is allowed the given action, mostly internal see Roles.player_allowed
|
||||
|
||||
Roles._prototype:set_flag(name,value) --- Sets the state of a flag for a role, flags can be used to apply effects to players
|
||||
Roles._prototype:clear_flags() --- Clears all flags from this role, individual flags can be removed with set_flag(name,false)
|
||||
Roles._prototype:has_flag(name) --- A test for if the role has a flag set
|
||||
|
||||
Roles._prototype:set_custom_tag(tag) --- Sets a custom player tag for the role, can be accessed by other code
|
||||
Roles._prototype:set_custom_color(color) --- Sets a custom colour for the role, can be accessed by other code
|
||||
Roles._prototype:set_permission_group(name,use_factorio_api) --- Sets the permission group for this role, players will be moved to the group of they highest role
|
||||
Roles._prototype:set_parent(role) --- Sets the parent for a role, any action not in allow or disallow will be looked for in its parents
|
||||
Roles._prototype:set_auto_promote_condition(callback) --- Sets an auto promote condition that is checked every 5 seconds, if true is returned then the player will recive the role
|
||||
Roles._prototype:set_block_auto_promote(state) --- Sets the role to not allow players to have auto promote effect them, useful to keep people locked to a punishment
|
||||
|
||||
Roles._prototype:add_player(player,skip_check,skip_event) --- Adds a player to this role, players can have more than one role at a time, used internally see Roles.assign
|
||||
Roles._prototype:remove_player(player,skip_check,skip_event) --- Removes a player from this role, players can have more than one role at a time, used internally see Roles.unassign
|
||||
Roles._prototype:get_players(online) --- Returns an array of all the players who have this role, can be filtered by online status
|
||||
Roles._prototype:print(message) --- Will print a message to all players with this role
|
||||
]]
|
||||
|
||||
local Game = require 'utils.game'
|
||||
local Global = require 'utils.global'
|
||||
local Event = require 'utils.event'
|
||||
local Groups = require 'expcore.permission_groups'
|
||||
local Colours = require 'resources.color_presets'
|
||||
|
||||
local Roles = {
|
||||
config={
|
||||
order={}, -- Contains the order of the roles, lower index is better
|
||||
roles={}, -- Contains the raw info for the roles, indexed by role name
|
||||
flags={}, -- Contains functions that run when a flag is added/removed from a player
|
||||
internal={}, -- Contains all internally accessed roles, such as root, default
|
||||
players={}
|
||||
},
|
||||
player_role_assigned=script.generate_event_name(),
|
||||
player_role_unassigned=script.generate_event_name(),
|
||||
_prototype={}
|
||||
}
|
||||
|
||||
--- Internal function used to trigger a few different things when roles are changed
|
||||
local function emit_player_roles_updated(player,type,roles,by_player_name)
|
||||
by_player_name = game.player and game.player.name or by_player_name or '<server>'
|
||||
local event = Roles.player_role_assigned
|
||||
if type == 'unassign' then
|
||||
event = Roles.player_role_unassigned
|
||||
end
|
||||
local by_player = Game.get_player_from_any(by_player_name)
|
||||
local by_player_index = by_player and by_player.index or 0
|
||||
local role_names = {}
|
||||
for _,role in pairs(roles) do
|
||||
role = Roles.get_role_from_any(role)
|
||||
if role then
|
||||
table.insert(role_names,role.name)
|
||||
end
|
||||
end
|
||||
game.print({'expcore-roles.game-message-'..type,player.name,table.concat(role_names,', '),by_player_name},Colours.cyan)
|
||||
script.raise_event(event,{
|
||||
name=Roles.player_roles_updated,
|
||||
tick=game.tick,
|
||||
player_index=player.index,
|
||||
by_player_index=by_player_index,
|
||||
roles=roles
|
||||
})
|
||||
game.write_file('log/roles.log',game.table_to_json{
|
||||
player_name=player.name,
|
||||
by_player_name=by_player_name,
|
||||
type=type,
|
||||
roles_changed=roles
|
||||
}..'\n',true,0)
|
||||
end
|
||||
|
||||
--- When global is loaded it will have the metatable re-assigned to the roles
|
||||
Global.register(Roles.config,function(tbl)
|
||||
Roles.config = tbl
|
||||
for _,role in pairs(Roles.config.roles) do
|
||||
setmetatable(role,{__index=Roles._prototype})
|
||||
local parent = Roles.config.roles[role.parent]
|
||||
if parent then
|
||||
setmetatable(role.allowed_actions, {__index=parent.allowed_actions})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- Returns a string which contains all roles in index order displaying all data for them
|
||||
-- @treturn string the debug output string
|
||||
function Roles.debug()
|
||||
local output = ''
|
||||
for index,role_name in pairs(Roles.config.order) do
|
||||
local role = Roles.config.roles[role_name]
|
||||
local color = role.custom_color or Colours.white
|
||||
color = string.format('[color=%d,%d,%d]',color.r,color.g,color.b)
|
||||
output = output..string.format('\n%s %s) %s',color,index,serpent.line(role))
|
||||
end
|
||||
return output
|
||||
end
|
||||
|
||||
--- Get a role for the given name
|
||||
-- @tparam name string the name of the role to get
|
||||
-- @treturn Roles._prototype the role with that name or nil
|
||||
function Roles.get_role_by_name(name)
|
||||
return Roles.config.roles[name]
|
||||
end
|
||||
|
||||
--- Get a role with the given order index
|
||||
-- @tparam index number the place in the oder list of the role to get
|
||||
-- @treturn Roles._prototype the role with that index in the order list or nil
|
||||
function Roles.get_role_by_order(index)
|
||||
local name = Roles.config.order[index]
|
||||
return Roles.config.roles[name]
|
||||
end
|
||||
|
||||
--- Gets a role from a name,index or role object (where it is just returned)
|
||||
-- nb: this function is used for the input for most outward facing functions
|
||||
-- @tparam any ?number|string|table the value used to find the role
|
||||
-- @treturn Roles._prototype the role that was found or nil see above
|
||||
function Roles.get_role_from_any(any)
|
||||
local tany = type(any)
|
||||
if tany == 'number' or tonumber(any) then
|
||||
any = tonumber(any)
|
||||
return Roles.get_role_by_order(any)
|
||||
elseif tany == 'string' then
|
||||
return Roles.get_role_by_name(any)
|
||||
elseif tany == 'table' then
|
||||
return Roles.get_role_by_name(any.name)
|
||||
end
|
||||
end
|
||||
|
||||
--- Gets all the roles of the given player, this will always contain the default role
|
||||
-- @tparam player LuaPlayer the player to get the roles of
|
||||
-- @treturn table a table where the values are the roles which the player has
|
||||
function Roles.get_player_roles(player)
|
||||
player = Game.get_player_from_any(player)
|
||||
if not player then return end
|
||||
local roles = Roles.config.players[player.name] or {}
|
||||
local default = Roles.config.roles[Roles.config.internal.default]
|
||||
local rtn = {default}
|
||||
for _,role_name in pairs(roles) do
|
||||
table.insert(rtn,Roles.config.roles[role_name])
|
||||
end
|
||||
return rtn
|
||||
end
|
||||
|
||||
--- Gets the highest role which the player has, can be used to compeer one player to another
|
||||
-- @tparam player LuaPlayer the player to get the highest role of
|
||||
-- @treturn the role with the highest order index which this player has
|
||||
function Roles.get_player_highest_role(player)
|
||||
local roles = Roles.get_player_roles(player)
|
||||
if not roles then return end
|
||||
local highest
|
||||
for _,role in pairs(roles) do
|
||||
if not highest or role.index < highest.index then
|
||||
highest = role
|
||||
end
|
||||
end
|
||||
return highest
|
||||
end
|
||||
|
||||
--- Gives a player the given role(s) with an option to pass a by player name used in the log
|
||||
-- @tparam player LuaPlayer the player that will be assigned the roles
|
||||
-- @tparam role table a table of roles that the player will be given, can be one role and can be role names
|
||||
-- @tparam[opt=<server>] by_player_name string the name of the player that will be shown in the log
|
||||
function Roles.assign_player(player,roles,by_player_name)
|
||||
player = Game.get_player_from_any(player)
|
||||
if not player then return end
|
||||
if type(roles) ~= 'table' or roles.name then
|
||||
roles = {roles}
|
||||
end
|
||||
for _,role in pairs(roles) do
|
||||
role = Roles.get_role_from_any(role)
|
||||
if role then
|
||||
role:add_player(player,false,true)
|
||||
end
|
||||
end
|
||||
emit_player_roles_updated(player,'assign',roles,by_player_name)
|
||||
end
|
||||
|
||||
--- Removes a player from the given role(s) with an option to pass a by player name used in the log
|
||||
-- @tparam player LuaPlayer the player that will have the roles removed
|
||||
-- @tparam roles table a table of roles to be removed from the player, can be one role and can be role names
|
||||
-- @tparam[opt=<server>] by_player_name string the name of the player that will be shown in the logs
|
||||
function Roles.unassign_player(player,roles,by_player_name)
|
||||
player = Game.get_player_from_any(player)
|
||||
if not player then return end
|
||||
if type(roles) ~= 'table' or roles.name then
|
||||
roles = {roles}
|
||||
end
|
||||
for _,role in pairs(roles) do
|
||||
role = Roles.get_role_from_any(role)
|
||||
if role then
|
||||
role:remove_player(player,false,true)
|
||||
end
|
||||
end
|
||||
emit_player_roles_updated(player,'unassign',roles,by_player_name)
|
||||
end
|
||||
|
||||
--- Overrides all player roles with the given table of roles, useful to mass set roles on game start
|
||||
-- @tparam roles table a table which is indexed by case sensitive player names and has the value of a table of role names
|
||||
function Roles.override_player_roles(roles)
|
||||
Roles.config.players = roles
|
||||
end
|
||||
|
||||
--- A test for weather a player has the given role
|
||||
-- @tparam player LuaPlayer the player to test the roles of
|
||||
-- @tparam search_role ?string|number|table a pointer to the role that is being searched for
|
||||
-- @treturn boolean true if the player has the role, false otherwise, nil for errors
|
||||
function Roles.player_has_role(player,search_role)
|
||||
local roles = Roles.get_player_roles(player)
|
||||
if not roles then return end
|
||||
search_role = Roles.get_role_from_any(search_role)
|
||||
if not search_role then return end
|
||||
for _,role in pairs(roles) do
|
||||
if role.name == search_role.name then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- A test for weather a player has the given flag true for at least one of they roles
|
||||
-- @tparam player LuaPlayer the player to test the roles of
|
||||
-- @tparam flag_name string the name of the flag that is being looked for
|
||||
-- @treturn boolean true if the player has at least one role which has the flag set to true, false otherwise, nil for errors
|
||||
function Roles.player_has_flag(player,flag_name)
|
||||
local roles = Roles.get_player_roles(player)
|
||||
if not roles then return end
|
||||
for _,role in pairs(roles) do
|
||||
if role:has_flag(flag_name) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- A test for weather a player has at least one role which is allowed the given action
|
||||
-- @tparam player LuaPlayer the player to test the roles of
|
||||
-- @tparam action string the name of the action that is being tested for
|
||||
-- @treturn boolean true if the player has at least one role which is allowed this action, false otherwise, nil for errors
|
||||
function Roles.player_allowed(player,action)
|
||||
local roles = Roles.get_player_roles(player)
|
||||
if not roles then return end
|
||||
for _,role in pairs(roles) do
|
||||
if role:is_allowed(action) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Used to set the role order, higher in the list is better, must be called at least once in config
|
||||
-- nb: function also re links parents due to expected position in the config file
|
||||
-- @tparam order table a table which is keyed only by numbers (start 1) and values are roles in order with highest first
|
||||
function Roles.define_role_order(order)
|
||||
-- Clears and then rebuilds the order table
|
||||
Roles.config.order = {}
|
||||
for _,role in ipairs(order) do
|
||||
if type(role) == 'table' and role.name then
|
||||
table.insert(Roles.config.order,role.name)
|
||||
else
|
||||
table.insert(Roles.config.order,role)
|
||||
end
|
||||
end
|
||||
-- Re-links roles to they parents as this is called at the end of the config
|
||||
for index,role in pairs(Roles.config.order) do
|
||||
role = Roles.config.roles[role]
|
||||
role.index = index
|
||||
local parent = Roles.config.roles[role.parent]
|
||||
if parent then
|
||||
setmetatable(role.allowed_actions,{__index=parent.allowed_actions})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Defines a new trigger for when a tag is added or removed from a player
|
||||
-- @tparam name string the name of the flag which the roles will have
|
||||
-- @tparam callback function the function that is called when roles are assigned
|
||||
-- flag param - player - the player that has had they roles changed
|
||||
-- flag param - state - the state of the flag, aka if the flag is present
|
||||
function Roles.define_flag_trigger(name,callback)
|
||||
Roles.config.flags[name] = callback -- this can desync if there are upvalues
|
||||
end
|
||||
|
||||
--- Sets the default role which every player will have, this needs to be called at least once
|
||||
-- @tparam name string the name of the default role
|
||||
function Roles.set_default(name)
|
||||
local role = Roles.config.roles[name]
|
||||
if not role then return end
|
||||
Roles.config.internal.default = name
|
||||
end
|
||||
|
||||
--- Sets the root role which will always have all permissions, any server actions act from this role
|
||||
-- @tparam name string the name of the root role
|
||||
function Roles.set_root(name)
|
||||
local role = Roles.config.roles[name]
|
||||
if not role then return end
|
||||
role:set_allow_all(true)
|
||||
Roles.config.internal.root = name
|
||||
end
|
||||
|
||||
--- Defines a new role and returns the prototype to allow configuration
|
||||
-- @tparam name string the name of the new role, must be unique
|
||||
-- @tparam[opt=name] shirt_hand string the shortened version of the name
|
||||
-- @treturn Roles._prototype the start of the config chain for this role
|
||||
function Roles.new_role(name,short_hand)
|
||||
if Roles.config.roles[name] then return error('Role name is non unique') end
|
||||
local role = setmetatable({
|
||||
name=name,
|
||||
short_hand=short_hand or name,
|
||||
allowed_actions={},
|
||||
allow_all_actions=false,
|
||||
flags={}
|
||||
},{__index=Roles._prototype})
|
||||
Roles.config.roles[name] = role
|
||||
return role
|
||||
end
|
||||
|
||||
--- Sets the default allow state of the role, true will allow all actions
|
||||
-- @tparam[opt=true] strate boolean true will allow all actions
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
function Roles._prototype:set_allow_all(state)
|
||||
if state == nil then state = true end
|
||||
self.allow_all_actions = not not state -- not not forces a boolean value
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets the allow actions for this role, actions in this list will be allowed for this role
|
||||
-- @tparam actions table indexed with numbers and is an array of action names, order has no effect
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
function Roles._prototype:allow(actions)
|
||||
if type(actions) ~= 'table' then
|
||||
actions = {actions}
|
||||
end
|
||||
for _,action in pairs(actions) do
|
||||
self.allowed_actions[action]=true
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets the disallow actions for this role, will prevent actions from being allowed regardless of inheritance
|
||||
-- @tparam actions table indexed with numbers and is an array of action names, order has no effect
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
function Roles._prototype:disallow(actions)
|
||||
if type(actions) ~= 'table' then
|
||||
actions = {actions}
|
||||
end
|
||||
for _,action in pairs(actions) do
|
||||
self.allowed_actions[action]=false
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Test for if a role is allowed the given action, mostly internal see Roles.player_allowed
|
||||
-- @tparam action string the name of the action to test if it is allowed
|
||||
-- @treturn boolean true if action is allowed, false otherwise
|
||||
function Roles._prototype:is_allowed(action)
|
||||
local is_root = Roles.config.internal.root.name == self.name
|
||||
return self.allowed_actions[action] or self.allow_all_actions or is_root
|
||||
end
|
||||
|
||||
--- Sets the state of a flag for a role, flags can be used to apply effects to players
|
||||
-- @tparam name string the name of the flag to set the value of
|
||||
-- @tparam[opt=true] value boolean the state to set the flag to
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
function Roles._prototype:set_flag(name,value)
|
||||
if value == nil then value = true end
|
||||
self.flags[name] = not not value -- not not forces a boolean value
|
||||
return self
|
||||
end
|
||||
|
||||
--- Clears all flags from this role, individual flags can be removed with set_flag(name,false)
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
function Roles._prototype:clear_flags()
|
||||
self.flags = {}
|
||||
return self
|
||||
end
|
||||
|
||||
--- A test for if the role has a flag set
|
||||
-- @tparam name string the name of the flag to test for
|
||||
-- @treturn boolean true if the flag is set, false otherwise
|
||||
function Roles._prototype:has_flag(name)
|
||||
return self.flags[name] or false
|
||||
end
|
||||
|
||||
--- Sets a custom player tag for the role, can be accessed by other code
|
||||
-- @tparam tag string the value that the tag will be
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
function Roles._prototype:set_custom_tag(tag)
|
||||
self.custom_tag = tag
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets a custom colour for the role, can be accessed by other code
|
||||
-- @tparam color ?string|table can either be and rgb colour table or the name of a colour defined in the presets
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
function Roles._prototype:set_custom_color(color)
|
||||
if type(color) ~= 'table' then
|
||||
color = Colours[color]
|
||||
end
|
||||
self.custom_color = color
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets the permission group for this role, players will be moved to the group of they highest role
|
||||
-- @tparam name string the name of the permission group to have players moved to
|
||||
-- @tparam[opt=false] use_factorio_api boolean when true the custom permission group module is ignored
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
function Roles._prototype:set_permission_group(name,use_factorio_api)
|
||||
if use_factorio_api then
|
||||
self.permission_group = {true,name}
|
||||
else
|
||||
local group = Groups.get_group_by_name(name)
|
||||
if not group then return end
|
||||
self.permission_group = name
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets the parent for a role, any action not in allow or disallow will be looked for in its parents
|
||||
-- nb: this is a recursive action, and changing the allows and disallows will effect all children roles
|
||||
-- @tparam role string the name of the role that will be the parent; has imminent effect if role is already defined
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
function Roles._prototype:set_parent(role)
|
||||
self.parent = role
|
||||
role = Roles.get_role_from_any(role)
|
||||
if not role then return self end
|
||||
setmetatable(self.allowed_actions, {__index=role.allowed_actions})
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets an auto promote condition that is checked every 5 seconds, if true is returned then the player will recive the role
|
||||
-- nb: this is one way, failing false after already gaining the role will not revoke the role
|
||||
-- @tparam callback function receives only one param which is player to promote, return true to promote the player
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
function Roles._prototype:set_auto_promote_condition(callback)
|
||||
self.auto_promote_condition = callback
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets the role to not allow players to have auto promote effect them, useful to keep people locked to a punishment
|
||||
-- @tparam[opt=true] state boolean when true the players with this role will not be auto promoted
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
function Roles._prototype:set_block_auto_promote(state)
|
||||
if state == nil then state = true end
|
||||
self.block_auto_promote = not not state -- forces a boolean value
|
||||
return self
|
||||
end
|
||||
|
||||
--- Adds a player to this role, players can have more than one role at a time, used internally see Roles.assign
|
||||
-- @tparam player LuaPlayer the player that will be given this role
|
||||
-- @tparam skip_check boolean when true player will be taken as the player name (use when player has not yet joined)
|
||||
-- @tparam skip_event boolean when true the event emit will be skipped, this is used internally with Roles.assign
|
||||
-- @treturn boolean true if the player was added successfully
|
||||
function Roles._prototype:add_player(player,skip_check,skip_event)
|
||||
player = Game.get_player_from_any(player)
|
||||
-- Check the player is valid, can be skipped but a name must be given
|
||||
if not player then
|
||||
if skip_check then
|
||||
player = {name=player}
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- Add the role name to the player's roles
|
||||
local player_roles = Roles.config.players[player.name]
|
||||
if player_roles then
|
||||
for _,role_name in pairs(player_roles) do
|
||||
if role_name == self.name then return false end
|
||||
end
|
||||
table.insert(player_roles,self.name)
|
||||
else
|
||||
Roles.config.players[player.name] = {self.name}
|
||||
end
|
||||
-- Emits event if required
|
||||
if not skip_event then
|
||||
emit_player_roles_updated(player,'assign',{self})
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Removes a player from this role, players can have more than one role at a time, used internally see Roles.unassign
|
||||
-- @tparam player LuaPlayer the player that will lose this role
|
||||
-- @tparam skip_check boolean when true player will be taken as the player name (use when player has not yet joined)
|
||||
-- @tparam skip_event boolean when true the event emit will be skipped, this is used internally with Roles.unassign
|
||||
-- @treturn boolean true if the player was removed successfully
|
||||
function Roles._prototype:remove_player(player,skip_check,skip_event)
|
||||
player = Game.get_player_from_any(player)
|
||||
-- Check the player is valid, can be skipped but a name must be given
|
||||
if not player then
|
||||
if skip_check then
|
||||
player = {name=player}
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- Remove the role from the players roles
|
||||
local player_roles = Roles.config.players[player.name]
|
||||
local rtn = false
|
||||
if player_roles then
|
||||
for index,role_name in pairs(player_roles) do
|
||||
if role_name == self.name then
|
||||
table.remove(player_roles,index)
|
||||
rtn = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if #player_roles == 0 then
|
||||
Roles.config.players[player.name] = nil
|
||||
end
|
||||
end
|
||||
-- Emits event if required
|
||||
if not skip_event then
|
||||
emit_player_roles_updated(player,'unassign',{self})
|
||||
end
|
||||
return rtn
|
||||
end
|
||||
|
||||
--- Returns an array of all the players who have this role, can be filtered by online status
|
||||
-- @tparam[opt=nil] online boolean when given will filter by this online state, nil will return all players
|
||||
-- @treturn table all the players who have this role, indexed order is meaningless
|
||||
function Roles._prototype:get_players(online)
|
||||
local players = {}
|
||||
-- Gets all players that have this role
|
||||
for player_name,player_roles in pairs(Roles.config.players) do
|
||||
for _,role_name in pairs(player_roles) do
|
||||
if role_name == self.name then
|
||||
table.insert(players,player_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Convert the player names to LuaPlayer
|
||||
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
|
||||
|
||||
--- Will print a message to all players with this role
|
||||
-- @tparam message string the message that will be printed to the players
|
||||
-- @treturn number the number of players who received the message
|
||||
function Roles._prototype:print(message)
|
||||
local players = self:get_players(true)
|
||||
for _,player in pairs(players) do
|
||||
player.print(message)
|
||||
end
|
||||
return #players
|
||||
end
|
||||
|
||||
--- 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 player = Game.get_player_by_index(event.player_index)
|
||||
-- Updates flags given to the player
|
||||
for flag,callback in pairs(Roles.config.flags) do
|
||||
local state = Roles.player_has_flag(player,flag)
|
||||
local success,err = pcall(callback,player,state)
|
||||
if not success then
|
||||
log{'expcore-roles.error-log-format-flag',flag,err}
|
||||
end
|
||||
end
|
||||
-- Updates the players permission group
|
||||
local highest = Roles.get_player_highest_role(player)
|
||||
if highest.permission_group then
|
||||
if highest.permission_group[1] then
|
||||
local group = game.permissions.get_group(highest.permission_group[2])
|
||||
if group then
|
||||
group.add_player(player)
|
||||
end
|
||||
else
|
||||
Groups.set_player_group(player,highest.permission_group)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- When a player joined or has a role change then the update is triggered
|
||||
Event.add(Roles.player_role_assigned,role_update)
|
||||
Event.add(Roles.player_role_unassigned,role_update)
|
||||
Event.add(defines.events.on_player_joined_game,role_update)
|
||||
-- Every 5 seconds the auto promote check is preformed
|
||||
Event.on_nth_tick(300,function()
|
||||
local promotes = {}
|
||||
for _,player in pairs(game.connected_players) do
|
||||
for _,role in pairs(Roles.config.roles) do
|
||||
if role.auto_promote_condition then
|
||||
local success,err = pcall(role.auto_promote_condition,player)
|
||||
if not success then
|
||||
log{'expcore-roles.error-log-format-promote',role.name,err}
|
||||
else
|
||||
if err == true and not Roles.player_has_role(player,role) then
|
||||
if promotes[player.name] then
|
||||
table.insert(promotes[player.name],role.name)
|
||||
else
|
||||
promotes[player.name] = {role.name}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for player_name,roles in pairs(promotes) do
|
||||
Roles.assign_player(player_name,roles)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Return Roles
|
||||
return Roles
|
||||
@@ -7,4 +7,7 @@ chelp-title=Help results for "__1__":
|
||||
chelp-footer=(__1__ results found; page __2__ of __3__)
|
||||
chelp-format=/__1__ __2__ - __3__ __4__
|
||||
chelp-alias=Alias: __1__
|
||||
chelp-out-of-range=__1__ is an invalid page number.
|
||||
chelp-out-of-range=__1__ is an invalid page number.
|
||||
roles-higher-role=The role you tried to assign is higher than your highest.
|
||||
roles-list=All active roles are:
|
||||
roles-list-element=__1__, [color=__2__]__3__
|
||||
@@ -4,13 +4,13 @@ time-symbol-days-short=__1__d
|
||||
unauthorized=Unauthorized, Access is denied due to invalid credentials
|
||||
reject-string-options=Invalid Option, Must be one of: __1__
|
||||
reject-string-max-length=Invalid Length, Max: __1__
|
||||
reject-number=Invalid Number
|
||||
reject-number=Invalid Number.
|
||||
reject-number-range=Invalid Range, Min (inclusive): __1__, Max (inclusive): __2__
|
||||
reject-player=Invaild Player Name, __1__ ,try using tab key to auto-complete the name
|
||||
reject-player-online=Player is offline.
|
||||
reject-player-alive=Player is dead.
|
||||
reject-force=Invaild Force Name
|
||||
reject-surface=Invaild surface Name
|
||||
reject-force=Invaild Force Name.
|
||||
reject-surface=Invaild Surface Name.
|
||||
invalid-inputs=Invalid Input, /__1__ __2__
|
||||
invalid-param=Invalid Param "__1__"; __2__
|
||||
command-help=__1__ - __2__
|
||||
@@ -18,7 +18,10 @@ command-ran=Command Complete
|
||||
command-fail=Command failed to run: __1__
|
||||
command-error-log-format=[ERROR] command/__1__ :: __2__
|
||||
|
||||
[time-format]
|
||||
simple-format-none=__1__
|
||||
simple-format-div=__1__:__2__
|
||||
simple-format-tagged=__1__ __2__
|
||||
[expcore-roles]
|
||||
error-log-format-flag=[ERROR] roleFlag/__1__ :: __2__
|
||||
error-log-format-promote=[ERROR] rolePromote/__1__ :: __2__
|
||||
game-message-assign=__1__ has been assigned to __2__ by __3__
|
||||
game-message-unassign=__1__ has been unassigned from __2__ by __3__
|
||||
reject-role=Invalid Role Name.
|
||||
reject-player-role=Player has a higher role.
|
||||
@@ -20,6 +20,8 @@ Global.register(
|
||||
end
|
||||
)
|
||||
|
||||
local Public = {}
|
||||
|
||||
--- This will re-create the speech bubble after it de-spawns called with set_timeout
|
||||
local callback =
|
||||
Token.register(
|
||||
@@ -38,6 +40,9 @@ local callback =
|
||||
--- This will move the messages onto the next message in the loop
|
||||
local function circle_messages()
|
||||
for name, ent in pairs(compilatrons) do
|
||||
if not ent.valid then
|
||||
Public.spawn_compilatron(game.players[1].surface,name)
|
||||
end
|
||||
local current_message = current_messages[name]
|
||||
local msg_number
|
||||
local message
|
||||
@@ -58,8 +63,6 @@ end
|
||||
|
||||
Event.on_nth_tick(config.message_cycle, circle_messages)
|
||||
|
||||
local Public = {}
|
||||
|
||||
--- This will add a compilatron to the global and start his message cycle
|
||||
-- @tparam entity LuaEntity the compilatron entity that moves around
|
||||
-- @tparam name string the name of the location that the complitron is at
|
||||
|
||||
13
modules/addons/pollution-grading.lua
Normal file
13
modules/addons/pollution-grading.lua
Normal file
@@ -0,0 +1,13 @@
|
||||
local Event = require 'utils.event'
|
||||
local config = require 'config.pollution_grading'
|
||||
|
||||
local delay = config.update_delay * 3600 -- convert from minutes to ticks
|
||||
Event.on_nth_tick(delay,function()
|
||||
local surface = game.surfaces[1]
|
||||
local true_max = surface.get_pollution(config.reference_point)
|
||||
local max = true_max*config.max_scalar
|
||||
local min = max*config.min_scalar
|
||||
local settings = game.map_settings.pollution
|
||||
settings.expected_max_per_chunk = max
|
||||
settings.min_to_show_per_chunk = min
|
||||
end)
|
||||
@@ -2,7 +2,7 @@ local Event = require 'utils.event'
|
||||
local Game = require 'utils.game'
|
||||
local Global = require 'utils.global'
|
||||
local print_grid_value, clear_flying_text = ext_require('expcore.common','print_grid_value','clear_flying_text')
|
||||
local config = require 'config.worn_paths'
|
||||
local config = require 'config.scorched_earth'
|
||||
|
||||
-- Loops over the config and finds the wile which has the highest value for strength
|
||||
local max_strength = 0
|
||||
@@ -140,5 +140,5 @@ Event.add(defines.events.on_player_created, function(event)
|
||||
spawn_entities(s,p)
|
||||
spawn_belts(s,p)
|
||||
spawn_turrets()
|
||||
player.teleport(s,p)
|
||||
player.teleport(p,s)
|
||||
end)
|
||||
@@ -4,7 +4,7 @@ require 'config.command_parse_general'
|
||||
Commands.new_command('admin-chat','Sends a message in chat that only admins can see.')
|
||||
:add_param('message',false) -- the message to send in the admin chat
|
||||
:enable_auto_concat()
|
||||
:add_tag('admin_only',true)
|
||||
:set_flag('admin_only',true)
|
||||
:add_alias('ac')
|
||||
:register(function(player,message,raw)
|
||||
local pcc = player and player.chat_color or {r=255,g=255,b=255}
|
||||
|
||||
@@ -3,10 +3,10 @@ require 'config.command_parse_general'
|
||||
|
||||
Commands.new_command('toggle-cheat-mode','Toggles cheat mode for your player, or another player.')
|
||||
:add_param('player',true,'player') -- player to toggle chest mode of, can be nil for self
|
||||
:add_defaults{player=function(player)
|
||||
:set_defaults{player=function(player)
|
||||
return player -- default is the user using the command
|
||||
end}
|
||||
:add_tag('admin_only',true)
|
||||
:set_flag('admin_only',true)
|
||||
:register(function(player,action_player,raw)
|
||||
action_player.cheat_mode = not action_player.cheat_mode
|
||||
end)
|
||||
@@ -12,7 +12,7 @@ end)
|
||||
Commands.new_command('chelp','Searches for a keyword in all commands you are allowed to use.')
|
||||
:add_param('keyword',true) -- the keyword that will be looked for
|
||||
:add_param('page',true,'integer') -- the keyword that will be looked for
|
||||
:add_defaults{keyword='',page=1}
|
||||
:set_defaults{keyword='',page=1}
|
||||
:register(function(player,keyword,page,raw)
|
||||
local player_index = player and player.index or 0
|
||||
-- if keyword is a number then treat it as page number
|
||||
|
||||
@@ -8,7 +8,8 @@ local interface_modules = {
|
||||
['_C']=Common,
|
||||
['Commands']=Commands,
|
||||
['output']=Common.player_return,
|
||||
['Group']='expcore.permission_groups'
|
||||
['Group']='expcore.permission_groups',
|
||||
['Roles']='expcore.roles'
|
||||
}
|
||||
|
||||
-- loads all the modules given in the above table
|
||||
@@ -48,7 +49,7 @@ end
|
||||
Commands.new_command('interface','Sends an innovation to be ran and returns the result.')
|
||||
:add_param('innovation',false) -- the message to send in the admin chat
|
||||
:enable_auto_concat()
|
||||
:add_tag('admin_only',true)
|
||||
:set_flag('admin_only',true)
|
||||
:register(function(player,innovation,raw)
|
||||
if not innovation:find('%s') and not innovation:find('return') then
|
||||
-- if there are no spaces and return is not present then return is appended to the start
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
local Commands = require 'expcore.commands'
|
||||
local Roles = require 'expcore.roles'
|
||||
require 'config.command_parse_general'
|
||||
require 'config.command_parse_roles'
|
||||
|
||||
Commands.new_command('kill','Kills yourself or another player.')
|
||||
:add_param('player',true,'player-alive') -- the player to kill, must be alive to be valid
|
||||
:add_defaults{player=function(player)
|
||||
:add_param('player',true,'player-role-alive') -- the player to kill, must be alive to be valid
|
||||
:set_defaults{player=function(player)
|
||||
-- default is the player unless they are dead
|
||||
if player.character and player.character.health > 0 then
|
||||
return player
|
||||
end
|
||||
end}
|
||||
:add_tag('admin_only',true)
|
||||
:register(function(player,action_player,raw)
|
||||
if not action_player then
|
||||
-- can only be nil if no player given and the user is dead
|
||||
return Commands.error{'exp-commands.kill-already-dead'}
|
||||
end
|
||||
action_player.character.die()
|
||||
if player == action_player then
|
||||
action_player.character.die()
|
||||
elseif Roles.player_allowed(player,'command/kill/always') then
|
||||
action_player.character.die()
|
||||
else
|
||||
return Commands.error{'expcore-commands.unauthorized'}
|
||||
end
|
||||
end)
|
||||
45
modules/commands/roles.lua
Normal file
45
modules/commands/roles.lua
Normal file
@@ -0,0 +1,45 @@
|
||||
local Commands = require 'expcore.commands'
|
||||
local Roles = require 'expcore.roles'
|
||||
local Colours = require 'resources.color_presets'
|
||||
|
||||
Commands.new_command('assign-role','Assigns a role to a player')
|
||||
:add_param('player',false,'player-role')
|
||||
:add_param('role',false,'role')
|
||||
:set_flag('admin-only',true)
|
||||
:add_alias('rpromote','assign','role','add-role')
|
||||
:register(function(player,action_player,role,raw)
|
||||
local player_highest = Roles.get_player_highest(player)
|
||||
if player_highest.index < role.index then
|
||||
Roles.assign_player(action_player,role,player.name)
|
||||
else
|
||||
return Commands.error{'exp-commands.roles-higher-role'}
|
||||
end
|
||||
end)
|
||||
|
||||
Commands.new_command('unassign-role','Unassigns a role from a player')
|
||||
:add_param('player',false,'player-role')
|
||||
:add_param('role',false,'role')
|
||||
:set_flag('admin-only',true)
|
||||
:add_alias('rdemote','unassign','remove-role')
|
||||
:register(function(player,action_player,role,raw)
|
||||
local player_highest = Roles.get_player_highest(player)
|
||||
if player_highest.index < role.index then
|
||||
Roles.unassign_player(action_player,role,player.name)
|
||||
else
|
||||
return Commands.error{'exp-commands.roles-higher-role'}
|
||||
end
|
||||
end)
|
||||
|
||||
Commands.new_command('list-roles','Lists all roles in they correct order')
|
||||
:add_alias('lroles','roles')
|
||||
:register(function(player,raw)
|
||||
local roles = Roles.config.order
|
||||
local message = {'exp-commands.roles-list'}
|
||||
for _,role_name in pairs(roles) do
|
||||
local role = Roles.get_role_by_name(role_name)
|
||||
local colour = role.custom_color or Colours.white
|
||||
colour = string.format('%d,%d,%d',colour.r,colour.g,colour.b)
|
||||
message = {'exp-commands.roles-list-element',message,colour,role_name}
|
||||
end
|
||||
return Commands.success(message)
|
||||
end)
|
||||
@@ -1,5 +1,7 @@
|
||||
local Commands = require 'expcore.commands'
|
||||
local Roles = require 'expcore.roles'
|
||||
require 'config.command_parse_general'
|
||||
require 'config.command_parse_roles'
|
||||
|
||||
Commands.new_command('tag','Sets your player tag.')
|
||||
:add_param('tag',false,'string-max-length',20) -- new tag for your player max 20 char
|
||||
@@ -9,15 +11,15 @@ Commands.new_command('tag','Sets your player tag.')
|
||||
end)
|
||||
|
||||
Commands.new_command('tag-clear','Clears your tag. Or another player if you are admin.')
|
||||
:add_param('player',true,'player') -- player to remove the tag of, nil to apply to self
|
||||
:add_defaults{player=function(player)
|
||||
:add_param('player',true,'player-role') -- player to remove the tag of, nil to apply to self
|
||||
:set_defaults{player=function(player)
|
||||
return player -- default is the user using the command
|
||||
end}
|
||||
:register(function(player,action_player,raw)
|
||||
if action_player.index == player.index then
|
||||
-- no player given so removes your tag
|
||||
action_player.tag = ''
|
||||
elseif player.admin then
|
||||
elseif Roles.player_allowed(player,'command/clear-tag/always') then
|
||||
-- player given and user is admin so clears that player's tag
|
||||
action_player.tag = ''
|
||||
else
|
||||
|
||||
@@ -14,7 +14,7 @@ Commands.new_command('teleport','Teleports a player to another player.')
|
||||
:add_param('from_player',false,'player-alive') -- player that will be teleported, must be alive
|
||||
:add_param('to_player',false,'player-online') -- player to teleport to, must be online (if dead goes to where they died)
|
||||
:add_alias('tp')
|
||||
:add_tag('admin_only',true)
|
||||
:set_flag('admin_only',true)
|
||||
:register(function(player,from_player,to_player,raw)
|
||||
if from_player.index == to_player.index then
|
||||
-- return if attempting to teleport to self
|
||||
@@ -28,7 +28,7 @@ end)
|
||||
|
||||
Commands.new_command('bring','Teleports a player to you.')
|
||||
:add_param('player',false,'player-alive') -- player that will be teleported, must be alive
|
||||
:add_tag('admin_only',true)
|
||||
:set_flag('admin_only',true)
|
||||
:register(function(player,from_player,raw)
|
||||
if from_player.index == player.index then
|
||||
-- return if attempting to teleport to self
|
||||
@@ -43,7 +43,7 @@ end)
|
||||
Commands.new_command('goto','Teleports you to a player.')
|
||||
:add_param('player',false,'player-online') -- player to teleport to, must be online (if dead goes to where they died)
|
||||
:add_alias('tp-me','tpme')
|
||||
:add_tag('admin_only',true)
|
||||
:set_flag('admin_only',true)
|
||||
:register(function(player,to_player,raw)
|
||||
if to_player.index == player.index then
|
||||
-- return if attempting to teleport to self
|
||||
|
||||
@@ -50,7 +50,7 @@ end
|
||||
function Game.get_player_from_any(obj)
|
||||
local o_type = type(obj)
|
||||
local p
|
||||
if type == 'number' then
|
||||
if o_type == 'number' then
|
||||
p = Game.get_player_by_index(obj)
|
||||
elseif o_type == 'string' then
|
||||
p = game.players[obj]
|
||||
|
||||
Reference in New Issue
Block a user