jamespicone

[1.1.3] BackgroundProcessing

Recommended Posts

SpaceDock: http://spacedock.info/mod/288/BackgroundProcessing

Source: https://bitbucket.org/j_picone/background-processing

BackgroundProcessing is a small and simple mod that performs some processing for vessels 'in the background' - probes or manned craft that have been left orbiting while the player is in the Kerbal Space Center or piloting another vessel.

Installation

* Download the BackgroundProcessing.zip file from KerbalStuff

* Extract it to your GameData folder

I'm a player. What does BackgroundProcessing offer me?

BackgroundProcessing will allow craft to gain and lose ElectricCharge while you're off doing something else. This doesn't actually happen in stock KSP - try building a spaceship made up of an empty battery, an RTG, and some wheels (to get it off the launchpad). Move it off the launchpad, check resources, notice that it's gaining charge over time. Then leave it and go back to the space center and speed up time. Check the craft again, and it won't have gained or lost any charge. That's a minor realism issue, but its nice to have fixed.

The other thing BackgroundProcessing provides is support for other mods that might want to do something while a craft is in the background. A scanner, something that produces a mod-specific resource, anything like that. Because of the way BackgroundProcessing is designed that other mod doesn't have to include BP, and it doesn't have to use its features, but if that mod has implemented BP-compatibility, BP will detect it and use it.

I'm a mod author. What does BackgroundProcessing offer me?

If you have a PartModule that should do stuff even while a craft isn't the actual active vessel - like a scanner, or a solar-wind collector - you can get background processing just by implementing a couple of functions. BackgroundProcessing has already implemented a lot of the boilerplate required to get this working. Your PartModule can do anything in the background that can be done with a ProtoVessel - which is quite a lot - and BP provides some mechanisms for producing or consuming resources easily. BP also allows mods to indicate that some mod-specific resource should be handled in the background, and then any ModuleGenerator or ModuleDeployableSolarPanel that produces that resource (with no resource consumed) will produce it in the background. Additionally, any ModuleCommand that consumes that resource will consume it in the background. All of this can be done without reference to the BackgroundProcessing assembly, so your users can choose whether or not they want background handling, and you don't have to package BP with your mod.

BackgroundProcessing is MIT-licensed, so there aren't any license worries.

What specific things are handled?

Any Part using the ModuleGenerator or ModuleDeployableSolarPanel to produce ElectricCharge with no inputs, any Part using ModuleComand to consume ElectricCharge. At present ModuleDeployableSolarPanel output charge takes into account the location of Kerbol, its power curve, planetary shadows, and panel orientation, including tracking solar panels.

Mods can instruct BackgroundProcessing that particular PartModule classes should be considered to produce or consume some resource at a given rate. They can also have BackgroundProcessing handle ModuleGenerator/ModuleDeployableSolarPanel/ModuleCommand that produces/consumes resources other than ElectricCharge. Finally, their background handling code can consume or produce any resource they please.

How do I get BackgroundProcessing support in my PartModule?

Implement some static functions in your PartModule.

 

 
public static void FixedBackgroundUpdate(Vessel v, uint partFlightID, ref System.Object data)

public static void FixedBackgroundUpdate(Vessel v, uint partFlightID, Func<Vessel, float, string, float> resourceRequest, ref System.Object data)

 

These two functions are the 'simple' and 'complex' background update functions. If you implement either of them, BackgroundProcessing will call it at FixedUpdate() intervals (if you implement both, only the complex version will get called). The function will only be called for unloaded vessels, and it will be called once per part per partmodule type - so if you have more than one of the same PartModule on the same part you'll only get one update for all of those PartModules. Vessel v is the Vessel object that you should update - be careful, it's quite likely unloaded and very little of it is there. partFlightID is the flightID of the Part this update was associated with. resourceRequest is a function that provides an analog of Part.RequestResource. It takes a vessel, an amount of resource to take, and a resource name, and returns the amount of resource that you got. Like Part.RequestResource, you can ask for a negative amount of some resource to fill up the tanks. The resource is consumed as if it can be reached from the entire vessel - be very careful with resources like liquid fuel that should only flow through crossfeeds. data is arbitrary per-part-per-partmodule-type storage - you can stash anything you want there, and it will persist between FixedBackgroundUpdate calls.

 

 
public static void BackgroundLoad(Vessel v, uint partFlightId, ref System.Object data)

 

