Jump to content

Universal Storage 1.4.0.0 (For KSP 1.4.x) 13th March 2018


Paul Kingtiger

Recommended Posts

This seems kind-of superfluous. We already have three very good in-line batteries, the largest of which is very thin, looks fine, and has a very high capacity. And for other situations you can always stuff the radially attached batteries into an empty bay.

Well, we've also got fine in-line fuel tanks and monopropellant, but there are wedges for those. :)

The KAS functionality could come in handy with battery wedges.

That being said, I'm much more excited for TAC support.

Edited by okbillybunnyface
tac
Link to comment
Share on other sites

Fixed the Elektron problem, I've set the input to use more water, then the output to give most of it back.

However this doesn't solve the issue where the water is still used even when you run out of power.

There doesn't seem to be a way around this in stock KSP. I'll keep looking into it.

Link to comment
Share on other sites

An idea on how to approach the Elektron issue of continuing resource consumption - stock jet engines stop working when they run out of intake air, maybe something similar can be done with the Elektron?

Link to comment
Share on other sites

An idea on how to approach the Elektron issue of continuing resource consumption - stock jet engines stop working when they run out of intake air, maybe something similar can be done with the Elektron?

The stop producing output, but they still use up fuel. Same with rocket engines. It affects any part that uses the ModuleEngine and ModuleGenerator function is KSP.

I raised this as a possible bug, but have been told it's been designed to do that and is working as intended.

The next course of action is to ask Squad to change it or make it toggleable in the part.cfg file.

But as of right now, short of writing custom code (which is beyond me) we're stuck.

Edited by Paul Kingtiger
Link to comment
Share on other sites

An idea on how to approach the Elektron issue of continuing resource consumption - stock jet engines stop working when they run out of intake air, maybe something similar can be done with the Elektron?

The difference with the Elektron is that it isn't running out of its fuel. Running out of ElectricCharge just means you can't switch off an already firing engine - the opposite of the behaviour that's wanted for the Elektron.

Link to comment
Share on other sites

The difference with the Elektron is that it isn't running out of its fuel. Running out of ElectricCharge just means you can't switch off an already firing engine - the opposite of the behaviour that's wanted for the Elektron.

Sort of. The way the logic works is you have inputs and outputs.

If you have more than one input then they must all be available for the output to work. Run out of 1 and the output with stop, be that H2 and O2 in the elektron or thrust in an engine.

However all inputs will continue to flow while the part is switched on (or thrust > 0), the system doesn't care if 1 or more input has run out, the others will keep going.

What is needed is a true/false flag in the part.cfg that will detect when 1 input has run out and automatically stop the other inputs as well as the output (deactivate the generator / engine)

EDIT

Having done my own testing this isn't what happens at all. Engines do cut off all inputs when one runs out, which makes sense.

However generators don't.

You can follow my support request here:

http://forum.kerbalspaceprogram.com/threads/87260-Input-resources-in-Generator-module

Edited by Paul Kingtiger
Link to comment
Share on other sites

Update on the elektron (and other generators, which is currently the Sabatier and the Fuel Cell).

I can fix the small numbers problem in the Elektron by using more water in the input but giving most of it back in the output. So that's easy.

However the issue when it's still using water even without power is an issue with KSP and not something I can fix or work around. I've raised this with the KSP team and we're now all on the same page. It's going to be added to the list of things to look at. However as to when it's fixed, no idea. Because it doesn't effect any stock parts it may not be fixed at all until stock parts need it. Hopefully it's a quick thing to fix and it might be included in 0.25? Who knows, but we've done all we can.

However there is another avenue open to me, which I'm currently testing. If I can get it to work and all come together then we might has a great fix with a more immediate time scale (in the order of days rather than months).

Link to comment
Share on other sites

Actually, I'm noticing there is a public "requiresAllInputs" boolean in the ModuleGenerator object, and that the Sabatier part.cfg isn't setting it. If you haven't already, you might try adding "requiresAllInputs = true" to the part.cfg

