Skip to content

Commit

Permalink
Add UBIs to all Stock bodies, and rework some code for the IC plugin
Browse files Browse the repository at this point in the history
StollD committed Oct 27, 2018
1 parent b4f265b commit f9a9ef6
Showing 8 changed files with 98 additions and 108 deletions.
49 changes: 33 additions & 16 deletions build/GameData/Kopernicus/Config/System.cfg
100755 → 100644
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ Kopernicus
Body
{
name = Sun
identifier = Squad/Sun
Template
{
name = Sun
@@ -26,9 +27,10 @@ Kopernicus
Body
{
name = Moho
identifier = Squad/Moho
Orbit
{
referenceBody = Sun
referenceBody = Squad/Sun
}
Template
{
@@ -54,9 +56,10 @@ Kopernicus
Body
{
name = Eve
identifier = Squad/Eve
Orbit
{
referenceBody = Sun
referenceBody = Squad/Sun
}
Template
{
@@ -86,9 +89,10 @@ Kopernicus
Body
{
name = Gilly
identifier = Squad/Gilly
Orbit
{
referenceBody = Eve
referenceBody = Squad/Eve
}
Template
{
@@ -114,9 +118,10 @@ Kopernicus
Body
{
name = Kerbin
identifier = Squad/Kerbin
Orbit
{
referenceBody = Sun
referenceBody = Squad/Sun
}
Template
{
@@ -146,9 +151,10 @@ Kopernicus
Body
{
name = Mun
identifier = Squad/Mun
Orbit
{
referenceBody = Kerbin
referenceBody = Squad/Kerbin
}
Template
{
@@ -174,9 +180,10 @@ Kopernicus
Body
{
name = Minmus
identifier = Squad/Minmus
Orbit
{
referenceBody = Kerbin
referenceBody = Squad/Kerbin
}
Template
{
@@ -202,9 +209,10 @@ Kopernicus
Body
{
name = Duna
identifier = Squad/Duna
Orbit
{
referenceBody = Sun
referenceBody = Squad/Sun
}
Template
{
@@ -234,9 +242,10 @@ Kopernicus
Body
{
name = Ike
identifier = Squad/Ike
Orbit
{
referenceBody = Duna
referenceBody = Squad/Duna
}
Template
{
@@ -262,9 +271,10 @@ Kopernicus
Body
{
name = Dres
identifier = Squad/Dres
Orbit
{
referenceBody = Sun
referenceBody = Squad/Sun
}
Template
{
@@ -290,9 +300,10 @@ Kopernicus
Body
{
name = Jool
identifier = Squad/Jool
Orbit
{
referenceBody = Sun
referenceBody = Squad/Sun
}
Template
{
@@ -318,9 +329,10 @@ Kopernicus
Body
{
name = Laythe
identifier = Squad/Laythe
Orbit
{
referenceBody = Jool
referenceBody = Squad/Jool
}
Template
{
@@ -350,9 +362,10 @@ Kopernicus
Body
{
name = Vall
identifier = Squad/Vall
Orbit
{
referenceBody = Jool
referenceBody = Squad/Jool
}
Template
{
@@ -378,9 +391,10 @@ Kopernicus
Body
{
name = Tylo
identifier = Squad/Tylo
Orbit
{
referenceBody = Jool
referenceBody = Squad/Jool
}
Template
{
@@ -406,9 +420,10 @@ Kopernicus
Body
{
name = Bop
identifier = Squad/Bop
Orbit
{
referenceBody = Jool
referenceBody = Squad/Jool
}
Template
{
@@ -434,9 +449,10 @@ Kopernicus
Body
{
name = Pol
identifier = Squad/Pol
Orbit
{
referenceBody = Jool
referenceBody = Squad/Jool
}
Template
{
@@ -462,9 +478,10 @@ Kopernicus
Body
{
name = Eeloo
identifier = Squad/Eeloo
Orbit
{
referenceBody = Sun
referenceBody = Squad/Sun
}
Template
{
46 changes: 12 additions & 34 deletions src/Kopernicus.Components/StorageComponent.cs
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@

using System;
using System.Collections.Generic;
using Kopernicus.Components;
using UnityEngine;
using Object = System.Object;

@@ -34,38 +35,26 @@ namespace Kopernicus
/// A component that stores data in a planet
/// </summary>
[RequireComponent(typeof(CelestialBody))]
public class StorageComponent : MonoBehaviour
public class StorageComponent : SerializableMonoBehaviour
{
/// <summary>
/// The data stored by the component
/// </summary>
private static Dictionary<String, Dictionary<String, System.Object>> data { get; set; }

static StorageComponent()
{
data = new Dictionary<String, Dictionary<String, Object>>();
}
[SerializeField]
private Dictionary<String, System.Object> data = new Dictionary<String, Object>();

private CelestialBody body
{
get { return GetComponent<CelestialBody>(); }
}

void Awake()
{
if (!data.ContainsKey(Unify(body.transform.name)))
data.Add(Unify(body.transform.name), new Dictionary<String, Object>());
}

/// <summary>
/// Gets data from the storage
/// </summary>
public T Get<T>(String id)
{
if (!data.ContainsKey(Unify(body.transform.name)))
data.Add(Unify(body.transform.name), new Dictionary<String, Object>());
if (data[Unify(body.transform.name)].ContainsKey(id))
return (T) data[Unify(body.transform.name)][id];
if (data.ContainsKey(id))
return (T) data[id];
throw new IndexOutOfRangeException();
}

@@ -74,40 +63,29 @@ public T Get<T>(String id)
/// </summary>
public Boolean Has(String id)
{
if (!data.ContainsKey(Unify(body.transform.name)))
data.Add(Unify(body.transform.name), new Dictionary<String, Object>());
return data[Unify(body.transform.name)].ContainsKey(id);
return data.ContainsKey(id);
}

/// <summary>
/// Writes data into the storage
/// </summary>
public void Set<T>(String id, T value)
{
if (!data.ContainsKey(Unify(body.transform.name)))
data.Add(Unify(body.transform.name), new Dictionary<String, Object>());
if (data[Unify(body.transform.name)].ContainsKey(id))
data[Unify(body.transform.name)][id] = value;
if (data.ContainsKey(id))
data[id] = value;
else
data[Unify(body.transform.name)].Add(id, value);
data.Add(id, value);
}

/// <summary>
/// Removes data from the storage
/// </summary>
public void Remove(String id)
{
if (!data.ContainsKey(Unify(body.transform.name)))
data.Add(Unify(body.transform.name), new Dictionary<String, Object>());
if(data[Unify(body.transform.name)].ContainsKey(id))
data[Unify(body.transform.name)].Remove(id);
if(data.ContainsKey(id))
data.Remove(id);
else
throw new IndexOutOfRangeException();
}

private String Unify(String id)
{
return id.Replace("(Clone)", "").Trim();
}
}
}
91 changes: 43 additions & 48 deletions src/Kopernicus/Configuration/Loader.cs
Original file line number Diff line number Diff line change
@@ -47,15 +47,9 @@ public class Loader : IParserEventSubscriber
// Name of the config type which holds the pqs subdivision definitions
public const String presetNodeName = "Preset";

// Currently edited body
public static Body currentBody { get; set; }

// The returned PSystem
public PSystem systemPrefab { get; set; }

// The current instance of the Loader
public static Loader Instance { get; set; }

// The name of the PSystem
[ParserTarget("name")]
public String name
@@ -174,12 +168,6 @@ public List<StringCollectionParser> removeLaunchSites
set { Templates.RemoveLaunchSites = value.SelectMany(v => v.Value).ToList(); }
}

// Instance
public Loader()
{
Instance = this;
}

// Create the new planetary system
void IParserEventSubscriber.Apply(ConfigNode node)
{
@@ -212,35 +200,44 @@ void IParserEventSubscriber.PostApply(ConfigNode node)
HashSet<String> seen = new HashSet<String>();

// Dictionary of bodies generated
Dictionary<String, Body> bodies = new Dictionary<String, Body>();
List<Body> bodies = new List<Body>();

Logger logger = new Logger();

// Load all of the bodies
foreach (ConfigNode bodyNode in node.GetNodes(bodyNodeName))
{
if ( seen.Contains(bodyNode.GetValue("name")) )
// Grab the name of the body
String name = bodyNode.GetValue("name");
if (bodyNode.HasValue("identifier"))
{
name = bodyNode.GetValue("identifier");
}

if ( seen.Contains(name) )
{
Logger.Default.Log("[Kopernicus::PostApply] Skipped duplicate body " + bodyNode.GetValue("name"));
Logger.Default.Log("[Kopernicus::PostApply] Skipped duplicate body " + name);
continue; //next body, please
}
else
{
seen.Add(bodyNode.GetValue("name"));
seen.Add(name);
}

try
{
// Create a logfile for this body
logger.SetFilename(bodyNode.GetValue("name") + ".Body");
logger.SetFilename(name + ".Body");
logger.SetAsActive();

// Attempt to create the body
currentBody = new Body();
Body currentBody = new Body();
Parser.SetState("Kopernicus:currentBody", () => currentBody);
Parser.LoadObjectFromConfigurationNode(currentBody, bodyNode, "Kopernicus"); //logs to active logger
bodies.Add(currentBody.name, currentBody);
bodies.Add(currentBody);
Events.OnLoaderLoadBody.Fire(currentBody, bodyNode);
Logger.Default.Log("[Kopernicus]: Configuration.Loader: Loaded Body: " + currentBody.name);
Parser.ClearState("Kopernicus:currentBody");

// Restore default logger
Logger.Default.SetAsActive();
@@ -250,15 +247,12 @@ void IParserEventSubscriber.PostApply(ConfigNode node)
{
logger.LogException(e);
logger.Close(); //implicit flush
Logger.Default.Log("[Kopernicus]: Configuration.Loader: Failed to load Body: " + bodyNode.GetValue("name") + ": " + e.Message);
throw new Exception("Failed to load Body: " + bodyNode.GetValue("name"));
Logger.Default.Log("[Kopernicus]: Configuration.Loader: Failed to load Body: " + name + ": " + e.Message);
throw new Exception("Failed to load Body: " + name);
}
}
seen.Clear();

// Event
Events.OnLoaderLoadedAllBodies.Fire(this, node);

// Load all of the asteroids
foreach (ConfigNode asteroidNode in node.GetNodes(asteroidNodeName))
{
@@ -332,53 +326,57 @@ void IParserEventSubscriber.PostApply(ConfigNode node)
}

// Register UBIs for all bodies
CelestialBody[] localBodies = bodies.Values.Select(b => b.generatedBody.celestialBody).ToArray();
foreach (KeyValuePair<String, Body> body in bodies)
CelestialBody[] localBodies = bodies.Select(b => b.generatedBody.celestialBody).ToArray();
foreach (Body body in bodies)
{
// Register the primary UBI
if (!String.IsNullOrEmpty(body.Value.identifier))
if (!String.IsNullOrEmpty(body.identifier))
{
UBI.RegisterUBI(body.Value.celestialBody, body.Value.identifier, localBodies: localBodies);
UBI.RegisterUBI(body.celestialBody, body.identifier, localBodies: localBodies);
}

// Register all implemented UBIs
foreach (String ubi in body.Value.implements.SelectMany(u => u.Value).Distinct())
foreach (String ubi in body.implements.SelectMany(u => u.Value).Distinct())
{
if (!String.IsNullOrEmpty(ubi))
{
UBI.RegisterUBI(body.Value.celestialBody, ubi, isAbstract: true, localBodies: localBodies);
UBI.RegisterUBI(body.celestialBody, ubi, isAbstract: true, localBodies: localBodies);
}
}
}

// Event
Events.OnLoaderLoadedAllBodies.Fire(this, node);

// Glue all the orbits together in the defined pattern
foreach (KeyValuePair<String, Body> body in bodies)
foreach (Body body in bodies)
{
// If this body is in orbit around another body
if (body.Value.orbit != null)
if (body.orbit != null)
{
// Convert a UBI reference into a normal one
String referenceBody = UBI.GetName(body.Value.orbit.referenceBody, localBodies: localBodies);
String referenceBody = UBI.GetName(body.orbit.referenceBody, localBodies: localBodies);

// Get the Body object for the reference body
if (!bodies.TryGetValue(referenceBody, out Body parent))
Body parent = bodies.Find(b => b.name == referenceBody);
if (parent == null)
{
throw new Exception("Reference body for \"" + body.Key + "\" could not be found. Missing body name is \"" + body.Value.orbit.referenceBody + "\".");
throw new Exception("Reference body for \"" + (body.identifier ?? body.name) + "\" could not be found. Missing body name is \"" + body.orbit.referenceBody + "\".");
}

// Setup the orbit of the body
parent.generatedBody.children.Add(body.Value.generatedBody);
body.Value.generatedBody.orbitDriver.referenceBody = parent.generatedBody.celestialBody;
body.Value.generatedBody.orbitDriver.orbit.referenceBody = parent.generatedBody.celestialBody;
parent.generatedBody.children.Add(body.generatedBody);
body.generatedBody.orbitDriver.referenceBody = parent.generatedBody.celestialBody;
body.generatedBody.orbitDriver.orbit.referenceBody = parent.generatedBody.celestialBody;
}

// Parent the generated body to the PSystem
body.Value.generatedBody.transform.parent = systemPrefab.transform;
body.generatedBody.transform.parent = systemPrefab.transform;

// Delete ghost space centers
if (!body.Value.generatedBody.celestialBody.isHomeWorld && body.Value.generatedBody.pqsVersion != null)
if (!body.generatedBody.celestialBody.isHomeWorld && body.generatedBody.pqsVersion != null)
{
SpaceCenter[] centers = body.Value.generatedBody.pqsVersion.GetComponentsInChildren<SpaceCenter>(true);
SpaceCenter[] centers = body.generatedBody.pqsVersion.GetComponentsInChildren<SpaceCenter>(true);
if (centers != null)
{
foreach (SpaceCenter c in centers)
@@ -389,14 +387,14 @@ void IParserEventSubscriber.PostApply(ConfigNode node)
}

// Event
Events.OnLoaderFinalizeBody.Fire(body.Value);
Events.OnLoaderFinalizeBody.Fire(body);
}

// Elect root body
systemPrefab.rootBody = bodies.First(p => p.Value.orbit == null).Value.generatedBody;
systemPrefab.rootBody = bodies.First(p => p.orbit == null).generatedBody;

// Try to find a home world
Body home = bodies.Values.FirstOrDefault(p => p.generatedBody.celestialBody.isHomeWorld);
Body home = bodies.FirstOrDefault(p => p.generatedBody.celestialBody.isHomeWorld);
if (home == null)
{
throw new Exception("Homeworld body could not be found.");
@@ -407,12 +405,9 @@ void IParserEventSubscriber.PostApply(ConfigNode node)

// Fix doubled flightGlobals
List<Int32> numbers = new List<Int32>() { 0, 1 };
Int32 index = bodies.Sum(b => b.Value.generatedBody.flightGlobalsIndex);
Int32 index = bodies.Sum(b => b.generatedBody.flightGlobalsIndex);
PatchFGI(ref numbers, ref index, systemPrefab.rootBody);

// We're done
currentBody.generatedBody = null;

// Event
Events.OnLoaderPostApply.Fire(this, node);
}
4 changes: 2 additions & 2 deletions src/Kopernicus/Configuration/Parser/BaseLoader.cs
Original file line number Diff line number Diff line change
@@ -36,13 +36,13 @@ public class BaseLoader
/// Provides an override for the currently edited body
/// </summary>
private PSystemBody currentBody = null;

/// <summary>
/// Singleton of the currently edited body
/// </summary>
protected PSystemBody generatedBody
{
get { return currentBody ?? Loader.currentBody?.generatedBody; }
get { return currentBody ?? (currentBody = Parser.GetState<Body>("Kopernicus:currentBody")?.generatedBody); }
set { currentBody = value; }
}
}
3 changes: 2 additions & 1 deletion src/Kopernicus/Configuration/Parser/BuiltinTypeParsers.cs
Original file line number Diff line number Diff line change
@@ -62,7 +62,8 @@ public PositionParser()
// Convert
public static implicit operator Vector3(PositionParser parser)
{
Double? radius = Loader.currentBody?.generatedBody?.celestialBody?.Radius;
PSystemBody generatedBody = Parser.GetState<Body>("Kopernicus:currentBody")?.generatedBody;
Double? radius = generatedBody?.celestialBody?.Radius;
return Utility.LLAtoECEF(parser.latitude, parser.longitude, parser.altitude, radius > 0 ? (Double)radius : 0);
}
}
5 changes: 2 additions & 3 deletions src/Kopernicus/Configuration/ScaledVersionLoader.cs
Original file line number Diff line number Diff line change
@@ -326,9 +326,8 @@ public ScaledVersionLoader()
// Get the scaled version object
Value = generatedBody.celestialBody;
Value.scaledBody = generatedBody.scaledVersion;
type = new EnumParser<BodyType>(Loader.currentBody.template == null
? BodyType.Atmospheric
: Loader.currentBody.template.type);
Body currentBody = Parser.GetState<Body>("Kopernicus:currentBody");
type = new EnumParser<BodyType>(currentBody.template?.type ?? BodyType.Atmospheric);

// Ensure scaled version at least has a mesh filter and mesh renderer
if (Value.scaledBody.GetComponent<MeshFilter>() == null)
2 changes: 1 addition & 1 deletion src/Kopernicus/Logger.cs
Original file line number Diff line number Diff line change
@@ -151,8 +151,8 @@ public void SetFilename(String LogFileName)
try
{
// Open the log file (overwrite existing logs)
LogFileName = LogFileName.Replace("/", "").Replace("\\", "");
String LogFile = Logger.LogDirectory + LogFileName + ".log";
Directory.CreateDirectory(Path.GetDirectoryName(LogFile));
loggerStream = new StreamWriter(LogFile);

// Write an opening message
6 changes: 3 additions & 3 deletions src/Kopernicus/RuntimeUtility/DiscoverableObjects.cs
Original file line number Diff line number Diff line change
@@ -126,7 +126,7 @@ public void SpawnAsteroid(Asteroid asteroid, UInt32 seed)
// Around
IEnumerable<Location.AroundLoader> arounds = GetProbabilityList(asteroid.location.around, asteroid.location.around.Select(a => a.probability.Value));
Location.AroundLoader around = arounds.ElementAt(Random.Range(0, arounds.Count()));
body = PSystemManager.Instance.localBodies.Find(b => b.name == around.body);
body = UBI.GetBody(around.body);
if (!body) return;
if (around.reached && !ReachedBody(body)) return;
orbit = new Orbit();
@@ -145,7 +145,7 @@ public void SpawnAsteroid(Asteroid asteroid, UInt32 seed)
// Nearby
Location.NearbyLoader[] nearbys = GetProbabilityList(asteroid.location.nearby, asteroid.location.nearby.Select(a => a.probability.Value)).ToArray();
Location.NearbyLoader nearby = nearbys[Random.Range(0, nearbys.Length)];
body = PSystemManager.Instance.localBodies.Find(b => b.name == nearby.body);
body = UBI.GetBody(nearby.body);
if (!body) return;
if (nearby.reached && !ReachedBody(body)) return;
orbit = new Orbit();
@@ -164,7 +164,7 @@ public void SpawnAsteroid(Asteroid asteroid, UInt32 seed)
// Flyby
Location.FlybyLoader[] flybys = GetProbabilityList(asteroid.location.flyby, asteroid.location.flyby.Select(a => a.probability.Value)).ToArray();
Location.FlybyLoader flyby = flybys[Random.Range(0, flybys.Length)];
body = PSystemManager.Instance.localBodies.Find(b => b.name == flyby.body);
body = UBI.GetBody(flyby.body);
if (!body) return;
if (flyby.reached && !ReachedBody(body)) return;
orbit = Orbit.CreateRandomOrbitFlyBy(body, Random.Range(flyby.minDuration, flyby.maxDuration));

0 comments on commit f9a9ef6

Please sign in to comment.