tiger_lib/ck3/data/
prov_history.rs1use std::path::PathBuf;
2
3use crate::block::{BV, Block};
4use crate::ck3::data::provinces::ProvId;
5use crate::ck3::data::titles::Titles;
6use crate::date::Date;
7use crate::everything::Everything;
8use crate::fileset::{FileEntry, FileHandler};
9use crate::helpers::{TigerHashMap, dup_error};
10use crate::item::Item;
11use crate::parse::ParserMemory;
12use crate::pdxfile::PdxFile;
13use crate::report::{ErrorKey, Severity, warn};
14use crate::scopes::Scopes;
15use crate::token::Token;
16use crate::tooltipped::Tooltipped;
17use crate::validator::Validator;
18use crate::variables::Variables;
19
20#[derive(Clone, Debug, Default)]
21pub struct ProvinceHistories {
22 provinces: TigerHashMap<ProvId, ProvinceHistory>,
23}
24
25impl ProvinceHistories {
26 fn load_item(&mut self, id: ProvId, key: Token, mut block: Block) {
27 if let Some(province) = self.provinces.get_mut(&id) {
28 if province.key.loc.kind >= key.loc.kind {
30 dup_error(&key, &province.key, "province");
31 }
32 province.block.append(&mut block);
33 } else {
34 self.provinces.insert(id, ProvinceHistory::new(key, block));
35 }
36 }
37
38 pub fn scan_variables(&self, registry: &mut Variables) {
39 for item in self.provinces.values() {
40 registry.scan(&item.block);
41 }
42 }
43
44 pub fn validate(&self, data: &Everything) {
45 for (provid, item) in &self.provinces {
46 item.validate(*provid, data);
47 }
48 }
49
50 pub fn check_pod_faiths(&self, data: &Everything, titles: &Titles) {
51 for bookmark in [
52 Date::new(1230, 1, 4),
53 Date::new(1230, 1, 5),
54 Date::new(1230, 1, 6),
55 Date::new(1375, 7, 5),
56 Date::new(1510, 1, 3),
57 ] {
58 for (provid, provhist) in &self.provinces {
59 if let Some(capital) = titles.capital_of(*provid) {
60 let religion = provhist.block.get_field_at_date("religion", bookmark);
61 if let Some(religion) = religion.and_then(BV::get_value) {
62 if !data.item_has_property(Item::Faith, religion.as_str(), "is_modded") {
63 let msg = format!(
64 "Vanilla or unknown religion in prov {} (county {}) at {}",
65 provhist.key, capital, bookmark
66 );
67 warn(ErrorKey::PrincesOfDarkness).msg(msg).loc(religion).push();
68 }
69 } else {
70 warn(ErrorKey::PrincesOfDarkness)
71 .msg("no religion")
72 .loc(&provhist.key)
73 .push();
74 }
75 }
76 }
77 }
78 }
79}
80
81impl FileHandler<Block> for ProvinceHistories {
82 fn subpath(&self) -> PathBuf {
83 PathBuf::from("history/provinces")
84 }
85
86 fn load_file(&self, entry: &FileEntry, parser: &ParserMemory) -> Option<Block> {
87 if !entry.filename().to_string_lossy().ends_with(".txt") {
88 return None;
89 }
90
91 PdxFile::read_detect_encoding(entry, parser)
92 }
93
94 fn handle_file(&mut self, _entry: &FileEntry, mut block: Block) {
95 for (key, block) in block.drain_definitions_warn() {
96 if let Ok(id) = key.as_str().parse() {
97 self.load_item(id, key, block);
98 } else {
99 let msg = "unexpected key, expected only province ids";
100 warn(ErrorKey::Validation).msg(msg).loc(key).push();
101 }
102 }
103 }
104}
105
106#[derive(Clone, Debug)]
107pub struct ProvinceHistory {
108 key: Token,
109 block: Block,
110}
111
112impl ProvinceHistory {
113 fn new(key: Token, block: Block) -> Self {
114 Self { key, block }
115 }
116
117 fn validate_common(vd: &mut Validator, data: &Everything) {
118 vd.field_item("culture", Item::Culture);
119 vd.field_item("religion", Item::Faith);
120 vd.field_item("faith", Item::Faith);
121 if let Some(token) = vd.field_value("holding") {
122 if !token.is("auto") && !token.is("none") {
123 data.verify_exists(Item::HoldingType, token);
124 }
125 }
126 vd.field_list_items("buildings", Item::Building);
127 vd.multi_field_item("special_building_slot", Item::SpecialBuilding);
128 vd.multi_field_item("special_building", Item::SpecialBuilding);
129 vd.field_item("duchy_capital_building", Item::Building);
132
133 vd.field_effect_rooted("effect", Tooltipped::No, Scopes::Province);
134 }
135
136 fn validate_history(_date: Date, _key: &Token, block: &Block, data: &Everything) {
137 let mut vd = Validator::new(block, data);
138 Self::validate_common(&mut vd, data);
139 }
140
141 fn validate(&self, provid: ProvId, data: &Everything) {
142 data.provinces_ck3.verify_exists_provid(provid, &self.key, Severity::Error);
143 let mut vd = Validator::new(&self.block, data);
146 Self::validate_common(&mut vd, data);
147 vd.field_value("terrain"); vd.validate_history_blocks(Self::validate_history);
149 }
150}