Edited by okbillybunnyface
Link to comment
Share on other sites

I wonder how hard it would be to code a new ModuleGenerator. I'm pretty experienced in Unity/C#. Methinks I'll make a stab at it for funzies. I'm sure others will encounter this issue; it might be nice for the modding community to have.

If you could get something working that would be Amazing!

Link to comment
Share on other sites

Actually, I'm noticing there is a public "requiresAllInputs" boolean in the ModuleGenerator object, and that the Sabatier part.cfg isn't setting it. If you haven't already, you might try adding "requiresAllInputs = true" to the part.cfg

That's not mentioned in the documentation. Giving it a try now.

EDIT

Doesn't make any difference, it still drains :(

The other main issue with ModuleGenerator is that it doesn't like small fractions.

To get it to work at all I have to increase the input rate then give some of it back as an output as shown below (Lionel_de_Lion worked this out above).

		MODULE
{
name = ModuleGenerator
isAlwaysActive = False
requiresAllInputs = true
activateGUIName = Electrolysis On
shutdownGUIName = Electrolysis Off

INPUT_RESOURCE
{
name = Water
// Units: Liters per second
rate = 0.001036
}

INPUT_RESOURCE
{
name = ElectricCharge
rate = 22
}

OUTPUT_RESOURCE
{
name = Hydrogen
// Units: Liters per second
rate = 0.0448
}

OUTPUT_RESOURCE
{
name = Oxygen
// Units: Liters per second
rate = 0.0224
}

OUTPUT_RESOURCE
{
name = Water
// Units: Liters per second
rate = 0.001
}
}

Edited by Paul Kingtiger
Link to comment
Share on other sites

That's not mentioned in the documentation. Giving it a try now.

EDIT

Doesn't make any difference, it still drains :(

The other main issue with ModuleGenerator is that it doesn't like small fractions.

To get it to work at all I have to increase the input rate then give some of it back as an output as shown below (Lionel_de_Lion worked this out above).

Yeah, I'm seeing the same thing here. I guess that would have been too easy. :)

I'm pretty sure the issue with rate is that it's using a float value, which only has precision to 7 digits. It doesn't exactly make sense to me, since the resources are stored in doubles, but w/e squad.

I'll see what I can do.

Link to comment
Share on other sites

Well, I managed to make something that should address the constant use of resources. It inherits all the functions of the stock ModuleGenerator, except it automatically tells the generator to shutdown if one of the input resources is deprived. I don't recommend using this with isAlwaysActive=true. I have no idea what will happen, lol.

Also, I should note that the player can still toggle the generator back on, and it will run for an extremely short amount of time before turning itself back off. I don't know why anyone would do this, since it'd just behave as before and consume (a tiny amount of) resources with no benefit.

Just put the .dll in your mod's plugins folder, and use the module name "ModuleGeneratorB" instead of "ModuleGenerator". All other parameters should be identical to the stock ModuleGenerator.

Here's a link: https://onedrive.live.com/redir?resid=D7B085CDE92BD749%216152

If anyone is interested, here is the code (feel free to do whatever with it):


using System;
using System.Collections;
using UnityEngine;

public class ModuleGeneratorB : ModuleGenerator
{
ModuleGenerator.GeneratorResource[] stuff;
public override void OnUpdate()
{
stuff = inputList.ToArray();
for (int i = 0; i < stuff.Length; i++)
{
if (stuff[i].isDeprived)
{
ShutdownAction(new KSPActionParam(KSPActionGroup.None, KSPActionType.Deactivate));
break;
}
}
}
}

Edited by okbillybunnyface
Link to comment
Share on other sites

I'm not sure what to do about the low precision with resource consumption. I can't see into the stock ModuleGenerator, so I have no way of figuring out why it's messing up. I strongly suspect it's converting the double-precision resource values to match rate, which is just a float, but the only real/non-hacky fix I can currently thing of would be to rewrite the entire ModuleGenerator instead of inheriting from it, which would take a LOT more poking around the game's code. :\

