Merge Game, FlyingText, Common and table

This commit is contained in:
Cooldude2606
2024-09-30 22:32:35 +01:00
parent 3145f7e904
commit f8c74c9dd3
66 changed files with 817 additions and 2035 deletions

View File

@@ -1,9 +1,8 @@
{ {
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json", "$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
"completion.requireSeparator": "/", "completion.requireSeparator": "/",
"doc.privateName": [ "__" ], "doc.privateName": [ "__(\\w+)" ],
"doc.protectedName": [ "_" ], "doc.protectedName": [ "_(\\w+)" ],
"runtime.version": "Lua 5.2",
"runtime.pluginArgs": [ "runtime.pluginArgs": [
"--clusterio-modules" "--clusterio-modules"
], ],
@@ -40,7 +39,15 @@
"type" : "pattern", "type" : "pattern",
"param": "_?_?(\\w+)", "param": "_?_?(\\w+)",
"$1": "snake_case" "$1": "snake_case"
}, "pascal_case"], }, {
"type" : "pattern",
"param": "_?_?(\\w+)",
"$1": "upper_snake_case"
}, {
"type" : "pattern",
"param": "_?_?(\\w+)",
"$1": "pascal_case"
}],
"function_param_name_style": [{ "function_param_name_style": [{
"type" : "pattern", "type" : "pattern",
"param": "_?_?(\\w+)?", "param": "_?_?(\\w+)?",
@@ -62,9 +69,14 @@
"$1": "snake_case" "$1": "snake_case"
}], }],
"global_variable_name_style": [{ "global_variable_name_style": [{
"type": "ignore", "type" : "pattern",
"param": ["_VERSION"] "param": "_?_?(\\w+)",
}, "snake_case", "upper_snake_case" ], "$1": "snake_case"
}, {
"type" : "pattern",
"param": "_?_?(\\w+)",
"$1": "upper_snake_case"
}],
"module_name_style": [ "pascal_case", "snake_case" ], "module_name_style": [ "pascal_case", "snake_case" ],
"require_module_name_style": [ "pascal_case", "snake_case" ], "require_module_name_style": [ "pascal_case", "snake_case" ],
"class_name_style": "pascal_case", "class_name_style": "pascal_case",

View File

@@ -22,12 +22,14 @@ setmetatable(rcon_statics, { __index = _G })
setmetatable(rcon_env, { __index = rcon_statics }) setmetatable(rcon_env, { __index = rcon_statics })
--- Some common static values which can be added now --- Some common static values which can be added now
--- @diagnostic disable: name-style-check
rcon_statics.Async = Async rcon_statics.Async = Async
rcon_statics.ExpUtil = ExpUtil rcon_statics.ExpUtil = ExpUtil
rcon_statics.Commands = Commands rcon_statics.Commands = Commands
rcon_statics.Clustorio = Clustorio rcon_statics.Clustorio = Clustorio
rcon_statics.output = Commands.print rcon_statics.output = Commands.print
rcon_statics.ipc = Clustorio.send_json rcon_statics.ipc = Clustorio.send_json
--- @diagnostic enable: name-style-check
--- Some common callback values which are useful when a player uses the command --- Some common callback values which are useful when a player uses the command
function rcon_callbacks.player(player) return player end function rcon_callbacks.player(player) return player end

View File

@@ -364,9 +364,11 @@ function Commands.print(message, color, sound)
if not player then if not player then
rcon.print(ExpUtil.format_any(message)) rcon.print(ExpUtil.format_any(message))
else else
local formatted = ExpUtil.format_any(message, nil, 20) local formatted = ExpUtil.format_any(message, { max_line_count = 20 })
player.print(formatted, color or Color.white) player.print(formatted, {
player.play_sound{ path = sound or "utility/scenario_message" } color = color or Color.white,
sound_path = sound or "utility/scenario_message",
})
end end
end end

View File

View File

@@ -47,7 +47,7 @@ return {
end end
end end
return { "chat-bot.afk", max.name, ExpUtil.format_locale_time(max.afk_time, "long", afk_time_units) } return { "chat-bot.afk", max.name, ExpUtil.format_time_locale(max.afk_time, "long", afk_time_units) }
end, end,
["players"] = function(_player, _is_command) ["players"] = function(_player, _is_command)
return { "chat-bot.players", #game.players } return { "chat-bot.players", #game.players }
@@ -70,7 +70,7 @@ return {
names[#names + 1] = next_player.name names[#names + 1] = next_player.name
end end
return { "chat-bot.blame", table.get_random_dictionary_entry(names) } return { "chat-bot.blame", table.get_random(names) }
end, end,
["magic"] = { "chat-bot.magic" }, ["magic"] = { "chat-bot.magic" },
["aids"] = { "chat-bot.aids" }, ["aids"] = { "chat-bot.aids" },
@@ -78,7 +78,7 @@ return {
["lenny"] = { "chat-bot.lenny" }, ["lenny"] = { "chat-bot.lenny" },
["hodor"] = function(_player, _is_command) ["hodor"] = function(_player, _is_command)
local options = { "?", ".", "!", "!!!" } local options = { "?", ".", "!", "!!!" }
return { "chat-bot.hodor", table.get_random_dictionary_entry(options) } return { "chat-bot.hodor", table.get_random(options) }
end, end,
["evolution"] = function(_player, _is_command) ["evolution"] = function(_player, _is_command)
return { "chat-bot.current-evolution", string.format("%.2f", game.forces["enemy"].evolution_factor) } return { "chat-bot.current-evolution", string.format("%.2f", game.forces["enemy"].evolution_factor) }

View File

@@ -19,6 +19,7 @@ see ./expcore/commands.lua for more details
surface surface
]] ]]
local ExpUtil = require("modules/exp_util")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
-- luacheck:ignore 212/player -- luacheck:ignore 212/player
@@ -37,7 +38,7 @@ end)
Commands.add_parse("string-options", function(input, player, reject, options) Commands.add_parse("string-options", function(input, player, reject, options)
if not input then return end -- nil check if not input then return end -- nil check
local option = _C.auto_complete(options, input) local option = ExpUtil.auto_complete(options, input)
return option or reject{ "expcore-commands.reject-string-options", table.concat(options, ", ") } return option or reject{ "expcore-commands.reject-string-options", table.concat(options, ", ") }
end) end)

View File

@@ -7,9 +7,10 @@
player-role-alive player-role-alive
]] ]]
local ExpUtil = require("modules/exp_util")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local auto_complete = _C.auto_complete --- @dep expcore.common local auto_complete = ExpUtil.auto_complete --- @dep expcore.common
require("modules.exp_legacy.config.expcore.command_general_parse") require("modules.exp_legacy.config.expcore.command_general_parse")
-- luacheck:ignore 212/player -- luacheck:ignore 212/player

View File

@@ -5,13 +5,14 @@
-- the key used for the name of the button is the permission name used by the role system; -- the key used for the name of the button is the permission name used by the role system;
-- @config Player-List -- @config Player-List
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local Reports = require("modules.exp_legacy.modules.control.reports") --- @dep modules.control.reports local Reports = require("modules.exp_legacy.modules.control.reports") --- @dep modules.control.reports
local Warnings = require("modules.exp_legacy.modules.control.warnings") --- @dep modules.control.warnings local Warnings = require("modules.exp_legacy.modules.control.warnings") --- @dep modules.control.warnings
local Jail = require("modules.exp_legacy.modules.control.jail") --- @dep modules.control.jail local Jail = require("modules.exp_legacy.modules.control.jail") --- @dep modules.control.jail
local Colors = require("modules/exp_util/include/color") local Colors = require("modules/exp_util/include/color")
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local format_player_name = ExpUtil.format_player_name_locale --- @dep expcore.common
local SelectedPlayer, SelectedAction local SelectedPlayer, SelectedAction
local function set_datastores(player, action) local function set_datastores(player, action)
@@ -31,7 +32,7 @@ end
local function get_action_player_name(player) local function get_action_player_name(player)
local selected_player_name = SelectedPlayer:get(player) local selected_player_name = SelectedPlayer:get(player)
local selected_player = game.players[selected_player_name] local selected_player = game.players[selected_player_name]
local selected_player_color = format_chat_player_name(selected_player) local selected_player_color = format_player_name(selected_player)
return selected_player_name, selected_player_color return selected_player_name, selected_player_color
end end
@@ -98,7 +99,7 @@ local report_player = new_button("utility/spawn_flag", { "player-list.report-pla
local function report_player_callback(player, reason) local function report_player_callback(player, reason)
local selected_player_name, selected_player_color = get_action_player_name(player) local selected_player_name, selected_player_color = get_action_player_name(player)
local by_player_name_color = format_chat_player_name(player) local by_player_name_color = format_player_name(player)
game.print{ "expcom-report.non-admin", selected_player_color, reason } game.print{ "expcom-report.non-admin", selected_player_color, reason }
Roles.print_to_roles_higher("Trainee", { "expcom-report.admin", selected_player_color, by_player_name_color, reason }) Roles.print_to_roles_higher("Trainee", { "expcom-report.admin", selected_player_color, by_player_name_color, reason })
Reports.report_player(selected_player_name, player.name, reason) Reports.report_player(selected_player_name, player.name, reason)
@@ -113,7 +114,7 @@ local warn_player = new_button("utility/spawn_flag", { "player-list.warn-player"
local function warn_player_callback(player, reason) local function warn_player_callback(player, reason)
local selected_player_name, selected_player_color = get_action_player_name(player) local selected_player_name, selected_player_color = get_action_player_name(player)
local by_player_name_color = format_chat_player_name(player) local by_player_name_color = format_player_name(player)
game.print{ "expcom-warnings.received", selected_player_color, by_player_name_color, reason } game.print{ "expcom-warnings.received", selected_player_color, by_player_name_color, reason }
Warnings.add_warning(selected_player_name, player.name, reason) Warnings.add_warning(selected_player_name, player.name, reason)
end end
@@ -132,7 +133,7 @@ local jail_player = new_button("utility/multiplayer_waiting_icon", { "player-lis
local function jail_player_callback(player, reason) local function jail_player_callback(player, reason)
local selected_player_name, selected_player_color = get_action_player_name(player) local selected_player_name, selected_player_color = get_action_player_name(player)
local by_player_name_color = format_chat_player_name(player) local by_player_name_color = format_player_name(player)
game.print{ "expcom-jail.give", selected_player_color, by_player_name_color, reason } game.print{ "expcom-jail.give", selected_player_color, by_player_name_color, reason }
Jail.jail_player(selected_player_name, player.name, reason) Jail.jail_player(selected_player_name, player.name, reason)
end end

View File

@@ -15,12 +15,6 @@ end
log("[START] -----| Explosive Gaming Scenario Loader |-----") log("[START] -----| Explosive Gaming Scenario Loader |-----")
log("[INFO] Setting up lua environment") log("[INFO] Setting up lua environment")
-- Require the global overrides
require("modules.exp_legacy.overrides.table") -- Adds alot more functions to the table module
storage.version = require("modules.exp_legacy.overrides.version") -- The current version for exp gaming scenario
--- @diagnostic disable-next-line
_C = require("modules.exp_legacy.expcore.common") -- _C is used to store lots of common functions expected to be used
-- Please go to config/file_loader.lua to edit the files that are loaded -- Please go to config/file_loader.lua to edit the files that are loaded
log("[INFO] Reading loader config") log("[INFO] Reading loader config")
local files = require("modules.exp_legacy.config._file_loader") local files = require("modules.exp_legacy.config._file_loader")

View File

@@ -185,7 +185,8 @@ end)
]] ]]
local player_return, write_json = _C.player_return, _C.write_json --- @dep expcore.common local ExpUtil = require("modules/exp_util")
local write_json = ExpUtil.write_json --- @dep expcore.common
local trace = debug.traceback local trace = debug.traceback
local Commands = { local Commands = {
@@ -203,12 +204,29 @@ local Commands = {
authenticators = {}, authenticators = {},
--- Used to store default functions which are common parse function such as player or number in range --- Used to store default functions which are common parse function such as player or number in range
parsers = {}, parsers = {},
--- Returns a value to the player, different to success as this does not signal the end of your command
print = player_return,
--- The command prototype which stores all command defining functions --- The command prototype which stores all command defining functions
_prototype = {}, _prototype = {},
} }
local Colours = ExpUtil.color
--- This is copied in so that _C.player_return can be removed
--- Returns a value to the player, different to success as this does not signal the end of your command
function Commands.print(value, colour, player)
colour = type(colour) == "table" and colour or Colours[colour] ~= Colours.white and Colours[colour] or Colours.white
player = player or game.player
local output = ExpUtil.format_any(value)
if player then
player = type(player) == "userdata" and player or game.get_player(player)
if not player then error("Invalid Player given to Commands.print", 2) end
player.print(output, {
color = colour,
sound_path = "utility/scenario_message",
})
else
rcon.print(output)
end
end
--- Authentication. --- Authentication.
-- Functions that control who can use commands -- Functions that control who can use commands
-- @section auth -- @section auth
@@ -658,8 +676,8 @@ return 'Your message has been printed'
]] ]]
function Commands.success(value) function Commands.success(value)
if value ~= nil then player_return(value) end if value ~= nil then Commands.print(value) end
player_return({ "expcore-commands.command-ran" }, "cyan") Commands.print({ "expcore-commands.command-ran" }, "cyan")
return Commands.defines.success return Commands.defines.success
end end
@@ -685,7 +703,7 @@ return Commands.error('The player you selected is offline')
]] ]]
function Commands.error(error_message, play_sound) function Commands.error(error_message, play_sound)
error_message = error_message or "" error_message = error_message or ""
player_return({ "expcore-commands.command-fail", error_message }, "orange_red") Commands.print({ "expcore-commands.command-fail", error_message }, "orange_red")
if play_sound ~= false then if play_sound ~= false then
play_sound = play_sound or "utility/wire_pickup" play_sound = play_sound or "utility/wire_pickup"
if game.player then game.player.play_sound{ path = play_sound } end if game.player then game.player.play_sound{ path = play_sound } end

View File

