Removed useless files

This commit is contained in:
Cooldude2606
2020-03-29 22:50:21 +01:00
parent 3141b8a75f
commit 6a2f99b069
56 changed files with 499 additions and 1846 deletions

View File

@@ -12,8 +12,8 @@ local Game = require 'utils.game' --- @dep utils.game
local Reports = require 'modules.control.reports' --- @dep modules.control.reports
local Warnings = require 'modules.control.warnings' --- @dep modules.control.warnings
local Jail = require 'modules.control.jail' --- @dep modules.control.jail
local Colors = require 'resources.color_presets' --- @dep resources.color_presets
local format_chat_player_name = ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
local format_chat_player_name = _C.ext_require('expcore.common','format_chat_player_name') --- @dep expcore.common
local selected_player_store = ''
local selected_action_store = ''

View File

@@ -2,7 +2,7 @@
-- @config Chat-Reply
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)
player.print(message)

View File

@@ -9,7 +9,7 @@
local Commands = require 'expcore.commands' --- @dep expcore.commands
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'
Commands.add_parse('role',function(input,player,reject)

View File

@@ -5,24 +5,17 @@
-- 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 |-----')
-- 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')
require 'resources.data_stages'
_LIFECYCLE = _STAGE.control -- Control stage
-- Overrides the _G.print function
require 'utils.print_override'
-- Omitting the math library is a very bad idea
require 'utils.math'
-- Global Debug and make sure our version file is registered
Debug = require 'utils.debug' --- @dep utils.debug
require 'resources.version'
-- 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
-- Require the global overrides
require 'overrides.stages' -- Data stages used in factorio, often used to test for runtime
require 'overrides.print' -- Overrides the _G.print function
require 'overrides.math' -- Omitting the math library is a very bad idea
require 'overrides.table' -- Adds alot more functions to the table module
inspect = require 'overrides.inspect' -- Used to covert any value into human readable string
Debug = require 'overrides.debug' -- Global Debug module
_C = require('expcore.common') -- _C is used to store lots of common functions expected to be used
global.expgaming_version = '6.0.0' -- The current version for exp gaming scenario
-- Please go to config/file_loader.lua to edit the files that are loaded
log('[INFO] Getting file loader config')
@@ -52,7 +45,7 @@ end
-- Override the default require; require can no longer load new scripts
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
log('[INFO] All files loaded with '..#errors..' errors:')

View File

@@ -196,7 +196,7 @@
]]
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 = {
defines={ -- common values are stored error like signals

View File

@@ -4,52 +4,276 @@
@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 Util = require 'util' --- @dep util
require 'utils.table'
require 'utils.math'
require 'overrides.table'
require 'overrides.math'
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') -- return false
-- @tparam any value the value to be tested
-- @tparam[opt=nil] string test_type the type to test for if not given then it tests for nil
-- @treturn boolean is v of type test_type
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
end
--- 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 string test_type the type that the value should be
-- @tparam string error_message the error message that is returned
-- @tparam number level the level to call the error on (level = 1 means the caller)
-- @treturn boolean true if no error was called
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
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
--- 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 string test_type the type that the value should be
-- @tparam string param_name the name of the param
-- @tparam number param_number the number param it is
-- @treturn boolean true if no error was raised
function Common.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
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)
end
return true
end
--- Raises an error when the value is the incorrect type, uses a consistent error message format
-- @usage validate_argument_type('foo',{'string','table'},'repeat_count',2) -- will raise error "Bad argument #02 to "<anon>"; "repeat_count" is of type string expected string or table"
-- @tparam any value the value that you want to test the type of
-- @tparam string test_types the types that the value should be
-- @tparam string param_name the name of the param
-- @tparam number param_number the number param it is
-- @treturn boolean true if no error was raised
function Common.validate_argument_multi_type(value, test_types, param_name, param_number)
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
-- @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
@@ -91,36 +315,6 @@ function Common.player_return(value,colour,player)
else rcon.print(returnAsString) 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
-- long will use words rather than letters
-- time will use : separates
@@ -213,6 +407,9 @@ function Common.format_time(ticks,options)
return rtn
end
--- Factorio.
-- @section factorio
--- Moves items to the position and stores them in the closest entity of the type given
-- @tparam table items items which are to be added to the chests, ['name']=count
-- @tparam[opt=navies] LuaSurface surface the surface that the items will be moved to
@@ -416,288 +613,4 @@ function Common.clear_flying_text(surface)
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

View File

@@ -117,8 +117,8 @@ local Global = require 'utils.global' --- @dep utils.global
local Event = require 'utils.event' --- @dep utils.event
local Groups = require 'expcore.permission_groups' --- @dep expcore.permission_groups
local Async = require 'expcore.async' --- @dep expcore.async
local Colours = require 'resources.color_presets' --- @dep resources.color_presets
local write_json = ext_require('expcore.common','write_json') --- @dep expcore.common
local Colours = require 'utils.color_presets' --- @dep utils.color_presets
local write_json = _C.ext_require('expcore.common','write_json') --- @dep expcore.common
local Roles = {
_prototype={},
@@ -437,7 +437,7 @@ function Roles.define_role_order(order)
end
end
-- 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
error('Role missing '..role_name..' from role order, all defined roles must be included.',2)
end

View File

@@ -5,7 +5,7 @@ local Event = require 'utils.event' --- @dep utils.event
local Game = require 'utils.game' --- @dep utils.game
local Global = require 'utils.global' --- @dep utils.global
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 = {
archive={} -- deaths moved here after body is gone

View File

@@ -3,8 +3,8 @@
local Event = require 'utils.event' --- @dep utils.event
local Game = require 'utils.game' --- @dep utils.game
local Colors = require 'resources.color_presets' --- @dep resources.color_presets
local write_json,format_time = ext_require('expcore.common','write_json','format_time') --- @dep expcore.common
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
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 function get_player_name(event)

View File

@@ -4,7 +4,7 @@ local Event = require 'utils.event' --- @dep utils.event
local Game = require 'utils.game' --- @dep utils.event
local config = require 'config.join_messages' --- @dep config.join_messages
local Global = require 'utils.global' --- @dep utils.global
require 'utils.table'
require 'overrides.table'
Global.register(config,function(tbl)
config = tbl

View File

@@ -1,12 +1,12 @@
--- Gives players random colours when they join, also applies preset colours to those who have them
-- @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 Event = require 'utils.event' --- @dep utils.event
local config = require 'config.preset_player_colours' --- @dep config.preset_player_colours
local Global = require 'utils.global' --- @dep utils.global
require 'utils.table'
require 'overrides.table'
Global.register(config,function(tbl)
config = tbl

View File

@@ -4,7 +4,7 @@
local Event = require 'utils.event' --- @dep utils.event
local Game = require 'utils.game' --- @dep utils.game
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
-- Loops over the config and finds the wile which has the highest value for strength

View File

@@ -4,7 +4,7 @@
]]
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'
--- Sends a message in chat that only admins can see

View File

@@ -4,7 +4,7 @@
]]
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'
--- Clears a players inventory

View File

@@ -5,7 +5,7 @@
local Commands = require 'expcore.commands' --- @dep expcore.commands
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'
--- Puts a player into jail and removes all other roles.

View File

@@ -4,7 +4,7 @@
]]
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)
if c1 < 0 then

