Zeex / sampgdk

Write SA-MP gamemodes in C/C++
http://zeex.github.io/sampgdk
Apache License 2.0
153 stars 83 forks source link

Preprocessor definition to disable any native function #181

Open IstuntmanI opened 7 years ago

IstuntmanI commented 7 years ago

For example, I don't want to use functions like IsPlayerInRangeOfPoint, GetPlayer/VehicleDistanceFromPoint, VectorSize, etc. because they are being called through the AMX layer. There's no need for that, we can make faster alternatives in C++. In C++ we can make lots of separate files, so we may sometimes forget a default function call (instead of calling the faster alternative) in a small file when we definitely don't want that in any file at all. (example: we could use the default sampgdk::IsPlayerInRangeOfPoint instead of MyGameMode::IsPlayerInRangeOfPoint and the compiler won't warn us about that)

We should be able to add a preprocessor definition "SAMPGDK_NO_[FUNCTION]" and then its creation would be disabled in sampgdk.h/c, so we will receive an error if using a disabled function.

Example:

/**

//...

ifndef SAMPGDK_NO_ISPLAYERINRANGEOFPOINT

inline bool IsPlayerInRangeOfPoint(int playerid, float range, float x, float y, float z) { return sampgdk_IsPlayerInRangeOfPoint(playerid, range, x, y, z); }

endif

//...

ifndef SAMPGDK_NO_ISPLAYERINRANGEOFPOINT

undef IsPlayerInRangeOfPoint

define IsPlayerInRangeOfPoint sampgdk_IsPlayerInRangeOfPoint

endif

//...

- ```sampgdk.c```:
```C++
// ...

#ifndef SAMPGDK_NO_ISPLAYERINRANGEOFPOINT
SAMPGDK_NATIVE(bool, IsPlayerInRangeOfPoint(int playerid, float range, float x, float y, float z)) {
  static AMX_NATIVE native;
  cell retval;
  cell params[6];
  sampgdk_log_debug("IsPlayerInRangeOfPoint(%d, %f, %f, %f, %f)", playerid, range, x, y, z);
  native = sampgdk_native_find_flexible("IsPlayerInRangeOfPoint", native);
  params[0] = 5 * sizeof(cell);
  params[1] = (cell)playerid;
  params[2] = amx_ftoc(range);
  params[3] = amx_ftoc(x);
  params[4] = amx_ftoc(y);
  params[5] = amx_ftoc(z);
  retval = native(sampgdk_fakeamx_amx(), params);
  return !!(retval);
}
#endif

//...

I checked the generate_code.py file and I think that this could be made pretty fast.

Y-Less commented 6 years ago

You could do this the other way round. Instead of having a definition to not include the symbol, use #undef after the fact. If you are not using SAMPGDK_CPP_WRAPPERS and using namespace sampgdk;, they are created (as you posted) as:

#undef  IsPlayerInRangeOfPoint
#define IsPlayerInRangeOfPoint sampgdk_IsPlayerInRangeOfPoint

So just do:

#include <sampgdk/a_player.h>
#undef  IsPlayerInRangeOfPoint

Then define your own version. Put that in a header used to always include sampgdk and you have your protection.

IstuntmanI commented 6 years ago

Well, doing that wouldn't allow alternatives in namespaces like MyNamespace::IsPlayerInRangeOfPoint, if including the declaration before sampGDK.

By the way, I am actually using SAMPGDK_CPP_WRAPPERS and not using using namespace sampgdk; .

ikkentim commented 6 years ago

By the way, I am actually using SAMPGDK_CPP_WRAPPERS and not using using namespace sampgdk; .

That's quite the contradiction, by defining SAMPGDK_CPP_WRAPPERS, you enable the sampgdk namespace, containing the function defintions.

Y-Less commented 6 years ago

That's not quite a contradiction. SAMPGDK_CPP_WRAPPERS enables the namespace, but you can have that and still not use using namespace sampgdk;, it just means you need to explicitly resolve every use as, say, sampgdk::SetPlayerPos.

IstuntmanI commented 6 years ago

Yes, it CREATES the sampgdk namespace, so we can use sampgdk::SendClientMessage instead of sampgdk_SendClientMessage. If I would use using namespace sampgdk; I could use directly SendClientMessage. I think you got their meaning wrong.

ikkentim commented 6 years ago

My bad, read @lstuntmanl 's message wrong, pretend I said nothing!