Skip to content

Commit 3a669de

Browse files
committed
Enabled manual control for resource transfers
1 parent 1371a1f commit 3a669de

File tree

4 files changed

+212
-152
lines changed

4 files changed

+212
-152
lines changed

src/ProgressiveColonizationSystem/IntervesselResourceTransfer.cs

Lines changed: 126 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4-
using System.Text;
54

65
namespace ProgressiveColonizationSystem
76
{
@@ -42,41 +41,56 @@ public double TransferPercent
4241

4342
public Vessel TargetVessel { get; set; }
4443

45-
public void StartTransfer()
44+
public void StartTransfer(IReadOnlyDictionary<string, TransferDirection> userOverrides)
4645
{
4746
if (IsTransferUnderway)
4847
{
4948
return;
5049
}
5150

52-
if (!TryFindResourceToTransfer(FlightGlobals.ActiveVessel, this.TargetVessel, out Dictionary<string,double> toSend, out Dictionary<string,double> toReceive))
53-
{
54-
return;
55-
}
51+
var transfers = TryFindResourceToTransfer(FlightGlobals.ActiveVessel, this.TargetVessel);
5652

57-
this.sourceVessel = FlightGlobals.ActiveVessel;
58-
this.resourceConverter = new ResourceConverter();
59-
this.thisVesselConversionRecipe = new ConversionRecipe();
60-
this.otherVesselConversionRecipe = new ConversionRecipe();
61-
this.lastTransferTime = transferStartTime = Planetarium.GetUniversalTime();
62-
this.expectedTransferCompleteTime = transferStartTime + transferTimeInSeconds;
63-
this.IsTransferUnderway = true;
64-
this.IsTransferComplete = false;
65-
foreach (string resource in toSend.Keys.Union(toReceive.Keys))
53+
var thisVesselConversionRecipe = new ConversionRecipe();
54+
var otherVesselConversionRecipe = new ConversionRecipe();
55+
56+
bool anythingGoingOn = false;
57+
foreach (var item in transfers)
6658
{
67-
bool isSending;
68-
double amount;
69-
isSending = toSend.TryGetValue(resource, out amount);
70-
if (!isSending)
59+
if (!userOverrides.TryGetValue(item.ResourceName, out var direction))
7160
{
72-
amount = toReceive[resource];
61+
direction = item.SuggestedDirection;
7362
}
7463

75-
double amountPerSecond = amount / transferTimeInSeconds;
76-
(isSending ? thisVesselConversionRecipe.Inputs : thisVesselConversionRecipe.Outputs)
77-
.Add(new ResourceRatio(resource, amountPerSecond, dumpExcess: false));
78-
(isSending ? otherVesselConversionRecipe.Outputs : otherVesselConversionRecipe.Inputs)
79-
.Add(new ResourceRatio(resource, amountPerSecond, dumpExcess: false));
64+
if (direction == TransferDirection.Send)
65+
{
66+
anythingGoingOn = true;
67+
double amountPerSecond = item.MaxCanSend / transferTimeInSeconds;
68+
thisVesselConversionRecipe.Inputs
69+
.Add(new ResourceRatio(item.ResourceName, amountPerSecond, dumpExcess: false));
70+
otherVesselConversionRecipe.Outputs
71+
.Add(new ResourceRatio(item.ResourceName, amountPerSecond, dumpExcess: false));
72+
}
73+
else if (direction == TransferDirection.Receive)
74+
{
75+
anythingGoingOn = true;
76+
double amountPerSecond = item.MaxCanReceive / transferTimeInSeconds;
77+
thisVesselConversionRecipe.Outputs
78+
.Add(new ResourceRatio(item.ResourceName, amountPerSecond, dumpExcess: false));
79+
otherVesselConversionRecipe.Inputs
80+
.Add(new ResourceRatio(item.ResourceName, amountPerSecond, dumpExcess: false));
81+
}
82+
}
83+
84+
if (anythingGoingOn)
85+
{
86+
this.sourceVessel = FlightGlobals.ActiveVessel;
87+
this.resourceConverter = new ResourceConverter();
88+
this.thisVesselConversionRecipe = thisVesselConversionRecipe;
89+
this.otherVesselConversionRecipe = otherVesselConversionRecipe;
90+
this.lastTransferTime = transferStartTime = Planetarium.GetUniversalTime();
91+
this.expectedTransferCompleteTime = transferStartTime + transferTimeInSeconds;
92+
this.IsTransferUnderway = true;
93+
this.IsTransferComplete = false;
8094
}
8195
}
8296

@@ -196,130 +210,120 @@ private static HashSet<string> GetVesselsConsumers(Vessel vessel)
196210
return consumers;
197211
}
198212

