Skip to content

Commit

Permalink
Detect and correct some localization key hash collisions (#2493) #patch
Browse files Browse the repository at this point in the history
  • Loading branch information
IhateTrains authored Feb 14, 2025
1 parent 66fb892 commit 3f76823
Showing 3 changed files with 31 additions and 1 deletion.
23 changes: 23 additions & 0 deletions ImperatorToCK3/CK3/CK3LocDB.cs
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
using commonItems.Localization;
using commonItems.Mods;
using ImperatorToCK3.CK3.Localization;
using Murmur;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -83,6 +84,15 @@ public CK3LocBlock GetOrCreateLocBlock(string id) {
return locBlock;
}

// Check for hash collision.
var murmur3A = MurmurHash.Create32();
var hashStr = GetHashStrForKey(murmur3A, id);
if (hashToKeyDict.TryGetValue(hashStr, out var existingKey)) {
Logger.Warn($"Hash collision detected for loc key: {id}. Existing key: {existingKey}");
} else {
hashToKeyDict[hashStr] = id;
}

// Create new loc block.
locBlock = new CK3LocBlock(id, ConverterGlobals.PrimaryLanguage);
Add(locBlock);
@@ -144,4 +154,17 @@ public List<string> GetLocLinesToOutputForLanguage(string language) {

return locLinesToOutput;
}

public bool KeyHasConflictingHash(string key) {
var murmur3A = MurmurHash.Create32();
return hashToKeyDict.ContainsKey(GetHashStrForKey(murmur3A, key));
}

private string GetHashStrForKey(Murmur32 murmur32, string key) {
var keyBytes = System.Text.Encoding.UTF8.GetBytes(key);
var hash = murmur32.ComputeHash(keyBytes);
return string.Join("", hash.Select(b => b.ToString("X2")));
}

private readonly Dictionary<string, string> hashToKeyDict = new(); // stores MurmurHash3A hash to key mapping
}
8 changes: 7 additions & 1 deletion ImperatorToCK3/CK3/Dynasties/Dynasty.cs
Original file line number Diff line number Diff line change
@@ -39,7 +39,13 @@ public Dynasty(Family irFamily, CharacterCollection irCharacters, CulturesDB irC

public Dynasty(CK3.Characters.Character character, string irFamilyName, ImperatorCharacter[] irMembers, CulturesDB irCulturesDB, LocDB irLocDB, CK3LocDB ck3LocDB, Date date) {
FromImperator = true;
Id = $"dynn_irtock3_from_{character.Id}";

string id = $"dynn_irtock3_from_{character.Id}";
uint counter = 0;
while (ck3LocDB.KeyHasConflictingHash(id)) {
id = $"dynn_irtock3_from_{character.Id}_{counter++}";
}
Id = id;
Name = Id;

CultureId = character.GetCultureId(date) ?? character.Father?.GetCultureId(date);
1 change: 1 addition & 0 deletions ImperatorToCK3/ImperatorToCK3.csproj
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="MurmurHash.NETStandard" Version="1.0.0" />
<PackageReference Include="PGCG.commonItems" Version="15.1.6" />
<PackageReference Include="PGCG.commonItems.SourceGenerators" Version="1.0.8"/>
<PackageReference Include="Polly" Version="8.5.2" />

0 comments on commit 3f76823

Please sign in to comment.