Link to comment
Share on other sites

I'm not sure what to do about the low precision with resource consumption. I can't see into the stock ModuleGenerator, so I have no way of figuring out why it's messing up. I strongly suspect it's converting the double-precision resource values to match rate, which is just a float, but the only real/non-hacky fix I can currently thing of would be to rewrite the entire ModuleGenerator instead of inheriting from it, which would take a LOT more poking around the game's code. :\

I'm sure (if its not somehow deliberate) it'll get patched sometime. In any case, thank you so much for your help! We'll have to have a kudos section in our release docs and include you in it :D

Link to comment
Share on other sites

I'm sure (if its not somehow deliberate) it'll get patched sometime. In any case, thank you so much for your help! We'll have to have a kudos section in our release docs and include you in it :D

You're welcome! That's not necessary; there are worse ways I could have spent my evening, and it only took a couple hours. :)

Link to comment
Share on other sites

I'm noticing that it is a little tricky to reactivate a generator that has run out of resources in the past when the resources have been restored, presumably because it's being shutdown again before isDeprived can be set back to false by the generator.

Additionally, the output resources are being filled at the normal rate even if the input resources are being supplied at less than the consumption rate, but I'm pretty sure that's an issue with the stock generator module rather than what I've done.

I'll try and fix it, but it'll probably be tomorrow sometime before I can.

Link to comment
Share on other sites

So, out of a pervasive curiosity, I ended up learning how to write modules, and then wrote a whole new generator module. >_>;

I know it doesn't have the issue I mentioned in my last post, and I believe it shouldn't have the precision issue either.

Here is a link https://onedrive.live.com/redir?resid=D7B085CDE92BD749!6159&authkey=!AOw-n6vJsRrKA-Y&ithint=folder%2c

This is how the part.cfg should look:


MODULE
{
name = ModuleResourceConverter
INPUT_RESOURCE
{
name = ElectricCharge
rate = 1
}
INPUT_RESOURCE
{
name = XenonGas
rate = 1
}
OUTPUT_RESOURCE
{
name = MonoPropellant
rate = 1
}
}

Source Code:


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