View File

@@ -6,7 +6,7 @@
local Roles = require 'expcore.roles' --- @dep expcore.roles
local Commands = require 'expcore.commands' --- @dep expcore.commands
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'
--- Reports a player and notifies moderators

View File

@@ -5,8 +5,8 @@
local Commands = require 'expcore.commands' --- @dep expcore.commands
local Roles = require 'expcore.roles' --- @dep expcore.roles
local Colours = require 'resources.color_presets' --- @dep resources.color_presets
local format_chat_player_name, format_chat_colour_localized = ext_require('expcore.common',
local Colours = require 'utils.color_presets' --- @dep utils.color_presets
local format_chat_player_name, format_chat_colour_localized = _C.ext_require('expcore.common',
'format_chat_player_name',
'format_chat_colour_localized'
)

View File

@@ -5,7 +5,7 @@
local Commands = require 'expcore.commands' --- @dep expcore.commands
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
require 'config.expcore-commands.parse_roles'

View File

@@ -23,7 +23,7 @@
local Roles = require 'expcore.roles' --- @dep expcore.roles
local Game = require 'utils.game' --- @dep utils.game
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 assign_roles = Roles.assign_player

View File

@@ -32,8 +32,8 @@
]]
local Colors = require 'resources.color_presets' --- @dep resources.color_presets
local format_number = ext_require('util','format_number') --- @dep util
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
local format_number = _C.ext_require('util','format_number') --- @dep util
local precision_index = defines.flow_precision_index
local Production = {}