@@ -1,832 +0,0 @@
--[[-- Core Module - Common
- Adds some commonly used functions used in many modules
@core Common
@alias Common
]]
local Colours = require("modules/exp_util/include/color")
local Game = require("modules.exp_legacy.utils.game") --- @dep utils.game
local Common = {}
--- Type Checking.
-- @section typeCheck
--[[-- Asserts the argument is of type test_type
@tparam any value the value to be tested
@tparam[opt=nil] string test_type the type to test for if not given then it tests for nil
@treturn boolean is v of type test_type
@usage-- Check for a string value
local is_string = type_check(value, 'string')
@usage-- Check for a nil value
local is_nil = type_check(value)
]]
function Common.type_check(value, test_type)
return test_type and value and type(value) == test_type or not test_type and not value or false
end
--[[-- Raises an error if the value is of the wrong type
@tparam any value the value that you want to test the type of
@tparam string test_type the type that the value should be
@tparam string error_message the error message that is returned
@tparam number level the level to call the error on (level = 1 is the caller)
@treturn boolean true if no error was called
@usage-- Raise error if value is not a number
type_error(value, 'number', 'Value must be a number')
]]
function Common.type_error(value, test_type, error_message, level)
level = level and level + 1 or 2
return Common.type_check(value, test_type) or error(error_message, level)
end
--[[-- Asserts the argument is one of type test_types
@param value the variable to check
@param test_types the type as a table of strings
@treturn boolean true if value is one of test_types
@usage-- Check for a string or table
local is_string_or_table = multi_type_check(value, {'string', 'table'})
]]
function Common.multi_type_check(value, test_types)
local vtype = type(value)
for _, arg_type in ipairs(test_types) do
if vtype == arg_type then
return true
end
end
return false
end
--[[-- Raises an error if the value is of the wrong type
@tparam any value the value that you want to test the type of
@tparam table test_types the type as a table of strings
@tparam string error_message the error message that is returned
@tparam number level the level to call the error on (level = 1 is the caller)
@treturn boolean true if no error was called
@usage-- Raise error if value is not a string or table
multi_type_error('foo', {'string', 'table'}, 'Value must be a string or table')
]]
function Common.multi_type_error(value, test_types, error_message, level)
level = level and level + 1 or 2
return Common.mult_type_check(value, test_types) or error(error_message, level)
end
--[[-- Raises an error when the value is the incorrect type, uses a consistent error message format
@tparam any value the value that you want to test the type of
@tparam string test_type the type that the value should be
@tparam number param_number the number param it is
@tparam[opt] string param_name the name of the param
@treturn boolean true if no error was raised
@usage-- Output: "Bad argument #2 to "<anon>"; argument is of type string expected number"
validate_argument_type(value, 'number', 2)
@usage-- Output: "Bad argument #2 to "<anon>"; "repeat_count" is of type string expected number"
validate_argument_type(value, 'number', 2, 'repeat_count')
]]
function Common.validate_argument_type(value, test_type, param_number, param_name)
if not Common.test_type(value, test_type) then
local function_name = debug.getinfo(2, "n").name or "<anon>"
local error_message
if param_name then
error_message = string.format("Bad argument #%d to %q; %q is of type %s expected %s", param_number, function_name, param_name, type(value), test_type)
else
error_message = string.format("Bad argument #%d to %q; argument is of type %s expected %s", param_number, function_name, type(value), test_type)
end
return error(error_message, 3)
end
return true
end
--[[-- Raises an error when the value is the incorrect type, uses a consistent error message format
@tparam any value the value that you want to test the type of
@tparam string test_types the types that the value should be
@tparam number param_number the number param it is
@tparam[opt] string param_name the name of the param
@treturn boolean true if no error was raised
@usage-- Output: "Bad argument #2 to "<anon>"; argument is of type number expected string or table"
validate_argument_type(value, {'string', 'table'}, 2)
@usage-- Output: "Bad argument #2 to "<anon>"; "player" is of type number expected string or table"
validate_argument_type(value, {'string', 'table'}, 2, 'player')
]]
function Common.validate_argument_multi_type(value, test_types, param_number, param_name)
if not Common.multi_type_check(value, test_types) then
local function_name = debug.getinfo(2, "n").name or "<anon>"
local error_message
if param_name then
error_message = string.format("Bad argument #%2d to %q; %q is of type %s expected %s", param_number, function_name, param_name, type(value), table.concat(test_types, " or "))
else
error_message = string.format("Bad argument #%2d to %q; argument is of type %s expected %s", param_number, function_name, type(value), table.concat(test_types, " or "))
end
return error(error_message, 3)
end
return true
end
--- Will raise an error if called during runtime
-- @usage error_if_runtime()
function Common.error_if_runtime()
if package.lifecycle == 8 then
local function_name = debug.getinfo(2, "n").name or "<anon>"
error(function_name .. " can not be called during runtime", 3)
end
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
@usage-- Test if a string contains a sub string
local found = string_contains(str, 'foo')
]]
function Common.string_contains(s, contains)
return s and string.find(s, contains) ~= nil
end
--[[-- 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 default value is a function then it is called with the first argument being self
local value = Common.resolve_value(self.defaut_value, self)
]]
function Common.resolve_value(value, ...)
return value and type(value) == "function" and value(...) or value
end
--- Converts a varible into its boolean value, nil and false return false
-- @treturn boolean the boolean form of the varible
-- @usage local bool = cast_bool(var)
function Common.cast_bool(var)
return var and true or false
end
--- Returns either the second or third argument based on the first argument
-- @usage ternary(input_string == 'test', 'Input is test', 'Input is not test')
function Common.ternary(c, t, f)
return c and t or f
end
--- Returns a string for a number with comma seperators
-- @usage comma_value(input_number)
function Common.comma_value(n) -- credit http://richard.warburton.it
local left, num, right = string.match(n, "^([^%d]*%d)(%d*)(.-)$")
return left .. (num:reverse():gsub("(%d%d%d)", "%1, "):reverse()) .. right
end
--[[-- Sets a table element to value while also returning value.
@tparam table tbl to change the element of
@tparam string key the key to set the value of
@tparam any value the value to set the key as
@treturn any the value that was set
@usage-- Set and return value
local value = set_and_return(players, player.name, player.online_time)
]]
function Common.set_and_return(tbl, key, value)
tbl[key] = value
return value
end
--[[-- Writes a table object to a file in json format
@tparam string path the path of the file to write include / to use dir
@tparam table tbl the table that will be converted to a json string and wrote to file
@usage-- Write a lua table as a json to script-outpt/dump
write_json('dump', tbl)
]]
function Common.write_json(path, tbl)
game.write_file(path, game.table_to_json(tbl) .. "\n", true, 0)
end
--[[-- Calls a require that will not error if the file is not found
@usage local file = opt_require('file.not.present') -- will not cause any error
@tparam string path the path that you want to require
@return the returns from that file or nil, error if not loaded
@usage-- Require a file without causing errors, for when a file might not exist
local Module = opt_require 'expcore.common'
]]
function Common.opt_require(path)
local success, rtn = pcall(require, path)
if success then
return rtn
else
return nil, rtn
end
end
--[[-- Returns a desync safe file path for the current file
@tparam[opt=0] number offset the offset in the stack to get, 0 is current file
@treturn string the file path
@usage-- Get the current file path
local file_path = get_file_path()
]]
function Common.get_file_path(offset)
offset = offset or 0
return debug.getinfo(offset + 2, "S").short_src:sub(10, -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
@usage-- Make an enum
local colors = enum{
'red',
'green',
'blue'
}
]]
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
@usage-- Get the element that includes "foo"
local value = auto_complete(tbl, "foo")
@usage-- Get the element with a key that includes "foo"
local value = auto_complete(tbl, "foo", true)
@usage-- Get the key with that includes "foo"
local key = auto_complete(tbl, "foo", true, true)
]]
function Common.auto_complete(options, input, use_key, rtn_key)
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
return rtn_key and key or value
end
end
end
--- Formatting.
-- @section formatting
--[[-- Returns a valid string with the name of the actor of a command.
@tparam string player_name the name of the player to use rather than server, used only if game.player is nil
@treturn string the name of the current actor
@usage-- Get the current actor
local player_name = get_actor()
]]
function Common.get_actor(player_name)
return game.player and game.player.name or player_name or "<server>"
end
--[[-- Returns a message with valid chat tags to change its colour
@tparam string message the message that will be in the output
@tparam table color a color which contains r, g, b as its keys
@treturn string the message with the color tags included
@usage-- Use factorio tags to color a chat message
local message = format_chat_colour('Hello, World!', { r=355, g=100, b=100 })
]]
function Common.format_chat_colour(message, color)
color = color or Colours.white
local color_tag = "[color=" .. math.round(color.r, 3) .. ", " .. math.round(color.g, 3) .. ", " .. math.round(color.b, 3) .. "]"
return string.format("%s%s[/color]", color_tag, message)
end
--[[-- Returns a message with valid chat tags to change its colour, using localization
@tparam ?string|table message the message that will be in the output
@tparam table color a color which contains r, g, b as its keys
@treturn table the message with the color tags included
@usage-- Use factorio tags and locale strings to color a chat message
local message = format_chat_colour_localized('Hello, World!', { r=355, g=100, b=100 })
]]
function Common.format_chat_colour_localized(message, color)
color = color or Colours.white
color = math.round(color.r, 3) .. ", " .. math.round(color.g, 3) .. ", " .. math.round(color.b, 3)
return { "color-tag", color, message }
end
--[[-- Returns the players name in the players color
@tparam LuaPlayer player the player to use the name and color of
@tparam[opt=false] boolean raw_string when true a string is returned rather than a localized string
@treturn table the players name with tags for the players color
@usage-- Format a players name using the players color as a string
local message = format_chat_player_name(game.player, true)
]]
function Common.format_chat_player_name(player, raw_string)
player = Game.get_player_from_any(player)
local player_name = player and player.name or "<Server>"
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
@tparam any value a value of any type that will be returned to the player or console
@tparam[opt=defines.colour.white] ?defines.color|string colour the colour of the text for the player, ignored when printing to console
@tparam[opt=game.player] LuaPlayer player the player that return will go to, if no game.player then returns to server
@usage-- Return a value to the current actor, rcon included
player_return('Hello, World!')
@usage-- Return a value to the current actor, with color
player_return('Hello, World!', 'green')
@usage-- Return to a player other than the current
player_return('Hello, World!', nil, player)
]]
function Common.player_return(value, colour, player)
colour = Common.type_check(colour, "table") and colour or Colours[colour] ~= Colours.white and Colours[colour] or Colours.white
player = player or game.player
-- converts the value to a string
local string_return
if Common.type_check(value, "table") or type(value) == "userdata" then
if Common.type_check(value.__self, "userdata") or type(value) == "userdata" then
-- value is userdata
string_return = "Cant Display Userdata"
elseif Common.type_check(value[1], "string") and string.find(value[1], ".+[.].+") and not string.find(value[1], "%s") then
-- value is a locale string
string_return = value
elseif getmetatable(value) ~= nil and not tostring(value):find("table: 0x") then
-- value has a tostring meta method
string_return = tostring(value)
else
-- value is a table
string_return = table.inspect(value, { depth = 5, indent = " ", newline = "\n" })
end
elseif Common.type_check(value, "function") then
-- value is a function
string_return = "Cant Display Functions"
else
string_return = tostring(value)
end
-- returns to the player or the server
if player then
-- allows any valid player identifier to be used
player = Game.get_player_from_any(player)
if not player then error("Invalid Player given to player_return", 2) end
-- plays a nice sound that is different to normal message sound
player.play_sound{ path = "utility/scenario_message" }
player.print(string_return, colour)
else
rcon.print(string_return)
end
end
--[[-- Formats tick into a clean format, denominations from highest to lowest
-- time will use : separates
-- when a denomination is false it will overflow into the next one
@tparam number ticks the number of ticks that represents a time
@tparam table options table a of options to use for the format
@treturn string a locale string that can be used
@usage-- Output: "0h 5m"
local time = format_time(18000, { hours=true, minutes=true, string=true })
@usage-- Output: "0 hours and 5 minutes"
local time = format_time(18000, { hours=true, minutes=true, string=true, long=true })
@usage-- Output: "00:05:00"
local time = format_time(18000, { hours=true, minutes=true, seconds=true, string=true })
@usage-- Output: "--:--:--"
local time = format_time(18000, { hours=true, minutes=true, seconds=true, string=true, null=true })
]]
function Common.format_time(ticks, options)
-- Sets up the options
options = options or {
days = false,
hours = true,
minutes = true,
seconds = false,
long = false,
time = false,
string = false,
null = false,
}
-- Basic numbers that are used in calculations
local max_days, max_hours, max_minutes, max_seconds = ticks / 5184000, ticks / 216000, ticks / 3600, ticks / 60
local days, hours = max_days, max_hours - math.floor(max_days) * 24
local minutes, seconds = max_minutes - math.floor(max_hours) * 60, max_seconds - math.floor(max_minutes) * 60
-- Handles overflow of disabled denominations
local rtn_days, rtn_hours, rtn_minutes, rtn_seconds =
math.floor(days) --[[@as string | number | table]],
math.floor(hours) --[[@as string | number | table]],
math.floor(minutes) --[[@as string | number | table]],
math.floor(seconds) --[[@as string | number | table]]
if not options.days then
rtn_hours = rtn_hours + rtn_days * 24
end
if not options.hours then
rtn_minutes = rtn_minutes + rtn_hours * 60
end
if not options.minutes then
rtn_seconds = rtn_seconds + rtn_minutes * 60
end
-- Creates the null time format, does not work with long
if options.null and not options.long then
rtn_days = "--"
rtn_hours = "--"
rtn_minutes = "--"
rtn_seconds = "--"
end
-- Format options
local suffix = "time-symbol-"
local suffix_2 = "-short"
if options.long then
suffix = ""
suffix_2 = ""
end
local div = options.string and " " or "time-format.simple-format-tagged"
if options.time then
div = options.string and ":" or "time-format.simple-format-div"
-- suffix = false -- Can't get the types to work
end
-- Adds formatting
if not options.time then -- Can't get the types to work
if options.string then
-- format it as a string
local long = suffix == ""
rtn_days = long and rtn_days .. " days" or rtn_days .. "d"
rtn_hours = long and rtn_hours .. " hours" or rtn_hours .. "h"
rtn_minutes = long and rtn_minutes .. " minutes" or rtn_minutes .. "m"
rtn_seconds = long and rtn_seconds .. " seconds" or rtn_seconds .. "s"
else
rtn_days = { suffix .. "days" .. suffix_2, rtn_days }
rtn_hours = { suffix .. "hours" .. suffix_2, rtn_hours }
rtn_minutes = { suffix .. "minutes" .. suffix_2, rtn_minutes }
rtn_seconds = { suffix .. "seconds" .. suffix_2, rtn_seconds }
end
elseif not options.null then
-- weather string or not it has same format
rtn_days = string.format("%02d", rtn_days)
rtn_hours = string.format("%02d", rtn_hours)
rtn_minutes = string.format("%02d", rtn_minutes)
rtn_seconds = string.format("%02d", rtn_seconds)
end
-- The final return is construed
local rtn
local append = function(dom, value)
if dom and options.string then
rtn = rtn and rtn .. div .. value or value
elseif dom then
rtn = rtn and { div, rtn, value } or value
end
end
append(options.days, rtn_days)
append(options.hours, rtn_hours)
append(options.minutes, rtn_minutes)
append(options.seconds, rtn_seconds)
return rtn
end
--- Factorio.
-- @section factorio
--[[-- Copies items to the position and stores them in the closest entity of the type given
-- Copies the items by prototype name, but keeps them in the original inventory
@tparam table items items which are to be added to the chests, an array of LuaItemStack
@tparam[opt=navies] LuaSurface surface the surface that the items will be copied to
@tparam[opt={0, 0}] table position the position that the items will be copied to {x=100, y=100}
@tparam[opt=32] number radius the radius in which the items are allowed to be placed
@tparam[opt=iron-chest] string chest_type the chest type that the items should be copied into
@treturn LuaEntity the last chest that had items inserted into it
@usage-- Copy all the items in a players inventory and place them in chests at {0, 0}
copy_items_stack(game.player.get_main_inventory().get_contents())
]]
function Common.copy_items_stack(items, surface, position, radius, chest_type)
chest_type = chest_type or "iron-chest"
surface = surface or game.surfaces[1]
if position and type(position) ~= "table" then return end
if type(items) ~= "table" then return end
-- Finds all entities of the given type
local p = position or { x = 0, y = 0 }
local r = radius or 32
local entities = surface.find_entities_filtered{ area = { { p.x - r, p.y - r }, { p.x + r, p.y + r } }, name = chest_type } or {}
local count = #entities
local current = 1
-- Makes a new empty chest when it is needed
local function make_new_chest()
local pos = surface.find_non_colliding_position(chest_type, position, 32, 1)
local chest = surface.create_entity{ name = chest_type, position = pos, force = "neutral" }
table.insert(entities, chest)
count = count + 1
return chest
end
-- Function used to round robin the items into all chests
local function next_chest(item)
local chest = entities[current]
if count == 0 then return make_new_chest() end
if chest.get_inventory(defines.inventory.chest).can_insert(item) then
-- If the item can be inserted then the chest is returned
current = current + 1
if current > count then current = 1 end
return chest
else
-- Other wise it is removed from the list
table.remove(entities, current)
count = count - 1
end
end
-- Inserts the items into the chests
local last_chest
for i = 1, #items do
local item = items[i]
if item.valid_for_read then
local chest = next_chest(item)
if not chest or not chest.valid then return error(string.format("Cant move item %s to %s{%s, %s} no valid chest in radius", item.name, surface.name, p.x, p.y)) end
chest.insert(item)
last_chest = chest
end
end
return last_chest
end
--[[-- Moves items to the position and stores them in the closest entity of the type given
-- Differs from move_items by accepting a table of LuaItemStack and transferring them into the inventory - not copying
@tparam table items items which are to be added to the chests, an array of LuaItemStack
@tparam[opt=navies] LuaSurface surface the surface that the items will be moved to
@tparam[opt={0, 0}] table position the position that the items will be moved to {x=100, y=100}
@tparam[opt=32] number radius the radius in which the items are allowed to be placed
@tparam[opt=iron-chest] string chest_type the chest type that the items should be moved into
@treturn LuaEntity the last chest that had items inserted into it
@usage-- Copy all the items in a players inventory and place them in chests at {0, 0}
move_items_stack(game.player.get_main_inventory())
]]
function Common.move_items_stack(items, surface, position, radius, chest_type)
chest_type = chest_type or "steel-chest"
surface = surface or game.surfaces[1]
if position and type(position) ~= "table" then
return
end
if type(items) ~= "table" then
return
end
-- Finds all entities of the given type
local p = position or { x = 0, y = 0 }
local r = radius or 32
local entities = surface.find_entities_filtered{ area = { { p.x - r, p.y - r }, { p.x + r, p.y + r } }, name = { chest_type, "iron-chest" } } or {}
local count = #entities
local current = 0
local last_entity = nil
-- ipairs does not work on LuaInventory
for i = 1, #items do
local item = items[i]
if item.valid_for_read then
local inserted = false
-- Attempt to insert the items
for j = 1, count do
local entity = entities[((current + j - 1) % count) + 1]
if entity.can_insert(item) then
last_entity = entity
current = current + 1
entity.insert(item)
inserted = true
break
end
end
-- If it was not inserted then a new entity is needed
if not inserted then
--[[
if not options.allow_creation then
error('Unable to insert items into a valid entity, consider enabling allow_creation')
end
if options.name == nil then
error('Name must be provided to allow creation of new entities')
end
if options.position then
pos = surface.find_non_colliding_position(chest_type, p, r, 1, true)
elseif options.area then
pos = surface.find_non_colliding_position_in_box(chest_type, options.area, 1, true)
else
pos = surface.find_non_colliding_position(chest_type, {0,0}, 0, 1, true)
end
]]
local pos = surface.find_non_colliding_position(chest_type, p, r, 1, true)
last_entity = surface.create_entity{ name = chest_type, position = pos, force = "neutral" }
count = count + 1
entities[count] = last_entity
last_entity.insert(item)
end
end
end
--[[
-- Makes a new empty chest when it is needed
local function make_new_chest()
local pos = surface.find_non_colliding_position(chest_type, position, 32, 1)
local chest = surface.create_entity{name=chest_type, position=pos, force='neutral'}
table.insert(entities, chest)
count = count + 1
return chest
end
-- Function used to round robin the items into all chests
local function next_chest(item)
local chest = entities[current]
if count == 0 then
return make_new_chest()
end
if chest.get_inventory(defines.inventory.chest).can_insert(item) then
-- If the item can be inserted then the chest is returned
current = current + 1
if current > count then
current = 1
end
return chest
else
-- Other wise it is removed from the list
table.remove(entities, current)
count = count - 1
end
end
-- Inserts the items into the chests
local last_chest
for i=1,#items do
local item = items[i]
if item.valid_for_read then
local chest = next_chest(item)
if not chest or not chest.valid then
return error(string.format('Cant move item %s to %s{%s, %s} no valid chest in radius', item.name, surface.name, p.x, p.y))
end
local empty_stack = chest.get_inventory(defines.inventory.chest).find_empty_stack(item.name)
if not empty_stack then
return error(string.format('Cant move item %s to %s{%s, %s} no valid chest in radius', item.name, surface.name, p.x, p.y))
end
empty_stack.transfer_stack(item)
last_chest = chest
end
end
return last_chest
]]
return last_entity
end
--[[-- Prints a colored value on a location, color is based on the value.
nb: src is below but the gradent has been edited
https://github.com/Refactorio/RedMew/blob/9184b2940f311d8c9c891e83429fc57ec7e0c4a2/map_gen/maps/diggy/debug.lua#L31
@tparam number value the value to show must be between -1 and 1, scale can be used to achive this
@tparam LuaSurface surface the surface to palce the value on
@tparam table position {x, y} the possition to palce the value at
@tparam[opt=1] number scale how much to scale the colours by
@tparam[opt=0] number offset the offset in the +x +y direction
@tparam[opt=false] boolean immutable if immutable, only set, never do a surface lookup, values never change
@usage-- Place a 0 at {0, 0}
print_grid_value(0, game.player.surface, { x=0, y=0 })
]]
function Common.print_grid_value(value, surface, position, scale, offset, immutable)
local is_string = type(value) == "string"
local color = Colours.white
local text = value
if type(immutable) ~= "boolean" then
immutable = false
end
if not is_string then
scale = scale or 1
offset = offset or 0
position = { x = position.x + offset, y = position.y + offset }
local r = math.clamp(-value / scale, 0, 1)
local g = math.clamp(1 - math.abs(value) / scale, 0, 1)
local b = math.clamp(value / scale, 0, 1)
color = { r = r, g = g, b = b }
-- round at precision of 2
text = math.floor(100 * value) * 0.01
if (0 == text) then
text = "0.00"
end
end
if not immutable then
local text_entity = surface.find_entity("flying-text", position)
if text_entity then
text_entity.text = text
text_entity.color = color
return
end
end
surface.create_entity{
name = "flying-text",
color = color,
text = text,
position = position,
}.active = false
end
--[[-- Clears all flying text entities on a surface
@tparam LuaSurface surface the surface to clear
@usage-- Remove all flying text on the surface
clear_flying_text(game.player.surface)
]]
function Common.clear_flying_text(surface)
local entities = surface.find_entities_filtered{ name = "flying-text" }
for _, entity in pairs(entities) do
if entity and entity.valid then
entity.destroy()
end
end
end
return Common

View File

@@ -129,7 +129,7 @@ end
--[[-- Connect a player to the given server --[[-- Connect a player to the given server
@tparam LuaPlayer player The player that you want to request to join a different server @tparam LuaPlayer player The player that you want to request to join a different server
@tparam string server_id The internal id of the server to connect to, can also be any address but this will show Unknown Server @tparam string server_id The internal id of the server to connect to, can also be any address but this will show Unknown Server
@tparam[opt=false] boolean self_requested If the player requested the join them selfs, this will hide the message about being asked to switch @tparam[opt=false] boolean self_requested If the player requested the join themself, this will hide the message about being asked to switch
@usage-- Request that a player joins a different server @usage-- Request that a player joins a different server
External.request_connection(player, 'eu-01') External.request_connection(player, 'eu-01')

View File

@@ -121,6 +121,7 @@ end)
]] ]]
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui.prototype") local Gui = require("modules.exp_legacy.expcore.gui.prototype")
require("modules.exp_legacy.expcore.gui.helper_functions") require("modules.exp_legacy.expcore.gui.helper_functions")
require("modules.exp_legacy.expcore.gui.core_defines") require("modules.exp_legacy.expcore.gui.core_defines")
@@ -128,8 +129,8 @@ require("modules.exp_legacy.expcore.gui.top_flow")
require("modules.exp_legacy.expcore.gui.left_flow") require("modules.exp_legacy.expcore.gui.left_flow")
require("modules.exp_legacy.expcore.gui.defines") require("modules.exp_legacy.expcore.gui.defines")
local Roles = _C.opt_require("modules.exp_legacy.expcore.roles") local Roles = ExpUtil.optional_require("modules.exp_legacy.expcore.roles")
local Event = _C.opt_require("modules/exp_legacy/utils/event") local Event = ExpUtil.optional_require("modules/exp_legacy/utils/event")
if Roles and Event then if Roles and Event then
Event.add(Roles.events.on_role_assigned, function(e) Event.add(Roles.events.on_role_assigned, function(e)

View File

@@ -3,6 +3,7 @@
@module Gui @module Gui
]] ]]
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui.prototype") local Gui = require("modules.exp_legacy.expcore.gui.prototype")
local mod_gui = require "mod-gui" local mod_gui = require "mod-gui"
@@ -38,7 +39,7 @@ example_flow_with_button:add_to_left_flow(true)
]] ]]
function Gui._prototype_element:add_to_left_flow(open_on_join) function Gui._prototype_element:add_to_left_flow(open_on_join)
_C.error_if_runtime() ExpUtil.assert_not_runtime()
if not self.name then error("Elements for the top flow must have a static name") end if not self.name then error("Elements for the top flow must have a static name") end
self.open_on_join = open_on_join or false self.open_on_join = open_on_join or false
table.insert(Gui.left_elements, self) table.insert(Gui.left_elements, self)

View File

@@ -3,6 +3,7 @@
@module Gui @module Gui
]] ]]
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Gui = { local Gui = {
@@ -107,7 +108,7 @@ end)
]] ]]
function Gui.element(element_define) function Gui.element(element_define)
_C.error_if_runtime() ExpUtil.assert_not_runtime()
-- Set the metatable to allow access to register events -- Set the metatable to allow access to register events
local element = setmetatable({}, Gui._mt_element) local element = setmetatable({}, Gui._mt_element)
@@ -182,7 +183,7 @@ end)
]] ]]
function Gui._prototype_element:style(style_define) function Gui._prototype_element:style(style_define)
_C.error_if_runtime() ExpUtil.assert_not_runtime()
-- Add the definition function -- Add the definition function
if type(style_define) == "table" then if type(style_define) == "table" then
Gui.debug_info[self.uid].style = style_define Gui.debug_info[self.uid].style = style_define
@@ -205,7 +206,7 @@ end
@treturn table the element define is returned to allow for event handlers to be registered @treturn table the element define is returned to allow for event handlers to be registered
]] ]]
function Gui._prototype_element:static_name(name) function Gui._prototype_element:static_name(name)
_C.error_if_runtime() ExpUtil.assert_not_runtime()
if name == Gui.unique_static_name then if name == Gui.unique_static_name then
self.name = "ExpGui_" .. tostring(self.uid) self.name = "ExpGui_" .. tostring(self.uid)
else else
@@ -255,7 +256,7 @@ end)
]] ]]
function Gui._prototype_element:on_event(event_name, handler) function Gui._prototype_element:on_event(event_name, handler)
_C.error_if_runtime() ExpUtil.assert_not_runtime()
table.insert(Gui.debug_info[self.uid].events, event_name) table.insert(Gui.debug_info[self.uid].events, event_name)
Gui.events[event_name] = event_name Gui.events[event_name] = event_name
self[event_name] = handler self[event_name] = handler

View File

@@ -3,6 +3,7 @@
@module Gui @module Gui
]] ]]
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui.prototype") local Gui = require("modules.exp_legacy.expcore.gui.prototype")
local mod_gui = require "mod-gui" --- @dep mod-gui local mod_gui = require "mod-gui" --- @dep mod-gui
@@ -75,7 +76,7 @@ end)
]] ]]
function Gui._prototype_element:add_to_top_flow(authenticator) function Gui._prototype_element:add_to_top_flow(authenticator)
_C.error_if_runtime() ExpUtil.assert_not_runtime()
if not self.name then error("Elements for the top flow must have a static name") end if not self.name then error("Elements for the top flow must have a static name") end
self.authenticator = authenticator or true self.authenticator = authenticator or true
table.insert(Gui.top_elements, self) table.insert(Gui.top_elements, self)

View File

@@ -23,8 +23,7 @@ Permission_Groups.new_group('Restricted') -- this defines a new group called "Re
]] ]]
local Game = require("modules.exp_legacy.utils.game") --- @dep utils.game local Event = require("modules/exp_legacy/utils/event")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Async = require("modules/exp_util/async") local Async = require("modules/exp_util/async")
local PermissionsGroups = { local PermissionsGroups = {
@@ -91,8 +90,6 @@ local group = Groups.get_group_from_player(game.player)
]] ]]
function PermissionsGroups.get_group_from_player(player) function PermissionsGroups.get_group_from_player(player)
player = Game.get_player_from_any(player)
if not player then return end
local group = player.permission_group local group = player.permission_group
if group then if group then
return PermissionsGroups.groups[group.name] return PermissionsGroups.groups[group.name]
@@ -125,7 +122,6 @@ Groups.set_player_group(game.player, 'Admin')
]] ]]
function PermissionsGroups.set_player_group(player, group) function PermissionsGroups.set_player_group(player, group)
player = Game.get_player_from_any(player)
group = PermissionsGroups.get_group_by_name(group) group = PermissionsGroups.get_group_by_name(group)
if not group or not player then return false end if not group or not player then return false end
group:add_player(player) group:add_player(player)
@@ -285,7 +281,6 @@ group:add_player(game.player)
]] ]]
function PermissionsGroups._prototype:add_player(player) function PermissionsGroups._prototype:add_player(player)
player = Game.get_player_from_any(player)
local group = self:get_raw() local group = self:get_raw()
if not group or not player then return false end if not group or not player then return false end
add_to_permission_group_async(group, player) add_to_permission_group_async(group, player)
@@ -301,7 +296,6 @@ group:remove_player(game.player)
]] ]]
function PermissionsGroups._prototype:remove_player(player) function PermissionsGroups._prototype:remove_player(player)
player = Game.get_player_from_any(player)
local group = self:get_raw() local group = self:get_raw()
if not group or not player then return false end if not group or not player then return false end
remove_from_permission_group_async(group, player) remove_from_permission_group_async(group, player)