199-
private enum SnacksDirection
213+
public class ResourceTransferPossibility
200214
{
201-
Send,
202-
Receive,
203-
Neither,
215+
public ResourceTransferPossibility(string resourceName, TransferDirection suggestedDirection, double maxCanSend, double maxCanRecieve)
216+
{
217+
this.ResourceName = resourceName;
218+
this.SuggestedDirection = suggestedDirection;
219+
this.MaxCanSend = maxCanSend;
220+
this.MaxCanReceive = maxCanRecieve;
221+
}
222+
223+
public string ResourceName { get; }
224+
public TransferDirection SuggestedDirection { get; }
225+
public double MaxCanSend { get; }
226+
public double MaxCanReceive { get; }
204227
}
205228

206-
public static bool TryFindResourceToTransfer(Vessel sourceVessel, Vessel otherVessel, out Dictionary<string, double> toSend, out Dictionary<string, double> toReceive)
229+
public static IReadOnlyList<ResourceTransferPossibility> TryFindResourceToTransfer(Vessel sourceVessel, Vessel otherVessel)
207230
{
208231
SnackConsumption.ResourceQuantities(sourceVessel, 1, out Dictionary<string, double> thisShipCanSupply, out Dictionary<string, double> thisShipCanStore);
209232
SnackConsumption.ResourceQuantities(otherVessel, 1, out Dictionary<string, double> otherShipCanSupply, out Dictionary<string, double> otherShipCanStore);
210233

211-
List<string> couldSend = thisShipCanSupply.Keys.Intersect(otherShipCanStore.Keys).ToList();
212-
List<string> couldTake = otherShipCanSupply.Keys.Intersect(thisShipCanStore.Keys).ToList();
213-
214234
List<PksTieredResourceConverter> otherVesselProducers = otherVessel.FindPartModulesImplementing<PksTieredResourceConverter>();
235+
HashSet<string> thisShipsProducts = GetVesselsProducers(sourceVessel);
236+
HashSet<string> otherShipsProducts = GetVesselsProducers(otherVessel);
237+
HashSet<string> thisShipsConsumption = GetVesselsConsumers(sourceVessel);
238+
HashSet<string> otherShipsConsumption = GetVesselsConsumers(otherVessel);
215239

216-
// Refactor me! Way too much "if other vessel has quality, then send, else if this vessel has that quality, receive."
240+
List<ResourceTransferPossibility> result = new List<ResourceTransferPossibility>();
217241

218-
toSend = new Dictionary<string, double>();
219-
toReceive = new Dictionary<string, double>();
220-
if ((otherVessel.GetCrewCount() == 0 && otherVesselProducers.Count > 0)
221-
|| otherVessel.vesselType == VesselType.Debris)
242+
foreach (string resourceName in thisShipCanStore.Keys.Union(thisShipCanStore.Keys).Union(otherShipCanSupply.Keys).Union(otherShipCanStore.Keys))
222243
{
223-
// The player's trying to abandon the base so we'll take everything and give nothing.
224-
foreach (var otherShipPair in otherShipCanSupply)
244+
double maxCanReceive;
225245
{
226-
string resourceName = otherShipPair.Key;
227-
if (thisShipCanStore.ContainsKey(resourceName))
228-
{
229-
toReceive.Add(resourceName, Math.Min(thisShipCanStore[resourceName], otherShipPair.Value));
230-
}
246+
thisShipCanStore.TryGetValue(resourceName, out double maxCanStore);
247+
otherShipCanSupply.TryGetValue(resourceName, out double maxCanBeSent);
248+
maxCanReceive = Math.Min(maxCanStore, maxCanBeSent);
231249
}
232-
return toReceive.Count > 0;
233-
}
234250

235-
// If other ship has a producer for a resource, take it
236-
// and if this ship has a producer for a resource (and the other doesn't), give it
237-
HashSet<string> thisShipsProducts = GetVesselsProducers(sourceVessel);
238-
HashSet<string> otherShipsProducts = GetVesselsProducers(otherVessel);
239-
foreach (string takeableStuff in otherShipCanSupply.Keys.Union(thisShipCanSupply.Keys))
240-
{
241-
if (otherShipsProducts.Contains(takeableStuff)
242-
&& !thisShipsProducts.Contains(takeableStuff)
243-
&& thisShipCanStore.ContainsKey(takeableStuff)
244-
&& otherShipCanSupply.ContainsKey(takeableStuff))
251+
double maxCanSend;
245252
{
246-
toReceive.Add(takeableStuff, Math.Min(thisShipCanStore[takeableStuff], otherShipCanSupply[takeableStuff]));
253+
otherShipCanStore.TryGetValue(resourceName, out double maxCanStore);
254+
thisShipCanSupply.TryGetValue(resourceName, out double maxCanBeSent);
255+
maxCanSend = Math.Min(maxCanBeSent, maxCanStore);
247256
}
248-
else if (!otherShipsProducts.Contains(takeableStuff)
249-
&& thisShipsProducts.Contains(takeableStuff)
250-
&& otherShipCanStore.ContainsKey(takeableStuff)
251-
&& thisShipCanSupply.ContainsKey(takeableStuff))
257+
258+
if (maxCanReceive == 0 && maxCanSend == 0)
252259
{
253-
toSend.Add(takeableStuff, Math.Min(otherShipCanStore[takeableStuff], thisShipCanSupply[takeableStuff]));
260+
continue;
254261
}
255-
}
256262

257-
// If one ship needs a resource to produce stuff and the other doesn't, but has some in storage, move it.
258-
HashSet<string> thisShipsConsumption = GetVesselsConsumers(sourceVessel);
259-
HashSet<string> otherShipsConsumption = GetVesselsConsumers(otherVessel);
260-
foreach (string resourceName in thisShipsConsumption.Union(otherShipsConsumption))
261-
{
262-
if (otherShipCanSupply.ContainsKey(resourceName)
263-
&& thisShipCanStore.ContainsKey(resourceName)
264-
&& thisShipsConsumption.Contains(resourceName)
265-
&& !otherShipsConsumption.Contains(resourceName))
263+
TransferDirection transferDirection = TransferDirection.Neither;
264+
265+
// if the player seems to have abandoned otherVessel
266+
if ((otherVessel.GetCrewCount() == 0 && otherVesselProducers.Count > 0)
267+
|| otherVessel.vesselType == VesselType.Debris)
268+
{
269+
transferDirection = TransferDirection.Receive;
270+
}
271+
// If other ship has a producer for a resource and we don't
272+
else if (otherShipsProducts.Contains(resourceName)
273+
&& !thisShipsProducts.Contains(resourceName))
266274
{
267-
toReceive.Add(resourceName, Math.Min(thisShipCanStore[resourceName], otherShipCanSupply[resourceName]));
275+
transferDirection = TransferDirection.Receive;
268276
}
269-
else if (thisShipCanSupply.ContainsKey(resourceName)
270-
&& otherShipCanStore.ContainsKey(resourceName)
271-
&& otherShipsConsumption.Contains(resourceName)
277+
// else if the converse...
278+
else if (!otherShipsProducts.Contains(resourceName)
279+
&& thisShipsProducts.Contains(resourceName))
280+
{
281+
transferDirection = TransferDirection.Send;
282+
}
283+
else if (thisShipsConsumption.Contains(resourceName)
284+
&& !otherShipsConsumption.Contains(resourceName))
285+
{
286+
transferDirection = TransferDirection.Receive;
287+
}
288+
else if (otherShipsConsumption.Contains(resourceName)
272289
&& !thisShipsConsumption.Contains(resourceName))
273290
{
274-
toSend.Add(resourceName, Math.Min(otherShipCanStore[resourceName], thisShipCanSupply[resourceName]));
291+
transferDirection = TransferDirection.Send;
292+
}
293+
else if (resourceName == "Snacks-Tier4")
294+
{
295+
if (sourceVessel.vesselType == VesselType.Ship && (otherVessel.vesselType == VesselType.Base || otherVessel.vesselType == VesselType.Rover || otherVessel.vesselType == VesselType.Lander)
296+
|| sourceVessel.vesselType == VesselType.Base && (otherVessel.vesselType == VesselType.Rover || otherVessel.vesselType == VesselType.Lander))
297+
{
298+
transferDirection = TransferDirection.Send;
299+
}
300+
else if (otherVessel.vesselType == VesselType.Ship && (sourceVessel.vesselType == VesselType.Base || sourceVessel.vesselType == VesselType.Rover || sourceVessel.vesselType == VesselType.Lander)
301+
|| otherVessel.vesselType == VesselType.Base && (sourceVessel.vesselType == VesselType.Rover || sourceVessel.vesselType == VesselType.Lander))
302+
{
303+
transferDirection = TransferDirection.Receive;
304+
}
305+
else if (otherVessel.GetCrewCount() > 0 && sourceVessel.GetCrewCount() == 0)
306+
{
307+
transferDirection = TransferDirection.Send;
308+
}
309+
else if (otherVessel.GetCrewCount() == 0 && sourceVessel.GetCrewCount() > 0)
310+
{
311+
transferDirection = TransferDirection.Receive;
312+
}
275313
}
276-
}
277-
278-
SnacksDirection snackDirectionBasedOnVesselType;
279-
if (sourceVessel.vesselType == VesselType.Ship && (otherVessel.vesselType == VesselType.Base || otherVessel.vesselType == VesselType.Rover || otherVessel.vesselType == VesselType.Lander)
280-
|| sourceVessel.vesselType == VesselType.Base && (otherVessel.vesselType == VesselType.Rover || otherVessel.vesselType == VesselType.Lander))
281-
{
282-
snackDirectionBasedOnVesselType = SnacksDirection.Send;
283-
}
284-
else if (otherVessel.vesselType == VesselType.Ship && (sourceVessel.vesselType == VesselType.Base || sourceVessel.vesselType == VesselType.Rover || sourceVessel.vesselType == VesselType.Lander)
285-
|| otherVessel.vesselType == VesselType.Base && (sourceVessel.vesselType == VesselType.Rover || sourceVessel.vesselType == VesselType.Lander))
286-
{
287-
snackDirectionBasedOnVesselType = SnacksDirection.Receive;
288-
}
289-
else if (otherVessel.GetCrewCount() > 0 && sourceVessel.GetCrewCount() == 0)
290-
{
291-
snackDirectionBasedOnVesselType = SnacksDirection.Send;
292-
}
293-
else if (otherVessel.GetCrewCount() == 0 && sourceVessel.GetCrewCount() > 0)
294-
{
295-
snackDirectionBasedOnVesselType = SnacksDirection.Receive;
296-
}
297-
else
298-
{
299-
snackDirectionBasedOnVesselType = SnacksDirection.Neither;
300-
}
301314

302-
// Send snacks?
303-
if (otherShipCanStore.ContainsKey("Snacks-Tier4")
304-
&& thisShipCanSupply.ContainsKey("Snacks-Tier4")
305-
&& (thisShipsProducts.Contains("Snacks-Tier4") // Always send if we produce it
306-
|| (!otherShipsProducts.Contains("Snacks-Tier4") // Don't send if the other guy produces
307-
&& snackDirectionBasedOnVesselType == SnacksDirection.Send)))
308-
{
309-
toReceive.Remove("Snacks-Tier4");
310-
toSend["Snacks-Tier4"] = Math.Min(thisShipCanSupply["Snacks-Tier4"], otherShipCanStore["Snacks-Tier4"]);
311-
}
312-
else if (thisShipCanStore.ContainsKey("Snacks-Tier4")
313-
&& otherShipCanSupply.ContainsKey("Snacks-Tier4")
314-
&& (otherShipsProducts.Contains("Snacks-Tier4") // Always take if the other guy produces
315-
|| (!thisShipsProducts.Contains("Snacks-Tier4") // Don't take if we produce it
316-
&& snackDirectionBasedOnVesselType == SnacksDirection.Receive)))
317-
{
318-
toSend.Remove("Snacks-Tier4");
319-
toReceive["Snacks-Tier4"] = Math.Min(thisShipCanStore["Snacks-Tier4"], otherShipCanSupply["Snacks-Tier4"]);
315+
if (transferDirection == TransferDirection.Send && maxCanSend == 0)
316+
{
317+
transferDirection = TransferDirection.Neither;
318+
}
319+
else if (transferDirection == TransferDirection.Receive && maxCanReceive == 0)
320+
{
321+
transferDirection = TransferDirection.Neither;
322+
}
323+
result.Add(new ResourceTransferPossibility(resourceName, transferDirection, maxCanSend, maxCanReceive));
320324
}
321325

322-
return toReceive.Any() || toSend.Any();
326+
return result;
323327
}
324328
}
325329
}

0 commit comments

Comments
 (0)