class ModuleResourceConverter : PartModule
{
private double efficiency = 1.00;

[KSPField(isPersistant = true, guiActive = true, guiName = "Activated")]
public bool generatorIsActive = false;


public override string GetInfo()
{
string info = "Input Resources:\n";

foreach (ModuleGenerator.GeneratorResource resource in inputList)
{
info = String.Concat(info, resource.name + " (" + resource.rate + " units/second)\n");
}
info = String.Concat(info, "\nOutput Resources:\n");
foreach (ModuleGenerator.GeneratorResource resource in outputList)
{
info = String.Concat(info, resource.name + " (" + resource.rate + " units/second)\n");
}

return info;
}

private ResourceTracker[] inputResources;

public List<ModuleGenerator.GeneratorResource> inputList = new List<ModuleGenerator.GeneratorResource>();
public List<ModuleGenerator.GeneratorResource> outputList = new List<ModuleGenerator.GeneratorResource>();
public override void OnLoad(ConfigNode node)
{
inputList.Clear();
outputList.Clear();
foreach (ConfigNode subNode in node.nodes)
{
ModuleGenerator.GeneratorResource stuff;
switch (subNode.name)
{
case "INPUT_RESOURCE":
stuff = new ModuleGenerator.GeneratorResource();
stuff.Load(subNode);
inputList.Add(stuff);
break;
case "OUTPUT_RESOURCE":
stuff = new ModuleGenerator.GeneratorResource();
stuff.Load(subNode);
outputList.Add(stuff);
break;
}
}

inputResources = new ResourceTracker[inputList.Count];
int temp = 0;
foreach (ModuleGenerator.GeneratorResource resource in inputList)
{
inputResources[temp] = new ResourceTracker(resource.name, resource.id, resource.rate);
temp++;
}
}

public override void OnSave(ConfigNode node)
{
foreach (ModuleGenerator.GeneratorResource resource in inputList)
{
resource.Save(node.AddNode("INPUT_RESOURCE"));
}
foreach (ModuleGenerator.GeneratorResource resource in outputList)
{
resource.Save(node.AddNode("OUTPUT_RESOURCE"));
}
}

public override void OnStart(StartState state)
{
Events["Activate"].active = true;
Events["Deactivate"].active = false;
}

public override void OnAwake()
{
if (inputList == null)
{
inputList = new List<ModuleGenerator.GeneratorResource>();
}
if (outputList == null)
{
outputList = new List<ModuleGenerator.GeneratorResource>();
}
}

public override void OnUpdate()
{
if (generatorIsActive)
{
efficiency = 1.00;

//Gather resources
for (int i = 0; i < inputResources.Length; i++)
{
inputResources[i].request = inputResources[i].rate * TimeWarp.deltaTime;
inputResources[i].amount += part.RequestResource(inputResources[i].id, inputResources[i].request - inputResources[i].amount);

double ratio = inputResources[i].amount / inputResources[i].request;
if (ratio < efficiency) { efficiency = ratio; }
}

//Subtract required resources
for (int i = 0; i < inputResources.Length; i++)
{
inputResources[i].amount -= inputResources[i].request * efficiency;
}


//Deliver output resources
foreach (ModuleGenerator.GeneratorResource resource in outputList)
{
part.RequestResource(resource.id, -resource.rate * efficiency * TimeWarp.deltaTime);
}
}
}

[KSPAction("Activate Converter")]
public void ActivateAction(KSPActionParam param)
{
Activate();
}

[KSPAction("Shutdown Converter")]
public void ShutdownAction(KSPActionParam param)
{
Deactivate();
}

[KSPAction("Toggle Converter")]
public void ToggleAction(KSPActionParam param)
{
if (generatorIsActive)
{
Deactivate();
}
else
{
Activate();
}
}

[KSPEvent(guiActive = true, guiName = "Activate Converter", active = true, guiActiveUnfocused = false, guiActiveEditor = false, externalToEVAOnly = true)]
public void Activate()
{
Events["Activate"].active = false;
Events["Deactivate"].active = true;

generatorIsActive = true;
}

[KSPEvent(guiActive = true, guiName = "Deactivate Converter", active = false, guiActiveUnfocused = false, guiActiveEditor = false, externalToEVAOnly = true)]
public void Deactivate()
{
Events["Activate"].active = true;
Events["Deactivate"].active = false;

generatorIsActive = false;
}

private class ResourceTracker
{
public int id;
public double rate;
public double amount;
public double request;

public ResourceTracker(string name, int id, double rate)
{
this.id = id;
this.rate = rate;
this.amount = 0;
this.request = 0;
}
}
}

Have fun with it. o/

Edited by okbillybunnyface
Link to comment
Share on other sites

Thanks for doing all this, you are a star!

The auto stop works perfectly!

The rounding issue is still there, although it's different to the stock generator.

In stock you've have to accelerate time to x50 to get it to work. With yours you only have to go to x5

However you can't get around it by adding additional inputs but giving it back as an output like I did with stock.

I did some digging around last night and TAC LS has a generator module, TACGenericConverter which stops all inputs and deals with small fractions. It's part of the TACLS.dll but it is separated out in the source code. I tried comparing yours with theirs but my limited coding knowledge isn't really helping here ;) It's overly complex for what we need as it has a scale factor system to make it easy to use in different sized parts (which TAC does a lot of)

I don't know if it would be useful to you (TAC's licence allows derivatives).

