mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
Update all code styles
This commit is contained in:
@@ -191,9 +191,9 @@ local trace = debug.traceback
|
||||
local Commands = {
|
||||
--- Constant values used by the command system
|
||||
defines = {
|
||||
error = 'CommandError',
|
||||
unauthorized = 'CommandErrorUnauthorized',
|
||||
success = 'CommandSuccess'
|
||||
error = "CommandError",
|
||||
unauthorized = "CommandErrorUnauthorized",
|
||||
success = "CommandSuccess",
|
||||
},
|
||||
--- An array of all custom commands that are registered
|
||||
commands = {},
|
||||
@@ -243,7 +243,7 @@ Commands.remove_authenticator(admin_authenticator)
|
||||
|
||||
]]
|
||||
function Commands.remove_authenticator(authenticator)
|
||||
if type(authenticator) == 'number' then
|
||||
if type(authenticator) == "number" then
|
||||
-- If a number is passed then it is assumed to be the index
|
||||
if Commands.authenticators[authenticator] then
|
||||
Commands.authenticators[authenticator] = nil
|
||||
@@ -281,15 +281,15 @@ function Commands.authorize(player, command_name)
|
||||
-- This is the reject function given to authenticators
|
||||
local failure_message
|
||||
local function reject(message)
|
||||
failure_message = message or {'expcore-commands.unauthorized'}
|
||||
failure_message = message or { "expcore-commands.unauthorized" }
|
||||
return Commands.defines.unauthorized
|
||||
end
|
||||
|
||||
-- This is the internal error function used when an authenticator errors
|
||||
local function authenticator_error(err)
|
||||
log('[ERROR] Authorization failed: '..trace(err))
|
||||
log("[ERROR] Authorization failed: " .. trace(err))
|
||||
if Commands.authorization_failure_on_error then
|
||||
return reject('Internal Error')
|
||||
return reject("Internal Error")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -298,7 +298,7 @@ function Commands.authorize(player, command_name)
|
||||
-- player: LuaPlayer, command: string, flags: table, reject: function(error_message: string)
|
||||
local _, rtn = xpcall(authenticator, authenticator_error, player, command_name, command_data.flags, reject)
|
||||
if rtn == false or rtn == Commands.defines.unauthorized or rtn == reject or failure_message ~= nil then
|
||||
if failure_message == nil then failure_message = {'expcore-commands.unauthorized'} end
|
||||
if failure_message == nil then failure_message = { "expcore-commands.unauthorized" } end
|
||||
return false, failure_message
|
||||
end
|
||||
end
|
||||
@@ -370,7 +370,10 @@ end)
|
||||
function Commands.parse(name, input, player, reject, ...)
|
||||
if not Commands.parsers[name] then return end
|
||||
local success, rtn = pcall(Commands.parsers[name], input, player, reject, ...)
|
||||
if not success then error(rtn, 2) return end
|
||||
if not success then
|
||||
error(rtn, 2)
|
||||
return
|
||||
end
|
||||
if not rtn or rtn == Commands.defines.error then return end
|
||||
return rtn
|
||||
end
|
||||
@@ -398,6 +401,7 @@ function Commands.get(player)
|
||||
allowed[name] = command_data
|
||||
end
|
||||
end
|
||||
|
||||
return allowed
|
||||
end
|
||||
|
||||
@@ -420,12 +424,13 @@ function Commands.search(keyword, player)
|
||||
-- Loops over custom commands
|
||||
for name, command_data in pairs(custom_commands) do
|
||||
-- combines name help and aliases into one message to be searched
|
||||
local search = string.format('%s %s %s %s', name, command_data.help, command_data.searchable_description, table.concat(command_data.aliases, ' '))
|
||||
local search = string.format("%s %s %s %s", name, command_data.help, command_data.searchable_description, table.concat(command_data.aliases, " "))
|
||||
|
||||
if search:lower():match(keyword) then
|
||||
matches[name] = command_data
|
||||
end
|
||||
end
|
||||
|
||||
-- Loops over the names of game commands
|
||||
for name, description in pairs(commands.game_commands) do
|
||||
if name:lower():match(keyword) then
|
||||
@@ -433,11 +438,12 @@ function Commands.search(keyword, player)
|
||||
matches[name] = {
|
||||
name = name,
|
||||
help = description,
|
||||
description = '',
|
||||
aliases = {}
|
||||
description = "",
|
||||
aliases = {},
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return matches
|
||||
end
|
||||
|
||||
@@ -458,16 +464,16 @@ function Commands.new_command(name, help, descr)
|
||||
local command = setmetatable({
|
||||
name = name,
|
||||
help = help,
|
||||
searchable_description = descr or '',
|
||||
callback = function() Commands.internal_error(false, name, 'No callback registered') end,
|
||||
searchable_description = descr or "",
|
||||
callback = function() Commands.internal_error(false, name, "No callback registered") end,
|
||||
auto_concat = false,
|
||||
min_param_count = 0,
|
||||
max_param_count = 0,
|
||||
flags = {}, -- stores flags that can be used by auth
|
||||
flags = {}, -- stores flags that can be used by auth
|
||||
aliases = {}, -- stores aliases to this command
|
||||
params = {}, -- [param_name] = {optional: boolean, default: any, parse: function, parse_args: table}
|
||||
params = {}, -- [param_name] = {optional: boolean, default: any, parse: function, parse_args: table}
|
||||
}, {
|
||||
__index = Commands._prototype
|
||||
__index = Commands._prototype,
|
||||
})
|
||||
Commands.commands[name] = command
|
||||
return command
|
||||
@@ -491,17 +497,17 @@ end)
|
||||
|
||||
]]
|
||||
function Commands._prototype:add_param(name, optional, parse, ...)
|
||||
local parse_args = {...}
|
||||
if type(optional) ~= 'boolean' then
|
||||
parse_args = {parse, ...}
|
||||
local parse_args = { ... }
|
||||
if type(optional) ~= "boolean" then
|
||||
parse_args = { parse, ... }
|
||||
parse = optional
|
||||
optional = false
|
||||
end
|
||||
|
||||
self.params[name] = {
|
||||
optional = optional,
|
||||
parse = parse or function(string) return string end,
|
||||
parse_args = parse_args
|
||||
optional = optional,
|
||||
parse = parse or function(string) return string end,
|
||||
parse_args = parse_args,
|
||||
}
|
||||
|
||||
self.max_param_count = self.max_param_count + 1
|
||||
@@ -532,6 +538,7 @@ function Commands._prototype:set_defaults(defaults)
|
||||
self.params[name].default = value
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -562,9 +569,10 @@ command:add_alias('name', 'rname')
|
||||
]]
|
||||
function Commands._prototype:add_alias(...)
|
||||
local start_index = #self.aliases
|
||||
for index, alias in ipairs{...} do
|
||||
self.aliases[start_index+index] = alias
|
||||
for index, alias in ipairs{ ... } do
|
||||
self.aliases[start_index + index] = alias
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -600,14 +608,15 @@ function Commands._prototype:register(callback)
|
||||
self.callback = callback
|
||||
|
||||
-- Generates a description to be used
|
||||
local description = ''
|
||||
local description = ""
|
||||
for param_name, param_details in pairs(self.params) do
|
||||
if param_details.optional then
|
||||
description = string.format('%s [%s]', description, param_name)
|
||||
description = string.format("%s [%s]", description, param_name)
|
||||
else
|
||||
description = string.format('%s <%s>', description, param_name)
|
||||
description = string.format("%s <%s>", description, param_name)
|
||||
end
|
||||
end
|
||||
|
||||
self.description = description
|
||||
|
||||
-- Last resort error handler for commands
|
||||
@@ -622,7 +631,7 @@ function Commands._prototype:register(callback)
|
||||
end
|
||||
|
||||
-- Registers the command under its own name
|
||||
local help = {'expcore-commands.command-help', description, self.help}
|
||||
local help = { "expcore-commands.command-help", description, self.help }
|
||||
commands.add_command(self.name, help, command_callback)
|
||||
|
||||
-- Adds any aliases that it has
|
||||
@@ -650,7 +659,7 @@ return 'Your message has been printed'
|
||||
]]
|
||||
function Commands.success(value)
|
||||
if value ~= nil then player_return(value) end
|
||||
player_return({'expcore-commands.command-ran'}, 'cyan')
|
||||
player_return({ "expcore-commands.command-ran" }, "cyan")
|
||||
return Commands.defines.success
|
||||
end
|
||||
|
||||
@@ -675,11 +684,11 @@ return Commands.error('The player you selected is offline')
|
||||
|
||||
]]
|
||||
function Commands.error(error_message, play_sound)
|
||||
error_message = error_message or ''
|
||||
player_return({'expcore-commands.command-fail', error_message}, 'orange_red')
|
||||
error_message = error_message or ""
|
||||
player_return({ "expcore-commands.command-fail", error_message }, "orange_red")
|
||||
if play_sound ~= false then
|
||||
play_sound = play_sound or 'utility/wire_pickup'
|
||||
if game.player then game.player.play_sound{path=play_sound} end
|
||||
play_sound = play_sound or "utility/wire_pickup"
|
||||
if game.player then game.player.play_sound{ path = play_sound } end
|
||||
end
|
||||
return Commands.defines.error
|
||||
end
|
||||
@@ -700,22 +709,22 @@ end
|
||||
]]
|
||||
function Commands.internal_error(success, command_name, error_message)
|
||||
if not success then
|
||||
Commands.error('Internal Error, Please contact an admin', 'utility/cannot_build')
|
||||
log{'expcore-commands.command-error-log-format', command_name, error_message}
|
||||
Commands.error("Internal Error, Please contact an admin", "utility/cannot_build")
|
||||
log{ "expcore-commands.command-error-log-format", command_name, error_message }
|
||||
end
|
||||
return not success
|
||||
end
|
||||
|
||||
--- Logs command usage to file
|
||||
local function command_log(player, command, comment, params, raw, details)
|
||||
local player_name = player and player.name or '<Server>'
|
||||
write_json('log/commands.log', {
|
||||
player_name = player_name,
|
||||
local player_name = player and player.name or "<Server>"
|
||||
write_json("log/commands.log", {
|
||||
player_name = player_name,
|
||||
command_name = command.name,
|
||||
comment = comment,
|
||||
details = details,
|
||||
params = params,
|
||||
raw = raw
|
||||
comment = comment,
|
||||
details = details,
|
||||
params = params,
|
||||
raw = raw,
|
||||
})
|
||||
end
|
||||
|
||||
@@ -733,46 +742,46 @@ function Commands.run_command(command_event)
|
||||
-- Check if the player is allowed to use the command
|
||||
local authorized, auth_fail = Commands.authorize(player, command_data.name)
|
||||
if not authorized then
|
||||
command_log(player, command_data, 'Failed Auth', {}, command_event.parameter)
|
||||
Commands.error(auth_fail, 'utility/cannot_build')
|
||||
command_log(player, command_data, "Failed Auth", {}, command_event.parameter)
|
||||
Commands.error(auth_fail, "utility/cannot_build")
|
||||
return
|
||||
end
|
||||
|
||||
-- Check for parameter being nil
|
||||
if command_data.min_param_count > 0 and not command_event.parameter then
|
||||
command_log(player, command_data, 'No Params Given', {}, command_event.parameter)
|
||||
Commands.error{'expcore-commands.invalid-inputs', command_data.name, command_data.description}
|
||||
command_log(player, command_data, "No Params Given", {}, command_event.parameter)
|
||||
Commands.error{ "expcore-commands.invalid-inputs", command_data.name, command_data.description }
|
||||
return
|
||||
end
|
||||
|
||||
-- Extract quoted arguments
|
||||
local raw_input = command_event.parameter or ''
|
||||
local raw_input = command_event.parameter or ""
|
||||
local quote_params = {}
|
||||
local input_string = raw_input:gsub('"[^"]-"', function(word)
|
||||
local no_spaces = word:gsub('%s', '%%s')
|
||||
local no_spaces = word:gsub("%s", "%%s")
|
||||
quote_params[no_spaces] = word:sub(2, -2)
|
||||
return ' '..no_spaces..' '
|
||||
return " " .. no_spaces .. " "
|
||||
end)
|
||||
|
||||
-- Extract unquoted arguments
|
||||
local raw_params = {}
|
||||
local last_index = 0
|
||||
local param_number = 0
|
||||
for word in input_string:gmatch('%S+') do
|
||||
for word in input_string:gmatch("%S+") do
|
||||
param_number = param_number + 1
|
||||
if param_number > command_data.max_param_count then
|
||||
-- there are too many params given to the command
|
||||
if not command_data.auto_concat then
|
||||
-- error as they should not be more
|
||||
command_log(player, command_data, 'Invalid Input: Too Many Params', raw_params, raw_input)
|
||||
Commands.error{'expcore-commands.invalid-inputs', command_data.name, command_data.description}
|
||||
command_log(player, command_data, "Invalid Input: Too Many Params", raw_params, raw_input)
|
||||
Commands.error{ "expcore-commands.invalid-inputs", command_data.name, command_data.description }
|
||||
return
|
||||
else
|
||||
-- concat to the last param
|
||||
if quote_params[word] then
|
||||
raw_params[last_index] = raw_params[last_index]..' "'..quote_params[word]..'"'
|
||||
raw_params[last_index] = raw_params[last_index] .. ' "' .. quote_params[word] .. '"'
|
||||
else
|
||||
raw_params[last_index] = raw_params[last_index]..' '..word
|
||||
raw_params[last_index] = raw_params[last_index] .. " " .. word
|
||||
end
|
||||
end
|
||||
else
|
||||
@@ -790,8 +799,8 @@ function Commands.run_command(command_event)
|
||||
-- Check the param count
|
||||
local param_count = #raw_params
|
||||
if param_count < command_data.min_param_count then
|
||||
command_log(player, command_data, 'Invalid Input: Not Enough Params', raw_params, raw_input)
|
||||
Commands.error{'expcore-commands.invalid-inputs', command_data.name, command_data.description}
|
||||
command_log(player, command_data, "Invalid Input: Not Enough Params", raw_params, raw_input)
|
||||
Commands.error{ "expcore-commands.invalid-inputs", command_data.name, command_data.description }
|
||||
return
|
||||
end
|
||||
|
||||
@@ -801,48 +810,46 @@ function Commands.run_command(command_event)
|
||||
for param_name, param_data in pairs(command_data.params) do
|
||||
local parse_callback = param_data.parse
|
||||
-- If its a string this get it from the parser table
|
||||
if type(parse_callback) == 'string' then
|
||||
if type(parse_callback) == "string" then
|
||||
parse_callback = Commands.parsers[parse_callback]
|
||||
end
|
||||
|
||||
-- If its not a function throw and error
|
||||
if type(parse_callback) ~= 'function' then
|
||||
Commands.internal_error(false, command_data.name, 'Invalid param parse '..tostring(param_data.parse))
|
||||
command_log(player, command_data, 'Internal Error: Invalid Param Parse', params, raw_input, tostring(param_data.parse))
|
||||
if type(parse_callback) ~= "function" then
|
||||
Commands.internal_error(false, command_data.name, "Invalid param parse " .. tostring(param_data.parse))
|
||||
command_log(player, command_data, "Internal Error: Invalid Param Parse", params, raw_input, tostring(param_data.parse))
|
||||
return
|
||||
end
|
||||
|
||||
-- This is the reject function given to parse callbacks
|
||||
local function reject(error_message)
|
||||
error_message = error_message or ''
|
||||
command_log(player, command_data, 'Invalid Param Given', raw_params, input_string)
|
||||
return Commands.error{'expcore-commands.invalid-param', param_name, error_message}
|
||||
error_message = error_message or ""
|
||||
command_log(player, command_data, "Invalid Param Given", raw_params, input_string)
|
||||
return Commands.error{ "expcore-commands.invalid-param", param_name, error_message }
|
||||
end
|
||||
|
||||
-- input: string, player: LuaPlayer, reject: function, ... extra args
|
||||
local success, param_parsed = pcall(parse_callback, raw_params[index], player, reject, table.unpack(param_data.parse_args))
|
||||
if Commands.internal_error(success, command_data.name, param_parsed) then
|
||||
return command_log(player, command_data, 'Internal Error: Param Parse Fail', params, raw_input, param_parsed)
|
||||
return command_log(player, command_data, "Internal Error: Param Parse Fail", params, raw_input, param_parsed)
|
||||
end
|
||||
|
||||
if param_data.optional == true and raw_params[index] == nil then
|
||||
-- If the param is optional and nil then it is set to default
|
||||
param_parsed = param_data.default
|
||||
if type(param_parsed) == 'function' then
|
||||
if type(param_parsed) == "function" then
|
||||
success, param_parsed = pcall(param_parsed, player)
|
||||
if Commands.internal_error(success, command_data.name, param_parsed) then
|
||||
return command_log(player, command_data, 'Internal Error: Default Value Fail', params, raw_input, param_parsed)
|
||||
return command_log(player, command_data, "Internal Error: Default Value Fail", params, raw_input, param_parsed)
|
||||
end
|
||||
end
|
||||
|
||||
elseif param_parsed == nil or param_parsed == Commands.defines.error or param_parsed == reject then
|
||||
-- No value was returned or error was returned, if nil then give generic error
|
||||
if param_parsed ~= Commands.defines.error then
|
||||
command_log(player, command_data, 'Invalid Param Given', raw_params, raw_input, param_name)
|
||||
Commands.error{'expcore-commands.command-error-param-format', param_name, 'please make sure it is the correct type'}
|
||||
command_log(player, command_data, "Invalid Param Given", raw_params, raw_input, param_name)
|
||||
Commands.error{ "expcore-commands.command-error-param-format", param_name, "please make sure it is the correct type" }
|
||||
end
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
-- Add the param to the table to be passed to the command callback
|
||||
@@ -852,19 +859,19 @@ function Commands.run_command(command_event)
|
||||
|
||||
-- Run the command
|
||||
-- player: LuaPlayer, ... command params, raw: string
|
||||
params[command_data.max_param_count+1] = raw_input
|
||||
params[command_data.max_param_count + 1] = raw_input
|
||||
local success, rtn = pcall(command_data.callback, player, table.unpack(params))
|
||||
if Commands.internal_error(success, command_data.name, rtn) then
|
||||
return command_log(player, command_data, 'Internal Error: Command Callback Fail', raw_params, command_event.parameter, rtn)
|
||||
return command_log(player, command_data, "Internal Error: Command Callback Fail", raw_params, command_event.parameter, rtn)
|
||||
end
|
||||
|
||||
-- Give output to the player
|
||||
if rtn == Commands.defines.error or rtn == Commands.error then
|
||||
return command_log(player, command_data, 'Custom Error', raw_params, raw_input)
|
||||
return command_log(player, command_data, "Custom Error", raw_params, raw_input)
|
||||
elseif rtn ~= Commands.defines.success and rtn ~= Commands.success then
|
||||
Commands.success(rtn)
|
||||
end
|
||||
command_log(player, command_data, 'Success', raw_params, raw_input)
|
||||
command_log(player, command_data, "Success", raw_params, raw_input)
|
||||
end
|
||||
|
||||
return Commands
|
||||
|
||||
@@ -40,7 +40,7 @@ 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
|
||||
level = level and level + 1 or 2
|
||||
return Common.type_check(value, test_type) or error(error_message, level)
|
||||
end
|
||||
|
||||
@@ -60,6 +60,7 @@ function Common.multi_type_check(value, test_types)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -75,7 +76,7 @@ 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
|
||||
level = level and level + 1 or 2
|
||||
return Common.mult_type_check(value, test_types) or error(error_message, level)
|
||||
end
|
||||
|
||||
@@ -95,12 +96,12 @@ 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 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)
|
||||
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)
|
||||
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
|
||||
@@ -123,12 +124,12 @@ 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 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 '))
|
||||
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 '))
|
||||
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
|
||||
@@ -139,8 +140,8 @@ end
|
||||
-- @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)
|
||||
local function_name = debug.getinfo(2, "n").name or "<anon>"
|
||||
error(function_name .. " can not be called during runtime", 3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -171,7 +172,7 @@ local value = Common.resolve_value(self.defaut_value, self)
|
||||
|
||||
]]
|
||||
function Common.resolve_value(value, ...)
|
||||
return value and type(value) == 'function' and value(...) or value
|
||||
return value and type(value) == "function" and value(...) or value
|
||||
end
|
||||
|
||||
--- Converts a varible into its boolean value, nil and false return false
|
||||
@@ -190,8 +191,8 @@ 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
|
||||
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.
|
||||
@@ -218,7 +219,7 @@ write_json('dump', tbl)
|
||||
|
||||
]]
|
||||
function Common.write_json(path, tbl)
|
||||
game.write_file(path, game.table_to_json(tbl)..'\n', true, 0)
|
||||
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
|
||||
@@ -232,8 +233,11 @@ 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
|
||||
if success then
|
||||
return rtn
|
||||
else
|
||||
return nil, rtn
|
||||
end
|
||||
end
|
||||
|
||||
--[[-- Returns a desync safe file path for the current file
|
||||
@@ -246,7 +250,7 @@ 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)
|
||||
return debug.getinfo(offset + 2, "S").short_src:sub(10, -5)
|
||||
end
|
||||
|
||||
--[[-- Converts a table to an enum
|
||||
@@ -264,18 +268,21 @@ local colors = enum{
|
||||
function Common.enum(tbl)
|
||||
local rtn = {}
|
||||
for k, v in pairs(tbl) do
|
||||
if type(k) ~= 'number' then
|
||||
rtn[v]=k
|
||||
if type(k) ~= "number" then
|
||||
rtn[v] = k
|
||||
end
|
||||
end
|
||||
|
||||
for k, v in pairs(tbl) do
|
||||
if type(k) == 'number' then
|
||||
if type(k) == "number" then
|
||||
table.insert(rtn, v)
|
||||
end
|
||||
end
|
||||
|
||||
for k, v in pairs(rtn) do
|
||||
rtn[v]=k
|
||||
rtn[v] = k
|
||||
end
|
||||
|
||||
return rtn
|
||||
end
|
||||
|
||||
@@ -297,7 +304,7 @@ 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
|
||||
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
|
||||
@@ -319,7 +326,7 @@ local player_name = get_actor()
|
||||
|
||||
]]
|
||||
function Common.get_actor(player_name)
|
||||
return game.player and game.player.name or player_name or '<server>'
|
||||
return game.player and game.player.name or player_name or "<server>"
|
||||
end
|
||||
|
||||
--[[-- Returns a message with valid chat tags to change its colour
|
||||
@@ -333,8 +340,8 @@ 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)
|
||||
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
|
||||
@@ -348,8 +355,8 @@ local message = format_chat_colour_localized('Hello, World!', { r=355, g=100, b=
|
||||
]]
|
||||
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}
|
||||
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
|
||||
@@ -363,7 +370,7 @@ 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_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)
|
||||
@@ -388,37 +395,41 @@ 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
|
||||
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 returnAsString
|
||||
if Common.type_check(value, 'table') or type(value) == 'userdata' then
|
||||
if Common.type_check(value.__self, 'userdata') or type(value) == 'userdata' then
|
||||
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
|
||||
returnAsString = 'Cant Display Userdata'
|
||||
elseif Common.type_check(value[1], 'string') and string.find(value[1], '.+[.].+') and not string.find(value[1], '%s') then
|
||||
returnAsString = "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
|
||||
returnAsString = value
|
||||
elseif getmetatable(value) ~= nil and not tostring(value):find('table: 0x') then
|
||||
elseif getmetatable(value) ~= nil and not tostring(value):find("table: 0x") then
|
||||
-- value has a tostring meta method
|
||||
returnAsString = tostring(value)
|
||||
else
|
||||
-- value is a table
|
||||
returnAsString = table.inspect(value, {depth=5, indent=' ', newline='\n'})
|
||||
returnAsString = table.inspect(value, { depth = 5, indent = " ", newline = "\n" })
|
||||
end
|
||||
elseif Common.type_check(value, 'function') then
|
||||
elseif Common.type_check(value, "function") then
|
||||
-- value is a function
|
||||
returnAsString = 'Cant Display Functions'
|
||||
else returnAsString = tostring(value) end
|
||||
returnAsString = "Cant Display Functions"
|
||||
else
|
||||
returnAsString = 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
|
||||
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.play_sound{ path = "utility/scenario_message" }
|
||||
player.print(returnAsString, colour)
|
||||
else rcon.print(returnAsString) end
|
||||
else
|
||||
rcon.print(returnAsString)
|
||||
end
|
||||
end
|
||||
|
||||
--[[-- Formats tick into a clean format, denominations from highest to lowest
|
||||
@@ -444,78 +455,78 @@ local time = format_time(18000, { hours=true, minutes=true, seconds=true, string
|
||||
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
|
||||
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
|
||||
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), math.floor(hours), math.floor(minutes), math.floor(seconds)
|
||||
if not options.days then
|
||||
rtn_hours = rtn_hours + rtn_days*24
|
||||
rtn_hours = rtn_hours + rtn_days * 24
|
||||
end
|
||||
if not options.hours then
|
||||
rtn_minutes = rtn_minutes + rtn_hours*60
|
||||
rtn_minutes = rtn_minutes + rtn_hours * 60
|
||||
end
|
||||
if not options.minutes then
|
||||
rtn_seconds = rtn_seconds + rtn_minutes*60
|
||||
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='--'
|
||||
rtn_days = "--"
|
||||
rtn_hours = "--"
|
||||
rtn_minutes = "--"
|
||||
rtn_seconds = "--"
|
||||
end
|
||||
-- Format options
|
||||
local suffix = 'time-symbol-'
|
||||
local suffix_2 = '-short'
|
||||
local suffix = "time-symbol-"
|
||||
local suffix_2 = "-short"
|
||||
if options.long then
|
||||
suffix = ''
|
||||
suffix_2 = ''
|
||||
suffix = ""
|
||||
suffix_2 = ""
|
||||
end
|
||||
local div = options.string and ' ' or 'time-format.simple-format-tagged'
|
||||
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'
|
||||
div = options.string and ":" or "time-format.simple-format-div"
|
||||
suffix = false
|
||||
end
|
||||
-- Adds formatting
|
||||
if suffix ~= false then
|
||||
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'
|
||||
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}
|
||||
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)
|
||||
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
|
||||
rtn = rtn and rtn .. div .. value or value
|
||||
elseif dom then
|
||||
rtn = rtn and {div, rtn, value} or value
|
||||
rtn = rtn and { div, rtn, value } or value
|
||||
end
|
||||
end
|
||||
append(options.days, rtn_days)
|
||||
@@ -542,51 +553,52 @@ 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
|
||||
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
|
||||
@@ -603,23 +615,23 @@ 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]
|
||||
chest_type = chest_type or "steel-chest"
|
||||
surface = surface or game.surfaces[1]
|
||||
|
||||
if position and type(position) ~= 'table' then
|
||||
if position and type(position) ~= "table" then
|
||||
return
|
||||
end
|
||||
|
||||
if type(items) ~= 'table' then
|
||||
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
|
||||
-- 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
|
||||
@@ -664,7 +676,7 @@ function Common.move_items_stack(items, surface, position, radius, chest_type)
|
||||
]]
|
||||
|
||||
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'}
|
||||
last_entity = surface.create_entity{ name = chest_type, position = pos, force = "neutral" }
|
||||
|
||||
count = count + 1
|
||||
entities[count] = last_entity
|
||||
@@ -675,63 +687,63 @@ function Common.move_items_stack(items, surface, position, radius, chest_type)
|
||||
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
|
||||
-- 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
|
||||
return chest
|
||||
end
|
||||
|
||||
-- Function used to round robin the items into all chests
|
||||
local function next_chest(item)
|
||||
local chest = entities[current]
|
||||
-- Function used to round robin the items into all chests
|
||||
local function next_chest(item)
|
||||
local chest = entities[current]
|
||||
|
||||
if count == 0 then
|
||||
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
|
||||
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
|
||||
return chest
|
||||
|
||||
else
|
||||
-- Other wise it is removed from the list
|
||||
table.remove(entities, current)
|
||||
count = count - 1
|
||||
end
|
||||
end
|
||||
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
|
||||
-- Inserts the items into the chests
|
||||
local last_chest
|
||||
|
||||
for i=1,#items do
|
||||
local item = items[i]
|
||||
for i=1,#items do
|
||||
local item = items[i]
|
||||
|
||||
if item.valid_for_read then
|
||||
local chest = next_chest(item)
|
||||
local chest = next_chest(item)
|
||||
|
||||
if not chest or not chest.valid then
|
||||
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)
|
||||
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
|
||||
empty_stack.transfer_stack(item)
|
||||
last_chest = chest
|
||||
end
|
||||
end
|
||||
return last_chest
|
||||
]]
|
||||
|
||||
@@ -753,34 +765,34 @@ 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 is_string = type(value) == "string"
|
||||
local color = Colours.white
|
||||
local text = value
|
||||
|
||||
if type(immutable) ~= 'boolean' then
|
||||
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)
|
||||
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}
|
||||
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'
|
||||
text = "0.00"
|
||||
end
|
||||
end
|
||||
|
||||
if not immutable then
|
||||
local text_entity = surface.find_entity('flying-text', position)
|
||||
local text_entity = surface.find_entity("flying-text", position)
|
||||
|
||||
if text_entity then
|
||||
text_entity.text = text
|
||||
@@ -790,10 +802,10 @@ function Common.print_grid_value(value, surface, position, scale, offset, immuta
|
||||
end
|
||||
|
||||
surface.create_entity{
|
||||
name = 'flying-text',
|
||||
name = "flying-text",
|
||||
color = color,
|
||||
text = text,
|
||||
position = position
|
||||
position = position,
|
||||
}.active = false
|
||||
end
|
||||
|
||||
@@ -805,7 +817,7 @@ clear_flying_text(game.player.surface)
|
||||
|
||||
]]
|
||||
function Common.clear_flying_text(surface)
|
||||
local entities = surface.find_entities_filtered{name ='flying-text'}
|
||||
local entities = surface.find_entities_filtered{ name = "flying-text" }
|
||||
for _, entity in pairs(entities) do
|
||||
if entity and entity.valid then
|
||||
entity.destroy()
|
||||
|
||||
@@ -169,8 +169,8 @@ end)
|
||||
--- Metatable used on datastores
|
||||
DatastoreManager.metatable = {
|
||||
__index = function(self, key) return rawget(self.children, key) or rawget(Datastore, key) end,
|
||||
__newidnex = function(_, _, _) error('Datastore can not be modified', 2) end,
|
||||
__call = function(self, ...) return self:get(...) end
|
||||
__newidnex = function(_, _, _) error("Datastore can not be modified", 2) end,
|
||||
__call = function(self, ...) return self:get(...) end,
|
||||
}
|
||||
|
||||
--[[-- Make a new datastore connection, if a connection already exists then it is returned
|
||||
@@ -188,7 +188,7 @@ function DatastoreManager.connect(datastoreName, saveToDisk, autoSave, propagate
|
||||
if Datastores[datastoreName] then return Datastores[datastoreName] end
|
||||
if package.lifecycle ~= package.lifecycle_stage.control then
|
||||
-- Only allow this function to be called during the control stage
|
||||
error('New datastore connection can not be created during runtime', 2)
|
||||
error("New datastore connection can not be created during runtime", 2)
|
||||
end
|
||||
|
||||
local new_datastore = {
|
||||
@@ -202,7 +202,7 @@ function DatastoreManager.connect(datastoreName, saveToDisk, autoSave, propagate
|
||||
children = {},
|
||||
metadata = {},
|
||||
events = {},
|
||||
data = {}
|
||||
data = {},
|
||||
}
|
||||
|
||||
Data[datastoreName] = new_datastore.data
|
||||
@@ -220,7 +220,7 @@ local BarData = Datastore.combine('ExampleData', 'Bar')
|
||||
|
||||
]]
|
||||
function DatastoreManager.combine(datastoreName, subDatastoreName)
|
||||
local datastore = assert(Datastores[datastoreName], 'Datastore not found '..tostring(datastoreName))
|
||||
local datastore = assert(Datastores[datastoreName], "Datastore not found " .. tostring(datastoreName))
|
||||
return datastore:combine(subDatastoreName)
|
||||
end
|
||||
|
||||
@@ -235,27 +235,23 @@ Datastore.ingest('request', 'ExampleData', 'TestKey', 'Foo')
|
||||
|
||||
]]
|
||||
function DatastoreManager.ingest(action, datastoreName, key, valueJson)
|
||||
local datastore = assert(Datastores[datastoreName], 'Datastore ingest error, Datastore not found '..tostring(datastoreName))
|
||||
assert(type(action) == 'string', 'Datastore ingest error, Action is not a string got: '..type(action))
|
||||
assert(type(key) == 'string', 'Datastore ingest error, Key is not a string got: '..type(key))
|
||||
local datastore = assert(Datastores[datastoreName], "Datastore ingest error, Datastore not found " .. tostring(datastoreName))
|
||||
assert(type(action) == "string", "Datastore ingest error, Action is not a string got: " .. type(action))
|
||||
assert(type(key) == "string", "Datastore ingest error, Key is not a string got: " .. type(key))
|
||||
|
||||
if action == 'remove' then
|
||||
if action == "remove" then
|
||||
datastore:raw_set(key)
|
||||
|
||||
elseif action == 'message' then
|
||||
elseif action == "message" then
|
||||
local success, value = pcall(game.json_to_table, valueJson)
|
||||
if not success or value == nil then value = tonumber(valueJson) or valueJson end
|
||||
datastore:raise_event('on_message', key, value)
|
||||
|
||||
elseif action == 'propagate' or action == 'request' then
|
||||
datastore:raise_event("on_message", key, value)
|
||||
elseif action == "propagate" or action == "request" then
|
||||
local success, value = pcall(game.json_to_table, valueJson)
|
||||
if not success or value == nil then value = tonumber(valueJson) or valueJson end
|
||||
local old_value = datastore:raw_get(key)
|
||||
value = datastore:raise_event('on_load', key, value, old_value)
|
||||
value = datastore:raise_event("on_load", key, value, old_value)
|
||||
datastore:set(key, value)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[-- Debug, Use to get all datastores, or return debug info on a datastore
|
||||
@@ -270,7 +266,7 @@ local debug_info = Datastore.debug('ExampleData')
|
||||
]]
|
||||
function DatastoreManager.debug(datastoreName)
|
||||
if not datastoreName then return Datastores end
|
||||
local datastore = assert(Datastores[datastoreName], 'Datastore not found '..tostring(datastoreName))
|
||||
local datastore = assert(Datastores[datastoreName], "Datastore not found " .. tostring(datastoreName))
|
||||
return datastore:debug()
|
||||
end
|
||||
|
||||
@@ -308,11 +304,13 @@ function Datastore:debug()
|
||||
end
|
||||
|
||||
local children = {}
|
||||
for name in pairs(self.children) do children[#children+1] = name end
|
||||
for name in pairs(self.children) do children[#children + 1] = name end
|
||||
|
||||
if #children > 0 then debug_info.children = children end
|
||||
|
||||
local events = {}
|
||||
for name, handlers in pairs(self.events) do events[name] = #handlers end
|
||||
|
||||
if next(events) then debug_info.events = events end
|
||||
|
||||
if next(self.metadata) then debug_info.metadata = self.metadata end
|
||||
@@ -334,7 +332,7 @@ function Datastore:raw_get(key, fromChild)
|
||||
local data = self.data
|
||||
if self.parent then
|
||||
data = self.parent:raw_get(key, true)
|
||||
key = self.value_name
|
||||
key = self.value_name
|
||||
end
|
||||
local value = data[key]
|
||||
if value ~= nil then return value end
|
||||
@@ -360,7 +358,7 @@ function Datastore:raw_set(key, value)
|
||||
end
|
||||
end
|
||||
|
||||
local function serialize_error(err) error('An error ocurred in a datastore serializer: '..trace(err)) end
|
||||
local function serialize_error(err) error("An error ocurred in a datastore serializer: " .. trace(err)) end
|
||||
--[[-- Internal, Return the serialized key
|
||||
@tparam any rawKey The key that needs to be serialized, if it is already a string then it is returned
|
||||
@treturn string The key after it has been serialized
|
||||
@@ -370,8 +368,8 @@ key = self:serialize(key)
|
||||
|
||||
]]
|
||||
function Datastore:serialize(rawKey)
|
||||
if type(rawKey) == 'string' then return rawKey end
|
||||
assert(self.serializer, 'Datastore does not have a serializer and received non string key')
|
||||
if type(rawKey) == "string" then return rawKey end
|
||||
assert(self.serializer, "Datastore does not have a serializer and received non string key")
|
||||
local success, key = xpcall(self.serializer, serialize_error, rawKey)
|
||||
return success and key or nil
|
||||
end
|
||||
@@ -389,11 +387,11 @@ self:write_action('save', 'TestKey', 'Foo')
|
||||
|
||||
]]
|
||||
function Datastore:write_action(action, key, value)
|
||||
local data = {action, self.name, key}
|
||||
local data = { action, self.name, key }
|
||||
if value ~= nil then
|
||||
data[4] = type(value) == 'table' and game.table_to_json(value) or value
|
||||
data[4] = type(value) == "table" and game.table_to_json(value) or value
|
||||
end
|
||||
game.write_file('ext/datastore.out', table.concat(data, ' ')..'\n', true, 0)
|
||||
game.write_file("ext/datastore.out", table.concat(data, " ") .. "\n", true, 0)
|
||||
end
|
||||
|
||||
----- Datastore Local
|
||||
@@ -409,7 +407,7 @@ local BarData = ExampleData:combine('Bar')
|
||||
|
||||
]]
|
||||
function Datastore:combine(subDatastoreName)
|
||||
local new_datastore = DatastoreManager.connect(self.name..'.'..subDatastoreName)
|
||||
local new_datastore = DatastoreManager.connect(self.name .. "." .. subDatastoreName)
|
||||
self.children[subDatastoreName] = new_datastore
|
||||
new_datastore.value_name = subDatastoreName
|
||||
new_datastore.serializer = self.serializer
|
||||
@@ -431,7 +429,7 @@ end)
|
||||
|
||||
]]
|
||||
function Datastore:set_serializer(callback)
|
||||
assert(type(callback) == 'function', 'Callback must be a function')
|
||||
assert(type(callback) == "function", "Callback must be a function")
|
||||
self.serializer = callback
|
||||
end
|
||||
|
||||
@@ -501,7 +499,7 @@ function Datastore:set(key, value)
|
||||
else
|
||||
self:raw_set(key, value)
|
||||
end
|
||||
self:raise_event('on_update', key, value, old_value)
|
||||
self:raise_event("on_update", key, value, old_value)
|
||||
if self.auto_save then self:save(key) end
|
||||
return value
|
||||
end
|
||||
@@ -521,7 +519,7 @@ function Datastore:increment(key, delta)
|
||||
return self:set(key, value + (delta or 1))
|
||||
end
|
||||
|
||||
local function update_error(err) log('An error occurred in datastore update:\n\t'..trace(err)) end
|
||||
local function update_error(err) log("An error occurred in datastore update:\n\t" .. trace(err)) end
|
||||
--[[-- Use a function to update the value locally, will trigger on_update then on_save, save_to_disk and auto_save is required for on_save
|
||||
@tparam any key The key that you want to apply the update to, must be a string unless a serializer is set
|
||||
@tparam function callback The function that will be used to update the value at this key
|
||||
@@ -546,7 +544,7 @@ function Datastore:update(key, callback)
|
||||
elseif raw_value == nil then
|
||||
self:set(key, value)
|
||||
else
|
||||
self:raise_event('on_update', key, value, old_value)
|
||||
self:raise_event("on_update", key, value, old_value)
|
||||
if self.auto_save then self:save(key) end
|
||||
end
|
||||
end
|
||||
@@ -563,12 +561,12 @@ function Datastore:remove(key)
|
||||
key = self:serialize(key)
|
||||
local old_value = self:raw_get(key)
|
||||
self:raw_set(key)
|
||||
self:raise_event('on_update', key, nil, old_value)
|
||||
if self.save_to_disk then self:write_action('remove', key) end
|
||||
self:raise_event("on_update", key, nil, old_value)
|
||||
if self.save_to_disk then self:write_action("remove", key) end
|
||||
if self.parent and self.parent.auto_save then return self.parent:save(key) end
|
||||
end
|
||||
|
||||
local function filter_error(err) log('An error ocurred in a datastore filter:\n\t'..trace(err)) end
|
||||
local function filter_error(err) log("An error ocurred in a datastore filter:\n\t" .. trace(err)) end
|
||||
--[[-- Internal, Used to filter elements from a table
|
||||
@tparam table tbl The table that will have the filter applied to it
|
||||
@tparam[opt] function callback The function that will be used as a filter, if none giving then the provided table is returned
|
||||
@@ -587,6 +585,7 @@ local function filter(tbl, callback)
|
||||
local success, add = xpcall(callback, filter_error, key, value)
|
||||
if success and add then rtn[key] = value end
|
||||
end
|
||||
|
||||
return rtn
|
||||
end
|
||||
|
||||
@@ -613,6 +612,7 @@ function Datastore:get_all(callback)
|
||||
for key, value in pairs(self.parent:get_all()) do
|
||||
data[key] = value[value_name]
|
||||
end
|
||||
|
||||
return filter(data, callback)
|
||||
end
|
||||
end
|
||||
@@ -635,7 +635,7 @@ function Datastore:update_all(callback)
|
||||
if success and new_value ~= nil then
|
||||
self:set(key, new_value)
|
||||
else
|
||||
self:raise_event('on_update', key, value, old_value)
|
||||
self:raise_event("on_update", key, value, old_value)
|
||||
if self.auto_save then self:save(key) end
|
||||
end
|
||||
end
|
||||
@@ -655,7 +655,7 @@ ExampleData:request('TestKey')
|
||||
function Datastore:request(key)
|
||||
if self.parent then return self.parent:request(key) end
|
||||
key = self:serialize(key)
|
||||
self:write_action('request', key)
|
||||
self:write_action("request", key)
|
||||
end
|
||||
|
||||
--[[-- Save a value to an external source, will trigger on_save before data is saved, save_to_disk must be set to true
|
||||
@@ -670,8 +670,8 @@ function Datastore:save(key)
|
||||
if self.parent then self.parent:save(key) end
|
||||
if not self.save_to_disk then return end
|
||||
key = self:serialize(key)
|
||||
local value = self:raise_event('on_save', key, copy(self:raw_get(key)))
|
||||
local action = self.propagate_changes and 'propagate' or 'save'
|
||||
local value = self:raise_event("on_save", key, copy(self:raw_get(key)))
|
||||
local action = self.propagate_changes and "propagate" or "save"
|
||||
self:write_action(action, key, value)
|
||||
end
|
||||
|
||||
@@ -686,7 +686,7 @@ ExampleData:unload('TestKey')
|
||||
function Datastore:unload(key)
|
||||
if self.parent then return self.parent:unload(key) end
|
||||
key = self:serialize(key)
|
||||
self:raise_event('on_unload', key, copy(self:raw_get(key)))
|
||||
self:raise_event("on_unload", key, copy(self:raw_get(key)))
|
||||
self:save(key)
|
||||
self:raw_set(key)
|
||||
end
|
||||
@@ -702,7 +702,7 @@ ExampleData:message('TestKey', 'Foo')
|
||||
]]
|
||||
function Datastore:message(key, message)
|
||||
key = self:serialize(key)
|
||||
self:write_action('message', key, message)
|
||||
self:write_action("message", key, message)
|
||||
end
|
||||
|
||||
--[[-- Save all the keys in the datastore, optional filter callback
|
||||
@@ -746,7 +746,7 @@ end
|
||||
----- Events
|
||||
-- @section events
|
||||
|
||||
local function event_error(err) log('An error ocurred in a datastore event handler:\n\t'..trace(err)) end
|
||||
local function event_error(err) log("An error ocurred in a datastore event handler:\n\t" .. trace(err)) end
|
||||
--[[-- Internal, Raise an event on this datastore
|
||||
@tparam string event_name The name of the event to raise for this datastore
|
||||
@tparam string key The key that this event is being raised for
|
||||
@@ -761,11 +761,11 @@ value = self:raise_event('on_save', key, value)
|
||||
]]
|
||||
function Datastore:raise_event(event_name, key, value, old_value, source)
|
||||
-- Raise the event for the children of this datastore
|
||||
if source ~= 'child' and next(self.children) then
|
||||
if type(value) ~= 'table' then value = {} end
|
||||
if source ~= "child" and next(self.children) then
|
||||
if type(value) ~= "table" then value = {} end
|
||||
for value_name, child in pairs(self.children) do
|
||||
local old_child_value = old_value and old_value[value_name] or nil
|
||||
value[value_name] = child:raise_event(event_name, key, value[value_name], old_child_value, 'parent')
|
||||
value[value_name] = child:raise_event(event_name, key, value[value_name], old_child_value, "parent")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -779,13 +779,13 @@ function Datastore:raise_event(event_name, key, value, old_value, source)
|
||||
end
|
||||
|
||||
-- Raise the event for the parent of this datastore
|
||||
if source ~= 'parent' and self.parent then
|
||||
if source ~= "parent" and self.parent then
|
||||
local parent_value = self.parent:raw_get(key, true)
|
||||
self.parent:raise_event(event_name, key, parent_value, parent_value, 'child')
|
||||
self.parent:raise_event(event_name, key, parent_value, parent_value, "child")
|
||||
end
|
||||
|
||||
-- If this is the save event and the table is empty then return nil
|
||||
if event_name == 'on_save' and next(self.children) and not next(value) then return end
|
||||
if event_name == "on_save" and next(self.children) and not next(value) then return end
|
||||
return value
|
||||
end
|
||||
|
||||
@@ -799,12 +799,12 @@ Datastore.on_load = event_factory('on_load')
|
||||
]]
|
||||
local function event_factory(event_name)
|
||||
return function(self, callback)
|
||||
assert(type(callback) == 'function', 'Handler must be a function')
|
||||
assert(type(callback) == "function", "Handler must be a function")
|
||||
local handlers = self.events[event_name]
|
||||
if not handlers then
|
||||
self.events[event_name] = { callback }
|
||||
else
|
||||
handlers[#handlers+1] = callback
|
||||
handlers[#handlers + 1] = callback
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -817,7 +817,7 @@ ExampleData:on_load(function(key, value)
|
||||
game.print('Test data loaded for: '..key)
|
||||
end)
|
||||
]]
|
||||
Datastore.on_load = event_factory('on_load')
|
||||
Datastore.on_load = event_factory("on_load")
|
||||
|
||||
--[[-- Register a callback that triggers before data is saved, returned value is saved externally
|
||||
@tparam function callback The handler that will be registered to the on_load event
|
||||
@@ -827,7 +827,7 @@ ExampleData:on_save(function(key, value)
|
||||
game.print('Test data saved for: '..key)
|
||||
end)
|
||||
]]
|
||||
Datastore.on_save = event_factory('on_save')
|
||||
Datastore.on_save = event_factory("on_save")
|
||||
|
||||
--[[-- Register a callback that triggers before data is unloaded, returned value is ignored
|
||||
@tparam function callback The handler that will be registered to the on_load event
|
||||
@@ -837,7 +837,7 @@ ExampleData:on_load(function(key, value)
|
||||
game.print('Test data unloaded for: '..key)
|
||||
end)
|
||||
]]
|
||||
Datastore.on_unload = event_factory('on_unload')
|
||||
Datastore.on_unload = event_factory("on_unload")
|
||||
|
||||
--[[-- Register a callback that triggers when a message is received, returned value is ignored
|
||||
@tparam function callback The handler that will be registered to the on_load event
|
||||
@@ -847,7 +847,7 @@ ExampleData:on_message(function(key, value)
|
||||
game.print('Test data message for: '..key)
|
||||
end)
|
||||
]]
|
||||
Datastore.on_message = event_factory('on_message')
|
||||
Datastore.on_message = event_factory("on_message")
|
||||
|
||||
--[[-- Register a callback that triggers any time a value is changed, returned value is ignored
|
||||
@tparam function callback The handler that will be registered to the on_load event
|
||||
@@ -857,7 +857,7 @@ ExampleData:on_update(function(key, value)
|
||||
game.print('Test data updated for: '..key)
|
||||
end)
|
||||
]]
|
||||
Datastore.on_update = event_factory('on_update')
|
||||
Datastore.on_update = event_factory("on_update")
|
||||
|
||||
----- Module Return
|
||||
return DatastoreManager
|
||||
|
||||
@@ -47,8 +47,8 @@ local servers = External.get_servers()
|
||||
|
||||
]]
|
||||
function External.get_servers()
|
||||
assert(ext, 'No external data was found, use External.valid() to ensure external data exists.')
|
||||
return assert(ext.servers, 'No server list was found, please ensure that the external service is running')
|
||||
assert(ext, "No external data was found, use External.valid() to ensure external data exists.")
|
||||
return assert(ext.servers, "No server list was found, please ensure that the external service is running")
|
||||
end
|
||||
|
||||
--[[-- Gets a table of all the servers filtered by name, key is the server id, value is the server details
|
||||
@@ -60,14 +60,15 @@ local servers = External.get_servers_filtered(public)
|
||||
|
||||
]]
|
||||
function External.get_servers_filtered(search)
|
||||
assert(ext, 'No external data was found, use External.valid() to ensure external data exists.')
|
||||
local servers = assert(ext.servers, 'No server list was found, please ensure that the external service is running')
|
||||
assert(ext, "No external data was found, use External.valid() to ensure external data exists.")
|
||||
local servers = assert(ext.servers, "No server list was found, please ensure that the external service is running")
|
||||
local found_servers = {}
|
||||
search = search:lower()
|
||||
for server_id, server in pairs(servers) do
|
||||
local str = concat{server.name, server.short_name, server.id}
|
||||
local str = concat{ server.name, server.short_name, server.id }
|
||||
if str:lower():find(search, 1, true) then found_servers[server_id] = server end
|
||||
end
|
||||
|
||||
return found_servers
|
||||
end
|
||||
|
||||
@@ -79,9 +80,9 @@ local server = External.get_current_server()
|
||||
|
||||
]]
|
||||
function External.get_current_server()
|
||||
assert(ext, 'No external data was found, use External.valid() to ensure external data exists.')
|
||||
local servers = assert(ext.servers, 'No server list was found, please ensure that the external service is running')
|
||||
local server_id = assert(ext.current, 'No current id was found, please ensure that the external service is running')
|
||||
assert(ext, "No external data was found, use External.valid() to ensure external data exists.")
|
||||
local servers = assert(ext.servers, "No server list was found, please ensure that the external service is running")
|
||||
local server_id = assert(ext.current, "No current id was found, please ensure that the external service is running")
|
||||
return servers[server_id]
|
||||
end
|
||||
|
||||
@@ -94,8 +95,8 @@ local server = External.get_server_details('eu-01')
|
||||
|
||||
]]
|
||||
function External.get_server_details(server_id)
|
||||
assert(ext, 'No external data was found, use External.valid() to ensure external data exists.')
|
||||
local servers = assert(ext.servers, 'No server list was found, please ensure that the external service is running')
|
||||
assert(ext, "No external data was found, use External.valid() to ensure external data exists.")
|
||||
local servers = assert(ext.servers, "No server list was found, please ensure that the external service is running")
|
||||
return servers[server_id]
|
||||
end
|
||||
|
||||
@@ -109,10 +110,10 @@ local status = External.get_server_status('eu-01')
|
||||
|
||||
]]
|
||||
function External.get_server_status(server_id, raw)
|
||||
assert(var, 'No external data was found, use External.valid() to ensure external data exists.')
|
||||
local servers = assert(var.status, 'No server status was found, please ensure that the external service is running')
|
||||
local current = assert(ext.current, 'No current id was found, please ensure that the external service is running')
|
||||
return not raw and server_id == current and 'Current' or servers[server_id]
|
||||
assert(var, "No external data was found, use External.valid() to ensure external data exists.")
|
||||
local servers = assert(var.status, "No server status was found, please ensure that the external service is running")
|
||||
local current = assert(ext.current, "No current id was found, please ensure that the external service is running")
|
||||
return not raw and server_id == current and "Current" or servers[server_id]
|
||||
end
|
||||
|
||||
--[[-- Gets the ups of the current server
|
||||
@@ -121,8 +122,8 @@ local server_ups = External.get_server_ups()
|
||||
|
||||
]]
|
||||
function External.get_server_ups()
|
||||
assert(var, 'No external data was found, use External.valid() to ensure external data exists.')
|
||||
return assert(var.server_ups, 'No server ups was found, please ensure that the external service is running')
|
||||
assert(var, "No external data was found, use External.valid() to ensure external data exists.")
|
||||
return assert(var.server_ups, "No server ups was found, please ensure that the external service is running")
|
||||
end
|
||||
|
||||
--[[-- Connect a player to the given server
|
||||
@@ -138,16 +139,16 @@ External.request_connection(player, 'eu-01', true)
|
||||
|
||||
]]
|
||||
function External.request_connection(player, server_id, self_requested)
|
||||
local server = { address = server_id, name = 'Unknown Server', description = 'This server is not ran by us, please check the address of the server.' }
|
||||
local server = { address = server_id, name = "Unknown Server", description = "This server is not ran by us, please check the address of the server." }
|
||||
if ext and ext.servers and ext.servers[server_id] then server = ext.servers[server_id] end
|
||||
local message = 'Please press the connect button below to join.'
|
||||
if not self_requested then message = 'You have been asked to switch to a different server.\n'..message end
|
||||
local message = "Please press the connect button below to join."
|
||||
if not self_requested then message = "You have been asked to switch to a different server.\n" .. message end
|
||||
player.connect_to_server{
|
||||
address = server.address,
|
||||
name = '\n[color=orange][font=heading-1]'..server.name..'[/font][/color]\n',
|
||||
description = server.description..'\n'..message
|
||||
name = "\n[color=orange][font=heading-1]" .. server.name .. "[/font][/color]\n",
|
||||
description = server.description .. "\n" .. message,
|
||||
}
|
||||
end
|
||||
|
||||
--- Module return
|
||||
return External
|
||||
return External
|
||||
|
||||
@@ -132,13 +132,12 @@ local Roles = _C.opt_require("modules.exp_legacy.expcore.roles")
|
||||
local Event = _C.opt_require("modules/exp_legacy/utils/event")
|
||||
|
||||
if Roles and Event then
|
||||
Event.add(Roles.events.on_role_assigned, function(e)
|
||||
Gui.update_top_flow(game.get_player(e.player_index))
|
||||
end)
|
||||
Event.add(Roles.events.on_role_unassigned, function(e)
|
||||
Gui.update_top_flow(game.get_player(e.player_index))
|
||||
end)
|
||||
Event.add(Roles.events.on_role_assigned, function(e)
|
||||
Gui.update_top_flow(game.get_player(e.player_index))
|
||||
end)
|
||||
Event.add(Roles.events.on_role_unassigned, function(e)
|
||||
Gui.update_top_flow(game.get_player(e.player_index))
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
return Gui
|
||||
return Gui
|
||||
|
||||
@@ -12,61 +12,61 @@ local Event = require("modules/exp_legacy/utils/event")
|
||||
--- Button which toggles the top flow elements, version which shows inside the top flow when top flow is visible
|
||||
-- @element hide_top_flow
|
||||
local hide_top_flow =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/preset',
|
||||
style = 'tool_button',
|
||||
tooltip = {'gui_util.button_tooltip'},
|
||||
name = Gui.unique_static_name
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 18,
|
||||
height = 36
|
||||
}
|
||||
:on_click(function(player, _,_)
|
||||
Gui.toggle_top_flow(player, false)
|
||||
end)
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/preset",
|
||||
style = "tool_button",
|
||||
tooltip = { "gui_util.button_tooltip" },
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 18,
|
||||
height = 36,
|
||||
}
|
||||
:on_click(function(player, _, _)
|
||||
Gui.toggle_top_flow(player, false)
|
||||
end)
|
||||
Gui.core_defines.hide_top_flow = hide_top_flow
|
||||
|
||||
--- Button which toggles the top flow elements, version which shows inside the left flow when top flow is hidden
|
||||
-- @element show_top_flow
|
||||
local show_top_flow =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/preset',
|
||||
style = 'tool_button',
|
||||
tooltip = {'gui_util.button_tooltip'},
|
||||
name = Gui.unique_static_name
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 18,
|
||||
height = 20
|
||||
}
|
||||
:on_click(function(player, _,_)
|
||||
Gui.toggle_top_flow(player, true)
|
||||
end)
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/preset",
|
||||
style = "tool_button",
|
||||
tooltip = { "gui_util.button_tooltip" },
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 18,
|
||||
height = 20,
|
||||
}
|
||||
:on_click(function(player, _, _)
|
||||
Gui.toggle_top_flow(player, true)
|
||||
end)
|
||||
Gui.core_defines.show_top_flow = show_top_flow
|
||||
|
||||
--- Button which hides the elements in the left flow, shows inside the left flow when frames are visible
|
||||
-- @element hide_left_flow
|
||||
local hide_left_flow =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = 'utility/close_black',
|
||||
style = 'tool_button',
|
||||
tooltip = {'expcore-gui.left-button-tooltip'},
|
||||
name = Gui.unique_static_name
|
||||
}
|
||||
:style{
|
||||
padding = -3,
|
||||
width = 18,
|
||||
height = 20
|
||||
}
|
||||
:on_click(function(player, _,_)
|
||||
Gui.hide_left_flow(player)
|
||||
end)
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/close_black",
|
||||
style = "tool_button",
|
||||
tooltip = { "expcore-gui.left-button-tooltip" },
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style{
|
||||
padding = -3,
|
||||
width = 18,
|
||||
height = 20,
|
||||
}
|
||||
:on_click(function(player, _, _)
|
||||
Gui.hide_left_flow(player)
|
||||
end)
|
||||
Gui.core_defines.hide_left_flow = hide_left_flow
|
||||
|
||||
--- Draw the core elements when a player joins the game
|
||||
@@ -80,10 +80,10 @@ Event.add(defines.events.on_player_created, function(event)
|
||||
|
||||
-- Draw the left flow
|
||||
local left_flow = Gui.get_left_flow(player)
|
||||
local button_flow = left_flow.add{ type = 'flow', name = 'gui_core_buttons', direction = 'vertical' }
|
||||
local button_flow = left_flow.add{ type = "flow", name = "gui_core_buttons", direction = "vertical" }
|
||||
local show_top = show_top_flow(button_flow)
|
||||
local hide_left = hide_left_flow(button_flow)
|
||||
show_top.visible = false
|
||||
hide_left.visible = false
|
||||
Gui.draw_left_flow(player)
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -24,19 +24,19 @@ local alignment = Gui.alignment(element, 'example_center_top_alignment', 'center
|
||||
|
||||
]]
|
||||
Gui.alignment =
|
||||
Gui.element(function(_, parent, name, _,_)
|
||||
return parent.add{
|
||||
name = name or 'alignment',
|
||||
type = 'flow',
|
||||
}
|
||||
end)
|
||||
:style(function(style, _,_, horizontal_align, vertical_align)
|
||||
style.padding = {1, 2}
|
||||
style.vertical_align = vertical_align or 'center'
|
||||
style.horizontal_align = horizontal_align or 'right'
|
||||
style.vertically_stretchable = style.vertical_align ~= 'center'
|
||||
style.horizontally_stretchable = style.horizontal_align ~= 'center'
|
||||
end)
|
||||
Gui.element(function(_, parent, name, _, _)
|
||||
return parent.add{
|
||||
name = name or "alignment",
|
||||
type = "flow",
|
||||
}
|
||||
end)
|
||||
:style(function(style, _, _, horizontal_align, vertical_align)
|
||||
style.padding = { 1, 2 }
|
||||
style.vertical_align = vertical_align or "center"
|
||||
style.horizontal_align = horizontal_align or "right"
|
||||
style.vertically_stretchable = style.vertical_align ~= "center"
|
||||
style.horizontally_stretchable = style.horizontal_align ~= "center"
|
||||
end)
|
||||
|
||||
--[[-- Draw a scroll pane that has a table inside of it
|
||||
@element Gui.scroll_table
|
||||
@@ -51,42 +51,42 @@ local scroll_table = Gui.scroll_table(element, 200, 3)
|
||||
|
||||
]]
|
||||
Gui.scroll_table =
|
||||
Gui.element(function(_, parent, height, column_count, name)
|
||||
-- Draw the scroll
|
||||
local scroll_pane =
|
||||
parent.add{
|
||||
name = name or 'scroll',
|
||||
type = 'scroll-pane',
|
||||
direction = 'vertical',
|
||||
horizontal_scroll_policy = 'never',
|
||||
vertical_scroll_policy = 'auto',
|
||||
style = 'scroll_pane_under_subheader'
|
||||
Gui.element(function(_, parent, height, column_count, name)
|
||||
-- Draw the scroll
|
||||
local scroll_pane =
|
||||
parent.add{
|
||||
name = name or "scroll",
|
||||
type = "scroll-pane",
|
||||
direction = "vertical",
|
||||
horizontal_scroll_policy = "never",
|
||||
vertical_scroll_policy = "auto",
|
||||
style = "scroll_pane_under_subheader",
|
||||
}
|
||||
|
||||
-- Set the style of the scroll pane
|
||||
local scroll_style = scroll_pane.style
|
||||
scroll_style.padding = { 1, 3 }
|
||||
scroll_style.maximal_height = height
|
||||
scroll_style.horizontally_stretchable = true
|
||||
|
||||
-- Draw the table
|
||||
local scroll_table =
|
||||
scroll_pane.add{
|
||||
type = "table",
|
||||
name = "table",
|
||||
column_count = column_count,
|
||||
}
|
||||
|
||||
-- Return the scroll table
|
||||
return scroll_table
|
||||
end)
|
||||
:style{
|
||||
padding = 0,
|
||||
cell_padding = 0,
|
||||
vertical_align = "center",
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
|
||||
-- Set the style of the scroll pane
|
||||
local scroll_style = scroll_pane.style
|
||||
scroll_style.padding = {1, 3}
|
||||
scroll_style.maximal_height = height
|
||||
scroll_style.horizontally_stretchable = true
|
||||
|
||||
-- Draw the table
|
||||
local scroll_table =
|
||||
scroll_pane.add{
|
||||
type = 'table',
|
||||
name = 'table',
|
||||
column_count = column_count
|
||||
}
|
||||
|
||||
-- Return the scroll table
|
||||
return scroll_table
|
||||
end)
|
||||
:style{
|
||||
padding = 0,
|
||||
cell_padding = 0,
|
||||
vertical_align = 'center',
|
||||
horizontally_stretchable = true
|
||||
}
|
||||
|
||||
--[[-- Used to add a frame with the header style, has the option for a right alignment flow for buttons
|
||||
@element Gui.header
|
||||
@tparam LuaGuiElement parent the parent element to which the header will be added
|
||||
@@ -105,35 +105,35 @@ local header = Gui.header(
|
||||
|
||||
]]
|
||||
Gui.header =
|
||||
Gui.element(function(_, parent, caption, tooltip, add_alignment, name, label_name)
|
||||
-- Draw the header
|
||||
local header =
|
||||
parent.add{
|
||||
name = name or 'header',
|
||||
type = 'frame',
|
||||
style = 'subheader_frame'
|
||||
}
|
||||
Gui.element(function(_, parent, caption, tooltip, add_alignment, name, label_name)
|
||||
-- Draw the header
|
||||
local header =
|
||||
parent.add{
|
||||
name = name or "header",
|
||||
type = "frame",
|
||||
style = "subheader_frame",
|
||||
}
|
||||
|
||||
-- Change the style of the header
|
||||
local style = header.style
|
||||
style.padding = {2, 4}
|
||||
style.use_header_filler = false
|
||||
style.horizontally_stretchable = true
|
||||
-- Change the style of the header
|
||||
local style = header.style
|
||||
style.padding = { 2, 4 }
|
||||
style.use_header_filler = false
|
||||
style.horizontally_stretchable = true
|
||||
|
||||
-- Draw the caption label
|
||||
if caption then
|
||||
header.add{
|
||||
name = label_name or 'header_label',
|
||||
type = 'label',
|
||||
style = 'frame_title',
|
||||
caption = caption,
|
||||
tooltip = tooltip
|
||||
}
|
||||
end
|
||||
-- Draw the caption label
|
||||
if caption then
|
||||
header.add{
|
||||
name = label_name or "header_label",
|
||||
type = "label",
|
||||
style = "frame_title",
|
||||
caption = caption,
|
||||
tooltip = tooltip,
|
||||
}
|
||||
end
|
||||
|
||||
-- Return either the header or the added alignment
|
||||
return add_alignment and Gui.alignment(header) or header
|
||||
end)
|
||||
-- Return either the header or the added alignment
|
||||
return add_alignment and Gui.alignment(header) or header
|
||||
end)
|
||||
|
||||
--[[-- Used to add a frame with the footer style, has the option for a right alignment flow for buttons
|
||||
@element Gui.footer
|
||||
@@ -153,35 +153,35 @@ local footer = Gui.footer(
|
||||
|
||||
]]
|
||||
Gui.footer =
|
||||
Gui.element(function(_, parent, caption, tooltip, add_alignment, name)
|
||||
-- Draw the header
|
||||
local footer =
|
||||
parent.add{
|
||||
name = name or 'footer',
|
||||
type = 'frame',
|
||||
style = 'subfooter_frame'
|
||||
}
|
||||
Gui.element(function(_, parent, caption, tooltip, add_alignment, name)
|
||||
-- Draw the header
|
||||
local footer =
|
||||
parent.add{
|
||||
name = name or "footer",
|
||||
type = "frame",
|
||||
style = "subfooter_frame",
|
||||
}
|
||||
|
||||
-- Change the style of the footer
|
||||
local style = footer.style
|
||||
style.padding = {2, 4}
|
||||
style.use_header_filler = false
|
||||
style.horizontally_stretchable = true
|
||||
-- Change the style of the footer
|
||||
local style = footer.style
|
||||
style.padding = { 2, 4 }
|
||||
style.use_header_filler = false
|
||||
style.horizontally_stretchable = true
|
||||
|
||||
-- Draw the caption label
|
||||
if caption then
|
||||
footer.add{
|
||||
name = 'footer_label',
|
||||
type = 'label',
|
||||
style = 'frame_title',
|
||||
caption = caption,
|
||||
tooltip = tooltip
|
||||
}
|
||||
end
|
||||
-- Draw the caption label
|
||||
if caption then
|
||||
footer.add{
|
||||
name = "footer_label",
|
||||
type = "label",
|
||||
style = "frame_title",
|
||||
caption = caption,
|
||||
tooltip = tooltip,
|
||||
}
|
||||
end
|
||||
|
||||
-- Return either the footer or the added alignment
|
||||
return add_alignment and Gui.alignment(footer) or footer
|
||||
end)
|
||||
-- Return either the footer or the added alignment
|
||||
return add_alignment and Gui.alignment(footer) or footer
|
||||
end)
|
||||
|
||||
--[[-- Used for left frames to give them a nice boarder
|
||||
@element Gui.container
|
||||
@@ -194,29 +194,29 @@ local container = Gui.container(parent, 'my_container', 200)
|
||||
|
||||
]]
|
||||
Gui.container =
|
||||
Gui.element(function(_, parent, name, _)
|
||||
-- Draw the external container
|
||||
local frame =
|
||||
parent.add{
|
||||
name = name,
|
||||
type = 'frame'
|
||||
}
|
||||
frame.style.horizontally_stretchable = false
|
||||
Gui.element(function(_, parent, name, _)
|
||||
-- Draw the external container
|
||||
local frame =
|
||||
parent.add{
|
||||
name = name,
|
||||
type = "frame",
|
||||
}
|
||||
frame.style.horizontally_stretchable = false
|
||||
|
||||
-- Return the container
|
||||
return frame.add{
|
||||
name = 'container',
|
||||
type = 'frame',
|
||||
direction = 'vertical',
|
||||
style = 'inside_shallow_frame_packed'
|
||||
}
|
||||
end)
|
||||
:style(function(style, element, _,width)
|
||||
style.vertically_stretchable = false
|
||||
local frame_style = element.parent.style
|
||||
frame_style.padding = 2
|
||||
frame_style.minimal_width = width
|
||||
end)
|
||||
-- Return the container
|
||||
return frame.add{
|
||||
name = "container",
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
style = "inside_shallow_frame_packed",
|
||||
}
|
||||
end)
|
||||
:style(function(style, element, _, width)
|
||||
style.vertically_stretchable = false
|
||||
local frame_style = element.parent.style
|
||||
frame_style.padding = 2
|
||||
frame_style.minimal_width = width
|
||||
end)
|
||||
|
||||
--[[-- Used to make a solid white bar in a gui
|
||||
@element Gui.bar
|
||||
@@ -228,19 +228,22 @@ local bar = Gui.bar(parent, 100)
|
||||
|
||||
]]
|
||||
Gui.bar =
|
||||
Gui.element(function(_, parent)
|
||||
return parent.add{
|
||||
type = 'progressbar',
|
||||
size = 1,
|
||||
value = 1
|
||||
}
|
||||
end)
|
||||
:style(function(style, _,width)
|
||||
style.height = 3
|
||||
style.color = {r=255, g=255, b=255}
|
||||
if width then style.width = width
|
||||
else style.horizontally_stretchable = true end
|
||||
end)
|
||||
Gui.element(function(_, parent)
|
||||
return parent.add{
|
||||
type = "progressbar",
|
||||
size = 1,
|
||||
value = 1,
|
||||
}
|
||||
end)
|
||||
:style(function(style, _, width)
|
||||
style.height = 3
|
||||
style.color = { r = 255, g = 255, b = 255 }
|
||||
if width then
|
||||
style.width = width
|
||||
else
|
||||
style.horizontally_stretchable = true
|
||||
end
|
||||
end)
|
||||
|
||||
--[[-- Used to make a label which is centered and of a certian size
|
||||
@element Gui.centered_label
|
||||
@@ -254,20 +257,20 @@ local label = Gui.centered_label(parent, 100, 'This is centered')
|
||||
|
||||
]]
|
||||
Gui.centered_label =
|
||||
Gui.element(function(_, parent, width, caption, tooltip)
|
||||
local label = parent.add{
|
||||
type = 'label',
|
||||
caption = caption,
|
||||
tooltip = tooltip,
|
||||
}
|
||||
Gui.element(function(_, parent, width, caption, tooltip)
|
||||
local label = parent.add{
|
||||
type = "label",
|
||||
caption = caption,
|
||||
tooltip = tooltip,
|
||||
}
|
||||
|
||||
local style = label.style
|
||||
style.horizontal_align = 'center'
|
||||
style.single_line = false
|
||||
style.width = width
|
||||
local style = label.style
|
||||
style.horizontal_align = "center"
|
||||
style.single_line = false
|
||||
style.width = width
|
||||
|
||||
return label
|
||||
end)
|
||||
return label
|
||||
end)
|
||||
|
||||
--[[-- Used to make a title which has two bars on either side
|
||||
@element Gui.title_label
|
||||
@@ -281,18 +284,18 @@ local label = Gui.centered_label(parent, 100, 'This is centered')
|
||||
|
||||
]]
|
||||
Gui.title_label =
|
||||
Gui.element(function(_, parent, width, caption, tooltip)
|
||||
local title_flow = parent.add{ type='flow' }
|
||||
title_flow.style.vertical_align = 'center'
|
||||
Gui.element(function(_, parent, width, caption, tooltip)
|
||||
local title_flow = parent.add{ type = "flow" }
|
||||
title_flow.style.vertical_align = "center"
|
||||
|
||||
Gui.bar(title_flow, width)
|
||||
local title_label = title_flow.add{
|
||||
type = 'label',
|
||||
caption = caption,
|
||||
tooltip = tooltip,
|
||||
style = 'frame_title'
|
||||
}
|
||||
Gui.bar(title_flow)
|
||||
Gui.bar(title_flow, width)
|
||||
local title_label = title_flow.add{
|
||||
type = "label",
|
||||
caption = caption,
|
||||
tooltip = tooltip,
|
||||
style = "frame_title",
|
||||
}
|
||||
Gui.bar(title_flow)
|
||||
|
||||
return title_label
|
||||
end)
|
||||
return title_label
|
||||
end)
|
||||
|
||||
@@ -88,4 +88,4 @@ function Gui.sprite_style(size, padding, style)
|
||||
style.height = size
|
||||
style.width = size
|
||||
return style
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
]]
|
||||
|
||||
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
|
||||
local mod_gui = require 'mod-gui'
|
||||
local mod_gui = require "mod-gui"
|
||||
|
||||
local hide_left_flow = Gui.core_defines.hide_left_flow.name
|
||||
|
||||
@@ -12,7 +12,7 @@ local hide_left_flow = Gui.core_defines.hide_left_flow.name
|
||||
-- @section leftFlow
|
||||
|
||||
-- Triggered when a user changed the visibility of a left flow element by clicking a button
|
||||
Gui.events.on_visibility_changed_by_click = 'on_visibility_changed_by_click'
|
||||
Gui.events.on_visibility_changed_by_click = "on_visibility_changed_by_click"
|
||||
|
||||
--- Contains the uids of the elements that will shown on the left flow and their join functions
|
||||
-- @table left_elements
|
||||
@@ -68,7 +68,7 @@ function Gui.left_toolbar_button(sprite, tooltip, element_define, authenticator)
|
||||
button:raise_event{
|
||||
name = Gui.events.on_visibility_changed_by_click,
|
||||
element = Gui.get_top_element(player, button),
|
||||
state = Gui.toggle_left_element(player, element_define)
|
||||
state = Gui.toggle_left_element(player, element_define),
|
||||
}
|
||||
end)
|
||||
|
||||
@@ -90,8 +90,8 @@ function Gui.inject_left_flow_order(provider)
|
||||
Gui.get_left_flow_order = provider
|
||||
local debug_info = debug.getinfo(2, "Sn")
|
||||
local file_name = debug_info.short_src:sub(10, -5)
|
||||
local func_name = debug_info.name or ("<anonymous:"..debug_info.linedefined..">")
|
||||
Gui._left_flow_order_src = file_name..":"..func_name
|
||||
local func_name = debug_info.name or ("<anonymous:" .. debug_info.linedefined .. ">")
|
||||
Gui._left_flow_order_src = file_name .. ":" .. func_name
|
||||
end
|
||||
|
||||
--[[-- Draw all the left elements onto the left flow, internal use only with on join
|
||||
@@ -121,17 +121,17 @@ function Gui.draw_left_flow(player)
|
||||
end, debug.traceback)
|
||||
|
||||
if not draw_success then
|
||||
log('There as been an error with an element draw function: '..element_define.defined_at..'\n\t'..left_element)
|
||||
log("There as been an error with an element draw function: " .. element_define.defined_at .. "\n\t" .. left_element)
|
||||
goto continue
|
||||
end
|
||||
|
||||
-- Check if it should be open by default
|
||||
local open_on_join = element_define.open_on_join
|
||||
local visible = type(open_on_join) == 'boolean' and open_on_join or false
|
||||
if type(open_on_join) == 'function' then
|
||||
local visible = type(open_on_join) == "boolean" and open_on_join or false
|
||||
if type(open_on_join) == "function" then
|
||||
local success, err = xpcall(open_on_join, debug.traceback, player)
|
||||
if not success then
|
||||
log('There as been an error with an open on join hander for a gui element:\n\t'..err)
|
||||
log("There as been an error with an open on join hander for a gui element:\n\t" .. err)
|
||||
goto continue
|
||||
end
|
||||
visible = err
|
||||
@@ -166,7 +166,7 @@ function Gui.reorder_left_flow(player)
|
||||
-- Reorder the elements, index 1 is the core ui buttons so +1 is required
|
||||
for index, element_define in ipairs(flow_order) do
|
||||
local element = left_flow[element_define.name]
|
||||
left_flow.swap_children(index+1, element.get_index_in_parent())
|
||||
left_flow.swap_children(index + 1, element.get_index_in_parent())
|
||||
end
|
||||
end
|
||||
|
||||
@@ -188,6 +188,7 @@ function Gui.update_left_flow(player)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
hide_button.visible = false
|
||||
return false
|
||||
end
|
||||
@@ -220,7 +221,7 @@ function Gui.hide_left_flow(player)
|
||||
element_define.toolbar_button:raise_event{
|
||||
name = Gui.events.on_visibility_changed_by_click,
|
||||
element = button,
|
||||
state = false
|
||||
state = false,
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -272,4 +273,4 @@ function Gui.toggle_left_element(player, element_define, state)
|
||||
Gui.toggle_toolbar_button(player, element_define.toolbar_button, state)
|
||||
end
|
||||
return state
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,7 +23,7 @@ local Gui = {
|
||||
--- The prototype used to store the functions of an element define
|
||||
_prototype_element = {},
|
||||
--- The prototype metatable applied to new element defines
|
||||
_mt_element = {}
|
||||
_mt_element = {},
|
||||
}
|
||||
|
||||
--- Allow access to the element prototype methods
|
||||
@@ -37,14 +37,14 @@ function Gui._mt_element.__call(self, parent, ...)
|
||||
-- Asserts to catch common errors
|
||||
if element then
|
||||
if self.name and self.name ~= element.name then
|
||||
error("Static name \""..self.name.."\" expected but got: "..tostring(element.name))
|
||||
error("Static name \"" .. self.name .. "\" expected but got: " .. tostring(element.name))
|
||||
end
|
||||
local event_triggers = element.tags and element.tags.ExpGui_event_triggers
|
||||
if event_triggers and table.array_contains(event_triggers, self.uid) then
|
||||
error("Element::triggers_events should not be called on the value you return from the definition")
|
||||
end
|
||||
elseif self.name then
|
||||
error("Static name \""..self.name.."\" expected but no element was returned from the definition")
|
||||
error("Static name \"" .. self.name .. "\" expected but no element was returned from the definition")
|
||||
end
|
||||
|
||||
-- Register events by default, but allow skipping them
|
||||
@@ -59,8 +59,8 @@ end
|
||||
local function get_defined_at(level)
|
||||
local debug_info = debug.getinfo(level, "Sn")
|
||||
local file_name = debug_info.short_src:sub(10, -5)
|
||||
local func_name = debug_info.name or ("<anonymous:"..debug_info.linedefined..">")
|
||||
return file_name..":"..func_name
|
||||
local func_name = debug_info.name or ("<anonymous:" .. debug_info.linedefined .. ">")
|
||||
return file_name .. ":" .. func_name
|
||||
end
|
||||
|
||||
--- Element Define.
|
||||
@@ -115,19 +115,20 @@ function Gui.element(element_define)
|
||||
local uid = Gui.uid + 1
|
||||
Gui.uid = uid
|
||||
element.uid = uid
|
||||
Gui.debug_info[uid] = { draw = 'None', style = 'None', events = {} }
|
||||
Gui.debug_info[uid] = { draw = "None", style = "None", events = {} }
|
||||
|
||||
-- Add the definition function
|
||||
if type(element_define) == 'table' then
|
||||
if type(element_define) == "table" then
|
||||
Gui.debug_info[uid].draw = element_define
|
||||
if element_define.name == Gui.unique_static_name then
|
||||
element_define.name = "ExpGui_"..tostring(uid)
|
||||
element_define.name = "ExpGui_" .. tostring(uid)
|
||||
end
|
||||
for k, v in pairs(element_define) do
|
||||
if element[k] == nil then
|
||||
element[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
element._draw = function(_, parent)
|
||||
return parent.add(element_define)
|
||||
end
|
||||
@@ -183,7 +184,7 @@ end)
|
||||
function Gui._prototype_element:style(style_define)
|
||||
_C.error_if_runtime()
|
||||
-- Add the definition function
|
||||
if type(style_define) == 'table' then
|
||||
if type(style_define) == "table" then
|
||||
Gui.debug_info[self.uid].style = style_define
|
||||
self._style = function(style)
|
||||
for key, value in pairs(style_define) do
|
||||
@@ -206,7 +207,7 @@ end
|
||||
function Gui._prototype_element:static_name(name)
|
||||
_C.error_if_runtime()
|
||||
if name == Gui.unique_static_name then
|
||||
self.name = "ExpGui_"..tostring(self.uid)
|
||||
self.name = "ExpGui_" .. tostring(self.uid)
|
||||
else
|
||||
self.name = name
|
||||
end
|
||||
@@ -295,7 +296,7 @@ function Gui._prototype_element:raise_event(event)
|
||||
|
||||
local success, err = xpcall(handler, debug.traceback, player, element, event)
|
||||
if not success then
|
||||
error('There as been an error with an event handler for a gui element:\n\t'..err)
|
||||
error("There as been an error with an event handler for a gui element:\n\t" .. err)
|
||||
end
|
||||
return self
|
||||
end
|
||||
@@ -328,84 +329,84 @@ end
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_open(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_open = event_handler_factory(defines.events.on_gui_opened)
|
||||
|
||||
--- Called when the player closes the GUI they have open.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_close(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_close = event_handler_factory(defines.events.on_gui_closed)
|
||||
|
||||
--- Called when LuaGuiElement is clicked.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_click(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_click = event_handler_factory(defines.events.on_gui_click)
|
||||
|
||||
--- Called when a LuaGuiElement is confirmed, for example by pressing Enter in a textfield.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_confirmed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_confirmed = event_handler_factory(defines.events.on_gui_confirmed)
|
||||
|
||||
--- Called when LuaGuiElement checked state is changed (related to checkboxes and radio buttons).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_checked_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_checked_changed = event_handler_factory(defines.events.on_gui_checked_state_changed)
|
||||
|
||||
--- Called when LuaGuiElement element value is changed (related to choose element buttons).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_elem_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_elem_changed = event_handler_factory(defines.events.on_gui_elem_changed)
|
||||
|
||||
--- Called when LuaGuiElement element location is changed (related to frames in player.gui.screen).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_location_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_location_changed = event_handler_factory(defines.events.on_gui_location_changed)
|
||||
|
||||
--- Called when LuaGuiElement selected tab is changed (related to tabbed-panes).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_tab_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_tab_changed = event_handler_factory(defines.events.on_gui_selected_tab_changed)
|
||||
|
||||
--- Called when LuaGuiElement selection state is changed (related to drop-downs and listboxes).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_selection_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_selection_changed = event_handler_factory(defines.events.on_gui_selection_state_changed)
|
||||
|
||||
--- Called when LuaGuiElement switch state is changed (related to switches).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_switch_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_switch_changed = event_handler_factory(defines.events.on_gui_switch_state_changed)
|
||||
|
||||
--- Called when LuaGuiElement text is changed by the player.
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_text_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_text_changed = event_handler_factory(defines.events.on_gui_text_changed)
|
||||
|
||||
--- Called when LuaGuiElement slider value is changed (related to the slider element).
|
||||
-- @tparam function handler the event handler which will be called
|
||||
-- @usage element_define:on_value_changed(function(event)
|
||||
-- event.player.print(table.inspect(event))
|
||||
--end)
|
||||
-- end)
|
||||
Gui._prototype_element.on_value_changed = event_handler_factory(defines.events.on_gui_value_changed)
|
||||
|
||||
-- Module return
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
]]
|
||||
|
||||
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
|
||||
|
||||
local toolbar_button_size = 36
|
||||
local hide_top_flow = Gui.core_defines.hide_top_flow.name
|
||||
@@ -14,7 +14,7 @@ local show_top_flow = Gui.core_defines.show_top_flow.name
|
||||
-- @section topFlow
|
||||
|
||||
-- Triggered when a user changed the visibility of a left flow element by clicking a button
|
||||
Gui.events.on_toolbar_button_toggled = 'on_toolbar_button_toggled'
|
||||
Gui.events.on_toolbar_button_toggled = "on_toolbar_button_toggled"
|
||||
|
||||
--- Contains the uids of the elements that will shown on the top flow and their auth functions
|
||||
-- @table top_elements
|
||||
@@ -26,7 +26,7 @@ Gui.top_flow_button_style = mod_gui.button_style
|
||||
|
||||
--- The style that should be used for buttons on the top flow when their flow is visible
|
||||
-- @field Gui.top_flow_button_toggled_style
|
||||
Gui.top_flow_button_toggled_style = 'menu_button_continue'
|
||||
Gui.top_flow_button_toggled_style = "menu_button_continue"
|
||||
|
||||
--[[-- Styles a top flow button depending on the state given
|
||||
@tparam LuaGuiElement button the button element to style
|
||||
@@ -40,7 +40,7 @@ Gui.toolbar_button_style(button, false)
|
||||
|
||||
]]
|
||||
function Gui.toolbar_button_style(button, state, size)
|
||||
---@cast button LuaGuiElement
|
||||
--- @cast button LuaGuiElement
|
||||
if state then
|
||||
button.style = Gui.top_flow_button_toggled_style
|
||||
else
|
||||
@@ -108,8 +108,8 @@ function Gui.inject_top_flow_order(provider)
|
||||
Gui.get_top_flow_order = provider
|
||||
local debug_info = debug.getinfo(2, "Sn")
|
||||
local file_name = debug_info.short_src:sub(10, -5)
|
||||
local func_name = debug_info.name or ("<anonymous:"..debug_info.linedefined..">")
|
||||
Gui._top_flow_order_src = file_name..":"..func_name
|
||||
local func_name = debug_info.name or ("<anonymous:" .. debug_info.linedefined .. ">")
|
||||
Gui._top_flow_order_src = file_name .. ":" .. func_name
|
||||
end
|
||||
|
||||
--[[-- Updates the visible state of all the elements on the players top flow, uses authenticator
|
||||
@@ -137,12 +137,12 @@ function Gui.update_top_flow(player)
|
||||
if not element then
|
||||
element = element_define(top_flow)
|
||||
else
|
||||
top_flow.swap_children(index+1, element.get_index_in_parent())
|
||||
top_flow.swap_children(index + 1, element.get_index_in_parent())
|
||||
end
|
||||
|
||||
-- Set the visible state
|
||||
local allowed = element_define.authenticator
|
||||
if type(allowed) == 'function' then allowed = allowed(player) end
|
||||
if type(allowed) == "function" then allowed = allowed(player) end
|
||||
element.visible = allowed or false
|
||||
|
||||
-- If its not visible and there is a left element, then hide it
|
||||
@@ -176,7 +176,7 @@ function Gui.reorder_top_flow(player)
|
||||
-- Reorder the elements, index 1 is the core ui buttons so +1 is required
|
||||
for index, element_define in ipairs(flow_order) do
|
||||
local element = top_flow[element_define.name]
|
||||
top_flow.swap_children(index+1, element.get_index_in_parent())
|
||||
top_flow.swap_children(index + 1, element.get_index_in_parent())
|
||||
end
|
||||
end
|
||||
|
||||
@@ -243,7 +243,7 @@ function Gui.toggle_toolbar_button(player, element_define, state)
|
||||
name = Gui.events.on_toolbar_button_toggled,
|
||||
element = toolbar_button,
|
||||
player = player,
|
||||
state = state
|
||||
state = state,
|
||||
}
|
||||
return state
|
||||
end
|
||||
@@ -262,18 +262,18 @@ end)
|
||||
]]
|
||||
function Gui.toolbar_button(sprite, tooltip, authenticator)
|
||||
return Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = sprite,
|
||||
tooltip = tooltip,
|
||||
style = Gui.top_flow_button_style,
|
||||
name = Gui.unique_static_name
|
||||
}
|
||||
:style{
|
||||
minimal_width = toolbar_button_size,
|
||||
height = toolbar_button_size,
|
||||
padding = -2
|
||||
}
|
||||
:add_to_top_flow(authenticator)
|
||||
type = "sprite-button",
|
||||
sprite = sprite,
|
||||
tooltip = tooltip,
|
||||
style = Gui.top_flow_button_style,
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style{
|
||||
minimal_width = toolbar_button_size,
|
||||
height = toolbar_button_size,
|
||||
padding = -2,
|
||||
}
|
||||
:add_to_top_flow(authenticator)
|
||||
end
|
||||
|
||||
--[[-- Creates a toggle button on the top flow with consistent styling
|
||||
@@ -293,23 +293,23 @@ end)
|
||||
]]
|
||||
function Gui.toolbar_toggle_button(sprite, tooltip, authenticator)
|
||||
local button =
|
||||
Gui.element{
|
||||
type = 'sprite-button',
|
||||
sprite = sprite,
|
||||
tooltip = tooltip,
|
||||
style = Gui.top_flow_button_style,
|
||||
name = Gui.unique_static_name
|
||||
}
|
||||
:style{
|
||||
minimal_width = toolbar_button_size,
|
||||
height = toolbar_button_size,
|
||||
padding = -2
|
||||
}
|
||||
:add_to_top_flow(authenticator)
|
||||
Gui.element{
|
||||
type = "sprite-button",
|
||||
sprite = sprite,
|
||||
tooltip = tooltip,
|
||||
style = Gui.top_flow_button_style,
|
||||
name = Gui.unique_static_name,
|
||||
}
|
||||
:style{
|
||||
minimal_width = toolbar_button_size,
|
||||
height = toolbar_button_size,
|
||||
padding = -2,
|
||||
}
|
||||
:add_to_top_flow(authenticator)
|
||||
|
||||
button:on_click(function(player, _, _)
|
||||
Gui.toggle_toolbar_button(player, button)
|
||||
end)
|
||||
|
||||
return button
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,28 +23,27 @@ 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") --- @dep utils.event
|
||||
local Async = require("modules/exp_util/async")
|
||||
|
||||
local Permissions_Groups = {
|
||||
groups={}, -- store for the different groups that are created
|
||||
_prototype={} -- stores functions that are used on group instances
|
||||
groups = {}, -- store for the different groups that are created
|
||||
_prototype = {}, -- stores functions that are used on group instances
|
||||
}
|
||||
|
||||
-- Async function to add players to permission groups
|
||||
local add_to_permission_group_async =
|
||||
Async.register(function(permission_group, player)
|
||||
permission_group.add_player(player)
|
||||
end)
|
||||
Async.register(function(permission_group, player)
|
||||
permission_group.add_player(player)
|
||||
end)
|
||||
Permissions_Groups.add_to_permission_group_async = add_to_permission_group_async
|
||||
|
||||
-- Async function to remove players from permission groups
|
||||
local remove_from_permission_group_async =
|
||||
Async.register(function(permission_group, player)
|
||||
permission_group.remove_player(player)
|
||||
end)
|
||||
Async.register(function(permission_group, player)
|
||||
permission_group.remove_player(player)
|
||||
end)
|
||||
Permissions_Groups.remove_from_permission_group_async = remove_from_permission_group_async
|
||||
|
||||
--- Getters.
|
||||
@@ -61,11 +60,11 @@ Groups.new_group('Admin')
|
||||
]]
|
||||
function Permissions_Groups.new_group(name)
|
||||
local group = setmetatable({
|
||||
name=name,
|
||||
actions={},
|
||||
allow_all_actions=true
|
||||
name = name,
|
||||
actions = {},
|
||||
allow_all_actions = true,
|
||||
}, {
|
||||
__index= Permissions_Groups._prototype
|
||||
__index = Permissions_Groups._prototype,
|
||||
})
|
||||
Permissions_Groups.groups[name] = group
|
||||
return group
|
||||
@@ -149,7 +148,7 @@ group:set_action('toggle_map_editor', false)
|
||||
function Permissions_Groups._prototype:set_action(action, state)
|
||||
local input_action = defines.input_action[action]
|
||||
if input_action == nil then input_action = action end
|
||||
assert(type(input_action) == 'number', tostring(action)..' is not a valid input action')
|
||||
assert(type(input_action) == "number", tostring(action) .. " is not a valid input action")
|
||||
self.actions[input_action] = state
|
||||
return self
|
||||
end
|
||||
@@ -165,12 +164,13 @@ group:allow{
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:allow(actions)
|
||||
if type(actions) ~= 'table' then
|
||||
actions = {actions}
|
||||
if type(actions) ~= "table" then
|
||||
actions = { actions }
|
||||
end
|
||||
for _, action in pairs(actions) do
|
||||
self:set_action(action, true)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -189,12 +189,13 @@ group:disallow{
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:disallow(actions)
|
||||
if type(actions) ~= 'table' then
|
||||
actions = {actions}
|
||||
if type(actions) ~= "table" then
|
||||
actions = { actions }
|
||||
end
|
||||
for _, action in pairs(actions) do
|
||||
self:set_action(action, false)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -231,7 +232,7 @@ local allowed = group:is_allowed('write_to_console')
|
||||
|
||||
]]
|
||||
function Permissions_Groups._prototype:is_allowed(action)
|
||||
if type(action) == 'string' then
|
||||
if type(action) == "string" then
|
||||
action = defines.input_action[action]
|
||||
end
|
||||
local state = self.actions[action]
|
||||
@@ -260,6 +261,7 @@ function Permissions_Groups._prototype:create()
|
||||
for _, action in pairs(defines.input_action) do
|
||||
group.set_allows_action(action, self:is_allowed(action))
|
||||
end
|
||||
|
||||
return group
|
||||
end
|
||||
|
||||
@@ -347,6 +349,7 @@ function Permissions_Groups._prototype:print(message)
|
||||
for _, player in pairs(players) do
|
||||
player.print(message)
|
||||
end
|
||||
|
||||
return #players
|
||||
end
|
||||
|
||||
@@ -355,4 +358,4 @@ Event.on_init(function()
|
||||
Permissions_Groups.reload_permissions()
|
||||
end)
|
||||
|
||||
return Permissions_Groups
|
||||
return Permissions_Groups
|
||||
|
||||
@@ -48,58 +48,59 @@ local Commands = require("modules.exp_legacy.expcore.commands") --- @dep expcore
|
||||
require("modules.exp_legacy.config.expcore.command_general_parse") --- @dep config.expcore.command_general_parse
|
||||
|
||||
--- Common player data that acts as the root store for player data
|
||||
local PlayerData = Datastore.connect('PlayerData', true) -- saveToDisk
|
||||
local PlayerData = Datastore.connect("PlayerData", true) -- saveToDisk
|
||||
PlayerData:set_serializer(Datastore.name_serializer) -- use player name
|
||||
|
||||
--- Store and enum for the data saving preference
|
||||
local DataSavingPreference = PlayerData:combine('DataSavingPreference')
|
||||
local PreferenceEnum = { 'All', 'Statistics', 'Settings', 'Required' }
|
||||
for k,v in ipairs(PreferenceEnum) do PreferenceEnum[v] = k end
|
||||
DataSavingPreference:set_default('All')
|
||||
local DataSavingPreference = PlayerData:combine("DataSavingPreference")
|
||||
local PreferenceEnum = { "All", "Statistics", "Settings", "Required" }
|
||||
for k, v in ipairs(PreferenceEnum) do PreferenceEnum[v] = k end
|
||||
|
||||
DataSavingPreference:set_default("All")
|
||||
DataSavingPreference:set_metadata{
|
||||
name = {'expcore-data.preference'},
|
||||
tooltip = {'expcore-data.preference-tooltip'},
|
||||
value_tooltip ={'expcore-data.preference-value-tooltip'}
|
||||
name = { "expcore-data.preference" },
|
||||
tooltip = { "expcore-data.preference-tooltip" },
|
||||
value_tooltip = { "expcore-data.preference-value-tooltip" },
|
||||
}
|
||||
|
||||
--- Sets your data saving preference
|
||||
-- @command set-data-preference
|
||||
Commands.new_command('set-preference', 'Allows you to set your data saving preference')
|
||||
:add_param('option', false, 'string-options', PreferenceEnum)
|
||||
:register(function(player, option)
|
||||
DataSavingPreference:set(player, option)
|
||||
return {'expcore-data.set-preference', option}
|
||||
end)
|
||||
Commands.new_command("set-preference", "Allows you to set your data saving preference")
|
||||
:add_param("option", false, "string-options", PreferenceEnum)
|
||||
:register(function(player, option)
|
||||
DataSavingPreference:set(player, option)
|
||||
return { "expcore-data.set-preference", option }
|
||||
end)
|
||||
|
||||
--- Gets your data saving preference
|
||||
-- @command data-preference
|
||||
Commands.new_command('preference', 'Shows you what your current data saving preference is')
|
||||
:register(function(player)
|
||||
return {'expcore-data.get-preference', DataSavingPreference:get(player)}
|
||||
end)
|
||||
Commands.new_command("preference", "Shows you what your current data saving preference is")
|
||||
:register(function(player)
|
||||
return { "expcore-data.get-preference", DataSavingPreference:get(player) }
|
||||
end)
|
||||
|
||||
--- Gets your data and writes it to a file
|
||||
Commands.new_command('save-data', 'Writes all your player data to a file on your computer')
|
||||
:register(function(player)
|
||||
player.print{'expcore-data.get-data'}
|
||||
game.write_file('expgaming_player_data.json', game.table_to_json(PlayerData:get(player, {})), false, player.index)
|
||||
end)
|
||||
Commands.new_command("save-data", "Writes all your player data to a file on your computer")
|
||||
:register(function(player)
|
||||
player.print{ "expcore-data.get-data" }
|
||||
game.write_file("expgaming_player_data.json", game.table_to_json(PlayerData:get(player, {})), false, player.index)
|
||||
end)
|
||||
|
||||
--- Async function called after 5 seconds with no player data loaded
|
||||
local check_data_loaded_async =
|
||||
Async.register(function(player)
|
||||
local player_data = PlayerData:get(player)
|
||||
if not player_data or not player_data.valid then
|
||||
player.print{'expcore-data.data-failed'}
|
||||
Datastore.ingest('request', 'PlayerData', player.name, '{"valid":false}')
|
||||
end
|
||||
end)
|
||||
Async.register(function(player)
|
||||
local player_data = PlayerData:get(player)
|
||||
if not player_data or not player_data.valid then
|
||||
player.print{ "expcore-data.data-failed" }
|
||||
Datastore.ingest("request", "PlayerData", player.name, '{"valid":false}')
|
||||
end
|
||||
end)
|
||||
|
||||
--- When player data loads tell the player if the load had failed previously
|
||||
PlayerData:on_load(function(player_name, player_data, existing_data)
|
||||
if not player_data or player_data.valid == false then return end
|
||||
if existing_data and existing_data.valid == false then
|
||||
game.players[player_name].print{'expcore-data.data-restore'}
|
||||
game.players[player_name].print{ "expcore-data.data-restore" }
|
||||
end
|
||||
player_data.valid = true
|
||||
end)
|
||||
@@ -122,7 +123,7 @@ end)
|
||||
|
||||
--- Display your data preference when your data loads
|
||||
DataSavingPreference:on_load(function(player_name, dataPreference)
|
||||
game.players[player_name].print{'expcore-data.get-preference', dataPreference or DataSavingPreference.default}
|
||||
game.players[player_name].print{ "expcore-data.get-preference", dataPreference or DataSavingPreference.default }
|
||||
end)
|
||||
|
||||
--- Load player data when they join
|
||||
@@ -139,15 +140,17 @@ Event.add(defines.events.on_player_left_game, function(event)
|
||||
local player_data = PlayerData:get(player)
|
||||
if player_data and player_data.valid == true then
|
||||
PlayerData:unload(player)
|
||||
else PlayerData:raw_set(player.name) end
|
||||
else
|
||||
PlayerData:raw_set(player.name)
|
||||
end
|
||||
end)
|
||||
|
||||
----- Module Return -----
|
||||
return {
|
||||
All = PlayerData, -- Root for all of a players data
|
||||
Statistics = PlayerData:combine('Statistics'), -- Common place for stats
|
||||
Settings = PlayerData:combine('Settings'), -- Common place for settings
|
||||
Required = PlayerData:combine('Required'), -- Common place for required data
|
||||
Statistics = PlayerData:combine("Statistics"), -- Common place for stats
|
||||
Settings = PlayerData:combine("Settings"), -- Common place for settings
|
||||
Required = PlayerData:combine("Required"), -- Common place for required data
|
||||
DataSavingPreference = DataSavingPreference, -- Stores what data groups will be saved
|
||||
PreferenceEnum = PreferenceEnum -- Enum for the allowed options for data saving preference
|
||||
}
|
||||
PreferenceEnum = PreferenceEnum, -- Enum for the allowed options for data saving preference
|
||||
}
|
||||
|
||||
@@ -119,24 +119,24 @@ local write_json = _C.write_json --- @dep expcore.common
|
||||
local Roles = {
|
||||
_prototype = {},
|
||||
config = {
|
||||
order = {}, -- Contains the order of the roles, lower index is better
|
||||
roles = {}, -- Contains the raw info for the roles, indexed by role name
|
||||
flags = {}, -- Contains functions that run when a flag is added/removed from a player
|
||||
internal = {}, -- Contains all internally accessed roles, such as root, default
|
||||
players = {}, -- Contains the roles that players have
|
||||
auto_assign = {}, -- Contains references to all roles which have auto assign conditions
|
||||
order = {}, -- Contains the order of the roles, lower index is better
|
||||
roles = {}, -- Contains the raw info for the roles, indexed by role name
|
||||
flags = {}, -- Contains functions that run when a flag is added/removed from a player
|
||||
internal = {}, -- Contains all internally accessed roles, such as root, default
|
||||
players = {}, -- Contains the roles that players have
|
||||
auto_assign = {}, -- Contains references to all roles which have auto assign conditions
|
||||
deferred_roles = {}, -- Contains the roles that are to be assigned to players when they are unjailed
|
||||
},
|
||||
events = {
|
||||
on_role_assigned = script.generate_event_name(),
|
||||
on_role_assigned = script.generate_event_name(),
|
||||
on_role_unassigned = script.generate_event_name(),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
--- When global is loaded it will have the metatable re-assigned to the roles
|
||||
Storage.register({
|
||||
Roles.config.players,
|
||||
Roles.config.deferred_roles
|
||||
Roles.config.deferred_roles,
|
||||
}, function(tbl)
|
||||
Roles.config.players = tbl[1]
|
||||
Roles.config.deferred_roles = tbl[2]
|
||||
@@ -150,12 +150,12 @@ end)
|
||||
-- this is the raw internal trigger as the other function is called at other times
|
||||
-- there is a second half called role_update which triggers after the event call, it also is called when a player joins
|
||||
local function emit_player_roles_updated(player, type, roles, by_player_name, skip_game_print)
|
||||
by_player_name = by_player_name or game.player and game.player.name or '<server>'
|
||||
by_player_name = by_player_name or game.player and game.player.name or "<server>"
|
||||
local by_player = game.players[by_player_name]
|
||||
local by_player_index = by_player and by_player.index or 0
|
||||
-- get the event id from the type of emit
|
||||
local event = Roles.events.on_role_assigned
|
||||
if type == 'unassign' then
|
||||
if type == "unassign" then
|
||||
event = Roles.events.on_role_unassigned
|
||||
end
|
||||
-- Get the names of the roles
|
||||
@@ -163,27 +163,28 @@ local function emit_player_roles_updated(player, type, roles, by_player_name, sk
|
||||
for index, role in ipairs(roles) do
|
||||
role_names[index] = role.name
|
||||
end
|
||||
|
||||
-- output to all the different locations: game print, player sound, event trigger and role log
|
||||
if not skip_game_print then
|
||||
game.print({'expcore-roles.game-message-'..type, player.name, table.concat(role_names, ', '), by_player_name}, Colours.cyan)
|
||||
game.print({ "expcore-roles.game-message-" .. type, player.name, table.concat(role_names, ", "), by_player_name }, Colours.cyan)
|
||||
end
|
||||
if type == 'assign' then
|
||||
player.play_sound{path='utility/achievement_unlocked'}
|
||||
if type == "assign" then
|
||||
player.play_sound{ path = "utility/achievement_unlocked" }
|
||||
else
|
||||
player.play_sound{path='utility/game_lost'}
|
||||
player.play_sound{ path = "utility/game_lost" }
|
||||
end
|
||||
script.raise_event(event, {
|
||||
name=event,
|
||||
tick=game.tick,
|
||||
player_index=player.index,
|
||||
by_player_index=by_player_index,
|
||||
roles=role_names
|
||||
name = event,
|
||||
tick = game.tick,
|
||||
player_index = player.index,
|
||||
by_player_index = by_player_index,
|
||||
roles = role_names,
|
||||
})
|
||||
write_json('log/roles.log', {
|
||||
player_name=player.name,
|
||||
by_player_name=by_player_name,
|
||||
type=type,
|
||||
roles_changed=role_names
|
||||
write_json("log/roles.log", {
|
||||
player_name = player.name,
|
||||
by_player_name = by_player_name,
|
||||
type = type,
|
||||
roles_changed = role_names,
|
||||
})
|
||||
end
|
||||
|
||||
@@ -195,13 +196,14 @@ game.player.print(Roles.debug())
|
||||
|
||||
]]
|
||||
function Roles.debug()
|
||||
local output = ''
|
||||
local output = ""
|
||||
for index, role_name in ipairs(Roles.config.order) do
|
||||
local role = Roles.config.roles[role_name]
|
||||
local color = role.custom_color or Colours.white
|
||||
color = string.format('[color=%d, %d, %d]', color.r, color.g, color.b)
|
||||
output = output..string.format('\n%s %s) %s[/color]', color, index, serpent.line(role))
|
||||
color = string.format("[color=%d, %d, %d]", color.r, color.g, color.b)
|
||||
output = output .. string.format("\n%s %s) %s[/color]", color, index, serpent.line(role))
|
||||
end
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
@@ -234,9 +236,10 @@ function Roles.print_to_roles_higher(role, message)
|
||||
local roles = {}
|
||||
for index, role_name in ipairs(Roles.config.order) do
|
||||
if index <= role.index and role_name ~= Roles.config.internal.default then
|
||||
roles[#roles+1] = role_name
|
||||
roles[#roles + 1] = role_name
|
||||
end
|
||||
end
|
||||
|
||||
Roles.print_to_roles(roles, message)
|
||||
end
|
||||
|
||||
@@ -254,9 +257,10 @@ function Roles.print_to_roles_lower(role, message)
|
||||
local roles = {}
|
||||
for index, role_name in ipairs(Roles.config.order) do
|
||||
if index >= role.index and role_name ~= Roles.config.internal.default then
|
||||
roles[#roles+1] = role_name
|
||||
roles[#roles + 1] = role_name
|
||||
end
|
||||
end
|
||||
|
||||
Roles.print_to_roles(roles, message)
|
||||
end
|
||||
|
||||
@@ -296,12 +300,12 @@ local role = Roles.get_role_from_any('Moderator')
|
||||
]]
|
||||
function Roles.get_role_from_any(any)
|
||||
local t_any = type(any)
|
||||
if t_any == 'number' or tonumber(any) then
|
||||
if t_any == "number" or tonumber(any) then
|
||||
any = tonumber(any)
|
||||
return Roles.get_role_by_order(any)
|
||||
elseif t_any == 'string' then
|
||||
elseif t_any == "string" then
|
||||
return Roles.get_role_by_name(any)
|
||||
elseif t_any == 'table' then
|
||||
elseif t_any == "table" then
|
||||
return Roles.get_role_by_name(any.name)
|
||||
end
|
||||
end
|
||||
@@ -316,13 +320,14 @@ local roles = Roles.get_player_roles(game.player)
|
||||
]]
|
||||
function Roles.get_player_roles(player)
|
||||
player = Game.get_player_from_any(player)
|
||||
if not player then return {Roles.config.roles[Roles.config.internal.root]} end
|
||||
if not player then return { Roles.config.roles[Roles.config.internal.root] } end
|
||||
local roles = Roles.config.players[player.name] or {}
|
||||
local default = Roles.config.roles[Roles.config.internal.default]
|
||||
local rtn = {default}
|
||||
local rtn = { default }
|
||||
for index, role_name in ipairs(roles) do
|
||||
rtn[index+1] = Roles.config.roles[role_name]
|
||||
rtn[index + 1] = Roles.config.roles[role_name]
|
||||
end
|
||||
|
||||
return rtn
|
||||
end
|
||||
|
||||
@@ -343,6 +348,7 @@ function Roles.get_player_highest_role(player)
|
||||
highest = role
|
||||
end
|
||||
end
|
||||
|
||||
return highest
|
||||
end
|
||||
|
||||
@@ -370,7 +376,7 @@ function Roles.assign_player(player, roles, by_player_name, skip_checks, silent)
|
||||
if not player then return end
|
||||
|
||||
-- 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
|
||||
roles = { roles }
|
||||
end
|
||||
|
||||
@@ -394,10 +400,11 @@ function Roles.assign_player(player, roles, by_player_name, skip_checks, silent)
|
||||
end
|
||||
else
|
||||
assign_later[role.name] = {
|
||||
count = 1, by_player_name = by_player_name or "<server>", silent = silent
|
||||
count = 1, by_player_name = by_player_name or "<server>", silent = silent,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
Roles.config.deferred_roles[valid_player.name] = assign_later
|
||||
return
|
||||
end
|
||||
@@ -407,7 +414,7 @@ function Roles.assign_player(player, roles, by_player_name, skip_checks, silent)
|
||||
end
|
||||
|
||||
if valid_player then
|
||||
emit_player_roles_updated(valid_player, 'assign', role_objects, by_player_name, silent)
|
||||
emit_player_roles_updated(valid_player, "assign", role_objects, by_player_name, silent)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -431,7 +438,7 @@ function Roles.unassign_player(player, roles, by_player_name, skip_checks, silen
|
||||
if not player then return end
|
||||
|
||||
-- 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
|
||||
roles = { roles }
|
||||
end
|
||||
|
||||
@@ -456,10 +463,11 @@ function Roles.unassign_player(player, roles, by_player_name, skip_checks, silen
|
||||
end
|
||||
else
|
||||
assign_later[role.name] = {
|
||||
count = -1, by_player_name = by_player_name or "<server>", silent = silent
|
||||
count = -1, by_player_name = by_player_name or "<server>", silent = silent,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
Roles.config.deferred_roles[valid_player.name] = assign_later
|
||||
end
|
||||
|
||||
@@ -490,17 +498,20 @@ function Roles.unassign_player(player, roles, by_player_name, skip_checks, silen
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for assign_by_player_name, assign_roles in pairs(assigns) do
|
||||
if #assign_roles > 0 then emit_player_roles_updated(valid_player, 'assign', assign_roles, assign_by_player_name) end
|
||||
if #assign_roles > 0 then emit_player_roles_updated(valid_player, "assign", assign_roles, assign_by_player_name) end
|
||||
end
|
||||
|
||||
for unassign_by_player_name, unassign_roles in pairs(unassigns) do
|
||||
if #unassign_roles > 0 then emit_player_roles_updated(valid_player, 'unassign', unassign_roles, unassign_by_player_name) end
|
||||
if #unassign_roles > 0 then emit_player_roles_updated(valid_player, "unassign", unassign_roles, unassign_by_player_name) end
|
||||
end
|
||||
|
||||
Roles.config.deferred_roles[player.name] = nil
|
||||
end
|
||||
|
||||
if valid_player and #role_changes > 0 then
|
||||
emit_player_roles_updated(valid_player, 'unassign', role_changes, by_player_name, silent)
|
||||
emit_player_roles_updated(valid_player, "unassign", role_changes, by_player_name, silent)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -518,10 +529,11 @@ Roles.override_player_roles{
|
||||
}
|
||||
|
||||
]]
|
||||
function Roles.override_player_roles(player_name,roles)
|
||||
function Roles.override_player_roles(player_name, roles)
|
||||
local player_roles = Roles.config.players
|
||||
if not roles then
|
||||
for k in pairs(player_roles) do player_roles[k] = nil end
|
||||
|
||||
for k, new_roles in pairs(player_name) do player_roles[k] = new_roles end
|
||||
else
|
||||
Roles.config.players[player_name] = roles
|
||||
@@ -549,6 +561,7 @@ function Roles.player_has_role(player, search_role)
|
||||
for _, role in ipairs(roles) do
|
||||
if role.name == search_role.name then return true end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -569,6 +582,7 @@ function Roles.player_has_flag(player, flag_name)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -589,6 +603,7 @@ function Roles.player_allowed(player, action)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -616,7 +631,7 @@ function Roles.define_role_order(order)
|
||||
Roles.config.order = {}
|
||||
local done = {}
|
||||
for index, role in ipairs(order) do
|
||||
if type(role) == 'table' and role.name then
|
||||
if type(role) == "table" and role.name then
|
||||
done[role.name] = true
|
||||
Roles.config.order[index] = role.name
|
||||
else
|
||||
@@ -624,22 +639,24 @@ function Roles.define_role_order(order)
|
||||
Roles.config.order[index] = role
|
||||
end
|
||||
end
|
||||
|
||||
-- Check no roles were missed
|
||||
for role_name in pairs(Roles.config.roles) do
|
||||
if not done[role_name] then
|
||||
error('Role missing '..role_name..' from role order, all defined roles must be included.', 2)
|
||||
error("Role missing " .. role_name .. " from role order, all defined roles must be included.", 2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Re-links roles to they parents as this is called at the end of the config
|
||||
for index, role_name in pairs(Roles.config.order) do
|
||||
local role = Roles.config.roles[role_name]
|
||||
if not role then
|
||||
error('Role with name '..role_name..' has not beed defined, either define it or remove it from the order list.', 2)
|
||||
error("Role with name " .. role_name .. " has not beed defined, either define it or remove it from the order list.", 2)
|
||||
end
|
||||
role.index = index
|
||||
local parent = Roles.config.roles[role.parent]
|
||||
if parent then
|
||||
setmetatable(role.allowed_actions, {__index=parent.allowed_actions})
|
||||
setmetatable(role.allowed_actions, { __index = parent.allowed_actions })
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -696,14 +713,14 @@ local role = Roles.new_role('Moderator', 'Mod')
|
||||
]]
|
||||
function Roles.new_role(name, short_hand)
|
||||
_C.error_if_runtime()
|
||||
if Roles.config.roles[name] then return error('Role name is non unique') end
|
||||
if Roles.config.roles[name] then return error("Role name is non unique") end
|
||||
local role = setmetatable({
|
||||
name=name,
|
||||
short_hand=short_hand or name,
|
||||
allowed_actions={},
|
||||
allow_all_actions=false,
|
||||
flags={}
|
||||
}, {__index=Roles._prototype})
|
||||
name = name,
|
||||
short_hand = short_hand or name,
|
||||
allowed_actions = {},
|
||||
allow_all_actions = false,
|
||||
flags = {},
|
||||
}, { __index = Roles._prototype })
|
||||
Roles.config.roles[name] = role
|
||||
return role
|
||||
end
|
||||
@@ -738,12 +755,13 @@ role:allow{
|
||||
|
||||
]]
|
||||
function Roles._prototype:allow(actions)
|
||||
if type(actions) ~= 'table' then
|
||||
actions = {actions}
|
||||
if type(actions) ~= "table" then
|
||||
actions = { actions }
|
||||
end
|
||||
for _, action in ipairs(actions) do
|
||||
self.allowed_actions[action]=true
|
||||
self.allowed_actions[action] = true
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -759,12 +777,13 @@ role:disallow{
|
||||
|
||||
]]
|
||||
function Roles._prototype:disallow(actions)
|
||||
if type(actions) ~= 'table' then
|
||||
actions = {actions}
|
||||
if type(actions) ~= "table" then
|
||||
actions = { actions }
|
||||
end
|
||||
for _, action in ipairs(actions) do
|
||||
self.allowed_actions[action]=false
|
||||
self.allowed_actions[action] = false
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -850,7 +869,7 @@ role:set_custom_color{ r=255, g=100, b=100}
|
||||
|
||||
]]
|
||||
function Roles._prototype:set_custom_color(color)
|
||||
if type(color) ~= 'table' then
|
||||
if type(color) ~= "table" then
|
||||
color = Colours[color]
|
||||
end
|
||||
self.custom_color = color
|
||||
@@ -869,7 +888,7 @@ role:set_permission_group('Admin')
|
||||
function Roles._prototype:set_permission_group(name, use_factorio_api)
|
||||
_C.error_if_runtime()
|
||||
if use_factorio_api then
|
||||
self.permission_group = {true, name}
|
||||
self.permission_group = { true, name }
|
||||
else
|
||||
local group = Groups.get_group_by_name(name)
|
||||
if not group then return end
|
||||
@@ -892,7 +911,7 @@ function Roles._prototype:set_parent(role)
|
||||
self.parent = role
|
||||
role = Roles.get_role_from_any(role)
|
||||
if not role then return self end
|
||||
setmetatable(self.allowed_actions, {__index=role.allowed_actions})
|
||||
setmetatable(self.allowed_actions, { __index = role.allowed_actions })
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -972,13 +991,14 @@ function Roles._prototype:add_player(player, skip_check, skip_event)
|
||||
for _, role_name in ipairs(player_roles) do
|
||||
if role_name == self.name then return false end
|
||||
end
|
||||
player_roles[#player_roles+1] = self.name
|
||||
|
||||
player_roles[#player_roles + 1] = self.name
|
||||
else
|
||||
Roles.config.players[player_name] = {self.name}
|
||||
Roles.config.players[player_name] = { self.name }
|
||||
end
|
||||
-- Emits event if required
|
||||
if valid_player and not skip_event then
|
||||
emit_player_roles_updated(valid_player, 'assign', {self})
|
||||
emit_player_roles_updated(valid_player, "assign", { self })
|
||||
end
|
||||
return true
|
||||
end
|
||||
@@ -1018,13 +1038,14 @@ function Roles._prototype:remove_player(player, skip_check, skip_event)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if #player_roles == 0 then
|
||||
Roles.config.players[player_name] = nil
|
||||
end
|
||||
end
|
||||
-- Emits event if required
|
||||
if valid_player and not skip_event then
|
||||
emit_player_roles_updated(valid_player, 'unassign', {self})
|
||||
emit_player_roles_updated(valid_player, "unassign", { self })
|
||||
end
|
||||
return found
|
||||
end
|
||||
@@ -1049,12 +1070,13 @@ function Roles._prototype:get_players(online)
|
||||
local player = game.players[player_name]
|
||||
-- Filter by online state if required
|
||||
if player and (online == nil or player.connected == online) then
|
||||
players[#players+1] = player
|
||||
players[#players + 1] = player
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return players
|
||||
end
|
||||
|
||||
@@ -1071,6 +1093,7 @@ function Roles._prototype:print(message)
|
||||
for _, player in ipairs(players) do
|
||||
player.print(message)
|
||||
end
|
||||
|
||||
return #players
|
||||
end
|
||||
|
||||
@@ -1082,6 +1105,7 @@ local function role_update(event)
|
||||
local state = Roles.player_has_flag(player, flag)
|
||||
async_function(player, state)
|
||||
end
|
||||
|
||||
-- Updates the players permission group
|
||||
local highest = Roles.get_player_highest_role(player)
|
||||
if highest.permission_group then
|
||||
@@ -1114,7 +1138,7 @@ local function auto_assign(event)
|
||||
if not lookup[role] then
|
||||
local success, rtn = pcall(condition, player)
|
||||
if not success then
|
||||
log{'expcore-roles.error-log-format-assign', role.name, rtn}
|
||||
log{ "expcore-roles.error-log-format-assign", role.name, rtn }
|
||||
elseif rtn == true then
|
||||
ctn = ctn + 1
|
||||
assigns[ctn] = role
|
||||
@@ -1139,6 +1163,5 @@ Event.on_nth_tick(3600, function()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
-- Return Roles
|
||||
return Roles
|
||||
return Roles
|
||||
|
||||
Reference in New Issue
Block a user