mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 11:35:22 +09:00
Updated Docs
This commit is contained in:
@@ -1,31 +1,31 @@
|
||||
--[[-- Core Module - Async
|
||||
- An extention of task and token to allow a single require to register and run async functions.
|
||||
@core Async
|
||||
@alias Async
|
||||
- An extention of task and token to allow a single require to register and run async functions.
|
||||
@core Async
|
||||
@alias Async
|
||||
|
||||
@usage
|
||||
-- To use Async you must register the allowed functions when the files are loaded, often this will just be giving access to
|
||||
-- some functions within a module if you expect that some parts may be blocked by in game permissions or a custom system you have made
|
||||
-- you may also want to register functions that you want to have a delayed call, such as waiting 2 seconds before printing a message
|
||||
@usage
|
||||
-- To use Async you must register the allowed functions when the file is loaded, often this will just be giving access to
|
||||
-- some functions within a module if you expect that at part may be blocked by in game permissions or a custom system you have made
|
||||
-- you may also want to register functions that you want to have a time delay, such as waiting 2 seconds before printing a message
|
||||
|
||||
-- This player.admin is called (command or gui element event) by a player who isnt admin then it will error
|
||||
-- here we register the function to promote the player so that it will run async
|
||||
local promote_player =
|
||||
Async.register(function(player)
|
||||
player.admin = true
|
||||
end)
|
||||
-- When player.admin is called (either command or gui element event) by a player who isnt admin then it will error
|
||||
-- here we register the function to promote the player so that it will run async and outside the player scope
|
||||
local promote_player =
|
||||
Async.register(function(player)
|
||||
player.admin = true
|
||||
end)
|
||||
|
||||
-- This will allow us to bypass this by running one tick later outside of any player scope
|
||||
Async(promote_player,game.player)
|
||||
-- This will allow us to bypass the error by running one tick later outside of any player scope
|
||||
Async(promote_player,game.player)
|
||||
|
||||
-- Here we make an sync function that we want to have a delay, note the delay is not defined here
|
||||
local print_message =
|
||||
Async.register(function(player,message)
|
||||
player.print(message)
|
||||
end)
|
||||
-- Here we make an sync function that we want to have a delay, note the delay is not defined here
|
||||
local print_message =
|
||||
Async.register(function(player,message)
|
||||
player.print(message)
|
||||
end)
|
||||
|
||||
-- We can then call the async function with a delay using the wait function
|
||||
Async.wait(60,print_message,game.player,'One second has passed!')
|
||||
-- We can then call the async function with a delay using the wait function
|
||||
Async.wait(60, print_message, game.player, 'One second has passed!')
|
||||
|
||||
]]
|
||||
local Task = require 'utils.task' --- @dep utils.task
|
||||
@@ -39,13 +39,38 @@ Token.register(function(params)
|
||||
return func(unpack(params.params))
|
||||
end)
|
||||
|
||||
--- Register a new async function, must called when the file is loaded
|
||||
-- @tparam function callback the function that will become an async function
|
||||
--[[-- Register a new async function, must called when the file is loaded
|
||||
@function register
|
||||
@tparam function callback the function that can be called as an async function
|
||||
@treturn string the uid of the async function which can be passed to Async.run and Async.wait
|
||||
|
||||
@usage-- Registering a function to set the admin state of a player
|
||||
local set_admin =
|
||||
Async.register(function(player, state)
|
||||
if player.valid then
|
||||
player.admin = state
|
||||
end
|
||||
end)
|
||||
|
||||
@usage-- Registering a function to print to a player
|
||||
local print_to_player =
|
||||
Async.register(function(player, message)
|
||||
if player.valid then
|
||||
player.print(message)
|
||||
end
|
||||
end)
|
||||
|
||||
]]
|
||||
Async.register = Token.register
|
||||
|
||||
--- Runs the async function linked to this token, you may supply any number of params as needed
|
||||
-- @tparam string token the token of the async function you want to run
|
||||
-- @tparam[opt] any ... the other params that you want to pass to your function
|
||||
--[[-- Runs an async function, you may supply any number of arguments as required by that function
|
||||
@tparam string token the token of the async function you want to run
|
||||
@tparam[opt] any ... the other params that you want to pass to your function
|
||||
|
||||
@usage-- Make a player admin regardless of if you are admin
|
||||
Async.run(set_admin, player, true)
|
||||
|
||||
]]
|
||||
function Async.run(token,...)
|
||||
Task.queue_task(internal_run, {
|
||||
token = token,
|
||||
@@ -53,10 +78,15 @@ function Async.run(token,...)
|
||||
})
|
||||
end
|
||||
|
||||
--- Runs the async function linked to this token after the given number of ticks, you may supply any number of params as needed
|
||||
-- @tparam number ticks the number of ticks that you want the function to run after
|
||||
-- @tparam string token the token of the async function you want to run
|
||||
-- @tparam[opt] any ... the other params that you want to pass to your function
|
||||
--[[-- Runs an async function after the given number of ticks, you may supply any number of arguments as required by that function
|
||||
@tparam number ticks the number of ticks that you want the function to run after
|
||||
@tparam string token the token of the async function you want to run
|
||||
@tparam[opt] any ... the other params that you want to pass to your function
|
||||
|
||||
@usage-- Print a message to a player after 5 seconds
|
||||
Async.wait(300, print_to_player, 'Hello, World!')
|
||||
|
||||
]]
|
||||
function Async.wait(ticks,token,...)
|
||||
Task.set_timeout_in_ticks(ticks, internal_run, {
|
||||
token = token,
|
||||
|
||||
@@ -1,197 +1,193 @@
|
||||
--[[-- Core Module - Commands
|
||||
- Factorio command making module that makes commands with better parse and more modularity
|
||||
@core Commands
|
||||
@alias Commands
|
||||
- Factorio command making module that makes commands with better parse and more modularity
|
||||
@core Commands
|
||||
@alias Commands
|
||||
|
||||
@usage
|
||||
---- 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:
|
||||
@usage--- Full code example, see below for explaination
|
||||
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
|
||||
else
|
||||
return false
|
||||
end
|
||||
end)
|
||||
: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)
|
||||
|
||||
-- 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
|
||||
local msg = ') '..player.name
|
||||
if smiley then
|
||||
msg = ':'..msg
|
||||
end
|
||||
|
||||
-- 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
|
||||
for 1 = 1,repeat_count do
|
||||
Command.print(1..msg)
|
||||
end
|
||||
end)
|
||||
|
||||
-- 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
|
||||
@usage--- 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.
|
||||
|
||||
-- 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
|
||||
-- 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.')
|
||||
|
||||
-- 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
|
||||
return true -- true return 1
|
||||
end
|
||||
end)
|
||||
-- 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)
|
||||
|
||||
@usage
|
||||
---- 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:
|
||||
-- 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)
|
||||
|
||||
-- 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
|
||||
-- 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}
|
||||
|
||||
-- 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
|
||||
-- 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
|
||||
}
|
||||
|
||||
-- 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
|
||||
-- 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
|
||||
|
||||
-- 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 double
|
||||
-- messages to the user:
|
||||
input = Commands.parse('number-int',input,player,reject)
|
||||
if not input then return end -- nil check
|
||||
-- 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)
|
||||
|
||||
-- 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
|
||||
-- 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)
|
||||
-- Other values that can be returned from register
|
||||
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 don't use this method see below
|
||||
return Commands.success(message[opt]) -- will return the success message to the user and your given message, halts execution
|
||||
return <any> -- if any value is returned then it will be returned to the player via a Commands.success call
|
||||
|
||||
@usage
|
||||
---- 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.
|
||||
@usage--- Example Authenticator:
|
||||
-- The command system is best used when you can control who uses 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 certain commands to require the user to be a game admin.
|
||||
|
||||
-- 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.')
|
||||
-- For our admin only example we will set a flag to true when we want it to be admin only;
|
||||
-- when we define the command will will use :set_flag('admin_only', true);
|
||||
-- then inside the authenticator we will test if the flag is present using: if flags.admin_only then
|
||||
|
||||
-- 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)
|
||||
-- When the authenticator is called by the command handler it will be passed 4 arguments:
|
||||
-- 1) player - the player who used the command
|
||||
-- 2) command - the name of the command that is being used
|
||||
-- 3) flags - the flags which have been set for this command, flags are set with :set_flag(name, value)
|
||||
-- 4) reject - the reject function which is the preferred method to prevent execution of the command
|
||||
|
||||
-- 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)
|
||||
-- No return is required to allow the command to execute but 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 assume that any one can use it
|
||||
-- 2) when the "admin_only" flag is set, and the player is admin
|
||||
|
||||
-- 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}
|
||||
-- When want to prevent exicution of the command we must reject it, listed is how that can be done:
|
||||
-- 1) return false -- this is the most basic rejection and should only be used while testing
|
||||
-- 2) return reject -- returning the reject function is as a fail safe in case you forget to call it, same as returning false
|
||||
-- 3) reject() -- this will block execution without to allowing further code to be ran in your 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 your code before rejecting
|
||||
|
||||
-- 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
|
||||
}
|
||||
-- Example Code:
|
||||
Commands.add_authenticator(function(player, command, flags, reject)
|
||||
-- Check if the command is admin only
|
||||
if flags.admin_only then
|
||||
-- Return true if player is admin, or reject and return error message
|
||||
return player.admin or reject('This command is for admins only!')
|
||||
else
|
||||
-- Return true if command was not admin only
|
||||
return true
|
||||
end
|
||||
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
|
||||
@usage--- Example Parse:
|
||||
-- Before you make a command 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 and validated before your command is executed;
|
||||
-- This module should is paired with a general command parse but you may want to create your own.
|
||||
|
||||
-- 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)
|
||||
-- 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
|
||||
:add_param('repeat_count', false, 'number-range-int', 5, 10) -- "repeat_count" is required "number-range-int" in a range 5 to 10 inclusive
|
||||
|
||||
-- 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 don't use this method see below
|
||||
return Commands.success(message[opt]) -- will return the success message to the user and your given message, halts execution
|
||||
return <any> if any value is returned then it will be returned to the player via a Commands.success call
|
||||
-- The command parse will be passed 3 arguments plus any other which you define, in our case:
|
||||
-- 1) input - 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) player - the player who is using the command, this is always present
|
||||
-- 3) reject - the reject function to throw an error to the user, this is always present
|
||||
-- 4) range_min - the range min, this is user defined and has the value given when the param is defined
|
||||
-- 5) range_max - the range max, this is user defined and has the value given when the param is defined
|
||||
|
||||
-- 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
|
||||
else
|
||||
return false
|
||||
end
|
||||
end)
|
||||
: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 1 = 1,repeat_count do
|
||||
Command.print(1..msg)
|
||||
end
|
||||
end)
|
||||
-- When returning from the param parse you 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 is rejected, 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 to the user
|
||||
-- nb: if you do not return reject after you call it then you will still be returning nil so there will be a duplicate error message
|
||||
|
||||
-- It should be noted that if you want to expand on an existing parse you can use Commands.parse(type, input, player, reject)
|
||||
-- this function will either return a new value for the input or nil, if it is nil you should return nil to prevent duplicate
|
||||
-- error 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
|
||||
-- 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)
|
||||
|
||||
]]
|
||||
|
||||
@@ -199,38 +195,58 @@ local Game = require 'utils.game' --- @dep utils.game
|
||||
local player_return,write_json = _C.player_return, _C.write_json --- @dep expcore.common
|
||||
|
||||
local Commands = {
|
||||
defines={ -- common values are stored error like signals
|
||||
--- Values returned by the signal functions to cause the command system to react
|
||||
defines = {
|
||||
error='CommandError',
|
||||
unauthorized='CommandErrorUnauthorized',
|
||||
success='CommandSuccess'
|
||||
},
|
||||
commands={}, -- custom command data will be stored here
|
||||
authorization_fail_on_error=false, -- set true to have authorize fail if a callback fails to run, more secure
|
||||
authorization={}, -- custom function are stored here which control who can use what commands
|
||||
parse_functions={}, -- used to store default functions which are common parse function such as player or number in range
|
||||
print=player_return, -- short cut so player_return does not need to be required in every module
|
||||
_prototype={}, -- used to store functions which gets added to new custom commands
|
||||
--- Custom command data will be stored here
|
||||
commands={},
|
||||
--- Set true to have authorize fail if a callback fails to run, more secure
|
||||
authorization_fail_on_error=false,
|
||||
--- Custom function are stored here which control who can use what commands
|
||||
authorization={},
|
||||
--- Used to store default functions which are common parse function such as player or number in range
|
||||
parse_functions={},
|
||||
-- Sends a value to the player, different to success as this does not signal the end of your command
|
||||
print=player_return,
|
||||
--- Used to store functions which gets added to new custom commands
|
||||
_prototype={},
|
||||
}
|
||||
|
||||
--- Authenication.
|
||||
-- Functions that control who can use commands
|
||||
-- @section auth
|
||||
|
||||
--- Adds an authorization callback, function used to check if a player if allowed to use a command
|
||||
-- @tparam function callback 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 - 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
|
||||
--[[-- Adds an authorization callback, function used to check if a player if allowed to use a command
|
||||
@tparam function callback the callback you want to register as an authenticator
|
||||
@treturn number the index it was inserted at use to remove the callback, if anon function used
|
||||
|
||||
@usage-- Test if a command is admin only and if the player is admin
|
||||
local admin_authenticator =
|
||||
Commands.add_authenticator(function(player, command, flags, reject)
|
||||
if flags.admin_only then
|
||||
return player.admin or reject('This command is for admins only!')
|
||||
else
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
]]
|
||||
function Commands.add_authenticator(callback)
|
||||
table.insert(Commands.authorization,callback)
|
||||
return #Commands.authorization
|
||||
end
|
||||
|
||||
--- Removes an authorization callback
|
||||
-- @tparam function|number callback the callback to remove, an index returned by add_authenticator can be passed
|
||||
-- @treturn boolean was the callback found and removed
|
||||
--[[-- Removes an authorization callback
|
||||
@tparam function|number callback the callback to remove, an index returned by add_authenticator can be passed
|
||||
@treturn boolean if the callback found and removed successfuly
|
||||
|
||||
@usage-- Removing the admin authenticator, can not be done dueing runtime
|
||||
Commands.remove_authenticator(admin_authenticator)
|
||||
|
||||
]]
|
||||
function Commands.remove_authenticator(callback)
|
||||
if type(callback) == 'number' then
|
||||
-- if a number is passed then it is assumed to be the index
|
||||
@@ -256,13 +272,18 @@ function Commands.remove_authenticator(callback)
|
||||
return false
|
||||
end
|
||||
|
||||
--- Mostly used internally, calls all authorization callbacks, returns if the player is authorized
|
||||
-- @tparam LuaPlayer player the player that is using the command, passed to callbacks
|
||||
-- @tparam string command_name the command that is being used, passed to callbacks
|
||||
-- @treturn[1] boolean true player is authorized
|
||||
-- @treturn[1] string commands const for success
|
||||
-- @treturn[2] boolean false player is unauthorized
|
||||
-- @treturn[2] string|locale_string the reason given by the authenticator
|
||||
--[[-- Mostly used internally, calls all authorization callbacks, returns if the player is authorized
|
||||
@tparam LuaPlayer player the player that is using the command, passed to callbacks
|
||||
@tparam string command_name the command that is being used, passed to callbacks
|
||||
@treturn[1] boolean true player is authorized
|
||||
@treturn[1] string commands const for success
|
||||
@treturn[2] boolean false player is unauthorized
|
||||
@treturn[2] string|locale_string the reason given by the authenticator
|
||||
|
||||
@usage-- Test if a player can use "repeat-name"
|
||||
local authorized, status = Commands.authorize(game.player, 'repeat-name')
|
||||
|
||||
]]
|
||||
function Commands.authorize(player,command_name)
|
||||
local failed
|
||||
if not player then return true end
|
||||
@@ -300,13 +321,22 @@ function Commands.authorize(player,command_name)
|
||||
return true, Commands.defines.success
|
||||
end
|
||||
end
|
||||
|
||||
--- Getters.
|
||||
-- Functions that get commands
|
||||
-- @section getters
|
||||
|
||||
--- Gets all commands that a player is allowed to use, game commands not included
|
||||
-- @tparam[opt] LuaPlayer player the player that you want to get commands of, nil will return all commands
|
||||
-- @treturn table all commands that that player is allowed to use, or all commands
|
||||
--[[-- Gets all commands that a player is allowed to use, game commands are not included
|
||||
@tparam[opt] LuaPlayer player the player that you want to get commands of, nil will return all commands
|
||||
@treturn table all commands that that player is allowed to use, or all commands
|
||||
|
||||
@usage-- Get the command you are allowed to use
|
||||
local commands = Commands.get(game.player)
|
||||
|
||||
@usage-- Get all commands that are registered
|
||||
local commands = Commands.get()
|
||||
|
||||
]]
|
||||
function Commands.get(player)
|
||||
player = Game.get_player_from_any(player)
|
||||
if not player then return Commands.commands end
|
||||
@@ -319,12 +349,20 @@ function Commands.get(player)
|
||||
return allowed
|
||||
end
|
||||
|
||||
--- Searches command names and help messages to find possible commands, game commands included
|
||||
-- @tparam string keyword the word which you are trying to find
|
||||
-- @tparam[opt] LuaPlayer allowed_player the player to get allowed commands of, if nil all commands are searched
|
||||
-- @treturn table all commands that contain the key word, and allowed by player if player given
|
||||
function Commands.search(keyword,allowed_player)
|
||||
local custom_commands = Commands.get(allowed_player)
|
||||
--[[-- Searches command names and help messages to find possible commands, game commands are included
|
||||
@tparam string keyword the word which you are trying to find in your search
|
||||
@tparam[opt] LuaPlayer player the player to get allowed commands of, if nil all commands are searched
|
||||
@treturn table all commands that contain the key word, and allowed by player if player given
|
||||
|
||||
@usage-- Get all commands which "repeat"
|
||||
local commands = Commands.search('repeat')
|
||||
|
||||
@usage-- Get all commands which "repeat" and you are allowed to use
|
||||
local commands = Commands.search('repeat', game.player)
|
||||
|
||||
]]
|
||||
function Commands.search(keyword,player)
|
||||
local custom_commands = Commands.get(player)
|
||||
local matches = {}
|
||||
keyword = keyword:lower()
|
||||
-- loops over custom commands
|
||||
@@ -354,15 +392,25 @@ end
|
||||
-- Functions that help with parsing
|
||||
-- @section parse
|
||||
|
||||
--- Adds a parse function which can be called by name rather than callback (used in add_param)
|
||||
-- nb: this is not needed as you can use the callback directly this just allows it to be called by name
|
||||
-- @tparam string name the name of the parse, should be the type like player or player_alive, must be unique
|
||||
-- @tparam function callback the callback that is ran to parse the input
|
||||
-- parse param - input: string - the input given by the user for this param
|
||||
-- parse param - player: LuaPlayer - the player who is using the command
|
||||
-- parse param - reject: function(error_message) - use this function to send a error to the user and fail running
|
||||
-- parse return - the value that will be passed to the command callback, must not be nil and if reject then command is not run
|
||||
-- @treturn boolean was the parse added will be false if the name is already used
|
||||
--[[-- Adds a parse function which can be called by name (used in add_param)
|
||||
nb: this is not required as you can use the callback directly this just allows it to be called by name
|
||||
@tparam string name the name of the parse, should be the type like player or player_alive, must be unique
|
||||
@tparam function callback the callback that is ran to parse the input
|
||||
@treturn boolean was the parse added will be false if the name is already used
|
||||
|
||||
@usage-- Adding a parse to validate ints in a given range
|
||||
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
|
||||
-- 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 rather than a string, thus the param is now the correct type
|
||||
return rtn
|
||||
end
|
||||
end)
|
||||
|
||||
]]
|
||||
function Commands.add_parse(name,callback)
|
||||
if Commands.parse_functions[name] then
|
||||
return false
|
||||
@@ -372,18 +420,28 @@ function Commands.add_parse(name,callback)
|
||||
end
|
||||
end
|
||||
|
||||
--- Removes a parse function, see add_parse for adding them
|
||||
-- @tparam string name the name of the parse to remove
|
||||
--[[-- Removes a parse function, see add_parse for adding them
|
||||
@tparam string name the name of the parse to remove
|
||||
|
||||
@usage-- Removing a parse
|
||||
Commands.remove_parse('number-range-int')
|
||||
|
||||
]]
|
||||
function Commands.remove_parse(name)
|
||||
Commands.parse_functions[name] = nil
|
||||
end
|
||||
|
||||
--- Intended to be used within other parse functions, runs a parse and returns success and new value
|
||||
-- @tparam string name the name of the parse to call, must be registered and cant be a function
|
||||
-- @tparam string input string the input to pass to the parse, will always be a but might not be the original input
|
||||
-- @tparam LuaPlayer player the player that is calling using the command
|
||||
-- @tparam function reject the reject function that was passed by the command hander
|
||||
-- @treturn any the new value for the input, may be nil, if nil then either there was an error or input was nil
|
||||
--[[-- Intended to be used within other parse functions, runs a parse and returns success and new value
|
||||
@tparam string name the name of the parse to call, must be registered parse
|
||||
@tparam string input string the input to pass to the parse, must be a string but not necessarily the original input
|
||||
@tparam LuaPlayer player the player that is using the command
|
||||
@tparam function reject the reject function that was passed by the command hander
|
||||
@treturn any the new value for the input, may be nil, if nil then either there was an error or input was nil
|
||||
|
||||
@usage-- Parsing a int in a given range
|
||||
local parsed_input = Commands.parse('number-range-int', '7', player, reject, 1, 10) -- valid range 1 to 10
|
||||
|
||||
]]
|
||||
function Commands.parse(name,input,player,reject,...)
|
||||
if not Commands.parse_functions[name] then return end
|
||||
local success,rtn = pcall(Commands.parse_functions[name],input,player,reject,...)
|
||||
@@ -397,10 +455,16 @@ end
|
||||
-- Functions that create a new command
|
||||
-- @section creation
|
||||
|
||||
--- Creates a new command object to added details to, note this does not register the command to the game
|
||||
-- @tparam string name the name of the command to be created
|
||||
-- @tparam string help the help message for the command
|
||||
-- @treturn Commands._prototype this will be used with other functions to generate the command functions
|
||||
--[[-- Creates a new command object to added details to, note this does not register the command to the game api
|
||||
@tparam string name the name of the command to be created
|
||||
@tparam string help the help message for the command
|
||||
@treturn Commands._prototype this will be used with other functions to generate the command functions
|
||||
|
||||
@usage-- Define a new command
|
||||
local command =
|
||||
Commands.new_command('repeat-name', 'Will repeat you name a number of times in chat.')
|
||||
|
||||
]]
|
||||
function Commands.new_command(name,help)
|
||||
local command = setmetatable({
|
||||
name=name,
|
||||
@@ -419,16 +483,23 @@ function Commands.new_command(name,help)
|
||||
return command
|
||||
end
|
||||
|
||||
--- Adds a new param to the command this will be displayed in the help and used to parse the input
|
||||
-- @tparam string name the name of the new param that is being added to the command
|
||||
-- @tparam[opt=false] boolean optional is this param required for this command, these must be after all required params
|
||||
-- @tparam[opt=pass function through] ?string|function parse this function will take the input and return a new (or same) value
|
||||
-- @param[opt] ... extra args you want to pass to the parse function; for example if the parse is general use
|
||||
-- parse param - input: string - the input given by the user for this param
|
||||
-- parse param - player: LuaPlayer - the player who is using the command
|
||||
-- parse param - reject: function(error_message) - use this function to send a error to the user and fail running
|
||||
-- parse return - the value that will be passed to the command callback, must not be nil and if reject then command is not run
|
||||
-- @treturn Commands._prototype pass through to allow more functions to be called
|
||||
--[[-- Adds a new param to the command this will be displayed in the help and used to parse the input
|
||||
@tparam string name the name of the new param that is being added to the command
|
||||
@tparam[opt=false] boolean optional is this param required for this command, these must be after all required params
|
||||
@tparam[opt=pass function through] ?string|function parse this function will take the input and return a new (or same) value
|
||||
@param[opt] ... extra args you want to pass to the parse function; for example if the parse is general use
|
||||
@treturn Commands._prototype pass through to allow more functions to be called
|
||||
|
||||
@usage-- Adding a param which has an parse defined
|
||||
command:add_param('repeat-count', false, 'number-range-int', 1, 5)
|
||||
|
||||
@usage-- Adding a param which has a custom parse, see Commands.add_parse for details
|
||||
command:add_param('smiley', true, function(input, player, reject)
|
||||
if not input then return end
|
||||
return input:lower() == 'true' or input:lower() == 'yes' or false
|
||||
end)
|
||||
|
||||
]]
|
||||
function Commands._prototype:add_param(name,optional,parse,...)
|
||||
local parse_args = {...}
|
||||
if type(optional) ~= 'boolean' then
|
||||
@@ -449,10 +520,20 @@ function Commands._prototype:add_param(name,optional,parse,...)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Adds default values to params only matters if the param is optional, if default value is a function it is called with param player
|
||||
-- @tparam table defaults table a 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
|
||||
--[[-- Add default values to params, only as an effect if the param is optional, if default value is a function it is called with acting player
|
||||
@tparam table defaults table which is keyed by the name of the param and the value is the default value
|
||||
@treturn Commands._prototype pass through to allow more functions to be called
|
||||
|
||||
@usage-- Adding default values
|
||||
command:set_defaults{
|
||||
smiley = false,
|
||||
-- not in example just used to show arguments given
|
||||
player_name = function(player)
|
||||
return player.name
|
||||
end
|
||||
}
|
||||
|
||||
]]
|
||||
function Commands._prototype:set_defaults(defaults)
|
||||
for name,value in pairs(defaults) do
|
||||
if self.params[name] then
|
||||
@@ -462,26 +543,32 @@ function Commands._prototype:set_defaults(defaults)
|
||||
return self
|
||||
end
|
||||
|
||||
--- 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 string name the name of the tag to be added; used to keep flags separate
|
||||
-- @tparam any value 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
|
||||
--[[-- 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 string name the name of the tag to be added, set to true if no value is given
|
||||
@tparam[opt=true] any value the tag that you want can be anything that the authenticators are expecting
|
||||
@treturn Commands._prototype pass through to allow more functions to be called
|
||||
|
||||
@usage-- Setting a custom flag
|
||||
command:set_flag('admin_only', true)
|
||||
|
||||
@usage-- When value is true it does not need to be given
|
||||
command:set_flag('admin_only')
|
||||
|
||||
]]
|
||||
function Commands._prototype:set_flag(name,value)
|
||||
if not value then
|
||||
-- value not given so name is the value
|
||||
table.insert(self.flags,name)
|
||||
else
|
||||
-- name is given so its key: value
|
||||
self.flags[name] = value
|
||||
end
|
||||
value = value or true
|
||||
self.flags[name] = value
|
||||
return self
|
||||
end
|
||||
|
||||
--- Adds an alias or multiple that will also be registered with the same callback, eg /teleport can be /tp with both working
|
||||
-- @usage command:add_alias('aliasOne','aliasTwo','etc')
|
||||
-- @tparam string any ... amount of aliases that you want this command to be callable with
|
||||
-- @treturn Commands._prototype pass through to allow more functions to be called
|
||||
--[[-- Adds an alias, or multiple, that will also be registered with the same callback, eg /teleport can be used as /tp
|
||||
@tparam string any ... amount of aliases that you want this command to be callable with
|
||||
@treturn Commands._prototype pass through to allow more functions to be called
|
||||
|
||||
@usage-- Added multiple aliases to a command
|
||||
command:add_alias('name', 'rname')
|
||||
|
||||
]]
|
||||
function Commands._prototype:add_alias(...)
|
||||
for _,alias in pairs({...}) do
|
||||
table.insert(self.aliases,alias)
|
||||
@@ -490,21 +577,35 @@ function Commands._prototype:add_alias(...)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Enables auto concatenation of any params on the end so quotes are not needed for last param
|
||||
-- nb: this will disable max param checking as they will be concatenated onto the end of that last param
|
||||
-- this can be useful for reasons or longs text, can only have one per command
|
||||
-- @treturn Commands._prototype pass through to allow more functions to be called
|
||||
--[[-- Enables auto concatenation of any params on the end so quotes are not needed for last param
|
||||
nb: this will disable max param checking as they will be concatenated onto the end of that last param
|
||||
this can be useful for reasons or longs text, can only have one per command
|
||||
@treturn Commands._prototype pass through to allow more functions to be called
|
||||
|
||||
@usage-- Enable auto concat for a command
|
||||
command:enable_auto_concat()
|
||||
|
||||
]]
|
||||
function Commands._prototype:enable_auto_concat()
|
||||
self.auto_concat = true
|
||||
return self
|
||||
end
|
||||
|
||||
--- Adds the callback to the command and registers all aliases, params and help message with the game
|
||||
-- nb: this must be the last function ran on the command and must be done for the command to work
|
||||
-- @tparam function callback the callback for the command, will receive the player running command, and params added with add_param
|
||||
-- callback param - player: LuaPlayer - the player who used the command
|
||||
-- callback param - ... - any params which were registered with add_param in the order they where registered
|
||||
-- callback param - raw: string - the raw input from the user, comes after every param added with add_param
|
||||
--[[-- Adds the callback to the command and registers all aliases, params and help message with the game api
|
||||
nb: this must be the last function ran on the command and must be done for the command to work
|
||||
@tparam function callback the callback for the command, will receive the player running command, and params added with add_param
|
||||
|
||||
@usage-- Registering your command to the game api
|
||||
command:register(function(player, repeat_count, smiley, _)
|
||||
local msg = ') '..player.name
|
||||
if smiley then msg = ':'..msg end
|
||||
|
||||
for 1 = 1,repeat_count do
|
||||
Command.print(1..msg)
|
||||
end
|
||||
end)
|
||||
|
||||
]]
|
||||
function Commands._prototype:register(callback)
|
||||
-- generates a description to be used
|
||||
self.callback = callback
|
||||
@@ -538,13 +639,16 @@ end
|
||||
-- Functions that indicate status
|
||||
-- @section status
|
||||
|
||||
--- Sends an error message to the player and returns a constant to return to command handler to exit execution
|
||||
-- nb: this is for non fatal errors meaning there is no log of this event
|
||||
-- nb: if reject is giving as a param to the callback use that instead
|
||||
-- @usage return Commands.error()
|
||||
-- @tparam[opt] string error_message an optional error message that can be sent to the user
|
||||
-- @tparam[opt] string play_sound the sound to play for the error
|
||||
-- @treturn Commands.defines.error return this to command handler to exit execution
|
||||
--[[-- Sends an error message to the player and when returned will stop exicution of the command
|
||||
nb: this is for non fatal errors meaning there is no log of this event, use during register callback
|
||||
@tparam[opt=''] string error_message an optional error message that can be sent to the user
|
||||
@tparam[opt=utility/wire_pickup] string play_sound the sound to play for the error
|
||||
@treturn Commands.defines.error return this to command handler to exit execution
|
||||
|
||||
@usage-- Send an error message to the player, and stops further code running
|
||||
return Commands.error('The player you selected is offline')
|
||||
|
||||
]]
|
||||
function Commands.error(error_message,play_sound)
|
||||
error_message = error_message or ''
|
||||
player_return({'expcore-commands.command-fail',error_message},'orange_red')
|
||||
@@ -555,12 +659,20 @@ function Commands.error(error_message,play_sound)
|
||||
return Commands.defines.error
|
||||
end
|
||||
|
||||
--- Sends an error to the player and logs the error, used with pcall within command handler please avoid direct use
|
||||
-- nb: use error(error_message) within your callback to trigger do not trigger directly as the handler may still continue
|
||||
-- @tparam boolean success the success value returned from pcall, or just false to trigger error
|
||||
-- @tparam string command_name the name of the command this is used within the log
|
||||
-- @tparam string error_message the error returned by pcall or some other error, this is logged and not returned to player
|
||||
-- @treturn boolean the opposite of success so true means to cancel execution, used internally
|
||||
--[[-- Sends an error to the player and logs the error, used with pcall within command handler please avoid direct use
|
||||
nb: use error(error_message) within your callback to trigger do not trigger directly as code exictuion may still continue
|
||||
@tparam boolean success the success value returned from pcall, or just false to trigger error
|
||||
@tparam string command_name the name of the command this is used within the log
|
||||
@tparam string error_message the error returned by pcall or some other error, this is logged and not returned to player
|
||||
@treturn boolean the opposite of success so true means to cancel execution, used internally
|
||||
|
||||
@usage-- Used in the command system to log handler errors
|
||||
local success, err = pcall(command_data.callback, player, unpack(params))
|
||||
if Commands.internal_error(success, command_data.name, err) then
|
||||
return command_log(player, command_data, 'Internal Error: Command Callback Fail', raw_params, command_event.parameter, err)
|
||||
end
|
||||
|
||||
]]
|
||||
function Commands.internal_error(success,command_name,error_message)
|
||||
if not success then
|
||||
Commands.error('Internal Error, Please contact an admin','utility/cannot_build')
|
||||
@@ -569,16 +681,34 @@ function Commands.internal_error(success,command_name,error_message)
|
||||
return not success
|
||||
end
|
||||
|
||||
--- Sends a value to the player, followed by a command complete message
|
||||
-- nb: either return a value from your callback to trigger or return the return of this to prevent two messages
|
||||
-- @tparam[opt] any value 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
|
||||
--[[-- Sends a value to the player, followed by a command complete message
|
||||
nb: returning any value from your callback will trigger this function, return this function to prevent duplicate messages
|
||||
@tparam[opt] any value 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
|
||||
|
||||
@usage-- Print a custom success message
|
||||
return Commands.success('Your message has been printed')
|
||||
|
||||
@usage-- Returning the value has the same result
|
||||
return 'Your message has been printed'
|
||||
|
||||
]]
|
||||
function Commands.success(value)
|
||||
if value ~= nil then player_return(value) end
|
||||
player_return({'expcore-commands.command-ran'},'cyan')
|
||||
return Commands.defines.success
|
||||
end
|
||||
|
||||
--[[-- Sends a value to the player, different to success as this does not signal the end of your command
|
||||
@function print
|
||||
@tparam any value the value that you want to return to the player
|
||||
@tparam table colour the colour of the message that the player sees
|
||||
|
||||
@usage-- Output a message to the player
|
||||
Commands.print('Your command is in progress')
|
||||
|
||||
]]
|
||||
|
||||
-- logs command usage to file
|
||||
local function command_log(player,command,comment,params,raw,details)
|
||||
local player_name = player and player.name or '<Server>'
|
||||
@@ -594,6 +724,7 @@ end
|
||||
|
||||
--- Main event function that is ran for all commands, used internally please avoid direct use
|
||||
-- @tparam table command_event passed directly from command event from the add_command function
|
||||
-- @usage Commands.run_command(event)
|
||||
function Commands.run_command(command_event)
|
||||
local command_data = Commands.commands[command_event.name]
|
||||
-- player can be nil when it is the server
|
||||
|
||||
@@ -1,46 +1,59 @@
|
||||
--[[-- Core Module - Common Library
|
||||
- Adds some commonly used functions used in many modules
|
||||
@core Common-Library
|
||||
@alias Common
|
||||
--[[-- Core Module - Common
|
||||
- Adds some commonly used functions used in many modules
|
||||
@core Common
|
||||
@alias Common
|
||||
]]
|
||||
|
||||
local Colours = require 'utils.color_presets' --- @dep utils.color_presets
|
||||
local Game = require 'utils.game' --- @dep utils.game
|
||||
local Util = require 'util' --- @dep util
|
||||
require 'overrides.table'
|
||||
require 'overrides.math'
|
||||
|
||||
local Common = {}
|
||||
|
||||
--- Type Checking.
|
||||
-- @section typeCheck
|
||||
|
||||
--- Asserts the argument is of type test_type
|
||||
-- @usage type_check('foo','string') -- return true
|
||||
-- @usage type_check('foo') -- return false
|
||||
-- @tparam any value the value to be tested
|
||||
-- @tparam[opt=nil] string test_type the type to test for if not given then it tests for nil
|
||||
-- @treturn boolean is v of type test_type
|
||||
--[[-- Asserts the argument is of type test_type
|
||||
@tparam any value the value to be tested
|
||||
@tparam[opt=nil] string test_type the type to test for if not given then it tests for nil
|
||||
@treturn boolean is v of type test_type
|
||||
|
||||
@usage-- Check for a string value
|
||||
local is_string = type_check(value, 'string')
|
||||
|
||||
@usage-- Check for a nil value
|
||||
local is_nil = type_check(value)
|
||||
|
||||
]]
|
||||
function Common.type_check(value, test_type)
|
||||
return test_type and value and type(value) == test_type or not test_type and not value or false
|
||||
end
|
||||
|
||||
--- Raises an error if the value is of the wrong type
|
||||
-- @usage type_error('foo','number','Value must be a number') -- will raise error "Value must be a number"
|
||||
-- @tparam any value the value that you want to test the type of
|
||||
-- @tparam string test_type the type that the value should be
|
||||
-- @tparam string error_message the error message that is returned
|
||||
-- @tparam number level the level to call the error on (level = 1 means the caller)
|
||||
-- @treturn boolean true if no error was called
|
||||
--[[-- Raises an error if the value is of the wrong type
|
||||
@tparam any value the value that you want to test the type of
|
||||
@tparam string test_type the type that the value should be
|
||||
@tparam string error_message the error message that is returned
|
||||
@tparam number level the level to call the error on (level = 1 is the caller)
|
||||
@treturn boolean true if no error was called
|
||||
|
||||
@usage-- Raise error if value is not a number
|
||||
type_error(value, 'number', 'Value must be a number')
|
||||
|
||||
]]
|
||||
function Common.type_error(value, test_type, error_message, level)
|
||||
level = level and level+1 or 2
|
||||
return Common.type_check(value,test_type) or error(error_message,level)
|
||||
end
|
||||
|
||||
--- Asserts the argument is one of type test_types
|
||||
-- @param value the variable to check
|
||||
-- @param test_types the type as a table of strings
|
||||
-- @treturn boolean true if value is one of test_types
|
||||
--[[-- Asserts the argument is one of type test_types
|
||||
@param value the variable to check
|
||||
@param test_types the type as a table of strings
|
||||
@treturn boolean true if value is one of test_types
|
||||
|
||||
@usage-- Check for a string or table
|
||||
local is_string_or_table = multi_type_check(value, {'string','table'})
|
||||
|
||||
]]
|
||||
function Common.multi_type_check(value, test_types)
|
||||
local vtype = type(value)
|
||||
for _, arg_type in ipairs(test_types) do
|
||||
@@ -51,45 +64,73 @@ function Common.multi_type_check(value, test_types)
|
||||
return false
|
||||
end
|
||||
|
||||
--- Raises an error if the value is of the wrong type
|
||||
-- @usage multi_type_error('foo',{'string','table'},'Value must be a string or table') -- will raise error "Value must be a string or table"
|
||||
-- @tparam any value the value that you want to test the type of
|
||||
-- @tparam table test_types the type as a table of strings
|
||||
-- @tparam string error_message the error message that is returned
|
||||
-- @tparam number level the level to call the error on (level = 1 means the caller)
|
||||
-- @treturn boolean true if no error was called
|
||||
--[[-- Raises an error if the value is of the wrong type
|
||||
@tparam any value the value that you want to test the type of
|
||||
@tparam table test_types the type as a table of strings
|
||||
@tparam string error_message the error message that is returned
|
||||
@tparam number level the level to call the error on (level = 1 is the caller)
|
||||
@treturn boolean true if no error was called
|
||||
|
||||
@usage-- Raise error if value is not a string or table
|
||||
multi_type_error('foo', {'string','table'}, 'Value must be a string or table')
|
||||
|
||||
]]
|
||||
function Common.multi_type_error(value, test_types, error_message, level)
|
||||
level = level and level+1 or 2
|
||||
return Common.mult_type_check(value, test_types) or error(error_message,level)
|
||||
end
|
||||
|
||||
--- Raises an error when the value is the incorrect type, uses a consistent error message format
|
||||
-- @usage validate_argument_type('foo','number','repeat_count',2) -- will raise error "Bad argument #02 to "<anon>"; "repeat_count" is of type string expected number"
|
||||
-- @tparam any value the value that you want to test the type of
|
||||
-- @tparam string test_type the type that the value should be
|
||||
-- @tparam string param_name the name of the param
|
||||
-- @tparam number param_number the number param it is
|
||||
-- @treturn boolean true if no error was raised
|
||||
function Common.validate_argument_type(value, test_type, param_name, param_number)
|
||||
--[[-- Raises an error when the value is the incorrect type, uses a consistent error message format
|
||||
@tparam any value the value that you want to test the type of
|
||||
@tparam string test_type the type that the value should be
|
||||
@tparam number param_number the number param it is
|
||||
@tparam[opt] string param_name the name of the param
|
||||
@treturn boolean true if no error was raised
|
||||
|
||||
@usage-- Output: "Bad argument #2 to "<anon>"; argument is of type string expected number"
|
||||
validate_argument_type(value, 'number', 2)
|
||||
|
||||
@usage-- Output: "Bad argument #2 to "<anon>"; "repeat_count" is of type string expected number"
|
||||
validate_argument_type(value, 'number', 2, 'repeat_count')
|
||||
|
||||
]]
|
||||
function Common.validate_argument_type(value, test_type, param_number, param_name)
|
||||
if not Common.test_type(value,test_type) then
|
||||
local function_name = debug.getinfo(2,'n').name or '<anon>'
|
||||
local error_message = string.format('Bad argument #%2d to %q; %q is of type %s expected %s', param_number, function_name, param_name, type(value), test_type)
|
||||
local error_message
|
||||
if param_name then
|
||||
error_message = string.format('Bad argument #%d to %q; %q is of type %s expected %s', param_number, function_name, param_name, type(value), test_type)
|
||||
else
|
||||
error_message = string.format('Bad argument #%d to %q; argument is of type %s expected %s', param_number, function_name, type(value), test_type)
|
||||
end
|
||||
return error(error_message,3)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Raises an error when the value is the incorrect type, uses a consistent error message format
|
||||
-- @usage validate_argument_type('foo',{'string','table'},'repeat_count',2) -- will raise error "Bad argument #02 to "<anon>"; "repeat_count" is of type string expected string or table"
|
||||
-- @tparam any value the value that you want to test the type of
|
||||
-- @tparam string test_types the types that the value should be
|
||||
-- @tparam string param_name the name of the param
|
||||
-- @tparam number param_number the number param it is
|
||||
-- @treturn boolean true if no error was raised
|
||||
function Common.validate_argument_multi_type(value, test_types, param_name, param_number)
|
||||
--[[-- Raises an error when the value is the incorrect type, uses a consistent error message format
|
||||
@tparam any value the value that you want to test the type of
|
||||
@tparam string test_types the types that the value should be
|
||||
@tparam number param_number the number param it is
|
||||
@tparam[opt] string param_name the name of the param
|
||||
@treturn boolean true if no error was raised
|
||||
|
||||
@usage-- Output: "Bad argument #2 to "<anon>"; argument is of type number expected string or table"
|
||||
validate_argument_type(value, {'string','table'}, 2)
|
||||
|
||||
@usage-- Output: "Bad argument #2 to "<anon>"; "player" is of type number expected string or table"
|
||||
validate_argument_type(value, {'string','table'}, 2, 'player')
|
||||
|
||||
]]
|
||||
function Common.validate_argument_multi_type(value, test_types, param_number, param_name)
|
||||
if not Common.multi_type_check(value,test_types) then
|
||||
local function_name = debug.getinfo(2,'n').name or '<anon>'
|
||||
local error_message = string.format('Bad argument #%2d to %q; %q is of type %s expected %s', param_number, function_name, param_name, type(value), table.concat(test_types,' or '))
|
||||
local error_message
|
||||
if param_name then
|
||||
error_message = string.format('Bad argument #%2d to %q; %q is of type %s expected %s', param_number, function_name, param_name, type(value), table.concat(test_types,' or '))
|
||||
else
|
||||
error_message = string.format('Bad argument #%2d to %q; argument is of type %s expected %s', param_number, function_name, type(value), table.concat(test_types,' or '))
|
||||
end
|
||||
return error(error_message,3)
|
||||
end
|
||||
return true
|
||||
@@ -116,10 +157,15 @@ end
|
||||
--- Value Returns.
|
||||
-- @section valueReturns
|
||||
|
||||
--- Tests if a string contains a given substring.
|
||||
-- @tparam string s the string to check for the substring
|
||||
-- @tparam string contains the substring to test for
|
||||
-- @treturn boolean true if the substring was found in the string
|
||||
--[[-- Tests if a string contains a given substring.
|
||||
@tparam string s the string to check for the substring
|
||||
@tparam string contains the substring to test for
|
||||
@treturn boolean true if the substring was found in the string
|
||||
|
||||
@usage-- Test if a string contains a sub string
|
||||
local found = string_contains(str, 'foo')
|
||||
|
||||
]]
|
||||
function Common.string_contains(s, contains)
|
||||
return s and string.find(s, contains) ~= nil
|
||||
end
|
||||
@@ -127,82 +173,104 @@ end
|
||||
--[[-- Used to resolve a value that could also be a function returning that value
|
||||
@tparam any value the value which you want to test is not nil and if it is a function then call the function
|
||||
@treturn any the value given or returned by value if it is a function
|
||||
|
||||
@usage-- Default value handling
|
||||
-- if default value is not a function then it is returned
|
||||
-- if it is a function then it is called with the first argument being self
|
||||
local value = Common.resolve_value(self.defaut_value,self)
|
||||
-- if default value is a function then it is called with the first argument being self
|
||||
local value = Common.resolve_value(self.defaut_value, self)
|
||||
|
||||
]]
|
||||
function Common.resolve_value(value,...)
|
||||
if value then
|
||||
if type(value) == 'function' then
|
||||
return value(...)
|
||||
else
|
||||
return value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns a valid string with the name of the actor of a command.
|
||||
-- @treturns string the name of the current actor
|
||||
function Common.get_actor()
|
||||
return game.player and game.player.name or '<server>'
|
||||
return value and type(value) == 'function' and value(...) or value
|
||||
end
|
||||
|
||||
--- Converts a varible into its boolean value, nil and false return false
|
||||
-- @treturn boolean the boolean form of the varible
|
||||
-- @usage local bool = cast_bool(var)
|
||||
function Common.cast_bool(var)
|
||||
return var and true or false
|
||||
end
|
||||
|
||||
--- Returns either the second or third argument based on the first argument
|
||||
-- @usage ternary(input_string == 'test', 'Input is test', 'Input is not test')
|
||||
function Common.ternary(c, t, f)
|
||||
return c and t or f
|
||||
end
|
||||
|
||||
--- Returns a string for a number with comma seperators
|
||||
-- @usage comma_value(input_number)
|
||||
function Common.comma_value(n) -- credit http://richard.warburton.it
|
||||
local left, num, right = string.match(n, '^([^%d]*%d)(%d*)(.-)$')
|
||||
return left .. (num:reverse():gsub('(%d%d%d)', '%1,'):reverse()) .. right
|
||||
end
|
||||
|
||||
--- Sets a table element to value while also returning value.
|
||||
-- @param tbl table to change the element of
|
||||
-- @param key string
|
||||
-- @param value nil|boolean|number|string|table to set the element to
|
||||
-- @return value
|
||||
--[[-- Sets a table element to value while also returning value.
|
||||
@tparam table tbl to change the element of
|
||||
@tparam string key the key to set the value of
|
||||
@tparam any value the value to set the key as
|
||||
@treturn any the value that was set
|
||||
|
||||
@usage-- Set and return value
|
||||
local value = set_and_return(players, player.name, player.online_time)
|
||||
|
||||
]]
|
||||
function Common.set_and_return(tbl, key, value)
|
||||
tbl[key] = value
|
||||
return value
|
||||
end
|
||||
|
||||
--- Writes a table object to a file in json format
|
||||
-- @tparam string path the path of the file to write include / to use dir
|
||||
-- @tparam table tbl the table that will be converted to a json string and wrote to file
|
||||
--[[-- Writes a table object to a file in json format
|
||||
@tparam string path the path of the file to write include / to use dir
|
||||
@tparam table tbl the table that will be converted to a json string and wrote to file
|
||||
|
||||
@usage-- Write a lua table as a json to script-outpt/dump
|
||||
write_json('dump', tbl)
|
||||
|
||||
]]
|
||||
function Common.write_json(path,tbl)
|
||||
game.write_file(path,game.table_to_json(tbl)..'\n',true,0)
|
||||
end
|
||||
|
||||
--- Calls a require that will not error if the file is not found
|
||||
-- @usage local file = opt_require('file.not.present') -- will not cause any error
|
||||
-- @tparam string path the path that you want to require
|
||||
-- @return the returns from that file or nil, error if not loaded
|
||||
--[[-- Calls a require that will not error if the file is not found
|
||||
@usage local file = opt_require('file.not.present') -- will not cause any error
|
||||
@tparam string path the path that you want to require
|
||||
@return the returns from that file or nil, error if not loaded
|
||||
|
||||
@usage-- Require a file without causing errors, for when a file might not exist
|
||||
local Module = opt_require 'expcore.common'
|
||||
|
||||
]]
|
||||
function Common.opt_require(path)
|
||||
local success, rtn = pcall(require,path)
|
||||
if success then return rtn
|
||||
else return nil,rtn end
|
||||
end
|
||||
|
||||
--- Returns a desync safe file path for the current file
|
||||
-- @tparam[opt=0] number offset the offset in the stack to get, 0 is current file
|
||||
-- @treturn string the file path
|
||||
--[[-- Returns a desync safe file path for the current file
|
||||
@tparam[opt=0] number offset the offset in the stack to get, 0 is current file
|
||||
@treturn string the file path
|
||||
|
||||
@usage-- Get the current file path
|
||||
local file_path = get_file_path()
|
||||
|
||||
]]
|
||||
function Common.get_file_path(offset)
|
||||
offset = offset or 0
|
||||
return debug.getinfo(offset+2, 'S').source:match('^.+/currently%-playing/(.+)$'):sub(1, -5)
|
||||
end
|
||||
|
||||
--- Converts a table to an enum
|
||||
-- @tparam table tbl table the that will be converted
|
||||
-- @treturn table the new table that acts like an enum
|
||||
--[[-- Converts a table to an enum
|
||||
@tparam table tbl table the that will be converted
|
||||
@treturn table the new table that acts like an enum
|
||||
|
||||
@usage-- Make an enum
|
||||
local colors = enum{
|
||||
'red',
|
||||
'green',
|
||||
'blue'
|
||||
}
|
||||
|
||||
]]
|
||||
function Common.enum(tbl)
|
||||
local rtn = {}
|
||||
for k,v in pairs(tbl) do
|
||||
@@ -221,12 +289,23 @@ function Common.enum(tbl)
|
||||
return rtn
|
||||
end
|
||||
|
||||
--- Returns the closest match to the input
|
||||
-- @tparam table options table a of options for the auto complete
|
||||
-- @tparam string input string the input that will be completed
|
||||
-- @tparam[opt=false] boolean use_key when true the keys of options will be used as the options
|
||||
-- @tparam[opt=false] boolean rtn_key when true the the key will be returned rather than the value
|
||||
-- @return the list item found that matches the input
|
||||
--[[-- Returns the closest match to the input
|
||||
@tparam table options table a of options for the auto complete
|
||||
@tparam string input string the input that will be completed
|
||||
@tparam[opt=false] boolean use_key when true the keys of options will be used as the options
|
||||
@tparam[opt=false] boolean rtn_key when true the the key will be returned rather than the value
|
||||
@return the list item found that matches the input
|
||||
|
||||
@usage-- Get the element that includes "foo"
|
||||
local value = auto_complete(tbl, "foo")
|
||||
|
||||
@usage-- Get the element with a key that includes "foo"
|
||||
local value = auto_complete(tbl, "foo", true)
|
||||
|
||||
@usage-- Get the key with that includes "foo"
|
||||
local key = auto_complete(tbl, "foo", true, true)
|
||||
|
||||
]]
|
||||
function Common.auto_complete(options,input,use_key,rtn_key)
|
||||
local rtn = {}
|
||||
if type(input) ~= 'string' then return end
|
||||
@@ -234,40 +313,65 @@ function Common.auto_complete(options,input,use_key,rtn_key)
|
||||
for key,value in pairs(options) do
|
||||
local check = use_key and key or value
|
||||
if Common.string_contains(string.lower(check),input) then
|
||||
local result = rtn_key and key or value
|
||||
table.insert(rtn,result)
|
||||
return rtn_key and key or value
|
||||
end
|
||||
end
|
||||
return rtn[1]
|
||||
end
|
||||
|
||||
--- Formating.
|
||||
-- @section formating
|
||||
|
||||
--- Returns a message with valid chat tags to change its colour
|
||||
-- @tparam string message the message that will be in the output
|
||||
-- @tparam table color a color which contains r,g,b as its keys
|
||||
-- @treturn string the message with the color tags included
|
||||
--[[-- Returns a valid string with the name of the actor of a command.
|
||||
@tparam string player_name the name of the player to use rather than server, used only if game.player is nil
|
||||
@treturn string the name of the current actor
|
||||
|
||||
@usage-- Get the current actor
|
||||
local player_name = get_actor()
|
||||
|
||||
]]
|
||||
function Common.get_actor(player_name)
|
||||
return game.player and game.player.name or player_name or '<server>'
|
||||
end
|
||||
|
||||
--[[-- Returns a message with valid chat tags to change its colour
|
||||
@tparam string message the message that will be in the output
|
||||
@tparam table color a color which contains r,g,b as its keys
|
||||
@treturn string the message with the color tags included
|
||||
|
||||
@usage-- Use factorio tags to color a chat message
|
||||
local message = format_chat_colour('Hello, World!', { r=355, g=100, b=100 })
|
||||
|
||||
]]
|
||||
function Common.format_chat_colour(message,color)
|
||||
color = color or Colours.white
|
||||
local color_tag = '[color='..math.round(color.r,3)..','..math.round(color.g,3)..','..math.round(color.b,3)..']'
|
||||
return string.format('%s%s[/color]',color_tag,message)
|
||||
end
|
||||
|
||||
--- Returns a message with valid chat tags to change its colour, using localization
|
||||
-- @tparam ?string|table message the message that will be in the output
|
||||
-- @tparam table color a color which contains r,g,b as its keys
|
||||
-- @treturn table the message with the color tags included
|
||||
--[[-- Returns a message with valid chat tags to change its colour, using localization
|
||||
@tparam ?string|table message the message that will be in the output
|
||||
@tparam table color a color which contains r,g,b as its keys
|
||||
@treturn table the message with the color tags included
|
||||
|
||||
@usage-- Use factorio tags and locale strings to color a chat message
|
||||
local message = format_chat_colour_localized('Hello, World!', { r=355, g=100, b=100 })
|
||||
|
||||
]]
|
||||
function Common.format_chat_colour_localized(message,color)
|
||||
color = color or Colours.white
|
||||
color = math.round(color.r,3)..','..math.round(color.g,3)..','..math.round(color.b,3)
|
||||
return {'color-tag',color,message}
|
||||
end
|
||||
|
||||
--- Returns the players name in the players color
|
||||
-- @tparam LuaPlayer player the player to use the name and color of
|
||||
-- @tparam[opt=false] boolean raw_string when true a is returned rather than a localized string
|
||||
-- @treturn table the players name with tags for the players color
|
||||
--[[-- Returns the players name in the players color
|
||||
@tparam LuaPlayer player the player to use the name and color of
|
||||
@tparam[opt=false] boolean raw_string when true a string is returned rather than a localized string
|
||||
@treturn table the players name with tags for the players color
|
||||
|
||||
@usage-- Format a players name using the players color as a string
|
||||
local message = format_chat_player_name(game.player, true)
|
||||
|
||||
]]
|
||||
function Common.format_chat_player_name(player,raw_string)
|
||||
player = Game.get_player_from_any(player)
|
||||
local player_name = player and player.name or '<Server>'
|
||||
@@ -279,13 +383,21 @@ function Common.format_chat_player_name(player,raw_string)
|
||||
end
|
||||
end
|
||||
|
||||
--- Will return a value of any type to the player/server console, allows colour for in-game players
|
||||
-- @usage player_return('Hello, World!') -- returns 'Hello, World!' to game.player or server console
|
||||
-- @usage player_return('Hello, World!','green') -- returns 'Hello, World!' to game.player with colour green or server console
|
||||
-- @usage player_return('Hello, World!',nil,player) -- returns 'Hello, World!' to the given player
|
||||
-- @param value any value of any type that will be returned to the player or console
|
||||
-- @tparam[opt=defines.colour.white] ?defines.color|string colour the colour of the text for the player, ignored when printing to console
|
||||
-- @tparam[opt=game.player] LuaPlayer player the player that return will go to, if no game.player then returns to server
|
||||
--[[-- Will return a value of any type to the player/server console, allows colour for in-game players
|
||||
@tparam any value a value of any type that will be returned to the player or console
|
||||
@tparam[opt=defines.colour.white] ?defines.color|string colour the colour of the text for the player, ignored when printing to console
|
||||
@tparam[opt=game.player] LuaPlayer player the player that return will go to, if no game.player then returns to server
|
||||
|
||||
@usage-- Return a value to the current actor, rcon included
|
||||
player_return('Hello, World!')
|
||||
|
||||
@usage-- Return a value to the current actor, with color
|
||||
player_return('Hello, World!', 'green')
|
||||
|
||||
@usage-- Return to a player other than the current
|
||||
player_return('Hello, World!', nil, player)
|
||||
|
||||
]]
|
||||
function Common.player_return(value,colour,player)
|
||||
colour = Common.type_check(colour,'table') and colour or Colours[colour] ~= Colours.white and Colours[colour] or Colours.white
|
||||
player = player or game.player
|
||||
@@ -320,14 +432,26 @@ function Common.player_return(value,colour,player)
|
||||
else rcon.print(returnAsString) end
|
||||
end
|
||||
|
||||
--- Formats tick into a clean format, denominations from highest to lowest
|
||||
-- long will use words rather than letters
|
||||
--[[-- Formats tick into a clean format, denominations from highest to lowest
|
||||
-- time will use : separates
|
||||
-- string will return a string not a locale string
|
||||
-- when a denomination is false it will overflow into the next one
|
||||
-- @tparam number ticks the number of ticks that represents a time
|
||||
-- @tparam table options table a of options to use for the format
|
||||
-- @treturn string a locale string that can be used
|
||||
@tparam number ticks the number of ticks that represents a time
|
||||
@tparam table options table a of options to use for the format
|
||||
@treturn string a locale string that can be used
|
||||
|
||||
@usage-- Output: "0h 5m"
|
||||
local time = format_time(18000, { hours=true, minutes=true, string=true })
|
||||
|
||||
@usage-- Output: "0 hours and 5 minutes"
|
||||
local time = format_time(18000, { hours=true, minutes=true, string=true, long=true })
|
||||
|
||||
@usage-- Output: "00:05:00"
|
||||
local time = format_time(18000, { hours=true, minutes=true, seconds=true, string=true })
|
||||
|
||||
@usage-- Output: "--:--:--"
|
||||
local time = format_time(18000, { hours=true, minutes=true, seconds=true, string=true, null=true })
|
||||
|
||||
]]
|
||||
function Common.format_time(ticks,options)
|
||||
-- Sets up the options
|
||||
options = options or {
|
||||
@@ -415,12 +539,18 @@ end
|
||||
--- Factorio.
|
||||
-- @section factorio
|
||||
|
||||
--- Moves items to the position and stores them in the closest entity of the type given
|
||||
-- @tparam table items items which are to be added to the chests, ['name']=count
|
||||
-- @tparam[opt=navies] LuaSurface surface the surface that the items will be moved to
|
||||
-- @tparam[opt={0,0}] table position the position that the items will be moved to {x=100,y=100}
|
||||
-- @tparam[opt=32] number radius the radius in which the items are allowed to be placed
|
||||
-- @tparam[opt=iron-chest] string chest_type the chest type that the items should be moved into
|
||||
--[[-- Moves items to the position and stores them in the closest entity of the type given
|
||||
@tparam table items items which are to be added to the chests, ['name']=count
|
||||
@tparam[opt=navies] LuaSurface surface the surface that the items will be moved to
|
||||
@tparam[opt={0,0}] table position the position that the items will be moved to {x=100,y=100}
|
||||
@tparam[opt=32] number radius the radius in which the items are allowed to be placed
|
||||
@tparam[opt=iron-chest] string chest_type the chest type that the items should be moved into
|
||||
@treturn LuaEntity the last chest that had items inserted into it
|
||||
|
||||
@usage-- Copy all the items in a players inventory and place them in chests at {0,0}
|
||||
move_items(game.player.get_main_inventory().get_contents())
|
||||
|
||||
]]
|
||||
function Common.move_items(items,surface,position,radius,chest_type)
|
||||
chest_type = chest_type or 'iron-chest'
|
||||
surface = surface or game.surfaces[1]
|
||||
@@ -466,14 +596,19 @@ function Common.move_items(items,surface,position,radius,chest_type)
|
||||
return last_chest
|
||||
end
|
||||
|
||||
--[[-- https://github.com/Refactorio/RedMew/blob/9184b2940f311d8c9c891e83429fc57ec7e0c4a2/map_gen/maps/diggy/debug.lua#L31
|
||||
Prints a colored value on a location.
|
||||
@param value between -1 and 1
|
||||
@param surface LuaSurface
|
||||
@param position Position {x, y}
|
||||
@param scale float
|
||||
@param offset float
|
||||
@param immutable bool if immutable, only set, never do a surface lookup, values never change
|
||||
--[[-- Prints a colored value on a location, color is based on the value.
|
||||
nb: src is below but the gradent has been edited
|
||||
https://github.com/Refactorio/RedMew/blob/9184b2940f311d8c9c891e83429fc57ec7e0c4a2/map_gen/maps/diggy/debug.lua#L31
|
||||
@tparam number value the value to show must be between -1 and 1, scale can be used to achive this
|
||||
@tparam LuaSurface surface the surface to palce the value on
|
||||
@tparam table position {x, y} the possition to palce the value at
|
||||
@tparam[opt=1] number scale how much to scale the colours by
|
||||
@tparam[opt=0] number offset the offset in the +x +y direction
|
||||
@tparam[opt=false] boolean immutable if immutable, only set, never do a surface lookup, values never change
|
||||
|
||||
@usage-- Place a 0 at {0,0}
|
||||
print_grid_value(0, game.player.surface, { x=0, y=0 })
|
||||
|
||||
]]
|
||||
function Common.print_grid_value(value, surface, position, scale, offset, immutable)
|
||||
local is_string = type(value) == 'string'
|
||||
@@ -488,23 +623,9 @@ function Common.print_grid_value(value, surface, position, scale, offset, immuta
|
||||
scale = scale or 1
|
||||
offset = offset or 0
|
||||
position = {x = position.x + offset, y = position.y + offset}
|
||||
local r = math.max(1, value) / scale
|
||||
local g = 1 - math.abs(value) / scale
|
||||
local b = math.min(1, value) / scale
|
||||
|
||||
if (r > 0) then
|
||||
r = 0
|
||||
end
|
||||
|
||||
if (b < 0) then
|
||||
b = 0
|
||||
end
|
||||
|
||||
if (g < 0) then
|
||||
g = 0
|
||||
end
|
||||
|
||||
r = math.abs(r)
|
||||
local r = math.clamp(-value/scale, 0, 1)
|
||||
local g = math.clamp(1-math.abs(value)/scale, 0, 1)
|
||||
local b = math.clamp(value/scale, 0, 1)
|
||||
|
||||
color = { r = r, g = g, b = b}
|
||||
|
||||
@@ -534,81 +655,13 @@ function Common.print_grid_value(value, surface, position, scale, offset, immuta
|
||||
}.active = false
|
||||
end
|
||||
|
||||
--[[--
|
||||
Prints a colored value on a location. When given a color_value and a delta_color,
|
||||
will change the color of the text from the base to base + value * delta. This will
|
||||
make the color of the text range from 'base_color' to 'base_color + delta_color'
|
||||
as the color_value ranges from 0 to 1
|
||||
@param value of number to be displayed
|
||||
@param surface LuaSurface
|
||||
@param position Position {x, y}
|
||||
@param offset float position offset
|
||||
@param immutable bool if immutable, only set, never do a surface lookup, values never change
|
||||
@param color_value float How far along the range of values of colors the value is to be displayed
|
||||
@param base_color {r,g,b} The color for the text to be if color_value is 0
|
||||
@param delta_color {r,g,b} The amount to correct the base_color if color_value is 1
|
||||
@param under_bound {r,g,b} The color to be used if color_value < 0
|
||||
@param over_bound {r,g,b} The color to be used if color_value > 1
|
||||
--[[-- Clears all flying text entities on a surface
|
||||
@tparam LuaSurface surface the surface to clear
|
||||
|
||||
@usage-- Remove all flying text on the surface
|
||||
clear_flying_text(game.player.surface)
|
||||
|
||||
]]
|
||||
function Common.print_colored_grid_value(value, surface, position, offset, immutable,
|
||||
color_value, base_color, delta_color, under_bound, over_bound)
|
||||
local is_string = type(value) == 'string'
|
||||
-- default values:
|
||||
local color = base_color or Colours.white
|
||||
local d_color = delta_color or Colours.black
|
||||
local u_color = under_bound or color
|
||||
local o_color = over_bound or color
|
||||
|
||||
if (color_value < 0) then
|
||||
color = u_color
|
||||
elseif (color_value > 1) then
|
||||
color = o_color
|
||||
else
|
||||
color = {
|
||||
r = color.r + color_value * d_color.r,
|
||||
g = color.g + color_value * d_color.g,
|
||||
b = color.b + color_value * d_color.b
|
||||
}
|
||||
end
|
||||
|
||||
local text = value
|
||||
|
||||
if type(immutable) ~= 'boolean' then
|
||||
immutable = false
|
||||
end
|
||||
|
||||
if not is_string then
|
||||
offset = offset or 0
|
||||
position = {x = position.x + offset, y = position.y + offset}
|
||||
|
||||
-- round at precision of 2
|
||||
text = math.floor(100 * value) * 0.01
|
||||
|
||||
if (0 == text) then
|
||||
text = '0.00'
|
||||
end
|
||||
end
|
||||
|
||||
if not immutable then
|
||||
local text_entity = surface.find_entity('flying-text', position)
|
||||
|
||||
if text_entity then
|
||||
text_entity.text = text
|
||||
text_entity.color = color
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
surface.create_entity{
|
||||
name = 'flying-text',
|
||||
color = color,
|
||||
text = text,
|
||||
position = position
|
||||
}.active = false
|
||||
end
|
||||
|
||||
--- Clears all flying text entities on a surface
|
||||
-- @tparam LuaSurface surface the surface to clear
|
||||
function Common.clear_flying_text(surface)
|
||||
local entities = surface.find_entities_filtered{name ='flying-text'}
|
||||
for _,entity in pairs(entities) do
|
||||
|
||||
@@ -1 +1 @@
|
||||
return require 'expcore.gui.require'
|
||||
return require 'expcore.gui._require'
|
||||
131
expcore/gui/_require.lua
Normal file
131
expcore/gui/_require.lua
Normal file
@@ -0,0 +1,131 @@
|
||||
--[[-- Core Module - Gui
|
||||
- Used to simplify gui creation using factory functions called element defines
|
||||
@core Gui
|
||||
@alias Gui
|
||||
|
||||
@usage-- To draw your element you only need to call the factory function
|
||||
-- You are able to pass any other arguments that are used in your custom functions but the first is always the parent element
|
||||
local example_button_element = example_button(parent_element)
|
||||
|
||||
@usage-- Making a factory function for a button with the caption "Example Button"
|
||||
-- This method has all the same features as LuaGuiElement.add
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button'
|
||||
}
|
||||
|
||||
@usage-- Making a factory function for a button which is contained within a flow
|
||||
-- This method is for when you still want to register event handlers but cant use the table method
|
||||
local example_flow_with_button =
|
||||
Gui.element(function(event_trigger,parent,...)
|
||||
-- ... shows that all other arguments from the factory call are passed to this function
|
||||
-- Here we are adding a flow which we will then later add a button to
|
||||
local flow =
|
||||
parent.add{ -- paraent is the element which is passed to the factory function
|
||||
name = 'example_flow',
|
||||
type = 'flow'
|
||||
}
|
||||
|
||||
-- Now we add the button to the flow that we created earlier
|
||||
local element =
|
||||
flow.add{
|
||||
name = event_trigger, -- event_trigger should be the name of any elements you want to trigger your event handlers
|
||||
type = 'button',
|
||||
caption = 'Example Button'
|
||||
}
|
||||
|
||||
-- You must return a new element, this is so styles can be applied and returned to the caller
|
||||
-- You may return any of your elements that you added, consider the context in which it will be used for which should be returned
|
||||
return element
|
||||
end)
|
||||
|
||||
@usage-- Styles can be added to any element define, simplest way mimics LuaGuiElement.style[key] = value
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button',
|
||||
style = 'forward_button' -- factorio styles can be applied here
|
||||
}
|
||||
:style{
|
||||
height = 25, -- same as element.style.height = 25
|
||||
width = 100 -- same as element.style.width = 25
|
||||
}
|
||||
|
||||
@usage-- Styles can also have a custom function when the style is dynamic and depends on other factors
|
||||
-- Use this method if your style is dynamic and depends on other factors
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button',
|
||||
style = 'forward_button' -- factorio styles can be applied here
|
||||
}
|
||||
:style(function(style,element,...)
|
||||
-- style is the current style object for the elemenent
|
||||
-- element is the element that is being changed
|
||||
-- ... shows that all other arguments from the factory call are passed to this function
|
||||
local player = game.players[element.player_index]
|
||||
style.height = 25
|
||||
style.width = 100
|
||||
style.font_color = player.color
|
||||
end)
|
||||
|
||||
@usage-- You are able to register event handlers to your elements, these can be factorio events or custom ones
|
||||
-- All events are checked to be valid before raising any handlers, this means element.valid = true and player.valid = true
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button'
|
||||
}
|
||||
:on_click(function(player,element,event)
|
||||
-- player is the player who interacted with the element to cause the event
|
||||
-- element is a refrence to the element which caused the event
|
||||
-- event is a raw refrence to the event data if player and element are not enough
|
||||
player.print('Clicked: '..element.name)
|
||||
end)
|
||||
|
||||
@usage-- Example from core_defines, Gui.core_defines.hide_left_flow, called like: hide_left_flow(parent_element)
|
||||
--- Button which hides the elements in the left flow, shows inside the left flow when frames are visible
|
||||
-- @element hide_left_flow
|
||||
local hide_left_flow =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/close_black',
|
||||
style = 'tool_button',
|
||||
tooltip = {'expcore-gui.left-button-tooltip'}
|
||||
}
|
||||
:style{
|
||||
padding = -3,
|
||||
width = 18,
|
||||
height = 20
|
||||
}
|
||||
:on_click(function(player,_,_)
|
||||
Gui.hide_left_flow(player)
|
||||
end)
|
||||
|
||||
@usage-- Eample from defines, Gui.alignment, called like: Gui.alignment(parent, name, horizontal_align, vertical_align)
|
||||
-- Notice how _ are used to blank arguments that are not needed in that context and how they line up with above
|
||||
Gui.alignment =
|
||||
Gui.element(function(_,parent,name,_,_)
|
||||
return parent.add{
|
||||
name = name or 'alignment',
|
||||
type = 'flow',
|
||||
}
|
||||
end)
|
||||
:style(function(style,_,_,horizontal_align,vertical_align)
|
||||
style.padding = {1,2}
|
||||
style.vertical_align = vertical_align or 'center'
|
||||
style.horizontal_align = horizontal_align or 'right'
|
||||
style.vertically_stretchable = style.vertical_align ~= 'center'
|
||||
style.horizontally_stretchable = style.horizontal_align ~= 'center'
|
||||
end)
|
||||
|
||||
]]
|
||||
|
||||
local Gui = require 'expcore.gui.prototype'
|
||||
require 'expcore.gui.core_defines'
|
||||
require 'expcore.gui.top_flow'
|
||||
require 'expcore.gui.left_flow'
|
||||
require 'expcore.gui.helper_functions'
|
||||
require 'expcore.gui.defines'
|
||||
|
||||
return Gui
|
||||
@@ -4,7 +4,7 @@
|
||||
]]
|
||||
|
||||
local Gui = require 'expcore.gui.prototype'
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Event = require 'utils.event'
|
||||
|
||||
--- Core Defines.
|
||||
-- @section coreDefines
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
]]
|
||||
|
||||
local Gui = require 'expcore.gui.prototype'
|
||||
local mod_gui = require 'mod-gui' --- @dep mod-gui
|
||||
local mod_gui = require 'mod-gui'
|
||||
|
||||
local hide_left_flow = Gui.core_defines.hide_left_flow.name
|
||||
|
||||
@@ -82,7 +82,7 @@ end
|
||||
--[[-- Draw all the left elements onto the left flow, internal use only with on join
|
||||
@tparam LuaPlayer player the player that you want to draw the elements for
|
||||
|
||||
@usage Draw all the left elements
|
||||
@usage-- Draw all the left elements
|
||||
Gui.draw_left_flow(player)
|
||||
|
||||
]]
|
||||
|
||||
@@ -1,152 +1,26 @@
|
||||
--[[-- Core Module - Gui
|
||||
- Used to simplify gui creation using factory functions called element defines
|
||||
@core Gui
|
||||
@alias Gui
|
||||
|
||||
@usage-- To draw your element you only need to call the factory function
|
||||
-- You are able to pass any other arguments that are used in your custom functions but the first is always the parent element
|
||||
local example_button_element = example_button(parent_element)
|
||||
|
||||
@usage-- Making a factory function for a button with the caption "Example Button"
|
||||
-- This method has all the same features as LuaGuiElement.add
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button'
|
||||
}
|
||||
|
||||
@usage-- Making a factory function for a button which is contained within a flow
|
||||
-- This method is for when you still want to register event handlers but cant use the table method
|
||||
local example_flow_with_button =
|
||||
Gui.element(function(event_trigger,parent,...)
|
||||
-- ... shows that all other arguments from the factory call are passed to this function
|
||||
-- Here we are adding a flow which we will then later add a button to
|
||||
local flow =
|
||||
parent.add{ -- paraent is the element which is passed to the factory function
|
||||
name = 'example_flow',
|
||||
type = 'flow'
|
||||
}
|
||||
|
||||
-- Now we add the button to the flow that we created earlier
|
||||
local element =
|
||||
flow.add{
|
||||
name = event_trigger, -- event_trigger should be the name of any elements you want to trigger your event handlers
|
||||
type = 'button',
|
||||
caption = 'Example Button'
|
||||
}
|
||||
|
||||
-- You must return a new element, this is so styles can be applied and returned to the caller
|
||||
-- You may return any of your elements that you added, consider the context in which it will be used for which should be returned
|
||||
return element
|
||||
end)
|
||||
|
||||
@usage-- Styles can be added to any element define, simplest way mimics LuaGuiElement.style[key] = value
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button',
|
||||
style = 'forward_button' -- factorio styles can be applied here
|
||||
}
|
||||
:style{
|
||||
height = 25, -- same as element.style.height = 25
|
||||
width = 100 -- same as element.style.width = 25
|
||||
}
|
||||
|
||||
@usage-- Styles can also have a custom function when the style is dynamic and depends on other factors
|
||||
-- Use this method if your style is dynamic and depends on other factors
|
||||
local example_button =
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button',
|
||||
style = 'forward_button' -- factorio styles can be applied here
|
||||
}
|
||||
:style(function(style,element,...)
|
||||
-- style is the current style object for the elemenent
|
||||
-- element is the element that is being changed
|
||||
-- ... shows that all other arguments from the factory call are passed to this function
|
||||
local player = game.players[element.player_index]
|
||||
style.height = 25
|
||||
style.width = 100
|
||||
style.font_color = player.color
|
||||
end)
|
||||
|
||||
@usage-- You are able to register event handlers to your elements, these can be factorio events or custom ones
|
||||
-- All events are checked to be valid before raising any handlers, this means element.valid = true and player.valid = true
|
||||
Gui.element{
|
||||
type = 'button',
|
||||
caption = 'Example Button'
|
||||
}
|
||||
:on_click(function(player,element,event)
|
||||
-- player is the player who interacted with the element to cause the event
|
||||
-- element is a refrence to the element which caused the event
|
||||
-- event is a raw refrence to the event data if player and element are not enough
|
||||
player.print('Clicked: '..element.name)
|
||||
end)
|
||||
|
||||
@usage-- Example from core_defines, Gui.core_defines.hide_left_flow, called like: hide_left_flow(parent_element)
|
||||
--- Button which hides the elements in the left flow, shows inside the left flow when frames are visible
|
||||
-- @element hide_left_flow
|
||||
local hide_left_flow =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/close_black',
|
||||
style = 'tool_button',
|
||||
tooltip = {'expcore-gui.left-button-tooltip'}
|
||||
}
|
||||
:style{
|
||||
padding = -3,
|
||||
width = 18,
|
||||
height = 20
|
||||
}
|
||||
:on_click(function(player,_,_)
|
||||
Gui.hide_left_flow(player)
|
||||
end)
|
||||
|
||||
@usage-- Eample from defines, Gui.alignment, called like: Gui.alignment(parent, name, horizontal_align, vertical_align)
|
||||
-- Notice how _ are used to blank arguments that are not needed in that context and how they line up with above
|
||||
Gui.alignment =
|
||||
Gui.element(function(_,parent,name,_,_)
|
||||
return parent.add{
|
||||
name = name or 'alignment',
|
||||
type = 'flow',
|
||||
}
|
||||
end)
|
||||
:style(function(style,_,_,horizontal_align,vertical_align)
|
||||
style.padding = {1,2}
|
||||
style.vertical_align = vertical_align or 'center'
|
||||
style.horizontal_align = horizontal_align or 'right'
|
||||
style.vertically_stretchable = style.vertical_align ~= 'center'
|
||||
style.horizontally_stretchable = style.horizontal_align ~= 'center'
|
||||
end)
|
||||
|
||||
@module Gui
|
||||
]]
|
||||
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
|
||||
local Gui = {
|
||||
--- The current highest uid that is being used by a define, will not increase during runtime
|
||||
-- @field uid
|
||||
uid = 0,
|
||||
--- String indexed table used to avoid conflict with custom event names, similar to how defines.events works
|
||||
-- @table events
|
||||
events = {},
|
||||
--- Uid indexed array that stores all the factory functions that were defined, no new values will be added during runtime
|
||||
-- @table defines
|
||||
defines = {},
|
||||
--- An string indexed table of all the defines which are used by the core of the gui system, used for internal refrence
|
||||
-- @table core_defines
|
||||
core_defines = {},
|
||||
--- Used to store the file names where elements were defined, this can be useful to find the uid of an element, mostly for debuging
|
||||
-- @table file_paths
|
||||
file_paths = {},
|
||||
--- Used to store extra infomation about elements as they get defined such as the params used and event handlers registered to them
|
||||
-- @table debug_info
|
||||
debug_info = {},
|
||||
--- The prototype used to store the functions of an element define
|
||||
-- @table _prototype_element
|
||||
_prototype_element = {},
|
||||
--- The prototype metatable applied to new element defines
|
||||
-- @table _mt_element
|
||||
_mt_element = {
|
||||
__call = function(self,parent,...)
|
||||
local element = self._draw(self.name,parent,...)
|
||||
@@ -365,50 +239,86 @@ end
|
||||
|
||||
--- Called when the player opens a GUI.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_open(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_open = event_handler_factory(defines.events.on_gui_opened)
|
||||
|
||||
--- Called when the player closes the GUI they have open.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_close(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_close = event_handler_factory(defines.events.on_gui_closed)
|
||||
|
||||
--- Called when LuaGuiElement is clicked.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_click(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_click = event_handler_factory(defines.events.on_gui_click)
|
||||
|
||||
--- Called when a LuaGuiElement is confirmed, for example by pressing Enter in a textfield.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_confirmed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_confirmed = event_handler_factory(defines.events.on_gui_confirmed)
|
||||
|
||||
--- Called when LuaGuiElement checked state is changed (related to checkboxes and radio buttons).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_checked_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_checked_changed = event_handler_factory(defines.events.on_gui_checked_state_changed)
|
||||
|
||||
--- Called when LuaGuiElement element value is changed (related to choose element buttons).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_elem_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_elem_changed = event_handler_factory(defines.events.on_gui_elem_changed)
|
||||
|
||||
--- Called when LuaGuiElement element location is changed (related to frames in player.gui.screen).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_location_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_location_changed = event_handler_factory(defines.events.on_gui_location_changed)
|
||||
|
||||
--- Called when LuaGuiElement selected tab is changed (related to tabbed-panes).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_tab_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_tab_changed = event_handler_factory(defines.events.on_gui_selected_tab_changed)
|
||||
|
||||
--- Called when LuaGuiElement selection state is changed (related to drop-downs and listboxes).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_selection_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_selection_changed = event_handler_factory(defines.events.on_gui_selection_state_changed)
|
||||
|
||||
--- Called when LuaGuiElement switch state is changed (related to switches).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_switch_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_switch_changed = event_handler_factory(defines.events.on_gui_switch_state_changed)
|
||||
|
||||
--- Called when LuaGuiElement text is changed by the player.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_text_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_text_changed = event_handler_factory(defines.events.on_gui_text_changed)
|
||||
|
||||
--- Called when LuaGuiElement slider value is changed (related to the slider element).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_value_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
Gui._prototype_element.on_value_changed = event_handler_factory(defines.events.on_gui_value_changed)
|
||||
|
||||
-- Module return
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
local Gui = require 'expcore.gui.prototype'
|
||||
require 'expcore.gui.core_defines'
|
||||
require 'expcore.gui.top_flow'
|
||||
require 'expcore.gui.left_flow'
|
||||
require 'expcore.gui.helper_functions'
|
||||
require 'expcore.gui.defines'
|
||||
|
||||
return Gui
|
||||
@@ -145,7 +145,7 @@ function Gui.toolbar_button(sprite,tooltip,authenticator)
|
||||
end
|
||||
|
||||
--[[-- Styles a top flow button depending on the state given
|
||||
@tparam LuaGuiElement the button element to style
|
||||
@tparam LuaGuiElement button the button element to style
|
||||
@tparam boolean state The state the button is in
|
||||
|
||||
@usage-- Sets the button to the visible style
|
||||
|
||||
@@ -1,29 +1,25 @@
|
||||
--[[-- Core Module - Permission Groups
|
||||
- Permission group making for factorio so you never have to make one by hand again
|
||||
@core Permissions-Groups
|
||||
@alias Permissions_Groups
|
||||
- Permission group making for factorio so you never have to make one by hand again
|
||||
@core Groups
|
||||
@alias Permissions_Groups
|
||||
|
||||
@usage
|
||||
---- Example Group (Allow All)
|
||||
@usage--- Example Group (Allow All)
|
||||
-- here we will create an admin group however we do not want them to use the map editor or mess with the permission groups
|
||||
Permission_Groups.new_group('Admin') -- this defines a new group called "Admin"
|
||||
:allow_all() -- this makes the default to allow any input action unless set other wise
|
||||
:disallow{ -- here we disallow the input action we don't want them to use
|
||||
'add_permission_group',
|
||||
'delete_permission_group',
|
||||
'import_permissions_string',
|
||||
'map_editor_action',
|
||||
'toggle_map_editor'
|
||||
}
|
||||
|
||||
-- here we will create an admin group however we do not want them to use the map editor or mess with the permission groups
|
||||
Permission_Groups.new_group('Admin') -- this defines a new group called "Admin"
|
||||
:allow_all() -- this makes the default to allow any input action unless set other wise
|
||||
:disallow{ -- here we disallow the input action we don't want them to use
|
||||
'add_permission_group',
|
||||
'delete_permission_group',
|
||||
'import_permissions_string',
|
||||
'map_editor_action',
|
||||
'toggle_map_editor'
|
||||
}
|
||||
|
||||
@usage
|
||||
---- Example Group (Disallow All)
|
||||
|
||||
-- here we will create a group that cant do anything but talk in chat
|
||||
Permission_Groups.new_group('Restricted') -- this defines a new group called "Restricted"
|
||||
:disallow_all() -- this makes the default to disallow any input action unless set other wise
|
||||
:allow('write_to_console') -- here we allow them to chat, {} can be used here if we had more than one action
|
||||
@usage--- Example Group (Disallow All)
|
||||
-- here we will create a group that cant do anything but talk in chat
|
||||
Permission_Groups.new_group('Restricted') -- this defines a new group called "Restricted"
|
||||
:disallow_all() -- this makes the default to disallow any input action unless set other wise
|
||||
:allow('write_to_console') -- here we allow them to chat, {} can be used here if we had more than one action
|
||||
|
||||
]]
|
||||
|
||||
@@ -55,9 +51,14 @@ Permissions_Groups.async_token_remove_from_permission_group = remove_from_permis
|
||||
-- Functions that get permission groups
|
||||
-- @section getters
|
||||
|
||||
--- Defines a new permission group that can have it actions set in the config
|
||||
-- @tparam string name the name of the new group
|
||||
-- @treturn Permissions_Groups._prototype the new group made with function to allow and disallow actions
|
||||
--[[-- Defines a new permission group that can have it actions set in the config
|
||||
@tparam string name the name of the new group
|
||||
@treturn Permissions_Groups._prototype the new group made with function to allow and disallow actions
|
||||
|
||||
@usage-- Defining a new permission group
|
||||
Groups.new_group('Admin')
|
||||
|
||||
]]
|
||||
function Permissions_Groups.new_group(name)
|
||||
local group = setmetatable({
|
||||
name=name,
|
||||
@@ -70,16 +71,26 @@ function Permissions_Groups.new_group(name)
|
||||
return group
|
||||
end
|
||||
|
||||
--- Returns the group with the given name, case sensitive
|
||||
-- @tparam string name the name of the group to get
|
||||
-- @treturn ?Permissions_Groups._prototype|nil the group with that name or nil if non found
|
||||
--[[-- Returns the group with the given name, case sensitive
|
||||
@tparam string name the name of the group to get
|
||||
@treturn ?Permissions_Groups._prototype|nil the group with that name or nil if non found
|
||||
|
||||
@usage-- Getting a permision group
|
||||
local admin_group = Groups.get_group_by_name('Admin')
|
||||
|
||||
]]
|
||||
function Permissions_Groups.get_group_by_name(name)
|
||||
return Permissions_Groups.groups[name]
|
||||
end
|
||||
|
||||
--- Returns the group that a player is in
|
||||
-- @tparam LuaPlayer player the player to get the group of can be name index etc
|
||||
-- @treturn ?Permissions_Groups._prototype|nil the group with that player or nil if non found
|
||||
--[[-- Returns the group that a player is in
|
||||
@tparam LuaPlayer player the player to get the group of can be name index etc
|
||||
@treturn ?Permissions_Groups._prototype|nil the group with that player or nil if non found
|
||||
|
||||
@usage-- Get your permission group
|
||||
local group = Groups.get_group_from_player(game.player)
|
||||
|
||||
]]
|
||||
function Permissions_Groups.get_group_from_player(player)
|
||||
player = Game.get_player_from_any(player)
|
||||
if not player then return end
|
||||
@@ -93,43 +104,27 @@ end
|
||||
-- Functions that control all groups
|
||||
-- @section players
|
||||
|
||||
--- Reloads/creates all permission groups and sets them to they configured state
|
||||
--[[-- Reloads/creates all permission groups and sets them to they configured state
|
||||
|
||||
@usage-- Reload the permission groups, used internally
|
||||
Groups.reload_permissions()
|
||||
|
||||
]]
|
||||
function Permissions_Groups.reload_permissions()
|
||||
for _,group in pairs(Permissions_Groups.groups) do
|
||||
group:create()
|
||||
end
|
||||
end
|
||||
|
||||
--- Removes all permissions from every permission group except for "Default" and any passed as exempt
|
||||
-- @tparam ?string|Array<string> exempt groups that you want to be except, "Default" is always exempt
|
||||
-- @treturn number the number of groups that had they permissions removed
|
||||
function Permissions_Groups.lockdown_permissions(exempt)
|
||||
local count = 0
|
||||
if type(exempt) ~= 'table' then
|
||||
exempt = {exempt}
|
||||
end
|
||||
for _,group in pairs(exempt) do
|
||||
if type(group) == 'string' then
|
||||
exempt[group:lower()] = true
|
||||
elseif type(group) == 'table' then
|
||||
exempt[group.name:lower()] = true
|
||||
end
|
||||
end
|
||||
for _,group in pairs(game.permissions.groups) do
|
||||
if not exempt[group.name:lower()] and not group.name == 'Default' then
|
||||
count = count +1
|
||||
for _,action in pairs(defines.input_action) do
|
||||
group.set_allows_action(action,false)
|
||||
end
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
--[[-- Sets a player's group to the one given, a player can only have one group at a time
|
||||
@tparam LuaPlayer player the player to effect can be name index etc
|
||||
@tparam string group the name of the group to give to the player
|
||||
@treturn boolean true if the player was added successfully, false other wise
|
||||
|
||||
--- Sets a player's group to the one given, a player can only have one group at a time
|
||||
-- @tparam LuaPlayer player the player to effect can be name index etc
|
||||
-- @tparam string group the name of the group to give to the player
|
||||
-- @treturn boolean true if the player was added successfully, false other wise
|
||||
@usage-- Set your permission group
|
||||
Groups.set_player_group(game.player, 'Admin')
|
||||
|
||||
]]
|
||||
function Permissions_Groups.set_player_group(player,group)
|
||||
player = Game.get_player_from_any(player)
|
||||
group = Permissions_Groups.get_group_by_name(group)
|
||||
@@ -142,10 +137,15 @@ end
|
||||
-- Functions that control group actions
|
||||
-- @section actions
|
||||
|
||||
--- Sets the allow state of an action for this group, used internally but is safe to use else where
|
||||
-- @tparam ?string|defines.input_action action the action that you want to set the state of
|
||||
-- @tparam boolean state the state that you want to set it to, true = allow, false = disallow
|
||||
-- @treturn Permissions_Groups._prototype returns self so function can be chained
|
||||
--[[-- Sets the allow state of an action for this group, used internally but is safe to use else where
|
||||
@tparam ?string|defines.input_action action the action that you want to set the state of
|
||||
@tparam boolean state the state that you want to set it to, true = allow, false = disallow
|
||||
@treturn Permissions_Groups._prototype returns self so function can be chained
|
||||
|
||||
@usage-- Set an action to be disalowed
|
||||
group:set_action('toggle_map_editor', false)
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:set_action(action,state)
|
||||
if type(action) == 'string' then
|
||||
action = defines.input_action[action]
|
||||
@@ -154,9 +154,16 @@ function Permissions_Groups._prototype:set_action(action,state)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets an action or actions to be allowed for this group even with disallow_all triggered, Do not use in runtime
|
||||
-- @tparam string|Array<string> actions the action or actions that you want to allow for this group
|
||||
-- @treturn Permissions_Groups._prototype returns self so function can be chained
|
||||
--[[-- Sets an action or actions to be allowed for this group even with disallow_all triggered, Do not use in runtime
|
||||
@tparam string|Array<string> actions the action or actions that you want to allow for this group
|
||||
@treturn Permissions_Groups._prototype returns self so function can be chained
|
||||
|
||||
@usage-- Allow some actions
|
||||
group:allow{
|
||||
'write_to_console'
|
||||
}
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:allow(actions)
|
||||
if type(actions) ~= 'table' then
|
||||
actions = {actions}
|
||||
@@ -167,9 +174,20 @@ function Permissions_Groups._prototype:allow(actions)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets an action or actions to be disallowed for this group even with allow_all triggered, Do not use in runtime
|
||||
-- @tparam string|Array<string> actions the action or actions that you want to disallow for this group
|
||||
-- @treturn Permissions_Groups._prototype returns self so function can be chained
|
||||
--[[-- Sets an action or actions to be disallowed for this group even with allow_all triggered, Do not use in runtime
|
||||
@tparam string|Array<string> actions the action or actions that you want to disallow for this group
|
||||
@treturn Permissions_Groups._prototype returns self so function can be chained
|
||||
|
||||
@usage-- Disalow some actions
|
||||
group:disallow{
|
||||
'add_permission_group',
|
||||
'delete_permission_group',
|
||||
'import_permissions_string',
|
||||
'map_editor_action',
|
||||
'toggle_map_editor'
|
||||
}
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:disallow(actions)
|
||||
if type(actions) ~= 'table' then
|
||||
actions = {actions}
|
||||
@@ -180,23 +198,38 @@ function Permissions_Groups._prototype:disallow(actions)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets the default state for any actions not given to be allowed, useful with :disallow
|
||||
-- @treturn Permissions_Groups._prototype returns self so function can be chained
|
||||
--[[-- Sets the default state for any actions not given to be allowed, useful with :disallow
|
||||
@treturn Permissions_Groups._prototype returns self so function can be chained
|
||||
|
||||
@usage-- Allow all actions unless given by disallow
|
||||
group:allow_all()
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:allow_all()
|
||||
self.allow_all_actions = true
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets the default state for any action not given to be disallowed, useful with :allow
|
||||
-- @treturn Permissions_Groups._prototype returns self so function can be chained
|
||||
--[[-- Sets the default state for any action not given to be disallowed, useful with :allow
|
||||
@treturn Permissions_Groups._prototype returns self so function can be chained
|
||||
|
||||
@usage-- Disallow all actions unless given by allow
|
||||
group:disallow_all()
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:disallow_all()
|
||||
self.allow_all_actions = false
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns if an input action is allowed for this group
|
||||
-- @tparam ?string|defines.input_action action the action that you want to test for
|
||||
-- @treturn boolean true if the group is allowed the action, false other wise
|
||||
--[[-- Returns if an input action is allowed for this group
|
||||
@tparam ?string|defines.input_action action the action that you want to test for
|
||||
@treturn boolean true if the group is allowed the action, false other wise
|
||||
|
||||
@usage-- Test if a group is allowed an action
|
||||
local allowed = group:is_allowed('write_to_console')
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:is_allowed(action)
|
||||
if type(action) == 'string' then
|
||||
action = defines.input_action[action]
|
||||
@@ -212,14 +245,13 @@ end
|
||||
-- Functions that control group players
|
||||
-- @section players
|
||||
|
||||
--- Returns the LuaPermissionGroup that was created with this group object, used internally
|
||||
-- @treturn LuaPermissionGroup the raw lua permission group
|
||||
function Permissions_Groups._prototype:get_raw()
|
||||
return game.permissions.get_group(self.name)
|
||||
end
|
||||
--[[-- Creates or updates the permission group with the configured actions, used internally
|
||||
@treturn LuaPermissionGroup the permission group that was created
|
||||
|
||||
--- Creates or updates the permission group with the configured actions, used internally
|
||||
-- @treturn LuaPermissionGroup the permission group that was created
|
||||
@usage-- Create the permission group so players can be added, used internally
|
||||
group:create()
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:create()
|
||||
local group = self:get_raw()
|
||||
if not group then
|
||||
@@ -231,9 +263,25 @@ function Permissions_Groups._prototype:create()
|
||||
return group
|
||||
end
|
||||
|
||||
--- Adds a player to this group
|
||||
-- @tparam LuaPlayer player LuaPlayer the player you want to add to this group can be name or index etc
|
||||
-- @treturn boolean true if the player was added successfully, false other wise
|
||||
--[[-- Returns the LuaPermissionGroup that was created with this group object, used internally
|
||||
@treturn LuaPermissionGroup the raw lua permission group
|
||||
|
||||
@usage-- Get the factorio api permision group, used internally
|
||||
local permission_group = group:get_raw()
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:get_raw()
|
||||
return game.permissions.get_group(self.name)
|
||||
end
|
||||
|
||||
--[[-- Adds a player to this group
|
||||
@tparam LuaPlayer player LuaPlayer the player you want to add to this group can be name or index etc
|
||||
@treturn boolean true if the player was added successfully, false other wise
|
||||
|
||||
@usage-- Add a player to this permission group
|
||||
group:add_player(game.player)
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:add_player(player)
|
||||
player = Game.get_player_from_any(player)
|
||||
local group = self:get_raw()
|
||||
@@ -242,9 +290,14 @@ function Permissions_Groups._prototype:add_player(player)
|
||||
return true
|
||||
end
|
||||
|
||||
--- Removes a player from this group
|
||||
-- @tparam LuaPlayer player LuaPlayer the player you want to remove from this group can be name or index etc
|
||||
-- @treturn boolean true if the player was removed successfully, false other wise
|
||||
--[[-- Removes a player from this group
|
||||
@tparam LuaPlayer player LuaPlayer the player you want to remove from this group can be name or index etc
|
||||
@treturn boolean true if the player was removed successfully, false other wise
|
||||
|
||||
@usage-- Remove a player from this permission group
|
||||
group:remove_player(game.player)
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:remove_player(player)
|
||||
player = Game.get_player_from_any(player)
|
||||
local group = self:get_raw()
|
||||
@@ -253,9 +306,17 @@ function Permissions_Groups._prototype:remove_player(player)
|
||||
return true
|
||||
end
|
||||
|
||||
--- Returns all player that are in this group with the option to filter to online/offline only
|
||||
-- @tparam[opt] boolean online if nil returns all players, if true online players only, if false returns online players only
|
||||
-- @treturn table a table of players that are in this group; filtered if online param is given
|
||||
--[[-- Returns all player that are in this group with the option to filter to online/offline only
|
||||
@tparam[opt] boolean online if nil returns all players, if true online players only, if false returns online players only
|
||||
@treturn table a table of players that are in this group; filtered if online param is given
|
||||
|
||||
@usage-- Get all players in this group
|
||||
local online_players = group:get_players()
|
||||
|
||||
@usage-- Get all online players in this group
|
||||
local online_players = group:get_players(true)
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:get_players(online)
|
||||
local players = {}
|
||||
local group = self:get_raw()
|
||||
@@ -273,9 +334,14 @@ function Permissions_Groups._prototype:get_players(online)
|
||||
return players
|
||||
end
|
||||
|
||||
--- Prints a message to every player in this group
|
||||
-- @tparam string message the message that you want to send to the players
|
||||
-- @treturn number the number of players that received the message
|
||||
--[[-- Prints a message to every player in this group
|
||||
@tparam string message the message that you want to send to the players
|
||||
@treturn number the number of players that received the message
|
||||
|
||||
@usage-- Print a message to all players in thie group
|
||||
group:print('Hello, World!')
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:print(message)
|
||||
local players = self:get_players(true)
|
||||
for _,player in pairs(players) do
|
||||
|
||||
@@ -1,115 +1,111 @@
|
||||
--[[-- Core Module - Roles
|
||||
- Factorio role system to manage custom permissions.
|
||||
@core Roles
|
||||
@alias Roles
|
||||
- Factorio role system to manage custom permissions.
|
||||
@core Roles
|
||||
@alias Roles
|
||||
|
||||
@usage
|
||||
---- 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'}
|
||||
}
|
||||
@usage--- Using Role System (assignment):
|
||||
--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
|
||||
--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
|
||||
|
||||
@usage
|
||||
---- 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
|
||||
@usage--- Using Role System (role testing):
|
||||
--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
|
||||
--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
|
||||
--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
|
||||
|
||||
@usage
|
||||
---- 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:
|
||||
@usage--- 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
|
||||
-- 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)
|
||||
|
||||
@usage
|
||||
---- 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')
|
||||
-- then on all your donator roles you would add
|
||||
Roles.new_role('Donator')
|
||||
:set_flag('is_donator')
|
||||
|
||||
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')
|
||||
-- and in your code you would test for
|
||||
if Roles.player_has_flag(player,'is_donator') then
|
||||
-- some donator only code
|
||||
end
|
||||
|
||||
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()
|
||||
@usage--- 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')
|
||||
|
||||
If you don't 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'
|
||||
}
|
||||
--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')
|
||||
|
||||
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'
|
||||
}
|
||||
--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()
|
||||
|
||||
@usage
|
||||
---- 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 linear order that the roles fall into:
|
||||
--If you don't 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'
|
||||
}
|
||||
|
||||
Roles.set_default('Guest')
|
||||
Roles.set_root('System')
|
||||
--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'
|
||||
}
|
||||
|
||||
Roles.define_role_order{
|
||||
'System',
|
||||
'Administrator',
|
||||
'Moderator',
|
||||
'Donator',
|
||||
'Guest'
|
||||
}
|
||||
@usage--- 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 linear 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.
|
||||
|
||||
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.
|
||||
]]
|
||||
|
||||
local Game = require 'utils.game' --- @dep utils.game
|
||||
@@ -196,8 +192,13 @@ local function emit_player_roles_updated(player,type,roles,by_player_name,skip_g
|
||||
})
|
||||
end
|
||||
|
||||
--- Returns a string which contains all roles in index order displaying all data for them
|
||||
-- @treturn string the debug output string
|
||||
--[[-- Returns a string which contains all roles in index order displaying all data for them
|
||||
@treturn string the debug output string
|
||||
|
||||
@usage-- Print the debug string
|
||||
game.player.print(Roles.debug())
|
||||
|
||||
]]
|
||||
function Roles.debug()
|
||||
local output = ''
|
||||
for index,role_name in pairs(Roles.config.order) do
|
||||
@@ -209,9 +210,14 @@ function Roles.debug()
|
||||
return output
|
||||
end
|
||||
|
||||
--- Prints a message to all players in the given roles, may send duplicate message however factorio blocks spam
|
||||
-- @tparam table roles table a of roles which to send the message to
|
||||
-- @tparam string message the message to send to the players
|
||||
--[[-- Prints a message to all players in the given roles, may send duplicate message however factorio blocks spam
|
||||
@tparam table roles table a of roles which to send the message to
|
||||
@tparam string message the message to send to the players
|
||||
|
||||
@usage-- Print a message to the given roles
|
||||
Roles.print_to_roles({'Administrator','Moderator'}, 'Hello, World!')
|
||||
|
||||
]]
|
||||
function Roles.print_to_roles(roles,message)
|
||||
for _,role in pairs(roles) do
|
||||
role = Roles.get_role_from_any(role)
|
||||
@@ -219,9 +225,14 @@ function Roles.print_to_roles(roles,message)
|
||||
end
|
||||
end
|
||||
|
||||
--- Prints a message to all players who have the given role or one which is higher (excluding default)
|
||||
-- @tparam string role the name of the role to send the message to
|
||||
-- @tparam string message the message to send to the players
|
||||
--[[-- Prints a message to all players who have the given role or one which is higher (excluding default)
|
||||
@tparam string role the name of the role to send the message to
|
||||
@tparam string message the message to send to the players
|
||||
|
||||
@usage-- Print a message to the roles above this role, includes the given role
|
||||
Roles.print_to_roles_higher('Moderator', 'Hello, World!')
|
||||
|
||||
]]
|
||||
function Roles.print_to_roles_higher(role,message)
|
||||
role = Roles.get_role_from_any(role)
|
||||
if not role then return end
|
||||
@@ -234,9 +245,14 @@ function Roles.print_to_roles_higher(role,message)
|
||||
Roles.print_to_roles(roles,message)
|
||||
end
|
||||
|
||||
--- Prints a message to all players who have the given role or one which is lower (excluding default)
|
||||
-- @tparam string role the name of the role to send the message to
|
||||
-- @tparam string message the message to send to the players
|
||||
--[[-- Prints a message to all players who have the given role or one which is lower (excluding default)
|
||||
@tparam string role the name of the role to send the message to
|
||||
@tparam string message the message to send to the players
|
||||
|
||||
@usage-- Print a message to the roles below this role, includes the given role
|
||||
Roles.print_to_roles_higher('Moderator', 'Hello, World!')
|
||||
|
||||
]]
|
||||
function Roles.print_to_roles_lower(role,message)
|
||||
role = Roles.get_role_from_any(role)
|
||||
if not role then return end
|
||||
@@ -249,25 +265,40 @@ function Roles.print_to_roles_lower(role,message)
|
||||
Roles.print_to_roles(roles,message)
|
||||
end
|
||||
|
||||
--- Get a role for the given name
|
||||
-- @tparam string name the name of the role to get
|
||||
-- @treturn Roles._prototype the role with that name or nil
|
||||
--[[-- Get a role for the given name
|
||||
@tparam string name the name of the role to get
|
||||
@treturn Roles._prototype the role with that name or nil
|
||||
|
||||
@usage-- Get a role by its name
|
||||
local role = Roles.get_role_by_name('Moderator')
|
||||
|
||||
]]
|
||||
function Roles.get_role_by_name(name)
|
||||
return Roles.config.roles[name]
|
||||
end
|
||||
|
||||
--- Get a role with the given order index
|
||||
-- @tparam number index the place in the order list of the role to get
|
||||
-- @treturn Roles._prototype the role with that index in the order list or nil
|
||||
--[[-- Get a role with the given order index
|
||||
@tparam number index the place in the order list of the role to get
|
||||
@treturn Roles._prototype the role with that index in the order list or nil
|
||||
|
||||
@usage-- Get a role by its index in the order list
|
||||
local role = Roles.get_role_by_name(2)
|
||||
|
||||
]]
|
||||
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 ?number|string|table any the value used to find the role
|
||||
-- @treturn Roles._prototype the role that was found or nil see above
|
||||
--[[-- 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 ?number|string|table any the value used to find the role
|
||||
@treturn Roles._prototype the role that was found or nil see above
|
||||
|
||||
@usage-- Get a role by its name or order
|
||||
local role = Roles.get_role_from_any('Moderator')
|
||||
|
||||
]]
|
||||
function Roles.get_role_from_any(any)
|
||||
local t_any = type(any)
|
||||
if t_any == 'number' or tonumber(any) then
|
||||
@@ -280,9 +311,14 @@ function Roles.get_role_from_any(any)
|
||||
end
|
||||
end
|
||||
|
||||
--- Gets all the roles of the given player, this will always contain the default role
|
||||
-- @tparam LuaPlayer player the player to get the roles of
|
||||
-- @treturn table a table where the values are the roles which the player has
|
||||
--[[-- Gets all the roles of the given player, this will always contain the default role
|
||||
@tparam LuaPlayer player the player to get the roles of
|
||||
@treturn table a table where the values are the roles which the player has
|
||||
|
||||
@usage-- Get the roles that a player has
|
||||
local roles = Roles.get_player_roles(game.player)
|
||||
|
||||
]]
|
||||
function Roles.get_player_roles(player)
|
||||
player = Game.get_player_from_any(player)
|
||||
if not player then return {Roles.config.roles[Roles.config.internal.root]} end
|
||||
@@ -295,9 +331,14 @@ function Roles.get_player_roles(player)
|
||||
return rtn
|
||||
end
|
||||
|
||||
--- Gets the highest role which the player has, can be used to compeer one player to another
|
||||
-- @tparam LuaPlayer player the player to get the highest role of
|
||||
-- @treturn the role with the highest order index which this player has
|
||||
--[[-- Gets the highest role which the player has, can be used to compeer one player to another
|
||||
@tparam LuaPlayer player the player to get the highest role of
|
||||
@treturn the role with the highest order index which this player has
|
||||
|
||||
@usage-- Get the highest role that a player has
|
||||
local role = Roles.get_player_highest_role(game.player)
|
||||
|
||||
]]
|
||||
function Roles.get_player_highest_role(player)
|
||||
local roles = Roles.get_player_roles(player)
|
||||
if not roles then return end
|
||||
@@ -314,12 +355,20 @@ end
|
||||
-- Functions for changing player's roles
|
||||
-- @section assinment
|
||||
|
||||
--- Gives a player the given role(s) with an option to pass a by player name used in the log
|
||||
-- @tparam LuaPlayer player the player that will be assigned the roles
|
||||
-- @tparam table roles table a of roles that the player will be given, can be one role and can be role names
|
||||
-- @tparam[opt=<server>] string by_player_name the name of the player that will be shown in the log
|
||||
-- @tparam[opt=false] boolean skip_checks when true there will be no checks are done for if the player is valid
|
||||
-- @tparam[opt=false] boolean silent when true there will be no game message printed
|
||||
--[[-- Gives a player the given role(s) with an option to pass a by player name used in the log
|
||||
@tparam LuaPlayer player the player that will be assigned the roles
|
||||
@tparam table roles table a of roles that the player will be given, can be one role and can be role names
|
||||
@tparam[opt=<server>] string by_player_name the name of the player that will be shown in the log
|
||||
@tparam[opt=false] boolean skip_checks when true there will be no checks are done for if the player is valid
|
||||
@tparam[opt=false] boolean silent when true there will be no game message printed
|
||||
|
||||
@usage-- Assign a player to the Moderator role
|
||||
Roles.assign_player(game.player, 'Moderator')
|
||||
|
||||
@usage-- Assign a player to the Moderator role, even if the player has never been on the map
|
||||
Roles.assign_player('Cooldude2606', 'Moderator', nil, true)
|
||||
|
||||
]]
|
||||
function Roles.assign_player(player,roles,by_player_name,skip_checks,silent)
|
||||
local valid_player = Game.get_player_from_any(player)
|
||||
if not skip_checks and not valid_player then return end
|
||||
@@ -337,12 +386,20 @@ function Roles.assign_player(player,roles,by_player_name,skip_checks,silent)
|
||||
end
|
||||
end
|
||||
|
||||
--- Removes a player from the given role(s) with an option to pass a by player name used in the log
|
||||
-- @tparam LuaPlayer player the player that will have the roles removed
|
||||
-- @tparam table roles table a of roles to be removed from the player, can be one role and can be role names
|
||||
-- @tparam[opt=<server>] string by_player_name the name of the player that will be shown in the logs
|
||||
-- @tparam[opt=false] boolean skip_checks when true there will be no checks are done for if the player is valid
|
||||
-- @tparam[opt=false] boolean silent when true there will be no game message printed
|
||||
--[[-- Removes a player from the given role(s) with an option to pass a by player name used in the log
|
||||
@tparam LuaPlayer player the player that will have the roles removed
|
||||
@tparam table roles table a of roles to be removed from the player, can be one role and can be role names
|
||||
@tparam[opt=<server>] string by_player_name the name of the player that will be shown in the logs
|
||||
@tparam[opt=false] boolean skip_checks when true there will be no checks are done for if the player is valid
|
||||
@tparam[opt=false] boolean silent when true there will be no game message printed
|
||||
|
||||
@usage-- Unassign a player from the Moderator role
|
||||
Roles.unassign_player(game.player, 'Moderator')
|
||||
|
||||
@usage-- Unassign a player from the Moderator role, even if the player has never been on the map
|
||||
Roles.unassign_player('Cooldude2606', 'Moderator', nil, true)
|
||||
|
||||
]]
|
||||
function Roles.unassign_player(player,roles,by_player_name,skip_checks,silent)
|
||||
local valid_player = Game.get_player_from_any(player)
|
||||
if not skip_checks and not valid_player then return end
|
||||
@@ -361,20 +418,41 @@ function Roles.unassign_player(player,roles,by_player_name,skip_checks,silent)
|
||||
end
|
||||
end
|
||||
|
||||
--- Overrides all player roles with the given table of roles, useful to mass set roles on game start
|
||||
-- @tparam table roles table a 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
|
||||
--[[-- Overrides all player roles with the given table of roles, useful to mass set roles on game start
|
||||
@tparam[opt] string player_name the player to set the roles for, if not given all roles are overriden
|
||||
@tparam table roles table a which is indexed by case sensitive player names and has the value of a table of role names
|
||||
|
||||
@usage-- Override the roles of a single player, other users are not effected
|
||||
Roles.override_player_roles('Cooldude2606', {'Moderator'})
|
||||
|
||||
@usage-- Override all existing roles, effects all users not just ones listed
|
||||
Roles.override_player_roles{
|
||||
['Cooldude2606'] = {'Administrator','Moderator'},
|
||||
['arty714'] = {'Administrator','Moderator'},
|
||||
}
|
||||
|
||||
]]
|
||||
function Roles.override_player_roles(player_name,roles)
|
||||
if not roles then
|
||||
Roles.config.players = player_name
|
||||
else
|
||||
Roles.config.players[player_name] = roles
|
||||
end
|
||||
end
|
||||
|
||||
--- Checks.
|
||||
-- Functions for checking player's roles
|
||||
-- @section checks
|
||||
|
||||
--- A test for weather a player has the given role
|
||||
-- @tparam LuaPlayer player the player to test the roles of
|
||||
-- @tparam ?string|number|table search_role a pointer to the role that is being searched for
|
||||
-- @treturn boolean true if the player has the role, false otherwise, nil for errors
|
||||
--[[-- A test for weather a player has the given role
|
||||
@tparam LuaPlayer player the player to test the roles of
|
||||
@tparam ?string|number|table search_role a pointer to the role that is being searched for
|
||||
@treturn boolean true if the player has the role, false otherwise, nil for errors
|
||||
|
||||
@usage-- Test if a player has a role
|
||||
local has_role = Roles.player_has_role(game.player, 'Moderator')
|
||||
|
||||
]]
|
||||
function Roles.player_has_role(player,search_role)
|
||||
local roles = Roles.get_player_roles(player)
|
||||
if not roles then return end
|
||||
@@ -386,10 +464,15 @@ function Roles.player_has_role(player,search_role)
|
||||
return false
|
||||
end
|
||||
|
||||
--- A test for weather a player has the given flag true for at least one of they roles
|
||||
-- @tparam LuaPlayer player the player to test the roles of
|
||||
-- @tparam string flag_name 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
|
||||
--[[-- A test for weather a player has the given flag true for at least one of they roles
|
||||
@tparam LuaPlayer player the player to test the roles of
|
||||
@tparam string flag_name 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
|
||||
|
||||
@usage-- Test if a player has a role
|
||||
local has_flag = Roles.player_has_flag(game.player, 'is_donator')
|
||||
|
||||
]]
|
||||
function Roles.player_has_flag(player,flag_name)
|
||||
local roles = Roles.get_player_roles(player)
|
||||
if not roles then return end
|
||||
@@ -401,10 +484,15 @@ function Roles.player_has_flag(player,flag_name)
|
||||
return false
|
||||
end
|
||||
|
||||
--- A test for weather a player has at least one role which is allowed the given action
|
||||
-- @tparam LuaPlayer player the player to test the roles of
|
||||
-- @tparam string action 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
|
||||
--[[-- A test for weather a player has at least one role which is allowed the given action
|
||||
@tparam LuaPlayer player the player to test the roles of
|
||||
@tparam string action 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
|
||||
|
||||
@usage-- Test if a player has a role
|
||||
local has_flag = Roles.player_has_flag(game.player, 'is_donator')
|
||||
|
||||
]]
|
||||
function Roles.player_allowed(player,action)
|
||||
local roles = Roles.get_player_roles(player)
|
||||
if not roles then return end
|
||||
@@ -420,9 +508,20 @@ end
|
||||
-- Functions which are used to define roles
|
||||
-- @section checks
|
||||
|
||||
--- Used to set the role order, higher in the list is better, must be called at least once in config
|
||||
--[[-- 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 table order table a which is keyed only by numbers (start 1) and values are roles in order with highest first
|
||||
@tparam table order table a which is keyed only by numbers (start 1) and values are roles in order with highest first
|
||||
|
||||
@usage-- Define which roles are higher than others
|
||||
Roles.define_role_order{
|
||||
'System',
|
||||
'Administrator',
|
||||
'Moderator',
|
||||
'Donator',
|
||||
'Guest'
|
||||
}
|
||||
|
||||
]]
|
||||
function Roles.define_role_order(order)
|
||||
-- Clears and then rebuilds the order table
|
||||
_C.error_if_runtime()
|
||||
@@ -457,26 +556,41 @@ function Roles.define_role_order(order)
|
||||
end
|
||||
end
|
||||
|
||||
--- Defines a new trigger for when a tag is added or removed from a player
|
||||
-- @tparam string name the name of the flag which the roles will have
|
||||
-- @tparam function callback the function that is called when roles are assigned
|
||||
-- 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
|
||||
--[[-- Defines a new trigger for when a tag is added or removed from a player
|
||||
@tparam string name the name of the flag which the roles will have
|
||||
@tparam function callback the function that is called when roles are assigned
|
||||
|
||||
@usage-- Defineing a flag trigger
|
||||
Roles.define_flag_trigger('is_donator', function(player, state)
|
||||
player.character_running_speed_modifier = state and 1.5 or 1
|
||||
end)
|
||||
|
||||
]]
|
||||
function Roles.define_flag_trigger(name,callback)
|
||||
_C.error_if_runtime()
|
||||
Roles.config.flags[name] = Async.register(callback)
|
||||
end
|
||||
|
||||
--- Sets the default role which every player will have, this needs to be called at least once
|
||||
-- @tparam string name the name of the default role
|
||||
--[[-- Sets the default role which every player will have, this needs to be called at least once
|
||||
@tparam string name the name of the default role
|
||||
|
||||
@usage-- Setting the default role
|
||||
Roles.set_default('Guest')
|
||||
|
||||
]]
|
||||
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 string name the name of the root role
|
||||
--[[-- Sets the root role which will always have all permissions, any server actions act from this role
|
||||
@tparam string name the name of the root role
|
||||
|
||||
@usage-- Setting the root role
|
||||
Roles.set_root('System')
|
||||
|
||||
]]
|
||||
function Roles.set_root(name)
|
||||
local role = Roles.config.roles[name]
|
||||
if not role then return end
|
||||
@@ -484,10 +598,15 @@ function Roles.set_root(name)
|
||||
Roles.config.internal.root = name
|
||||
end
|
||||
|
||||
--- Defines a new role and returns the prototype to allow configuration
|
||||
-- @tparam string name the name of the new role, must be unique
|
||||
-- @tparam[opt=name] string short_hand the shortened version of the name
|
||||
-- @treturn Roles._prototype the start of the config chain for this role
|
||||
--[[-- Defines a new role and returns the prototype to allow configuration
|
||||
@tparam string name the name of the new role, must be unique
|
||||
@tparam[opt=name] string short_hand the shortened version of the name
|
||||
@treturn Roles._prototype the start of the config chain for this role
|
||||
|
||||
@usage-- Defineing a new role
|
||||
local role = Roles.new_role('Moderator', 'Mod')
|
||||
|
||||
]]
|
||||
function Roles.new_role(name,short_hand)
|
||||
_C.error_if_runtime()
|
||||
if Roles.config.roles[name] then return error('Role name is non unique') end
|
||||
@@ -506,18 +625,31 @@ end
|
||||
-- Functions for using the role action system
|
||||
-- @section actions
|
||||
|
||||
--- Sets the default allow state of the role, true will allow all actions
|
||||
-- @tparam[opt=true] boolean state true will allow all actions
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
--[[-- Sets the default allow state of the role, true will allow all actions
|
||||
@tparam[opt=true] boolean state true will allow all actions
|
||||
@treturn Roles._prototype allows chaining
|
||||
|
||||
@usage-- Allow all actions for this role, useful for root like roles
|
||||
role:set_allow_all()
|
||||
|
||||
]]
|
||||
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 table actions indexed with numbers and is an array of action names, order has no effect
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
--[[-- Sets the allow actions for this role, actions in this list will be allowed for this role
|
||||
@tparam table actions indexed with numbers and is an array of action names, order has no effect
|
||||
@treturn Roles._prototype allows chaining
|
||||
|
||||
@usage-- Allow some actions for a role
|
||||
role:allow{
|
||||
'command/kill',
|
||||
'gui/game settings'
|
||||
}
|
||||
|
||||
]]
|
||||
function Roles._prototype:allow(actions)
|
||||
if type(actions) ~= 'table' then
|
||||
actions = {actions}
|
||||
@@ -528,9 +660,17 @@ function Roles._prototype:allow(actions)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets the disallow actions for this role, will prevent actions from being allowed regardless of inheritance
|
||||
-- @tparam table actions indexed with numbers and is an array of action names, order has no effect
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
--[[-- Sets the disallow actions for this role, will prevent actions from being allowed regardless of inheritance
|
||||
@tparam table actions indexed with numbers and is an array of action names, order has no effect
|
||||
@treturn Roles._prototype allows chaining
|
||||
|
||||
@usage-- Disalow an action for a role, useful if inherit an action from a parent
|
||||
role:disallow{
|
||||
'command/kill',
|
||||
'gui/game settings'
|
||||
}
|
||||
|
||||
]]
|
||||
function Roles._prototype:disallow(actions)
|
||||
if type(actions) ~= 'table' then
|
||||
actions = {actions}
|
||||
@@ -541,9 +681,14 @@ function Roles._prototype:disallow(actions)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Test for if a role is allowed the given action, mostly internal see Roles.player_allowed
|
||||
-- @tparam string action the name of the action to test if it is allowed
|
||||
-- @treturn boolean true if action is allowed, false otherwise
|
||||
--[[-- Test for if a role is allowed the given action, mostly internal see Roles.player_allowed
|
||||
@tparam string action the name of the action to test if it is allowed
|
||||
@treturn boolean true if action is allowed, false otherwise
|
||||
|
||||
@usage-- Test if a role is allowed an action
|
||||
local allowed = role:is_allowed('command/kill')
|
||||
|
||||
]]
|
||||
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
|
||||
@@ -553,26 +698,41 @@ end
|
||||
-- Functions for using the role flag system
|
||||
-- @section flags
|
||||
|
||||
--- Sets the state of a flag for a role, flags can be used to apply effects to players
|
||||
-- @tparam string name the name of the flag to set the value of
|
||||
-- @tparam[opt=true] boolean value the state to set the flag to
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
--[[-- Sets the state of a flag for a role, flags can be used to apply effects to players
|
||||
@tparam string name the name of the flag to set the value of
|
||||
@tparam[opt=true] boolean value the state to set the flag to
|
||||
@treturn Roles._prototype allows chaining
|
||||
|
||||
@usage-- Set a flag for a role
|
||||
role:set_flag('is_admin')
|
||||
|
||||
]]
|
||||
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
|
||||
--[[-- Clears all flags from this role, individual flags can be removed with set_flag(name,false)
|
||||
@treturn Roles._prototype allows chaining
|
||||
|
||||
@usage-- Remove all flags from a role
|
||||
role:clear_flags()
|
||||
|
||||
]]
|
||||
function Roles._prototype:clear_flags()
|
||||
self.flags = {}
|
||||
return self
|
||||
end
|
||||
|
||||
--- A test for if the role has a flag set
|
||||
-- @tparam string name the name of the flag to test for
|
||||
-- @treturn boolean true if the flag is set, false otherwise
|
||||
--[[-- A test for if the role has a flag set
|
||||
@tparam string name the name of the flag to test for
|
||||
@treturn boolean true if the flag is set, false otherwise
|
||||
|
||||
@usage-- Test if a role has a flag
|
||||
local has_flag = role:has_flag('is_admin')
|
||||
|
||||
]]
|
||||
function Roles._prototype:has_flag(name)
|
||||
return self.flags[name] or false
|
||||
end
|
||||
@@ -581,17 +741,27 @@ end
|
||||
-- Functions for chaning other proerties
|
||||
-- @section properties
|
||||
|
||||
--- Sets a custom player tag for the role, can be accessed by other code
|
||||
-- @tparam string tag the value that the tag will be
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
--[[-- Sets a custom player tag for the role, can be accessed by other code
|
||||
@tparam string tag the value that the tag will be
|
||||
@treturn Roles._prototype allows chaining
|
||||
|
||||
@usage-- Set a custom tag for this role, other code is required to set the tag
|
||||
role:set_custom_tag('Mod')
|
||||
|
||||
]]
|
||||
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 table color ?string|table can either be and rgb colour or the name of a colour defined in the presets
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
--[[-- Sets a custom colour for the role, can be accessed by other code
|
||||
@tparam table color ?string|table can either be and rgb colour or the name of a colour defined in the presets
|
||||
@treturn Roles._prototype allows chaining
|
||||
|
||||
@usage-- Set a custom colour for this role, other code is required to use this value
|
||||
role:set_custom_color{ r=255, g=100, b=100}
|
||||
|
||||
]]
|
||||
function Roles._prototype:set_custom_color(color)
|
||||
if type(color) ~= 'table' then
|
||||
color = Colours[color]
|
||||
@@ -600,10 +770,15 @@ function Roles._prototype:set_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 string name the name of the permission group to have players moved to
|
||||
-- @tparam[opt=false] boolean use_factorio_api when true the custom permission group module is ignored
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
--[[-- Sets the permission group for this role, players will be moved to the group of they highest role
|
||||
@tparam string name the name of the permission group to have players moved to
|
||||
@tparam[opt=false] boolean use_factorio_api when true the custom permission group module is ignored
|
||||
@treturn Roles._prototype allows chaining
|
||||
|
||||
@usage-- Set the permission group for this role, see permission_groups.lua
|
||||
role:set_permission_group('Admin')
|
||||
|
||||
]]
|
||||
function Roles._prototype:set_permission_group(name,use_factorio_api)
|
||||
_C.error_if_runtime()
|
||||
if use_factorio_api then
|
||||
@@ -616,10 +791,15 @@ function Roles._prototype:set_permission_group(name,use_factorio_api)
|
||||
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 string role the name of the role that will be the parent; has imminent effect if role is already defined
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
--[[-- 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 string role the name of the role that will be the parent; has imminent effect if role is already defined
|
||||
@treturn Roles._prototype allows chaining
|
||||
|
||||
@usage-- Set the parent for this role to inherit all actions allowed
|
||||
role:set_parent('Guest')
|
||||
|
||||
]]
|
||||
function Roles._prototype:set_parent(role)
|
||||
_C.error_if_runtime()
|
||||
self.parent = role
|
||||
@@ -629,19 +809,31 @@ function Roles._prototype:set_parent(role)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets an auto promote condition that is checked every 5 seconds, if true is returned then the player will receive the role
|
||||
-- nb: this is one way, failing false after already gaining the role will not revoke the role
|
||||
-- @tparam function callback 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)
|
||||
--[[-- Sets an auto assign condition that is checked every 60 seconds, if true is returned then the player will receive the role
|
||||
nb: this is one way, failing false after already gaining the role will not revoke the role
|
||||
@tparam function callback receives only one param which is player to promote, return true to promote the player
|
||||
@treturn Roles._prototype allows chaining
|
||||
|
||||
@usage-- Give this role to a user if there are admin, ran every 60 seconds
|
||||
role:set_auto_assign_condition(function(player)
|
||||
return player.admin
|
||||
end)
|
||||
|
||||
]]
|
||||
function Roles._prototype:set_auto_assign_condition(callback)
|
||||
_C.error_if_runetime_closure(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] boolean state when true the players with this role will not be auto promoted
|
||||
-- @treturn Roles._prototype allows chaining
|
||||
--[[-- Sets the role to not allow players to have auto assign effect them, useful to keep people locked to a role
|
||||
@tparam[opt=true] boolean state when true the players with this role will not be auto assigned to other roles
|
||||
@treturn Roles._prototype allows chaining
|
||||
|
||||
@usage-- Make a role stop players from being auto assigned to other roles
|
||||
role:set_block_auto_promote()
|
||||
|
||||
]]
|
||||
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
|
||||
@@ -652,11 +844,16 @@ end
|
||||
-- Functions that control players in a role
|
||||
-- @section players
|
||||
|
||||
--- Adds a player to this role, players can have more than one role at a time, used internally see Roles.assign
|
||||
-- @tparam LuaPlayer player the player that will be given this role
|
||||
-- @tparam boolean skip_check when true player will be taken as the player name (use when player has not yet joined)
|
||||
-- @tparam boolean skip_event when true the event emit will be skipped, this is used internally with Roles.assign
|
||||
-- @treturn boolean true if the player was added successfully
|
||||
--[[-- Adds a player to this role, players can have more than one role at a time, used internally see Roles.assign
|
||||
@tparam LuaPlayer player the player that will be given this role
|
||||
@tparam boolean skip_check when true player will be taken as the player name (use when player has not yet joined)
|
||||
@tparam boolean skip_event when true the event emit will be skipped, this is used internally with Roles.assign
|
||||
@treturn boolean true if the player was added successfully
|
||||
|
||||
@usage-- Assign a player to this role
|
||||
role:add_player(game.player)
|
||||
|
||||
]]
|
||||
function Roles._prototype:add_player(player,skip_check,skip_event)
|
||||
player = Game.get_player_from_any(player)
|
||||
-- Default role cant have players added or removed
|
||||
@@ -686,11 +883,16 @@ function Roles._prototype:add_player(player,skip_check,skip_event)
|
||||
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 LuaPlayer player the player that will lose this role
|
||||
-- @tparam boolean skip_check when true player will be taken as the player name (use when player has not yet joined)
|
||||
-- @tparam boolean skip_event when true the event emit will be skipped, this is used internally with Roles.unassign
|
||||
-- @treturn boolean true if the player was removed successfully
|
||||
--[[-- Removes a player from this role, players can have more than one role at a time, used internally see Roles.unassign
|
||||
@tparam LuaPlayer player the player that will lose this role
|
||||
@tparam boolean skip_check when true player will be taken as the player name (use when player has not yet joined)
|
||||
@tparam boolean skip_event when true the event emit will be skipped, this is used internally with Roles.unassign
|
||||
@treturn boolean true if the player was removed successfully
|
||||
|
||||
@usage-- Unassign a player from this role
|
||||
role:remove_player(game.player)
|
||||
|
||||
]]
|
||||
function Roles._prototype:remove_player(player,skip_check,skip_event)
|
||||
player = Game.get_player_from_any(player)
|
||||
-- Default role cant have players added or removed
|
||||
@@ -725,9 +927,17 @@ function Roles._prototype:remove_player(player,skip_check,skip_event)
|
||||
return rtn
|
||||
end
|
||||
|
||||
--- Returns an array of all the players who have this role, can be filtered by online status
|
||||
-- @tparam[opt=nil] boolean online 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
|
||||
--[[-- Returns an array of all the players who have this role, can be filtered by online status
|
||||
@tparam[opt=nil] boolean online 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
|
||||
|
||||
@usage-- Get all the players with this role
|
||||
local players = role:get_players()
|
||||
|
||||
@usage-- Get all online players with this role
|
||||
local players = role:get_players(true)
|
||||
|
||||
]]
|
||||
function Roles._prototype:get_players(online)
|
||||
local players = {}
|
||||
-- Gets all players that have this role
|
||||
@@ -756,9 +966,14 @@ function Roles._prototype:get_players(online)
|
||||
end
|
||||
end
|
||||
|
||||
--- Will print a message to all players with this role
|
||||
-- @tparam string message the message that will be printed to the players
|
||||
-- @treturn number the number of players who received the message
|
||||
--[[-- Will print a message to all players with this role
|
||||
@tparam string message the message that will be printed to the players
|
||||
@treturn number the number of players who received the message
|
||||
|
||||
@usage-- Print a message to all players with this role
|
||||
role:print('Hello, World!')
|
||||
|
||||
]]
|
||||
function Roles._prototype:print(message)
|
||||
local players = self:get_players(true)
|
||||
for _,player in pairs(players) do
|
||||
|
||||
Reference in New Issue
Block a user