161 lines
6.4 KiB
C#
161 lines
6.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
#nullable enable
|
|
|
|
namespace GameCult.Aetheria.State.Unity
|
|
{
|
|
public static class AetheriaRuntimeLoadoutSnapshotProjector
|
|
{
|
|
public static string AppendToZone(
|
|
AetheriaRuntimeRunCheckpointCommit run,
|
|
int zoneIndex,
|
|
string parentEntityKey,
|
|
AetheriaRuntimeLoadoutTemplateCommit template)
|
|
{
|
|
if (run == null || template?.RootEntity == null)
|
|
return "";
|
|
|
|
var zones = (run.Zones ?? Array.Empty<AetheriaRuntimeZoneSnapshotCommit>()).ToArray();
|
|
var zone = zones.FirstOrDefault(candidate => candidate != null && candidate.ZoneIndex == zoneIndex);
|
|
if (zone == null)
|
|
return "";
|
|
|
|
var entities = (zone.Entities ?? Array.Empty<AetheriaRuntimeEntitySnapshotCommit>()).ToList();
|
|
var parentIndex = TryParseEntityKey(parentEntityKey, out var parentZoneIndex, out var parsedParentIndex) &&
|
|
parentZoneIndex == zoneIndex
|
|
? parsedParentIndex
|
|
: -1;
|
|
var rootIndex = AppendEntity(entities, template.RootEntity, template.Name);
|
|
|
|
if (parentIndex >= 0 && parentIndex < entities.Count)
|
|
{
|
|
var children = (entities[parentIndex].ChildEntityIndices ?? Array.Empty<int>()).ToList();
|
|
if (!children.Contains(rootIndex))
|
|
children.Add(rootIndex);
|
|
entities[parentIndex].ChildEntityIndices = children.ToArray();
|
|
}
|
|
|
|
zone.Entities = entities.ToArray();
|
|
run.Zones = zones;
|
|
return EntityKey(run.RunId, zoneIndex, rootIndex);
|
|
}
|
|
|
|
private static int AppendEntity(
|
|
List<AetheriaRuntimeEntitySnapshotCommit> entities,
|
|
AetheriaRuntimeEntityLoadoutCommit loadout,
|
|
string templateName)
|
|
{
|
|
var entityIndex = entities.Count;
|
|
var entity = new AetheriaRuntimeEntitySnapshotCommit
|
|
{
|
|
EntityIndex = entityIndex,
|
|
Name = string.IsNullOrWhiteSpace(loadout.Name) ? templateName ?? "" : loadout.Name,
|
|
Kind = string.IsNullOrWhiteSpace(loadout.Kind) ? "ship" : loadout.Kind,
|
|
DirectionX = 0,
|
|
DirectionY = 1,
|
|
IsActive = true,
|
|
HullItemKey = loadout.Hull?.ItemKey ?? "",
|
|
FactionKey = loadout.FactionKey ?? "",
|
|
Equipment = CloneSlots(loadout.Equipment),
|
|
CargoBays = CloneSlots(loadout.CargoBays),
|
|
DockingBays = CloneSlots(loadout.DockingBays),
|
|
CargoContents = CloneCargo(loadout.CargoContents),
|
|
DockingBayContents = CloneCargo(loadout.DockingBayContents),
|
|
DockingBayAssignments = (loadout.DockingBayAssignments ?? Array.Empty<int>()).ToArray(),
|
|
WeaponGroups = (loadout.WeaponGroups ?? Array.Empty<IReadOnlyList<int>>())
|
|
.Select(group => (IReadOnlyList<int>)(group ?? Array.Empty<int>()).ToArray())
|
|
.ToArray(),
|
|
TargetEntityIndex = -1,
|
|
ShutdownPerformance = 0.25
|
|
};
|
|
entities.Add(entity);
|
|
|
|
var childIndices = new List<int>();
|
|
foreach (var child in loadout.Children ?? Array.Empty<AetheriaRuntimeEntityLoadoutCommit>())
|
|
{
|
|
if (child == null)
|
|
continue;
|
|
childIndices.Add(AppendEntity(entities, child, ""));
|
|
}
|
|
|
|
entity.ChildEntityIndices = childIndices.ToArray();
|
|
return entityIndex;
|
|
}
|
|
|
|
private static AetheriaRuntimeLoadoutItemSlotCommit[] CloneSlots(
|
|
IReadOnlyList<AetheriaRuntimeLoadoutItemSlotCommit>? slots)
|
|
{
|
|
return (slots ?? Array.Empty<AetheriaRuntimeLoadoutItemSlotCommit>())
|
|
.Where(slot => slot != null)
|
|
.Select(CloneSlot)
|
|
.ToArray();
|
|
}
|
|
|
|
private static AetheriaRuntimeCargoBayLoadoutCommit[] CloneCargo(
|
|
IReadOnlyList<AetheriaRuntimeCargoBayLoadoutCommit>? cargo)
|
|
{
|
|
return (cargo ?? Array.Empty<AetheriaRuntimeCargoBayLoadoutCommit>())
|
|
.Select(bay => new AetheriaRuntimeCargoBayLoadoutCommit
|
|
{
|
|
Items = CloneSlots(bay?.Items)
|
|
})
|
|
.ToArray();
|
|
}
|
|
|
|
private static AetheriaRuntimeLoadoutItemSlotCommit CloneSlot(AetheriaRuntimeLoadoutItemSlotCommit slot)
|
|
{
|
|
return new AetheriaRuntimeLoadoutItemSlotCommit
|
|
{
|
|
X = slot.X,
|
|
Y = slot.Y,
|
|
Item = CloneItem(slot.Item)
|
|
};
|
|
}
|
|
|
|
private static AetheriaRuntimeLoadoutItemCommit CloneItem(AetheriaRuntimeLoadoutItemCommit? item)
|
|
{
|
|
return new AetheriaRuntimeLoadoutItemCommit
|
|
{
|
|
ItemKey = item?.ItemKey ?? "",
|
|
Quality = item?.Quality ?? 1.0,
|
|
Durability = item?.Durability ?? 1.0,
|
|
Quantity = item?.Quantity ?? 1,
|
|
Enabled = item?.Enabled ?? true,
|
|
OverrideShutdown = item?.OverrideShutdown ?? false
|
|
};
|
|
}
|
|
|
|
private static string EntityKey(string runId, int zoneIndex, int entityIndex)
|
|
{
|
|
return $"global:aetheria.run_state.{(string.IsNullOrWhiteSpace(runId) ? "local" : runId)}.zone.{zoneIndex}.entity.{entityIndex}.v1";
|
|
}
|
|
|
|
private static bool TryParseEntityKey(string entityKey, out int zoneIndex, out int entityIndex)
|
|
{
|
|
zoneIndex = -1;
|
|
entityIndex = -1;
|
|
if (string.IsNullOrWhiteSpace(entityKey))
|
|
return false;
|
|
|
|
var parts = entityKey.Split('.');
|
|
for (var i = 0; i < parts.Length - 1; i++)
|
|
{
|
|
if (string.Equals(parts[i], "zone", StringComparison.Ordinal) &&
|
|
int.TryParse(parts[i + 1], out zoneIndex))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (string.Equals(parts[i], "entity", StringComparison.Ordinal) &&
|
|
int.TryParse(parts[i + 1], out entityIndex))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return zoneIndex >= 0 && entityIndex >= 0;
|
|
}
|
|
}
|
|
}
|