Jump to content

ModuleScienceLab::ProcessData and the merits of patience


Recommended Posts

EDIT2 answered (thanks xEvilReeperx!) ProcessData is meant to be used in a Coroutine, not called as a regular member function:

 StartCoroutine( myLab.ProcessData( myData, myDoneCallback) );

Read on for my big long sob story of doing it every which way except the right way (facepalm)...

Hi. Grab a beer, pull up a bar stool. It's a long story, and I'm a little frustrated.

I'm trying to automate some science features for my mod. One thing I'd like to do is make a data-research copy of a ScienceData using the MPL Lab via code.

Now - this seems like the obvious choice to do that:

 public IEnumerator ModuleScienceLab::ProcessData( ScienceData item, Callback<ScienceData> onComplete ); 

except when I run it, nothing happens. No "Sending data to vessel labs.." etc print in the log, no top left green text running up a percentage complete, and the callback never fired. I provided a simple dummy print method callback, which never called (no print).

Why doesn't this function work? Is a specific callback expected?

EDIT1 - The following has been answered as a stock bug, thanks to jkortech.

http://bugs.kerbalspaceprogram.com/issues/5212

Next up, we have the magic callback:

 public Callback<ScienceData> ExperimentResultDialogPage::OnSendToLab; 

Now this actually does work. However I don't like this route: you have to call a ReviewData N times for N IScienceDataContainers, to get a result page and therein a callback each, then fire said callbacks and dismiss the dialog yourself, while the user sees N dialogs flash by for 1 frame uninvited... ugh. It's abusing an entire dialog class just to get callback, and we're better than that, damnit.

Ok, so lets get MacGyver:

If we know that OnSendToLab works, and it's a callback, we can use reflection to see what it's calling, and we find it's actually a multidelegate calling

- void ModuleScienceExperiment::sendDataToLab(ScienceData)
- void ExperimentsResultDialog::dismissCurrentPage(ScienceData)

...which I don't see in the assembly object viewer in VS 2015. This leads me to think the delegates are calling private / hidden methods Squad doesn't want us using. So let's use those!

Disclaimer: kids don't do this at home! Abusing reflection to access private methods of strange assemblies that can change at any moment is clearly a quick trip to brittle, breaky code. Beware.

So we roll up our sleeves, remember some reflection code, and arrive here:

Type modSciExperiType = Type.GetType("ModuleScienceExperiment, Assembly-CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); //grabbing types from assemblies other than yours needs fully qualified name
MethodInfo privateMethodInfo = modSciExperiType.GetMethod("sendDataToLab", BindingFlags.Instance | BindingFlags.NonPublic); //specifically search for non-public instance methods to find hidden/private ones
privateMethodInfo.Invoke(myLabModuleInstance, new object[] {myScienceData}); //invoke private method on an instance, passing a science data as a parameter

Now, this actually works. You can directly call it on the module. It prints the "Sending Data to Vessel Labs..." print in log. The green progress text shows up top left. The data gets copied into the lab's research-data bank.

But...it always ends the progress with the top left orange failure text "[MPL] not enough data storage...". Even when the lab clearly has enough storage for said data.

And that's about when I rage quit.

I can accept the brittle factor of using the private sendDataToLab; I feel like that functionality is what ProcessData should have given me to begin with. But spewing a failure message each time, I can't accept. Can RoverDude/NathanKell/Squad bretheren please read my plea, and explain to me what is happening? The function succeeds in every way - except throwing the fail message up to the player.

I'm also open to unknown other ways to get the MPL to make a data-research copy of a ScienceData into an onboard MPL lab.

<clink my beer to yours>As always, any help is appreciated. Thanks for reading.

Edited by SixHourDays
100% answered
Link to comment
Share on other sites

Wow... I haven't done any ships with a lab since 1.02, and was just remembering it working correctly!

Yet, I tested on 1.04 and so did my friend (unrelated save & PCs), and sure enough:

http://bugs.kerbalspaceprogram.com/issues/5212

each and every time.

Ok! Thank you jkortech. I'll update my post to the remaining question; why doesn't ProcessData work in the first place?

Link to comment
Share on other sites

You didn't say how you were calling it, but I suspect that's the problem. It's meant to be used as a coroutine:

private void DoSomethingWithScience(ScienceData data)
{
var myLab = // ModuleScienceLab here

StartCoroutine(myLab.ProcessData(data, ScienceProcessingFinished)); // MonoBehaviour.StartCoroutine
}


private void ScienceProcessingFinished(ScienceData data)
{
PopupDialog.SpawnPopupDialog("Finished", "Science data has been processed", "OK", false, HighLogic.Skin);
}

Link to comment
Share on other sites

THAT is the real answer! Thank you xEvilReeperx.

I was calling ProcessData as a plain member function in my mod's update... calling it as a Coroutine works perfectly, including firing the OnComplete callback.

In hindsight, the IEnumerator return type should have been the hint. My C# experience hadn't encountered Coroutines yet :-) Learn something new every day...

Link to comment
Share on other sites

My C# experience hadn't encountered Coroutines yet :-)

Should make a note here that while the IEnumerator type comes from one of the general C# collections libraries, Coroutines are Unity functionality for classes inheriting from MonoBehaviour.

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...