Skip to content

Commit ca6a379

Browse files
committed
changed module inserter item to selection tool (MP/Player afk safe)
fixed data not being cleaned up when ghost timed out
1 parent 41b03fc commit ca6a379

3 files changed

Lines changed: 114 additions & 176 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
PACKAGE_NAME := ModuleInserter
2-
VERSION_STRING := 0.1.35
2+
VERSION_STRING := 0.1.4
33

44
OUTPUT_NAME := $(PACKAGE_NAME)_$(VERSION_STRING)
55
OUTPUT_DIR := build/$(OUTPUT_NAME)

control.lua

Lines changed: 85 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
if not defines then
2-
require "defines"
3-
end
41
require "util"
52

63
MAX_CONFIG_SIZE = 6
@@ -60,12 +57,13 @@ end
6057
function on_tick(event)
6158
if global.removeTicks[event.tick] then
6259
local status, err = pcall(function()
63-
for _, g in pairs(global.removeTicks[event.tick]) do
60+
for key, g in pairs(global.removeTicks[event.tick]) do
6461
if not g.g.valid then
6562
if g.p.get_item_count("module-inserter-proxy") > 0 then
6663
g.p.remove_item{name="module-inserter-proxy", count = 1}
6764
end
68-
global.entitiesToInsert[g.key] = nil
65+
global.entitiesToInsert[key] = nil
66+
global.removeTicks[event.tick][key] = nil
6967
end
7068
end
7169
if count_keys(global.removeTicks[event.tick]) == 0 then
@@ -81,9 +79,9 @@ function on_tick(event)
8179
end
8280
end
8381

84-
function add_ghost(key, data)
85-
global.removeTicks[key] = global.removeTicks[key] or {}
86-
global.removeTicks[key][key] = data
82+
function add_ghost(key, data, tick)
83+
global.removeTicks[tick] = global.removeTicks[tick] or {}
84+
global.removeTicks[tick][key] = data
8785
script.on_event(defines.events.on_tick, on_tick)
8886
end
8987

@@ -106,152 +104,103 @@ function remove_ghost(key)
106104
end
107105
end
108106

109-
script.on_event(defines.events.on_marked_for_deconstruction, function(event)
107+
script.on_event({defines.events.on_player_selected_area,defines.events.on_player_alt_selected_area}, function(event)
108+
--log(serpent.block(event, {comment=false}))
110109
local status, err = pcall(function()
111-
local entity = event.entity
112-
local deconstruction = false
113-
local filtered_deconstruction = false
114-
local upgrade = false
115-
local module_inserter = false
116-
local player = nil
117-
-- Determine which player used upgrade planner.
118-
-- If more than one player has upgrade planner in their hand or one
119-
-- player has a upgrade planner and other has deconstruction planner,
120-
-- we can't determine it, so we have to discard deconstruction order.
121-
for _, p in pairs(game.players) do
122-
if p.connected then
123-
local stack = p.cursor_stack
124-
if stack and stack.valid_for_read then
125-
if stack.name == "upgrade-planner" then
126-
if upgrade or deconstruction or module_inserter or filtered_deconstruction then
127-
--debugDump("Upgrade planner used", true)
128-
return
129-
end
130-
upgrade = true
131-
elseif stack.name == "deconstruction-planner" then
132-
if upgrade or module_inserter or filtered_deconstruction then
133-
--debugDump("Deconstruction/Module planner used", true)
134-
return
135-
end
136-
deconstruction = true
137-
elseif stack.name == "filtered-deconstruction-planner" then
138-
if upgrade or module_inserter or deconstruction then
139-
return
140-
end
141-
filtered_deconstruction = true
142-
elseif stack.name == "module-inserter" then
143-
if upgrade or deconstruction or filtered_deconstruction then
144-
--debugDump("Deconstruction/Upgrade planner used", true)
145-
return
146-
end
147-
player = p
148-
module_inserter = true
149-
end
150-
end
151-
end
152-
end
153-
154-
if not player then
155-
return
156-
end
157-
110+
if not event.player_index then return end
111+
local player = game.players[event.player_index]
158112
if not global["config"][player.index] then
159113

160114
-- Config for this player does not exist yet, so we have nothing to do.
161115
-- We can create it now for later usage.
162116
global["config"][player.index] = {}
163-
entity.cancel_deconstruction(entity.force)
164117
return
165118
end
166119

167120
local config = global["config"][player.index]
168121

169-
-- Check if entity is valid and stored in config as a source.
170-
local index = 0
171-
for i = 1, #config do
172-
if config[i].from == entity.name then
173-
index = i
174-
break
122+
for _, entity in pairs(event.entities) do
123+
124+
-- Check if entity is valid and stored in config as a source.
125+
local index
126+
for i = 1, #config do
127+
if config[i].from == entity.name then
128+
index = i
129+
break
130+
end
175131
end
176-
end
177-
if index == 0 then
178-
entity.cancel_deconstruction(entity.force)
179-
return
180-
end
181132

182-
local proxy = {name="module-inserter-proxy", count=1}
133+
local proxy = {name="module-inserter-proxy", count=1}
183134

184-
local can_insert_main = player.get_inventory(defines.inventory.player_main).can_insert(proxy)
185-
local can_insert_quick = player.get_inventory(defines.inventory.player_quickbar).can_insert(proxy)
135+
local can_insert_main = player.get_inventory(defines.inventory.player_main).can_insert(proxy)
136+
local can_insert_quick = player.get_inventory(defines.inventory.player_quickbar).can_insert(proxy)
186137

187-
if can_insert_main or can_insert_quick then
188-
if entity.type == "assembling-machine" and not entity.recipe then
189-
player.print("Can't insert modules in assembler without recipe")
190-
entity.cancel_deconstruction(entity.force)
191-
return
192-
end
193-
local modules = util.table.deepcopy(config[index].to)
194-
local cTable = {}
195-
for i, module in pairs(modules) do
196-
if module then
197-
if not cTable[module] then
198-
cTable[module] = 1
199-
else
200-
cTable[module] = cTable[module] + 1
201-
end
202-
end
203-
local prototype = game.item_prototypes[module]
204-
if module and prototype.module_effects and prototype.module_effects["productivity"] then
205-
if prototype.module_effects["productivity"] ~= 0 then
206-
if entity.type == "beacon" then
207-
player.print("Can't insert "..module.." in "..entity.name)
208-
entity.cancel_deconstruction(entity.force)
209-
return
138+
if index and (can_insert_main or can_insert_quick) then
139+
if entity.type == "assembling-machine" and not entity.recipe then
140+
player.print("Can't insert modules in assembler without recipe")
141+
else
142+
local modules = util.table.deepcopy(config[index].to)
143+
local cTable = {}
144+
local valid_modules = true
145+
for i, module in pairs(modules) do
146+
if module then
147+
if not cTable[module] then
148+
cTable[module] = 1
149+
else
150+
cTable[module] = cTable[module] + 1
151+
end
210152
end
211-
if global.productivityAllowed and entity.type == "assembling-machine" then
212-
if entity.recipe and not global.productivityAllowed[entity.recipe.name] == true then
213-
player.print("Can't use "..module.." with recipe: " .. entity.recipe.name)
214-
entity.cancel_deconstruction(entity.force)
215-
return
153+
local prototype = game.item_prototypes[module]
154+
if module and prototype.module_effects and prototype.module_effects["productivity"] then
155+
if prototype.module_effects["productivity"] ~= 0 then
156+
if entity.type == "beacon" then
157+
player.print("Can't insert "..module.." in "..entity.name)
158+
valid_modules = false
159+
end
160+
if global.productivityAllowed and entity.type == "assembling-machine" then
161+
if entity.recipe and not global.productivityAllowed[entity.recipe.name] == true then
162+
player.print("Can't use "..module.." with recipe: " .. entity.recipe.name)
163+
valid_modules = false
164+
end
165+
end
216166
end
217167
end
218168
end
219-
end
220-
end
221-
local inventory = entity.get_inventory(typeToSlot[entity.type])
222-
local contents = inventory.get_contents()
223-
if not util.table.compare(cTable,contents) then
224-
-- proxy entity that the robots fly to
225-
local new_entity = {
226-
name = "entity-ghost",
227-
inner_name = "module-inserter-proxy",
228-
position = entity.position,
229-
direction = entity.direction,
230-
force = entity.force
231-
}
232-
233-
local key = entityKey(new_entity)
234-
if global.entitiesToInsert[key] then
235-
global.entitiesToInsert[key] = nil
236-
if player.get_item_count("module-inserter-proxy") > 0 then
237-
player.remove_item(proxy)
238-
end
239-
remove_ghost(key)
240-
end
241-
if not global.entitiesToInsert[key] then -- or (global.entitiesToInsert[key].ghost and not global.entitiesToInsert[key].ghost.valid) then
242-
local ghost = entity.surface.create_entity(new_entity)
243-
global.entitiesToInsert[key] = {entity = entity, player = player, modules = modules, ghost = ghost}
244-
--ghost.time_to_live = 60*30
245-
add_ghost(key, {p=player,g=ghost})
246-
if can_insert_main then
247-
player.get_inventory(defines.inventory.player_main).insert(proxy)
248-
elseif can_insert_quick then
249-
player.get_inventory(defines.inventory.player_quickbar).insert(proxy)
169+
local inventory = entity.get_inventory(typeToSlot[entity.type])
170+
local contents = inventory.get_contents()
171+
if valid_modules and not util.table.compare(cTable,contents) then
172+
-- proxy entity that the robots fly to
173+
local new_entity = {
174+
name = "entity-ghost",
175+
inner_name = "module-inserter-proxy",
176+
position = entity.position,
177+
direction = entity.direction,
178+
force = entity.force
179+
}
180+
181+
local key = entityKey(new_entity)
182+
if global.entitiesToInsert[key] then
183+
global.entitiesToInsert[key] = nil
184+
if player.get_item_count("module-inserter-proxy") > 0 then
185+
player.remove_item(proxy)
186+
end
187+
remove_ghost(key)
188+
end
189+
if not global.entitiesToInsert[key] then -- or (global.entitiesToInsert[key].ghost and not global.entitiesToInsert[key].ghost.valid) then
190+
local ghost = entity.surface.create_entity(new_entity)
191+
global.entitiesToInsert[key] = {entity = entity, player = player, modules = modules, ghost = ghost}
192+
ghost.time_to_live = 60*30
193+
add_ghost(key, {p=player,g=ghost}, game.tick + ghost.time_to_live + 1)
194+
if can_insert_main then
195+
player.get_inventory(defines.inventory.player_main).insert(proxy)
196+
elseif can_insert_quick then
197+
player.get_inventory(defines.inventory.player_quickbar).insert(proxy)
198+
end
199+
end
250200
end
251201
end
252202
end
253203
end
254-
entity.cancel_deconstruction(entity.force)
255204
end)
256205
if not status then
257206
debugDump(err, true)
@@ -435,6 +384,11 @@ local function on_configuration_changed(data)
435384
end
436385
cleanup(true)
437386
end
387+
if oldVersion < "0.1.4" then
388+
global.entitiesToInsert = {}
389+
global.removeTicks = {}
390+
on_load()
391+
end
438392
global.version = newVersion
439393
--mod was updated
440394
-- update/change gui for all players via game.players.gui ?
@@ -463,33 +417,6 @@ script.on_event(defines.events.on_player_created, on_player_created)
463417
script.on_event(defines.events.on_force_created, on_force_created)
464418
script.on_event(defines.events.on_forces_merging, on_forces_merging)
465419

466-
local function on_player_inactive(event)
467-
local drop_items = {["upgrade-planner"]=true, ["deconstruction-planner"]=true,["filtered-deconstruction-planner"]=true,["module-inserter"]=true}
468-
469-
local p = game.players[event.player_index]
470-
local stack = p.cursor_stack.valid_for_read and p.cursor_stack or false
471-
472-
--inactive player is holding an item
473-
if stack and drop_items[stack.name] then
474-
local can_insert_main = p.get_inventory(defines.inventory.player_main).can_insert(stack)
475-
local can_insert_quick = p.get_inventory(defines.inventory.player_quickbar).can_insert(stack)
476-
local inventory
477-
if can_insert_quick then
478-
inventory = p.get_inventory(defines.inventory.player_quickbar)
479-
elseif can_insert_main then
480-
inventory = p.get_inventory(defines.inventory.player_main)
481-
end
482-
if inventory then
483-
inventory.insert(stack)
484-
p.cursor_stack.clear()
485-
end
486-
end
487-
end
488-
489-
if remote.interfaces.EventsPlus then
490-
script.on_event(remote.call("EventsPlus", "getEvent", "on_player_inactive"), on_player_inactive)
491-
end
492-
493420
function get_config_item(player, index, type1)
494421
if not global["config-tmp"][player.index]
495422
or index > #global["config-tmp"][player.index]

prototypes/item.lua

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
1-
local mi_planner = copyPrototype("deconstruction-item", "deconstruction-planner", "module-inserter")
2-
mi_planner.order = "c[automated-construction]-d[module-inserter]"
3-
mi_planner.icon = "__ModuleInserter__/graphics/module-inserter-icon.png"
4-
5-
6-
local mi_proxy = copyPrototype("container","wooden-chest","module-inserter-proxy")
7-
mi_proxy.icon = "__ModuleInserter__/graphics/module-inserter-icon.png"
8-
table.insert(mi_proxy.flags, "placeable-off-grid")
9-
mi_proxy.collision_box = {{-0.1,-0.1},{0.1,0.1}}
10-
mi_proxy.collision_mask = {"doodad-layer", "not-colliding-with-itself"}
11-
12-
local mi_proxy_i = copyPrototype("item","wooden-chest","module-inserter-proxy")
13-
table.insert(mi_proxy_i.flags, "hidden")
14-
mi_proxy_i.icon = "__ModuleInserter__/graphics/module-inserter-icon.png"
15-
mi_proxy_i.stack_size = 1000
16-
17-
data:extend({mi_planner,mi_proxy, mi_proxy_i,})
1+
local mi_planner = {
2+
type = "selection-tool",
3+
name = "module-inserter",
4+
icon = "__ModuleInserter__/graphics/module-inserter-icon.png",
5+
flags = {"goes-to-quickbar"},
6+
subgroup = "tool",
7+
order = "c[automated-construction]-d[module-inserter]",
8+
stack_size = 1,
9+
selection_color = { r = 0, g = 1, b = 0 },
10+
alt_selection_color = { r = 0, g = 0, b = 1 },
11+
selection_mode = {"matches-force", "buildable-type"},
12+
alt_selection_mode = {"matches-force", "buildable-type"},
13+
selection_cursor_box_type = "copy",
14+
alt_selection_cursor_box_type = "copy"
15+
}
16+
17+
local mi_proxy = copyPrototype("container","wooden-chest","module-inserter-proxy")
18+
mi_proxy.icon = "__ModuleInserter__/graphics/module-inserter-icon.png"
19+
table.insert(mi_proxy.flags, "placeable-off-grid")
20+
mi_proxy.collision_box = {{-0.1,-0.1},{0.1,0.1}}
21+
mi_proxy.collision_mask = {"doodad-layer", "not-colliding-with-itself"}
22+
23+
local mi_proxy_i = copyPrototype("item","wooden-chest","module-inserter-proxy")
24+
table.insert(mi_proxy_i.flags, "hidden")
25+
mi_proxy_i.icon = "__ModuleInserter__/graphics/module-inserter-icon.png"
26+
mi_proxy_i.stack_size = 1000
27+
28+
data:extend({mi_planner,mi_proxy, mi_proxy_i,})

0 commit comments

Comments
 (0)