/**
* Thunder Aerospace Corporation's Life Support for Kerbal Space Program.
* Written by Taranis Elsu.
*
* (C) Copyright 2013, Taranis Elsu
*
* Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This
* project is in no way associated with nor endorsed by Squad.
*
* This code is licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 3.0)
* creative commons license. See <http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode>
* for full details.
*
* Attribution  You are free to modify this code, so long as you mention that the resulting
* work is based upon or adapted from this code.
*
* Non-commercial - You may not use this work for commercial purposes.
*
* Share Alike  If you alter, transform, or build upon this work, you may distribute the
* resulting work only under the same or similar license to the CC BY-NC-SA 3.0 license.
*
* Note that Thunder Aerospace Corporation is a ficticious entity created for entertainment
* purposes. It is in no way meant to represent a real entity. Any similarity to a real entity
* is purely coincidental.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace Tac
{
/*
* Example config file:
* MODULE
* {
* name = TacGenericConverter
*
* // Displayed when right clicking the part
* converterName = Carbon Extractor
*
* // [Optional] Sets the converter so that it is enabled initially
* // so that you do not need to worry about forgeting to turn it on
* // before launching.
* // converterEnabled = false
*
* // [Optional] When set to true, the converter cannot be disabled
* // (or turned off)
* // alwaysOn = false
*
* // Number of units to convert per day (24 hours)
* conversionRate = 8
*
* // A comma separated list of resources to use as inputs.
* // For each resource, list the resource name and the amount (which
* // is multiplied by the conversionRate)
* inputResources = CarbonDioxide, 1, ElectricCharge, 1000
*
* // A comma separated list of resources to output. Same as above
* // but also specify whether it should keep converting if the
* // resource is full (generating excess that will be thrown away).
* outputResources = Oxygen, 0.9, false, Waste, 2.218, true
*
* // [Optional] When set to true, the converter will not run unless
* // on a planet that has oxygen in the atmosphere (only Kerbin or
* // Laythe).
* requiresOxygenAtmo = false
* }
* or
* MODULE
* {
* name = TacGenericConverter
* converterName = Water Purifier
* conversionRate = 8
* inputResources = WasteWater, 1, ElectricCharge, 1000
* outputResources = Water, 0.9, false, Waste, 6.382, true
* }
*/
[KSPModule("TAC Converter")]
public class TacGenericConverter : PartModule
{
private static char[] delimiters = { ' ', ',', '\t', ';' };

[KSPField]
public string converterName = "TAC Generic Converter";

[KSPField(guiActive = true, guiName = "Converter Status")]
public string converterStatus = "Unknown";

[KSPField(isPersistant = true)]
public bool converterEnabled = false;

[KSPField]
public bool alwaysOn = false;

[KSPField]
public float conversionRate = 1.0f;

[KSPField]
public string inputResources = "";

[KSPField]
public string outputResources = "";

[KSPField]
public bool requiresOxygenAtmo = false;

private double lastUpdateTime = 0.0f;

private List<ResourceRatio> inputResourceList;
private List<ResourceRatio> outputResourceList;

public override void OnAwake()
{
this.Log("OnAwake");
base.OnAwake();
UpdateResourceLists();
}

public override void OnStart(PartModule.StartState state)
{
this.Log("OnStart: " + state);
base.OnStart(state);

if (state != StartState.Editor)
{
part.force_activate();
}

UpdateEvents();
}

public override void OnFixedUpdate()
{
base.OnFixedUpdate();

if (Time.timeSinceLevelLoad < 1.0f || !FlightGlobals.ready)
{
return;
}

if (lastUpdateTime == 0.0f)
{
// Just started running
lastUpdateTime = Planetarium.GetUniversalTime();
return;
}

GlobalSettings globalSettings = TacLifeSupport.Instance.globalSettings;

double deltaTime = Math.Min(Planetarium.GetUniversalTime() - lastUpdateTime, globalSettings.MaxDeltaTime);
lastUpdateTime += deltaTime;

if (converterEnabled)
{
if (requiresOxygenAtmo && !vessel.mainBody.atmosphereContainsOxygen)
{
converterStatus = "Atmo lacks oxygen.";
return;
}

double desiredAmount = conversionRate * deltaTime;
double maxElectricityDesired = Math.Min(desiredAmount, conversionRate * Math.Max(globalSettings.ElectricityMaxDeltaTime, TimeWarp.fixedDeltaTime)); // Limit the max electricity consumed when reloading a vessel

// Limit the resource amounts so that we do not produce more than we have room for, nor consume more than is available
foreach (ResourceRatio output in outputResourceList)
{
if (!output.allowExtra)
{
if (output.resource.id == globalSettings.ElectricityId && desiredAmount > maxElectricityDesired)
{
// Special handling for electricity
double desiredElectricity = maxElectricityDesired * output.ratio;
double availableSpace = -part.IsResourceAvailable(output.resource, -desiredElectricity);
desiredAmount = desiredAmount * (availableSpace / desiredElectricity);
}
else
{
double availableSpace = -part.IsResourceAvailable(output.resource, -desiredAmount * output.ratio);
desiredAmount = availableSpace / output.ratio;
}

if (desiredAmount <= 0.000000001)
{
// Out of space, so no need to run
converterStatus = "No space for more " + output.resource.name;
return;
}
}
}

foreach (ResourceRatio input in inputResourceList)
{
if (input.resource.id == globalSettings.ElectricityId && desiredAmount > maxElectricityDesired)
{
// Special handling for electricity
double desiredElectricity = maxElectricityDesired * input.ratio;
double amountAvailable = part.IsResourceAvailable(input.resource, desiredElectricity);
desiredAmount = desiredAmount * (amountAvailable / desiredElectricity);
}
else
{
double amountAvailable = part.IsResourceAvailable(input.resource, desiredAmount * input.ratio);
desiredAmount = amountAvailable / input.ratio;
}

if (desiredAmount <= 0.000000001)
{
// Not enough input resources
converterStatus = "Not enough " + input.resource.name;
return;
}
}

foreach (ResourceRatio input in inputResourceList)
{
double desired;
if (input.resource.id == globalSettings.ElectricityId)
{
desired = Math.Min(desiredAmount, maxElectricityDesired) * input.ratio;
}
else
{
desired = desiredAmount * input.ratio;
}

double actual = part.TakeResource(input.resource, desired);

if (actual < (desired * 0.999))
{
this.LogWarning("OnFixedUpdate: obtained less " + input.resource.name + " than expected: " + desired.ToString("0.000000000") + "/" + actual.ToString("0.000000000"));
}
}

foreach (ResourceRatio output in outputResourceList)
{
double desired;
if (output.resource.id == globalSettings.ElectricityId)
{
desired = Math.Min(desiredAmount, maxElectricityDesired) * output.ratio;
}
else
{
desired = desiredAmount * output.ratio;
}

double actual = -part.TakeResource(output.resource.id, -desired);

if (actual < (desired * 0.999) && !output.allowExtra)
{
this.LogWarning("OnFixedUpdate: put less " + output.resource.name + " than expected: " + desired.ToString("0.000000000") + "/" + actual.ToString("0.000000000"));
}
}

converterStatus = "Running";
}
}

public override void OnLoad(ConfigNode node)
{
this.Log("OnLoad: " + node);
base.OnLoad(node);
lastUpdateTime = Utilities.GetValue(node, "lastUpdateTime", lastUpdateTime);

UpdateResourceLists();
UpdateEvents();
}

public override void OnSave(ConfigNode node)
{
node.AddValue("lastUpdateTime", lastUpdateTime);
this.Log("OnSave: " + node);
}

public override string GetInfo()
{
StringBuilder sb = new StringBuilder();
sb.Append(converterName);
sb.Append("\n\nInputs:");
foreach (var input in inputResourceList)
{
double ratio = input.ratio * conversionRate;
sb.Append("\n - ").Append(input.resource.name).Append(": ").Append(Utilities.FormatValue(ratio, 3)).Append("U/sec");
}
sb.Append("\n\nOutputs: ");
foreach (var output in outputResourceList)
{
double ratio = output.ratio * conversionRate;
sb.Append("\n - ").Append(output.resource.name).Append(": ").Append(Utilities.FormatValue(ratio, 3)).Append("U/sec");
}
sb.Append("\n");
if (requiresOxygenAtmo)
{
sb.Append("\nRequires an atmosphere containing Oxygen.");
}
if (alwaysOn)
{
sb.Append("\nCannot be turned off.");
}

return sb.ToString();
}

[KSPEvent(active = false, guiActive = true, guiActiveEditor = true, guiName = "Activate Converter")]
public void ActivateConverter()
{
converterEnabled = true;
UpdateEvents();
}

[KSPEvent(active = false, guiActive = true, guiActiveEditor = true, guiName = "Deactivate Converter")]
public void DeactivateConverter()
{
converterEnabled = false;
UpdateEvents();
}

[KSPAction("Toggle Converter")]
public void ToggleConverter(KSPActionParam param)
{
converterEnabled = !converterEnabled;
UpdateEvents();
}

private void UpdateEvents()
{
if (alwaysOn)
{
Events["ActivateConverter"].active = false;
Events["DeactivateConverter"].active = false;
converterEnabled = true;
}
else
{
Events["ActivateConverter"].active = !converterEnabled;
Events["DeactivateConverter"].active = converterEnabled;

if (!converterEnabled)
{
converterStatus = "Inactive";
}
}
}

private void UpdateResourceLists()
{
if (inputResourceList == null)
{
inputResourceList = new List<ResourceRatio>();
}
if (outputResourceList == null)
{
outputResourceList = new List<ResourceRatio>();
}

ParseInputResourceString(inputResources, inputResourceList);
ParseOutputResourceString(outputResources, outputResourceList);

Events["ActivateConverter"].guiName = "Activate " + converterName;
Events["DeactivateConverter"].guiName = "Deactivate " + converterName;
Actions["ToggleConverter"].guiName = "Toggle " + converterName;
Fields["converterStatus"].guiName = converterName;
}

private void ParseInputResourceString(string resourceString, List<ResourceRatio> resources)
{
resources.Clear();

string[] tokens = resourceString.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);

for (int i = 0; i < (tokens.Length - 1); i += 2)
{
PartResourceDefinition resource = PartResourceLibrary.Instance.GetDefinition(tokens[i]);
double ratio;
if (resource != null && double.TryParse(tokens[i + 1], out ratio))
{
resources.Add(new ResourceRatio(resource, ratio));
}
else
{
this.Log("Cannot parse \"" + resourceString + "\", something went wrong.");
}
}

var ratios = resources.Aggregate("", (result, value) => result + value.resource.name + ", " + value.ratio + ", ");
this.Log("Input resources parsed: " + ratios + "\nfrom " + resourceString);
}

private void ParseOutputResourceString(string resourceString, List<ResourceRatio> resources)
{
resources.Clear();

string[] tokens = resourceString.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);

for (int i = 0; i < (tokens.Length - 2); i += 3)
{
PartResourceDefinition resource = PartResourceLibrary.Instance.GetDefinition(tokens[i]);
double ratio;
bool allowExtra;
if (resource != null && double.TryParse(tokens[i + 1], out ratio) && bool.TryParse(tokens[i + 2], out allowExtra))
{
resources.Add(new ResourceRatio(resource, ratio, allowExtra));
}
else
{
this.Log("Cannot parse \"" + resourceString + "\", something went wrong.");
}
}

var ratios = resources.Aggregate("", (result, value) => result + value.resource.name + ", " + value.ratio + ", ");
this.Log("Output resources parsed: " + ratios + "\nfrom " + resourceString);
}
}

public class ResourceRatio
{
public PartResourceDefinition resource;
public double ratio;
public bool allowExtra;

public ResourceRatio(PartResourceDefinition resource, double ratio, bool allowExtra = false)
{
this.resource = resource;
this.ratio = ratio;
this.allowExtra = allowExtra;
}
}
}

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...