tiger_lib/vic3/data/
history.rs1use std::path::PathBuf;
2
3use crate::block::Block;
4use crate::context::ScopeContext;
5use crate::effect::validate_effect;
6use crate::everything::Everything;
7use crate::fileset::{FileEntry, FileHandler};
8use crate::helpers::TigerHashMap;
9use crate::parse::ParserMemory;
10use crate::pdxfile::PdxFile;
11use crate::report::{ErrorKey, err, warn};
12use crate::scopes::Scopes;
13use crate::token::Token;
14use crate::tooltipped::Tooltipped;
15use crate::variables::Variables;
16
17#[derive(Clone, Debug, Default)]
22pub struct History {
23 history: TigerHashMap<&'static str, HistoryEffect>,
24}
25
26impl History {
27 fn load_item(&mut self, key: Token, mut block: Block) {
28 if let Some(entry) = self.history.get_mut(key.as_str()) {
29 entry.block.append(&mut block);
30 } else {
31 self.history.insert(key.as_str(), HistoryEffect::new(key, block));
32 }
33 }
34
35 pub fn scan_variables(&self, registry: &mut Variables) {
36 for item in self.history.values() {
37 registry.scan(&item.block);
38 }
39 }
40
41 pub fn validate(&self, data: &Everything) {
42 for name in HISTORY_SEQUENCE {
43 if let Some(item) = self.history.get(name) {
44 item.validate(data);
45 }
46 }
47
48 for (name, item) in &self.history {
51 if HISTORY_SEQUENCE.contains(name) {
52 continue;
53 }
54 if *name == "CONSCRIPTION" {
55 let msg = "CONSCRIPTION history is not processed by the game";
56 let info = "as of 1.9.7";
57 warn(ErrorKey::Bugs).msg(msg).info(info).loc(&item.key).push();
58 continue;
59 }
60 let msg = format!("unknown history classification `{name}`");
61 err(ErrorKey::UnknownField).msg(msg).loc(&item.key).push();
62 item.validate(data);
63 }
64 }
65}
66
67impl FileHandler<Block> for History {
68 fn subpath(&self) -> PathBuf {
69 PathBuf::from("common/history/")
70 }
71
72 fn load_file(&self, entry: &FileEntry, parser: &ParserMemory) -> Option<Block> {
73 if !entry.filename().to_string_lossy().ends_with(".txt") {
74 return None;
75 }
76
77 PdxFile::read(entry, parser)
78 }
79
80 fn handle_file(&mut self, _entry: &FileEntry, mut block: Block) {
81 for (key, block) in block.drain_definitions_warn() {
82 self.load_item(key, block);
83 }
84 }
85}
86
87#[derive(Clone, Debug)]
88pub struct HistoryEffect {
89 key: Token,
90 block: Block,
91}
92
93impl HistoryEffect {
94 pub fn new(key: Token, block: Block) -> Self {
95 Self { key, block }
96 }
97
98 pub fn validate(&self, data: &Everything) {
99 let mut sc = ScopeContext::new(Scopes::None, &self.key);
100 validate_effect(&self.block, data, &mut sc, Tooltipped::No);
101 }
102}
103
104const HISTORY_SEQUENCE: &[&str] = &[
109 "STATES",
110 "COUNTRIES",
111 "POPS",
112 "DIPLOMACY",
113 "POPULATION",
114 "POWER_BLOCS",
115 "INTERESTS",
116 "BUILDINGS",
117 "PRODUCTION_METHODS",
118 "MILITARY_FORMATIONS",
119 "AI",
120 "TREATIES",
121 "LOBBIES",
122 "DIPLOMATIC_PLAYS",
123 "TRADE",
124 "GLOBAL",
126 "POLITICAL_MOVEMENTS",
127 "CHARACTERS",
128 "GOVERNMENT",
129 "GOVERNMENT_SETUP",
130 "MILITARY_DEPLOYMENTS",
131 "CULTURES",
133];