AMX Mod X 1.70 Scripting Changes

From AlliedModders Wiki
Revision as of 02:20, 1 March 2006 by BAILOPAN (talk | contribs) (Fast File Natives: - better example)
Jump to: navigation, search

This article goes over the new scripting changes available in AMX Mod X version 1.70.

New Systems

These are entirely new categories of functions added to AMX Mod X in 1.70.

CVAR Pointers

CVAR pointers are a new method of getting/retrieving CVAR values. It is a much faster method than using the get/set_cvar functions. The difference is instead of passing a "cvar name", you pass the "cvar pointer", which is a direct memory access rather than a string lookup. In order to easily accomodate this, register_cvar now returns a CVAR pointer from the CVAR you created. You can also use get_cvar_pointer. Usage is mapped as such:

  • get_cvar_flags -> get_pcvar_flags
  • set_cvar_flags -> set_pcvar_flags
  • get_cvar_string -> get_pcvar_string
  • set_cvar_string -> NONE (not implemented)
  • get_cvar_num -> get_pcvar_num
  • set_cvar_num -> set_pcvar_num
  • get_cvar_float -> get_pcvar_float

An example of old code might be:

#include <amxmodx>
 
public plugin_init()
{
   register_cvar("csdm_active", "1")
}
 
public pfn_touch()
{
   if (!get_cvar_num("csdm_active"))
      return PLUGIN_CONTINUE
}

To use CVAR pointers and optimize your code:

#include <amxmodx>
 
new g_csdm_active
 
public plugin_init()
{
   g_csdm_active = register_cvar("csdm_active", "1")
}
 
public pfn_touch()
{
   if (!get_pcvar_num(g_csdm_active))
      return PLUGIN_CONTINUE
}

Event Forwarding

One of AMX Mod X's first advanced API additions was "callfunc", which let plugins intercommunicate. This expanded with the "module forward API", then to "dynamic natives". Now, AMX Mod X has a "plugin forward API". This lets you call a public function in all plugins at once, which is very useful for global event/messaging creation. The new natives are:

  • CreateMultiForward - Creates a global forward to a public function in all plugins.
  • CreateOneForward - Creates a single, per-plugin forward to a public function.
  • PrepareArray - Prepares an array to be passed into a forward.
  • ExecuteForward - Executes a forward, calling all the public functions it contains.
  • DestroyForward - Removes a forward from memory.

An example of creating a forward is below. This plugin creates the forward, and fires it when the command is typed.

#include <amxmodx>
 
new g_fwd_what
 
public plugin_init()
{
    register_plugin("forward test", "1.0", "BAILOPAN")
    register_srvcmd("fwd_test", "Command_FwdTest")
 
    g_fwd_what = CreateMultiForward("Event_What", ET_STOP, FP_STRING, FP_CELL, FP_ARRAY)
}
 
public Event_What(str[], d, arr[])
{
    server_print("Event what called with (%s) num = %d|%d (should be 5|37)", str, d, arr[d])
 
    return PLUGIN_CONTINUE
}
 
public Command_FwdTest()
{
    new array[6], ret
    array[5] = 37
 
    new pArray = PrepareArray(array, 6)
    if (!ExecuteForward(g_fwd_what, ret, "gaben", 5, pArray))
    {
        server_print("FAILED!")
    }
}

Fast File Natives

One of the biggest flaws in the original AMX Mod core is the tendency to replace direct access handles with bad abstraction layers. Write_file and read_file are examples of this. To read or write line N to a file, they must open the file, seek to line N, then close it. For reading sequentially, this is an O(n^2) operation -- very slow!

These have been made obsolete with:

  • fopen - Opens and returns a file handle on success.
  • fclose - Closes a file handle.
  • feof - Checks for end of file.
  • fprintf - Writes to a file.
  • fgets - Reads text from a file.
  • fseek - Seek to a position in a file.
  • ftell - Get the current position of a file.
  • fread/fread_blocks/fread_raw - Read binary data from a file.
  • fwrite/fwrite_blocks/fwrite_raw - Write binary data to a file.

An example of reading a file with the new system:

#include <file>
 
stock CopyTextFile(const infile[], const outfile[])
{
   new infp = fopen(infile, "rt")    //read text
   new outfp = fopen(outfile, "wt")  //write text
 
   if (!infp || !outfp)
      return 0
 
   new buffer[2048]
   while (!feof(infp))
   {
      fgets(infp, buffer, 2047)
      fprintf(outfp, "%s", buffer)
   }
   fclose(infp)
   fclose(outfp)
}

Note that fgets includes a newline if one is reached. A quick way to strip newlines is:

new len = strlen(string)
if (string[len-1] == '^n')
   string[--len] = 0