View File

@@ -108,13 +108,14 @@ Roles.define_role_order{
]] ]]
local ExpUtil = require("modules/exp_util")
local Async = require("modules/exp_util/async") local Async = require("modules/exp_util/async")
local Storage = require("modules/exp_util/storage") local Storage = require("modules/exp_util/storage")
local Game = require("modules.exp_legacy.utils.game") --- @dep utils.game local Event = require("modules/exp_legacy/utils/event")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Groups = require("modules.exp_legacy.expcore.permission_groups")
local Groups = require("modules.exp_legacy.expcore.permission_groups") --- @dep expcore.permission_groups
local Colours = require("modules/exp_util/include/color") local Colours = ExpUtil.color
local write_json = _C.write_json --- @dep expcore.common local write_json = ExpUtil.write_json
local Roles = { local Roles = {
_prototype = {}, _prototype = {},
@@ -319,7 +320,6 @@ local roles = Roles.get_player_roles(game.player)
]] ]]
function Roles.get_player_roles(player) function Roles.get_player_roles(player)
player = Game.get_player_from_any(player)
if not player then return { Roles.config.roles[Roles.config.internal.root] } end if not player then return { Roles.config.roles[Roles.config.internal.root] } end
local roles = Roles.config.players[player.name] or {} local roles = Roles.config.players[player.name] or {}
local default = Roles.config.roles[Roles.config.internal.default] local default = Roles.config.roles[Roles.config.internal.default]
@@ -370,9 +370,8 @@ Roles.assign_player('Cooldude2606', 'Moderator', nil, true)
]] ]]
function Roles.assign_player(player, roles, by_player_name, skip_checks, silent) function Roles.assign_player(player, roles, by_player_name, skip_checks, silent)
local valid_player = Game.get_player_from_any(player) local valid_player = type(player) == "userdata" and player or game.get_player(player)
if not skip_checks and not valid_player then return end if not skip_checks and not valid_player then return end
if not player then return end
-- Convert the roles into a table (allows for optional array) -- Convert the roles into a table (allows for optional array)
if type(roles) ~= "table" or roles.name then if type(roles) ~= "table" or roles.name then
@@ -387,7 +386,7 @@ function Roles.assign_player(player, roles, by_player_name, skip_checks, silent)
end end
-- If the player has a role that needs to defer the role changes, save the roles that need to be assigned later into a table -- If the player has a role that needs to defer the role changes, save the roles that need to be assigned later into a table
if valid_player and Roles.player_has_flag(player, "defer_role_changes") then if valid_player and Roles.player_has_flag(valid_player, "defer_role_changes") then
local assign_later = Roles.config.deferred_roles[valid_player.name] or {} local assign_later = Roles.config.deferred_roles[valid_player.name] or {}
for _, role in ipairs(role_objects) do for _, role in ipairs(role_objects) do
local role_change = assign_later[role.name] local role_change = assign_later[role.name]
@@ -432,7 +431,7 @@ Roles.unassign_player('Cooldude2606', 'Moderator', nil, true)
]] ]]
function Roles.unassign_player(player, roles, by_player_name, skip_checks, silent) function Roles.unassign_player(player, roles, by_player_name, skip_checks, silent)
local valid_player = Game.get_player_from_any(player) local valid_player = type(player) == "userdata" and player or game.get_player(player)
if not skip_checks and not valid_player then return end if not skip_checks and not valid_player then return end
if not player then return end if not player then return end
@@ -626,7 +625,7 @@ Roles.define_role_order{
]] ]]
function Roles.define_role_order(order) function Roles.define_role_order(order)
-- Clears and then rebuilds the order table -- Clears and then rebuilds the order table
_C.error_if_runtime() ExpUtil.assert_not_runtime()
Roles.config.order = {} Roles.config.order = {}
local done = {} local done = {}
for index, role in ipairs(order) do for index, role in ipairs(order) do
@@ -711,7 +710,7 @@ local role = Roles.new_role('Moderator', 'Mod')
]] ]]
function Roles.new_role(name, short_hand) function Roles.new_role(name, short_hand)
_C.error_if_runtime() ExpUtil.assert_not_runtime()
if Roles.config.roles[name] then return error("Role name is non unique") end if Roles.config.roles[name] then return error("Role name is non unique") end
local role = setmetatable({ local role = setmetatable({
name = name, name = name,
@@ -885,7 +884,7 @@ role:set_permission_group('Admin')
]] ]]
function Roles._prototype:set_permission_group(name, use_factorio_api) function Roles._prototype:set_permission_group(name, use_factorio_api)
_C.error_if_runtime() ExpUtil.assert_not_runtime()
if use_factorio_api then if use_factorio_api then
self.permission_group = { true, name } self.permission_group = { true, name }
else else
@@ -906,7 +905,7 @@ role:set_parent('Guest')
]] ]]
function Roles._prototype:set_parent(role) function Roles._prototype:set_parent(role)
_C.error_if_runtime() ExpUtil.assert_not_runtime()
self.parent = role self.parent = role
role = Roles.get_role_from_any(role) role = Roles.get_role_from_any(role)
if not role then return self end if not role then return self end
@@ -926,7 +925,7 @@ end)
]] ]]
function Roles._prototype:set_auto_assign_condition(callback) function Roles._prototype:set_auto_assign_condition(callback)
_C.error_if_runtime() ExpUtil.assert_not_runtime()
self.auto_assign_condition = true self.auto_assign_condition = true
Roles.config.auto_assign[self.name] = callback Roles.config.auto_assign[self.name] = callback
return self return self
@@ -972,7 +971,7 @@ role:add_player(game.player)
]] ]]
function Roles._prototype:add_player(player, skip_check, skip_event) function Roles._prototype:add_player(player, skip_check, skip_event)
local valid_player = Game.get_player_from_any(player) local valid_player = type(player) == "userdata" and player or game.get_player(player)
-- Default role cant have players added or removed -- Default role cant have players added or removed
if self.name == Roles.config.internal.default then return end if self.name == Roles.config.internal.default then return end
-- Check the player is valid, can be skipped but a name must be given -- Check the player is valid, can be skipped but a name must be given
@@ -1013,7 +1012,7 @@ role:remove_player(game.player)
]] ]]
function Roles._prototype:remove_player(player, skip_check, skip_event) function Roles._prototype:remove_player(player, skip_check, skip_event)
local valid_player = Game.get_player_from_any(player) local valid_player = type(player) == "userdata" and player or game.get_player(player)
-- Default role cant have players added or removed -- Default role cant have players added or removed
if self.name == Roles.config.internal.default then return end if self.name == Roles.config.internal.default then return end
-- Check the player is valid, can be skipped but a name must be given -- Check the player is valid, can be skipped but a name must be given

View File

@@ -2,12 +2,10 @@
-- also displays a ping above users who are named in the message -- also displays a ping above users who are named in the message
-- @addon Chat-Popups -- @addon Chat-Popups
local FloatingText = require("modules/exp_util/floating_text") local FlyingText = require("modules/exp_util/flying_text")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local config = require("modules.exp_legacy.config.popup_messages") --- @dep config.popup_messages local config = require("modules.exp_legacy.config.popup_messages") --- @dep config.popup_messages
local send_text = FloatingText.print_as_player -- (player, text)
Event.add(defines.events.on_console_chat, function(event) Event.add(defines.events.on_console_chat, function(event)
if not event.player_index or event.player_index < 1 then return end if not event.player_index or event.player_index < 1 then return end
local player = game.players[event.player_index] local player = game.players[event.player_index]
@@ -18,7 +16,10 @@ Event.add(defines.events.on_console_chat, function(event)
-- Sends the message as text above them -- Sends the message as text above them
if config.show_player_messages then if config.show_player_messages then
send_text(player, { "chat-popup.message", player.name, event.message }) FlyingText.create_as_player{
target_player = player,
text = { "chat-popup.message", player.name, event.message },
}
end end
if not config.show_player_mentions then return end if not config.show_player_mentions then return end
@@ -30,7 +31,10 @@ Event.add(defines.events.on_console_chat, function(event)
for _, mentioned_player in pairs(game.connected_players) do for _, mentioned_player in pairs(game.connected_players) do
if mentioned_player.index ~= player.index then if mentioned_player.index ~= player.index then
if search_string:find(mentioned_player.name:lower(), 1, true) then if search_string:find(mentioned_player.name:lower(), 1, true) then
send_text(mentioned_player, { "chat-popup.ping", player.name }) FlyingText.create_as_player{
target_player = mentioned_player,
text = { "chat-popup.ping", player.name },
}
end end
end end
end end

View File

@@ -2,7 +2,7 @@
-- also shows player health when a player is attacked -- also shows player health when a player is attacked
-- @addon Damage-Popups -- @addon Damage-Popups
local FloatingText = require("modules/exp_util/floating_text") local FlyingText = require("modules/exp_util/flying_text")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local config = require("modules.exp_legacy.config.popup_messages") --- @dep config.popup_messages local config = require("modules.exp_legacy.config.popup_messages") --- @dep config.popup_messages
@@ -31,11 +31,10 @@ Event.add(defines.events.on_entity_damaged, function(event)
-- Outputs the message as floating text -- Outputs the message as floating text
if message then if message then
FloatingText.print( FlyingText.create{
entity.surface, text = message,
position, position = position,
message, color = text_colour,
text_colour }
)
end end
end) end)

View File

@@ -1,10 +1,10 @@
--- Makes markers on the map where places have died and reclaims items if not recovered --- Makes markers on the map where places have died and reclaims items if not recovered
-- @addon Death-Logger -- @addon Death-Logger
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Storage = require("modules/exp_util/storage") local Storage = require("modules/exp_util/storage")
local config = require("modules.exp_legacy.config.death_logger") --- @dep config.death_logger local config = require("modules.exp_legacy.config.death_logger") --- @dep config.death_logger
local format_time, move_items = _C.format_time, _C.move_items_stack --- @dep expcore.common
-- Max amount of ticks a corpse can be alive -- Max amount of ticks a corpse can be alive
local corpse_lifetime = 60 * 60 * 15 local corpse_lifetime = 60 * 60 * 15
@@ -17,12 +17,14 @@ Storage.register(deaths, function(tbl)
deaths = tbl deaths = tbl
end) end)
local map_tag_time_format = ExpUtil.format_time_factory{ format = "short", hours = true, minutes = true }
--- Creates a new death marker and saves it to the given death --- Creates a new death marker and saves it to the given death
local function create_map_tag(death) local function create_map_tag(death)
local player = game.players[death.player_name] local player = game.players[death.player_name]
local message = player.name .. " died" local message = player.name .. " died"
if config.include_time_of_death then if config.include_time_of_death then
local time = format_time(death.time_of_death, { hours = true, minutes = true, string = true }) local time = map_tag_time_format(death.time_of_death)
message = message .. " at " .. time message = message .. " at " .. time
end end
death.tag = player.force.add_chart_tag(player.surface, { death.tag = player.force.add_chart_tag(player.surface, {
@@ -60,14 +62,21 @@ local function check_map_tags()
end end
-- when a player dies a new death is added to the records and a map marker is made -- when a player dies a new death is added to the records and a map marker is made
--- @param event EventData.on_player_died
Event.add(defines.events.on_player_died, function(event) Event.add(defines.events.on_player_died, function(event)
local player = game.players[event.player_index] local player = game.players[event.player_index]
local corpse = player.surface.find_entity("character-corpse", player.position) local corpse = player.surface.find_entity("character-corpse", player.position)
if not corpse or not corpse.valid then return end if not corpse or not corpse.valid then return end
if config.use_chests_as_bodies then if config.use_chests_as_bodies then
local items = corpse.get_inventory(defines.inventory.character_corpse) local inventory = assert(corpse.get_inventory(defines.inventory.character_corpse))
local chest = move_items(items, corpse.surface, corpse.position) local chest = ExpUtil.transfer_inventory_to_surface{
chest.destructible = false inventory = inventory,
surface = corpse.surface,
position = corpse.position,
name = "iron-chest",
allow_creation = true,
}
corpse.destroy() corpse.destroy()
corpse = chest corpse = chest
end end
@@ -139,10 +148,16 @@ if config.show_map_markers then
end end
if config.auto_collect_bodies then if config.auto_collect_bodies then
--- @param event EventData.on_character_corpse_expired
Event.add(defines.events.on_character_corpse_expired, function(event) Event.add(defines.events.on_character_corpse_expired, function(event)
local corpse = event.corpse local corpse = event.corpse
local items = corpse.get_inventory(defines.inventory.character_corpse) local inventory = assert(corpse.get_inventory(defines.inventory.character_corpse))
move_items(items, corpse.surface, { x = 0, y = 0 }) ExpUtil.transfer_inventory_to_surface{
inventory = inventory,
surface = corpse.surface,
name = "iron-chest",
allow_creation = true,
}
end) end)
end end

View File

@@ -1,20 +1,21 @@
--- Log certain actions into a file when events are triggered --- Log certain actions into a file when events are triggered
-- @addon Deconlog -- @addon Deconlog
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local format_time = _C.format_time --- @dep expcore.common
local format_number = require("util").format_number --- @dep util local format_number = require("util").format_number --- @dep util
local config = require("modules.exp_legacy.config.deconlog") --- @dep config.deconlog local config = require("modules.exp_legacy.config.deconlog") --- @dep config.deconlog
local filepath = "log/decon.log" local filepath = "log/decon.log"
local seconds_time_format = ExpUtil.format_time_factory{ format = "short", hours = true, minutes = true, seconds = true }
local function add_log(data) local function add_log(data)
game.write_file(filepath, data .. "\n", true, 0) -- write data game.write_file(filepath, data .. "\n", true, 0) -- write data
end end
local function get_secs() local function get_secs()
return format_time(game.tick, { hours = true, minutes = true, seconds = true, string = true }) return seconds_time_format(game.tick)
end end
local function pos_to_string(pos) local function pos_to_string(pos)

View File

@@ -1,12 +1,14 @@
--- Sends alert messages to our discord server when certain events are triggered --- Sends alert messages to our discord server when certain events are triggered
-- @addon Discord-Alerts -- @addon Discord-Alerts
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Colors = require("modules/exp_util/include/color") local Colors = require("modules/exp_util/include/color")
local write_json, format_time = _C.write_json, _C.format_time --- @dep expcore.common
local config = require("modules.exp_legacy.config.discord_alerts") --- @dep config.discord_alerts local config = require("modules.exp_legacy.config.discord_alerts") --- @dep config.discord_alerts
local write_json = ExpUtil.write_json
local playtime_format = { hours = true, minutes = true, short = true, string = true } local playtime_format = ExpUtil.format_time_factory{ format = "short", hours = true, minutes = true, seconds = true }
local emit_event_time_format = ExpUtil.format_time_factory{ format = "short", hours = true, minutes = true }
local function append_playtime(player_name) local function append_playtime(player_name)
if not config.show_playtime then if not config.show_playtime then
@@ -19,7 +21,7 @@ local function append_playtime(player_name)
return player_name return player_name
end end
return player.name .. " (" .. format_time(player.online_time, playtime_format) .. ")" return player.name .. " (" .. playtime_format(player.online_time) .. ")"
end end
local function get_player_name(event) local function get_player_name(event)
@@ -48,7 +50,7 @@ local function emit_event(args)
end end
local tick = args.tick or game.tick local tick = args.tick or game.tick
local tick_formatted = format_time(tick, { days = false, hours = true, minutes = true, short = true, string = true }) local tick_formatted = emit_event_time_format(tick)
local players_online = 0 local players_online = 0
local admins_online = 0 local admins_online = 0

View File

@@ -1,15 +1,19 @@
--- Will move players items to spawn when they are banned or kicked, option to clear on leave --- Will move players items to spawn when they are banned or kicked, option to clear on leave
-- @addon Inventory-Clear -- @addon Inventory-Clear
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local events = require("modules.exp_legacy.config.inventory_clear") --- @dep config.inventory_clear local events = require("modules.exp_legacy.config.inventory_clear") --- @dep config.inventory_clear
local move_items_stack = _C.move_items_stack --- @dep expcore.common
local function clear_items(event) local function clear_items(event)
local player = game.players[event.player_index] local player = game.players[event.player_index]
local inv = player.get_main_inventory() --- @cast inv -nil local inventory = assert(player.get_main_inventory())
move_items_stack(inv) ExpUtil.transfer_inventory_to_surface{
inv.clear() inventory = inventory,
surface = game.surfaces[1],
name = "iron-chest",
allow_creation = true,
}
end end
for _, event_name in ipairs(events) do Event.add(event_name, clear_items) end for _, event_name in ipairs(events) do Event.add(event_name, clear_items) end

View File

@@ -110,7 +110,7 @@ local function miner_check(entity)
local entities = es.find_entities_filtered{ area = { { ep.x - r, ep.y - r }, { ep.x + r, ep.y + r } }, type = { "mining-drill", "pipe", "pipe-to-ground" } } local entities = es.find_entities_filtered{ area = { { ep.x - r, ep.y - r }, { ep.x + r, ep.y + r } }, type = { "mining-drill", "pipe", "pipe-to-ground" } }
local entities_t = es.find_entities_filtered{ area = { { ep.x - r, ep.y - r }, { ep.x + r, ep.y + r } }, ghost_type = { "pipe", "pipe-to-ground" } } local entities_t = es.find_entities_filtered{ area = { { ep.x - r, ep.y - r }, { ep.x + r, ep.y + r } }, ghost_type = { "pipe", "pipe-to-ground" } }
table.array_insert(entities, entities_t) table.insert_array(entities, entities_t)
for _, e in pairs(entities) do for _, e in pairs(entities) do
if (e.position.x > ep.x) and (e.position.y == ep.y) then if (e.position.x > ep.x) and (e.position.y == ep.y) then

View File

@@ -1,26 +1,36 @@
--- Disable new players from having certain items in their inventory, most commonly nukes --- Disable new players from having certain items in their inventory, most commonly nukes
-- @addon Nukeprotect -- @addon Nukeprotect
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local config = require("modules.exp_legacy.config.nukeprotect") --- @dep config.nukeprotect local config = require("modules.exp_legacy.config.nukeprotect") --- @dep config.nukeprotect
local move_items_stack = _C.move_items_stack --- @dep expcore.common
--- Check all items in the given inventory
---@param player LuaPlayer
---@param type defines.inventory
local function check_items(player, type) local function check_items(player, type)
-- if the player has perms to be ignored, then they should be -- if the player has perms to be ignored, then they should be
if config.ignore_permisison and Roles.player_allowed(player, config.ignore_permisison) then return end if config.ignore_permisison and Roles.player_allowed(player, config.ignore_permisison) then return end
-- if the players -- if the players
if config.ignore_admins and player.admin then return end if config.ignore_admins and player.admin then return end
local inventory = player.get_inventory(type) local items = {} --- @type LuaItemStack[]
local inventory = assert(player.get_inventory(type))
for i = 1, #inventory do for i = 1, #inventory do
local item = inventory[i] local item = inventory[i]
if item.valid and item.valid_for_read and config[tostring(type)][item.name] then if item.valid and item.valid_for_read and config[tostring(type)][item.name] then
player.print{ "nukeprotect.found", { "item-name." .. item.name } } player.print{ "nukeprotect.found", { "item-name." .. item.name } }
-- insert the items into the table so all items are transferred at once items[#items + 1] = item
move_items_stack{ item }
end end
end end
ExpUtil.move_items_to_surface{
items = items,
surface = player.surface,
allow_creation = true,
name = "iron-chest",
}
end end
for _, inventory in ipairs(config.inventories) do for _, inventory in ipairs(config.inventories) do

View File

@@ -1,11 +1,12 @@
--- When a player triggers protection multiple times they are automatically jailed --- When a player triggers protection multiple times they are automatically jailed
-- @addon protection-jail -- @addon protection-jail
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Storage = require("modules/exp_util/storage") --- @dep utils.global local Storage = require("modules/exp_util/storage") --- @dep utils.global
local Jail = require("modules.exp_legacy.modules.control.jail") --- @dep modules.control.jail local Jail = require("modules.exp_legacy.modules.control.jail") --- @dep modules.control.jail
local Protection = require("modules.exp_legacy.modules.control.protection") --- @dep modules.control.protection local Protection = require("modules.exp_legacy.modules.control.protection") --- @dep modules.control.protection
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local format_player_name = ExpUtil.format_player_name_locale --- @dep expcore.common
--- Stores how many times the repeat violation was triggered --- Stores how many times the repeat violation was triggered
local repeat_count = {} local repeat_count = {}
@@ -29,7 +30,7 @@ Event.add(Protection.events.on_repeat_violation, function(event)
return return
end end
local player_name_color = format_chat_player_name(player) local player_name_color = format_player_name(player)
Jail.jail_player(player, "<protection>", "Removed too many protected entities, please wait for a moderator.") Jail.jail_player(player, "<protection>", "Removed too many protected entities, please wait for a moderator.")
game.print{ "protection-jail.jail", player_name_color } game.print{ "protection-jail.jail", player_name_color }
end) end)

View File

@@ -1,10 +1,11 @@
--- When a player is reported, the player is automatically jailed if the combined playtime of the reporters exceeds the reported player --- When a player is reported, the player is automatically jailed if the combined playtime of the reporters exceeds the reported player
-- @addon report-jail -- @addon report-jail
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Jail = require("modules.exp_legacy.modules.control.jail") --- @dep modules.control.jail local Jail = require("modules.exp_legacy.modules.control.jail") --- @dep modules.control.jail
local Reports = require("modules.exp_legacy.modules.control.reports") --- @dep modules.control.reports local Reports = require("modules.exp_legacy.modules.control.reports") --- @dep modules.control.reports
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local format_player_name = ExpUtil.format_player_name_locale --- @dep expcore.common
--- Returns the playtime of the reporter. Used when calculating the total playtime of all reporters --- Returns the playtime of the reporter. Used when calculating the total playtime of all reporters
local function reporter_playtime(_, by_player_name, _) local function reporter_playtime(_, by_player_name, _)
@@ -21,7 +22,7 @@ Event.add(Reports.events.on_player_reported, function(event)
-- player less than 30 min -- player less than 30 min
if (Reports.count_reports(player) > 1) and (total_playtime > math.max(player.online_time * 2, 108000)) then if (Reports.count_reports(player) > 1) and (total_playtime > math.max(player.online_time * 2, 108000)) then
local player_name_color = format_chat_player_name(player) local player_name_color = format_player_name(player)
Jail.jail_player(player, "<reports>", "Reported by too many players, please wait for a moderator.") Jail.jail_player(player, "<reports>", "Reported by too many players, please wait for a moderator.")
game.print{ "report-jail.jail", player_name_color } game.print{ "report-jail.jail", player_name_color }
end end

View File

@@ -2,8 +2,6 @@
-- @addon Scorched-Earth -- @addon Scorched-Earth
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Storage = require("modules/exp_util/storage")
local print_grid_value, clear_flying_text = _C.print_grid_value, _C.clear_flying_text --- @dep expcore.common
local config = require("modules.exp_legacy.config.scorched_earth") --- @dep config.scorched_earth local config = require("modules.exp_legacy.config.scorched_earth") --- @dep config.scorched_earth
-- Loops over the config and finds the wile which has the highest value for strength -- Loops over the config and finds the wile which has the highest value for strength
@@ -14,12 +12,6 @@ for _, strength in pairs(config.strengths) do
end end
end end
-- Used for debugging the degrade chances
local debug_players = {}
Storage.register(debug_players, function(tbl)
debug_players = tbl
end)
-- Will degrade a tile down to the next tile when called -- Will degrade a tile down to the next tile when called
local function degrade(surface, position) local function degrade(surface, position)
local tile = surface.get_tile(position) local tile = surface.get_tile(position)
@@ -80,19 +72,6 @@ local function get_tile_strength(surface, position)
return strength / 9 return strength / 9
end end
-- Same as get_tile_strength but returns to a in game text rather than as a value
local function debug_get_tile_strength(surface, position)
for x = -3, 3 do -- x loop
local px = position.x + x
for y = -3, 3 do -- y loop
local p = { x = px, y = position.y + y }
local strength = get_tile_strength(surface, p) or 0
local tile = surface.get_tile(p)
print_grid_value(get_probability(strength) * config.weakness_value, surface, tile.position)
end
end
end
-- When the player changes position the tile will have a chance to downgrade, debug check is here -- When the player changes position the tile will have a chance to downgrade, debug check is here
Event.add(defines.events.on_player_changed_position, function(event) Event.add(defines.events.on_player_changed_position, function(event)
local player = game.players[event.player_index] local player = game.players[event.player_index]
@@ -103,9 +82,6 @@ Event.add(defines.events.on_player_changed_position, function(event)
if get_probability(strength) > math.random() then if get_probability(strength) > math.random() then
degrade(surface, position) degrade(surface, position)
end end
if debug_players[player.name] then
debug_get_tile_strength(surface, position)
end
end) end)
-- When an entity is build there is a much higher chance that the tiles will degrade -- When an entity is build there is a much higher chance that the tiles will degrade
@@ -131,10 +107,3 @@ Event.add(defines.events.on_robot_built_entity, function(event)
degrade_entity(entity) degrade_entity(entity)
end end
end) end)
-- Used as a way to access the global table
return function(player_name, state)
local player = game.players[player_name]
clear_flying_text(player.surface)
debug_players[player_name] = state
end

View File

@@ -3,8 +3,9 @@
@commands Admin-Chat @commands Admin-Chat
]] ]]
local ExpUtil = require("modules/exp_util")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local format_player_name = ExpUtil.format_player_name_locale --- @dep expcore.common
require("modules.exp_legacy.config.expcore.command_general_parse") require("modules.exp_legacy.config.expcore.command_general_parse")
--- Sends a message in chat that only admins can see --- Sends a message in chat that only admins can see
@@ -16,7 +17,7 @@ Commands.new_command("admin-chat", { "expcom-admin-chat.description" }, "Sends a
:set_flag("admin_only") :set_flag("admin_only")
:add_alias("ac") :add_alias("ac")
:register(function(player, message) :register(function(player, message)
local player_name_colour = format_chat_player_name(player) local player_name_colour = format_player_name(player)
for _, return_player in pairs(game.connected_players) do for _, return_player in pairs(game.connected_players) do
if return_player.admin then if return_player.admin then
return_player.print{ "expcom-admin-chat.format", player_name_colour, message } return_player.print{ "expcom-admin-chat.format", player_name_colour, message }

View File

@@ -3,21 +3,26 @@
@commands Clear-Inventory @commands Clear-Inventory
]] ]]
local ExpUtil = require("modules/exp_util")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local move_items_stack = _C.move_items_stack --- @dep expcore.common
require("modules.exp_legacy.config.expcore.command_role_parse") require("modules.exp_legacy.config.expcore.command_role_parse")
--- Clears a players inventory --- Clears a players inventory
-- @command clear-inventory -- @command clear-inventory
-- @tparam LuaPlayer player the player to clear the inventory of -- @tparam LuaPlayer player the player to clear the inventory of
Commands.new_command("clear-inventory", { "expcom-clr-inv.description" }, "Clears a players inventory") Commands.new_command("clear-inventory", { "expcom-clr-inv.description" }, "Clears a players inventory")
:add_param("player", false, "player-role") :add_param("player", false, "player-role")
:add_alias("clear-inv", "move-inventory", "move-inv") :add_alias("clear-inv", "move-inventory", "move-inv")
:register(function(_, player) :register(function(_, player)
local inv = player.get_main_inventory() local inventory = player.get_main_inventory()
if not inv then if not inventory then
return Commands.error{ "expcore-commands.reject-player-alive" } return Commands.error{ "expcore-commands.reject-player-alive" }
end end
move_items_stack(inv)
inv.clear() ExpUtil.transfer_inventory_to_surface{
end) inventory = inventory,
surface = player.surface,
name = "iron-chest",
allow_creation = true,
}
end)

View File

@@ -3,13 +3,14 @@
@commands Interface @commands Interface
]] ]]
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local ExpUtil = require("modules/exp_util")
local Storage = require("modules/exp_util/storage") local Storage = require("modules/exp_util/storage")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
-- modules that are loaded into the interface env to be accessed -- modules that are loaded into the interface env to be accessed
local interface_modules = { local interface_modules = {
["Commands"] = Commands, ["Commands"] = Commands,
["output"] = _C.player_return, ["output"] = Commands.print,
["Group"] = "expcore.permission_groups", ["Group"] = "expcore.permission_groups",
["Roles"] = "expcore.roles", ["Roles"] = "expcore.roles",
["Gui"] = "expcore.gui", ["Gui"] = "expcore.gui",
@@ -20,7 +21,7 @@ local interface_modules = {
-- loads all the modules given in the above table -- loads all the modules given in the above table
for key, value in pairs(interface_modules) do for key, value in pairs(interface_modules) do
if type(value) == "string" then if type(value) == "string" then
interface_modules[key] = _C.opt_require(value) interface_modules[key] = ExpUtil.optional_require(value)
end end
end end

View File

@@ -3,9 +3,10 @@
@commands Jail @commands Jail
]] ]]
local ExpUtil = require("modules/exp_util")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local Jail = require("modules.exp_legacy.modules.control.jail") --- @dep modules.control.jail local Jail = require("modules.exp_legacy.modules.control.jail") --- @dep modules.control.jail
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local format_player_name = ExpUtil.format_player_name_locale --- @dep expcore.common
require("modules.exp_legacy.config.expcore.command_role_parse") require("modules.exp_legacy.config.expcore.command_role_parse")
--- Puts a player into jail and removes all other roles. --- Puts a player into jail and removes all other roles.
@@ -18,8 +19,8 @@ Commands.new_command("jail", { "expcom-jail.description-jail" }, "Puts a player
:enable_auto_concat() :enable_auto_concat()
:register(function(player, action_player, reason) :register(function(player, action_player, reason)
reason = reason or "Non Given." reason = reason or "Non Given."
local action_player_name_color = format_chat_player_name(action_player) local action_player_name_color = format_player_name(action_player)
local by_player_name_color = format_chat_player_name(player) local by_player_name_color = format_player_name(player)
local player_name = player and player.name or "<server>" local player_name = player and player.name or "<server>"
if Jail.jail_player(action_player, player_name, reason) then if Jail.jail_player(action_player, player_name, reason) then
game.print{ "expcom-jail.give", action_player_name_color, by_player_name_color, reason } game.print{ "expcom-jail.give", action_player_name_color, by_player_name_color, reason }
@@ -36,8 +37,8 @@ Commands.new_command("unjail", { "expcom-jail.description-unjail" }, "Removes a
:add_alias("clear-jail", "remove-jail") :add_alias("clear-jail", "remove-jail")
:enable_auto_concat() :enable_auto_concat()
:register(function(player, action_player) :register(function(player, action_player)
local action_player_name_color = format_chat_player_name(action_player) local action_player_name_color = format_player_name(action_player)
local by_player_name_color = format_chat_player_name(player) local by_player_name_color = format_player_name(player)
local player_name = player and player.name or "<server>" local player_name = player and player.name or "<server>"
if Jail.unjail_player(action_player, player_name) then if Jail.unjail_player(action_player, player_name) then
game.print{ "expcom-jail.remove", action_player_name_color, by_player_name_color } game.print{ "expcom-jail.remove", action_player_name_color, by_player_name_color }

View File

@@ -3,8 +3,9 @@
@commands LastLocation @commands LastLocation
]] ]]
local ExpUtil = require("modules/exp_util")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local format_player_name = ExpUtil.format_player_name_locale --- @dep expcore.common
require("modules.exp_legacy.config.expcore.command_general_parse") require("modules.exp_legacy.config.expcore.command_general_parse")
--- Get the last location of a player. --- Get the last location of a player.
@@ -14,6 +15,6 @@ Commands.new_command("last-location", { "expcom-lastlocation.description" }, "Se
:add_alias("location") :add_alias("location")
:add_param("player", false, "player") :add_param("player", false, "player")
:register(function(_, action_player) :register(function(_, action_player)
local action_player_name_color = format_chat_player_name(action_player) local action_player_name_color = format_player_name(action_player)
return Commands.success{ "expcom-lastlocation.response", action_player_name_color, string.format("%.1f", action_player.position.x), string.format("%.1f", action_player.position.y) } return Commands.success{ "expcom-lastlocation.response", action_player_name_color, string.format("%.1f", action_player.position.x), string.format("%.1f", action_player.position.y) }
end) end)

View File

@@ -3,11 +3,12 @@
@commands Protection @commands Protection
]] ]]
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Storage = require("modules/exp_util/storage") local Storage = require("modules/exp_util/storage")
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local format_player_name = ExpUtil.format_player_name_locale --- @dep expcore.common
local EntityProtection = require("modules.exp_legacy.modules.control.protection") --- @dep modules.control.protection local EntityProtection = require("modules.exp_legacy.modules.control.protection") --- @dep modules.control.protection
local Selection = require("modules.exp_legacy.modules.control.selection") --- @dep modules.control.selection local Selection = require("modules.exp_legacy.modules.control.selection") --- @dep modules.control.selection
@@ -215,6 +216,6 @@ end)
--- When there is a repeat offence print it in chat --- When there is a repeat offence print it in chat
Event.add(EntityProtection.events.on_repeat_violation, function(event) Event.add(EntityProtection.events.on_repeat_violation, function(event)
local player_name = format_chat_player_name(event.player_index) local player_name = format_player_name(event.player_index)
Roles.print_to_roles_higher("Regular", { "expcom-protection.repeat-offence", player_name, event.entity.localised_name, event.entity.position.x, event.entity.position.y }) Roles.print_to_roles_higher("Regular", { "expcom-protection.repeat-offence", player_name, event.entity.localised_name, event.entity.position.x, event.entity.position.y })
end) end)

