Skip to content

Commit

Permalink
Fix exception when using unsupported CK3 map mod combinations (#1636)…
Browse files Browse the repository at this point in the history
… #patch

Sentry event ID: 6a21957012454c3f9a7267777859cfd3
  • Loading branch information
IhateTrains authored Dec 14, 2023
1 parent 0984e79 commit 016c269
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 54 deletions.
2 changes: 1 addition & 1 deletion ImperatorToCK3.UnitTests/CK3/Titles/TitleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ public void CapitalBaronyDefaultsToNull() {
var titles = new Title.LandedTitles();
var title = titles.Add("k_testtitle");

Assert.Null(title.CapitalBaronyProvince);
Assert.Null(title.CapitalBaronyProvinceId);
}

[Fact]
Expand Down
4 changes: 2 additions & 2 deletions ImperatorToCK3/CK3/Provinces/Province.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,8 @@ private void SetHoldingFromImperator(Title.LandedTitles landedTitles) {

public bool IsCountyCapital(Title.LandedTitles landedTitles) {
var capitalProvIds = landedTitles
.Where(t => t.CapitalBaronyProvince is not null)
.Select(t => (ulong)t.CapitalBaronyProvince!);
.Where(t => t.CapitalBaronyProvinceId is not null)
.Select(t => (ulong)t.CapitalBaronyProvinceId!);
return capitalProvIds.Contains(Id);
}
}
6 changes: 3 additions & 3 deletions ImperatorToCK3/CK3/Religions/ReligionCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ public void LoadDoctrines(ModFilesystem ck3ModFS) {
return null;
}

var capitalBaronyProvince = landedTitles[holySite.CountyId].CapitalBaronyProvince;
if (capitalBaronyProvince is not null) {
return landedTitles.GetBaronyForProvince((ulong)capitalBaronyProvince);
var capitalBaronyProvinceId = landedTitles[holySite.CountyId].CapitalBaronyProvinceId;
if (capitalBaronyProvinceId is not null) {
return landedTitles.GetBaronyForProvince((ulong)capitalBaronyProvinceId);
}

return null;
Expand Down
66 changes: 37 additions & 29 deletions ImperatorToCK3/CK3/Titles/LandedTitles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public override void Remove(string name) {
}
public Title? GetCountyForProvince(ulong provinceId) {
foreach (var county in this.Where(title => title.Rank == TitleRank.county)) {
if (county.CountyProvinces.Contains(provinceId)) {
if (county.CountyProvinceIds.Contains(provinceId)) {
return county;
}
}
Expand Down Expand Up @@ -593,7 +593,7 @@ public void SetDeJureKingdomsAndEmpires(Date ck3BookmarkDate, ProvinceCollection
continue;
}
kingdomRealmShares.TryGetValue(kingdomRealm.Id, out var currentCount);
kingdomRealmShares[kingdomRealm.Id] = currentCount + county.CountyProvinces.Count();
kingdomRealmShares[kingdomRealm.Id] = currentCount + county.CountyProvinceIds.Count();
}
if (kingdomRealmShares.Count > 0) {
var biggestShare = kingdomRealmShares.MaxBy(pair => pair.Value);
Expand All @@ -608,7 +608,7 @@ public void SetDeJureKingdomsAndEmpires(Date ck3BookmarkDate, ProvinceCollection
var empireShares = new Dictionary<string, int>();
var kingdomProvincesCount = 0;
foreach (var county in kingdom.GetDeJureVassalsAndBelow("c").Values) {
var countyProvincesCount = county.CountyProvinces.Count();
var countyProvincesCount = county.CountyProvinceIds.Count();
kingdomProvincesCount += countyProvincesCount;

var empireRealm = county.GetRealmOfRank(TitleRank.empire, ck3BookmarkDate);
Expand Down Expand Up @@ -638,7 +638,7 @@ public void SetDeJureKingdomsAndEmpires(Date ck3BookmarkDate, ProvinceCollection

foreach (var kingdom in kingdomsWithoutEmpire) {
var counties = kingdom.GetDeJureVassalsAndBelow("c").Values;
var kingdomProvinceIds = counties.SelectMany(c => c.CountyProvinces).ToImmutableHashSet();
var kingdomProvinceIds = counties.SelectMany(c => c.CountyProvinceIds).ToImmutableHashSet();
var kingdomProvinces = ck3Provinces.Where(p => kingdomProvinceIds.Contains(p.Id));
var dominantHeritage = kingdomProvinces
.Select(p => new { Province = p, p.GetCulture(ck3BookmarkDate, ck3Cultures)?.Heritage})
Expand Down Expand Up @@ -687,38 +687,20 @@ private HashSet<string> GetCountyHolderIds(Date date) {
}

public void ImportDevelopmentFromImperator(ProvinceCollection ck3Provinces, Date date, double irCivilizationWorth) {
static (Dictionary<string, int>, Dictionary<ulong, int>) GetIRProvsPerCounty(ProvinceCollection ck3Provinces, IEnumerable<Title> counties) {
var impProvsPerCounty = new Dictionary<string, int>();
var ck3ProvsPerImperatorProv = new Dictionary<ulong, int>();
foreach (var county in counties) {
var imperatorProvs = new HashSet<ulong>();
foreach (var ck3ProvId in county.CountyProvinces) {
var ck3Province = ck3Provinces[ck3ProvId];
var sourceProvinces = ck3Province.ImperatorProvinces;
foreach (var irProvince in sourceProvinces) {
imperatorProvs.Add(irProvince.Id);
ck3ProvsPerImperatorProv.TryGetValue(irProvince.Id, out var currentValue);
ck3ProvsPerImperatorProv[irProvince.Id] = currentValue + 1;
}
}

impProvsPerCounty[county.Id] = imperatorProvs.Count;
}

return (impProvsPerCounty, ck3ProvsPerImperatorProv);
}

static bool IsCountyOutsideImperatorMap(Title county, IReadOnlyDictionary<string, int> impProvsPerCounty) {
return impProvsPerCounty[county.Id] == 0;
}

double CalculateCountyDevelopment(Title county, IReadOnlyDictionary<ulong, int> ck3ProvsPerIRProv) {
double dev = 0;
var countyProvinces = county.CountyProvinces;
var provsCount = 0;
foreach (var ck3ProvId in countyProvinces) {
IEnumerable<ulong> countyProvinceIds = county.CountyProvinceIds;
int provsCount = 0;
foreach (var ck3ProvId in countyProvinceIds) {
if (!ck3Provinces.TryGetValue(ck3ProvId, out var ck3Province)) {
Logger.Warn($"CK3 province {ck3ProvId} not found!");
continue;
}
++provsCount;
var ck3Province = ck3Provinces[ck3ProvId];
var sourceProvinces = ck3Province.ImperatorProvinces;
if (sourceProvinces.Count == 0) {
continue;
Expand Down Expand Up @@ -751,6 +733,32 @@ double CalculateCountyDevelopment(Title county, IReadOnlyDictionary<ulong, int>
}

Logger.IncrementProgress();
return;

static (Dictionary<string, int>, Dictionary<ulong, int>) GetIRProvsPerCounty(ProvinceCollection ck3Provinces, IEnumerable<Title> counties) {
Dictionary<string, int> impProvsPerCounty = [];
Dictionary<ulong, int> ck3ProvsPerImperatorProv = [];
foreach (var county in counties) {
HashSet<ulong> imperatorProvs = [];
foreach (ulong ck3ProvId in county.CountyProvinceIds) {
if (!ck3Provinces.TryGetValue(ck3ProvId, out var ck3Province)) {
Logger.Warn($"CK3 province {ck3ProvId} not found!");
continue;
}

var sourceProvinces = ck3Province.ImperatorProvinces;
foreach (var irProvince in sourceProvinces) {
imperatorProvs.Add(irProvince.Id);
ck3ProvsPerImperatorProv.TryGetValue(irProvince.Id, out var currentValue);
ck3ProvsPerImperatorProv[irProvince.Id] = currentValue + 1;
}
}

impProvsPerCounty[county.Id] = imperatorProvs.Count;
}

return (impProvsPerCounty, ck3ProvsPerImperatorProv);
}
}

public IEnumerable<Title> GetCountriesImportedFromImperator() {
Expand Down
12 changes: 6 additions & 6 deletions ImperatorToCK3/CK3/Titles/Title.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,7 @@ private void TrySetCapitalBarony() {
ulong baronyProvinceId = (ulong)deJureVassal.Province;

if (deJureVassal.Id == CapitalBaronyId) {
CapitalBaronyProvince = baronyProvinceId;
CapitalBaronyProvinceId = baronyProvinceId;
break;
}
}
Expand Down Expand Up @@ -1063,7 +1063,7 @@ public ISet<ulong> GetProvincesInCountry(Date date) {
var heldProvinces = new HashSet<ulong>();
// add directly held counties
foreach (var county in heldCounties) {
heldProvinces.UnionWith(county.CountyProvinces);
heldProvinces.UnionWith(county.CountyProvinceIds);
}
// add vassals' counties
foreach (var vassal in GetDeFactoVassalsAndBelow(date).Values) {
Expand All @@ -1076,7 +1076,7 @@ public ISet<ulong> GetProvincesInCountry(Date date) {
parentCollection.Where(t => t.GetHolderId(date) == vassalHolderId && t.Rank == TitleRank.county)
);
foreach (var vassalCounty in heldVassalCounties) {
heldProvinces.UnionWith(vassalCounty.CountyProvinces);
heldProvinces.UnionWith(vassalCounty.CountyProvinceIds);
}
}
return heldProvinces;
Expand All @@ -1099,7 +1099,7 @@ public bool DuchyContainsProvince(ulong provinceId) {
return false;
}

return DeJureVassals.Any(vassal => vassal.Rank == TitleRank.county && vassal.CountyProvinces.Contains(provinceId));
return DeJureVassals.Any(vassal => vassal.Rank == TitleRank.county && vassal.CountyProvinceIds.Contains(provinceId));
}

public Title GetTopRealm(Date date) {
Expand Down Expand Up @@ -1153,9 +1153,9 @@ public Title GetTopRealm(Date date) {
}

// used by county titles only
[commonItems.Serialization.NonSerialized] public IEnumerable<ulong> CountyProvinces => DeJureVassals.Where(v => v.Rank == TitleRank.barony).Select(v => (ulong)v.Province!);
[commonItems.Serialization.NonSerialized] public IEnumerable<ulong> CountyProvinceIds => DeJureVassals.Where(v => v.Rank == TitleRank.barony).Select(v => (ulong)v.Province!);
[commonItems.Serialization.NonSerialized] private string CapitalBaronyId { get; set; } = string.Empty; // used when parsing inside county to save first barony
[commonItems.Serialization.NonSerialized] public ulong? CapitalBaronyProvince { get; private set; } // county barony's province; 0 is not a valid barony ID
[commonItems.Serialization.NonSerialized] public ulong? CapitalBaronyProvinceId { get; private set; } // county barony's province; 0 is not a valid barony ID

// used by barony titles only
[SerializedName("province")] public ulong? Province { get; private set; } // province is area on map. b_barony is its corresponding title.
Expand Down
28 changes: 20 additions & 8 deletions ImperatorToCK3/CK3/World.cs
Original file line number Diff line number Diff line change
Expand Up @@ -360,11 +360,11 @@ private void OverwriteCountiesHistory(IEnumerable<Governorship> governorships, I
var countyLevelGovernorshipsSet = countyLevelGovernorships.ToHashSet();

foreach (var county in LandedTitles.Where(t => t.Rank == TitleRank.county)) {
if (county.CapitalBaronyProvince is null) {
if (county.CapitalBaronyProvinceId is null) {
Logger.Warn($"County {county} has no capital barony province!");
continue;
}
ulong capitalBaronyProvinceId = (ulong)county.CapitalBaronyProvince;
ulong capitalBaronyProvinceId = (ulong)county.CapitalBaronyProvinceId;
if (capitalBaronyProvinceId == 0) {
// title's capital province has an invalid ID (0 is not a valid province in CK3)
Logger.Warn($"County {county} has invalid capital barony province!");
Expand Down Expand Up @@ -590,7 +590,7 @@ private void HandleIcelandAndFaroeIslands(Configuration config) {
foreach (var county in title.GetDeJureVassalsAndBelow(rankFilter: "c").Values) {
county.SetHolder(hermit, bookmarkDate);
county.SetDevelopmentLevel(0, bookmarkDate);
foreach (var provinceId in county.CountyProvinces) {
foreach (var provinceId in county.CountyProvinceIds) {
var province = Provinces[provinceId];
province.History.RemoveHistoryPastDate("1.1.1");
province.SetFaithId(faithId, date: null);
Expand Down Expand Up @@ -689,14 +689,26 @@ private void GenerateFillerHoldersForUnownedLands(CultureCollection cultures, Co
}

var candidateProvinces = new OrderedSet<Province>();
if (county.CapitalBaronyProvince is not null) {
if (county.CapitalBaronyProvinceId is not null) {
// Give priority to capital province.
candidateProvinces.Add(Provinces[county.CapitalBaronyProvince.Value]);
if (Provinces.TryGetValue(county.CapitalBaronyProvinceId.Value, out var capitalProvince)) {
candidateProvinces.Add(capitalProvince);
}
}
var allCountyProvinces = county.CountyProvinces
.Select(p => Provinces[p]);

var allCountyProvinces = county.CountyProvinceIds
.Select(id => Provinces.TryGetValue(id, out var province) ? province : null)
.Where(p => p is not null)
.Select(p => p!);
candidateProvinces.UnionWith(allCountyProvinces);
var pseudoRandomSeed = (int)candidateProvinces.First().Id;

int pseudoRandomSeed;
if (candidateProvinces.Count != 0) {
pseudoRandomSeed = (int)candidateProvinces.First().Id;
} else {
// Use county ID for seed if no province is available.
pseudoRandomSeed = county.Id.Aggregate(0, (current, c) => current + c);
}

// Determine culture of the holder.
var culture = candidateProvinces
Expand Down
2 changes: 1 addition & 1 deletion ImperatorToCK3/Mappers/Region/CK3Region.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public bool ContainsProvince(ulong provinceId) {
if (Duchies.Values.Any(duchy => duchy.DuchyContainsProvince(provinceId))) {
return true;
}
if (Counties.Values.Any(county => county.CountyProvinces.Contains(provinceId))) {
if (Counties.Values.Any(county => county.CountyProvinceIds.Contains(provinceId))) {
return true;
}
return Provinces.Contains(provinceId);
Expand Down
4 changes: 2 additions & 2 deletions ImperatorToCK3/Mappers/Region/CK3RegionMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public bool ProvinceIsInRegion(ulong provinceId, string regionName) {
}

// And sometimes they don't mean what people think they mean at all.
return counties.TryGetValue(regionName, out var county) && county.CountyProvinces.Contains(provinceId);
return counties.TryGetValue(regionName, out var county) && county.CountyProvinceIds.Contains(provinceId);
}
public bool RegionNameIsValid(string regionName) {
if (regions.ContainsKey(regionName)) {
Expand All @@ -68,7 +68,7 @@ public bool RegionNameIsValid(string regionName) {
}
public string? GetParentCountyName(ulong provinceId) {
foreach (var (countyName, county) in counties) {
if (county.CountyProvinces.Contains(provinceId)) {
if (county.CountyProvinceIds.Contains(provinceId)) {
return countyName;
}
}
Expand Down
2 changes: 1 addition & 1 deletion ImperatorToCK3/Mappers/TagTitle/Mapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class Mapping {
}

var ck3ProvincesInDuchy = duchy.GetDeJureVassalsAndBelow("c").Values
.SelectMany(c => c.CountyProvinces)
.SelectMany(c => c.CountyProvinceIds)
.ToImmutableHashSet();

var governorshipProvincesInDuchy = governorship.GetCK3ProvinceIds(irProvinces, provMapper)
Expand Down
2 changes: 1 addition & 1 deletion ImperatorToCK3/Mappers/TagTitle/TagTitleMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public void RegisterGovernorship(string imperatorRegion, string imperatorCountry

private string? GetCountyForGovernorship(Governorship governorship, Country country, Title.LandedTitles titles, ProvinceCollection ck3Provinces, ImperatorRegionMapper imperatorRegionMapper) {
foreach (var county in titles.Where(t => t.Rank == TitleRank.county)) {
ulong capitalBaronyProvinceId = (ulong)county.CapitalBaronyProvince!;
ulong capitalBaronyProvinceId = (ulong)county.CapitalBaronyProvinceId!;
if (capitalBaronyProvinceId == 0) {
// title's capital province has an invalid ID (0 is not a valid province in CK3)
continue;
Expand Down

0 comments on commit 016c269

Please sign in to comment.