diff --git a/README.md b/README.md index 851be090..08e9c873 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ All are welcome to make pull requests and issues for this scenario, if you are i | Scenario Version* | Version Name | Factorio Version** | |---|---|---| +| [v6.1][s6.1] | External Data Overhaul | [v1.0.0][f1.0.0] | | [v6.0][s6.0] | Gui / 0.18 Overhaul | [v0.18.17][f0.18.17] | | [v5.10][s5.10] | Data Store Rewrite | [v0.17.71][f0.17.71] | | [v5.9][s5.9] | Control Modules and Documentation | [v0.17.63][f0.17.63] | @@ -80,6 +81,7 @@ All are welcome to make pull requests and issues for this scenario, if you are i \*\* Factorio versions show the version they were made for, often the minimum requirement. +[s6.1]: https://github.com/explosivegaming/scenario/releases/tag/6.1.0 [s6.0]: https://github.com/explosivegaming/scenario/releases/tag/6.0.0 [s5.10]: https://github.com/explosivegaming/scenario/releases/tag/5.10.0 [s5.9]: https://github.com/explosivegaming/scenario/releases/tag/5.9.0 @@ -98,6 +100,7 @@ All are welcome to make pull requests and issues for this scenario, if you are i [s1.0]: https://github.com/explosivegaming/scenario/releases/tag/v1.0 [s0.1]: https://github.com/explosivegaming/scenario/releases/tag/v0.1 +[f1.0.0]: https://wiki.factorio.com/Version_history/1.0.0#1.0.0 [f0.18.17]: https://wiki.factorio.com/Version_history/0.18.0#0.18.17 [f0.17.71]: https://wiki.factorio.com/Version_history/0.17.0#0.17.71 [f0.17.63]: https://wiki.factorio.com/Version_history/0.17.0#0.17.63 diff --git a/expcore/player_data.lua b/expcore/player_data.lua index e05caa6c..2eba29f5 100644 --- a/expcore/player_data.lua +++ b/expcore/player_data.lua @@ -128,6 +128,7 @@ end) Event.add(defines.events.on_player_joined_game, function(event) local player = game.players[event.player_index] Async.wait(300, check_data_loaded, player) + PlayerData:raw_set(player.name) PlayerData:request(player) end) @@ -135,7 +136,7 @@ end) Event.add(defines.events.on_player_left_game, function(event) local player = game.players[event.player_index] local player_data = PlayerData:get(player) - if player_data.valid == true then + if player_data and player_data.valid == true then PlayerData:unload(player) else PlayerData:raw_set(player.name) end end) diff --git a/expcore/roles.lua b/expcore/roles.lua index 477a5fb5..f97771a7 100644 --- a/expcore/roles.lua +++ b/expcore/roles.lua @@ -153,12 +153,11 @@ local function emit_player_roles_updated(player, type, roles, by_player_name, sk event = Roles.events.on_role_unassigned end -- convert the roles to objects and get the names of the roles - local index, role_names, valid_roles = 0, {}, {} + local index, role_names = 0, {} for _, role in ipairs(roles) do role = Roles.get_role_from_any(role) if role then index = index + 1 - valid_roles[index] = role role_names[index] = role.name end end @@ -176,7 +175,7 @@ local function emit_player_roles_updated(player, type, roles, by_player_name, sk tick=game.tick, player_index=player.index, by_player_index=by_player_index, - roles=valid_roles + roles=role_names }) write_json('log/roles.log', { player_name=player.name, @@ -946,7 +945,7 @@ function Roles._prototype:get_players(online) if role_name == self.name then local player = game.players[player_name] -- Filter by online state if required - if online == nil or player.connected == online then + if player and (online == nil or player.connected == online) then players[#players+1] = player end break @@ -1001,7 +1000,7 @@ Event.add(defines.events.on_player_joined_game, role_update) -- Every 60 seconds the auto promote check is preformed Event.on_nth_tick(3600, function() local promotes = {} - for _, player in ipairs(game.connected_players) do + for _, player in pairs(game.connected_players) do for _, role in ipairs(Roles.config.roles) do if role.auto_promote_condition then local success, err = pcall(role.auto_promote_condition, player) diff --git a/modules/addons/tree-decon.lua b/modules/addons/tree-decon.lua index da32b298..29e13707 100644 --- a/modules/addons/tree-decon.lua +++ b/modules/addons/tree-decon.lua @@ -17,6 +17,7 @@ end) Event.add(defines.events.on_marked_for_deconstruction, function(event) -- Check which type of decon a player is allowed local index = event.player_index + if not index then return end if chache[index] == nil then local player = game.players[index] if Roles.player_allowed(player, 'fast-tree-decon') then chache[index] = 'fast' diff --git a/modules/commands/interface.lua b/modules/commands/interface.lua index 41d2942d..a95d66be 100644 --- a/modules/commands/interface.lua +++ b/modules/commands/interface.lua @@ -31,67 +31,75 @@ Global.register(interface_env, function(tbl) interface_env = tbl end) ---- Adds a callback function when the interface command is used --- nb: returned value is saved in the env that the interface uses --- @tparam string name the name that the value is loaded under, cant use upvalues --- @tparam function callback the function that will run whent he command is used +--- Adds a static module that can be accessed with the interface +-- @tparam string name The name that the value is assigned to +-- @tparam any value The value that will be accessible in the interface env -- callback param - player: LuaPlayer - the player who used the command +local function add_interface_module(name, value) + interface_modules[name] = value +end + +--- Adds a dynamic value that is calculated when the interface is used +-- @tparam string name The name that the value is assigned to +-- @tparam function callback The function that will be called to get the value local function add_interface_callback(name, callback) if type(callback) == 'function' then interface_callbacks[name] = callback end end --- this is a meta function for __index when self[key] is nil +--- Internal, this is a meta function for __index when self[key] is nil local function get_index(_, key) if interface_env[key] then return interface_env[key] elseif interface_modules[key] then return interface_modules[key] + elseif _G[key] then + return _G[key] end end ---- Sends an innovation to be ran and returns the result. +--- Sends an invocation to be ran and returns the result. -- @command interface --- @tparam string innovation the command that will be run -Commands.new_command('interface', 'Sends an innovation to be ran and returns the result.') -:add_param('innovation', false) +-- @tparam string invocation the command that will be run +Commands.new_command('interface', 'Sends an invocation to be ran and returns the result.') +:add_param('invocation', false) :enable_auto_concat() :set_flag('admin_only') -:register(function(player, innovation) - if not innovation:find('%s') and not innovation:find('return') then - -- if there are no spaces and return is not present then return is appended to the start - innovation='return '..innovation +:register(function(player, invocation) + -- If the invocation has no white space then prepend return to it + if not invocation:find('%s') and not invocation:find('return') then + invocation = 'return '..invocation end - -- temp_env will index to interface_env and interface_modules if value not found - local temp_env = setmetatable({}, {__index=get_index}) - if player then -- player can be nil when it is the server + + -- _env will be the new _ENV that the invocation will run inside of + local _env = setmetatable({}, { + __index = get_index, + __newindex = interface_env + }) + + -- If the command is ran by a player then load the dynamic values + if player then for name, callback in pairs(interface_callbacks) do - -- loops over callbacks and loads the values returned local _, rtn = pcall(callback, player) - temp_env[name]=rtn + rawset(_env, name, rtn) end end - -- sets the global metatable to prevent new values being made - -- global will index to temp_env and new indexes saved to interface_sandbox - local old_mt = getmetatable(_G) - setmetatable(_G, {__index=temp_env, __newindex=interface_env}) - -- runs the innovation and returns values to the player - innovation = loadstring(innovation) - local success, rtn = pcall(innovation) - setmetatable(_G, old_mt) + + -- Compile the invocation with the custom _env value + local invocation_func, compile_error = load(invocation, 'interface', nil, _env) + if compile_error then return Commands.error(compile_error) end + + -- Run the invocation + local success, rtn = pcall(invocation_func) if not success then - if type(rtn) == 'string' then - -- there may be stack trace that must be removed to avoid desyncs - rtn = rtn:gsub('%.%.%..-/temp/currently%-playing', '') - end - return Commands.error(rtn) - else - return Commands.success(rtn) + local err = rtn:gsub('%.%.%..-/temp/currently%-playing', '') + return Commands.error(err) end + return Commands.success(rtn) end) --- adds some basic callbacks for the interface +-- Adds some basic callbacks for the interface add_interface_callback('player', function(player) return player end) add_interface_callback('surface', function(player) return player.surface end) add_interface_callback('force', function(player) return player.force end) @@ -99,9 +107,10 @@ add_interface_callback('position', function(player) return player.position end) add_interface_callback('entity', function(player) return player.selected end) add_interface_callback('tile', function(player) return player.surface.get_tile(player.position) end) +-- Module Return return { - add_interface_callback=add_interface_callback, - interface_env=interface_env, - interface_callbacks=interface_callbacks, - clean_stack_trace=function(str) return str:gsub('%.%.%..-/temp/currently%-playing', '') end + add_interface_module = add_interface_module, + add_interface_callback = add_interface_callback, + interface_env = interface_env, + clean_stack_trace = function(str) return str:gsub('%.%.%..-/temp/currently%-playing', '') end } \ No newline at end of file diff --git a/modules/control/warps.lua b/modules/control/warps.lua index 07be1b0f..b846460a 100644 --- a/modules/control/warps.lua +++ b/modules/control/warps.lua @@ -229,7 +229,7 @@ function Warps.remove_warp_area(warp_id) {position.x+radius, position.y+radius} } } - for _, entity in pairs(entities) do if entity.name ~= 'player' then entity.destroy() end end + for _, entity in pairs(entities) do if entity and entity.valid and entity.name ~= 'player' then entity.destroy() end end end --[[-- Set a warp to be the spawn point for a force, force must own this warp diff --git a/modules/data/player-colours.lua b/modules/data/player-colours.lua index aff392a8..f32aa7ff 100644 --- a/modules/data/player-colours.lua +++ b/modules/data/player-colours.lua @@ -26,18 +26,23 @@ local function compact(colour) } end +--- Returns a colour that is a bit lighter than the one given +local function lighten(c) + return {r = 255 - (255 - c.r) * 0.5, g = 255 - (255 - c.g) * 0.5, b = 255 - (255 - c.b) * 0.5, a = 255} +end + --- When your data loads apply the players colour, or a random on if none is saved PlayerColours:on_load(function(player_name, player_colour) if not player_colour then local preset = config.players[player_name] if preset then - player_colour = {preset, preset} + player_colour = {preset, lighten(preset)} else local colour_name = 'white' while config.disallow[colour_name] do colour_name = table.get_random_dictionary_entry(Colours, true) end - player_colour = {Colours[colour_name], Colours[colour_name]} + player_colour = {Colours[colour_name], lighten(Colours[colour_name])} end end diff --git a/modules/data/statistics.lua b/modules/data/statistics.lua index b350d3b7..709610fb 100644 --- a/modules/data/statistics.lua +++ b/modules/data/statistics.lua @@ -89,7 +89,7 @@ if config.DamageDealt then local stat = Statistics:combine('DamageDealt') Event.add(defines.events.on_entity_damaged, function(event) local character = event.cause -- Check character is valid - if not character.valid or character.type ~= 'character' then return end + if not character or not character.valid or character.type ~= 'character' then return end local player = character.player -- Check player is valid if not player.valid or not player.connected then return end local entity = event.entity -- Check entity is valid diff --git a/modules/gui/player-list.lua b/modules/gui/player-list.lua index ab9bb13d..f0923073 100644 --- a/modules/gui/player-list.lua +++ b/modules/gui/player-list.lua @@ -324,6 +324,7 @@ local function get_player_list_order() end --[[Adds fake players to the player list + local tick = game.tick+1 for i = 1, 10 do local online_time = math.random(1, tick) local afk_time = math.random(online_time-(tick/10), tick) @@ -337,7 +338,7 @@ local function get_player_list_order() caption = caption, tooltip = tooltip } - end]] + end--]] return player_list_order end diff --git a/modules/gui/server-ups.lua b/modules/gui/server-ups.lua index 798ac45e..9d294b36 100644 --- a/modules/gui/server-ups.lua +++ b/modules/gui/server-ups.lua @@ -33,7 +33,7 @@ Gui.element{ UsesServerUps:on_load(function(player_name, visible) local player = game.players[player_name] local label = player.gui.screen[server_ups.name] - if not global.ext or not global.ext.server_ups then visible = false end + if not External.valid() or not global.ext.var.server_ups then visible = false end label.visible = visible end)