mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
Removed useless files
This commit is contained in:
@@ -12,8 +12,8 @@ local Game = require 'utils.game' --- @dep utils.game
|
||||
local Reports = require 'modules.control.reports' --- @dep modules.control.reports
|
||||
local 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 = ''
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
27
control.lua
27
control.lua
@@ -5,24 +5,17 @@
|
||||
-- this file is the landing point for all scenarios please DO NOT edit directly, further comments are to aid development
|
||||
|
||||
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:')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
)
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -161,4 +161,4 @@ function Debug.is_closure(func)
|
||||
end
|
||||
end
|
||||
|
||||
return Debug
|
||||
return Debug
|
||||
@@ -338,5 +338,4 @@ end
|
||||
|
||||
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
|
||||
|
||||
return inspect
|
||||
|
||||
return inspect
|
||||
@@ -52,4 +52,4 @@ math.degrees = function(angle)
|
||||
return angle * deg_to_rad
|
||||
end
|
||||
|
||||
return math
|
||||
return math
|
||||
@@ -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
|
||||
@@ -1,4 +1,5 @@
|
||||
local loaded = _G.package.loaded
|
||||
--luacheck:ignore global require
|
||||
local loaded = package.loaded
|
||||
local raw_require = require
|
||||
|
||||
function require(path)
|
||||
@@ -10,3 +10,5 @@ _STAGE = {
|
||||
--config_change = 7,
|
||||
runtime = 8
|
||||
}
|
||||
|
||||
_LIFECYCLE = _STAGE.control
|
||||
@@ -22,7 +22,7 @@ end
|
||||
-- The catch is that fast_remove doesn't guarantee to maintain the order of items in the array.
|
||||
-- @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
|
||||
@@ -262,4 +434,4 @@ table.merge = util.merge
|
||||
-- @return <boolean>
|
||||
table.equals = table.compare
|
||||
|
||||
return table
|
||||
return table
|
||||
@@ -1,2 +0,0 @@
|
||||
global.redmew_version = nil
|
||||
global.expgaming_version = '5.0.0'
|
||||
@@ -1,179 +0,0 @@
|
||||
--[[-- info
|
||||
Original (javascript) version: https://hastebin.com/udakacavap.js
|
||||
Can be tested against: https://wiki.factorio.com/Enemies#Spawn_chances_by_evolution_factor
|
||||
]]
|
||||
|
||||
-- dependencies
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local Debug = require 'utils.debug' --- @dep utils.debug
|
||||
local table = require 'utils.table' --- @dep utils.table
|
||||
|
||||
-- localized functions
|
||||
local get_random_weighted = table.get_random_weighted
|
||||
local round = math.round
|
||||
local ceil = math.ceil
|
||||
local floor = math.floor
|
||||
local random = math.random
|
||||
local pairs = pairs
|
||||
local format = string.format
|
||||
|
||||
-- this
|
||||
local AlienEvolutionProgress = {}
|
||||
|
||||
local memory = {
|
||||
spawner_specifications = {},
|
||||
spawner_specifications_count = 0,
|
||||
evolution_cache = {
|
||||
['biter-spawner'] = {
|
||||
evolution = -1,
|
||||
weight_table = {},
|
||||
},
|
||||
['spitters-spawner'] = {
|
||||
evolution = -1,
|
||||
weight_table = {},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Global.register_init({
|
||||
memory = memory,
|
||||
}, function(tbl)
|
||||
for name, prototype in pairs(game.entity_prototypes) do
|
||||
if prototype.type == 'unit-spawner' and prototype.subgroup.name == 'enemies' then
|
||||
tbl.memory.spawner_specifications[name] = prototype.result_units
|
||||
memory.spawner_specifications_count = memory.spawner_specifications_count + 1
|
||||
end
|
||||
end
|
||||
end, function(tbl)
|
||||
memory = tbl.memory
|
||||
end)
|
||||
|
||||
local function lerp(low, high, pos)
|
||||
local s = high.evolution_factor - low.evolution_factor;
|
||||
local l = (pos - low.evolution_factor) / s;
|
||||
return (low.weight * (1 - l)) + (high.weight * l)
|
||||
end
|
||||
|
||||
local function get_values(map, evolution_factor)
|
||||
local result = {}
|
||||
local sum = 0
|
||||
|
||||
for _, spawner_data in pairs(map) do
|
||||
local list = spawner_data.spawn_points;
|
||||
local low = list[1];
|
||||
local high = list[#list];
|
||||
|
||||
for _, val in pairs(list) do
|
||||
local val_evolution = val.evolution_factor
|
||||
if val_evolution <= evolution_factor and val_evolution > low.evolution_factor then
|
||||
low = val;
|
||||
end
|
||||
if val_evolution >= evolution_factor and val_evolution < high.evolution_factor then
|
||||
high = val
|
||||
end
|
||||
end
|
||||
|
||||
local val
|
||||
if evolution_factor <= low.evolution_factor then
|
||||
val = low.weight
|
||||
elseif evolution_factor >= high.evolution_factor then
|
||||
val = high.weight;
|
||||
else
|
||||
val = lerp(low, high, evolution_factor)
|
||||
end
|
||||
sum = sum + val;
|
||||
|
||||
result[spawner_data.unit] = val;
|
||||
end
|
||||
|
||||
local weighted_table = {}
|
||||
local count = 0
|
||||
for index, _ in pairs(result) do
|
||||
count = count + 1
|
||||
weighted_table[count] = {index, result[index] / sum}
|
||||
end
|
||||
|
||||
return weighted_table;
|
||||
end
|
||||
|
||||
local function get_spawner_values(spawner, evolution)
|
||||
local spawner_specification = memory.spawner_specifications[spawner]
|
||||
if not spawner_specification then
|
||||
Debug.print(format('Spawner "%s" does not exist in the prototype data', spawner))
|
||||
return
|
||||
end
|
||||
|
||||
local cache = memory.evolution_cache[spawner]
|
||||
|
||||
if not cache then
|
||||
cache = {
|
||||
evolution = -1,
|
||||
weight_table = {},
|
||||
}
|
||||
memory.evolution_cache[spawner] = cache
|
||||
end
|
||||
|
||||
local evolution_value = round(evolution * 100)
|
||||
if (cache.evolution < evolution_value) then
|
||||
cache.evolution = evolution_value
|
||||
cache.weight_table = get_values(spawner_specification, evolution)
|
||||
end
|
||||
|
||||
return cache.weight_table
|
||||
end
|
||||
|
||||
local function calculate_total(count, spawner, evolution)
|
||||
if count == 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local spawner_values = get_spawner_values(spawner, evolution)
|
||||
if not spawner_values then
|
||||
return {}
|
||||
end
|
||||
|
||||
local aliens = {}
|
||||
for _ = 1, count do
|
||||
local name = get_random_weighted(spawner_values)
|
||||
aliens[name] = (aliens[name] or 0) + 1
|
||||
end
|
||||
|
||||
return aliens
|
||||
end
|
||||
|
||||
---Creates the spawner_request structure required for AlienEvolutionProgress.get_aliens for all
|
||||
---available spawner's. If dividing the total spawner's by the total aliens causes a fraction, the
|
||||
---fraction will decide a chance to spawn. 1 alien for 2 spawner's will have 50% on both.
|
||||
---@param total_aliens table
|
||||
function AlienEvolutionProgress.create_spawner_request(total_aliens)
|
||||
local per_spawner = total_aliens / memory.spawner_specifications_count
|
||||
local fraction = per_spawner % 1
|
||||
|
||||
local spawner_request = {}
|
||||
for spawner, _ in pairs(memory.spawner_specifications) do
|
||||
local count = per_spawner
|
||||
if fraction > 0 then
|
||||
if random() > fraction then
|
||||
count = ceil(count)
|
||||
else
|
||||
count = floor(count)
|
||||
end
|
||||
end
|
||||
spawner_request[spawner] = count
|
||||
end
|
||||
|
||||
return spawner_request
|
||||
end
|
||||
|
||||
function AlienEvolutionProgress.get_aliens(spawner_requests, evolution)
|
||||
local aliens = {}
|
||||
for spawner, count in pairs(spawner_requests) do
|
||||
for name, amount in pairs(calculate_total(count, spawner, evolution)) do
|
||||
aliens[name] = (aliens[name] or 0) + amount
|
||||
end
|
||||
end
|
||||
|
||||
return aliens
|
||||
end
|
||||
|
||||
return AlienEvolutionProgress
|
||||
@@ -1,326 +0,0 @@
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Game = require 'utils.game' --- @dep utils.game
|
||||
local Utils = require 'utils.core' --- @dep utils.core
|
||||
local Timestamp = require 'utils.timestamp' --- @dep utils.timestamp
|
||||
local Rank = require 'features.rank_system' --- @dep features.rank_system
|
||||
local Donator = require 'features.donator' --- @dep features.donator
|
||||
local Server = require 'features.server' --- @dep features.server
|
||||
local Ranks = require 'resources.ranks' --- @dep resources.ranks
|
||||
|
||||
local insert = table.insert
|
||||
local format = string.format
|
||||
local next = next
|
||||
local serialize = serpent.line
|
||||
local match = string.match
|
||||
local gmatch = string.gmatch
|
||||
local get_rank_name = Rank.get_rank_name
|
||||
|
||||
local Command = {}
|
||||
|
||||
local deprecated_command_alternatives = {
|
||||
['silent-command'] = 'sc',
|
||||
['tpplayer'] = 'tp <player>',
|
||||
['tppos'] = 'tp',
|
||||
['tpmode'] = 'tp mode',
|
||||
['color-redmew'] = 'redmew-color'
|
||||
}
|
||||
|
||||
local notify_on_commands = {
|
||||
['version'] = 'RedMew has a version as well, accessible via /redmew-version',
|
||||
['color'] = 'RedMew allows color saving and a color randomiser: check out /redmew-color',
|
||||
['ban'] = 'In case your forgot: please remember to include a message on how to appeal a ban'
|
||||
}
|
||||
|
||||
local option_names = {
|
||||
['description'] = 'A description of the command',
|
||||
['arguments'] = 'A table of arguments, example: {"foo", "bar"} would map the first 2 arguments to foo and bar',
|
||||
['default_values'] = 'A default value for a given argument when omitted, example: {bar = false}',
|
||||
['required_rank'] = 'Set this to determines what rank is required to execute a command',
|
||||
['donator_only'] = 'Set this to true if only donators may execute this command',
|
||||
['debug_only'] = 'Set this to true if it should be registered when _DEBUG is true',
|
||||
['cheat_only'] = 'Set this to true if it should be registered when _CHEATS is true',
|
||||
['allowed_by_server'] = 'Set to true if the server (host) may execute this command',
|
||||
['allowed_by_player'] = 'Set to false to disable players from executing this command',
|
||||
['log_command'] = 'Set to true to log commands. Always true when admin is required',
|
||||
['capture_excess_arguments'] = 'Allows the last argument to be the remaining text in the command',
|
||||
['custom_help_text'] = 'Sets a custom help text to override the auto-generated help',
|
||||
}
|
||||
|
||||
---Validates if there aren't any wrong fields in the options.
|
||||
---@param command_name string
|
||||
---@param options table
|
||||
local function assert_existing_options(command_name, options)
|
||||
local invalid = {}
|
||||
for name, _ in pairs(options) do
|
||||
if not option_names[name] then
|
||||
insert(invalid, name)
|
||||
end
|
||||
end
|
||||
|
||||
if next(invalid) then
|
||||
error(format("The following options were given to the command '%s' but are invalid: %s", command_name, serialize(invalid)))
|
||||
end
|
||||
end
|
||||
|
||||
---Adds a command to be executed.
|
||||
---
|
||||
---Options table accepts the following structure: {
|
||||
--- description = 'A description of the command',
|
||||
--- arguments = {'foo', 'bar'}, -- maps arguments to these names in the given sequence
|
||||
--- default_values = {bar = false}, -- gives a default value to 'bar' when omitted
|
||||
--- required_rank = Ranks.regular, -- defaults to Ranks.guest
|
||||
--- donator_only = true, -- defaults to false
|
||||
--- debug_only = true, -- registers the command if _DEBUG is set to true, defaults to false
|
||||
--- cheat_only = true, -- registers the command if _CHEATS is set to true, defaults to false
|
||||
--- allowed_by_server = true, -- lets the server execute this, defaults to false
|
||||
--- allowed_by_player = false, -- lets players execute this, defaults to true
|
||||
--- log_command = true, -- defaults to false unless admin only, then always true
|
||||
--- capture_excess_arguments = true, -- defaults to false, captures excess arguments in the last argument, useful for sentences
|
||||
---}
|
||||
---
|
||||
---The callback receives the following arguments:
|
||||
--- - arguments (indexed by name, value is extracted from the parameters)
|
||||
--- - the LuaPlayer or nil if it doesn't exist (such as the server player)
|
||||
--- - the game tick in which the command was executed
|
||||
---
|
||||
---@param command_name string
|
||||
---@param options table
|
||||
---@param callback function
|
||||
function Command.add(command_name, options, callback)
|
||||
local description = options.description or '[Undocumented command]'
|
||||
local arguments = options.arguments or {}
|
||||
local default_values = options.default_values or {}
|
||||
local required_rank = options.required_rank or Ranks.guest
|
||||
local donator_only = options.donator_only or false
|
||||
local debug_only = options.debug_only or false
|
||||
local cheat_only = options.cheat_only or false
|
||||
local capture_excess_arguments = options.capture_excess_arguments or false
|
||||
local custom_help_text = options.custom_help_text or false
|
||||
local allowed_by_server = options.allowed_by_server or false
|
||||
local allowed_by_player = options.allowed_by_player
|
||||
local log_command = options.log_command or (required_rank >= Ranks.admin) or false
|
||||
local argument_list_size = table_size(arguments)
|
||||
local argument_list = ''
|
||||
|
||||
assert_existing_options(command_name, options)
|
||||
|
||||
if nil == options.allowed_by_player then
|
||||
allowed_by_player = true
|
||||
end
|
||||
|
||||
if (not _DEBUG and debug_only) and (not _CHEATS and cheat_only) then
|
||||
return
|
||||
end
|
||||
|
||||
if not allowed_by_player and not allowed_by_server then
|
||||
error(format("The command '%s' is not allowed by the server nor player, please enable at least one of them.", command_name))
|
||||
end
|
||||
|
||||
for index, argument_name in pairs(arguments) do
|
||||
local argument_display = argument_name
|
||||
for default_value_name, _ in pairs(default_values) do
|
||||
if default_value_name == argument_name then
|
||||
argument_display = argument_display .. ':optional'
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if argument_list_size == index and capture_excess_arguments then
|
||||
argument_display = argument_display .. ':sentence'
|
||||
end
|
||||
|
||||
argument_list = format('%s<%s> ', argument_list, argument_display)
|
||||
end
|
||||
|
||||
local extra = ''
|
||||
|
||||
if allowed_by_server and not allowed_by_player then
|
||||
extra = ' (Server only)'
|
||||
elseif allowed_by_player and (required_rank > Ranks.guest) then
|
||||
extra = {'command.required_rank', get_rank_name(required_rank)}
|
||||
elseif allowed_by_player and donator_only then
|
||||
extra = ' (Donator only)'
|
||||
end
|
||||
|
||||
local help_text = {'command.help_text_format',(custom_help_text or argument_list), description, extra}
|
||||
|
||||
commands.add_command(command_name, help_text, function (command)
|
||||
local print -- custom print reference in case no player is present
|
||||
local player = game.player
|
||||
local player_name = player and player.valid and player.name or '<server>'
|
||||
if not player or not player.valid then
|
||||
print = log
|
||||
|
||||
if not allowed_by_server then
|
||||
print(format("The command '%s' is not allowed to be executed by the server.", command_name))
|
||||
return
|
||||
end
|
||||
else
|
||||
print = player.print
|
||||
|
||||
if not allowed_by_player then
|
||||
print(format("The command '%s' is not allowed to be executed by players.", command_name))
|
||||
return
|
||||
end
|
||||
|
||||
if Rank.less_than(player_name, required_rank) then
|
||||
print({'command.higher_rank_needed', command_name, get_rank_name(required_rank)})
|
||||
return
|
||||
end
|
||||
|
||||
if donator_only and not Donator.is_donator(player_name) then
|
||||
print(format("The command '%s' is only allowed for donators.", command_name))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local named_arguments = {}
|
||||
local from_command = {}
|
||||
local raw_parameter_index = 1
|
||||
for param in gmatch(command.parameter or '', '%S+') do
|
||||
if capture_excess_arguments and raw_parameter_index == argument_list_size then
|
||||
if not from_command[raw_parameter_index] then
|
||||
from_command[raw_parameter_index] = param
|
||||
else
|
||||
from_command[raw_parameter_index] = from_command[raw_parameter_index] .. ' ' .. param
|
||||
end
|
||||
else
|
||||
from_command[raw_parameter_index] = param
|
||||
raw_parameter_index = raw_parameter_index + 1
|
||||
end
|
||||
end
|
||||
|
||||
local errors = {}
|
||||
|
||||
for index, argument in pairs(arguments) do
|
||||
local parameter = from_command[index]
|
||||
|
||||
if not parameter then
|
||||
for default_value_name, default_value in pairs(default_values) do
|
||||
if default_value_name == argument then
|
||||
parameter = default_value
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if parameter == nil then
|
||||
insert(errors, format('Argument "%s" from command %s is missing.', argument, command_name))
|
||||
else
|
||||
named_arguments[argument] = parameter
|
||||
end
|
||||
end
|
||||
|
||||
local return_early = false
|
||||
|
||||
for _, error in pairs(errors) do
|
||||
return_early = true
|
||||
print(error)
|
||||
end
|
||||
|
||||
if return_early then
|
||||
return
|
||||
end
|
||||
|
||||
if log_command then
|
||||
local tick = 'pre-game'
|
||||
if game then
|
||||
tick = Utils.format_time(game.tick)
|
||||
end
|
||||
local server_time = Server.get_current_time()
|
||||
if server_time then
|
||||
server_time = format('(Server time: %s)', Timestamp.to_string(server_time))
|
||||
else
|
||||
server_time = ''
|
||||
end
|
||||
|
||||
log(format('%s(Map time: %s) [%s Command] %s, used: %s %s', server_time, tick, (options.required_rank >= Ranks.admin) and 'Admin' or 'Player', player_name, command_name, serialize(named_arguments)))
|
||||
end
|
||||
|
||||
local success, error = pcall(function ()
|
||||
callback(named_arguments, player, command.tick)
|
||||
end)
|
||||
|
||||
if not success then
|
||||
local serialized_arguments = serialize(named_arguments)
|
||||
if _DEBUG then
|
||||
print(format("%s triggered an error running a command and has been logged: '%s' with arguments %s", player_name, command_name, serialized_arguments))
|
||||
print(error)
|
||||
return
|
||||
end
|
||||
|
||||
print(format('There was an error running %s, it has been logged.', command_name))
|
||||
log(format("Error while running '%s' with arguments %s: %s", command_name, serialized_arguments, error))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function Command.search(keyword)
|
||||
local matches = {}
|
||||
local count = 0
|
||||
keyword = keyword:lower()
|
||||
for name, description in pairs(commands.commands) do
|
||||
local command = format('%s %s', name, description)
|
||||
if match(command:lower(), keyword) then
|
||||
count = count + 1
|
||||
matches[count] = command
|
||||
end
|
||||
end
|
||||
|
||||
-- built-in commands use LocalisedString, which cannot be translated until player.print is called
|
||||
for name in pairs(commands.game_commands) do
|
||||
name = name
|
||||
if match(name:lower(), keyword) then
|
||||
count = count + 1
|
||||
matches[count] = name
|
||||
end
|
||||
end
|
||||
|
||||
return matches
|
||||
end
|
||||
|
||||
--- Trigger messages on deprecated or defined commands, ignores the server
|
||||
local function on_command(event)
|
||||
if not event.player_index then
|
||||
return
|
||||
end
|
||||
|
||||
local alternative = deprecated_command_alternatives[event.command]
|
||||
if alternative then
|
||||
local player = Game.get_player_by_index(event.player_index)
|
||||
if player then
|
||||
player.print(format('Warning! Usage of the command "/%s" is deprecated. Please use "/%s" instead.', event.command, alternative))
|
||||
end
|
||||
end
|
||||
|
||||
local notification = notify_on_commands[event.command]
|
||||
if notification and event.player_index then
|
||||
local player = Game.get_player_by_index(event.player_index)
|
||||
if player then
|
||||
player.print(notification)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Traps command errors if not in DEBUG.
|
||||
if not _DEBUG then
|
||||
local old_add_command = commands.add_command
|
||||
commands.add_command =
|
||||
function(name, desc, func)
|
||||
old_add_command(
|
||||
name,
|
||||
desc,
|
||||
function(cmd)
|
||||
local success, error = pcall(func, cmd)
|
||||
if not success then
|
||||
log(error)
|
||||
Game.player_print('Sorry there was an error running ' .. cmd.name)
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_console_command, on_command)
|
||||
|
||||
return Command
|
||||
223
utils/core.lua
223
utils/core.lua
@@ -1,223 +0,0 @@
|
||||
--- This file contains core utilities used by the redmew scenario.
|
||||
|
||||
-- Dependencies
|
||||
local Game = require 'utils.game' --- @dep utils.game
|
||||
local Color = require 'resources.color_presets' --- @dep resources.color_presets
|
||||
|
||||
-- localized functions
|
||||
local random = math.random
|
||||
local sqrt = math.sqrt
|
||||
local floor = math.floor
|
||||
local match = string.match
|
||||
local insert = table.insert
|
||||
local concat = table.concat
|
||||
|
||||
-- local constants
|
||||
local prefix = '## - '
|
||||
local minutes_to_ticks = 60 * 60
|
||||
local hours_to_ticks = 60 * 60 * 60
|
||||
local ticks_to_minutes = 1 / minutes_to_ticks
|
||||
local ticks_to_hours = 1 / hours_to_ticks
|
||||
|
||||
-- local variables
|
||||
local Module = {}
|
||||
|
||||
--- Measures distance between pos1 and pos2
|
||||
function Module.distance(pos1, pos2)
|
||||
local dx = pos2.x - pos1.x
|
||||
local dy = pos2.y - pos1.y
|
||||
return sqrt(dx * dx + dy * dy)
|
||||
end
|
||||
|
||||
--- Takes msg and prints it to all players except provided player
|
||||
-- @param msg <string|table> table if locale is used
|
||||
-- @param player <LuaPlayer> the player not to send the message to
|
||||
-- @param color <table> the color to use for the message, defaults to white
|
||||
function Module.print_except(msg, player, color)
|
||||
if not color then
|
||||
color = Color.white
|
||||
end
|
||||
|
||||
for _, p in pairs(game.connected_players) do
|
||||
if p ~= player then
|
||||
p.print(msg, color)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Prints a message to all online admins
|
||||
-- @param msg <string|table> table if locale is used
|
||||
-- @param source <LuaPlayer|string|nil> string must be the name of a player, nil for server.
|
||||
function Module.print_admins(msg, source)
|
||||
local source_name
|
||||
local chat_color
|
||||
if source then
|
||||
if type(source) == 'string' then
|
||||
source_name = source
|
||||
chat_color = game.players[source].chat_color
|
||||
else
|
||||
source_name = source.name
|
||||
chat_color = source.chat_color
|
||||
end
|
||||
else
|
||||
source_name = 'Server'
|
||||
chat_color = Color.yellow
|
||||
end
|
||||
local formatted_msg = {'utils_core.print_admins',prefix, source_name, msg}
|
||||
log(formatted_msg)
|
||||
for _, p in pairs(game.connected_players) do
|
||||
if p.admin then
|
||||
p.print(formatted_msg, chat_color)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns a valid string with the name of the actor of a command.
|
||||
function Module.get_actor()
|
||||
if game.player then
|
||||
return game.player.name
|
||||
end
|
||||
return '<server>'
|
||||
end
|
||||
|
||||
function Module.cast_bool(var)
|
||||
if var then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function Module.find_entities_by_last_user(player, surface, filters)
|
||||
if type(player) == 'string' or not player then
|
||||
error("bad argument #1 to '" .. debug.getinfo(1, 'n').name .. "' (number or LuaPlayer expected, got " .. type(player) .. ')', 1)
|
||||
return
|
||||
end
|
||||
if type(surface) ~= 'table' and type(surface) ~= 'number' then
|
||||
error("bad argument #2 to '" .. debug.getinfo(1, 'n').name .. "' (number or LuaSurface expected, got " .. type(surface) .. ')', 1)
|
||||
return
|
||||
end
|
||||
local entities = {}
|
||||
local filter = filters or {}
|
||||
if type(surface) == 'number' then
|
||||
surface = game.surfaces[surface]
|
||||
end
|
||||
if type(player) == 'number' then
|
||||
player = Game.get_player_by_index(player)
|
||||
end
|
||||
filter.force = player.force.name
|
||||
for _, e in pairs(surface.find_entities_filtered(filter)) do
|
||||
if e.last_user == player then
|
||||
insert(entities, e)
|
||||
end
|
||||
end
|
||||
return entities
|
||||
end
|
||||
|
||||
function Module.ternary(c, t, f)
|
||||
if c then
|
||||
return t
|
||||
else
|
||||
return f
|
||||
end
|
||||
end
|
||||
|
||||
--- Takes a time in ticks and returns a string with the time in format "x hour(s) x minute(s)"
|
||||
function Module.format_time(ticks)
|
||||
local result = {}
|
||||
|
||||
local hours = floor(ticks * ticks_to_hours)
|
||||
if hours > 0 then
|
||||
ticks = ticks - hours * hours_to_ticks
|
||||
insert(result, hours)
|
||||
if hours == 1 then
|
||||
insert(result, 'hour')
|
||||
else
|
||||
insert(result, 'hours')
|
||||
end
|
||||
end
|
||||
|
||||
local minutes = floor(ticks * ticks_to_minutes)
|
||||
insert(result, minutes)
|
||||
if minutes == 1 then
|
||||
insert(result, 'minute')
|
||||
else
|
||||
insert(result, 'minutes')
|
||||
end
|
||||
|
||||
return concat(result, ' ')
|
||||
end
|
||||
|
||||
--- Prints a message letting the player know they cannot run a command
|
||||
-- @param name string name of the command
|
||||
function Module.cant_run(name)
|
||||
Game.player_print("Can't run command (" .. name .. ') - insufficient permission.')
|
||||
end
|
||||
|
||||
--- Logs the use of a command and its user
|
||||
-- @param actor string with the actor's name (usually acquired by calling get_actor)
|
||||
-- @param command the command's name as table element
|
||||
-- @param parameters the command's parameters as a table (optional)
|
||||
function Module.log_command(actor, command, parameters)
|
||||
local action = concat {'[Admin-Command] ', actor, ' used: ', command}
|
||||
if parameters then
|
||||
action = concat {action, ' ', parameters}
|
||||
end
|
||||
log(action)
|
||||
end
|
||||
|
||||
function Module.comma_value(n) -- credit http://richard.warburton.it
|
||||
local left, num, right = match(n, '^([^%d]*%d)(%d*)(.-)$')
|
||||
return left .. (num:reverse():gsub('(%d%d%d)', '%1,'):reverse()) .. right
|
||||
end
|
||||
|
||||
--- Asserts the argument is one of type arg_types
|
||||
-- @param arg the variable to check
|
||||
-- @param arg_types the type as a table of sings
|
||||
-- @return boolean
|
||||
function Module.verify_mult_types(arg, arg_types)
|
||||
for _, arg_type in pairs(arg_types) do
|
||||
if type(arg) == arg_type then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Returns a random RGB color as a table
|
||||
function Module.random_RGB()
|
||||
return {r = random(0, 255), g = random(0, 255), b = random(0, 255)}
|
||||
end
|
||||
|
||||
--- Sets a table element to value while also returning value.
|
||||
-- @param tbl table to change the element of
|
||||
-- @param key string
|
||||
-- @param value nil|boolean|number|string|table to set the element to
|
||||
-- @return value
|
||||
function Module.set_and_return(tbl, key, value)
|
||||
tbl[key] = value
|
||||
return value
|
||||
end
|
||||
|
||||
-- add utility functions that exist in base factorio/util
|
||||
require 'util'
|
||||
|
||||
--- Moves a position according to the parameters given
|
||||
-- Notice: only accepts cardinal directions as direction
|
||||
-- @param position <table> table containing a map position
|
||||
-- @param direction <defines.direction> north, east, south, west
|
||||
-- @param distance <number>
|
||||
-- @return <table> modified position
|
||||
Module.move_position = util.moveposition
|
||||
|
||||
--- Takes a direction and gives you the opposite
|
||||
-- @param direction <defines.direction> north, east, south, west, northeast, northwest, southeast, southwest
|
||||
-- @return <number> representing the direction
|
||||
Module.opposite_direction = util.oppositedirection
|
||||
|
||||
--- Takes the string of a module and returns whether is it available or not
|
||||
-- @param name <string> the name of the module (ex. 'utils.core')
|
||||
-- @return <boolean>
|
||||
Module.is_module_available = util.ismoduleavailable
|
||||
|
||||
return Module
|
||||
@@ -1,32 +0,0 @@
|
||||
--- A small debugging tool that writes the contents of _ENV to a file when the game loads.
|
||||
-- Useful for ensuring you get the same information when loading
|
||||
-- the reference and desync levels in desync reports.
|
||||
-- dependencies
|
||||
local table = require 'utils.table' --- @dep utils.table
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
|
||||
-- localized functions
|
||||
local inspect = table.inspect
|
||||
|
||||
-- local constants
|
||||
local filename = 'env_dump.lua'
|
||||
|
||||
-- Removes metatables and the package table
|
||||
local filter = function(item, path)
|
||||
if path[#path] ~= inspect.METATABLE and item ~= 'package' then
|
||||
return item
|
||||
end
|
||||
end
|
||||
|
||||
local function player_joined(event)
|
||||
local dump_string = inspect(_ENV, {process = filter})
|
||||
if dump_string then
|
||||
local s = string.format('tick on join: %s\n%s', event.tick, dump_string)
|
||||
game.write_file(filename, s)
|
||||
game.print('_ENV dumped into ' .. filename)
|
||||
else
|
||||
game.print('_ENV not dumped, dump_string was nil')
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_player_joined_game, player_joined)
|
||||
@@ -97,7 +97,7 @@
|
||||
local EventCore = require 'utils.event_core' --- @dep utils.event_core
|
||||
local 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
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local Game = require 'utils.game' --- @dep utils.game
|
||||
local PlayerStats = require 'features.player_stats' --- @dep features.player_stats
|
||||
local Command = require 'utils.command' --- @dep utils.command
|
||||
local Ranks = require 'resources.ranks' --- @dep resources.ranks
|
||||
|
||||
local format = string.format
|
||||
local abs = math.abs
|
||||
local concat = table.concat
|
||||
|
||||
local Public = {}
|
||||
local reward_token = {global.config.player_rewards.token} or {global.config.market.currency} or {'coin'}
|
||||
|
||||
Global.register(
|
||||
{
|
||||
reward_token = reward_token
|
||||
},
|
||||
function(tbl)
|
||||
reward_token = tbl.reward_token
|
||||
end
|
||||
)
|
||||
|
||||
--- Returns the single or plural form of the token name
|
||||
local function get_token_plural(quantity)
|
||||
if quantity and quantity > 1 then
|
||||
return concat({reward_token[1], 's'})
|
||||
else
|
||||
return reward_token[1]
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the item to use for rewards
|
||||
-- @param reward string - item name to use as reward
|
||||
-- @return boolean true - indicating success
|
||||
Public.set_reward = function(reward)
|
||||
if global.config.player_rewards.enabled == false then
|
||||
return false
|
||||
end
|
||||
|
||||
reward_token[1] = reward
|
||||
return true
|
||||
end
|
||||
|
||||
--- Returns the name of the reward item
|
||||
Public.get_reward = function()
|
||||
return reward_token[1]
|
||||
end
|
||||
|
||||
--- Gives reward tokens to the player
|
||||
-- @param player <number|LuaPlayer>
|
||||
-- @param amount <number> of reward tokens
|
||||
-- @param message <string> an optional message to send to the affected player
|
||||
-- @return <number> indicating how many were inserted or if operation failed
|
||||
Public.give_reward = function(player, amount, message)
|
||||
if global.config.player_rewards.enabled == false then
|
||||
return 0
|
||||
end
|
||||
|
||||
local player_index
|
||||
if type(player) == 'number' then
|
||||
player_index = player
|
||||
player = Game.get_player_by_index(player)
|
||||
else
|
||||
player_index = player.index
|
||||
end
|
||||
local reward = {name = reward_token[1], count = amount}
|
||||
if not player.can_insert(reward) then
|
||||
return 0
|
||||
end
|
||||
if message then
|
||||
player.print(message)
|
||||
end
|
||||
local coin_difference = player.insert(reward)
|
||||
if reward_token[1] == 'coin' then
|
||||
PlayerStats.change_coin_earned(player_index, coin_difference)
|
||||
end
|
||||
return coin_difference
|
||||
end
|
||||
|
||||
--- Removes reward tokens from the player
|
||||
-- @param player <number|LuaPlayer>
|
||||
-- @param amount <number> of reward tokens
|
||||
-- @param message <string> an optional message to send to the affected player
|
||||
-- @return <number> indicating how many were removed or if operation failed
|
||||
Public.remove_reward = function(player, amount, message)
|
||||
if global.config.player_rewards.enabled == false then
|
||||
return 0
|
||||
end
|
||||
|
||||
local player_index
|
||||
if type(player) == 'number' then
|
||||
player_index = player
|
||||
player = Game.get_player_by_index(player)
|
||||
else
|
||||
player_index = player.index
|
||||
end
|
||||
local unreward = {name = reward_token[1], count = amount}
|
||||
if message then
|
||||
player.print(message)
|
||||
end
|
||||
local coin_difference = player.remove_item(unreward)
|
||||
if reward_token[1] == 'coin' then
|
||||
PlayerStats.change_coin_earned(player_index, -coin_difference)
|
||||
end
|
||||
return coin_difference
|
||||
end
|
||||
|
||||
Command.add(
|
||||
'reward',
|
||||
{
|
||||
description = 'Gives a reward to a target player (removes if quantity is negative)',
|
||||
arguments = {'target', 'quantity', 'reason'},
|
||||
default_values = {reason = false},
|
||||
required_rank = Ranks.admin,
|
||||
capture_excess_arguments = true,
|
||||
allowed_by_server = true,
|
||||
allowed_by_player = true
|
||||
},
|
||||
function(args, player)
|
||||
local player_name = 'server'
|
||||
if player then
|
||||
player_name = player.name
|
||||
end
|
||||
|
||||
local target_name = args.target
|
||||
local target = game.players[target_name]
|
||||
if not target then
|
||||
player.print('Target not found.')
|
||||
return
|
||||
end
|
||||
|
||||
local quantity = tonumber(args.quantity)
|
||||
if quantity > 0 then
|
||||
Public.give_reward(target, quantity)
|
||||
local string = format('%s has rewarded %s with %s %s', player_name, target_name, quantity, get_token_plural(quantity))
|
||||
if args.reason then
|
||||
string = format('%s for %s', string, args.reason)
|
||||
end
|
||||
game.print(string)
|
||||
elseif quantity < 0 then
|
||||
quantity = abs(quantity)
|
||||
Public.remove_reward(target, quantity)
|
||||
local string = format('%s has punished %s by taking %s %s', player_name, target_name, quantity, get_token_plural(quantity))
|
||||
if args.reason then
|
||||
string = format('%s for %s', string, args.reason)
|
||||
end
|
||||
game.print(string)
|
||||
else
|
||||
Game.player_print(" A reward of 0 is neither a reward nor a punishment, it's just dumb. Try harder.")
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
return Public
|
||||
@@ -1,58 +0,0 @@
|
||||
--- A module to prevent recipes from being unlocked by research. Accessed via the public functions.
|
||||
local Event = require 'utils.event' --- @dep utils.event
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
|
||||
local Public = {}
|
||||
|
||||
local recipes = {}
|
||||
|
||||
Global.register(
|
||||
{
|
||||
recipes = recipes
|
||||
},
|
||||
function(tbl)
|
||||
recipes = tbl.recipes
|
||||
end
|
||||
)
|
||||
|
||||
Event.add(
|
||||
defines.events.on_research_finished,
|
||||
function(event)
|
||||
local p_force = game.forces.player
|
||||
local r = event.research
|
||||
for _, effect in pairs(r.effects) do
|
||||
local recipe = effect.recipe
|
||||
if recipe and recipes[recipe] then
|
||||
p_force.recipes[recipe].enabled = false
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
Event.on_init(
|
||||
function()
|
||||
for recipe in pairs(recipes) do
|
||||
game.forces.player.recipes[recipe].enabled = false
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
--- Locks recipes, preventing them from being enabled by research.
|
||||
-- Does not check if they should be enabled/disabled by existing research.
|
||||
-- @param tbl <table> an array of recipe strings
|
||||
function Public.lock_recipes(tbl)
|
||||
for i = 1, #tbl do
|
||||
recipes[tbl[i]] = true
|
||||
end
|
||||
end
|
||||
|
||||
--- Unlocks recipes, allowing them to be enabled by research.
|
||||
-- Does not check if they should be enabled/disabled by existing research.
|
||||
-- @param tbl <table> an array of recipe strings
|
||||
function Public.unlock_recipes(tbl)
|
||||
for i = 1, #tbl do
|
||||
recipes[tbl[i]] = nil
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
||||
@@ -1,178 +0,0 @@
|
||||
local Global = require 'utils.global' --- @dep utils.global
|
||||
local type = type
|
||||
local error = error
|
||||
local tonumber = tonumber
|
||||
local tostring = tostring
|
||||
local pairs = pairs
|
||||
local format = string.format
|
||||
|
||||
--- Contains a set of callable that will attempt to sanitize and transform the input
|
||||
local settings_type = {
|
||||
fraction = function (input)
|
||||
input = tonumber(input)
|
||||
|
||||
if input == nil then
|
||||
return false, 'fraction setting type requires the input to be a valid number between 0 and 1.'
|
||||
end
|
||||
|
||||
if input < 0 then
|
||||
input = 0
|
||||
end
|
||||
|
||||
if input > 1 then
|
||||
input = 1
|
||||
end
|
||||
|
||||
return true, input
|
||||
end,
|
||||
string = function (input)
|
||||
if input == nil then
|
||||
return true, ''
|
||||
end
|
||||
|
||||
local input_type = type(input)
|
||||
if input_type == 'string' then
|
||||
return true, input
|
||||
end
|
||||
|
||||
if input_type == 'number' or input_type == 'boolean' then
|
||||
return true, tostring(input)
|
||||
end
|
||||
|
||||
return false, 'string setting type requires the input to be either a valid string or something that can be converted to a string.'
|
||||
end,
|
||||
boolean = function (input)
|
||||
local input_type = type(input)
|
||||
|
||||
if input_type == 'boolean' then
|
||||
return true, input
|
||||
end
|
||||
|
||||
if input_type == 'string' then
|
||||
if input == '0' or input == '' or input == 'false' or input == 'no' then
|
||||
return true, false
|
||||
end
|
||||
if input == '1' or input == 'true' or input == 'yes' then
|
||||
return true, true
|
||||
end
|
||||
|
||||
return true, tonumber(input) ~= nil
|
||||
end
|
||||
|
||||
if input_type == 'number' then
|
||||
return true, input ~= 0
|
||||
end
|
||||
|
||||
return false, 'boolean setting type requires the input to be either a boolean, number or string that can be transformed to a boolean.'
|
||||
end,
|
||||
}
|
||||
|
||||
local settings = {}
|
||||
local memory = {}
|
||||
|
||||
Global.register(memory, function (tbl) memory = tbl end)
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.types = {fraction = 'fraction', string = 'string', boolean = 'boolean'}
|
||||
|
||||
---Register a specific setting with a sensitization setting type.
|
||||
---
|
||||
--- Available setting types:
|
||||
--- - fraction (number between 0 and 1) in either number or string form
|
||||
--- - string a string or anything that can be cast to a string
|
||||
--- - boolean, 1, 0, yes, no, true, false or an empty string for false
|
||||
---
|
||||
--- This function must be called in the control stage, i.e. not inside an event.
|
||||
---
|
||||
---@param name string
|
||||
---@param setting_type string
|
||||
---@param default mixed
|
||||
function Public.register(name, setting_type, default)
|
||||
if _LIFECYCLE ~= _STAGE.control then
|
||||
error(format('You can only register setting names in the control stage, i.e. not inside events. Tried setting "%s" with type "%s".', name, setting_type), 2)
|
||||
end
|
||||
|
||||
if settings[name] then
|
||||
error(format('Trying to register setting for "%s" while it has already been registered.', name), 2)
|
||||
end
|
||||
|
||||
local callback = settings_type[setting_type]
|
||||
if not callback then
|
||||
error(format('Trying to register setting for "%s" with type "%s" while this type does not exist.', name, setting_type), 2)
|
||||
end
|
||||
|
||||
local setting = {
|
||||
default = default,
|
||||
callback = callback,
|
||||
}
|
||||
|
||||
settings[name] = setting
|
||||
|
||||
return setting
|
||||
end
|
||||
|
||||
---Sets a setting to a specific value for a player.
|
||||
---
|
||||
---In order to get a setting value, it has to be registered via the "register" function.
|
||||
---
|
||||
---@param player_index number
|
||||
---@param name string
|
||||
---@param value mixed
|
||||
function Public.set(player_index, name, value)
|
||||
local setting = settings[name]
|
||||
if not setting then
|
||||
return error(format('Setting "%s" does not exist.', name), 2)
|
||||
end
|
||||
|
||||
local success, sanitized_value = setting.callback(value)
|
||||
|
||||
if not success then
|
||||
error(format('Setting "%s" failed: %s', name, sanitized_value), 2)
|
||||
end
|
||||
|
||||
local player_settings = memory[player_index]
|
||||
if not player_settings then
|
||||
player_settings = {}
|
||||
memory[player_index] = player_settings
|
||||
end
|
||||
|
||||
player_settings[name] = sanitized_value
|
||||
|
||||
return sanitized_value
|
||||
end
|
||||
|
||||
---Returns the value of a setting for this player.
|
||||
---
|
||||
---In order to set a setting value, it has to be registered via the "register" function.
|
||||
---
|
||||
---@param player_index number
|
||||
---@param name string
|
||||
function Public.get(player_index, name)
|
||||
local setting = settings[name]
|
||||
if not setting then
|
||||
return error(format('Setting "%s" does not exist.', name), 2)
|
||||
end
|
||||
|
||||
local player_settings = memory[player_index]
|
||||
if not player_settings then
|
||||
return setting.default
|
||||
end
|
||||
|
||||
local player_setting = player_settings[name]
|
||||
return player_setting ~= nil and player_setting or setting.default
|
||||
end
|
||||
|
||||
---Returns a table of all settings for a given player in a key => value set-up
|
||||
---@param player_index number
|
||||
function Public.all(player_index)
|
||||
local player_settings = memory[player_index] or {}
|
||||
local output = {}
|
||||
for name, data in pairs(settings) do
|
||||
output[name] = player_settings[name] or data.default
|
||||
end
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
return Public
|
||||
@@ -1,119 +0,0 @@
|
||||
--- This module provides a classical mealy/moore state machine.
|
||||
-- Each machine in constructed by calling new()
|
||||
-- States and Transitions are lazily added to the machine as transition handlers and state tick handlers are registered.
|
||||
-- However the state machine must be fully defined after init is done. Dynamic machine changes are currently unsupported
|
||||
-- An example usage can be found here: map_gen\combined\tetris\control.lua
|
||||
|
||||
local Module = {}
|
||||
|
||||
local Debug = require 'utils.debug' --- @dep utils.debug
|
||||
|
||||
local in_state_callbacks = {}
|
||||
local transaction_callbacks = {}
|
||||
local max_stack_depth = 20
|
||||
local machine_count = 0
|
||||
local control_stage = _STAGE.control
|
||||
|
||||
--- Transitions the supplied machine into a given state and executes all transaction_callbacks
|
||||
-- @param self StateMachine
|
||||
-- @param new_state number/string The new state to transition to
|
||||
function Module.transition(self, new_state)
|
||||
Debug.print(string.format('Transitioning from state %d to state %d.', self.state, new_state))
|
||||
local old_state = self.state
|
||||
|
||||
local stack_depth = self.stack_depth
|
||||
self.stack_depth = stack_depth + 1
|
||||
if stack_depth > max_stack_depth then
|
||||
if _DEBUG then
|
||||
error('[WARNING] Stack overflow at:' .. debug.traceback())
|
||||
else
|
||||
log('[WARNING] Stack overflow at:' .. debug.traceback())
|
||||
end
|
||||
end
|
||||
|
||||
local exit_callbacks = transaction_callbacks[self.id][old_state]
|
||||
if exit_callbacks then
|
||||
local entry_callbacks = exit_callbacks[new_state]
|
||||
if entry_callbacks then
|
||||
for i = 1, #entry_callbacks do
|
||||
local callback = entry_callbacks[i]
|
||||
if callback then
|
||||
callback()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
self.state = new_state
|
||||
end
|
||||
|
||||
--- Is this machine in this state?
|
||||
-- @param self StateMachine
|
||||
-- @param state number/string
|
||||
-- @return boolean
|
||||
function Module.in_state(self, state)
|
||||
return self.state == state
|
||||
end
|
||||
|
||||
--- Invoke a machine tick. Will execute all in_state_callbacks of the given machine
|
||||
-- @param self StateMachine the machine, whose handlers will be invoked
|
||||
function Module.machine_tick(self)
|
||||
local callbacks = in_state_callbacks[self.id][self.state]
|
||||
if callbacks then
|
||||
for i=1, #callbacks do
|
||||
local callback = callbacks[i]
|
||||
if callback then
|
||||
callback()
|
||||
end
|
||||
end
|
||||
end
|
||||
self.stack_depth = 0
|
||||
end
|
||||
|
||||
--- Register a handler that will be invoked by StateMachine.machine_tick
|
||||
-- You may register multiple handlers for the same transition
|
||||
-- NOTICE: This function will invoke an error if called after init. Dynamic machine changes are currently unsupported
|
||||
-- @param self StateMachine the machine
|
||||
-- @param state number/string The state, that the machine will be in, when callback is invoked
|
||||
-- @param callback function
|
||||
function Module.register_state_tick_callback(self, state, callback)
|
||||
if _LIFECYCLE ~= control_stage then
|
||||
error('Calling StateMachine.register_state_tick_callback after the control stage is unsupported due to desyncs.', 2)
|
||||
end
|
||||
in_state_callbacks[self.id][state] = in_state_callbacks[self.id][state] or {}
|
||||
table.insert(in_state_callbacks[self.id][state], callback)
|
||||
end
|
||||
|
||||
--- Register a handler that will be invoked by StateMachine.transition
|
||||
-- You may register multiple handlers for the same transition
|
||||
-- NOTICE: This function will invoke an error if called after init. Dynamic machine changes are currently unsupported
|
||||
-- @param self StateMachine the machine
|
||||
-- @param old number/string exiting state
|
||||
-- @param new number/string entering state
|
||||
-- @param callback function
|
||||
function Module.register_transition_callback(self, old, new, callback)
|
||||
if _LIFECYCLE ~= control_stage then
|
||||
error('Calling StateMachine.register_transition_callback after the control stage is unsupported due to desyncs.', 2)
|
||||
end
|
||||
transaction_callbacks[self.id][old] = transaction_callbacks[self.id][old] or {}
|
||||
transaction_callbacks[self.id][old][new] = transaction_callbacks[self.id][old][new] or {}
|
||||
table.insert(transaction_callbacks[self.id][old][new], callback)
|
||||
end
|
||||
|
||||
--- Constructs a new state machine
|
||||
-- @param init_state number/string The starting state of the machine
|
||||
-- @return StateMachine The constructed state machine object
|
||||
function Module.new(init_state)
|
||||
if _LIFECYCLE ~= control_stage then
|
||||
error('Calling StateMachine.new after the control stage is unsupported due to desyncs.', 2)
|
||||
end
|
||||
machine_count = machine_count + 1
|
||||
in_state_callbacks[machine_count] = {}
|
||||
transaction_callbacks[machine_count] = {}
|
||||
return {
|
||||
state = init_state,
|
||||
stack_depth = 0,
|
||||
id = machine_count,
|
||||
}
|
||||
end
|
||||
|
||||
return Module
|
||||
@@ -1,152 +0,0 @@
|
||||
--- source https://github.com/daurnimator/luatz/blob/master/luatz/timetable.lua
|
||||
-- edited down to just what is needed.
|
||||
|
||||
local Public = {}
|
||||
|
||||
local floor = math.floor
|
||||
local strformat = string.format
|
||||
|
||||
local function borrow(tens, units, base)
|
||||
local frac = tens % 1
|
||||
units = units + frac * base
|
||||
tens = tens - frac
|
||||
return tens, units
|
||||
end
|
||||
|
||||
local function carry(tens, units, base)
|
||||
if units >= base then
|
||||
tens = tens + floor(units / base)
|
||||
units = units % base
|
||||
elseif units < 0 then
|
||||
tens = tens + floor(units / base)
|
||||
units = (base + units) % base
|
||||
end
|
||||
return tens, units
|
||||
end
|
||||
|
||||
local function is_leap(y)
|
||||
if (y % 4) ~= 0 then
|
||||
return false
|
||||
elseif (y % 100) ~= 0 then
|
||||
return true
|
||||
else
|
||||
return (y % 400) == 0
|
||||
end
|
||||
end
|
||||
|
||||
local mon_lengths = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
||||
|
||||
-- Number of days in year until start of month; not corrected for leap years
|
||||
local months_to_days_cumulative = {0}
|
||||
for i = 2, 12 do
|
||||
months_to_days_cumulative[i] = months_to_days_cumulative[i - 1] + mon_lengths[i - 1]
|
||||
end
|
||||
|
||||
local function month_length(m, y)
|
||||
if m == 2 then
|
||||
return is_leap(y) and 29 or 28
|
||||
else
|
||||
return mon_lengths[m]
|
||||
end
|
||||
end
|
||||
|
||||
local function day_of_year(day, month, year)
|
||||
local y_day = months_to_days_cumulative[month]
|
||||
if month > 2 and is_leap(year) then
|
||||
y_day = y_day + 1
|
||||
end
|
||||
return y_day + day
|
||||
end
|
||||
|
||||
local function leap_years_since(year)
|
||||
return floor(year / 4) - floor(year / 100) + floor(year / 400)
|
||||
end
|
||||
|
||||
local leap_years_since_1970 = leap_years_since(1970)
|
||||
|
||||
local function normalise(year, month, day, hour, min, sec)
|
||||
-- `month` and `day` start from 1, need -1 and +1 so it works modulo
|
||||
month, day = month - 1, day - 1
|
||||
|
||||
-- Convert everything (except seconds) to an integer
|
||||
-- by propagating fractional components down.
|
||||
year, month = borrow(year, month, 12)
|
||||
-- Carry from month to year first, so we get month length correct in next line around leap years
|
||||
year, month = carry(year, month, 12)
|
||||
month, day = borrow(month, day, month_length(floor(month + 1), year))
|
||||
day, hour = borrow(day, hour, 24)
|
||||
hour, min = borrow(hour, min, 60)
|
||||
min, sec = borrow(min, sec, 60)
|
||||
|
||||
-- Propagate out of range values up
|
||||
-- e.g. if `min` is 70, `hour` increments by 1 and `min` becomes 10
|
||||
-- This has to happen for all columns after borrowing, as lower radix's may be pushed out of range
|
||||
min, sec = carry(min, sec, 60) -- TODO: consider leap seconds?
|
||||
hour, min = carry(hour, min, 60)
|
||||
day, hour = carry(day, hour, 24)
|
||||
-- Ensure `day` is not underflowed
|
||||
-- Add a whole year of days at a time, this is later resolved by adding months
|
||||
-- TODO[OPTIMIZE]: This could be slow if `day` is far out of range
|
||||
while day < 0 do
|
||||
month = month - 1
|
||||
if month < 0 then
|
||||
year = year - 1
|
||||
month = 11
|
||||
end
|
||||
day = day + month_length(month + 1, year)
|
||||
end
|
||||
year, month = carry(year, month, 12)
|
||||
|
||||
-- TODO[OPTIMIZE]: This could potentially be slow if `day` is very large
|
||||
while true do
|
||||
local i = month_length(month + 1, year)
|
||||
if day < i then
|
||||
break
|
||||
end
|
||||
day = day - i
|
||||
month = month + 1
|
||||
if month >= 12 then
|
||||
month = 0
|
||||
year = year + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Now we can place `day` and `month` back in their normal ranges
|
||||
-- e.g. month as 1-12 instead of 0-11
|
||||
month, day = month + 1, day + 1
|
||||
|
||||
return {year = year, month = month, day = day, hour = hour, min = min, sec = sec}
|
||||
end
|
||||
|
||||
--- Converts unix epoch timestamp into table {year: number, month: number, day: number, hour: number, min: number, sec: number}
|
||||
-- @param seconds<number> unix epoch timestamp
|
||||
-- @return {year: number, month: number, day: number, hour: number, min: number, sec: number}
|
||||
function Public.to_timetable(seconds)
|
||||
return normalise(1970, 1, 1, 0, 0, seconds)
|
||||
end
|
||||
|
||||
--- Converts timetable into unix epoch timestamp
|
||||
-- @param timetable<table> {year: number, month: number, day: number, hour: number, min: number, sec: number}
|
||||
-- @return number
|
||||
function Public.from_timetable(timetable)
|
||||
local tt = normalise(timetable.year, timetable.month, timetable.day, timetable.hour, timetable.min, timetable.sec)
|
||||
|
||||
local year, month, day, hour, min, sec = tt.year, tt.month, tt.day, tt.hour, tt.min, tt.sec
|
||||
|
||||
local days_since_epoch =
|
||||
day_of_year(day, month, year) + 365 * (year - 1970) + -- Each leap year adds one day
|
||||
(leap_years_since(year - 1) - leap_years_since_1970) -
|
||||
1
|
||||
|
||||
return days_since_epoch * (60 * 60 * 24) + hour * (60 * 60) + min * 60 + sec
|
||||
end
|
||||
|
||||
--- Converts unix epoch timestamp into human readable string.
|
||||
-- @param seconds<type> unix epoch timestamp
|
||||
-- @return string
|
||||
function Public.to_string(seconds)
|
||||
local tt = normalise(1970, 1, 1, 0, 0, seconds)
|
||||
return strformat('%04u-%02u-%02u %02u:%02u:%02d', tt.year, tt.month, tt.day, tt.hour, tt.min, tt.sec)
|
||||
end
|
||||
|
||||
return Public
|
||||
Reference in New Issue
Block a user