@@ -2441,7 +2443,7 @@ nb: use error(error_message) within your callback to trigger do not trigger dire
generated by LDoc
diff --git a/docs/core/Common.html b/docs/core/Common.html
index 9658dbfc..423ec0b9 100644
--- a/docs/core/Common.html
+++ b/docs/core/Common.html
@@ -92,6 +92,7 @@
Moves items to the position and stores them in the closest entity of the type given
+
Moves items to the position and stores them in the closest entity of the type given
+-- Copies the items by prototype name, but keeps them in the original inventory
Moves items to the position and stores them in the closest entity of the type given
+-- Differs from move_items by accepting a table of LuaItemStack and transferring them into the inventory - not copying
Moves items to the position and stores them in the closest entity of the type given
+
Moves items to the position and stores them in the closest entity of the type given
+-- Copies the items by prototype name, but keeps them in the original inventory
Moves items to the position and stores them in the closest entity of the type given
+-- Differs from move_items by accepting a table of LuaItemStack and transferring them into the inventory - not copying
+
+
+
+ Parameters:
+
+
+
+
+
+
+
+
+
+ items
+
+ :
+
+ (table)
+
+ items which are to be added to the chests, an array of LuaItemStack
+
+
+
+
+
+
+
+
+
+ surface
+
+ :
+
+ (LuaSurface)
+
+ the surface that the items will be moved to
+
+ (default: navies)
+
+
+
+
+
+
+
+
+ position
+
+ :
+
+ (table)
+
+ the position that the items will be moved to {x=100, y=100}
+
+ (default: {0)
+
+
+
+
+
+
+
+
+ radius
+
+ :
+
+ (number)
+
+ the radius in which the items are allowed to be placed
+
+ (default: 32)
+
+
+
+
+
+
+
+
+ chest_type
+
+ :
+
+ (string)
+
+ the chest type that the items should be moved into
+
+ (default: iron-chest)
+
+
+
+
+
+
+
+
+ Returns:
+
+
+ (LuaEntity)
+ the last chest that had items inserted into it
+
+
+
+
+
+
+
+
+
+ Usage:
+
-- Copy all the items in a players inventory and place them in chests at {0, 0}
+move_items(game.player.get_main_inventory())
+
+
@@ -2780,7 +2918,7 @@ https://github.com/Refactorio/RedMew/blob/9184b2940f311d8c9c891e83429fc57ec7e0c4
generated by LDoc
@@ -3404,7 +3406,7 @@ nb: this is one way, failing false after already gaining the role will not revok
generated by LDoc
diff --git a/docs/data/Alt-View.html b/docs/data/Alt-View.html
index f374bb9b..8dba5a81 100644
--- a/docs/data/Alt-View.html
+++ b/docs/data/Alt-View.html
@@ -101,6 +101,7 @@
Sends alert messages to our discord server when certain events are triggered
@@ -429,6 +433,10 @@
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
@@ -377,7 +379,7 @@
generated by LDoc
diff --git a/expcore/common.lua b/expcore/common.lua
index 64886316..38d58e52 100644
--- a/expcore/common.lua
+++ b/expcore/common.lua
@@ -539,6 +539,7 @@ end
-- @section factorio
--[[-- Moves items to the position and stores them in the closest entity of the type given
+-- Copies the items by prototype name, but keeps them in the original inventory
@tparam table items items which are to be added to the chests, ['name']=count
@tparam[opt=navies] LuaSurface surface the surface that the items will be moved to
@tparam[opt={0, 0}] table position the position that the items will be moved to {x=100, y=100}
@@ -595,6 +596,67 @@ function Common.move_items(items, surface, position, radius, chest_type)
return last_chest
end
+--[[-- Moves items to the position and stores them in the closest entity of the type given
+-- Differs from move_items by accepting a table of LuaItemStack and transferring them into the inventory - not copying
+@tparam table items items which are to be added to the chests, an array of LuaItemStack
+@tparam[opt=navies] LuaSurface surface the surface that the items will be moved to
+@tparam[opt={0, 0}] table position the position that the items will be moved to {x=100, y=100}
+@tparam[opt=32] number radius the radius in which the items are allowed to be placed
+@tparam[opt=iron-chest] string chest_type the chest type that the items should be moved into
+@treturn LuaEntity the last chest that had items inserted into it
+
+@usage-- Copy all the items in a players inventory and place them in chests at {0, 0}
+move_items(game.player.get_main_inventory())
+
+]]
+function Common.move_items_stack(items, surface, position, radius, chest_type)
+ chest_type = chest_type or 'iron-chest'
+ surface = surface or game.surfaces[1]
+ if position and type(position) ~= 'table' then return end
+ if type(items) ~= 'table' then return end
+ -- Finds all entities of the given type
+ local p = position or {x=0, y=0}
+ local r = radius or 32
+ local entities = surface.find_entities_filtered{area={{p.x-r, p.y-r}, {p.x+r, p.y+r}}, name=chest_type} or {}
+ local count = #entities
+ local current = 1
+ -- Makes a new empty chest when it is needed
+ local function make_new_chest()
+ local pos = surface.find_non_colliding_position(chest_type, position, 32, 1)
+ local chest = surface.create_entity{name=chest_type, position=pos, force='neutral'}
+ table.insert(entities, chest)
+ count = count + 1
+ return chest
+ end
+ -- Function used to round robin the items into all chests
+ local function next_chest(item)
+ local chest = entities[current]
+ if count == 0 then return make_new_chest() end
+ if chest.get_inventory(defines.inventory.chest).can_insert(item) then
+ -- If the item can be inserted then the chest is returned
+ current = current+1
+ if current > count then current = 1 end
+ return chest
+ else
+ -- Other wise it is removed from the list
+ table.remove(entities, current)
+ count = count - 1
+ end
+ end
+ -- Inserts the items into the chests
+ local last_chest
+ for i=1,#items do
+ local item = items[i]
+ if item.valid_for_read then
+ local chest = next_chest(item)
+ if not chest or not chest.valid then return error(string.format('Cant move item %s to %s{%s, %s} no valid chest in radius', item.name, surface.name, p.x, p.y)) end
+ chest.insert(item)
+ last_chest = chest
+ end
+ end
+ return last_chest
+end
+
--[[-- Prints a colored value on a location, color is based on the value.
nb: src is below but the gradent has been edited
https://github.com/Refactorio/RedMew/blob/9184b2940f311d8c9c891e83429fc57ec7e0c4a2/map_gen/maps/diggy/debug.lua#L31
diff --git a/locale/en/gui.cfg b/locale/en/gui.cfg
index 8a822b82..5a638410 100644
--- a/locale/en/gui.cfg
+++ b/locale/en/gui.cfg
@@ -200,4 +200,10 @@ data-settings=Settings
data-statistics=Statistics
data-required=Required
data-misc=Miscellaneous
-data-format=__1____2__
\ No newline at end of file
+data-format=__1____2__
+
+[tree-decon]
+main-tooltip=Toggle fast tree decon
+enabled=enabled
+disabled=disabled
+toggle-msg=Fast decon has been __1__
\ No newline at end of file
diff --git a/modules/addons/death-logger.lua b/modules/addons/death-logger.lua
index 97c057fe..092bcd4a 100644
--- a/modules/addons/death-logger.lua
+++ b/modules/addons/death-logger.lua
@@ -4,7 +4,7 @@
local Event = require 'utils.event' --- @dep utils.event
local Global = require 'utils.global' --- @dep utils.global
local config = require 'config.death_logger' --- @dep config.death_logger
-local format_time, move_items = _C.format_time, _C.move_items --- @dep expcore.common
+local format_time, move_items = _C.format_time, _C.move_items_stack --- @dep expcore.common
-- Max amount of ticks a corpse can be alive
local corpse_lifetime = 60*60*15
@@ -64,7 +64,7 @@ Event.add(defines.events.on_player_died, function(event)
local player = game.players[event.player_index]
local corpse = player.surface.find_entity('character-corpse', player.position)
if config.use_chests_as_bodies then
- local items = corpse.get_inventory(defines.inventory.character_corpse).get_contents()
+ local items = corpse.get_inventory(defines.inventory.character_corpse)
local chest = move_items(items, corpse.surface, corpse.position)
chest.destructible = false
corpse.destroy()
@@ -140,7 +140,7 @@ end
if config.auto_collect_bodies then
Event.add(defines.events.on_character_corpse_expired, function(event)
local corpse = event.corpse
- local items = corpse.get_inventory(defines.inventory.character_corpse).get_contents()
+ local items = corpse.get_inventory(defines.inventory.character_corpse)
move_items(items, corpse.surface, {x=0, y=0})
end)
end
diff --git a/modules/addons/deconlog.lua b/modules/addons/deconlog.lua
new file mode 100644
index 00000000..4b2529d6
--- /dev/null
+++ b/modules/addons/deconlog.lua
@@ -0,0 +1,64 @@
+--- Log certain actions into a file when events are triggered
+-- @addon Deconlog
+
+local Event = require 'utils.event' --- @dep utils.event
+local Roles = require 'expcore.roles' --- @dep expcore.roles
+local format_time = _C.format_time
+local config = require 'config.deconlog' --- @dep config.deconlog
+
+local filepath = "log/decon.log"
+
+local function add_log(data)
+ game.write_file(filepath, data .. "\n", true, 0) -- write data
+end
+local function get_secs ()
+ return format_time(game.tick, { hours = true, minutes = true, seconds = true, string = true })
+end
+local function pos_tostring (pos)
+ return tostring(pos.x) .. "," .. tostring(pos.y)
+end
+
+Event.on_init(function()
+ game.write_file(filepath, "\n", false, 0) -- write data
+end)
+
+if config.decon_area then
+ Event.add(defines.events.on_player_deconstructed_area, function (e)
+ local player = game.get_player(e.player_index)
+ if Roles.player_has_flag(player, "deconlog-bypass") then return end
+ add_log(get_secs() .. player.name .. ",decon_area," .. pos_tostring(e.area.left_top) .. "," .. pos_tostring(e.area.right_bottom))
+ end)
+end
+
+if config.built_entity then
+ Event.add(defines.events.on_built_entity, function (e)
+ if not e.player_index then return end
+ local player = game.get_player(e.player_index)
+ if Roles.player_has_flag(player, "deconlog-bypass") then return end
+ local ent = e.created_entity
+ add_log(get_secs() .. player.name .. ",built_entity," .. ent.name .. "," .. pos_tostring(ent.position) .. "," .. tostring(ent.direction) .. "," .. tostring(ent.orientation))
+ end)
+end
+
+if config.mined_entity then
+ Event.add(defines.events.on_player_mined_entity, function (e)
+ local player = game.get_player(e.player_index)
+ if Roles.player_has_flag(player, "deconlog-bypass") then return end
+ local ent = e.entity
+ add_log(get_secs() .. player.name .. ",mined_entity," .. ent.name .. "," .. pos_tostring(ent.position) .. "," .. tostring(ent.direction) .. "," .. tostring(ent.orientation))
+ end)
+end
+
+if config.fired_nuke then
+ Event.add(defines.events.on_player_ammo_inventory_changed, function (e)
+ -- this works only if the player took more than one nuke, which they usually do
+ local player = game.get_player(e.player_index)
+ if Roles.player_has_flag(player, "deconlog-bypass") then return end
+ local ammo_inv = player.get_inventory(defines.inventory.character_ammo)
+ local item = ammo_inv[player.character.selected_gun_index]
+ if not item or not item.valid or not item.valid_for_read then return end
+ if item.name == "atomic-bomb" then
+ add_log(get_secs() .. player.name .. ",shot-bomb," .. pos_tostring(player.position) .. "," .. pos_tostring(player.shooting_state.position))
+ end
+ end)
+end
\ No newline at end of file
diff --git a/modules/addons/inventory-clear.lua b/modules/addons/inventory-clear.lua
index 57ae4958..51dc18e2 100644
--- a/modules/addons/inventory-clear.lua
+++ b/modules/addons/inventory-clear.lua
@@ -3,13 +3,13 @@
local Event = require 'utils.event' --- @dep utils.event
local events = require 'config.inventory_clear' --- @dep config.inventory_clear
-local move_items = _C.move_items --- @dep expcore.common
+local move_items_stack = _C.move_items_stack --- @dep expcore.common
local function clear_items(event)
local player = game.players[event.player_index]
local inv = player.get_main_inventory()
- move_items(inv.get_contents())
+ move_items_stack(inv)
inv.clear()
end
-for _, event_name in ipairs(events) do Event.add(event_name, clear_items) end
\ No newline at end of file
+for _, event_name in ipairs(events) do Event.add(event_name, clear_items) end
diff --git a/modules/addons/tree-decon.lua b/modules/addons/tree-decon.lua
index 29e13707..95a34396 100644
--- a/modules/addons/tree-decon.lua
+++ b/modules/addons/tree-decon.lua
@@ -4,6 +4,8 @@
local Event = require 'utils.event' --- @dep utils.event
local Global = require 'utils.global' --- @dep utils.global
local Roles = require 'expcore.roles' --- @dep expcore.roles
+local Gui = require 'expcore.gui' --- @dep expcore.gui
+local PlayerData = require 'expcore.player_data' --- @dep expcore.player_data
-- Global queue used to store trees that need to be removed, also chache for player roles
local chache = {}
@@ -13,6 +15,22 @@ Global.register({ tree_queue, chache }, function(tbl)
chache = tbl[2]
end)
+
+-- Left menu button to toggle between fast decon and normal decon marking
+local HasEnabledDecon = PlayerData.Settings:combine('HasEnabledDecon')
+HasEnabledDecon:set_default(false)
+
+Gui.toolbar_button("entity/tree-01", {'tree-decon.main-tooltip'}, function (player)
+ return Roles.player_allowed(player, "fast-tree-decon")
+end)
+:on_click(function(player, element)
+ local status = HasEnabledDecon:get(player)
+ HasEnabledDecon:set(player, not status)
+ Gui.toolbar_button_style(element, not status)
+ player.print(status and {'tree-decon.toggle-msg', {'tree-decon.disabled'}} or {'tree-decon.toggle-msg', {'tree-decon.enabled'}})
+end)
+
+
-- Add trees to queue when marked, only allows simple entities and for players with role permission
Event.add(defines.events.on_marked_for_deconstruction, function(event)
-- Check which type of decon a player is allowed
@@ -40,6 +58,10 @@ Event.add(defines.events.on_marked_for_deconstruction, function(event)
-- Allowed to decon this entity, but not fast
if allow ~= 'fast' then return end
+
+ local player = game.get_player(index)
+ if not HasEnabledDecon:get(player) then return end
+
-- Allowed fast decon on this entity, just trees
local head = tree_queue._head + 1
if not last_user and entity.type ~= 'cliff' then
diff --git a/modules/commands/clear-inventory.lua b/modules/commands/clear-inventory.lua
index 04155978..ceb6b3e9 100644
--- a/modules/commands/clear-inventory.lua
+++ b/modules/commands/clear-inventory.lua
@@ -4,7 +4,7 @@
]]
local Commands = require 'expcore.commands' --- @dep expcore.commands
-local move_items = _C.move_items --- @dep expcore.common
+local move_items_stack = _C.move_items_stack --- @dep expcore.common
require 'config.expcore.command_role_parse'
--- Clears a players inventory
@@ -14,10 +14,10 @@ Commands.new_command('clear-inventory', 'Clears a players inventory')
:add_param('player', false, 'player-role')
:add_alias('clear-inv', 'move-inventory', 'move-inv')
:register(function(_, player)
- local inv = player.get_main_inventory()
- if not inv then
- return Commands.error{'expcore-commands.reject-player-alive'}
- end
- move_items(inv.get_contents())
- inv.clear()
-end)
\ No newline at end of file
+ local inv = player.get_main_inventory()
+ if not inv then
+ return Commands.error{'expcore-commands.reject-player-alive'}
+ end
+ move_items_stack(inv)
+ inv.clear()
+end)
diff --git a/modules/graftorio/forcestats.lua b/modules/graftorio/forcestats.lua
new file mode 100644
index 00000000..9839a484
--- /dev/null
+++ b/modules/graftorio/forcestats.lua
@@ -0,0 +1,190 @@
+local Event = require("utils.event")
+local general = require("modules.graftorio.general")
+local config = require("config.graftorio")
+
+local lib = {}
+
+lib.collect_production = function()
+ for _, force in pairs(game.forces) do
+ ---@class ProductionStatistics
+ ---@field item_input table
+ ---@field item_output table
+ ---@field fluid_input table
+ ---@field fluid_output table
+ ---@field kill_input table
+ ---@field kill_output table
+ ---@field build_input table
+ ---@field build_output table
+ local stats = {
+ item_input = {},
+ item_output = {},
+ fluid_input = {},
+ fluid_output = {},
+ kill_input = {},
+ kill_output = {},
+ build_input = {},
+ build_output = {},
+ }
+
+ for name, count in pairs(force.item_production_statistics.input_counts) do
+ local itemstats = stats.item_input[name] or {}
+ itemstats.count = count
+ stats.item_input[name] = itemstats
+ end
+ for name, count in pairs(force.item_production_statistics.output_counts) do
+ local itemstats = stats.item_output[name] or {}
+ itemstats.count = count
+ stats.item_output[name] = itemstats
+ end
+
+ for name, count in pairs(force.fluid_production_statistics.input_counts) do
+ local fluidstats = stats.fluid_input[name] or {}
+ fluidstats.count = count
+ stats.fluid_input[name] = fluidstats
+ end
+ for name, count in pairs(force.fluid_production_statistics.output_counts) do
+ local fluidstats = stats.fluid_output[name] or {}
+ fluidstats.count = count
+ stats.fluid_output[name] = fluidstats
+ end
+
+ for name, count in pairs(force.kill_count_statistics.input_counts) do
+ local killstats = stats.kill_input[name] or {}
+ killstats.count = count
+ stats.kill_input[name] = killstats
+ end
+ for name, count in pairs(force.kill_count_statistics.output_counts) do
+ local killstats = stats.kill_output[name] or {}
+ killstats.count = count
+ stats.kill_output[name] = killstats
+ end
+
+ for name, count in pairs(force.entity_build_count_statistics.input_counts) do
+ local buildstats = stats.build_input[name] or {}
+ buildstats.count = count
+ stats.build_input[name] = buildstats
+ end
+ for name, count in pairs(force.entity_build_count_statistics.output_counts) do
+ local buildstats = stats.build_output[name] or {}
+ buildstats.count = count
+ stats.build_output[name] = buildstats
+ end
+
+ general.data.output[force.name].production = stats
+ end
+end
+
+lib.collect_loginet = function()
+ for _, force in pairs(game.forces) do
+ ---@class RobotStatistics
+ ---@field all_construction_robots uint
+ ---@field available_construction_robot uint
+ ---@field all_logistic_robots uint
+ ---@field available_logistic_robots uint
+ ---@field charging_robot_count uint
+ ---@field to_charge_robot_count uint
+ ---@field items table
+ ---@field pickups table
+ ---@field deliveries table
+ local stats = {
+ all_construction_robots = 0,
+ available_construction_robots = 0,
+
+ all_logistic_robots = 0,
+ available_logistic_robots = 0,
+
+ charging_robot_count = 0,
+ to_charge_robot_count = 0,
+
+ items = {},
+ pickups = {},
+ deliveries = {},
+ }
+ for _, networks in pairs(force.logistic_networks) do
+ for _, network in pairs(networks) do
+ stats.available_construction_robots = network.available_construction_robots
+ stats.all_construction_robots = network.all_construction_robots
+
+ stats.available_logistic_robots = network.available_logistic_robots
+ stats.all_logistic_robots = network.all_logistic_robots
+
+ stats.charging_robot_count = 0
+ stats.to_charge_robot_count = 0
+ for _, cell in pairs(network.cells) do
+ stats.charging_robot_count = (stats.charging_robot_count) + cell.charging_robot_count
+ stats.to_charge_robot_count = (stats.to_charge_robot_count) + cell.to_charge_robot_count
+ end
+
+ if config.modules.logistorage then
+ for name, v in pairs(network.get_contents()) do
+ stats.items[name] = (stats.items[name] or 0) + v
+ end
+
+ -- pickups and deliveries of items
+ for _, point_list in pairs({ network.provider_points, network.requester_points, network.storage_points }) do
+ for _, point in pairs(point_list) do
+ for name, qty in pairs(point.targeted_items_pickup) do
+ stats.pickups[name] = (stats.pickups[name] or 0) + qty
+ end
+ for name, qty in pairs(point.targeted_items_deliver) do
+ stats.deliveries[name] = (stats.deliveries[name] or 0) + qty
+ end
+ end
+ end
+ end
+ end
+ end
+ general.data.output[force.name].robots = stats
+ end
+end
+
+
+---@class ResearchStatistics
+---@field current Research
+---@field queue Research[]
+
+---@class Research
+---@field name string
+---@field level uint
+---@field progress double
+
+
+Event.add(defines.events.on_research_finished, function(evt)
+ local research = evt.research
+ if not general.data.output[research.force.name] then general.data.output[research.force.name] = {} end
+ if not general.data.output[research.force.name].research then general.data.output[research.force.name].research = {} end
+
+ local force_research = general.data.output[research.force.name].research or {}
+ table.remove(force_research, 1)
+ general.data.output[research.force.name].research = force_research
+end)
+
+Event.add(defines.events.on_research_started, function(evt)
+ -- move queue up
+ local research = evt.research
+ if not general.data.output[research.force.name].research then general.data.output[research.force.name].research = {} end
+
+ local force_research = general.data.output[research.force.name].research or {}
+ table.remove(force_research, 1)
+ general.data.output[research.force.name].research = force_research
+end)
+
+Event.on_nth_tick(60, function()
+ for _, force in pairs(game.forces) do
+ if not general.data.output[force.name].research then general.data.output[force.name].research = {} end
+
+ local force_research = {}
+ -- this works even if the queue is disabled, but it will always be just 1 long in that case
+ for _, research in pairs(force.research_queue) do
+ table.insert(force_research, {
+ name = research.name,
+ level = research.level,
+ progress = force.get_saved_technology_progress(research) or 0,
+ })
+ end
+
+ general.data.output[force.name].research = force_research
+ end
+end)
+
+return lib
diff --git a/modules/graftorio/general.lua b/modules/graftorio/general.lua
new file mode 100644
index 00000000..29c9ca1f
--- /dev/null
+++ b/modules/graftorio/general.lua
@@ -0,0 +1,65 @@
+local Event = require("utils.event")
+local Global = require("utils.global")
+
+local lib = {}
+
+lib.data = {
+ output = {}
+}
+
+Global.register(lib.data, function(tbl)
+ lib.data = tbl
+end)
+
+---@class Statistics
+---@field trains TrainStatistics
+---@field power PowerStatistics
+---@field production ProductionStatistics
+---@field robots RobotStatistics
+---@field other OtherStatistics
+
+Event.on_init(function()
+ ---@type table
+ lib.data.output = {}
+ for _, force in pairs(game.forces) do
+ lib.data.output[force.name] = {}
+ end
+end)
+
+---@class OtherStatistics
+---@field tick uint
+---@field evolution EvolutionStatistics
+---@field research ResearchStatistics
+
+---@class EvolutionStatistics
+---@field evolution_factor double
+---@field evolution_factor_by_pollution double
+---@field evolution_factor_by_time double
+---@field evolution_factor_by_killing_spawners double
+
+lib.collect_other = function()
+ for _, force in pairs(game.forces) do
+ ---@type OtherStatistics
+ local other = lib.data.output[force.name].other or {}
+
+ other.evolution = {
+ evolution_factor = force.evolution_factor,
+ evolution_factor_by_pollution = force.evolution_factor_by_pollution,
+ evolution_factor_by_time = force.evolution_factor_by_time,
+ evolution_factor_by_killing_spawners = force.evolution_factor_by_killing_spawners
+ }
+ for k, v in pairs(other) do
+ lib.data.output[force.name].other[k] = v
+ end
+ end
+end
+
+Event.add(defines.events.on_force_created, function(evt)
+ lib.data.output[evt.force.name] = {}
+end)
+
+Event.add(defines.events.on_forces_merged, function(evt)
+ lib.data.output[evt.source_name] = nil
+end)
+
+return lib
diff --git a/modules/graftorio/require.lua b/modules/graftorio/require.lua
new file mode 100644
index 00000000..d4c05257
--- /dev/null
+++ b/modules/graftorio/require.lua
@@ -0,0 +1,26 @@
+local Commands = require("expcore.commands")
+local config = require("config.graftorio")
+local statics = require("modules.graftorio.statics")
+local forcestats = nil
+local general = nil
+if config.modules.forcestats then
+ forcestats = require("modules.graftorio.forcestats")
+end
+if config.modules.general then
+ general = require("modules.graftorio.general")
+end
+
+Commands.new_command("collectdata", "Collect data for RCON usage")
+ :add_param("location", true)
+ :register(function()
+ -- this must be first as it overwrites the stats
+ -- also makes the .other table for all forces
+ statics.collect_statics()
+ if config.modules.general then general.collect_other() end
+ if config.modules.forcestats then
+ forcestats.collect_production()
+ forcestats.collect_loginet()
+ end
+ rcon.print(game.table_to_json(general.data.output))
+ return Commands.success()
+ end)
diff --git a/modules/graftorio/statics.lua b/modules/graftorio/statics.lua
new file mode 100644
index 00000000..3f065e47
--- /dev/null
+++ b/modules/graftorio/statics.lua
@@ -0,0 +1,35 @@
+local general = require("modules.graftorio.general")
+
+local lib = {}
+
+---@class StaticStatistics
+---@field tick uint
+---@field online_players string[]
+---@field mods table
+---@field seed table
+
+lib.collect_statics = function()
+ local stats = {}
+ stats.tick = game.tick
+
+ stats.online_players = {}
+ for _, player in pairs(game.connected_players) do
+ table.insert(stats.online_players, player.name)
+ end
+
+ stats.mods = {}
+ for name, version in pairs(game.active_mods) do
+ stats.mods[name] = version
+ end
+
+ -- reason behind this is that the map gen settings can be changed during runtime so just get them fresh
+ stats.seed = {}
+ for _, surface in pairs(game.surfaces) do
+ stats.seed[surface.name] = surface.map_gen_settings.seed
+ end
+ for _, force in pairs(game.forces) do
+ general.data.output[force.name].other = stats
+ end
+end
+
+return lib
diff --git a/modules/gui/warp-list.lua b/modules/gui/warp-list.lua
index e95e4589..9763233f 100644
--- a/modules/gui/warp-list.lua
+++ b/modules/gui/warp-list.lua
@@ -764,8 +764,8 @@ Event.on_nth_tick(math.floor(60/config.update_smoothing), function()
end
-- Check if the force has any warps
- local closest_warp
- local closest_distance
+ local closest_warp = nil
+ local closest_distance = nil
if #warp_ids > 0 then
local surface = player.surface
local pos = player.position
@@ -794,7 +794,7 @@ Event.on_nth_tick(math.floor(60/config.update_smoothing), function()
end
-- Check the dist to the closest warp
- local in_range = closest_warp.warp_id == warp_ids.spawn and closest_distance < rs2 or closest_distance < r2
+ local in_range = closest_warp ~= nil and (closest_warp.warp_id == warp_ids.spawn and closest_distance < rs2 or closest_distance < r2)
if was_in_range and not in_range then
PlayerInRange:set(player, nil)
elseif not was_in_range and in_range then
@@ -804,17 +804,16 @@ Event.on_nth_tick(math.floor(60/config.update_smoothing), function()
-- Change the enabled state of the add warp button
local frame = Gui.get_left_element(player, warp_list_container)
local add_warp_element = frame.container.header.alignment[add_new_warp.name]
- local old_closest_warp_name = add_warp_element.tooltip[2] or closest_warp.name
+ local old_closest_warp_name = add_warp_element.tooltip[2] or closest_warp and closest_warp.name
local was_able_to_make_warp = add_warp_element.enabled
- local can_make_warp = closest_distance > mr2
+ local can_make_warp = closest_distance == nil or closest_distance > mr2
if can_make_warp and not was_able_to_make_warp then
add_warp_element.enabled = true
add_warp_element.tooltip = {'warp-list.add-tooltip'}
- elseif not can_make_warp and was_able_to_make_warp or old_closest_warp_name ~= closest_warp.name then
+ elseif not can_make_warp and was_able_to_make_warp or closest_warp and (old_closest_warp_name ~= closest_warp.name) then
add_warp_element.enabled = false
add_warp_element.tooltip = {'warp-list.too-close', closest_warp.name}
end
-
end
end