1use bobbin_bits::U4::{self, B0000, B0001, B0010, B0100, B1000};
5use std::error::Error;
6use std::fmt;
7
8use crate::data::dynamic::{DynData, DynType};
9use crate::data::map::Build;
10use crate::data::{self, renderer::*, CompressError};
11use crate::data::{DataRead, GridPos, ReadError as DataReadError};
12use crate::item::storage::ItemStorage;
13
14macro_rules! mods {
15 ($($mod:ident)*) => {
16 $(pub mod $mod;)*
17
18 mod all {
19 $(#[allow(unused_imports)] pub use crate::block::$mod::*;)*
20 pub use super::simple::BasicBlock;
21 }
22 }
23}
24
25mods! {
26 content defense distribution drills liquid logic payload power production turrets walls units
27}
28
29pub mod ratios;
30mod simple;
31use simple::*;
32
33macro_rules! disp {
34 ($($k:ident,)+) => {
35 use all::{$($k,)+};
36 #[enum_dispatch::enum_dispatch]
37 pub(crate) enum BlockLogicEnum {
38 $($k,)+
39 }
40
41 impl ratios::Ratios for BlockLogicEnum {
42 fn io(&self, state: Option<&State>, name: &str) -> ratios::Io {
43 match self {
44 $(Self::$k(x) => x.io(state, name),)+
45 }
46 }
47 }
48
49 #[const_trait]
50 pub trait ConstFrom<T>: Sized {
51 fn fro(value: T) -> Self;
52 }
53 $(
54 impl const ConstFrom<$k> for BlockLogicEnum {
55 fn fro(v: $k) -> Self {
56 BlockLogicEnum::$k(v)
57 }
58 }
59 )+
60
61 }
69}
70
71disp! {
72 BasicBlock,
73 WallBlock,
74 DuctBlock,
75 BridgeBlock,
76 ItemBlock,
77 ProductionBlock,
78 SeparatorBlock,
79 StackConveyor,
80 HeatCrafter,
81 ConnectorBlock,
82 ItemTurret,
83 ConveyorBlock,
84 PayloadRouter,
85 WallDrillBlock,
86 DrillBlock,
87 NuclearGeneratorBlock,
88 GeneratorBlock,
89 ConduitBlock,
90 HeatedBlock,
91 RadarBlock,
92 ShieldBlock,
93 PointDefenseTurret,
94 JunctionBlock,
95 Turret,
96 MemoryBlock,
97 MessageLogic,
98 ConstructorBlock,
99 AssemblerBlock,
100 UnitFactory,
101 SimpleDuctBlock,
102 SurgeRouter,
103 SimplePayloadBlock,
104 PayloadConveyor,
105 ImpactReactorBlock,
106 Neoplasia,
107 DiodeBlock,
108 HeatConduit,
109 ContinousTurret,
110 TractorBeamTurret,
111 AssemblerModule,
112 RepairTurret,
113 FluidBlock,
114 CanvasBlock,
115 SwitchLogic,
116 ProcessorLogic,
117 PayloadBlock,
118 LampBlock,
119 UnitCargoLoader,
120 DoorBlock,
121}
122
123pub trait Cast {
124 fn downcast_ref(state: &State) -> Option<&Self>;
125 fn downcast_mut(state: &mut State) -> Option<&mut Self>;
126}
127
128macro_rules! stater {
129 ($($k: ident($v: ty),)+) => {
130 #[derive(Debug, Clone)]
131 pub enum State {
132 $($k($v),)+
133 }
134
135 $(
136 impl From<$v> for State {
137 fn from(v: $v) -> State { State::$k(v) }
138 }
139
140 impl Cast for $v {
141 fn downcast_ref(state: &State) -> Option<&Self> {
142 match state {
143 State::$k(v) => Some(v),
144 _ => None,
145 }
146 }
147 fn downcast_mut(state: &mut State) -> Option<&mut Self> {
148 match state {
149 State::$k(v) => Some(v),
150 _ => None,
151 }
152 }
153 }
154 )+
155 }
156}
157
158stater! {
159 String(String),
161 Item(Option<crate::item::Type>),
162 Fluid(Option<crate::fluid::Type>),
163 Image(Image<Box<[u8]>, 1>),
164 Point(Option<(i32, i32)>),
165 Bool(bool),
166 Processor(logic::ProcessorState),
167 Payload(payload::Payload),
168 Power(Vec<(i16, i16)>),
169 Color(power::Rgba),
170 Command(Option<crate::data::command::UnitCommand>),
171 Unit(Option<crate::unit::Type>),
172}
173
174impl State {
175 pub fn downcast_ref<T: Cast>(&self) -> Option<&T> {
176 T::downcast_ref(self)
177 }
178
179 pub fn downcast_mut<T: Cast>(&mut self) -> Option<&mut T> {
180 T::downcast_mut(self)
181 }
182
183 pub fn new<T: Into<Self>>(from: T) -> Self {
184 from.into()
185 }
186}
187
188#[enum_dispatch::enum_dispatch(BlockLogicEnum)]
189pub trait BlockLogic: ratios::Ratios {
190 fn get_size(&self) -> u8;
192
193 fn is_symmetric(&self) -> bool;
194
195 fn create_build_cost(&self) -> Option<ItemStorage>;
196
197 fn data_from_i32(&self, config: i32, pos: GridPos) -> Result<DynData, DataConvertError>;
198
199 fn deserialize_state(&self, data: DynData) -> Result<Option<State>, DeserializeError>;
200
201 #[allow(unused_variables)]
202 fn mirror_state(&self, state: &mut State, horizontally: bool, vertically: bool) {}
203
204 #[allow(unused_variables)]
205 fn rotate_state(&self, state: &mut State, clockwise: bool) {}
206
207 fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError>;
208
209 #[allow(unused_variables)]
210 fn draw(
211 &self,
212 name: &str,
213 state: Option<&State>,
214 context: Option<&RenderingContext>,
215 rot: Rotation,
216 scale: Scale,
217 ) -> ImageHolder<4> {
218 unimplemented!("{name}")
219 }
220
221 #[allow(unused_variables)]
222 fn read(&self, build: &mut Build, buff: &mut DataRead) -> Result<(), DataReadError> {
223 Ok(())
224 }
225}
226
227macro_rules! impl_block {
229 () => {
230 fn get_size(&self) -> u8 {
231 self.size
232 }
233
234 fn is_symmetric(&self) -> bool {
235 self.symmetric
236 }
237
238 fn create_build_cost(&self) -> Option<$crate::item::storage::ItemStorage> {
239 if self.build_cost.is_empty() {
240 None
241 } else {
242 let mut storage = crate::item::storage::Storage::new();
243 for (ty, cnt) in self.build_cost {
244 storage.add(*ty, *cnt, u32::MAX);
245 }
246 Some(storage)
247 }
248 }
249 };
250}
251pub(crate) use impl_block;
252
253#[derive(Debug, thiserror::Error)]
254pub enum DataConvertError {
255 #[error(transparent)]
256 Custom(#[from] Box<dyn Error + Sync + Send>),
257}
258
259impl DataConvertError {
260 pub fn forward<T, E: Error + Sync + Send + 'static>(result: Result<T, E>) -> Result<T, Self> {
261 match result {
262 Ok(v) => Ok(v),
263 Err(e) => Err(Self::Custom(Box::new(e))),
264 }
265 }
266}
267
268#[derive(Debug, thiserror::Error)]
269pub enum DeserializeError {
270 #[error(transparent)]
271 DecompressError(#[from] data::DecompressError),
272 #[error("expected type {expect:?} but got {have:?}")]
273 InvalidType { have: DynType, expect: DynType },
274 #[error(transparent)]
275 Custom(#[from] Box<dyn Error + Sync + Send>),
276}
277
278impl DeserializeError {
279 pub fn forward<T, E: Error + Sync + Send + 'static>(result: Result<T, E>) -> Result<T, Self> {
280 match result {
281 Ok(v) => Ok(v),
282 Err(e) => Err(Self::Custom(Box::new(e))),
283 }
284 }
285}
286
287#[derive(Debug, thiserror::Error)]
288pub enum SerializeError {
289 #[error(transparent)]
290 Custom(#[from] Box<dyn Error + Sync + Send>),
291 #[error(transparent)]
292 Compress(#[from] CompressError),
293}
294
295impl SerializeError {
296 pub fn forward<T, E: Error + Sync + Send + 'static>(result: Result<T, E>) -> Result<T, Self> {
297 match result {
298 Ok(v) => Ok(v),
299 Err(e) => Err(Self::Custom(Box::new(e))),
300 }
301 }
302}
303
304pub struct Block {
306 image: Option<[Image<&'static [u8], 4>; 3]>,
307 name: &'static str,
308 logic: BlockLogicEnum,
309}
310
311impl PartialEq for Block {
312 fn eq(&self, rhs: &Block) -> bool {
313 self.name == rhs.name
314 }
315}
316
317impl Block {
318 #[must_use]
320 #[inline]
321 pub(crate) const fn new(
322 name: &'static str,
323 logic: BlockLogicEnum,
324 image: Option<[Image<&'static [u8], 4>; 3]>,
325 ) -> Self {
326 Self { image, name, logic }
327 }
328
329 #[must_use]
334 #[inline]
335 pub const fn name(&self) -> &'static str {
336 self.name
337 }
338
339 pub fn io(&self, state: Option<&State>) -> ratios::Io {
340 <BlockLogicEnum as ratios::Ratios>::io(&self.logic, state, self.name)
341 }
342
343 #[must_use]
345 #[inline]
346 pub const fn wants_context(&self) -> bool {
347 use BlockLogicEnum::*;
348 matches!(
349 self.logic,
350 ConveyorBlock(..) | DuctBlock(..) | StackConveyor(..) | ConduitBlock(..)
351 )
352 }
353
354 #[must_use]
356 #[inline]
357 pub fn image(
358 &self,
359 state: Option<&State>,
360 context: Option<&RenderingContext>,
361 rot: Rotation,
362 scale: Scale,
363 ) -> ImageHolder<4> {
364 if let Some(imgs) = &self.image {
365 return ImageHolder::from((imgs[scale as usize]).copy());
366 }
367 self.logic.draw(self.name, state, context, rot, scale)
368 }
369
370 #[must_use]
372 #[inline]
373 pub fn get_size(&self) -> u8 {
374 self.logic.get_size()
375 }
376
377 #[must_use]
379 #[inline]
380 pub fn is_symmetric(&self) -> bool {
381 self.logic.is_symmetric()
382 }
383
384 #[must_use]
386 #[inline]
387 pub fn get_build_cost(&self) -> Option<ItemStorage> {
388 self.logic.create_build_cost()
389 }
390
391 pub(crate) fn data_from_i32(
392 &self,
393 config: i32,
394 pos: GridPos,
395 ) -> Result<DynData, DataConvertError> {
396 self.logic.data_from_i32(config, pos)
397 }
398
399 pub(crate) fn deserialize_state(
400 &self,
401 data: DynData,
402 ) -> Result<Option<State>, DeserializeError> {
403 self.logic.deserialize_state(data)
404 }
405
406 pub(crate) fn mirror_state(&self, state: &mut State, horizontally: bool, vertically: bool) {
407 self.logic.mirror_state(state, horizontally, vertically);
408 }
409
410 pub(crate) fn rotate_state(&self, state: &mut State, clockwise: bool) {
411 self.logic.rotate_state(state, clockwise);
412 }
413
414 pub(crate) fn serialize_state(&self, state: &State) -> Result<DynData, SerializeError> {
415 self.logic.serialize_state(state)
416 }
417
418 #[inline]
419 pub(crate) fn read(&self, build: &mut Build, buff: &mut DataRead) -> Result<(), DataReadError> {
420 self.logic.read(build, buff)
421 }
422}
423
424impl fmt::Debug for Block {
425 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
426 write!(f, "Block<{:?}>", self.name)
427 }
428}
429
430#[derive(Clone, Copy, Debug, Eq, PartialEq)]
431#[repr(u8)]
433pub enum Rotation {
434 Up,
435 Right,
436 Down,
437 Left,
438}
439
440impl Rotation {
441 #[must_use]
442 pub const fn count(self) -> u8 {
444 self as u8
445 }
446
447 #[must_use]
448 pub const fn mask(self) -> U4 {
450 match self {
451 Rotation::Up => B1000,
452 Rotation::Right => B0100,
453 Rotation::Down => B0010,
454 Rotation::Left => B0001,
455 }
456 }
457
458 #[must_use]
459 pub const fn ch(self) -> char {
461 match self {
462 Rotation::Right => '>',
463 Rotation::Up => '^',
464 Rotation::Left => '<',
465 Rotation::Down => 'v',
466 }
467 }
468
469 #[must_use]
470 pub const fn mirrored(self, horizontally: bool, vertically: bool) -> Self {
472 match self {
473 Self::Right => {
474 if horizontally {
475 Self::Left
476 } else {
477 Self::Right
478 }
479 }
480 Self::Up => {
481 if vertically {
482 Self::Down
483 } else {
484 Self::Up
485 }
486 }
487 Self::Left => {
488 if horizontally {
489 Self::Right
490 } else {
491 Self::Left
492 }
493 }
494 Self::Down => {
495 if vertically {
496 Self::Up
497 } else {
498 Self::Down
499 }
500 }
501 }
502 }
503
504 pub fn mirror(&mut self, horizontally: bool, vertically: bool) {
506 *self = self.mirrored(horizontally, vertically);
507 }
508
509 #[must_use]
510 pub const fn rotated(self, clockwise: bool) -> Self {
512 match self {
513 Self::Right => {
514 if clockwise {
515 Self::Down
516 } else {
517 Self::Up
518 }
519 }
520 Self::Up => {
521 if clockwise {
522 Self::Right
523 } else {
524 Self::Left
525 }
526 }
527 Self::Left => {
528 if clockwise {
529 Self::Up
530 } else {
531 Self::Down
532 }
533 }
534 Self::Down => {
535 if clockwise {
536 Self::Left
537 } else {
538 Self::Right
539 }
540 }
541 }
542 }
543
544 pub fn rotate(&mut self, clockwise: bool) {
546 *self = self.rotated(clockwise);
547 }
548
549 #[must_use]
550 pub const fn rotated_180(self) -> Self {
552 match self {
553 Self::Right => Self::Left,
554 Self::Up => Self::Down,
555 Self::Left => Self::Right,
556 Self::Down => Self::Up,
557 }
558 }
559
560 pub fn rotate_180(&mut self) {
562 *self = self.rotated_180();
563 }
564}
565
566impl From<u8> for Rotation {
567 fn from(val: u8) -> Self {
568 match val & 3 {
569 0 => Self::Right,
570 1 => Self::Up,
571 2 => Self::Left,
572 _ => Self::Down,
573 }
574 }
575}
576
577impl From<Rotation> for u8 {
578 fn from(rot: Rotation) -> Self {
579 match rot {
580 Rotation::Right => 0,
581 Rotation::Up => 1,
582 Rotation::Left => 2,
583 Rotation::Down => 3,
584 }
585 }
586}
587
588macro_rules! make_register {
589 ($($field:literal $op:tt $logic:expr;)+) => { paste::paste! {
590 $(
591 make_register!(impl $field $op $logic);
592 )+
593 pub static BLOCK_REGISTRY: phf::Map<&str, &Block> = phf::phf_map! {$(
594 $field => &[<$field:snake:upper>],
595 )+};
596
597 impl content::Type {
598 pub fn to_block(self) -> Option<&'static Block> {
599 match self {
602 $(content::Type::[<$field:camel>] => Some(&[<$field:snake:upper>]),)+
603 _ => None,
604 }
605 }
606 }
607 }};
608 (impl $field: literal => $logic: expr) => {
609 paste::paste! { pub static [<$field:snake:upper>]: Block = Block::new(
610 $field, <crate::block::BlockLogicEnum as crate::block::ConstFrom<_>>::fro($logic), None
611 ); }
612 };
613 (impl $field: literal -> $logic: expr) => {
614 paste::paste! { pub static [<$field:snake:upper>]: Block = Block::new(
615 $field, <crate::block::BlockLogicEnum as crate::block::ConstFrom<_>>::fro($logic), Some(crate::data::renderer::load!($field))
616 ); }
617 };
618 (impl $field: literal : $size: literal) => {
619 paste::paste! { pub static [<$field:snake:upper>]: Block = Block::new(
620 $field, BlockLogicEnum::BasicBlock(BasicBlock::new($size, true, &[])), Some(crate::data::renderer::load!($field))
621 ); }
622 };
623 (impl $field: literal > $size: literal) => {
625 paste::paste! { pub static [<$field:snake:upper>]: Block = Block::new(
626 $field, BlockLogicEnum::BasicBlock(BasicBlock::new($size, true, &[])), Some(crate::data::renderer::load!("empty4"))
627 ); }
628 };
629}
630make_register! {
632 "darksand" > 1;
633 "sand-floor" > 1;
634 "yellow-stone" > 1;
635 "arkyic-stone" > 1;
636 "carbon-stone" > 1;
637 "dacite" > 1;
638 "dirt" > 1;
639 "arkycite-floor" > 1;
640 "basalt" > 1;
641 "ice" > 1;
642 "molten-slag" > 1;
643 "moss" > 1;
644 "mud" > 1;
645 "magmarock" > 1;
646 "grass" > 1;
647 "ice-snow" > 1;
648 "hotrock" > 1;
649 "char" > 1;
650 "snow" > 1;
651 "salt" > 1;
652 "shale" > 1;
653 "metal-floor" > 1;
654 "metal-floor-2" > 1;
655 "metal-floor-3" > 1;
656 "metal-floor-4" > 1;
657 "metal-floor-5" > 1;
658 "dark-panel-1" > 1;
659 "dark-panel-2" > 1;
660 "dark-panel-3" > 1;
661 "dark-panel-4" > 1;
662 "dark-panel-5" > 1;
663 "dark-panel-6" > 1;
664 "darksand-tainted-water" > 1;
665 "darksand-water" > 1;
666 "deep-tainted-water" > 1;
667 "deep-water" > 1;
668 "sand-water" > 1;
669 "shallow-water" > 1;
670 "space" > 1;
671 "stone" > 1;
672 "arkyic-vent" > 1;
673 "beryllic-stone" > 1;
674 "bluemat" > 1;
675 "carbon-vent" > 1;
676 "core-zone" > 1;
677 "crater-stone" > 1;
678 "crystal-floor" > 1;
679 "crystalline-stone" > 1;
680 "crystalline-vent" > 1;
681 "metal-floor-damaged" > 1;
682 "dense-red-stone" > 1;
683 "ferric-craters" > 1; "ferric-stone" > 1;
685 "pooled-cryofluid" > 1;
686 "red-ice" > 1;
687 "red-stone-vent" > 1;
688 "red-stone" > 1;
689 "redmat" > 1;
690 "regolith" > 1;
691 "rhyolite-crater" > 1;
692 "rhyolite" > 1;
693 "rough-rhyolite" > 1;
694 "tainted-water" > 1;
695 "tar" > 1;
696 "yellow-stone-plates" > 1;
697 "yellow-stone-vent" > 1;
698 "spore-moss" > 1;
699 "ore-beryllium": 1;
700 "ore-copper": 1;
701 "ore-lead": 1;
702 "ore-coal": 1;
703 "ore-scrap": 1;
704 "ore-thorium": 1;
705 "ore-titanium": 1;
706 "ore-tungsten": 1;
707 "ore-crystal-thorium": 1;
708 "ore-wall-beryllium": 1;
709 "ore-wall-thorium": 1;
710 "ore-wall-tungsten": 1;
711 "graphitic-wall": 1;
712 "boulder": 1;
713 "arkyic-wall": 1;
714 "beryllic-stone-wall": 1;
715 "carbon-wall": 1;
716 "cliff": 1;
717 "crystalline-stone-wall": 1;
718 "dacite-wall": 1;
719 "dark-metal": 1;
720 "dirt-wall": 1;
721 "dune-wall": 1;
722 "ferric-stone-wall": 1;
723 "ice-wall": 1;
724 "pebbles": 1;
725 "pine": 1;
726 "red-diamond-wall": 1;
727 "red-ice-wall": 1;
728 "red-stone-wall": 1;
729 "regolith-wall": 1;
730 "rhyolite-vent" > 1;
731 "rhyolite-wall": 1;
732 "salt-wall": 1;
733 "sand-wall": 1;
734 "shale-wall": 1;
735 "shrubs": 1;
736 "snow-pine": 1;
737 "snow-wall": 1;
738 "spawn": 1;
739 "spore-pine": 1;
740 "spore-wall": 1;
741 "stone-wall": 1;
742 "yellow-stone-wall": 1;
743 "yellow-stone-boulder": 1;
745 "snow-boulder": 1;
746 "shale-boulder": 1;
747 "arkyic-boulder": 1;
748 "basalt-boulder": 1;
749 "beryllic-boulder": 1;
750 "carbon-boulder": 1;
751 "crystalline-boulder": 1;
752 "dacite-boulder": 1;
753 "ferric-boulder": 1;
754 "red-ice-boulder": 1;
755 "red-stone-boulder": 1;
756 "rhyolite-boulder": 1;
757 "sand-boulder": 1;
758 "pur-bush": 1;
759 "tendrils": 1;
760 "white-tree-dead": 1;
762 "yellowcoral": 1;
763 "white-tree": 1;
764 "redweed": 1;
765 "spore-cluster": 1;
766 "crystal-blocks": 1;
767 "crystal-cluster": 1;
768 "vibrant-crystal-cluster": 1;
769 "crystal-orbs": 1;
770 "build1": 1;
772 "build2": 1;
773 "build3": 1;
774 "build4": 1;
775 "build5": 1;
776 "build6": 1;
777 "build7": 1;
778 "build8": 1;
779 "build9": 1;
780 "build10": 1;
781 "build11": 1;
782 "build12": 1;
783 "build13": 1;
784 "build14": 1;
785 "build15": 1;
786 "build16": 1;
787 "conveyor" => ConveyorBlock::new(1, false, cost!(Copper: 1));
788 "titanium-conveyor" => ConveyorBlock::new(1, false, cost!(Copper: 1, Lead: 1, Titanium: 1));
789 "plastanium-conveyor" => StackConveyor::new(1, false, cost!(Graphite: 1, Silicon: 1, Plastanium: 1));
790 "armored-conveyor" => ConveyorBlock::new(1, false, cost!(Metaglass: 1, Thorium: 1, Plastanium: 1));
791 "junction" -> JunctionBlock::new(1, true, cost!(Copper: 2));
792 "bridge-conveyor" -> BridgeBlock::new(1, false, cost!(Copper: 6, Lead: 6), 4, true);
793 "phase-conveyor" -> BridgeBlock::new(1, false, cost!(Lead: 10, Graphite: 10, Silicon: 7, PhaseFabric: 5), 12, true);
794 "sorter" => ItemBlock::new(1, true, cost!(Copper: 2, Lead: 2));
795 "inverted-sorter" => ItemBlock::new(1, true, cost!(Copper: 2, Lead: 2));
796 "unloader" => ItemBlock::new(1, true, cost!(Titanium: 25, Silicon: 30));
797 "router" -> BasicBlock::new(1, true, cost!(Copper: 3));
798 "distributor" -> BasicBlock::new(2, true, cost!(Copper: 4, Lead: 4));
799 "overflow-gate" -> BasicBlock::new(1, true, cost!(Copper: 4, Lead: 2));
800 "underflow-gate" -> BasicBlock::new(1, true, cost!(Copper: 4, Lead: 2));
801 "mass-driver" => BridgeBlock::new(3, true, cost!(Lead: 125, Titanium: 125, Thorium: 50, Silicon: 75), 55, false);
802 "duct" => DuctBlock::new(1, false, cost!(Beryllium: 1));
803 "armored-duct" => DuctBlock::new(1, false, cost!(Beryllium: 2, Tungsten: 1));
804 "duct-router" => ItemBlock::new(1, true, cost!(Beryllium: 10));
805 "overflow-duct" => SimpleDuctBlock::new(1, true, cost!(Graphite: 8, Beryllium: 8));
806 "underflow-duct" => SimpleDuctBlock::new(1, true, cost!(Graphite: 8, Beryllium: 8));
807 "duct-bridge" => BridgeBlock::new(1, true, cost!(Beryllium: 20), 3, true);
808 "duct-unloader" => ItemBlock::new(1, true, cost!(Graphite: 20, Silicon: 20, Tungsten: 10));
809 "surge-conveyor" => StackConveyor::new(1, false, cost!(SurgeAlloy: 1, Tungsten: 1));
810 "surge-router" => SurgeRouter::new(1, false, cost!(SurgeAlloy: 5, Tungsten: 1)); "unit-cargo-loader" -> UnitCargoLoader::new(3, true, cost!(Silicon: 80, SurgeAlloy: 50, Oxide: 20));
812 "unit-cargo-unload-point" => ItemBlock::new(2, true, cost!(Silicon: 60, Tungsten: 60));
813 "cultivator" -> ProductionBlock::new(2, true, cost!(Copper: 25, Lead: 25, Silicon: 10));
814 "graphite-press" -> ProductionBlock::new(2, true, cost!(Copper: 75, Lead: 30));
815 "multi-press" -> ProductionBlock::new(3, true, cost!(Lead: 100, Graphite: 50, Titanium: 100, Silicon: 25));
816 "silicon-smelter" -> ProductionBlock::new(2, true, cost!(Copper: 30, Lead: 25));
817 "silicon-crucible" -> ProductionBlock::new(3, true, cost!(Metaglass: 80, Titanium: 120, Silicon: 60, Plastanium: 35));
818 "kiln" -> ProductionBlock::new(2, true, cost!(Copper: 60, Lead: 30, Graphite: 30));
819 "plastanium-compressor" -> ProductionBlock::new(2, true, cost!(Lead: 115, Graphite: 60, Titanium: 80, Silicon: 80));
820 "phase-weaver" -> ProductionBlock::new(2, true, cost!(Lead: 120, Thorium: 75, Silicon: 130));
821 "surge-smelter" -> ProductionBlock::new(3, true, cost!(Lead: 80, Thorium: 70, Silicon: 80));
822 "cryofluid-mixer" -> ProductionBlock::new(2, true, cost!(Lead: 65, Titanium: 60, Silicon: 40));
823 "pyratite-mixer" -> ProductionBlock::new(2, true, cost!(Copper: 50, Lead: 25));
824 "blast-mixer" -> ProductionBlock::new(2, true, cost!(Lead: 30, Titanium: 20));
825 "melter" -> ProductionBlock::new(1, true, cost!(Copper: 30, Lead: 35, Graphite: 45));
826 "separator" -> SeparatorBlock::new(2, true, cost!(Copper: 30, Titanium: 25));
827 "disassembler" -> SeparatorBlock::new(3, true, cost!(Titanium: 100, Thorium: 80, Silicon: 150, Plastanium: 40));
828 "spore-press" -> ProductionBlock::new(2, true, cost!(Lead: 35, Silicon: 30));
829 "pulverizer" -> ProductionBlock::new(1, true, cost!(Copper: 30, Lead: 25));
830 "coal-centrifuge" -> ProductionBlock::new(2, true, cost!(Lead: 30, Graphite: 40, Titanium: 20));
831 "incinerator" -> BasicBlock::new(1, true, cost!(Lead: 15, Graphite: 5));
832 "silicon-arc-furnace" -> ProductionBlock::new(3, true, cost!(Beryllium: 70, Graphite: 80));
833 "electrolyzer" => ProductionBlock::new(3, true, cost!(Silicon: 50, Graphite: 40, Beryllium: 130, Tungsten: 80));
834 "atmospheric-concentrator" -> ProductionBlock::new(3, true, cost!(Oxide: 60, Beryllium: 180, Silicon: 150));
835 "oxidation-chamber" => HeatCrafter::new(3, true, cost!(Tungsten: 120, Graphite: 80, Silicon: 100, Beryllium: 120));
836 "electric-heater" => HeatCrafter::new(2, false, cost!(Tungsten: 30, Oxide: 30));
837 "slag-heater" => HeatCrafter::new(3, false, cost!(Tungsten: 50, Oxide: 20, Beryllium: 20));
838 "phase-heater" => HeatCrafter::new(2, false, cost!(Oxide: 30, Carbide: 30, Beryllium: 30));
839 "heat-redirector" => HeatConduit::new(3, false, cost!(Tungsten: 10, Graphite: 10));
840 "small-heat-redirector" => HeatConduit::new(2, false, cost!(SurgeAlloy: 8, Graphite: 8));
841 "heat-router" => HeatConduit::new(3, false, cost!(Tungsten: 15, Graphite: 10));
842 "slag-incinerator" -> BasicBlock::new(1, true, cost!(Tungsten: 15));
843 "carbide-crucible" -> ProductionBlock::new(3, true, cost!(Tungsten: 110, Thorium: 150, Oxide: 60));
844 "surge-crucible" -> ProductionBlock::new(3, true, cost!(Silicon: 100, Graphite: 80, Tungsten: 80, Oxide: 80));
846 "cyanogen-synthesizer" -> ProductionBlock::new(3, true, cost!(Carbide: 50, Silicon: 80, Beryllium: 90));
847 "phase-synthesizer" -> ProductionBlock::new(3, true, cost!(Carbide: 90, Silicon: 100, Thorium: 100, Tungsten: 200));
848 "payload-conveyor" => PayloadConveyor::new(3, false, cost!(Copper: 10, Graphite: 10));
850 "payload-router" => PayloadRouter::new(3, false, cost!(Copper: 10, Graphite: 15));
851 "reinforced-payload-conveyor" => PayloadConveyor::new(3, false, cost!(Tungsten: 10));
852 "reinforced-payload-router" => PayloadRouter::new(3, false, cost!(Tungsten: 15));
853 "payload-mass-driver" -> BridgeBlock::new(3, true, cost!(Tungsten: 120, Silicon: 120, Graphite: 50), 700, false);
854 "large-payload-mass-driver" -> BridgeBlock::new(5, true, cost!(Thorium: 200, Tungsten: 200, Silicon: 200, Graphite: 100, Oxide: 30), 1100, false);
855 "small-deconstructor" => SimplePayloadBlock::new(3, true, cost!(Beryllium: 100, Silicon: 100, Oxide: 40, Graphite: 80));
856 "deconstructor" => SimplePayloadBlock::new(5, true, cost!(Beryllium: 250, Oxide: 100, Silicon: 250, Carbide: 250));
857 "constructor" => PayloadBlock::new(3, true, cost!(Silicon: 100, Beryllium: 150, Tungsten: 80));
858 "large-constructor" => PayloadBlock::new(5, true, cost!(Silicon: 150, Oxide: 150, Tungsten: 200, PhaseFabric: 40));
859 "payload-loader" => SimplePayloadBlock::new(3, false, cost!(Graphite: 50, Silicon: 50, Tungsten: 80));
860 "payload-unloader" => SimplePayloadBlock::new(3, false, cost!(Graphite: 50, Silicon: 50, Tungsten: 30));
861 "copper-wall" -> WallBlock::new(1, true, cost!(Copper: 6));
862 "copper-wall-large" -> WallBlock::new(2, true, cost!(Copper: 6 * 4));
863 "titanium-wall" -> WallBlock::new(1, true, cost!(Titanium: 6));
864 "titanium-wall-large" -> WallBlock::new(2, true, cost!(Titanium: 6 * 4));
865 "plastanium-wall" -> WallBlock::new(1, true, cost!(Metaglass: 2, Plastanium: 5));
866 "plastanium-wall-large" -> WallBlock::new(2, true, cost!(Metaglass: 2 * 4, Plastanium: 5 * 4));
867 "thorium-wall" -> WallBlock::new(1, true, cost!(Thorium: 6));
868 "thorium-wall-large" -> WallBlock::new(2, true, cost!(Thorium: 6 * 4));
869 "phase-wall" -> WallBlock::new(1, true, cost!(PhaseFabric: 6));
870 "phase-wall-large" -> WallBlock::new(2, true, cost!(PhaseFabric: 6 * 4));
871 "surge-wall" -> WallBlock::new(1, true, cost!(SurgeAlloy: 6));
872 "surge-wall-large" -> WallBlock::new(2, true, cost!(SurgeAlloy: 6 * 4));
873 "door" => DoorBlock::new(1, true, cost!(Titanium: 6, Silicon: 4));
874 "door-large" => DoorBlock::new(2, true, cost!(Titanium: 6 * 4, Silicon: 4 * 4));
875 "tungsten-wall" -> WallBlock::new(1, true, cost!(Tungsten: 6));
876 "tungsten-wall-large" -> WallBlock::new(2, true, cost!(Tungsten: 6 * 4));
877 "blast-door" -> DoorBlock::new(2, true, cost!(Tungsten: 24, Silicon: 24));
878 "reinforced-surge-wall" -> WallBlock::new(1, true, cost!(SurgeAlloy: 6, Tungsten: 2));
879 "reinforced-surge-wall-large" -> WallBlock::new(2, true, cost!(SurgeAlloy: 6 * 4, Tungsten: 2 * 4));
880 "carbide-wall" -> WallBlock::new(1, true, cost!(Thorium: 6, Carbide: 6));
881 "carbide-wall-large" -> WallBlock::new(2, true, cost!(Thorium: 6 * 4, Carbide: 6 * 4));
882 "shielded-wall" -> WallBlock::new(2, true, cost!(PhaseFabric: 20, SurgeAlloy: 12, Beryllium: 12));
883 "beryllium-wall" -> WallBlock::new(1, true, cost!(Beryllium: 6));
884 "beryllium-wall-large" -> WallBlock::new(2, true, cost!(Beryllium: 6 * 4));
885 "scrap-wall" -> WallBlock::new(1, true, cost!(Scrap: 6));
886 "scrap-wall-large" -> WallBlock::new(2, true, cost!(Scrap: 24));
887 "scrap-wall-huge" -> WallBlock::new(3, true, cost!(Scrap: 54));
888 "scrap-wall-gigantic" -> WallBlock::new(4, true, cost!(Scrap: 96));
889 "thruster" => WallBlock::new(4, false, cost!(Scrap: 96));
890 "mender" -> HeatedBlock::new(1, true, cost!(Copper: 25, Lead: 30));
891 "mend-projector" -> HeatedBlock::new(2, true, cost!(Copper: 50, Lead: 100, Titanium: 25, Silicon: 40));
892 "overdrive-projector" -> HeatedBlock::new(2, true, cost!(Lead: 100, Titanium: 75, Silicon: 75, Plastanium: 30));
893 "overdrive-dome" -> HeatedBlock::new(3, true, cost!(Lead: 200, Titanium: 130, Silicon: 130, Plastanium: 80, SurgeAlloy: 120));
894 "force-projector" -> BasicBlock::new(3, true, cost!(Lead: 100, Titanium: 75, Silicon: 125));
895 "regen-projector" -> BasicBlock::new(3, true, cost!(Silicon: 80, Tungsten: 60, Oxide: 40, Beryllium: 80));
896 "shock-mine" -> BasicBlock::new(1, true, cost!(Lead: 25, Silicon: 12));
897 "radar" -> RadarBlock::new(1, true, cost!(Silicon: 60, Graphite: 50, Beryllium: 10));
898 "build-tower" -> BasicBlock::new(3, true, cost!(Silicon: 150, Oxide: 40, Thorium: 60));
899 "shockwave-tower" -> BasicBlock::new(3, true, cost!(SurgeAlloy: 50, Silicon: 150, Oxide: 30, Tungsten: 100));
900 "reinforced-pump" -> BasicBlock::new(2, true, cost!(Beryllium: 40, Tungsten: 30, Silicon: 20));
901 "mechanical-pump" -> BasicBlock::new(1, true, cost!(Copper: 15, Metaglass: 10));
902 "rotary-pump" -> BasicBlock::new(2, true, cost!(Copper: 70, Metaglass: 50, Titanium: 35, Silicon: 20));
903 "impulse-pump" -> BasicBlock::new(3, true, cost!(Copper: 80, Metaglass: 90, Titanium: 40, Thorium: 35, Silicon: 30));
904 "conduit" => ConduitBlock::new(1, false, cost!(Metaglass: 1));
905 "pulse-conduit" => ConduitBlock::new(1, false, cost!(Metaglass: 1, Titanium: 2));
906 "plated-conduit" => ConduitBlock::new(1, false, cost!(Metaglass: 1, Thorium: 2, Plastanium: 1));
907 "liquid-router" -> BasicBlock::new(1, true, cost!(Metaglass: 2, Graphite: 4));
908 "liquid-container" -> BasicBlock::new(2, true, cost!(Metaglass: 15, Titanium: 10));
909 "liquid-tank" -> BasicBlock::new(3, true, cost!(Metaglass: 40, Titanium: 30));
910 "liquid-junction" -> BasicBlock::new(1, true, cost!(Metaglass: 8, Graphite: 4));
911 "bridge-conduit" -> BridgeBlock::new(1, true, cost!(Metaglass: 8, Graphite: 4), 4, true);
912 "phase-conduit" -> BridgeBlock::new(1, true, cost!(Metaglass: 20, Titanium: 10, Silicon: 7, PhaseFabric: 5), 12, true);
913 "reinforced-conduit" => ConduitBlock::new(1, false, cost!(Beryllium: 2));
914 "reinforced-liquid-junction" -> BasicBlock::new(1, true, cost!(Graphite: 4, Beryllium: 8));
915 "reinforced-bridge-conduit" => BridgeBlock::new(1, true, cost!(Graphite: 8, Beryllium: 20), 4, true);
916 "reinforced-liquid-router" -> BasicBlock::new(1, true, cost!(Graphite: 8, Beryllium: 4));
917 "reinforced-liquid-container" -> BasicBlock::new(2, true, cost!(Tungsten: 10, Beryllium: 16));
918 "reinforced-liquid-tank" -> BasicBlock::new(3, true, cost!(Tungsten: 40, Beryllium: 50));
919 "ground-factory" => UnitFactory::new(3, false, cost!(Copper: 50, Lead: 120, Silicon: 80), units::GROUND_UNITS);
920 "air-factory" => UnitFactory::new(3, false, cost!(Copper: 60, Lead: 70), units::AIR_UNITS);
921 "naval-factory" => UnitFactory::new(3, false, cost!(Copper: 150, Lead: 130, Metaglass: 120), units::NAVAL_UNITS);
922 "additive-reconstructor" => ConstructorBlock::new(3, false, cost!(Copper: 200, Lead: 120, Silicon: 90));
923 "multiplicative-reconstructor" => ConstructorBlock::new(5, false, cost!(Lead: 650, Titanium: 350, Thorium: 650, Silicon: 450));
924 "exponential-reconstructor" => ConstructorBlock::new(7, false, cost!(Lead: 2000, Titanium: 2000, Thorium: 750, Silicon: 1000, Plastanium: 450, PhaseFabric: 600));
925 "tetrative-reconstructor" => ConstructorBlock::new(9, false, cost!(Lead: 4000, Thorium: 1000, Silicon: 3000, Plastanium: 600, PhaseFabric: 600, SurgeAlloy: 800));
926 "repair-point" -> RepairTurret::new(1, true, cost!(Copper: 30, Lead: 30, Silicon: 20));
927 "repair-turret" -> RepairTurret::new(2, true, cost!(Thorium: 80, Silicon: 90, Plastanium: 60));
928 "tank-fabricator" => UnitFactory::new(3, true, cost!(Silicon: 200, Beryllium: 150), &[crate::unit::Type::Stell]);
929 "ship-fabricator" => UnitFactory::new(3, true, cost!(Silicon: 250, Beryllium: 200), &[crate::unit::Type::Elude]);
930 "mech-fabricator" => UnitFactory::new(3, true, cost!(Silicon: 200, Graphite: 300, Tungsten: 60), &[crate::unit::Type::Merui]);
931 "tank-refabricator" => ConstructorBlock::new(3, true, cost!(Beryllium: 200, Tungsten: 80, Silicon: 100));
932 "mech-refabricator" => ConstructorBlock::new(3, true, cost!(Beryllium: 250, Tungsten: 120, Silicon: 150));
933 "ship-refabricator" => ConstructorBlock::new(3, true, cost!(Beryllium: 200, Tungsten: 100, Silicon: 150, Oxide: 40));
934 "prime-refabricator" => ConstructorBlock::new(5, true, cost!(Thorium: 250, Oxide: 200, Tungsten: 200, Silicon: 400));
935 "tank-assembler" => AssemblerBlock::new(5, true, cost!(Thorium: 500, Oxide: 150, Carbide: 80, Silicon: 500));
936 "ship-assembler" => AssemblerBlock::new(5, true, cost!(Carbide: 100, Oxide: 200, Tungsten: 500, Silicon: 800, Thorium: 400));
937 "mech-assembler" => AssemblerBlock::new(5, true, cost!(Carbide: 200, Thorium: 600, Oxide: 200, Tungsten: 500, Silicon: 900)); "basic-assembler-module" => AssemblerModule::new(5, true, cost!(Carbide: 300, Thorium: 500, Oxide: 200, PhaseFabric: 400)); "unit-repair-tower" -> BasicBlock::new(2, true, cost!(Graphite: 90, Silicon: 90, Tungsten: 80));
940 "launch-pad" -> BasicBlock::new(3, true, cost!(Copper: 350, Lead: 200, Titanium: 150, Silicon: 140));
941 "landing-pad" -> BasicBlock::new(3, true, cost!(Copper: 200, Graphite: 100, Titanium: 100));
942 "advanced-launch-pad" -> BasicBlock::new(4, true, cost!(Copper: 350, Silicon: 250, Lead: 300, Titanium: 200));
943 "interplanetary-accelerator" -> BasicBlock::new(7, true, cost!(Copper: 16000, Silicon: 11000, Thorium: 13000, Titanium: 12000, SurgeAlloy: 6000, PhaseFabric: 5000));
944 "mechanical-drill" -> DrillBlock::new(2, true, cost!(Copper: 12));
945 "pneumatic-drill" -> DrillBlock::new(2, true, cost!(Copper: 18, Graphite: 10));
946 "laser-drill" -> DrillBlock::new(3, true, cost!(Copper: 35, Graphite: 30, Titanium: 20, Silicon: 30));
947 "blast-drill" -> DrillBlock::new(4, true, cost!(Copper: 65, Titanium: 50, Thorium: 75, Silicon: 60));
948 "water-extractor" -> BasicBlock::new(2, true, cost!(Copper: 30, Lead: 30, Metaglass: 30, Graphite: 30));
949 "oil-extractor" -> BasicBlock::new(3, true, cost!(Copper: 150, Lead: 115, Graphite: 175, Thorium: 115, Silicon: 75));
950 "vent-condenser" -> ProductionBlock::new(3, true, cost!(Graphite: 20, Beryllium: 60));
951 "cliff-crusher" => WallDrillBlock::new(2, false, cost!(Beryllium: 100, Graphite: 40));
952 "large-cliff-crusher" => WallDrillBlock::new(3, false, cost!(Silicon: 80, SurgeAlloy: 15, Beryllium: 100, Tungsten: 50));
953 "plasma-bore" => DrillBlock::new(2, false, cost!(Beryllium: 40));
954 "large-plasma-bore" => DrillBlock::new(3, false, cost!(Silicon: 100, Oxide: 25, Beryllium: 100, Tungsten: 70));
955 "impact-drill" -> DrillBlock::new(4, true, cost!(Silicon: 70, Beryllium: 90, Graphite: 60));
956 "eruption-drill" -> DrillBlock::new(5, true, cost!(Silicon: 200, Oxide: 20, Tungsten: 200, Thorium: 120));
957 "reinforced-message" -> MessageLogic::new(1, true, cost!(Graphite: 10, Beryllium: 5));
958 "message" -> MessageLogic::new(1, true, cost!(Copper: 5, Graphite: 5));
959 "switch" => SwitchLogic::new(1, true, cost!(Copper: 5, Graphite: 5));
960 "micro-processor" -> ProcessorLogic::new(1, true, cost!(Copper: 90, Lead: 50, Silicon: 50));
961 "logic-processor" -> ProcessorLogic::new(2, true, cost!(Lead: 320, Graphite: 60, Thorium: 50, Silicon: 80));
962 "hyper-processor" -> ProcessorLogic::new(3, true, cost!(Lead: 450, Thorium: 75, Silicon: 150, SurgeAlloy: 50));
963 "memory-cell" -> MemoryBlock::new(1, true, cost!(Copper: 30, Graphite: 30, Silicon: 30));
964 "memory-bank" -> MemoryBlock::new(2, true, cost!(Copper: 30, Graphite: 80, Silicon: 80, PhaseFabric: 30));
965 "logic-display" -> BasicBlock::new(3, true, cost!(Lead: 100, Metaglass: 50, Silicon: 50));
966 "large-logic-display" -> BasicBlock::new(6, true, cost!(Lead: 200, Metaglass: 100, Silicon: 150, PhaseFabric: 75));
967 "canvas" => CanvasBlock::new(2, true, cost!(Silicon: 30, Beryllium: 10), 12);
968 "illuminator" -> LampBlock::new(1, true, cost!(Lead: 8, Graphite: 12, Silicon: 8));
969 "power-node" -> ConnectorBlock::new(1, true, cost!(Copper: 1, Lead: 3), 10);
970 "power-node-large" -> ConnectorBlock::new(2, true, cost!(Lead: 10, Titanium: 5, Silicon: 3), 15);
971 "surge-tower" -> ConnectorBlock::new(2, true, cost!(Lead: 10, Titanium: 7, Silicon: 15, SurgeAlloy: 15), 2);
972 "diode" => DiodeBlock::new(1, false, cost!(Metaglass: 10, Silicon: 10, Plastanium: 5));
973 "battery" -> BasicBlock::new(1, true, cost!(Copper: 5, Lead: 20));
974 "battery-large" -> BasicBlock::new(3, true, cost!(Lead: 50, Titanium: 20, Silicon: 30));
975 "combustion-generator" -> GeneratorBlock::new(1, true, cost!(Copper: 25, Lead: 15));
976 "thermal-generator" -> GeneratorBlock::new(2, true, cost!(Copper: 40, Lead: 50, Metaglass: 40, Graphite: 35, Silicon: 35));
977 "steam-generator" -> GeneratorBlock::new(2, true, cost!(Copper: 35, Lead: 40, Graphite: 25, Silicon: 30));
978 "differential-generator" -> GeneratorBlock::new(3, true, cost!(Copper: 70, Lead: 100, Metaglass: 50, Titanium: 50, Silicon: 65));
979 "rtg-generator" -> GeneratorBlock::new(2, true, cost!(Lead: 100, Thorium: 50, Silicon: 75, Plastanium: 75, PhaseFabric: 25));
980 "solar-panel" -> GeneratorBlock::new(1, true, cost!(Lead: 10, Silicon: 15));
981 "solar-panel-large" -> GeneratorBlock::new(3, true, cost!(Lead: 80, Silicon: 110, PhaseFabric: 15));
982 "thorium-reactor" -> NuclearGeneratorBlock::new(3, true, cost!(Lead: 300, Metaglass: 50, Graphite: 150, Thorium: 150, Silicon: 200));
983 "impact-reactor" -> ImpactReactorBlock::new(4, true, cost!(Lead: 500, Metaglass: 250, Graphite: 400, Thorium: 100, Silicon: 300, SurgeAlloy: 250));
984 "beam-node" -> ConnectorBlock::new(1, true, cost!(Beryllium: 8), 4);
985 "beam-tower" -> ConnectorBlock::new(3, true, cost!(Beryllium: 30, Oxide: 10, Silicon: 10), 12);
986 "turbine-condenser" -> GeneratorBlock::new(3, true, cost!(Beryllium: 60));
987 "chemical-combustion-chamber" -> GeneratorBlock::new(3, true, cost!(Graphite: 40, Tungsten: 40, Oxide: 40, Silicon: 30));
988 "pyrolysis-generator" -> GeneratorBlock::new(3, true, cost!(Graphite: 50, Carbide: 50, Oxide: 60, Silicon: 50));
989 "flux-reactor" -> GeneratorBlock::new(5, true, cost!(Graphite: 300, Carbide: 200, Oxide: 100, Silicon: 600, SurgeAlloy: 300));
990 "neoplasia-reactor" => Neoplasia::new(5, true, cost!(Tungsten: 1000, Carbide: 300, Oxide: 150, Silicon: 500, PhaseFabric: 300, SurgeAlloy: 200));
991 "core-shard" -> BasicBlock::new(3, true, cost!(Copper: 1000, Lead: 800));
992 "core-foundation" -> BasicBlock::new(4, true, cost!(Copper: 3000, Lead: 3000, Silicon: 2000));
993 "core-nucleus" -> BasicBlock::new(5, true, cost!(Copper: 8000, Lead: 8000, Thorium: 4000, Silicon: 5000));
994 "core-bastion" -> BasicBlock::new(4, true, cost!(Graphite: 1000, Silicon: 1000, Beryllium: 800));
995 "core-citadel" -> BasicBlock::new(5, true, cost!(Silicon: 4000, Beryllium: 4000, Tungsten: 3000, Oxide: 1000));
996 "core-acropolis" -> BasicBlock::new(6, true, cost!(Beryllium: 6000, Silicon: 5000, Tungsten: 5000, Carbide: 3000, Oxide: 3000));
997 "container" -> BasicBlock::new(2, true, cost!(Titanium: 100));
998 "vault" -> BasicBlock::new(3, true, cost!(Titanium: 250, Thorium: 125));
999 "reinforced-container" -> BasicBlock::new(2, true, cost!(Tungsten: 30, Graphite: 40));
1000 "reinforced-vault" -> BasicBlock::new(3, true, cost!(Tungsten: 125, Thorium: 70, Beryllium: 100));
1001 "duo" -> ItemTurret::new(1, true, cost!(Copper: 35));
1002 "scatter" -> ItemTurret::new(2, true, cost!(Copper: 85, Lead: 45));
1003 "scorch" -> ItemTurret::new(1, true, cost!(Copper: 25, Graphite: 22));
1004 "hail" -> ItemTurret::new(1, true, cost!(Copper: 40, Graphite: 17));
1005 "wave" -> Turret::new(2, true, cost!(Copper: 25, Lead: 75, Metaglass: 45));
1006 "tsunami" -> Turret::new(3, true, cost!(Lead: 400, Metaglass: 100, Titanium: 250, Thorium: 100));
1007 "lancer" -> Turret::new(2, true, cost!(Copper: 60, Lead: 70, Titanium: 30, Silicon: 60));
1008 "arc" -> Turret::new(1, true, cost!(Copper: 50, Lead: 50));
1009 "parallax" -> TractorBeamTurret::new(2, true, cost!(Graphite: 30, Titanium: 90, Silicon: 120));
1010 "swarmer" -> ItemTurret::new(2, true, cost!(Graphite: 35, Titanium: 35, Silicon: 30, Plastanium: 45));
1011 "salvo" -> ItemTurret::new(2, true, cost!(Copper: 100, Graphite: 80, Titanium: 50));
1012 "segment" -> PointDefenseTurret::new(2, true, cost!(Titanium: 40, Thorium: 80, Silicon: 130, PhaseFabric: 40));
1013 "fuse" -> ItemTurret::new(3, true, cost!(Copper: 225, Graphite: 225, Thorium: 100));
1014 "ripple" -> ItemTurret::new(3, true, cost!(Copper: 150, Graphite: 135, Titanium: 60));
1015 "cyclone" -> ItemTurret::new(3, true, cost!(Copper: 200, Titanium: 125, Plastanium: 80));
1016 "foreshadow" -> ItemTurret::new(4, true, cost!(Copper: 1000, Metaglass: 600, Silicon: 600, Plastanium: 200, SurgeAlloy: 300));
1017 "spectre" -> ItemTurret::new(4, true, cost!(Copper: 900, Graphite: 300, Thorium: 250, Plastanium: 175, SurgeAlloy: 250));
1018 "meltdown" -> Turret::new(4, true, cost!(Copper: 1200, Lead: 350, Graphite: 300, Silicon: 325, SurgeAlloy: 325));
1019 "breach" -> ItemTurret::new(3, true, cost!(Beryllium: 150, Silicon: 150, Graphite: 250));
1020 "diffuse" -> ItemTurret::new(3, true, cost!(Beryllium: 150, Silicon: 200, Graphite: 200, Tungsten: 50));
1021 "sublimate" -> ContinousTurret::new(3, true, cost!(Tungsten: 150, Silicon: 200, Oxide: 40, Beryllium: 400));
1022 "titan" -> ItemTurret::new(4, true, cost!(Tungsten: 250, Silicon: 300, Thorium: 400));
1023 "disperse" -> ItemTurret::new(4, true, cost!(Thorium: 50, Oxide: 150, Silicon: 200, Beryllium: 350));
1024 "afflict" -> Turret::new(4, true, cost!(SurgeAlloy: 100, Silicon: 200, Graphite: 250, Oxide: 40));
1025 "lustre" -> ContinousTurret::new(4, true, cost!(Silicon: 250, Graphite: 200, Oxide: 50, Carbide: 90));
1026 "scathe" -> ItemTurret::new(4, true, cost!(Oxide: 200, SurgeAlloy: 400, Silicon: 800, Carbide: 500, PhaseFabric: 300));
1027 "malign" -> Turret::new(5, true, cost!(Carbide: 400, Beryllium: 2000, Silicon: 800, Graphite: 800, PhaseFabric: 300));
1028 "smite" -> ItemTurret::new(5, true, cost!(Oxide: 200, SurgeAlloy: 400, Silicon: 800, Carbide: 500, PhaseFabric: 300));
1029 "beam-link" -> ConnectorBlock::new(3, true, &[], 12);
1031 "power-source" -> ConnectorBlock::new(1, true, &[], 100);
1032 "power-void" -> BasicBlock::new(1, true, &[]);
1033 "world-processor" -> BasicBlock::new(1, true, &[]);
1034 "world-message" -> MessageLogic::new(1, true, &[]);
1035 "world-cell" -> MemoryBlock::new(1, true, &[]);
1036 "world-switch" => SwitchLogic::new(1, true, &[]);
1037 "liquid-source" => FluidBlock::new(1, true, &[]);
1038 "liquid-void" -> BasicBlock::new(1, true, &[]);
1039 "shield-projector" -> ShieldBlock::new(3, true, &[]);
1040 "large-shield-projector" -> ShieldBlock::new(4, true, &[]);
1041 "payload-source" => PayloadBlock::new(5, false, &[]);
1042 "payload-void" => SimplePayloadBlock::new(5, true, &[]);
1043 "item-source" => ItemBlock::new(1, true, &[]);
1044 "item-void" -> BasicBlock::new(1, true, &[]);
1045 "heat-source" => HeatCrafter::new(1, false, &[]);
1046}