AMX Mod X 1.75 Scripting Changes

From AlliedModders Wiki
Revision as of 10:57, 15 May 2006 by DS (talk | contribs) (FakeMeta)
Jump to: navigation, search

The AMX Mod X 1.75 release made important changes. While backwards compatibility was kept, intended functionality shifted in esoteric areas that will affect some plugins. Reading this article is highly recommended.

Module Requirement System

As part of the new Automatic Module Loading, the old #pragma library has been deprecated. You must now use:

#pragma reqlib <library>

This means "require library". Plugins still compiled with #pragma library will still fail on load if the given module is not found. However, core will try to load each module given the rules below under "Automatic Module Loading".

Automatic Module Loading

Overview

As of AMX Mod X 1.75, there is a new, powerful automatic module loading system. That means that modules.ini is largely deprecated for general use. Instead, modules are loaded as plugins need them. This is done dynamically by core before plugins are even loaded, without the need to patch modules.ini and then change the map.

Modules can now define "Libraries" and "Library Classes". A library is a specific identifier that should match the filename of the module. For example, Engine's defined library is "engine". FakeMeta's library is "fakemeta", and so on.

A "library class" defines membership to a set of modules. For example, CSX has the library name "csx", but it is part of the library class "xstats". Library classes are also used for DBI and SQLX. This is very useful for being able to require one module type of any implementation.

New API

Compiler Pragmas

This is expanded with a number of new #pragma directives:

  • #pragma reqlib <library> - Requires that a given library must be loaded.
  • #pragma reqclass <libclass> - Requires that a given library class must be loaded.
  • #pragma loadlib <library> - Automatically attempts to load a given library (see more info below).
  • #pragma expectlib <library1> <library2> - If the first library is not loaded, the second one will be attempted to load (not very useful).
  • #pragma expectclass <class> <library> - If the expected class is not found, the given library will be attempted to load. This is useful for defining a default module to be loaded with a given class of modules.
  • #pragma defclasslib <class> <library> - Same as expectclass, however, defclasslib waits until all expectations are resolved. This lets plugins override defaults by adding their own expectations.

Module Filtering

The module_filter prototype now includes a second parameter, which tells you whether the requirement is a class or library.

Furthermore, module_exists has been deprecated for LibraryExists().

How it Works

The precise order of events is as follows:

  • When the first entity is spawned, AMX Mod X loads all unloaded modules in modules.ini.
  • After modules.ini is parsed, plugins.ini is read. Each file is mapped into a cache.
  • The cache is previewed.
    • First, the "library" table is read. This table is read for backwards compatibility with AMX Mod X 1.71 and prior. Each entry is read as a module file shortname, and the module is loaded if it exists.
    • Next, the "pubtags" table is read. Each entry is decoded to one of the special #pragma commands.
      • All loadlib commands are executed, and the modules loaded.
      • All expect commands are executed.
      • All defclasslib commands are executed.
  • AMX Mod X then waits until ServerActivate is called.
  • All plugins are loaded. If the plugin is in the cache, the cache is read instead. For each plugin...
    • The library table is read. For each library that is both nonexistant and unhandled by a module filter, the plugin fails to load.
    • The pubtags table is read. For each reqlib and reqclass entry that are both nonexistant and unhandled by a module filter, the plugin fails to load.
  • The plugin cache is invalidated and the server is considered "loaded".

New Natives / Native Changes

Register Message

The register_message set of natives, including get/set_msg_block, has been moved to Core. This is to facilitate users who prefer to use FakeMeta, and like the simplicity and speed of using Engine's message interception functions.
This change is backwards compatible.

Argument Formatting

The format_args function is now replaced with a much faster, more compatible vformat function. Its usage is slightly different (read the include file, string.inc), but it accepts %L, whereas format_args does not. A quick example:

debugprint(const fmt[], ...)
{
   static temp[2048]
   vformat(temp, sizeof(temp)-1, fmt, 2)
   log_message("[DEBUG] %s", temp)
}

Other Core Natives

  • register_plugin - Now returns a plugin id.
  • get_amxx_verstring - Returns the AMX Mod X version string.
  • get_weaponid - Gets a weapon id from a weapon name.

FakeMeta

