Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

Could some one please tell me what happened to "Staging"?

Between 1.1.2 and 1.1.3 it seems to have moved or gone.

There used to be a public class in Assembly-CSharp and now I just get "The name 'Staging' does not exist in the current context"

Sure I just being dumb but if some one could enlighten me that would be wonderful.

Link to comment
Share on other sites

37 minutes ago, Z-Key Aerospace said:

Could some one please tell me what happened to "Staging"?

Between 1.1.2 and 1.1.3 it seems to have moved or gone.

There used to be a public class in Assembly-CSharp and now I just get "The name 'Staging' does not exist in the current context"

Sure I just being dumb but if some one could enlighten me that would be wonderful.

I believe it was superseded in 1.1.0 by KSP.UI.Screens.StageManager but the old Staging class wasn't removed until 1.1.3.

Link to comment
Share on other sites

I´m using the EditorGizmos.GizmoRotate and EditorGizmos.GizmoOffset to move and rotate objets in the flight scene with this code (for Offset):

gofs = EditorGizmos.GizmoOffset.Attach(loadedTrack.cpList[editionCp].transform, rCompTran, rCompTran);

Now in KSP 1.1.3 using same code there are no errors logged, the transform.position seem correct, but the gizmos does not show at all.

Is there any change on gizmo behaviour?

(blame google for confusing translation!)

Link to comment
Share on other sites

  • 3 weeks later...

I have a menu that displays some information about Kerbals on my ship such as what their name is, their trait.  I also want to use two buttons:  EVA and Crew Transfer.  I just figured out how to initialize the EVA ( FlightEVA.SpawnEVA (ProtoCrewMember.KerbalRef) for reference).

 

For the crew transfer, I've checked out Sarbian's Crew Manifest and going by the API, it looks like I should be looking at the Monobehaviour.CrewTransfer class, specifically the Create(Part, ProtoCrewMember, Callback<CrewTransfer.DismissAction>) method.  However, Sarbian's code doesn't seem to match up with that class and I'm not sure why, specifically lines 190-204 of CrewManifestModule.  Indeed, he doesn't seem to use it in any of his code.  Can anyone explain why he would need to create his own class instead of using the one with KSP?  Or what the Callback method/pointer is for?

To give reference to what I'm envisioning, I'd want the user to press the Transfer button next to the Kerbal's name (which will already have access to the ProtoCrewMember of that Kerbal) and then click on the part that they want to transfer to.  Basically identical to the right-click context menu's Crew Transfer but in my own GUI window.

Link to comment
Share on other sites

7 minutes ago, Tralfagar said:

I have a menu that displays some information about Kerbals on my ship such as what their name is, their trait.  I also want to use two buttons:  EVA and Crew Transfer.  I just figured out how to initialize the EVA ( FlightEVA.SpawnEVA (ProtoCrewMember.KerbalRef) for reference).

 

For the crew transfer, I've checked out Sarbian's Crew Manifest and going by the API, it looks like I should be looking at the Monobehaviour.CrewTransfer class, specifically the Create(Part, ProtoCrewMember, Callback<CrewTransfer.DismissAction>) method.  However, Sarbian's code doesn't seem to match up with that class and I'm not sure why, specifically lines 190-204 of CrewManifestModule.  Indeed, he doesn't seem to use it in any of his code.  Can anyone explain why he would need to create his own class instead of using the one with KSP?  Or what the Callback method/pointer is for?

To give reference to what I'm envisioning, I'd want the user to press the Transfer button next to the Kerbal's name (which will already have access to the ProtoCrewMember of that Kerbal) and then click on the part that they want to transfer to.  Basically identical to the right-click context menu's Crew Transfer but in my own GUI window.

Pretty much what @Papa_Joe does in Ship Manifest then.

Link to comment
Share on other sites

13 hours ago, JPLRepo said:

Pretty much what @Papa_Joe does in Ship Manifest then.

The reason I do not use the class @Tralfagar mentioned is 1)  It did not exist when these mods were created, and 2), it does not give me sufficient resolution for my needs.  The class works just fine, but does not give you the ability to pick a specific seat, nor does it allow for crew swaps.  In ShipManifest, I account for both.  Therefore I've continued to use the method similar to CrewManifest, but with several enhancements.  ShipManifest will allow seat to seat transfers within the same part, and part to part transfers (including swapping crew members if the seat/part is full in both cases).  Additionally, in Realism mode, I've also included sounds and a delay to simulate the time needed to move from part to part or seat.

