diff --git a/ExpLib.lua b/ExpLib.lua index ff382edc..6dc17c0f 100644 --- a/ExpLib.lua +++ b/ExpLib.lua @@ -11,33 +11,13 @@ Discord: https://discord.gg/r6dC2uK -- @module ExpLib -- @usage require('/ExpLib') -local ExpLib = { - text_hex = { - ['']='0x0', - info='0x36F2FF', - alert='0x000000', - low='0x2dc42d', - med='0xffe242', - high='0xff5400', - crit='0xFF0000' - }, - text_rgb = { - ['']={0,0,0}, - info={54,242,255}, - alert={0,0,0}, - low={45,196,45}, - med={255,226,66}, - high={255,84,0}, - crit={255,0,0} - } -} - +local ExpLib = {} --- Loads a table into the global lua table -- @usage a = {k1='foo',k2='bar'} -- _load_to_G(a) -- @tparam table tbl table to add to the global lua table function ExpLib._load_to_G(tbl) - if not is_type(tbl,'table') or game then return end + if not type(tbl) == 'table' or game then return end for name,value in pairs(tbl) do if not _G[name] then _G[name] = value end end @@ -74,30 +54,41 @@ function ExpLib.player_return(rtn) end --- Logs an embed to the json.data we use a js script to add things we cant here --- @usage a = 'some data' --- json_emit('data','info',a) --- @tparam string type the type of emit your programe will look for --- @tparam string colour the colour based on the the text_hex use '' for no colour --- @param data any data which you want to include this will also be conevert to json -function ExpLib.discord_emit(title,colour,description,fields,add_to_server_detail) - if not is_type(title,'string') or - not is_type(fields,'table') then return end - local add_to_server_detail = add_to_server_detail or '' - local colour = colour or '' - local description or '' +-- @usage json_emit{title='BAN',color_name='info',description='A player was banned' ... } +-- @tparam table arg a table which contains everything that the embeded will use +-- @param[opt=''] title the tile of the embed +-- @param[opt='0x0'] color the color given in hex you can use Color.to_hex{r=0,g=0,b=0} +-- @param[opt=''] description the description of the embed +-- @param[opt=''] server_detail sting to add onto the pre-set server detail +-- @param[opt] fieldone the filed to add to the embed (key is name) (value is text) (start value with <> to make inline) +-- @param[optchain] fieldtwo +function ExpLib.discord_emit(args) + if not is_type(args,'table') then return end + local title = is_type(args.title,'string') and args.title or '' + local color = is_type(args.color,'string') and args.color:find("0x") and args.color or '0x0' + local description = is_type(args.description,'string') and args.description or '' + local server_detail = is_type(args.server_detail,'string') and args.server_detail or '' + local done, fields = {title=true,color=true,description=true,server_detail=true}, {{ + name='Server Details', + value='Server Name: {{ serverName }} Online Players: '..#game.connected_players..' Server Time: '..tick_to_display_format(game.tick)..' '..server_detail + }} + for key, value in pairs(args) do + if not done[key] then + done[key] = true + local f = {name=key,value='',inline=false} + local value, inline = value:gsub("<>",'',1) + f.value = value + if inline > 0 then f.inline = true end + table.insert(fields,f) + end + end local log_data = { - title=title - description=description - color=text_hex[colour], - fields={ - { - name='Server Details', - value='Server Name: {{ serverName }} Online Players: '..#game.connected_players..' Server Time: '..tick_to_display_format(game.tick)..' '..add_to_server_detail - }, - unpack(fields) - } + title=title, + description=description, + color=color, + fields=fields } - game.write_file('json.data',table.json(log_data),true,0) + game.write_file('json.data','\n'..table.json(log_data),true,0) end --- Convert ticks to hours @@ -139,16 +130,4 @@ function ExpLib.tick_to_display_format(tick) end end ---- Returns a string as a hex format (also a string) --- @usage a = 'foo' --- string.to_hex(a) -- return '666f6f' --- @tparam string str the string to encode --- @treturn string the hex format of the string -function string.to_hex(str) - if not is_type(str,'string') then return '' end - return str:gsub('.',function (c) - return string.format('%02X',string.byte(c)) - end) -end - return ExpLib \ No newline at end of file diff --git a/control.lua b/control.lua index 88200d7b..8f55a0f8 100644 --- a/control.lua +++ b/control.lua @@ -8,10 +8,25 @@ Discord: https://discord.gg/r6dC2uK ]] --Please Only Edit Below This Line----------------------------------------------------------- +-- replaces the base error function +_error = error +error = function(err) + if _G.discord_emit then + local color = _G.Color and Color.to_hex(defines.text_color.bg) or '0x0' + discord_emit{title='SCRIPT ERROR',color=color,description=err} + elseif _G.game then + if Game.print_all(err) == 0 then + _error(err) + end + else + _error(err) + end +end + -- loads the stdlib and allows Core Game and Event local StdLib = require '/locale/StdLib/load' local Core, Game, Event = StdLib.Core, StdLib.Game, StdLib.Event -- loads the ExpLib, functions are plased into the lua global local ExpLib = require 'ExpLib' -ExpLib._load_to_G(ExpLib) \ No newline at end of file +ExpLib._load_to_G(ExpLib) diff --git a/locale/StdLib/color.lua b/locale/StdLib/color.lua new file mode 100644 index 00000000..d62fef50 --- /dev/null +++ b/locale/StdLib/color.lua @@ -0,0 +1,314 @@ +--- A defines module for retrieving colors by name. +-- Extends the Factorio defines table. +-- @usage require('stdlib/defines/color') +-- @module defines.color +-- @see Concepts.Color + +-- defines table is automatically required in all mod loading stages. +-- luacheck: ignore 122/defines +-- Ignore assigning to read only defines table. defines table is not ready only, however +-- marking it this way allows warnings to be generated when trying to assign values + +defines = defines or {} --luacheck: ignore defines (This is used for testing locally) + +--- A table of colors allowing retrieval by color name. +-- @usage color = defines.color.red +-- @tfield Concepts.Color white +-- @tfield Concepts.Color black +-- @tfield Concepts.Color darkgrey +-- @tfield Concepts.Color grey +-- @tfield Concepts.Color lightgrey +-- @tfield Concepts.Color red +-- @tfield Concepts.Color darkred +-- @tfield Concepts.Color lightred +-- @tfield Concepts.Color green +-- @tfield Concepts.Color darkgreen +-- @tfield Concepts.Color lightgreen +-- @tfield Concepts.Color blue +-- @tfield Concepts.Color darkblue +-- @tfield Concepts.Color lightblue +-- @tfield Concepts.Color orange +-- @tfield Concepts.Color yellow +-- @tfield Concepts.Color pink +-- @tfield Concepts.Color purple +-- @tfield Concepts.Color brown +defines.color = {} + +local colors = { + white = {r = 1.00, g = 1.00, b = 1.00}, + black = {r = 0.00, g = 0.00, b = 0.00}, + darkgrey = {r = 0.25, g = 0.25, b = 0.25}, + grey = {r = 0.50, g = 0.50, b = 0.50}, + lightgrey = {r = 0.75, g = 0.75, b = 0.75}, + red = {r = 1.00, g = 0.00, b = 0.00}, + darkred = {r = 0.50, g = 0.00, b = 0.00}, + lightred = {r = 1.00, g = 0.50, b = 0.50}, + green = {r = 0.00, g = 1.00, b = 0.00}, + darkgreen = {r = 0.00, g = 0.50, b = 0.00}, + lightgreen = {r = 0.50, g = 1.00, b = 0.50}, + blue = {r = 0.00, g = 0.00, b = 1.00}, + darkblue = {r = 0.00, g = 0.00, b = 0.50}, + lightblue = {r = 0.50, g = 0.50, b = 1.00}, + orange = {r = 1.00, g = 0.55, b = 0.10}, + yellow = {r = 1.00, g = 1.00, b = 0.00}, + pink = {r = 1.00, g = 0.00, b = 1.00}, + purple = {r = 0.60, g = 0.10, b = 0.60}, + brown = {r = 0.60, g = 0.40, b = 0.10} +} + +--- Returns white for dark colors or black for lighter colors. +-- @tfield Concepts.Color green defines.color.black +-- @tfield Concepts.Color grey defines.color.black +-- @tfield Concepts.Color lightblue defines.color.black +-- @tfield Concepts.Color lightgreen defines.color.black +-- @tfield Concepts.Color lightgrey defines.color.black +-- @tfield Concepts.Color lightred defines.color.black +-- @tfield Concepts.Color orange defines.color.black +-- @tfield Concepts.Color white defines.color.black +-- @tfield Concepts.Color yellow defines.color.black +-- @tfield Concepts.Color black defines.color.white +-- @tfield Concepts.Color blue defines.color.white +-- @tfield Concepts.Color brown defines.color.white +-- @tfield Concepts.Color darkblue defines.color.white +-- @tfield Concepts.Color darkgreen defines.color.white +-- @tfield Concepts.Color darkgrey defines.color.white +-- @tfield Concepts.Color darkred defines.color.white +-- @tfield Concepts.Color pink defines.color.white +-- @tfield Concepts.Color purple defines.color.white +-- @tfield Concepts.Color red defines.color.white +defines.anticolor = {} + +local anticolors = { + green = colors.black, + grey = colors.black, + lightblue = colors.black, + lightgreen = colors.black, + lightgrey = colors.black, + lightred = colors.black, + orange = colors.black, + white = colors.black, + yellow = colors.black, + black = colors.white, + blue = colors.white, + brown = colors.white, + darkblue = colors.white, + darkgreen = colors.white, + darkgrey = colors.white, + darkred = colors.white, + pink = colors.white, + purple = colors.white, + red = colors.white +} + +--- Returns a lighter color of a named color. +-- @tfield Concepts.Color white defines.color.lightgrey +-- @tfield Concepts.Color grey defines.color.darkgrey +-- @tfield Concepts.Color lightgrey defines.color.grey +-- @tfield Concepts.Color red defines.color.lightred +-- @tfield Concepts.Color green defines.color.lightgreen +-- @tfield Concepts.Color blue defines.color.lightblue +-- @tfield Concepts.Color yellow defines.color.orange +-- @tfield Concepts.Color pink defines.color.purple +defines.lightcolor = {} +local lightcolors = { + white = colors.lightgrey, + grey = colors.darkgrey, + lightgrey = colors.grey, + red = colors.lightred, + green = colors.lightgreen, + blue = colors.lightblue, + yellow = colors.orange, + pink = colors.purple +} + +-- added by cooldude2606 +--- Returns a lighter color of a named color. +-- @tfield Concepts.Color info +-- @tfield Concepts.Color bg +-- @tfield Concepts.Color low +-- @tfield Concepts.Color med +-- @tfield Concepts.Color high +-- @tfield Concepts.Color crit +defines.text_color = {} +local text_color = { + info = {r = 0.21, g = 0.95, b = 1.00}, + bg = {r = 0.00, g = 0.00, b = 0.00}, + low = {r = 0.18, g = 0.77, b = 0.18}, + med = {r = 1.00, g = 0.89, b = 0.26}, + high = {r = 1.00, g = 0.33, b = 0.00}, + crit = {r = 1.00, g = 0.00, b = 0.00} +} + +local _mt = { + color = { + __index = function(_, c) + return colors[c] + and { r = colors[c]['r'], g=colors[c]['g'], b=colors[c]['b'], a = colors[c]['a'] } + or { r = 1, g = 1, b = 1, a = 1 } + end, + __pairs = function() + local k = nil + local c = colors + return function() + local v + k, v = next(c, k) + return k, (v and {r = v['r'], g = v['g'], b = v['b'], a = v['a']}) or nil + end + end + }, + anticolor = { + __index = function(_, c) + return anticolors[c] + and { r = anticolors[c]['r'], g=anticolors[c]['g'], b=anticolors[c]['b'], a = anticolors[c]['a'] } + or { r = 1, g = 1, b = 1, a = 1 } + end, + __pairs = function() + local k = nil + local c = anticolors + return function() + local v + k, v = next(c, k) + return k, (v and {r = v['r'], g = v['g'], b = v['b'], a = v['a']}) or nil + end + end + }, + lightcolor = { + __index = function(_, c) + return lightcolors[c] + and { r = lightcolors[c]['r'], g=lightcolors[c]['g'], b=lightcolors[c]['b'], a = lightcolors[c]['a'] } + or { r = 1, g = 1, b = 1, a = 1 } + end, + __pairs = function() + local k = nil + local c = lightcolors + return function() + local v + k, v = next(c, k) + return k, (v and {r = v['r'], g = v['g'], b = v['b'], a = v['a']}) or nil + end + end + }, + text_color = { -- added by cooldude2606 + __index = function(_, c) + return text_color[c] + and { r = text_color[c]['r'], g=text_color[c]['g'], b=text_color[c]['b'], a = text_color[c]['a'] } + or { r = 1, g = 1, b = 1, a = 1 } + end, + __pairs = function() + local k = nil + local c = text_color + return function() + local v + k, v = next(c, k) + return k, (v and {r = v['r'], g = v['g'], b = v['b'], a = v['a']}) or nil + end + end + } +} +setmetatable(defines.color, _mt.color) +setmetatable(defines.anticolor, _mt.anticolor) +setmetatable(defines.text_color, _mt.text_color) +setmetatable(defines.lightcolor, _mt.lightcolor) + +--- For playing with colors. +-- @module Color +-- @usage local Color = require('stdlib/color/color') + +--require 'stdlib/defines/color' +local fail_if_missing = require 'game'['fail_if_missing'] + +Color = {} --luacheck: allow defined top + +--- Set a value for the alpha channel in the given color table. +-- `color.a` represents the alpha channel in the given color table. +-- +-- @tparam[opt=white] defines.color|Concepts.Color color the color to configure +-- @tparam[opt=1] float alpha the alpha value (*[0 - 1]*) to set for the given color +-- @treturn Concepts.Color a color table that has the specified value for the alpha channel +function Color.set(color, alpha) + color = color or defines.color.white + Color.to_table(color) + color.a = alpha or color.a or 1 + return color +end + +--- Converts a color in the array format to a color in the table format. +-- @tparam array c_arr the color to convert — { [1] = @{float}, [2] = @{float}, [3] = @{float}, [4] = @{float} } +-- @treturn Concepts.Color a converted color — { r = c\_arr[1], g = c\_arr[2], b = c\_arr[3], a = c\_arr[4] } +function Color.to_table(c_arr) + if #c_arr > 0 then + return {r = c_arr[1], g = c_arr[2], b = c_arr[3], a = c_arr[4]} + end + return c_arr +end + +--- Converts a color in the rgb format to a color table +-- @tparam[opt=0] int r 0-255 red +-- @tparam[opt=0] int g 0-255 green +-- @tparam[opt=0] int b 0-255 blue +-- @tparam[opt=255] int a 0-255 alpha +-- @treturn Concepts.Color +function Color.from_rgb(r, g, b, a) + r = r or 0 + g = g or 0 + b = b or 0 + a = a or 255 + return {r = r/255, g = g/255, b = b/255, a = a/255} +end + +--- Get a color table with a hexadecimal string. +-- Optionally provide the value for the alpha channel. +-- @tparam string hex hexadecimal color string (#ffffff, not #fff) +-- @tparam[opt=1] float alpha the alpha value to set; such that ***[ 0 ⋜ value ⋜ 1 ]*** +-- @treturn Concepts.Color a color table with RGB converted from Hex and with alpha +function Color.from_hex(hex, alpha) + fail_if_missing(hex, "missing color hex value") + if hex:find("#") then hex = hex:sub(2) end + if not(#hex == 6) then error("invalid color hex value: "..hex) end + local number = tonumber(hex, 16) + return { + r = bit32.extract(number, 16, 8) / 255, + g = bit32.extract(number, 8, 8) / 255, + b = bit32.extract(number, 0, 8) / 255, + a = alpha or 1 + } +end + +--added by cooldude2606 +--- Converts a color in the color table format to rgb +-- @tparam table color the color to convert +-- @treturn table the color as rgb +function Color.to_rgb(color) + local r = color.r or 0 + local g = color.g or 0 + local b = color.b or 0 + local a = color.a or 0.5 + return {r = r*255, g = g*255, b = b*255, a = a*255} +end + +--added by cooldude2606 +--- Converts a color in the color table format to hex +-- @tparam table color the color to convert +-- @treturn string the color as hex +function Color.to_hex(color) + local hexadecimal = '0x' + for key, value in pairs{math.floor(color.r*255),math.floor(color.g*255),math.floor(color.b*255)} do + local hex = '' + while(value > 0)do + local index = math.fmod(value, 16) + 1 + value = math.floor(value / 16) + hex = string.sub('0123456789ABCDEF', index, index) .. hex + end + if string.len(hex) == 0 then hex = '00' + elseif string.len(hex) == 1 then hex = '0' .. hex + end + hexadecimal = hexadecimal .. hex + end + return hexadecimal +end + +return Color diff --git a/locale/StdLib/core.lua b/locale/StdLib/core.lua deleted file mode 100644 index 3fb83a51..00000000 --- a/locale/StdLib/core.lua +++ /dev/null @@ -1,16 +0,0 @@ ---- Core module --- @module Core - -Core = {} --luacheck: allow defined top - ---- Errors if the variable evaluates to false, with an optional msg --- @param var variable to evaluate --- @tparam[opt='missing value'] string msg message -function Core.fail_if_missing(var, msg) - if not var then - error(msg or "Missing value", 3) - end - return false -end - -return Core \ No newline at end of file diff --git a/locale/StdLib/event.lua b/locale/StdLib/event.lua index 6725dacb..db8c0ed7 100644 --- a/locale/StdLib/event.lua +++ b/locale/StdLib/event.lua @@ -5,7 +5,7 @@ -- @module Event -- @usage require('stdlib/event/event') -local fail_if_missing = require 'core'['fail_if_missing'] +local fail_if_missing = require 'game'['fail_if_missing'] local Game = require 'game' local Event = { --luacheck: allow defined top @@ -102,9 +102,11 @@ function Event.dispatch(event) -- If the handler errors lets make sure someone notices if not success then if _G.game then -- may be nil in on_load - if Game.print_all(err) == 0 then - error(err) -- no players received the message, force a real error so someone notices - end + -- edit by cooldude2606 custom error haddle + --if Game.print_all(err) == 0 then + --error(err) -- no players received the message, force a real error so someone notices + --end + error(err) else error(err) -- no way to handle errors cleanly when the game is not up end diff --git a/locale/StdLib/game.lua b/locale/StdLib/game.lua index 642e7913..b31468ac 100644 --- a/locale/StdLib/game.lua +++ b/locale/StdLib/game.lua @@ -1,26 +1,103 @@ ---- Game module +--- The game module. -- @module Game -- @usage local Game = require('stdlib/game') -Game = {} --luacheck: allow defined top +Game = { --luacheck: allow defined top + VALID_FILTER = function(v) + return v and v.valid + end, + _protect = function(module_name) + return { + __newindex = function() error("Attempt to mutatate read-only "..module_name.." Module") end, + __metatable = true + } + end, + _concat = function(lhs, rhs) + --Sanatize to remove address + return tostring(lhs):gsub("(%w+)%: %x+", "%1: (ADDR)") .. tostring(rhs):gsub("(%w+)%: %x+", "%1: (ADDR)") + end, + _rawstring = function (t) + local m = getmetatable(t) + local f = m.__tostring + m.__tostring = nil + local s = tostring(t) + m.__tostring = f + return s + end +} -Game.VALID_FILTER = function(v) - return v.valid +-- No Doc +-- This is a helper global and functions until .16 +-- to set the name of your mod in control.lua set _stdlib_mod_name = 'name of your mod' +-- luacheck: ignore _stdlib_mod_name +function Game.get_mod_name() + local ok, mod_name = pcall(function() return script.mod_name end) + return ok and mod_name or _stdlib_mod_name or "stdlib" end ---- Messages all players currently connected to the game --- @tparam string msg message to send to players --- @param[opt] condition condition to be true for the player to be messaged --- @treturn int the number of players who received the message. Offline players are not counted as having received the message. +--- Print msg if specified var evaluates to false. +-- @tparam Mixed var variable to evaluate +-- @tparam[opt="missing value"] string msg message +function Game.fail_if_missing(var, msg) + if not var then + error(msg or "Missing value", 3) + end + return false +end + +--- Return a valid player object from event, index, string, or userdata +-- @tparam string|number|LuaPlayer|event mixed +-- @treturn LuaPlayer a valid player or nil +function Game.get_player(mixed) + if type(mixed) == "table" then + if mixed.__self then + return mixed and mixed.valid and mixed + elseif mixed.player_index then + local player = game.players[mixed.player_index] + return player and player.valid and player + end + elseif mixed then + local player = game.players[mixed] + return player and player.valid and player + end +end + +--- Return a valid force object from event, string, or userdata +-- @tparam string|LuaForce|event mixed +-- @treturn LuaForce a valid force or nil +function Game.get_force(mixed) + if type(mixed) == "table" then + if mixed.__self then + return mixed and mixed.valid and mixed + elseif mixed.force then + return Game.get_force(mixed.force) + end + elseif type(mixed) == "string" then + local force = game.forces[mixed] + return (force and force.valid) and force + end +end + +--- Messages all players currently connected to the game. +--> Offline players are not counted as having received the message. +-- If no players exist msg is stored in the `global._print_queue` table. +-- @tparam string msg the message to send to players +-- @tparam[opt] ?|nil|boolean condition the condition to be true for a player to be messaged +-- @treturn uint the number of players who received the message. function Game.print_all(msg, condition) local num = 0 - for _, player in pairs(game.connected_players) do - if condition == nil or select(2, pcall(condition, player)) then - player.print(msg) - num = num + 1 + if #game.players > 0 then + for _, player in pairs(game.players) do + if condition == nil or select(2, pcall(condition, player)) then + player.print(msg) + num = num + 1 + end end + return num + else + global._print_queue = global._print_queue or {} + global._print_queue[#global._print_queue + 1] = msg end - return num end -return Game \ No newline at end of file +return Game diff --git a/locale/StdLib/load.lua b/locale/StdLib/load.lua index 2d4ec45d..3ff84f77 100644 --- a/locale/StdLib/load.lua +++ b/locale/StdLib/load.lua @@ -16,9 +16,11 @@ The array returned contains the stdlib modules so there can be decleared after t local StdLib = {} -StdLib.Core = require 'core' -StdLib.Game = require 'game' -StdLib.Event = require 'event' require '/table' +require '/string' +require '/time' +StdLib.Colour = require '/color' +StdLib.Game = require '/game' +StdLib.Event = require '/event' return StdLib \ No newline at end of file diff --git a/locale/StdLib/string.lua b/locale/StdLib/string.lua new file mode 100644 index 00000000..b151e34a --- /dev/null +++ b/locale/StdLib/string.lua @@ -0,0 +1,86 @@ +--- Extends Lua 5.2 string. +-- @module string +-- @see string + +-- luacheck: globals string (Allow mutating string) + +--- Returns a copy of the string with any leading or trailing whitespace from the string removed. +-- @tparam string s the string to remove leading or trailing whitespace from +-- @treturn string a copy of the string without leading or trailing whitespace +function string.trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +--- Tests if a string starts with a given substring. +-- @tparam string s the string to check for the start substring +-- @tparam string start the substring to test for +-- @treturn boolean true if the start substring was found in the string +function string.starts_with(s, start) + return string.find(s, start, 1, true) == 1 +end + +--- Tests if a string ends with a given substring. +-- @tparam string s the string to check for the end substring +-- @tparam string ends the substring to test for +-- @treturn boolean true if the end substring was found in the string +function string.ends_with(s, ends) + return #s >= #ends and string.find(s, ends, #s - #ends + 1, true) and true or false +end + +--- Tests if a string contains a given substring. +-- @tparam string s the string to check for the substring +-- @tparam string contains the substring to test for +-- @treturn boolean true if the substring was found in the string +function string.contains(s, contains) + return s and string.find(s, contains) ~= nil +end + +--- Tests whether a string is empty. +-- @tparam string s the string to test +-- @treturn boolean true if the string is empty +function string.is_empty(s) + return s == nil or s == '' +end + +--- Splits a string into an array. +-- *Note:* Empty split substrings are not included in the resulting table. +--

