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