Additionally, I've included support for ConnectedLivingSpace, When in realism mode and with CLS enalbled within SM, transfers now respect whether or not the parts have an internal connection to each other. if not, then the transfer must be accomplished by EVA.  hmm... you gave me an idea.  if you cannot transfer internally, I could change the xfer button to initiate an eva instead...

 

Update.  I've added the capability to send a Kerbal EVA in realism mode if CLS prevents an internal transfer.  I will be releasing this feature soon in a point upgrade.   thanks for giving me this great idea.

@Tralfagar feel free to look over and leverage any of the code you see of value in SM.  I hope it helps you in some small way.  

Edited by Papa_Joe
grammer, spelling, clarifications
Link to comment
Share on other sites

From a recent devnotes:

Quote

code optimisations: removing foreach() loops and linq statements. It’s a very technical story, but ultimately it will help run the game more smoothly by reducing the amount of ‘garbage’ that is created in the memory and that has to be removed regularly.

 

So, uh.. I guess mod developers should be doing this too?

I just looked and one of my OnUpdate()'s has nested foreach() loops:

foreach (PartResource pumpRes in part.Resources) {
  ...
  foreach (Part shipPart in vessel.Parts) {
    ...
    foreach (PartResource shipPartRes in shipPart.Resources) {
      ...

What should we be replacing foreach() with?

Also if I'm not using "from" or "select" then I'm not using linq, right?  Anything else to look out for to avoid making garbage that needs to be collected?

Link to comment
Share on other sites

33 minutes ago, hab136 said:

From a recent devnotes:

 

So, uh.. I guess mod developers should be doing this too?

I just looked and one of my OnUpdate()'s has nested foreach() loops:


foreach (PartResource pumpRes in part.Resources) {
  ...
  foreach (Part shipPart in vessel.Parts) {
    ...
    foreach (PartResource shipPartRes in shipPart.Resources) {
      ...

What should we be replacing foreach() with?

Also if I'm not using "from" or "select" then I'm not using linq, right?  Anything else to look out for to avoid making garbage that needs to be collected?

Depends. foreach is OK if you are using Visual Studio. replace them with for loops if you want.
The most efficient is:
 

for (int i = <something>.Length - 1; i >= 0; --i)
                

IF you have the following then you are using linq somewhere.

using System.Linq;

There are lots of things that are bad. Another is strings.
Another useful links I found. But just google...
http://www.gamasutra.com/blogs/WendelinReich/20131109/203841/C_Memory_Management_for_Unity_Developers_part_1_of_3.php

 

Link to comment
Share on other sites

1 hour ago, JPLRepo said:

Depends. foreach is OK if you are using Visual Studio.

This is only true if the GetEnumerator function of the object you are doing it on returns a struct type.  If it returns a class type or an interface then it will cause garbage with any compiler.  System classes like List<T> do return a struct but some of the KSP classes that are basically a wrapper around a List<T> return an interface (e.g. PartResourceList).  These are on the list for fixing for KSP 1.2 though with that sort of nesting, you will probably get better performance with plain for loops (using foreach also requires the code to make two function calls to the enumerator object every time around the loop).

1 hour ago, JPLRepo said:

The most efficient is:


for (int i = <something>.Length - 1; i >= 0; --i)

Bear in mind that this will go through the list in the opposite order, which may affect what your code does.  To go forwards through the list do:

int count = <something>.Length; // (or .Count or whatever works for the object concerned)
for (int i = 0; i < count; ++i)
2 hours ago, hab136 said:

I just looked and one of my OnUpdate()'s has nested foreach() loops:

Doing that on every update is probably affecting the performance of the game quite considerably.  You would be better off looking for another way to do what you are doing, e.g. by caching a list of the things you actually need to loop through and use relevant GameEvents to trigger updates of the list.

Link to comment
Share on other sites

3 hours ago, JPLRepo said:

IF you have the following then you are using linq somewhere.


using System.Linq;

 

Not necessarily, since VS adds that to the using list by default.

But the quickest way to check if you are using Linq is to delete that using line if it's there. Then everything with Linq will have errors. And there are many more things other than the From, Select that use Linq; lots of methods that are used to modify or specify certain members of a list use it, like Any, OfType, Where, First, FirstOrDefault, etc...

Link to comment
Share on other sites

Hi All,

For one of my mods I store and read data from the mod folder

I'm currently using this to get the gamepath

GamePath = System.IO.Directory.GetParent(Application.dataPath);
        

This is appended with the path to the game folder:

string CommercialOfferingsPath = "/GameData/RoutineMissionManager/";

 

However this apparently does not work on a mac. I've tried something like

                GamePath = System.IO.Directory.GetParent(Application.dataPath);
                if (GamePath.Name.Length > 7 && GamePath.Name.Substring(GamePath.Name.Length - 8) == "KSP.app")
                    GamePath = GamePath.Parent;

apparently this does not work.

 

Since I don't own a mac, this is hard for me to test. According to Unity site "Application.dataPath" refers to the  <path to player app bundle>/<AppName.app>/Data. So I'm inclined to try something along the lines "GamePath.Parent.Parent" For mac. Would this work? Could anyone give me some quick tips on how to handle this?

 

Link to comment
Share on other sites

I'm really stumped on this one, does anybody know how to get the staging icon to appear/vanish in the VAB/SPH? I know that PartModule now has fields and methods related to staging such as:

    public bool overrideStagingIconIfBlank;
    [KSPField]
    public string stagingDisableText;
    [KSPField(isPersistant = true)]
    public bool stagingEnabled;
    [KSPField]
    public string stagingEnableText;
    [KSPField]
    public bool stagingToggleEnabledEditor;
    [KSPField]
    public bool stagingToggleEnabledFlight;

    public virtual string GetStagingDisableText();
    public virtual string GetStagingEnableText();
    public virtual bool IsStageable();
    public virtual void SetStaging(bool newValue);
    public virtual bool StagingEnabled();
    public virtual bool StagingToggleEnabledEditor();
    public virtual bool StagingToggleEnabledFlight();
    [KSPEvent(guiActiveEditor = false, guiActive = false, guiName = "Disable Staging")]
    public void ToggleStaging();
    public virtual void UpdateStagingToggle();

My custom part module has the fields set up like so:

	MODULE
	{
		name = MyPartModule
		stagingEnableText =  Staging ON
		stagingDisableText = Staging OFF
		stagingEnabled = true
		stagingToggleEnabledEditor = true
		stagingToggleEnabledFlight = true
		overrideStagingIconIfBlank = true
	}

In the VAB/SPH, I can toggle the staging button. But unlike, say, ModuleDecoupler, no icon shows up. Is there something extra I need to do to get an icon in the staging list? One of the default icons is just fine.

Link to comment
Share on other sites

1 hour ago, Angel-125 said:

In the VAB/SPH, I can toggle the staging button. But unlike, say, ModuleDecoupler, no icon shows up. Is there something extra I need to do to get an icon in the staging list? One of the default icons is just fine.

AFAIK you need to make sure the part.stagingIcon is not string.Empty. Set it with a  DefaultIcons.XXXX.toString();

Link to comment
Share on other sites

8 hours ago, sarbian said:

AFAIK you need to make sure the part.stagingIcon is not string.Empty. Set it with a  DefaultIcons.XXXX.toString();

Thanks for the info. I set the part.stagingIcon to a default icon. Unfortunately I'm still not seeing anything show up in the staging list, but I appreciate the suggestion. :) Maybe @Mu or @NathanKell knows how to set up a part module to make the staging icon show up?

Link to comment
Share on other sites

For my plugin, I want to do some background processing on unfocused vessels:  Adding a given amount of resources over time to a vessel implementing my plugin and occasionally spawn new Kerbals on those vessels when a limit is hit.  Initially, I was going to use the Background Processing mod by @jamespicone.  But now that I've done some research, it seems that mod may be overkill for what I want to do.  Looking through the API, it looks like I can use FlightGlobals.vessels to get a list of all vessels in the game, and use vessel.isActiveVessel to determine if it is focused or not.  It would look something like this:

void checkBackgroundVessels()
    {
      foreach(Vessel myVessel in FlightGlobals.Vessels)
      {
        if (!myVessel.isActiveVessel && myVessel.FindPartModulesImplementing<myModule> () != null) {
            //do some stuff
        }
      }
    }

However, Background Processing specifically mentions accessing ProtoVessels instead of Vessels.  Is there an issue with accessing vessels that are unfocused?  Or am I going to hit a brick wall down the road?

Edited by Tralfagar
Formatting
Link to comment
Share on other sites

14 minutes ago, Tralfagar said:

For my plugin, I want to do some background processing on unfocused vessels:  Adding a given amount of resources over time to a vessel implementing my plugin and occasionally spawn new Kerbals on those vessels when a limit is hit.  Initially, I was going to use the Background Processing mod by @jamespicone.  But now that I've done some research, it seems that mod may be overkill for what I want to do.  Looking through the API, it looks like I can use FlightGlobals.vessels to get a list of all vessels in the game, and use vessel.isActiveVessel to determine if it is focused or not.  It would look something like this:


void checkBackgroundVessels()
    {
      foreach(Vessel myVessel in FlightGlobals.Vessels)
      {
        if (!myVessel.isActiveVessel && myVessel.FindPartModulesImplementing<myModule> () != null) {
            //do some stuff
        }
      }
    }

However, Background Processing specifically mentions accessing ProtoVessels instead of Vessels.  Is there an issue with accessing vessels that are unfocused?  Or am I going to hit a brick wall down the road?

You can't access the resources,etc for vessels that are on rails (packed). In that case you have to access/update the ProtoVessel.

Link to comment
Share on other sites

How to delete/add part from/to (current) ship? As in: Poof, nothing left. Poof, suddenly part hangs from node.

I made button in context menu on part, I got child part from attachment node (which of course is not a child of attachment node owner even if it is root part, ugh). But actual handling appears to be more complex than simple calling Remove(child).

I dug out ProtoPartSnapshot, cloned part with it, then filled out attachedPart, called Couple(). And game freezes to death.

So I checked KAS/KIS sources, found a lot of dark magic inside. Is all that initializing/synchronizing magic really necessary? Is there no simpler way?

Link to comment
Share on other sites

I

On 7/27/2016 at 3:34 AM, PT said:

How to delete/add part from/to (current) ship? As in: Poof, nothing left. Poof, suddenly part hangs from node.

I made button in context menu on part, I got child part from attachment node (which of course is not a child of attachment node owner even if it is root part, ugh). But actual handling appears to be more complex than simple calling Remove(child).

I dug out ProtoPartSnapshot, cloned part with it, then filled out attachedPart, called Couple(). And game freezes to death.

So I checked KAS/KIS sources, found a lot of dark magic inside. Is all that initializing/synchronizing magic really necessary? Is there no simpler way?

I'd also like to know how to spawn a part to a part in scene. From my mucking around I've been using the following to kill a via a button, however it also kills anything that was surface attached as well. Anything node attached becomes debris. Is there something that will keep surface attached items?

thisPart.part.Die();

 

Edited by wile1411
Link to comment
Share on other sites

5 hours ago, wile1411 said:

I

I'd also like to know how to spawn a part to a part in scene. From my mucking around I've been using the following to kill a via a button, however it also kills anything that was surface attached as well. Anything node attached becomes debris. Is there something that will keep surface attached items?


thisPart.part.Die();

 

I think you need to part.Decouple every part you want to keep. You might also want to rename decoupled parts. That's how KAS/KIS does it.

However, if you want to remove part in middle but keep ship intact, part coupling will be necessary, and that is overly complicated.

I picked different approach in my project.

  1. Save game
  2. Edit .sfs
  3. Save modified .sfs
  4. Load game

(mods can save and load saves)

Of course there are other problems, as .sfs format can hardly be called format. More than half of its content does nothing. I am making little ugly .sfs editor library. As of now I can recursively delete parts from part tree with it. Sometimes modified .sfs can even be loaded correctly in game :wink:

Using that sfs library I managed to delete parts from cargo bay inner nodes (named top2 and bottom2), sum their mass (I still need to find way to get weight of resources in part), add/remove resources and so on. Oh, I also can .Open() .Close() on cargo bay parts :)

After playing with first version of my lib I learned enough to make second edition, which should be able to delete parts without breaking part tree. Which is not a tree. It is list, with references to other item. And of course references are in various forms. Node attachments are both ways (parent<->child) while surface attachments are one way (child->parent). Oh, and of course there are no part id's specified in part itself, it is just index of PART entry in VESSEL entry in save file, so order is important (looks like someone hit graph with sledgehammer few dozen times to flatten it). All this trash means that removing part requires recalculating id's of every part in order to attachment node info. Ugh.

Adding parts will require calculating position, but it does not seem hard as it is relative to root or parent part if I am not mistaken.

If you are interested I can share my proof of concept code. Proper release must wait for code I won't be ashamed of.

Link to comment
Share on other sites

32 minutes ago, PT said:

Adding parts will require calculating position, but it does not seem hard as it is relative to root or parent part if I am not mistaken.

If you are interested I can share my proof of concept code. Proper release must wait for code I won't be ashamed of.

If you do have a proof of concept bit of code, it'd be great to have a look.

Is all the clean up necessary only if you want to keep a tree intact when pruning from the middle? I figures with craft always being broken via various impacts, that killing off a parts should be within scope of the default process.

I'm looking to use a part I've built and add a part to that known piece as an "end node". Depending on when the player does down the track, I plan to remove it later using the part.die command. I was hoping with the information I already know about my parts location and orientation, spawning in a part attached to it could be a matter of working out the location if reference to the known part rather than from the root part.

 

Link to comment
Share on other sites

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