Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin interfaces (plugins v4) #615

Merged
merged 73 commits into from
Feb 4, 2024

Conversation

uniboi
Copy link
Contributor

@uniboi uniboi commented Dec 14, 2023

Replaces the current plugin api with source interfaces.

  • backwards compatible
  • no more json in binaries (wtf)
  • does not rely on structs from third party libraries (wtf)
  • actually initializes variables
  • no more basically unused classes

The launcher exposes almost everything required by plugins in interfaces that allow for backwards compatibility.
The only thing that's passed to a plugin directly is the northstar dll HWND and a struct of data that's different for each plugin.

Plugins are required to expose a void* CreateInterface(const char* name, int* status) function to share their own interfaces.
The launcher loads the PluginId interface from the plugin to query info such as it's name.

Plugins can use the CreateInterface function exposed by the Northstar DLL to use Northstar interfaces such as for logging.
An interface is just an abstract class to force all functions into a vftable.

Northstar Interfaces

NSSys001

Exposes some system functionality to plugins

// 32 bit
enum LogLevel {
  INFO,
  WARN,
  ERR,
};

// handle: handle of the plugin. Passed to the plugin on init.
void Log(HMODULE handle, LogLevel level, char* msg); // logs a message with the plugin's log name
void Unload(HMODULE handle); // unloads the plugin
void Reload(HMODULE handle);

Required Plugin Interfaces

Interfaces that have to be exposed for the plugin to be loaded.

PluginId001

// strings of data about the plugin itself. may be extended in the future
// 32 bit
enum PluginString {
  NAME, // the name of the plugin
  LOG_NAME, // the name used for logging
  DEPENDENCY_NAME, // the name used for squirrel dependency constants created. The value returned for this has to be a valid squirrel identifier or the plugin will fail to load
}

// bitfields about the plugin
// 32 bit
enum PluginField {
  CONTEXT // 0x1 if the plugin is allowed to run on dedicated servers and 0x2 if the plugin is allowed to run on clients (is this even needed seems useless to me)
}

char* GetString(PluginString prop);
i64 GetField(PluginField prop);

PluginCallbacks001

struct PluginNorthstarData { HMODULE handle; };

// COPY THE initData IT MAY BE MOVED AT RUNTIME
void Init(HMODULE nsModule, const PluginNorthstarData* initData, bool reloaded); // called after the plugin has been validated. The nsmodule allows northstar plugins to work for the ronin client as well (assuming they update their fork lmao)
void Finalize(); // called after all plugins have been loaded. Useful for dependencies
void Unload(); // called just before the plugin is getting unloaded
void OnSqvmCreated(CSquirrelVM* sqvm); // the context of the sqvm is contained in the instance
void OnSqvmDestroying(CSquirrelVM* sqvm); // callback with the sqvm instance that's about to be destroyed (for UI, CLIENT is destroyed for some reason??)
void OnLibraryLoaded(HMODULE module, const char* libraryName); // called for any library loaded by the game (for example engine.dll)
void RunFrame(); // just runs on every frame of the game I think

What's an interface anyways?

Interfaces are just abstract classes. So make sure the first parameter is always a pointer to the instance of the interface you're using.

an example what NSSys001 looks like in C:

typedef enum {
  LOG_INFO,
  LOG_WARN,
  LOG_ERR,
};

typedef struct CSys {
  struct {
    void (*log)(struct CSys* self, HMODULE handle, LogLevel level, char* msg);
    void (*unload)(struct CSys* self, HMODULE handle);
  }* vftable;
} CSys;

// use like this
g_c_sys->vftable->log(g_c_sys, g_handle, LOG_INFO, "my balls are itching");

Interfaces are created with CreateInterface that's exposed in another dll.

Removed stuff

  • plugins no longer get cvar constructs etc. Instead they are required to use the game's interfaces (the shocker)
  • no squirrel api functions are exposed. Plugins need to collect the pointers themselves
  • plugins are required to implement their own message buffer for the sqvm if necessary. Thank god because the one in NS sucks
  • no more plugin_abi.h that you can include in plugins for the required typedefs. Not a big con because that barely worked to begin with because of the billion files the plugin_abi.h file included.

I've made an example plugin that I try to keep up to date with the new api

That's it not really that complicated imo

Copy link
Member

@catornot catornot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

everything looks good now :)
seams to be all working well with rrplug.

although probably later there should be a pr to expose access to some hooked northstar functions.

@uniboi
Copy link
Contributor Author

uniboi commented Jan 21, 2024

yeah interfaces aren't done and I wouldn't even consider the ones in this PR final, this is just to replace the plugin sys and expand on interfaces later

@github-actions github-actions bot added the merge conflicts Blocked by merge conflicts, waiting on the author to resolve label Jan 21, 2024
@uniboi uniboi closed this Jan 22, 2024
@uniboi
Copy link
Contributor Author

uniboi commented Jan 22, 2024

what

@uniboi
Copy link
Contributor Author

uniboi commented Jan 22, 2024

note to self; read git output before force pushing

@uniboi uniboi reopened this Jan 22, 2024
@GeckoEidechse GeckoEidechse added almost ready to merge Apart from any small remaining other issues addressed by other labels, this would be ready to merge and removed merge conflicts Blocked by merge conflicts, waiting on the author to resolve labels Jan 22, 2024
primedev/plugins/interfaces/sys/ISys.cpp Show resolved Hide resolved
primedev/plugins/pluginmanager.h Show resolved Hide resolved
primedev/plugins/plugins.cpp Outdated Show resolved Hide resolved
primedev/plugins/plugins.cpp Outdated Show resolved Hide resolved
primedev/plugins/plugins.cpp Show resolved Hide resolved
Copy link
Member

@GeckoEidechse GeckoEidechse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-confirmed working in testing. Tested with:

Copy link
Member

@GeckoEidechse GeckoEidechse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skimmed code a bit again and overall I also like the improvement in code quality here and there (as far as I could tell).

I'm just gonna hope that other code reviews found all the potential issues and the rest we figure out post-merge ig ^^

@GeckoEidechse GeckoEidechse dismissed ASpoonPlaysGames’s stale review February 4, 2024 01:07

requested have been addressed

@GeckoEidechse
Copy link
Member

GeckoEidechse commented Feb 4, 2024

* requested changes have been addressed
(thanks for not letting me edit review dismiss GitHub, very great)

@GeckoEidechse GeckoEidechse changed the title Plugin interfaces Plugins v4 / interfaces Feb 4, 2024
@GeckoEidechse GeckoEidechse changed the title Plugins v4 / interfaces Plugin interfaces (plugins v4) Feb 4, 2024
@GeckoEidechse GeckoEidechse merged commit edf0139 into R2Northstar:main Feb 4, 2024
3 checks passed
@uniboi uniboi deleted the plugins/nsiface branch February 4, 2024 10:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
almost ready to merge Apart from any small remaining other issues addressed by other labels, this would be ready to merge needs code review Changes from PR still need to be reviewed in code
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

4 participants