View File

@@ -3,8 +3,9 @@
@commands Rainbow @commands Rainbow
]] ]]
local ExpUtil = require("modules/exp_util")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local format_chat_colour = _C.format_chat_colour --- @dep expcore.common local format_chat_colour = ExpUtil.format_rich_text_color --- @dep expcore.common
local function step_component(c1, c2) local function step_component(c1, c2)
if c1 < 0 then if c1 < 0 then

View File

@@ -3,10 +3,11 @@
@commands Reports @commands Reports
]] ]]
local ExpUtil = require("modules/exp_util")
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local Reports = require("modules.exp_legacy.modules.control.reports") --- @dep modules.control.reports local Reports = require("modules.exp_legacy.modules.control.reports") --- @dep modules.control.reports
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local format_player_name = ExpUtil.format_player_name_locale --- @dep expcore.common
require("modules.exp_legacy.config.expcore.command_general_parse") require("modules.exp_legacy.config.expcore.command_general_parse")
--- Print a message to all players who match the value of admin --- Print a message to all players who match the value of admin
@@ -38,8 +39,8 @@ Commands.new_command("report", { "expcom-report.description-report" }, "Reports
:add_alias("report-player") :add_alias("report-player")
:enable_auto_concat() :enable_auto_concat()
:register(function(player, action_player, reason) :register(function(player, action_player, reason)
local action_player_name_color = format_chat_player_name(action_player) local action_player_name_color = format_player_name(action_player)
local by_player_name_color = format_chat_player_name(player) local by_player_name_color = format_player_name(player)
if Reports.report_player(action_player, player.name, reason) then if Reports.report_player(action_player, player.name, reason) then
print_to_players(false, { "expcom-report.non-admin", action_player_name_color, reason }) print_to_players(false, { "expcom-report.non-admin", action_player_name_color, reason })
print_to_players(true, { "expcom-report.admin", action_player_name_color, by_player_name_color, reason }) print_to_players(true, { "expcom-report.admin", action_player_name_color, by_player_name_color, reason })
@@ -58,17 +59,17 @@ Commands.new_command("get-reports", { "expcom-report.description-get-reports" },
:register(function(_, player) :register(function(_, player)
if player then if player then
local reports = Reports.get_reports(player) local reports = Reports.get_reports(player)
local player_name_color = format_chat_player_name(player) local player_name_color = format_player_name(player)
Commands.print{ "expcom-report.player-report-title", player_name_color } Commands.print{ "expcom-report.player-report-title", player_name_color }
for player_name, reason in pairs(reports) do for player_name, reason in pairs(reports) do
local by_player_name_color = format_chat_player_name(player_name) local by_player_name_color = format_player_name(player_name)
Commands.print{ "expcom-report.list", by_player_name_color, reason } Commands.print{ "expcom-report.list", by_player_name_color, reason }
end end
else else
local user_reports = Reports.user_reports local user_reports = Reports.user_reports
Commands.print{ "expcom-report.player-count-title" } Commands.print{ "expcom-report.player-count-title" }
for player_name in pairs(user_reports) do for player_name in pairs(user_reports) do
local player_name_color = format_chat_player_name(player_name) local player_name_color = format_player_name(player_name)
local report_count = Reports.count_reports(player_name) local report_count = Reports.count_reports(player_name)
Commands.print{ "expcom-report.list", player_name_color, report_count } Commands.print{ "expcom-report.list", player_name_color, report_count }
end end
@@ -92,7 +93,7 @@ Commands.new_command("clear-reports", { "expcom-report.description-clear-reports
return Commands.error{ "expcom-report.not-reported" } return Commands.error{ "expcom-report.not-reported" }
end end
end end
local action_player_name_color = format_chat_player_name(action_player) local action_player_name_color = format_player_name(action_player)
local by_player_name_color = format_chat_player_name(player) local by_player_name_color = format_player_name(player)
game.print{ "expcom-report.removed", action_player_name_color, by_player_name_color } game.print{ "expcom-report.removed", action_player_name_color, by_player_name_color }
end) end)

View File

@@ -3,10 +3,11 @@
@commands Roles @commands Roles
]] ]]
local ExpUtil = require("modules/exp_util")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local Colours = require("modules/exp_util/include/color") local Colours = require("modules/exp_util/include/color")
local format_chat_player_name, format_chat_colour_localized = _C.format_chat_player_name, _C.format_chat_colour_localized local format_player_name, format_color = ExpUtil.format_player_name_locale, ExpUtil.format_rich_text_color
--- Assigns a role to a player --- Assigns a role to a player
-- @command assign-role -- @command assign-role
@@ -63,11 +64,11 @@ Commands.new_command("list-roles", { "expcom-roles.description-list-roles" }, "L
for index, role in pairs(roles) do for index, role in pairs(roles) do
role = Roles.get_role_from_any(role) role = Roles.get_role_from_any(role)
local colour = role.custom_color or Colours.white local colour = role.custom_color or Colours.white
local role_name = format_chat_colour_localized(role.name, colour) local role_name = format_color(role.name, colour)
if index == 1 then if index == 1 then
message = { "expcom-roles.list", role_name } message = { "expcom-roles.list", role_name }
if player then if player then
local player_name_colour = format_chat_player_name(player) local player_name_colour = format_player_name(player)
message = { "expcom-roles.list-player", player_name_colour, role_name } message = { "expcom-roles.list-player", player_name_colour, role_name }
end end
else else

View File

@@ -3,10 +3,10 @@
@commands InventorySearch @commands InventorySearch
]] ]]
local ExpUtil = require("modules/exp_util")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local format_number = require("util").format_number --- @dep util local format_number = require("util").format_number --- @dep util
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local format_player_name = ExpUtil.format_player_name_locale
local format_time = _C.format_time
require("modules.exp_legacy.config.expcore.command_general_parse") require("modules.exp_legacy.config.expcore.command_general_parse")
--- Input parse for items by name --- Input parse for items by name
@@ -85,13 +85,15 @@ local function sort_players(players, func)
return sorted return sorted
end end
local display_players_time_format = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true }
--- Display to the player the top players which were found --- Display to the player the top players which were found
local function display_players(player, players, item) local function display_players(player, players, item)
player.print{ "expcom-inv-search.results-heading", item.name } player.print{ "expcom-inv-search.results-heading", item.name }
for index, data in ipairs(players) do for index, data in ipairs(players) do
local player_name_color = format_chat_player_name(data.player) local player_name_color = format_player_name(data.player)
local amount = format_number(data.count) local amount = format_number(data.count)
local time = format_time(data.online_time) local time = display_players_time_format(data.online_time)
player.print{ "expcom-inv-search.results-item", index, player_name_color, amount, time } player.print{ "expcom-inv-search.results-item", index, player_name_color, amount, time }
end end
end end

View File