For example, `string.split("foo.bar...", ".", false)` results in the table `{"foo", "bar"}`. +-- @tparam string s the string to split +-- @tparam[opt="."] string sep the separator to use. +-- @tparam[opt=false] boolean pattern whether to interpret the separator as a lua pattern or plaintext for the string split +-- @treturn {string,...} an array of strings +function string.split(s, sep, pattern) + sep = sep or "." + sep = sep ~= "" and sep or "." + sep = not pattern and string.gsub(sep, "([^%w])", "%%%1") or sep + + local fields = {} + local start_idx, end_idx = string.find(s, sep) + local last_find = 1 + while start_idx do + local substr = string.sub(s, last_find, start_idx - 1) + if string.len(substr) > 0 then + table.insert(fields, string.sub(s, last_find, start_idx - 1)) + end + last_find = end_idx + 1 + start_idx, end_idx = string.find(s, sep, end_idx + 1) + end + local substr = string.sub(s, last_find) + if string.len(substr) > 0 then + table.insert(fields, string.sub(s, last_find)) + end + return fields +end + +-- added by cooldude2606 +--- Returns a string as a hex format (also a string) +-- @usage a = 'foo' +-- string.to_hex(a) -- return '666f6f' +-- @tparam string str the string to encode +-- @treturn string the hex format of the string +function string.to_hex(str) + if not is_type(str,'string') then return '' end + return str:gsub('.',function (c) + return string.format('%02X',string.byte(c)) + end) +end \ No newline at end of file diff --git a/locale/StdLib/table.lua b/locale/StdLib/table.lua index 5388752a..2a26e73b 100644 --- a/locale/StdLib/table.lua +++ b/locale/StdLib/table.lua @@ -462,7 +462,7 @@ function table.json(lua_table) local result, done, only_indexs = {}, {}, true for key,value in ipairs(lua_table) do done[key] = true - if type(value) == 'table' then table.insert(result,json_log(value,true)) + if type(value) == 'table' then table.insert(result,table.json(value,true)) elseif type(value) == 'string' then table.insert(result,'"'..value..'"') elseif type(value) == 'number' then table.insert(result,value) elseif type(value) == 'boolean' then table.insert(result,tostring(value)) @@ -472,7 +472,7 @@ function table.json(lua_table) for key,value in pairs(lua_table) do if not done[key] then only_indexs = false - if type(value) == 'table' then table.insert(result,'"'..key..'":'..json_log(value,true)) + if type(value) == 'table' then table.insert(result,'"'..key..'":'..table.json(value,true)) elseif type(value) == 'string' then table.insert(result,'"'..key..'":"'..value..'"') elseif type(value) == 'number' then table.insert(result,'"'..key..'":'..value) elseif type(value) == 'boolean' then table.insert(result,'"'..key..'":'..tostring(value)) diff --git a/locale/StdLib/time.lua b/locale/StdLib/time.lua new file mode 100644 index 00000000..b3b520cb --- /dev/null +++ b/locale/StdLib/time.lua @@ -0,0 +1,31 @@ +--- A defines module for retrieving the number of ticks in 1 unit of time. +-- Extends the Factorio defines table. +-- @module defines.time +-- @usage require('stdlib/defines/time') + +-- defines table is automatically required in all mod loading stages. +-- luacheck: ignore 122/defines +-- Ignore assigning to read only defines table. defines table is not read only, however +-- marking it this way allows warnings to be generated when trying to assign values. + +defines = defines or {} --luacheck: ignore defines (This is used for testing locally) + +local SECOND = 60 +local MINUTE = SECOND * 60 +local HOUR = MINUTE * 60 +local DAY = HOUR * 24 +local WEEK = DAY * 7 +local MONTH = DAY * 30 +local YEAR = DAY * 365 + +--- Returns the number of ticks in a second, minute, hour, day, week, month, or year. +-- @usage local ten_seconds = defines.time.second * 10 +defines.time = { + second = SECOND, -- the number of Factorio ticks in a second + minute = MINUTE, -- the number of Factorio ticks in a second + hour = HOUR, -- the number of Factorio ticks in an hour + day = DAY, -- the number of Factorio ticks in an day + week = WEEK, -- the number of Factorio ticks in a week + month = MONTH, -- the number of Factorio ticks in a month (30 days) + year = YEAR, -- the number of Factorio ticks in a year (365 days) +}