@expcluster/legacy 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/LICENSE.md +21 -0
  2. package/dist/browser/package.json +40 -0
  3. package/dist/browser/tsconfig.browser.tsbuildinfo +1 -0
  4. package/dist/browser/web/index.d.ts +1 -0
  5. package/dist/browser/web/index.d.ts.map +1 -0
  6. package/dist/browser/web/index.js +2 -0
  7. package/dist/browser/web/index.js.map +1 -0
  8. package/dist/node/index.d.ts +3 -0
  9. package/dist/node/index.d.ts.map +1 -0
  10. package/dist/node/index.js +10 -0
  11. package/dist/node/index.js.map +1 -0
  12. package/dist/node/instance.d.ts +4 -0
  13. package/dist/node/instance.d.ts.map +1 -0
  14. package/dist/node/instance.js +8 -0
  15. package/dist/node/instance.js.map +1 -0
  16. package/dist/node/tsconfig.node.tsbuildinfo +1 -0
  17. package/dist/web/manifest.json +7 -0
  18. package/dist/web/static/exp_legacy.9b6538559ed5e689539c.js +355 -0
  19. package/dist/web/static/index_ts.8f9d451c8d3f7f293da6.js +22 -0
  20. package/dist/web/static/main.94e1b48804112ca8bdfc.js +118 -0
  21. package/dist/web/static/package_json.a83729efdb0697b12396.js +22 -0
  22. package/dist/web/static/web_index_tsx.e5a01ac0e4b0a6f6517f.js +21 -0
  23. package/index.ts +8 -0
  24. package/instance.ts +7 -0
  25. package/module/config/_file_loader.lua +29 -0
  26. package/module/config/advanced_start.lua +112 -0
  27. package/module/config/afk_kick.lua +14 -0
  28. package/module/config/bonus.lua +105 -0
  29. package/module/config/chat_reply.lua +136 -0
  30. package/module/config/compilatron.lua +25 -0
  31. package/module/config/death_logger.lua +15 -0
  32. package/module/config/deconlog.lua +11 -0
  33. package/module/config/discord_alerts.lua +25 -0
  34. package/module/config/expcore/permission_groups.lua +143 -0
  35. package/module/config/graftorio.lua +7 -0
  36. package/module/config/gui/autofill.lua +129 -0
  37. package/module/config/gui/player_list_actions.lua +201 -0
  38. package/module/config/gui/rockets.lua +47 -0
  39. package/module/config/gui/science.lua +21 -0
  40. package/module/config/gui/tasks.lua +13 -0
  41. package/module/config/gui/warps.lua +52 -0
  42. package/module/config/inventory_clear.lua +9 -0
  43. package/module/config/join_messages.lua +8 -0
  44. package/module/config/lawnmower.lua +6 -0
  45. package/module/config/logging.lua +30 -0
  46. package/module/config/miner.lua +8 -0
  47. package/module/config/module.lua +86 -0
  48. package/module/config/nukeprotect.lua +30 -0
  49. package/module/config/pollution_grading.lua +9 -0
  50. package/module/config/popup_messages.lua +10 -0
  51. package/module/config/preset_player_colours.lua +33 -0
  52. package/module/config/preset_player_quickbar.lua +6 -0
  53. package/module/config/protection.lua +17 -0
  54. package/module/config/repair.lua +8 -0
  55. package/module/config/research.lua +179 -0
  56. package/module/config/scorched_earth.lua +116 -0
  57. package/module/config/spawn_area.lua +255 -0
  58. package/module/config/station_auto_name.lua +11 -0
  59. package/module/config/statistics.lua +46 -0
  60. package/module/config/vlayer.lua +180 -0
  61. package/module/config/warnings.lua +38 -0
  62. package/module/control.lua +46 -0
  63. package/module/expcore/datastore.lua +884 -0
  64. package/module/expcore/external.lua +146 -0
  65. package/module/expcore/permission_groups.lua +355 -0
  66. package/module/expcore/player_data.lua +152 -0
  67. package/module/locale/en/addons.cfg +31 -0
  68. package/module/locale/en/data.cfg +114 -0
  69. package/module/locale/en/expcore.cfg +16 -0
  70. package/module/locale/en/gui.cfg +114 -0
  71. package/module/locale/zh-CN/addons.cfg +31 -0
  72. package/module/locale/zh-CN/data.cfg +114 -0
  73. package/module/locale/zh-CN/expcore.cfg +16 -0
  74. package/module/locale/zh-CN/gui.cfg +122 -0
  75. package/module/locale/zh-TW/addons.cfg +31 -0
  76. package/module/locale/zh-TW/data.cfg +114 -0
  77. package/module/locale/zh-TW/expcore.cfg +16 -0
  78. package/module/locale/zh-TW/gui.cfg +122 -0
  79. package/module/module.json +14 -0
  80. package/module/module_exports.lua +3 -0
  81. package/module/modules/control/jail.lua +119 -0
  82. package/module/modules/control/protection.lua +204 -0
  83. package/module/modules/control/reports.lua +225 -0
  84. package/module/modules/control/spectate.lua +173 -0
  85. package/module/modules/control/vlayer.lua +807 -0
  86. package/module/modules/control/warnings.lua +331 -0
  87. package/module/modules/control/warps.lua +488 -0
  88. package/module/modules/data/alt-view.lua +26 -0
  89. package/module/modules/data/greetings.lua +45 -0
  90. package/module/modules/data/language.lua +21 -0
  91. package/module/modules/data/player-colours.lua +63 -0
  92. package/module/modules/data/quickbar.lua +72 -0
  93. package/module/modules/data/statistics.lua +181 -0
  94. package/module/modules/data/tag.lua +82 -0
  95. package/module/modules/data/toolbar.lua +31 -0
  96. package/module/modules/graftorio/forcestats.lua +196 -0
  97. package/module/modules/graftorio/general.lua +63 -0
  98. package/module/modules/graftorio/require.lua +28 -0
  99. package/module/modules/graftorio/statics.lua +36 -0
  100. package/module/modules/gui/vlayer.lua +547 -0
  101. package/module/modules/gui/warp-list.lua +909 -0
  102. package/module/utils/event.lua +86 -0
  103. package/package.json +38 -0
  104. package/tsconfig.browser.json +4 -0
  105. package/tsconfig.json +7 -0
  106. package/tsconfig.node.json +5 -0
  107. package/web/index.tsx +0 -0
  108. package/webpack.config.js +29 -0