@@ -3,22 +3,28 @@
@commands Clear Item On Ground @commands Clear Item On Ground
]] ]]
local copy_items_stack = _C.copy_items_stack --- @dep expcore.common local ExpUtil = require("modules/exp_util")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
require("modules.exp_legacy.config.expcore.command_general_parse") require("modules.exp_legacy.config.expcore.command_general_parse")
Commands.new_command("clear-item-on-ground", { "expcom-surface-clearing.description-ci" }, "Clear Item On Ground") Commands.new_command("clear-item-on-ground", { "expcom-surface-clearing.description-ci" }, "Clear Item On Ground")
:add_param("range", false, "integer-range", 1, 1000) :add_param("range", false, "integer-range", 1, 1000)
:register(function(player, range) :register(function(player, range)
for _, e in pairs(player.surface.find_entities_filtered{ position = player.position, radius = range, name = "item-on-ground" }) do local items = {} --- @type LuaItemStack[]
local entities = player.surface.find_entities_filtered{ position = player.position, radius = range, name = "item-on-ground" }
for _, e in pairs(entities) do
if e.stack then if e.stack then
-- calling move_items_stack(e.stack) will crash to desktop items[#items + 1] = e.stack
-- https://forums.factorio.com/viewtopic.php?f=7&t=110322
copy_items_stack{ e.stack }
e.stack.clear()
end end
end end
ExpUtil.move_items_to_surface{
items = items,
surface = player.surface,
allow_creation = true,
name = "iron-chest",
}
return Commands.success return Commands.success
end) end)

View File

@@ -3,9 +3,10 @@
@commands Warnings @commands Warnings
]] ]]
local ExpUtil = require("modules/exp_util")
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local Warnings = require("modules.exp_legacy.modules.control.warnings") --- @dep modules.control.warnings local Warnings = require("modules.exp_legacy.modules.control.warnings") --- @dep modules.control.warnings
local format_chat_player_name = _C.format_chat_player_name --- @dep expcore.common local format_player_name = ExpUtil.format_player_name_locale
local config = require("modules.exp_legacy.config.warnings") --- @dep config.warnings local config = require("modules.exp_legacy.config.warnings") --- @dep config.warnings
require("modules.exp_legacy.config.expcore.command_role_parse") require("modules.exp_legacy.config.expcore.command_role_parse")
@@ -20,8 +21,8 @@ Commands.new_command("give-warning", { "expcom-warnings.description-give" }, "Gi
:enable_auto_concat() :enable_auto_concat()
:register(function(player, action_player, reason) :register(function(player, action_player, reason)
Warnings.add_warning(action_player, player.name, reason) Warnings.add_warning(action_player, player.name, reason)
local action_player_name_color = format_chat_player_name(action_player) local action_player_name_color = format_player_name(action_player)
local by_player_name_color = format_chat_player_name(player) local by_player_name_color = format_player_name(player)
game.print{ "expcom-warnings.received", action_player_name_color, by_player_name_color, reason } game.print{ "expcom-warnings.received", action_player_name_color, by_player_name_color, reason }
end) end)
@@ -35,10 +36,10 @@ Commands.new_command("get-warnings", { "expcom-warnings.description-get" }, "Get
if player then if player then
local warnings = Warnings.get_warnings(player) local warnings = Warnings.get_warnings(player)
local script_warnings = Warnings.get_script_warnings(player) local script_warnings = Warnings.get_script_warnings(player)
local player_name_color = format_chat_player_name(player) local player_name_color = format_player_name(player)
Commands.print{ "expcom-warnings.player", player_name_color, #warnings, #script_warnings, config.temp_warning_limit } Commands.print{ "expcom-warnings.player", player_name_color, #warnings, #script_warnings, config.temp_warning_limit }
for _, warning in ipairs(warnings) do for _, warning in ipairs(warnings) do
Commands.print{ "expcom-warnings.player-detail", format_chat_player_name(warning.by_player_name), warning.reason } Commands.print{ "expcom-warnings.player-detail", format_player_name(warning.by_player_name), warning.reason }
end end
else else
local rtn = {} local rtn = {}
@@ -56,7 +57,7 @@ Commands.new_command("get-warnings", { "expcom-warnings.description-get" }, "Get
Commands.print{ "expcom-warnings.list-title" } Commands.print{ "expcom-warnings.list-title" }
for player_name, warnings in pairs(rtn) do for player_name, warnings in pairs(rtn) do
local player_name_color = format_chat_player_name(player_name) local player_name_color = format_player_name(player_name)
Commands.print{ "expcom-warnings.list", player_name_color, warnings[1], warnings[2], config.temp_warning_limit } Commands.print{ "expcom-warnings.list", player_name_color, warnings[1], warnings[2], config.temp_warning_limit }
end end
end end
@@ -70,7 +71,7 @@ Commands.new_command("clear-warnings", { "expcom-warnings.description-clear" },
:register(function(player, action_player) :register(function(player, action_player)
Warnings.clear_warnings(action_player, player.name) Warnings.clear_warnings(action_player, player.name)
Warnings.clear_script_warnings(action_player) Warnings.clear_script_warnings(action_player)
local action_player_name_color = format_chat_player_name(action_player) local action_player_name_color = format_player_name(action_player)
local by_player_name_color = format_chat_player_name(player) local by_player_name_color = format_player_name(player)
game.print{ "expcom-warnings.cleared", action_player_name_color, by_player_name_color } game.print{ "expcom-warnings.cleared", action_player_name_color, by_player_name_color }
end) end)

View File

@@ -16,10 +16,9 @@
Jail.unjail_player('MrBiter', 'Cooldude2606') Jail.unjail_player('MrBiter', 'Cooldude2606')
]] ]]
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles")
local Game = require("modules.exp_legacy.utils.game") --- @dep utils.game
local valid_player = Game.get_player_from_any local valid_player = function(p) return type(p) == "userdata" and p or game.get_player(p) end
local assign_roles = Roles.assign_player local assign_roles = Roles.assign_player
local unassign_roles = Roles.unassign_player local unassign_roles = Roles.unassign_player
local has_role = Roles.player_has_role local has_role = Roles.player_has_role
@@ -65,7 +64,7 @@ end
-- @tparam LuaPlayer player the player to check if they are in jail -- @tparam LuaPlayer player the player to check if they are in jail
-- @treturn boolean whether the player is currently in jail -- @treturn boolean whether the player is currently in jail
function Jail.is_jailed(player) function Jail.is_jailed(player)
return has_role(player, "Jail") return has_role(valid_player(player), "Jail")
end end
--- Moves a player to jail and removes all other roles --- Moves a player to jail and removes all other roles

View File

@@ -24,10 +24,9 @@
]] ]]
local Game = require("modules.exp_legacy.utils.game") --- @dep utils.game
local Storage = require("modules/exp_util/storage") local Storage = require("modules/exp_util/storage")
local valid_player = Game.get_player_from_any local valid_player = function(p) return type(p) == "userdata" and p or game.get_player(p) end
local Reports = { local Reports = {
user_reports = {}, -- stores all user reports, global table user_reports = {}, -- stores all user reports, global table

View File

@@ -4,10 +4,10 @@
@alias vlayer @alias vlayer
]] ]]
local ExpUtil = require("modules/exp_util")
local Storage = require("modules/exp_util/storage") local Storage = require("modules/exp_util/storage")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local config = require("modules.exp_legacy.config.vlayer") --- @dep config.vlayer local config = require("modules.exp_legacy.config.vlayer") --- @dep config.vlayer
local move_items_stack = _C.move_items_stack
local mega = 1000000 local mega = 1000000
@@ -682,13 +682,25 @@ function vlayer.remove_interface(surface, position)
-- Return the type of interface removed and do some clean up -- Return the type of interface removed and do some clean up
if name == "logistic-chest-storage" then if name == "logistic-chest-storage" then
move_items_stack(interface.get_inventory(defines.inventory.chest).get_contents()) local inventory = assert(interface.get_inventory(defines.inventory.chest))
ExpUtil.transfer_inventory_to_surface{
inventory = inventory,
surface = interface.surface,
name = "iron-chest",
allow_creation = true,
}
table.remove_element(vlayer_data.entity_interfaces.storage_input, interface) table.remove_element(vlayer_data.entity_interfaces.storage_input, interface)
interface.destroy() interface.destroy()
return "storage-input", pos return "storage-input", pos
elseif name == "logistic-chest-requester" then elseif name == "logistic-chest-requester" then
move_items_stack(interface.get_inventory(defines.inventory.chest).get_contents()) local inventory = assert(interface.get_inventory(defines.inventory.chest))
ExpUtil.transfer_inventory_to_surface{
inventory = inventory,
surface = interface.surface,
name = "iron-chest",
allow_creation = true,
}
table.remove_element(vlayer_data.entity_interfaces.storage_output, interface) table.remove_element(vlayer_data.entity_interfaces.storage_output, interface)
interface.destroy() interface.destroy()

View File

@@ -21,12 +21,11 @@
Warnings.clear_warnings('MrBiter', 'Cooldude2606') Warnings.clear_warnings('MrBiter', 'Cooldude2606')
]] ]]
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event")
local Game = require("modules.exp_legacy.utils.game") --- @dep utils.game
local Storage = require("modules/exp_util/storage") local Storage = require("modules/exp_util/storage")
local config = require("modules.exp_legacy.config.warnings") --- @dep config.warnings local config = require("modules.exp_legacy.config.warnings")
local valid_player = Game.get_player_from_any local valid_player = function(p) return type(p) == "userdata" and p or game.get_player(p) end
--- Stores the quickbar filters for a player --- Stores the quickbar filters for a player
local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data

View File

@@ -70,7 +70,7 @@ WrapData:on_update(function(warp_id, warp, old_warp)
end end
-- Sort the warp names in alphabetical order -- Sort the warp names in alphabetical order
local new_warp_ids = table.get_values(table.keysort(warp_names)) local new_warp_ids = table.get_values(table.key_sort(warp_names))
table.insert(new_warp_ids, 1, spawn_id) table.insert(new_warp_ids, 1, spawn_id)
new_warp_ids.spawn = spawn_id new_warp_ids.spawn = spawn_id
force_warps[force_name] = new_warp_ids force_warps[force_name] = new_warp_ids

View File

@@ -40,7 +40,7 @@ PlayerColours:on_load(function(player_name, player_colour)
else else
local colour_name = "white" local colour_name = "white"
while config.disallow[colour_name] do while config.disallow[colour_name] do
colour_name = table.get_random_dictionary_entry(Colours, true) colour_name = table.get_random(Colours, true)
end end
player_colour = { Colours[colour_name], lighten(Colours[colour_name]) } player_colour = { Colours[colour_name], lighten(Colours[colour_name]) }

View File

@@ -1,7 +1,7 @@
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Storage = require("modules/exp_util/storage") --- @dep utils.global local Storage = require("modules/exp_util/storage") --- @dep utils.global
local config = require("modules.exp_legacy.config.statistics") --- @dep config.statistics local config = require("modules.exp_legacy.config.statistics") --- @dep config.statistics
local format_time = _C.format_time
local floor = math.floor local floor = math.floor
local afk_required = 5 * 3600 -- 5 minutes local afk_required = 5 * 3600 -- 5 minutes
@@ -46,25 +46,8 @@ Statistics:on_load(function(player_name, player_statistics)
return player_statistics return player_statistics
end) end)
--- Used to format time in minute format local long_time_format = ExpUtil.format_time_factory_locale{ format = "long", coefficient = 3600, hours = true, minutes = true }
local function format_minutes(value) local short_time_format = ExpUtil.format_time_factory_locale{ format = "short", coefficient = 3600, hours = true, minutes = true }
return format_time(value * 3600, {
long = true,
hours = true,
minutes = true,
})
end
--- Used to format time into a clock
local function format_clock(value)
return format_time(value * 3600, {
hours = true,
minutes = true,
seconds = false,
time = false,
string = true,
})
end
--- Add MapsPlayed if it is enabled --- Add MapsPlayed if it is enabled
if config.MapsPlayed then if config.MapsPlayed then
@@ -80,11 +63,11 @@ if config.Playtime or config.AfkTime then
local playtime, afk_time local playtime, afk_time
if config.Playtime then if config.Playtime then
playtime = Statistics:combine("Playtime") playtime = Statistics:combine("Playtime")
playtime:set_metadata{ stringify = format_minutes, stringify_short = format_clock } playtime:set_metadata{ stringify = long_time_format, stringify_short = short_time_format }
end end
if config.AfkTime then if config.AfkTime then
afk_time = Statistics:combine("AfkTime") afk_time = Statistics:combine("AfkTime")
afk_time:set_metadata{ stringify = format_minutes, stringify_short = format_clock } afk_time:set_metadata{ stringify = long_time_format, stringify_short = short_time_format }
end end
Event.on_nth_tick(3600, function() Event.on_nth_tick(3600, function()
if game.tick == 0 then return end if game.tick == 0 then return end

View File

@@ -6,119 +6,119 @@ local use_silo_script = not config.disable_base_game_silo_script
local util = require("util") local util = require("util")
local silo_script local silo_script
if use_silo_script then if use_silo_script then
silo_script = require("silo-script") silo_script = require("silo-script")
end end
local global = {} local global = {}
Storage.register(global, function(tbl) Storage.register(global, function(tbl)
global = tbl global = tbl
end) end)
local created_items = function() local created_items = function()
return return
{ {
["iron-plate"] = 8, ["iron-plate"] = 8,
["wood"] = 1, ["wood"] = 1,
["pistol"] = 1, ["pistol"] = 1,
["firearm-magazine"] = 10, ["firearm-magazine"] = 10,
["burner-mining-drill"] = 1, ["burner-mining-drill"] = 1,
["stone-furnace"] = 1, ["stone-furnace"] = 1,
} }
end end
local respawn_items = function() local respawn_items = function()
return return
{ {
["pistol"] = 1, ["pistol"] = 1,
["firearm-magazine"] = 10, ["firearm-magazine"] = 10,
} }
end end
if use_silo_script then if use_silo_script then
for k, v in pairs(silo_script.get_events()) do for k, v in pairs(silo_script.get_events()) do
Event.add(k, v) Event.add(k, v)
end end
end end
Event.add(defines.events.on_player_created, function(event) Event.add(defines.events.on_player_created, function(event)
local player = game.players[event.player_index] local player = game.players[event.player_index]
util.insert_safe(player, global.created_items) util.insert_safe(player, global.created_items)
local r = global.chart_distance or 200 local r = global.chart_distance or 200
player.force.chart(player.surface, { { player.position.x - r, player.position.y - r }, { player.position.x + r, player.position.y + r } }) player.force.chart(player.surface, { { player.position.x - r, player.position.y - r }, { player.position.x + r, player.position.y + r } })
if not global.skip_intro then if not global.skip_intro then
if game.is_multiplayer() then if game.is_multiplayer() then
player.print{ "msg-intro" } player.print{ "msg-intro" }
else else
game.show_message_dialog{ text = { "msg-intro" } } game.show_message_dialog{ text = { "msg-intro" } }
end
end end
end
if use_silo_script then if use_silo_script then
silo_script.on_event(event) silo_script.on_event(event)
end end
end) end)
Event.add(defines.events.on_player_respawned, function(event) Event.add(defines.events.on_player_respawned, function(event)
local player = game.players[event.player_index] local player = game.players[event.player_index]
util.insert_safe(player, global.respawn_items) util.insert_safe(player, global.respawn_items)
if use_silo_script then if use_silo_script then
silo_script.on_event(event) silo_script.on_event(event)
end end
end) end)
if use_silo_script then if use_silo_script then
Event.on_load(function() Event.on_load(function()
silo_script.on_load() silo_script.on_load()
end) end)
end end
Event.on_init(function() Event.on_init(function()
global.created_items = created_items() global.created_items = created_items()
global.respawn_items = respawn_items() global.respawn_items = respawn_items()
if use_silo_script then if use_silo_script then
silo_script.on_init() silo_script.on_init()
end end
end) end)
if use_silo_script then if use_silo_script then
silo_script.add_remote_interface() silo_script.add_remote_interface()
silo_script.add_commands() silo_script.add_commands()
end end
remote.add_interface("freeplay", remote.add_interface("freeplay",
{ {
get_created_items = function() get_created_items = function()
return global.created_items return global.created_items
end, end,
set_created_items = function(map) set_created_items = function(map)
global.created_items = map global.created_items = map
end, end,
get_respawn_items = function() get_respawn_items = function()
return global.respawn_items return global.respawn_items
end, end,
set_respawn_items = function(map) set_respawn_items = function(map)
global.respawn_items = map global.respawn_items = map
end, end,
set_skip_intro = function(bool) set_skip_intro = function(bool)
global.skip_intro = bool global.skip_intro = bool
end, end,
set_chart_distance = function(value) set_chart_distance = function(value)
global.chart_distance = tonumber(value) global.chart_distance = tonumber(value)
end, end,
set_disable_crashsite = function() set_disable_crashsite = function()
end, end,
get_ship_items = function() get_ship_items = function()
return {} return {}
end, end,
set_ship_items = function() set_ship_items = function()
return return
end, end,
get_debris_items = function() get_debris_items = function()
return {} return {}
end, end,
set_debris_items = function() set_debris_items = function()
return return
end, end,
}) })

View File

@@ -4,7 +4,7 @@
@alias autofill @alias autofill
]] ]]
local FloatingText = require("modules/exp_util/floating_text") local FlyingText = require("modules/exp_util/flying_text")
local Gui = require("modules.exp_legacy.expcore.gui") -- @dep expcore.gui local Gui = require("modules.exp_legacy.expcore.gui") -- @dep expcore.gui
local Roles = require("modules.exp_legacy.expcore.roles") -- @dep expcore.gui local Roles = require("modules.exp_legacy.expcore.roles") -- @dep expcore.gui
local Storage = require("modules/exp_util/storage") -- @dep utils.global local Storage = require("modules/exp_util/storage") -- @dep utils.global
@@ -12,8 +12,6 @@ local config = require("modules.exp_legacy.config.gui.autofill") -- @dep config.
local Event = require("modules/exp_legacy/utils/event") -- @dep utils.event local Event = require("modules/exp_legacy/utils/event") -- @dep utils.event
local table = require("modules.exp_legacy.overrides.table") -- @dep overrides.table local table = require("modules.exp_legacy.overrides.table") -- @dep overrides.table
local print_text = FloatingText.print -- (surface, position, text, color)
--- Table that stores if autofill is enabled or not --- Table that stores if autofill is enabled or not
local autofill_player_settings = {} local autofill_player_settings = {}
Storage.register(autofill_player_settings, function(tbl) Storage.register(autofill_player_settings, function(tbl)
@@ -324,7 +322,6 @@ local function entity_build(event)
-- Get the inventory of the player -- Get the inventory of the player
local player_inventory = player.get_main_inventory() --- @cast player_inventory -nil local player_inventory = player.get_main_inventory() --- @cast player_inventory -nil
local text_position = { x = entity.position.x, y = entity.position.y }
-- Loop over all possible items to insert into the entity -- Loop over all possible items to insert into the entity
for _, item in pairs(entity_settings.items) do for _, item in pairs(entity_settings.items) do
-- Check if the item is enabled or goto next item -- Check if the item is enabled or goto next item
@@ -338,7 +335,6 @@ local function entity_build(event)
local item_amount = player_inventory.get_item_count(item.name) local item_amount = player_inventory.get_item_count(item.name)
if item_amount ~= 0 then if item_amount ~= 0 then
local inserted local inserted
text_position.y = text_position.y - 0.5
local color = { r = 0, g = 255, b = 0, a = 1 } local color = { r = 0, g = 255, b = 0, a = 1 }
if item_amount >= preferd_amount then if item_amount >= preferd_amount then
-- Can item be inserted? no, goto next item! -- Can item be inserted? no, goto next item!
@@ -351,7 +347,12 @@ local function entity_build(event)
color = { r = 255, g = 165, b = 0, a = 1 } color = { r = 255, g = 165, b = 0, a = 1 }
end end
player_inventory.remove{ name = item.name, count = inserted } player_inventory.remove{ name = item.name, count = inserted }
print_text(entity.surface, text_position, { "autofill.inserted", inserted, rich_img("item", item.name), rich_img("entity", entity.name) }, color) FlyingText.create_above_entity{
target_entity = entity,
text = { "autofill.inserted", inserted, rich_img("item", item.name), rich_img("entity", entity.name) },
player = player,
color = color,
}
end end
::end_item:: ::end_item::
end end

View File

@@ -23,7 +23,7 @@ function Public.show(container)
local left_panel_style = left_panel.style local left_panel_style = left_panel.style
left_panel_style.width = 300 left_panel_style.width = 300
for name in pairs(table.keysort(Datastore.debug())) do for name in pairs(table.key_sort(Datastore.debug())) do
local header = left_panel.add{ type = "flow" }.add{ type = "label", name = header_name, caption = name } local header = left_panel.add{ type = "flow" }.add{ type = "label", name = header_name, caption = name }
Gui.set_data(header, name) Gui.set_data(header, name)
end end
@@ -69,7 +69,7 @@ Gui.on_click(
header_name, header_name,
function(event) function(event)
local element = event.element local element = event.element
local tableName = Gui.get_data(element) local table_name = Gui.get_data(element)
local left_panel = element.parent.parent local left_panel = element.parent.parent
local data = Gui.get_data(left_panel) local data = Gui.get_data(left_panel)
@@ -84,10 +84,10 @@ Gui.on_click(
element.style.font_color = Color.orange element.style.font_color = Color.orange
data.selected_header = element data.selected_header = element
input_text_box.text = tableName input_text_box.text = table_name
input_text_box.style.font_color = Color.black input_text_box.style.font_color = Color.black
local content = Datastore.debug(tableName) local content = Datastore.debug(table_name)
local content_string = {} local content_string = {}
for key, value in pairs(content) do for key, value in pairs(content) do
content_string[#content_string + 1] = key:gsub("^%l", string.upper) .. " = " .. dump(value) content_string[#content_string + 1] = key:gsub("^%l", string.upper) .. " = " .. dump(value)

View File

@@ -5,13 +5,12 @@
]] ]]
-- luacheck:ignore 211/Colors -- luacheck:ignore 211/Colors
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local Datastore = require("modules.exp_legacy.expcore.datastore") --- @dep expcore.datastore local Datastore = require("modules.exp_legacy.expcore.datastore") --- @dep expcore.datastore
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local config = require("modules.exp_legacy.config.gui.player_list_actions") --- @dep config.gui.player_list_actions local config = require("modules.exp_legacy.config.gui.player_list_actions") --- @dep config.gui.player_list_actions
local Colors = require("modules/exp_util/include/color")
local format_time = _C.format_time --- @dep expcore.common
--- Stores all data for the warp gui --- Stores all data for the warp gui
local PlayerListData = Datastore.connect("PlayerListData") local PlayerListData = Datastore.connect("PlayerListData")
@@ -261,12 +260,15 @@ Gui.left_toolbar_button("entity/character", { "player-list.main-tooltip" }, play
return Roles.player_allowed(player, "gui/player-list") return Roles.player_allowed(player, "gui/player-list")
end) end)
local online_time_format = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true }
local afk_time_format = ExpUtil.format_time_factory_locale{ format = "long", minutes = true }
-- Get caption and tooltip format for a player -- Get caption and tooltip format for a player
local function get_time_formats(online_time, afk_time) local function get_time_formats(online_time, afk_time)
local tick = game.tick > 0 and game.tick or 1 local tick = game.tick > 0 and game.tick or 1
local percent = math.round(online_time / tick, 3) * 100 local percent = math.round(online_time / tick, 3) * 100
local caption = format_time(online_time) local caption = online_time_format(online_time)
local tooltip = { "player-list.afk-time", percent, format_time(afk_time, { minutes = true, long = true }) } local tooltip = { "player-list.afk-time", percent, afk_time_format(afk_time) }
return caption, tooltip return caption, tooltip
end end
@@ -333,7 +335,7 @@ local function get_player_list_order()
index=0-i, index=0-i,
tag='', tag='',
role_name = 'Fake Player', role_name = 'Fake Player',
chat_color = table.get_random_dictionary_entry(Colors), chat_color = table.get_random(Colors),
caption = caption, caption = caption,
tooltip = tooltip tooltip = tooltip
} }

View File

