Skip to content

Commit

Permalink
[#158] Improvements to docked vessel tracking.
Browse files Browse the repository at this point in the history
  • Loading branch information
jrossignol committed Mar 31, 2015
1 parent a0061de commit 36f6a57
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 144 deletions.
1 change: 1 addition & 0 deletions CHANGES.txt
@@ -1,6 +1,7 @@
Contract Configurator 0.7.5
- Possible fix for duration counters resetting (thanks dorin6565 and many others).
- Fix for HasCrew with count > 0 (thanks Yemo).
- Improvements to tracking across docked vessels.
- SpawnPassengers now only spawns passengers on Kerbin (closes EPL exploit).
- Sequence parameter no longer fails if child parameters complete out of order.
- Added hideChildren attribute to contract parameters to hide children.
Expand Down
Binary file modified GameData/ContractConfigurator/CC_RemoteTech.dll
Binary file not shown.
Binary file modified GameData/ContractConfigurator/CC_SCANsat.dll
Binary file not shown.
Binary file modified GameData/ContractConfigurator/ContractConfigurator.dll
Binary file not shown.
134 changes: 3 additions & 131 deletions source/ContractConfigurator/ContractParameter/VesselParameter.cs
Expand Up @@ -388,7 +388,7 @@ protected virtual void OnVesselCreate(Vessel vessel)

// Go through the hashes to try to set the parameters for this vessel
KeyValuePair<ParamStrength, double>? dockedInfo = null;
foreach (uint hash in GetVesselHashes(vessel))
foreach (uint hash in vessel.GetHashes())
{
if (dockedVesselInfo.ContainsKey(hash))
{
Expand Down Expand Up @@ -438,7 +438,7 @@ protected virtual void OnPartJointBreak(PartJoint p)
if (strength == ParamStrength.MEDIUM)
{
strength = null;
foreach (uint hash in GetVesselHashes(p.Parent.vessel))
foreach (uint hash in p.Parent.vessel.GetHashes())
{
if (dockedVesselInfo.ContainsKey(hash))
{
Expand Down Expand Up @@ -472,7 +472,6 @@ protected virtual void OnPartJointBreak(PartJoint p)

protected virtual void OnPartAttach(GameEvents.HostTargetAction<Part, Part> e)
{

if (HighLogic.LoadedScene == GameScenes.EDITOR || e.host.vessel == null || e.target.vessel == null)
{
return;
Expand Down Expand Up @@ -555,7 +554,7 @@ protected virtual void OnPartAttach(GameEvents.HostTargetAction<Part, Part> e)
/// <param name="completionTime">The completion time</param>
private void SaveSubVesselInfo(Vessel vessel, ParamStrength strength, double completionTime)
{
foreach (uint hash in GetVesselHashes(vessel))
foreach (uint hash in vessel.GetHashes())
{
if (!dockedVesselInfo.ContainsKey(hash) ||
dockedVesselInfo[hash].Key < strength)
Expand All @@ -565,133 +564,6 @@ private void SaveSubVesselInfo(Vessel vessel, ParamStrength strength, double com
}
}

/// <summary>
/// Create a hash of the vessel.
/// </summary>
/// <param name="vessel">The vessel to hash</param>
/// <returns>A list of hashes for this vessel</returns>
public static List<uint> GetVesselHashes(Vessel vessel)
{
LoggingUtil.LogVerbose(typeof(VesselParameter), "-> GetVesselHashes(" + vessel.id + ")");

if (vessel.rootPart == null)
{
return new List<uint>();
}

Queue<Part> queue = new Queue<Part>();
Dictionary<Part, int> visited = new Dictionary<Part, int>();
Dictionary<uint, uint> dockedParts = new Dictionary<uint, uint>();
Queue<Part> otherVessel = new Queue<Part>();

// Add the root
queue.Enqueue(vessel.rootPart);
visited[vessel.rootPart] = 1;

// Do a BFS of all parts.
List<uint> hashes = new List<uint>();
uint hash = 0;
while (queue.Count > 0 || otherVessel.Count > 0)
{
bool decoupler = false;

// Start a new ship
if (queue.Count == 0)
{
// Reset our hash
hashes.Add(hash);
hash = 0;

// Find an unhandled part to use as the new vessel
Part px;
while (px = otherVessel.Dequeue()) {
if (visited[px] != 2)
{
queue.Enqueue(px);
break;
}
}
dockedParts.Clear();
continue;
}

Part p = queue.Dequeue();

// Check if this is for a new vessel
if (dockedParts.ContainsKey(p.flightID))
{
otherVessel.Enqueue(p);
continue;
}

// Special handling of certain modules
for (int i = 0; i < p.Modules.Count; i++)
{
PartModule pm = p.Modules.GetModule(i);

// If this is a docking node, track the docked part
if (pm.moduleName == "ModuleDockingNode")
{
ModuleDockingNode dock = (ModuleDockingNode)pm;
if (dock.dockedPartUId != 0)
{
dockedParts[dock.dockedPartUId] = dock.dockedPartUId;
}
}
else if (pm.moduleName == "ModuleDecouple")
{
// Just assume all parts can decouple from this, it's easier and
// effectively the same thing
decoupler = true;

// Parent may be null if this is the root of the stack
if (p.parent != null)
{
dockedParts[p.parent.flightID] = p.parent.flightID;
}

// Add all children as possible new vessels
foreach (Part child in p.children)
{
dockedParts[child.flightID] = child.flightID;
}
}
}

// Go through our child parts
foreach (Part child in p.children)
{
if (!visited.ContainsKey(child))
{
queue.Enqueue(child);
visited[child] = 1;
}
}

// Confirm if parent part has been visited
if (p.parent != null && !visited.ContainsKey(p.parent))
{
queue.Enqueue(p.parent);
visited[p.parent] = 1;
}

// Add this part to the hash
if (!decoupler)
{
hash ^= p.flightID;
}

// We've processed this node
visited[p] = 2;
}

// Add the last hash
hashes.Add(hash);

LoggingUtil.LogVerbose(typeof(VesselParameter), "<- GetVesselHashes = " + hashes);
return hashes;
}

/// <summary>
/// Checks whether the given vessel meets the condition, and completes the contract parameter as necessary.
/// </summary>
Expand Down
Expand Up @@ -110,7 +110,12 @@ protected override string GetTitle()
{
if (ParameterCount == 1)
{
return GetParameter(0).Title;
output = "";
if (trackedVessel != null)
{
output += "Vessel: " + trackedVessel.vesselName + ": ";
}
output += GetParameter(0).Title;
}
}

Expand Down

0 comments on commit 36f6a57

Please sign in to comment.