2021-01-15 20:07:39 +00:00
|
|
|
using System;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using MessagePack;
|
|
|
|
|
using Unity.Mathematics;
|
|
|
|
|
|
2021-03-13 03:23:58 +00:00
|
|
|
public static class EntitySerializer
|
2021-01-15 20:07:39 +00:00
|
|
|
{
|
2021-01-18 02:35:56 +00:00
|
|
|
public static EntityPack Pack(Entity entity)
|
2021-01-15 20:07:39 +00:00
|
|
|
{
|
2021-03-13 03:23:58 +00:00
|
|
|
EntityPack pack;
|
|
|
|
|
if (entity is OrbitalEntity orbital)
|
2021-03-14 03:56:49 +00:00
|
|
|
pack = new OrbitalEntityPack
|
|
|
|
|
{
|
2021-05-02 20:59:45 +01:00
|
|
|
Orbit = orbital.OrbitData,
|
|
|
|
|
SecurityLevel = orbital.SecurityLevel,
|
|
|
|
|
SecurityRadius = orbital.SecurityRadius
|
2021-03-14 03:56:49 +00:00
|
|
|
};
|
|
|
|
|
else if (entity is Ship ship)
|
|
|
|
|
pack = new ShipPack
|
|
|
|
|
{
|
|
|
|
|
Position = ship.Position,
|
2021-03-15 11:40:46 +00:00
|
|
|
Direction = ship.Direction,
|
|
|
|
|
IsPlayerShip = ship.IsPlayerShip
|
2021-03-14 03:56:49 +00:00
|
|
|
};
|
|
|
|
|
else throw new ArgumentException("Attempted to pack an instance of abstract class Entity!");
|
2021-03-15 11:40:46 +00:00
|
|
|
|
|
|
|
|
pack.Settings = entity.Settings;
|
2021-01-15 20:07:39 +00:00
|
|
|
|
|
|
|
|
// Filter item behavior collections by those with any persistent behaviors
|
|
|
|
|
// For each item create an object containing the item position and a list of persistent behaviors
|
|
|
|
|
// Then turn that into a dictionary mapping from item position to an array of every behaviors persistent data
|
|
|
|
|
pack.PersistedBehaviors = entity.Equipment
|
|
|
|
|
.Where(item => item.Behaviors.Any(b=>b is IPersistentBehavior))
|
|
|
|
|
.Select(item => new {equippable=item, behaviors = item.Behaviors
|
|
|
|
|
.Where(b=>b is IPersistentBehavior)
|
|
|
|
|
.Cast<IPersistentBehavior>()})
|
|
|
|
|
.ToDictionary(x=> x.equippable.Position, x=>x.behaviors.Select(b => b.Store()).ToArray());
|
2021-01-18 02:35:56 +00:00
|
|
|
|
|
|
|
|
pack.Hull = entity.Hull;
|
|
|
|
|
pack.Name = entity.Name;
|
2021-03-18 22:48:33 +00:00
|
|
|
pack.Faction = entity.Faction?.ID ?? Guid.Empty;
|
2021-01-15 20:07:39 +00:00
|
|
|
pack.Equipment = entity.Equipment.Select(e => (e.Position, e.EquippableItem)).ToArray();
|
|
|
|
|
pack.CargoBays = entity.CargoBays.Select(e => (e.Position, e.EquippableItem)).ToArray();
|
|
|
|
|
pack.DockingBays = entity.DockingBays.Select(e => (e.Position, e.EquippableItem)).ToArray();
|
|
|
|
|
pack.DockingBayAssignments = entity.DockingBays.Select(x => entity.Children.IndexOf(x.DockedShip)).ToArray();
|
|
|
|
|
pack.CargoContents = entity.CargoBays.Select(b => b.Cargo.Select(i => (i.Value, i.Key)).ToArray()).ToArray();
|
|
|
|
|
pack.DockingBayContents = entity.DockingBays.Select(b => b.Cargo.Select(i => (i.Value, i.Key)).ToArray()).ToArray();
|
|
|
|
|
pack.Armor = entity.Armor;
|
|
|
|
|
pack.Temperature = entity.Temperature;
|
2021-01-18 02:35:56 +00:00
|
|
|
pack.Conductivity = entity.HullConductivity;
|
|
|
|
|
pack.Children = entity.Children.Select(Pack).ToArray();
|
2021-05-02 20:59:45 +01:00
|
|
|
pack.WeaponGroups = entity.WeaponGroups.Select(wg => wg.items.Select(item => entity.Equipment.IndexOf(item)).ToArray()).ToArray();
|
2021-01-15 20:07:39 +00:00
|
|
|
return pack;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-13 03:23:58 +00:00
|
|
|
public static Entity Unpack(ItemManager itemManager, Zone zone, EntityPack pack, bool instantiate = false)
|
|
|
|
|
{
|
2021-03-15 11:40:46 +00:00
|
|
|
pack.Settings ??= MessagePackSerializer.Deserialize<EntitySettings>(
|
|
|
|
|
MessagePackSerializer.Serialize(itemManager.GameplaySettings.DefaultEntitySettings));
|
2021-03-13 03:23:58 +00:00
|
|
|
return pack switch
|
|
|
|
|
{
|
|
|
|
|
ShipPack shipPack => Unpack(itemManager, zone, shipPack, instantiate),
|
|
|
|
|
OrbitalEntityPack orbitalEntityPack => Unpack(itemManager, zone, orbitalEntityPack, instantiate),
|
|
|
|
|
_ => null
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-14 03:56:49 +00:00
|
|
|
|
|
|
|
|
private static Ship Unpack(ItemManager itemManager, Zone zone, ShipPack pack, bool instantiate = false)
|
2021-01-15 20:07:39 +00:00
|
|
|
{
|
2021-03-15 11:40:46 +00:00
|
|
|
|
2021-03-14 03:56:49 +00:00
|
|
|
var entity = new Ship(itemManager, zone, instantiate ? (EquippableItem) itemManager.Instantiate(pack.Hull) : pack.Hull, pack.Settings);
|
2021-01-19 01:22:56 +00:00
|
|
|
Restore(itemManager, zone, pack, entity, instantiate);
|
2021-03-15 11:40:46 +00:00
|
|
|
entity.Position = pack.Position;
|
|
|
|
|
entity.Direction = pack.Direction;
|
|
|
|
|
entity.IsPlayerShip = pack.IsPlayerShip;
|
2021-01-15 20:07:39 +00:00
|
|
|
return entity;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-14 03:56:49 +00:00
|
|
|
private static OrbitalEntity Unpack(ItemManager itemManager, Zone zone, OrbitalEntityPack pack, bool instantiate = false)
|
2021-01-15 20:07:39 +00:00
|
|
|
{
|
2021-03-14 03:56:49 +00:00
|
|
|
var entity = new OrbitalEntity(itemManager, zone, instantiate ? (EquippableItem) itemManager.Instantiate(pack.Hull) : pack.Hull, pack.Orbit, pack.Settings);
|
2021-01-19 01:22:56 +00:00
|
|
|
Restore(itemManager, zone, pack, entity, instantiate);
|
2021-05-02 20:59:45 +01:00
|
|
|
entity.SecurityLevel = pack.SecurityLevel;
|
|
|
|
|
entity.SecurityRadius = pack.SecurityRadius;
|
2021-01-15 20:07:39 +00:00
|
|
|
return entity;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-14 03:56:49 +00:00
|
|
|
private static void Restore(ItemManager itemManager, Zone zone, EntityPack pack, Entity entity, bool instantiate = false)
|
2021-01-15 20:07:39 +00:00
|
|
|
{
|
2021-01-18 02:35:56 +00:00
|
|
|
entity.Name = pack.Name;
|
2021-03-20 04:20:17 +00:00
|
|
|
entity.Faction = itemManager.ItemData.Get<Faction>(pack.Faction);
|
2021-01-15 20:07:39 +00:00
|
|
|
entity.Children = pack.Children.Select(c =>
|
|
|
|
|
{
|
2021-01-19 01:22:56 +00:00
|
|
|
var child = Unpack(itemManager, zone, c, instantiate);
|
2021-01-15 20:07:39 +00:00
|
|
|
child.Parent = entity;
|
2021-03-14 03:56:49 +00:00
|
|
|
return child;
|
2021-01-15 20:07:39 +00:00
|
|
|
}).ToList();
|
2021-01-19 01:22:56 +00:00
|
|
|
foreach (var (position, item) in pack.Equipment) entity.TryEquip(instantiate ? (EquippableItem) itemManager.Instantiate(item) : item, position);
|
|
|
|
|
foreach (var (position, item) in pack.CargoBays) entity.TryEquip(instantiate ? (EquippableItem) itemManager.Instantiate(item) : item, position);
|
|
|
|
|
foreach (var (position, item) in pack.DockingBays) entity.TryEquip(instantiate ? (EquippableItem) itemManager.Instantiate(item) : item, position);
|
2021-01-15 20:07:39 +00:00
|
|
|
|
|
|
|
|
for (var i = 0; i < pack.DockingBayAssignments.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (pack.DockingBayAssignments[i] != -1)
|
|
|
|
|
entity.DockingBays[i].DockedShip = entity.Children[pack.DockingBayAssignments[i]] as Ship;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var bayIndex = 0; bayIndex < pack.CargoContents.Length; bayIndex++)
|
2021-02-26 19:01:47 +00:00
|
|
|
if(entity.CargoBays.Count >= bayIndex + 1)
|
|
|
|
|
foreach (var (position, item) in pack.CargoContents[bayIndex])
|
|
|
|
|
entity.CargoBays[bayIndex].TryStore(instantiate ? itemManager.Instantiate(item) : item, position);
|
2021-01-15 20:07:39 +00:00
|
|
|
|
|
|
|
|
for (var bayIndex = 0; bayIndex < pack.DockingBayContents.Length; bayIndex++)
|
2021-02-26 19:01:47 +00:00
|
|
|
if(entity.DockingBays.Count >= bayIndex + 1)
|
|
|
|
|
foreach (var (position, item) in pack.DockingBayContents[bayIndex])
|
|
|
|
|
entity.DockingBays[bayIndex].TryStore(instantiate ? itemManager.Instantiate(item) : item, position);
|
2021-01-15 20:07:39 +00:00
|
|
|
|
|
|
|
|
// Iterate only over the behaviors of items which contain persistent data
|
|
|
|
|
// Filter the behaviors for each item to get the persistent ones, then cast them and combine with the persisted data array for that item
|
|
|
|
|
foreach (var persistentBehaviorData in entity.Equipment
|
|
|
|
|
.Where(item => pack.PersistedBehaviors.ContainsKey(item.Position))
|
|
|
|
|
.SelectMany(item => item.Behaviors
|
|
|
|
|
.Where(b=> b is IPersistentBehavior)
|
|
|
|
|
.Cast<IPersistentBehavior>()
|
|
|
|
|
.Zip(pack.PersistedBehaviors[item.Position], (behavior, data) => new{behavior, data})))
|
|
|
|
|
persistentBehaviorData.behavior.Restore(persistentBehaviorData.data);
|
|
|
|
|
|
2021-02-01 08:13:14 +00:00
|
|
|
if(!instantiate)
|
|
|
|
|
entity.Temperature = pack.Temperature;
|
|
|
|
|
|
|
|
|
|
if(!instantiate)
|
|
|
|
|
entity.Armor = pack.Armor;
|
|
|
|
|
|
|
|
|
|
var hullData = itemManager.GetData(entity.Hull);
|
|
|
|
|
|
|
|
|
|
foreach(var v in hullData.Shape.Coordinates)
|
|
|
|
|
entity.HullConductivity[v.x,v.y] = pack.Conductivity[v.x,v.y];
|
2021-05-02 20:59:45 +01:00
|
|
|
|
|
|
|
|
entity.WeaponGroups = pack.WeaponGroups.Select(itemIndices =>
|
|
|
|
|
{
|
|
|
|
|
var items = itemIndices.Select(i => entity.Equipment[i]);
|
|
|
|
|
return (items.Select(i => i.GetBehavior<Weapon>()).ToList(), items.ToList());
|
|
|
|
|
}).ToArray();
|
2021-01-15 20:07:39 +00:00
|
|
|
}
|
2021-03-13 03:23:58 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-27 16:44:44 +01:00
|
|
|
[MessagePackObject]
|
|
|
|
|
public class SavedStory
|
|
|
|
|
{
|
2021-05-02 20:59:45 +01:00
|
|
|
[Key(0)] public string StoryJson;
|
|
|
|
|
[Key(1)] public string StateJson;
|
2021-04-27 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
|
2021-03-13 03:23:58 +00:00
|
|
|
[MessagePackObject]
|
2021-03-14 03:56:49 +00:00
|
|
|
public class ShipPack : EntityPack
|
|
|
|
|
{
|
2021-05-02 20:59:45 +01:00
|
|
|
[Key(17)] public float3 Position;
|
|
|
|
|
[Key(18)] public float2 Direction;
|
|
|
|
|
[Key(19)] public bool IsPlayerShip;
|
2021-03-14 03:56:49 +00:00
|
|
|
}
|
2021-03-13 03:23:58 +00:00
|
|
|
|
|
|
|
|
[MessagePackObject]
|
|
|
|
|
public class OrbitalEntityPack : EntityPack
|
|
|
|
|
{
|
2021-05-02 20:59:45 +01:00
|
|
|
[Key(17)] public Guid Orbit;
|
|
|
|
|
[Key(18)] public SavedStory Story;
|
|
|
|
|
[Key(19)] public SecurityLevel SecurityLevel;
|
|
|
|
|
[Key(20)] public float SecurityRadius;
|
2021-03-13 03:23:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[MessagePackObject,
|
|
|
|
|
Union(0, typeof(OrbitalEntityPack)),
|
|
|
|
|
Union(1, typeof(ShipPack))]
|
2021-03-15 11:40:46 +00:00
|
|
|
public abstract class EntityPack
|
2021-03-13 03:23:58 +00:00
|
|
|
{
|
2021-05-02 20:59:45 +01:00
|
|
|
[Key(0)] public string Name;
|
|
|
|
|
[Key(1)] public EquippableItem Hull;
|
|
|
|
|
[Key(2)] public (int2 position, EquippableItem item)[] Equipment;
|
|
|
|
|
[Key(3)] public (int2 position, EquippableItem item)[] CargoBays;
|
|
|
|
|
[Key(4)] public (int2 position, EquippableItem item)[] DockingBays;
|
|
|
|
|
[Key(5)] public Dictionary<int2, PersistentBehaviorData[]> PersistedBehaviors;
|
|
|
|
|
[Key(6)] public float[,] Temperature;
|
|
|
|
|
[Key(7)] public float[,] Armor;
|
|
|
|
|
[Key(8)] public bool2[,] Conductivity;
|
|
|
|
|
[Key(10)] public int[] DockingBayAssignments;
|
|
|
|
|
[Key(11)] public (int2 position, ItemInstance item)[][] CargoContents;
|
|
|
|
|
[Key(12)] public (int2 position, ItemInstance item)[][] DockingBayContents;
|
|
|
|
|
[Key(13)] public EntityPack[] Children;
|
|
|
|
|
[Key(14)] public EntitySettings Settings;
|
|
|
|
|
[Key(15)] public Guid Faction;
|
|
|
|
|
[Key(16)] public int[][] WeaponGroups;
|
2021-03-18 22:48:33 +00:00
|
|
|
|
2021-03-13 03:23:58 +00:00
|
|
|
private int _price;
|
2021-01-19 01:22:56 +00:00
|
|
|
|
|
|
|
|
public int Price(ItemManager itemManager)
|
|
|
|
|
{
|
2021-03-14 03:56:49 +00:00
|
|
|
if (_price != 0) return _price;
|
|
|
|
|
|
|
|
|
|
var hullData = itemManager.GetData(Hull);
|
|
|
|
|
_price = hullData.Price;
|
|
|
|
|
|
|
|
|
|
foreach (var (_, item) in Equipment)
|
2021-01-19 01:22:56 +00:00
|
|
|
{
|
2021-03-14 03:56:49 +00:00
|
|
|
var itemData = itemManager.GetData(item);
|
|
|
|
|
_price += itemData.Price;
|
|
|
|
|
}
|
|
|
|
|
foreach (var (_, item) in CargoBays)
|
|
|
|
|
{
|
|
|
|
|
var itemData = itemManager.GetData(item);
|
|
|
|
|
_price += itemData.Price;
|
|
|
|
|
}
|
|
|
|
|
foreach (var (_, item) in DockingBays)
|
|
|
|
|
{
|
|
|
|
|
var itemData = itemManager.GetData(item);
|
|
|
|
|
_price += itemData.Price;
|
|
|
|
|
}
|
2021-01-19 01:22:56 +00:00
|
|
|
|
2021-03-14 03:56:49 +00:00
|
|
|
foreach (var t in CargoContents)
|
|
|
|
|
{
|
|
|
|
|
foreach (var (_, item) in t)
|
2021-01-19 01:22:56 +00:00
|
|
|
{
|
2021-04-18 05:13:20 +01:00
|
|
|
var itemData = item.Data.Value;
|
2021-03-14 03:56:49 +00:00
|
|
|
if (item is SimpleCommodity s)
|
|
|
|
|
_price += itemData.Price * s.Quantity;
|
|
|
|
|
else
|
|
|
|
|
_price += itemData.Price;
|
2021-01-19 01:22:56 +00:00
|
|
|
}
|
2021-03-14 03:56:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var t in DockingBayContents)
|
|
|
|
|
{
|
|
|
|
|
foreach (var (_, item) in t)
|
2021-01-19 01:22:56 +00:00
|
|
|
{
|
2021-04-18 05:13:20 +01:00
|
|
|
var itemData = item.Data.Value;
|
2021-03-14 03:56:49 +00:00
|
|
|
if (item is SimpleCommodity s)
|
|
|
|
|
_price += itemData.Price * s.Quantity;
|
|
|
|
|
else
|
|
|
|
|
_price += itemData.Price;
|
2021-01-19 01:22:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _price;
|
|
|
|
|
}
|
2021-01-15 20:07:39 +00:00
|
|
|
}
|