This function will be called once prior to FixedBackgroundUpdate, and it gives you a chance to load data out of the ConfigNodes on the vessel's protovessel into the storage BackgroundProcessing manages for you.

 

 
public static void BackgroundSave(Vessel v, uint partFlightId, System.Object data)

 

This function will be called prior to the game scene changing or the game otherwise being saved. Use it to persist background data to the vessel's confignodes. Note that System.Object data is *not* a ref type here, unlike the other functions that have it as an argument.

 

 
public static List<string> GetInterestingResources()

 

Implement this function to return a list of resources that your PartModule would like BackgroundProcessing to handle in the background. It's okay if multiple PartModules say a given resource is interesting.

 

 
public static int GetBackgroundResourceCount()

public static void GetBackgroundResource(int index, out string resourceName, out float resourceRate)

 

Implement these functions to inform BackgroundProcessing that your PartModule should be considered to produce or consume a resource in the background. GetBackgroundResourceCount() should return the number of different resources that your PartModule produces/consumes. GetBackgroundResource() will then be called with each index from 0 up to one less than the count you indicated, and you should set resourceName and resourceRate to the appropriate values for the index-th resource your PartModule produces. resourceRate is the amount of resource your part should produce each second - if your part consumes resources, it should be negative. If your part only consumes or produces resources in some situation, it's better to implement the complex background update and use the resource request function.

How do I distribute a mod that uses BackgroundProcessing?

Having multiple copies of the BackgroundProcessing DLL in a GameData directory is fine - only the most recent version will run. If your mod absolutely needs BackgroundProcessing present to be useful, consider including the BackgroundProcessing DLL in your mod's zip file, the same way ModuleManager is handled.

If BackgroundProcessing isn't central to your mod, feel free not to distribute it at all. If players don't have this mod installed, they just won't get your off-rails features.

Are there any caveats when writing code that uses BackgroundProcessing?

BackgroundProcessing works optimally with PartModules that are present in prefab parts. The list of modules that has BackgroundProcessing handling is constructed by walking all the AvailablePart objects in PartLoader.LoadedPartLists at the main menu. If your partmodule isn't in that set, very little will work. Similarly, if your PartModule is added to a part's module list after part instantiation, and isn't present in the part's prefab module list, resource handling will likely not work. This is all only relevant if your PartModule is added dynamically to parts, after construction. It isn't relevant to PartModules that are present in config files, or to PartModules added by ModuleManager (which appropriately modifies prefab parts). The takeaway is that if you intend to dynamically add PartModules to parts, and those dynamically-added PartModules should have BackgroundProcessing behaviour, make sure you add them to the appropriate part prefab before the main menu, like ModuleManager.

Edited by jamespicone
Update for 1.1.3
  • Like 9

Share this post


Link to post
Share on other sites

cool, thanks! Just read the detail page. This could be very useful. Could this also take into account the orbits of not-active vessels? I've noticed that if a not-active vessel is in an eccentric orbit that hits atmosphere, the orbit doesn't decay like it would on an active vessel. Wondering if this could be used in that situation?

Share this post


Link to post
Share on other sites

Possibly. I'm not sure this mod would strictly be the right place to do it. I'd need to look into it.

IIRC some other mod devs I've talked to in the #kspmodders channel have noted that adjusting orbital parameters with unloaded vessels doesn't work terribly well. It would also be quite hard to match KSPs behaviour accurately. I'll keep it in mind as a future thing to consider.

Share this post


Link to post
Share on other sites

Great to see this released. Hope to see background EC consumption soon as well!

cool, thanks! Just read the detail page. This could be very useful. Could this also take into account the orbits of not-active vessels? I've noticed that if a not-active vessel is in an eccentric orbit that hits atmosphere, the orbit doesn't decay like it would on an active vessel. Wondering if this could be used in that situation?

Already done. Although I have it installed, have not been able to see it in action myself so don't know how well it works. Was planning to test it with a recent launch but ended up dropping my spent stage at 75km :P

Share this post


Link to post
Share on other sites
Great to see this released. Hope to see background EC consumption soon as well!

