Addititional Libraries for PAWN
#1

https://github.com/YashasSamaga/PAWN-Library-Extension (25% completed)

I've had a secret plugin (yes, a secret, only a handful of people know that such a project exists) for years. The
plugin allowed me to use many of the C/++ standard libraries from your PAWN code. Apart from those, there are new libraries (Interscript communication, a completely new time library exclusively designed for PAWN, etc).

The plugin was really buggy and incomplete (and it worked only on Windows when compiled using VC++). The functions which worked properly were those which I used to use. Now I have decided to make a new copy of the same plugin but this time, I am writing it in such a way that it can be released.

CallExternalFunction vs CallRemoteFunction (500 publics in 3 scripts)


Код:
new efid = GetExternalFunctionID(0, "RandomPublic");
	if(efid == INVALID_EXT_FID) print("[TEST] GetExternalFunction failed.");
	
	new sk, id;
	GetExternalFunctionInfo(efid, sk, id);
	if(sk != 0) print("[TEST] GetExternalFunctionInfo failed.");
	if(id != 3) print("[TEST] GetExternalFunctionInfo failed.");
	
	new avg1 = 0, avg2 = 0, ret;
	for(new k = 0; k < 10; k++)
	{
		new a = GetTickCount();
		for(new i = 0; i < 1000000; i++)
		{
			CallExternalFunction(efid, ret, "iss", 1337, "abcdefg", "ABCD");
		}
		new b = GetTickCount();
		for(new i = 0; i < 1000000; i++)
		{
	    	//test(1337, "abcdefg", "ABCD");
			CallRemoteFunction("RandomPublic", "iss", 1337, "abcdefg", "ABCD");
		}
		new c = GetTickCount();
		avg1 += b-a;
		avg2 += c-b;
		
		printf("Trial #%d: %d %d" , k+1, b-a, c-b);
	}
	
	printf("\nAverage: %d %d" , avg1/10, avg2/10);
Every script has an id known as ScriptKey (assigned by the plugin) and an identification string know as ScriptIdentifier (which is set by the scripter).

All resources are shared. You can maintain a player id list (STL list) for the entire server instead of having a separate foreach in each script.

I wanted to know what libraries are needed (or there is something which is terribly slow as PAWN code and must be moved to a plugin).
Reply
#2

Pretty good
Reply
#3

tolower, toupper, CallLocalFunction, CallRemoteFunction

swap, SortArray
Reply
#4

Already there.
Reply
#5

Includes:
https://github.com/YashasSamaga/PAWN...r/includes/PLE

