Jump to content

[WIP 0.90] PartOnRails - my 1st project in an attempt to learn C# and KSP modding


Deadpan110

Recommended Posts

Please be kind to this 42 year old dog wanting to learn new tricks!

Help, encouragement and kind words are appreciated.

So hello everyone!

With a background in Linux, Perl, PHP, LUA scripting, server and web design; I have spent the last few years thinking about learning to code mods for this game that occupies a nice chunk of my daily life.

Inspired by the modders in the community, the likes of RoverDude, TriggerAu, TaranisElsu, DMagic and many many more who continually provide their awesome skills to all KSP fans - I have finally bitten the bullet and have decided to stop thinking about it and learn.

Concept

This mod aims to provide an easy way to add background processing to selected individual parts that use their own PartModule while making PartOnRails completely optional for the player.

Modders wanting to make use of the feature do not need to hard code any dependencies (simply do not install the PartOnRails.dll in your game and it wont break any existing mod that makes use of it).

Caveats

  • This mod is potentially a bad idea as there is no multi-threading (although it does make use of coroutine type yields) and anything in the background could potentially slow your game.
  • There is already a mod called BackgroundProcessing which handles things like ElectricCharge from solar panels and also allows modders to implement methods into their PartModule, PartOnRails only exposes the ProtoPartSnapshot to called methods when the part/vessel is not loaded (it is up to the modder on what they want to do with it).

Reason