View File

@@ -25,7 +25,6 @@ local Store = require 'expcore.store' --- @dep expcore.store
local Global = require 'utils.global' --- @dep utils.global
local Token = require 'utils.token' --- @dep utils.token
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 = {}
@@ -64,7 +63,7 @@ Store.watch(warp_store,function(warp,warp_id)
end
-- 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)
new_warp_ids.spawn = spawn_id
force_warps[force_name] = new_warp_ids

View File

@@ -1,6 +1,6 @@
local Gui = require 'utils.gui' --- @dep utils.gui
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

View File

@@ -1,5 +1,5 @@
local Event = require 'utils.event'
local table = require 'utils.table'
local table = require 'overrides.table'
local Gui = require 'utils.gui'
local Model = require 'modules.gui.debug.model'

View File

@@ -1,6 +1,6 @@
local Gui = require 'utils.gui' --- @dep utils.gui
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 dump = Model.dump

View File

@@ -1,6 +1,6 @@
local Gui = require 'utils.gui' --- @dep utils.gui
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 dump = Model.dump

View File

@@ -1,6 +1,6 @@
local Gui = require 'utils.gui' --- @dep utils.gui
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_text = Model.dump_text

View File

@@ -1,5 +1,5 @@
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 = {}

View File

@@ -1,5 +1,5 @@
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 type = type

View File

@@ -1,5 +1,5 @@
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 dump_function = Model.dump_function
@@ -17,9 +17,9 @@ local ignore = {
math = true,
debug = true,
serpent = true,
['utils.math'] = true,
['overrides.math'] = true,
util = true,
['utils.inspect'] = true,
['overrides.inspect'] = true,
['mod-gui'] = true
}

View File

@@ -1,7 +1,7 @@
local Gui = require 'utils.gui' --- @dep utils.gui
local Global = require 'utils.global' --- @dep utils.global
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 dump = Model.dump

View File

