Skip to content

Commit

Permalink
Track vessel orbits using a custom identifier
Browse files Browse the repository at this point in the history
If no identifier (for example a GUID) is given, it falls back to the body name.
  • Loading branch information
StollD committed Oct 11, 2017
1 parent ac6786c commit 26a2a2b
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 19 deletions.
19 changes: 14 additions & 5 deletions src/Kopernicus/Configuration/Body.cs
Expand Up @@ -30,7 +30,7 @@

namespace Kopernicus
{
namespace Configuration
namespace Configuration
{
[RequireConfigType(ConfigType.Node)]
public class Body : IParserEventSubscriber
Expand Down Expand Up @@ -77,15 +77,24 @@ public String cbNameLater
generatedBody.celestialBody.gameObject.GetComponent<NameChanger>().newName = value;
}
}

// Flight globals index of this body - for computing reference id
[ParserTarget("flightGlobalsIndex")]
public NumericParser<Int32> flightGlobalsIndex
public NumericParser<Int32> flightGlobalsIndex
{
get { return generatedBody.flightGlobalsIndex; }
set { generatedBody.flightGlobalsIndex = value.value; }
}

// An identifier that is used for referencing the orbiting body.
// This must be unique!
[ParserTarget("identifier")]
public String identifier
{
get { return generatedBody.Has("identifier") ? generatedBody.Get<String>("identifier") : null; }
set { generatedBody.Set("identifier", value); }
}

// Finalize the orbit of the body?
[ParserTarget("finalizeOrbit")]
public NumericParser<Boolean> finalizeOrbit
Expand Down Expand Up @@ -126,7 +135,7 @@ public NumericParser<Int32> contractWeight
// Wrapper around the settings for the world's scaled version
[ParserTarget("ScaledVersion", allowMerge = true)]
public ScaledVersionLoader scaledVersion { get; set; }

// Wrapper around the settings for the world's atmosphere
[ParserTarget("Atmosphere", allowMerge = true)]
public AtmosphereLoader atmosphere { get; set; }
Expand All @@ -146,7 +155,7 @@ public NumericParser<Int32> contractWeight
// Wrapper around Particle class for editing/loading
[ParserTargetCollection("Particles", nameSignificance = NameSignificance.None, allowMerge = true)]
public List<ParticleLoader> particle = new List<ParticleLoader>();

// Wrapper around the settings for the SpaceCenter
[ParserTarget("SpaceCenter", allowMerge = true)]
public SpaceCenterLoader spaceCenter { get; set; }
Expand Down
40 changes: 26 additions & 14 deletions src/Kopernicus/Configuration/Loader.cs
Expand Up @@ -182,7 +182,7 @@ void IParserEventSubscriber.PostApply(ConfigNode node)
Dictionary<String, Body> bodies = new Dictionary<String, Body>();

// Load all of the bodies
foreach (ConfigNode bodyNode in node.GetNodes(bodyNodeName))
foreach (ConfigNode bodyNode in node.GetNodes(bodyNodeName))
{
// Create a logger for this body
Logger bodyLogger = new Logger(bodyNode.GetValue("name") + ".Body");
Expand All @@ -196,17 +196,17 @@ void IParserEventSubscriber.PostApply(ConfigNode node)
bodies.Add(currentBody.name, currentBody);
Events.OnLoaderLoadBody.Fire(currentBody, bodyNode);
Logger.Default.Log("[Kopernicus]: Configuration.Loader: Loaded Body: " + currentBody.name);
}
catch (Exception e)
}
catch (Exception e)
{
bodyLogger.LogException(e);
Logger.Default.Log("[Kopernicus]: Configuration.Loader: Failed to load Body: " + bodyNode.GetValue("name"));
throw new Exception("Failed to load Body: " + bodyNode.GetValue("name"));
}

// Restore default logger
bodyLogger.Flush ();
Logger.Default.SetAsActive ();
bodyLogger.Flush();
Logger.Default.SetAsActive();
}

// Event
Expand Down Expand Up @@ -240,14 +240,14 @@ void IParserEventSubscriber.PostApply(ConfigNode node)
}

