1use std::collections::HashMap;
2use std::io;
3use std::io::Read;
4
5use factorio_blueprint::objects::{
6 Blueprint, ControlBehavior, ControlFilter, Entity, EntityConnections, EntityNumber,
7 OneBasedIndex, Position, SignalID, SignalIDType,
8};
9
10use itertools::Itertools;
11use noisy_float::types::R64;
12
13pub const SIGNALS: [(&str, SignalIDType); 256] = [
15 ("signal-1", SignalIDType::Virtual),
16 ("signal-2", SignalIDType::Virtual),
17 ("signal-3", SignalIDType::Virtual),
18 ("signal-4", SignalIDType::Virtual),
19 ("signal-5", SignalIDType::Virtual),
20 ("signal-6", SignalIDType::Virtual),
21 ("signal-7", SignalIDType::Virtual),
22 ("signal-8", SignalIDType::Virtual),
23 ("signal-9", SignalIDType::Virtual),
24 ("signal-0", SignalIDType::Virtual),
25 ("signal-A", SignalIDType::Virtual),
26 ("signal-B", SignalIDType::Virtual),
27 ("signal-C", SignalIDType::Virtual),
28 ("signal-D", SignalIDType::Virtual),
29 ("signal-E", SignalIDType::Virtual),
30 ("signal-F", SignalIDType::Virtual),
31 ("signal-G", SignalIDType::Virtual),
32 ("signal-H", SignalIDType::Virtual),
33 ("signal-I", SignalIDType::Virtual),
34 ("signal-J", SignalIDType::Virtual),
35 ("signal-K", SignalIDType::Virtual),
36 ("signal-L", SignalIDType::Virtual),
37 ("signal-M", SignalIDType::Virtual),
38 ("signal-N", SignalIDType::Virtual),
39 ("signal-O", SignalIDType::Virtual),
40 ("signal-P", SignalIDType::Virtual),
41 ("signal-Q", SignalIDType::Virtual),
42 ("signal-R", SignalIDType::Virtual),
43 ("signal-S", SignalIDType::Virtual),
44 ("signal-T", SignalIDType::Virtual),
45 ("signal-U", SignalIDType::Virtual),
46 ("signal-V", SignalIDType::Virtual),
47 ("signal-W", SignalIDType::Virtual),
48 ("signal-X", SignalIDType::Virtual),
49 ("signal-Y", SignalIDType::Virtual),
50 ("signal-Z", SignalIDType::Virtual),
51 ("signal-red", SignalIDType::Virtual),
52 ("signal-green", SignalIDType::Virtual),
53 ("signal-blue", SignalIDType::Virtual),
54 ("signal-yellow", SignalIDType::Virtual),
55 ("signal-pink", SignalIDType::Virtual),
56 ("signal-cyan", SignalIDType::Virtual),
57 ("signal-check", SignalIDType::Virtual),
58 ("signal-info", SignalIDType::Virtual),
59 ("signal-dot", SignalIDType::Virtual),
60 ("water", SignalIDType::Fluid),
61 ("crude-oil", SignalIDType::Fluid),
62 ("steam", SignalIDType::Fluid),
63 ("heavy-oil", SignalIDType::Fluid),
64 ("light-oil", SignalIDType::Fluid),
65 ("petroleum-gas", SignalIDType::Fluid),
66 ("sulfuric-acid", SignalIDType::Fluid),
67 ("lubricant", SignalIDType::Fluid),
68 ("wooden-chest", SignalIDType::Item),
69 ("iron-chest", SignalIDType::Item),
70 ("steel-chest", SignalIDType::Item),
71 ("storage-tank", SignalIDType::Item),
72 ("transport-belt", SignalIDType::Item),
73 ("fast-transport-belt", SignalIDType::Item),
74 ("express-transport-belt", SignalIDType::Item),
75 ("underground-belt", SignalIDType::Item),
76 ("fast-underground-belt", SignalIDType::Item),
77 ("express-underground-belt", SignalIDType::Item),
78 ("splitter", SignalIDType::Item),
79 ("fast-splitter", SignalIDType::Item),
80 ("express-splitter", SignalIDType::Item),
81 ("burner-inserter", SignalIDType::Item),
82 ("inserter", SignalIDType::Item),
83 ("long-handed-inserter", SignalIDType::Item),
84 ("fast-inserter", SignalIDType::Item),
85 ("filter-inserter", SignalIDType::Item),
86 ("stack-inserter", SignalIDType::Item),
87 ("stack-filter-inserter", SignalIDType::Item),
88 ("small-electric-pole", SignalIDType::Item),
89 ("medium-electric-pole", SignalIDType::Item),
90 ("big-electric-pole", SignalIDType::Item),
91 ("substation", SignalIDType::Item),
92 ("pipe", SignalIDType::Item),
93 ("pipe-to-ground", SignalIDType::Item),
94 ("pump", SignalIDType::Item),
95 ("rail", SignalIDType::Item),
96 ("train-stop", SignalIDType::Item),
97 ("rail-signal", SignalIDType::Item),
98 ("rail-chain-signal", SignalIDType::Item),
99 ("locomotive", SignalIDType::Item),
100 ("cargo-wagon", SignalIDType::Item),
101 ("fluid-wagon", SignalIDType::Item),
102 ("artillery-wagon", SignalIDType::Item),
103 ("car", SignalIDType::Item),
104 ("tank", SignalIDType::Item),
105 ("spidertron", SignalIDType::Item),
106 ("spidertron-remote", SignalIDType::Item),
107 ("logistic-robot", SignalIDType::Item),
108 ("construction-robot", SignalIDType::Item),
109 ("logistic-chest-active-provider", SignalIDType::Item),
110 ("logistic-chest-passive-provider", SignalIDType::Item),
111 ("logistic-chest-storage", SignalIDType::Item),
112 ("logistic-chest-buffer", SignalIDType::Item),
113 ("logistic-chest-requester", SignalIDType::Item),
114 ("roboport", SignalIDType::Item),
115 ("small-lamp", SignalIDType::Item),
116 ("red-wire", SignalIDType::Item),
117 ("green-wire", SignalIDType::Item),
118 ("arithmetic-combinator", SignalIDType::Item),
119 ("decider-combinator", SignalIDType::Item),
120 ("constant-combinator", SignalIDType::Item),
121 ("power-switch", SignalIDType::Item),
122 ("programmable-speaker", SignalIDType::Item),
123 ("stone-brick", SignalIDType::Item),
124 ("concrete", SignalIDType::Item),
125 ("hazard-concrete", SignalIDType::Item),
126 ("refined-concrete", SignalIDType::Item),
127 ("refined-hazard-concrete", SignalIDType::Item),
128 ("landfill", SignalIDType::Item),
129 ("cliff-explosives", SignalIDType::Item),
130 ("repair-pack", SignalIDType::Item),
131 ("blueprint", SignalIDType::Item),
132 ("deconstruction-planner", SignalIDType::Item),
133 ("upgrade-planner", SignalIDType::Item),
134 ("blueprint-book", SignalIDType::Item),
135 ("boiler", SignalIDType::Item),
136 ("steam-engine", SignalIDType::Item),
137 ("solar-panel", SignalIDType::Item),
138 ("accumulator", SignalIDType::Item),
139 ("nuclear-reactor", SignalIDType::Item),
140 ("heat-pipe", SignalIDType::Item),
141 ("heat-exchanger", SignalIDType::Item),
142 ("steam-turbine", SignalIDType::Item),
143 ("burner-mining-drill", SignalIDType::Item),
144 ("electric-mining-drill", SignalIDType::Item),
145 ("offshore-pump", SignalIDType::Item),
146 ("pumpjack", SignalIDType::Item),
147 ("stone-furnace", SignalIDType::Item),
148 ("steel-furnace", SignalIDType::Item),
149 ("electric-furnace", SignalIDType::Item),
150 ("assembling-machine-1", SignalIDType::Item),
151 ("assembling-machine-2", SignalIDType::Item),
152 ("assembling-machine-3", SignalIDType::Item),
153 ("oil-refinery", SignalIDType::Item),
154 ("chemical-plant", SignalIDType::Item),
155 ("centrifuge", SignalIDType::Item),
156 ("lab", SignalIDType::Item),
157 ("beacon", SignalIDType::Item),
158 ("speed-module", SignalIDType::Item),
159 ("speed-module-2", SignalIDType::Item),
160 ("speed-module-3", SignalIDType::Item),
161 ("effectivity-module", SignalIDType::Item),
162 ("effectivity-module-2", SignalIDType::Item),
163 ("effectivity-module-3", SignalIDType::Item),
164 ("productivity-module", SignalIDType::Item),
165 ("productivity-module-2", SignalIDType::Item),
166 ("productivity-module-3", SignalIDType::Item),
167 ("wood", SignalIDType::Item),
168 ("coal", SignalIDType::Item),
169 ("stone", SignalIDType::Item),
170 ("iron-ore", SignalIDType::Item),
171 ("copper-ore", SignalIDType::Item),
172 ("uranium-ore", SignalIDType::Item),
173 ("raw-fish", SignalIDType::Item),
174 ("iron-plate", SignalIDType::Item),
175 ("copper-plate", SignalIDType::Item),
176 ("solid-fuel", SignalIDType::Item),
177 ("steel-plate", SignalIDType::Item),
178 ("plastic-bar", SignalIDType::Item),
179 ("sulfur", SignalIDType::Item),
180 ("battery", SignalIDType::Item),
181 ("explosives", SignalIDType::Item),
182 ("crude-oil-barrel", SignalIDType::Item),
183 ("heavy-oil-barrel", SignalIDType::Item),
184 ("light-oil-barrel", SignalIDType::Item),
185 ("lubricant-barrel", SignalIDType::Item),
186 ("petroleum-gas-barrel", SignalIDType::Item),
187 ("sulfuric-acid-barrel", SignalIDType::Item),
188 ("water-barrel", SignalIDType::Item),
189 ("copper-cable", SignalIDType::Item),
190 ("iron-stick", SignalIDType::Item),
191 ("iron-gear-wheel", SignalIDType::Item),
192 ("empty-barrel", SignalIDType::Item),
193 ("electronic-circuit", SignalIDType::Item),
194 ("advanced-circuit", SignalIDType::Item),
195 ("processing-unit", SignalIDType::Item),
196 ("engine-unit", SignalIDType::Item),
197 ("electric-engine-unit", SignalIDType::Item),
198 ("flying-robot-frame", SignalIDType::Item),
199 ("satellite", SignalIDType::Item),
200 ("rocket-control-unit", SignalIDType::Item),
201 ("low-density-structure", SignalIDType::Item),
202 ("rocket-fuel", SignalIDType::Item),
203 ("nuclear-fuel", SignalIDType::Item),
204 ("uranium-235", SignalIDType::Item),
205 ("uranium-238", SignalIDType::Item),
206 ("uranium-fuel-cell", SignalIDType::Item),
207 ("used-up-uranium-fuel-cell", SignalIDType::Item),
208 ("automation-science-pack", SignalIDType::Item),
209 ("logistic-science-pack", SignalIDType::Item),
210 ("military-science-pack", SignalIDType::Item),
211 ("chemical-science-pack", SignalIDType::Item),
212 ("production-science-pack", SignalIDType::Item),
213 ("utility-science-pack", SignalIDType::Item),
214 ("space-science-pack", SignalIDType::Item),
215 ("pistol", SignalIDType::Item),
216 ("submachine-gun", SignalIDType::Item),
217 ("shotgun", SignalIDType::Item),
218 ("combat-shotgun", SignalIDType::Item),
219 ("rocket-launcher", SignalIDType::Item),
220 ("flamethrower", SignalIDType::Item),
221 ("land-mine", SignalIDType::Item),
222 ("firearm-magazine", SignalIDType::Item),
223 ("piercing-rounds-magazine", SignalIDType::Item),
224 ("uranium-rounds-magazine", SignalIDType::Item),
225 ("shotgun-shell", SignalIDType::Item),
226 ("piercing-shotgun-shell", SignalIDType::Item),
227 ("cannon-shell", SignalIDType::Item),
228 ("explosive-cannon-shell", SignalIDType::Item),
229 ("uranium-cannon-shell", SignalIDType::Item),
230 ("explosive-uranium-cannon-shell", SignalIDType::Item),
231 ("artillery-shell", SignalIDType::Item),
232 ("rocket", SignalIDType::Item),
233 ("explosive-rocket", SignalIDType::Item),
234 ("atomic-bomb", SignalIDType::Item),
235 ("flamethrower-ammo", SignalIDType::Item),
236 ("grenade", SignalIDType::Item),
237 ("cluster-grenade", SignalIDType::Item),
238 ("poison-capsule", SignalIDType::Item),
239 ("slowdown-capsule", SignalIDType::Item),
240 ("defender-capsule", SignalIDType::Item),
241 ("distractor-capsule", SignalIDType::Item),
242 ("destroyer-capsule", SignalIDType::Item),
243 ("light-armor", SignalIDType::Item),
244 ("heavy-armor", SignalIDType::Item),
245 ("modular-armor", SignalIDType::Item),
246 ("power-armor", SignalIDType::Item),
247 ("power-armor-mk2", SignalIDType::Item),
248 ("solar-panel-equipment", SignalIDType::Item),
249 ("fusion-reactor-equipment", SignalIDType::Item),
250 ("battery-equipment", SignalIDType::Item),
251 ("battery-mk2-equipment", SignalIDType::Item),
252 ("belt-immunity-equipment", SignalIDType::Item),
253 ("exoskeleton-equipment", SignalIDType::Item),
254 ("personal-roboport-equipment", SignalIDType::Item),
255 ("personal-roboport-mk2-equipment", SignalIDType::Item),
256 ("night-vision-equipment", SignalIDType::Item),
257 ("energy-shield-equipment", SignalIDType::Item),
258 ("energy-shield-mk2-equipment", SignalIDType::Item),
259 ("personal-laser-defense-equipment", SignalIDType::Item),
260 ("discharge-defense-equipment", SignalIDType::Item),
261 ("discharge-defense-remote", SignalIDType::Item),
262 ("stone-wall", SignalIDType::Item),
263 ("gate", SignalIDType::Item),
264 ("gun-turret", SignalIDType::Item),
265 ("laser-turret", SignalIDType::Item),
266 ("flamethrower-turret", SignalIDType::Item),
267 ("artillery-turret", SignalIDType::Item),
268 ("artillery-targeting-remote", SignalIDType::Item),
269 ("radar", SignalIDType::Item),
270 ("rocket-silo", SignalIDType::Item),
271];
272
273pub fn pack_read<R: Read>(mut from: R) -> Result<Blueprint, io::Error> {
274 let mut buf = Vec::new();
275 from.read_to_end(&mut buf)?;
276
277 let chunks = buf
278 .iter()
279 .chunks(4);
280
281 let mut words = chunks
282 .into_iter()
283 .map(|word| {
284 let (b1, b2, b3, b4) = word.pad_using(4, |_| &0).cloned().collect_tuple().unwrap();
285 u32::from_le_bytes([b1, b2, b3, b4])
286 });
287
288 Ok(pack(&mut words))
289}
290
291pub fn pack<I: Iterator<Item = u32>>(iter: &mut I) -> Blueprint {
292 let entities = iter
293 .chunks(SIGNALS.len())
294 .into_iter()
295 .enumerate()
296 .map(move |(cluster_n, words)| {
297 words
298 .zip(SIGNALS.into_iter())
299 .chunks(20)
300 .into_iter()
301 .map(|signals| {
302 let filters = signals
303 .enumerate()
304 .map(|(signal_n, (word, (signal, signal_type)))| {
305 ControlFilter {
306 signal: SignalID { name: signal.to_owned(), type_: signal_type },
307 index: OneBasedIndex::new(signal_n + 1).unwrap(),
308 count: i32::from_le_bytes(word.to_le_bytes()),
310 }
311 })
312 .collect::<Vec<_>>();
313
314 ControlBehavior {
315 arithmetic_conditions: None,
316 decider_conditions: None,
317 filters: Some(filters),
318 is_on: Some(true),
319 }
320 })
321 .enumerate()
322 .map(move |(ent_n, control)| Entity {
323 entity_number: EntityNumber::new((&cluster_n + 1) * (ent_n + 1)).unwrap(),
324 name: "constant-combinator".to_owned(),
325 position: {
326 let n = &ent_n % 7;
327 let r = &ent_n / 7 + &cluster_n * 2;
328
329 Position { x: R64::new(r as f64), y: R64::new(n as f64) }
330 },
331 direction: Some(4), connections: Some(EntityConnections::NumberIdx(HashMap::new())),
333 control_behavior: Some(control),
334 orientation: None,
335 items: None,
336 recipe: None,
337 bar: None,
338 inventory: None,
339 infinity_settings: None,
340 type_: None,
341 input_priority: None,
342 output_priority: None,
343 filter: None,
344 filters: None,
345 filter_mode: None,
346 override_stack_size: None,
347 drop_position: None,
348 pickup_position: None,
349 request_filters: None,
350 request_from_buffers: None,
351 parameters: None,
352 alert_parameters: None,
353 auto_launch: None,
354 variation: None,
355 color: None,
356 station: None,
357 })
358 .collect::<Vec<_>>()
359 })
360 .map(|vec| vec.into_iter())
361 .flatten()
362 .collect::<Vec<_>>();
363
364 Blueprint {
365 item: "blueprint".to_owned(),
366 label: "auto generated".to_owned(),
367 label_color: None,
368 entities,
369 tiles: vec![],
370 icons: vec![],
371 schedules: vec![],
372 version: 1u64 << (64 - 16) | 1u64 << (64 - 32) | 46u64 << (64 - 16) | 59110u64,
373 }
374}