alliedmodders / sourcepawn

A small, statically typed scripting language.
Other
369 stars 63 forks source link

[Feature Request] Multiple implementation of forwards #789

Open TheByKotik opened 2 years ago

TheByKotik commented 2 years ago

I'll be short: Sometimes we all use libs and sometime libs require to calling initial functions for hooking something, checking and etc

1. Simple example:

// csgo_colors.inc
// Implements chat colors for csgo only
public APLRes AskPluginLoad2 (Handle myself, bool late, char[] error, int err_max)
{
    char szGameFolder[32];
    GetGameFolderName( szGameFolder, sizeof szGameFolder );
    if ( !strcmp( szGameFolder, "csgo" ) )
    {
        strcopy( error, err_max, "Not a CS:GO!" );
        return APLRes_Failure;
    }
    return APLRes_Success;
}

Dev of this library want to check game to prevent errors but what if dev of plugin that used this library require to use AskPluginLoad2 too? Okay, dev of lib add function that must be called in AskPluginLoad2 by plugin but what if dev of plugin forget it? Okay, this is not critical by what if library require detect game, as example, this may be lib for L4D1/2

2. More complex example:

Some time ago i need to rewrite very old plugin that implement bans / mutes / gags system (like SourceBans++), original plugin was very dirty, many strange names of functions, sometime params was DataPack instead 4-7 simple types (funcs were never called asynchronously) and i started write re:0 I fast seen that all of punishments require almost same funcs but different was only implement punishment func Good idea just isolate each punishment type with all variable and funcs I used macros-templating for this, but it's not important Each type require to register command, connect translations and etc Okay, i just create some functions:

// bans.sp
void Bans_OnPluginStart ()
{
/**/
}
// mutes.sp
void Mutes_OnPluginStart ()
{
/**/
}
// Gags.sp
void Gags_OnPluginStart ()
{
/**/
}
// Plugin.sp
#include "bans.sp"
#include "mutes.sp"
#include "gag.sp"

public void OnPluginStart ()
{
  Bans_OnPluginStart();
  Gags_OnPluginStart();
  Mutes_OnPluginStart(); 
}

You can see from the examples that if we can just implement one forward several times in the plugin, this will greatly simplify such implementations

3. So I suggest adding syntax like this:

// Just idea, not real

// csgo_colors.inc
static APLRes color_AskPluginLoad2 (Handle myself, bool late, char[] error, int err_max) : AskPluginLoad2 
{
    char szGameFolder[32];
    GetGameFolderName( szGameFolder, sizeof szGameFolder );
    if ( !strcmp( szGameFolder, "csgo" ) )
    {
        strcopy( error, err_max, "Not a CS:GO!" );
        return APLRes_Failure;
    }
    return APLRes_Success;
}
// plugin,sp
#include "csgo_colors.inc"
static APLRes plugin_AskPluginLoad2 (Handle myself, bool late, char[] error, int err_max) : AskPluginLoad2 
{
/**/
}

In low level implementation we just did this:

public APLRes AskPluginLoad2 (Handle myself, bool late, char[] error, int err_max)
{
  color_AskPluginLoad2();
  plugin_AskPluginLoad2();
}
Alienmario commented 1 year ago

Could this get implemented, even if just for simple no return callbacks? Right now, libraries are very limited in what they can do on their own. There's also an ugly solution by redefining functions with #define that I'd rather not use.

Alienmario commented 1 year ago

If it makes it any easier, I could also see this being implemented on methodmaps. For example

// cool_include.inc

methodmap CoolSystem
{
    public global void OnPluginStart() { dothings... }
}