I've never worked with the extension system in Game Maker outside of JavaScript, but I'm thinking this is actually a possible option for modding.
With my approach (assuming my assumptions are correct) you should be able to create mods that can:
- Create custom objects (with custom code and implementable events) outside of GM
- Have drawing done outside of GM
- Have functions outside of GM
- Manipulate and manage objects in GM with resources made in GM.
- Utilize the GM library and variables from the outside code
Now all of this is some big talk for someone who has never experimented with this kind of technology, but I believe this is completely possible given the techniques that have been talked around the gmc for a while.
For now, I'll just state my idea for the windows platform as that's the easiest for me to conceive of.
How can we do any of this?
- An extension that handles it all. An extension that interacts with other extensions. A wrapper of sorts with a small middle-man interface so people can add their own code to yours.
My Imagined limitations:
A lot of things are going to be limited to what you define to begin with. It's not going to be 100% dynamically moddable, but with enough work it should be robust enough to actually
MOD how your game works.
- People will not be able to directly edit your own objects (their functionality), they will simply be able to
add on to your game. But, if modding is really important to you, I bet you could think something up along with my proposed ideas. IE: (have an object or controller that replaces said object with theirs and etc..etc.. possiblities)
- Regarding the point above, that
does not mean that your objects can't use the added objects and such, you'll just make a system that intelligently works with added objects.
How would we have custom objects?
An empty object. It will be completely controlled by code outside of GML, probably someone's DLL. Class variables, methods, and ETC will be handled here. You'll pre-define what events you want this object to run and your object will call the DLL and make sure that the specific class it's running's code gets executed. Essentially, your GM object will be a reflection of an object in entirely differently language.
What about drawing?
This is where the stuff I am completely hesitant on comes in, but I feel comfortable enough to say that (I think) this has been done and is commonly done in certain extensions. Specifically, if there are extensions out there that can build on top of the 3D engine and render their 3D into game maker from a DLL it should be possible to do more drawing calls. If it gets more complicated than this you can probably go ahead and pass in draw-buffers / surface buffers to the reflecting instance and it can render it from there. There would be other workarounds as well as simply just having the DLL handle what sprite the class is currently implementing as well as having it call some Game Maker library draw calls in its reflected draw call.
Functions outside of GM?
Well, if the objects that are being added to your game are being written and manipulated by in a completely different language they'll be able to utilize all of the features of that language. No problem here.
Okay, this "sounds" nice, but what about actually working with Native GM objects
This sounds tricky, but a few patterns of "dynamic"(not really) patterns have been used to edit variables and manipulate the system. So there are possible ways to do this.
Say a person was working on an extension on an enemy and wanted to "drain" the health of the player.
They would call a function provided by your DLL which in action takes an instance ID (integer), variable name (string), and value (probably string for easier conversions later)
Using this information they could run a commonly used pattern such as:
Code:
with( passedId ){
switch( passedVal ){
case "hp": hp = real( passedValue ); break;
}
}
Similar patterns could be used for having the external code access Game Maker's library and such ->>
You'll probably need to include functions that iterate over objects and find objects. In this scenario, providing asset_get_index() will be a must for anyone trying to have code interact with other instances.
You'll probably want to include a lot of helpful functions in there as well as like collision functions and such, and you'll probably need to add some helper functions of your own to help define and iterate through custom defined instances (which should have unique IDs to define their object names and such )
I see a loophole, how can you access and edit multiple variables and function calls to GM without knowing ahead of time?
This is a tough one. Probably the biggest thing that has stumped me while writing this, but I think there could be a few solutions.
My first idea is using local networking between the DLL and GM utilizing a combination of synchronous TCP reading and writing from the extensions and Game Maker handling the incoming asynchronously. This is the closest to ideal way of accomplishing an abstraction to the modders without having them do a lot of loopholes on their side for handling this situation.
Other than that I imagine the modders would have to implement some sort of asynchronous system with nesting or some sort waiting for you to process the requests (in a loop) on GML's end.
There could be more ways, these are the approaches I'd first attempt.
And all of that being said it may, in fact, be completely possible to have "Extra + Mixed", modded game if you will, content in your game. Sounds pretty complicated huh? I think after you've made something work for one platform like windows the rest would be on similar grounds and the mods could be system independent depending on the language you decided to wrap/how you wrapped it.
- I'd love to hear what others have to say who can confidently answer any of the questions brought up in my proposal.
Edit: I believe, compared to MishMash's proposals, mine is "similar" to his stream idea. Especially since a part of my solution involves blips of networking for asynchronous calls back to GML back-end.