-
Notifications
You must be signed in to change notification settings - Fork 0
/
control.lua
1227 lines (1015 loc) · 31.4 KB
/
control.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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
local PriorityQueue = require("priority-queue")
local memoize = require("__stdlib__/stdlib/vendor/memoize")
local VEHICLE_ENTITY_TYPES = {
"car",
"artillery-wagon",
"cargo-wagon",
"fluid-wagon",
"locomotive"
}
local VEHICLE_ENTITY_NAMES
local VEHICLE_ENTITY_NAMES_MAP
-- aliases to global.<name>
local Vehicles -- with an equipment grid with a burner generator
local Trains -- with an equipment grid with a burner generator
local Players -- wearing armor with an equipment grid with a burner generator.
local Queue -- in ascending order of next_tick
--- functions start here
local function enqueue(data)
Queue:put(data, data.next_tick)
end
local items_in_fuel_category
local function _items_in_fuel_category(fuel_category)
local prototypes = game.get_filtered_item_prototypes{
{
filter = "fuel-category",
["fuel-category"] = fuel_category
}
}
local item_data = {}
for _, item_prototype in pairs(prototypes) do
item_data[#item_data + 1] = {
item_name = item_prototype.name,
fuel_value = item_prototype.fuel_value,
stack_fuel_value = item_prototype.fuel_value * item_prototype.stack_size,
emissions_multiplier = item_prototype.fuel_emissions_multiplier
}
end
table.sort(
item_data,
function(a,b)
return a.stack_fuel_value > b.stack_fuel_value
end
)
return item_data
end
local items_in_fuel_categories = function(_) end
local function _items_in_fuel_categories(fuel_categories)
local merged
for fuel_category in pairs(fuel_categories) do
local data = items_in_fuel_category(fuel_category)
-- merge sort on stack_fuel_value
if merged then
local temp = merged
merged = {}
local i = 1
local j = 1
while data[i] and temp[j] do
if data[i].stack_fuel_value > temp[j].stack_fuel_value then
merged[#merged + 1] = data[i]
i = i + 1
else
merged[#merged + 1] = temp[j]
j = j + 1
end
end
while data[i] do
merged[#merged + 1] = data[i]
i = i + 1
end
while temp[j] do
merged[#merged + 1] = temp[j]
j = j + 1
end
else
merged = data
end
end
return merged
end
local function find_burner_generators(grid, complain)
local generators = {}
for _,equipment in ipairs(grid.equipment) do
local burner = equipment.burner
if not burner then goto next_equipment end
local inventory = burner.inventory
if not inventory.valid then
-- shouldn't happen?
complain({"GridGuelManager-message.generator-no-inventory", equipment.prototype.localised_name})
goto next_equipment
end
local burnt_result_inventory = burner.burnt_result_inventory
if not burnt_result_inventory.valid then
burnt_result_inventory = nil
end
local power = equipment.generator_power
if power == 0 then
complain({"GridGuelManager-message.powerless-generator", equipment.prototype.localised_name})
goto next_equipment
end
generators[#generators + 1] = {
equipment = equipment,
ipower = 1 / power,
burner = burner,
inventory = inventory,
burnt_result_inventory = burnt_result_inventory,
fuel_categories = burner.fuel_categories
}
::next_equipment::
end
return generators
end
local function handle_train(data)
local train_id = data.train_id
local train_data = Trains[train_id]
if not train_data then return end
local train = train_data.train
if not train.valid then
Trains[train_id] = nil
return
end
local generators = {}
local failed
for unit_number,_ in pairs(train_data.units) do
local vehicle_data = Vehicles[unit_number]
if not vehicle_data then
failed = true
goto next_vehicle
end
local vehicle = vehicle_data.vehicle
if not vehicle.valid then
Vehicles[unit_number] = nil
failed = true
goto next_vehicle
end
local grid = vehicle.grid
if grid and not grid.valid then
Vehicles[unit_number] = nil
failed = true
goto next_vehicle
end
local vehicle_generators = vehicle_data.generators
if vehicle_generators then
for i=#vehicle_generators,1,-1 do
local generator=vehicle_generators[i]
local remove = false
if not generator.equipment.valid then
remove = true
end
if not generator.burner.valid then
remove = true
end
if not generator.inventory.valid then
remove = true
end
if generator.burnt_result_inventory then
if not generator.burnt_result_inventory.valid then
remove = true
end
end
if not remove then
generators[#generators + 1] = generator
else
vehicle_generators[i] = vehicle_generators[#vehicle_generators]
vehicle_generators[#vehicle_generators] = nil
end
end
end
::next_vehicle::
end
if failed then
-- TODO try and track down where the train is now?
local force = train.force
force.print({"description.broken-train", "[train=" .. train_id .. "]"},{r=1,a=1})
log("No longer updating train " .. train_id .. " due to failure during update.")
Trains[train_id] = nil
return
end
local min_remaining_time = nil
for _,generator in pairs(generators) do
local inventory = generator.inventory
inventory.sort_and_merge()
-- try to fill inventory with more of what's already there
local contents = inventory.get_contents()
for name, _ in pairs(contents) do
local available = train.get_item_count(name)
if available > 0 then
local moved = inventory.insert{name = name, count = available}
if moved > 0 then
train.remove_item{name = name, count = moved}
end
end
end
-- TODO cache this in generator? it boils down to a table lookup, so maybe not worth it?
local fuel_items = items_in_fuel_categories(generator.fuel_categories)
-- put the fuel that will burn the longest into inventory
for _,fuel_item in ipairs(fuel_items) do
local name = fuel_item.item_name
local available = train.get_item_count(name)
if available > 0 then
local moved = inventory.insert{name = name, count = available}
if moved > 0 then
train.remove_item{name = name, count = moved}
end
end
end
local remaining_energy = 0
-- count the remaining run time
for _,fuel_item in ipairs(fuel_items) do
local name = fuel_item.item_name
local count = inventory.get_item_count(name)
local energy = count * fuel_item.fuel_value
remaining_energy = remaining_energy + energy
end
local remaining_time = remaining_energy * generator.ipower
if not min_remaining_time then
min_remaining_time = remaining_time
else
if remaining_time < min_remaining_time then
min_remaining_time = remaining_time
end
end
end
-- evict the burnt result to the train inventory, so it can be taken away.
for _,generator in pairs(generators) do
local burnt_result_inventory = generator.burnt_result_inventory
if burnt_result_inventory then
local contents = burnt_result_inventory.get_contents()
for name, count in pairs(contents) do
local moved = train.insert{name = name, count = count}
if moved > 0 then
burnt_result_inventory.remove{name = name, count = moved}
end
end
end
end
if min_remaining_time then
-- return when we've burnt through 1/2 of the remaining time
data.next_tick = game.tick + math.floor(min_remaining_time / 2) + 1
enqueue(data)
end
end
local function handle_vehicle(data)
local unit_number = data.unit_number
local vehicle_data = Vehicles[unit_number]
if not vehicle_data then return end
local vehicle = vehicle_data.vehicle
if not vehicle.valid then
Vehicles[unit_number] = nil
return
end
local grid = vehicle_data.grid
if not grid.valid then
Vehicles[unit_number] = nil
return
end
local vehicle_inventory = vehicle_data.inventory
if not vehicle_inventory.valid then
Vehicles[unit_number] = nil
return
end
local vehicle_fuel_inventory = vehicle_data.fuel_inventory
if vehicle_fuel_inventory then
if not vehicle_fuel_inventory.valid then
Vehicles[unit_number] = nil
return
end
end
local vehicle_burnt_result_inventory = vehicle_data.burnt_result_inventory
if vehicle_burnt_result_inventory then
if not vehicle_burnt_result_inventory.valid then
Vehicles[unit_number] = nil
return
end
end
-- TODO should we be paranoid and check for new generators, or just watch the player and hope it's enough?
local generators = vehicle_data.generators
local min_remaining_time = nil
for i=#generators,1,-1 do
local generator=generators[i]
local remove = false
do
if not generator.equipment.valid then
remove = true
goto next
end
if not generator.burner.valid then
remove = true
goto next
end
local inventory = generator.inventory
if not inventory.valid then
remove = true
goto next
end
if generator.burnt_result_inventory then
if not generator.burnt_result_inventory.valid then
remove = true
goto next
end
end
-- sort the inventory to free up space
inventory.sort_and_merge()
-- try to fill inventory with more of what's already there
local contents = inventory.get_contents()
for name, _ in pairs(contents) do
local available = vehicle_inventory.get_item_count(name)
if available > 0 then
local moved = inventory.insert{name = name, count = available}
if moved > 0 then
vehicle_inventory.remove{name = name, count = moved}
end
end
end
-- TODO cache this in generator? it boils down to a table lookup, so maybe not worth it?
local fuel_items = items_in_fuel_categories(generator.fuel_categories)
-- put the fuel that will burn the longest into inventory
for _,fuel_item in ipairs(fuel_items) do
local name = fuel_item.item_name
local available = vehicle_inventory.get_item_count(name)
if available > 0 then
local moved = inventory.insert{name = name, count = available}
if moved > 0 then
vehicle_inventory.remove{name = name, count = moved}
end
end
end
-- pull fuel from the vehicle's fuel inventory if there's none available elsewhere
for _,fuel_item in ipairs(fuel_items) do
local name = fuel_item.item_name
local available = vehicle_fuel_inventory.get_item_count(name)
if available > 0 then
local moved = inventory.insert{name = name, count = available}
if moved > 0 then
vehicle_fuel_inventory.remove{name = name, count = moved}
end
end
end
-- TODO should we attempt to count the remaining energy in the burner?
local remaining_energy = 0
--local remaining_energy = burner.remaining_burning_fuel -- ?
-- count the remaining run time
for _,fuel_item in ipairs(fuel_items) do
local name = fuel_item.item_name
local count = inventory.get_item_count(name)
local energy = count * fuel_item.fuel_value
remaining_energy = remaining_energy + energy
end
local remaining_time = remaining_energy / generator.ipower
if not min_remaining_time then
min_remaining_time = remaining_time
else
if remaining_time < min_remaining_time then
min_remaining_time = remaining_time
end
end
end
::next::
if remove then
generators[i] = generators[#generators]
generators[#generators] = nil
end
end
-- compact the inventory to try and free up some space.
vehicle_inventory.sort_and_merge()
-- evict the burnt result to the main inventory, so it can be taken away.
for _,generator in ipairs(generators) do
local burnt_result_inventory = generator.burnt_result_inventory
if burnt_result_inventory then
local contents = burnt_result_inventory.get_contents()
for name, count in pairs(contents) do
local moved = vehicle_inventory.insert{name = name, count = count}
if moved > 0 then
burnt_result_inventory.remove{name = name, count = moved}
end
end
end
end
if vehicle_burnt_result_inventory then
local contents = vehicle_burnt_result_inventory.get_contents()
for name, count in pairs(contents) do
local moved = vehicle_inventory.insert{name = name, count = count}
if moved > 0 then
vehicle_burnt_result_inventory.remove{name = name, count = moved}
end
end
end
-- if min_remaining_time is nil, there were no valid generators found
if min_remaining_time then
-- return when we've burnt through 1/2 of the remaining time
data.next_tick = game.tick + math.floor(min_remaining_time / 2) + 1
enqueue(data)
end
end
local function handle_player(data)
local player_index = data.player_index
local player_data = Players[player_index]
if not player_data then return end
local player = player_data.player
if not player.valid then
Players[player_index] = nil
return
end
local grid = player_data.grid
if not grid.valid then
Players[player_index] = nil
return
end
local generators = player_data.generators
local min_remaining_time = nil
for i=#generators,1,-1 do
local generator=generators[i]
local remove = false
do
if not generator.equipment.valid then
remove = true
goto next
end
if not generator.burner.valid then
remove = true
goto next
end
local inventory = generator.inventory
if not inventory.valid then
remove = true
goto next
end
if generator.burnt_result_inventory then
if not generator.burnt_result_inventory.valid then
remove = true
goto next
end
end
-- sort the inventory to free up space
inventory.sort_and_merge()
-- try to fill inventory with more of what's already there
local contents = inventory.get_contents()
for name, _ in pairs(contents) do
local available = player.get_item_count(name)
if available > 0 then
local moved = inventory.insert{name = name, count = available}
if moved > 0 then
player.remove_item{name = name, count = moved}
end
end
end
-- TODO cache this in generator? it boils down to a table lookup, so maybe not worth it?
local fuel_items = items_in_fuel_categories(generator.fuel_categories)
-- put the fuel that will burn the longest into inventory
for _,fuel_item in ipairs(fuel_items) do
local name = fuel_item.item_name
local available = player.get_item_count(name)
if available > 0 then
local moved = inventory.insert{name = name, count = available}
if moved > 0 then
player.remove_item{name = name, count = moved}
end
end
end
-- TODO should we attempt to count the remaining energy in the burner?
local remaining_energy = 0
--local remaining_energy = burner.remaining_burning_fuel -- ?
-- count the remaining run time
for _,fuel_item in ipairs(fuel_items) do
local name = fuel_item.item_name
local count = inventory.get_item_count(name)
local energy = count * fuel_item.fuel_value
remaining_energy = remaining_energy + energy
end
local remaining_time = remaining_energy / generator.ipower
if not min_remaining_time then
min_remaining_time = remaining_time
else
if remaining_time < min_remaining_time then
min_remaining_time = remaining_time
end
end
end
::next::
if remove then
generators[i] = generators[#generators]
generators[#generators] = nil
end
end
-- evict the burnt result to the main inventory, so it can be taken away.
for _,generator in pairs(generators) do
local burnt_result_inventory = generator.burnt_result_inventory
if burnt_result_inventory then
local contents = burnt_result_inventory.get_contents()
for name, count in pairs(contents) do
local moved = player.insert{name = name, count = count}
if moved > 0 then
burnt_result_inventory.remove{name = name, count = moved}
end
end
end
end
-- if min_remaining_time is nil, there were no valid generators found
if min_remaining_time then
-- return when we've burnt through 1/2 of the remaining time
data.next_tick = game.tick + math.floor(min_remaining_time / 2) + 1
enqueue(data)
end
end
local function handle_thing(data)
local type = data.type
if type == "train" then
handle_train(data)
elseif type == "vehicle" then
handle_vehicle(data)
elseif type == "player" then
handle_player(data)
end
end
local function on_tick(event)
local item = Queue:peek()
if not item then return end
local tick = event.tick
if item.next_tick > tick then return end
Queue:pop()
handle_thing(item)
end
local function register_vehicle_with_equipment_grid(entity, grid)
local unit_number = entity.unit_number
local vehicle_type = entity.type
local vehicle_data = {
vehicle = entity,
grid = grid
}
local generators = find_burner_generators(
grid,
function(message)
local force = entity.force
force.print(message)
end
)
vehicle_data.generators = generators
local train = entity.train
local train_data
local train_id
if train then
train_id = train.id
vehicle_data.train_id = train_id
train_data = Trains[train_id]
if not train_data then
train_data = {
train = train,
units = {}
}
Trains[train_id] = train_data
end
train_data.units[unit_number] = true
end
local queue_data
if next(generators) then
if train_id then
queue_data = train_data.queue_data
if not queue_data then
queue_data = {
type = "train",
train_id = train_id,
next_tick = 0,
}
train_data.queue_data = queue_data
enqueue(queue_data)
end
else
queue_data = {
type = "vehicle",
unit_number = unit_number,
next_tick = 0,
}
vehicle_data.queue_data = queue_data
enqueue(queue_data)
end
end
if vehicle_type == "car" then
vehicle_data.inventory = entity.get_inventory(defines.inventory.car_trunk)
vehicle_data.fuel_inventory = entity.get_fuel_inventory()
vehicle_data.burnt_result_inventory = entity.get_burnt_result_inventory()
end
Vehicles[unit_number] = vehicle_data
end
local function deregister_vehicle_with_equipment_grid(entity)
local unit_number = entity.unit_number
local vehicle_data = Vehicles[unit_number]
if not vehicle_data then return end
Vehicles[unit_number] = nil
local train_id = vehicle_data.train_id
local train_data
if train_id then
train_data = Trains[train_id]
if not train_data then return end
Trains[train_id] = nil
end
local queue_data
if train_data then
queue_data = train_data.queue_data
else
queue_data = vehicle_data.queue_data
end
-- can't efficiently delete from Queue, but if we set type to blank, it will do nothing when this reaches the head of the queue.
if queue_data then
queue_data.type = ''
end
end
local function on_train_created(event)
local train = event.train
local train_id = train.id
local train_data = Trains[train_id]
if not train_data then
train_data = {
units = {}
}
end
train_data.train = train
local units = train_data.units
local old_train_id_1 = event.old_train_id_1
if old_train_id_1 then
local old_train_data = Trains[old_train_id_1]
if old_train_data then
Trains[old_train_id_1] = nil
local queue_data = old_train_data.queue_data
if queue_data then
old_train_data.queue_data = nil
queue_data.type = ''
end
end
end
local old_train_id_2 = event.old_train_id_2
if old_train_id_2 then
local old_train_data = Trains[old_train_id_2]
if old_train_data then
Trains[old_train_id_2] = nil
local queue_data = old_train_data.queue_data
if queue_data then
old_train_data.queue_data = nil
queue_data.type = ''
end
end
end
Trains[train_id] = train_data
local has_generators
local carriages = train.carriages
for _,carriage in ipairs(carriages) do
local grid = carriage.grid
if not grid then goto next_carriage end
local unit_number = carriage.unit_number
local vehicle_data = Vehicles[unit_number]
if vehicle_data then
units[unit_number] = true
vehicle_data.train_id = train_id
if next(vehicle_data.generators) then
has_generators = true
end
else
register_vehicle_with_equipment_grid(carriage, grid)
end
::next_carriage::
end
if has_generators then
local queue_data = train_data.queue_data
if not queue_data then
queue_data = {
type = "train",
train_id = train_id,
next_tick = 0
}
train_data.queue_data = queue_data
enqueue(queue_data)
end
end
end
local function on_entity_created(entity)
local grid = entity.grid
if not grid then return end
register_vehicle_with_equipment_grid(entity, grid)
end
local function on_entity_destroyed(entity)
local grid = entity.grid
if not grid then return end
deregister_vehicle_with_equipment_grid(entity, grid)
end
local function on_player_placed_equipment(event)
local equipment = event.equipment
local burner = equipment.burner
if not burner then return end
local player_index = event.player_index
local grid = event.grid
local player_data = Players[player_index]
local player
if player_data then
player = player_data.player
else
player = game.players[player_index]
end
local generators
local thing_data
local queue_data = {
next_tick = 0
}
local entity = player.opened
if entity == grid then -- player.opened == grid for power armor, despite what the doco says
if player_data.grid == grid then
queue_data.type = 'player'
queue_data.player_index = player_index
thing_data = player_data
generators = player_data.generators
else
player.print({"GridFuelManager-message.where-did-you-put-that", equipment.prototype.localised_name})
end
else
if entity.grid == grid then
if VEHICLE_ENTITY_NAMES_MAP[entity.name] then
local unit_number = entity.unit_number
local vehicle_data = Vehicles[unit_number]
if not vehicle_data then
register_vehicle_with_equipment_grid(entity, grid)
vehicle_data = Vehicles[unit_number]
end
generators = vehicle_data.generators
local train_id = vehicle_data.train_id
if train_id then
queue_data.type = 'train'
queue_data.train_id = train_id
thing_data = Trains[train_id]
else
queue_data.type = 'vehicle'
queue_data.unit_number = unit_number
thing_data = vehicle_data
end
end
end
end
if ((generators == nil) or (not thing_data)) then
player.print({"GridFuelManager-message.where-did-you-put-that", equipment.prototype.localised_name})
-- TODO do an exhaustive search?
return
end
local burnt_result_inventory = burner.burnt_result_inventory
if not burnt_result_inventory.valid then
burnt_result_inventory = nil
end
local power = equipment.generator_power
if power == 0 then
player.print({"GridFuelManager-message.powerless-generator"})
return
end
generators[#generators + 1] = {
equipment = equipment,
ipower = 1 / power,
burner = burner,
inventory = burner.inventory,
burnt_result_inventory = burnt_result_inventory,
fuel_categories = burner.fuel_categories,
}
local old_queue_data = thing_data.queue_data
if old_queue_data then
if old_queue_data.next_tick == 0 then
return
end
old_queue_data.type = ''
end
thing_data.queue_data = queue_data
enqueue(queue_data)
end
local function on_player_armor_inventory_changed(event)
local player_index = event.player_index
local player_data = Players[player_index]
local player
if player_data then
player = player_data.player
player_data.grid = nil
player_data.generators = nil
local queue_data = player_data.queue_data
if queue_data then
queue_data.type = ''
player_data.queue_data = nil
end
else
player = game.players[player_index]
player_data = {
player = player
}
end
local armor_inventory = player.get_inventory(defines.inventory.character_armor)
if not armor_inventory then return end -- shouldn't happen?
local armor_stack = armor_inventory[1]
if not armor_stack then return end
if not armor_stack.valid then return end
if not armor_stack.valid_for_read then return end
local grid = armor_stack.grid
if not grid then return end
player_data.grid = grid
local generators = find_burner_generators(
grid,
function (message)
player.print(message)
end
)
player_data.generators = generators
if next(generators) then
local queue_data = {
type = "player",
player_index = player_index,
next_tick = 0,
}
player_data.queue_data = queue_data
enqueue(queue_data)
end
Players[player_index] = player_data
end
local function on_player_joined_game(event)
local player_index = event.player_index
local player_data = Players[player_index]
if not player_data then return end
if not next(player_data.generators) then return end
local queue_data = {
type = "player",
player_index = player_index,
next_tick = 0
}
player_data.queue_data = queue_data
enqueue(queue_data)
end
local function on_player_left_game(event)
local player_index = event.player_index
local player_data = Players[player_index]
if not player_data then return end
if not next(player_data.generators) then return end
local queue_data = player_data.queue_data
if not queue_data then return end
queue_data.type = ''
player_data.queue_data = nil
end
local function on_player_died(event)
local player_index = event.player_index