Aetheria/Assets/Scripts/Gameplay/AetheriaUnityEntityConstructionBlueprintProjector.cs
2026-06-25 18:09:33 +01:00

153 lines
6.2 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;
using Unity.Mathematics;
public sealed class AetheriaUnityEntityConstructionBlueprintProjector
{
private readonly AetheriaUnityLoadoutItemProjector _loadoutItemProjector;
public AetheriaUnityEntityConstructionBlueprintProjector(
AetheriaUnityLoadoutItemProjector loadoutItemProjector)
{
_loadoutItemProjector = loadoutItemProjector ?? throw new ArgumentNullException(nameof(loadoutItemProjector));
}
public EntityConstructionBlueprint ProjectTemplate(AetheriaRuntimeLoadoutTemplateSnapshot template)
{
if (template == null)
return null;
var blueprint = ProjectLoadoutEntity(template.RootEntity);
if (blueprint != null && string.IsNullOrWhiteSpace(blueprint.Name))
blueprint.Name = template.Name;
return blueprint;
}
public EntityConstructionBlueprint ProjectLoadoutEntity(AetheriaRuntimeEntityLoadoutSnapshot entity)
{
if (entity == null)
return null;
var hull = CreateEquippableItem(entity.Hull);
if (hull == null)
return null;
var blueprint = CreateBlueprint(entity.Kind);
if (blueprint is ShipConstructionBlueprint shipBlueprint)
{
shipBlueprint.Direction = new float2(0, 1);
}
blueprint.Name = entity.Name;
blueprint.FactionKey = entity.FactionKey ?? "";
blueprint.Hull = hull;
blueprint.Equipment = CreateEquippableSlots(entity.Equipment);
blueprint.CargoBays = CreateEquippableSlots(entity.CargoBays);
blueprint.DockingBays = CreateEquippableSlots(entity.DockingBays);
blueprint.CargoContents = CreateCargoBayContents(entity.CargoContents);
blueprint.DockingBayContents = CreateCargoBayContents(entity.DockingBayContents);
blueprint.DockingBayAssignments = entity.DockingBayAssignments.ToArray();
blueprint.WeaponGroups = entity.WeaponGroups.Select(group => group.ToArray()).ToArray();
blueprint.Children = entity.Children
.Select(ProjectLoadoutEntity)
.Where(child => child != null)
.ToArray();
return blueprint;
}
public EntityConstructionBlueprint ProjectObservedEntity(
AetheriaRuntimeEntitySnapshot entity,
bool isCurrentEntity)
{
if (entity == null)
return null;
var hull = CreateEquippableItem(new AetheriaRuntimeLoadoutItemSnapshot(
entity.HullItemKey,
1,
1,
1,
true,
false));
if (hull == null)
return null;
var blueprint = CreateBlueprint(entity.Kind);
if (blueprint is ShipConstructionBlueprint shipBlueprint)
{
shipBlueprint.Position = new float3((float)entity.PositionX, (float)entity.PositionY, (float)entity.PositionZ);
shipBlueprint.Direction = new float2((float)entity.DirectionX, (float)entity.DirectionY);
shipBlueprint.IsPlayerShip = isCurrentEntity;
}
blueprint.Name = entity.Name ?? "";
blueprint.FactionKey = entity.FactionKey ?? "";
blueprint.Hull = hull;
blueprint.Equipment = CreateEquippableSlots(entity.Equipment);
blueprint.CargoBays = CreateEquippableSlots(entity.CargoBays);
blueprint.DockingBays = CreateEquippableSlots(entity.DockingBays);
blueprint.CargoContents = CreateCargoBayContents(entity.CargoContents);
blueprint.DockingBayContents = CreateCargoBayContents(entity.DockingBayContents);
blueprint.DockingBayAssignments = entity.DockingBayAssignments.ToArray();
blueprint.WeaponGroups = entity.WeaponGroups.Select(group => group.ToArray()).ToArray();
blueprint.Children = Array.Empty<EntityConstructionBlueprint>();
return blueprint;
}
private static EntityConstructionBlueprint CreateBlueprint(string kind)
{
return string.Equals(kind, "orbital", StringComparison.OrdinalIgnoreCase)
? new OrbitalEntityConstructionBlueprint()
: new ShipConstructionBlueprint();
}
private (int2 position, EquippableItem item)[] CreateEquippableSlots(
IReadOnlyList<AetheriaRuntimeLoadoutItemSlotSnapshot> slots)
{
return (slots ?? Array.Empty<AetheriaRuntimeLoadoutItemSlotSnapshot>())
.Select(slot => (position: new int2(slot.X, slot.Y), item: CreateEquippableItem(slot.Item)))
.Where(slot => slot.item != null)
.ToArray();
}
private (int2 position, EquippableItem item)[] CreateEquippableSlots(
IReadOnlyList<AetheriaRuntimeEntityItemSlotSnapshot> slots)
{
return (slots ?? Array.Empty<AetheriaRuntimeEntityItemSlotSnapshot>())
.Select(slot => (position: new int2(slot.X, slot.Y), item: CreateEquippableItem(new AetheriaRuntimeLoadoutItemSnapshot(
slot.ItemKey,
slot.Quality,
slot.Durability,
slot.Quantity,
slot.Enabled,
slot.OverrideShutdown,
slot.Temperature))))
.Where(slot => slot.item != null)
.ToArray();
}
private (int2 position, ItemInstance item)[][] CreateCargoBayContents(
IReadOnlyList<AetheriaRuntimeCargoBayLoadoutSnapshot> bays)
{
return (bays ?? Array.Empty<AetheriaRuntimeCargoBayLoadoutSnapshot>())
.Select(bay => (bay.Items ?? Array.Empty<AetheriaRuntimeLoadoutItemSlotSnapshot>())
.Select(slot => (position: new int2(slot.X, slot.Y), item: _loadoutItemProjector.CreateLoadoutItem(slot.Item)))
.Where(slot => slot.item != null)
.ToArray())
.ToArray();
}
private EquippableItem CreateEquippableItem(AetheriaRuntimeLoadoutItemSnapshot item)
{
var instance = _loadoutItemProjector.CreateLoadoutItem(item) as EquippableItem;
if (instance != null && item.Durability > 0)
instance.Durability = (float)item.Durability;
return instance;
}
}