Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix landed title definitions from multiple files not being correctly merged #2240

Merged
merged 1 commit into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion ImperatorToCK3.UnitTests/CK3/Titles/LandedTitlesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -582,4 +582,29 @@ public void GetBaronyForProvinceReturnsCorrectBaronyOrNullWhenNotFound() {
Assert.Equal("b_barony3", titles.GetBaronyForProvince(3)?.Id);
Assert.Null(titles.GetBaronyForProvince(4));
}
}

[Fact]
public void TitlesCanBeExpandedInOtherFiles() {
var titles = new Title.LandedTitles();
titles.LoadTitles(ck3ModFS, new TestCK3LocDB());

// e_mongolia's color is defined in base_landed_titles.txt.
// But its capital is defined in extra_landed_titles.txt.
// If both are properly set, it means that we're correctly loading a title from multiple files.
var mongoliaEmpire = titles["e_mongolia"];
Assert.Equal(new Color(90, 90, 240), mongoliaEmpire.Color1);
Assert.Equal("c_karakorum", mongoliaEmpire.CapitalCountyId);

// It has k_mongolia and k_angara defined as de jure vassals in base_landed_titles.txt.
// It also has k_jubu defined as a de jure vassal in extra_landed_titles.txt.
Assert.Equal(3, mongoliaEmpire.DeJureVassals.Count);

// k_mongolia's color is defined in base_landed_titles.txt.
// But its capital is defined in extra_landed_titles.txt.
// This checks if we can correctly load lower rank titles (nested in the structure) from multiple files.
var mongoliaKingdom = titles["k_mongolia"];
Assert.Equal(new Color(20, 65, 25), mongoliaKingdom.Color1);
Assert.Equal("c_karakorum", mongoliaKingdom.CapitalCountyId);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
e_mongolia = {
color = { 90 90 240 }

k_mongolia = {
color = { 20 65 25 }
}

k_angara = {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
e_mongolia = {
capital = c_karakorum

k_mongolia = {
capital = c_karakorum
}

k_jubu = {}
}
14 changes: 9 additions & 5 deletions ImperatorToCK3/CK3/Titles/LandedTitles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,14 @@ private void RegisterKeys(Parser parser) {
Variables[variableName[1..]] = variableValue;
});
parser.RegisterRegex(Regexes.TitleId, (reader, titleNameStr) => {
// Pull the titles beneath this one and add them to the lot, overwriting existing ones.
var newTitle = Add(titleNameStr);
newTitle.LoadTitles(reader);
// Pull the titles beneath this one and add them to the lot.
// A title can be defined in multiple files, in that case merge the definitions.
if (TryGetValue(titleNameStr, out var titleToUpdate)) {
titleToUpdate.LoadTitles(reader);
} else {
var newTitle = Add(titleNameStr);
newTitle.LoadTitles(reader);
}
});
parser.IgnoreAndLogUnregisteredItems();
}
Expand Down Expand Up @@ -221,8 +226,7 @@ ImperatorRegionMapper imperatorRegionMapper
}
public override void Remove(string name) {
if (dict.TryGetValue(name, out var titleToErase)) {
var deJureLiege = titleToErase.DeJureLiege;
deJureLiege?.DeJureVassals.Remove(name);
titleToErase.DeJureLiege = null; // Remove two-way liege-vassal link.

foreach (var vassal in titleToErase.DeJureVassals) {
vassal.DeJureLiege = null;
Expand Down
26 changes: 16 additions & 10 deletions ImperatorToCK3/CK3/Titles/Title.cs
Original file line number Diff line number Diff line change
Expand Up @@ -940,9 +940,9 @@ public Title? DeJureLiege { // direct de jure liege title
Logger.Warn($"Cannot set de jure liege {value} to {Id}: rank is not higher!");
return;
}
deJureLiege?.DeJureVassals.Remove(Id);
deJureLiege?.deJureVassals.Remove(Id);
deJureLiege = value;
value?.DeJureVassals.AddOrReplace(this);
value?.deJureVassals.AddOrReplace(this);
}
}
public Title? GetDeFactoLiege(Date date) { // direct de facto liege title
Expand Down Expand Up @@ -978,7 +978,8 @@ public void SetDeFactoLiege(Title? newLiege, Date date) {
}
}

[SerializeOnlyValue] public TitleCollection DeJureVassals { get; } = new(); // DIRECT de jure vassals
private readonly TitleCollection deJureVassals = [];
[SerializeOnlyValue] public IReadOnlyTitleCollection DeJureVassals => deJureVassals; // DIRECT de jure vassals
public IDictionary<string, Title> GetDeJureVassalsAndBelow() {
return GetDeJureVassalsAndBelow("bcdke");
}
Expand Down Expand Up @@ -1090,16 +1091,21 @@ public ICollection<string> GetSuccessionLaws(Date date) {

private void RegisterKeys(Parser parser) {
parser.RegisterRegex(Regexes.TitleId, (reader, titleNameStr) => {
// Pull the titles beneath this one and add them to the lot, overwriting existing ones.
var newTitle = parentCollection.Add(titleNameStr);
newTitle.LoadTitles(reader);
// Pull the titles beneath this one and add them to the lot.
// A title can be defined in multiple files, in that case merge the definitions.
if (parentCollection.TryGetValue(titleNameStr, out var childTitle)) {
childTitle.LoadTitles(reader);
} else {
childTitle = parentCollection.Add(titleNameStr);
childTitle.LoadTitles(reader);
}

if (newTitle.Rank == TitleRank.barony && string.IsNullOrEmpty(CapitalBaronyId)) {
if (childTitle.Rank == TitleRank.barony && string.IsNullOrEmpty(CapitalBaronyId)) {
// title is a barony, and no other barony has been found in this scope yet
CapitalBaronyId = newTitle.Id;
CapitalBaronyId = childTitle.Id;
}

newTitle.DeJureLiege = this;
childTitle.DeJureLiege = this;
});
parser.RegisterKeyword("definite_form", reader => HasDefiniteForm = reader.GetBool());
parser.RegisterKeyword("ruler_uses_title_name", reader => RulerUsesTitleName = reader.GetBool());
Expand Down
7 changes: 6 additions & 1 deletion ImperatorToCK3/CK3/Titles/TitleCollection.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
using commonItems.Collections;
using System.Collections.Generic;

namespace ImperatorToCK3.CK3.Titles;

public class TitleCollection : IdObjectCollection<string, Title>;
public interface IReadOnlyTitleCollection : IReadOnlyCollection<Title> {
public bool ContainsKey(string key);
}

public class TitleCollection : IdObjectCollection<string, Title>, IReadOnlyTitleCollection;
Loading