Already done. Although I have it installed, have not been able to see it in action myself so don't know how well it works. Was planning to test it with a recent launch but ended up dropping my spent stage at 75km :P

Thanks for pointing to this mod! It's something I've wanted for quite a while; it's nice to see it actually exists.

Share this post


Link to post
Share on other sites

[ERR 17:54:19.121] BackgroundProcessing: Ran out of modules before finding module FARBasicDragModel

is all is eem to get from this tons of messages saying ran out of modules. guess shouldnt use tthis maybe till mod authors incorprate it first maybe.

Share this post


Link to post
Share on other sites
[ERR 17:54:19.121] BackgroundProcessing: Ran out of modules before finding module FARBasicDragModel

is all is eem to get from this tons of messages saying ran out of modules. guess shouldnt use tthis maybe till mod authors incorprate it first maybe.

That particular error message isn't super important - it's in there because it's good for me to know about, but it shouldn't break too much. It happens when I can't find a PartModule for a given unloaded Part in a vessel - in this case, it looks like FAR creates some PartModules on all parts when they're created, but doesn't modify the part prefab, so I can't find an actual instantiated instance of the FAR modules. That means I won't do background resource handling for those modules, but given that FAR's inserted modules don't contain or consume resources anyway that shouldn't matter too much. I'm looking into ways of improving this behaviour, but it's kind of tricky to get some of the information I want for a PartModule from its ProtoPartModuleSnapshot.

  • Like 1

Share this post


Link to post
Share on other sites
That particular error message isn't super important - it's in there because it's good for me to know about, but it shouldn't break too much. It happens when I can't find a PartModule for a given unloaded Part in a vessel - in this case, it looks like FAR creates some PartModules on all parts when they're created, but doesn't modify the part prefab, so I can't find an actual instantiated instance of the FAR modules. That means I won't do background resource handling for those modules, but given that FAR's inserted modules don't contain or consume resources anyway that shouldn't matter too much. I'm looking into ways of improving this behaviour, but it's kind of tricky to get some of the information I want for a PartModule from its ProtoPartModuleSnapshot.

ok thats good then. but its annoying to keep seeing when i was trying to hunt down a incompatiable mod and haveing a message from it every time i left the hangers lol.

Share this post


Link to post
Share on other sites

I'm really excited to see if this will affect non-active ships. I'm tired of my space stations spinning around as if they have no internal reaction wheels and such

  • Like 1

Share this post


Link to post
Share on other sites
I'm really excited to see if this will affect non-active ships. I'm tired of my space stations spinning around as if they have no internal reaction wheels and such

I don't make any attempt to maintain orientation or anything like that. It does work on non-active ships, but as a user, and with close to zero mods using this right now, the only change you'll notice is that electric charge will be consumed by command modules and generated by solar panels and anything using ModuleGenerator (The PB-NUK in stock, maybe some mods).

  • Like 1

Share this post


Link to post
Share on other sites

As a cheaty workaround, could you lock orientation in exchange for a constant power draw (hopefully offset by panels)?

  • Like 1

Share this post


Link to post
Share on other sites

I was fooling around with attempting to support BackgroundProcessing in BTSM this evening, which seems to run fine on its own, but soon as I attempt to add callbacks into my own part modules, it appears to crash the game during loading before hitting the main menu.

I only added a single function to my part module, as follows:


public static void FixedBackgroundUpdate( Vessel vessel, uint uiFlightID, Func<Vessel, float, string, float> ResourceRequestFunc )
{
Debug.Log( "BTSMModuleProbePower: Persistant update for " + vessel.vesselName );
}

Which is obviously not intended to do anything other than establish that the callback is indeed being called at the appropriate time. Removing the single Debug.Log() call results in the same crash.

Any ideas as to what might be causing it? Am I doing something funky or am I simply the first to test out the mod support functionality?

  • Like 1

Share this post


Link to post
Share on other sites
I was fooling around with attempting to support BackgroundProcessing in BTSM this evening, which seems to run fine on its own, but soon as I attempt to add callbacks into my own part modules, it appears to crash the game during loading before hitting the main menu.

I only added a single function to my part module, as follows:


