Jump to content

Daily GameTime Callbacks & C# Reflective Invocation Questions


Recommended Posts

So I'm in the process of making a Subterranean Base mod, and I'm either not happy with the solutions I have, or am completely clueless on problems I'm facing.

First question: Is there a callback/event/etc. that happens whenever a Day ticks in game? I can always implement a polling mechanic on the Universal time to do it myself, but every time I've tried stuff like that, I always introduce time drift bugs, and those will be exasperated by KSP's Time Warp. Is there a function or class that I just overlooked?

Next question: Reflection. For those of you who don't know, reflection is (in CompSci) something that allows you to discover and instantiate objects at Runtime, useful when you don't know the object at compile time. C# supports this, so you could do something like: findAllObjectsImplementingInterface("MyInterfaceName").each { object -> AssemblyInfo.invokeByName(object) } (obviously not C# syntax). I'm looking into this because I can see alot of potential for other mods wanting to create their own Subterranean Base Modules, and since the Subterranean Base exists entirely in code, if I can provide them with an interface they can implement to make their own Base Module, and I can dynamically discover and create the ones others have made in my mod, everyone wins. If a player who has the other mod and not mine plays, the base module will just be dead code, but if they play with both our mods, the module shows up and functions.

My Question is this: Since I am a complete noob to the C# build process...will this work? Will it actually make it easier to interface with other mod makers here, or just make both our lives harder? How will I have to package the mod and interfaces for use by others? Is there an easier solution to this problem I'm completely overlooking?

Thanks to any who has input.

Link to comment
Share on other sites

1) I am not aware of any call back on 'Day' in KSP.

For game time/date, I use Planatarium.GetUniversalTime(), which returns a Double. (Did not check that method name, but it's close.) You then have to do your own math on it. I'm using it for a simple 15 second delay so I have not considered the code needed to do what you are looking for.

2) Yes, reflection works. I'm 99% sure Blizzy's toolbar has example code you could look at. Then just make sure the methods you need for other mods to access to be declared Public so they can be called. (I'm personally not 100% clear on the details, not something I've had to deal with yet for my mods.)

D.

Link to comment
Share on other sites

1. I'm not aware of any, but implementing sth like this with Planetarium.GetUniversalTime() shouldn't be that hard.

2. Jop, that should work. Here is some code i used to find the game's file loading classes and stores them in dictionary by file extension:


return AppDomain
.CurrentDomain
.GetAssemblies()
.SelectMany(assembly => assembly
.GetTypes()
.Where(t => t.IsSubclassOf(typeof(DatabaseLoader<T>)) && t.GetCustomAttributes(typeof(DatabaseLoaderAttrib), true).Any()))
.SelectMany(t =>
{
var loader = (DatabaseLoader<T>)Activator.CreateInstance(t);
return loader.extensions.Select(ext => ext.ToUpper()).Distinct().Select(ext => new { ext = ext, loader = loader });
}).ToDictionary(el => el.ext, el => el.loader);

The code basically loops though all loaded classes, does some checking and uses Activator.CreateInstance to create the actual instances. It worked fine for KSP's stuff and should have for any other assemblies as well, though i never tried that. IsSubclassOf seems to not work on interfaces, so you might want to check out other stuff like IsAssignableFrom or GetInterface.

Link to comment
Share on other sites

Thanks for both the confirmation on the time thing and the examples on how to do the reflection thing; its always nice to see multiple ways of doing stuff so you can pick the best. :)

That just leaves the building/packaging question: in order to minimize the coupling between mods, how would I go about packaging up the interfaces/abstract classes needed? Extract them and put them in their own .dll that both mods reference? Or should I not bother with that if C# is smart enough to figure it out on its own?

Link to comment
Share on other sites

Yes, thats a difficult question, especially when considering version compatibility.

Another mod that implements your interface would have to create a separate DLL for the your-mod-specific stuff anyway (unless it fully depends on your mod). This separate DLL will fail to load without its dependencies, what is kinda fine for KSP installs that doesn't have your mod installed.

A problem might be the order in what mods are loaded. The depended assembly has to either be already loaded or has to be in the same directory as the current dll (+ some other specific paths not in GameData).

A working solution could be for your mod to place a dll with those public interfaces directly within GameData (should be loaded first) & never change its version number.

Link to comment
Share on other sites

A problem might be the order in what mods are loaded. The depended assembly has to either be already loaded or has to be in the same directory as the current dll (+ some other specific paths not in GameData).

To get around this problem in RasterPropMonitor, Mihara created DLLs that were intended to load after the linked DLL. To enforce ordering, they are in separate directories that have the original mod's directory name + "RPM" tacked on to the end (eg, the SCANsat RPM DLL lives in SCANsatRPM, so it loads after SCANsat does, and after RasterPropMonitor (which is in the directory JSI). It's not the prettiest looking approach, but it guarantees the interface DLL loads after the DLLs it's interfacing with.

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