Import typed corporation allegiances
This commit is contained in:
parent
8b6c9e4294
commit
de36150dc2
158 changed files with 319 additions and 185 deletions
Binary file not shown.
|
|
@ -91,7 +91,7 @@ await node.PutMigrationLedgerAsync(new AetheriaMigrationLedger
|
|||
},
|
||||
new AetheriaMigrationCount
|
||||
{
|
||||
DocumentType = "aetheria.corporation.v1",
|
||||
DocumentType = "aetheria.corporation.v2",
|
||||
Count = corporations.Length
|
||||
},
|
||||
new AetheriaMigrationCount
|
||||
|
|
@ -412,7 +412,8 @@ internal static class LegacyCatalogReader
|
|||
AllegianceCount = GetMapCount(payload, 12),
|
||||
OverworldMusic = GetUInt(payload, 13),
|
||||
CombatMusic = GetUInt(payload, 14),
|
||||
BossMusic = GetUInt(payload, 15)
|
||||
BossMusic = GetUInt(payload, 15),
|
||||
Allegiances = ReadAllegiances(payload, 12)
|
||||
}
|
||||
: null,
|
||||
unionKey == 9
|
||||
|
|
@ -507,12 +508,22 @@ internal static class LegacyCatalogReader
|
|||
for (var index = 0; index < length; index++)
|
||||
{
|
||||
var key = ReadValue(ref reader);
|
||||
values[key?.ToString() ?? ""] = ReadValue(ref reader);
|
||||
values[FormatMapKey(key)] = ReadValue(ref reader);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
private static string FormatMapKey(object? key)
|
||||
{
|
||||
return key switch
|
||||
{
|
||||
byte[] bytes when bytes.Length == 16 => new Guid(bytes).ToString("D"),
|
||||
string text => text,
|
||||
_ => key?.ToString() ?? ""
|
||||
};
|
||||
}
|
||||
|
||||
private static object? SkipValue(ref MessagePackReader reader)
|
||||
{
|
||||
reader.Skip();
|
||||
|
|
@ -598,6 +609,30 @@ internal static class LegacyCatalogReader
|
|||
return payload.TryGetValue(key, out var value) && value is Dictionary<string, object?> map ? map.Count : 0;
|
||||
}
|
||||
|
||||
private static AetheriaCorporationAllegiance[] ReadAllegiances(IReadOnlyDictionary<int, object?> payload, int key)
|
||||
{
|
||||
if (!payload.TryGetValue(key, out var value) || value is not Dictionary<string, object?> map)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
return map
|
||||
.Select(entry => new AetheriaCorporationAllegiance
|
||||
{
|
||||
CorporationLegacyId = NormalizeLegacyId(entry.Key),
|
||||
Weight = ReadDoubleValue(entry.Value)
|
||||
})
|
||||
.Where(allegiance => !string.IsNullOrWhiteSpace(allegiance.CorporationLegacyId))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static string NormalizeLegacyId(string legacyId)
|
||||
{
|
||||
return Guid.TryParse(legacyId, out var parsed) && parsed != Guid.Empty
|
||||
? parsed.ToString("D")
|
||||
: "";
|
||||
}
|
||||
|
||||
private static int GetArrayLength(IReadOnlyDictionary<int, object?> payload, int key)
|
||||
{
|
||||
return payload.TryGetValue(key, out var value) && value is object?[] array ? array.Length : 0;
|
||||
|
|
|
|||
|
|
@ -109,12 +109,22 @@ if (catalog.GetManufacturer(manufactured) == null)
|
|||
}
|
||||
|
||||
var packageCorporation = packageCatalog.Corporations.FirstOrDefault(corporation => !string.IsNullOrWhiteSpace(corporation.GeonameFileLegacyId));
|
||||
var packageNameFile = packageCorporation == null ? null : packageCatalog.GetNameFile(packageCorporation);
|
||||
if (packageCorporation == null)
|
||||
{
|
||||
throw new InvalidOperationException("Package catalog store did not read any corporation name-file links.");
|
||||
}
|
||||
|
||||
var packageNameFile = packageCatalog.GetNameFile(packageCorporation);
|
||||
if (packageNameFile == null || packageNameFile.Names.Count == 0 || packageNameFile.Names.Count != packageNameFile.NameCount)
|
||||
{
|
||||
throw new InvalidOperationException("Package catalog store did not read corporation/name-file links with full names.");
|
||||
}
|
||||
|
||||
if (packageCorporation.Allegiances.Count == 0 || packageCorporation.Allegiances.Count != packageCorporation.AllegianceCount)
|
||||
{
|
||||
throw new InvalidOperationException("Package catalog store did not read corporation allegiance edges.");
|
||||
}
|
||||
|
||||
if (surface?.Schema != "gamecult.eve.surface.v1" ||
|
||||
surface.Surface.Id != AetheriaCatalogSurfaceProjector.SurfaceId)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -107,7 +107,10 @@ internal static class AetheriaRuntimeCatalogSnapshotMapper
|
|||
corporation.GeonameFileLegacyId,
|
||||
corporation.BossHullLegacyId,
|
||||
corporation.InfluenceDistance,
|
||||
corporation.AllegianceCount);
|
||||
corporation.AllegianceCount,
|
||||
corporation.Allegiances.Select(allegiance => new AetheriaRuntimeCorporationAllegiance(
|
||||
allegiance.CorporationLegacyId,
|
||||
allegiance.Weight)).ToArray());
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeNameFile FromState(AetheriaNameFile nameFile)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ var catalog = node.ReadCatalogSnapshot();
|
|||
var surface = AetheriaCatalogSurfaceProjector.Build(catalog, DateTimeOffset.UtcNow.ToString("O"));
|
||||
|
||||
RequireCount(ledger, "aetheria.item_definition.v1", items.Length);
|
||||
RequireCount(ledger, "aetheria.corporation.v1", corporations.Length);
|
||||
RequireCount(ledger, "aetheria.corporation.v2", corporations.Length);
|
||||
RequireCount(ledger, "aetheria.name_file.v2", nameFiles.Length);
|
||||
|
||||
if (items.Length == 0)
|
||||
|
|
@ -68,6 +68,7 @@ var weaponItems = items.Count(item =>
|
|||
!string.IsNullOrWhiteSpace(item.WeaponCaliber));
|
||||
var describedCorporations = corporations.Count(corporation => !string.IsNullOrWhiteSpace(corporation.Description));
|
||||
var corporationNameLinks = corporations.Count(corporation => !string.IsNullOrWhiteSpace(corporation.GeonameFileLegacyId));
|
||||
var corporationAllegianceEdges = corporations.Sum(corporation => corporation.Allegiances.Length);
|
||||
|
||||
if (pricedItems == 0)
|
||||
{
|
||||
|
|
@ -208,6 +209,11 @@ if (corporationNameLinks == 0)
|
|||
throw new InvalidOperationException("Typed corporations did not import geoname file legacy IDs.");
|
||||
}
|
||||
|
||||
if (corporationAllegianceEdges == 0 || corporations.Any(corporation => corporation.Allegiances.Length != corporation.AllegianceCount))
|
||||
{
|
||||
throw new InvalidOperationException("Typed corporations did not import full allegiance edges.");
|
||||
}
|
||||
|
||||
var tradeItems = catalog.TradeItems.ToArray();
|
||||
if (tradeItems.Length != pricedItems)
|
||||
{
|
||||
|
|
@ -297,6 +303,7 @@ Console.WriteLine($"Typed catalog trade items: {tradeItems.Length}");
|
|||
Console.WriteLine($"Eve catalog surface: {surface.Surface.Id} ({surface.Surface.Root.Children.Length} root children)");
|
||||
Console.WriteLine($"Corporations: {corporations.Length}");
|
||||
Console.WriteLine($"Described/geoname-linked corporations: {describedCorporations}/{corporationNameLinks}");
|
||||
Console.WriteLine($"Corporation allegiance edges: {corporationAllegianceEdges}");
|
||||
Console.WriteLine($"Name files: {nameFiles.Length}");
|
||||
|
||||
static void RequireCount(AetheriaMigrationLedger ledger, string documentType, int actual)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using MessagePack;
|
|||
|
||||
namespace Aetheria.State.Documents;
|
||||
|
||||
[CultDocument("aetheria.corporation", "aetheria.corporation.v1")]
|
||||
[CultDocument("aetheria.corporation", "aetheria.corporation.v2")]
|
||||
[MessagePackObject]
|
||||
public sealed class AetheriaCorporation
|
||||
{
|
||||
|
|
@ -43,4 +43,17 @@ public sealed class AetheriaCorporation
|
|||
|
||||
[Key(10)]
|
||||
public uint BossMusic { get; set; }
|
||||
|
||||
[Key(11)]
|
||||
public AetheriaCorporationAllegiance[] Allegiances { get; set; } = [];
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public sealed class AetheriaCorporationAllegiance
|
||||
{
|
||||
[Key(0)]
|
||||
public string CorporationLegacyId { get; set; } = "";
|
||||
|
||||
[Key(1)]
|
||||
public double Weight { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,9 +58,11 @@ stable equipment facets: hardpoint type, hull type, stack size, durability, and
|
|||
weapon range/caliber/type/fire/modifier classifications.
|
||||
Typed corporation documents include the legacy short name, the true description
|
||||
field from key 3, name-file and boss-hull legacy IDs, influence distance,
|
||||
allegiance count, and music bank IDs. Runtime object graphs, typed behavior
|
||||
factory construction, and simulation state remain legacy until dedicated typed
|
||||
runtime documents exist.
|
||||
allegiance count, full allegiance edges, and music bank IDs. Corporation
|
||||
documents are `aetheria.corporation.v2` records because runtime generation
|
||||
needs actual allegiance weights, not only display counts. Runtime object graphs,
|
||||
typed behavior factory construction, and simulation state remain legacy until
|
||||
dedicated typed runtime documents exist.
|
||||
Typed name-file documents are `aetheria.name_file.v2` records. They carry the
|
||||
legacy ID, display name, count, compact sample names for surfaces, and the full
|
||||
name array needed to move `Galaxy`/Markov name generation off legacy
|
||||
|
|
@ -94,11 +96,11 @@ published Eve catalog surface. It does not deserialize legacy `DatabaseEntry`
|
|||
objects and does not write state. Unity can use this as the first package
|
||||
boundary once CultLib/Eve runtime packaging is available.
|
||||
`Galaxy` now consumes this package-owned runtime catalog for faction selection
|
||||
and name generation, so generated sectors use typed corporation and
|
||||
and name generation, so generated sectors use typed corporation v2 and
|
||||
`aetheria.name_file.v2` records instead of legacy `Faction`/`NameFile`
|
||||
catalog documents. It still projects typed corporations into temporary
|
||||
`Faction` DTOs because the surrounding simulation has not yet been rebuilt
|
||||
around typed corporation records.
|
||||
`Faction` DTOs, including allegiance dictionaries, because the surrounding
|
||||
simulation has not yet been rebuilt around typed corporation records.
|
||||
|
||||
`Aetheria.State.Smoke` writes and reopens full typed player settings plus a
|
||||
typed loadout template in addition to world, catalog, run state, zone state, and
|
||||
|
|
|
|||
|
|
@ -220,7 +220,8 @@ public class Galaxy
|
|||
|
||||
private static Faction[] ProjectFactions(AetheriaRuntimeCatalogSnapshot runtimeCatalog)
|
||||
{
|
||||
var factions = runtimeCatalog.Corporations
|
||||
var corporations = runtimeCatalog.Corporations.ToArray();
|
||||
var factions = corporations
|
||||
.Select(ProjectFaction)
|
||||
.ToArray();
|
||||
if (factions.Length == 0)
|
||||
|
|
@ -228,6 +229,20 @@ public class Galaxy
|
|||
throw new InvalidOperationException("Typed catalog has no factions for galaxy generation.");
|
||||
}
|
||||
|
||||
var factionsByLegacyId = factions.ToDictionary(faction => faction.ID.ToString("D"), StringComparer.OrdinalIgnoreCase);
|
||||
for (var index = 0; index < corporations.Length; index++)
|
||||
{
|
||||
foreach (var allegiance in corporations[index].Allegiances)
|
||||
{
|
||||
if (Guid.TryParse(allegiance.CorporationLegacyId, out var corporationId) &&
|
||||
corporationId != Guid.Empty &&
|
||||
factionsByLegacyId.ContainsKey(corporationId.ToString("D")))
|
||||
{
|
||||
factions[index].Allegiance[corporationId] = (float) allegiance.Weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return factions;
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue