mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-30 20:41:41 +09:00
Removed useless files
This commit is contained in:
@@ -12,8 +12,8 @@ local Game = require 'utils.game' --- @dep utils.game
|
|||||||
local Reports = require 'modules.control.reports' --- @dep modules.control.reports
|
local Reports = require 'modules.control.reports' --- @dep modules.control.reports
|
||||||
local Warnings = require 'modules.control.warnings' --- @dep modules.control.warnings
|
local Warnings = require 'modules.control.warnings' --- @dep modules.control.warnings
|
||||||
local Jail = require 'modules.control.jail' --- @dep modules.control.jail
|
local Jail = require 'modules.control.jail' --- @dep modules.control.jail
|
||||||
local Colors = require 'resources.color_presets' --- @dep resources.color_presets
|
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
|
local format_chat_player_name = _C.ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
|
||||||
|
|
||||||
local selected_player_store = ''
|
local selected_player_store = ''
|
||||||
local selected_action_store = ''
|
local selected_action_store = ''
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
-- @config Chat-Reply
|
-- @config Chat-Reply
|
||||||
|
|
||||||
local Async = require 'expcore.async'
|
local Async = require 'expcore.async'
|
||||||
local format_time = ext_require('expcore.common','format_time') --- @dep expcore.common
|
local format_time = _C.ext_require('expcore.common','format_time') --- @dep expcore.common
|
||||||
|
|
||||||
local async_message = Async.register(function(player, message)
|
local async_message = Async.register(function(player, message)
|
||||||
player.print(message)
|
player.print(message)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
||||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||||
local auto_complete = ext_require('expcore.common','auto_complete') --- @dep expcore.common
|
local auto_complete = _C.ext_require('expcore.common','auto_complete') --- @dep expcore.common
|
||||||
require 'config.expcore-commands.parse_general'
|
require 'config.expcore-commands.parse_general'
|
||||||
|
|
||||||
Commands.add_parse('role',function(input,player,reject)
|
Commands.add_parse('role',function(input,player,reject)
|
||||||
|
|||||||
27
control.lua
27
control.lua
@@ -5,24 +5,17 @@
|
|||||||
-- this file is the landing point for all scenarios please DO NOT edit directly, further comments are to aid development
|
-- this file is the landing point for all scenarios please DO NOT edit directly, further comments are to aid development
|
||||||
|
|
||||||
log('[START] -----| Explosive Gaming Scenario Loader |-----')
|
log('[START] -----| Explosive Gaming Scenario Loader |-----')
|
||||||
|
|
||||||
-- Info on the data lifecycle and how we use it: https://github.com/Refactorio/RedMew/wiki/The-data-lifecycle
|
|
||||||
log('[INFO] Setting up lua environment')
|
log('[INFO] Setting up lua environment')
|
||||||
require 'resources.data_stages'
|
|
||||||
_LIFECYCLE = _STAGE.control -- Control stage
|
|
||||||
|
|
||||||
-- Overrides the _G.print function
|
-- Require the global overrides
|
||||||
require 'utils.print_override'
|
require 'overrides.stages' -- Data stages used in factorio, often used to test for runtime
|
||||||
|
require 'overrides.print' -- Overrides the _G.print function
|
||||||
-- Omitting the math library is a very bad idea
|
require 'overrides.math' -- Omitting the math library is a very bad idea
|
||||||
require 'utils.math'
|
require 'overrides.table' -- Adds alot more functions to the table module
|
||||||
|
inspect = require 'overrides.inspect' -- Used to covert any value into human readable string
|
||||||
-- Global Debug and make sure our version file is registered
|
Debug = require 'overrides.debug' -- Global Debug module
|
||||||
Debug = require 'utils.debug' --- @dep utils.debug
|
_C = require('expcore.common') -- _C is used to store lots of common functions expected to be used
|
||||||
require 'resources.version'
|
global.expgaming_version = '6.0.0' -- The current version for exp gaming scenario
|
||||||
|
|
||||||
-- Global require function used to extract parts of a module, because simply being in common is not good enough
|
|
||||||
ext_require = require('expcore.common').ext_require --- @dep expcore.common.ext_require
|
|
||||||
|
|
||||||
-- Please go to config/file_loader.lua to edit the files that are loaded
|
-- Please go to config/file_loader.lua to edit the files that are loaded
|
||||||
log('[INFO] Getting file loader config')
|
log('[INFO] Getting file loader config')
|
||||||
@@ -52,7 +45,7 @@ end
|
|||||||
|
|
||||||
-- Override the default require; require can no longer load new scripts
|
-- Override the default require; require can no longer load new scripts
|
||||||
log('[INFO] Require Overright! No more requires can be made!')
|
log('[INFO] Require Overright! No more requires can be made!')
|
||||||
require 'utils.require_override'
|
require 'overrides.require'
|
||||||
|
|
||||||
-- Logs all errors again to make it make it easy to find
|
-- Logs all errors again to make it make it easy to find
|
||||||
log('[INFO] All files loaded with '..#errors..' errors:')
|
log('[INFO] All files loaded with '..#errors..' errors:')
|
||||||
|
|||||||
@@ -196,7 +196,7 @@
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
local Game = require 'utils.game' --- @dep utils.game
|
local Game = require 'utils.game' --- @dep utils.game
|
||||||
local player_return,write_json = ext_require('expcore.common','player_return','write_json') --- @dep expcore.common
|
local player_return,write_json = _C.ext_require('expcore.common','player_return','write_json') --- @dep expcore.common
|
||||||
|
|
||||||
local Commands = {
|
local Commands = {
|
||||||
defines={ -- common values are stored error like signals
|
defines={ -- common values are stored error like signals
|
||||||
|
|||||||
@@ -4,52 +4,276 @@
|
|||||||
@alias Common
|
@alias Common
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local Colours = require 'resources.color_presets' --- @dep resources.color_presets
|
local Colours = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local Game = require 'utils.game' --- @dep utils.game
|
local Game = require 'utils.game' --- @dep utils.game
|
||||||
local Util = require 'util' --- @dep util
|
local Util = require 'util' --- @dep util
|
||||||
require 'utils.table'
|
require 'overrides.table'
|
||||||
require 'utils.math'
|
require 'overrides.math'
|
||||||
|
|
||||||
local Common = {}
|
local Common = {}
|
||||||
|
|
||||||
--- Compare types faster for faster validation of params
|
--- Type Checking.
|
||||||
|
-- @section typeCheck
|
||||||
|
|
||||||
|
--- Asserts the argument is of type test_type
|
||||||
-- @usage type_check('foo','string') -- return true
|
-- @usage type_check('foo','string') -- return true
|
||||||
-- @usage type_check('foo') -- return false
|
-- @usage type_check('foo') -- return false
|
||||||
-- @tparam any value the value to be tested
|
-- @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
|
-- @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
|
-- @treturn boolean is v of type test_type
|
||||||
function Common.type_check(value,test_type)
|
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
|
return test_type and value and type(value) == test_type or not test_type and not value or false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Raises an error if the value is of the wrong type
|
--- Raises an error if the value is of the wrong type
|
||||||
-- @usage type_check_error('foo','number','Value must be a number') -- will raise error "Value must be a number"
|
-- @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 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 test_type the type that the value should be
|
||||||
-- @tparam string error_message the error message that is returned
|
-- @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)
|
-- @tparam number level the level to call the error on (level = 1 means the caller)
|
||||||
-- @treturn boolean true if no error was called
|
-- @treturn boolean true if no error was called
|
||||||
function Common.type_check_error(value,test_type,error_message,level)
|
function Common.type_error(value, test_type, error_message, level)
|
||||||
level = level and level+1 or 2
|
level = level and level+1 or 2
|
||||||
return Common.test_type(value,test_type) or error(error_message,level)
|
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
|
||||||
|
function Common.multi_type_check(value, test_types)
|
||||||
|
local vtype = type(value)
|
||||||
|
for _, arg_type in ipairs(test_types) do
|
||||||
|
if vtype == arg_type then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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
|
||||||
|
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
|
end
|
||||||
|
|
||||||
--- Raises an error when the value is the incorrect type, uses a consistent error message format
|
--- Raises an error when the value is the incorrect type, uses a consistent error message format
|
||||||
-- @usage param_check('foo','number','repeat_count',2) -- will raise error "Invalid param #02 given to <anon>; repeat_count is not of type number"
|
-- @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 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 test_type the type that the value should be
|
||||||
-- @tparam string param_name the name of the param
|
-- @tparam string param_name the name of the param
|
||||||
-- @tparam number param_number the number param it is
|
-- @tparam number param_number the number param it is
|
||||||
-- @treturn boolean true if no error was raised
|
-- @treturn boolean true if no error was raised
|
||||||
function Common.param_check(value,test_type,param_name,param_number)
|
function Common.validate_argument_type(value, test_type, param_name, param_number)
|
||||||
if not Common.test_type(value,test_type) then
|
if not Common.test_type(value,test_type) then
|
||||||
local function_name = debug.getinfo(2,'n').name or '<anon>'
|
local function_name = debug.getinfo(2,'n').name or '<anon>'
|
||||||
local error_message = string.format('Invalid param #%2d given to %s; %s is not of type %s',param_number,function_name,param_name,test_type)
|
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)
|
||||||
return error(error_message,3)
|
return error(error_message,3)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
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)
|
||||||
|
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 '))
|
||||||
|
return error(error_message,3)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
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
|
||||||
|
function Common.string_contains(s, contains)
|
||||||
|
return s and string.find(s, contains) ~= nil
|
||||||
|
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)
|
||||||
|
]]
|
||||||
|
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>'
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Converts a varible into its boolean value, nil and false return false
|
||||||
|
-- @treturn boolean the boolean form of the varible
|
||||||
|
function Common.cast_bool(var)
|
||||||
|
return var and true or false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns either the second or third argument based on the first argument
|
||||||
|
function Common.ternary(c, t, f)
|
||||||
|
return c and t or f
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns a string for a number with comma seperators
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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
|
||||||
|
function Common.opt_require(path)
|
||||||
|
local success, rtn = pcall(require,path)
|
||||||
|
if success then return rtn
|
||||||
|
else return nil,rtn end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Calls a require and returns only the keys given, file must return a table
|
||||||
|
-- @usage local extract, param_check = _C.ext_require('expcore.common','extract','param_check') --- @dep expcore.common
|
||||||
|
-- @tparam string path the path that you want to require
|
||||||
|
-- @tparam string ... the name of the keys that you want returned
|
||||||
|
-- @return the keys in the order given
|
||||||
|
function Common.ext_require(path,...)
|
||||||
|
local rtn = require(path)
|
||||||
|
if type(rtn) ~= 'table' then
|
||||||
|
error('File did not return a table, can not extract keys.',2)
|
||||||
|
end
|
||||||
|
return table.extract_keys(rtn,...)
|
||||||
|
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
|
||||||
|
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
|
||||||
|
function Common.enum(tbl)
|
||||||
|
local rtn = {}
|
||||||
|
for k,v in pairs(tbl) do
|
||||||
|
if type(k) ~= 'number' then
|
||||||
|
rtn[v]=k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for k,v in pairs(tbl) do
|
||||||
|
if type(k) == 'number' then
|
||||||
|
table.insert(rtn,v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for k,v in pairs(rtn) do
|
||||||
|
rtn[v]=k
|
||||||
|
end
|
||||||
|
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
|
||||||
|
function Common.auto_complete(options,input,use_key,rtn_key)
|
||||||
|
local rtn = {}
|
||||||
|
if type(input) ~= 'string' then return end
|
||||||
|
input = input:lower()
|
||||||
|
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)
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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>'
|
||||||
|
local player_chat_colour = player and player.chat_color or Colours.white
|
||||||
|
if raw_string then
|
||||||
|
return Common.format_chat_colour(player_name,player_chat_colour)
|
||||||
|
else
|
||||||
|
return Common.format_chat_colour_localized(player_name,player_chat_colour)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Will return a value of any type to the player/server console, allows colour for in-game players
|
--- 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!') -- 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!','green') -- returns 'Hello, World!' to game.player with colour green or server console
|
||||||
@@ -91,36 +315,6 @@ function Common.player_return(value,colour,player)
|
|||||||
else rcon.print(returnAsString) end
|
else rcon.print(returnAsString) end
|
||||||
end
|
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
|
|
||||||
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
|
|
||||||
function Common.opt_require(path)
|
|
||||||
local success, rtn = pcall(require,path)
|
|
||||||
if success then return rtn
|
|
||||||
else return nil,rtn end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Calls a require and returns only the keys given, file must return a table
|
|
||||||
-- @usage local extract, param_check = ext_require('expcore.common','extract','param_check') --- @dep expcore.common
|
|
||||||
-- @tparam string path the path that you want to require
|
|
||||||
-- @tparam string ... the name of the keys that you want returned
|
|
||||||
-- @return the keys in the order given
|
|
||||||
function Common.ext_require(path,...)
|
|
||||||
local rtn = require(path)
|
|
||||||
if type(rtn) ~= 'table' then
|
|
||||||
error('File did not return a table, can not extract keys.',2)
|
|
||||||
end
|
|
||||||
return Common.extract_keys(rtn,...)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Formats tick into a clean format, denominations from highest to lowest
|
--- Formats tick into a clean format, denominations from highest to lowest
|
||||||
-- long will use words rather than letters
|
-- long will use words rather than letters
|
||||||
-- time will use : separates
|
-- time will use : separates
|
||||||
@@ -213,6 +407,9 @@ function Common.format_time(ticks,options)
|
|||||||
return rtn
|
return rtn
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Factorio.
|
||||||
|
-- @section factorio
|
||||||
|
|
||||||
--- Moves items to the position and stores them in the closest entity of the type given
|
--- 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 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=navies] LuaSurface surface the surface that the items will be moved to
|
||||||
@@ -416,288 +613,4 @@ function Common.clear_flying_text(surface)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- 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
|
|
||||||
function Common.string_contains(s, contains)
|
|
||||||
return s and string.find(s, contains) ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Extracts certain keys from a table
|
|
||||||
-- @usage local key_three, key_one = extract({key_one='foo',key_two='bar',key_three=true},'key_three','key_one')
|
|
||||||
-- @tparam table tbl table the which contains the keys
|
|
||||||
-- @tparam string ... the names of the keys you want extracted
|
|
||||||
-- @return the keys in the order given
|
|
||||||
function Common.extract_keys(tbl,...)
|
|
||||||
local values = {}
|
|
||||||
for _,key in pairs({...}) do
|
|
||||||
table.insert(values,tbl[key])
|
|
||||||
end
|
|
||||||
return unpack(values)
|
|
||||||
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
|
|
||||||
function Common.enum(tbl)
|
|
||||||
local rtn = {}
|
|
||||||
for k,v in pairs(tbl) do
|
|
||||||
if type(k) ~= 'number' then
|
|
||||||
rtn[v]=k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for k,v in pairs(tbl) do
|
|
||||||
if type(k) == 'number' then
|
|
||||||
table.insert(rtn,v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for k,v in pairs(rtn) do
|
|
||||||
rtn[v]=k
|
|
||||||
end
|
|
||||||
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
|
|
||||||
function Common.auto_complete(options,input,use_key,rtn_key)
|
|
||||||
local rtn = {}
|
|
||||||
if type(input) ~= 'string' then return end
|
|
||||||
input = input:lower()
|
|
||||||
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)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return rtn[1]
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Default table comparator sort function.
|
|
||||||
-- @local
|
|
||||||
-- @param x one comparator operand
|
|
||||||
-- @param y the other comparator operand
|
|
||||||
-- @return true if x logically comes before y in a list, false otherwise
|
|
||||||
local function sortFunc(x, y) --sorts tables with mixed index types.
|
|
||||||
local tx = type(x)
|
|
||||||
local ty = type(y)
|
|
||||||
if tx == ty then
|
|
||||||
if type(x) == 'string' then
|
|
||||||
return string.lower(x) < string.lower(y)
|
|
||||||
else
|
|
||||||
return x < y
|
|
||||||
end
|
|
||||||
elseif tx == 'number' then
|
|
||||||
return true --only x is a number and goes first
|
|
||||||
else
|
|
||||||
return false --only y is a number and goes first
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns a copy of all of the values in the table.
|
|
||||||
-- @tparam table tbl the to copy the keys from, or an empty table if tbl is nil
|
|
||||||
-- @tparam[opt] boolean sorted whether to sort the keys (slower) or keep the random order from pairs()
|
|
||||||
-- @tparam[opt] boolean as_string whether to try and parse the values as strings, or leave them as their existing type
|
|
||||||
-- @treturn array an array with a copy of all the values in the table
|
|
||||||
function Common.table_values(tbl, sorted, as_string)
|
|
||||||
if not tbl then return {} end
|
|
||||||
local valueset = {}
|
|
||||||
local n = 0
|
|
||||||
if as_string then --checking as_string /before/ looping is faster
|
|
||||||
for _, v in pairs(tbl) do
|
|
||||||
n = n + 1
|
|
||||||
valueset[n] = tostring(v)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
for _, v in pairs(tbl) do
|
|
||||||
n = n + 1
|
|
||||||
valueset[n] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if sorted then
|
|
||||||
table.sort(valueset,sortFunc)
|
|
||||||
end
|
|
||||||
return valueset
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns a copy of all of the keys in the table.
|
|
||||||
-- @tparam table tbl the to copy the keys from, or an empty table if tbl is nil
|
|
||||||
-- @tparam[opt] boolean sorted whether to sort the keys (slower) or keep the random order from pairs()
|
|
||||||
-- @tparam[opt] boolean as_string whether to try and parse the keys as strings, or leave them as their existing type
|
|
||||||
-- @treturn array an array with a copy of all the keys in the table
|
|
||||||
function Common.table_keys(tbl, sorted, as_string)
|
|
||||||
if not tbl then return {} end
|
|
||||||
local keyset = {}
|
|
||||||
local n = 0
|
|
||||||
if as_string then --checking as_string /before/ looping is faster
|
|
||||||
for k, _ in pairs(tbl) do
|
|
||||||
n = n + 1
|
|
||||||
keyset[n] = tostring(k)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
for k, _ in pairs(tbl) do
|
|
||||||
n = n + 1
|
|
||||||
keyset[n] = k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if sorted then
|
|
||||||
table.sort(keyset,sortFunc)
|
|
||||||
end
|
|
||||||
return keyset
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns the list is a sorted way that would be expected by people (this is by key)
|
|
||||||
-- @tparam table tbl the table to be sorted
|
|
||||||
-- @treturn table the sorted table
|
|
||||||
function Common.table_alphanumsort(tbl)
|
|
||||||
local o = Common.table_keys(tbl)
|
|
||||||
local function padnum(d) local dec, n = string.match(d, "(%.?)0*(.+)")
|
|
||||||
return #dec > 0 and ("%.12f"):format(d) or ("%s%03d%s"):format(dec, #n, n) end
|
|
||||||
table.sort(o, function(a,b)
|
|
||||||
return tostring(a):gsub("%.?%d+",padnum)..("%3d"):format(#b)
|
|
||||||
< tostring(b):gsub("%.?%d+",padnum)..("%3d"):format(#a) end)
|
|
||||||
local _tbl = {}
|
|
||||||
for _,k in pairs(o) do _tbl[k] = tbl[k] end
|
|
||||||
return _tbl
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns the list is a sorted way that would be expected by people (this is by key) (faster alternative than above)
|
|
||||||
-- @tparam table tbl the table to be sorted
|
|
||||||
-- @treturn table the sorted table
|
|
||||||
function Common.table_keysort(tbl)
|
|
||||||
local o = Common.table_keys(tbl,true)
|
|
||||||
local _tbl = {}
|
|
||||||
for _,k in pairs(o) do _tbl[k] = tbl[k] end
|
|
||||||
return _tbl
|
|
||||||
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
|
|
||||||
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
|
|
||||||
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
|
|
||||||
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>'
|
|
||||||
local player_chat_colour = player and player.chat_color or Colours.white
|
|
||||||
if raw_string then
|
|
||||||
return Common.format_chat_colour(player_name,player_chat_colour)
|
|
||||||
else
|
|
||||||
return Common.format_chat_colour_localized(player_name,player_chat_colour)
|
|
||||||
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
|
|
||||||
function Common.get_file_path(offset)
|
|
||||||
offset = offset or 0
|
|
||||||
return debug.getinfo(offset+2, 'S').source:match('^.+/currently%-playing/(.+)$'):sub(1, -5)
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[-- Much faster method for inserting items into an array
|
|
||||||
@tparam table tbl the table that will have the values added to it
|
|
||||||
@tparam[opt] number start_index the index at which values will be added, nil means end of the array
|
|
||||||
@tparam table values the new values that will be added to the table
|
|
||||||
@treturn table the table that was passed as the first argument
|
|
||||||
@usage-- Adding 1000 values into the middle of the array
|
|
||||||
local tbl = {}
|
|
||||||
local values = {}
|
|
||||||
for i = 1,1000 do tbl[i] = i values[i] = i end
|
|
||||||
Common.array_insert(tbl,500,values) -- around 0.4ms
|
|
||||||
]]
|
|
||||||
function Common.array_insert(tbl,start_index,values)
|
|
||||||
if not values then
|
|
||||||
values = start_index
|
|
||||||
start_index = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if start_index then
|
|
||||||
local starting_length = #tbl
|
|
||||||
local adding_length = #values
|
|
||||||
local move_to = start_index+adding_length+1
|
|
||||||
for offset = starting_length-start_index, 0, -1 do
|
|
||||||
tbl[move_to+offset] = tbl[starting_length+offset]
|
|
||||||
end
|
|
||||||
start_index = start_index-1
|
|
||||||
else
|
|
||||||
start_index = #tbl
|
|
||||||
end
|
|
||||||
|
|
||||||
for offset, item in ipairs(values) do
|
|
||||||
tbl[start_index+offset] = item
|
|
||||||
end
|
|
||||||
|
|
||||||
return tbl
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[-- Much faster method for inserting keys into a table
|
|
||||||
@tparam table tbl the table that will have keys added to it
|
|
||||||
@tparam[opt] number start_index the index at which values will be added, nil means end of the array, numbered indexs only
|
|
||||||
@tparam table tbl2 the table that may contain both string and numbered keys
|
|
||||||
@treturn table the table passed as the first argument
|
|
||||||
@usage-- Merging two tables
|
|
||||||
local tbl = {}
|
|
||||||
local tbl2 = {}
|
|
||||||
for i = 1,100 do tbl[i] = i tbl['_'..i] = i tbl2[i] = i tbl2['__'..i] = i end
|
|
||||||
Common.table_insert(tbl,50,tbl2)
|
|
||||||
]]
|
|
||||||
function Common.table_insert(tbl,start_index,tbl2)
|
|
||||||
if not tbl2 then
|
|
||||||
tbl2 = start_index
|
|
||||||
start_index = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
Common.array_insert(tbl,start_index,tbl2)
|
|
||||||
for key, value in pairs(tbl2) do
|
|
||||||
if not tonumber(key) then
|
|
||||||
tbl[key] = value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return tbl
|
|
||||||
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)
|
|
||||||
]]
|
|
||||||
function Common.resolve_value(value,...)
|
|
||||||
if value then
|
|
||||||
if type(value) == 'function' then
|
|
||||||
return value(...)
|
|
||||||
else
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return Common
|
return Common
|
||||||
@@ -117,8 +117,8 @@ local Global = require 'utils.global' --- @dep utils.global
|
|||||||
local Event = require 'utils.event' --- @dep utils.event
|
local Event = require 'utils.event' --- @dep utils.event
|
||||||
local Groups = require 'expcore.permission_groups' --- @dep expcore.permission_groups
|
local Groups = require 'expcore.permission_groups' --- @dep expcore.permission_groups
|
||||||
local Async = require 'expcore.async' --- @dep expcore.async
|
local Async = require 'expcore.async' --- @dep expcore.async
|
||||||
local Colours = require 'resources.color_presets' --- @dep resources.color_presets
|
local Colours = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local write_json = ext_require('expcore.common','write_json') --- @dep expcore.common
|
local write_json = _C.ext_require('expcore.common','write_json') --- @dep expcore.common
|
||||||
|
|
||||||
local Roles = {
|
local Roles = {
|
||||||
_prototype={},
|
_prototype={},
|
||||||
@@ -437,7 +437,7 @@ function Roles.define_role_order(order)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Check no roles were missed
|
-- Check no roles were missed
|
||||||
for role_name,_ in pairs(Role.config.roles) do
|
for role_name,_ in pairs(Roles.config.roles) do
|
||||||
if not done[role_name] then
|
if not done[role_name] then
|
||||||
error('Role missing '..role_name..' from role order, all defined roles must be included.',2)
|
error('Role missing '..role_name..' from role order, all defined roles must be included.',2)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ local Event = require 'utils.event' --- @dep utils.event
|
|||||||
local Game = require 'utils.game' --- @dep utils.game
|
local Game = require 'utils.game' --- @dep utils.game
|
||||||
local Global = require 'utils.global' --- @dep utils.global
|
local Global = require 'utils.global' --- @dep utils.global
|
||||||
local config = require 'config.death_logger' --- @dep config.death_logger
|
local config = require 'config.death_logger' --- @dep config.death_logger
|
||||||
local format_time,move_items = ext_require('expcore.common','format_time','move_items') --- @dep expcore.common
|
local format_time,move_items = _C.ext_require('expcore.common','format_time','move_items') --- @dep expcore.common
|
||||||
|
|
||||||
local deaths = {
|
local deaths = {
|
||||||
archive={} -- deaths moved here after body is gone
|
archive={} -- deaths moved here after body is gone
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
local Event = require 'utils.event' --- @dep utils.event
|
local Event = require 'utils.event' --- @dep utils.event
|
||||||
local Game = require 'utils.game' --- @dep utils.game
|
local Game = require 'utils.game' --- @dep utils.game
|
||||||
local Colors = require 'resources.color_presets' --- @dep resources.color_presets
|
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local write_json,format_time = ext_require('expcore.common','write_json','format_time') --- @dep expcore.common
|
local write_json,format_time = _C.ext_require('expcore.common','write_json','format_time') --- @dep expcore.common
|
||||||
local config = require 'config.discord_alerts' --- @dep config.discord_alerts
|
local config = require 'config.discord_alerts' --- @dep config.discord_alerts
|
||||||
|
|
||||||
local function get_player_name(event)
|
local function get_player_name(event)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ local Event = require 'utils.event' --- @dep utils.event
|
|||||||
local Game = require 'utils.game' --- @dep utils.event
|
local Game = require 'utils.game' --- @dep utils.event
|
||||||
local config = require 'config.join_messages' --- @dep config.join_messages
|
local config = require 'config.join_messages' --- @dep config.join_messages
|
||||||
local Global = require 'utils.global' --- @dep utils.global
|
local Global = require 'utils.global' --- @dep utils.global
|
||||||
require 'utils.table'
|
require 'overrides.table'
|
||||||
|
|
||||||
Global.register(config,function(tbl)
|
Global.register(config,function(tbl)
|
||||||
config = tbl
|
config = tbl
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
--- Gives players random colours when they join, also applies preset colours to those who have them
|
--- Gives players random colours when they join, also applies preset colours to those who have them
|
||||||
-- @addon Player-Colours
|
-- @addon Player-Colours
|
||||||
|
|
||||||
local Colours = require 'resources.color_presets' --- @dep resources.color_presets
|
local Colours = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local Game = require 'utils.game' --- @dep utils.game
|
local Game = require 'utils.game' --- @dep utils.game
|
||||||
local Event = require 'utils.event' --- @dep utils.event
|
local Event = require 'utils.event' --- @dep utils.event
|
||||||
local config = require 'config.preset_player_colours' --- @dep config.preset_player_colours
|
local config = require 'config.preset_player_colours' --- @dep config.preset_player_colours
|
||||||
local Global = require 'utils.global' --- @dep utils.global
|
local Global = require 'utils.global' --- @dep utils.global
|
||||||
require 'utils.table'
|
require 'overrides.table'
|
||||||
|
|
||||||
Global.register(config,function(tbl)
|
Global.register(config,function(tbl)
|
||||||
config = tbl
|
config = tbl
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
local Event = require 'utils.event' --- @dep utils.event
|
local Event = require 'utils.event' --- @dep utils.event
|
||||||
local Game = require 'utils.game' --- @dep utils.game
|
local Game = require 'utils.game' --- @dep utils.game
|
||||||
local Global = require 'utils.global' --- @dep utils.global
|
local Global = require 'utils.global' --- @dep utils.global
|
||||||
local print_grid_value, clear_flying_text = ext_require('expcore.common','print_grid_value','clear_flying_text') --- @dep expcore.common
|
local print_grid_value, clear_flying_text = _C.ext_require('expcore.common','print_grid_value','clear_flying_text') --- @dep expcore.common
|
||||||
local config = require 'config.scorched_earth' --- @dep config.scorched_earth
|
local config = require 'config.scorched_earth' --- @dep config.scorched_earth
|
||||||
|
|
||||||
-- Loops over the config and finds the wile which has the highest value for strength
|
-- Loops over the config and finds the wile which has the highest value for strength
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
||||||
local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
|
local format_chat_player_name = _C.ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
|
||||||
require 'config.expcore-commands.parse_general'
|
require 'config.expcore-commands.parse_general'
|
||||||
|
|
||||||
--- Sends a message in chat that only admins can see
|
--- Sends a message in chat that only admins can see
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
||||||
local move_items = ext_require('expcore.common','move_items') --- @dep expcore.common
|
local move_items = _C.ext_require('expcore.common','move_items') --- @dep expcore.common
|
||||||
require 'config.expcore-commands.parse_roles'
|
require 'config.expcore-commands.parse_roles'
|
||||||
|
|
||||||
--- Clears a players inventory
|
--- Clears a players inventory
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
||||||
local Jail = require 'modules.control.jail' --- @dep modules.control.jail
|
local Jail = require 'modules.control.jail' --- @dep modules.control.jail
|
||||||
local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
|
local format_chat_player_name = _C.ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
|
||||||
require 'config.expcore-commands.parse_roles'
|
require 'config.expcore-commands.parse_roles'
|
||||||
|
|
||||||
--- Puts a player into jail and removes all other roles.
|
--- Puts a player into jail and removes all other roles.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
||||||
local format_chat_colour = ext_require('expcore.common','format_chat_colour') --- @dep expcore.common
|
local format_chat_colour = _C.ext_require('expcore.common','format_chat_colour') --- @dep expcore.common
|
||||||
|
|
||||||
local function step_component(c1,c2)
|
local function step_component(c1,c2)
|
||||||
if c1 < 0 then
|
if c1 < 0 then
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||||
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
||||||
local Reports = require 'modules.control.reports' --- @dep modules.control.reports
|
local Reports = require 'modules.control.reports' --- @dep modules.control.reports
|
||||||
local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
|
local format_chat_player_name = _C.ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
|
||||||
require 'config.expcore-commands.parse_general'
|
require 'config.expcore-commands.parse_general'
|
||||||
|
|
||||||
--- Reports a player and notifies moderators
|
--- Reports a player and notifies moderators
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
||||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||||
local Colours = require 'resources.color_presets' --- @dep resources.color_presets
|
local Colours = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local format_chat_player_name, format_chat_colour_localized = ext_require('expcore.common',
|
local format_chat_player_name, format_chat_colour_localized = _C.ext_require('expcore.common',
|
||||||
'format_chat_player_name',
|
'format_chat_player_name',
|
||||||
'format_chat_colour_localized'
|
'format_chat_colour_localized'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
local Commands = require 'expcore.commands' --- @dep expcore.commands
|
||||||
local Warnings = require 'modules.control.warnings' --- @dep modules.control.warnings
|
local Warnings = require 'modules.control.warnings' --- @dep modules.control.warnings
|
||||||
local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
|
local format_chat_player_name = _C.ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
|
||||||
local config = require 'config.warnings' --- @dep config.warnings
|
local config = require 'config.warnings' --- @dep config.warnings
|
||||||
require 'config.expcore-commands.parse_roles'
|
require 'config.expcore-commands.parse_roles'
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||||
local Game = require 'utils.game' --- @dep utils.game
|
local Game = require 'utils.game' --- @dep utils.game
|
||||||
local Global = require 'utils.global' --- @dep utils.global
|
local Global = require 'utils.global' --- @dep utils.global
|
||||||
local move_items = ext_require('expcore.common','move_items') --- @dep expcore.common
|
local move_items = _C.ext_require('expcore.common','move_items') --- @dep expcore.common
|
||||||
|
|
||||||
local valid_player = Game.get_player_from_any
|
local valid_player = Game.get_player_from_any
|
||||||
local assign_roles = Roles.assign_player
|
local assign_roles = Roles.assign_player
|
||||||
|
|||||||
@@ -32,8 +32,8 @@
|
|||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local Colors = require 'resources.color_presets' --- @dep resources.color_presets
|
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local format_number = ext_require('util','format_number') --- @dep util
|
local format_number = _C.ext_require('util','format_number') --- @dep util
|
||||||
|
|
||||||
local precision_index = defines.flow_precision_index
|
local precision_index = defines.flow_precision_index
|
||||||
local Production = {}
|
local Production = {}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ local Store = require 'expcore.store' --- @dep expcore.store
|
|||||||
local Global = require 'utils.global' --- @dep utils.global
|
local Global = require 'utils.global' --- @dep utils.global
|
||||||
local Token = require 'utils.token' --- @dep utils.token
|
local Token = require 'utils.token' --- @dep utils.token
|
||||||
local config = require 'config.warps' --- @dep config.warps
|
local config = require 'config.warps' --- @dep config.warps
|
||||||
local table_values,table_keysort = ext_require('expcore.common','table_values','table_keysort') --- @dep expcore.common
|
|
||||||
|
|
||||||
local Warps = {}
|
local Warps = {}
|
||||||
|
|
||||||
@@ -64,7 +63,7 @@ Store.watch(warp_store,function(warp,warp_id)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Sort the warp names in alphabetical order
|
-- Sort the warp names in alphabetical order
|
||||||
local new_warp_ids = table_values(table_keysort(warp_names))
|
local new_warp_ids = table.get_values(table.keysort(warp_names))
|
||||||
table.insert(new_warp_ids,1,spawn_id)
|
table.insert(new_warp_ids,1,spawn_id)
|
||||||
new_warp_ids.spawn = spawn_id
|
new_warp_ids.spawn = spawn_id
|
||||||
force_warps[force_name] = new_warp_ids
|
force_warps[force_name] = new_warp_ids
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
local Gui = require 'utils.gui' --- @dep utils.gui
|
local Gui = require 'utils.gui' --- @dep utils.gui
|
||||||
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
||||||
local Color = require 'resources.color_presets' --- @dep resources.color_presets
|
local Color = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
|
|
||||||
local dump = Model.dump
|
local dump = Model.dump
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
local Event = require 'utils.event'
|
local Event = require 'utils.event'
|
||||||
local table = require 'utils.table'
|
local table = require 'overrides.table'
|
||||||
local Gui = require 'utils.gui'
|
local Gui = require 'utils.gui'
|
||||||
local Model = require 'modules.gui.debug.model'
|
local Model = require 'modules.gui.debug.model'
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
local Gui = require 'utils.gui' --- @dep utils.gui
|
local Gui = require 'utils.gui' --- @dep utils.gui
|
||||||
local ExpGui = require 'expcore.gui' --- @dep utils.global
|
local ExpGui = require 'expcore.gui' --- @dep utils.global
|
||||||
local Color = require 'resources.color_presets' --- @dep resources.color_presets
|
local Color = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
||||||
|
|
||||||
local dump = Model.dump
|
local dump = Model.dump
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
local Gui = require 'utils.gui' --- @dep utils.gui
|
local Gui = require 'utils.gui' --- @dep utils.gui
|
||||||
local Store = require 'expcore.store' --- @dep utils.global
|
local Store = require 'expcore.store' --- @dep utils.global
|
||||||
local Color = require 'resources.color_presets' --- @dep resources.color_presets
|
local Color = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
||||||
|
|
||||||
local dump = Model.dump
|
local dump = Model.dump
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
local Gui = require 'utils.gui' --- @dep utils.gui
|
local Gui = require 'utils.gui' --- @dep utils.gui
|
||||||
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
||||||
local Color = require 'resources.color_presets' --- @dep resources.color_presets
|
local Color = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
|
|
||||||
local dump = Model.dump
|
local dump = Model.dump
|
||||||
local dump_text = Model.dump_text
|
local dump_text = Model.dump_text
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
local Gui = require 'utils.gui' --- @dep utils.gui
|
local Gui = require 'utils.gui' --- @dep utils.gui
|
||||||
local Color = require 'resources.color_presets' --- @dep resources.color_presets
|
local Color = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
|
|
||||||
local Public = {}
|
local Public = {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
local Gui = require 'utils.gui' --- @dep utils.gui
|
local Gui = require 'utils.gui' --- @dep utils.gui
|
||||||
local table = require 'utils.table' --- @dep utils.table
|
local table = require 'overrides.table' --- @dep overrides.table
|
||||||
|
|
||||||
local gui_names = Gui.names
|
local gui_names = Gui.names
|
||||||
local type = type
|
local type = type
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
local Gui = require 'utils.gui' --- @dep utils.gui
|
local Gui = require 'utils.gui' --- @dep utils.gui
|
||||||
local Color = require 'resources.color_presets' --- @dep resources.color_presets
|
local Color = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
||||||
|
|
||||||
local dump_function = Model.dump_function
|
local dump_function = Model.dump_function
|
||||||
@@ -17,9 +17,9 @@ local ignore = {
|
|||||||
math = true,
|
math = true,
|
||||||
debug = true,
|
debug = true,
|
||||||
serpent = true,
|
serpent = true,
|
||||||
['utils.math'] = true,
|
['overrides.math'] = true,
|
||||||
util = true,
|
util = true,
|
||||||
['utils.inspect'] = true,
|
['overrides.inspect'] = true,
|
||||||
['mod-gui'] = true
|
['mod-gui'] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
local Gui = require 'utils.gui' --- @dep utils.gui
|
local Gui = require 'utils.gui' --- @dep utils.gui
|
||||||
local Global = require 'utils.global' --- @dep utils.global
|
local Global = require 'utils.global' --- @dep utils.global
|
||||||
local Token = require 'utils.token' --- @dep utils.token
|
local Token = require 'utils.token' --- @dep utils.token
|
||||||
local Color = require 'resources.color_presets' --- @dep resources.color_presets
|
local Color = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
local Model = require 'modules.gui.debug.model' --- @dep modules.gui.debug.model
|
||||||
|
|
||||||
local dump = Model.dump
|
local dump = Model.dump
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ local Roles = require 'expcore.roles' --- @dep expcore.roles
|
|||||||
local Store = require 'expcore.store' --- @dep expcore.store
|
local Store = require 'expcore.store' --- @dep expcore.store
|
||||||
local Game = require 'utils.game' --- @dep utils.game
|
local Game = require 'utils.game' --- @dep utils.game
|
||||||
local Event = require 'utils.event' --- @dep utils.event
|
local Event = require 'utils.event' --- @dep utils.event
|
||||||
local format_time = ext_require('expcore.common','format_time') --- @dep expcore.common
|
local format_time = _C.ext_require('expcore.common','format_time') --- @dep expcore.common
|
||||||
local config = require 'config.action_buttons' --- @dep config.action_buttons
|
local config = require 'config.action_buttons' --- @dep config.action_buttons
|
||||||
local Colors = require 'resources.color_presets' --- @dep resources.color_presets
|
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
|
|
||||||
-- Stores the name of the player a player has selected
|
-- Stores the name of the player a player has selected
|
||||||
local selected_player_store = Store.register(function(player)
|
local selected_player_store = Store.register(function(player)
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ local Gui = require 'expcore.gui' --- @dep expcore.gui
|
|||||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||||
local Event = require 'utils.event' --- @dep utils.event
|
local Event = require 'utils.event' --- @dep utils.event
|
||||||
local config = require 'config.rockets' --- @dep config.rockets
|
local config = require 'config.rockets' --- @dep config.rockets
|
||||||
local format_time = ext_require('expcore.common','format_time') --- @dep expcore.common
|
local format_time = _C.ext_require('expcore.common','format_time') --- @dep expcore.common
|
||||||
local Colors = require 'resources.color_presets' --- @dep resources.color_presets
|
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local Rockets = require 'modules.control.rockets' --- @dep modules.control.rockets
|
local Rockets = require 'modules.control.rockets' --- @dep modules.control.rockets
|
||||||
|
|
||||||
local time_formats = {
|
local time_formats = {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
local Gui = require 'expcore.gui' --- @dep expcore.gui
|
local Gui = require 'expcore.gui' --- @dep expcore.gui
|
||||||
local Roles = require 'expcore.roles' --- @dep expcore.gui
|
local Roles = require 'expcore.roles' --- @dep expcore.gui
|
||||||
local Event = require 'utils.event' --- @dep utils.event
|
local Event = require 'utils.event' --- @dep utils.event
|
||||||
local format_time = ext_require('expcore.common','format_time') --- @dep expcore.common
|
local format_time = _C.ext_require('expcore.common','format_time') --- @dep expcore.common
|
||||||
local config = require 'config.science' --- @dep config.science
|
local config = require 'config.science' --- @dep config.science
|
||||||
local Production = require 'modules.control.production' --- @dep modules.control.production
|
local Production = require 'modules.control.production' --- @dep modules.control.production
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ local Gui = require 'expcore.gui' --- @dep expcore.gui
|
|||||||
local Event = require 'utils.event' --- @dep utils.event
|
local Event = require 'utils.event' --- @dep utils.event
|
||||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||||
local config = require 'config.tasks' --- @dep config.tasks
|
local config = require 'config.tasks' --- @dep config.tasks
|
||||||
local format_time,table_keys = ext_require('expcore.common','format_time','table_keys') --- @dep expcore.common
|
|
||||||
local Tasks = require 'modules.control.tasks' --- @dep modules.control.tasks
|
local Tasks = require 'modules.control.tasks' --- @dep modules.control.tasks
|
||||||
|
local format_time = _C.format_time --- @dep expcore.common
|
||||||
|
|
||||||
-- Styles used for sprite buttons
|
-- Styles used for sprite buttons
|
||||||
local Styles = {
|
local Styles = {
|
||||||
@@ -223,7 +223,7 @@ end)
|
|||||||
local function update_task(player,task_table,task_id)
|
local function update_task(player,task_table,task_id)
|
||||||
local task = Tasks.get_task(task_id)
|
local task = Tasks.get_task(task_id)
|
||||||
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
||||||
local task_number = table.index_of(task_ids, task_id)
|
local task_number = table.get_index(task_ids, task_id)
|
||||||
|
|
||||||
-- Task no longer exists so should be removed from the list
|
-- Task no longer exists so should be removed from the list
|
||||||
if not task then
|
if not task then
|
||||||
@@ -240,7 +240,7 @@ local function update_task(player,task_table,task_id)
|
|||||||
-- Update the edit flow
|
-- Update the edit flow
|
||||||
local edit_flow = task_table['edit-'..task_id]
|
local edit_flow = task_table['edit-'..task_id]
|
||||||
local player_allowed_edit = check_player_permissions(player,task)
|
local player_allowed_edit = check_player_permissions(player,task)
|
||||||
local players_editing = table_keys(task.curently_editing)
|
local players_editing = table.get_keys(task.curently_editing)
|
||||||
local edit_task_element = edit_flow[edit_task.name]
|
local edit_task_element = edit_flow[edit_task.name]
|
||||||
local discard_task_element = edit_flow[discard_task.name]
|
local discard_task_element = edit_flow[discard_task.name]
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ local Global = require 'utils.global' --- @dep utils.global
|
|||||||
local Event = require 'utils.event' --- @dep utils.event
|
local Event = require 'utils.event' --- @dep utils.event
|
||||||
local Game = require 'utils.game' --- @dep utils.game
|
local Game = require 'utils.game' --- @dep utils.game
|
||||||
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
local Roles = require 'expcore.roles' --- @dep expcore.roles
|
||||||
local Colors = require 'resources.color_presets' --- @dep resources.color_presets
|
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local config = require 'config.warps' --- @dep config.warps
|
local config = require 'config.warps' --- @dep config.warps
|
||||||
local format_time,table_keys = ext_require('expcore.common','format_time','table_keys') --- @dep expcore.common
|
|
||||||
local Warps = require 'modules.control.warps' --- @dep modules.control.warps
|
local Warps = require 'modules.control.warps' --- @dep modules.control.warps
|
||||||
|
local format_time = _C.format_time --- @dep expcore.common
|
||||||
|
|
||||||
-- Stores a boolean value indexed by player name
|
-- Stores a boolean value indexed by player name
|
||||||
local player_in_range_store = Store.register(function(player)
|
local player_in_range_store = Store.register(function(player)
|
||||||
@@ -319,7 +319,7 @@ local function update_warp(player,warp_table,warp_id)
|
|||||||
-- Update the edit flow
|
-- Update the edit flow
|
||||||
local edit_flow = warp_table['edit-'..warp_id]
|
local edit_flow = warp_table['edit-'..warp_id]
|
||||||
local player_allowed_edit = check_player_permissions(player,'allow_edit_warp',warp)
|
local player_allowed_edit = check_player_permissions(player,'allow_edit_warp',warp)
|
||||||
local players_editing = table_keys(warp.currently_editing)
|
local players_editing = table.get_keys(warp.currently_editing)
|
||||||
local edit_warp_element = edit_flow[edit_warp.name]
|
local edit_warp_element = edit_flow[edit_warp.name]
|
||||||
local discard_warp_element = edit_flow[discard_warp.name]
|
local discard_warp_element = edit_flow[discard_warp.name]
|
||||||
|
|
||||||
|
|||||||
@@ -339,4 +339,3 @@ end
|
|||||||
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
|
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
|
||||||
|
|
||||||
return inspect
|
return inspect
|
||||||
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
local Public = {}
|
--luacheck:ignore global print
|
||||||
|
|
||||||
local locale_string = {'', '[PRINT] ', nil}
|
local locale_string = {'', '[PRINT] ', nil}
|
||||||
local raw_print = print
|
local raw_print = print
|
||||||
|
|
||||||
@@ -8,6 +7,4 @@ function print(str)
|
|||||||
log(locale_string)
|
log(locale_string)
|
||||||
end
|
end
|
||||||
|
|
||||||
Public.raw_print = raw_print
|
return raw_print
|
||||||
|
|
||||||
return Public
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
local loaded = _G.package.loaded
|
--luacheck:ignore global require
|
||||||
|
local loaded = package.loaded
|
||||||
local raw_require = require
|
local raw_require = require
|
||||||
|
|
||||||
function require(path)
|
function require(path)
|
||||||
@@ -10,3 +10,5 @@ _STAGE = {
|
|||||||
--config_change = 7,
|
--config_change = 7,
|
||||||
runtime = 8
|
runtime = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_LIFECYCLE = _STAGE.control
|
||||||
@@ -22,7 +22,7 @@ end
|
|||||||
-- The catch is that fast_remove doesn't guarantee to maintain the order of items in the array.
|
-- The catch is that fast_remove doesn't guarantee to maintain the order of items in the array.
|
||||||
-- @param tbl <table> arrayed table
|
-- @param tbl <table> arrayed table
|
||||||
-- @param index <number> Must be >= 0. The case where index > #tbl is handled.
|
-- @param index <number> Must be >= 0. The case where index > #tbl is handled.
|
||||||
function table.fast_remove(tbl, index)
|
function table.remove_index(tbl, index)
|
||||||
local count = #tbl
|
local count = #tbl
|
||||||
if index > count then
|
if index > count then
|
||||||
return
|
return
|
||||||
@@ -36,7 +36,7 @@ end
|
|||||||
--- Adds the contents of table t2 to table t1
|
--- Adds the contents of table t2 to table t1
|
||||||
-- @param t1 <table> to insert into
|
-- @param t1 <table> to insert into
|
||||||
-- @param t2 <table> to insert from
|
-- @param t2 <table> to insert from
|
||||||
function table.add_all(t1, t2)
|
function table.merge_table(t1, t2)
|
||||||
for k, v in pairs(t2) do
|
for k, v in pairs(t2) do
|
||||||
if tonumber(k) then
|
if tonumber(k) then
|
||||||
t1[#t1 + 1] = v
|
t1[#t1 + 1] = v
|
||||||
@@ -46,11 +46,74 @@ function table.add_all(t1, t2)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[-- Much faster method for inserting items into an array
|
||||||
|
@tparam table tbl the table that will have the values added to it
|
||||||
|
@tparam[opt] number start_index the index at which values will be added, nil means end of the array
|
||||||
|
@tparam table values the new values that will be added to the table
|
||||||
|
@treturn table the table that was passed as the first argument
|
||||||
|
@usage-- Adding 1000 values into the middle of the array
|
||||||
|
local tbl = {}
|
||||||
|
local values = {}
|
||||||
|
for i = 1,1000 do tbl[i] = i values[i] = i end
|
||||||
|
table.array_insert(tbl,500,values) -- around 0.4ms
|
||||||
|
]]
|
||||||
|
function table.array_insert(tbl,start_index,values)
|
||||||
|
if not values then
|
||||||
|
values = start_index
|
||||||
|
start_index = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if start_index then
|
||||||
|
local starting_length = #tbl
|
||||||
|
local adding_length = #values
|
||||||
|
local move_to = start_index+adding_length+1
|
||||||
|
for offset = starting_length-start_index, 0, -1 do
|
||||||
|
tbl[move_to+offset] = tbl[starting_length+offset]
|
||||||
|
end
|
||||||
|
start_index = start_index-1
|
||||||
|
else
|
||||||
|
start_index = #tbl
|
||||||
|
end
|
||||||
|
|
||||||
|
for offset, item in ipairs(values) do
|
||||||
|
tbl[start_index+offset] = item
|
||||||
|
end
|
||||||
|
|
||||||
|
return tbl
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[-- Much faster method for inserting keys into a table
|
||||||
|
@tparam table tbl the table that will have keys added to it
|
||||||
|
@tparam[opt] number start_index the index at which values will be added, nil means end of the array, numbered indexs only
|
||||||
|
@tparam table tbl2 the table that may contain both string and numbered keys
|
||||||
|
@treturn table the table passed as the first argument
|
||||||
|
@usage-- Merging two tables
|
||||||
|
local tbl = {}
|
||||||
|
local tbl2 = {}
|
||||||
|
for i = 1,100 do tbl[i] = i tbl['_'..i] = i tbl2[i] = i tbl2['__'..i] = i end
|
||||||
|
table.table_insert(tbl,50,tbl2)
|
||||||
|
]]
|
||||||
|
function table.table_insert(tbl,start_index,tbl2)
|
||||||
|
if not tbl2 then
|
||||||
|
tbl2 = start_index
|
||||||
|
start_index = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
table.array_insert(tbl,start_index,tbl2)
|
||||||
|
for key, value in pairs(tbl2) do
|
||||||
|
if not tonumber(key) then
|
||||||
|
tbl[key] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return tbl
|
||||||
|
end
|
||||||
|
|
||||||
--- Checks if a table contains an element
|
--- Checks if a table contains an element
|
||||||
-- @param t <table>
|
-- @param t <table>
|
||||||
-- @param e <any> table element
|
-- @param e <any> table element
|
||||||
-- @return <any> the index of the element or nil
|
-- @return <any> the index of the element or nil
|
||||||
function table.index_of(t, e)
|
function table.get_key(t, e)
|
||||||
for k, v in pairs(t) do
|
for k, v in pairs(t) do
|
||||||
if v == e then
|
if v == e then
|
||||||
return k
|
return k
|
||||||
@@ -63,7 +126,7 @@ end
|
|||||||
-- @param t <table>
|
-- @param t <table>
|
||||||
-- @param e <any> table element
|
-- @param e <any> table element
|
||||||
-- @return <number|nil> the index of the element or nil
|
-- @return <number|nil> the index of the element or nil
|
||||||
function table.index_of_in_array(t, e)
|
function table.get_index(t, e)
|
||||||
for i = 1, #t do
|
for i = 1, #t do
|
||||||
if t[i] == e then
|
if t[i] == e then
|
||||||
return i
|
return i
|
||||||
@@ -72,22 +135,33 @@ function table.index_of_in_array(t, e)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local index_of = table.index_of
|
|
||||||
--- Checks if a table contains an element
|
--- Checks if a table contains an element
|
||||||
-- @param t <table>
|
-- @param t <table>
|
||||||
-- @param e <any> table element
|
-- @param e <any> table element
|
||||||
-- @return <boolean> indicating success
|
-- @return <boolean> indicating success
|
||||||
function table.contains(t, e)
|
function table.contains(t, e)
|
||||||
return index_of(t, e) and true or false
|
return table.get_key(t, e) and true or false
|
||||||
end
|
end
|
||||||
|
|
||||||
local index_of_in_array = table.index_of_in_array
|
|
||||||
--- Checks if the arrayed portion of a table contains an element
|
--- Checks if the arrayed portion of a table contains an element
|
||||||
-- @param t <table>
|
-- @param t <table>
|
||||||
-- @param e <any> table element
|
-- @param e <any> table element
|
||||||
-- @return <boolean> indicating success
|
-- @return <boolean> indicating success
|
||||||
function table.array_contains(t, e)
|
function table.array_contains(t, e)
|
||||||
return index_of_in_array(t, e) and true or false
|
return table.get_index(t, e) and true or false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Extracts certain keys from a table
|
||||||
|
-- @usage local key_three, key_one = extract({key_one='foo',key_two='bar',key_three=true},'key_three','key_one')
|
||||||
|
-- @tparam table tbl table the which contains the keys
|
||||||
|
-- @tparam string ... the names of the keys you want extracted
|
||||||
|
-- @return the keys in the order given
|
||||||
|
function table.extract_keys(tbl,...)
|
||||||
|
local values = {}
|
||||||
|
for _,key in pairs({...}) do
|
||||||
|
table.insert(values,tbl[key])
|
||||||
|
end
|
||||||
|
return unpack(values)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Adds an element into a specific index position while shuffling the rest down
|
--- Adds an element into a specific index position while shuffling the rest down
|
||||||
@@ -151,6 +225,21 @@ function table.get_random_weighted(weighted_table, item_index, weight_index)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Clears all existing entries in a table
|
||||||
|
-- @param t <table> to clear
|
||||||
|
-- @param array <boolean> to indicate whether the table is an array or not
|
||||||
|
function table.clear_table(t, array)
|
||||||
|
if array then
|
||||||
|
for i = 1, #t do
|
||||||
|
t[i] = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for i in pairs(t) do
|
||||||
|
t[i] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Creates a fisher-yates shuffle of a sequential number-indexed table
|
--- Creates a fisher-yates shuffle of a sequential number-indexed table
|
||||||
-- because this uses math.random, it cannot be used outside of events if no rng is supplied
|
-- because this uses math.random, it cannot be used outside of events if no rng is supplied
|
||||||
-- from: http://www.sdknews.com/cross-platform/corona/tutorial-how-to-shuffle-table-items
|
-- from: http://www.sdknews.com/cross-platform/corona/tutorial-how-to-shuffle-table-items
|
||||||
@@ -171,19 +260,102 @@ function table.shuffle_table(t, rng)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Clears all existing entries in a table
|
--- Default table comparator sort function.
|
||||||
-- @param t <table> to clear
|
-- @local
|
||||||
-- @param array <boolean> to indicate whether the table is an array or not
|
-- @param x one comparator operand
|
||||||
function table.clear_table(t, array)
|
-- @param y the other comparator operand
|
||||||
if array then
|
-- @return true if x logically comes before y in a list, false otherwise
|
||||||
for i = 1, #t do
|
local function sortFunc(x, y) --sorts tables with mixed index types.
|
||||||
t[i] = nil
|
local tx = type(x)
|
||||||
|
local ty = type(y)
|
||||||
|
if tx == ty then
|
||||||
|
if type(x) == 'string' then
|
||||||
|
return string.lower(x) < string.lower(y)
|
||||||
|
else
|
||||||
|
return x < y
|
||||||
|
end
|
||||||
|
elseif tx == 'number' then
|
||||||
|
return true --only x is a number and goes first
|
||||||
|
else
|
||||||
|
return false --only y is a number and goes first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns a copy of all of the values in the table.
|
||||||
|
-- @tparam table tbl the to copy the keys from, or an empty table if tbl is nil
|
||||||
|
-- @tparam[opt] boolean sorted whether to sort the keys (slower) or keep the random order from pairs()
|
||||||
|
-- @tparam[opt] boolean as_string whether to try and parse the values as strings, or leave them as their existing type
|
||||||
|
-- @treturn array an array with a copy of all the values in the table
|
||||||
|
function table.get_values(tbl, sorted, as_string)
|
||||||
|
if not tbl then return {} end
|
||||||
|
local valueset = {}
|
||||||
|
local n = 0
|
||||||
|
if as_string then --checking as_string /before/ looping is faster
|
||||||
|
for _, v in pairs(tbl) do
|
||||||
|
n = n + 1
|
||||||
|
valueset[n] = tostring(v)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
for i in pairs(t) do
|
for _, v in pairs(tbl) do
|
||||||
t[i] = nil
|
n = n + 1
|
||||||
|
valueset[n] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if sorted then
|
||||||
|
table.sort(valueset,sortFunc)
|
||||||
|
end
|
||||||
|
return valueset
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns a copy of all of the keys in the table.
|
||||||
|
-- @tparam table tbl the to copy the keys from, or an empty table if tbl is nil
|
||||||
|
-- @tparam[opt] boolean sorted whether to sort the keys (slower) or keep the random order from pairs()
|
||||||
|
-- @tparam[opt] boolean as_string whether to try and parse the keys as strings, or leave them as their existing type
|
||||||
|
-- @treturn array an array with a copy of all the keys in the table
|
||||||
|
function table.get_keys(tbl, sorted, as_string)
|
||||||
|
if not tbl then return {} end
|
||||||
|
local keyset = {}
|
||||||
|
local n = 0
|
||||||
|
if as_string then --checking as_string /before/ looping is faster
|
||||||
|
for k, _ in pairs(tbl) do
|
||||||
|
n = n + 1
|
||||||
|
keyset[n] = tostring(k)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for k, _ in pairs(tbl) do
|
||||||
|
n = n + 1
|
||||||
|
keyset[n] = k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if sorted then
|
||||||
|
table.sort(keyset,sortFunc)
|
||||||
|
end
|
||||||
|
return keyset
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns the list is a sorted way that would be expected by people (this is by key)
|
||||||
|
-- @tparam table tbl the table to be sorted
|
||||||
|
-- @treturn table the sorted table
|
||||||
|
function table.alphanumsort(tbl)
|
||||||
|
local o = table.get_keys(tbl)
|
||||||
|
local function padnum(d) local dec, n = string.match(d, "(%.?)0*(.+)")
|
||||||
|
return #dec > 0 and ("%.12f"):format(d) or ("%s%03d%s"):format(dec, #n, n) end
|
||||||
|
table.sort(o, function(a,b)
|
||||||
|
return tostring(a):gsub("%.?%d+",padnum)..("%3d"):format(#b)
|
||||||
|
< tostring(b):gsub("%.?%d+",padnum)..("%3d"):format(#a) end)
|
||||||
|
local _tbl = {}
|
||||||
|
for _,k in pairs(o) do _tbl[k] = tbl[k] end
|
||||||
|
return _tbl
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns the list is a sorted way that would be expected by people (this is by key) (faster alternative than above)
|
||||||
|
-- @tparam table tbl the table to be sorted
|
||||||
|
-- @treturn table the sorted table
|
||||||
|
function table.keysort(tbl)
|
||||||
|
local o = table.get_keys(tbl,true)
|
||||||
|
local _tbl = {}
|
||||||
|
for _,k in pairs(o) do _tbl[k] = tbl[k] end
|
||||||
|
return _tbl
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
@@ -238,7 +410,7 @@ require 'util'
|
|||||||
-- process is a function which allow altering the passed object before transforming it into a string.
|
-- process is a function which allow altering the passed object before transforming it into a string.
|
||||||
-- A typical way to use it would be to remove certain values so that they don't appear at all.
|
-- A typical way to use it would be to remove certain values so that they don't appear at all.
|
||||||
-- return <string> the prettied table
|
-- return <string> the prettied table
|
||||||
table.inspect = require 'utils.inspect' --- @dep utils.inspect
|
table.inspect = require 'overrides.inspect' --- @dep overrides.inspect
|
||||||
|
|
||||||
--- Takes a table and returns the number of entries in the table. (Slower than #table, faster than iterating via pairs)
|
--- Takes a table and returns the number of entries in the table. (Slower than #table, faster than iterating via pairs)
|
||||||
table.size = table_size
|
table.size = table_size
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
global.redmew_version = nil
|
|
||||||
global.expgaming_version = '5.0.0'
|
|
||||||
@@ -1,179 +0,0 @@
|
|||||||
--[[-- info
|
|
||||||
Original (javascript) version: https://hastebin.com/udakacavap.js
|
|
||||||
Can be tested against: https://wiki.factorio.com/Enemies#Spawn_chances_by_evolution_factor
|
|
||||||
]]
|
|
||||||
|
|
||||||
-- dependencies
|
|
||||||
local Global = require 'utils.global' --- @dep utils.global
|
|
||||||
local Debug = require 'utils.debug' --- @dep utils.debug
|
|
||||||
local table = require 'utils.table' --- @dep utils.table
|
|
||||||
|
|
||||||
-- localized functions
|
|
||||||
local get_random_weighted = table.get_random_weighted
|
|
||||||
local round = math.round
|
|
||||||
local ceil = math.ceil
|
|
||||||
local floor = math.floor
|
|
||||||
local random = math.random
|
|
||||||
local pairs = pairs
|
|
||||||
local format = string.format
|
|
||||||
|
|
||||||
-- this
|
|
||||||
local AlienEvolutionProgress = {}
|
|
||||||
|
|
||||||
local memory = {
|
|
||||||
spawner_specifications = {},
|
|
||||||
spawner_specifications_count = 0,
|
|
||||||
evolution_cache = {
|
|
||||||
['biter-spawner'] = {
|
|
||||||
evolution = -1,
|
|
||||||
weight_table = {},
|
|
||||||
},
|
|
||||||
['spitters-spawner'] = {
|
|
||||||
evolution = -1,
|
|
||||||
weight_table = {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Global.register_init({
|
|
||||||
memory = memory,
|
|
||||||
}, function(tbl)
|
|
||||||
for name, prototype in pairs(game.entity_prototypes) do
|
|
||||||
if prototype.type == 'unit-spawner' and prototype.subgroup.name == 'enemies' then
|
|
||||||
tbl.memory.spawner_specifications[name] = prototype.result_units
|
|
||||||
memory.spawner_specifications_count = memory.spawner_specifications_count + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end, function(tbl)
|
|
||||||
memory = tbl.memory
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function lerp(low, high, pos)
|
|
||||||
local s = high.evolution_factor - low.evolution_factor;
|
|
||||||
local l = (pos - low.evolution_factor) / s;
|
|
||||||
return (low.weight * (1 - l)) + (high.weight * l)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_values(map, evolution_factor)
|
|
||||||
local result = {}
|
|
||||||
local sum = 0
|
|
||||||
|
|
||||||
for _, spawner_data in pairs(map) do
|
|
||||||
local list = spawner_data.spawn_points;
|
|
||||||
local low = list[1];
|
|
||||||
local high = list[#list];
|
|
||||||
|
|
||||||
for _, val in pairs(list) do
|
|
||||||
local val_evolution = val.evolution_factor
|
|
||||||
if val_evolution <= evolution_factor and val_evolution > low.evolution_factor then
|
|
||||||
low = val;
|
|
||||||
end
|
|
||||||
if val_evolution >= evolution_factor and val_evolution < high.evolution_factor then
|
|
||||||
high = val
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local val
|
|
||||||
if evolution_factor <= low.evolution_factor then
|
|
||||||
val = low.weight
|
|
||||||
elseif evolution_factor >= high.evolution_factor then
|
|
||||||
val = high.weight;
|
|
||||||
else
|
|
||||||
val = lerp(low, high, evolution_factor)
|
|
||||||
end
|
|
||||||
sum = sum + val;
|
|
||||||
|
|
||||||
result[spawner_data.unit] = val;
|
|
||||||
end
|
|
||||||
|
|
||||||
local weighted_table = {}
|
|
||||||
local count = 0
|
|
||||||
for index, _ in pairs(result) do
|
|
||||||
count = count + 1
|
|
||||||
weighted_table[count] = {index, result[index] / sum}
|
|
||||||
end
|
|
||||||
|
|
||||||
return weighted_table;
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_spawner_values(spawner, evolution)
|
|
||||||
local spawner_specification = memory.spawner_specifications[spawner]
|
|
||||||
if not spawner_specification then
|
|
||||||
Debug.print(format('Spawner "%s" does not exist in the prototype data', spawner))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local cache = memory.evolution_cache[spawner]
|
|
||||||
|
|
||||||
if not cache then
|
|
||||||
cache = {
|
|
||||||
evolution = -1,
|
|
||||||
weight_table = {},
|
|
||||||
}
|
|
||||||
memory.evolution_cache[spawner] = cache
|
|
||||||
end
|
|
||||||
|
|
||||||
local evolution_value = round(evolution * 100)
|
|
||||||
if (cache.evolution < evolution_value) then
|
|
||||||
cache.evolution = evolution_value
|
|
||||||
cache.weight_table = get_values(spawner_specification, evolution)
|
|
||||||
end
|
|
||||||
|
|
||||||
return cache.weight_table
|
|
||||||
end
|
|
||||||
|
|
||||||
local function calculate_total(count, spawner, evolution)
|
|
||||||
if count == 0 then
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
|
|
||||||
local spawner_values = get_spawner_values(spawner, evolution)
|
|
||||||
if not spawner_values then
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
|
|
||||||
local aliens = {}
|
|
||||||
for _ = 1, count do
|
|
||||||
local name = get_random_weighted(spawner_values)
|
|
||||||
aliens[name] = (aliens[name] or 0) + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
return aliens
|
|
||||||
end
|
|
||||||
|
|
||||||
---Creates the spawner_request structure required for AlienEvolutionProgress.get_aliens for all
|
|
||||||
---available spawner's. If dividing the total spawner's by the total aliens causes a fraction, the
|
|
||||||
---fraction will decide a chance to spawn. 1 alien for 2 spawner's will have 50% on both.
|
|
||||||
---@param total_aliens table
|
|
||||||
function AlienEvolutionProgress.create_spawner_request(total_aliens)
|
|
||||||
local per_spawner = total_aliens / memory.spawner_specifications_count
|
|
||||||
local fraction = per_spawner % 1
|
|
||||||
|
|
||||||
local spawner_request = {}
|
|
||||||
for spawner, _ in pairs(memory.spawner_specifications) do
|
|
||||||
local count = per_spawner
|
|
||||||
if fraction > 0 then
|
|
||||||
if random() > fraction then
|
|
||||||
count = ceil(count)
|
|
||||||
else
|
|
||||||
count = floor(count)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
spawner_request[spawner] = count
|
|
||||||
end
|
|
||||||
|
|
||||||
return spawner_request
|
|
||||||
end
|
|
||||||
|
|
||||||
function AlienEvolutionProgress.get_aliens(spawner_requests, evolution)
|
|
||||||
local aliens = {}
|
|
||||||
for spawner, count in pairs(spawner_requests) do
|
|
||||||
for name, amount in pairs(calculate_total(count, spawner, evolution)) do
|
|
||||||
aliens[name] = (aliens[name] or 0) + amount
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return aliens
|
|
||||||
end
|
|
||||||
|
|
||||||
return AlienEvolutionProgress
|
|
||||||
@@ -1,326 +0,0 @@
|
|||||||
local Event = require 'utils.event' --- @dep utils.event
|
|
||||||
local Game = require 'utils.game' --- @dep utils.game
|
|
||||||
local Utils = require 'utils.core' --- @dep utils.core
|
|
||||||
local Timestamp = require 'utils.timestamp' --- @dep utils.timestamp
|
|
||||||
local Rank = require 'features.rank_system' --- @dep features.rank_system
|
|
||||||
local Donator = require 'features.donator' --- @dep features.donator
|
|
||||||
local Server = require 'features.server' --- @dep features.server
|
|
||||||
local Ranks = require 'resources.ranks' --- @dep resources.ranks
|
|
||||||
|
|
||||||
local insert = table.insert
|
|
||||||
local format = string.format
|
|
||||||
local next = next
|
|
||||||
local serialize = serpent.line
|
|
||||||
local match = string.match
|
|
||||||
local gmatch = string.gmatch
|
|
||||||
local get_rank_name = Rank.get_rank_name
|
|
||||||
|
|
||||||
local Command = {}
|
|
||||||
|
|
||||||
local deprecated_command_alternatives = {
|
|
||||||
['silent-command'] = 'sc',
|
|
||||||
['tpplayer'] = 'tp <player>',
|
|
||||||
['tppos'] = 'tp',
|
|
||||||
['tpmode'] = 'tp mode',
|
|
||||||
['color-redmew'] = 'redmew-color'
|
|
||||||
}
|
|
||||||
|
|
||||||
local notify_on_commands = {
|
|
||||||
['version'] = 'RedMew has a version as well, accessible via /redmew-version',
|
|
||||||
['color'] = 'RedMew allows color saving and a color randomiser: check out /redmew-color',
|
|
||||||
['ban'] = 'In case your forgot: please remember to include a message on how to appeal a ban'
|
|
||||||
}
|
|
||||||
|
|
||||||
local option_names = {
|
|
||||||
['description'] = 'A description of the command',
|
|
||||||
['arguments'] = 'A table of arguments, example: {"foo", "bar"} would map the first 2 arguments to foo and bar',
|
|
||||||
['default_values'] = 'A default value for a given argument when omitted, example: {bar = false}',
|
|
||||||
['required_rank'] = 'Set this to determines what rank is required to execute a command',
|
|
||||||
['donator_only'] = 'Set this to true if only donators may execute this command',
|
|
||||||
['debug_only'] = 'Set this to true if it should be registered when _DEBUG is true',
|
|
||||||
['cheat_only'] = 'Set this to true if it should be registered when _CHEATS is true',
|
|
||||||
['allowed_by_server'] = 'Set to true if the server (host) may execute this command',
|
|
||||||
['allowed_by_player'] = 'Set to false to disable players from executing this command',
|
|
||||||
['log_command'] = 'Set to true to log commands. Always true when admin is required',
|
|
||||||
['capture_excess_arguments'] = 'Allows the last argument to be the remaining text in the command',
|
|
||||||
['custom_help_text'] = 'Sets a custom help text to override the auto-generated help',
|
|
||||||
}
|
|
||||||
|
|
||||||
---Validates if there aren't any wrong fields in the options.
|
|
||||||
---@param command_name string
|
|
||||||
---@param options table
|
|
||||||
local function assert_existing_options(command_name, options)
|
|
||||||
local invalid = {}
|
|
||||||
for name, _ in pairs(options) do
|
|
||||||
if not option_names[name] then
|
|
||||||
insert(invalid, name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if next(invalid) then
|
|
||||||
error(format("The following options were given to the command '%s' but are invalid: %s", command_name, serialize(invalid)))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---Adds a command to be executed.
|
|
||||||
---
|
|
||||||
---Options table accepts the following structure: {
|
|
||||||
--- description = 'A description of the command',
|
|
||||||
--- arguments = {'foo', 'bar'}, -- maps arguments to these names in the given sequence
|
|
||||||
--- default_values = {bar = false}, -- gives a default value to 'bar' when omitted
|
|
||||||
--- required_rank = Ranks.regular, -- defaults to Ranks.guest
|
|
||||||
--- donator_only = true, -- defaults to false
|
|
||||||
--- debug_only = true, -- registers the command if _DEBUG is set to true, defaults to false
|
|
||||||
--- cheat_only = true, -- registers the command if _CHEATS is set to true, defaults to false
|
|
||||||
--- allowed_by_server = true, -- lets the server execute this, defaults to false
|
|
||||||
--- allowed_by_player = false, -- lets players execute this, defaults to true
|
|
||||||
--- log_command = true, -- defaults to false unless admin only, then always true
|
|
||||||
--- capture_excess_arguments = true, -- defaults to false, captures excess arguments in the last argument, useful for sentences
|
|
||||||
---}
|
|
||||||
---
|
|
||||||
---The callback receives the following arguments:
|
|
||||||
--- - arguments (indexed by name, value is extracted from the parameters)
|
|
||||||
--- - the LuaPlayer or nil if it doesn't exist (such as the server player)
|
|
||||||
--- - the game tick in which the command was executed
|
|
||||||
---
|
|
||||||
---@param command_name string
|
|
||||||
---@param options table
|
|
||||||
---@param callback function
|
|
||||||
function Command.add(command_name, options, callback)
|
|
||||||
local description = options.description or '[Undocumented command]'
|
|
||||||
local arguments = options.arguments or {}
|
|
||||||
local default_values = options.default_values or {}
|
|
||||||
local required_rank = options.required_rank or Ranks.guest
|
|
||||||
local donator_only = options.donator_only or false
|
|
||||||
local debug_only = options.debug_only or false
|
|
||||||
local cheat_only = options.cheat_only or false
|
|
||||||
local capture_excess_arguments = options.capture_excess_arguments or false
|
|
||||||
local custom_help_text = options.custom_help_text or false
|
|
||||||
local allowed_by_server = options.allowed_by_server or false
|
|
||||||
local allowed_by_player = options.allowed_by_player
|
|
||||||
local log_command = options.log_command or (required_rank >= Ranks.admin) or false
|
|
||||||
local argument_list_size = table_size(arguments)
|
|
||||||
local argument_list = ''
|
|
||||||
|
|
||||||
assert_existing_options(command_name, options)
|
|
||||||
|
|
||||||
if nil == options.allowed_by_player then
|
|
||||||
allowed_by_player = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if (not _DEBUG and debug_only) and (not _CHEATS and cheat_only) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if not allowed_by_player and not allowed_by_server then
|
|
||||||
error(format("The command '%s' is not allowed by the server nor player, please enable at least one of them.", command_name))
|
|
||||||
end
|
|
||||||
|
|
||||||
for index, argument_name in pairs(arguments) do
|
|
||||||
local argument_display = argument_name
|
|
||||||
for default_value_name, _ in pairs(default_values) do
|
|
||||||
if default_value_name == argument_name then
|
|
||||||
argument_display = argument_display .. ':optional'
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if argument_list_size == index and capture_excess_arguments then
|
|
||||||
argument_display = argument_display .. ':sentence'
|
|
||||||
end
|
|
||||||
|
|
||||||
argument_list = format('%s<%s> ', argument_list, argument_display)
|
|
||||||
end
|
|
||||||
|
|
||||||
local extra = ''
|
|
||||||
|
|
||||||
if allowed_by_server and not allowed_by_player then
|
|
||||||
extra = ' (Server only)'
|
|
||||||
elseif allowed_by_player and (required_rank > Ranks.guest) then
|
|
||||||
extra = {'command.required_rank', get_rank_name(required_rank)}
|
|
||||||
elseif allowed_by_player and donator_only then
|
|
||||||
extra = ' (Donator only)'
|
|
||||||
end
|
|
||||||
|
|
||||||
local help_text = {'command.help_text_format',(custom_help_text or argument_list), description, extra}
|
|
||||||
|
|
||||||
commands.add_command(command_name, help_text, function (command)
|
|
||||||
local print -- custom print reference in case no player is present
|
|
||||||
local player = game.player
|
|
||||||
local player_name = player and player.valid and player.name or '<server>'
|
|
||||||
if not player or not player.valid then
|
|
||||||
print = log
|
|
||||||
|
|
||||||
if not allowed_by_server then
|
|
||||||
print(format("The command '%s' is not allowed to be executed by the server.", command_name))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
else
|
|
||||||
print = player.print
|
|
||||||
|
|
||||||
if not allowed_by_player then
|
|
||||||
print(format("The command '%s' is not allowed to be executed by players.", command_name))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if Rank.less_than(player_name, required_rank) then
|
|
||||||
print({'command.higher_rank_needed', command_name, get_rank_name(required_rank)})
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if donator_only and not Donator.is_donator(player_name) then
|
|
||||||
print(format("The command '%s' is only allowed for donators.", command_name))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local named_arguments = {}
|
|
||||||
local from_command = {}
|
|
||||||
local raw_parameter_index = 1
|
|
||||||
for param in gmatch(command.parameter or '', '%S+') do
|
|
||||||
if capture_excess_arguments and raw_parameter_index == argument_list_size then
|
|
||||||
if not from_command[raw_parameter_index] then
|
|
||||||
from_command[raw_parameter_index] = param
|
|
||||||
else
|
|
||||||
from_command[raw_parameter_index] = from_command[raw_parameter_index] .. ' ' .. param
|
|
||||||
end
|
|
||||||
else
|
|
||||||
from_command[raw_parameter_index] = param
|
|
||||||
raw_parameter_index = raw_parameter_index + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local errors = {}
|
|
||||||
|
|
||||||
for index, argument in pairs(arguments) do
|
|
||||||
local parameter = from_command[index]
|
|
||||||
|
|
||||||
if not parameter then
|
|
||||||
for default_value_name, default_value in pairs(default_values) do
|
|
||||||
if default_value_name == argument then
|
|
||||||
parameter = default_value
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if parameter == nil then
|
|
||||||
insert(errors, format('Argument "%s" from command %s is missing.', argument, command_name))
|
|
||||||
else
|
|
||||||
named_arguments[argument] = parameter
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local return_early = false
|
|
||||||
|
|
||||||
for _, error in pairs(errors) do
|
|
||||||
return_early = true
|
|
||||||
print(error)
|
|
||||||
end
|
|
||||||
|
|
||||||
if return_early then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if log_command then
|
|
||||||
local tick = 'pre-game'
|
|
||||||
if game then
|
|
||||||
tick = Utils.format_time(game.tick)
|
|
||||||
end
|
|
||||||
local server_time = Server.get_current_time()
|
|
||||||
if server_time then
|
|
||||||
server_time = format('(Server time: %s)', Timestamp.to_string(server_time))
|
|
||||||
else
|
|
||||||
server_time = ''
|
|
||||||
end
|
|
||||||
|
|
||||||
log(format('%s(Map time: %s) [%s Command] %s, used: %s %s', server_time, tick, (options.required_rank >= Ranks.admin) and 'Admin' or 'Player', player_name, command_name, serialize(named_arguments)))
|
|
||||||
end
|
|
||||||
|
|
||||||
local success, error = pcall(function ()
|
|
||||||
callback(named_arguments, player, command.tick)
|
|
||||||
end)
|
|
||||||
|
|
||||||
if not success then
|
|
||||||
local serialized_arguments = serialize(named_arguments)
|
|
||||||
if _DEBUG then
|
|
||||||
print(format("%s triggered an error running a command and has been logged: '%s' with arguments %s", player_name, command_name, serialized_arguments))
|
|
||||||
print(error)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
print(format('There was an error running %s, it has been logged.', command_name))
|
|
||||||
log(format("Error while running '%s' with arguments %s: %s", command_name, serialized_arguments, error))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Command.search(keyword)
|
|
||||||
local matches = {}
|
|
||||||
local count = 0
|
|
||||||
keyword = keyword:lower()
|
|
||||||
for name, description in pairs(commands.commands) do
|
|
||||||
local command = format('%s %s', name, description)
|
|
||||||
if match(command:lower(), keyword) then
|
|
||||||
count = count + 1
|
|
||||||
matches[count] = command
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- built-in commands use LocalisedString, which cannot be translated until player.print is called
|
|
||||||
for name in pairs(commands.game_commands) do
|
|
||||||
name = name
|
|
||||||
if match(name:lower(), keyword) then
|
|
||||||
count = count + 1
|
|
||||||
matches[count] = name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return matches
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Trigger messages on deprecated or defined commands, ignores the server
|
|
||||||
local function on_command(event)
|
|
||||||
if not event.player_index then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local alternative = deprecated_command_alternatives[event.command]
|
|
||||||
if alternative then
|
|
||||||
local player = Game.get_player_by_index(event.player_index)
|
|
||||||
if player then
|
|
||||||
player.print(format('Warning! Usage of the command "/%s" is deprecated. Please use "/%s" instead.', event.command, alternative))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local notification = notify_on_commands[event.command]
|
|
||||||
if notification and event.player_index then
|
|
||||||
local player = Game.get_player_by_index(event.player_index)
|
|
||||||
if player then
|
|
||||||
player.print(notification)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Traps command errors if not in DEBUG.
|
|
||||||
if not _DEBUG then
|
|
||||||
local old_add_command = commands.add_command
|
|
||||||
commands.add_command =
|
|
||||||
function(name, desc, func)
|
|
||||||
old_add_command(
|
|
||||||
name,
|
|
||||||
desc,
|
|
||||||
function(cmd)
|
|
||||||
local success, error = pcall(func, cmd)
|
|
||||||
if not success then
|
|
||||||
log(error)
|
|
||||||
Game.player_print('Sorry there was an error running ' .. cmd.name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Event.add(defines.events.on_console_command, on_command)
|
|
||||||
|
|
||||||
return Command
|
|
||||||
223
utils/core.lua
223
utils/core.lua
@@ -1,223 +0,0 @@
|
|||||||
--- This file contains core utilities used by the redmew scenario.
|
|
||||||
|
|
||||||
-- Dependencies
|
|
||||||
local Game = require 'utils.game' --- @dep utils.game
|
|
||||||
local Color = require 'resources.color_presets' --- @dep resources.color_presets
|
|
||||||
|
|
||||||
-- localized functions
|
|
||||||
local random = math.random
|
|
||||||
local sqrt = math.sqrt
|
|
||||||
local floor = math.floor
|
|
||||||
local match = string.match
|
|
||||||
local insert = table.insert
|
|
||||||
local concat = table.concat
|
|
||||||
|
|
||||||
-- local constants
|
|
||||||
local prefix = '## - '
|
|
||||||
local minutes_to_ticks = 60 * 60
|
|
||||||
local hours_to_ticks = 60 * 60 * 60
|
|
||||||
local ticks_to_minutes = 1 / minutes_to_ticks
|
|
||||||
local ticks_to_hours = 1 / hours_to_ticks
|
|
||||||
|
|
||||||
-- local variables
|
|
||||||
local Module = {}
|
|
||||||
|
|
||||||
--- Measures distance between pos1 and pos2
|
|
||||||
function Module.distance(pos1, pos2)
|
|
||||||
local dx = pos2.x - pos1.x
|
|
||||||
local dy = pos2.y - pos1.y
|
|
||||||
return sqrt(dx * dx + dy * dy)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Takes msg and prints it to all players except provided player
|
|
||||||
-- @param msg <string|table> table if locale is used
|
|
||||||
-- @param player <LuaPlayer> the player not to send the message to
|
|
||||||
-- @param color <table> the color to use for the message, defaults to white
|
|
||||||
function Module.print_except(msg, player, color)
|
|
||||||
if not color then
|
|
||||||
color = Color.white
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, p in pairs(game.connected_players) do
|
|
||||||
if p ~= player then
|
|
||||||
p.print(msg, color)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Prints a message to all online admins
|
|
||||||
-- @param msg <string|table> table if locale is used
|
|
||||||
-- @param source <LuaPlayer|string|nil> string must be the name of a player, nil for server.
|
|
||||||
function Module.print_admins(msg, source)
|
|
||||||
local source_name
|
|
||||||
local chat_color
|
|
||||||
if source then
|
|
||||||
if type(source) == 'string' then
|
|
||||||
source_name = source
|
|
||||||
chat_color = game.players[source].chat_color
|
|
||||||
else
|
|
||||||
source_name = source.name
|
|
||||||
chat_color = source.chat_color
|
|
||||||
end
|
|
||||||
else
|
|
||||||
source_name = 'Server'
|
|
||||||
chat_color = Color.yellow
|
|
||||||
end
|
|
||||||
local formatted_msg = {'utils_core.print_admins',prefix, source_name, msg}
|
|
||||||
log(formatted_msg)
|
|
||||||
for _, p in pairs(game.connected_players) do
|
|
||||||
if p.admin then
|
|
||||||
p.print(formatted_msg, chat_color)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns a valid string with the name of the actor of a command.
|
|
||||||
function Module.get_actor()
|
|
||||||
if game.player then
|
|
||||||
return game.player.name
|
|
||||||
end
|
|
||||||
return '<server>'
|
|
||||||
end
|
|
||||||
|
|
||||||
function Module.cast_bool(var)
|
|
||||||
if var then
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Module.find_entities_by_last_user(player, surface, filters)
|
|
||||||
if type(player) == 'string' or not player then
|
|
||||||
error("bad argument #1 to '" .. debug.getinfo(1, 'n').name .. "' (number or LuaPlayer expected, got " .. type(player) .. ')', 1)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if type(surface) ~= 'table' and type(surface) ~= 'number' then
|
|
||||||
error("bad argument #2 to '" .. debug.getinfo(1, 'n').name .. "' (number or LuaSurface expected, got " .. type(surface) .. ')', 1)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local entities = {}
|
|
||||||
local filter = filters or {}
|
|
||||||
if type(surface) == 'number' then
|
|
||||||
surface = game.surfaces[surface]
|
|
||||||
end
|
|
||||||
if type(player) == 'number' then
|
|
||||||
player = Game.get_player_by_index(player)
|
|
||||||
end
|
|
||||||
filter.force = player.force.name
|
|
||||||
for _, e in pairs(surface.find_entities_filtered(filter)) do
|
|
||||||
if e.last_user == player then
|
|
||||||
insert(entities, e)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return entities
|
|
||||||
end
|
|
||||||
|
|
||||||
function Module.ternary(c, t, f)
|
|
||||||
if c then
|
|
||||||
return t
|
|
||||||
else
|
|
||||||
return f
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Takes a time in ticks and returns a string with the time in format "x hour(s) x minute(s)"
|
|
||||||
function Module.format_time(ticks)
|
|
||||||
local result = {}
|
|
||||||
|
|
||||||
local hours = floor(ticks * ticks_to_hours)
|
|
||||||
if hours > 0 then
|
|
||||||
ticks = ticks - hours * hours_to_ticks
|
|
||||||
insert(result, hours)
|
|
||||||
if hours == 1 then
|
|
||||||
insert(result, 'hour')
|
|
||||||
else
|
|
||||||
insert(result, 'hours')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local minutes = floor(ticks * ticks_to_minutes)
|
|
||||||
insert(result, minutes)
|
|
||||||
if minutes == 1 then
|
|
||||||
insert(result, 'minute')
|
|
||||||
else
|
|
||||||
insert(result, 'minutes')
|
|
||||||
end
|
|
||||||
|
|
||||||
return concat(result, ' ')
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Prints a message letting the player know they cannot run a command
|
|
||||||
-- @param name string name of the command
|
|
||||||
function Module.cant_run(name)
|
|
||||||
Game.player_print("Can't run command (" .. name .. ') - insufficient permission.')
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Logs the use of a command and its user
|
|
||||||
-- @param actor string with the actor's name (usually acquired by calling get_actor)
|
|
||||||
-- @param command the command's name as table element
|
|
||||||
-- @param parameters the command's parameters as a table (optional)
|
|
||||||
function Module.log_command(actor, command, parameters)
|
|
||||||
local action = concat {'[Admin-Command] ', actor, ' used: ', command}
|
|
||||||
if parameters then
|
|
||||||
action = concat {action, ' ', parameters}
|
|
||||||
end
|
|
||||||
log(action)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Module.comma_value(n) -- credit http://richard.warburton.it
|
|
||||||
local left, num, right = match(n, '^([^%d]*%d)(%d*)(.-)$')
|
|
||||||
return left .. (num:reverse():gsub('(%d%d%d)', '%1,'):reverse()) .. right
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Asserts the argument is one of type arg_types
|
|
||||||
-- @param arg the variable to check
|
|
||||||
-- @param arg_types the type as a table of sings
|
|
||||||
-- @return boolean
|
|
||||||
function Module.verify_mult_types(arg, arg_types)
|
|
||||||
for _, arg_type in pairs(arg_types) do
|
|
||||||
if type(arg) == arg_type then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns a random RGB color as a table
|
|
||||||
function Module.random_RGB()
|
|
||||||
return {r = random(0, 255), g = random(0, 255), b = random(0, 255)}
|
|
||||||
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
|
|
||||||
function Module.set_and_return(tbl, key, value)
|
|
||||||
tbl[key] = value
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
|
|
||||||
-- add utility functions that exist in base factorio/util
|
|
||||||
require 'util'
|
|
||||||
|
|
||||||
--- Moves a position according to the parameters given
|
|
||||||
-- Notice: only accepts cardinal directions as direction
|
|
||||||
-- @param position <table> table containing a map position
|
|
||||||
-- @param direction <defines.direction> north, east, south, west
|
|
||||||
-- @param distance <number>
|
|
||||||
-- @return <table> modified position
|
|
||||||
Module.move_position = util.moveposition
|
|
||||||
|
|
||||||
--- Takes a direction and gives you the opposite
|
|
||||||
-- @param direction <defines.direction> north, east, south, west, northeast, northwest, southeast, southwest
|
|
||||||
-- @return <number> representing the direction
|
|
||||||
Module.opposite_direction = util.oppositedirection
|
|
||||||
|
|
||||||
--- Takes the string of a module and returns whether is it available or not
|
|
||||||
-- @param name <string> the name of the module (ex. 'utils.core')
|
|
||||||
-- @return <boolean>
|
|
||||||
Module.is_module_available = util.ismoduleavailable
|
|
||||||
|
|
||||||
return Module
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
--- A small debugging tool that writes the contents of _ENV to a file when the game loads.
|
|
||||||
-- Useful for ensuring you get the same information when loading
|
|
||||||
-- the reference and desync levels in desync reports.
|
|
||||||
-- dependencies
|
|
||||||
local table = require 'utils.table' --- @dep utils.table
|
|
||||||
local Event = require 'utils.event' --- @dep utils.event
|
|
||||||
|
|
||||||
-- localized functions
|
|
||||||
local inspect = table.inspect
|
|
||||||
|
|
||||||
-- local constants
|
|
||||||
local filename = 'env_dump.lua'
|
|
||||||
|
|
||||||
-- Removes metatables and the package table
|
|
||||||
local filter = function(item, path)
|
|
||||||
if path[#path] ~= inspect.METATABLE and item ~= 'package' then
|
|
||||||
return item
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function player_joined(event)
|
|
||||||
local dump_string = inspect(_ENV, {process = filter})
|
|
||||||
if dump_string then
|
|
||||||
local s = string.format('tick on join: %s\n%s', event.tick, dump_string)
|
|
||||||
game.write_file(filename, s)
|
|
||||||
game.print('_ENV dumped into ' .. filename)
|
|
||||||
else
|
|
||||||
game.print('_ENV not dumped, dump_string was nil')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Event.add(defines.events.on_player_joined_game, player_joined)
|
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
local EventCore = require 'utils.event_core' --- @dep utils.event_core
|
local EventCore = require 'utils.event_core' --- @dep utils.event_core
|
||||||
local Global = require 'utils.global' --- @dep utils.global
|
local Global = require 'utils.global' --- @dep utils.global
|
||||||
local Token = require 'utils.token' --- @dep utils.token
|
local Token = require 'utils.token' --- @dep utils.token
|
||||||
local Debug = require 'utils.debug' --- @dep utils.debug
|
local Debug = require 'overrides.debug' --- @dep overrides.debug
|
||||||
|
|
||||||
local table_remove = table.remove
|
local table_remove = table.remove
|
||||||
local core_add = EventCore.add
|
local core_add = EventCore.add
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
local Global = require 'utils.global' --- @dep utils.global
|
local Global = require 'utils.global' --- @dep utils.global
|
||||||
local Color = require 'resources.color_presets' --- @dep resources.color_presets
|
local Color = require 'utils.color_presets' --- @dep utils.color_presets
|
||||||
local pairs = pairs
|
local pairs = pairs
|
||||||
|
|
||||||
local Game = {}
|
local Game = {}
|
||||||
|
|||||||
@@ -1,154 +0,0 @@
|
|||||||
local Global = require 'utils.global' --- @dep utils.global
|
|
||||||
local Game = require 'utils.game' --- @dep utils.game
|
|
||||||
local PlayerStats = require 'features.player_stats' --- @dep features.player_stats
|
|
||||||
local Command = require 'utils.command' --- @dep utils.command
|
|
||||||
local Ranks = require 'resources.ranks' --- @dep resources.ranks
|
|
||||||
|
|
||||||
local format = string.format
|
|
||||||
local abs = math.abs
|
|
||||||
local concat = table.concat
|
|
||||||
|
|
||||||
local Public = {}
|
|
||||||
local reward_token = {global.config.player_rewards.token} or {global.config.market.currency} or {'coin'}
|
|
||||||
|
|
||||||
Global.register(
|
|
||||||
{
|
|
||||||
reward_token = reward_token
|
|
||||||
},
|
|
||||||
function(tbl)
|
|
||||||
reward_token = tbl.reward_token
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Returns the single or plural form of the token name
|
|
||||||
local function get_token_plural(quantity)
|
|
||||||
if quantity and quantity > 1 then
|
|
||||||
return concat({reward_token[1], 's'})
|
|
||||||
else
|
|
||||||
return reward_token[1]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set the item to use for rewards
|
|
||||||
-- @param reward string - item name to use as reward
|
|
||||||
-- @return boolean true - indicating success
|
|
||||||
Public.set_reward = function(reward)
|
|
||||||
if global.config.player_rewards.enabled == false then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
reward_token[1] = reward
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns the name of the reward item
|
|
||||||
Public.get_reward = function()
|
|
||||||
return reward_token[1]
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Gives reward tokens to the player
|
|
||||||
-- @param player <number|LuaPlayer>
|
|
||||||
-- @param amount <number> of reward tokens
|
|
||||||
-- @param message <string> an optional message to send to the affected player
|
|
||||||
-- @return <number> indicating how many were inserted or if operation failed
|
|
||||||
Public.give_reward = function(player, amount, message)
|
|
||||||
if global.config.player_rewards.enabled == false then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local player_index
|
|
||||||
if type(player) == 'number' then
|
|
||||||
player_index = player
|
|
||||||
player = Game.get_player_by_index(player)
|
|
||||||
else
|
|
||||||
player_index = player.index
|
|
||||||
end
|
|
||||||
local reward = {name = reward_token[1], count = amount}
|
|
||||||
if not player.can_insert(reward) then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
if message then
|
|
||||||
player.print(message)
|
|
||||||
end
|
|
||||||
local coin_difference = player.insert(reward)
|
|
||||||
if reward_token[1] == 'coin' then
|
|
||||||
PlayerStats.change_coin_earned(player_index, coin_difference)
|
|
||||||
end
|
|
||||||
return coin_difference
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Removes reward tokens from the player
|
|
||||||
-- @param player <number|LuaPlayer>
|
|
||||||
-- @param amount <number> of reward tokens
|
|
||||||
-- @param message <string> an optional message to send to the affected player
|
|
||||||
-- @return <number> indicating how many were removed or if operation failed
|
|
||||||
Public.remove_reward = function(player, amount, message)
|
|
||||||
if global.config.player_rewards.enabled == false then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local player_index
|
|
||||||
if type(player) == 'number' then
|
|
||||||
player_index = player
|
|
||||||
player = Game.get_player_by_index(player)
|
|
||||||
else
|
|
||||||
player_index = player.index
|
|
||||||
end
|
|
||||||
local unreward = {name = reward_token[1], count = amount}
|
|
||||||
if message then
|
|
||||||
player.print(message)
|
|
||||||
end
|
|
||||||
local coin_difference = player.remove_item(unreward)
|
|
||||||
if reward_token[1] == 'coin' then
|
|
||||||
PlayerStats.change_coin_earned(player_index, -coin_difference)
|
|
||||||
end
|
|
||||||
return coin_difference
|
|
||||||
end
|
|
||||||
|
|
||||||
Command.add(
|
|
||||||
'reward',
|
|
||||||
{
|
|
||||||
description = 'Gives a reward to a target player (removes if quantity is negative)',
|
|
||||||
arguments = {'target', 'quantity', 'reason'},
|
|
||||||
default_values = {reason = false},
|
|
||||||
required_rank = Ranks.admin,
|
|
||||||
capture_excess_arguments = true,
|
|
||||||
allowed_by_server = true,
|
|
||||||
allowed_by_player = true
|
|
||||||
},
|
|
||||||
function(args, player)
|
|
||||||
local player_name = 'server'
|
|
||||||
if player then
|
|
||||||
player_name = player.name
|
|
||||||
end
|
|
||||||
|
|
||||||
local target_name = args.target
|
|
||||||
local target = game.players[target_name]
|
|
||||||
if not target then
|
|
||||||
player.print('Target not found.')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local quantity = tonumber(args.quantity)
|
|
||||||
if quantity > 0 then
|
|
||||||
Public.give_reward(target, quantity)
|
|
||||||
local string = format('%s has rewarded %s with %s %s', player_name, target_name, quantity, get_token_plural(quantity))
|
|
||||||
if args.reason then
|
|
||||||
string = format('%s for %s', string, args.reason)
|
|
||||||
end
|
|
||||||
game.print(string)
|
|
||||||
elseif quantity < 0 then
|
|
||||||
quantity = abs(quantity)
|
|
||||||
Public.remove_reward(target, quantity)
|
|
||||||
local string = format('%s has punished %s by taking %s %s', player_name, target_name, quantity, get_token_plural(quantity))
|
|
||||||
if args.reason then
|
|
||||||
string = format('%s for %s', string, args.reason)
|
|
||||||
end
|
|
||||||
game.print(string)
|
|
||||||
else
|
|
||||||
Game.player_print(" A reward of 0 is neither a reward nor a punishment, it's just dumb. Try harder.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
return Public
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
--- A module to prevent recipes from being unlocked by research. Accessed via the public functions.
|
|
||||||
local Event = require 'utils.event' --- @dep utils.event
|
|
||||||
local Global = require 'utils.global' --- @dep utils.global
|
|
||||||
|
|
||||||
local Public = {}
|
|
||||||
|
|
||||||
local recipes = {}
|
|
||||||
|
|
||||||
Global.register(
|
|
||||||
{
|
|
||||||
recipes = recipes
|
|
||||||
},
|
|
||||||
function(tbl)
|
|
||||||
recipes = tbl.recipes
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
Event.add(
|
|
||||||
defines.events.on_research_finished,
|
|
||||||
function(event)
|
|
||||||
local p_force = game.forces.player
|
|
||||||
local r = event.research
|
|
||||||
for _, effect in pairs(r.effects) do
|
|
||||||
local recipe = effect.recipe
|
|
||||||
if recipe and recipes[recipe] then
|
|
||||||
p_force.recipes[recipe].enabled = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
Event.on_init(
|
|
||||||
function()
|
|
||||||
for recipe in pairs(recipes) do
|
|
||||||
game.forces.player.recipes[recipe].enabled = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Locks recipes, preventing them from being enabled by research.
|
|
||||||
-- Does not check if they should be enabled/disabled by existing research.
|
|
||||||
-- @param tbl <table> an array of recipe strings
|
|
||||||
function Public.lock_recipes(tbl)
|
|
||||||
for i = 1, #tbl do
|
|
||||||
recipes[tbl[i]] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Unlocks recipes, allowing them to be enabled by research.
|
|
||||||
-- Does not check if they should be enabled/disabled by existing research.
|
|
||||||
-- @param tbl <table> an array of recipe strings
|
|
||||||
function Public.unlock_recipes(tbl)
|
|
||||||
for i = 1, #tbl do
|
|
||||||
recipes[tbl[i]] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return Public
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
local Global = require 'utils.global' --- @dep utils.global
|
|
||||||
local type = type
|
|
||||||
local error = error
|
|
||||||
local tonumber = tonumber
|
|
||||||
local tostring = tostring
|
|
||||||
local pairs = pairs
|
|
||||||
local format = string.format
|
|
||||||
|
|
||||||
--- Contains a set of callable that will attempt to sanitize and transform the input
|
|
||||||
local settings_type = {
|
|
||||||
fraction = function (input)
|
|
||||||
input = tonumber(input)
|
|
||||||
|
|
||||||
if input == nil then
|
|
||||||
return false, 'fraction setting type requires the input to be a valid number between 0 and 1.'
|
|
||||||
end
|
|
||||||
|
|
||||||
if input < 0 then
|
|
||||||
input = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
if input > 1 then
|
|
||||||
input = 1
|
|
||||||
end
|
|
||||||
|
|
||||||
return true, input
|
|
||||||
end,
|
|
||||||
string = function (input)
|
|
||||||
if input == nil then
|
|
||||||
return true, ''
|
|
||||||
end
|
|
||||||
|
|
||||||
local input_type = type(input)
|
|
||||||
if input_type == 'string' then
|
|
||||||
return true, input
|
|
||||||
end
|
|
||||||
|
|
||||||
if input_type == 'number' or input_type == 'boolean' then
|
|
||||||
return true, tostring(input)
|
|
||||||
end
|
|
||||||
|
|
||||||
return false, 'string setting type requires the input to be either a valid string or something that can be converted to a string.'
|
|
||||||
end,
|
|
||||||
boolean = function (input)
|
|
||||||
local input_type = type(input)
|
|
||||||
|
|
||||||
if input_type == 'boolean' then
|
|
||||||
return true, input
|
|
||||||
end
|
|
||||||
|
|
||||||
if input_type == 'string' then
|
|
||||||
if input == '0' or input == '' or input == 'false' or input == 'no' then
|
|
||||||
return true, false
|
|
||||||
end
|
|
||||||
if input == '1' or input == 'true' or input == 'yes' then
|
|
||||||
return true, true
|
|
||||||
end
|
|
||||||
|
|
||||||
return true, tonumber(input) ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if input_type == 'number' then
|
|
||||||
return true, input ~= 0
|
|
||||||
end
|
|
||||||
|
|
||||||
return false, 'boolean setting type requires the input to be either a boolean, number or string that can be transformed to a boolean.'
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
local settings = {}
|
|
||||||
local memory = {}
|
|
||||||
|
|
||||||
Global.register(memory, function (tbl) memory = tbl end)
|
|
||||||
|
|
||||||
local Public = {}
|
|
||||||
|
|
||||||
Public.types = {fraction = 'fraction', string = 'string', boolean = 'boolean'}
|
|
||||||
|
|
||||||
---Register a specific setting with a sensitization setting type.
|
|
||||||
---
|
|
||||||
--- Available setting types:
|
|
||||||
--- - fraction (number between 0 and 1) in either number or string form
|
|
||||||
--- - string a string or anything that can be cast to a string
|
|
||||||
--- - boolean, 1, 0, yes, no, true, false or an empty string for false
|
|
||||||
---
|
|
||||||
--- This function must be called in the control stage, i.e. not inside an event.
|
|
||||||
---
|
|
||||||
---@param name string
|
|
||||||
---@param setting_type string
|
|
||||||
---@param default mixed
|
|
||||||
function Public.register(name, setting_type, default)
|
|
||||||
if _LIFECYCLE ~= _STAGE.control then
|
|
||||||
error(format('You can only register setting names in the control stage, i.e. not inside events. Tried setting "%s" with type "%s".', name, setting_type), 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
if settings[name] then
|
|
||||||
error(format('Trying to register setting for "%s" while it has already been registered.', name), 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
local callback = settings_type[setting_type]
|
|
||||||
if not callback then
|
|
||||||
error(format('Trying to register setting for "%s" with type "%s" while this type does not exist.', name, setting_type), 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
local setting = {
|
|
||||||
default = default,
|
|
||||||
callback = callback,
|
|
||||||
}
|
|
||||||
|
|
||||||
settings[name] = setting
|
|
||||||
|
|
||||||
return setting
|
|
||||||
end
|
|
||||||
|
|
||||||
---Sets a setting to a specific value for a player.
|
|
||||||
---
|
|
||||||
---In order to get a setting value, it has to be registered via the "register" function.
|
|
||||||
---
|
|
||||||
---@param player_index number
|
|
||||||
---@param name string
|
|
||||||
---@param value mixed
|
|
||||||
function Public.set(player_index, name, value)
|
|
||||||
local setting = settings[name]
|
|
||||||
if not setting then
|
|
||||||
return error(format('Setting "%s" does not exist.', name), 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
local success, sanitized_value = setting.callback(value)
|
|
||||||
|
|
||||||
if not success then
|
|
||||||
error(format('Setting "%s" failed: %s', name, sanitized_value), 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
local player_settings = memory[player_index]
|
|
||||||
if not player_settings then
|
|
||||||
player_settings = {}
|
|
||||||
memory[player_index] = player_settings
|
|
||||||
end
|
|
||||||
|
|
||||||
player_settings[name] = sanitized_value
|
|
||||||
|
|
||||||
return sanitized_value
|
|
||||||
end
|
|
||||||
|
|
||||||
---Returns the value of a setting for this player.
|
|
||||||
---
|
|
||||||
---In order to set a setting value, it has to be registered via the "register" function.
|
|
||||||
---
|
|
||||||
---@param player_index number
|
|
||||||
---@param name string
|
|
||||||
function Public.get(player_index, name)
|
|
||||||
local setting = settings[name]
|
|
||||||
if not setting then
|
|
||||||
return error(format('Setting "%s" does not exist.', name), 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
local player_settings = memory[player_index]
|
|
||||||
if not player_settings then
|
|
||||||
return setting.default
|
|
||||||
end
|
|
||||||
|
|
||||||
local player_setting = player_settings[name]
|
|
||||||
return player_setting ~= nil and player_setting or setting.default
|
|
||||||
end
|
|
||||||
|
|
||||||
---Returns a table of all settings for a given player in a key => value set-up
|
|
||||||
---@param player_index number
|
|
||||||
function Public.all(player_index)
|
|
||||||
local player_settings = memory[player_index] or {}
|
|
||||||
local output = {}
|
|
||||||
for name, data in pairs(settings) do
|
|
||||||
output[name] = player_settings[name] or data.default
|
|
||||||
end
|
|
||||||
|
|
||||||
return output
|
|
||||||
end
|
|
||||||
|
|
||||||
return Public
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
--- This module provides a classical mealy/moore state machine.
|
|
||||||
-- Each machine in constructed by calling new()
|
|
||||||
-- States and Transitions are lazily added to the machine as transition handlers and state tick handlers are registered.
|
|
||||||
-- However the state machine must be fully defined after init is done. Dynamic machine changes are currently unsupported
|
|
||||||
-- An example usage can be found here: map_gen\combined\tetris\control.lua
|
|
||||||
|
|
||||||
local Module = {}
|
|
||||||
|
|
||||||
local Debug = require 'utils.debug' --- @dep utils.debug
|
|
||||||
|
|
||||||
local in_state_callbacks = {}
|
|
||||||
local transaction_callbacks = {}
|
|
||||||
local max_stack_depth = 20
|
|
||||||
local machine_count = 0
|
|
||||||
local control_stage = _STAGE.control
|
|
||||||
|
|
||||||
--- Transitions the supplied machine into a given state and executes all transaction_callbacks
|
|
||||||
-- @param self StateMachine
|
|
||||||
-- @param new_state number/string The new state to transition to
|
|
||||||
function Module.transition(self, new_state)
|
|
||||||
Debug.print(string.format('Transitioning from state %d to state %d.', self.state, new_state))
|
|
||||||
local old_state = self.state
|
|
||||||
|
|
||||||
local stack_depth = self.stack_depth
|
|
||||||
self.stack_depth = stack_depth + 1
|
|
||||||
if stack_depth > max_stack_depth then
|
|
||||||
if _DEBUG then
|
|
||||||
error('[WARNING] Stack overflow at:' .. debug.traceback())
|
|
||||||
else
|
|
||||||
log('[WARNING] Stack overflow at:' .. debug.traceback())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local exit_callbacks = transaction_callbacks[self.id][old_state]
|
|
||||||
if exit_callbacks then
|
|
||||||
local entry_callbacks = exit_callbacks[new_state]
|
|
||||||
if entry_callbacks then
|
|
||||||
for i = 1, #entry_callbacks do
|
|
||||||
local callback = entry_callbacks[i]
|
|
||||||
if callback then
|
|
||||||
callback()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.state = new_state
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Is this machine in this state?
|
|
||||||
-- @param self StateMachine
|
|
||||||
-- @param state number/string
|
|
||||||
-- @return boolean
|
|
||||||
function Module.in_state(self, state)
|
|
||||||
return self.state == state
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Invoke a machine tick. Will execute all in_state_callbacks of the given machine
|
|
||||||
-- @param self StateMachine the machine, whose handlers will be invoked
|
|
||||||
function Module.machine_tick(self)
|
|
||||||
local callbacks = in_state_callbacks[self.id][self.state]
|
|
||||||
if callbacks then
|
|
||||||
for i=1, #callbacks do
|
|
||||||
local callback = callbacks[i]
|
|
||||||
if callback then
|
|
||||||
callback()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.stack_depth = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Register a handler that will be invoked by StateMachine.machine_tick
|
|
||||||
-- You may register multiple handlers for the same transition
|
|
||||||
-- NOTICE: This function will invoke an error if called after init. Dynamic machine changes are currently unsupported
|
|
||||||
-- @param self StateMachine the machine
|
|
||||||
-- @param state number/string The state, that the machine will be in, when callback is invoked
|
|
||||||
-- @param callback function
|
|
||||||
function Module.register_state_tick_callback(self, state, callback)
|
|
||||||
if _LIFECYCLE ~= control_stage then
|
|
||||||
error('Calling StateMachine.register_state_tick_callback after the control stage is unsupported due to desyncs.', 2)
|
|
||||||
end
|
|
||||||
in_state_callbacks[self.id][state] = in_state_callbacks[self.id][state] or {}
|
|
||||||
table.insert(in_state_callbacks[self.id][state], callback)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Register a handler that will be invoked by StateMachine.transition
|
|
||||||
-- You may register multiple handlers for the same transition
|
|
||||||
-- NOTICE: This function will invoke an error if called after init. Dynamic machine changes are currently unsupported
|
|
||||||
-- @param self StateMachine the machine
|
|
||||||
-- @param old number/string exiting state
|
|
||||||
-- @param new number/string entering state
|
|
||||||
-- @param callback function
|
|
||||||
function Module.register_transition_callback(self, old, new, callback)
|
|
||||||
if _LIFECYCLE ~= control_stage then
|
|
||||||
error('Calling StateMachine.register_transition_callback after the control stage is unsupported due to desyncs.', 2)
|
|
||||||
end
|
|
||||||
transaction_callbacks[self.id][old] = transaction_callbacks[self.id][old] or {}
|
|
||||||
transaction_callbacks[self.id][old][new] = transaction_callbacks[self.id][old][new] or {}
|
|
||||||
table.insert(transaction_callbacks[self.id][old][new], callback)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Constructs a new state machine
|
|
||||||
-- @param init_state number/string The starting state of the machine
|
|
||||||
-- @return StateMachine The constructed state machine object
|
|
||||||
function Module.new(init_state)
|
|
||||||
if _LIFECYCLE ~= control_stage then
|
|
||||||
error('Calling StateMachine.new after the control stage is unsupported due to desyncs.', 2)
|
|
||||||
end
|
|
||||||
machine_count = machine_count + 1
|
|
||||||
in_state_callbacks[machine_count] = {}
|
|
||||||
transaction_callbacks[machine_count] = {}
|
|
||||||
return {
|
|
||||||
state = init_state,
|
|
||||||
stack_depth = 0,
|
|
||||||
id = machine_count,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
return Module
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
--- source https://github.com/daurnimator/luatz/blob/master/luatz/timetable.lua
|
|
||||||
-- edited down to just what is needed.
|
|
||||||
|
|
||||||
local Public = {}
|
|
||||||
|
|
||||||
local floor = math.floor
|
|
||||||
local strformat = string.format
|
|
||||||
|
|
||||||
local function borrow(tens, units, base)
|
|
||||||
local frac = tens % 1
|
|
||||||
units = units + frac * base
|
|
||||||
tens = tens - frac
|
|
||||||
return tens, units
|
|
||||||
end
|
|
||||||
|
|
||||||
local function carry(tens, units, base)
|
|
||||||
if units >= base then
|
|
||||||
tens = tens + floor(units / base)
|
|
||||||
units = units % base
|
|
||||||
elseif units < 0 then
|
|
||||||
tens = tens + floor(units / base)
|
|
||||||
units = (base + units) % base
|
|
||||||
end
|
|
||||||
return tens, units
|
|
||||||
end
|
|
||||||
|
|
||||||
local function is_leap(y)
|
|
||||||
if (y % 4) ~= 0 then
|
|
||||||
return false
|
|
||||||
elseif (y % 100) ~= 0 then
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return (y % 400) == 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local mon_lengths = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
|
||||||
|
|
||||||
-- Number of days in year until start of month; not corrected for leap years
|
|
||||||
local months_to_days_cumulative = {0}
|
|
||||||
for i = 2, 12 do
|
|
||||||
months_to_days_cumulative[i] = months_to_days_cumulative[i - 1] + mon_lengths[i - 1]
|
|
||||||
end
|
|
||||||
|
|
||||||
local function month_length(m, y)
|
|
||||||
if m == 2 then
|
|
||||||
return is_leap(y) and 29 or 28
|
|
||||||
else
|
|
||||||
return mon_lengths[m]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function day_of_year(day, month, year)
|
|
||||||
local y_day = months_to_days_cumulative[month]
|
|
||||||
if month > 2 and is_leap(year) then
|
|
||||||
y_day = y_day + 1
|
|
||||||
end
|
|
||||||
return y_day + day
|
|
||||||
end
|
|
||||||
|
|
||||||
local function leap_years_since(year)
|
|
||||||
return floor(year / 4) - floor(year / 100) + floor(year / 400)
|
|
||||||
end
|
|
||||||
|
|
||||||
local leap_years_since_1970 = leap_years_since(1970)
|
|
||||||
|
|
||||||
local function normalise(year, month, day, hour, min, sec)
|
|
||||||
-- `month` and `day` start from 1, need -1 and +1 so it works modulo
|
|
||||||
month, day = month - 1, day - 1
|
|
||||||
|
|
||||||
-- Convert everything (except seconds) to an integer
|
|
||||||
-- by propagating fractional components down.
|
|
||||||
year, month = borrow(year, month, 12)
|
|
||||||
-- Carry from month to year first, so we get month length correct in next line around leap years
|
|
||||||
year, month = carry(year, month, 12)
|
|
||||||
month, day = borrow(month, day, month_length(floor(month + 1), year))
|
|
||||||
day, hour = borrow(day, hour, 24)
|
|
||||||
hour, min = borrow(hour, min, 60)
|
|
||||||
min, sec = borrow(min, sec, 60)
|
|
||||||
|
|
||||||
-- Propagate out of range values up
|
|
||||||
-- e.g. if `min` is 70, `hour` increments by 1 and `min` becomes 10
|
|
||||||
-- This has to happen for all columns after borrowing, as lower radix's may be pushed out of range
|
|
||||||
min, sec = carry(min, sec, 60) -- TODO: consider leap seconds?
|
|
||||||
hour, min = carry(hour, min, 60)
|
|
||||||
day, hour = carry(day, hour, 24)
|
|
||||||
-- Ensure `day` is not underflowed
|
|
||||||
-- Add a whole year of days at a time, this is later resolved by adding months
|
|
||||||
-- TODO[OPTIMIZE]: This could be slow if `day` is far out of range
|
|
||||||
while day < 0 do
|
|
||||||
month = month - 1
|
|
||||||
if month < 0 then
|
|
||||||
year = year - 1
|
|
||||||
month = 11
|
|
||||||
end
|
|
||||||
day = day + month_length(month + 1, year)
|
|
||||||
end
|
|
||||||
year, month = carry(year, month, 12)
|
|
||||||
|
|
||||||
-- TODO[OPTIMIZE]: This could potentially be slow if `day` is very large
|
|
||||||
while true do
|
|
||||||
local i = month_length(month + 1, year)
|
|
||||||
if day < i then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
day = day - i
|
|
||||||
month = month + 1
|
|
||||||
if month >= 12 then
|
|
||||||
month = 0
|
|
||||||
year = year + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Now we can place `day` and `month` back in their normal ranges
|
|
||||||
-- e.g. month as 1-12 instead of 0-11
|
|
||||||
month, day = month + 1, day + 1
|
|
||||||
|
|
||||||
return {year = year, month = month, day = day, hour = hour, min = min, sec = sec}
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Converts unix epoch timestamp into table {year: number, month: number, day: number, hour: number, min: number, sec: number}
|
|
||||||
-- @param seconds<number> unix epoch timestamp
|
|
||||||
-- @return {year: number, month: number, day: number, hour: number, min: number, sec: number}
|
|
||||||
function Public.to_timetable(seconds)
|
|
||||||
return normalise(1970, 1, 1, 0, 0, seconds)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Converts timetable into unix epoch timestamp
|
|
||||||
-- @param timetable<table> {year: number, month: number, day: number, hour: number, min: number, sec: number}
|
|
||||||
-- @return number
|
|
||||||
function Public.from_timetable(timetable)
|
|
||||||
local tt = normalise(timetable.year, timetable.month, timetable.day, timetable.hour, timetable.min, timetable.sec)
|
|
||||||
|
|
||||||
local year, month, day, hour, min, sec = tt.year, tt.month, tt.day, tt.hour, tt.min, tt.sec
|
|
||||||
|
|
||||||
local days_since_epoch =
|
|
||||||
day_of_year(day, month, year) + 365 * (year - 1970) + -- Each leap year adds one day
|
|
||||||
(leap_years_since(year - 1) - leap_years_since_1970) -
|
|
||||||
1
|
|
||||||
|
|
||||||
return days_since_epoch * (60 * 60 * 24) + hour * (60 * 60) + min * 60 + sec
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Converts unix epoch timestamp into human readable string.
|
|
||||||
-- @param seconds<type> unix epoch timestamp
|
|
||||||
-- @return string
|
|
||||||
function Public.to_string(seconds)
|
|
||||||
local tt = normalise(1970, 1, 1, 0, 0, seconds)
|
|
||||||
return strformat('%04u-%02u-%02u %02u:%02u:%02d', tt.year, tt.month, tt.day, tt.hour, tt.min, tt.sec)
|
|
||||||
end
|
|
||||||
|
|
||||||
return Public
|
|
||||||
Reference in New Issue
Block a user