public static void FixedBackgroundUpdate( Vessel vessel, uint uiFlightID, Func<Vessel, float, string, float> ResourceRequestFunc )
{
Debug.Log( "BTSMModuleProbePower: Persistant update for " + vessel.vesselName );
}

Which is obviously not intended to do anything other than establish that the callback is indeed being called at the appropriate time. Removing the single Debug.Log() call results in the same crash.

Any ideas as to what might be causing it? Am I doing something funky or am I simply the first to test out the mod support functionality?

All of my prior tests had only one part with a given partmodule that had a FixedBackgroundUpdate, so I hadn't noticed that I was handling each partmodule once for each part that contained it. And the handling includes calling Add on a dictionary, so that's a crash. Should be fixed in 0.3.5.2, which I just pushed to KerbalStuff and source control. Sorry for the mistake, thanks for the catch.

  • Like 1

Share this post


Link to post
Share on other sites
All of my prior tests had only one part with a given partmodule that had a FixedBackgroundUpdate, so I hadn't noticed that I was handling each partmodule once for each part that contained it. And the handling includes calling Add on a dictionary, so that's a crash. Should be fixed in 0.3.5.2, which I just pushed to KerbalStuff and source control. Sorry for the mistake, thanks for the catch.

Cool stuff man. Much obliged for the quick fix. Will have another go at it tomorrow.

- - - Updated - - -

Well, decided to give it a try with 3.5.2, and unfortunately same crash is occurring. Here's the full source file in case it helps any:


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

