From 06b4ae9b25d2173a93e2e8dbb3a88e7985b53644 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 24 Mar 2019 15:38:27 +0000 Subject: [PATCH 1/6] Moved ExpGamingLib --- old/modules/DONE/ExpGamingLib/control.lua | 330 +++++++++++++++++++++ old/modules/DONE/ExpGamingLib/softmod.json | 19 ++ 2 files changed, 349 insertions(+) create mode 100644 old/modules/DONE/ExpGamingLib/control.lua create mode 100644 old/modules/DONE/ExpGamingLib/softmod.json diff --git a/old/modules/DONE/ExpGamingLib/control.lua b/old/modules/DONE/ExpGamingLib/control.lua new file mode 100644 index 00000000..77b4685c --- /dev/null +++ b/old/modules/DONE/ExpGamingLib/control.lua @@ -0,0 +1,330 @@ +--- Adds some common functions used though out all ExpGaming modules +-- @module ExpGamingLib +-- @alias ExpLib +-- @author Cooldude2606 +-- @license https://github.com/explosivegaming/scenario/blob/master/LICENSE + +local Game = require('FactorioStdLib.Game') +local Color = require('FactorioStdLib.Color') + +local module_verbose = false -- there is no verbose in this file so true will do nothing +local ExpLib = {} + +--- Loads a table into _G even when sandboxes; will not overwrite values or append to tables; will not work during runtime to avoid desyncs +-- @usage unpack_to_G{key1='foo',key2='bar'} +-- @tparam table tbl table to be unpacked +function ExpLib.unpack_to_G(tbl) + if not type(tbl) == 'table' or game then return end + for key,value in pairs(tbl) do + if not _G[key] then rawset(_G,key,value) end + end +end + +--- Used to get the current ENV with all _G keys removed; useful when saving function to global +-- @usage get_env() returns current ENV with _G keys removed +-- @treturn table the env table with _G keys removed +-- @warning does not work from console +function ExpLib.get_env(level) + level = level and level+1 or 2 + local env = setmetatable({},{__index=_G}) + while true do + if not debug.getinfo(level) then break end + local i = 1 + while true do + local name, value = debug.getlocal(level,i) + if not name or _G[name] == value then break else env[name] = value end + i=i+1 + end + level=level+1 + end + return env +end + +--- Used to get the current ENV with all _G keys removed; useful when saving function to global +-- @usage get_env() returns current ENV with _G keys removed +-- @treturn table the env table with _G keys removed +-- @warning does not work from console +function ExpLib.get_upvalues(level) + local func = level and ExpLib.is_type(level,'function') and level or nil + level = level and ExpLib.is_type(level,'number') and level+1 or 2 + func = func or debug.getinfo(level).func + local upvalues = setmetatable({},{__index=_G}) + local i = 1 + while true do + local name, value = debug.getupvalue(func,i) + if not name then break else upvalues[name] = value end + i=i+1 + end + return upvalues +end + +--- Creates a table that will act like a string and a function +-- @usage add_metatable({},function) -- returns table +-- @tparam table tbl the table that will have its metatable set +-- @tparam[opt=tostring] function callback the function that will be used for the call +-- @tparam[opt=table.tostring] ?function|string string a function that resolves to a string or a string +-- @treturn table the new table with its metatable set +function ExpLib.add_metatable(tbl,callback,string) + if not ExpLib.is_type(tbl,'table') then error('No table given to add_metatable',2) end + callback = ExpLib.is_type(callback,'function') and callback or tostring + string = ExpLib.is_type(string,'function') and string or ExpLib.is_type(string,'string') and function() return string end or table.tostring + return setmetatable(tbl,{ + __tostring=string, + __concat=function(val1,val2) return type(val1) == 'string' and val1..string(val2) or string(val1)..val2 end, + __call=callback + }) +end + +--- Compare types faster for faster validation of prams +-- @usage is_type('foo','string') -- return true +-- @usage is_type('foo') -- return false +-- @param v the value to be tested +-- @tparam[opt=nil] string test_type the type to test for if not given then it tests for nil +-- @treturn boolean is v of type test_type +function ExpLib.is_type(v,test_type) + return test_type and v and type(v) == test_type or not test_type and not v or false +end + +--- Compare types faster for faster validation of prams, including giving an error if incorrect +-- @usage type_error('foo','string','Value is not a string') -- return true +-- @usage type_error('foo','table','Value is not a string') -- return error +-- @param value the value to be tested +-- @tparam[opt=nil] string type the type that the value should be +-- @tparam string error_message the message given when type is not matched +-- @treturn boolean if it matched or and error +function ExpLib.type_error(value,type,error_message) + return ExpLib.is_type(value,type) or error(error_message,3) +end + +--- A specialised version of type_error to test for self +-- @usage self_test(self,'Object','get_name') +-- @tparam table self the table that is the object +-- @tparam string prototype_name the name of the class +-- @tparam string function_name the name of the function +function ExpLib.self_test(self,prototype_name,function_name) + return ExpLib.is_type(self,'table') or error('Call to prototype without context, either supply a '..prototype_name..' or use '..prototype_name..':'..function_name,3) +end + +--- Will return a value of any type to the player/server console, allows colour for in-game players +-- @usage player_return('Hello, World!') -- returns 'Hello, World!' to game.player or server console +-- @usage player_return('Hello, World!','green') -- returns 'Hello, World!' to game.player with colour green or server console +-- @usage player_return('Hello, World!',nil,player) -- returns 'Hello, World!' to the given player +-- @param rtn any value of any type that will be returned to the player or console +-- @tparam[opt=defines.colour.white] ?defines.color|string colour the colour of the text for the player, ignored when printing to console +-- @tparam[opt=game.player] LuaPlayer player the player that return will go to, if no game.player then returns to server +function ExpLib.player_return(rtn,colour,player) + colour = ExpLib.is_type(colour,'table') and colour or defines.textcolor[colour] ~= defines.color.white and defines.textcolor[colour] or defines.color[colour] + player = player or game.player + -- converts the value to a string + local returnAsString + if ExpLib.is_type(rtn,'table') then + if ExpLib.is_type(rtn.__self,'userdata') then + -- value is userdata + returnAsString = 'Cant Display Userdata' + elseif ExpLib.is_type(rtn[1],'string') and string.find(rtn[1],'.+[.].+') and not string.find(rtn[1],'%s') then + -- value is a locale string + returnAsString = rtn + elseif getmetatable(rtn) ~= nil and not tostring(rtn):find('table: 0x') then + -- value has a tostring meta method + returnAsString = tostring(rtn) + else + -- value is a table + returnAsString = table.tostring(rtn) + end + elseif ExpLib.is_type(rtn,'function') then + -- value is a function + returnAsString = 'Cant Display Functions' + else returnAsString = tostring(rtn) end + -- returns to the player or the server + if player then + -- allows any valid player identifier to be used + player = Game.get_player(player) + if not player then error('Invalid Player given to player_return',2) end + -- plays a nice sound that is different to normal message sound + player.play_sound{path='utility/scenario_message'} + player.print(returnAsString,colour) + else rcon.print(returnAsString) end +end + +--- Convert ticks to hours +-- @usage tick_to_hour(216001) -- return 1 +-- @tparam number tick tick to convert to hours +-- @treturn number the number of whole hours from this tick +function ExpLib.tick_to_hour(tick) + if not ExpLib.is_type(tick,'number') then return 0 end + if not game then return math.floor(tick/216000) end + return math.floor(tick/(216000*game.speed)) +end + +--- Convert ticks to minutes +-- @usage tick_to_hour(3601) -- return 1 +-- @tparam number tick tick to convert to minutes +-- @treturn number the number of whole minutes from this tick +function ExpLib.tick_to_min (tick) + if not ExpLib.is_type(tick,'number') then return 0 end + if not game then return math.floor(tick/3600) end + return math.floor(tick/(3600*game.speed)) +end + +--- Converts a tick into a clean format for end user +-- @usage tick_to_display_format(3600) -- return '1.00 M' +-- @usage tick_to_display_format(234000) -- return '1 H 5 M' +-- @tparam number tick the tick to convert +-- @treturn string the formated string +function ExpLib.tick_to_display_format(tick) + if not ExpLib.is_type(tick,'number') then return '0H 0M' end + if ExpLib.tick_to_min(tick) < 10 then + if not game then return math.floor(tick/3600) end + return string.format('%.2f M',tick/(3600*game.speed)) + else + return string.format('%d H %d M', + ExpLib.tick_to_hour(tick), + ExpLib.tick_to_min(tick)-60*ExpLib.tick_to_hour(tick) + ) + end +end + +--- Used as a way to view the structure of a gui, used for debugging +-- @usage Gui_tree(root) returns all children of gui recursively +-- @tparam LuaGuiElement root the root to start the tree from +-- @treturn table the table that describes the gui +function ExpLib.gui_tree(root) + if not ExpLib.is_type(root,'table') or not root.valid then error('Invalid Gui Element given to gui_tree',2) end + local tree = {} + for _,child in pairs(root.children) do + if #child.children > 0 then + if child.name then tree[child.name] = ExpLib.gui_tree(child) + else table.insert(tree,ExpLib.gui_tree(child)) end + else + if child.name then tree[child.name] = child.type + else table.insert(tree,child.type) end + end + end + return tree +end + +--- Extents the table class +-- @type table +-- @alias table + +--- Returns a value in a form able to be read as a value, any value to string +-- @usage table.val_to_str{a='foo'} -- return '"foo"' +-- @param v value to convert +-- @treturn string the converted value +function table.val_to_str(v) + if "string" == type( v ) then + v = string.gsub(v,"\n","\\n") + if string.match(string.gsub(v,"[^'\"]",""),'^"+$') then + return "'"..v.."'" + end + return '"'..string.gsub(v,'"', '\\"' )..'"' + else + return "table" == type( v) and table.tostring(v) or + "function" == type(v) and '"cant-display-function"' or + "userdata" == type(v) and '"cant-display-userdata"' or + tostring(v) + end +end + +--- Returns a value in a form able to be read as a key, any key to string +-- @usage table.val_to_str{a='foo'} -- return '["a"]' +-- @param k key to convert +-- @treturn string the converted key +function table.key_to_str (k) + if "string" == type(k) and string.match(k,"^[_%player][_%player%d]*$") then + return k + else + return "["..table.val_to_str(k).."]" + end +end + +--- Returns a table in a form able to be read as a table +-- @usage table.tostring{k1='foo',k2='bar'} -- return '{["k1"]="foo",["k2"]="bar"}' +-- @tparam table tbl table to convert +-- @treturn string the converted table +function table.tostring(tbl) + if type(tbl) ~= 'table' then return tostring(tbl) end + local result, done = {}, {} + for k, v in ipairs(tbl) do + table.insert(result,table.val_to_str(v)) + done[k] = true + end + for k, v in pairs(tbl) do + if not done[k] then + table.insert(result, + table.key_to_str(k).."="..table.val_to_str(v)) + end + end + return "{"..table.concat(result,",") .."}" +end + +--- Similar to table.tostring but converts a lua table to a json one +-- @usage table.json{k1='foo',k2='bar'} -- return '{"k1":"foo","k2":"bar"}' +-- @tparam table lua_table the table to convert +-- @treturn string the table in a json format +function table.json(lua_table) + --if game and game.table_to_json then return game.table_to_json(lua_table) end + local result, done, only_indexes = {}, {}, true + for key,value in ipairs(lua_table) do + done[key] = true + if type(value) == 'table' then table.insert(result,table.json(value,true)) + elseif not value then table.insert(result,'null') + else table.insert(result,table.val_to_str(value)) + end + end + for key,value in pairs(lua_table) do + if not done[key] then + only_indexes = false + if type(value) == 'table' then table.insert(result,table.val_to_str(key)..':'..table.json(value,true)) + elseif not value then table.insert(result,table.val_to_str(key)..':null') + else table.insert(result,table.val_to_str(key)..':'..table.val_to_str(value)) + end + end + end + if only_indexes then return "["..table.concat(result,",").."]" + else return "{"..table.concat(result,",").."}" + end +end + +--- Returns the closest match to a key +-- @usage table.autokey({foo=1,bar=2},'f') -- return 1 +-- @tparam table tbl the table that will be searched +-- @tparam string str the string that will be looked for in the keys +function table.autokey(tbl,str) + if not ExpLib.is_type(str,'string') then return end + local _return = {} + for key,value in pairs(tbl) do + if string.contains(string.lower(key),string.lower(str)) then table.insert(_return,value) end + end + return _return[1] or false +end + +--- Returns the list is a sorted way that would be expected by people (this is by key) +-- @usage tbl = table.alphanumsort(tbl) +-- @tparam table tbl the table to be sorted +-- @treturn table the sorted table +function table.alphanumsort(tbl) + local o = table.keys(tbl) + local function padnum(d) local dec, n = string.match(d, "(%.?)0*(.+)") + return #dec > 0 and ("%.12f"):format(d) or ("%s%03d%s"):format(dec, #n, n) end + table.sort(o, function(a,b) + return tostring(a):gsub("%.?%d+",padnum)..("%3d"):format(#b) + < tostring(b):gsub("%.?%d+",padnum)..("%3d"):format(#a) end) + local _tbl = {} + for _,k in pairs(o) do _tbl[k] = tbl[k] end + return _tbl +end + +--- Returns the list is a sorted way that would be expected by people (this is by key) (faster alterative than above) +-- @usage tbl = table.alphanumsort(tbl) +-- @tparam table tbl the table to be sorted +-- @treturn table the sorted table +function table.keysort(tbl) + local o = table.keys(tbl,true) + local _tbl = {} + for _,k in pairs(o) do _tbl[k] = tbl[k] end + return _tbl +end + +ExpLib:unpack_to_G() +return ExpLib \ No newline at end of file diff --git a/old/modules/DONE/ExpGamingLib/softmod.json b/old/modules/DONE/ExpGamingLib/softmod.json new file mode 100644 index 00000000..160803be --- /dev/null +++ b/old/modules/DONE/ExpGamingLib/softmod.json @@ -0,0 +1,19 @@ +{ + "name": "ExpGamingLib", + "version": "4.0.0", + "description": "Adds some common functions used though out all ExpGaming modules", + "location": "FSM_ARCHIVE", + "keywords": [ + "ExpGaming", + "Lib" + ], + "author": "Cooldude2606", + "contact": "Discord: Cooldude2606#5241", + "license": "https://github.com/explosivegaming/scenario/blob/master/LICENSE", + "dependencies": { + "FactorioStdLib.Game": "^0.8.0", + "FactorioStdLib.Color": "^0.8.0", + "FactorioStdLib.Table": "^0.8.0" + }, + "submodules": {} +} From 7c4210f8b48d821c1c90087d3e7c016264072451 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 24 Mar 2019 15:39:17 +0000 Subject: [PATCH 2/6] Added command_auth_runtime_disable --- config/command_auth_admin.lua | 2 +- config/command_auth_runtime_disable.lua | 25 ++ config/config.cfg | 3 + config/death_markers.lua | 12 + config/file_loader.lua | 3 +- locale/en/config.cfg | 3 + modules/addons/death-markers.lua | 7 + .../{ => DONE}/DeathMarkers/control.lua | 0 .../{ => DONE}/DeathMarkers/softmod.json | 0 old/modules/ExpGamingLib/control.lua | 330 ------------------ old/modules/ExpGamingLib/softmod.json | 19 - 11 files changed, 53 insertions(+), 351 deletions(-) create mode 100644 config/command_auth_runtime_disable.lua create mode 100644 config/config.cfg create mode 100644 config/death_markers.lua create mode 100644 locale/en/config.cfg create mode 100644 modules/addons/death-markers.lua rename old/modules/{ => DONE}/DeathMarkers/control.lua (100%) rename old/modules/{ => DONE}/DeathMarkers/softmod.json (100%) delete mode 100644 old/modules/ExpGamingLib/control.lua delete mode 100644 old/modules/ExpGamingLib/softmod.json diff --git a/config/command_auth_admin.lua b/config/command_auth_admin.lua index 4817e643..19ef9198 100644 --- a/config/command_auth_admin.lua +++ b/config/command_auth_admin.lua @@ -8,7 +8,7 @@ Commands.add_authenticator(function(player,command,tags,reject) if player.admin then return true else - return reject('This command is for admins only!') + return reject{'command-auth.admin-only'} end else return true diff --git a/config/command_auth_runtime_disable.lua b/config/command_auth_runtime_disable.lua new file mode 100644 index 00000000..0f4861fb --- /dev/null +++ b/config/command_auth_runtime_disable.lua @@ -0,0 +1,25 @@ +--- This config for command auth allows commands to be globally enabled and disabled during runtime +-- this config adds Commands.disable and Commands.enable to enable and disable commands for all users +local Commands = require 'expcore.commands' +local Global = require 'utils.global' + +local disabled_commands = {} +Global.register(disabled_commands,function(tbl) + disabled_commands = tbl +end) + +function Commands.disable(command_name) + disabled_commands[command_name] = true +end + +function Commands.enable(command_name) + disabled_commands[command_name] = nil +end + +Commands.add_authenticator(function(player,command,tags,reject) + if disabled_commands[command] then + return reject{'command-auth.command-disabled'} + else + return true + end +end) \ No newline at end of file diff --git a/config/config.cfg b/config/config.cfg new file mode 100644 index 00000000..b12b17cf --- /dev/null +++ b/config/config.cfg @@ -0,0 +1,3 @@ +[command-auth] +admin-only=This command is for (game) admins only! +command-disabled=This command has been disabled by management! \ No newline at end of file diff --git a/config/death_markers.lua b/config/death_markers.lua new file mode 100644 index 00000000..cb195cde --- /dev/null +++ b/config/death_markers.lua @@ -0,0 +1,12 @@ +--- This config controls what happens when a player dies mostly about map markers and item collection +-- allow_teleport_to_body_command and allow_collect_bodies_command can be over ridden if command_auth_runtime_disable is present +-- if not present then the commands will not be loaded into the game +return { + allow_teleport_to_body_command=false, -- allows use of /return-to-body which teleports you to your last death + allow_collect_bodies_command=false, -- allows use of /collect-body which returns all your items to you and removes the body + use_chests_as_bodies=false, -- weather items should be moved into a chest when a player dies + auto_collect_bodies=false, -- enables items being returned to the spawn point in chests upon death + show_map_markers=true, -- shows markers on the map where bodies are + include_time_of_death=true, -- weather to include the time of death on the map marker + map_icon='' -- the icon that the map marker shows '' means no icon +} \ No newline at end of file diff --git a/config/file_loader.lua b/config/file_loader.lua index 79f42801..c87e9d85 100644 --- a/config/file_loader.lua +++ b/config/file_loader.lua @@ -18,6 +18,7 @@ return { 'modules.addons.chat-popups', 'modules.addons.damage-popups', -- Config Files - 'config.command_auth_admin', -- commands tags with admin_only are blocked for non admins + 'config.command_auth_admin', -- commands tagged with admin_only are blocked for non admins + 'config.command_auth_runtime_disable', -- allows commands to be enabled and disabled during runtime 'config.permission_groups', -- loads some predefined permission groups } \ No newline at end of file diff --git a/locale/en/config.cfg b/locale/en/config.cfg new file mode 100644 index 00000000..b12b17cf --- /dev/null +++ b/locale/en/config.cfg @@ -0,0 +1,3 @@ +[command-auth] +admin-only=This command is for (game) admins only! +command-disabled=This command has been disabled by management! \ No newline at end of file diff --git a/modules/addons/death-markers.lua b/modules/addons/death-markers.lua new file mode 100644 index 00000000..616854b9 --- /dev/null +++ b/modules/addons/death-markers.lua @@ -0,0 +1,7 @@ +local Event = require 'utils.event' +local Game = require 'utils.game' +local Global = require 'utils.global' +local Commands = require 'expcore.commands' +local config = require 'config.death_markers' +local opt_require = ext_require('expcore.common','opt_require') +opt_require 'config.command_auth_runtime_disable' -- if the file is present then we can disable the commands \ No newline at end of file diff --git a/old/modules/DeathMarkers/control.lua b/old/modules/DONE/DeathMarkers/control.lua similarity index 100% rename from old/modules/DeathMarkers/control.lua rename to old/modules/DONE/DeathMarkers/control.lua diff --git a/old/modules/DeathMarkers/softmod.json b/old/modules/DONE/DeathMarkers/softmod.json similarity index 100% rename from old/modules/DeathMarkers/softmod.json rename to old/modules/DONE/DeathMarkers/softmod.json diff --git a/old/modules/ExpGamingLib/control.lua b/old/modules/ExpGamingLib/control.lua deleted file mode 100644 index 77b4685c..00000000 --- a/old/modules/ExpGamingLib/control.lua +++ /dev/null @@ -1,330 +0,0 @@ ---- Adds some common functions used though out all ExpGaming modules --- @module ExpGamingLib --- @alias ExpLib --- @author Cooldude2606 --- @license https://github.com/explosivegaming/scenario/blob/master/LICENSE - -local Game = require('FactorioStdLib.Game') -local Color = require('FactorioStdLib.Color') - -local module_verbose = false -- there is no verbose in this file so true will do nothing -local ExpLib = {} - ---- Loads a table into _G even when sandboxes; will not overwrite values or append to tables; will not work during runtime to avoid desyncs --- @usage unpack_to_G{key1='foo',key2='bar'} --- @tparam table tbl table to be unpacked -function ExpLib.unpack_to_G(tbl) - if not type(tbl) == 'table' or game then return end - for key,value in pairs(tbl) do - if not _G[key] then rawset(_G,key,value) end - end -end - ---- Used to get the current ENV with all _G keys removed; useful when saving function to global --- @usage get_env() returns current ENV with _G keys removed --- @treturn table the env table with _G keys removed --- @warning does not work from console -function ExpLib.get_env(level) - level = level and level+1 or 2 - local env = setmetatable({},{__index=_G}) - while true do - if not debug.getinfo(level) then break end - local i = 1 - while true do - local name, value = debug.getlocal(level,i) - if not name or _G[name] == value then break else env[name] = value end - i=i+1 - end - level=level+1 - end - return env -end - ---- Used to get the current ENV with all _G keys removed; useful when saving function to global --- @usage get_env() returns current ENV with _G keys removed --- @treturn table the env table with _G keys removed --- @warning does not work from console -function ExpLib.get_upvalues(level) - local func = level and ExpLib.is_type(level,'function') and level or nil - level = level and ExpLib.is_type(level,'number') and level+1 or 2 - func = func or debug.getinfo(level).func - local upvalues = setmetatable({},{__index=_G}) - local i = 1 - while true do - local name, value = debug.getupvalue(func,i) - if not name then break else upvalues[name] = value end - i=i+1 - end - return upvalues -end - ---- Creates a table that will act like a string and a function --- @usage add_metatable({},function) -- returns table --- @tparam table tbl the table that will have its metatable set --- @tparam[opt=tostring] function callback the function that will be used for the call --- @tparam[opt=table.tostring] ?function|string string a function that resolves to a string or a string --- @treturn table the new table with its metatable set -function ExpLib.add_metatable(tbl,callback,string) - if not ExpLib.is_type(tbl,'table') then error('No table given to add_metatable',2) end - callback = ExpLib.is_type(callback,'function') and callback or tostring - string = ExpLib.is_type(string,'function') and string or ExpLib.is_type(string,'string') and function() return string end or table.tostring - return setmetatable(tbl,{ - __tostring=string, - __concat=function(val1,val2) return type(val1) == 'string' and val1..string(val2) or string(val1)..val2 end, - __call=callback - }) -end - ---- Compare types faster for faster validation of prams --- @usage is_type('foo','string') -- return true --- @usage is_type('foo') -- return false --- @param v the value to be tested --- @tparam[opt=nil] string test_type the type to test for if not given then it tests for nil --- @treturn boolean is v of type test_type -function ExpLib.is_type(v,test_type) - return test_type and v and type(v) == test_type or not test_type and not v or false -end - ---- Compare types faster for faster validation of prams, including giving an error if incorrect --- @usage type_error('foo','string','Value is not a string') -- return true --- @usage type_error('foo','table','Value is not a string') -- return error --- @param value the value to be tested --- @tparam[opt=nil] string type the type that the value should be --- @tparam string error_message the message given when type is not matched --- @treturn boolean if it matched or and error -function ExpLib.type_error(value,type,error_message) - return ExpLib.is_type(value,type) or error(error_message,3) -end - ---- A specialised version of type_error to test for self --- @usage self_test(self,'Object','get_name') --- @tparam table self the table that is the object --- @tparam string prototype_name the name of the class --- @tparam string function_name the name of the function -function ExpLib.self_test(self,prototype_name,function_name) - return ExpLib.is_type(self,'table') or error('Call to prototype without context, either supply a '..prototype_name..' or use '..prototype_name..':'..function_name,3) -end - ---- Will return a value of any type to the player/server console, allows colour for in-game players --- @usage player_return('Hello, World!') -- returns 'Hello, World!' to game.player or server console --- @usage player_return('Hello, World!','green') -- returns 'Hello, World!' to game.player with colour green or server console --- @usage player_return('Hello, World!',nil,player) -- returns 'Hello, World!' to the given player --- @param rtn any value of any type that will be returned to the player or console --- @tparam[opt=defines.colour.white] ?defines.color|string colour the colour of the text for the player, ignored when printing to console --- @tparam[opt=game.player] LuaPlayer player the player that return will go to, if no game.player then returns to server -function ExpLib.player_return(rtn,colour,player) - colour = ExpLib.is_type(colour,'table') and colour or defines.textcolor[colour] ~= defines.color.white and defines.textcolor[colour] or defines.color[colour] - player = player or game.player - -- converts the value to a string - local returnAsString - if ExpLib.is_type(rtn,'table') then - if ExpLib.is_type(rtn.__self,'userdata') then - -- value is userdata - returnAsString = 'Cant Display Userdata' - elseif ExpLib.is_type(rtn[1],'string') and string.find(rtn[1],'.+[.].+') and not string.find(rtn[1],'%s') then - -- value is a locale string - returnAsString = rtn - elseif getmetatable(rtn) ~= nil and not tostring(rtn):find('table: 0x') then - -- value has a tostring meta method - returnAsString = tostring(rtn) - else - -- value is a table - returnAsString = table.tostring(rtn) - end - elseif ExpLib.is_type(rtn,'function') then - -- value is a function - returnAsString = 'Cant Display Functions' - else returnAsString = tostring(rtn) end - -- returns to the player or the server - if player then - -- allows any valid player identifier to be used - player = Game.get_player(player) - if not player then error('Invalid Player given to player_return',2) end - -- plays a nice sound that is different to normal message sound - player.play_sound{path='utility/scenario_message'} - player.print(returnAsString,colour) - else rcon.print(returnAsString) end -end - ---- Convert ticks to hours --- @usage tick_to_hour(216001) -- return 1 --- @tparam number tick tick to convert to hours --- @treturn number the number of whole hours from this tick -function ExpLib.tick_to_hour(tick) - if not ExpLib.is_type(tick,'number') then return 0 end - if not game then return math.floor(tick/216000) end - return math.floor(tick/(216000*game.speed)) -end - ---- Convert ticks to minutes --- @usage tick_to_hour(3601) -- return 1 --- @tparam number tick tick to convert to minutes --- @treturn number the number of whole minutes from this tick -function ExpLib.tick_to_min (tick) - if not ExpLib.is_type(tick,'number') then return 0 end - if not game then return math.floor(tick/3600) end - return math.floor(tick/(3600*game.speed)) -end - ---- Converts a tick into a clean format for end user --- @usage tick_to_display_format(3600) -- return '1.00 M' --- @usage tick_to_display_format(234000) -- return '1 H 5 M' --- @tparam number tick the tick to convert --- @treturn string the formated string -function ExpLib.tick_to_display_format(tick) - if not ExpLib.is_type(tick,'number') then return '0H 0M' end - if ExpLib.tick_to_min(tick) < 10 then - if not game then return math.floor(tick/3600) end - return string.format('%.2f M',tick/(3600*game.speed)) - else - return string.format('%d H %d M', - ExpLib.tick_to_hour(tick), - ExpLib.tick_to_min(tick)-60*ExpLib.tick_to_hour(tick) - ) - end -end - ---- Used as a way to view the structure of a gui, used for debugging --- @usage Gui_tree(root) returns all children of gui recursively --- @tparam LuaGuiElement root the root to start the tree from --- @treturn table the table that describes the gui -function ExpLib.gui_tree(root) - if not ExpLib.is_type(root,'table') or not root.valid then error('Invalid Gui Element given to gui_tree',2) end - local tree = {} - for _,child in pairs(root.children) do - if #child.children > 0 then - if child.name then tree[child.name] = ExpLib.gui_tree(child) - else table.insert(tree,ExpLib.gui_tree(child)) end - else - if child.name then tree[child.name] = child.type - else table.insert(tree,child.type) end - end - end - return tree -end - ---- Extents the table class --- @type table --- @alias table - ---- Returns a value in a form able to be read as a value, any value to string --- @usage table.val_to_str{a='foo'} -- return '"foo"' --- @param v value to convert --- @treturn string the converted value -function table.val_to_str(v) - if "string" == type( v ) then - v = string.gsub(v,"\n","\\n") - if string.match(string.gsub(v,"[^'\"]",""),'^"+$') then - return "'"..v.."'" - end - return '"'..string.gsub(v,'"', '\\"' )..'"' - else - return "table" == type( v) and table.tostring(v) or - "function" == type(v) and '"cant-display-function"' or - "userdata" == type(v) and '"cant-display-userdata"' or - tostring(v) - end -end - ---- Returns a value in a form able to be read as a key, any key to string --- @usage table.val_to_str{a='foo'} -- return '["a"]' --- @param k key to convert --- @treturn string the converted key -function table.key_to_str (k) - if "string" == type(k) and string.match(k,"^[_%player][_%player%d]*$") then - return k - else - return "["..table.val_to_str(k).."]" - end -end - ---- Returns a table in a form able to be read as a table --- @usage table.tostring{k1='foo',k2='bar'} -- return '{["k1"]="foo",["k2"]="bar"}' --- @tparam table tbl table to convert --- @treturn string the converted table -function table.tostring(tbl) - if type(tbl) ~= 'table' then return tostring(tbl) end - local result, done = {}, {} - for k, v in ipairs(tbl) do - table.insert(result,table.val_to_str(v)) - done[k] = true - end - for k, v in pairs(tbl) do - if not done[k] then - table.insert(result, - table.key_to_str(k).."="..table.val_to_str(v)) - end - end - return "{"..table.concat(result,",") .."}" -end - ---- Similar to table.tostring but converts a lua table to a json one --- @usage table.json{k1='foo',k2='bar'} -- return '{"k1":"foo","k2":"bar"}' --- @tparam table lua_table the table to convert --- @treturn string the table in a json format -function table.json(lua_table) - --if game and game.table_to_json then return game.table_to_json(lua_table) end - local result, done, only_indexes = {}, {}, true - for key,value in ipairs(lua_table) do - done[key] = true - if type(value) == 'table' then table.insert(result,table.json(value,true)) - elseif not value then table.insert(result,'null') - else table.insert(result,table.val_to_str(value)) - end - end - for key,value in pairs(lua_table) do - if not done[key] then - only_indexes = false - if type(value) == 'table' then table.insert(result,table.val_to_str(key)..':'..table.json(value,true)) - elseif not value then table.insert(result,table.val_to_str(key)..':null') - else table.insert(result,table.val_to_str(key)..':'..table.val_to_str(value)) - end - end - end - if only_indexes then return "["..table.concat(result,",").."]" - else return "{"..table.concat(result,",").."}" - end -end - ---- Returns the closest match to a key --- @usage table.autokey({foo=1,bar=2},'f') -- return 1 --- @tparam table tbl the table that will be searched --- @tparam string str the string that will be looked for in the keys -function table.autokey(tbl,str) - if not ExpLib.is_type(str,'string') then return end - local _return = {} - for key,value in pairs(tbl) do - if string.contains(string.lower(key),string.lower(str)) then table.insert(_return,value) end - end - return _return[1] or false -end - ---- Returns the list is a sorted way that would be expected by people (this is by key) --- @usage tbl = table.alphanumsort(tbl) --- @tparam table tbl the table to be sorted --- @treturn table the sorted table -function table.alphanumsort(tbl) - local o = table.keys(tbl) - local function padnum(d) local dec, n = string.match(d, "(%.?)0*(.+)") - return #dec > 0 and ("%.12f"):format(d) or ("%s%03d%s"):format(dec, #n, n) end - table.sort(o, function(a,b) - return tostring(a):gsub("%.?%d+",padnum)..("%3d"):format(#b) - < tostring(b):gsub("%.?%d+",padnum)..("%3d"):format(#a) end) - local _tbl = {} - for _,k in pairs(o) do _tbl[k] = tbl[k] end - return _tbl -end - ---- Returns the list is a sorted way that would be expected by people (this is by key) (faster alterative than above) --- @usage tbl = table.alphanumsort(tbl) --- @tparam table tbl the table to be sorted --- @treturn table the sorted table -function table.keysort(tbl) - local o = table.keys(tbl,true) - local _tbl = {} - for _,k in pairs(o) do _tbl[k] = tbl[k] end - return _tbl -end - -ExpLib:unpack_to_G() -return ExpLib \ No newline at end of file diff --git a/old/modules/ExpGamingLib/softmod.json b/old/modules/ExpGamingLib/softmod.json deleted file mode 100644 index 160803be..00000000 --- a/old/modules/ExpGamingLib/softmod.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "ExpGamingLib", - "version": "4.0.0", - "description": "Adds some common functions used though out all ExpGaming modules", - "location": "FSM_ARCHIVE", - "keywords": [ - "ExpGaming", - "Lib" - ], - "author": "Cooldude2606", - "contact": "Discord: Cooldude2606#5241", - "license": "https://github.com/explosivegaming/scenario/blob/master/LICENSE", - "dependencies": { - "FactorioStdLib.Game": "^0.8.0", - "FactorioStdLib.Color": "^0.8.0", - "FactorioStdLib.Table": "^0.8.0" - }, - "submodules": {} -} From 6f6a1732cec8b8d80470c1ad18a1523605e731d8 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 24 Mar 2019 16:58:20 +0000 Subject: [PATCH 3/6] Added format_time --- expcore/common.lua | 62 ++++++++++++++++++++++++++++++++ locale/en/expcore.cfg | 17 ++++++++- modules/addons/death-markers.lua | 37 +++++++++++++++++-- modules/commands/interface.lua | 1 + 4 files changed, 114 insertions(+), 3 deletions(-) diff --git a/expcore/common.lua b/expcore/common.lua index 1f7f6448..6cd27b56 100644 --- a/expcore/common.lua +++ b/expcore/common.lua @@ -135,4 +135,66 @@ function Public.ext_require(path,...) return Public.extract_keys(rtn,...) end +--- Formats ticks into a time format - this is alot of work and will do later +-- time denominations: D,H,M,S,T days,hours,minutes,seconds,ticks +-- time prefixes (minutes as example): %m,%m,%M,%MM just the value, value with short tag, value with long tag +-- adding a number after the prefix AND denomination will show that many decimal palaces +-- examples: '%H %M' => '0H 0M'; '%MM and %SS3' => '0 Minutes and 0.000 Seconds' +function Public.format_time(ticks,format) + local has_days, has_hours, has_minutes, has_seconds, has_ticks = false,false,false,false,false + local max_days, max_hours = ticks/5184000, ticks/216000 + local max_minutes, max_seconds, max_ticks = ticks/3600, ticks/60, ticks + local days, hours = max_days, max_hours-math.floor(max_days)*5184000 + local minutes, seconds = max_minutes-math.floor(max_hours)*216000, max_seconds-math.floor(max_minutes)*3600 + local tags = {} + return 'Use format_time_simple currently WIP' +end + +--- Formats tick into a time format, this format is predefined to either H:M:S; HH MM SS or H Hours M Minutes S seconds +-- seconds are not required to be shown with option show_seconds = false, true to show them, default false +-- show_sub_seconds will show three decimal places for the seconds +-- long_format will use words rather than letters +-- tagged is default to true when false it will remove all letters and use : +-- @tparam ticks number the number of ticks that represents a time +-- @tparam options table a table of options to use for the format +function Public.format_time_simple(ticks,options) + -- Sets up the options + options = { + show_seconds = options.show_seconds or false, + show_sub_seconds = options.show_sub_seconds or false, + long_format = options.long_format or false, + tagged = options.tagged or true + } + -- Basic numbers that are used in calculations + local max_hours, max_minutes, max_seconds = ticks/216000, ticks/3600, ticks/60 + local hours, minutes, seconds = max_hours, max_minutes-math.floor(max_hours)*216000, max_seconds-math.floor(max_minutes)*3600 + -- Format options + local suffix = 'time-format.short-' + if options.long_format then + suffix = 'time-format.long-' + end + local div = 'time-format.simple-format-tagged' + if options.tagged then + div = 'time-format.simple-format-div' + suffix = false + end + -- The returned numbers in the right format + local rtn_hours, rtn_minutes, rtn_seconds = math.floor(hours), math.floor(minutes), math.floor(seconds) + if suffix then + rtn_hours = {suffix..'hours',rtn_hours} + rtn_minutes = {suffix..'minutes',rtn_minutes} + if options.show_sub_seconds then + rtn_seconds = {suffix..'seconds',string.format('%d03',seconds)} + else + rtn_seconds = {suffix..'seconds',rtn_seconds} + end + end + -- The final return is construed + local rtn = {div,rtn_hours,rtn_minutes} + if options.show_seconds then + rtn = {div,rtn,rtn_seconds} + end + return rtn +end + return Public \ No newline at end of file diff --git a/locale/en/expcore.cfg b/locale/en/expcore.cfg index b33e7ee3..6dbc9b41 100644 --- a/locale/en/expcore.cfg +++ b/locale/en/expcore.cfg @@ -14,4 +14,19 @@ invalid-param=Invalid Param "__1__"; __2__ command-help=__1__ - __2__ command-ran=Command Complete command-fail=Command failed to run: __1__ -command-error-log-format=[ERROR] command/__1__ :: __2__ \ No newline at end of file +command-error-log-format=[ERROR] command/__1__ :: __2__ + +[time-format] +simple-format-none=__1__ +simple-format-div=__1__:__2__ +simple-format-tagged=__1__ __2__ +long-days=__1__ __plural_for_parameter_1_{1=Day|rest=Days}__ +short-days=__1__D +long-hours=__1__ __plural_for_parameter_1_{1=Hour|rest=Hours}__ +short-hours=__1__H +long-minutes=__1__ __plural_for_parameter_1_{1=Minute|rest=Minutes}__ +short-minutes=__1__M +long-seconds=__1__ __plural_for_parameter_1_{1=Second|rest=Seconds}__ +short-seconds=__1__S +long-ticks=__1__ __plural_for_parameter_1_{1=Tick|rest=Ticks}__ +short-ticks=__1__T \ No newline at end of file diff --git a/modules/addons/death-markers.lua b/modules/addons/death-markers.lua index 616854b9..c161dc5a 100644 --- a/modules/addons/death-markers.lua +++ b/modules/addons/death-markers.lua @@ -3,5 +3,38 @@ local Game = require 'utils.game' local Global = require 'utils.global' local Commands = require 'expcore.commands' local config = require 'config.death_markers' -local opt_require = ext_require('expcore.common','opt_require') -opt_require 'config.command_auth_runtime_disable' -- if the file is present then we can disable the commands \ No newline at end of file +local opt_require, format_time = ext_require('expcore.common','opt_require','format_time_simple') +opt_require 'config.command_auth_runtime_disable' -- if the file is present then we can disable the commands rather than not load them + +local bodies = { + --{player_name='Cooldude2606',time_of_death='15H 15M',body=LuaEntity,tag=LuaCustomChartTag} +} +Global.register(bodies,function(tbl) + bodies = tbl +end) + +--- Checks that all map tags are present and valid +-- adds missing ones, deletes expired ones +local function check_map_tags() + +end + +--- Teleports the owner of a body to the body +local function teleport_player(body) + +end + +--- Teleports the items in a body to a certain position putting it in chests +-- if there are no chests close by them some are created +local function teleport_items(body,position) + +end + +Event.add(defines.events.on_player_died,function(event) + +end) + +local check_period = 60*60*5 -- five minutes +Event.on_nth_tick(check_period,function(event) + +end) \ No newline at end of file diff --git a/modules/commands/interface.lua b/modules/commands/interface.lua index 24424ebf..da03fdd1 100644 --- a/modules/commands/interface.lua +++ b/modules/commands/interface.lua @@ -5,6 +5,7 @@ local Common = require 'expcore.common' -- modules that are loaded into the interface env to be accessed local interface_modules = { ['Game']='utils.game', + ['_C']=Common, ['Commands']=Commands, ['output']=Common.player_return, ['Group']='expcore.permission_groups' From 2f4f100b6306cb2ae1890e130eb370b3f0a5c9de Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 24 Mar 2019 17:37:33 +0000 Subject: [PATCH 4/6] Improved format_time --- expcore/common.lua | 101 +++++++++++++++++++++++------------------- locale/en/expcore.cfg | 12 +---- 2 files changed, 58 insertions(+), 55 deletions(-) diff --git a/expcore/common.lua b/expcore/common.lua index 6cd27b56..fbc9c158 100644 --- a/expcore/common.lua +++ b/expcore/common.lua @@ -135,64 +135,75 @@ function Public.ext_require(path,...) return Public.extract_keys(rtn,...) end ---- Formats ticks into a time format - this is alot of work and will do later --- time denominations: D,H,M,S,T days,hours,minutes,seconds,ticks --- time prefixes (minutes as example): %m,%m,%M,%MM just the value, value with short tag, value with long tag --- adding a number after the prefix AND denomination will show that many decimal palaces --- examples: '%H %M' => '0H 0M'; '%MM and %SS3' => '0 Minutes and 0.000 Seconds' -function Public.format_time(ticks,format) - local has_days, has_hours, has_minutes, has_seconds, has_ticks = false,false,false,false,false - local max_days, max_hours = ticks/5184000, ticks/216000 - local max_minutes, max_seconds, max_ticks = ticks/3600, ticks/60, ticks - local days, hours = max_days, max_hours-math.floor(max_days)*5184000 - local minutes, seconds = max_minutes-math.floor(max_hours)*216000, max_seconds-math.floor(max_minutes)*3600 - local tags = {} - return 'Use format_time_simple currently WIP' -end - ---- Formats tick into a time format, this format is predefined to either H:M:S; HH MM SS or H Hours M Minutes S seconds --- seconds are not required to be shown with option show_seconds = false, true to show them, default false --- show_sub_seconds will show three decimal places for the seconds --- long_format will use words rather than letters --- tagged is default to true when false it will remove all letters and use : +--- Formats tick into a clean format, denominations from highest to lowest +-- long will use words rather than letters +-- time will use : separates +-- when a denomination is false it will overflow into the next one -- @tparam ticks number the number of ticks that represents a time -- @tparam options table a table of options to use for the format -function Public.format_time_simple(ticks,options) +-- @treturn string a locale string that can be used +function Public.format_time(ticks,options) -- Sets up the options - options = { - show_seconds = options.show_seconds or false, - show_sub_seconds = options.show_sub_seconds or false, - long_format = options.long_format or false, - tagged = options.tagged or true + options = options or { + days=false, + hours=true, + minutes=true, + seconds=false, + long=false, + time=false } -- Basic numbers that are used in calculations - local max_hours, max_minutes, max_seconds = ticks/216000, ticks/3600, ticks/60 - local hours, minutes, seconds = max_hours, max_minutes-math.floor(max_hours)*216000, max_seconds-math.floor(max_minutes)*3600 + 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 + end + if not options.hours then + rtn_minutes = rtn_minutes + rtn_hours*60 + end + if not options.minutes then + rtn_seconds = rtn_seconds + rtn_minutes*60 + end -- Format options - local suffix = 'time-format.short-' - if options.long_format then - suffix = 'time-format.long-' + local suffix = 'time-symbol-' + local suffix_2 = '-short' + if options.long then + suffix = '' + suffix_2 = '' end local div = 'time-format.simple-format-tagged' - if options.tagged then + if options.time then div = 'time-format.simple-format-div' suffix = false end - -- The returned numbers in the right format - local rtn_hours, rtn_minutes, rtn_seconds = math.floor(hours), math.floor(minutes), math.floor(seconds) - if suffix then - rtn_hours = {suffix..'hours',rtn_hours} - rtn_minutes = {suffix..'minutes',rtn_minutes} - if options.show_sub_seconds then - rtn_seconds = {suffix..'seconds',string.format('%d03',seconds)} - else - rtn_seconds = {suffix..'seconds',rtn_seconds} - end + -- Adds formatting + if suffix ~= false then + 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} + else + 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 = {div,rtn_hours,rtn_minutes} - if options.show_seconds then - rtn = {div,rtn,rtn_seconds} + local rtn + if options.days then + rtn = rtn_days + end + if options.hours then + rtn = rtn and {div,rtn,rtn_hours} or rtn_hours + end + if options.minutes then + rtn = rtn and {div,rtn,rtn_minutes} or rtn_minutes + end + if options.seconds then + rtn = rtn and {div,rtn,rtn_seconds} or rtn_seconds end return rtn end diff --git a/locale/en/expcore.cfg b/locale/en/expcore.cfg index 6dbc9b41..e5572501 100644 --- a/locale/en/expcore.cfg +++ b/locale/en/expcore.cfg @@ -1,3 +1,5 @@ +time-symbol-days-short=__1__d + [expcore-commands] unauthorized=Unauthorized, Access is denied due to invalid credentials reject-string-options=Invalid Option, Must be one of: __1__ @@ -20,13 +22,3 @@ command-error-log-format=[ERROR] command/__1__ :: __2__ simple-format-none=__1__ simple-format-div=__1__:__2__ simple-format-tagged=__1__ __2__ -long-days=__1__ __plural_for_parameter_1_{1=Day|rest=Days}__ -short-days=__1__D -long-hours=__1__ __plural_for_parameter_1_{1=Hour|rest=Hours}__ -short-hours=__1__H -long-minutes=__1__ __plural_for_parameter_1_{1=Minute|rest=Minutes}__ -short-minutes=__1__M -long-seconds=__1__ __plural_for_parameter_1_{1=Second|rest=Seconds}__ -short-seconds=__1__S -long-ticks=__1__ __plural_for_parameter_1_{1=Tick|rest=Ticks}__ -short-ticks=__1__T \ No newline at end of file From 498edfd58d3ad27e3ffd265fc9a6de2b8058108f Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 24 Mar 2019 18:47:43 +0000 Subject: [PATCH 5/6] Added Death logger --- .../{death_markers.lua => death_logger.lua} | 2 +- config/file_loader.lua | 1 + expcore/common.lua | 47 +++++++---- modules/addons/death-logger.lua | 84 +++++++++++++++++++ modules/addons/death-markers.lua | 40 --------- 5 files changed, 115 insertions(+), 59 deletions(-) rename config/{death_markers.lua => death_logger.lua} (90%) create mode 100644 modules/addons/death-logger.lua delete mode 100644 modules/addons/death-markers.lua diff --git a/config/death_markers.lua b/config/death_logger.lua similarity index 90% rename from config/death_markers.lua rename to config/death_logger.lua index cb195cde..f93518e0 100644 --- a/config/death_markers.lua +++ b/config/death_logger.lua @@ -8,5 +8,5 @@ return { auto_collect_bodies=false, -- enables items being returned to the spawn point in chests upon death show_map_markers=true, -- shows markers on the map where bodies are include_time_of_death=true, -- weather to include the time of death on the map marker - map_icon='' -- the icon that the map marker shows '' means no icon + map_icon=nil -- the icon that the map marker shows; nil means no icon; format as a SingleID } \ No newline at end of file diff --git a/config/file_loader.lua b/config/file_loader.lua index c87e9d85..db6b68bc 100644 --- a/config/file_loader.lua +++ b/config/file_loader.lua @@ -17,6 +17,7 @@ return { -- QoL Addons 'modules.addons.chat-popups', 'modules.addons.damage-popups', + 'modules.addons.death-markers', -- Config Files 'config.command_auth_admin', -- commands tagged with admin_only are blocked for non admins 'config.command_auth_runtime_disable', -- allows commands to be enabled and disabled during runtime diff --git a/expcore/common.lua b/expcore/common.lua index fbc9c158..74f2eb3a 100644 --- a/expcore/common.lua +++ b/expcore/common.lua @@ -138,6 +138,7 @@ end --- Formats tick into a clean format, denominations from highest to lowest -- long will use words rather than letters -- time will use : separates +-- string will return a string not a locale string -- when a denomination is false it will overflow into the next one -- @tparam ticks number the number of ticks that represents a time -- @tparam options table a table of options to use for the format @@ -150,7 +151,8 @@ function Public.format_time(ticks,options) minutes=true, seconds=false, long=false, - time=false + time=false, + string=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 @@ -174,18 +176,28 @@ function Public.format_time(ticks,options) suffix = '' suffix_2 = '' end - local div = 'time-format.simple-format-tagged' + local div = options.string and ' ' or 'time-format.simple-format-tagged' if options.time then - div = 'time-format.simple-format-div' + div = options.string and ':' or 'time-format.simple-format-div' suffix = false end -- Adds formatting if suffix ~= false then - 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} + if options.string then + -- format it as a string + local long = suffix == '' + rtn_days = long and rtn_days..' days' or rtn_days..'d' + rtn_hours = long and rtn_hours..' hours' or rtn_hours..'h' + rtn_minutes = long and rtn_minutes..' minutes' or rtn_minutes..'m' + rtn_seconds = long and rtn_seconds..' seconds' or rtn_seconds..'s' + else + rtn_days = {suffix..'days'..suffix_2,rtn_days} + rtn_hours = {suffix..'hours'..suffix_2,rtn_hours} + rtn_minutes = {suffix..'minutes'..suffix_2,rtn_minutes} + rtn_seconds = {suffix..'seconds'..suffix_2,rtn_seconds} + end else + -- 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) @@ -193,18 +205,17 @@ function Public.format_time(ticks,options) end -- The final return is construed local rtn - if options.days then - rtn = rtn_days - end - if options.hours then - rtn = rtn and {div,rtn,rtn_hours} or rtn_hours - end - if options.minutes then - rtn = rtn and {div,rtn,rtn_minutes} or rtn_minutes - end - if options.seconds then - rtn = rtn and {div,rtn,rtn_seconds} or rtn_seconds + local append = function(dom,value) + if dom and options.string then + rtn = rtn and rtn..div..value or value + elseif dom then + rtn = rtn and {div,rtn,value} or value + end end + append(options.day,rtn_days) + append(options.hours,rtn_hours) + append(options.minutes,rtn_minutes) + append(options.seconds,rtn_seconds) return rtn end diff --git a/modules/addons/death-logger.lua b/modules/addons/death-logger.lua new file mode 100644 index 00000000..4743b99d --- /dev/null +++ b/modules/addons/death-logger.lua @@ -0,0 +1,84 @@ +local Event = require 'utils.event' +local Game = require 'utils.game' +local Global = require 'utils.global' +local config = require 'config.death_logger' +local format_time = ext_require('expcore.common','format_time') + +local deaths = { + archive={} -- deaths moved here after body is gone + --{player_name='Cooldude2606',time_of_death='15H 15M',position={x=0,y=0},corpse=LuaEntity,tag=LuaCustomChartTag} +} +Global.register(deaths,function(tbl) + deaths = tbl +end) + +--- Creates a new death marker and saves it to the given death +local function create_map_tag(death) + local player = Game.get_player_from_any(death.player_name) + local message = player.name..' died' + if config.include_time_of_death then + local time = format_time(death.time_of_death,{hours=true,minutes=true,string=true}) + message = message..' at '..time + end + death.tag = player.force.add_chart_tag(player.surface,{ + position=death.position, + icon=config.map_icon, + text=message + }) +end + +--- Checks that all map tags are present and valid +-- adds missing ones, deletes expired ones +local function check_map_tags() + for index,death in ipairs(deaths) do + local map_tag = death.tag + local corpse = death.corpse + -- Check the corpse is valid + if corpse and corpse.valid then + -- Corpse is valid check the map tag + if not map_tag or not map_tag.valid then + -- Map tag is not valid make a new one + create_map_tag(death) + end + else + -- Corpse is not valid so remove the map tag + if map_tag and map_tag.valid then + map_tag.destroy() + end + -- Move the death to the archive + death.corpse = nil + death.tag = nil + table.insert(deaths.archive,death) + table.remove(deaths,index) + end + end +end + +-- when a player dies a new death is added to the records and a map marker is made +Event.add(defines.events.on_player_died,function(event) + local player = Game.get_player_by_index(event.player_index) + local corpse = player.surface.find_entity('character-corpse',player.position) + local death = { + player_name = player.name, + time_of_death = event.tick, + position = player.position, + corpse = corpse + } + if config.show_map_markers then + create_map_tag(death) + end + table.insert(deaths,death) +end) + +-- every 5 min all bodies are checked for valid map tags +if config.show_map_markers then + local check_period = 60*60*5 -- five minutes + Event.on_nth_tick(check_period,function(event) + check_map_tags() + end) +end + +-- this is so other modules can access the logs +return function() + return deaths +end \ No newline at end of file diff --git a/modules/addons/death-markers.lua b/modules/addons/death-markers.lua deleted file mode 100644 index c161dc5a..00000000 --- a/modules/addons/death-markers.lua +++ /dev/null @@ -1,40 +0,0 @@ -local Event = require 'utils.event' -local Game = require 'utils.game' -local Global = require 'utils.global' -local Commands = require 'expcore.commands' -local config = require 'config.death_markers' -local opt_require, format_time = ext_require('expcore.common','opt_require','format_time_simple') -opt_require 'config.command_auth_runtime_disable' -- if the file is present then we can disable the commands rather than not load them - -local bodies = { - --{player_name='Cooldude2606',time_of_death='15H 15M',body=LuaEntity,tag=LuaCustomChartTag} -} -Global.register(bodies,function(tbl) - bodies = tbl -end) - ---- Checks that all map tags are present and valid --- adds missing ones, deletes expired ones -local function check_map_tags() - -end - ---- Teleports the owner of a body to the body -local function teleport_player(body) - -end - ---- Teleports the items in a body to a certain position putting it in chests --- if there are no chests close by them some are created -local function teleport_items(body,position) - -end - -Event.add(defines.events.on_player_died,function(event) - -end) - -local check_period = 60*60*5 -- five minutes -Event.on_nth_tick(check_period,function(event) - -end) \ No newline at end of file From 79ed80c60cd739107e87a0b09c149c3ceb0c3a44 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 24 Mar 2019 18:49:04 +0000 Subject: [PATCH 6/6] Commented out WIP config settings --- config/death_logger.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/death_logger.lua b/config/death_logger.lua index f93518e0..4b5ba5f5 100644 --- a/config/death_logger.lua +++ b/config/death_logger.lua @@ -2,10 +2,10 @@ -- allow_teleport_to_body_command and allow_collect_bodies_command can be over ridden if command_auth_runtime_disable is present -- if not present then the commands will not be loaded into the game return { - allow_teleport_to_body_command=false, -- allows use of /return-to-body which teleports you to your last death - allow_collect_bodies_command=false, -- allows use of /collect-body which returns all your items to you and removes the body - use_chests_as_bodies=false, -- weather items should be moved into a chest when a player dies - auto_collect_bodies=false, -- enables items being returned to the spawn point in chests upon death + --allow_teleport_to_body_command=false, -- allows use of /return-to-body which teleports you to your last death + --allow_collect_bodies_command=false, -- allows use of /collect-body which returns all your items to you and removes the body + --use_chests_as_bodies=false, -- weather items should be moved into a chest when a player dies + --auto_collect_bodies=false, -- enables items being returned to the spawn point in chests upon death show_map_markers=true, -- shows markers on the map where bodies are include_time_of_death=true, -- weather to include the time of death on the map marker map_icon=nil -- the icon that the map marker shows; nil means no icon; format as a SingleID