@@ -0,0 +1,72 @@
1
+ --[[-- Commands Module - Quickbar
2
+ - Adds a command that allows players to load Quickbar presets
3
+ @data Quickbar
4
+ ]]
5
+
6
+ local Commands = require("modules/exp_commands")
7
+ local config = require("modules.exp_legacy.config.preset_player_quickbar") --- @dep config.preset_player_quickbar
8
+
9
+ --- Stores the quickbar filters for a player
10
+ local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
11
+ local PlayerFilters = PlayerData.Settings:combine("QuickbarFilters")
12
+ PlayerFilters:set_metadata{
13
+ permission = "exp_scenario.command.save_quickbar",
14
+ stringify = function(value)
15
+ if not value then return "No filters set" end
16
+ local count = 0
17
+ for _ in pairs(value) do count = count + 1 end
18
+
19
+ return count .. " filters set"
20
+ end,
21
+ }
22
+
23
+ --- Loads your quickbar preset
24
+ PlayerFilters:on_load(function(player_name, filters)
25
+ if not filters then filters = config[player_name] end
26
+ if not filters then return end
27
+ local player = game.players[player_name]
28
+ for i, item_name in pairs(filters) do
29
+ if item_name ~= nil and item_name ~= "" then
30
+ player.set_quick_bar_slot(i, item_name)
31
+ end
32
+ end
33
+ end)
34
+
35
+ local ignored_items = {
36
+ ["blueprint"] = true,
37
+ ["blueprint-book"] = true,
38
+ ["deconstruction-planner"] = true,
39
+ ["spidertron-remote"] = true,
40
+ ["upgrade-planner"] = true,
41
+ }
42
+
43
+ --- Saves your quickbar preset to the script-output folder
44
+ Commands.new("save-quickbar", "Saves your Quickbar preset items to file")
45
+ :add_aliases{ "save-toolbar" }
46
+ :add_flags{ "disabled" }
47
+ :register(function(player)
48
+ local filters = {}
49
+
50
+ error("2.1 changes to get_quick_bar_slot beak compatibility with 2.0; waiting for upstream")
51
+ -- Upstream may add method to compat, or change inventory sync to have a quickbar only mode
52
+ for i = 1, 100 do
53
+ --[[
54
+ local slot = player.get_quick_bar_slot(i)
55
+ -- Need to filter out blueprint and blueprint books because the slot is a LuaItemPrototype and does not contain a way to export blueprint data
56
+ if slot ~= nil then
57
+ local ignored = ignored_items[slot.name]
58
+ if ignored ~= true then
59
+ filters[i] = slot.name
60
+ end
61
+ end
62
+ ]]
63
+ end
64
+
65
+ if next(filters) then
66
+ PlayerFilters:set(player, filters)
67
+ else
68
+ PlayerFilters:remove(player)
69
+ end
70
+
71
+ return Commands.status.success{ "quickbar.saved" }
72
+ end)
@@ -0,0 +1,181 @@
1
+ local ExpUtil = require("modules/exp_util")
2
+ local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
3
+ local Storage = require("modules/exp_util/storage") --- @dep utils.global
4
+ local config = require("modules.exp_legacy.config.statistics") --- @dep config.statistics
5
+ local floor = math.floor
6
+ local afk_required = 5 * 3600 -- 5 minutes
7
+
8
+ --- Stores players who have been created, required to avoid loss of data
9
+ local new_players = {}
10
+ Storage.register(new_players, function(tbl)
11
+ new_players = tbl
12
+ end)
13
+
14
+ --- Stores the statistics on a player
15
+ local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
16
+ local AllPlayerData = PlayerData.All
17
+ local Statistics = PlayerData.Statistics
18
+ Statistics:set_metadata{
19
+ display_order = config.display_order,
20
+ }
21
+
22
+ --- Update your statistics with any which happened before the data was valid
23
+ Statistics:on_load(function(player_name, player_statistics)
24
+ local existing_data = AllPlayerData:get(player_name)
25
+ if existing_data and existing_data.valid then return end
26
+ local counters = config.counters
27
+
28
+ -- Merge all data from before you data loaded
29
+ for key, value in pairs(Statistics:get(player_name, {})) do
30
+ if config[key] or counters[key] then
31
+ if not player_statistics[key] then
32
+ player_statistics[key] = value
33
+ else
34
+ player_statistics[key] = player_statistics[key] + value
35
+ end
36
+ end
37
+ end
38
+
39
+ -- Increment your maps played if this is your first time on this map
40
+ if new_players[player_name] then
41
+ new_players[player_name] = nil
42
+ local ctn = player_statistics.MapsPlayed
43
+ player_statistics["MapsPlayed"] = ctn and ctn + 1 or 1
44
+ end
45
+
46
+ return player_statistics
47
+ end)
48
+
49
+ local long_time_format = ExpUtil.format_time_factory_locale{ format = "long", coefficient = 3600, hours = true, minutes = true }
50
+ local short_time_format = ExpUtil.format_time_factory_locale{ format = "short", coefficient = 3600, hours = true, minutes = true }
51
+
52
+ --- Add MapsPlayed if it is enabled
53
+ if config.MapsPlayed then
54
+ Statistics:combine("MapsPlayed")
55
+ Event.add(defines.events.on_player_created, function(event)
56
+ local player = game.players[event.player_index]
57
+ new_players[player.name] = true
58
+ end)
59
+ end
60
+
61
+ --- Add Playtime and AfkTime if it is enabled
62
+ if config.Playtime or config.AfkTime then
63
+ local playtime, afk_time
64
+ if config.Playtime then
65
+ playtime = Statistics:combine("Playtime")
66
+ playtime:set_metadata{ stringify = long_time_format, stringify_short = short_time_format }
67
+ end
68
+ if config.AfkTime then
69
+ afk_time = Statistics:combine("AfkTime")
70
+ afk_time:set_metadata{ stringify = long_time_format, stringify_short = short_time_format }
71
+ end
72
+ Event.on_nth_tick(3600, function()
73
+ if game.tick == 0 then return end
74
+ for _, player in pairs(game.connected_players) do
75
+ if playtime then playtime:increment(player) end
76
+ if afk_time and player.afk_time > afk_required then afk_time:increment(player) end
77
+ end
78
+ end)
79
+ end
80
+
81
+ --- Add DistanceTravelled if it is enabled
82
+ if config.DistanceTravelled then
83
+ local stat = Statistics:combine("DistanceTravelled")
84
+ stat:set_metadata{ unit = " tiles" }
85
+ Event.add(defines.events.on_player_changed_position, function(event)
86
+ local player = game.players[event.player_index]
87
+ if not player.valid or not player.connected or player.afk_time > afk_required then return end
88
+ stat:increment(player)
89
+ end)
90
+ end
91
+
92
+ --- Add MachinesRemoved and TreesDestroyed and config.OreMined if it is enabled
93
+ if config.MachinesRemoved or config.TreesDestroyed or config.OreMined then
94
+ local machines, trees, ore
95
+ if config.MachinesRemoved then machines = Statistics:combine("MachinesRemoved") end
96
+ if config.TreesDestroyed then trees = Statistics:combine("TreesDestroyed") end
97
+ if config.OreMined then ore = Statistics:combine("OreMined") end
98
+ local function on_event(event)
99
+ if not event.player_index then return end -- Check player is valid
100
+ local player = game.players[event.player_index]
101
+ if not player.valid or not player.connected then return end
102
+ local entity = event.entity -- Check entity is valid
103
+ if not entity.valid then return end
104
+ if entity.type == "resource" then
105
+ ore:increment(player)
106
+ elseif entity.type == "tree" then
107
+ trees:increment(player)
108
+ elseif entity.force == player.force then
109
+ machines:increment(player)
110
+ end
111
+ end
112
+ Event.add(defines.events.on_marked_for_deconstruction, on_event)
113
+ Event.add(defines.events.on_player_mined_entity, on_event)
114
+ end
115
+
116
+ --- Add DamageDealt if it is enabled
117
+ if config.DamageDealt then
118
+ local stat = Statistics:combine("DamageDealt")
119
+ Event.add(defines.events.on_entity_damaged, function(event)
120
+ local character = event.cause -- Check character is valid
121
+ if not character or not character.valid or character.type ~= "character" then return end
122
+ local player = character.player -- Check player is valid
123
+ if not player.valid or not player.connected then return end
124
+ local entity = event.entity -- Check entity is valid
125
+ if not entity.valid or entity.force == player.force or entity.force.name == "neutral" then return end
126
+ stat:increment(player, floor(event.final_damage_amount))
127
+ end)
128
+ end
129
+
130
+ --- Add Kills if it is enabled
131
+ if config.Kills then
132
+ local stat = Statistics:combine("Kills")
133
+ Event.add(defines.events.on_entity_died, function(event)
134
+ local character = event.cause -- Check character is valid
135
+ if not character or not character.valid or character.type ~= "character" then return end
136
+ local player = character.player -- Check player is valid
137
+ if not player or not player.valid or not player.connected then return end
138
+ local entity = event.entity -- Check entity is valid
139
+ if not entity.valid or entity.force == player.force or entity.force.name == "neutral" then return end
140
+ stat:increment(player)
141
+ end)
142
+ end
143
+
144
+ --- Add RocketsLaunched if it is enabled
145
+ if config.RocketsLaunched then
146
+ local stat = Statistics:combine("RocketsLaunched")
147
+ Event.add(defines.events.on_rocket_launched, function(event)
148
+ local silo = event.rocket_silo -- Check silo is valid
149
+ if not silo or not silo.valid then return end
150
+ local force = silo.force -- Check force is valid
151
+ if not force or not force.valid then return end
152
+ for _, player in pairs(force.connected_players) do
153
+ stat:increment(player)
154
+ end
155
+ end)
156
+ end
157
+
158
+ --- Add RocketsLaunched if it is enabled
159
+ if config.ResearchCompleted then
160
+ local stat = Statistics:combine("ResearchCompleted")
161
+ Event.add(defines.events.on_research_finished, function(event)
162
+ local research = event.research -- Check research is valid
163
+ if event.by_script or not research or not research.valid then return end
164
+ local force = research.force -- Check force is valid
165
+ if not force or not force.valid then return end
166
+ for _, player in pairs(force.connected_players) do
167
+ stat:increment(player)
168
+ end
169
+ end)
170
+ end
171
+
172
+ --- Add all the remaining statistics from the config
173
+ for statistic, event_name in pairs(config.counters) do
174
+ local stat = Statistics:combine(statistic)
175
+ Event.add(event_name, function(event)
176
+ if not event.player_index then return end
177
+ local player = game.players[event.player_index]
178
+ if not player.valid or not player.connected then return end
179
+ stat:increment(player)
180
+ end)
181
+ end
@@ -0,0 +1,82 @@
1
+ --[[-- Commands Module - Tag
2
+ - Adds a command that allows players to have a custom tag after their name
3
+ @data Tag
4
+ ]]
5
+
6
+ local Commands = require("modules/exp_commands")
7
+ local Roles = require("modules/exp_roles")
8
+
9
+ --- Stores the tag for a player
10
+ local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
11
+ local PlayerTags = PlayerData.Settings:combine("Tag")
12
+ local PlayerTagColors = PlayerData.Settings:combine("TagColor")
13
+ PlayerTags:set_metadata{
14
+ permission = "exp_scenario.command.tag",
15
+ }
16
+ PlayerTagColors:set_metadata{
17
+ permission = "exp_scenario.command.tag_color",
18
+ }
19
+
20
+ local set_tag = function(player, tag, color)
21
+ if tag == nil or tag == "" then
22
+ player.tag = ""
23
+ elseif color then
24
+ player.tag = "- [color=" .. color .. "]" .. tag .. "[/color]"
25
+ else
26
+ player.tag = "- " .. tag
27
+ end
28
+ end
29
+
30
+ --- When your tag is updated then apply the changes
31
+ PlayerTags:on_update(function(player_name, player_tag)
32
+ local player = game.players[player_name]
33
+ local player_tag_color = PlayerTagColors:get(player)
34
+
35
+ set_tag(player, player_tag, player_tag_color)
36
+ end)
37
+
38
+ --- When your tag color is updated then apply the changes
39
+ PlayerTagColors:on_update(function(player_name, player_tag_color)
40
+ local player = game.players[player_name]
41
+ local player_tag = PlayerTags:get(player)
42
+
43
+ set_tag(player, player_tag, player_tag_color)
44
+ end)
45
+
46
+ --- Sets your player tag.
47
+ Commands.new("tag", "Sets your player tag.")
48
+ :argument("tag", "", Commands.types.string_max_length(20))
49
+ :enable_auto_concatenation()
50
+ :register(function(player, tag)
51
+ --- @cast tag string
52
+ PlayerTags:set(player, tag)
53
+ end)
54
+
55
+ --- Sets your player tag color.
56
+ Commands.new("tag-color", "Sets your player tag color.")
57
+ :argument("color", "", Commands.types.color)
58
+ :enable_auto_concatenation()
59
+ :register(function(player, color)
60
+ --- @cast color Color
61
+ PlayerTagColors:set(player, color)
62
+ end)
63
+
64
+ --- Clears your tag. Or another player if you are admin.
65
+ Commands.new("tag-clear", "Clears your tag. Or another player if you are admin.")
66
+ :optional("player", "", Commands.types.lower_role_player)
67
+ :defaults{
68
+ player = function(player) return player end
69
+ }
70
+ :register(function(player, other_player)
71
+ --- @cast other_player LuaPlayer
72
+ if other_player == player then
73
+ -- No player given so removes your tag
74
+ PlayerTags:remove(other_player)
75
+ elseif Roles.player_has_permission(player, "exp_scenario.command.tag_clear.always") then
76
+ -- Player given and user is admin so clears that player's tag
77
+ PlayerTags:remove(other_player)
78
+ else
79
+ -- User is not admin and tried to clear another users tag
80
+ return Commands.status.unauthorised()
81
+ end
82
+ end)
@@ -0,0 +1,31 @@
1
+ local Gui = require("modules/exp_gui")
2
+ local PlayerData = require("modules.exp_legacy.expcore.player_data")
3
+
4
+ -- Used to store the state of the toolbar when a player leaves
5
+ local ToolbarState = PlayerData.Settings:combine("ToolbarState")
6
+ ToolbarState:set_metadata{
7
+ stringify = function()
8
+ return "Toolbar is saved on exit"
9
+ end,
10
+ }
11
+
12
+ --- Uncompress the data to be more useable
13
+ ToolbarState:on_load(function(player_name, value)
14
+ -- If there is no value, do nothing
15
+ if value == nil then return end
16
+ -- Old format, we discard it [ string[], string[], string[], boolean ]
17
+ if type(value) ~= "string" then return end
18
+
19
+ local decompressed = helpers.json_to_table(assert(helpers.decode_string(value), "Failed String Decode"))
20
+ local player = assert(game.get_player(player_name))
21
+ Gui.toolbar.set_state(player, decompressed --[[@as Gui.ToolbarState]])
22
+
23
+ return nil -- We don't save the state, use Gui.toolbar.get_state
24
+ end)
25
+
26
+ --- Save the current state of the players toolbar menu
27
+ ToolbarState:on_save(function(player_name, _)
28
+ local player = assert(game.get_player(player_name))
29
+ local value = Gui.toolbar.get_state(player)
30
+ return helpers.encode_string(helpers.table_to_json(value))
31
+ end)
@@ -0,0 +1,196 @@
1
+ local Event = require("modules/exp_legacy/utils/event")
2
+ local general = require("modules.exp_legacy.modules.graftorio.general")
3
+ local config = require("modules.exp_legacy.config.graftorio")
4
+
5
+ local lib = {}
6
+
7
+ lib.collect_production = function()
8
+ for _, force in pairs(game.forces) do
9
+ general.data.output[force.name].production = {}
10
+ for _, surface in pairs(game.surfaces) do
11
+ --- @class ItemStats
12
+ --- @field count number
13
+
14
+ --- @class ProductionStatistics
15
+ --- @field item_input table<string, ItemStats>
16
+ --- @field item_output table<string, ItemStats>
17
+ --- @field fluid_input table<string, ItemStats>
18
+ --- @field fluid_output table<string, ItemStats>
19
+ --- @field kill_input table<string, ItemStats>
20
+ --- @field kill_output table<string, ItemStats>
21
+ --- @field build_input table<string, ItemStats>
22
+ --- @field build_output table<string, ItemStats>
23
+ local stats = {
24
+ item_input = {},
25
+ item_output = {},
26
+ fluid_input = {},
27
+ fluid_output = {},
28
+ kill_input = {},
29
+ kill_output = {},
30
+ build_input = {},
31
+ build_output = {},
32
+ }
33
+
34
+ for name, count in pairs(force.get_item_production_statistics(surface).input_counts) do
35
+ local itemstats = stats.item_input[name] or {}
36
+ itemstats.count = count
37
+ stats.item_input[name] = itemstats
38
+ end
39
+
40
+ for name, count in pairs(force.get_item_production_statistics(surface).output_counts) do
41
+ local itemstats = stats.item_output[name] or {}
42
+ itemstats.count = count
43
+ stats.item_output[name] = itemstats
44
+ end
45
+
46
+ for name, count in pairs(force.get_fluid_production_statistics(surface).input_counts) do
47
+ local fluidstats = stats.fluid_input[name] or {}
48
+ fluidstats.count = count
49
+ stats.fluid_input[name] = fluidstats
50
+ end
51
+
52
+ for name, count in pairs(force.get_fluid_production_statistics(surface).output_counts) do
53
+ local fluidstats = stats.fluid_output[name] or {}
54
+ fluidstats.count = count
55
+ stats.fluid_output[name] = fluidstats
56
+ end
57
+
58
+ for name, count in pairs(force.get_kill_count_statistics(surface).input_counts) do
59
+ local killstats = stats.kill_input[name] or {}
60
+ killstats.count = count
61
+ stats.kill_input[name] = killstats
62
+ end
63
+
64
+ for name, count in pairs(force.get_kill_count_statistics(surface).output_counts) do
65
+ local killstats = stats.kill_output[name] or {}
66
+ killstats.count = count
67
+ stats.kill_output[name] = killstats
68
+ end
69
+
70
+ for name, count in pairs(force.get_entity_build_count_statistics(surface).input_counts) do
71
+ local buildstats = stats.build_input[name] or {}
72
+ buildstats.count = count
73
+ stats.build_input[name] = buildstats
74
+ end
75
+
76
+ for name, count in pairs(force.get_entity_build_count_statistics(surface).output_counts) do
77
+ local buildstats = stats.build_output[name] or {}
78
+ buildstats.count = count
79
+ stats.build_output[name] = buildstats
80
+ end
81
+
82
+ general.data.output[force.name].production[surface.name] = stats
83
+ end
84
+ end
85
+ end
86
+
87
+ lib.collect_loginet = function()
88
+ for _, force in pairs(game.forces) do
89
+ --- @class RobotStatistics
90
+ --- @field all_construction_robots uint
91
+ --- @field available_construction_robot uint
92
+ --- @field all_logistic_robots uint
93
+ --- @field available_logistic_robots uint
94
+ --- @field charging_robot_count uint
95
+ --- @field to_charge_robot_count uint
96
+ --- @field items table<string, uint>
97
+ --- @field pickups table<string, uint>
98
+ --- @field deliveries table<string, uint>
99
+ local stats = {
100
+ all_construction_robots = 0,
101
+ available_construction_robots = 0,
102
+
103
+ all_logistic_robots = 0,
104
+ available_logistic_robots = 0,
105
+
106
+ charging_robot_count = 0,
107
+ to_charge_robot_count = 0,
108
+
109
+ items = {},
110
+ pickups = {},
111
+ deliveries = {},
112
+ }
113
+ for _, networks in pairs(force.logistic_networks) do
114
+ for _, network in pairs(networks) do
115
+ stats.available_construction_robots = network.available_construction_robots
116
+ stats.all_construction_robots = network.all_construction_robots
117
+
118
+ stats.available_logistic_robots = network.available_logistic_robots
119
+ stats.all_logistic_robots = network.all_logistic_robots
120
+
121
+ stats.charging_robot_count = 0
122
+ stats.to_charge_robot_count = 0
123
+ for _, cell in pairs(network.cells) do
124
+ stats.charging_robot_count = (stats.charging_robot_count) + cell.charging_robot_count
125
+ stats.to_charge_robot_count = (stats.to_charge_robot_count) + cell.to_charge_robot_count
126
+ end
127
+
128
+ if config.modules.logistorage then
129
+ for _, item in pairs(network.get_contents()) do
130
+ stats.items[item.name] = (stats.items[item.name] or 0) + item.count
131
+ end
132
+
133
+ -- pickups and deliveries of items
134
+ for _, point_list in pairs{ network.provider_points, network.requester_points, network.storage_points } do
135
+ for _, point in pairs(point_list) do
136
+ for _, item in pairs(point.targeted_items_pickup) do
137
+ stats.pickups[item.name] = (stats.pickups[item.name] or 0) + item.count
138
+ end
139
+
140
+ for _, item in pairs(point.targeted_items_deliver) do
141
+ stats.deliveries[item.name] = (stats.deliveries[item.name] or 0) + item.count
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ general.data.output[force.name].robots = stats
150
+ end
151
+ end
152
+
153
+ --- @class Research
154
+ --- @field name string
155
+ --- @field level uint
156
+ --- @field progress double
157
+
158
+ Event.add(defines.events.on_research_finished, function(evt)
159
+ local research = evt.research
160
+ if not general.data.output[research.force.name] then general.data.output[research.force.name] = {} end
161
+ if not general.data.output[research.force.name].research then general.data.output[research.force.name].research = {} end
162
+
163
+ local force_research = general.data.output[research.force.name].research or {}
164
+ table.remove(force_research, 1)
165
+ general.data.output[research.force.name].research = force_research
166
+ end)
167
+
168
+ Event.add(defines.events.on_research_started, function(evt)
169
+ -- move queue up
170
+ local research = evt.research
171
+ if not general.data.output[research.force.name].research then general.data.output[research.force.name].research = {} end
172
+
173
+ local force_research = general.data.output[research.force.name].research or {}
174
+ table.remove(force_research, 1)
175
+ general.data.output[research.force.name].research = force_research
176
+ end)
177
+
178
+ Event.on_nth_tick(60, function()
179
+ for _, force in pairs(game.forces) do
180
+ if not general.data.output[force.name].research then general.data.output[force.name].research = {} end
181
+
182
+ local force_research = {}
183
+ -- this works even if the queue is disabled, but it will always be just 1 long in that case
184
+ for _, research in pairs(force.research_queue) do
185
+ table.insert(force_research, {
186
+ name = research.name,
187
+ level = research.level,
188
+ progress = force.technologies[research.name].saved_progress
189
+ })
190
+ end
191
+
192
+ general.data.output[force.name].research = force_research
193
+ end
194
+ end)
195
+
196
+ return lib
@@ -0,0 +1,63 @@
1
+ local Event = require("modules/exp_legacy/utils/event")
2
+ local Storage = require("modules/exp_util/storage")
3
+
4
+ local lib = {}
5
+
6
+ lib.data = {
7
+ output = {},
8
+ }
9
+
10
+ Storage.register(lib.data, function(tbl)
11
+ lib.data = tbl
12
+ end)
13
+
14
+ --- @class Statistics
15
+ --- @field production ProductionStatistics?
16
+ --- @field robots RobotStatistics?
17
+ --- @field other OtherStatistics?
18
+ --- @field research Research[]?
19
+
20
+ Event.on_init(function()
21
+ --- @type table<string, Statistics>
22
+ lib.data.output = {}
23
+ for _, force in pairs(game.forces) do
24
+ lib.data.output[force.name] = {}
25
+ end
26
+ end)
27
+
28
+ --- @class OtherStatistics
29
+ --- @field tick uint
30
+ --- @field evolution EvolutionStatistics
31
+
32
+ --- @class EvolutionStatistics
33
+ --- @field evolution_factor double
34
+ --- @field evolution_factor_by_pollution double
35
+ --- @field evolution_factor_by_time double
36
+ --- @field evolution_factor_by_killing_spawners double
37
+
38
+ lib.collect_other = function()
39
+ for _, force in pairs(game.forces) do
40
+ --- @type OtherStatistics
41
+ local other = lib.data.output[force.name].other or {}
42
+
43
+ other.evolution = {
44
+ evolution_factor = force.get_evolution_factor(game.surfaces[1]),
45
+ evolution_factor_by_pollution = force.get_evolution_factor_by_pollution(game.surfaces[1]),
46
+ evolution_factor_by_time = force.get_evolution_factor_by_time(game.surfaces[1]),
47
+ evolution_factor_by_killing_spawners = force.get_evolution_factor_by_killing_spawners(game.surfaces[1]),
48
+ }
49
+ for k, v in pairs(other) do
50
+ lib.data.output[force.name].other[k] = v
51
+ end
52
+ end
53
+ end
54
+
55
+ Event.add(defines.events.on_force_created, function(evt)
56
+ lib.data.output[evt.force.name] = {}
57
+ end)
58
+
59
+ Event.add(defines.events.on_forces_merged, function(evt)
60
+ lib.data.output[evt.source_name] = nil
61
+ end)
62
+
63
+ return lib
@@ -0,0 +1,28 @@
1
+ local Commands = require("modules/exp_commands")
2
+ local config = require("modules.exp_legacy.config.graftorio")
3
+ local statics = require("modules.exp_legacy.modules.graftorio.statics")
4
+ local general = require("modules.exp_legacy.modules.graftorio.general")
5
+ local forcestats = nil
6
+
7
+ local table_to_json = helpers.table_to_json
8
+
9
+ if config.modules.forcestats then
10
+ forcestats = require("modules.exp_legacy.modules.graftorio.forcestats")
11
+ end
12
+
13
+ Commands.new("collectdata", "Collect data for RCON usage")
14
+ :optional("location", "", Commands.types.string) -- Not sure what this is for, i didn't write this
15
+ :register(function()
16
+ -- this must be first as it overwrites the stats
17
+ -- also makes the .other table for all forces
18
+ statics.collect_statics()
19
+ if config.modules.other then
20
+ general.collect_other()
21
+ end
22
+ if config.modules.forcestats then
23
+ --- @cast forcestats -nil
24
+ forcestats.collect_production()
25
+ forcestats.collect_loginet()
26
+ end
27
+ return Commands.status.success(table_to_json(general.data.output))
28
+ end)
@@ -0,0 +1,36 @@
1
+ local general = require("modules.exp_legacy.modules.graftorio.general")
2
+
3
+ local lib = {}
4
+
5
+ --- @class StaticStatistics
6
+ --- @field tick uint
7
+ --- @field online_players string[]
8
+ --- @field mods table<string, string>
9
+ --- @field seed table<string, uint>
10
+
11
+ lib.collect_statics = function()
12
+ local stats = {}
13
+ stats.tick = game.tick
14
+
15
+ stats.online_players = {}
16
+ for _, player in pairs(game.connected_players) do
17
+ table.insert(stats.online_players, player.name)
18
+ end
19
+
20
+ stats.mods = {}
21
+ for name, version in pairs(script.active_mods) do
22
+ stats.mods[name] = version
23
+ end
24
+
25
+ -- reason behind this is that the map gen settings can be changed during runtime so just get them fresh
26
+ stats.seed = {}
27
+ for _, surface in pairs(game.surfaces) do
28
+ stats.seed[surface.name] = surface.map_gen_settings.seed
29
+ end
30
+
31
+ for _, force in pairs(game.forces) do
32
+ general.data.output[force.name].other = stats
33
+ end
34
+ end
35
+
36
+ return lib