diff --git a/Aetheria.Shared/Aetheria.Shared.csproj b/Aetheria.Shared/Aetheria.Shared.csproj
index 3783e7469..5274558da 100644
--- a/Aetheria.Shared/Aetheria.Shared.csproj
+++ b/Aetheria.Shared/Aetheria.Shared.csproj
@@ -25,6 +25,8 @@
+
+
diff --git a/Assets/Scripts/ServerShared/AetheriaStores.cs b/Assets/Scripts/ServerShared/AetheriaStores.cs
new file mode 100644
index 000000000..4394e89d6
--- /dev/null
+++ b/Assets/Scripts/ServerShared/AetheriaStores.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Linq;
+using GameCult.Caching;
+using GameCult.Caching.MessagePack;
+
+// Aetheria's stores: one home store per type, composed here and nowhere else.
+public static class AetheriaStores
+{
+ public static readonly Type[] CatalogTypes = { typeof(ItemData), typeof(Faction), typeof(FactionProductData), typeof(PersonalityAttribute), typeof(NameFile) };
+ public static readonly Type[] RunTypes = { typeof(OrbitData), typeof(BodyData), typeof(SavedZone), typeof(SavedGame) };
+ public static readonly Type[] PlayerTypes = { typeof(PlayerSettings), typeof(InputLayout) };
+
+ // Attaches (hydrates) the catalog read-only unless catalogWritable, then the run and player stores when given.
+ // A read-only catalog throws when a [CultGlobal] type routed to it has no record. A writable catalog is being
+ // authored (the importer starts from an empty file), so it is not held to that.
+ public static CultCache Open(string catalogPath, string runPath = null, string playerPath = null, bool catalogWritable = false)
+ {
+ var cache = new CultCache();
+ try
+ {
+ cache.AddBackingStore(new SingleFileMessagePackBackingStore(catalogPath, !catalogWritable), CatalogTypes);
+ if (runPath != null) cache.AddBackingStore(new SingleFileMessagePackBackingStore(runPath), RunTypes);
+ if (playerPath != null) cache.AddBackingStore(new SingleFileMessagePackBackingStore(playerPath), PlayerTypes);
+ var missing = catalogWritable ? null : cache.Registry.AllDescriptors.FirstOrDefault(descriptor =>
+ descriptor.IsGlobal &&
+ CatalogTypes.Any(home => home.IsAssignableFrom(descriptor.DocumentType)) &&
+ cache.AllStoredDocuments.All(stored => stored.Descriptor != descriptor));
+ if (missing != null)
+ throw new InvalidOperationException($"Catalog {catalogPath} has no {missing.SchemaName} record; catalog globals are authored, never invented.");
+ return cache;
+ }
+ catch
+ {
+ cache.Dispose();
+ throw;
+ }
+ }
+}
+
+public static class CultRecordRefs
+{
+ public static bool IsSet(this CultRecordKey key) => !string.IsNullOrEmpty(key.Value);
+ public static bool IsSet(this CultRecordRef reference) => reference.Key.IsSet();
+
+ // The document a reference names, or null when it is unset or names nothing this cache holds.
+ public static T Get(this CultCache cache, CultRecordRef reference) where T : class =>
+ reference.IsSet() ? cache.Get(reference.Key) : null;
+
+ // A reference to a document this cache holds. The key comes from the cache, never from the document.
+ public static CultRecordRef RefOf(this CultCache cache, T document) where T : class =>
+ new CultRecordRef(cache.TryGetHandle(document)?.Key ??
+ throw new InvalidOperationException($"This cache holds no such {document.GetType().Name}."));
+
+ // Writes a document to its home store; the cache mints its key the first time.
+ public static CultRecordRef Upsert(this CultCache cache, T document) where T : class =>
+ new CultRecordRef(cache.UpsertAsync(document).Result.Key);
+}
diff --git a/Assets/Scripts/ServerShared/AetheriaStores.cs.meta b/Assets/Scripts/ServerShared/AetheriaStores.cs.meta
new file mode 100644
index 000000000..7e8c26029
--- /dev/null
+++ b/Assets/Scripts/ServerShared/AetheriaStores.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a37c91e4d05b4f8e82c6b1d9e4f0a2c7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/ServerShared/Agents/States/MoveTo.cs b/Assets/Scripts/ServerShared/Agents/States/MoveTo.cs
index 5aa1925fd..39c4e1135 100644
--- a/Assets/Scripts/ServerShared/Agents/States/MoveTo.cs
+++ b/Assets/Scripts/ServerShared/Agents/States/MoveTo.cs
@@ -1,4 +1,5 @@
+using GameCult.Caching;
using System;
using CultMath;
using static CultMath.math;
@@ -29,7 +30,7 @@ public abstract class MoveToState : BaseState
public class MoveToOrbitState : MoveToState
{
- public Guid Orbit { get; set; }
+ public CultRecordKey Orbit { get; set; }
public MoveToOrbitState(Agent agent) : base(agent) { }
protected override float2 TargetPosition => _agent.Ship.Zone.GetOrbitPosition(Orbit);
diff --git a/Assets/Scripts/ServerShared/Agents/Tasks/AgentTask.cs b/Assets/Scripts/ServerShared/Agents/Tasks/AgentTask.cs
index 1e6e86fb8..26b70716c 100644
--- a/Assets/Scripts/ServerShared/Agents/Tasks/AgentTask.cs
+++ b/Assets/Scripts/ServerShared/Agents/Tasks/AgentTask.cs
@@ -1,31 +1,23 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
+/* 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;
using System.Collections.Generic;
-using JsonKnownTypes;
using MessagePack;
using Newtonsoft.Json;
-[MessagePackObject,
- Union(0, typeof(StationTowing)),
- Union(1, typeof(Mining)),
- Union(2, typeof(Survey)),
- Union(3, typeof(HaulingTask)),
- JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter))]
-public abstract class AgentTask : DatabaseEntry
+// Agent tasks are owned by their Agent and not persisted.
+[JsonObject(MemberSerialization.OptIn)]
+public abstract class AgentTask
{
[JsonProperty("priority"), Key(1)]
public int Priority;
-
- [JsonProperty("zone"), Key(2)]
- public Guid Zone;
-
+
[JsonProperty("reserved"), Key(3)]
public bool Reserved;
-
+
[IgnoreMember] public abstract TaskType Type { get; }
}
diff --git a/Assets/Scripts/ServerShared/Agents/Tasks/HaulingTask.cs b/Assets/Scripts/ServerShared/Agents/Tasks/HaulingTask.cs
index 137fca75f..e657ef0aa 100644
--- a/Assets/Scripts/ServerShared/Agents/Tasks/HaulingTask.cs
+++ b/Assets/Scripts/ServerShared/Agents/Tasks/HaulingTask.cs
@@ -2,6 +2,7 @@
* 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 GameCult.Caching;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -19,7 +20,7 @@ public class HaulingTask : AgentTask
public Entity Target;
[JsonProperty("itemType"), Key(6)]
- public Guid ItemType;
+ public CultRecordKey ItemType;
[JsonProperty("quantity"), Key(7)]
public int Quantity;
diff --git a/Assets/Scripts/ServerShared/Agents/Tasks/Mining.cs b/Assets/Scripts/ServerShared/Agents/Tasks/Mining.cs
index d61cf31fa..e4e935519 100644
--- a/Assets/Scripts/ServerShared/Agents/Tasks/Mining.cs
+++ b/Assets/Scripts/ServerShared/Agents/Tasks/Mining.cs
@@ -2,19 +2,19 @@
* 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 GameCult.Caching;
using System;
using System.Collections;
using System.Collections.Generic;
-using JsonKnownTypes;
using MessagePack;
using Newtonsoft.Json;
[MessagePackObject,
- JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter))]
+ JsonObject(MemberSerialization.OptIn)]
public class Mining : AgentTask
{
[IgnoreMember] public override TaskType Type => TaskType.Mine;
[JsonProperty("asteroids"), Key(4)]
- public Guid Asteroids;
+ public CultRecordKey Asteroids;
}
\ No newline at end of file
diff --git a/Assets/Scripts/ServerShared/Agents/Tasks/PatrolOrbits.cs b/Assets/Scripts/ServerShared/Agents/Tasks/PatrolOrbits.cs
index 653764217..f2a26771d 100644
--- a/Assets/Scripts/ServerShared/Agents/Tasks/PatrolOrbits.cs
+++ b/Assets/Scripts/ServerShared/Agents/Tasks/PatrolOrbits.cs
@@ -1,15 +1,16 @@
+using GameCult.Caching;
using System;
public class PatrolOrbitsTask : AgentTask
{
public override TaskType Type => TaskType.Defend;
- public Guid[] Circuit;
+ public CultRecordKey[] Circuit;
}
public class PatrolOrbitsState : BaseState
{
public PatrolOrbitsTask Task;
- public Guid CurrentTarget
+ public CultRecordKey CurrentTarget
{
get => Task.Circuit[_currentTargetIndex];
}
diff --git a/Assets/Scripts/ServerShared/Agents/Tasks/StationTowing.cs b/Assets/Scripts/ServerShared/Agents/Tasks/StationTowing.cs
index 926fc3cf8..e37eadaa5 100644
--- a/Assets/Scripts/ServerShared/Agents/Tasks/StationTowing.cs
+++ b/Assets/Scripts/ServerShared/Agents/Tasks/StationTowing.cs
@@ -2,15 +2,15 @@
* 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 GameCult.Caching;
using System;
using System.Collections;
using System.Collections.Generic;
-using JsonKnownTypes;
using MessagePack;
using Newtonsoft.Json;
[MessagePackObject,
- JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter))]
+ JsonObject(MemberSerialization.OptIn)]
public class StationTowing : AgentTask
{
[IgnoreMember] public override TaskType Type => TaskType.Tow;
@@ -19,7 +19,7 @@ public class StationTowing : AgentTask
public OrbitalEntity Station;
[JsonProperty("orbitParent"), Key(5)]
- public Guid OrbitParent;
+ public CultRecordKey OrbitParent;
[JsonProperty("orbitDistance"), Key(6)]
public float OrbitDistance;
diff --git a/Assets/Scripts/ServerShared/Agents/Tasks/Survey.cs b/Assets/Scripts/ServerShared/Agents/Tasks/Survey.cs
index 5d43dcebc..787ee0a4f 100644
--- a/Assets/Scripts/ServerShared/Agents/Tasks/Survey.cs
+++ b/Assets/Scripts/ServerShared/Agents/Tasks/Survey.cs
@@ -2,19 +2,19 @@
* 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 GameCult.Caching;
using System;
using System.Collections;
using System.Collections.Generic;
-using JsonKnownTypes;
using MessagePack;
using Newtonsoft.Json;
[MessagePackObject,
- JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter))]
+ JsonObject(MemberSerialization.OptIn)]
public class Survey : AgentTask
{
[IgnoreMember] public override TaskType Type => TaskType.Explore;
[JsonProperty("station"), Key(4)]
- public List Planets;
+ public List Planets;
}
\ No newline at end of file
diff --git a/Assets/Scripts/ServerShared/AssemblyInfo.cs b/Assets/Scripts/ServerShared/AssemblyInfo.cs
new file mode 100644
index 000000000..d632eca81
--- /dev/null
+++ b/Assets/Scripts/ServerShared/AssemblyInfo.cs
@@ -0,0 +1,4 @@
+using GameCult.Caching.MessagePack;
+
+// CultCache serializes this assembly's documents with MathResolver ahead of MessagePack's standard resolvers.
+[assembly: CultCacheFormatterResolver(typeof(MathResolver))]
diff --git a/Assets/Scripts/ServerShared/AssemblyInfo.cs.meta b/Assets/Scripts/ServerShared/AssemblyInfo.cs.meta
new file mode 100644
index 000000000..fd4671abe
--- /dev/null
+++ b/Assets/Scripts/ServerShared/AssemblyInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5d8e2b7a1c4f4e3a9b6d0f2c8a1e7b43
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/ServerShared/Behaviors/AetherDrive.cs b/Assets/Scripts/ServerShared/Behaviors/AetherDrive.cs
index dd104f7f2..3e43ebc92 100644
--- a/Assets/Scripts/ServerShared/Behaviors/AetherDrive.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/AetherDrive.cs
@@ -2,6 +2,7 @@
* 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 GameCult.Caching;
using MessagePack;
using Newtonsoft.Json;
using CultMath;
@@ -40,13 +41,13 @@ public class AetherDriveData : BehaviorData
[Inspectable, JsonProperty("passiveCoupling"), Key(10), RuntimeInspectable]
public PerformanceStat PassiveCoupling;
- [InspectableAudioParameter, JsonProperty("rpmAudio"), Key(11), RuntimeInspectable]
+ [Inspectable, JsonProperty("rpmAudio"), Key(11), RuntimeInspectable]
public uint RpmAudioParameter;
- [InspectableAudioParameter, JsonProperty("torqueAudio"), Key(12), RuntimeInspectable]
+ [Inspectable, JsonProperty("torqueAudio"), Key(12), RuntimeInspectable]
public uint TorqueRatioAudioParameter;
- [InspectablePrefab, JsonProperty("particles"), Key(13)]
+ [Inspectable, CultInspectorAssetPath, JsonProperty("particles"), Key(13)]
public string Particles;
public override Behavior CreateInstance(EquippedItem item)
diff --git a/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs b/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs
index 6fe54a95b..cd0cc98ec 100644
--- a/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs
@@ -6,7 +6,6 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
-using JsonKnownTypes;
using MessagePack;
using Newtonsoft.Json;
using CultMath;
@@ -142,8 +141,7 @@ public interface IPopulationAssignment
}
[MessagePackObject,
- JsonObject(MemberSerialization.OptIn),
- JsonConverter(typeof(JsonKnownTypesConverter))]
+ JsonObject(MemberSerialization.OptIn)]
public abstract class PersistentBehaviorData
{
}
@@ -187,7 +185,7 @@ public abstract class PersistentBehaviorData
Union(36, typeof(ConstantWeaponData)),
Union(37, typeof(ChargedWeaponData)),
Union(38, typeof(AutoWeaponData)),
- JsonConverter(typeof(JsonKnownTypesConverter)), JsonObject(MemberSerialization.OptIn)]
+ JsonObject(MemberSerialization.OptIn)]
public abstract class BehaviorData
{
[Inspectable, JsonProperty("group"), Key(0)]
diff --git a/Assets/Scripts/ServerShared/Behaviors/ConstantWeapon.cs b/Assets/Scripts/ServerShared/Behaviors/ConstantWeapon.cs
index 2b2a1bbaa..7e4eaf1d5 100644
--- a/Assets/Scripts/ServerShared/Behaviors/ConstantWeapon.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/ConstantWeapon.cs
@@ -11,7 +11,7 @@ using static CultMath.math;
[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class ConstantWeaponData : WeaponData
{
- [InspectablePrefab, JsonProperty("ammoInterval"), Key(17)]
+ [Inspectable, JsonProperty("ammoInterval"), Key(17)]
public float AmmoInterval = 1;
public override Behavior CreateInstance(EquippedItem item)
@@ -83,7 +83,7 @@ public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior
OnStopFiring?.Invoke();
return false;
}
- if (_data.AmmoType != Guid.Empty)
+ if (_data.AmmoType.IsSet())
{
if (_reloading)
{
@@ -103,10 +103,10 @@ public class ConstantWeapon : Weapon, IProgressBehavior, IEventBehavior
if (_data.MagazineSize > 1 && _ammo > 0) _ammo--;
else
{
- var cargo = Entity.FindItemInCargo(_data.AmmoType);
+ var cargo = Entity.FindItemInCargo(_data.AmmoType.Key);
if (cargo != null)
{
- var item = cargo.ItemsOfType[_data.AmmoType][0];
+ var item = cargo.ItemsOfType[_data.AmmoType.Key][0];
if (item is SimpleCommodity simpleCommodity)
cargo.Remove(simpleCommodity, 1);
diff --git a/Assets/Scripts/ServerShared/Behaviors/Cooldown.cs b/Assets/Scripts/ServerShared/Behaviors/Cooldown.cs
index 4d046db1d..88336cfe5 100644
--- a/Assets/Scripts/ServerShared/Behaviors/Cooldown.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/Cooldown.cs
@@ -9,7 +9,7 @@ using Newtonsoft.Json;
using CultMath;
using static CultMath.math;
-[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(-10), RuntimeInspectable]
+[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), RuntimeInspectable]
public class CooldownData : BehaviorData
{
[Inspectable, JsonProperty("cooldown"), Key(1), RuntimeInspectable]
diff --git a/Assets/Scripts/ServerShared/Behaviors/EnergyDraw.cs b/Assets/Scripts/ServerShared/Behaviors/EnergyDraw.cs
index faf8ae709..5fd4b9277 100644
--- a/Assets/Scripts/ServerShared/Behaviors/EnergyDraw.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/EnergyDraw.cs
@@ -7,7 +7,7 @@ using System.Linq;
using MessagePack;
using Newtonsoft.Json;
-[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(-20), RuntimeInspectable]
+[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), RuntimeInspectable]
public class EnergyDrawData : BehaviorData
{
[Inspectable, JsonProperty("draw"), Key(1), RuntimeInspectable]
diff --git a/Assets/Scripts/ServerShared/Behaviors/Heat.cs b/Assets/Scripts/ServerShared/Behaviors/Heat.cs
index e507d2b28..3d8914880 100644
--- a/Assets/Scripts/ServerShared/Behaviors/Heat.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/Heat.cs
@@ -7,7 +7,7 @@ using System.Linq;
using MessagePack;
using Newtonsoft.Json;
-[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(10)]
+[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class HeatData : BehaviorData
{
[Inspectable, JsonProperty("heat"), Key(1), RuntimeInspectable]
diff --git a/Assets/Scripts/ServerShared/Behaviors/InstantWeapon.cs b/Assets/Scripts/ServerShared/Behaviors/InstantWeapon.cs
index aa59411d5..cf50f7494 100644
--- a/Assets/Scripts/ServerShared/Behaviors/InstantWeapon.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/InstantWeapon.cs
@@ -18,7 +18,7 @@ public class InstantWeaponData : WeaponData
[Inspectable, JsonProperty("cooldown"), Key(19), RuntimeInspectable]
public PerformanceStat Cooldown = new PerformanceStat();
- [InspectablePrefab, JsonProperty("ammoInterval"), Key(20)]
+ [Inspectable, JsonProperty("ammoInterval"), Key(20)]
public bool SingleAmmoBurst;
public override Behavior CreateInstance(EquippedItem item)
@@ -124,12 +124,12 @@ public class InstantWeapon : Weapon, IProgressBehavior, IEventBehavior
}
var hasAmmo = true;
- if (_data.AmmoType != Guid.Empty)
+ if (_data.AmmoType.IsSet())
{
- var cargo = Entity.FindItemInCargo(_data.AmmoType);
+ var cargo = Entity.FindItemInCargo(_data.AmmoType.Key);
if (cargo != null)
{
- var item = cargo.ItemsOfType[_data.AmmoType][0];
+ var item = cargo.ItemsOfType[_data.AmmoType.Key][0];
if (item is SimpleCommodity simpleCommodity)
cargo.Remove(simpleCommodity, 1);
}
diff --git a/Assets/Scripts/ServerShared/Behaviors/ItemUsage.cs b/Assets/Scripts/ServerShared/Behaviors/ItemUsage.cs
index f5dda8a5f..e8c5e7dd0 100644
--- a/Assets/Scripts/ServerShared/Behaviors/ItemUsage.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/ItemUsage.cs
@@ -2,16 +2,17 @@
* 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 GameCult.Caching;
using System;
using System.Linq;
using MessagePack;
using Newtonsoft.Json;
-[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(-5), RuntimeInspectable]
+[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), RuntimeInspectable]
public class ItemUsageData : BehaviorData
{
- [InspectableDatabaseLink(typeof(SimpleCommodityData)), JsonProperty("item"), Key(1), RuntimeInspectable]
- public Guid Item;
+ [Inspectable, JsonProperty("item"), Key(1), RuntimeInspectable]
+ public CultRecordRef Item;
public override Behavior CreateInstance(EquippedItem item)
{
@@ -40,10 +41,10 @@ public class ItemUsage : Behavior
public override bool Execute(float dt)
{
- var cargo = Entity.FindItemInCargo(_data.Item);
+ var cargo = Entity.FindItemInCargo(_data.Item.Key);
if (cargo == null) return false;
- var item = cargo.ItemsOfType[_data.Item][0];
+ var item = cargo.ItemsOfType[_data.Item.Key][0];
if (item is SimpleCommodity simpleCommodity)
cargo.Remove(simpleCommodity, 1);
if (item is CraftedItemInstance craftedItemInstance)
diff --git a/Assets/Scripts/ServerShared/Behaviors/MiningTool.cs b/Assets/Scripts/ServerShared/Behaviors/MiningTool.cs
index d13dc765c..f03c12fac 100644
--- a/Assets/Scripts/ServerShared/Behaviors/MiningTool.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/MiningTool.cs
@@ -2,6 +2,7 @@
* 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 GameCult.Caching;
using System;
using System.Linq;
using MessagePack;
@@ -9,7 +10,7 @@ using Newtonsoft.Json;
using CultMath;
using static CultMath.math;
-[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(10)]
+[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class MiningToolData : BehaviorData
{
[Inspectable, JsonProperty("dps"), Key(1)]
@@ -36,7 +37,7 @@ public class MiningToolData : BehaviorData
public class MiningTool : Behavior
{
- public Guid AsteroidBelt;
+ public CultRecordKey AsteroidBelt;
public int Asteroid;
private MiningToolData _data;
@@ -56,7 +57,7 @@ public class MiningTool : Behavior
{
Range = Evaluate(_data.Range);
var belt = Entity.Zone.AsteroidBelts[AsteroidBelt];
- if (AsteroidBelt != Guid.Empty &&
+ if (AsteroidBelt.IsSet() &&
Entity.Zone.AsteroidExists(AsteroidBelt, Asteroid) &&
length(Entity.Position.xz - belt.Transforms[Asteroid].xy) - belt.Transforms[Asteroid].w < Range)
{
diff --git a/Assets/Scripts/ServerShared/Behaviors/ResourceScanner.cs b/Assets/Scripts/ServerShared/Behaviors/ResourceScanner.cs
index c7035c8ef..0b708cd96 100644
--- a/Assets/Scripts/ServerShared/Behaviors/ResourceScanner.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/ResourceScanner.cs
@@ -2,6 +2,7 @@
* 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 GameCult.Caching;
using System;
using System.Linq;
using MessagePack;
@@ -38,18 +39,18 @@ public class ResourceScanner : Behavior, IAlwaysUpdatedBehavior
private ResourceScannerData _data;
private float _scanTime;
- private Guid _scanTarget;
+ private CultRecordKey _scanTarget;
public float Range { get; private set; }
public float MinimumDensity { get; private set; }
public float ScanDuration { get; private set; }
- public Guid ScanTarget
+ public CultRecordKey ScanTarget
{
get => _scanTarget;
set
{
- if (value != _scanTarget)
+ if (!value.Equals(_scanTarget))
{
_scanTarget = value;
_scanTime = 0;
@@ -90,7 +91,7 @@ public class ResourceScanner : Behavior, IAlwaysUpdatedBehavior
}
else
{
- if(length(Entity.Position.xz - Entity.Zone.GetOrbitPosition(planetData.Orbit)) < Range)
+ if(length(Entity.Position.xz - Entity.Zone.GetOrbitPosition(planetData.Orbit.Key)) < Range)
{
_scanTime += dt;
if (_scanTime > ScanDuration)
diff --git a/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs b/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs
index 6d29d5472..6f1f506c5 100644
--- a/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/StatModifier.cs
@@ -1,4 +1,4 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
+/* 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/. */
@@ -10,18 +10,19 @@ using Newtonsoft.Json;
[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class StatModifierData : BehaviorData
{
- [Inspectable, JsonProperty("stat"), Key(1)]
+ [Inspectable, JsonProperty("stat"), Key(1)]
public StatReference Stat = new StatReference();
-
- [Inspectable, JsonProperty("modifier"), Key(2)]
+
+ [Inspectable, JsonProperty("modifier"), Key(2)]
public PerformanceStat Modifier = new PerformanceStat();
-
- [Inspectable, JsonProperty("type"), Key(3)]
+
+ [Inspectable, JsonProperty("type"), Key(3)]
public StatModifierType Type;
+ // The simple name of a BehaviorData type, as InspectableType writes it
[InspectableType(typeof(BehaviorData)), JsonProperty("requireBehavior"), Key(4)]
- public Type RequireBehavior;
-
+ public string RequireBehavior;
+
public override Behavior CreateInstance(EquippedItem item)
{
return new StatModifier(this, item);
@@ -33,13 +34,12 @@ public class StatModifierData : BehaviorData
}
}
-[Order(-4)]
public class StatModifier : Behavior, IInitializableBehavior, IDisposable, IAlwaysUpdatedBehavior
{
private StatModifierData _data;
private PerformanceStat[] _stats;
-
+
private static Type[] _statObjects;
private bool _applied;
@@ -70,14 +70,14 @@ public class StatModifier : Behavior, IInitializableBehavior, IDisposable, IAlwa
if (typeof(EquippableItemData).IsAssignableFrom(targetType))
_stats = Entity.Equipment
.Select(hp => hp.EquippableItem)
- .Where(gear => _data.RequireBehavior == null || ItemManager.GetData(gear).Behaviors.Any(behavior => behavior.GetType() == _data.RequireBehavior))
+ .Where(gear => string.IsNullOrEmpty(_data.RequireBehavior) || ItemManager.GetData(gear).Behaviors.Any(behavior => behavior.GetType().Name == _data.RequireBehavior))
.Where(gear => ItemManager.GetData(gear).GetType() == targetType)
.Select(gear => statField.GetValue(ItemManager.GetData(gear)) as PerformanceStat)
.ToArray();
else
_stats = Entity.Equipment
.Select(hp => hp.EquippableItem)
- .Where(gear => _data.RequireBehavior == null || ItemManager.GetData(gear).Behaviors.Any(behavior => behavior.GetType() == _data.RequireBehavior))
+ .Where(gear => string.IsNullOrEmpty(_data.RequireBehavior) || ItemManager.GetData(gear).Behaviors.Any(behavior => behavior.GetType().Name == _data.RequireBehavior))
.SelectMany(gear => ItemManager.GetData(gear).Behaviors)
.Where(behaviorData => behaviorData.GetType() == targetType)
.Select(behaviorData => statField.GetValue(behaviorData) as PerformanceStat)
@@ -135,7 +135,7 @@ public class StatReference
{
[InspectableType(typeof(BehaviorData)), JsonProperty("behavior"), Key(1)]
public string Target;
-
+
[Inspectable, JsonProperty("stat"), Key(2)]
public string Stat;
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/ServerShared/Behaviors/Switch.cs b/Assets/Scripts/ServerShared/Behaviors/Switch.cs
index 4795a2b2e..47990c4b2 100644
--- a/Assets/Scripts/ServerShared/Behaviors/Switch.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/Switch.cs
@@ -7,7 +7,7 @@ using System.Linq;
using MessagePack;
using Newtonsoft.Json;
-[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(-25)]
+[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class SwitchData : BehaviorData
{
public override Behavior CreateInstance(EquippedItem item)
diff --git a/Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs b/Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs
index 009a04c9e..05a354d8b 100644
--- a/Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/Thermotoggle.cs
@@ -7,7 +7,7 @@ using System.Linq;
using MessagePack;
using Newtonsoft.Json;
-[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(-22)]
+[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class ThermotoggleData : BehaviorData
{
[InspectableTemperature, JsonProperty("targetTemp"), Key(1)]
diff --git a/Assets/Scripts/ServerShared/Behaviors/Thruster.cs b/Assets/Scripts/ServerShared/Behaviors/Thruster.cs
index 79dac790b..54aa39c34 100644
--- a/Assets/Scripts/ServerShared/Behaviors/Thruster.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/Thruster.cs
@@ -2,6 +2,7 @@
* 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 GameCult.Caching;
using MessagePack;
using Newtonsoft.Json;
using CultMath;
@@ -22,7 +23,7 @@ public class ThrusterData : BehaviorData
[Inspectable, JsonProperty("energy"), Key(4), RuntimeInspectable]
public PerformanceStat EnergyUsage = new PerformanceStat();
- [InspectablePrefab, JsonProperty("Particles"), Key(5)]
+ [Inspectable, CultInspectorAssetPath, JsonProperty("Particles"), Key(5)]
public string ParticlesPrefab;
public override Behavior CreateInstance(EquippedItem item)
diff --git a/Assets/Scripts/ServerShared/Behaviors/Trigger.cs b/Assets/Scripts/ServerShared/Behaviors/Trigger.cs
index 26262d8a7..be7c9b9dc 100644
--- a/Assets/Scripts/ServerShared/Behaviors/Trigger.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/Trigger.cs
@@ -7,7 +7,7 @@ using System.Linq;
using MessagePack;
using Newtonsoft.Json;
-[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(-20)]
+[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class TriggerData : BehaviorData
{
public override Behavior CreateInstance(EquippedItem item)
diff --git a/Assets/Scripts/ServerShared/Behaviors/VelocityLimit.cs b/Assets/Scripts/ServerShared/Behaviors/VelocityLimit.cs
index 64a312478..407e5f949 100644
--- a/Assets/Scripts/ServerShared/Behaviors/VelocityLimit.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/VelocityLimit.cs
@@ -23,7 +23,6 @@ public class VelocityLimitData : BehaviorData
}
}
-[Order(100)]
public class VelocityLimit : Behavior
{
public float Limit { get; private set; }
diff --git a/Assets/Scripts/ServerShared/Behaviors/Weapon.cs b/Assets/Scripts/ServerShared/Behaviors/Weapon.cs
index 73e733b5d..417751b4c 100644
--- a/Assets/Scripts/ServerShared/Behaviors/Weapon.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/Weapon.cs
@@ -2,6 +2,7 @@
* 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 GameCult.Caching;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -24,10 +25,10 @@ public abstract class WeaponData : BehaviorData
[Inspectable, JsonProperty("damage"), Key(2), RuntimeInspectable]
public PerformanceStat Damage = new PerformanceStat();
- [InspectableRangedFloat(0,1), JsonProperty("penetration"), Key(3), RuntimeInspectable]
+ [Inspectable, CultInspectorRange(0, 1), JsonProperty("penetration"), Key(3), RuntimeInspectable]
public PerformanceStat Penetration = new PerformanceStat();
- [InspectableRangedFloat(0,1), JsonProperty("damageSpread"), Key(4)]
+ [Inspectable, CultInspectorRange(0, 1), JsonProperty("damageSpread"), Key(4)]
public PerformanceStat DamageSpread = new PerformanceStat();
[Inspectable, JsonProperty("minRange"), Key(5)]
@@ -39,28 +40,28 @@ public abstract class WeaponData : BehaviorData
[InspectableAnimationCurve, JsonProperty("damageCurve"), Key(7)]
public BezierCurve DamageCurve;
- [InspectablePrefab, JsonProperty("effect"), Key(8)]
+ [Inspectable, CultInspectorAssetPath, JsonProperty("effect"), Key(8)]
public string EffectPrefab;
- [InspectablePrefab, JsonProperty("energy"), Key(9), RuntimeInspectable]
+ [Inspectable, JsonProperty("energy"), Key(9), RuntimeInspectable]
public PerformanceStat Energy = new PerformanceStat();
- [InspectablePrefab, JsonProperty("heat"), Key(10), RuntimeInspectable]
+ [Inspectable, JsonProperty("heat"), Key(10), RuntimeInspectable]
public PerformanceStat Heat = new PerformanceStat();
- [InspectablePrefab, JsonProperty("visibility"), Key(11), RuntimeInspectable]
+ [Inspectable, JsonProperty("visibility"), Key(11), RuntimeInspectable]
public PerformanceStat Visibility = new PerformanceStat();
- [InspectableDatabaseLink(typeof(SimpleCommodityData)), JsonProperty("ammo"), Key(12), RuntimeInspectable]
- public Guid AmmoType;
+ [Inspectable, JsonProperty("ammo"), Key(12), RuntimeInspectable]
+ public CultRecordRef AmmoType;
- [InspectablePrefab, JsonProperty("magSize"), Key(13)]
+ [Inspectable, JsonProperty("magSize"), Key(13)]
public int MagazineSize;
- [InspectablePrefab, JsonProperty("reloadTime"), Key(14)]
+ [Inspectable, JsonProperty("reloadTime"), Key(14)]
public float ReloadTime = 1;
- [InspectablePrefab, JsonProperty("spread"), Key(15)]
+ [Inspectable, JsonProperty("spread"), Key(15)]
public PerformanceStat Spread = new PerformanceStat();
[Inspectable, JsonProperty("velocity"), Key(16)]
diff --git a/Assets/Scripts/ServerShared/Behaviors/Wear.cs b/Assets/Scripts/ServerShared/Behaviors/Wear.cs
index e6ea327ee..e2e0b1f53 100644
--- a/Assets/Scripts/ServerShared/Behaviors/Wear.cs
+++ b/Assets/Scripts/ServerShared/Behaviors/Wear.cs
@@ -8,7 +8,7 @@ using Newtonsoft.Json;
using CultMath;
using static CultMath.math;
-[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), Order(1000), RuntimeInspectable]
+[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn), RuntimeInspectable]
public class WearData : BehaviorData
{
[InspectableTemperature, JsonProperty("perSecond"), Key(1)]
diff --git a/Assets/Scripts/ServerShared/Corporations.cs b/Assets/Scripts/ServerShared/Corporations.cs
index fea1a4be8..23f9ba337 100644
--- a/Assets/Scripts/ServerShared/Corporations.cs
+++ b/Assets/Scripts/ServerShared/Corporations.cs
@@ -1,79 +1,67 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
+/* 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;
using System.Collections.Generic;
+using GameCult.Caching;
using MessagePack;
using Newtonsoft.Json;
using CultMath;
-[DatabaseCategory("Galaxy"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
-public class Faction : DatabaseEntry, INamedEntry
+[CultDocument("aetheria.faction", "1"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+public class Faction
{
- [Inspectable, JsonProperty("name"), Key(1)]
+ [Inspectable, CultName, JsonProperty("name"), Key(1)]
public string Name;
-
+
[Inspectable, JsonProperty("shortName"), Key(2)]
public string ShortName;
-
- [InspectableText, JsonProperty("description"), Key(3)]
+
+ [Inspectable, CultInspectorTextArea, JsonProperty("description"), Key(3)]
public string Description;
-
- [InspectableTexture, JsonProperty("logo"), Key(4)]
+
+ [Inspectable, CultInspectorAssetPath, JsonProperty("logo"), Key(4)]
public string Logo;
-
- [InspectableDatabaseLink(typeof(PersonalityAttribute)), JsonProperty("personality"), Key(5)]
- public Dictionary Personality = new Dictionary();
+
+ [Inspectable, CultReference(typeof(PersonalityAttribute), many: true), JsonProperty("personality"), Key(5)]
+ public Dictionary, float> Personality = new Dictionary, float>();
// [Inspectable, JsonProperty("hostile"), Key(6)]
// public bool PlayerHostile;
[InspectableColor, JsonProperty("primaryColor"), Key(7)]
public float3 PrimaryColor;
-
+
[InspectableColor, JsonProperty("secondaryColor"), Key(8)]
public float3 SecondaryColor;
- [InspectableDatabaseLink(typeof(NameFile)), JsonProperty("nameFile"), Key(9)]
- public Guid GeonameFile;
+ [Inspectable, JsonProperty("nameFile"), Key(9)]
+ public CultRecordRef GeonameFile;
- [InspectableDatabaseLink(typeof(HullData)), JsonProperty("bossHull"), Key(10)]
- public Guid BossHull;
+ [Inspectable, JsonProperty("bossHull"), Key(10)]
+ public CultRecordRef BossHull;
[Inspectable, JsonProperty("influence"), Key(11)]
public int InfluenceDistance = 4;
-
- [InspectableDatabaseLink(typeof(Faction)), RangedFloat(0, 1), JsonProperty("allegiance"), Key(12)]
- public Dictionary Allegiance = new Dictionary();
- [InspectableSoundBank, JsonProperty("overworldMusic"), Key(13)]
+ [Inspectable, CultReference(typeof(Faction), many: true), CultInspectorRange(0, 1), JsonProperty("allegiance"), Key(12)]
+ public Dictionary, float> Allegiance = new Dictionary, float>();
+
+ [Inspectable, JsonProperty("overworldMusic"), Key(13)]
public uint OverworldMusic;
- [InspectableSoundBank, JsonProperty("combatMusic"), Key(14)]
+ [Inspectable, JsonProperty("combatMusic"), Key(14)]
public uint CombatMusic;
- [InspectableSoundBank, JsonProperty("bossMusic"), Key(15)]
+ [Inspectable, JsonProperty("bossMusic"), Key(15)]
public uint BossMusic;
-
- [IgnoreMember] public string EntryName
- {
- get => Name;
- set => Name = value;
- }
}
-[Inspectable, MessagePackObject]
-public class NameFile : DatabaseEntry, INamedEntry
+[CultDocument("aetheria.namefile", "1"), Inspectable, MessagePackObject]
+public class NameFile
{
- [Key(1)] public string Name;
+ [CultName, Key(1)] public string Name;
[Key(2)] public string[] Names;
-
- [IgnoreMember]
- public string EntryName
- {
- get => Name;
- set => Name = value;
- }
}
diff --git a/Assets/Scripts/ServerShared/Entity.cs b/Assets/Scripts/ServerShared/Entity.cs
index 798522793..016b2bd4f 100644
--- a/Assets/Scripts/ServerShared/Entity.cs
+++ b/Assets/Scripts/ServerShared/Entity.cs
@@ -2,6 +2,7 @@
* 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 GameCult.Caching;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -288,7 +289,7 @@ public abstract class Entity
// TODO: Inter-faction hostility
// When the entity faction owns the zone, they are hostile to trespassers or those hostile to them
- if (Faction.ID == Zone.GalaxyZone.Owner?.ID)
+ if (Faction == Zone.GalaxyZone.Owner)
return recursive ? !(other.PresencePermitted?.Value ?? true) : !(other.PresencePermitted?.Value ?? true)|| other.IsHostileTo(this, true);
return !recursive && other.IsHostileTo(this, true);
@@ -301,7 +302,7 @@ public abstract class Entity
return FactionRelationship.Neutral;
if (this is Ship {IsPlayerShip: true})
return Zone.Galaxy.FactionRelationships[faction];
- return faction.ID == Faction.ID ? FactionRelationship.Beloved : FactionRelationship.Neutral;
+ return faction == Faction ? FactionRelationship.Beloved : FactionRelationship.Neutral;
}
public static bool IsPresencePermitted(FactionRelationship relationship, SecurityLevel securityLevel) =>
@@ -316,7 +317,7 @@ public abstract class Entity
public ConsumableItemEffect FindActiveConsumable(ConsumableItemData data)
{
- return _activeConsumables.FirstOrDefault(ac => ac.Data.ID == data.ID);
+ return _activeConsumables.FirstOrDefault(ac => ac.Data == data);
}
public bool CanActivateConsumable(ConsumableItemData data)
@@ -328,10 +329,11 @@ public abstract class Entity
{
if (!CanActivateConsumable(data)) return false;
- var bay = FindItemInCargo(data.ID);
+ var key = ItemManager.ItemData.RefOf(data).Key;
+ var bay = FindItemInCargo(key);
if (bay == null) return false;
- var item = (ConsumableItem) bay.ItemsOfType[data.ID].First();
+ var item = (ConsumableItem) bay.ItemsOfType[key].First();
ActivateConsumable(item);
bay.Remove(item);
return true;
@@ -377,7 +379,7 @@ public abstract class Entity
public void GenerateWeaponGroups()
{
foreach (var group in Weapons
- .GroupBy(w => w.Item.EquippableItem.Data.LinkID)
+ .GroupBy(w => w.Item.EquippableItem.Data.Key)
.OrderBy(wg=>wg.Average(w=>w.Range))
.Select((weapons, index) => (weapons, index)))
{
@@ -394,7 +396,7 @@ public abstract class Entity
Temperature[position.x, position.y] += heat / ThermalMass[position.x, position.y];
}
- public int CountItemsInCargo(Guid itemDataID)
+ public int CountItemsInCargo(CultRecordKey itemDataID)
{
int sum = 0;
foreach (var x in CargoBays)
@@ -408,7 +410,7 @@ public abstract class Entity
return sum;
}
- public EquippedCargoBay FindItemInCargo(Guid itemDataID)
+ public EquippedCargoBay FindItemInCargo(CultRecordKey itemDataID)
{
return CargoBays.FirstOrDefault(c => c.ItemsOfType.ContainsKey(itemDataID));
}
@@ -431,7 +433,7 @@ public abstract class Entity
// Attempts to move a given number of items of the given type to the target Entity
// Returns the number of items successfully transferred
- public int TryTransferItems(Entity target, Guid itemDataID, int quantity)
+ public int TryTransferItems(Entity target, CultRecordKey itemDataID, int quantity)
{
int quantityTransferred = 0;
while (quantityTransferred < quantity)
@@ -1052,7 +1054,7 @@ public class ConsumableItemEffect
{
Item = item;
Entity = entity;
- Data = (ConsumableItemData) item.Data.Value;
+ Data = (ConsumableItemData) entity.ItemManager.GetData(item);
RemainingDuration = Data.Duration;
Behaviors = Data.Behaviors
@@ -1329,7 +1331,7 @@ public class EquippedCargoBay : EquippedItem
public readonly ItemInstance[,] Occupancy;
- public readonly Dictionary> ItemsOfType = new Dictionary>();
+ public readonly Dictionary> ItemsOfType = new Dictionary>();
public new readonly CargoBayData Data;
@@ -1362,7 +1364,7 @@ public class EquippedCargoBay : EquippedItem
// Check whether the given item will fit when its origin is placed at the given coordinate
public bool ItemFits(ItemInstance item, int2 cargoCoord)
{
- var itemData = item.Data.Value;
+ var itemData = ItemManager.GetData(item);
// Check every cell of the item's shape
foreach (var i in itemData.Shape.Coordinates)
{
@@ -1395,7 +1397,7 @@ public class EquippedCargoBay : EquippedItem
// For simple commodities, search for existing item stacks to add to
foreach (var cargoItem in Cargo.Keys)
{
- if (item.Data != cargoItem.Data) continue;
+ if (!item.Data.Key.Equals(cargoItem.Data.Key)) continue;
var cargoCommodity = (SimpleCommodity) cargoItem;
if (cargoCommodity.Quantity >= itemData.MaxStack) continue;
@@ -1486,11 +1488,11 @@ public class EquippedCargoBay : EquippedItem
}
Cargo[item] = cargoCoord;
- if(!ItemsOfType.ContainsKey(item.Data.LinkID))
- ItemsOfType[item.Data.LinkID] = new List();
- ItemsOfType[item.Data.LinkID].Add(item);
+ if(!ItemsOfType.ContainsKey(item.Data.Key))
+ ItemsOfType[item.Data.Key] = new List();
+ ItemsOfType[item.Data.Key].Add(item);
}
- else if (Occupancy[cargoCoord.x, cargoCoord.y] is SimpleCommodity cargoCommodity && cargoCommodity.Data == item.Data)
+ else if (Occupancy[cargoCoord.x, cargoCoord.y] is SimpleCommodity cargoCommodity && cargoCommodity.Data.Key.Equals(item.Data.Key))
{
if (cargoCommodity.Quantity + item.Quantity <= itemData.MaxStack)
{
@@ -1530,9 +1532,9 @@ public class EquippedCargoBay : EquippedItem
}
Cargo[item] = cargoCoord;
- if(!ItemsOfType.ContainsKey(item.Data.LinkID))
- ItemsOfType[item.Data.LinkID] = new List();
- ItemsOfType[item.Data.LinkID].Add(item);
+ if(!ItemsOfType.ContainsKey(item.Data.Key))
+ ItemsOfType[item.Data.Key] = new List();
+ ItemsOfType[item.Data.Key].Add(item);
Mass += ItemManager.GetMass(item);
ThermalMass += ItemManager.GetThermalMass(item);
@@ -1555,9 +1557,9 @@ public class EquippedCargoBay : EquippedItem
Occupancy[v.x, v.y] = null;
Cargo.Remove(item);
- ItemsOfType[item.Data.LinkID].Remove(item);
- if (!ItemsOfType[item.Data.LinkID].Any())
- ItemsOfType.Remove(item.Data.LinkID);
+ ItemsOfType[item.Data.Key].Remove(item);
+ if (!ItemsOfType[item.Data.Key].Any())
+ ItemsOfType.Remove(item.Data.Key);
Mass -= ItemManager.GetMass(item);
ThermalMass -= ItemManager.GetThermalMass(item);
@@ -1584,9 +1586,9 @@ public class EquippedCargoBay : EquippedItem
Occupancy[v.x, v.y] = null;
Cargo.Remove(item);
- ItemsOfType[item.Data.LinkID].Remove(item);
- if (!ItemsOfType[item.Data.LinkID].Any())
- ItemsOfType.Remove(item.Data.LinkID);
+ ItemsOfType[item.Data.Key].Remove(item);
+ if (!ItemsOfType[item.Data.Key].Any())
+ ItemsOfType.Remove(item.Data.Key);
Mass -= ItemManager.GetMass(item);
ThermalMass -= ItemManager.GetThermalMass(item);
diff --git a/Assets/Scripts/ServerShared/EntitySerializer.cs b/Assets/Scripts/ServerShared/EntitySerializer.cs
index ea276a60a..75a0e5c23 100644
--- a/Assets/Scripts/ServerShared/EntitySerializer.cs
+++ b/Assets/Scripts/ServerShared/EntitySerializer.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+using GameCult.Caching;
using MessagePack;
using CultMath;
@@ -13,7 +14,7 @@ public static class EntitySerializer
if (entity is OrbitalEntity orbital)
pack = new OrbitalEntityPack
{
- Orbit = orbital.OrbitData,
+ Orbit = new CultRecordRef(orbital.OrbitData),
SecurityLevel = orbital.SecurityLevel,
SecurityRadius = orbital.SecurityRadius
};
@@ -27,7 +28,7 @@ public static class EntitySerializer
else throw new ArgumentException("Attempted to pack an instance of abstract class Entity!");
pack.Settings = entity.Settings;
-
+
// 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
@@ -40,7 +41,7 @@ public static class EntitySerializer
pack.Hull = entity.Hull;
pack.Name = entity.Name;
- pack.Faction = entity.Faction?.ID ?? Guid.Empty;
+ pack.Faction = entity.Faction == null ? default : entity.ItemManager.ItemData.RefOf(entity.Faction);
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();
@@ -70,7 +71,7 @@ public static class EntitySerializer
private static Ship Unpack(ItemManager itemManager, Zone zone, ShipPack pack, bool instantiate = false)
{
-
+
var entity = new Ship(itemManager, zone, instantiate ? (EquippableItem) itemManager.Instantiate(pack.Hull) : pack.Hull, pack.Settings);
Restore(itemManager, zone, pack, entity, instantiate);
entity.Position = pack.Position;
@@ -81,7 +82,7 @@ public static class EntitySerializer
private static OrbitalEntity Unpack(ItemManager itemManager, Zone zone, OrbitalEntityPack pack, bool instantiate = false)
{
- var entity = new OrbitalEntity(itemManager, zone, instantiate ? (EquippableItem) itemManager.Instantiate(pack.Hull) : pack.Hull, pack.Orbit, pack.Settings);
+ var entity = new OrbitalEntity(itemManager, zone, instantiate ? (EquippableItem) itemManager.Instantiate(pack.Hull) : pack.Hull, pack.Orbit.Key, pack.Settings);
Restore(itemManager, zone, pack, entity, instantiate);
entity.SecurityLevel = pack.SecurityLevel;
entity.SecurityRadius = pack.SecurityRadius;
@@ -92,7 +93,7 @@ public static class EntitySerializer
private static void Restore(ItemManager itemManager, Zone zone, EntityPack pack, Entity entity, bool instantiate = false)
{
entity.Name = pack.Name;
- entity.Faction = itemManager.ItemData.Get(pack.Faction);
+ entity.Faction = itemManager.ItemData.Get(pack.Faction);
entity.Children = pack.Children.Select(c =>
{
var child = Unpack(itemManager, zone, c, instantiate);
@@ -131,12 +132,12 @@ public static class EntitySerializer
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];
@@ -166,13 +167,13 @@ public class ShipPack : EntityPack
[MessagePackObject]
public class OrbitalEntityPack : EntityPack
{
- [Key(17)] public Guid Orbit;
+ [Key(17)] public CultRecordRef Orbit;
[Key(18)] public int Story = -1;
[Key(19)] public SecurityLevel SecurityLevel;
[Key(20)] public float SecurityRadius;
}
-[MessagePackObject,
+[MessagePackObject,
Union(0, typeof(OrbitalEntityPack)),
Union(1, typeof(ShipPack))]
public abstract class EntityPack
@@ -191,7 +192,7 @@ public abstract class EntityPack
[Key(12)] public (int2 position, ItemInstance item)[][] DockingBayContents;
[Key(13)] public EntityPack[] Children;
[Key(14)] public EntitySettings Settings;
- [Key(15)] public Guid Faction;
+ [Key(15)] public CultRecordRef Faction;
[Key(16)] public int[][] WeaponGroups;
private int _price;
@@ -199,7 +200,7 @@ public abstract class EntityPack
public int Price(ItemManager itemManager)
{
if (_price != 0) return _price;
-
+
var hullData = itemManager.GetData(Hull);
_price = hullData.Price;
@@ -223,7 +224,7 @@ public abstract class EntityPack
{
foreach (var (_, item) in t)
{
- var itemData = item.Data.Value;
+ var itemData = itemManager.GetData(item);
if (item is SimpleCommodity s)
_price += itemData.Price * s.Quantity;
else
@@ -235,7 +236,7 @@ public abstract class EntityPack
{
foreach (var (_, item) in t)
{
- var itemData = item.Data.Value;
+ var itemData = itemManager.GetData(item);
if (item is SimpleCommodity s)
_price += itemData.Price * s.Quantity;
else
diff --git a/Assets/Scripts/ServerShared/Extensions.cs b/Assets/Scripts/ServerShared/Extensions.cs
index a3a111556..e264af2c2 100644
--- a/Assets/Scripts/ServerShared/Extensions.cs
+++ b/Assets/Scripts/ServerShared/Extensions.cs
@@ -15,9 +15,6 @@ using float2 = CultMath.float2;
public static class Extensions
{
- //public static IDatabaseEntry Get(this Guid entry) => Database.Get(entry);
- //public static T Get(this Guid entry) where T : class, IDatabaseEntry => Database.Get(entry) as T;
-
public static bool IsImplementationOf(this Type baseType, Type interfaceType)
{
return baseType.GetInterfaces().Any(interfaceType.Equals);
diff --git a/Assets/Scripts/ServerShared/FactionProduct.cs b/Assets/Scripts/ServerShared/FactionProduct.cs
index 335045452..a0770304a 100644
--- a/Assets/Scripts/ServerShared/FactionProduct.cs
+++ b/Assets/Scripts/ServerShared/FactionProduct.cs
@@ -4,36 +4,30 @@
using System;
using System.Collections.Generic;
+using GameCult.Caching;
using MessagePack;
using Newtonsoft.Json;
// A manufacturer's branded variant of a generic design: its name, its flavor text, and how it builds each of
// the design's roles. Which products exist is what a faction makes, so market segmentation and regional
// progression are authored here rather than as duplicate item entries.
-[DatabaseCategory("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
-public class FactionProductData : DatabaseEntry, INamedEntry
+[CultDocument("aetheria.factionproductdata", "1"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+public class FactionProductData
{
- [Inspectable, JsonProperty("name"), Key(1)]
+ [Inspectable, CultName, JsonProperty("name"), Key(1)]
public string Name;
- [InspectableText, JsonProperty("description"), Key(2)]
+ [Inspectable, CultInspectorTextArea, JsonProperty("description"), Key(2)]
public string Description;
- [InspectableDatabaseLink(typeof(CraftedItemData)), JsonProperty("design"), Key(3)]
- public Guid Design;
+ [Inspectable, JsonProperty("design"), Key(3)]
+ public CultRecordRef Design;
- [InspectableDatabaseLink(typeof(Faction)), JsonProperty("manufacturer"), Key(4)]
- public Guid Manufacturer;
+ [Inspectable, JsonProperty("manufacturer"), Key(4)]
+ public CultRecordRef Manufacturer;
[Inspectable, JsonProperty("roles"), Key(5)]
public List Roles = new List();
-
- [IgnoreMember]
- public string EntryName
- {
- get => Name;
- set => Name = value;
- }
}
// How good this product's part is in one of its design's roles: a pseudo-gaussian distribution whose mean is
diff --git a/Assets/Scripts/ServerShared/Galaxy.cs b/Assets/Scripts/ServerShared/Galaxy.cs
index a103000d8..730daadf0 100644
--- a/Assets/Scripts/ServerShared/Galaxy.cs
+++ b/Assets/Scripts/ServerShared/Galaxy.cs
@@ -1,3 +1,4 @@
+using GameCult.Caching;
using System;
using System.Collections.Generic;
using System.IO;
@@ -29,7 +30,7 @@ public class Galaxy
private Action Log { get; }
public bool IsPrelude { get; }
- private HashSet _containedFactions;
+ private HashSet _containedFactions;
private GalaxyZone[] _exitPath;
private Dictionary _nameGenerators = new Dictionary();
private readonly CultCache _cache;
@@ -51,13 +52,14 @@ public class Galaxy
Log = log;
Background = savedGame.Background;
- Factions = savedGame.Factions.Select(cultCache.Get).ToArray();
+ Factions = savedGame.Factions.Select(faction => cultCache.Get(faction)).ToArray();
for (var i = 0; i < Factions.Length; i++)
{
FactionRelationships[Factions[i]] = savedGame.Relationships[i];
}
- Zones = savedGame.Zones.Select(zone =>
+ var savedZones = savedGame.Zones.Select(zone => cultCache.Get(zone)).ToArray();
+ Zones = savedZones.Select(zone =>
{
return new GalaxyZone
{
@@ -69,9 +71,9 @@ public class Galaxy
foreach (var i in savedGame.DiscoveredZones) DiscoveredZones.Add(Zones[i]);
for (var i = 0; i < Zones.Length; i++)
{
- Zones[i].AdjacentZones = savedGame.Zones[i].AdjacentZones.Select(azi => Zones[azi]).ToList();
- Zones[i].Factions = savedGame.Zones[i].Factions.Select(mi => Factions[mi]).ToArray();
- Zones[i].Owner = savedGame.Zones[i].Owner < 0 ? null : Factions[savedGame.Zones[i].Owner];
+ Zones[i].AdjacentZones = savedZones[i].AdjacentZones.Select(azi => Zones[azi]).ToList();
+ Zones[i].Factions = savedZones[i].Factions.Select(mi => Factions[mi]).ToArray();
+ Zones[i].Owner = savedZones[i].Owner < 0 ? null : Factions[savedZones[i].Owner];
}
HomeZones = savedGame.HomeZones.ToDictionary(
@@ -269,7 +271,7 @@ public class Galaxy
// Choose some megas to have bosses placed based on whether a boss hull is assigned
var bossMegas = Factions
- .Where(m => m.BossHull != Guid.Empty)
+ .Where(m => m.BossHull.IsSet())
.Take(bossCount)
.ToArray();
@@ -335,7 +337,7 @@ public class Galaxy
progressCallback?.Invoke($"Feeding Markov Chains: {i + 1} / {Factions.Length}");
//if(progressCallback!=null) Thread.Sleep(250); // Inserting Delay to make it seem like it's doing more work lmao
var faction = Factions[i];
- _nameGenerators[faction] = new MarkovNameGenerator(ref random, cache.Get(faction.GeonameFile).Names, nameGeneratorSettings);
+ _nameGenerators[faction] = new MarkovNameGenerator(ref random, cache.Get(faction.GeonameFile).Names, nameGeneratorSettings);
}
// Generate zone name using the owner's name generator, otherwise assign catalogue ID
@@ -435,10 +437,10 @@ public class Galaxy
}
}
- public bool ContainsFaction(Guid factionID)
+ public bool ContainsFaction(CultRecordRef faction)
{
- _containedFactions ??= new HashSet(Factions.Select(f => f.ID));
- return _containedFactions.Contains(factionID);
+ _containedFactions ??= new HashSet(Factions.Select(f => _cache.RefOf(f).Key));
+ return _containedFactions.Contains(faction.Key);
}
class DijkstraVertex
diff --git a/Assets/Scripts/UI/InputScreen/InputLayout.cs b/Assets/Scripts/ServerShared/InputLayout.cs
similarity index 91%
rename from Assets/Scripts/UI/InputScreen/InputLayout.cs
rename to Assets/Scripts/ServerShared/InputLayout.cs
index 994d0d148..a688598b2 100644
--- a/Assets/Scripts/UI/InputScreen/InputLayout.cs
+++ b/Assets/Scripts/ServerShared/InputLayout.cs
@@ -1,8 +1,9 @@
using System.Collections.Generic;
-using JsonKnownTypes;using MessagePack;
+using GameCult.Caching;
+using MessagePack;
using Newtonsoft.Json;
-[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+[CultDocument("aetheria.inputlayout", "1"), MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class InputLayout
{
[Key(0), JsonProperty("rows")] public InputLayoutRow[] Rows;
@@ -12,7 +13,7 @@ public class InputLayout
foreach (var row in Rows)
{
if (!(row is InputLayoutKeyRow keyRow)) continue;
-
+
foreach (var column in keyRow.Columns)
{
if (column is InputLayoutBindableKey bindableKey)
@@ -24,8 +25,7 @@ public class InputLayout
}
}
-[JsonConverter(typeof(JsonKnownTypesConverter)),
- MessagePackObject,
+[MessagePackObject,
Union(0, typeof(InputLayoutRowSpacer)),
Union(1, typeof(InputLayoutKeyRow))
]
@@ -43,8 +43,7 @@ public class InputLayoutKeyRow : InputLayoutRow
[Key(0), JsonProperty("columns")] public InputLayoutColumn[] Columns;
}
-[JsonConverter(typeof(JsonKnownTypesConverter)),
- MessagePackObject,
+[MessagePackObject,
Union(0, typeof(InputLayoutColumnSpacer)),
Union(1, typeof(InputLayoutKey)),
Union(2, typeof(InputLayoutBindableKey)),
@@ -82,6 +81,7 @@ public class InputLayoutBindableKey : InputLayoutKey, IBindableButton
}
}
+[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class InputLayoutMultiRowKey : InputLayoutBindableKey
{
[Key(4), JsonProperty("height")] public int Height;
@@ -100,4 +100,4 @@ public class InputLayoutMouseButton : IBindableButton
public interface IBindableButton
{
public string InputSystemPath { get; set; }
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/UI/InputScreen/InputLayout.cs.meta b/Assets/Scripts/ServerShared/InputLayout.cs.meta
similarity index 100%
rename from Assets/Scripts/UI/InputScreen/InputLayout.cs.meta
rename to Assets/Scripts/ServerShared/InputLayout.cs.meta
diff --git a/Assets/Scripts/ServerShared/ItemData.cs b/Assets/Scripts/ServerShared/ItemData.cs
index 208b0d9e8..e2bc01fb2 100644
--- a/Assets/Scripts/ServerShared/ItemData.cs
+++ b/Assets/Scripts/ServerShared/ItemData.cs
@@ -6,7 +6,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
-using JsonKnownTypes;
+using GameCult.Caching;
using MessagePack;
using Newtonsoft.Json;
using CultMath;
@@ -268,17 +268,17 @@ public class Shape
}
-[MessagePackObject, JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter))]
-public abstract class ItemData : DatabaseEntry, INamedEntry
+[JsonObject(MemberSerialization.OptIn)]
+public abstract class ItemData
{
- [Inspectable, JsonProperty("name"), Key(1)]
+ [Inspectable, CultName, JsonProperty("name"), Key(1)]
public string Name;
- [InspectableText, JsonProperty("description"), Key(2)]
+ [Inspectable, CultInspectorTextArea, JsonProperty("description"), Key(2)]
public string Description;
- [InspectableDatabaseLink(typeof(Faction)), JsonProperty("creator"), Key(3)]
- public Guid Manufacturer;
+ [Inspectable, JsonProperty("creator"), Key(3)]
+ public CultRecordRef Manufacturer;
[Inspectable, JsonProperty("mass"), Key(4)]
public float Mass;
@@ -295,16 +295,9 @@ public abstract class ItemData : DatabaseEntry, INamedEntry
[Inspectable, JsonProperty("price"), Key(8)]
public int Price = 0;
-
- [IgnoreMember] public string EntryName
- {
- get => Name;
- set => Name = value;
- }
-
}
-[DatabaseCategory("Items"), Inspectable, MessagePackObject]
+[CultDocument("aetheria.simplecommoditydata", "1"), Inspectable, MessagePackObject]
public class SimpleCommodityData : ItemData
{
// MessagePack keys 6, 7, 8 and 11 belonged to removed resource-distribution fields; do not reuse them.
@@ -316,7 +309,7 @@ public class SimpleCommodityData : ItemData
public SimpleCommodityCategory Category;
}
-[MessagePackObject, JsonObject(MemberSerialization.OptIn), JsonConverter(typeof(JsonKnownTypesConverter))]
+[JsonObject(MemberSerialization.OptIn)]
public abstract class CraftedItemData : ItemData
{
// The named slots this design is assembled from. A stat may read the quality of the part filling one.
@@ -334,17 +327,17 @@ public class ItemRole
public string Name;
}
-[DatabaseCategory("Items"), Inspectable, MessagePackObject]
+[CultDocument("aetheria.compoundcommoditydata", "1"), Inspectable, MessagePackObject]
public class CompoundCommodityData : CraftedItemData
{
- [InspectableDatabaseLink(typeof(PersonalityAttribute)), JsonProperty("demandProfile"), Key(10)]
- public Dictionary DemandProfile = new Dictionary();
+ [Inspectable, CultReference(typeof(PersonalityAttribute), many: true), JsonProperty("demandProfile"), Key(10)]
+ public Dictionary, float> DemandProfile = new Dictionary, float>();
[Inspectable, JsonProperty("category"), Key(11)]
public CompoundCommodityCategory Category;
}
-[DatabaseCategory("Items"), Inspectable, MessagePackObject]
+[CultDocument("aetheria.consumableitemdata", "1"), Inspectable, MessagePackObject]
public class ConsumableItemData : CraftedItemData
{
[Inspectable, JsonProperty("behaviors"), Key(10)]
@@ -356,7 +349,7 @@ public class ConsumableItemData : CraftedItemData
[Inspectable, JsonProperty("duration"), Key(12)]
public float Duration;
- [InspectableTexture, JsonProperty("icon"), Key(13)]
+ [Inspectable, CultInspectorAssetPath, JsonProperty("icon"), Key(13)]
public string Icon;
[Inspectable, JsonProperty("effectiveness"), Key(14)]
@@ -366,7 +359,7 @@ public class ConsumableItemData : CraftedItemData
[JsonObject(MemberSerialization.OptIn)]
public abstract class EquippableItemData : CraftedItemData
{
- [InspectableTexture, JsonProperty("schematic"), Key(10)]
+ [Inspectable, CultInspectorAssetPath, JsonProperty("schematic"), Key(10)]
public string Schematic;
[Inspectable, JsonProperty("behaviors"), Key(11)]
@@ -396,10 +389,10 @@ public abstract class EquippableItemData : CraftedItemData
// [Inspectable, JsonProperty("sfx"), Key(19)]
// public string SoundEffectTrigger;
- [InspectableTexture, JsonProperty("actionIcon"), Key(20)]
+ [Inspectable, CultInspectorAssetPath, JsonProperty("actionIcon"), Key(20)]
public string ActionBarIcon;
- [InspectableSoundBank, JsonProperty("soundBank"), Key(21)]
+ [Inspectable, JsonProperty("soundBank"), Key(21)]
public uint SoundBank;
[Inspectable, JsonProperty("audioStats"), Key(22)]
@@ -446,14 +439,14 @@ public abstract class EquippableItemData : CraftedItemData
[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class AudioStat
{
- [InspectableAudioParameter, JsonProperty("parameter"), Key(0)]
+ [Inspectable, JsonProperty("parameter"), Key(0)]
public uint Parameter;
[Inspectable, JsonProperty("stat"), Key(1)]
public PerformanceStat Stat = new PerformanceStat();
}
-[DatabaseCategory("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+[CultDocument("aetheria.geardata", "1"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class GearData : EquippableItemData
{
[Inspectable, JsonProperty("hardpointType"), Key(23)]
@@ -462,7 +455,7 @@ public class GearData : EquippableItemData
[IgnoreMember] public override HardpointType HardpointType => Hardpoint;
}
-[DatabaseCategory("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+[CultDocument("aetheria.cargobaydata", "1"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class CargoBayData : EquippableItemData
{
[Inspectable, JsonProperty("interiorShape"), Key(24)]
@@ -471,14 +464,14 @@ public class CargoBayData : EquippableItemData
[IgnoreMember] public override HardpointType HardpointType => HardpointType.Tool;
}
-[DatabaseCategory("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+[CultDocument("aetheria.dockingbaydata", "1"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class DockingBayData : CargoBayData
{
[Inspectable, JsonProperty("maxSize"), Key(25)]
public int2 MaxSize;
}
-[DatabaseCategory("Items"), MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+[CultDocument("aetheria.weaponitemdata", "1"), MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class WeaponItemData : GearData
{
[Inspectable, JsonProperty("range"), Key(24)]
@@ -497,13 +490,13 @@ public class WeaponItemData : GearData
public WeaponModifiers WeaponModifiers;
}
-[DatabaseCategory("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+[CultDocument("aetheria.hulldata", "1"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class HullData : EquippableItemData
{
[Inspectable, JsonProperty("hardpoints"), Key(23)]
public List Hardpoints = new List();
- [InspectablePrefab, JsonProperty("prefab"), Key(24)]
+ [Inspectable, CultInspectorAssetPath, JsonProperty("prefab"), Key(24)]
public string Prefab;
[Inspectable, JsonProperty("hullType"), Key(25)]
@@ -541,7 +534,7 @@ public class HullData : EquippableItemData
}
[Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
-public class HardpointData : ITintInspector
+public class HardpointData
{
[Inspectable, JsonProperty("type"), Key(0)] public HardpointType Type;
[Inspectable, JsonProperty("position"), Key(1)] public int2 Position;
@@ -628,10 +621,10 @@ public class PerformanceStat
}
}
-[DatabaseCategory("Items"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
-public class PersonalityAttribute : DatabaseEntry, INamedEntry
+[CultDocument("aetheria.personalityattribute", "1"), Inspectable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+public class PersonalityAttribute
{
- [Inspectable, JsonProperty("name"), Key(1)]
+ [Inspectable, CultName, JsonProperty("name"), Key(1)]
public string Name;
[Inspectable, JsonProperty("low"), Key(2)]
@@ -640,9 +633,4 @@ public class PersonalityAttribute : DatabaseEntry, INamedEntry
[Inspectable, JsonProperty("high"), Key(3)]
public string HighName;
- [IgnoreMember] public string EntryName
- {
- get => Name;
- set => Name = value;
- }
}
\ No newline at end of file
diff --git a/Assets/Scripts/ServerShared/ItemInstance.cs b/Assets/Scripts/ServerShared/ItemInstance.cs
index 71c2dabb7..8021501f1 100644
--- a/Assets/Scripts/ServerShared/ItemInstance.cs
+++ b/Assets/Scripts/ServerShared/ItemInstance.cs
@@ -7,7 +7,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
-using JsonKnownTypes;
+using GameCult.Caching;
//using JM.LinqFaster;
using MessagePack;
using MessagePack.Formatters;
@@ -19,34 +19,28 @@ using static CultMath.math;
Union(1, typeof(CompoundCommodity)),
Union(2, typeof(EquippableItem)),
Union(3, typeof(ConsumableItem)),
- JsonObject(MemberSerialization.OptIn),
- JsonConverter(typeof(JsonKnownTypesConverter))]
+ JsonObject(MemberSerialization.OptIn)]
public abstract class ItemInstance
{
- [JsonProperty("data"), Key(0)] public DatabaseLink Data;
+ [JsonProperty("data"), Key(0)] public CultRecordRef Data;
[JsonProperty("rotation"), Key(1)] public ItemRotation Rotation;
}
[Union(0, typeof(CompoundCommodity)),
Union(1, typeof(EquippableItem)),
Union(2, typeof(ConsumableItem)),
- JsonObject(MemberSerialization.OptIn),
- JsonConverter(typeof(JsonKnownTypesConverter))]
+ JsonObject(MemberSerialization.OptIn)]
public abstract class CraftedItemInstance : ItemInstance
{
// The workmanship of this particular unit, as distinct from the parts that went into it.
[JsonProperty("quality"), Key(2)] public float Quality;
- // Keys 9 and 10, past every key the derived instances use: an item saved before these existed has no
- // element there at all. Keys 3 to 6 sit inside the old range and read back as nil, which a non-nullable
- // Guid cannot deserialize, so nothing new may go there.
-
// How good the part filling each of the design's roles turned out. Empty on items made before roles
// existed; stats then read Quality as they always did.
[JsonProperty("ingredients"), Key(9)] public List Ingredients = new List();
// The manufacturer's branded product this was built as, naming it and carrying its flavor text.
- [JsonProperty("product"), Key(10)] public Guid Product;
+ [JsonProperty("product"), Key(10)] public CultRecordRef Product;
// The quality a stat reads for one of the design's roles. An unnamed role, a design without roles, and an
// item built before roles existed all fall back to this item's own workmanship.
diff --git a/Assets/Scripts/ServerShared/ItemManager.cs b/Assets/Scripts/ServerShared/ItemManager.cs
index be7b8a7fb..51ba2f2be 100644
--- a/Assets/Scripts/ServerShared/ItemManager.cs
+++ b/Assets/Scripts/ServerShared/ItemManager.cs
@@ -1,4 +1,4 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
+/* 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/. */
@@ -6,6 +6,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+using GameCult.Caching;
using CultMath;
using static CultMath.math;
using float2 = CultMath.float2;
@@ -17,36 +18,12 @@ using float4 = CultMath.float4;
public class ItemManager
{
public Random Random = new Random((uint) (DateTime.Now.Ticks%uint.MaxValue));
- // public Dictionary MapLayers = new Dictionary();
- // public SimpleCommodityData[] Resources;
- // public Dictionary> CorporationControllers = new Dictionary>();
- // public Dictionary GalaxyZones;
-
+
private Action _logger;
- private double _time;
- private float _deltaTime;
- private Dictionary _zones = new Dictionary();
-
- // private Guid _forceLoadZone;
-
- // public GlobalData GlobalData => _globalData ?? (_globalData = ItemData.GetAll().FirstOrDefault());
public CultCache ItemData { get; }
public GameplaySettings GameplaySettings { get; }
- // public double Time
- // {
- // get => _time;
- // set
- // {
- // _deltaTime = (float) (value - _time);
- // _time = value;
- // //Log($"GameContext delta time: {_deltaTime}");
- // }
- // }
-
- // private readonly Dictionary Tier = new Dictionary();
-
public ItemManager(CultCache itemData, GameplaySettings settings, Action logger)
{
ItemData = itemData;
@@ -59,34 +36,28 @@ public class ItemManager
_logger(s);
}
- public SimpleCommodityData GetData(SimpleCommodity item)
- {
- return item.Data.Value as SimpleCommodityData;
- }
+ // The one resolution path from an item instance to its design
+ public ItemData GetData(ItemInstance item) => ItemData.Get(item.Data);
- public CraftedItemData GetData(CraftedItemInstance item)
- {
- return item.Data.Value as CraftedItemData;
- }
+ public SimpleCommodityData GetData(SimpleCommodity item) => GetData((ItemInstance) item) as SimpleCommodityData;
- public EquippableItemData GetData(EquippableItem item)
- {
- return item.Data.Value as EquippableItemData;
- }
+ public CraftedItemData GetData(CraftedItemInstance item) => GetData((ItemInstance) item) as CraftedItemData;
+
+ public EquippableItemData GetData(EquippableItem item) => GetData((ItemInstance) item) as EquippableItemData;
public float GetMass(ItemInstance item)
{
return item switch
{
- CraftedItemInstance _ => item.Data.Value.Mass,
- SimpleCommodity commodity => item.Data.Value.Mass * commodity.Quantity,
+ CraftedItemInstance _ => GetData(item).Mass,
+ SimpleCommodity commodity => GetData(item).Mass * commodity.Quantity,
_ => 0
};
}
public float GetThermalMass(ItemInstance item)
{
- var data = item.Data.Value;
+ var data = GetData(item);
return item switch
{
CraftedItemInstance _ => data.Mass * data.SpecificHeat,
@@ -106,7 +77,7 @@ public class ItemManager
pow(item.Quality, GameplaySettings.DurabilityQualityExponent));
var durability = pow(item.Durability / data.Durability, durabilityExponent * stat.DurabilityExponentMultiplier);
var result = lerp(stat.Min, stat.Max, quality * durability);
- if (float.IsNaN(result))
+ if (float.IsNaN(result))
throw new InvalidOperationException($"Performance Stat on {data.Name} evaluating as NaN: input data is invalid! Durability: {item.Durability} / {data.Durability}");
return result;
@@ -124,20 +95,19 @@ public class ItemManager
{
var newItem = new SimpleCommodity
{
- Data = new DatabaseLink{LinkID = item.ID},
+ Data = ItemData.RefOf(item),
Quantity = count
};
- //ItemData.Add(newItem);
return newItem;
}
-
+
_logger("Attempted to create Simple Commodity instance using missing or incorrect item id");
return null;
}
public ItemInstance Instantiate(ItemInstance item)
{
- var data = item.Data.Value;
+ var data = GetData(item);
if(data is CraftedItemData c)
{
var i = CreateInstance(c);
@@ -159,24 +129,23 @@ public class ItemManager
{
return new EquippableItem
{
- Data = new DatabaseLink {LinkID = item.ID}, Quality = quality, Durability = equippableItemData.Durability
+ Data = ItemData.RefOf(item), Quality = quality, Durability = equippableItemData.Durability
};
}
var newCommodity = new CompoundCommodity
{
- Data = new DatabaseLink{LinkID = item.ID},
+ Data = ItemData.RefOf(item),
Quality = quality
};
return newCommodity;
}
-
+
public CraftedItemInstance CreateInstance(CraftedItemData item)
{
if (item == null)
{
throw new NullReferenceException("Attempted to create crafted item instance using missing or incorrect item data!");
- return null;
}
var quality = Random.NextFloat();
@@ -194,7 +163,7 @@ public class ItemManager
// the design's roles filled with a part whose quality is drawn from that manufacturer's distribution for it.
public CraftedItemInstance CreateInstance(FactionProductData product)
{
- var design = ItemData.Get(product.Design);
+ var design = ItemData.Get(product.Design);
if (design == null)
{
_logger($"Product {product.Name} names a design that does not exist!");
@@ -202,7 +171,7 @@ public class ItemManager
}
var instance = CreateInstance(design);
- instance.Product = product.ID;
+ instance.Product = ItemData.RefOf(product);
if (design.Roles == null) return instance;
foreach (var role in design.Roles)
{
@@ -226,4 +195,4 @@ public class ItemManager
int upgrades = (int) ((item.Quality - tier.Quality) / .0499f);
return (tier, upgrades);
}
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/ServerShared/LoadoutGenerator.cs b/Assets/Scripts/ServerShared/LoadoutGenerator.cs
index 473071fa0..571c52d15 100644
--- a/Assets/Scripts/ServerShared/LoadoutGenerator.cs
+++ b/Assets/Scripts/ServerShared/LoadoutGenerator.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using GameCult.Caching;
using CultMath;
using static CultMath.math;
using Random = CultMath.Random;
@@ -57,7 +58,7 @@ public class LoadoutGenerator
return null;
}
var hull = ItemManager.CreateInstance(hullProduct) as EquippableItem;
- var entity = new OrbitalEntity(ItemManager, null, hull, Guid.Empty, ItemManager.GameplaySettings.DefaultEntitySettings);
+ var entity = new OrbitalEntity(ItemManager, null, hull, default, ItemManager.GameplaySettings.DefaultEntitySettings);
entity.Faction = Faction;
OutfitEntity(entity);
return EntitySerializer.Pack(entity) as OrbitalEntityPack;
@@ -72,7 +73,7 @@ public class LoadoutGenerator
return null;
}
var hull = ItemManager.CreateInstance(hullProduct) as EquippableItem;
- var entity = new OrbitalEntity(ItemManager, null, hull, Guid.Empty, ItemManager.GameplaySettings.DefaultEntitySettings);
+ var entity = new OrbitalEntity(ItemManager, null, hull, default, ItemManager.GameplaySettings.DefaultEntitySettings);
entity.Faction = Faction;
// Hardpoint gear goes in first so the docking bay can only take space that gear left free
@@ -123,11 +124,11 @@ public class LoadoutGenerator
public (FactionProductData product, T design)[] RandomProducts(int count, float sizeExponent, Predicate filter = null, bool required = false) where T : EquippableItemData
{
var candidates = ItemManager.ItemData.GetAll()
- .Select(product => (product, design: ItemManager.ItemData.Get(product.Design) as T))
+ .Select(product => (product, design: ItemManager.ItemData.Get(product.Design) as T))
.Where(entry =>
entry.design != null &&
entry.design.Price > 0 &&
- entry.product.Manufacturer != Guid.Empty &&
+ entry.product.Manufacturer.IsSet() &&
(filter?.Invoke(entry.design) ?? true))
.ToArray();
var available = candidates.Where(entry => IsAvailable(entry.product)).ToArray();
@@ -153,12 +154,13 @@ public class LoadoutGenerator
Galaxy.ContainsFaction(product.Manufacturer) && (Faction == null || Faction.Allegiance.ContainsKey(product.Manufacturer));
// Prioritize products from the zone faction and its allies, penalizing distance to the manufacturer's headquarters
- private float ManufacturerPreference(Guid manufacturer)
+ private float ManufacturerPreference(CultRecordRef manufacturer)
{
if (Faction == null || Galaxy == null) return 1;
- var allegiance = manufacturer == Faction.ID ? 1 :
+ var maker = ItemManager.ItemData.Get(manufacturer);
+ var allegiance = maker == Faction ? 1 :
Faction.Allegiance.TryGetValue(manufacturer, out var a) ? a : 0;
- var home = Galaxy.HomeZones.FirstOrDefault(h => h.Key.ID == manufacturer).Value;
+ var home = maker != null && Galaxy.HomeZones.TryGetValue(maker, out var h) ? h : null;
var distance = home != null && Zone?.Distance != null && Zone.Distance.TryGetValue(home, out var d) ? d : 0;
return allegiance / (1 + distance);
}
diff --git a/Assets/Scripts/ServerShared/Narrative/ZoneConstraints.cs b/Assets/Scripts/ServerShared/Narrative/ZoneConstraints.cs
index f707dc399..4c3d52688 100644
--- a/Assets/Scripts/ServerShared/Narrative/ZoneConstraints.cs
+++ b/Assets/Scripts/ServerShared/Narrative/ZoneConstraints.cs
@@ -15,12 +15,12 @@ public interface IFactionResolver
public abstract class ZoneConstraint
{
public bool Flip = false;
-
+
public bool Test(GalaxyZone zone)
{
return Flip ^ TestZone(zone);
}
-
+
protected abstract bool TestZone(GalaxyZone zone);
}
@@ -34,14 +34,14 @@ public class FactionPresenceConstraint : ZoneConstraint
protected override bool TestZone(GalaxyZone zone)
{
- return zone.Factions.Any(f=>f.ID == TargetFaction?.ID);
+ return zone.Factions.Any(f => f == TargetFaction);
}
}
public class FactionOwnerConstraint : ZoneConstraint
{
private Faction TargetFaction { get; }
-
+
public FactionOwnerConstraint(string[] args, IFactionResolver resolver)
{
TargetFaction = resolver.ResolveFaction(args[0]);
@@ -49,7 +49,7 @@ public class FactionOwnerConstraint : ZoneConstraint
protected override bool TestZone(GalaxyZone zone)
{
- return zone.Owner.ID == TargetFaction?.ID;
+ return TargetFaction != null && zone.Owner == TargetFaction;
}
}
@@ -57,7 +57,7 @@ public class DistanceConstraint : ZoneConstraint
{
private GalaxyZone _targetZone;
private Predicate _test;
-
+
public DistanceConstraint(string[] args, IZoneResolver zoneResolver)
{
if (args.Length == 3)
@@ -86,4 +86,4 @@ public class DistanceConstraint : ZoneConstraint
{
return _targetZone != null && _test(zone.Distance[_targetZone]);
}
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/ServerShared/OrbitalEntity.cs b/Assets/Scripts/ServerShared/OrbitalEntity.cs
index 47121eb16..93f055804 100644
--- a/Assets/Scripts/ServerShared/OrbitalEntity.cs
+++ b/Assets/Scripts/ServerShared/OrbitalEntity.cs
@@ -1,35 +1,36 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
+/* 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;
using System.Collections.Generic;
+using GameCult.Caching;
using CultMath;
using static CultMath.math;
using float2 = CultMath.float2;
public class OrbitalEntity : Entity
{
- public Guid OrbitData;
+ public CultRecordKey OrbitData;
public SecurityLevel SecurityLevel;
public float SecurityRadius;
public LocationStory Story;
public bool CanTow;
-
- public OrbitalEntity(ItemManager itemManager, Zone zone, EquippableItem hull, Guid orbit, EntitySettings settings) : base(itemManager, zone, hull, settings)
+
+ public OrbitalEntity(ItemManager itemManager, Zone zone, EquippableItem hull, CultRecordKey orbit, EntitySettings settings) : base(itemManager, zone, hull, settings)
{
OrbitData = orbit;
}
public override void Update(float delta)
{
- if (OrbitData != Guid.Empty)
+ if (OrbitData.IsSet())
{
Position.xz = Zone.GetOrbitPosition(OrbitData);
Velocity = Zone.GetOrbitVelocity(OrbitData);
}
-
+
base.Update(delta);
}
diff --git a/Assets/Scripts/ServerShared/PlayerSettings.cs b/Assets/Scripts/ServerShared/PlayerSettings.cs
index 6280b06b2..0476a1491 100644
--- a/Assets/Scripts/ServerShared/PlayerSettings.cs
+++ b/Assets/Scripts/ServerShared/PlayerSettings.cs
@@ -1,9 +1,10 @@
+using GameCult.Caching;
using System;
using System.Collections.Generic;
using System.Globalization;
using MessagePack;
-[MessagePackObject]
+[CultDocument("aetheria.playersettings", "1"), CultGlobal, MessagePackObject]
public class PlayerSettings
{
[Key(0)] public string Name = "Anonymous";
diff --git a/Assets/Scripts/ServerShared/SavedGame.cs b/Assets/Scripts/ServerShared/SavedGame.cs
index 2f0579fb2..4cd91e52c 100644
--- a/Assets/Scripts/ServerShared/SavedGame.cs
+++ b/Assets/Scripts/ServerShared/SavedGame.cs
@@ -1,34 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using GameCult.Caching;
using MessagePack;
using CultMath;
using static CultMath.math;
-[MessagePackObject]
+[CultDocument("aetheria.savedgame", "1"), CultGlobal, MessagePackObject]
public class SavedGame
{
[Key(0)]
- public SavedZone[] Zones;
-
+ public CultRecordRef[] Zones;
+
[Key(1)]
- public Guid[] Factions;
-
+ public CultRecordRef[] Factions;
+
[Key(2)]
public Dictionary HomeZones;
-
+
[Key(3)]
public Dictionary BossZones;
-
+
[Key(4)]
public int Entrance;
-
+
[Key(5)]
public int Exit;
-
+
[Key(6)]
public int CurrentZone;
-
+
[Key(7)]
public int CurrentZoneEntity;
@@ -46,59 +47,61 @@ public class SavedGame
[Key(12)]
public FactionRelationship[] Relationships;
-
+
public SavedGame() { }
- public SavedGame(Galaxy galaxy, Zone currentZone, Entity currentEntity)
+ // Writes a SavedZone record for every galaxy zone through the cache.
+ public SavedGame(CultCache cache, Galaxy galaxy, Zone currentZone, Entity currentEntity)
{
DiscoveredZones = galaxy.DiscoveredZones.Select(dz => Array.IndexOf(galaxy.Zones, dz)).ToArray();
Background = galaxy.Background;
- Factions = galaxy.HomeZones.Keys.Select(f => f.ID).ToArray();
+ var factions = galaxy.HomeZones.Keys.ToArray();
+ Factions = factions.Select(f => cache.RefOf(f)).ToArray();
Relationships = galaxy.Factions.Select(f => galaxy.FactionRelationships[f]).ToArray();
-
+
HomeZones = galaxy.HomeZones.ToDictionary(
- x => Array.IndexOf(Factions, x.Key.ID),
+ x => Array.IndexOf(factions, x.Key),
x => Array.IndexOf(galaxy.Zones, x.Value));
BossZones = galaxy.BossZones.ToDictionary(
- x => Array.IndexOf(Factions, x.Key.ID),
+ x => Array.IndexOf(factions, x.Key),
x => Array.IndexOf(galaxy.Zones, x.Value));
-
- Zones = galaxy.Zones.Select(zone => new SavedZone
+
+ Zones = galaxy.Zones.Select(zone => cache.Upsert(new SavedZone
{
Name = zone.Name,
Position = zone.Position,
AdjacentZones = zone.AdjacentZones.Select(az=> Array.IndexOf(galaxy.Zones, az)).ToArray(),
- Factions = zone.Factions.Select(f=> Array.IndexOf(Factions, f.ID)).ToArray(),
+ Factions = zone.Factions.Select(f=> Array.IndexOf(factions, f)).ToArray(),
Contents = zone.Contents?.PackZone(),
- Owner = zone.Owner == null ? -1 : Array.IndexOf(Factions, zone.Owner.ID)
- }).ToArray();
+ Owner = zone.Owner == null ? -1 : Array.IndexOf(factions, zone.Owner)
+ })).ToArray();
CurrentZone = Array.FindIndex(galaxy.Zones, zone => zone.Contents == currentZone);
CurrentZoneEntity = currentZone.Entities.IndexOf(currentEntity);
-
+
Entrance = Array.IndexOf(galaxy.Zones, galaxy.Entrance);
Exit = Array.IndexOf(galaxy.Zones, galaxy.Exit);
}
}
-[MessagePackObject]
+[CultDocument("aetheria.savedzone", "1"), MessagePackObject]
public class SavedZone
{
[Key(0)]
public string Name;
-
+
[Key(1)]
public float2 Position;
-
+
[Key(2)]
public int[] AdjacentZones;
-
+
[Key(3)]
public int[] Factions;
-
+
[Key(4)]
public int Owner;
-
+
[Key(5)]
public ZonePack Contents;
}
@@ -115,7 +118,7 @@ public abstract class SavedActionBarBinding
[MessagePackObject]
public class SavedActionBarConsumableBinding : SavedActionBarBinding
{
- [Key(0)] public DatabaseLink Target;
+ [Key(0)] public CultRecordRef Target;
}
[MessagePackObject]
@@ -129,4 +132,4 @@ public class SavedActionBarGearBinding : SavedActionBarBinding
public class SavedActionBarWeaponGroupBinding : SavedActionBarBinding
{
[Key(0)] public int Group;
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/ServerShared/Zone.cs b/Assets/Scripts/ServerShared/Zone.cs
index e9fefd78e..740529a1c 100644
--- a/Assets/Scripts/ServerShared/Zone.cs
+++ b/Assets/Scripts/ServerShared/Zone.cs
@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using GameCult.Caching;
using UniRx;
using CultMath;
using static CultMath.math;
@@ -17,17 +18,15 @@ using Random = CultMath.Random;
public class Zone
{
public Action Log;
- //public HashSet Planets = new HashSet();
public ReactiveCollection Entities = new ReactiveCollection();
- //public Dictionary Orbits = new Dictionary();
- public Dictionary Planets = new Dictionary();
- public Dictionary PlanetInstances = new Dictionary();
+ public Dictionary Planets = new Dictionary();
+ public Dictionary PlanetInstances = new Dictionary();
- public Dictionary Orbits = new Dictionary();
- public Dictionary AsteroidBelts = new Dictionary();
+ public Dictionary Orbits = new Dictionary();
+ public Dictionary AsteroidBelts = new Dictionary();
public PlanetSettings Settings;
-
- private HashSet _updatedOrbits = new HashSet();
+
+ private HashSet _updatedOrbits = new HashSet();
private ItemManager _itemManager;
private double _time;
@@ -35,7 +34,7 @@ public class Zone
public List Agents = new List();
private List BeltUpdates = new List();
-
+
public float Time
{
get => (float) _time;
@@ -53,28 +52,30 @@ public class Zone
_itemManager = itemManager;
Settings = settings;
_random = new Random(Convert.ToUInt32(abs(galaxyZone?.Name.GetHashCode() ?? 1337)));
-
+ var cache = itemManager.ItemData;
+
foreach (var orbit in pack.Orbits)
{
- Orbits.Add(orbit.ID, new Orbit(Settings, orbit));
+ Orbits.Add(orbit.Key, new Orbit(Settings, cache.Get(orbit)));
}
-
- foreach (var planet in pack.Planets)
+
+ foreach (var body in pack.Planets)
{
- Planets.Add(planet.ID, planet);
+ var planet = cache.Get(body);
+ Planets.Add(body.Key, planet);
switch (planet)
{
case AsteroidBeltData belt:
- AsteroidBelts[belt.ID] = new AsteroidBelt(belt);
+ AsteroidBelts[body.Key] = new AsteroidBelt(belt);
break;
case SunData sun:
- PlanetInstances.Add(sun.ID, new Sun(settings, sun, Orbits[planet.Orbit]));
+ PlanetInstances.Add(body.Key, new Sun(settings, sun, Orbits[planet.Orbit.Key]));
break;
case GasGiantData gas:
- PlanetInstances.Add(gas.ID, new GasGiant(settings, gas, Orbits[planet.Orbit]));
+ PlanetInstances.Add(body.Key, new GasGiant(settings, gas, Orbits[planet.Orbit.Key]));
break;
default:
- PlanetInstances.Add(planet.ID, new Planet(settings, planet, Orbits[planet.Orbit]));
+ PlanetInstances.Add(body.Key, new Planet(settings, planet, Orbits[planet.Orbit.Key]));
break;
}
}
@@ -111,15 +112,15 @@ public class Zone
Radius = Pack.Radius,
Mass = Pack.Mass,
Entities = Entities.Select(EntitySerializer.Pack).ToList(),
- Orbits = Orbits.Values.Select(o=>o.Data).ToList(),
- Planets = Planets.Values.ToList(),
+ Orbits = Orbits.Keys.Select(key => new CultRecordRef(key)).ToList(),
+ Planets = Planets.Keys.Select(key => new CultRecordRef(key)).ToList(),
Time = _time
};
}
public void AddOrbit(OrbitData orbit)
{
- Orbits.Add(orbit.ID, new Orbit(Settings, orbit));
+ Orbits.Add(_itemManager.ItemData.RefOf(orbit).Key, new Orbit(Settings, orbit));
}
public void Update(float deltaTime)
@@ -142,25 +143,25 @@ public class Zone
belt.Value.OrbitPosition = belt.Value.NewOrbitPosition;
BeltUpdates.Add(Task.Run(() => UpdateAsteroidTransforms(belt.Key)));
}
-
+
foreach(var agent in Agents)
agent.Update(deltaTime);
-
+
foreach (var entity in Entities.ToArray()) entity.Update(deltaTime);
}
-
+
// Determine orbital position recursively, caching parent positions to avoid repeated calculations
- public float2 GetOrbitPosition(Guid orbitID)
+ public float2 GetOrbitPosition(CultRecordKey orbitID)
{
// Root orbit is fixed at origin
- if(orbitID==Guid.Empty)
+ if(!orbitID.IsSet())
return float2.zero;
if (!Orbits.ContainsKey(orbitID))
{
Log?.Invoke("Requested orbit is not part of this zone!");
return float2.zero;
}
-
+
if (!_updatedOrbits.Contains(orbitID))
{
var orbit = Orbits[orbitID];
@@ -169,7 +170,7 @@ public class Zone
{
var phase = (float) frac(_time / orbit.Period);
pos = OrbitData.Evaluate(frac(phase + orbit.Data.Phase)) * orbit.Data.Distance;
-
+
if (float.IsNaN(pos.x))
{
//_context.Log("Orbit position is NaN, something went very wrong!");
@@ -177,9 +178,9 @@ public class Zone
}
}
- var parentPosition = Orbits[orbitID].Data.Parent == Guid.Empty
- ? Orbits[orbitID].Data.FixedPosition :
- GetOrbitPosition(orbit.Data.Parent);
+ var parentPosition = !Orbits[orbitID].Data.Parent.IsSet()
+ ? Orbits[orbitID].Data.FixedPosition :
+ GetOrbitPosition(orbit.Data.Parent.Key);
Orbits[orbitID].Position = parentPosition + pos;
_updatedOrbits.Add(orbitID);
}
@@ -187,14 +188,14 @@ public class Zone
return Orbits[orbitID].Position;
}
- public float2 GetOrbitVelocity(Guid orbit)
+ public float2 GetOrbitVelocity(CultRecordKey orbit)
{
if (Orbits.ContainsKey(orbit))
return Orbits[orbit].Velocity;
return float2.zero;
}
- public int NearestAsteroid(Guid planetDataID, float2 position)
+ public int NearestAsteroid(CultRecordKey planetDataID, float2 position)
{
var beltData = Planets[planetDataID] as AsteroidBeltData;
@@ -215,16 +216,16 @@ public class Zone
return nearest;
}
- public bool AsteroidExists(Guid planetDataID, int asteroid) => ((AsteroidBeltData) Planets[planetDataID]).Asteroids.Length > asteroid && asteroid >= 0;
+ public bool AsteroidExists(CultRecordKey planetDataID, int asteroid) => ((AsteroidBeltData) Planets[planetDataID]).Asteroids.Length > asteroid && asteroid >= 0;
- private void UpdateAsteroidTransforms(Guid planetDataID)
+ private void UpdateAsteroidTransforms(CultRecordKey planetDataID)
{
var beltData = Planets[planetDataID] as AsteroidBeltData;
-
+
var belt = AsteroidBelts[planetDataID];
- var orbitData = Orbits[beltData.Orbit].Data;
- belt.NewOrbitPosition = GetOrbitPosition(orbitData.Parent);
+ var orbitData = Orbits[beltData.Orbit.Key].Data;
+ belt.NewOrbitPosition = GetOrbitPosition(orbitData.Parent.Key);
for (var i = 0; i < beltData.Asteroids.Length; i++)
{
float size;
@@ -245,7 +246,7 @@ public class Zone
}
}
- public OrbitData CreateOrbit(Guid parent, float2 position)
+ public OrbitData CreateOrbit(CultRecordKey parent, float2 position)
{
var parentPosition = GetOrbitPosition(parent);
var delta = position - parentPosition;
@@ -257,16 +258,15 @@ public class Zone
var orbit = new OrbitData
{
- ID = Guid.NewGuid(),
Distance = distance,
- Parent = parent,
+ Parent = new CultRecordRef(parent),
Phase = storedPhase
};
- Orbits.Add(orbit.ID, new Orbit(Settings, orbit));
+ Orbits.Add(_itemManager.ItemData.Upsert(orbit).Key, new Orbit(Settings, orbit));
return orbit;
}
- public void MineAsteroid(Entity miner, Guid asteroidBelt, int asteroid, float damage, float efficiency, float penetration)
+ public void MineAsteroid(Entity miner, CultRecordKey asteroidBelt, int asteroid, float damage, float efficiency, float penetration)
{
var beltData = Planets[asteroidBelt] as AsteroidBeltData;
var belt = AsteroidBelts[asteroidBelt];
@@ -274,15 +274,15 @@ public class Zone
var size = beltData.Asteroids[asteroid].Size;
var asteroidHitpoints = Settings.AsteroidHitpoints.Evaluate(size);
-
+
if (!belt.Damage.ContainsKey(asteroid))
belt.Damage[asteroid] = 0;
belt.Damage[asteroid] = belt.Damage[asteroid] + damage;
-
+
if (!belt.MiningAccumulator.ContainsKey((miner, asteroid)))
belt.MiningAccumulator[(miner, asteroid)] = 0;
belt.MiningAccumulator[(miner, asteroid)] = belt.MiningAccumulator[(miner, asteroid)] + damage;
-
+
if (belt.Damage[asteroid] > asteroidHitpoints)
{
belt.RespawnTimers[asteroid] = Settings.AsteroidRespawnTime.Evaluate(size);
@@ -309,11 +309,11 @@ public class Zone
public SecurityLevel GetSecurityLevel(float2 pos)
{
if (GalaxyZone.Owner==null) return SecurityLevel.Open;
-
+
var security = SecurityLevel.Open;
foreach (var entity in Entities)
{
- if (entity is OrbitalEntity orbitalEntity && orbitalEntity.SecurityRadius > 1 && entity.Faction.ID == GalaxyZone.Owner.ID)
+ if (entity is OrbitalEntity orbitalEntity && orbitalEntity.SecurityRadius > 1 && entity.Faction == GalaxyZone.Owner)
{
if (orbitalEntity.SecurityLevel > security && length(orbitalEntity.Position.xz - pos) < orbitalEntity.SecurityRadius * Settings.SecureAreaRadiusMultiplier)
security = orbitalEntity.SecurityLevel;
@@ -322,7 +322,7 @@ public class Zone
return security;
}
-
+
public float GetHeight(float2 position)
{
var result = -PowerPulse(length(position)/(Pack.Radius*2), Settings.ZoneDepthExponent) * Settings.ZoneDepth;
diff --git a/Assets/Scripts/ServerShared/ZoneData.cs b/Assets/Scripts/ServerShared/ZoneData.cs
index 72c623ac2..90158fdb4 100644
--- a/Assets/Scripts/ServerShared/ZoneData.cs
+++ b/Assets/Scripts/ServerShared/ZoneData.cs
@@ -1,10 +1,11 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
+/* 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;
using System.Collections.Generic;
+using GameCult.Caching;
using MessagePack;
using Newtonsoft.Json;
using UniRx;
@@ -17,14 +18,14 @@ using float3 = CultMath.float3;
public class ZonePack
{
[JsonProperty("planets"), Key(0)]
- public List Planets = new List();
-
+ public List> Planets = new List>();
+
[JsonProperty("orbits"), Key(1)]
- public List Orbits = new List();
-
+ public List> Orbits = new List>();
+
[JsonProperty("entities"), Key(2)]
public List Entities = new List();
-
+
[JsonProperty("radius"), Key(3)]
public float Radius = 2000;
@@ -33,29 +34,24 @@ public class ZonePack
[JsonProperty("time"), Key(5)]
public double Time;
-
-
+
+
}
-[MessagePackObject,
- JsonObject(MemberSerialization.OptIn),
- Union(0, typeof(PlanetData)),
- Union(1, typeof(AsteroidBeltData)),
- Union(2, typeof(GasGiantData)),
- Union(3, typeof(SunData))]
-public abstract class BodyData : DatabaseEntry, INamedEntry
+[JsonObject(MemberSerialization.OptIn)]
+public abstract class BodyData
{
- [JsonProperty("name"), Key(1)]
+ [CultName, JsonProperty("name"), Key(1)]
public string Name = "";
[JsonProperty("orbit"), Key(2)]
- public Guid Orbit;
+ public CultRecordRef Orbit;
[JsonProperty("mass"), Key(3)]
public float Mass = 0;
- [JsonProperty("resources"), Key(4)]
- public Dictionary Resources = new Dictionary();
+ [CultReference(typeof(SimpleCommodityData), many: true), JsonProperty("resources"), Key(4)]
+ public Dictionary, float> Resources = new Dictionary, float>();
[JsonProperty("bodyRadiusMul")] [Key(5)]
public float BodyRadiusMultiplier = 1;
@@ -68,42 +64,36 @@ public abstract class BodyData : DatabaseEntry, INamedEntry
[JsonProperty("depthExp")] [Key(8)]
public float GravityDepthExponent = 16;
-
- [IgnoreMember] public string EntryName
- {
- get => Name;
- set => Name = value;
- }
}
-[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+[CultDocument("aetheria.planetdata", "1"), MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class PlanetData : BodyData
{
-
+
}
-[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+[CultDocument("aetheria.asteroidbeltdata", "1"), MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class AsteroidBeltData : BodyData
{
[JsonProperty("asteroids"), Key(9)]
public Asteroid[] Asteroids;
}
-[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+[CultDocument("aetheria.gasgiantdata", "1"), MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class GasGiantData : BodyData
{
[JsonProperty("firstOffsetDomainRotationSpeed"), Key(9)]
public float FirstOffsetDomainRotationSpeed = 1;
-
+
[JsonProperty("firstOffsetRotationSpeed"), Key(10)]
public float FirstOffsetRotationSpeed = 1;
-
+
[JsonProperty("secondOffsetDomainRotationSpeed"), Key(11)]
public float SecondOffsetDomainRotationSpeed = 1;
-
+
[JsonProperty("secondOffsetRotationSpeed"), Key(12)]
public float SecondOffsetRotationSpeed = 1;
-
+
[JsonProperty("albedoRotationSpeed"), Key(13)]
public float AlbedoRotationSpeed = 1;
@@ -118,19 +108,20 @@ public class GasGiantData : BodyData
[JsonProperty("depthExp")] [Key(17)]
public float WaveSpeedMultiplier = 8;
-
+
[JsonProperty("materialOverrides"), Key(18)]
public List MaterialOverrides = new List();
-
+
[JsonProperty("colors"), Key(19)]
public float4[] Colors = new float4[0];
}
+[CultDocument("aetheria.sundata", "1"), MessagePackObject, JsonObject(MemberSerialization.OptIn)]
public class SunData : GasGiantData
{
[JsonProperty("lightColor"), Key(20)]
public float3 LightColor = float3.zero;
-
+
[JsonProperty("fogTintColor"), Key(21)]
public float3 FogTintColor = float3.zero;
@@ -143,32 +134,32 @@ public class Asteroid
{
[JsonProperty("distance"), Key(0)]
public float Distance;
-
+
[JsonProperty("phase"), Key(1)]
public float Phase;
-
+
[JsonProperty("size"), Key(2)]
public float Size;
-
+
[JsonProperty("rotationSpeed"), Key(3)]
public float RotationSpeed;
}
-[MessagePackObject, JsonObject(MemberSerialization.OptIn)]
-public class OrbitData : DatabaseEntry
+[CultDocument("aetheria.orbitdata", "1"), MessagePackObject, JsonObject(MemberSerialization.OptIn)]
+public class OrbitData
{
[JsonProperty("parent"), Key(1)]
- public Guid Parent;
+ public CultRecordRef Parent;
[JsonProperty("distance"), Key(2)]
public float Distance;
[JsonProperty("phase"), Key(3)]
public float Phase;
-
+
[JsonProperty("phase"), Key(4)]
public float2 FixedPosition = float2.zero;
-
+
// [JsonProperty("period"), Key(4)]
// public float Period;
@@ -177,4 +168,4 @@ public class OrbitData : DatabaseEntry
phase *= PI * 2;
return new float2(cos(phase), sin(phase));
}
-}
\ No newline at end of file
+}
diff --git a/Assets/Scripts/ServerShared/ZoneGenerator.cs b/Assets/Scripts/ServerShared/ZoneGenerator.cs
index f75526adc..533fe2ebb 100644
--- a/Assets/Scripts/ServerShared/ZoneGenerator.cs
+++ b/Assets/Scripts/ServerShared/ZoneGenerator.cs
@@ -1,4 +1,4 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
+/* 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/. */
@@ -43,6 +43,7 @@ public static class ZoneGenerator
bool isTutorial = false)
{
var pack = new ZonePack();
+ var cache = itemManager.ItemData;
var random = new Random(unchecked((uint) galaxyZone.Name.GetHashCode()) ^ (uint) pcg3d(galaxyZone.Position).x);
@@ -50,7 +51,7 @@ public static class ZoneGenerator
pack.Radius = zoneSettings.ZoneRadius.Evaluate(density);
pack.Mass = zoneSettings.ZoneMass.Evaluate(density);
var targetSubzoneCount = zoneSettings.SubZoneCount.Evaluate(density);
-
+
//Debug.Log($"Generating zone at position {zone.Position} with radius {zoneRadius} and mass {zoneMass}");
var planets = new List();
@@ -58,10 +59,10 @@ public static class ZoneGenerator
{
var zoneBoundary = new Circle(float2.zero, pack.Radius * zoneSettings.ZoneBoundaryRadius);
float boundaryTangentRadius(float2 point) => -zoneBoundary.DistanceTo(point);
-
+
var occupiedAreas = new List();
float tangentRadius(float2 point) => min(boundaryTangentRadius(point), occupiedAreas.Min(circle => circle.DistanceTo(point)));
-
+
var startPosition = random.NextFloat(pack.Radius * .25f, pack.Radius * .5f) * random.NextFloat2Direction();
occupiedAreas.Add(new Circle(startPosition, boundaryTangentRadius(startPosition)));
@@ -91,52 +92,29 @@ public static class ZoneGenerator
}
else
planets.AddRange(GenerateEntities(zoneSettings, ref random, pack.Mass, pack.Radius, float2.zero));
-
- // Create collections to map between zone generator output and database entries
+
+ // Every orbit is a record; parents link to records, so each orbit holds its key before any child names it
var orbitMap = new Dictionary();
- var orbitInverseMap = new Dictionary();
-
- // Create orbit database entries
- pack.Orbits = planets.Select(planet =>
- {
- var data = new OrbitData
+ foreach (var planet in planets)
+ cache.Upsert(orbitMap[planet] = new OrbitData
{
FixedPosition = planet.FixedPosition,
Distance = planet.Distance,
- //Period = planet.Period,
Phase = planet.Phase
- };
- orbitMap[planet] = data;
- orbitInverseMap[data] = planet;
- return data;
- }).ToList();
+ });
+ foreach (var planet in planets.Where(p => p.Parent != null))
+ {
+ orbitMap[planet].Parent = cache.RefOf(orbitMap[planet.Parent]);
+ cache.Upsert(orbitMap[planet]);
+ }
+ pack.Orbits = planets.Select(planet => cache.RefOf(orbitMap[planet])).ToList();
- // Link OrbitData parents to database GUIDs
- foreach (var data in pack.Orbits)
- data.Parent = orbitInverseMap[data].Parent != null
- ? orbitMap[orbitInverseMap[data].Parent].ID
- : Guid.Empty;
-
- // Cache resource densities
- // var resourceMaps = mapLayers.Values
- // .ToDictionary(m => m.ID, m => m.Evaluate(zone.Position, settings.ShapeSettings));
-
pack.Planets = planets.Where(p=>!p.Empty).Select(planet =>
{
- // Dictionary planetResources = new Dictionary();
BodyType bodyType = planet.Belt ? BodyType.Asteroid :
planet.Mass > zoneSettings.SunMass ? BodyType.Sun :
planet.Mass > zoneSettings.GasGiantMass ? BodyType.GasGiant :
planet.Mass > zoneSettings.PlanetMass ? BodyType.Planet : BodyType.Planetoid;
-
- // foreach (var r in resources)
- // {
- // if ((bodyType & r.ResourceBodyType) != 0)
- // {
- // float quantity = ResourceValue(ref random, settings, r, r.ResourceDensity.Aggregate(1f, (m, rdm) => m * resourceMaps[rdm]));
- // if (r.Floor < quantity) planetResources.Add(r.ID, quantity);
- // }
- // }
BodyData planetData;
switch (bodyType)
@@ -159,12 +137,10 @@ public static class ZoneGenerator
}
planetData.Mass = planet.Mass;
- planetData.Orbit = orbitMap[planet].ID;
- // planetData.Resources = planetResources;
- planetData.Name = planetData.ID.ToString().Substring(0, 8);
+ planetData.Orbit = cache.RefOf(orbitMap[planet]);
if (planetData is AsteroidBeltData beltData)
{
- beltData.Asteroids =
+ beltData.Asteroids =
Enumerable.Range(0, (int) zoneSettings.AsteroidCount.Evaluate(beltData.Mass * orbitMap[planet].Distance))
.Select(_ => new Asteroid
{
@@ -197,12 +173,12 @@ public static class ZoneGenerator
float primary = random.NextFloat();
float right = frac(primary + zoneSettings.GasGiantBandColorSeparation);
float left = frac(primary + 1 - zoneSettings.GasGiantBandColorSeparation);
-
+
// Create n time keys from 0 to 1
var bandCount = (int) (zoneSettings.GasGiantBandCount.Evaluate(random.NextFloat()) + .5f);
var times = Enumerable.Range(0, bandCount)
.Select(i => (float) i / (bandCount-1));
-
+
// Each band has a chance of being either the primary or one of the adjacent hues
// Saturation and Value are random with curves applied
gas.Colors = times
@@ -211,7 +187,7 @@ public static class ZoneGenerator
zoneSettings.GasGiantBandSaturation.Evaluate(random.NextFloat()),
zoneSettings.GasGiantBandSaturation.Evaluate(random.NextFloat()))),time))
.ToArray();
-
+
gas.FirstOffsetDomainRotationSpeed = 0;
}
gas.AlbedoRotationSpeed = -3;
@@ -219,7 +195,10 @@ public static class ZoneGenerator
gas.SecondOffsetRotationSpeed = 10;
gas.SecondOffsetDomainRotationSpeed = -25;
}
- return planetData;
+
+ // A body is named for the first eight characters of the key the cache mints for it
+ planetData.Name = cache.Upsert(planetData).Key.Value.Substring(0, 8);
+ return cache.Upsert(planetData);
}).ToList();
var nearestFaction = galaxy.Factions.MinBy(f => galaxy.HomeZones[f].Distance[galaxyZone]);
@@ -253,30 +232,28 @@ public static class ZoneGenerator
{
var lagrangeOrbit = new OrbitData
{
- ID = Guid.NewGuid(),
Parent = baseOrbit.Parent,
Distance = baseOrbit.Distance,
Phase = baseOrbit.Phase + PI / 3 * sign(random.NextFloat() - .5f)
};
- pack.Orbits.Add(lagrangeOrbit);
+ pack.Orbits.Add(cache.Upsert(lagrangeOrbit));
return lagrangeOrbit;
}
void PlaceTurret(OrbitData orbit, LoadoutGenerator loadoutGenerator, int distanceMultiplier)
{
var phase = 20f * distanceMultiplier / orbit.Distance;
-
+
var turretOrbit = new OrbitData
{
- ID = Guid.NewGuid(),
Parent = orbit.Parent,
Distance = orbit.Distance,
Phase = orbit.Phase + phase
};
- pack.Orbits.Add(turretOrbit);
+ pack.Orbits.Add(cache.Upsert(turretOrbit));
var turret = loadoutGenerator.GenerateTurretLoadout();
if (turret == null) return;
- turret.Orbit = turretOrbit.ID;
+ turret.Orbit = cache.RefOf(turretOrbit);
pack.Entities.Add(turret);
}
@@ -301,7 +278,7 @@ public static class ZoneGenerator
itemManager.Log($"Story station for {story.Faction?.Name} could not be generated; its story has nowhere to live!");
continue;
}
- station.Orbit = lagrangeOrbit.ID;
+ station.Orbit = cache.RefOf(lagrangeOrbit);
station.SecurityLevel = story.Security;
station.SecurityRadius = pack.Radius;
station.Story = i;
@@ -318,7 +295,7 @@ public static class ZoneGenerator
var lagrangeOrbit = CreateLagrangeOrbit(orbit);
var station = GetLoadoutGenerator(nearestFaction).GenerateStationLoadout();
if (station == null) continue;
- station.Orbit = lagrangeOrbit.ID;
+ station.Orbit = cache.RefOf(lagrangeOrbit);
station.SecurityLevel = security;
station.SecurityRadius = pack.Radius;
pack.Entities.Add(station);
@@ -336,7 +313,7 @@ public static class ZoneGenerator
return pack;
}
-
+
// static float ResourceValue(ref Random random, ZoneGenerationSettings settings, SimpleCommodityData resource, float density)
// {
// return random.NextPowerDistribution(resource.Minimum, resource.Maximum, resource.Exponent,
@@ -357,20 +334,20 @@ public static class ZoneGenerator
// There is some chance of generating a rosette or binary system
// Probabilities which are fixed for the entire galaxy are in GlobalData, contained in the GameContext
var rosette = random.NextFloat() < settings.RosetteProbability;
-
+
if (rosette)
{
// Create a rosette with a number of vertices between 2 and 9 inclusive
root.ExpandRosette(ref random, (int)(random.NextFloat(1, 5) + random.NextFloat(1, 5)));
-
+
// Create a small number of less massive "captured" planets orbiting past the rosette
root.ExpandSolar(
ref random,
- count: (int)(random.NextFloat(1, 3) * random.NextFloat(1, 2)),
- massMulMin: .6f,
- massMulMax: .8f,
- distMulMin: 1.25f,
- distMulMax: 1.75f,
+ count: (int)(random.NextFloat(1, 3) * random.NextFloat(1, 2)),
+ massMulMin: .6f,
+ massMulMax: .8f,
+ distMulMin: 1.25f,
+ distMulMax: 1.75f,
jupiterJump: 1,
massFraction: .1f);
@@ -381,9 +358,9 @@ public static class ZoneGenerator
// Give each child in the rosette its own mini solar system
p.ExpandSolar(
ref random,
- count: (int) (random.NextFloat(1, 3 * m) + random.NextFloat(1, 3 * m)),
- massMulMin: 0.75f,
- massMulMax: 2.5f,
+ count: (int) (random.NextFloat(1, 3 * m) + random.NextFloat(1, 3 * m)),
+ massMulMin: 0.75f,
+ massMulMax: 2.5f,
distMulMin: 1 + m * .25f,
distMulMax: 1.05f + m * .5f,
jupiterJump: random.NextFloat() * random.NextFloat() * 10 + 1,
@@ -396,9 +373,9 @@ public static class ZoneGenerator
// Create a regular old boring solar system
root.ExpandSolar(
ref random,
- count: random.NextInt(5, 15),
- massMulMin: 0.75f,
- massMulMax: 2.5f,
+ count: random.NextInt(5, 15),
+ massMulMin: 0.75f,
+ massMulMax: 2.5f,
distMulMin: 1.1f,
distMulMax: 1.25f,
jupiterJump: random.NextFloat() * random.NextFloat() * 10 + 1,
@@ -412,13 +389,13 @@ public static class ZoneGenerator
{
// Get all children that are above the satellite creation mass floor and not rosette members
var satelliteCandidates = rosette
- ? root.AllPlanets().Where(p =>
- p != root &&
- p.Parent != root &&
+ ? root.AllPlanets().Where(p =>
+ p != root &&
+ p.Parent != root &&
p.Mass > settings.SatelliteCreationMassFloor &&
!alreadyExpanded.Contains(p))
- : root.AllPlanets().Where(p =>
- p != root &&
+ : root.AllPlanets().Where(p =>
+ p != root &&
p.Mass > settings.SatelliteCreationMassFloor &&
!alreadyExpanded.Contains(p));
@@ -455,7 +432,7 @@ public static class ZoneGenerator
var beltCandidates = rosette
? root.AllPlanets().Where(p => p != root && p.Parent != root && p.Mass < settings.BeltMassCeiling && !binaries.Contains(p) && p.Children.Count == 0)
: root.AllPlanets().Where(p => p != root && p.Mass < settings.BeltMassCeiling && !binaries.Contains(p) && p.Children.Count == 0);
-
+
foreach(var planet in beltCandidates.Reverse())
if (random.NextFloat() < settings.BeltProbability && !planet.Parent.Children.Any(p=>p.Belt))
planet.Belt = true;
@@ -498,29 +475,29 @@ public class GeneratorPlanet
public void ExpandRosette(ref Random random, int vertices)
{
//Debug.Log("Expanding Rosette");
-
+
// Rosette children replace the parent, parent orbital node is left empty
Empty = true;
-
+
// Masses in a rosette alternate, so every sequential pair has the same shared mass
var sharedMass = Mass / vertices * 2;
-
+
// Proportion of the masses of sequential pairs is random, but only for even vertex counts
var proportion = vertices % 2 == 0 ? random.NextFloat(.5f,.95f) : .5f;
-
+
// Place children at a fixed distance in the center of the range
var dist = (ChildDistanceMinimum + ChildDistanceMaximum) / 2;
-
+
// Position of first child
var p0 = new float2(0, dist);
-
+
// Position of second child
var p1 = OrbitData.Evaluate(1.0f / vertices) * dist;
-
+
// Maximum child distance is half the distance to the neighbor minus the neighbor's radius
var p0ChildDist = (distance(p0, p1) * proportion - Settings.PlanetSafetyRadius.Evaluate(sharedMass * (1 - proportion))) * .75f;
var p1ChildDist = (distance(p0, p1) * (1 - proportion) - Settings.PlanetSafetyRadius.Evaluate(sharedMass * proportion)) * .75f;
-
+
for (int i = 0; i < vertices; i++)
{
var child = new GeneratorPlanet
@@ -547,14 +524,14 @@ public class GeneratorPlanet
// Expansion is impossible when child space is full
if (count == 0 || ChildDistanceMaximum < ChildDistanceMinimum)
return;
-
+
var masses = new float[count];
var distances = new float[count];
-
- // Accumulate total mass
+
+ // Accumulate total mass
// Initialize first mass and distance, actual number doesn't matter since total mass will be divided proportionally
float massTotal = distances[0] = masses[0] = 1;
-
+
// Masses and distances multiply from one planet to the next
// Mass typically increases exponentially as you go further out
// jupiterJump is an additional mass multiplier applied after half of the planets
@@ -580,7 +557,7 @@ public class GeneratorPlanet
distances[i] = lerp(ChildDistanceMinimum, ChildDistanceMaximum,
(oldDistances[i] - oldDistances[0]) / (oldDistances[count - 1] - oldDistances[0])) + Settings.PlanetSafetyRadius.Evaluate(masses[i]);
}
-
+
for (var i = 0; i < count; i++)
{
// Only instantiate children above the mass floor
@@ -606,4 +583,4 @@ public class GeneratorPlanet
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 5bb98fe75..da7151646 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -4,6 +4,8 @@
Condition="'$(SkipCultLibRevisionCheck)' != 'true' and '@(ProjectReference->AnyHaveMetadataValue('Identity', '$(CultLibRoot)\packages\cultmath\src\CultMath\CultMath.csproj'))' == 'true'">
+