[Plugin] More control over plugin native errors (PoC)
#1

I recommend reading this over at the GitHub page at it is formatted better: https://github.com/Whitetigerswt/Dyn...ster/README.md

(I made this a year ago and never made a post about it on here)


Native Control


Have you ever been making a SA-MP plugin, and you just got the ever so common, "File or Function not found"? This error is extremely useful, and it is a good thing the server does not continue executing when this error comes up. However, sometimes it may be useful to include information about what is missing. What file or function is not found? Thus NativeChecker was born. The Native Checker plugin tells you which function was not found. This plugin is a proof-of-concept that the "File or Function not found" error can be completely eliminated.

What's the difference between this and NativeChecker?

This allows you to put your own custom error messages if a plugin is not loaded. Or maybe, you could run your gamemode or filterscript in a less-than-complete mode without an error and recover from the "file or function not found" error.

How might this be useful?

If plugin developers adapt this technique to their plugins, it would allow some pretty great things like:
pawn Код:
public OnFilterScriptInit()
{
    if(IsPluginLoaded())
    {
        printf("Hey!! You need to download the latest version of plugin [x] at link [y].
        printf("
The server will now terminate. Install the plugin to continue.");
        SendRconCommand("
exit");
    }
}
Which can provide a lot better information to servers than just "File or function not found", or even "Function not found: MapAndreas_FindZ". It allows people to understand why something may have went wrong when they are installing your gamemode, filterscript, or include. This is valuable so that you can make your gamemode or filterscript run with or without plugins.

How does it work?

This plugin hooks the native GetGravity from the AMX list. It uses this native, but it really does not matter which native you use. Any native can be hooked and achieve the same effect, it does not mess up the original "GetGravity" native.

Since PAWN allows us to pass params to natives even if they don't use them, this plugin takes advantage of that. Everytime GetGravity is called, it checks if an extra parameter is attached to it, a string, which is the "real" function name. If the extra param is there, we call that function instead of GetGravity. This allows all plugin natives to be defined by a proxy native which is GetGravity. In reality, you are calling a defined native "GetGravity". Only, if the plugin is loaded, GetGravity is hooked. If the proxy native returns the same value as "GetGravity", then the plugin is not loaded, ASSUMING you are using a native that actually exists.

Other parameters can be added onto natives to have multi-paramed functions. No functionality in plugins will be lost if implemented correctly.

Here's an example include that is using this technique in another plugin: http://samp-ac.com/sampac.inc

Full code and information here: https://github.com/Whitetigerswt/Dynamic_Natives

If you need to contact me about this, discord is probably the best way. Whitetiger#2767
Reply
#2

It will be useful, I will use it definitely for my plugins!
Reply
#3

Hello

Your some function added with the plugin are pretty cool

On "surface", its include water too ?

What about the onplayerpaused, can we check if player is writing a message ?

See you
Reply
#4

Quote:
Originally Posted by ******
Посмотреть сообщение
What is the performance impact of this? The point of using natives is that they can be very fast, since they are written in a native language, with run-time optimisation to replace each native call with a direct reference to the function in the in-memory p-code. This removes all of that and replaces it with a string lookup, which could be significant overhead for short natives (especially since you appear to be using a linear string search).

Given the relatively tiny (IMHO) problems caused by a missing plugin, this seems like a huge price to pay to "fix" them.

Edit: Re-read and better understood what is going on. I still wonder about the performance hit, but not about the other issues I previously had.

Edit 2: Since you are using "GetGravity" by default, your "IsPluginLoaded" example won't work. If the plugin isn't loaded, then the original will be called and return the current non-zero gravity, which this will interpret as "plugin loaded".
I'm not sure of a performance impact, I have only tested this code on servers with low player counts (<50). I'm sure it could be made more efficient. From my experience it hasn't been necessary to test for a performance impact as I haven't noticed one. You could probably calculate the function addresses once (instead of every plugin call) and store in a hashmap, then you'd have faster lookup time.

The problems are pretty small but can be useful to automatically enable or disable functionality when you want your game mode to run with or without a plugin. Most people now are not doing any verification if a plugin is loaded and that can cause problems if a sa-mp version is updated and a plugin doesn't support a new sa-mp version. You can keep your game mode or filterscript working as you wait for a plugin developer to update.

This should work on new versions of sa-mp released without any modifications.

I'm not sure what you meant by your last paragraph. IsPluginLoaded has to be defined as a comparison function. See here:
pawn Код:
native plugin_gateway_param0(func[]) = GetGravity;

#define IsPluginLoaded() ((_:GetGravity()) != plugin_gateway_param0("IsPluginLoaded"))
If the plugin isn't loaded, these functions will return the same values.

Quote:
Originally Posted by chneubeul
Посмотреть сообщение
Hello

Your some function added with the plugin are pretty cool

On "surface", its include water too ?

What about the onplayerpaused, can we check if player is writing a message ?

See you
That plugin really isn't what this topic is about, but you can find out more about it from the website that's linking it.
Reply
#5

You can use any sa-mp native in the server, it doesn't have to be GetGravity. The reason I used GetGravity is because it's been in every sa-mp version down to 0.1b, and it's easier to understand the code when you use a function with no parameters.

Also, to be fair doesn't

pawn Код:
if(1 == _:1.000000)
not work?

What gravity could you set to make this a false positive? Can you give me a use case?

EDIT: I thought I'd mention two more examples of how this could be helpful for plugin devs:
- plugin interaction. Often times it's useful for plugins to know what other plugins are loaded for compatibility. (See YSF and SKY incompatibility).
- if you're having a problem with a plugin, you could remove that plugin quickly and test again without recompiling any PAWN.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)