veloren_rtsim/data/
mod.rs1pub mod airship;
2pub mod architect;
3pub mod faction;
4pub mod nature;
5pub mod npc;
6pub mod report;
7pub mod sentiment;
8pub mod site;
9
10pub use self::{
11 faction::{Faction, FactionId, Factions},
12 nature::Nature,
13 npc::{Npc, NpcId, Npcs},
14 report::{Report, ReportId, ReportKind, Reports},
15 sentiment::{Sentiment, Sentiments},
16 site::{Site, SiteId, Sites},
17};
18use airship::AirshipSim;
19use architect::Architect;
20use common::resources::TimeOfDay;
21use enum_map::{EnumArray, EnumMap, enum_map};
22use serde::{Deserialize, Serialize, de, ser};
23use std::{
24 cmp::PartialEq,
25 fmt,
26 io::{Read, Write},
27 marker::PhantomData,
28};
29
30pub const CURRENT_VERSION: u32 = 9;
36
37#[derive(Clone, Serialize, Deserialize)]
38pub struct Data {
39 #[serde(default)]
41 pub version: u32,
42
43 pub nature: Nature,
44 #[serde(default)]
45 pub npcs: Npcs,
46 #[serde(default)]
47 pub sites: Sites,
48 #[serde(default)]
49 pub factions: Factions,
50 #[serde(default)]
51 pub reports: Reports,
52 #[serde(default)]
53 pub architect: Architect,
54
55 #[serde(default)]
56 pub tick: u64,
57 #[serde(default)]
58 pub time_of_day: TimeOfDay,
59
60 #[serde(default)]
62 pub should_purge: bool,
63
64 #[serde(skip)]
65 pub airship_sim: AirshipSim,
66}
67
68pub enum ReadError {
69 Load(rmp_serde::decode::Error),
70 VersionMismatch(Box<Data>),
72}
73
74impl fmt::Debug for ReadError {
75 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76 match self {
77 Self::Load(err) => err.fmt(f),
78 Self::VersionMismatch(_) => write!(f, "VersionMismatch"),
79 }
80 }
81}
82
83pub type WriteError = rmp_serde::encode::Error;
84
85impl Data {
86 pub fn spawn_npc(&mut self, npc: Npc) -> NpcId {
87 let home = npc.home;
88 let id = self.npcs.create_npc(npc);
89 if let Some(home) = home.and_then(|home| self.sites.get_mut(home)) {
90 home.population.insert(id);
91 }
92 id
93 }
94
95 pub fn from_reader<R: Read>(reader: R) -> Result<Box<Self>, ReadError> {
96 rmp_serde::decode::from_read(reader)
97 .map_err(ReadError::Load)
98 .and_then(|data: Data| {
99 if data.version == CURRENT_VERSION {
100 Ok(Box::new(data))
101 } else {
102 Err(ReadError::VersionMismatch(Box::new(data)))
103 }
104 })
105 }
106
107 pub fn write_to<W: Write>(&self, mut writer: W) -> Result<(), WriteError> {
108 rmp_serde::encode::write_named(&mut writer, self)
109 }
110}
111
112fn rugged_ser_enum_map<
113 K: EnumArray<V> + Serialize,
114 V: From<i16> + PartialEq + Serialize,
115 S: ser::Serializer,
116 const DEFAULT: i16,
117>(
118 map: &EnumMap<K, V>,
119 ser: S,
120) -> Result<S::Ok, S::Error> {
121 ser.collect_map(map.iter().filter(|(_, v)| v != &&V::from(DEFAULT)))
122}
123
124fn rugged_de_enum_map<
125 'a,
126 K: EnumArray<V> + EnumArray<Option<V>> + Deserialize<'a>,
127 V: From<i16> + Deserialize<'a>,
128 D: de::Deserializer<'a>,
129 const DEFAULT: i16,
130>(
131 de: D,
132) -> Result<EnumMap<K, V>, D::Error> {
133 struct Visitor<K, V, const DEFAULT: i16>(PhantomData<(K, V)>);
134
135 impl<'de, K, V, const DEFAULT: i16> de::Visitor<'de> for Visitor<K, V, DEFAULT>
136 where
137 K: EnumArray<V> + EnumArray<Option<V>> + Deserialize<'de>,
138 V: From<i16> + Deserialize<'de>,
139 {
140 type Value = EnumMap<K, V>;
141
142 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
143 write!(formatter, "a map")
144 }
145
146 fn visit_map<M: de::MapAccess<'de>>(self, mut access: M) -> Result<Self::Value, M::Error> {
147 let mut entries = EnumMap::default();
148 while let Some((key, value)) = access.next_entry()? {
149 entries[key] = Some(value);
150 }
151 Ok(enum_map! { key => entries[key].take().unwrap_or_else(|| V::from(DEFAULT)) })
152 }
153 }
154
155 de.deserialize_map(Visitor::<_, _, DEFAULT>(PhantomData))
156}