rustorio_engine/
research.rs1use std::{fmt::Debug, marker::PhantomData};
7
8pub use rustorio_derive::{TechnologyEx, technology_doc};
9
10use crate::{
11 ResourceType, Sealed,
12 recipe::{Recipe, RecipeEx},
13 resources::{Bundle, Resource},
14};
15
16pub trait Technology: Sealed + Debug + Sized + TechnologyEx {
19 const NAME: &'static str;
21 const REQUIRED_RESEARCH_POINTS: u32 = Self::REQUIRED_RESEARCH_POINTS_EX;
23
24 type Unlocks;
26
27 fn research(
29 self,
30 research_points: Bundle<ResearchPoint<Self>, { Self::REQUIRED_RESEARCH_POINTS }>,
31 ) -> Self::Unlocks;
32}
33
34#[doc(hidden)]
36pub trait TechnologyEx {
37 type Inputs: Debug;
40 type InputAmountsType: Debug;
43 type InputBundle: Debug;
46 const INPUT_AMOUNTS: Self::InputAmountsType;
48 const POINT_RECIPE_TIME: u64;
50 const REQUIRED_RESEARCH_POINTS_EX: u32;
52
53 fn new_inputs() -> Self::Inputs;
55
56 fn iter_inputs(items: &mut Self::Inputs)
58 -> impl Iterator<Item = (&'static str, u32, &mut u32)>;
59}
60
61#[derive(Debug)]
64#[non_exhaustive]
65pub struct ResearchPoint<T: Technology> {
66 _marker: PhantomData<T>,
67}
68
69impl<T: Technology> Sealed for ResearchPoint<T> {}
70impl<T: Technology> ResourceType for ResearchPoint<T> {
71 const NAME: &'static str = T::NAME;
72}
73
74#[derive(Debug)]
76pub struct TechRecipe<T: Technology> {
77 _marker: PhantomData<T>,
78}
79
80impl<T> Recipe for TechRecipe<T>
81where
82 T: Technology,
83{
84 const TIME: u64 = T::POINT_RECIPE_TIME;
85 type Inputs = T::Inputs;
86 type InputAmountsType = T::InputAmountsType;
87 const INPUT_AMOUNTS: Self::InputAmountsType = T::INPUT_AMOUNTS;
88 type Outputs = (Resource<ResearchPoint<T>>,);
89
90 type OutputAmountsType = (u32,);
91
92 const OUTPUT_AMOUNTS: (u32,) = (1,);
93
94 fn new_inputs() -> Self::Inputs {
95 T::new_inputs()
96 }
97
98 fn new_outputs() -> Self::Outputs {
99 (Resource::new_empty(),)
100 }
101}
102
103impl<T: Technology> RecipeEx for TechRecipe<T> {
104 type InputBundle = T::InputBundle;
105 type OutputBundle = Bundle<ResearchPoint<T>, 1>;
106
107 fn new_output_bundle() -> Self::OutputBundle {
108 Bundle::<ResearchPoint<T>, 1>::new()
109 }
110
111 fn iter_inputs(
112 items: &mut Self::Inputs,
113 ) -> impl Iterator<Item = (&'static str, u32, &mut u32)> {
114 T::iter_inputs(items)
115 }
116
117 fn iter_outputs(
118 items: &mut Self::Outputs,
119 ) -> impl Iterator<Item = (&'static str, u32, &mut u32)> {
120 [(ResearchPoint::<T>::NAME, 1u32, &mut items.0.amount)].into_iter()
121 }
122}
123
124pub const fn tech_recipe<T: Technology>() -> TechRecipe<T> {
127 TechRecipe {
128 _marker: PhantomData,
129 }
130}