namespace BTSM
{
[KSPModule( "Probe Core" )]
class BTSMModuleProbePower : BTSMPartModule
{
private static int m_iNumOutOfEnergyUpdatesForDamage = 20;

[KSPField( isPersistant = false )]
public float energyConsumedRate = 0.16666668F; // default is same as Stayputnik (6X a stock probe core)

[KSPField( isPersistant = false )]
public bool canBeDisabled = false;

[KSPField( isPersistant = true )]
public bool m_bProbeDamaged = false; // persistant variable to track if the probe has been damaged by lack of power

private float m_fEnergyRequiredLeftovers = 0F; // variable to store any energy remnants required which haven't been consumed on a previous update
private int m_iOutOfEnergyUpdateCount = 0; // acts as buffer to prevent momentary power supply problems due to vanilla bugs causing probe cores to fail

[KSPField( isPersistant = true, guiActive = true, guiActiveEditor = true, guiName = "Probe Core"), UI_Toggle( disabledText="Enabled", enabledText="Disabled" )]
public bool coreDisabled = false;

public bool m_bPreviousCoreDisabled = false;

[KSPAction( "Toggle Probe Core" )]
public void ToggleProbeCoreAction( KSPActionParam param )
{
if ( vessel != null && vessel.IsControllable && canBeDisabled )
{
coreDisabled = !coreDisabled;

RefreshAssociatedWindows();
}
}

public override void OnStart( StartState state )
{
base.OnStart(state);

if ( !m_bInEditor )
{
if ( m_bProbeDamaged )
{
DamageAssociatedProbeCore();
}
else
{
SetProbeCoreDeactivated( coreDisabled );
}
}
else
{
BaseField coreEnabledField = Fields["coreDisabled"];

if ( coreEnabledField != null )
{
coreEnabledField.guiActive = canBeDisabled;
coreEnabledField.guiActiveEditor = canBeDisabled;
}
}

m_bPreviousCoreDisabled = coreDisabled;
m_fEnergyRequiredLeftovers = 0F;
m_iOutOfEnergyUpdateCount = 0;
}

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

if ( !m_bInEditor )
{
bool bShouldGUIBeActive = canBeDisabled;

if ( m_bProbeDamaged )
{
bShouldGUIBeActive = false;
}
else
{
if ( m_bPreviousCoreDisabled != coreDisabled )
{
SetProbeCoreDeactivated( coreDisabled );

m_fEnergyRequiredLeftovers = 0F;
m_iOutOfEnergyUpdateCount = 0;
}

if ( !coreDisabled )
{
if ( !AttemptToDeductEnergyForUse() )
{
if ( !canBeDisabled )
{
DamageAssociatedProbeCore();

bShouldGUIBeActive = false;
}
else
{
coreDisabled = true;

SetProbeCoreDeactivated( true );

ScreenMessages.PostScreenMessage( part.partInfo.title + " shut itself down due to lack of power.", 10F, ScreenMessageStyle.UPPER_CENTER );

m_fEnergyRequiredLeftovers = 0F;
m_iOutOfEnergyUpdateCount = 0;
}
}
}
else if ( !vessel.IsControllable )
{
bShouldGUIBeActive = false;
}
}

BaseField coreEnabledField = Fields["coreDisabled"];

if ( coreEnabledField != null )
{
if ( coreEnabledField.guiActive != bShouldGUIBeActive )
{
coreEnabledField.guiActive = bShouldGUIBeActive;

RefreshAssociatedWindows();
}
}

UpdateStateString();
}

m_bPreviousCoreDisabled = coreDisabled;
}

private bool AttemptToDeductEnergyForUse()
{
return ConsumeResourceReliable( "ElectricCharge", energyConsumedRate, m_iNumOutOfEnergyUpdatesForDamage, ref m_iOutOfEnergyUpdateCount, ref m_fEnergyRequiredLeftovers );
}

private void DamageAssociatedProbeCore()
{
ModuleCommand associatedCommandModule = FindAssociatedCommandModule();

if ( associatedCommandModule != null )
{
associatedCommandModule.minimumCrew = 1;

if ( !m_bProbeDamaged )
{
m_bProbeDamaged = true;

ScreenMessages.PostScreenMessage( part.partInfo.title + " was damaged due to lack of power.", 10F, ScreenMessageStyle.UPPER_CENTER );
}
}
}

private void SetProbeCoreDeactivated( bool bDeactivated )
{
ModuleCommand associatedCommandModule = FindAssociatedCommandModule();

if ( associatedCommandModule != null )
{
if ( bDeactivated )
{
associatedCommandModule.minimumCrew = 1;
}
else
{
associatedCommandModule.minimumCrew = 0;
}
}
}

private void UpdateStateString()
{
ModuleCommand associatedCommandModule = FindAssociatedCommandModule();

if ( associatedCommandModule != null )
{
string sDesiredStateString = "Operational";

if ( m_bProbeDamaged )
{
sDesiredStateString = "Damaged";
}
else if ( coreDisabled )
{
sDesiredStateString = "Disabled";
}

associatedCommandModule.controlSrcStatusText = sDesiredStateString;
}
}

private ModuleCommand FindAssociatedCommandModule()
{
return (ModuleCommand)FindAssociatedModuleOfType( "ModuleCommand" );
}

public override string GetInfo()
{
string sDescString =
"<b><color=#99ff00ff>Requires:</color></b>\n" +
"- <b>Electric Charge: </b>" + FormatRateString( energyConsumedRate ) + "\n";

if ( canBeDisabled )
{
sDescString += "\n<b>Can Be Safely Powered Down</b>\n";
}
else
{
sDescString += "\n<b>WARNING: Requires constant power to avoid damage</b>\n";
}

return sDescString;
}

public static void FixedBackgroundUpdate( Vessel vessel, uint uiFlightID, Func<Vessel, float, string, float> ResourceRequestFunc )
{
Debug.Log( "BTSMModuleProbePower: Persistant update for " + vessel.vesselName );

/*
float fResourceToRequest = 10F;

float fResourceConsumed = ResourceRequestFunc( vessel, fResourceToRequest, "ElectricCharge" );
*/
}
}
}

FixedBackgroundUpdate() callback is right at that bottom there, and is the only thing I've changed from previous versions.

BTSMModuleProbePower is basically added to every probe core in the game and replaces the stock energy management for probe cores in the mod to handle them being damaged due to lack of power, and also to get around stock rounding errors in resource management by tracking remainders between ticks. If you take a look at the mod itself, the modules are added in BTSMPartChanges.cfg with an example right at the top of the file for the Stayputnik, like so:


