diff --git a/.github/workflows/ck3-tiger.conf b/.github/workflows/ck3-tiger.conf index 1c68de53e..fee616406 100644 --- a/.github/workflows/ck3-tiger.conf +++ b/.github/workflows/ck3-tiger.conf @@ -29,6 +29,7 @@ filter = { text = "OR with only one item inside is probably not what you intended" # vanilla issues + text = "missing english localization key c_nf_new_noble_dynasty_adj" text = "missing english localization key d_tyrol_adj" text = "missing english localization key d_lothian_adj" text = "missing english localization key d_valois_adj" @@ -123,6 +124,120 @@ filter = { text = "missing english localization key d_shimen_adj" text = "missing english localization key d_luoshi_adj" text = "missing english localization key d_luodian_adj" + text = "missing english localization key d_SW_qingxingan_adj" + text = "missing english localization key d_SW_lingxiguo_adj" + text = "missing english localization key d_SW_ruzheguo_adj" + text = "missing english localization key d_SW_puyudao_adj" + text = "missing english localization key d_SW_sushenguo_adj" + text = "missing english localization key d_SW_heicheziguo_adj" + text = "missing english localization key d_SW_dashiweiguo_adj" + text = "missing english localization key d_em_tataria_adj" + text = "missing english localization key d_em_wuguguo_adj" + text = "missing english localization key d_gobi_dadaels_adj" + text = "missing english localization key d_gobi_shatuoguo_adj" + text = "missing english localization key d_gobi_ongi_adj" + text = "missing english localization key d_EM_onon_adj" + text = "missing english localization key d_EM_yujuelu_adj" + text = "missing english localization key d_EM_wajiezi_adj" + text = "missing english localization key d_LIAO_linhuang_adj" + text = "missing english localization key d_LIAO_shangjing_adj" + text = "missing english localization key d_LIAO_zhongjing_adj" + text = "missing english localization key d_liaoxi_adj" + text = "missing english localization key d_yanyun_yuyi_adj" + text = "missing english localization key d_dongji_adj" + text = "missing english localization key d_biansong_adj" + text = "missing english localization key d_shanguo_adj" + text = "missing english localization key d_zhenghua_adj" + text = "missing english localization key d_chenxu_adj" + text = "missing english localization key d_ziqing_adj" + text = "missing english localization key d_yanhai_adj" + text = "missing english localization key d_xusi_adj" + text = "missing english localization key d_yuncao_adj" + text = "missing english localization key d_weibo_adj" + text = "missing english localization key d_xingming_adj" + text = "missing english localization key d_chengde_adj" + text = "missing english localization key d_cangjing_adj" + text = "missing english localization key d_heyang_adj" + text = "missing english localization key d_hedong_adj" + text = "missing english localization key d_yanmen_adj" + text = "missing english localization key d_hezhong_adj" + text = "missing english localization key d_zelu_adj" + text = "missing english localization key d_youzhou_adj" + text = "missing english localization key d_yideng_adj" + text = "missing english localization key d_yingmo_adj" + text = "missing english localization key d_yunshuo_adj" + text = "missing english localization key d_sanggan_adj" + text = "missing english localization key d_xinan_adj" + text = "missing english localization key d_yongxing_adj" + text = "missing english localization key d_fengxiang_adj" + text = "missing english localization key d_jinshang_adj" + text = "missing english localization key d_binning_adj" + text = "missing english localization key d_fufang_adj" + text = "missing english localization key d_jingyuan_adj" + text = "missing english localization key d_qincheng_adj" + text = "missing english localization key d_xingfeng_adj" + text = "missing english localization key d_longyou_adj" + text = "missing english localization key d_qilian_adj" + text = "missing english localization key d_gansu_adj" + text = "missing english localization key d_guasha_adj" + text = "missing english localization key d_shuofang_adj" + text = "missing english localization key d_xiasui_adj" + text = "missing english localization key d_tiande_adj" + text = "missing english localization key d_langshan_adj" + text = "missing english localization key d_xiutu_adj" + text = "missing english localization key d_juyan_adj" + text = "missing english localization key d_jingnan_adj" + text = "missing english localization key d_xuanshe_adj" + text = "missing english localization key d_zhexi_adj" + text = "missing english localization key d_zhedong_adj" + text = "missing english localization key d_weiwu_adj" + text = "missing english localization key d_pinghai_adj" + text = "missing english localization key d_jianning_adj" + text = "missing english localization key d_huainan_adj" + text = "missing english localization key d_huaixi_adj" + text = "missing english localization key d_jiangxi_adj" + text = "missing english localization key d_dingjiang_adj" + text = "missing english localization key d_zhaoxin_adj" + text = "missing english localization key d_xiangdeng_adj" + text = "missing english localization key d_eyue_adj" + text = "missing english localization key d_hunan_adj" + text = "missing english localization key d_lingling_adj" + text = "missing english localization key d_xichuan_adj" + text = "missing english localization key d_qiongnan_adj" + text = "missing english localization key d_wuxin_adj" + text = "missing english localization key d_kuizhong_adj" + text = "missing english localization key d_qianzhong_adj" + text = "missing english localization key d_wuxi_adj" + text = "missing english localization key d_mongnai_adj" + text = "missing english localization key d_yongchang_adj" + text = "missing english localization key d_tengchong_adj" + text = "missing english localization key d_lop_buri_adj" + text = "missing english localization key d_muang_sua_adj" + text = "missing english localization key d_sukhothai_adj" + text = "missing english localization key d_tun_sun_adj" + text = "missing english localization key d_haripunjaya_adj" + text = "missing english localization key d_sipsongpanna_adj" + text = "missing english localization key d_baigaur_adj" + text = "missing english localization key d_vyadhapura_adj" + text = "missing english localization key d_angkor_adj" + text = "missing english localization key d_ratanakiri_adj" + text = "missing english localization key d_angkor_borey_adj" + text = "missing english localization key d_phonsavan_adj" + text = "missing english localization key d_mukdahan_adj" + text = "missing english localization key d_BAL_dongpyeong_adj" + text = "missing english localization key d_BAL_cheolli_adj" + text = "missing english localization key d_BAL_hoewon_adj" + text = "missing english localization key d_BAL_yeojintang_adj" + text = "missing english localization key d_BAL_anwon_adj" + text = "missing english localization key d_amur_boli_adj" + text = "missing english localization key d_eman_boli_adj" + text = "missing english localization key d_eman_sikhotebei_adj" + text = "missing english localization key d_eman_samagero_adj" + text = "missing english localization key d_eman_nivkhia_adj" + text = "missing english localization key d_eman_amar_adj" + text = "missing english localization key d_eman_bureya_adj" + text = "missing english localization key d_laamp_" # ignores all missing adjectives for LAAMP titles + text = "missing english localization key d_nf_" # ignores all missing adjectives for noble family titles text = "missing english localization key k_mentese_adj" text = "missing english localization key k_mediterranean_sea_adj" text = "missing english localization key k_visigoths_adj" @@ -143,6 +258,36 @@ filter = { text = "missing english localization key k_lingnan_adj" text = "missing english localization key k_dali_adj" text = "missing english localization key k_qianzhong_adj" + text = "missing english localization key k_gobi_adj" + text = "missing english localization key k_raole_adj" + text = "missing english localization key k_henan_adj" + text = "missing english localization key k_qingxu_adj" + text = "missing english localization key k_hebei_adj" + text = "missing english localization key k_youji_adj" + text = "missing english localization key k_daibei_adj" + text = "missing english localization key k_guannei_adj" + text = "missing english localization key k_hexi_adj" + text = "missing english localization key k_hedong_adj" + text = "missing english localization key k_shannan_adj" + text = "missing english localization key k_hunan_adj" + text = "missing english localization key k_jiangdong_adj" + text = "missing english localization key k_liangzhe_adj" + text = "missing english localization key k_fujian_adj" + text = "missing english localization key k_jiangxi_adj" + text = "missing english localization key k_xichuan_adj" + text = "missing english localization key k_xingyuan_adj" + text = "missing english localization key k_dongchuan_adj" + text = "missing english localization key k_kuizhou_adj" + text = "missing english localization key k_caucasus_adj" + text = "missing english localization key k_silla_adj" + text = "missing english localization key k_goguryeo_adj" + text = "missing english localization key k_liuqiu_adj" + text = "missing english localization key k_kabisay-an_adj" + text = "missing english localization key k_malayadvipa_adj" + text = "missing english localization key k_tanjungnagara_adj" + text = "missing english localization key k_maluku_adj" + text = "missing english localization key k_yavakadvipa_adj" + text = "missing english localization key k_dvaravati_adj" text = "missing english localization key e_rajastan_adj" text = "missing english localization key e_ilkhanate_adj" text = "missing english localization key e_chagatai_adj" @@ -157,8 +302,27 @@ filter = { text = "missing english localization key e_kambuja_adj" text = "missing english localization key e_suvarnabhumi_adj" text = "missing english localization key e_lingnan_adj" - text = "missing english localization key d_laamp_" # ignores all missing adjectives for LAAMP titles - text = "missing english localization key d_nf_" # ignores all missing adjectives for noble family titles + text = "missing english localization key e_red_horde_adj" + text = "missing english localization key e_great_yuan_adj" + text = "missing english localization key e_blue_horde_adj" + text = "missing english localization key e_omnod_dalai_khanate_adj" + text = "missing english localization key e_viet_adj" + text = "missing english localization key e_majapahit_adj" + text = "missing english localization key e_amur_adj" + text = "missing english localization key e_srivijaya_adj" + text = "missing english localization key e_zhongyuan_adj" + text = "missing english localization key e_yongliang_adj" + text = "missing english localization key e_jingyang_adj" + text = "missing english localization key e_minister_chancellor_adj" + text = "missing english localization key e_minister_censor_adj" + text = "missing english localization key e_minister_grand_marshal_adj" + text = "missing english localization key e_minister_of_personnel_adj" + text = "missing english localization key e_minister_of_revenue_adj" + text = "missing english localization key e_minister_of_rites_adj" + text = "missing english localization key e_minister_of_war_adj" + text = "missing english localization key e_minister_of_justice_adj" + text = "missing english localization key e_minister_of_works_adj" + text = "missing english localization key e_liangyi_adj" text = "missing english localization key basque_pagan_desc" text = "missing english localization key baltic_pagan_desc" @@ -218,7 +382,6 @@ filter = { text = "missing english localization key NEGOTIATE_SETTLEMENT_ATTACKING_REASON" text = "missing english localization key NEGOTIATE_SETTLEMENT_POTENTIAL_WAR_TARGET_REASON" text = "missing english localization key NEGOTIATE_SETTLEMENT_CLAIMANT_REASON" - text = "missing english localization key NEGOTIATE_SETTLEMENT_FOREIGN_COUNTY_CULTURE_REASON" text = "missing english localization key NEGOTIATE_LAND_DISTANCE_REASON" text = "missing english localization key hinduism_trickster_god_namepossessive" text = "missing english localization key urartuism_fertility_god_name_possessiv" @@ -227,7 +390,6 @@ filter = { text = "missing english localization key Builder or Pious Builder" text = "missing english localization key lesser ruler, high medieval" text = "missing english localization key significant ruler, high medieval" - text = "missing english localization key lesser ruler, high medieval" text = "missing english localization key lesser ruler, late medieval" text = "missing english localization key ai_directive" text = "missing english localization key default value" @@ -242,6 +404,11 @@ filter = { text = "missing english localization key situation_parameter_hide_in_phases_list" text = "missing english localization key situation_parameter_era_type_stable" text = "missing english localization key dynastic_cycle_situation_dynastic_cycle_phase_stability_situation_phase" + text = "missing english localization key not_courtly_or_communal_desc" + text = "missing english localization key culture_parameter_male_only_inheritance" + text = "missing english localization key culture_parameter_male_preference_inheritance" + text = "missing english localization key not_bellicose_courtly_spiritual_or_stoic_desc" + text = "missing english localization key not_courtly_communal_egalitarian_or_spiritual_desc" text = "missing english localization key Komatsu" text = "missing english localization key Kinmei" text = "missing english localization key Kameyama" diff --git a/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs b/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs index 40f088e4e..b5e122baf 100644 --- a/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs +++ b/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs @@ -415,6 +415,27 @@ public void NameCanBeInitializedFromImperator() { Assert.Equal("Predrag \"Peja\" Stojaković", ck3LocDB.GetLocBlockForKey(irCharacter2NameLocKey)!["english"]); Assert.Equal($" {irCharacter2NameLocKey}: \"Predrag \\\"Peja\\\" Stojaković\"", ck3LocDB.GetYmlLocLineForLanguage(irCharacter2NameLocKey, "english")); } + + [Fact] + public void VariablesAreConvertedFromImperator() { + var imperatorCharacter = new ImperatorToCK3.Imperator.Characters.Character.Parse( + new BufferedReader( + "variables = {\n" + + " irtock3_ambition_progress = 1234000\n" + // 12.34 * 100000 + " irtock3_some_other_variable = 18446744073708317616\n" + // 2^64 - 12.34 * 100000 + "}" + ), + "1", + new GenesDB() + ); + + var character = builder + .WithImperatorCharacter(imperatorCharacter) + .Build(); + var date = new Date(1, 1, 1); + Assert.Equal(12.34, character.History.GetFieldValue("irtock3_ambition_progress", date)); + Assert.Equal(-12.34, character.History.GetFieldValue("irtock3_some_other_variable", date)); + } [Fact] public void AgeSexReturnsCorrectString() { diff --git a/ImperatorToCK3.UnitTests/CK3/Characters/CharacterCollectionTests.cs b/ImperatorToCK3.UnitTests/CK3/Characters/CharacterCollectionTests.cs index 32639ace5..21b27d42f 100644 --- a/ImperatorToCK3.UnitTests/CK3/Characters/CharacterCollectionTests.cs +++ b/ImperatorToCK3.UnitTests/CK3/Characters/CharacterCollectionTests.cs @@ -102,7 +102,6 @@ public void MarriageDateCanBeEstimatedFromChild() { new NicknameMapper(), new ProvinceMapper(), new DeathReasonMapper(), - new DNAFactory(irModFS, ck3ModFS), new TestCK3LocDB(), endDate, configuration); @@ -147,7 +146,6 @@ public void MarriageDateCanBeEstimatedFromUnbornChild() { new NicknameMapper(), new ProvinceMapper(), new DeathReasonMapper(), - new DNAFactory(irModFS, ck3ModFS), new TestCK3LocDB(), endDate, configuration); @@ -199,7 +197,6 @@ public void OnlyEarlyPregnanciesAreImportedFromImperator() { new NicknameMapper(), new ProvinceMapper(), new DeathReasonMapper(), - new DNAFactory(irModFS, ck3ModFS), new TestCK3LocDB(), conversionDate, configuration); @@ -344,7 +341,6 @@ public void ImperatorCountriesGoldCanBeDistributedAmongRulerAndVassals() { nicknameMapper, provinceMapper, deathReasonMapper, - new DNAFactory(irModFS, ck3ModFS), ck3LocDB, conversionDate, config); @@ -434,7 +430,6 @@ public void ImperatorCharacterNamesCanBeOverriddenByConfigurable() { new NicknameMapper(), new ProvinceMapper(), new DeathReasonMapper(), - new DNAFactory(irModFS, ck3ModFS), new TestCK3LocDB(), new Date(1000, 1, 1, AUC: true), config); diff --git a/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs b/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs index 03797ef0b..9f537a0d3 100644 --- a/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs +++ b/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs @@ -116,7 +116,7 @@ public void PrimaryImperatorProvinceIsProperlyDeterminedForCK3Province() { var ck3Provinces = new ProvinceCollection { new(1) }; var ck3RegionMapper = new CK3RegionMapper(); - AreaCollection areas = new(); + AreaCollection areas = []; areas.LoadAreas(irModFS, irWorld.Provinces); var irRegionMapper = new ImperatorRegionMapper(areas, new MapData(irModFS)); irRegionMapper.LoadRegions(irModFS, colorFactory); @@ -145,4 +145,65 @@ public void PrimaryImperatorProvinceIsProperlyDeterminedForCK3Province() { Assert.NotNull(primarySourceProvince); Assert.Equal((ulong)6, primarySourceProvince.Id); // province of country 2 } + + [Fact] + public void VariablesAreConvertedFromImperator() { + //var country1 = new Country(1); + var irProvsReader = new BufferedReader( + """ + = { + 1={ + { + flag="bool_negative + data={ + type=boolean # false + } + } + { + flag="bool_positive" + data={ + type=boolean + identity=1 # true + } + } + { + flag="number_positive" + data={ + type=value + identity=1234000 # 12.34 + } + } + { + flag="number_negative" + data={ + type=value + identity=18446744073708317616 # -12.34 + } + } + } + } + """ + ); + var provinces = new ImperatorToCK3.Imperator.Provinces.ProvinceCollection(); + provinces.LoadProvinces(irProvsReader, states: [], countries: [], new MapData(irModFS)); + var conversionDate = new Date(476, 1, 1); + var config = new Configuration { CK3BookmarkDate = conversionDate }; + var irWorld = new TestImperatorWorld(config); + + var provinceMapper = new ProvinceMapper(); + const string provinceMappingsPath = "TestFiles/LandedTitlesTests/province_mappings.txt"; + provinceMapper.LoadMappings(provinceMappingsPath); + + var ck3Provinces = new ProvinceCollection { new(1) }; + var ck3MapData = new MapData(ck3ModFs); + ck3MapData.ProvinceDefinitions.Add(new ProvinceDefinition(1)); + ck3Provinces.ImportImperatorProvinces(irWorld, ck3MapData, titles: [], new CultureMapper(new ImperatorRegionMapper(new AreaCollection(), new MapData(irModFS)), new CK3RegionMapper(), new CultureCollection(colorFactory, new PillarCollection(colorFactory, []), [])), new ReligionMapper(new ReligionCollection(new Title.LandedTitles()), new ImperatorRegionMapper(new AreaCollection(), new MapData(irModFS)), new CK3RegionMapper()), provinceMapper, new Date(867, 1, 1), new Configuration()); + + var ck3Province = ck3Provinces[1]; + Assert.Equal(4, ck3Province.Variables.Count); + Assert.Equal(false, ck3Province.Variables.GetValueById("bool_negative")); + Assert.Equal(true, ck3Province.Variables.GetValueById("bool_positive")); + Assert.Equal(12.34, ck3Province.Variables.GetValueById("number_positive")); + Assert.Equal(-12.34, ck3Province.Variables.GetValueById("number_negative")); + } } \ No newline at end of file diff --git a/ImperatorToCK3.UnitTests/CK3/Titles/LandedTitlesTests.cs b/ImperatorToCK3.UnitTests/CK3/Titles/LandedTitlesTests.cs index 2d54f0c87..f95e74b56 100644 --- a/ImperatorToCK3.UnitTests/CK3/Titles/LandedTitlesTests.cs +++ b/ImperatorToCK3.UnitTests/CK3/Titles/LandedTitlesTests.cs @@ -295,7 +295,6 @@ public void GovernorshipsCanBeRecognizedAsCountyLevel() { nicknameMapper, provinceMapper, deathReasonMapper, - dnaFactory, new TestCK3LocDB(), conversionDate, config diff --git a/ImperatorToCK3/CK3/Characters/CharacterCollection.cs b/ImperatorToCK3/CK3/Characters/CharacterCollection.cs index 1902b5b48..fa8ea1e07 100644 --- a/ImperatorToCK3/CK3/Characters/CharacterCollection.cs +++ b/ImperatorToCK3/CK3/Characters/CharacterCollection.cs @@ -40,7 +40,6 @@ internal void ImportImperatorCharacters( NicknameMapper nicknameMapper, ProvinceMapper provinceMapper, DeathReasonMapper deathReasonMapper, - DNAFactory dnaFactory, CK3LocDB ck3LocDB, Date conversionDate, Configuration config diff --git a/ImperatorToCK3/CK3/World.cs b/ImperatorToCK3/CK3/World.cs index 08671c53e..4ae3fadb4 100644 --- a/ImperatorToCK3/CK3/World.cs +++ b/ImperatorToCK3/CK3/World.cs @@ -269,7 +269,6 @@ internal World(Imperator.World impWorld, Configuration config, Thread? irCoaExtr nicknameMapper, provinceMapper, deathReasonMapper, - dnaFactory, LocDB, impWorld.EndDate, config @@ -362,8 +361,6 @@ internal World(Imperator.World impWorld, Configuration config, Thread? irCoaExtr Characters.RemoveEmployerIdFromLandedCharacters(LandedTitles, CorrectedDate); Characters.PurgeUnneededCharacters(LandedTitles, Dynasties, DynastyHouses, config.CK3BookmarkDate); - // We could convert Imperator character DNA while importing the characters. - // But that'd be wasteful, because some of them are purged. So, we do it now. Characters.ConvertImperatorCharacterDNA(dnaFactory); // If there's a gap between the Imperator save date and the CK3 bookmark date, diff --git a/ImperatorToCK3/Imperator/CharacterVariable.cs b/ImperatorToCK3/Imperator/CharacterVariable.cs new file mode 100644 index 000000000..98e98ad12 --- /dev/null +++ b/ImperatorToCK3/Imperator/CharacterVariable.cs @@ -0,0 +1,8 @@ +using commonItems.Collections; + +namespace ImperatorToCK3.Imperator; + +public readonly struct Variable(string id, object value) : IIdentifiable { + public string Id { get; } = id; + public object Value { get; init; } = value; +} \ No newline at end of file diff --git a/ImperatorToCK3/Imperator/Characters/Character.cs b/ImperatorToCK3/Imperator/Characters/Character.cs index 6df3e754e..4fe915347 100644 --- a/ImperatorToCK3/Imperator/Characters/Character.cs +++ b/ImperatorToCK3/Imperator/Characters/Character.cs @@ -1,11 +1,13 @@ -using commonItems; +using commonItems; using commonItems.Collections; +using ImperatorToCK3.CK3.Characters; using ImperatorToCK3.CommonUtils; using ImperatorToCK3.Imperator.Countries; using ImperatorToCK3.Imperator.Families; using ImperatorToCK3.CommonUtils.Genes; using ImperatorToCK3.CommonUtils.Map; using Open.Collections; +using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -90,8 +92,8 @@ public Family? Family { public List Traits { get; set; } = []; public CharacterAttributes Attributes { get; private set; } = new(); - public IReadOnlySet Variables { get; private set; } = ImmutableHashSet.Empty; - public bool IsBald => Variables.Contains("bald"); + public IdObjectCollection Variables { get; private set; } = []; + public bool IsBald { get; private set; } public uint Age { get; private set; } = 0; public string? DNA { get; private set; } public PortraitData? PortraitData { get; private set; } @@ -145,23 +147,77 @@ private static void RegisterCharacterKeywords(Parser parser, Character character } private static void SetVariables(Character character, BufferedReader reader) { - var variables = new HashSet(); - var variablesParser = new Parser(); - variablesParser.RegisterKeyword("data", dataReader => { - var blobParser = new Parser(); - blobParser.RegisterKeyword("flag", blobReader => variables.Add(string.Intern(blobReader.GetString()))); - blobParser.IgnoreUnregisteredItems(); - - foreach (var blob in new BlobList(dataReader).Blobs) { - blobParser.ParseStream(new BufferedReader(blob)); + var variablesParser = new Parser(); + variablesParser.RegisterKeyword("data", dataReader => { + foreach (var blob in new BlobList(dataReader).Blobs) { + ParseCharacterVariable(blob, character.Variables); + } + }); + variablesParser.RegisterKeyword("list", ParserHelpers.IgnoreItem); + variablesParser.IgnoreAndLogUnregisteredItems(); + variablesParser.ParseStream(reader); + if (character.Variables.ContainsKey("bald")) { // TODO: check if antigonus is converted bald + character.IsBald = true; + // Remove the "bald" flag to save memory. + character.Variables.Remove("bald"); + } + } + + private static void ParseCharacterVariable(string blob, IdObjectCollection variables) { + string? name = null; + int? tick = null; + string? type = null; + + var blobParser = new Parser(); + + // TODO: use CharacterVariable struct here + + blobParser.RegisterKeyword("flag", blobReader => name = string.Intern(blobReader.GetString())); + blobParser.RegisterKeyword("data", dataReader => { + var variableDataParser = new Parser(); + variableDataParser.RegisterKeyword("type", typeReader => { + type = typeReader.GetString(); + }); + // TODO: also handle "tick" (days remaining) + variableDataParser.RegisterKeyword("tick", tickReader => tick = tickReader.GetInt()); + variableDataParser.RegisterKeyword("identity", valueReader => { + // At this point we know everything we need, so we can add the variable to the collection right after reading its value. + if (name is null) { + Logger.Warn("Can't store character variable without knowing its name!"); + return; + } + if (type is null) { + Logger.Warn("Can't store character variable without knowing its type!"); + } + switch (type) { + case "boolean": + variables.Add(new Variable(name, valueReader.GetBool())); + break; + case "value": + // This represents a real number. + // The game uses fixed point arithmetic, for example: + // 12.34 is stores as 12.34 * 100000 = 1234000. + // Negative values: + // -12.34 is stored as 2^64 - (12.34 * 100000) = 18446744073708317616. + var ulongValue = valueReader.GetULong(); + var signedValue = unchecked((long)ulongValue); + var realValue = signedValue / 100000.0; + variables.Add(new Variable(name, realValue)); + break; + default: + Logger.Warn($"Unrecognized character variable type: {type}!"); + break; } }); - variablesParser.RegisterKeyword("list", ParserHelpers.IgnoreItem); - variablesParser.IgnoreAndLogUnregisteredItems(); - variablesParser.ParseStream(reader); - character.Variables = variables.ToImmutableHashSet(); + variableDataParser.IgnoreAndLogUnregisteredItems(); + variableDataParser.ParseStream(dataReader); + }); + blobParser.IgnoreUnregisteredItems(); + + var blobReader = new BufferedReader(blob); + blobParser.ParseStream(blobReader); } - + private static void SetCharacterName(Character character, BufferedReader reader) { var characterName = new CharacterName(reader); character.Name = characterName.Name; @@ -198,7 +254,7 @@ private static void SetUnborns(Character character, BufferedReader reader) { } character.Unborns = [.. unborns]; } - + public static Character Parse(BufferedReader reader, string idString, GenesDB? genesDB) { var parser = new Parser(implicitVariableHandling: false); var parsedCharacter = new Character(ulong.Parse(idString)); diff --git a/ImperatorToCK3/Imperator/Provinces/ProvinceFactory.cs b/ImperatorToCK3/Imperator/Provinces/ProvinceFactory.cs index d28dcb9fe..3fd0a4717 100644 --- a/ImperatorToCK3/Imperator/Provinces/ProvinceFactory.cs +++ b/ImperatorToCK3/Imperator/Provinces/ProvinceFactory.cs @@ -2,6 +2,7 @@ using ImperatorToCK3.CommonUtils; using ImperatorToCK3.Imperator.Countries; using ImperatorToCK3.Imperator.States; +using System; using System.Linq; namespace ImperatorToCK3.Imperator.Provinces; @@ -53,6 +54,9 @@ static Province() { var buildingsList = reader.GetInts(); parsedProvince.BuildingCount = (uint)buildingsList.Sum(); }); + provinceParser.RegisterKeyword("variables", reader => { + throw new NotImplementedException("TODO: convert variables to CK3"); + }); provinceParser.IgnoreAndStoreUnregisteredItems(IgnoredTokens); }