@@ -1,12 +1,12 @@
---- module pd ---- module pd
-- @gui PlayerData -- @gui PlayerData
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
require("modules.exp_legacy.modules.data.statistics") require("modules.exp_legacy.modules.data.statistics")
local format_time = _C.format_time --- @dep expcore.common
local format_number = require("util").format_number --- @dep util local format_number = require("util").format_number --- @dep util
local pd_container local pd_container
@@ -16,66 +16,60 @@ local label_width = {
["total"] = 480, ["total"] = 480,
} }
local function format_time_short(value) local short_time_format = ExpUtil.format_time_factory_locale{ format = "short", coefficient = 3600, hours = true, minutes = true }
return format_time(value * 3600, {
hours = true,
minutes = true,
seconds = false,
})
end
local function format_number_n(n) local function format_number_n(n)
return format_number(math.floor(n)) .. string.format("%.2f", n % 1):sub(2) return format_number(math.floor(n)) .. string.format("%.2f", n % 1):sub(2)
end end
local playerStats = PlayerData.Statistics local PlayerStats = PlayerData.Statistics
local computed_stats = { local computed_stats = {
DamageDeathRatio = { DamageDeathRatio = {
default = format_number_n(0), default = format_number_n(0),
calculate = function(player_name) calculate = function(player_name)
return format_number_n(playerStats["DamageDealt"]:get(player_name, 0) / playerStats["Deaths"]:get(player_name, 1)) return format_number_n(PlayerStats["DamageDealt"]:get(player_name, 0) / PlayerStats["Deaths"]:get(player_name, 1))
end, end,
}, },
KillDeathRatio = { KillDeathRatio = {
default = format_number_n(0), default = format_number_n(0),
calculate = function(player_name) calculate = function(player_name)
return format_number_n(playerStats["Kills"]:get(player_name, 0) / playerStats["Deaths"]:get(player_name, 1)) return format_number_n(PlayerStats["Kills"]:get(player_name, 0) / PlayerStats["Deaths"]:get(player_name, 1))
end, end,
}, },
SessionTime = { SessionTime = {
default = format_time_short(0), default = short_time_format(0),
calculate = function(player_name) calculate = function(player_name)
return format_time_short((playerStats["Playtime"]:get(player_name, 0) - playerStats["AfkTime"]:get(player_name, 0)) / playerStats["JoinCount"]:get(player_name, 1)) return short_time_format((PlayerStats["Playtime"]:get(player_name, 0) - PlayerStats["AfkTime"]:get(player_name, 0)) / PlayerStats["JoinCount"]:get(player_name, 1))
end, end,
}, },
BuildRatio = { BuildRatio = {
default = format_number_n(0), default = format_number_n(0),
calculate = function(player_name) calculate = function(player_name)
return format_number_n(playerStats["MachinesBuilt"]:get(player_name, 0) / playerStats["MachinesRemoved"]:get(player_name, 1)) return format_number_n(PlayerStats["MachinesBuilt"]:get(player_name, 0) / PlayerStats["MachinesRemoved"]:get(player_name, 1))
end, end,
}, },
RocketPerHour = { RocketPerHour = {
default = format_number_n(0), default = format_number_n(0),
calculate = function(player_name) calculate = function(player_name)
return format_number_n(playerStats["RocketsLaunched"]:get(player_name, 0) * 60 / playerStats["Playtime"]:get(player_name, 1)) return format_number_n(PlayerStats["RocketsLaunched"]:get(player_name, 0) * 60 / PlayerStats["Playtime"]:get(player_name, 1))
end, end,
}, },
TreeKillPerMinute = { TreeKillPerMinute = {
default = format_number_n(0), default = format_number_n(0),
calculate = function(player_name) calculate = function(player_name)
return format_number_n(playerStats["TreesDestroyed"]:get(player_name, 0) / playerStats["Playtime"]:get(player_name, 1)) return format_number_n(PlayerStats["TreesDestroyed"]:get(player_name, 0) / PlayerStats["Playtime"]:get(player_name, 1))
end, end,
}, },
NetPlayTime = { NetPlayTime = {
default = format_time_short(0), default = short_time_format(0),
calculate = function(player_name) calculate = function(player_name)
return format_time_short((playerStats["Playtime"]:get(player_name, 0) - playerStats["AfkTime"]:get(player_name, 0))) return short_time_format((PlayerStats["Playtime"]:get(player_name, 0) - PlayerStats["AfkTime"]:get(player_name, 0)))
end, end,
}, },
AFKTimeRatio = { AFKTimeRatio = {
default = format_number_n(0), default = format_number_n(0),
calculate = function(player_name) calculate = function(player_name)
return format_number_n(playerStats["AfkTime"]:get(player_name, 0) * 100 / playerStats["Playtime"]:get(player_name, 1)) return format_number_n(PlayerStats["AfkTime"]:get(player_name, 0) * 100 / PlayerStats["Playtime"]:get(player_name, 1))
end, end,
}, },
} }

View File

@@ -4,13 +4,13 @@
@alias readme @alias readme
]] ]]
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore.commands
local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
local External = require("modules.exp_legacy.expcore.external") --- @dep expcore.external local External = require("modules.exp_legacy.expcore.external") --- @dep expcore.external
local format_time = _C.format_time --- @dep expcore.common
local format_number = require("util").format_number --- @dep util local format_number = require("util").format_number --- @dep util
local tabs = {} local tabs = {}
@@ -109,6 +109,8 @@ local join_server =
External.request_connection(player, server_id, true) External.request_connection(player, server_id, true)
end) end)
local welcome_time_format = ExpUtil.format_time_factory_locale{ format = "long", days = true, hours = true, minutes = true }
--- Content area for the welcome tab --- Content area for the welcome tab
-- @element welcome_content -- @element welcome_content
define_tab({ "readme.welcome-tab" }, { "readme.welcome-tooltip" }, define_tab({ "readme.welcome-tab" }, { "readme.welcome-tooltip" },
@@ -139,7 +141,7 @@ define_tab({ "readme.welcome-tab" }, { "readme.welcome-tooltip" },
-- Add the other information to the gui -- Add the other information to the gui
container.add{ type = "flow" }.style.height = 4 container.add{ type = "flow" }.style.height = 4
local online_time = format_time(game.tick, { days = true, hours = true, minutes = true, long = true }) local online_time = welcome_time_format(game.tick)
Gui.centered_label(sub_content(container), frame_width, { "readme.welcome-general", server_details.reset_time, online_time }) Gui.centered_label(sub_content(container), frame_width, { "readme.welcome-general", server_details.reset_time, online_time })
Gui.centered_label(sub_content(container), frame_width, { "readme.welcome-roles", table.concat(role_names, ", ") }) Gui.centered_label(sub_content(container), frame_width, { "readme.welcome-roles", table.concat(role_names, ", ") })
Gui.centered_label(sub_content(container), frame_width, { "readme.welcome-chat" }) Gui.centered_label(sub_content(container), frame_width, { "readme.welcome-chat" })

View File

@@ -1,12 +1,12 @@
--- research gui --- research gui
-- @gui Research -- @gui Research
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
local Storage = require("modules/exp_util/storage") local Storage = require("modules/exp_util/storage")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local config = require("modules.exp_legacy.config.research") --- @dep config.research local config = require("modules.exp_legacy.config.research") --- @dep config.research
local format_time = _C.format_time --- @dep expcore.common
local research = {} local research = {}
Storage.register(research, function(tbl) Storage.register(research, function(tbl)
@@ -16,22 +16,8 @@ end)
research.time = {} research.time = {}
research.res_queue_enable = false research.res_queue_enable = false
local research_time_format = { local research_time_format = ExpUtil.format_time_factory{ format = "clock", hours = true, minutes = true, seconds = true }
hours = true, local empty_time = research_time_format(nil)
minutes = true,
seconds = true,
time = true,
string = true,
}
local empty_time = format_time(0, {
hours = true,
minutes = true,
seconds = true,
time = true,
string = true,
null = true,
})
local font_color = { local font_color = {
-- positive -- positive
@@ -57,7 +43,7 @@ do
res["disp"][i] = { res["disp"][i] = {
raw_name = k, raw_name = k,
target = res_total, target = res_total,
target_disp = format_time(res_total, research_time_format), target_disp = research_time_format(res_total),
} }
i = i + 1 i = i + 1
@@ -118,12 +104,12 @@ local function research_notification(event)
end end
else else
if not (event.by_script) then if not (event.by_script) then
game.print{ "expcom-res.inf", format_time(game.tick, research_time_format), event.research.name, event.research.level - 1 } game.print{ "expcom-res.inf", research_time_format(game.tick), event.research.name, event.research.level - 1 }
end end
end end
else else
if not (event.by_script) then if not (event.by_script) then
game.print{ "expcom-res.msg", format_time(game.tick, research_time_format), event.research.name } game.print{ "expcom-res.msg", research_time_format(game.tick), event.research.name }
end end
if config.bonus_inventory.enabled then if config.bonus_inventory.enabled then
@@ -159,13 +145,13 @@ local function research_gui_update()
res_disp[i]["difference_color"] = font_color[1] res_disp[i]["difference_color"] = font_color[1]
else else
res_disp[i]["target"] = res["disp"][res_i].target_disp res_disp[i]["target"] = res["disp"][res_i].target_disp
res_disp[i]["attempt"] = format_time(research.time[res_i], research_time_format) res_disp[i]["attempt"] = research_time_format(research.time[res_i])
if research.time[res_i] < res["disp"][res_i].target then if research.time[res_i] < res["disp"][res_i].target then
res_disp[i]["difference"] = "-" .. format_time(res["disp"][res_i].target - research.time[res_i], research_time_format) res_disp[i]["difference"] = "-" .. research_time_format(res["disp"][res_i].target - research.time[res_i])
res_disp[i]["difference_color"] = font_color[1] res_disp[i]["difference_color"] = font_color[1]
else else
res_disp[i]["difference"] = format_time(research.time[res_i] - res["disp"][res_i].target, research_time_format) res_disp[i]["difference"] = research_time_format(research.time[res_i] - res["disp"][res_i].target)
res_disp[i]["difference_color"] = font_color[2] res_disp[i]["difference_color"] = font_color[2]
end end
end end
@@ -313,7 +299,7 @@ Event.add(defines.events.on_research_finished, function(event)
end) end)
Event.on_nth_tick(60, function() Event.on_nth_tick(60, function()
local current_time = format_time(game.tick, research_time_format) local current_time = research_time_format(game.tick)
for _, player in pairs(game.connected_players) do for _, player in pairs(game.connected_players) do
local frame = Gui.get_left_element(player, research_container) local frame = Gui.get_left_element(player, research_container)

View File

@@ -4,19 +4,19 @@
@alias rocket_info @alias rocket_info
]] ]]
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local config = require("modules.exp_legacy.config.gui.rockets") --- @dep config.gui.rockets local config = require("modules.exp_legacy.config.gui.rockets") --- @dep config.gui.rockets
local Colors = require("modules/exp_util/include/color") local Colors = require("modules/exp_util/include/color")
local Rockets = require("modules.exp_legacy.modules.control.rockets") --- @dep modules.control.rockets local Rockets = require("modules.exp_legacy.modules.control.rockets") --- @dep modules.control.rockets
local format_time = _C.format_time --- @dep expcore.common
local time_formats = { local time_formats = {
caption = function(value) return format_time(value, { minutes = true, seconds = true }) end, caption = ExpUtil.format_time_factory_locale{ format = "short", minutes = true, seconds = true },
caption_hours = function(value) return format_time(value) end, caption_hours = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true },
tooltip = function(value) return format_time(value, { minutes = true, seconds = true, long = true }) end, tooltip = ExpUtil.format_time_factory_locale{ format = "long", minutes = true, seconds = true },
tooltip_hours = function(value) return format_time(value, { hours = true, minutes = true, seconds = true, long = true }) end, tooltip_hours = ExpUtil.format_time_factory_locale{ format = "long", hours = true, minutes = true, seconds = true },
} }
--- Check if a player is allowed to use certain interactions --- Check if a player is allowed to use certain interactions

View File

@@ -4,15 +4,18 @@
@alias science_info @alias science_info
]] ]]
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.gui local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.gui
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local config = require("modules.exp_legacy.config.gui.science") --- @dep config.gui.science local config = require("modules.exp_legacy.config.gui.science") --- @dep config.gui.science
local Production = require("modules.exp_legacy.modules.control.production") --- @dep modules.control.production local Production = require("modules.exp_legacy.modules.control.production") --- @dep modules.control.production
local format_time = _C.format_time --- @dep expcore.common
local null_time_short = { "science-info.eta-time", format_time(0, { hours = true, minutes = true, seconds = true, time = true, null = true }) } local clock_time_format = ExpUtil.format_time_factory_locale{ format = "clock", hours = true, minutes = true, seconds = true }
local null_time_long = format_time(0, { hours = true, minutes = true, seconds = true, long = true, null = true }) local long_time_format = ExpUtil.format_time_factory_locale{ format = "long", hours = true, minutes = true, seconds = true }
local null_time_clock = { "science-info.eta-time", clock_time_format(nil) }
local null_time_long = long_time_format(nil)
--- Data label that contains the value and the surfix --- Data label that contains the value and the surfix
-- @element production_label -- @element production_label
@@ -235,16 +238,18 @@ local function get_eta_label_data(player)
-- Return the caption and tooltip -- Return the caption and tooltip
return limit and limit > 0 and { return limit and limit > 0 and {
research = true, research = true,
caption = format_time(limit, { hours = true, minutes = true, seconds = true, time = true }), caption = clock_time_format(limit),
tooltip = format_time(limit, { hours = true, minutes = true, seconds = true, long = true }), tooltip = long_time_format(limit),
} or { research = false } } or {
research = false
}
end end
-- Updates the eta label -- Updates the eta label
local function update_eta_label(element, eta_label_data) local function update_eta_label(element, eta_label_data)
-- If no research selected show null -- If no research selected show null
if not eta_label_data.research then if not eta_label_data.research then
element.caption = null_time_short element.caption = null_time_clock
element.tooltip = null_time_long element.tooltip = null_time_long
return return
end end
@@ -293,7 +298,7 @@ local science_info_container =
footer.add{ footer.add{
name = "label", name = "label",
type = "label", type = "label",
caption = null_time_short, caption = null_time_clock,
tooltip = null_time_long, tooltip = null_time_long,
style = "frame_title", style = "frame_title",
} }

View File

@@ -3,13 +3,16 @@
@gui Task-List @gui Task-List
@alias task_list @alias task_list
]] ]]
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local Datastore = require("modules.exp_legacy.expcore.datastore") --- @dep expcore.datastore local Datastore = require("modules.exp_legacy.expcore.datastore") --- @dep expcore.datastore
local config = require("modules.exp_legacy.config.gui.tasks") --- @dep config.gui.tasks local config = require("modules.exp_legacy.config.gui.tasks") --- @dep config.gui.tasks
local Tasks = require("modules.exp_legacy.modules.control.tasks") --- @dep modules.control.tasks local Tasks = require("modules.exp_legacy.modules.control.tasks") --- @dep modules.control.tasks
local format_time = _C.format_time --- @dep expcore.common
local format_time = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true }
--- Stores all data for the task gui by player --- Stores all data for the task gui by player
local TaskGuiData = Datastore.connect("TaskGuiData") local TaskGuiData = Datastore.connect("TaskGuiData")

View File

@@ -4,6 +4,7 @@
@alias warp_list @alias warp_list
]] ]]
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
local Datastore = require("modules.exp_legacy.expcore.datastore") --- @dep expcore.datastore local Datastore = require("modules.exp_legacy.expcore.datastore") --- @dep expcore.datastore
local Storage = require("modules/exp_util/storage") local Storage = require("modules/exp_util/storage")
@@ -12,7 +13,8 @@ local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
local Colors = require("modules/exp_util/include/color") local Colors = require("modules/exp_util/include/color")
local config = require("modules.exp_legacy.config.gui.warps") --- @dep config.gui.warps local config = require("modules.exp_legacy.config.gui.warps") --- @dep config.gui.warps
local Warps = require("modules.exp_legacy.modules.control.warps") --- @dep modules.control.warps local Warps = require("modules.exp_legacy.modules.control.warps") --- @dep modules.control.warps
local format_time, player_return = _C.format_time, _C.player_return --- @dep expcore.common
local format_time = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true }
--- Stores all data for the warp gui --- Stores all data for the warp gui
local WrapGuiData = Datastore.connect("WrapGuiData") local WrapGuiData = Datastore.connect("WrapGuiData")
@@ -94,7 +96,10 @@ local add_new_warp =
-- Check if the warp is too close to water -- Check if the warp is too close to water
local water_tiles = surface.find_tiles_filtered{ collision_mask = "water-tile", radius = config.standard_proximity_radius + 1, position = position } local water_tiles = surface.find_tiles_filtered{ collision_mask = "water-tile", radius = config.standard_proximity_radius + 1, position = position }
if #water_tiles > 0 then if #water_tiles > 0 then
player_return({ "expcore-commands.command-fail", { "warp-list.too-close-to-water", config.standard_proximity_radius + 1 } }, "orange_red", player) player.print(
{ "expcore-commands.command-fail", { "warp-list.too-close-to-water", config.standard_proximity_radius + 1 } },
{ color = Colors.orange_red }
)
if game.player then game.player.play_sound{ path = "utility/wire_pickup" } end if game.player then game.player.play_sound{ path = "utility/wire_pickup" } end
for _, tile in pairs(water_tiles) do for _, tile in pairs(water_tiles) do
rendering.draw_sprite{ rendering.draw_sprite{
@@ -121,7 +126,10 @@ local add_new_warp =
} }
-- Remove 1 because that is the current player -- Remove 1 because that is the current player
if #entities > 1 then if #entities > 1 then
player_return({ "expcore-commands.command-fail", { "warp-list.too-close-to-entities", config.standard_proximity_radius + 2.5 } }, "orange_red", player) player.print(
{ "expcore-commands.command-fail", { "warp-list.too-close-to-entities", config.standard_proximity_radius + 2.5 } },
{ color = Colors.orange_red }
)
if game.player then game.player.play_sound{ path = "utility/wire_pickup" } end if game.player then game.player.play_sound{ path = "utility/wire_pickup" } end
local character = player.character local character = player.character
for _, entity in pairs(entities) do for _, entity in pairs(entities) do

View File