// Stayputnik Mk1
@PART[probeCoreSphere]
{
@TechRequired = start

@description = The Stayputnik offers the ultimate solution in crew safety. A "lightweight" sphere equipped with remote receivers, it carries no crew at all, thus keeping them perfectly safe from all harm. This device does require electricity to operate however, and will cease to function if the power runs out. The built-in batteries should keep it going for about 10 minutes.

@cost = 500 // 300 stock

@mass = 0.5 // 0.6 1.522 // 0.05 stock

// noseconeish drag
@maximum_drag = 0.1
@minimum_drag = 0.1
@angularDrag = 0.5

@MODULE[ModuleCommand]
{
!RESOURCE[ElectricCharge]
{
}
}

MODULE
{
name = BTSMModuleProbePower

energyConsumedRate = 0.165 // 6X stock core (0.02777778 rounded to 0.0275)
}

@RESOURCE[ElectricCharge]
{
@amount = 100 // 10 stock
@maxAmount = 100 // 10
}

!MODULE[ModuleReactionWheel]
{
}

!MODULE[ModuleSAS]
{
}

MODULE
{
name = BTSMModulePressureRated
}
}

Let me know if there's any other relevant info I can provide.

Edited by FlowerChild

Share this post


Link to post
Share on other sites

Debug log would be most relevant. I assume it's crashing in the same place - during load?

I just double-checked my own multiple-parts-with-the-same-partmodule-with-background-update test, and it's definitely working over here.

I'm currently in #kspmodders on Espernet if you'd prefer a more real-time chat.

EDIT: Of course you're doing something more complicated than that, duh. Ignore the below:

Incidentally, background processing already does electric charge consumption for ModuleCommands with electric charge in inputResources, so unless you're doing something more complicated than that (or replacing that) you might be able to get away without a callback.

Share this post


Link to post
Share on other sites

EDIT: Of course you're doing something more complicated than that, duh. Ignore the below:

Hehe...yeah, and I'm also using this as a simple test case to see how the system works overall. More complicated stuff like the mod's life support system and resource processors can wait until I've learned the basics of how everything works :)

Will PM you the relevant portions of the log momentarily.

Share this post


Link to post
Share on other sites

All right, as per our discussion last night just tried compiling with .NET Framework 3.5 instead of the 4.5 I was using and everything seems to be working fine so far. I suspect I had changed to 4.5 awhile back to compile relative to another mod I was working with, but really can't remember the details there other than knowing I did it intentionally at some point. Thanks for the help on tracking it down.

On one point of immediate feedback: the debug log spam is currently rather out of control and I suspect I will likely compile my own version of BackgroundProcessing to get rid of that for now. While it might not be a priority for end-users (although I think excessive log spam tends to negatively impact performance), for mod developers it's a rather big deal in being able to track down our own debugging messages amongst a wall of text :)

Share this post


Link to post
Share on other sites
All right, as per our discussion last night just tried compiling with .NET Framework 3.5 instead of the 4.5 I was using and everything seems to be working fine so far. I suspect I had changed to 4.5 awhile back to compile relative to another mod I was working with, but really can't remember the details there other than knowing I did it intentionally at some point. Thanks for the help on tracking it down.

On one point of immediate feedback: the debug log spam is currently rather out of control and I suspect I will likely compile my own version of BackgroundProcessing to get rid of that for now. While it might not be a priority for end-users (although I think excessive log spam tends to negatively impact performance), for mod developers it's a rather big deal in being able to track down our own debugging messages amongst a wall of text :)

AFAIK you really have to compile against .net 3.5 for KSP to load you properly, although that might have changed in 0.90. Good to see it was a simple problem though, and you helped me find a legitimate bug in my code.

Debug log spam should be substantially lessened in the source control head, I just haven't made a release of it. I've been pretty terrible at release management, and occasionally some stuff I left in there for debugging is still there.

  • Like 1

Share this post


Link to post
Share on other sites
AFAIK you really have to compile against .net 3.5 for KSP to load you properly, although that might have changed in 0.90. Good to see it was a simple problem though, and you helped me find a legitimate bug in my code.

Can't remember precisely when I changed it, but I've certainly released several version of BTSM compiled with 4.5, so if it was a problem at some point, it definitely isn't with current versions of KSP or I would have heard back from players about it by now :)

Debug log spam should be substantially lessened in the source control head, I just haven't made a release of it. I've been pretty terrible at release management, and occasionally some stuff I left in there for debugging is still there.

Cool stuff man. That should help a lot.

Share this post


