Facepunch / garrysmod-requests

Feature requests for Garry's Mod
83 stars 24 forks source link

Enable the loading of Plugins on Local/Singleplayer games #931

Open ghost opened 7 years ago

ghost commented 7 years ago

I'm currently writing a module which must call something every frame- to accomplish this and prevent having to sigscan for gmod_gamerules functions I decided to make it use the plugin interface. However, the problem I've run into is that, at least to my knowledge, there is no way of loading plugins in local/singleplayer games (which is what the module is intended to be used for). Can this be changed?

neico commented 7 years ago

https://developer.valvesoftware.com/wiki/Client_plugins

might help you, unless it's entirely disabled on gmod...

ghost commented 7 years ago

@neico This is a serverside plugin.

neico commented 7 years ago

But what you described is a client plugin as it runs on the client, it doesn't matter on which state it runs in (listenserver or client), it stops being a server plugin once it's not run on a dedicated server.

As a matter of fact a "client" is both client and server side, while a dedicated server is only server side.
To make it a bit more clear: the server side inside the client is called listenserver, as it's the client and server in one instance.
And to prevent cheats valve added this safeguard on the client.

Though I have issues following your rationale about using a plugin in the first place as a lua module is essentially a plugin with extended permissions (such as being able to access the lua stack / states), you just have to include the headers and do some GetProcAddress call stuff.

https://github.com/alliedmodders/hl2sdk/tree/gmod should help you in that regard a bit...

ghost commented 7 years ago

@neico I'm writing a module, but also using the plugin interface with it so I can access the callbacks the engine gives to it. I.e. CMyPlugin::GameFrame and all that.

Oh, and what do you mean by GetProcAddress stuff? I could load the plugin offline/hook into callbacks by using it?

neico commented 7 years ago

https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx

Scroll down a bit for a example usage, using this method you can pretty much access any interface (you just need to target client.dll / server.dll respectively), see:

https://github.com/alliedmodders/hl2sdk/blob/gmod/game/client/cdll_client_int.cpp#L677 https://github.com/alliedmodders/hl2sdk/blob/gmod/public/tier1/interface.h#L73

and for some internal details: https://github.com/alliedmodders/hl2sdk/blob/gmod/tier1/interface.cpp#L58

in the interface.h/cpp files are also some utility functions that use GetProcAddress as well so they might help you figure this stuff out (and show you how to do it on non-windows as well if needed)

I had some example code doing that stuff from inside a lua module once, but don't have it at hand right now, so I hope those links provide sufficient information to get you what you need instead...

PS: getting something called every frame should be doable by adding a "Tick" hook or?
https://github.com/Bromvlieg/gm_bromsock/blob/master/Source/gm_bromsock/Objects/Engine.cpp#L196

ghost commented 7 years ago

@neico Using the Lua interface to add Think hooks would work, yes- But what has me worried is speed. Many calculations/algorithms will have to be run (The purpose of this module is to add AI player bots to the game), and I feel a bit iffy about the speed that approach will allow, especially since it's calling the Lua func from C++, which then has to call the C++ func from Lua, etc.

Oh, and a note, I realize that I can access the interfaces without plugins and I know what to do for that, my problem now is just being able to get the engine to send a callback for GameFrame.

neico commented 7 years ago

For now the "Think" / "Tick" hook is your best chance then,
I'll spend some time investigating in how to access the GameFrame / Think functions as it looks like it'll be tricky to get a callback for those.

Feel free to investigate yourself: https://github.com/LestaD/SourceEngine2007/tree/master/se2007

If performance is a concern you can always put the actual AI into a separate thread and then make a synchronized lua call whenever there's something the game needs to know (move commands etc.),
the link above about gm_bromsock shows how such a thing can be done (granted, the code isn't the easiest to read)

PS: I guess it would be a great thing if there were some extra functions (we currently only have gmod_load and gmod_unload) / interfaces exposed for lua modules, ones that expose things such as Think()

ghost commented 7 years ago

@neico The other option would be to sigscan for the gmod_gamerules entity's "EndGameFrame" function and through some not-very-fun memory manipulation "hook" into it (CS:S uses this function for their bot code), but of course that'd be hell.

mcd1992 commented 7 years ago

The plugin_load concommand was removed but you can still use vdf files to load plugins.

https://developer.valvesoftware.com/wiki/Server_plugins#Installing https://gitlab.com/fgthouse/fgt_navstuff/wikis/loading-module-as-a-source-plugin https://gitlab.com/fgthouse/fgt_navstuff/blob/master/src/plugincallbacks.cpp#L139

EDIT: Actually, reading my own wiki I wrote 2 years ago... 'This module can unfortunatly only be loaded on dedicated servers, you can thank Garry for that'. Not sure if that means the client ignores vdfs or what.