-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathinventory-filters.lua
288 lines (256 loc) · 7.69 KB
/
inventory-filters.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
local gui = require("__flib__.gui")
local migration = require("__flib__.migration")
local util = require("scripts.util")
local filters_table_version = 0
local filters_table_migrations = {}
--- @param player LuaPlayer
--- @param string string
local function import_filters(player, string)
if string == "" then
return
end
local decoded_string = helpers.decode_string(string)
if
decoded_string
and string.sub(decoded_string, 1, 16) == "EditorExtensions"
and string.sub(decoded_string, 18, 34) == "inventory_filters"
then
-- Extract version for migrations
local version, json = string.match(decoded_string, "^.-%-.-%-(%d-)%-(.*)$")
local input = helpers.json_to_table(json)
if input then
-- Run migrations
migration.run(version, filters_table_migrations, nil, input)
-- Sanitize the filters to only include currently existing prototypes
local item_prototypes = prototypes.item
local output = {}
local i = 0
local filters = input.filters
for _, filter in pairs(filters) do
if item_prototypes[filter.name] then
i = i + 1
filter.index = i
output[i] = filter
end
end
player.infinity_inventory_filters = output
player.remove_unfiltered_items = input.remove_unfiltered_items
return true
end
end
return false
end
--- @param player LuaPlayer
--- @return string?
local function export_filters(player)
local filters = player.infinity_inventory_filters
local output = {
filters = filters,
remove_unfiltered_items = player.remove_unfiltered_items,
}
return helpers.encode_string(
"EditorExtensions-inventory_filters-" .. filters_table_version .. "-" .. helpers.table_to_json(output)
)
end
-- String GUI
--- @param player LuaPlayer
--- @return boolean
local function destroy_string_gui(player)
local window = player.gui.screen.ee_inventory_filters
if not window or not window.valid then
return false
end
window.destroy()
return true
end
--- @param e EventData.on_gui_click
local function on_string_gui_import_click(e)
local player = game.get_player(e.player_index)
if not player then
return
end
local string = e.element.parent.parent.textbox.text
if import_filters(player, string) then
destroy_string_gui(player)
util.flying_text(player, { "message.ee-imported-infinity-filters" })
else
util.flying_text(player, { "message.ee-invalid-infinity-filters-string" }, true)
end
end
--- @param e EventData.on_gui_click
local function on_string_gui_cancel_click(e)
local player = game.get_player(e.player_index)
if not player then
return
end
destroy_string_gui(player)
-- Keep controller GUI open
player.opened = defines.gui_type.controller
end
--- @param player LuaPlayer
--- @param mode string
local function build_string_gui(player, mode)
destroy_string_gui(player)
local elems = gui.add(player.gui.screen, {
type = "frame",
name = "ee_inventory_filters",
direction = "vertical",
caption = { "gui.ee-" .. mode .. "-infinity-filters" },
elem_mods = { auto_center = true },
{
type = "text-box",
name = "textbox",
style_mods = { width = 400, height = 300 },
clear_and_focus_on_right_click = true,
text = mode == "import" and "" or export_filters(player),
elem_mods = { word_wrap = true },
},
{
type = "flow",
style = "dialog_buttons_horizontal_flow",
drag_target = "ee_inventory_filters",
{
type = "button",
style = "back_button",
caption = { "gui.cancel" },
handler = on_string_gui_cancel_click,
},
{
type = "empty-widget",
style = "flib_dialog_footer_drag_handle",
style_mods = mode == "export" and { right_margin = 0 } or nil,
ignored_by_interaction = true,
},
{
type = "button",
style = "confirm_button",
caption = { "gui.confirm" },
visible = mode == "import",
handler = on_string_gui_import_click,
},
},
})
elems.textbox.select_all()
elems.textbox.focus()
end
-- Relative GUI
--- @param player LuaPlayer
local function destroy_relative_gui(player)
local window = player.gui.relative.ee_inventory_filters
if window and window.valid then
window.destroy()
end
end
--- @param e EventData.on_gui_click
local function on_relative_gui_button_click(e)
local player = game.get_player(e.player_index)
if not player then
return
end
local mode = e.element.name
build_string_gui(player, mode)
end
--- @param player LuaPlayer
local function build_relative_gui(player)
destroy_relative_gui(player)
gui.add(player.gui.relative, {
type = "frame",
name = "ee_inventory_filters",
style = "slot_window_frame",
anchor = {
gui = defines.relative_gui_type.controller_gui,
position = defines.relative_gui_position.left,
name = "editor",
},
{
type = "frame",
style = "shortcut_bar_inner_panel",
direction = "vertical",
{
type = "sprite-button",
name = "import",
style = "shortcut_bar_button",
sprite = "ee_import_inventory_filters",
tooltip = { "gui.ee-import-infinity-filters" },
handler = on_relative_gui_button_click,
},
{
type = "sprite-button",
name = "export",
style = "shortcut_bar_button",
sprite = "ee_export_inventory_filters",
tooltip = { "gui.ee-export-infinity-filters" },
handler = on_relative_gui_button_click,
},
},
})
end
--- @param e EventData.on_gui_closed
local function on_gui_closed(e)
if e.gui_type ~= defines.gui_type.controller then
return
end
local player = game.get_player(e.player_index)
if not player then
return
end
if destroy_string_gui(player) then
player.opened = defines.gui_type.controller
end
end
--- @param e EventData.on_player_toggled_map_editor
local function on_player_toggled_map_editor(e)
local player = game.get_player(e.player_index)
if not player then
return
end
local in_editor = player.controller_type == defines.controllers.editor
if not in_editor or storage.applied_default_filters[e.player_index] then
return
end
-- Apply default infinity filters if this is their first time in the editor
storage.applied_default_filters[e.player_index] = true
local default_filters = player.mod_settings["ee-default-infinity-filters"].value --[[@as string]]
if default_filters == "" then
return
end
import_filters(player, default_filters)
end
--- @param e EventData.on_player_created
local function on_player_created(e)
local player = game.get_player(e.player_index)
if not player then
return
end
build_relative_gui(player)
end
--- @param e EventData.on_player_removed
local function on_player_removed(e)
if storage.applied_default_filters then
storage.applied_default_filters[e.player_index] = nil
end
end
local inventory_filters = {}
inventory_filters.on_init = function()
--- @type table<uint, boolean>
storage.applied_default_filters = {}
end
inventory_filters.on_configuration_changed = function()
for _, player in pairs(game.players) do
destroy_string_gui(player)
build_relative_gui(player)
end
end
inventory_filters.events = {
[defines.events.on_gui_closed] = on_gui_closed,
[defines.events.on_player_created] = on_player_created,
[defines.events.on_player_removed] = on_player_removed,
[defines.events.on_player_toggled_map_editor] = on_player_toggled_map_editor,
}
gui.add_handlers({
destroy_string_gui = destroy_string_gui,
on_relative_gui_button_click = on_relative_gui_button_click,
on_string_gui_cancel_click = on_string_gui_cancel_click,
on_string_gui_import_click = on_string_gui_import_click,
})
return inventory_filters