As stated above, I am wanting to learn (reading docs and howto's is all well and good, but getting feedback and advice from others is far better) and this seems like a fun project.

I do not mind at all if PartOnRails never makes it past Add-on Development but it would be great if I get hints and tips along the way (not just "You are doing it wrong" - but instead "This way is better" followed by the all important "Because <insert reason and links to info here>" :)

Example Usage


[FONT=Monospace] [COLOR=#009695]namespace[/COLOR][COLOR=#333333] MyNamespace[/COLOR]
[COLOR=#333333]{[/COLOR]
[/FONT][FONT=Monospace][COLOR=#009695][FONT=Monospace] [COLOR=#888888][I]//[/I][/COLOR][COLOR=#888888][I]Your [/I][/COLOR][COLOR=#888888][I]KSP[/I][/COLOR][COLOR=#888888][I] PartModule[/I][/COLOR]
[COLOR=#009695]public [/COLOR][COLOR=#009695]class [/COLOR][COLOR=#3364a4]MyPartModule [/COLOR][COLOR=#333333]: [/COLOR][COLOR=#3364a4]PartModule[/COLOR]
[COLOR=#333333]{

[FONT=Monospace] [COLOR=#888888][I]// Enable and show [/I][/COLOR][COLOR=#888888][I]where[/I][/COLOR][COLOR=#888888][I] PartOnRails [/I][/COLOR][COLOR=#888888][I]should [/I][/COLOR][COLOR=#888888][I]look [/I][/COLOR][COLOR=#888888][I]for [/I][/COLOR][COLOR=#888888][I]your [/I][/COLOR][COLOR=#888888][I]methods[/I][/COLOR]
[COLOR=#333333][[/COLOR][COLOR=#333333]KSPField[/COLOR][COLOR=#333333]([/COLOR][COLOR=#333333]isPersistant [/COLOR][COLOR=#333333]= [/COLOR][COLOR=#009695]true[/COLOR][COLOR=#333333],[/COLOR][COLOR=#333333] guiActive [/COLOR][COLOR=#333333]= [/COLOR][COLOR=#009695]false[/COLOR][COLOR=#333333])][/COLOR]
[COLOR=#009695]public[/COLOR][COLOR=#009695] bool [/COLOR][COLOR=#333333]PartOnRails [/COLOR][COLOR=#333333]= true[/COLOR][COLOR=#333333];[/COLOR][/FONT]
[/COLOR][/FONT][/COLOR]
[COLOR=#888888][I]//[/I][/COLOR][COLOR=#888888][I] Optional[/I][/COLOR]
[COLOR=#888888][I]//[/I][/COLOR][COLOR=#888888][I] Called[/I][/COLOR][COLOR=#888888][I] once [/I][/COLOR][COLOR=#888888][I]for [/I][/COLOR][COLOR=#888888][I]each [/I][/COLOR][COLOR=#888888][I]PartOnRails [/I][/COLOR][COLOR=#888888][I]enabled [/I][/COLOR][COLOR=#888888][I]part [/I][/COLOR][COLOR=#888888][I]on [/I][/COLOR][COLOR=#888888][I]EveryScene[/I][/COLOR]
[COLOR=#888888][I]//[/I][/COLOR][COLOR=#888888][I] where[/I][/COLOR][COLOR=#888888][I] time [/I][/COLOR][COLOR=#888888][I]passes[/I][/COLOR][COLOR=#888888][I]([/I][/COLOR][COLOR=#888888][I]KSC[/I][/COLOR][COLOR=#888888][I],[/I][/COLOR][COLOR=#888888][I] Tracking [/I][/COLOR][COLOR=#888888][I]and [/I][/COLOR][COLOR=#888888][I]Flight[/I][/COLOR][COLOR=#888888][I]) [/I][/COLOR][COLOR=#888888][I]if [/I][/COLOR][COLOR=#888888][I]not[/I][/COLOR][COLOR=#888888][I] loaded[/I][/COLOR]
[COLOR=#009695]public[/COLOR][COLOR=#009695] static [/COLOR][COLOR=#009695]void [/COLOR][COLOR=#333333]PartOnRailsStart[/COLOR][COLOR=#333333]([/COLOR][COLOR=#3364a4]ProtoPartSnapshot [/COLOR][COLOR=#333333]part[/COLOR][COLOR=#333333])[/COLOR]
[COLOR=#333333]{[/COLOR]
[COLOR=#3364a4]Debug[/COLOR][COLOR=#333333].[/COLOR][COLOR=#333333]Log[/COLOR][COLOR=#333333]([/COLOR][COLOR=#f57d00]"[/COLOR][COLOR=#f57d00]Part[/COLOR][COLOR=#f57d00]id[/COLOR][COLOR=#f57d00]:[/COLOR][COLOR=#f57d00] " [/COLOR][COLOR=#333333]+ [/COLOR][COLOR=#333333]part[/COLOR][COLOR=#333333].[/COLOR][COLOR=#333333]flightID[/COLOR][COLOR=#333333])[/COLOR][COLOR=#333333];[/COLOR]
[COLOR=#333333]}[/COLOR]
[COLOR=#888888][I]//[/I][/COLOR][COLOR=#888888][I] Optional[/I][/COLOR]
[COLOR=#888888][I]// [/I][/COLOR][COLOR=#888888][I]Called [/I][/COLOR][COLOR=#888888][I]once [/I][/COLOR][COLOR=#888888][I]every [/I][/COLOR][COLOR=#888888][I]frame [/I][/COLOR][COLOR=#888888][I]for [/I][/COLOR][COLOR=#888888][I]each [/I][/COLOR][COLOR=#888888][I]PartOnRails[/I][/COLOR][COLOR=#888888][I] enabled [/I][/COLOR][COLOR=#888888][I]part [/I][/COLOR][COLOR=#888888][I]on [/I][/COLOR][COLOR=#888888][I]EveryScene[/I][/COLOR]
[COLOR=#888888][I]// [/I][/COLOR][COLOR=#888888][I]where[/I][/COLOR][COLOR=#888888][I] time [/I][/COLOR][COLOR=#888888][I]passes[/I][/COLOR][COLOR=#888888][I] ([/I][/COLOR][COLOR=#888888][I]KSC[/I][/COLOR][COLOR=#888888][I],[/I][/COLOR][COLOR=#888888][I] Tracking[/I][/COLOR][COLOR=#888888][I] and [/I][/COLOR][COLOR=#888888][I]Flight[/I][/COLOR][COLOR=#888888][I]) [/I][/COLOR][COLOR=#888888][I]if [/I][/COLOR][COLOR=#888888][I]not[/I][/COLOR][COLOR=#888888][I] loaded[/I][/COLOR]
[COLOR=#009695]public [/COLOR][COLOR=#009695]static [/COLOR][COLOR=#009695]void [/COLOR][COLOR=#333333][FONT=Monospace][COLOR=#333333]PartOnRails[/COLOR][/FONT]Update[/COLOR][COLOR=#333333]([/COLOR][COLOR=#3364a4]ProtoPartSnapshot [/COLOR][COLOR=#333333]part[/COLOR][COLOR=#333333])[/COLOR]
[COLOR=#333333]{[/COLOR]
[COLOR=#3364a4]Debug[/COLOR][COLOR=#333333].[/COLOR][COLOR=#333333]Log[/COLOR][COLOR=#333333]([/COLOR][COLOR=#f57d00]"[/COLOR][COLOR=#f57d00]Part[/COLOR][COLOR=#f57d00]id[/COLOR][COLOR=#f57d00]:[/COLOR][COLOR=#f57d00] " [/COLOR][COLOR=#333333]+ [/COLOR][COLOR=#333333]part[/COLOR][COLOR=#333333].[/COLOR][COLOR=#333333]flightID[/COLOR][COLOR=#333333])[/COLOR][COLOR=#333333];[/COLOR]
[COLOR=#333333]}[/COLOR]
[COLOR=#888888][I]//[/I][/COLOR][COLOR=#888888][I] Optional[/I][/COLOR]
[COLOR=#888888][I]// [/I][/COLOR][COLOR=#888888][I]Called [/I][/COLOR][COLOR=#888888][I]at [/I][/COLOR][COLOR=#888888][I]a [/I][/COLOR][COLOR=#888888][I]fixed[/I][/COLOR][COLOR=#888888][I] time [/I][/COLOR][COLOR=#888888][I]interval [/I][/COLOR][COLOR=#888888][I]determined[/I][/COLOR][COLOR=#888888][I] by [/I][/COLOR][COLOR=#888888][I]the [/I][/COLOR][COLOR=#888888][I]physics [/I][/COLOR][COLOR=#888888][I]time[/I][/COLOR][COLOR=#888888][I] step[/I][/COLOR]
[COLOR=#888888][I]// [/I][/COLOR][COLOR=#888888][I]for[/I][/COLOR][COLOR=#888888][I] each [/I][/COLOR][COLOR=#888888][I]PartOnRails[/I][/COLOR][COLOR=#888888][I] enabled[/I][/COLOR][COLOR=#888888][I] part [/I][/COLOR][COLOR=#888888][I]on [/I][/COLOR][COLOR=#888888][I]EveryScene[/I][/COLOR]
[COLOR=#888888][I]//[/I][/COLOR][COLOR=#888888][I] where [/I][/COLOR][COLOR=#888888][I]time [/I][/COLOR][COLOR=#888888][I]passes [/I][/COLOR][COLOR=#888888][I]([/I][/COLOR][COLOR=#888888][I]KSC[/I][/COLOR][COLOR=#888888][I], [/I][/COLOR][COLOR=#888888][I]Tracking [/I][/COLOR][COLOR=#888888][I]and [/I][/COLOR][COLOR=#888888][I]Flight[/I][/COLOR][COLOR=#888888][I]) [/I][/COLOR][COLOR=#888888][I]if [/I][/COLOR][COLOR=#888888][I]not[/I][/COLOR][COLOR=#888888][I] loaded[/I][/COLOR]
[COLOR=#009695]public [/COLOR][COLOR=#009695]static [/COLOR][COLOR=#009695]void [/COLOR][COLOR=#333333][FONT=Monospace][COLOR=#333333]PartOnRails[/COLOR][/FONT]FixedUpdate[/COLOR][COLOR=#333333]([/COLOR][COLOR=#3364a4]ProtoPartSnapshot [/COLOR][COLOR=#333333]part[/COLOR][COLOR=#333333])[/COLOR]
[COLOR=#333333]{[/COLOR]
[COLOR=#3364a4]Debug[/COLOR][COLOR=#333333].[/COLOR][COLOR=#333333]Log[/COLOR][COLOR=#333333]([/COLOR][COLOR=#f57d00]"[/COLOR][COLOR=#f57d00]Part[/COLOR][COLOR=#f57d00]id[/COLOR][COLOR=#f57d00]:[/COLOR][COLOR=#f57d00] " [/COLOR][COLOR=#333333]+ [/COLOR][COLOR=#333333]part[/COLOR][COLOR=#333333].[/COLOR][COLOR=#333333]flightID[/COLOR][COLOR=#333333])[/COLOR][COLOR=#333333];[/COLOR]
[COLOR=#333333]}[/COLOR]
[COLOR=#888888][I]//[/I][/COLOR][COLOR=#888888][I] Optional[/I][/COLOR]
[COLOR=#888888][I]// [/I][/COLOR][COLOR=#888888][I]Called [/I][/COLOR][COLOR=#888888][I]when[/I][/COLOR][COLOR=#888888][I] the [/I][/COLOR][COLOR=#888888][I]game [/I][/COLOR][COLOR=#888888][I]is [/I][/COLOR][COLOR=#888888][I]leaving [/I][/COLOR][COLOR=#888888][I]the [/I][/COLOR][COLOR=#888888][I]scene [/I][/COLOR][COLOR=#888888][I]for[/I][/COLOR][COLOR=#888888][I] each [/I][/COLOR][COLOR=#888888][I]PartOnRails[/I][/COLOR][COLOR=#888888][I] enabled[/I][/COLOR]
[COLOR=#888888][I]// [/I][/COLOR][COLOR=#888888][I]part [/I][/COLOR][COLOR=#888888][I]on [/I][/COLOR][COLOR=#888888][I]EveryScene[/I][/COLOR][COLOR=#888888][I] where[/I][/COLOR][COLOR=#888888][I] time[/I][/COLOR][COLOR=#888888][I] passes[/I][/COLOR][COLOR=#888888][I]([/I][/COLOR][COLOR=#888888][I]KSC[/I][/COLOR][COLOR=#888888][I],[/I][/COLOR][COLOR=#888888][I] Tracking [/I][/COLOR][COLOR=#888888][I]and[/I][/COLOR][COLOR=#888888][I] Flight[/I][/COLOR][COLOR=#888888][I]) [/I][/COLOR][COLOR=#888888][I]if [/I][/COLOR][COLOR=#888888][I]not[/I][/COLOR][COLOR=#888888][I] loaded[/I][/COLOR]
[COLOR=#009695]public [/COLOR][COLOR=#009695]static [/COLOR][COLOR=#009695]void [/COLOR][COLOR=#333333][FONT=Monospace][COLOR=#333333]PartOnRails[/COLOR][/FONT]OnDestroy[/COLOR][COLOR=#333333]([/COLOR][COLOR=#3364a4]ProtoPartSnapshot [/COLOR][COLOR=#333333]part[/COLOR][COLOR=#333333])[/COLOR]
[COLOR=#333333]{[/COLOR]
[COLOR=#3364a4]Debug[/COLOR][COLOR=#333333].[/COLOR][COLOR=#333333]Log[/COLOR][COLOR=#333333]([/COLOR][COLOR=#f57d00]"[/COLOR][COLOR=#f57d00]Part[/COLOR][COLOR=#f57d00]id[/COLOR][COLOR=#f57d00]: [/COLOR][COLOR=#f57d00]" [/COLOR][COLOR=#333333]+ [/COLOR][COLOR=#333333]part[/COLOR][COLOR=#333333].[/COLOR][COLOR=#333333]flightID[/COLOR][COLOR=#333333])[/COLOR][COLOR=#333333];[/COLOR]
[COLOR=#333333]}[/COLOR]

[COLOR=#888888][I]// [/I][/COLOR][COLOR=#888888][I]Rest[/I][/COLOR][COLOR=#888888][I] of [/I][/COLOR][COLOR=#888888][I]your [/I][/COLOR][COLOR=#888888][I]awesome [/I][/COLOR][COLOR=#888888][I]mod[/I][/COLOR][COLOR=#888888][I] here[/I][/COLOR]

[COLOR=#333333]}[/COLOR]
[COLOR=#333333]}[/COLOR][/FONT]

Links

Source code on GitHub

GNU General Public License version 3

To Follow

This code is under development - core features, optimisations, methods, downloads and example mods are missing but are planned.

Use at your own risk!

I welcome Pull Requests etc.

Edited by Deadpan110
Added source code and licence links
Link to comment
Share on other sites

Thanks all,

I have been struggling a little with possibly how C# and KSP works - its most likely my unfamiliarity with it all (although I do read that C# as well as KSP has a bit of quirky behaviour - lol).

I feel I'm making progress however and hope to have my source code available for viewing soon...

(I though I could have posted it shortly after creating this thread but there were a lot of embarrassing mistakes - too many even for a newbie like myself).

@NathanKell - wow ty, I hadn't seen that project before, lots of stuffs in it I can have a look at (licence seems to not permit raiding, but yeah - definitely some nice things to learn from).

@Starwaster - yeps, I would like to make this threaded (appeals to my love of servers and the home made Beowulf cluster I once owned - I miss that beast) but for now it only makes use of yield (I am not entirely sure how effective yield is within the KSP game loop but some type of yield method will also be beneficial if it ran in its own thread).

Before getting into learning how to use a separate thread safely, I would like to somehow be able to check if the time is close to running over when calling the methods for all background enabled parts and do a more controlled yield - continuing where it left off on the next frame (this means that part mods using PartOnRails should make use of delta time calculations as there is no guarantee their part code will run every frame and could also mean a heavily burdened game will have less parts updated per loop).

Ima enjoying figuring it all out so far so I hope the above makes sense :confused:

Link to comment
Share on other sites

OK, I was kinda shy about my first ever stab at coding a mod... tidied up and committed the source code to GitHub.

The links are in the OP.

I aim to commit changes often now its viewable - and perhaps make an example part and downloads over the weekend :)

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