@@ -9,9 +9,9 @@ local Roles = require 'expcore.roles' --- @dep expcore.roles
local Store = require 'expcore.store' --- @dep expcore.store
local Game = require 'utils.game' --- @dep utils.game
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 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
local selected_player_store = Store.register(function(player)

View File

@@ -8,8 +8,8 @@ local Gui = require 'expcore.gui' --- @dep expcore.gui
local Roles = require 'expcore.roles' --- @dep expcore.roles
local Event = require 'utils.event' --- @dep utils.event
local config = require 'config.rockets' --- @dep config.rockets
local format_time = ext_require('expcore.common','format_time') --- @dep expcore.common
local Colors = require 'resources.color_presets' --- @dep resources.color_presets
local format_time = _C.ext_require('expcore.common','format_time') --- @dep expcore.common
local Colors = require 'utils.color_presets' --- @dep utils.color_presets
local Rockets = require 'modules.control.rockets' --- @dep modules.control.rockets
local time_formats = {

View File

@@ -7,7 +7,7 @@
local Gui = require 'expcore.gui' --- @dep expcore.gui
local Roles = require 'expcore.roles' --- @dep expcore.gui
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 Production = require 'modules.control.production' --- @dep modules.control.production

View File

@@ -8,8 +8,8 @@ local Gui = require 'expcore.gui' --- @dep expcore.gui
local Event = require 'utils.event' --- @dep utils.event
local Roles = require 'expcore.roles' --- @dep expcore.roles
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 format_time = _C.format_time --- @dep expcore.common
-- Styles used for sprite buttons
local Styles = {
@@ -223,7 +223,7 @@ end)
local function update_task(player,task_table,task_id)
local task = Tasks.get_task(task_id)
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
if not task then
@@ -240,7 +240,7 @@ local function update_task(player,task_table,task_id)
-- Update the edit flow
local edit_flow = task_table['edit-'..task_id]
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 discard_task_element = edit_flow[discard_task.name]

View File

@@ -10,10 +10,10 @@ local Global = require 'utils.global' --- @dep utils.global
local Event = require 'utils.event' --- @dep utils.event
local Game = require 'utils.game' --- @dep utils.game
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 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 format_time = _C.format_time --- @dep expcore.common
-- Stores a boolean value indexed by player name
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
local edit_flow = warp_table['edit-'..warp_id]
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 discard_warp_element = edit_flow[discard_warp.name]

View File

@@ -339,4 +339,3 @@ end
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
return inspect

View File

@@ -1,5 +1,4 @@
local Public = {}
--luacheck:ignore global print
local locale_string = {'', '[PRINT] ', nil}
local raw_print = print
@@ -8,6 +7,4 @@ function print(str)
log(locale_string)
end
Public.raw_print = raw_print
return Public
return raw_print

View File

@@ -1,4 +1,5 @@
local loaded = _G.package.loaded
--luacheck:ignore global require
local loaded = package.loaded
local raw_require = require
function require(path)

View File

@@ -10,3 +10,5 @@ _STAGE = {
--config_change = 7,
runtime = 8
}
_LIFECYCLE = _STAGE.control

View File

@@ -22,7 +22,7 @@ end
-- The catch is that fast_remove doesn't guarantee to maintain the order of items in the array.
-- @param tbl <table> arrayed table
-- @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
if index > count then
return
@@ -36,7 +36,7 @@ end
--- Adds the contents of table t2 to table t1
-- @param t1 <table> to insert into
-- @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
if tonumber(k) then
t1[#t1 + 1] = v
@@ -46,11 +46,74 @@ function table.add_all(t1, t2)
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
-- @param t <table>
-- @param e <any> table element
-- @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
if v == e then
return k
@@ -63,7 +126,7 @@ end
-- @param t <table>
-- @param e <any> table element
-- @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
if t[i] == e then
return i
@@ -72,22 +135,33 @@ function table.index_of_in_array(t, e)
return nil
end
local index_of = table.index_of
--- Checks if a table contains an element
-- @param t <table>
-- @param e <any> table element
-- @return <boolean> indicating success
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
local index_of_in_array = table.index_of_in_array
--- Checks if the arrayed portion of a table contains an element
-- @param t <table>
-- @param e <any> table element
-- @return <boolean> indicating success
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
--- 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
--- 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
-- 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
@@ -171,19 +260,102 @@ function table.shuffle_table(t, rng)
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
--- 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 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
else
for i in pairs(t) do
t[i] = nil
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 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
--[[
@@ -238,7 +410,7 @@ require 'util'
-- 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.
-- 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)
table.size = table_size

View File

@@ -1,2 +0,0 @@
global.redmew_version = nil
global.expgaming_version = '5.0.0'

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -97,7 +97,7 @@
local EventCore = require 'utils.event_core' --- @dep utils.event_core
local Global = require 'utils.global' --- @dep utils.global
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 core_add = EventCore.add

View File

@@ -1,5 +1,5 @@
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 Game = {}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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