// Glue all the orbits together in the defined pattern
foreach (KeyValuePair<String, Body> body in bodies)
foreach (KeyValuePair<String, Body> body in bodies)
{
// If this body is in orbit around another body
if(body.Value.orbit != null)
if (body.Value.orbit != null)
{
// Get the Body object for the reference body
Body parent = null;
if(!bodies.TryGetValue(body.Value.orbit.referenceBody, out parent))
if (!bodies.TryGetValue(body.Value.orbit.referenceBody, out parent))
{
throw new Exception("Reference body for \"" + body.Key + "\" could not be found. Missing body name is \"" + body.Value.orbit.referenceBody + "\".");
}
Expand All @@ -274,6 +274,12 @@ void IParserEventSubscriber.PostApply(ConfigNode node)
}
}

// Set an unique identifier if there is noone
if (!body.Value.generatedBody.Has("identifier"))
{
body.Value.generatedBody.Set("identifier", body.Value.name);
}

// Event
Events.OnLoaderFinalizeBody.Fire(body.Value);
}
Expand All @@ -289,17 +295,23 @@ void IParserEventSubscriber.PostApply(ConfigNode node)
}

// Sort by distance from parent (discover how this effects local bodies)
RecursivelySortBodies (systemPrefab.rootBody);
RecursivelySortBodies(systemPrefab.rootBody);

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

// Check if all bodies have an unique identifier
if (bodies.Any(b => bodies.Count(body => body.Value.identifier == b.Value.identifier) > 1))
{
throw new InvalidOperationException("Found duplicated body identifiers!");
}

// Main Menu bodies
if (randomMainMenuBodies.Any())
Templates.menuBody = randomMainMenuBodies[new System.Random().Next(0, randomMainMenuBodies.Count)];
Templates.menuBody = randomMainMenuBodies[new System.Random().Next(0, randomMainMenuBodies.Count)];

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

Expand All @@ -308,12 +320,12 @@ void IParserEventSubscriber.PostApply(ConfigNode node)
}

// Sort bodies by distance from parent body
public static void RecursivelySortBodies (PSystemBody body)
public static void RecursivelySortBodies(PSystemBody body)
{
body.children = body.children.OrderBy(b => b.orbitDriver.orbit.semiMajorAxis * (1 + b.orbitDriver.orbit.eccentricity)).ToList();
foreach (PSystemBody child in body.children)
foreach (PSystemBody child in body.children)
{
RecursivelySortBodies (child);
RecursivelySortBodies(child);
}
}

Expand Down
29 changes: 29 additions & 0 deletions src/Kopernicus/RuntimeUtility/RuntimeUtility.cs
Expand Up @@ -98,6 +98,8 @@ void Awake()
foreach (TimeOfDayAnimation anim in Resources.FindObjectsOfTypeAll<TimeOfDayAnimation>())
anim.target = KopernicusStar.GetNearest(FlightGlobals.GetHomeBody()).gameObject.transform;
});
GameEvents.onProtoVesselLoad.Add(TransformBodyReferencesOnLoad);
GameEvents.onProtoVesselSave.Add(TransformBodyReferencesOnSave);

// Update Music Logic
if (MusicLogic.fetch != null && FlightGlobals.fetch != null && FlightGlobals.GetHomeBody() != null)
Expand Down Expand Up @@ -673,6 +675,33 @@ void PatchFI()
ModularFlightIntegrator.RegisterCalculateSunBodyFluxOverride(KopernicusStar.SunBodyFlux);
}

// Transforms body references in the savegames
void TransformBodyReferencesOnLoad(GameEvents.FromToAction<ProtoVessel, ConfigNode> data)
{
// Check if the config node is null
if (data.to == null)
return;
ConfigNode orbit = data.to.GetNode("ORBIT");
String bodyIdent = orbit.GetValue("IDENT");
CelestialBody body = PSystemManager.Instance.localBodies.FirstOrDefault(b => b.Get<String>("identifier") == bodyIdent);
if (body == null)
return;
orbit.SetValue("REF", body.flightGlobalsIndex);
}

// Transforms body references in the savegames
void TransformBodyReferencesOnSave(GameEvents.FromToAction<ProtoVessel, ConfigNode> data)
{
// Save the reference to the real body
if (data.to == null)
return;
ConfigNode orbit = data.to.GetNode("ORBIT");
CelestialBody body = PSystemManager.Instance.localBodies.FirstOrDefault(b => b.flightGlobalsIndex == data.from.orbitSnapShot.ReferenceBodyIndex);
if (body == null)
return;
orbit.AddValue("IDENT", body.Get<String>("identifier"));
}

// Remove the Handlers
void OnDestroy()
{
Expand Down

0 comments on commit 26a2a2b

Please sign in to comment.