using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using JsonKnownTypes; using MessagePack; using Newtonsoft.Json; using Unity.Mathematics; using static Unity.Mathematics.math; [MessagePackObject, JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter))] public class Entity : DatabaseEntry, IMessagePackSerializationCallbackReceiver { [IgnoreMember] public Dictionary AxisOverrides = new Dictionary(); [IgnoreMember] public readonly Dictionary VisibilitySources = new Dictionary(); public float Temperature; public float Energy; public float2 Position; public float2 Direction = float2(0,1); public float2 Velocity; [IgnoreMember] public Dictionary> Bindings; [IgnoreMember] public Dictionary Axes; public readonly List Cargo; public readonly List EquippedItems; [IgnoreMember] protected List Behaviors; public Gear Hull { get; } [IgnoreMember] public float Mass { get; private set; } [IgnoreMember] public float SpecificHeat { get; private set; } [IgnoreMember] public float Visibility => VisibilitySources.Values.Sum(); public object[] PersistedBehaviors; public Entity(GameContext context, Gear hull, IEnumerable items, IEnumerable cargo) { Context = context; EquippedItems = items.ToList(); Cargo = cargo.ToList(); Hull = hull; RecalculateMass(); var activeItems = Hull == null ? EquippedItems : EquippedItems.Append(Hull); Behaviors = activeItems .Where(i=>i.ItemData.Behaviors?.Any()??false) .SelectMany(i => i.ItemData.Behaviors .Select(bd => bd.CreateInstance(Context, this, i))) .OrderBy(b => b.GetType().GetCustomAttribute()?.Order ?? 0).ToList(); Bindings = Behaviors .Where(b => b is IActivatedBehavior) .GroupBy(b => b.Item.ID, (guid, behaviors) => new {guid, behaviors}) .ToDictionary(g => g.guid, g => g.behaviors.Cast().ToList()); Axes = Behaviors .Where(b => b is IAnalogBehavior) .ToDictionary(b => b as IAnalogBehavior, b => 0f); foreach (var behavior in Behaviors) { behavior.Initialize(); } } public void RecalculateMass() { Mass = Hull?.Mass ?? 0 + EquippedItems.Sum(i => i.Mass) + Cargo.Sum(ii => ii.Mass); SpecificHeat = (Hull?.HeatCapacity ?? 0) + EquippedItems.Sum(i => i.HeatCapacity) + Cargo.Sum(ii => ii.HeatCapacity); } public IEnumerable GetBehaviors() where T : class, IBehavior { foreach (var behavior in Behaviors) if (behavior is T b) yield return b; } public IEnumerable GetBehaviorData() where T : class, IBehaviorData { foreach (var behavior in Behaviors) if (behavior.Data is T b) yield return b; } public void AddHeat(float heat) { Temperature += heat / SpecificHeat; } public virtual void Update(float delta) { foreach(var analogBehavior in Axes.Keys) analogBehavior.SetAxis(AxisOverrides.ContainsKey(analogBehavior) ? AxisOverrides[analogBehavior] : Axes[analogBehavior]); foreach(var behavior in Behaviors) behavior.Update(delta); foreach (var item in EquippedItems.Where(item => item.ItemData.Performance(Temperature) < .01f)) item.Durability -= delta; } public void OnBeforeSerialize() { PersistedBehaviors = Behaviors .Where(b => b is IPersistentBehavior) .Cast() .Select(b => b.Store()).ToArray(); } public void OnAfterDeserialize() { RecalculateMass(); var activeItems = Hull == null ? EquippedItems : EquippedItems.Append(Hull); Behaviors = activeItems .Where(i=>i.ItemData.Behaviors?.Any()??false) .SelectMany(i => i.ItemData.Behaviors .Select(bd => bd.CreateInstance(Context, this, i))) .OrderBy(b => b.GetType().GetCustomAttribute()?.Order ?? 0).ToList(); Bindings = Behaviors .Where(b => b is IActivatedBehavior) .GroupBy(b => b.Item.ID, (guid, behaviors) => new {guid, behaviors}) .ToDictionary(g => g.guid, g => g.behaviors.Cast().ToList()); Axes = Behaviors .Where(b => b is IAnalogBehavior) .ToDictionary(b => b as IAnalogBehavior, b => 0f); foreach (var behavior in Behaviors) { behavior.Initialize(); } } }