New Natives

  • get_orig_retval - Gets the original return value of an engine or game DLL function.
  • copy_infokey_buffer - Copies the given infobuffer pointer into output buffer.
  • get/set_cd - Gets or sets members of a clientdata data structure (used with UpdateClientData).
  • get/set_es - Gets or sets members of an entity_state data structure (used with AddToFullPack).
  • get/set_uc - Gets or sets members of a usecmd data structure (used with CmdStart).

New Engine/GameDLL Functions

The register_forward native now allows for hooking a number of new functions from the engine or game DLL including:

  • UpdateClientData
  • AddToFullPack
  • CmdStart
  • CmdEnd
  • CreateInstBaselines - Game DLL function
  • CreateInstBaseline - Engine function
  • CreateBaseline
  • GetInfoKeyBuffer

These functions can also be called via engfunc or dllfunc.

Breaking Changes

Using engfunc in order to call EngFunc_InfoKeyValue, EngFunc_SetKeyValue, or EngFunc_SetClientKeyValue now requires passing an infobuffer pointer. An infobuffer pointer can be obtained by calling EngFunc_GetInfoKeyBuffer. For example:

some_function(id, name[])
{
   new infokey = engfunc(EngFunc_GetInfoKeyBuffer, id)
   engfunc(EngFunc_SetClientKeyValue, id, infokey, "model", name)
}

If you hook ClientUserInfoChanged via Fakemeta, an infobuffer pointer is now also forwarded to your function in addition to the client id.

Cstrike

  • cs_set_user_vip - Now takes two additional (but optional) parameters for determing whether or not the player model and scoreboard get updated.

New Stocks

Engine

  • IsInWorld - Checks if an entity is within the bounds of the world (from HLSDK).

FakeMeta

  • DF_UpdateClientData - Calls UpdateClientData game DLL function.
  • DF_AddToFullPack - Calls AddToFullPack game DLL function.
  • DF_CmdStart - Calls CmdStart game DLL function.
  • DF_CmdEnd - Calls CmdEnd game DLL function.
  • DF_CreateBaseline - Calls CreateBaseline game DLL function.
  • DF_CreateInstBaselines - Calls CreateInstancedBaselines game DLL function.
  • EF_CreateInstBaseline - Calls CreateInstancedBaseline engine function.
  • EF_GetInfoKeyBuffer - Calls GetInfoKeyBuffer engine function.

New Constants

Various sound constants (SND_SPAWNING, SND_STOP, SND_CHANGE_VOL, and SND_CHANGE_PITCH) from the HLSDK as well as a constant for pi were added to amxconst.inc.

Module API

The AMX Mod X module API received a small overhaul for 1.75.

Versioning/Interface Additions

The internal module interface version is 4. However, modules from M/SDK 3 will still load.

M/SDK Version 4 modules have two new members of public information: the library string, and the library class string. These contain comma delimited names of whatever libraries or library classes the module would like to be registered.

For backwards compatibility, M/SDK Version 4 modules have an automatically empty library class string, and a library string equal to the logtag string.

New Callbacks

Modules can now be informed of when plugins are about to be unloaded, and when plugins have been fully unloaded. This means that modules don't have to hook ServerActivate and ServerActivate_Post (implementation dependent), don't need to be loaded by Metamod, and don't need to detach simply to release resources.

New Functions

  • MF_GetLocalInfo - Intended for modules using LOCALINFO, which required a Metamod attachment. This is equal to AMX Mod X's core function get_localinfo.
  • MF_OverrideNatives - Given a native list, this specifies that any other module already providing these natives will no longer provide them. This was added to force backwards compatibility between SQLITE and MySQLX. Usage is not recommended.
  • MF_FindLibrary - Essentially the same function as LibraryExists() for plugins.
  • MF_AddLibraries - Adds a comma delimited list of libraries or library classes. You must specify a "parent" pointer that identifies the module. This is easily accomplished by taking the address of any static variable.
  • MF_RemoveLibraries - Removes all library entries with the given parent pointer. This is useful if your module adds custom entries not in its defined list.

MSVC8 Compatibility

M/SDK Version 4 now contains preprocessor definitions for compatibility with Microsoft's Visual Studio 2005/8.0 (provided by Damaged Soul). These macros can be turned off in the moduleconfig.h file by uncommenting the definition of NO_MSVC8_AUTO_COMPAT.

Minor Changes

Compiler Defines

Since __DATE__ was fixed in 1.75, the macro __TIME__ was also added.