!Work in progress!
  • Function Objects
    You can store functions in variables and use them as arguments to functions. Many functions which this library provides accept function objects as arguments. For example, the find_if algorithm accepts a function which it uses to decide if the required information was found. You can make a function which accepts two arguments accept one argument by binding one or more of its arguments. There are over 25 fast built-in function objects to do common tasks.

    Код:
    public CheckPlayerForCheats(playerid)
    {
         //anti cheat code
    }
    
    new array[] = {1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6};
    function<bool(cell,cell)> myfunction;
    myfunction = not_fn(bind1st(functions::modulus, 2)); //there are over 25 function templates
    new even_no_count = count_if(array, sizeof(array), myfunction); //counts how many even numbers are there
    
    make_function(myfunction, "CheckPlayerForCheats", 2); //myfunction = make_function(myfunction, "CheckPlayerForCheats", 2); is also valid syntax but slower.
    for_each(playerList, GetPlayerPoolSize(), myfunction);
  • Algorithms
    Apart from countless functions which each individual library provides, the algorithm library provides over 100 more functions to do common tasks quickly and efficiently. These algorithm functions have proper names which helps improve readablity of your code. Obviously, using the 'find' function to search for a value is more readable than having a loop which does the finding work. Moreover, these functions are insanely fast. If used properly and wherever necessary, it will help you cut down the size of your AMX file drastically. Not to mention that, using the functions save your time and also keep your code free from silly errors. It is a WIN-WIN-WIN-WIN situation.
    Код:
    new str[][] = {"Yashas", "str1", "str2", "str3", "str4", "str5", "str6"};
    if(sbsearch("Yashas", str, idx))
    {
          //found at index idx
    }
    
    new adminList[MAX_PLAYERS];
    new last_idx = copy_if(playerList, GetPlayerPoolSize(), adminList, yourIsPlayerAdminFunction); //makes a list of admins from the playerlist
    
    sort(adminList, last_idx + 1); //by default sort uses functions::less
    
    new Float:playerDamage[MAX_PLAYERS][MAX_PLAYERS]; //an array which stores how much damage a player received from each player
    
    new Float:total_damage_for_player = accumulate(playerDamage[playerid], MAX_PLAYERS, 0, functions::plusf); //plusf is a builtin function to add rational numbers
    //if the functions::plusf was not mentioned, accumulate would use functions::plus as default but you cannot add rational numbers like integers
  • Containers
    The plugin provides 6 different types of data containers to store information. Each type of container is optimized to store a specific type of information. While some containers dynamically expand their size as your add more and more data, some containers use fixed sizes. Even though the memory allocation of the dynamic containers is managed internally, you are responsible for destroying the container as a whole.
    Код:
    func()
    {
          new bitset:mybitset<1000>; //creates a bitset which can hold 1000 bits
          printf("Size of the bitset: %s", bitset_size(mybitset));
          bitset_set(mybitset, bitno);
          bitset_reset(mybitset, 755);
          printf("Any bits set: %d", bitset_any(mybitset));
          printf("All bits set: %d", bitset_all(mybitset));
          printf("None of the bits set: %d", bitset_none(mybitset));
    
          new str[1001];
          bitset_tostring(mybitset, str);
          if(str[555] == '1') { //bit 555 is set }
          printf("Bitset Contents: %s", str); //useful for debugging
    
          new bitset:admins<MAX_PLAYERS>;
          new bitset:vips<MAX_PLAYERS>;
       
          printf("No of admins: %d No of VIPs:%d", bitset_count(admins), bitset_count(vips)); //uses lookup table to count; hence, counting is done amazingly fast.
    
          new bitset:admins_and_vips<MAX_PLAYERS>;
          bitset_and(admins, vips, admins_and_vips);
    
          //admins_and_vips contains a list of admins who are VIPs.
          if(bitset_equal(admins, admins_and_vips)) { //all the admins are VIPs }
    
         bitset_foreach_set(admins, bind1st(SendPlayerMessage, getAddress("Hi Admin! How are you?"))); //first param is forcefully binded, so foreach will pass the second param as the admin's playerid
         //bitsets are automatically destroyed when they go out of scope
    }
  • Interscript-Communication
    This library makes communication and sharing resources between scripts easier with little to zero overhead. Every script is assigned a unique identity number known as ScriptKey. Additionally, you can specify a script identification string for each script yourself. The plugin calls OnScriptInit and OnScriptExit for every script — irrespective of whether or not the script is PLE compliant — which is loaded and unloaded respectively. Using the ScriptKey, you can call remote functions, modify or read remote variables/arrays or even edit a filterscript's code from your gamemode ( ).

    Код:
    #define SCRIPT_IDENTIFIER "gamemode" //you give a name for each script
    
    new AdminFSScriptKey = -1;
    public OnScriptInit(ScriptKey, ScriptIdentifier[])
    {
           if(!strcmp(ScriptIdentifier, "admin-fs")) AdminFSScriptKey = ScriptKey; //assume that you named your admin fs as "admin-fs"
           else if(!strcmp(ScriptIdentifier, UNDEFINED_SCRIPT_IDENTIFIER)) printf("Undefined Script Loaded (%s)", ScriptIdentifier); //the script is PLE compliant but is using the default script identifier
           else if(!strcmp(ScriptIdentifier, UNSUPPORTED_SCRIPT_IDENTIFIER)) printf("Unsupported Script Loaded (%s)", ScriptIdentifier); //the script is not a PLE compliant script
           //A script which is not PLE compliant will still work but you won't be able to identify it.
           //You can still access it via the inter-script communication functions as it also gets a unique script id
    }
    public OnScriptExit(scriptKey, scriptIdentifier[])
    {
        if(scriptKey == AdminFSScriptKey) 
        {
               //the admin filterscript unloaded for some reason
        }
    }
    
    new extFuncID = GetExternalFunctionID(AdminFSScriptKey , "PublicInAdminFS"), ret;
    if(extFuncID != INVALID_EXT_FID)
    {
         //that public exists
         if(CallExternalFunction(extFuncID, ret, "iss", 1337, "abcdefg", "ABCD")) //calls the public in the admin fs insanely fast.
         {
                //function was called without problems
         }
    }
    
    new extVarID = GetExternalVariableID(AdminFSScriptKey , "PublicVarInAdminFS");
    if(evid != INVALID_EXT_VID) 
    {
         //public var exists
         SetExternalVariable(extVarID , 1234); //sets the variable in the admin fs to 1234
         // this is as fast as doing
        myarray[idx] = 1234;
         // very efficient, huh?
    }
    
    //If you need to do more, you can edit anything in any script that is loaded (you even even edit a filterscript's code)
    new hdr[AMX_HEADER]; //AMX_HEADER structure is defined in isc.inc
    GetAMXHeader(AdminFSScriptKey, hdr);
    printf("Address of the public function table in Admin FS: %d",hdr[AMX_HEADER_PUBLICS]);
    
    WriteAMXMemory(AdminFSScriptKey, addr, 'c'); //addr is the address relative to DAT of the target AMX
    ReadAMXMemory(AdminFSScriptKey, addr, val);
    
    WriteAMXMemoryArray(AdminFSScriptKey, addr, "apple", 6);
    ReadAMXMemoryArray(AdminFSScriptKey, addr, arr, sizeof(arr))
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)