use std::collections::HashMap;
use std::io;
use std::io::Read;
use factorio_blueprint::objects::{
Blueprint, ControlBehavior, ControlFilter, Entity, EntityConnections, EntityNumber,
OneBasedIndex, Position, SignalID, SignalIDType,
};
use itertools::Itertools;
use noisy_float::types::R64;
pub const SIGNALS: [(&str, SignalIDType); 256] = [
("signal-1", SignalIDType::Virtual),
("signal-2", SignalIDType::Virtual),
("signal-3", SignalIDType::Virtual),
("signal-4", SignalIDType::Virtual),
("signal-5", SignalIDType::Virtual),
("signal-6", SignalIDType::Virtual),
("signal-7", SignalIDType::Virtual),
("signal-8", SignalIDType::Virtual),
("signal-9", SignalIDType::Virtual),
("signal-0", SignalIDType::Virtual),
("signal-A", SignalIDType::Virtual),
("signal-B", SignalIDType::Virtual),
("signal-C", SignalIDType::Virtual),
("signal-D", SignalIDType::Virtual),
("signal-E", SignalIDType::Virtual),
("signal-F", SignalIDType::Virtual),
("signal-G", SignalIDType::Virtual),
("signal-H", SignalIDType::Virtual),
("signal-I", SignalIDType::Virtual),
("signal-J", SignalIDType::Virtual),
("signal-K", SignalIDType::Virtual),
("signal-L", SignalIDType::Virtual),
("signal-M", SignalIDType::Virtual),
("signal-N", SignalIDType::Virtual),
("signal-O", SignalIDType::Virtual),
("signal-P", SignalIDType::Virtual),
("signal-Q", SignalIDType::Virtual),
("signal-R", SignalIDType::Virtual),
("signal-S", SignalIDType::Virtual),
("signal-T", SignalIDType::Virtual),
("signal-U", SignalIDType::Virtual),
("signal-V", SignalIDType::Virtual),
("signal-W", SignalIDType::Virtual),
("signal-X", SignalIDType::Virtual),
("signal-Y", SignalIDType::Virtual),
("signal-Z", SignalIDType::Virtual),
("signal-red", SignalIDType::Virtual),
("signal-green", SignalIDType::Virtual),
("signal-blue", SignalIDType::Virtual),
("signal-yellow", SignalIDType::Virtual),
("signal-pink", SignalIDType::Virtual),
("signal-cyan", SignalIDType::Virtual),
("signal-check", SignalIDType::Virtual),
("signal-info", SignalIDType::Virtual),
("signal-dot", SignalIDType::Virtual),
("water", SignalIDType::Fluid),
("crude-oil", SignalIDType::Fluid),
("steam", SignalIDType::Fluid),
("heavy-oil", SignalIDType::Fluid),
("light-oil", SignalIDType::Fluid),
("petroleum-gas", SignalIDType::Fluid),
("sulfuric-acid", SignalIDType::Fluid),
("lubricant", SignalIDType::Fluid),
("wooden-chest", SignalIDType::Item),
("iron-chest", SignalIDType::Item),
("steel-chest", SignalIDType::Item),
("storage-tank", SignalIDType::Item),
("transport-belt", SignalIDType::Item),
("fast-transport-belt", SignalIDType::Item),
("express-transport-belt", SignalIDType::Item),
("underground-belt", SignalIDType::Item),
("fast-underground-belt", SignalIDType::Item),
("express-underground-belt", SignalIDType::Item),
("splitter", SignalIDType::Item),
("fast-splitter", SignalIDType::Item),
("express-splitter", SignalIDType::Item),
("burner-inserter", SignalIDType::Item),
("inserter", SignalIDType::Item),
("long-handed-inserter", SignalIDType::Item),
("fast-inserter", SignalIDType::Item),
("filter-inserter", SignalIDType::Item),
("stack-inserter", SignalIDType::Item),
("stack-filter-inserter", SignalIDType::Item),
("small-electric-pole", SignalIDType::Item),
("medium-electric-pole", SignalIDType::Item),
("big-electric-pole", SignalIDType::Item),
("substation", SignalIDType::Item),
("pipe", SignalIDType::Item),
("pipe-to-ground", SignalIDType::Item),
("pump", SignalIDType::Item),
("rail", SignalIDType::Item),
("train-stop", SignalIDType::Item),
("rail-signal", SignalIDType::Item),
("rail-chain-signal", SignalIDType::Item),
("locomotive", SignalIDType::Item),
("cargo-wagon", SignalIDType::Item),
("fluid-wagon", SignalIDType::Item),
("artillery-wagon", SignalIDType::Item),
("car", SignalIDType::Item),
("tank", SignalIDType::Item),
("spidertron", SignalIDType::Item),
("spidertron-remote", SignalIDType::Item),
("logistic-robot", SignalIDType::Item),
("construction-robot", SignalIDType::Item),
("logistic-chest-active-provider", SignalIDType::Item),
("logistic-chest-passive-provider", SignalIDType::Item),
("logistic-chest-storage", SignalIDType::Item),
("logistic-chest-buffer", SignalIDType::Item),
("logistic-chest-requester", SignalIDType::Item),
("roboport", SignalIDType::Item),
("small-lamp", SignalIDType::Item),
("red-wire", SignalIDType::Item),
("green-wire", SignalIDType::Item),
("arithmetic-combinator", SignalIDType::Item),
("decider-combinator", SignalIDType::Item),
("constant-combinator", SignalIDType::Item),
("power-switch", SignalIDType::Item),
("programmable-speaker", SignalIDType::Item),
("stone-brick", SignalIDType::Item),
("concrete", SignalIDType::Item),
("hazard-concrete", SignalIDType::Item),
("refined-concrete", SignalIDType::Item),
("refined-hazard-concrete", SignalIDType::Item),
("landfill", SignalIDType::Item),
("cliff-explosives", SignalIDType::Item),
("repair-pack", SignalIDType::Item),
("blueprint", SignalIDType::Item),
("deconstruction-planner", SignalIDType::Item),
("upgrade-planner", SignalIDType::Item),
("blueprint-book", SignalIDType::Item),
("boiler", SignalIDType::Item),
("steam-engine", SignalIDType::Item),
("solar-panel", SignalIDType::Item),
("accumulator", SignalIDType::Item),
("nuclear-reactor", SignalIDType::Item),
("heat-pipe", SignalIDType::Item),
("heat-exchanger", SignalIDType::Item),
("steam-turbine", SignalIDType::Item),
("burner-mining-drill", SignalIDType::Item),
("electric-mining-drill", SignalIDType::Item),
("offshore-pump", SignalIDType::Item),
("pumpjack", SignalIDType::Item),
("stone-furnace", SignalIDType::Item),
("steel-furnace", SignalIDType::Item),
("electric-furnace", SignalIDType::Item),
("assembling-machine-1", SignalIDType::Item),
("assembling-machine-2", SignalIDType::Item),
("assembling-machine-3", SignalIDType::Item),
("oil-refinery", SignalIDType::Item),
("chemical-plant", SignalIDType::Item),
("centrifuge", SignalIDType::Item),
("lab", SignalIDType::Item),
("beacon", SignalIDType::Item),
("speed-module", SignalIDType::Item),
("speed-module-2", SignalIDType::Item),
("speed-module-3", SignalIDType::Item),
("effectivity-module", SignalIDType::Item),
("effectivity-module-2", SignalIDType::Item),
("effectivity-module-3", SignalIDType::Item),
("productivity-module", SignalIDType::Item),
("productivity-module-2", SignalIDType::Item),
("productivity-module-3", SignalIDType::Item),
("wood", SignalIDType::Item),
("coal", SignalIDType::Item),
("stone", SignalIDType::Item),
("iron-ore", SignalIDType::Item),
("copper-ore", SignalIDType::Item),
("uranium-ore", SignalIDType::Item),
("raw-fish", SignalIDType::Item),
("iron-plate", SignalIDType::Item),
("copper-plate", SignalIDType::Item),
("solid-fuel", SignalIDType::Item),
("steel-plate", SignalIDType::Item),
("plastic-bar", SignalIDType::Item),
("sulfur", SignalIDType::Item),
("battery", SignalIDType::Item),
("explosives", SignalIDType::Item),
("crude-oil-barrel", SignalIDType::Item),
("heavy-oil-barrel", SignalIDType::Item),
("light-oil-barrel", SignalIDType::Item),
("lubricant-barrel", SignalIDType::Item),
("petroleum-gas-barrel", SignalIDType::Item),
("sulfuric-acid-barrel", SignalIDType::Item),
("water-barrel", SignalIDType::Item),
("copper-cable", SignalIDType::Item),
("iron-stick", SignalIDType::Item),
("iron-gear-wheel", SignalIDType::Item),
("empty-barrel", SignalIDType::Item),
("electronic-circuit", SignalIDType::Item),
("advanced-circuit", SignalIDType::Item),
("processing-unit", SignalIDType::Item),
("engine-unit", SignalIDType::Item),
("electric-engine-unit", SignalIDType::Item),
("flying-robot-frame", SignalIDType::Item),
("satellite", SignalIDType::Item),
("rocket-control-unit", SignalIDType::Item),
("low-density-structure", SignalIDType::Item),
("rocket-fuel", SignalIDType::Item),
("nuclear-fuel", SignalIDType::Item),
("uranium-235", SignalIDType::Item),
("uranium-238", SignalIDType::Item),
("uranium-fuel-cell", SignalIDType::Item),
("used-up-uranium-fuel-cell", SignalIDType::Item),
("automation-science-pack", SignalIDType::Item),
("logistic-science-pack", SignalIDType::Item),
("military-science-pack", SignalIDType::Item),
("chemical-science-pack", SignalIDType::Item),
("production-science-pack", SignalIDType::Item),
("utility-science-pack", SignalIDType::Item),
("space-science-pack", SignalIDType::Item),
("pistol", SignalIDType::Item),
("submachine-gun", SignalIDType::Item),
("shotgun", SignalIDType::Item),
("combat-shotgun", SignalIDType::Item),
("rocket-launcher", SignalIDType::Item),
("flamethrower", SignalIDType::Item),
("land-mine", SignalIDType::Item),
("firearm-magazine", SignalIDType::Item),
("piercing-rounds-magazine", SignalIDType::Item),
("uranium-rounds-magazine", SignalIDType::Item),
("shotgun-shell", SignalIDType::Item),
("piercing-shotgun-shell", SignalIDType::Item),
("cannon-shell", SignalIDType::Item),
("explosive-cannon-shell", SignalIDType::Item),
("uranium-cannon-shell", SignalIDType::Item),
("explosive-uranium-cannon-shell", SignalIDType::Item),
("artillery-shell", SignalIDType::Item),
("rocket", SignalIDType::Item),
("explosive-rocket", SignalIDType::Item),
("atomic-bomb", SignalIDType::Item),
("flamethrower-ammo", SignalIDType::Item),
("grenade", SignalIDType::Item),
("cluster-grenade", SignalIDType::Item),
("poison-capsule", SignalIDType::Item),
("slowdown-capsule", SignalIDType::Item),
("defender-capsule", SignalIDType::Item),
("distractor-capsule", SignalIDType::Item),
("destroyer-capsule", SignalIDType::Item),
("light-armor", SignalIDType::Item),
("heavy-armor", SignalIDType::Item),
("modular-armor", SignalIDType::Item),
("power-armor", SignalIDType::Item),
("power-armor-mk2", SignalIDType::Item),
("solar-panel-equipment", SignalIDType::Item),
("fusion-reactor-equipment", SignalIDType::Item),
("battery-equipment", SignalIDType::Item),
("battery-mk2-equipment", SignalIDType::Item),
("belt-immunity-equipment", SignalIDType::Item),
("exoskeleton-equipment", SignalIDType::Item),
("personal-roboport-equipment", SignalIDType::Item),
("personal-roboport-mk2-equipment", SignalIDType::Item),
("night-vision-equipment", SignalIDType::Item),
("energy-shield-equipment", SignalIDType::Item),
("energy-shield-mk2-equipment", SignalIDType::Item),
("personal-laser-defense-equipment", SignalIDType::Item),
("discharge-defense-equipment", SignalIDType::Item),
("discharge-defense-remote", SignalIDType::Item),
("stone-wall", SignalIDType::Item),
("gate", SignalIDType::Item),
("gun-turret", SignalIDType::Item),
("laser-turret", SignalIDType::Item),
("flamethrower-turret", SignalIDType::Item),
("artillery-turret", SignalIDType::Item),
("artillery-targeting-remote", SignalIDType::Item),
("radar", SignalIDType::Item),
("rocket-silo", SignalIDType::Item),
];
pub fn pack_read<R: Read>(mut from: R) -> Result<Blueprint, io::Error> {
let mut buf = Vec::new();
from.read_to_end(&mut buf)?;
let chunks = buf
.iter()
.chunks(4);
let mut words = chunks
.into_iter()
.map(|word| {
let (b1, b2, b3, b4) = word.pad_using(4, |_| &0).cloned().collect_tuple().unwrap();
u32::from_le_bytes([b1, b2, b3, b4])
});
Ok(pack(&mut words))
}
pub fn pack<I: Iterator<Item = u32>>(iter: &mut I) -> Blueprint {
let entities = iter
.chunks(SIGNALS.len())
.into_iter()
.enumerate()
.map(move |(cluster_n, words)| {
words
.zip(SIGNALS.into_iter())
.chunks(20)
.into_iter()
.map(|signals| {
let filters = signals
.enumerate()
.map(|(signal_n, (word, (signal, signal_type)))| {
ControlFilter {
signal: SignalID { name: signal.to_owned(), type_: signal_type },
index: OneBasedIndex::new(signal_n + 1).unwrap(),
count: i32::from_le_bytes(word.to_le_bytes()),
}
})
.collect::<Vec<_>>();
ControlBehavior {
arithmetic_conditions: None,
decider_conditions: None,
filters: Some(filters),
is_on: Some(true),
}
})
.enumerate()
.map(move |(ent_n, control)| Entity {
entity_number: EntityNumber::new((&cluster_n + 1) * (ent_n + 1)).unwrap(),
name: "constant-combinator".to_owned(),
position: {
let n = &ent_n % 7;
let r = &ent_n / 7 + &cluster_n * 2;
Position { x: R64::new(r as f64), y: R64::new(n as f64) }
},
direction: Some(4), connections: Some(EntityConnections::NumberIdx(HashMap::new())),
control_behavior: Some(control),
orientation: None,
items: None,
recipe: None,
bar: None,
inventory: None,
infinity_settings: None,
type_: None,
input_priority: None,
output_priority: None,
filter: None,
filters: None,
filter_mode: None,
override_stack_size: None,
drop_position: None,
pickup_position: None,
request_filters: None,
request_from_buffers: None,
parameters: None,
alert_parameters: None,
auto_launch: None,
variation: None,
color: None,
station: None,
})
.collect::<Vec<_>>()
})
.map(|vec| vec.into_iter())
.flatten()
.collect::<Vec<_>>();
Blueprint {
item: "blueprint".to_owned(),
label: "auto generated".to_owned(),
label_color: None,
entities,
tiles: vec![],
icons: vec![],
schedules: vec![],
version: 1u64 << (64 - 16) | 1u64 << (64 - 32) | 46u64 << (64 - 16) | 59110u64,
}
}