From dc04944cc8786aa05c5c1bdcff7125c469a9fe6a Mon Sep 17 00:00:00 2001 From: iht Date: Tue, 21 Oct 2025 21:19:34 +0200 Subject: [PATCH 1/6] Expand parsing of variables --- .../CK3/Characters/CK3CharacterTests.cs | 21 ++++++ .../Characters/CharacterCollectionTests.cs | 5 -- .../CK3/Titles/LandedTitlesTests.cs | 1 - .../CK3/Characters/CharacterCollection.cs | 1 - ImperatorToCK3/CK3/World.cs | 3 - .../Exceptions/ConverterException.cs | 11 --- .../Exceptions/UserErrorException.cs | 11 --- ImperatorToCK3/Imperator/CharacterVariable.cs | 8 +++ .../Imperator/Characters/Character.cs | 72 +++++++++++++++++-- .../Imperator/Provinces/ProvinceFactory.cs | 4 ++ 10 files changed, 98 insertions(+), 39 deletions(-) delete mode 100644 ImperatorToCK3/Exceptions/ConverterException.cs delete mode 100644 ImperatorToCK3/Exceptions/UserErrorException.cs create mode 100644 ImperatorToCK3/Imperator/CharacterVariable.cs diff --git a/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs b/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs index dbd0a7cf2..237eb3fad 100644 --- a/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs +++ b/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs @@ -399,6 +399,27 @@ public void NameCanBeInitializedFromImperator() { Assert.Equal("alexandros", character.GetName(ConversionDate)); Assert.Equal("Alexandros", ck3LocDB.GetLocBlockForKey("alexandros")!["english"]); } + + [Fact] + public void VariablesAreConvertedFromImperator() { + var imperatorCharacter = new ImperatorToCK3.Imperator.Characters.Character.Parse( + new BufferedReader( + "variables = {\n" + + " irtock3_ambition_progress = 0.42\n" + + " irtock3_some_other_variable = 69.0\n" + + "}" + ), + "1", + new GenesDB() + ); + + var character = builder + .WithImperatorCharacter(imperatorCharacter) + .Build(); + var date = new Date(1, 1, 1); + Assert.Equal(0.42, character.History.GetFieldValue("irtock3_ambition_progress", date)); + Assert.Equal(69.0, 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 0f285dfb2..7627ce7ad 100644 --- a/ImperatorToCK3.UnitTests/CK3/Characters/CharacterCollectionTests.cs +++ b/ImperatorToCK3.UnitTests/CK3/Characters/CharacterCollectionTests.cs @@ -97,7 +97,6 @@ public void MarriageDateCanBeEstimatedFromChild() { new NicknameMapper(), new ProvinceMapper(), new DeathReasonMapper(), - new DNAFactory(irModFS, ck3ModFS), new TestCK3LocDB(), endDate, configuration); @@ -142,7 +141,6 @@ public void MarriageDateCanBeEstimatedFromUnbornChild() { new NicknameMapper(), new ProvinceMapper(), new DeathReasonMapper(), - new DNAFactory(irModFS, ck3ModFS), new TestCK3LocDB(), endDate, configuration); @@ -194,7 +192,6 @@ public void OnlyEarlyPregnanciesAreImportedFromImperator() { new NicknameMapper(), new ProvinceMapper(), new DeathReasonMapper(), - new DNAFactory(irModFS, ck3ModFS), new TestCK3LocDB(), conversionDate, configuration); @@ -314,7 +311,6 @@ public void ImperatorCountriesGoldCanBeDistributedAmongRulerAndVassals() { nicknameMapper, provinceMapper, deathReasonMapper, - new DNAFactory(irModFS, ck3ModFS), ck3LocDB, conversionDate, config); @@ -404,7 +400,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/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 024a1dd48..ec371e92f 100644 --- a/ImperatorToCK3/CK3/Characters/CharacterCollection.cs +++ b/ImperatorToCK3/CK3/Characters/CharacterCollection.cs @@ -38,7 +38,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 c7bd18c4d..28dc14cb2 100644 --- a/ImperatorToCK3/CK3/World.cs +++ b/ImperatorToCK3/CK3/World.cs @@ -260,7 +260,6 @@ public World(Imperator.World impWorld, Configuration config, Thread? irCoaExtrac nicknameMapper, provinceMapper, deathReasonMapper, - dnaFactory, LocDB, impWorld.EndDate, config @@ -349,8 +348,6 @@ public World(Imperator.World impWorld, Configuration config, Thread? irCoaExtrac 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 I:R save date and the CK3 bookmark date, diff --git a/ImperatorToCK3/Exceptions/ConverterException.cs b/ImperatorToCK3/Exceptions/ConverterException.cs deleted file mode 100644 index c7a0fa140..000000000 --- a/ImperatorToCK3/Exceptions/ConverterException.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace ImperatorToCK3.Exceptions; - -internal class ConverterException : Exception { - public ConverterException(string message) : base(message) { } - - public ConverterException(string? message, Exception? innerException) : base(message, innerException) { } - - public ConverterException() : base() { } -} \ No newline at end of file diff --git a/ImperatorToCK3/Exceptions/UserErrorException.cs b/ImperatorToCK3/Exceptions/UserErrorException.cs deleted file mode 100644 index a877a4e2c..000000000 --- a/ImperatorToCK3/Exceptions/UserErrorException.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace ImperatorToCK3.Exceptions; - -internal class UserErrorException : ConverterException { - public UserErrorException(string message) : base(message) { } - - public UserErrorException(string? message, Exception? innerException) : base(message, innerException) { } - - public UserErrorException() : base() { } -} \ No newline at end of file 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 89ffe1dcb..6628d0752 100644 --- a/ImperatorToCK3/Imperator/Characters/Character.cs +++ b/ImperatorToCK3/Imperator/Characters/Character.cs @@ -1,11 +1,13 @@ 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; @@ -91,7 +93,7 @@ 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 bool IsBald { get; private set; } public uint Age { get; private set; } = 0; public string? DNA { get; private set; } public PortraitData? PortraitData { get; private set; } @@ -170,22 +172,78 @@ public static void RegisterCharacterKeywords(Parser parser, Character character) 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) { - var blobReader = new BufferedReader(blob); - blobParser.ParseStream(blobReader); + + ParseCharacterVariable(c); } }); variablesParser.RegisterKeyword("list", ParserHelpers.IgnoreItem); variablesParser.IgnoreAndLogUnregisteredItems(); variablesParser.ParseStream(reader); character.Variables = variables.ToImmutableHashSet(); + if (character.Variables.Contains("bald")) { + character.IsBald = true; + // Remove the "bald" flag to save memory. + variables.Remove("bald"); + } }); parser.IgnoreAndStoreUnregisteredItems(IgnoredTokens); } + + 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": // TODO: check if needed + // This represent a real number. + // For example, 12.34 is stores as "1234000". + var ulongValue = valueReader.GetULong(); + var realValue = ulongValue / 100000.0f; + variables.Add(new Variable(name, realValue)); + // TODO: HOW TO HANDLE NEGATIVE VALUES? + throw new NotImplementedException(); + break; + default: + Logger.Warn($"Unrecognized character variable type: {type}!"); + break; + } + + variables.Add(new CharacterVariable(name, value)); + }); + variableDataParser.IgnoreAndLogUnregisteredItems(); + variableDataParser.ParseStream(dataReader); + }); + blobParser.IgnoreUnregisteredItems(); + + var blobReader = new BufferedReader(blob); + blobParser.ParseStream(blobReader); + } public static Character Parse(BufferedReader reader, string idString, GenesDB? genesDB) { var parser = new Parser(); var parsedCharacter = new Character(ulong.Parse(idString)); diff --git a/ImperatorToCK3/Imperator/Provinces/ProvinceFactory.cs b/ImperatorToCK3/Imperator/Provinces/ProvinceFactory.cs index 3c0308df3..da96d1be6 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); } From 9eaa0ab4d9576e60cefbeea5bf367ce98b08ba40 Mon Sep 17 00:00:00 2001 From: codefactor-io Date: Sat, 24 Jan 2026 00:22:03 +0000 Subject: [PATCH 2/6] [CodeFactor] Apply fixes --- ImperatorToCK3/Imperator/Characters/Character.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ImperatorToCK3/Imperator/Characters/Character.cs b/ImperatorToCK3/Imperator/Characters/Character.cs index 6628d0752..f97621b6b 100644 --- a/ImperatorToCK3/Imperator/Characters/Character.cs +++ b/ImperatorToCK3/Imperator/Characters/Character.cs @@ -1,4 +1,4 @@ -using commonItems; +using commonItems; using commonItems.Collections; using ImperatorToCK3.CK3.Characters; using ImperatorToCK3.CommonUtils; @@ -173,7 +173,6 @@ public static void RegisterCharacterKeywords(Parser parser, Character character) var variablesParser = new Parser(); variablesParser.RegisterKeyword("data", dataReader => { foreach (var blob in new BlobList(dataReader).Blobs) { - ParseCharacterVariable(c); } }); From 900fc7b825e5de5aa21e2bde9c0f36067a704e46 Mon Sep 17 00:00:00 2001 From: iht Date: Sat, 31 Jan 2026 01:00:50 +0100 Subject: [PATCH 3/6] Handle negative values in variables --- .../CK3/Characters/CK3CharacterTests.cs | 8 +-- .../CK3/Provinces/ProvincesTests.cs | 66 ++++++++++++++++++- .../Imperator/Characters/Character.cs | 26 ++++---- 3 files changed, 80 insertions(+), 20 deletions(-) diff --git a/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs b/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs index 237eb3fad..83bc7f084 100644 --- a/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs +++ b/ImperatorToCK3.UnitTests/CK3/Characters/CK3CharacterTests.cs @@ -405,8 +405,8 @@ public void VariablesAreConvertedFromImperator() { var imperatorCharacter = new ImperatorToCK3.Imperator.Characters.Character.Parse( new BufferedReader( "variables = {\n" + - " irtock3_ambition_progress = 0.42\n" + - " irtock3_some_other_variable = 69.0\n" + + " irtock3_ambition_progress = 1234000\n" + // 12.34 * 100000 + " irtock3_some_other_variable = 18446744073708317616\n" + // 2^64 - 12.34 * 100000 "}" ), "1", @@ -417,8 +417,8 @@ public void VariablesAreConvertedFromImperator() { .WithImperatorCharacter(imperatorCharacter) .Build(); var date = new Date(1, 1, 1); - Assert.Equal(0.42, character.History.GetFieldValue("irtock3_ambition_progress", date)); - Assert.Equal(69.0, character.History.GetFieldValue("irtock3_some_other_variable", date)); + Assert.Equal(12.34, character.History.GetFieldValue("irtock3_ambition_progress", date)); + Assert.Equal(-12.34, character.History.GetFieldValue("irtock3_some_other_variable", date)); } [Fact] diff --git a/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs b/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs index 73699d4f5..bd41bb489 100644 --- a/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs +++ b/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs @@ -8,6 +8,7 @@ using ImperatorToCK3.CommonUtils.Map; using ImperatorToCK3.Imperator.Countries; using ImperatorToCK3.Imperator.Geography; +using ImperatorToCK3.Imperator.States; using ImperatorToCK3.Mappers.Culture; using ImperatorToCK3.Mappers.Province; using ImperatorToCK3.Mappers.Region; @@ -122,9 +123,9 @@ public void PrimaryImperatorProvinceIsProperlyDeterminedForCK3Province() { Assert.NotNull(primarySourceProvince); Assert.Equal((ulong)3, primarySourceProvince.Id); // most developed province in country 1 - // Scenario 2: Single developed province in country 2 outweighs sum of civilisation in country 1. + // Scenario 2: Single developed province in country 2 outweighs sum of civilization in country 1. irProvince6.CivilizationValue = 100; - ck3Provinces = new ProvinceCollection { new(1) }; + ck3Provinces = [new(1)]; ck3Provinces.ImportImperatorProvinces(irWorld, ck3MapData, titles, cultureMapper, religionMapper, provinceMapper, conversionDate, config); targetProvince = ck3Provinces[1]; @@ -133,4 +134,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, new StateCollection(), new CountryCollection(), 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, new Title.LandedTitles(), 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/Imperator/Characters/Character.cs b/ImperatorToCK3/Imperator/Characters/Character.cs index f97621b6b..f01963a70 100644 --- a/ImperatorToCK3/Imperator/Characters/Character.cs +++ b/ImperatorToCK3/Imperator/Characters/Character.cs @@ -92,7 +92,7 @@ public Family? Family { public List Traits { get; set; } = []; public CharacterAttributes Attributes { get; private set; } = new(); - public IReadOnlySet Variables { get; private set; } = ImmutableHashSet.Empty; + 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; } @@ -169,21 +169,19 @@ public static void RegisterCharacterKeywords(Parser parser, Character character) }); parser.RegisterKeyword("prisoner_home", reader => character.parsedPrisonerHomeId = reader.GetULong()); parser.RegisterKeyword("variables", reader => { - var variables = new HashSet(); var variablesParser = new Parser(); variablesParser.RegisterKeyword("data", dataReader => { foreach (var blob in new BlobList(dataReader).Blobs) { - ParseCharacterVariable(c); + ParseCharacterVariable(blob, character.Variables); } }); variablesParser.RegisterKeyword("list", ParserHelpers.IgnoreItem); variablesParser.IgnoreAndLogUnregisteredItems(); variablesParser.ParseStream(reader); - character.Variables = variables.ToImmutableHashSet(); - if (character.Variables.Contains("bald")) { + if (character.Variables.ContainsKey("bald")) { // TODO: check if antigonus is converted bald character.IsBald = true; // Remove the "bald" flag to save memory. - variables.Remove("bald"); + character.Variables.Remove("bald"); } }); parser.IgnoreAndStoreUnregisteredItems(IgnoredTokens); @@ -219,21 +217,21 @@ private static void ParseCharacterVariable(string blob, IdObjectCollection Date: Tue, 17 Mar 2026 15:31:32 +0000 Subject: [PATCH 4/6] [CodeFactor] Apply fixes --- ImperatorToCK3/Imperator/Characters/Character.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/ImperatorToCK3/Imperator/Characters/Character.cs b/ImperatorToCK3/Imperator/Characters/Character.cs index 2b8de69c7..4e2f5e153 100644 --- a/ImperatorToCK3/Imperator/Characters/Character.cs +++ b/ImperatorToCK3/Imperator/Characters/Character.cs @@ -147,7 +147,6 @@ private static void RegisterCharacterKeywords(Parser parser, Character character variablesParser.RegisterKeyword("data", dataReader => { foreach (var blob in new BlobList(dataReader).Blobs) { ParseCharacterVariable(blob, character.Variables); - } }); variablesParser.RegisterKeyword("list", ParserHelpers.IgnoreItem); From 50270da0ce363245eff9c93aa759a16030337304 Mon Sep 17 00:00:00 2001 From: iht Date: Tue, 17 Mar 2026 17:22:35 +0100 Subject: [PATCH 5/6] Update ck3-tiger.conf --- .github/workflows/ck3-tiger.conf | 175 ++++++++++++++++++++++++++++++- 1 file changed, 171 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ck3-tiger.conf b/.github/workflows/ck3-tiger.conf index 2c3107bdc..9d4499b95 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" } } } From 085b87c4a93cbfcb3d38fcc2ec8651c70ea2f433 Mon Sep 17 00:00:00 2001 From: iht Date: Sat, 21 Mar 2026 01:01:26 +0100 Subject: [PATCH 6/6] Bring back the SetVariables method from upstream --- .../CK3/Provinces/ProvincesTests.cs | 7 ++-- .../Imperator/Characters/Character.cs | 32 ++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs b/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs index 93af2abe4..9f537a0d3 100644 --- a/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs +++ b/ImperatorToCK3.UnitTests/CK3/Provinces/ProvincesTests.cs @@ -8,7 +8,6 @@ using ImperatorToCK3.CommonUtils.Map; using ImperatorToCK3.Imperator.Countries; using ImperatorToCK3.Imperator.Geography; -using ImperatorToCK3.Imperator.States; using ImperatorToCK3.Mappers.Culture; using ImperatorToCK3.Mappers.Province; using ImperatorToCK3.Mappers.Region; @@ -117,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); @@ -186,7 +185,7 @@ public void VariablesAreConvertedFromImperator() { """ ); var provinces = new ImperatorToCK3.Imperator.Provinces.ProvinceCollection(); - provinces.LoadProvinces(irProvsReader, new StateCollection(), new CountryCollection(), new MapData(irModFS)); + 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); @@ -198,7 +197,7 @@ public void VariablesAreConvertedFromImperator() { var ck3Provinces = new ProvinceCollection { new(1) }; var ck3MapData = new MapData(ck3ModFs); ck3MapData.ProvinceDefinitions.Add(new ProvinceDefinition(1)); - ck3Provinces.ImportImperatorProvinces(irWorld, ck3MapData, new Title.LandedTitles(), 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()); + 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); diff --git a/ImperatorToCK3/Imperator/Characters/Character.cs b/ImperatorToCK3/Imperator/Characters/Character.cs index 4e2f5e153..cc5f4d61e 100644 --- a/ImperatorToCK3/Imperator/Characters/Character.cs +++ b/ImperatorToCK3/Imperator/Characters/Character.cs @@ -142,23 +142,25 @@ private static void RegisterCharacterKeywords(Parser parser, Character character parser.RegisterKeyword("wealth", reader => character.Wealth = reader.GetFloat()); parser.RegisterKeyword("unborn", r => SetUnborns(character, r)); parser.RegisterKeyword("prisoner_home", reader => character.parsedPrisonerHomeId = reader.GetULong()); - parser.RegisterKeyword("variables", reader => { - 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"); + parser.RegisterKeyword("variables", r => SetVariables(character, r)); + parser.IgnoreAndStoreUnregisteredItems(IgnoredTokens); + } + + private static void SetVariables(Character character, BufferedReader reader) { + var variablesParser = new Parser(); + variablesParser.RegisterKeyword("data", dataReader => { + foreach (var blob in new BlobList(dataReader).Blobs) { + ParseCharacterVariable(blob, character.Variables); } }); - parser.IgnoreAndStoreUnregisteredItems(IgnoredTokens); + 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) {