Aetheria/Assets/Scripts/Gameplay/AetheriaUnityDaemonEntitySnapshotProjector.cs
2026-06-28 11:26:11 +01:00

255 lines
10 KiB
C#

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
using System;
using System.Collections.Generic;
using System.Linq;
using GameCult.Aetheria.State.Verse;
public static class AetheriaUnityDaemonEntitySnapshotProjector
{
public static AetheriaRuntimeEntitySnapshot[] CreateSnapshots(
string runId,
AetheriaRuntimeZoneSnapshotCommit zone)
{
if (zone == null)
return Array.Empty<AetheriaRuntimeEntitySnapshot>();
return CreateSnapshots(runId, zone.ZoneIndex, zone.Entities);
}
public static AetheriaRuntimeEntitySnapshot[] CreateSnapshots(
string runId,
int zoneIndex,
IReadOnlyList<AetheriaRuntimeEntitySnapshotCommit> entities)
{
return (entities ?? Array.Empty<AetheriaRuntimeEntitySnapshotCommit>())
.Where(entity => entity != null)
.Select(entity => CreateSnapshot(runId, zoneIndex, entity))
.ToArray();
}
public static string DaemonEntityRecordKey(string runId, int zoneIndex, int entityIndex)
{
return string.IsNullOrWhiteSpace(runId)
? ""
: $"global:aetheria.run_state.{runId}.zone.{zoneIndex}.entity.{entityIndex}.v1";
}
private static AetheriaRuntimeEntitySnapshot CreateSnapshot(
string runId,
int zoneIndex,
AetheriaRuntimeEntitySnapshotCommit entity)
{
return new AetheriaRuntimeEntitySnapshot(
DaemonEntityRecordKey(runId, zoneIndex, entity.EntityIndex),
entity.EntityIndex,
entity.Name ?? "",
entity.Kind ?? "",
entity.PositionX,
entity.PositionY,
entity.PositionZ,
entity.DirectionX,
entity.DirectionY,
entity.FactionKey ?? "",
entity.HullItemKey ?? "",
CreateItemSlots(entity.Equipment),
CreateItemSlots(entity.CargoBays),
CreateItemSlots(entity.DockingBays),
(entity.ChildEntityIndices ?? Array.Empty<int>())
.Where(index => index >= 0)
.Select(index => DaemonEntityRecordKey(runId, zoneIndex, index))
.ToArray(),
(entity.WeaponGroups ?? Array.Empty<IReadOnlyList<int>>())
.Select(group => (IReadOnlyList<int>)(group ?? Array.Empty<int>()).ToArray())
.ToArray(),
(entity.StatGrids ?? Array.Empty<AetheriaRuntimeEntityStatGridCommit>())
.Select(grid => new AetheriaRuntimeEntityStatGridSnapshot(
grid.Name ?? "",
grid.Width,
grid.Height,
(grid.Values ?? Array.Empty<double>()).ToArray()))
.ToArray(),
entity.VelocityX,
entity.VelocityY,
entity.TargetEntityIndex < 0 ? "" : DaemonEntityRecordKey(runId, zoneIndex, entity.TargetEntityIndex),
entity.IsActive,
entity.HeatsinksEnabled,
entity.OverrideShutdown,
entity.TractorPower,
entity.Heatstroke,
entity.Hypothermia,
(entity.ActiveConsumables ?? Array.Empty<AetheriaRuntimeActiveConsumableCommit>())
.Select(consumable => new AetheriaRuntimeActiveConsumableSnapshot(
consumable.ItemKey ?? "",
consumable.Quality,
consumable.RemainingDuration,
consumable.Duration))
.ToArray(),
(entity.BehaviorProgress ?? Array.Empty<AetheriaRuntimeBehaviorProgressCommit>())
.Select(progress => new AetheriaRuntimeBehaviorProgressSnapshot(
progress.OwnerKind ?? "",
progress.OwnerIndex,
progress.BehaviorIndex,
progress.BehaviorKind ?? "",
progress.Progress))
.ToArray(),
CreateWeaponStates(runId, zoneIndex, entity.WeaponStates),
CreateBehaviorStates(entity.BehaviorStates),
CreateCargoBays(entity.CargoContents),
CreateCargoBays(entity.DockingBayContents),
(entity.DockingBayAssignments ?? Array.Empty<int>()).ToArray(),
entity.Visibility,
entity.VisibilitySourceCount,
(entity.Contacts ?? Array.Empty<AetheriaRuntimeEntityContactCommit>())
.Where(contact => contact != null && contact.TargetEntityIndex >= 0)
.Select(contact => new AetheriaRuntimeEntityContactSnapshot(
DaemonEntityRecordKey(runId, zoneIndex, contact.TargetEntityIndex),
contact.InfoGathered,
contact.Hostile,
contact.Visible))
.ToArray(),
entity.ShutdownPerformance);
}
private static AetheriaRuntimeEntityItemSlotSnapshot[] CreateItemSlots(
IReadOnlyList<AetheriaRuntimeLoadoutItemSlotCommit> slots)
{
return (slots ?? Array.Empty<AetheriaRuntimeLoadoutItemSlotCommit>())
.Where(slot => slot?.Item != null)
.Select(slot => new AetheriaRuntimeEntityItemSlotSnapshot(
slot.X,
slot.Y,
slot.Item.ItemKey ?? "",
slot.Item.Quality,
slot.Item.Durability,
slot.Item.Quantity,
slot.Item.Enabled,
slot.Item.OverrideShutdown,
slot.Item.Temperature))
.ToArray();
}
private static AetheriaRuntimeCargoBayLoadoutSnapshot[] CreateCargoBays(
IReadOnlyList<AetheriaRuntimeCargoBayLoadoutCommit> cargoBays)
{
return (cargoBays ?? Array.Empty<AetheriaRuntimeCargoBayLoadoutCommit>())
.Select(bay => new AetheriaRuntimeCargoBayLoadoutSnapshot(
CreateLoadoutSlots(bay?.Items)))
.ToArray();
}
private static AetheriaRuntimeLoadoutItemSlotSnapshot[] CreateLoadoutSlots(
IReadOnlyList<AetheriaRuntimeLoadoutItemSlotCommit> slots)
{
return (slots ?? Array.Empty<AetheriaRuntimeLoadoutItemSlotCommit>())
.Where(slot => slot?.Item != null)
.Select(slot => new AetheriaRuntimeLoadoutItemSlotSnapshot(
slot.X,
slot.Y,
new AetheriaRuntimeLoadoutItemSnapshot(
slot.Item.ItemKey ?? "",
slot.Item.Quality,
slot.Item.Durability,
slot.Item.Quantity,
slot.Item.Enabled,
slot.Item.OverrideShutdown,
slot.Item.Temperature)))
.ToArray();
}
private static AetheriaRuntimeWeaponStateSnapshot[] CreateWeaponStates(
string runId,
int zoneIndex,
IReadOnlyList<AetheriaRuntimeWeaponStateCommit> weaponStates)
{
return (weaponStates ?? Array.Empty<AetheriaRuntimeWeaponStateCommit>())
.Where(state => state != null)
.Select(state => new AetheriaRuntimeWeaponStateSnapshot(
state.OwnerKind ?? "",
state.OwnerIndex,
state.BehaviorIndex,
state.BehaviorKind ?? "",
state.Firing,
state.Ammo,
state.BurstRemaining,
state.BurstTimer,
state.BurstInterval,
state.CooldownProgress,
state.CoolingDown,
state.Charging,
state.Charged,
state.Charge,
state.Reloading,
state.ReloadProgress,
state.AmmoIntervalProgress,
state.LockProgress,
state.LockTargetEntityIndex < 0 ? "" : DaemonEntityRecordKey(runId, zoneIndex, state.LockTargetEntityIndex)))
.ToArray();
}
private static AetheriaRuntimeBehaviorStateSnapshot[] CreateBehaviorStates(
IReadOnlyList<AetheriaRuntimeBehaviorStateCommit> behaviorStates)
{
return (behaviorStates ?? Array.Empty<AetheriaRuntimeBehaviorStateCommit>())
.Where(state => state != null)
.Select(state => new AetheriaRuntimeBehaviorStateSnapshot(
state.OwnerKind ?? "",
state.OwnerIndex,
state.BehaviorIndex,
state.BehaviorKind ?? "",
state.Pinging,
state.PingCooldown,
state.PingLerp,
state.PingRadius,
state.PingedEntityCount,
state.RadiatorTemperature,
state.Emissivity,
state.PumpedHeat,
state.WasteHeat,
state.EnergyUsage,
state.ReactorDraw,
state.ReactorLoadRatio,
state.CapacitorCharge,
state.CapacitorCapacity,
state.CapacitorEfficiency,
state.AetherDriveAxisX,
state.AetherDriveAxisY,
state.AetherDriveAxisZ,
state.AetherDriveThrustX,
state.AetherDriveThrustY,
state.AetherDriveThrustZ,
state.AetherDriveRpmX,
state.AetherDriveRpmY,
state.AetherDriveRpmZ,
state.AetherDriveMaximumRpm,
state.AetherDriveThrustDirectionX,
state.AetherDriveThrustDirectionY,
state.ResourceScannerTargetBodyKey ?? "",
state.ResourceScannerAsteroidIndex,
state.ResourceScannerScanTime,
state.ResourceScannerRange,
state.ResourceScannerMinimumDensity,
state.ResourceScannerScanDuration,
state.MiningToolAsteroidBeltKey ?? "",
state.MiningToolAsteroidIndex,
state.MiningToolRange,
state.ThrusterAxis,
state.ThrusterThrust,
state.ThrusterTorque,
state.ShieldEfficiency,
state.ShieldEnergyUsage,
state.VelocityLimit,
state.ThermotoggleTargetTemperature,
state.SwitchActivated,
state.TriggerPulled,
state.StatModifierApplied,
state.StatModifierExecuted,
state.StatModifierTargetStatCount,
state.TurretControllerWeaponCount,
state.TurretControllerShotSpeed,
state.TurretControllerPredictShots))
.ToArray();
}
}