Skip to content

Commit d2959f2

Browse files
authored
1.5.1
- improved performance by 8% for 120 Sensors - bumped required Factorio version to current stable - moved config.lua settings to mod settings
1 parent ce95ad8 commit d2959f2

File tree

6 files changed

+209
-75
lines changed

6 files changed

+209
-75
lines changed

changelog.txt

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
1.5.1
2+
- improved performance by 8% for 120 Sensors
3+
4+
1.5.0
5+
- bumped required Factorio version to current stable
6+
- moved config.lua settings to mod settings
7+
8+
1.4.12
9+
- fixed ambigous config variables
10+
111
1.4.11
212
- deconstruction triggers only if sensors exist
313

control.lua

+150-70
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
require "config"
2-
31
-- constant prototypes names
42
local SENSOR = "item-sensor"
53

@@ -33,106 +31,157 @@ local floor = math.floor
3331
local ceil = math.ceil
3432

3533

36-
---- Events ----
37-
38-
function init_events()
39-
script.on_event({defines.events.on_built_entity, defines.events.on_robot_built_entity}, OnEntityCreated)
40-
if global.ItemSensors and #global.ItemSensors > 0 then
41-
script.on_event(defines.events.on_tick, OnTick)
42-
script.on_event({defines.events.on_preplayer_mined_item, defines.events.on_robot_pre_mined, defines.events.on_entity_died}, OnEntityRemoved)
43-
end
44-
end
45-
46-
script.on_init(function()
47-
global.ItemSensors = global.ItemSensors or {}
48-
init_events()
34+
---- MOD SETTINGS ----
35+
36+
local UpdateInterval = settings.global["inv_sensor_update_interval"].value
37+
local ScanInterval = settings.global["inv_sensor_find_entity_interval"].value
38+
local ScanOffset = settings.global["inv_sensor_BBox_offset"].value
39+
local ScanRange = settings.global["inv_sensor_BBox_range"].value
40+
41+
script.on_event(defines.events.on_runtime_mod_setting_changed, function(event)
42+
if event.setting == "inv_sensor_update_interval" then
43+
UpdateInterval = settings.global["inv_sensor_update_interval"].value
44+
ResetStride()
45+
end
46+
if event.setting == "inv_sensor_find_entity_interval" then
47+
ScanInterval = settings.global["inv_sensor_find_entity_interval"].value
48+
end
49+
if event.setting == "inv_sensor_BBox_offset" then
50+
ScanOffset = settings.global["inv_sensor_BBox_offset"].value
51+
ResetSensors()
52+
end
53+
if event.setting == "inv_sensor_BBox_range" then
54+
ScanRange = settings.global["inv_sensor_BBox_range"].value
55+
ResetSensors()
56+
end
4957
end)
5058

51-
script.on_load(function()
52-
init_events()
53-
end)
5459

55-
script.on_configuration_changed(function(data)
56-
global.ItemSensors = global.ItemSensors or {}
57-
for i=1, #global.ItemSensors do
58-
local itemSensor = global.ItemSensors[i]
59-
itemSensor.ID = itemSensor.Sensor.unit_number
60-
itemSensor.ScanArea = GetScanArea(itemSensor.Sensor)
61-
itemSensor.ConnectedEntity = nil
62-
itemSensor.Inventory = {}
63-
SetConnectedEntity(itemSensor)
64-
end
65-
init_events()
66-
end)
60+
---- EVENTS ----
6761

6862
function OnEntityCreated(event)
6963
if (event.created_entity.name == "item-sensor") then
70-
CreateItemSensor(event.created_entity)
64+
local entity = event.created_entity
65+
global.ItemSensors = global.ItemSensors or {}
66+
67+
entity.operable = false
68+
entity.rotatable = false
69+
local itemSensor = {}
70+
itemSensor.ID = entity.unit_number
71+
itemSensor.Sensor = entity
72+
itemSensor.ScanArea = GetScanArea(entity)
73+
SetConnectedEntity(itemSensor)
74+
75+
global.ItemSensors[#global.ItemSensors+1] = itemSensor
76+
7177
if #global.ItemSensors == 1 then
7278
script.on_event(defines.events.on_tick, OnTick)
7379
script.on_event({defines.events.on_preplayer_mined_item, defines.events.on_robot_pre_mined, defines.events.on_entity_died}, OnEntityRemoved)
7480
end
81+
82+
ResetStride()
7583
end
7684
end
7785

7886
function OnEntityRemoved(event)
7987
-- script.on_event({defines.events.on_preplayer_mined_item, defines.events.on_robot_pre_mined, defines.events.on_entity_died}, function(event)
8088
if event.entity.name == SENSOR then
81-
RemoveItemSensor(event.entity)
89+
for i=#global.ItemSensors, 1, -1 do
90+
if event.entity.unit_number == global.ItemSensors[i].ID then
91+
table.remove(global.ItemSensors,i)
92+
end
93+
end
94+
8295
if #global.ItemSensors == 0 then
8396
script.on_event(defines.events.on_tick, nil)
8497
script.on_event({defines.events.on_preplayer_mined_item, defines.events.on_robot_pre_mined, defines.events.on_entity_died}, nil)
8598
end
99+
100+
ResetStride()
86101
end
87102
end
88103

104+
89105
function OnTick(event)
90-
local tick = game.tick
91-
for i=1, #global.ItemSensors do
92-
local itemSensor = global.ItemSensors[i]
93-
if not itemSensor.SkipEntityScanning and (i + tick) % find_entity_interval == 0 then
94-
SetConnectedEntity(itemSensor)
95-
end
96-
if (i + tick) % update_interval == 0 then
97-
UpdateSensor(itemSensor)
98-
end
99-
end
106+
global.tickCount = global.tickCount or 1
107+
global.SensorIndex = global.SensorIndex or 1
108+
109+
-- only work if index is within bounds
110+
if global.SensorIndex <= #global.ItemSensors then
111+
local lastIndex = global.SensorIndex + global.SensorStride - 1
112+
if lastIndex >= #global.ItemSensors then
113+
lastIndex = #global.ItemSensors
114+
end
115+
116+
-- log("[IS] "..global.tickCount.." / "..game.tick.." updating sensors "..global.SensorIndex.." to "..lastIndex)
117+
for i=global.SensorIndex, lastIndex do
118+
local itemSensor = global.ItemSensors[i]
119+
-- log("[IS] skipScan: "..tostring(itemSensor.SkipEntityScanning).." LastScan: "..tostring(itemSensor.LastScanned).."/"..game.tick)
120+
if not itemSensor.SkipEntityScanning and (game.tick - itemSensor.LastScanned) >= ScanInterval then
121+
SetConnectedEntity(itemSensor)
122+
end
123+
124+
UpdateSensor(itemSensor)
125+
end
126+
global.SensorIndex = lastIndex + 1
127+
end
128+
129+
-- reset clock and chest index
130+
if global.tickCount < UpdateInterval then
131+
global.tickCount = global.tickCount + 1
132+
else
133+
global.tickCount = 1
134+
global.SensorIndex = 1
135+
end
100136
end
101137

102-
103-
---- Logic ----
104-
105-
function CreateItemSensor(entity)
106-
global.ItemSensors = global.ItemSensors or {}
107-
108-
entity.operable = false
109-
entity.rotatable = false
110-
local itemSensor = {}
111-
itemSensor.ID = entity.unit_number
112-
itemSensor.Sensor = entity
113-
itemSensor.ScanArea = GetScanArea(entity)
114-
SetConnectedEntity(itemSensor)
115-
116-
global.ItemSensors[#global.ItemSensors+1] = itemSensor
138+
-- function OnTick(event)
139+
-- local tick = game.tick
140+
-- for i=1, #global.ItemSensors do
141+
-- local itemSensor = global.ItemSensors[i]
142+
-- if not itemSensor.SkipEntityScanning and (i + tick) % ScanInterval == 0 then
143+
-- SetConnectedEntity(itemSensor)
144+
-- end
145+
-- if (i + tick) % UpdateInterval == 0 then
146+
-- UpdateSensor(itemSensor)
147+
-- end
148+
-- end
149+
-- end
150+
151+
---- LOGIC ----
152+
153+
-- recalculates how many sensors are updated each tick
154+
function ResetStride()
155+
if #global.ItemSensors > UpdateInterval then
156+
global.SensorStride = math.ceil(#global.ItemSensors/UpdateInterval)
157+
else
158+
global.SensorStride = 1
159+
end
160+
log("[IS] sride set to "..global.SensorStride)
117161
end
118162

119-
function RemoveItemSensor(entity)
120-
for i=#global.ItemSensors, 1, -1 do
121-
if entity.unit_number == global.ItemSensors[i].ID then
122-
table.remove(global.ItemSensors,i)
123-
end
163+
164+
function ResetSensors()
165+
global.ItemSensors = global.ItemSensors or {}
166+
for i=1, #global.ItemSensors do
167+
local itemSensor = global.ItemSensors[i]
168+
itemSensor.ID = itemSensor.Sensor.unit_number
169+
itemSensor.ScanArea = GetScanArea(itemSensor.Sensor)
170+
itemSensor.ConnectedEntity = nil
171+
itemSensor.Inventory = {}
172+
SetConnectedEntity(itemSensor)
124173
end
125174
end
126175

127176
function GetScanArea(sensor)
128177
if sensor.direction == 0 then --south
129-
return{{sensor.position.x - BBox_offset, sensor.position.y}, {sensor.position.x + BBox_offset, sensor.position.y + BBox_range}}
178+
return{{sensor.position.x - ScanOffset, sensor.position.y}, {sensor.position.x + ScanOffset, sensor.position.y + ScanRange}}
130179
elseif sensor.direction == 2 then --west
131-
return{{sensor.position.x - BBox_range, sensor.position.y - BBox_offset}, {sensor.position.x, sensor.position.y + BBox_offset}}
180+
return{{sensor.position.x - ScanRange, sensor.position.y - ScanOffset}, {sensor.position.x, sensor.position.y + ScanOffset}}
132181
elseif sensor.direction == 4 then --north
133-
return{{sensor.position.x - BBox_offset, sensor.position.y - BBox_range}, {sensor.position.x + BBox_offset, sensor.position.y}}
182+
return{{sensor.position.x - ScanOffset, sensor.position.y - ScanRange}, {sensor.position.x + ScanOffset, sensor.position.y}}
134183
elseif sensor.direction == 6 then --east
135-
return{{sensor.position.x, sensor.position.y - BBox_offset}, {sensor.position.x + BBox_range, sensor.position.y + BBox_offset}}
184+
return{{sensor.position.x, sensor.position.y - ScanOffset}, {sensor.position.x + ScanRange, sensor.position.y + ScanOffset}}
136185
end
137186
end
138187

@@ -143,14 +192,15 @@ function SetInventories(itemSensor, entity)
143192
inv = entity.get_inventory(i)
144193
if inv then
145194
itemSensor.Inventory[#itemSensor.Inventory+1] = inv
146-
-- log("adding inventory "..tostring(inv.index))
195+
-- log("[IS] adding inventory "..tostring(inv.index))
147196
end
148197
end
149198
end
150199

151200
function SetConnectedEntity(itemSensor)
201+
itemSensor.LastScanned = game.tick
152202
local connectedEntities = itemSensor.Sensor.surface.find_entities(itemSensor.ScanArea)
153-
--printmsg("Found "..#connectedEntities.." entities in direction "..sensor.direction)
203+
--printmsg("[IS] Found "..#connectedEntities.." entities in direction "..sensor.direction)
154204
if connectedEntities then
155205
for i=1, #connectedEntities do
156206
local entity = connectedEntities[i]
@@ -185,7 +235,7 @@ function UpdateSensor(itemSensor)
185235
if connectedEntity.type == LOCO then
186236
if connectedEntity.train.state == defines.train_state.wait_station
187237
or connectedEntity.train.state == defines.train_state.wait_signal
188-
or connectedEntity.train.state == defines.train_state.manual_control then --keeps showing inventory for find_entity_interval ticks after movement start > neglect able
238+
or connectedEntity.train.state == defines.train_state.manual_control then --keeps showing inventory for ScanInterval ticks after movement start > neglect able
189239
signals[signalIndex] = {index = signalIndex, signal={type="virtual",name="inv-sensor-detected-locomotive"},count=1}
190240
signalIndex = signalIndex+1
191241
else -- train is moving > remove connection
@@ -198,7 +248,7 @@ function UpdateSensor(itemSensor)
198248
elseif connectedEntity.type == WAGON or connectedEntity.type == WAGONFLUID then
199249
if connectedEntity.train.state == defines.train_state.wait_station
200250
or connectedEntity.train.state == defines.train_state.wait_signal
201-
or connectedEntity.train.state == defines.train_state.manual_control then --keeps showing inventory for find_entity_interval ticks after movement start > neglect able
251+
or connectedEntity.train.state == defines.train_state.manual_control then --keeps showing inventory for ScanInterval ticks after movement start > neglect able
202252
signals[signalIndex] = {index = signalIndex, signal={type="virtual",name="inv-sensor-detected-wagon"},count=1}
203253
signalIndex = signalIndex+1
204254
else -- train is moving > remove connection
@@ -281,3 +331,33 @@ function UpdateSensor(itemSensor)
281331

282332
sensor.get_control_behavior().parameters = {parameters=signals}
283333
end
334+
335+
336+
---- INIT ----
337+
do
338+
local function init_events()
339+
script.on_event({defines.events.on_built_entity, defines.events.on_robot_built_entity}, OnEntityCreated)
340+
if global.ItemSensors and #global.ItemSensors > 0 then
341+
script.on_event(defines.events.on_tick, OnTick)
342+
script.on_event({defines.events.on_preplayer_mined_item, defines.events.on_robot_pre_mined, defines.events.on_entity_died}, OnEntityRemoved)
343+
end
344+
end
345+
346+
script.on_load(function()
347+
init_events()
348+
end)
349+
350+
script.on_init(function()
351+
global.ItemSensors = global.ItemSensors or {}
352+
ResetStride()
353+
init_events()
354+
end)
355+
356+
script.on_configuration_changed(function(data)
357+
ResetSensors()
358+
ResetStride()
359+
init_events()
360+
log("[IS] on_config_changed complete.")
361+
end)
362+
363+
end

info.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"name": "Inventory Sensor",
3-
"version": "1.4.11",
3+
"version": "1.5.1",
44
"title": "Inventory Sensor",
55
"author": "Optera",
66
"contact": "https://forums.factorio.com/memberlist.php?mode=viewprofile&u=21729",
77
"homepage": "https://forums.factorio.com/viewtopic.php?f=97&t=30454",
8-
"description": "Adds a combinator that reads inventories of locomotives, wagons, cars, furnaces, assemblers, reactors and roboports.",
8+
"description": "Adds a combinator that reads inventories of locomotives, wagons, cars, furnaces, assemblers, roboports, rocket silos and reactors.",
99
"factorio_version": "0.15",
10-
"dependencies": ["base >= 0.15.18"]
10+
"dependencies": ["base >= 0.15.32"]
1111
}

locale/de/de.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ inv-sensor-detected-wagon=Güterwaggon Gefunden
1313
inv-sensor-detected-car=Auto Gefunden
1414
inv-sensor-detected-tank=Panzer Gefunden
1515
inv-sensor-temperature=Temperatur
16-
inv-sensor-progress=Fortschritt
16+
inv-sensor-progress=Fortschritt

locale/en/en.cfg

+13-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,16 @@ inv-sensor-detected-wagon=Cargo Wagon Detected
1313
inv-sensor-detected-car=Car Detected
1414
inv-sensor-detected-tank=Tank Detected
1515
inv-sensor-temperature=Temperature
16-
inv-sensor-progress=Crafting Progress
16+
inv-sensor-progress=Crafting Progress
17+
18+
[mod-setting-name]
19+
inv_sensor_update_interval=Inventory update interval (ticks)
20+
inv_sensor_find_entity_interval=Entity scan interval (ticks)
21+
inv_sensor_BBox_range=Scan Range
22+
inv_sensor_BBox_offset=Scan Offset
23+
24+
[mod-setting-description]
25+
inv_sensor_update_interval=How often inventories are updated.\nDefault = 10
26+
inv_sensor_find_entity_interval=How often for new/changed entities is scanned.\nDefault = 120
27+
inv_sensor_BBox_range=Length of search rectangle in front of sensors.\nWARNING, entities may not be detected properly after changing this value!\nDefault = 1.5
28+
inv_sensor_BBox_offset=Half width of search rectangle.\nWARNING, entities may not be detected properly after changing this value!\nDefault = 0.2

settings.lua

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
data:extend({
2+
{
3+
type = "int-setting",
4+
name = "inv_sensor_update_interval",
5+
order = "aa",
6+
setting_type = "runtime-global",
7+
default_value = 10,
8+
minimum_value = 1,
9+
},
10+
{
11+
type = "int-setting",
12+
name = "inv_sensor_find_entity_interval",
13+
order = "ab",
14+
setting_type = "runtime-global",
15+
default_value = 120,
16+
minimum_value = 1,
17+
},
18+
{
19+
type = "double-setting",
20+
name = "inv_sensor_BBox_offset",
21+
order = "ad",
22+
setting_type = "runtime-global",
23+
default_value = 0.2,
24+
},
25+
{
26+
type = "double-setting",
27+
name = "inv_sensor_BBox_range",
28+
order = "ac",
29+
setting_type = "runtime-global",
30+
default_value = 1.5,
31+
},
32+
})

0 commit comments

Comments
 (0)