Link to post
Share on other sites

KSP uses .net 3.5, but you can use 4.0 or higher without problems until you run into one.

Share this post


Link to post
Share on other sites
Can't remember precisely when I changed it, but I've certainly released several version of BTSM compiled with 4.5, so if it was a problem at some point, it definitely isn't with current versions of KSP or I would have heard back from players about it by now :)

Previously targetting 4.0+ only went wonky for some specific functionality (from memory, reflection results in fairly consistent breakages if 3.5 isn't targetted) and/or platforms (problems on Linux but not Windows).

Compile against 3.5, it saves you many headaches if things do go wrong.

Share this post


Link to post
Share on other sites

A bit more feedback based on my further experimentation:

It's occurring to me that it would be super useful in implementing custom background processing for a module if some basic data storage on a per module basis were provided.

Looking over the source, it appears you are already doing this kind of thing for stock parts (for example, solar panels) so that when initializing each of the background vessels you can parse the config nodes associated with them once and then refer to that data later on without having to parse it every update.

For custom handlers though, unless I'm missing something, modders aren't really left with much of a choice other than to parse those config nodes every update (which would likely be a nasty drain on performance) or maintain their own independent vessel/module lists to store custom data, which effectively duplicates a lot of the functionality already in BackgroundProcessing.

So what I'm wondering is if it might not be really helpful to have static callback functions for initializing such custom data within a part module, called when BackgroundProcessing initializes the rest of the vessel data, and returning a reference to it. The list of BackgroundProcessing vessel/module data could then contain a reference to it (null by default), and pass it along to the FixedBackgroundUpdate() functions so that custom handlers could type cast it into whatever specific data type we setup and do with it what they will.

To provide a more concrete example, in the case of my probe core energy management code that I posted previously, it would be super handy if I could store whether a particular probe was damaged or disabled during initialization of a background vessel, along with its energy consumption rate, then refer to those stored variables in my custom FixedBackgroundUpdate() function to determine whether it should be draining power or not and how much. I can also see that kind of thing being useful for other things I'm going to be implementing, such as needing to know how many Kerbals are within a part to determine its life support requirements.

So maybe something along these lines:


public static object InitializeCustomModuleData( Vessel vessel, uint uiFlightID )
{
// parse vessel data here

return new BTSMModuleProbePowerBackgroundStorage( bIsActiveCore, fEnergyConsumptionRate );
}

public static void FixedBackgroundUpdate( Vessel vessel, uint uiFlightID, Func<Vessel, float, string, float> ResourceRequestFunc, object customModuleData )
{
BTSMModuleProbePowerBackgroundStorage probeModuleData = (BTSMModuleProbePowerBackgroundStorage)customModuleData;

if ( probeModuleData.m_bIsActiveCore )
{
// do stuff
}
}

Any thoughts on this? The above may not represent the best implementation for such a scheme, but is what struck me as immediately useful while I was working on creating a custom background update handler.

Edited by FlowerChild

Share this post


Link to post
Share on other sites

There's a big difference between the resource module data that I store and providing a generic per-module data store for other users - the resource module info isn't really associated with a given partmodule once I've made it.

If I was storing per partmodule data for modders, I'd have to guarantee that they were getting the same data with the same module, and there's no good identifying features for ProtoPartModuleSnapshots. Mapping the data to an individual ProtoPartModuleSnapshot across a save/load is ugly. I *think* I could do it by using the index into the module list as a key, but that's not a very stable solution under, for example, someone saving the game, removing a mod, and then loading the game.

It has to persist across save/load because someone can close the game while a vessel is in the background and then open it again with the same vessel in the background.

Although now that I think about it, partmodules on an unloaded vessel won't get the opportunity to read from the persistence file, which means the "let them sort it out" option has some problems...

I'll look into it.

Incidentally, as of right now FixedBackgroundUpdate isn't called once per PartModule on unloaded vessels. It's called once per PartModule type per part. So if a Part has two PartModules of the same type that both implement FixedBackgroundUpdate, FixedBackgroundUpdate will only get called /once/ on that partmodule type with that partFlightID. That's another one that's a result of trying to sidestep how tricky it is to keep ProtoPartSnapshot module lists in sync with Part module lists.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now