From 8986575c596cf933ff67195b08804eafaa7f8636 Mon Sep 17 00:00:00 2001 From: hyperion51 Date: Thu, 30 Apr 2020 02:54:31 +0100 Subject: [PATCH] Factory Changes Factory now has the ability to persist its state Added exponents to control speed/quality tradeoff and quality randomness --- .../.idea/contentModel.xml | 1 - Assembly-CSharp.csproj | 1 - .../ServerShared/Behaviors/Behaviors.cs | 7 +- .../ServerShared/Behaviors/FactoryBehavior.cs | 125 +++++++++----- Assets/Scripts/ServerShared/BlueprintData.cs | 20 ++- Assets/Scripts/ServerShared/Entity.cs | 10 +- Assets/Scripts/ServerShared/GameContext.cs | 10 +- Assets/Scripts/ServerShared/ItemInstance.cs | 2 +- Assets/Scripts/ServerShared/Ship.cs | 2 - Assets/Scripts/ServerShared/ZoneGenerator.cs | 90 +++++----- Assets/Scripts/StrategyGameManager.cs | 2 +- Assets/Scripts/ZoneGeneratorTest.cs | 159 ------------------ Assets/Scripts/ZoneGeneratorTest.cs.meta | 11 -- RethinkDB Queries.txt | 8 +- 14 files changed, 174 insertions(+), 274 deletions(-) delete mode 100644 Assets/Scripts/ZoneGeneratorTest.cs delete mode 100644 Assets/Scripts/ZoneGeneratorTest.cs.meta diff --git a/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml b/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml index b9b4754f5..290455063 100644 --- a/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml +++ b/.idea/.idea.Aetheria-Economy/.idea/contentModel.xml @@ -1752,7 +1752,6 @@ - diff --git a/Assembly-CSharp.csproj b/Assembly-CSharp.csproj index 2a94f5290..4448c81c3 100644 --- a/Assembly-CSharp.csproj +++ b/Assembly-CSharp.csproj @@ -918,7 +918,6 @@ - diff --git a/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs b/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs index e6cd4892e..4e78c1b7c 100644 --- a/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs +++ b/Assets/Scripts/ServerShared/Behaviors/Behaviors.cs @@ -32,9 +32,12 @@ public interface IAnalogBehavior : IBehavior public interface IPersistentBehavior// where T : IBehavior { - object Store(); - IBehavior Restore(GameContext context, Entity entity, Gear item, Guid data); + PersistentBehaviorData Store(); + void Restore(PersistentBehaviorData data); } +[Union(0, typeof(FactoryPersistence)), + JsonConverter(typeof(JsonKnownTypesConverter))] +public class PersistentBehaviorData { } [InspectableField, Union(0, typeof(ProjectileWeaponData)), diff --git a/Assets/Scripts/ServerShared/Behaviors/FactoryBehavior.cs b/Assets/Scripts/ServerShared/Behaviors/FactoryBehavior.cs index 61154c85a..53b7e608c 100644 --- a/Assets/Scripts/ServerShared/Behaviors/FactoryBehavior.cs +++ b/Assets/Scripts/ServerShared/Behaviors/FactoryBehavior.cs @@ -5,6 +5,7 @@ using MessagePack; using Newtonsoft.Json; using Unity.Mathematics; using static Unity.Mathematics.math; +using Random = Unity.Mathematics.Random; [MessagePackObject, JsonObject(MemberSerialization.OptIn)] public class FactoryData : IBehaviorData @@ -31,12 +32,13 @@ public class Factory : IBehavior, IPersistentBehavior// private FactoryData _data; - private BlueprintData _blueprint; + private Guid _blueprint; private float _remainingManHours; private bool _retooling; + private bool _producing; private List _reservedStock = new List(); private int _assignedPopulation; - private int _productionQuality; + private float _productionQuality; public Factory(GameContext context, FactoryData data, Entity entity, Gear item) { @@ -52,58 +54,91 @@ public class Factory : IBehavior, IPersistentBehavior// public void Update(float delta) { - if (_retooling || _reservedStock.Count > 0) + var blueprint = Context.Cache.Get(_blueprint); + if (_retooling || _producing) { - _remainingManHours -= delta / 3600 * (_assignedPopulation + _data.AutomationPoints) / _productionQuality; + _remainingManHours -= delta / 3600 * (_assignedPopulation + _data.AutomationPoints) / + pow(lerp(blueprint.QualityFloor, 1, saturate(_productionQuality)), + blueprint.ProductionExponent); } if (_remainingManHours < 0) { if (_retooling) _retooling = false; - else if (_reservedStock.Count > 0) + else if (_producing) { - var blueprintItemData = Context.Cache.Get(_blueprint.Item); + var blueprintItemData = Context.Cache.Get(blueprint.Item); - for (int i = 0; i < _blueprint.Quantity; i++) + if (blueprintItemData is CraftedItemData) { - CraftedItemInstance newItem; - - if (blueprintItemData is EquippableItemData equippableItemData) + for (int i = 0; i < blueprint.Quantity; i++) { - var newGear = new Gear + CraftedItemInstance newItem; + + // Applying exponents to two random numbers and adding them produces a range of interesting probability distributions + var quality = blueprint.Quality * + pow(_productionQuality, blueprint.QualityExponent) * + (pow(Context.Random.NextFloat(), blueprint.RandomExponent) + + pow(Context.Random.NextFloat(), blueprint.RandomExponent)) / 2; + + if (blueprintItemData is EquippableItemData equippableItemData) + { + var newGear = new Gear + { + Context = Context, + Data = blueprintItemData.ID, + ID = Guid.NewGuid(), + Ingredients = _reservedStock.Select(ii=>ii.ID).ToList(), + Quality = quality, + Blueprint = _blueprint + }; + newGear.Durability = Context.Evaluate(equippableItemData.Durability, newGear); + newItem = newGear; + } + else + { + newItem = new CompoundCommodity + { + Context = Context, + Data = blueprintItemData.ID, + ID = Guid.NewGuid(), + Ingredients = _reservedStock.Select(ii=>ii.ID).ToList(), + Quality = quality, + Blueprint = _blueprint + }; + } + Context.Cache.Add(newItem); + Entity.Cargo.Add(newItem); + } + } + else + { + var simpleCommodityData = blueprintItemData as SimpleCommodityData; + var simpleCommodityInstance = Entity.Cargo.FirstOrDefault(i => i.Data == simpleCommodityData.ID) as SimpleCommodity; + if (simpleCommodityInstance == null) + { + simpleCommodityInstance = new SimpleCommodity { Context = Context, - Data = blueprintItemData.ID, + Data = simpleCommodityData.ID, ID = Guid.NewGuid(), - Ingredients = _reservedStock.Select(ii=>ii.ID).ToList(), - Quality = _productionQuality * _blueprint.Quality, - Blueprint = _blueprint + Quantity = blueprint.Quantity }; - newGear.Durability = Context.Evaluate(equippableItemData.Durability, newGear); - newItem = newGear; + Context.Cache.Add(simpleCommodityInstance); + Entity.Cargo.Add(simpleCommodityInstance); } else { - newItem = new CompoundCommodity - { - Context = Context, - Data = blueprintItemData.ID, - ID = Guid.NewGuid(), - Ingredients = _reservedStock.Select(ii=>ii.ID).ToList(), - Quality = _productionQuality * _blueprint.Quality, - Blueprint = _blueprint - }; + simpleCommodityInstance.Quantity += blueprint.Quantity; } - Context.Cache.Add(newItem); - Entity.Cargo.Add(newItem); } Entity.RecalculateMass(); var simpleIngredients = new List(); var compoundIngredients = new List(); var hasAllIngredients = true; - foreach (var kvp in _blueprint.Ingredients) + foreach (var kvp in blueprint.Ingredients) { var itemData = Context.Cache.Get(kvp.Key); if (itemData is SimpleCommodityData) @@ -137,7 +172,7 @@ public class Factory : IBehavior, IPersistentBehavior// } foreach (var simpleCommodity in simpleIngredients) { - var blueprintQuantity = _blueprint.Ingredients + var blueprintQuantity = blueprint.Ingredients .First(ingredient => ingredient.Key == simpleCommodity.ID).Value; if (simpleCommodity.Quantity == blueprintQuantity) { @@ -157,35 +192,49 @@ public class Factory : IBehavior, IPersistentBehavior// _reservedStock.Add(newSimpleCommodity); } } + Entity.RecalculateMass(); + _remainingManHours = blueprint.ProductionTime; + _producing = true; } } } } - public object Store() + public PersistentBehaviorData Store() { return new FactoryPersistence { - Blueprint = _blueprint.ID, + Blueprint = _blueprint, RemainingManHours = _remainingManHours, Retooling = _retooling, - ReservedStock = _reservedStock.Select(i=>i.ID).ToArray() + Producing = _producing, + ReservedStock = _reservedStock.Select(i=>i.ID).ToArray(), + AssignedPopulation = _assignedPopulation, + ProductionQuality = _productionQuality }; } - public IBehavior Restore(GameContext context, Entity entity, Gear item, Guid data) + public void Restore(PersistentBehaviorData data) { - var equippable = item.ItemData; - var behaviorData = (FactoryData) equippable.Behaviors.First(b => b is FactoryData); - return new Factory(context, behaviorData, entity, item); + var factoryPersistence = data as FactoryPersistence; + _blueprint = factoryPersistence.Blueprint; + _remainingManHours = factoryPersistence.RemainingManHours; + _retooling = factoryPersistence.Retooling; + _producing = factoryPersistence.Producing; + _reservedStock = factoryPersistence.ReservedStock.Select(id => Context.Cache.Get(id)).ToList(); + _assignedPopulation = factoryPersistence.AssignedPopulation; + _productionQuality = factoryPersistence.ProductionQuality; } } [MessagePackObject, JsonObject(MemberSerialization.OptIn)] -public class FactoryPersistence +public class FactoryPersistence : PersistentBehaviorData { public Guid Blueprint; public float RemainingManHours; public bool Retooling; + public bool Producing; public Guid[] ReservedStock; + public int AssignedPopulation; + public float ProductionQuality; } \ No newline at end of file diff --git a/Assets/Scripts/ServerShared/BlueprintData.cs b/Assets/Scripts/ServerShared/BlueprintData.cs index 8aa6f0fad..739839138 100644 --- a/Assets/Scripts/ServerShared/BlueprintData.cs +++ b/Assets/Scripts/ServerShared/BlueprintData.cs @@ -27,16 +27,28 @@ public class BlueprintData : DatabaseEntry, INamedEntry [InspectableField, JsonProperty("quality"), Key(6)] public float Quality; - [InspectableField, JsonProperty("statEffects"), Key(7)] + [InspectableField, JsonProperty("qualityExponent"), Key(7)] + public float QualityExponent = 1; + + [InspectableField, JsonProperty("productionExponent"), Key(8)] + public float ProductionExponent = 1; + + [InspectableField, JsonProperty("randomExponent"), Key(9)] + public float RandomExponent = 1; + + [InspectableField, JsonProperty("qualityFloor"), Key(10)] + public float QualityFloor = .25f; + + [InspectableField, JsonProperty("statEffects"), Key(11)] public List StatEffects = new List(); - [InspectableField, JsonProperty("researchTime"), Key(8)] + [InspectableField, JsonProperty("researchTime"), Key(12)] public float ResearchTime; - [InspectableDatabaseLink(typeof(BlueprintData)), JsonProperty("researchDependencies"), Key(9)] + [InspectableDatabaseLink(typeof(BlueprintData)), JsonProperty("researchDependencies"), Key(13)] public List Dependencies = new List(); - [InspectableDatabaseLink(typeof(CraftedItemData)), JsonProperty("factoryItem"), Key(11)] + [InspectableDatabaseLink(typeof(CraftedItemData)), JsonProperty("factoryItem"), Key(14)] public Guid FactoryItem; [IgnoreMember] public string EntryName diff --git a/Assets/Scripts/ServerShared/Entity.cs b/Assets/Scripts/ServerShared/Entity.cs index 8d63329b4..9bed240bb 100644 --- a/Assets/Scripts/ServerShared/Entity.cs +++ b/Assets/Scripts/ServerShared/Entity.cs @@ -33,7 +33,7 @@ public class Entity : DatabaseEntry, IMessagePackSerializationCallbackReceiver [IgnoreMember] public float SpecificHeat { get; private set; } [IgnoreMember] public float Visibility => VisibilitySources.Values.Sum(); - public object[] PersistedBehaviors; + public PersistentBehaviorData[] PersistedBehaviors; public Entity(GameContext context, Gear hull, IEnumerable items, IEnumerable cargo) { @@ -129,6 +129,14 @@ public class Entity : DatabaseEntry, IMessagePackSerializationCallbackReceiver .SelectMany(i => i.ItemData.Behaviors .Select(bd => bd.CreateInstance(Context, this, i))) .OrderBy(b => b.GetType().GetCustomAttribute()?.Order ?? 0).ToList(); + + var index = 0; + foreach (var persistentBehavior in Behaviors + .Where(b => b is IPersistentBehavior) + .Cast()) + { + persistentBehavior.Restore(PersistedBehaviors[index++]); + } Bindings = Behaviors .Where(b => b is IActivatedBehavior) diff --git a/Assets/Scripts/ServerShared/GameContext.cs b/Assets/Scripts/ServerShared/GameContext.cs index f3e8a2053..4bfb491db 100644 --- a/Assets/Scripts/ServerShared/GameContext.cs +++ b/Assets/Scripts/ServerShared/GameContext.cs @@ -3,9 +3,11 @@ using System.Collections; using System.Collections.Generic; using System.Linq; using static Unity.Mathematics.math; +using Random = Unity.Mathematics.Random; public class GameContext { + public Random Random = new Random((uint) (DateTime.Now.Ticks%uint.MaxValue)); public List Agents = new List(); public Dictionary> ZoneContents = new Dictionary>(); public Dictionary MapLayers = new Dictionary(); @@ -197,8 +199,8 @@ public class GameContext // Determine quality of either the item itself or the specific ingredient this stat depends on public float Quality(PerformanceStat stat, Gear item) { - - var activeEffects = item.Blueprint.StatEffects.Where(x => GetAffectedStat(item.Blueprint, x) == stat).ToArray(); + var blueprint = Cache.Get(item.Blueprint); + var activeEffects = blueprint.StatEffects.Where(x => GetAffectedStat(blueprint, x) == stat).ToArray(); float quality; if (!activeEffects.Any()) quality = item.CompoundQuality(); @@ -309,7 +311,7 @@ public class GameContext ID = Guid.NewGuid(), Ingredients = ingredients.Select(i=>i.ID).ToList(), Quality = quality, - Blueprint = blueprint + Blueprint = blueprint.ID }; newGear.Durability = Evaluate(equippableItemData.Durability, newGear); Cache.Add(newGear); @@ -323,7 +325,7 @@ public class GameContext ID = Guid.NewGuid(), Ingredients = ingredients.Select(i=>i.ID).ToList(), Quality = quality, - Blueprint = blueprint + Blueprint = blueprint.ID }; Cache.Add(newCommodity); return newCommodity; diff --git a/Assets/Scripts/ServerShared/ItemInstance.cs b/Assets/Scripts/ServerShared/ItemInstance.cs index dce5754c9..ed236daea 100644 --- a/Assets/Scripts/ServerShared/ItemInstance.cs +++ b/Assets/Scripts/ServerShared/ItemInstance.cs @@ -35,7 +35,7 @@ public abstract class CraftedItemInstance : ItemInstance [JsonProperty("ingredients"), Key(3)] public List Ingredients = new List(); - [JsonProperty("blueprint"), Key(4)] public BlueprintData Blueprint; + [JsonProperty("blueprint"), Key(4)] public Guid Blueprint; } [MessagePackObject, JsonObject(MemberSerialization.OptIn)] diff --git a/Assets/Scripts/ServerShared/Ship.cs b/Assets/Scripts/ServerShared/Ship.cs index 58b1edbe6..0a8656e8f 100644 --- a/Assets/Scripts/ServerShared/Ship.cs +++ b/Assets/Scripts/ServerShared/Ship.cs @@ -10,8 +10,6 @@ using static Unity.Mathematics.math; [MessagePackObject] public class Ship : Entity { - [Key("hull")] - public Gear Hull; [Key("hardpoints")] public List Hardpoints = new List(); diff --git a/Assets/Scripts/ServerShared/ZoneGenerator.cs b/Assets/Scripts/ServerShared/ZoneGenerator.cs index 09844cbd4..e856f815e 100644 --- a/Assets/Scripts/ServerShared/ZoneGenerator.cs +++ b/Assets/Scripts/ServerShared/ZoneGenerator.cs @@ -12,29 +12,29 @@ public class ZoneGenerator { public static void GenerateZone( - GlobalData global, + GameContext context, ZoneData zone, IEnumerable mapLayers, IEnumerable resources, out OrbitData[] orbitData, out PlanetData[] planetsData) { - var zoneRadius = lerp(global.MinimumZoneRadius, - global.MaximumZoneRadius, + var zoneRadius = lerp(context.GlobalData.MinimumZoneRadius, + context.GlobalData.MaximumZoneRadius, mapLayers.First(m => m.Name == "Radius") .Evaluate(zone.Position, - global)); + context.GlobalData)); zone.Radius = zoneRadius; - var zoneMass = lerp(global.MinimumZoneMass, - global.MaximumZoneMass, + var zoneMass = lerp(context.GlobalData.MinimumZoneMass, + context.GlobalData.MaximumZoneMass, mapLayers.First(m => m.Name == "Mass") .Evaluate(zone.Position, - global)); + context.GlobalData)); //Debug.Log($"Generating zone at position {zone.Position} with radius {zoneRadius} and mass {zoneMass}"); - var planets = GenerateEntities(global, zone, zoneMass, zoneRadius); + var planets = GenerateEntities(context, zone, zoneMass, zoneRadius); // Create collections to map between zone generator output and database entries var orbitMap = new Dictionary(); @@ -63,9 +63,7 @@ public class ZoneGenerator : Guid.Empty; // Cache resource densities - var resourceMaps = mapLayers.ToDictionary(m => m.ID, m => m.Evaluate(zone.Position, global)); - - var random = new Random((uint) (DateTime.Now.Ticks%uint.MaxValue)); + var resourceMaps = mapLayers.ToDictionary(m => m.ID, m => m.Evaluate(zone.Position, context.GlobalData)); planetsData = planets.Where(p=>!p.Empty).Select(planet => { @@ -80,15 +78,15 @@ public class ZoneGenerator // Filter resources where the body type matches the current planet .Where(r => ((planet.Belt ? BodyType.Asteroid : - planet.Mass > global.SunMass ? BodyType.Sun : - planet.Mass > global.GasGiantMass ? BodyType.GasGiant : - planet.Mass > global.PlanetMass ? BodyType.Planet : BodyType.Planetoid) & r.ResourceBodyType) != 0) + planet.Mass > context.GlobalData.SunMass ? BodyType.Sun : + planet.Mass > context.GlobalData.GasGiantMass ? BodyType.GasGiant : + planet.Mass > context.GlobalData.PlanetMass ? BodyType.Planet : BodyType.Planetoid) & r.ResourceBodyType) != 0) // NextUnbounded is our extension function containing resource placement formula // Obtain bias variable by multiplying all resource maps together .Select(r => new { resource = r, - quantity = random.NextUnbounded( + quantity = context.Random.NextUnbounded( r.ResourceDensity.Aggregate(1f, (m, rdm) => m * resourceMaps[rdm]), r.ResourceDensityBiasPower) }) @@ -104,23 +102,22 @@ public class ZoneGenerator zone.Orbits = orbitData.Select(od => od.ID).ToList(); } - public static Planet[] GenerateEntities(GlobalData global, ZoneData data, float mass, float radius) + public static Planet[] GenerateEntities(GameContext context, ZoneData data, float mass, float radius) { var random = new Random(); random.InitState(unchecked((uint)data.Name.GetHashCode())); var root = new Planet { - Random = random, - Global = global, + Context = context, Mass = mass, ChildDistanceMaximum = radius * .75f, - ChildDistanceMinimum = global.PlanetRadius(mass) + ChildDistanceMinimum = context.GlobalData.PlanetRadius(mass) }; // 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() < global.RosetteProbability; + var rosette = random.NextFloat() < context.GlobalData.RosetteProbability; if (rosette) { @@ -138,7 +135,7 @@ public class ZoneGenerator massFraction: .1f); var averageChildMass = root.Children.Sum(p => p.Mass) / root.Children.Count; - foreach(var p in root.Children.Where(c=>c.Mass>global.GasGiantMass)) + foreach(var p in root.Children.Where(c=>c.Mass>context.GlobalData.GasGiantMass)) { var m = p.Mass / averageChildMass; // Give each child in the rosette its own mini solar system @@ -169,24 +166,24 @@ public 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 && p.Mass > global.SatelliteCreationMassFloor) - : root.AllPlanets().Where(p => p != root && p.Mass > global.SatelliteCreationMassFloor); + ? root.AllPlanets().Where(p => p != root && p.Parent != root && p.Mass > context.GlobalData.SatelliteCreationMassFloor) + : root.AllPlanets().Where(p => p != root && p.Mass > context.GlobalData.SatelliteCreationMassFloor); var binaries = new List(); foreach (var planet in satelliteCandidates) { // There's a chance of generating satellites for each qualified planet - if (random.NextFloat() < global.SatelliteCreationProbability) + if (random.NextFloat() < context.GlobalData.SatelliteCreationProbability) { // Sometimes the satellite is so massive that it forms a binary system (like Earth!) - if (random.NextFloat() < global.BinaryCreationProbability) + if (random.NextFloat() < context.GlobalData.BinaryCreationProbability) { planet.ExpandRosette(2); binaries.AddRange(planet.Children); } // Otherwise, terrestrial planets get a couple satellites while gas giants get many else planet.ExpandSolar( - count: planet.Mass < global.GasGiantMass ? random.NextInt(1,3) : random.NextInt(4,10), + count: planet.Mass < context.GlobalData.GasGiantMass ? random.NextInt(1,3) : random.NextInt(4,10), massMulMin: .75f, massMulMax: 1.5f, distMulMin: 1.05f, @@ -198,10 +195,10 @@ public class ZoneGenerator // Get all children that are below the belt creation mass floor and not rosette members, also exclude binaries var beltCandidates = rosette - ? root.AllPlanets().Where(p => p != root && p.Parent != root && p.Mass < global.BeltMassCeiling && !binaries.Contains(p)) - : root.AllPlanets().Where(p => p != root && p.Mass < global.BeltMassCeiling && !binaries.Contains(p)); + ? root.AllPlanets().Where(p => p != root && p.Parent != root && p.Mass < context.GlobalData.BeltMassCeiling && !binaries.Contains(p)) + : root.AllPlanets().Where(p => p != root && p.Mass < context.GlobalData.BeltMassCeiling && !binaries.Contains(p)); foreach(var planet in beltCandidates.Reverse()) - if (random.NextFloat() < global.BeltProbability && !planet.Parent.Children.Any(p=>p.Belt)) + if (random.NextFloat() < context.GlobalData.BeltProbability && !planet.Parent.Children.Any(p=>p.Belt)) planet.Belt = true; return root.AllPlanets().ToArray(); @@ -213,8 +210,7 @@ public class ZoneGenerator // Because they were objects we observed to move in the sky instead of remaining fixed like the stars public class Planet { - public Random Random; - public GlobalData Global; + public GameContext Context; public float Distance; public float Phase; public float Mass; @@ -245,7 +241,7 @@ public class Planet 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; + var proportion = vertices % 2 == 0 ? Context.Random.NextFloat(.5f,.95f) : .5f; // Place children at a fixed distance in the center of the range var dist = (ChildDistanceMinimum + ChildDistanceMaximum) / 2; @@ -257,23 +253,22 @@ public class Planet 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 - Global.PlanetRadius(sharedMass * (1 - proportion))) * .75f; - var p1ChildDist = (distance(p0, p1) * (1 - proportion) - Global.PlanetRadius(sharedMass * proportion)) * .75f; + var p0ChildDist = (distance(p0, p1) * proportion - Context.GlobalData.PlanetRadius(sharedMass * (1 - proportion))) * .75f; + var p1ChildDist = (distance(p0, p1) * (1 - proportion) - Context.GlobalData.PlanetRadius(sharedMass * proportion)) * .75f; for (int i = 0; i < vertices; i++) { var child = new Planet { - Random = Random, - Global = Global, + Context = Context, Parent = this, Mass = sharedMass * (i % 2 == 0 ? proportion : 1 - proportion), // Masses alternate Distance = dist, Phase = (float) i / vertices, ChildDistanceMaximum = (i % 2 == 0 ? p0ChildDist : p1ChildDist) }; - child.ChildDistanceMinimum = Global.PlanetRadius(child.Mass) * 2; - child.Period = pow(child.Distance, Global.OrbitPeriodExponent) * Global.OrbitPeriodMultiplier; + child.ChildDistanceMinimum = Context.GlobalData.PlanetRadius(child.Mass) * 2; + child.Period = pow(child.Distance, Context.GlobalData.OrbitPeriodExponent) * Context.GlobalData.OrbitPeriodMultiplier; Children.Add(child); } @@ -300,13 +295,13 @@ public class Planet // jupiterJump is an additional mass multiplier applied after half of the planets for (var i = 1; i < count; i++) { - massTotal += masses[i] = masses[i - 1] * Random.NextFloat(massMulMin, massMulMax) * (count/2==i ? jupiterJump : 1); - distances[i] = distances[i - 1] * Random.NextFloat(distMulMin, distMulMax); + massTotal += masses[i] = masses[i - 1] * Context.Random.NextFloat(massMulMin, massMulMax) * (count/2==i ? jupiterJump : 1); + distances[i] = distances[i - 1] * Context.Random.NextFloat(distMulMin, distMulMax); } // Add some randomness to child masses for (var i = 0; i < masses.Length; i++) - masses[i] *= Random.NextFloat(.1f, 1f); + masses[i] *= Context.Random.NextFloat(.1f, 1f); // Normalize the masses of the children for (var i = 0; i < count; i++) @@ -318,25 +313,24 @@ public class Planet var oldDistances = (float[]) distances.Clone(); for (var i = 0; i < count; i++) distances[i] = lerp(ChildDistanceMinimum, ChildDistanceMaximum, - (oldDistances[i] - oldDistances[0]) / (oldDistances[count - 1] - oldDistances[0])) + Global.PlanetRadius(masses[i]); + (oldDistances[i] - oldDistances[0]) / (oldDistances[count - 1] - oldDistances[0])) + Context.GlobalData.PlanetRadius(masses[i]); } for (var i = 0; i < count; i++) { // Only instantiate children above the mass floor - if (masses[i] > Global.MassFloor) + if (masses[i] > Context.GlobalData.MassFloor) { var child = new Planet { - Random = Random, - Global = Global, + Context = Context, Parent = this, Mass = masses[i], Distance = distances[i], - Phase = Random.NextFloat() + Phase = Context.Random.NextFloat() }; - child.Period = pow(child.Distance, Global.OrbitPeriodExponent) * Global.OrbitPeriodMultiplier; - child.ChildDistanceMinimum = Global.PlanetRadius(child.Mass) * 2; + child.Period = pow(child.Distance, Context.GlobalData.OrbitPeriodExponent) * Context.GlobalData.OrbitPeriodMultiplier; + child.ChildDistanceMinimum = Context.GlobalData.PlanetRadius(child.Mass) * 2; // Maximum child distance of child is the smallest distance to either of its neighbors child.ChildDistanceMaximum = min(i == 0 ? child.Distance - ChildDistanceMinimum : child.Distance - distances[i - 1], i < count - 1 ? distances[i + 1] - child.Distance : float.PositiveInfinity); diff --git a/Assets/Scripts/StrategyGameManager.cs b/Assets/Scripts/StrategyGameManager.cs index 8197bb519..351ac0af8 100644 --- a/Assets/Scripts/StrategyGameManager.cs +++ b/Assets/Scripts/StrategyGameManager.cs @@ -422,7 +422,7 @@ public class StrategyGameManager : MonoBehaviour OrbitData[] orbits; PlanetData[] planets; ZoneGenerator.GenerateZone( - global: _context.GlobalData, + context: _context, zone: zoneData, mapLayers: _context.MapLayers.Values, resources: _cache.GetAll().Where(i=>i.ResourceDensity.Any()), diff --git a/Assets/Scripts/ZoneGeneratorTest.cs b/Assets/Scripts/ZoneGeneratorTest.cs deleted file mode 100644 index c58bd8ffa..000000000 --- a/Assets/Scripts/ZoneGeneratorTest.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using Unity.Mathematics; -using UnityEngine; -using static Unity.Mathematics.math; -using Random = UnityEngine.Random; - -public class ZoneGeneratorTest : MonoBehaviour -{ - public Galaxy Galaxy; - public MeshRenderer ZoneBackground; - public MeshRenderer ZoneBoundary; - public ZoneObject ZoneObjectPrefab; - public ParticleSystem BeltPrefab; - public Texture2D PlanetSprite; - public Texture2D GasGiantSprite; - public Texture2D SunSprite; - public float ZoneSizeScale = .01f; - public float ZoneMassScale = .5f; - public float ZoneMassPower = .33f; - public float ZoneOrbitSpeed = 10; - - private DatabaseCache _cache; - private Dictionary _zoneObjects = new Dictionary(); - private Dictionary _zoneBelts = new Dictionary(); - private List _wormholes = new List(); - private Dictionary _orbitPositions = new Dictionary(); - private GameContext _context; - private Material _boundaryMaterial; - - // Determine orbital position recursively, caching parent positions to avoid repeated calculations - private float2 GetOrbitPosition(Guid orbit) - { - // Root orbit is fixed at center - if(orbit==Guid.Empty) - return Unity.Mathematics.float2.zero; - - if (!_orbitPositions.ContainsKey(orbit)) - { - var orbitData = _cache.Get(orbit); - _orbitPositions[orbit] = GetOrbitPosition(orbitData.Parent) + (orbitData.Period < .01f ? Unity.Mathematics.float2.zero : - OrbitData.Evaluate(Time.time * ZoneOrbitSpeed / -orbitData.Period + orbitData.Phase) * - orbitData.Distance); - } - - var position = _orbitPositions[orbit]; - if (float.IsNaN(position.x)) - { - Debug.Log("Orbit position is NaN, something went very wrong!"); - return Unity.Mathematics.float2.zero; - } - return _orbitPositions[orbit]; - } - - void Start() - { - _cache = new DatabaseCache(); - _context = new GameContext(_cache, Debug.Log); - _boundaryMaterial = ZoneBoundary.material; - } - - void Update() - { - _orbitPositions.Clear(); - foreach (var planet in _zoneObjects) - { - var planetData = _cache.Get(planet.Key); - - planet.Value.transform.position = (Vector2) GetOrbitPosition(planetData.Orbit) * ZoneSizeScale; - } - - foreach (var belt in _zoneBelts) - { - var planetData = _cache.Get(belt.Key); - - belt.Value.transform.position = float3(GetOrbitPosition(_cache.Get(planetData.Orbit).Parent) * ZoneSizeScale, .15f); - } - if (Input.GetKeyDown(KeyCode.Space)) - { - PopulateZone(); - } - } - - void PopulateZone() - { - // Delete all the existing zone contents - foreach (var zoneObject in _zoneObjects.Values) Destroy(zoneObject.gameObject);//zoneObject.GetComponent().ReturnToPool(); - _zoneObjects.Clear(); - foreach (var zoneObject in _wormholes) Destroy(zoneObject.gameObject); //zoneObject.GetComponent().ReturnToPool(); - _wormholes.Clear(); - foreach (var belt in _zoneBelts.Values) Destroy(belt.gameObject); - _zoneBelts.Clear(); - - float2 position; - do - { - position = float2(Random.value, Random.value); - } while (Galaxy.MapData.StarDensity.Evaluate(position, Galaxy.MapData.GlobalData) < .1f); - - var zone = new ZoneData{Context = _context, Name = Guid.NewGuid().ToString(), Position = position}; - OrbitData[] orbits; - PlanetData[] planets; - ZoneGenerator.GenerateZone( - global: Galaxy.MapData.GlobalData, - zone: zone, - mapLayers: Galaxy.MapData.ResourceDensities, - resources: Array.Empty(), - orbitData: out orbits, - planetsData: out planets); - _cache.AddAll(orbits); - _cache.AddAll(planets); - _cache.Add(zone); - - float zoneDepth = 0; - foreach (var planet in planets) - { - if (!planet.Belt) - { - var planetObject = Instantiate(ZoneObjectPrefab, transform); - _zoneObjects[planet.ID] = planetObject; - planetObject.Label.text = planet.Name; - planetObject.GravityMesh.gameObject.SetActive(true); - planetObject.GravityMesh.transform.localScale = - Vector3.one * (pow(planet.Mass, Galaxy.MapData.GlobalData.GravityRadiusExponent) * - Galaxy.MapData.GlobalData.GravityRadiusMultiplier * 2 * ZoneSizeScale); - var depth = pow(planet.Mass, ZoneMassPower) * ZoneMassScale; - if (depth > zoneDepth) - zoneDepth = depth; - planetObject.GravityMesh.material.SetFloat("_Depth", depth); - planetObject.Icon.material.SetTexture("_MainTex", - planet.Mass > Galaxy.MapData.GlobalData.SunMass ? SunSprite : - planet.Mass > Galaxy.MapData.GlobalData.GasGiantMass ? GasGiantSprite : - PlanetSprite); - } - else - { - var beltObject = Instantiate(BeltPrefab, transform); - _zoneBelts[planet.ID] = beltObject; - var orbit = _cache.Get(planet.Orbit); - var beltEmission = beltObject.emission; - beltEmission.rateOverTime = new ParticleSystem.MinMaxCurve(pow(planet.Mass,Galaxy.MapData.GlobalData.BeltMassExponent) / Galaxy.MapData.GlobalData.BeltMassRatio * orbit.Distance); - var beltShape = beltObject.shape; - beltShape.radius = orbit.Distance * ZoneSizeScale; - beltShape.donutRadius = orbit.Distance * ZoneSizeScale / 2; - var beltVelocity = beltObject.velocityOverLifetime; - beltVelocity.orbitalZ = orbit.Distance * ZoneSizeScale / orbit.Period * ZoneOrbitSpeed; - beltObject.Simulate(60); - beltObject.Play(); - } - } - - var zoneRadius = (zone.Radius * ZoneSizeScale * 2); - ZoneBackground.material.SetFloat("_ClipDistance", zoneRadius); - ZoneBackground.material.SetFloat("_HeightRange", zoneDepth + _boundaryMaterial.GetFloat("_Depth")); - ZoneBoundary.transform.localScale = Vector3.one * zoneRadius; - } -} diff --git a/Assets/Scripts/ZoneGeneratorTest.cs.meta b/Assets/Scripts/ZoneGeneratorTest.cs.meta deleted file mode 100644 index 024acfd30..000000000 --- a/Assets/Scripts/ZoneGeneratorTest.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0ae6f9307731b8f469a018c69d95d2ba -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/RethinkDB Queries.txt b/RethinkDB Queries.txt index 364d2e943..74341613c 100644 --- a/RethinkDB Queries.txt +++ b/RethinkDB Queries.txt @@ -6,4 +6,10 @@ r.db('Aetheria').table('Galaxy').filter({$type:'OrbitData'}).delete() r.db('Aetheria').table('Galaxy').filter({$type:'PlanetData'}).delete() Find Unassigned Items -r.db('Aetheria').table('Items').filter({mass:0}).pluck('$type','name') \ No newline at end of file +r.db('Aetheria').table('Items').filter({mass:0}).pluck('$type','name') + +Find Unassigned Blueprints +r.db('Aetheria').table('Items').filter({researchTime:0}).pluck('name') + +Find Unassigned Stats +r.db('Aetheria').table('Items').filter({durabilityStat:{min:0}}).pluck('$type','name') \ No newline at end of file