@@ -1,448 +0,0 @@
---@diagnostic disable: duplicate-set-field
-- luacheck:ignore global table
local random = math.random
local floor = math.floor
local remove = table.remove
local tonumber = tonumber
local pairs = pairs
local table_size = table_size
--- Searches a table to remove a specific element without an index
-- @param t <table> to search
-- @param <any> table element to search for
function table.remove_element(t, element)
for k, v in pairs(t) do
if v == element then
remove(t, k)
break
end
end
end
--- Removes an item from an array in O(1) time.
-- 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.remove_index(tbl, index)
local count = #tbl
if index > count then
return
elseif index < count then
tbl[index] = tbl[count]
end
tbl[count] = nil
end
--- Adds the contents of table t2 to table t1
-- @param t1 <table> to insert into
-- @param t2 <table> to insert from
function table.merge_table(t1, t2)
for k, v in pairs(t2) do
if tonumber(k) then
t1[#t1 + 1] = v
else
t1[k] = v
end
end
end
--[[-- Much faster method for inserting items into an array
@tparam table tbl the table that will have the values added to it
@tparam[opt] number start_index the index at which values will be added, nil means end of the array
@tparam table values the new values that will be added to the table
@treturn table the table that was passed as the first argument
@usage-- Adding 1000 values into the middle of the array
local tbl = {}
local values = {}
for i = 1, 1000 do tbl[i] = i values[i] = i end
table.array_insert(tbl, 500, values) -- around 0.4ms
]]
function table.array_insert(tbl, start_index, values)
if not values then
values = start_index
start_index = nil
end
if start_index then
local starting_length = #tbl
local adding_length = #values
local move_to = start_index + adding_length + 1
for offset = starting_length - start_index, 0, -1 do
tbl[move_to + offset] = tbl[starting_length + offset]
end
start_index = start_index - 1
else
start_index = #tbl
end
for offset, item in ipairs(values) do
tbl[start_index + offset] = item
end
return tbl
end
--[[-- Much faster method for inserting keys into a table
@tparam table tbl the table that will have keys added to it
@tparam[opt] number start_index the index at which values will be added, nil means end of the array, numbered indexs only
@tparam table tbl2 the table that may contain both string and numbered keys
@treturn table the table passed as the first argument
@usage-- Merging two tables
local tbl = {}
local tbl2 = {}
for i = 1, 100 do tbl[i] = i tbl['_'..i] = i tbl2[i] = i tbl2['__'..i] = i end
table.table_insert(tbl, 50, tbl2)
]]
function table.table_insert(tbl, start_index, tbl2)
if not tbl2 then
tbl2 = start_index
start_index = nil
end
table.array_insert(tbl, start_index, tbl2)
for key, value in pairs(tbl2) do
if not tonumber(key) then
tbl[key] = value
end
end
return tbl
end
--- Checks if a table contains an element
-- @param t <table>
-- @param e <any> table element
-- @return <any> the index of the element or nil
function table.get_key(t, e)
for k, v in pairs(t) do
if v == e then
return k
end
end
return nil
end
--- Checks if the arrayed portion of a table contains an element
-- @param t <table>
-- @param e <any> table element
-- @return <number|nil> the index of the element or nil
function table.get_index(t, e)
for i = 1, #t do
if t[i] == e then
return i
end
end
return nil
end
--- 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 table.get_key(t, e) and true or false
end
--- 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 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 table.unpack(values)
end
--- Adds an element into a specific index position while shuffling the rest down
-- @param t <table> to add into
-- @param index <number> the position in the table to add to
-- @param element <any> to add to the table
function table.set(t, index, element)
local i = 1
for k in pairs(t) do
if i == index then
t[k] = element
return nil
end
i = i + 1
end
error("Index out of bounds", 2)
end
--- Chooses a random entry from a table
-- because this uses math.random, it cannot be used outside of events
-- @param t <table>
-- @param key <boolean> to indicate whether to return the key or value
-- @return <any> a random element of table t
function table.get_random_dictionary_entry(t, key)
local target_index = random(1, table_size(t))
local count = 1
for k, v in pairs(t) do
if target_index == count then
if key then
return k
else
return v
end
end
count = count + 1
end
end
--- Chooses a random entry from a weighted table
-- because this uses math.random, it cannot be used outside of events
-- @param weighted_table <table> of tables with items and their weights
-- @param item_index <number> of the index of items, defaults to 1
-- @param weight_index <number> of the index of the weights, defaults to 2
-- @return <any> table element
function table.get_random_weighted(weighted_table, item_index, weight_index)
local total_weight = 0
item_index = item_index or 1
weight_index = weight_index or 2
for _, w in pairs(weighted_table) do
total_weight = total_weight + w[weight_index]
end
local index = random() * total_weight
local weight_sum = 0
for _, w in pairs(weighted_table) do
weight_sum = weight_sum + w[weight_index]
if weight_sum >= index then
return w[item_index]
end
end
end
--- Clears all existing entries in a table
-- @param t <table> to clear
-- @param array <boolean> to indicate whether the table is an array or not
function table.clear_table(t, array)
if array then
for i = 1, #t do
t[i] = nil
end
else
for i in pairs(t) do
t[i] = nil
end
end
end
--- Creates a fisher-yates shuffle of a sequential number-indexed table
-- 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
-- @param t <table> to shuffle
-- @param rng <function> to provide random numbers
function table.shuffle_table(t, rng)
local rand = rng or math.random
local iterations = #t
if iterations == 0 then
error("Not a sequential table")
return
end
local j
for i = iterations, 2, -1 do
j = rand(i)
t[i], t[j] = t[j], t[i]
end
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 sort_func(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 _, v in pairs(tbl) do
n = n + 1
valueset[n] = v
end
end
if sorted then
table.sort(valueset, sort_func)
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, sort_func)
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
--[[
Returns the index where t[index] == target.
If there is no such index, returns a negative value such that bit32.bnot(value) is
the index that the value should be inserted to keep the list ordered.
t must be a list in ascending order for the return value to be valid.
Usage example:
local t = {1, 3,5, 7,9}
local x = 5
local index = table.binary_search(t, x)
if index < 0 then
game.print("value not found, smallest index where t[index] > x is: " .. bit32.bnot(index))
else
game.print("value found at index: " .. index)
end
]]
function table.binary_search(t, target)
-- For some reason bit32.bnot doesn't return negative numbers so I'm using ~x = -1 - x instead.
local lower = 1
local upper = #t
if upper == 0 then
return -2 -- ~1
end
repeat
local mid = floor((lower + upper) * 0.5)
local value = t[mid]
if value == target then
return mid
elseif value < target then
lower = mid + 1
else
upper = mid - 1
end
until lower > upper
return -1 - lower -- ~lower
end
-- add table-related functions that exist in base factorio/util to the 'table' table
require("util")
--- Similar to serpent.block, returns a string with a pretty representation of a table.
-- Notice: This method is not appropriate for saving/restoring tables. It is meant to be used by the programmer mainly while debugging a program.
-- @param table <table> the table to serialize
-- @param options <table> options are depth, newline, indent, process
-- depth sets the maximum depth that will be printed out. When the max depth is reached, inspect will stop parsing tables and just return {...}
-- 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("modules/exp_util/include/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
--- Creates a deepcopy of a table. Metatables and LuaObjects inside the table are shallow copies.
-- Shallow copies meaning it copies the reference to the object instead of the object itself.
-- @param object <table> the object to copy
-- @return <table> the copied object
table.deep_copy = table.deepcopy
--- Merges multiple tables. Tables later in the list will overwrite entries from tables earlier in the list.
-- Ex. merge({{1, 2, 3}, {[2] = 0}, {[3] = 0}}) will return {1, 0, 0}
-- @param tables <table> takes a table of tables to merge
-- @return <table> a merged table
table.merge = util.merge
--- Determines if two tables are structurally equal.
-- Notice: tables that are LuaObjects or contain LuaObjects won't be compared correctly, use == operator for LuaObjects
-- @param tbl1 <table>
-- @param tbl2 <table>
-- @return <boolean>
table.equals = table.compare
return table

View File

@@ -1,5 +0,0 @@
return {
expgaming_lua = "6.2.0",
expgaming_api = "2.0.0",
redmew_lua = "2019-02-24-76871ee",
}

View File

@@ -1,40 +0,0 @@
local Color = require("modules/exp_util/include/color")
local Game = {}
--[[ Note to readers
Game.get_player_from_name was removed because game.players[name] works without any edge cases
always true: game.players[name].name == name
Game.get_player_by_index was added originally as a workaround for the following edge case:
player with index of 5 and name of "Cooldude2606"
player with index of 10 and name of "5"
game.players[5].name == "5"
Discovered the following logic:
all keys are first converted to string and search against player names
if this fails it attempts to convert it to a number and search against player indexes
sometimes fails: game.players[index].index == index
Game.get_player_by_index was removed after the above logic was corrected to the following:
when a key is a number it is searched against player indexes, and only their indexes
when a key is a string it is searched against player names, and then against their indexes
always true: game.players[name].name == name; game.players[index].index == index
]]
--- Returns a valid LuaPlayer if given a number, string, or LuaPlayer. Returns nil otherwise.
-- obj <number|string|LuaPlayer>
function Game.get_player_from_any(obj)
local o_type, p = type(obj)
if o_type == "table" then
p = obj
elseif o_type == "string" or o_type == "number" then
p = game.players[obj]
end
if p and p.valid and p.is_player() then
return p
end
end
return Game

View File

@@ -1,7 +1,5 @@
--[[-- Util Module - Common --[[-- Util Module - Common
- Adds some commonly used functions used in many modules Adds some commonly used functions used in many modules
@core Common
@alias Common
]] ]]
local assert = assert local assert = assert
@@ -35,6 +33,10 @@ end]]
--- Check the type of a value, also considers LuaObject.object_name and metatable.__class --- Check the type of a value, also considers LuaObject.object_name and metatable.__class
--- Returns true when the check failed and an error should be raised --- Returns true when the check failed and an error should be raised
--- @param value any The value to check the type of
--- @param type_name string The type name the value should be
--- @return boolean failed True if the check failed and an error should be raised
--- @return string actual_type The actual type of the value
local function check_type(value, type_name) local function check_type(value, type_name)
local value_type = type(value) --[[@as string]] local value_type = type(value) --[[@as string]]
if value_type == "userdata" then if value_type == "userdata" then
@@ -56,9 +58,9 @@ end
local assert_type_fmt = "%s expected to be of type %s but got %s" local assert_type_fmt = "%s expected to be of type %s but got %s"
--- Raise an error if the type of a value is not as expected --- Raise an error if the type of a value is not as expected
-- @param value The value to assert the type of --- @param value any The value to assert the type of
-- @tparam string type_name The name of the type that value is expected to be --- @param type_name string The name of the type that value is expected to be
-- @tparam[opt=Value] string value_name The name of the value being tested, this is included in the error message --- @param value_name string? The name of the value being tested, this is included in the error message
function Common.assert_type(value, type_name, value_name) function Common.assert_type(value, type_name, value_name)
local failed, actual_type = check_type(value, type_name) local failed, actual_type = check_type(value, type_name)
if failed then if failed then
@@ -68,10 +70,10 @@ end
local assert_argument_fmt = "Bad argument #%d to %s; %s expected to be of type %s but got %s" local assert_argument_fmt = "Bad argument #%d to %s; %s expected to be of type %s but got %s"
--- Raise an error if the type of any argument is not as expected, more performant than assert_argument_types, but requires more manual input --- Raise an error if the type of any argument is not as expected, more performant than assert_argument_types, but requires more manual input
-- @param arg_value The argument to assert the type of --- @param arg_value any The argument to assert the type of
-- @tparam string type_name The name of the type that value is expected to be --- @param type_name string The name of the type that value is expected to be
-- @tparam number arg_index The index of the argument being tested, this is included in the error message --- @param arg_index number The index of the argument being tested, this is included in the error message
-- @tparam[opt=Argument] string arg_name The name of the argument being tested, this is included in the error message --- @param arg_name string? The name of the argument being tested, this is included in the error message
function Common.assert_argument_type(arg_value, type_name, arg_index, arg_name) function Common.assert_argument_type(arg_value, type_name, arg_index, arg_name)
local failed, actual_type = check_type(arg_value, type_name) local failed, actual_type = check_type(arg_value, type_name)
if failed then if failed then
@@ -81,10 +83,11 @@ function Common.assert_argument_type(arg_value, type_name, arg_index, arg_name)
end end
--- Write a luu table to a file as a json string, note the defaults are different to game.write_file --- Write a luu table to a file as a json string, note the defaults are different to game.write_file
-- @tparam string path The path to write the json to --- @param path string The path to write the json to
-- @tparam table value The table to write to file --- @param tbl table The table to write to file
-- @tparam[opt=false] boolean overwrite When true the json replaces the full contents of the file --- @param overwrite boolean? When true the json replaces the full contents of the file
-- @tparam[opt=0] number player_index The player's machine to write on, -1 means all, 0 means host only --- @param player_index number? The player's machine to write on, -1 means all, 0 is default means host only
--- @return nil
function Common.write_json(path, tbl, overwrite, player_index) function Common.write_json(path, tbl, overwrite, player_index)
if player_index == -1 then if player_index == -1 then
return game.write_file(path, game.table_to_json(tbl) .. "\n", not overwrite) return game.write_file(path, game.table_to_json(tbl) .. "\n", not overwrite)
@@ -93,8 +96,9 @@ function Common.write_json(path, tbl, overwrite, player_index)
end end
--- Clear a file by replacing its contents with an empty string --- Clear a file by replacing its contents with an empty string
-- @tparam string path The path to clear the contents of --- @param path string The path to clear the contents of
-- @tparam[opt=0] number player_index The player's machine to write on, -1 means all, 0 means host only --- @param player_index number? The player's machine to write on, -1 means all, 0 is default and means host only
--- @return nil
function Common.clear_file(path, player_index) function Common.clear_file(path, player_index)
if player_index == -1 then if player_index == -1 then
return game.write_file(path, "", false) return game.write_file(path, "", false)
@@ -103,8 +107,9 @@ function Common.clear_file(path, player_index)
end end
--- Same as require but will return nil if the module does not exist, all other errors will propagate to the caller --- Same as require but will return nil if the module does not exist, all other errors will propagate to the caller
-- @tparam string module_path The path to the module to require, same syntax as normal require --- @param module_path string The path to the module to require, same syntax as normal require
-- @return The contents of the module, or nil if the module does not exist or did not return a value --- @return any # The contents of the module, or nil if the module does not exist or did not return a value
--- @deprecated
function Common.optional_require(module_path) function Common.optional_require(module_path)
local success, rtn = xpcall(require, traceback, module_path) local success, rtn = xpcall(require, traceback, module_path)
if success then return rtn end if success then return rtn end
@@ -114,16 +119,16 @@ function Common.optional_require(module_path)
end end
--- Returns a desync sale filepath for a given stack frame, default is the current file --- Returns a desync sale filepath for a given stack frame, default is the current file
-- @tparam number level The level of the stack to get the file of, a value of 1 is the caller of this function --- @param level number? The level of the stack to get the file of, a value of 1 is the caller of this function
-- @treturn string The relative filepath of the given stack frame --- @return string # The relative filepath of the given stack frame
function Common.safe_file_path(level) function Common.safe_file_path(level)
level = level or 1 level = level or 1
return getinfo(level + 1, "S").short_src:sub(10, -5) return getinfo(level + 1, "S").short_src:sub(10, -5)
end end
--- Returns the name of your module, this assumes your module is stored within /modules (which it is for clustorio) --- Returns the name of your module, this assumes your module is stored within /modules (which it is for clustorio)
-- @tparam[opt=1] number level The level of the stack to get the module of, a value of 1 is the caller of this function --- @param level number? The level of the stack to get the module of, a value of 1 is the caller of this function
-- @treturn string The name of the module at the given stack frame --- @return string # The name of the module at the given stack frame
function Common.get_module_name(level) function Common.get_module_name(level)
local file_within_module = getinfo((level or 1) + 1, "S").short_src:sub(18, -5) local file_within_module = getinfo((level or 1) + 1, "S").short_src:sub(18, -5)
local next_slash = file_within_module:find("/") local next_slash = file_within_module:find("/")
@@ -135,9 +140,9 @@ function Common.get_module_name(level)
end end
--- Returns the name of a function in a safe and consistent format --- Returns the name of a function in a safe and consistent format
-- @tparam number|function func The level of the stack to get the name of, a value of 1 is the caller of this function --- @param func number | function The level of the stack to get the name of, a value of 1 is the caller of this function
-- @tparam boolean raw When true there will not be any < > around the name --- @param raw boolean When true there will not be any < > around the name
-- @treturn string The name of the function at the given stack frame or provided as an argument --- @return string # The name of the function at the given stack frame or provided as an argument
function Common.get_function_name(func, raw) function Common.get_function_name(func, raw)
local debug_info = getinfo(func, "Sn") local debug_info = getinfo(func, "Sn")
local safe_source = debug_info.source:find("__level__") local safe_source = debug_info.source:find("__level__")
@@ -148,11 +153,11 @@ function Common.get_function_name(func, raw)
end end
--- Attempt a simple autocomplete search from a set of options --- Attempt a simple autocomplete search from a set of options
-- @tparam table options The table representing the possible options which can be selected --- @param options table The table representing the possible options which can be selected
-- @tparam string input The user input string which should be matched to an option --- @param input string The user input string which should be matched to an option
-- @tparam[opt=false] boolean use_key When true the keys will be searched, when false the values will be searched --- @param use_key boolean? When true the keys will be searched, when false the values will be searched
-- @tparam[opt=false] boolean rtn_key When true the selected key will be returned, when false the selected value will be returned --- @param rtn_key boolean? When true the selected key will be returned, when false the selected value will be returned
-- @return The selected key or value which first matches the input text --- @return any # The selected key or value which first matches the input text
function Common.auto_complete(options, input, use_key, rtn_key) function Common.auto_complete(options, input, use_key, rtn_key)
input = input:lower() input = input:lower()
if use_key then if use_key then
@@ -170,61 +175,71 @@ function Common.auto_complete(options, input, use_key, rtn_key)
end end
end end
--- Formats any value into a safe representation, useful with table.insert --- Formats any value into a safe representation, useful with table.inspect
-- @param value The value to be formated --- @param value any The value to be formatted
-- @return The formated version of the value --- @return string | LocalisedString # The formatted version of the value
-- @return True if value is a locale string, nil otherwise --- @return boolean # True if value is a locale string, nil otherwise
function Common.safe_value(value) function Common.safe_value(value)
if type(value) == "table" or type(value) == "userdata" then if type(value) == "table" then
if type(value.__self) == "userdata" or type(value) == "userdata" then local v1 = value[1]
local success, rtn = pcall(function() -- some userdata doesnt contain "valid" local str = tostring(value)
if value.valid then -- userdata if type(v1) == "string" and not v1:find("%s")
return "<userdata:" .. value.object_name .. ">" and (v1 == "" or v1 == "?" or v1:find(".+[.].+")) then
else -- invalid userdata
return "<userdata:" .. value.object_name .. ":invalid>"
end
end)
return success and rtn or "<userdata:" .. value.object_name .. ">"
elseif type(value[1]) == "string" and string.find(value[1], ".+[.].+") and not string.find(value[1], "%s") then
return value, true -- locale string return value, true -- locale string
elseif tostring(value) ~= "table" then elseif str ~= "table" then
return tostring(value) -- has __tostring metamethod return str, false -- has __tostring metamethod
else -- plain table else -- plain table
return value return value, false
end end
elseif type(value) == "function" then -- function elseif type(value) == "function" then -- function
return "<function:" .. Common.get_function_name(value, true) .. ">" return "<function:" .. Common.get_function_name(value, true) .. ">", false
else -- not: table, userdata, or function else -- not: table or function
return tostring(value) return tostring(value), false
end end
end end
--- @class Common.format_any_param
--- @field as_json boolean? If table values should be returned as json
--- @field max_line_count number? If table newline count exceeds provided then it will be inlined, if 0 then always inline
--- @field no_locale_strings boolean? If value is a locale string it will be treated like a normal table
--- @field depth number? The max depth to process tables to, the default is 5
--- Formats any value to be presented in a safe and human readable format --- Formats any value to be presented in a safe and human readable format
-- @param value The value to be formated --- @param value any The value to be formatted
-- @param[opt] tableAsJson If table values should be returned as json --- @param options Common.format_any_param? Options for the formatter
-- @param[opt] maxLineCount If table newline count exceeds provided then it will be inlined --- @return string | LocalisedString # The formatted version of the value
-- @return The formated version of the value function Common.format_any(value, options)
function Common.format_any(value, as_json, max_line_count) options = options or {}
local formatted, is_locale_string = Common.safe_value(value) local formatted, is_locale_string = Common.safe_value(value)
if type(formatted) == "table" and not is_locale_string then if type(formatted) == "table" and (not is_locale_string or options.no_locale_strings) then
if as_json then if options.as_json then
local success, rtn = pcall(game.table_to_json, value) local success, rtn = pcall(game.table_to_json, value)
if success then return rtn end if success then return rtn end
end end
local rtn = table.inspect(value, { depth = 5, indent = " ", newline = "\n", process = Common.safe_value }) if options.max_line_count ~= 0 then
if max_line_count == nil or select(2, rtn:gsub("\n", "")) < max_line_count then return rtn end local rtn = table.inspect(value, { depth = options.depth or 5, indent = " ", newline = "\n", process = Common.safe_value })
return table.inspect(value, { depth = 5, indent = "", newline = "", process = Common.safe_value }) if options.max_line_count == nil or select(2, rtn:gsub("\n", "")) < options.max_line_count then return rtn end
end
return table.inspect(value, { depth = options.depth or 5, indent = "", newline = "", process = Common.safe_value })
end end
return formatted return formatted
end end
--- @alias Common.format_time_param_format "short" | "long" | "clock"
--- @class Common.format_time_param_units
--- @field days boolean? True if days are included
--- @field hours boolean? True if hours are included
--- @field minutes boolean? True if minutes are included
--- @field seconds boolean? True if seconds are included
--- Format a tick value into one of a selection of pre-defined formats (short, long, clock) --- Format a tick value into one of a selection of pre-defined formats (short, long, clock)
-- @tparam number ticks The number of ticks which will be represented, can be any duration or time value --- @param ticks number|nil The number of ticks which will be represented, can be any duration or time value
-- @tparam string format The format to display, must be one of: short, long, clock --- @param format Common.format_time_param_format format to display, must be one of: short, long, clock
-- @tparam[opt] table units A table selecting which units should be displayed, options are: days, hours, minutes, seconds --- @param units Common.format_time_param_units A table selecting which units should be displayed, options are: days, hours, minutes, seconds
-- @treturn string The ticks formatted into a string of the desired format --- @return string # The ticks formatted into a string of the desired format
function Common.format_time(ticks, format, units) function Common.format_time(ticks, format, units)
units = units or { days = false, hours = true, minutes = true, seconds = false } --- @type string | number, string | number, string | number, string | number
local rtn_days, rtn_hours, rtn_minutes, rtn_seconds = "--", "--", "--", "--" local rtn_days, rtn_hours, rtn_minutes, rtn_seconds = "--", "--", "--", "--"
if ticks ~= nil then if ticks ~= nil then
@@ -234,7 +249,6 @@ function Common.format_time(ticks, format, units)
local minutes, seconds = max_minutes - floor(max_hours) * 60, max_seconds - floor(max_minutes) * 60 local minutes, seconds = max_minutes - floor(max_hours) * 60, max_seconds - floor(max_minutes) * 60
-- Calculate rhw units to be displayed -- Calculate rhw units to be displayed
--- @diagnostic disable: cast-local-type
rtn_days, rtn_hours, rtn_minutes, rtn_seconds = floor(days), floor(hours), floor(minutes), floor(seconds) rtn_days, rtn_hours, rtn_minutes, rtn_seconds = floor(days), floor(hours), floor(minutes), floor(seconds)
if not units.days then rtn_hours = rtn_hours + rtn_days * 24 end if not units.days then rtn_hours = rtn_hours + rtn_days * 24 end
if not units.hours then rtn_minutes = rtn_minutes + rtn_hours * 60 end if not units.hours then rtn_minutes = rtn_minutes + rtn_hours * 60 end
@@ -269,12 +283,12 @@ function Common.format_time(ticks, format, units)
end end
--- Format a tick value into one of a selection of pre-defined formats (short, long, clock) --- Format a tick value into one of a selection of pre-defined formats (short, long, clock)
-- @tparam number ticks The number of ticks which will be represented, can be any duration or time value --- @param ticks number|nil The number of ticks which will be represented, can be any duration or time value
-- @tparam string format The format to display, must be one of: short, long, clock --- @param format Common.format_time_param_format format to display, must be one of: short, long, clock
-- @tparam[opt] table units A table selecting which units should be displayed, options are: days, hours, minutes, seconds --- @param units Common.format_time_param_units A table selecting which units should be displayed, options are: days, hours, minutes, seconds
-- @treturn LocaleString The ticks formatted into a LocaleString of the desired format --- @return LocalisedString # The ticks formatted into a string of the desired format
function Common.format_locale_time(ticks, format, units) function Common.format_time_locale(ticks, format, units)
units = units or { days = false, hours = true, minutes = true, seconds = false } --- @type string | number, string | number, string | number, string | number
local rtn_days, rtn_hours, rtn_minutes, rtn_seconds = "--", "--", "--", "--" local rtn_days, rtn_hours, rtn_minutes, rtn_seconds = "--", "--", "--", "--"
if ticks ~= nil then if ticks ~= nil then
@@ -284,23 +298,20 @@ function Common.format_locale_time(ticks, format, units)
local minutes, seconds = max_minutes - floor(max_hours) * 60, max_seconds - floor(max_minutes) * 60 local minutes, seconds = max_minutes - floor(max_hours) * 60, max_seconds - floor(max_minutes) * 60
-- Calculate rhw units to be displayed -- Calculate rhw units to be displayed
--- @diagnostic disable: cast-local-type
rtn_days, rtn_hours, rtn_minutes, rtn_seconds = floor(days), floor(hours), floor(minutes), floor(seconds) rtn_days, rtn_hours, rtn_minutes, rtn_seconds = floor(days), floor(hours), floor(minutes), floor(seconds)
if not units.days then rtn_hours = rtn_hours + rtn_days * 24 end if not units.days then rtn_hours = rtn_hours + rtn_days * 24 end
if not units.hours then rtn_minutes = rtn_minutes + rtn_hours * 60 end if not units.hours then rtn_minutes = rtn_minutes + rtn_hours * 60 end
if not units.minutes then rtn_seconds = rtn_seconds + rtn_minutes * 60 end if not units.minutes then rtn_seconds = rtn_seconds + rtn_minutes * 60 end
--- @diagnostic enable: cast-local-type
end end
local rtn = {} local rtn = {}
local join = ", " local join = ", " --- @type string | LocalisedString
if format == "clock" then if format == "clock" then
-- Example 12:34:56 or --:--:-- -- Example 12:34:56 or --:--:--
if units.days then rtn[#rtn + 1] = rtn_days end if units.days then rtn[#rtn + 1] = rtn_days end
if units.hours then rtn[#rtn + 1] = rtn_hours end if units.hours then rtn[#rtn + 1] = rtn_hours end
if units.minutes then rtn[#rtn + 1] = rtn_minutes end if units.minutes then rtn[#rtn + 1] = rtn_minutes end
if units.seconds then rtn[#rtn + 1] = rtn_seconds end if units.seconds then rtn[#rtn + 1] = rtn_seconds end
--- @diagnostic disable-next-line: cast-local-type
join = { "colon" } join = { "colon" }
elseif format == "short" then elseif format == "short" then
-- Example 12d 34h 56m or --d --h --m -- Example 12d 34h 56m or --d --h --m
@@ -318,81 +329,225 @@ function Common.format_locale_time(ticks, format, units)
rtn[#rtn] = { "", { "and" }, " ", rtn[#rtn] } rtn[#rtn] = { "", { "and" }, " ", rtn[#rtn] }
end end
local joined = { "" } --[[@as any]] --- @type LocalisedString
local joined = { "" }
for k, v in ipairs(rtn) do for k, v in ipairs(rtn) do
joined[2 * k] = v joined[2 * k] = v
joined[2 * k + 1] = join --[[@as any]] joined[2 * k + 1] = join
end end
return joined return joined
end end
--- Insert a copy of the given items into the found / created entities. If no entities are found then they will be created if possible. --- @class Common.format_time_factory_param: Common.format_time_param_units
-- @tparam table items The items which are to be inserted into the entities, an array of LuaItemStack --- @field format Common.format_time_param_format The format to use
-- @tparam LuaSurface surface The surface which will be searched to find the entities --- @field coefficient number? If present will multiply the input by this amount before formatting
-- @tparam table options A table of various optional options similar to find_entities_filtered
-- position + radius or area can be used to define a search area on the surface
-- type can be used to find all entities of a given type, such as a chest
-- name can be used to further specify which entity to insert into, this field is required if entity creation is desired
-- allow_creation is a boolean which when true will allow the function to create new entities in order to insert all items
-- force is the force which new entities will be created to, the default is the neutral force
-- @treturn LuaEntity the last entity that had items inserted into it
function Common.insert_item_stacks(items, surface, options)
local entities = surface.find_entities_filtered(options)
local count, current, last_entity = #entities, 0, nil
for _, item in ipairs(items) do --- Create a formatter to format a tick value into one of a selection of pre-defined formats (short, long, clock)
if item.valid_for_read then --- @param options Common.format_time_factory_param
local inserted = false --- @return fun(ticks: number|nil): string
function Common.format_time_factory(options)
local formatter, format, coefficient = Common.format_time, options.format, options.coefficient
if coefficient then
return function(ticks) return formatter(ticks and ticks * coefficient or nil, format, options) end
end
return function(ticks) return formatter(ticks, format, options) end
end
-- Attempt to insert the items --- Create a formatter to format a tick value into one of a selection of pre-defined formats (short, long, clock)
for i = 1, count do --- @param options Common.format_time_factory_param
local entity = entities[((current + i - 1) % count) + 1] --- @return fun(ticks: number|nil): LocalisedString
if entity.can_insert(item) then function Common.format_time_factory_locale(options)
last_entity = entity local formatter, format, coefficient = Common.format_local_time, options.format, options.coefficient
current = current + 1 if coefficient then
entity.insert(item) return function(ticks) return formatter(ticks and ticks * coefficient or nil, format, options) end
inserted = true end
end return function(ticks) return formatter(ticks, format, options) end
end end
-- If it was not inserted then a new entity is needed --- @class Common.get_or_create_storage_cache
if not inserted then --- @field entities LuaEntity[] Array of found entities matching the search
if not options.allow_creation then error("Unable to insert items into a valid entity, consider enabling allow_creation") end --- @field current number The current index within the entity array
if options.name == nil then error("Name must be provided to allow creation of new entities") end --- @field count number The number of entities found
local position --- @class Common.get_or_create_storage_param: EntitySearchFilters
if options.position then --- @field item ItemStackIdentification The item stack that must be insertable
position = surface.find_non_colliding_position(options.name, options.position, options.radius, 1, true) --- @field surface LuaSurface The surface to search for targets on
elseif options.area then --- @field allow_creation boolean? If new entities can be create to store the items
position = surface.find_non_colliding_position_in_box(options.name, options.area, 1, true) --- @field cache Common.get_or_create_storage_cache? Internal search cache passed between subsequent calls
else
position = surface.find_non_colliding_position(options.name, { 0, 0 }, 0, 1, true)
end
last_entity = surface.create_entity{ name = options.name, position = position, force = options.force or "neutral" }
count = count + 1 --- Find, or optionally create, a storage entity which a stack can be inserted into
entities[count] = last_entity --- @param options Common.get_or_create_storage_param
last_entity.insert(item) --- @return LuaEntity
end function Common.get_storage_for_stack(options)
local surface = assert(options.surface, "A surface must be provided")
local item = assert(options.item, "An item stack must be provided")
-- Perform a search if on has not been done already
local cache = options.cache
if cache then
local entities = surface.find_entities_filtered(options)
cache = {
entities = entities,
count = #entities,
current = 0,
}
options.cache = cache
end
--- @cast cache -nil
-- Find a valid entity from the search results
local current, count, entities = cache.current, cache.count, cache.entities
for i = 1, cache.count do
local entity = entities[((current + i - 1) % count) + 1]
if entity.can_insert(item) then
cache.current = current + 1
return entity
end end
end end
return last_entity -- No entity was found so one needs to be created
assert(options.allow_creation, "Unable to find valid entity, consider enabling allow_creation")
assert(options.name, "Name must be provided to allow creation of new entities")
local position
if options.position then
position = surface.find_non_colliding_position(options.name, options.position, options.radius or 0, 1, true)
elseif options.area then
position = surface.find_non_colliding_position_in_box(options.name, options.area, 1, true)
else
position = surface.find_non_colliding_position(options.name, { 0, 0 }, 0, 1, true)
end
assert(position, "Failed to find valid location")
local entity = surface.create_entity{ name = options.name, position = position, force = options.force or "neutral" }
assert(entity, "Failed to create a new entity")
cache.count = count + 1
entities[count] = entity
return entity
end end
--- Move the given items into the found / created entities. If no entities are found then they will be created if possible. --- @class Common.copy_items_to_surface_param: Common.get_or_create_storage_param
-- @tparam table items The items which are to be inserted into the entities, an array of LuaItemStack --- @field items ItemStackIdentification[] | LuaInventory The item stacks to copy
-- @tparam LuaSurface surface The surface which will be searched to find the entities
-- @tparam table options A table of various optional options similar to find_entities_filtered --- Insert a copy of the given items into the found entities. If no entities are found then they will be created if possible.
-- position + radius or area can be used to define a search area on the surface --- @param options Common.copy_items_to_surface_param
-- type can be used to find all entities of a given type, such as a chest --- @return LuaEntity # The last entity inserted into
-- name can be used to further specify which entity to insert into, this field is required if entity creation is desired function Common.copy_items_to_surface(options)
-- allow_creation is a boolean which when true will allow the function to create new entities in order to insert all items local entity
-- @treturn LuaEntity the last entity that had items inserted into it for item_index = 1, #options.items do
function Common.transfer_item_stacks(inventory, surface, options) options.item = options.items[item_index]
Common.insert_item_stacks(inventory, surface, options) entity = Common.get_storage_for_stack(options)
inventory.clear() entity.insert(options.item)
end
return entity
end
--- @class Common.move_items_to_surface_param: Common.get_or_create_storage_param
--- @field items LuaItemStack[] The item stacks to move
--- Insert a copy of the given items into the found entities. If no entities are found then they will be created if possible.
--- @param options Common.move_items_to_surface_param
--- @return LuaEntity # The last entity inserted into
function Common.move_items_to_surface(options)
local entity
for item_index = 1, #options.items do
options.item = options.items[item_index]
entity = Common.get_storage_for_stack(options)
entity.insert(options.item)
options.item.clear()
end
return entity
end
--- @class Common.transfer_inventory_to_surface_param: Common.copy_items_to_surface_param
--- @field inventory LuaInventory The inventory to transfer
--- Move the given inventory into the found entities. If no entities are found then they will be created if possible.
--- @param options Common.transfer_inventory_to_surface_param
--- @return LuaEntity # The last entity inserted into
function Common.transfer_inventory_to_surface(options)
options.items = options.inventory
local entity = Common.copy_items_to_surface(options)
options.inventory.clear()
return entity
end
--- Create an enum table from a set of strings, can use custom indexes to change base
--- @param values { [number]: string }
--- @return { [string | number]: string | number }
function Common.enum(values)
local enum = {}
local index = 0 -- Real index within values
local offset = 0 -- Offset from base for next index
local base = 0 -- Start point for offset
for k, v in pairs(values) do
index = index + 1
if k ~= index then
offset = 0
base = k
end
enum[base + offset] = v
offset = offset + 1
end
for k, v in pairs(enum) do
if type(k) == "number" then
enum[v] = k
end
end
return enum
end
--- Returns a string for a number with comma separators
--- @param n number
--- @return string
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
--- Returns a message formatted for game chat using rich text colour tags
--- @param message string
--- @param color Color | string
--- @return string
function Common.format_rich_text_color(message, color)
color = color or Common.color.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 formatted for game chat using rich text colour tags
--- @param message string
--- @param color Color | string
--- @return LocalisedString
function Common.format_rich_text_color_locale(message, color)
color = color or Common.color.white
color = math.round(color.r, 3) .. ", " .. math.round(color.g, 3) .. ", " .. math.round(color.b, 3)
return { "color-tag", color, message }
end
--- Formats a players name using rich text color
--- @param player LuaPlayer
--- @return string
function Common.format_player_name(player)
local valid_player = type(player) == "userdata" and player or game.get_player(player)
local player_name = valid_player and valid_player.name or "<Server>"
local player_chat_colour = valid_player and valid_player.chat_color or Common.color.white
return Common.format_rich_text_color(player_name, player_chat_colour)
end
--- Formats a players name using rich text color
--- @param player LuaPlayer
--- @return LocalisedString
function Common.format_player_name_locale(player)
local valid_player = type(player) == "userdata" and player or game.get_player(player)
local player_name = valid_player and valid_player.name or "<Server>"
local player_chat_colour = valid_player and valid_player.chat_color or Common.color.white
return Common.format_rich_text_color_locale(player_name, player_chat_colour)
end end
return Common return Common

View File

@@ -1,180 +0,0 @@
--[[-- Util Module - FloatingText
- Provides a method of creating floating text and tags in the world
@core FloatingText
@alias FloatingText
@usage-- Show player chat message in world
local function on_console_chat(event)
local player = game.players[event.player_index]
FloatingText.print_as_player(player, event.message)
end
@usage-- Show player tags above their characters
local function on_player_respawned(event)
local player = game.players[event.player_index]
FloatingText.create_tag_as_player(player, player.tag)
end
@usage-- Show placed an entity in alt mode
local function on_built_entity(event)
local entity = event.created_entity
local player = game.players[event.player_index]
FloatingText.create_tag_above_entity(entity, player.name, player.color, true)
end
]]
local FloatingText = {}
FloatingText.color = require("modules/exp_util/include/color")
--- Print Messages.
-- Short lived messages that last at most a few seconds
-- @section floating-text_print
--- Print floating text at the given position on the given surface
-- @tparam LuaSurface surface The surface where the floating text will be created
-- @tparam MapPosition position The position to create the floating text at
-- @tparam string text The text which will be printed
-- @tparam[opt=FloatingText.color.white] Color color The colour to print the text in
-- @treturn LuaEntity The floating text entity which was created for the message
function FloatingText.print(surface, position, text, color)
return surface.create_entity{
text = text,
name = "tutorial-flying-text",
color = color or FloatingText.color.white,
position = position,
}
end
--- Print floating text above the given entity
-- @tparam LuaEntity The entity to create the text above
-- @tparam string text The text which will be printed
-- @tparam[opt=FloatingText.color.white] Color color The colour to print the text in
-- @treturn LuaEntity The floating text entity which was created for the message
function FloatingText.print_above_entity(entity, text, color)
local size_y = entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y
return entity.surface.create_entity{
text = text,
name = "tutorial-flying-text",
color = color or FloatingText.color.white,
position = {
x = entity.position.x,
y = entity.position.y - size_y * 0.25,
},
}
end
--- Print floating text above the given player
-- @tparam LuaPlayer The player to create the text above
-- @tparam string text The text which will be printed
-- @tparam[opt=FloatingText.color.white] Color color The colour to print the text in
-- @treturn LuaEntity The floating text entity which was created for the message
function FloatingText.print_above_player(player, text, color)
return player.surface.create_entity{
text = text,
name = "tutorial-flying-text",
color = color or FloatingText.color.white,
position = {
x = player.position.x,
y = player.position.y - 1.5,
},
}
end
--- Print floating text above the given player in their chat color
-- @tparam LuaPlayer The player to create the text above
-- @tparam string text The text which will be printed
-- @treturn LuaEntity The floating text entity which was created for the message
function FloatingText.print_as_player(player, text)
return player.surface.create_entity{
text = text,
name = "tutorial-flying-text",
color = player.chat_color,
position = {
x = player.position.x,
y = player.position.y - 1.5,
},
}
end
--- Tag Messages.
-- Long lived messages that last until their are removed
-- @section floating-text_tags
--- Create floating text at the given position on the given surface
-- @tparam LuaSurface surface The surface where the floating text will be created
-- @tparam MapPosition position The position to create the floating text at
-- @tparam string text The text which will be printed
-- @tparam[opt=FloatingText.color.white] Color color The colour to print the text in
-- @tparam[opt=false] boolean alt_mode When true, the text will only appear when a player is in alt mode
-- @treturn LuaEntity The floating text entity which was created for the message
function FloatingText.create_tag(surface, position, text, color, alt_mode)
return rendering.draw_text{
text = text,
surface = surface,
color = color or FloatingText.color.white,
only_in_alt_mode = alt_mode,
target = position,
}
end
--- Create floating text above the given entity
-- @tparam LuaEntity The entity to create the text above
-- @tparam string text The text which will be printed
-- @tparam[opt=FloatingText.color.white] Color color The colour to print the text in
-- @tparam[opt=false] boolean alt_mode When true, the text will only appear when a player is in alt mode
-- @treturn LuaEntity The floating text entity which was created for the message
function FloatingText.create_tag_above_entity(entity, text, color, alt_mode)
return rendering.draw_text{
text = text,
surface = entity.surface,
color = color or FloatingText.color.white,
only_in_alt_mode = alt_mode,
target = entity,
target_offset = {
x = 0,
y = (entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y) * -0.25,
},
}
end
--- Create floating text above the given player
-- @tparam LuaPlayer The player to create the text above
-- @tparam string text The text which will be printed
-- @tparam[opt=FloatingText.color.white] Color color The colour to print the text in
-- @tparam[opt=false] boolean alt_mode When true, the text will only appear when a player is in alt mode
-- @treturn LuaEntity The floating text entity which was created for the message
function FloatingText.create_tag_above_player(player, text, color, alt_mode)
return rendering.draw_text{
text = text,
surface = player.surface,
color = color or FloatingText.color.white,
only_in_alt_mode = alt_mode,
target = player.character,
target_offset = {
x = 0,
y = -1.5,
},
}
end
--- Create floating text above the given player in their character color
-- @tparam LuaPlayer The player to create the text above
-- @tparam string text The text which will be printed
-- @tparam[opt=false] boolean alt_mode When true, the text will only appear when a player is in alt mode
-- @treturn LuaEntity The floating text entity which was created for the message
function FloatingText.create_tag_as_player(player, text, alt_mode)
return rendering.draw_text{
text = text,
surface = player.surface,
color = player.color,
only_in_alt_mode = alt_mode,
target = player.character,
target_offset = {
x = 0,
y = -1.5,
},
}
end
return FloatingText

View File

@@ -0,0 +1,89 @@
--[[-- Util Module - FlyingText
Provides a method of creating floating text and tags in the world
]]
local FlyingText = {}
FlyingText.color = require("modules/exp_util/include/color")
--- @class FlyingText.create_param:LuaPlayer.create_local_flying_text_param
--- @field player? LuaPlayer The player to create the text for
--- @field surface? LuaSurface The surface to create the text for
--- @field force? LuaForce The force to create the text for
--- Create flying text for a player, force, or surface; default is all online players
--- @param options FlyingText.create_param
function FlyingText.create(options)
if options.player then
options.player.create_local_flying_text(options)
elseif options.force then
for _, player in pairs(options.force.connected_players) do
player.create_local_flying_text(options)
end
elseif options.surface then
for _, player in pairs(game.connected_players) do
if player.surface == options.surface then
player.create_local_flying_text(options)
end
end
else
for _, player in pairs(game.connected_players) do
player.create_local_flying_text(options)
end
end
end
--- @class FlyingText.create_above_entity_param:FlyingText.create_param
--- @field target_entity? LuaEntity The entity to create the text above
--- Create flying above an entity, overrides the position option of FlyingText.create
--- @param options FlyingText.create_above_entity_param
function FlyingText.create_above_entity(options)
local entity = assert(options.target_entity, "A target entity is required")
local size_y = entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y
options.position = {
x = entity.position.x,
y = entity.position.y - size_y * 0.25,
}
FlyingText.create(options)
end
--- @class FlyingText.create_above_player_param:FlyingText.create_param
--- @field target_player? LuaPlayer The player to create the text above
--- Create flying above a player, overrides the position option of FlyingText.create
--- @param options FlyingText.create_above_player_param
function FlyingText.create_above_player(options)
local player = assert(options.target_player, "A target entity is required")
local entity = player.character; if not entity then return end
local size_y = entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y
options.position = {
x = entity.position.x,
y = entity.position.y - size_y * 0.25,
}
FlyingText.create(options)
end
--- @class FlyingText.create_as_player_param:FlyingText.create_param
--- @field target_player? LuaPlayer The player to create the text above
--- Create flying above a player, overrides the position and color option of FlyingText.create
--- @param options FlyingText.create_as_player_param
function FlyingText.create_as_player(options)
local player = assert(options.target_player, "A target entity is required")
local entity = player.character; if not entity then return end
local size_y = entity.bounding_box.left_top.y - entity.bounding_box.right_bottom.y
options.color = player.chat_color
options.position = {
x = entity.position.x,
y = entity.position.y - size_y * 0.25,
}
FlyingText.create(options)
end
return FlyingText

View File

@@ -32,9 +32,9 @@ end
local tbl = {} local tbl = {}
local values = {} local values = {}
for i = 1, 1000 do tbl[i] = i values[i] = i end for i = 1, 1000 do tbl[i] = i values[i] = i end
table.array_insert(tbl, 500, values) -- around 0.4ms table.insert_array(tbl, 500, values) -- around 0.4ms
]] ]]
function table.array_insert(tbl, start_index, values) function table.insert_array(tbl, start_index, values)
if not values then if not values then
values = start_index values = start_index
start_index = nil start_index = nil
@@ -69,15 +69,15 @@ end
local tbl = {} local tbl = {}
local tbl2 = {} local tbl2 = {}
for i = 1, 100 do tbl[i] = i tbl['_'..i] = i tbl2[i] = i tbl2['__'..i] = i end for i = 1, 100 do tbl[i] = i tbl['_'..i] = i tbl2[i] = i tbl2['__'..i] = i end
table.table_insert(tbl, 50, tbl2) table.insert_table(tbl, 50, tbl2)
]] ]]
function table.table_insert(tbl, start_index, tbl2) function table.insert_table(tbl, start_index, tbl2)
if not tbl2 then if not tbl2 then
tbl2 = start_index tbl2 = start_index
start_index = nil start_index = nil
end end
table.array_insert(tbl, start_index, tbl2) table.insert_array(tbl, start_index, tbl2)
for key, value in pairs(tbl2) do for key, value in pairs(tbl2) do
if not tonumber(key) then if not tonumber(key) then
tbl[key] = value tbl[key] = value
@@ -112,11 +112,6 @@ function table.remove_index(tbl, index)
tbl[count] = nil tbl[count] = nil
end end
--- Removes an item from an array in O(1) time. Does not guarantee the order of elements.
-- @tparam table tbl The array to remove the element from
-- @tparam number index Must be >= 0. The case where index > #tbl is handled.
table.fast_remove = table.remove_index
--- Return the key which holds this element element --- Return the key which holds this element element
-- @tparam table tbl The table to search -- @tparam table tbl The table to search
-- @param element The element to find -- @param element The element to find
@@ -428,7 +423,6 @@ table.deep_copy = table.deepcopy -- added by util
table.deep_merge = util.merge table.deep_merge = util.merge
--- Determines if two tables are structurally equal. --- Determines if two tables are structurally equal.
-- Notice: tables that are LuaObjects or contain LuaObjects won't be compared correctly, use == operator for LuaObjects
-- @tparam table tbl1 The first table -- @tparam table tbl1 The first table
-- @tparam table tbl2 The second table -- @tparam table tbl2 The second table
-- @treturn boolean True if the tables are equal -- @treturn boolean True if the tables are equal