dvander@498: /** dvander@562: * =============================================================== dvander@562: * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. dvander@562: * =============================================================== dvander@562: * dvander@562: * This file is not open source and may not be copied without explicit dvander@562: * written permission of AlliedModders LLC. This file may not be redistributed dvander@562: * in whole or significant part. dvander@562: * For information, see LICENSE.txt or http://www.sourcemod.net/license.php dvander@562: * dvander@562: * Version: $Id$ dvander@562: */ dvander@498: dvander@498: #include "sm_globals.h" dvander@498: #include "sourcemm_api.h" dvander@498: #include "HandleSys.h" ds@580: #include "ConVarManager.h" ds@579: #include "ConCmdManager.h" dvander@514: #include "PluginSys.h" dvander@518: #include "sm_stringutil.h" dvander@591: #include "PlayerManager.h" dvander@498: dvander@498: static cell_t sm_CreateConVar(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: char *name, *defaultVal, *helpText; dvander@498: dvander@498: pContext->LocalToString(params[1], &name); dvander@498: dvander@498: // While the engine seems to accept a blank convar name, it causes a crash upon server quit dvander@498: if (name == NULL || strcmp(name, "") == 0) dvander@498: { ds@582: return pContext->ThrowNativeError("Convar with blank name is not permitted"); dvander@498: } dvander@498: dvander@498: pContext->LocalToString(params[2], &defaultVal); dvander@498: pContext->LocalToString(params[3], &helpText); dvander@498: dvander@498: bool hasMin = params[5] ? true : false; dvander@498: bool hasMax = params[7] ? true : false; dvander@498: float min = sp_ctof(params[6]); dvander@498: float max = sp_ctof(params[8]); dvander@498: ds@582: Handle_t hndl = g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max); ds@582: ds@582: if (hndl == BAD_HANDLE) ds@582: { ds@582: return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same name already exists.", name); ds@582: } ds@582: ds@582: return hndl; dvander@498: } dvander@498: dvander@498: static cell_t sm_FindConVar(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: char *name; dvander@498: dvander@498: pContext->LocalToString(params[1], &name); dvander@498: dvander@498: return g_ConVarManager.FindConVar(name); dvander@498: } dvander@498: dvander@498: static cell_t sm_HookConVarChange(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: ds@582: IPluginFunction *pFunction = pContext->GetFunctionById(params[2]); ds@582: ds@582: if (!pFunction) ds@582: { ds@582: return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); ds@582: } ds@582: ds@582: g_ConVarManager.HookConVarChange(pConVar, pFunction); dvander@498: dvander@498: return 1; dvander@498: } dvander@498: dvander@498: static cell_t sm_UnhookConVarChange(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: ds@582: IPluginFunction *pFunction = pContext->GetFunctionById(params[2]); ds@582: ds@582: if (!pFunction) ds@582: { ds@582: return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); ds@582: } ds@582: ds@582: g_ConVarManager.UnhookConVarChange(pConVar, pFunction); dvander@498: dvander@498: return 1; dvander@498: } dvander@498: dvander@498: static cell_t sm_GetConVarBool(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: ds@576: return pConVar->GetBool(); dvander@498: } dvander@498: dvander@498: static cell_t sm_GetConVarInt(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: ds@576: return pConVar->GetInt(); dvander@498: } dvander@498: dvander@498: /* This handles both SetConVarBool() and SetConVarInt() */ dvander@498: static cell_t sm_SetConVarNum(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: ds@576: pConVar->SetValue(params[2]); dvander@498: dvander@498: return 1; dvander@498: } dvander@498: dvander@498: static cell_t sm_GetConVarFloat(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: ds@576: float value = pConVar->GetFloat(); dvander@498: dvander@498: return sp_ftoc(value); dvander@498: } dvander@498: dvander@498: static cell_t sm_SetConVarFloat(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: dvander@498: float value = sp_ctof(params[2]); ds@576: pConVar->SetValue(value); dvander@498: dvander@498: return 1; dvander@498: } dvander@498: dvander@498: static cell_t sm_GetConVarString(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: ds@576: pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetString(), NULL); dvander@498: dvander@498: return 1; dvander@498: } dvander@498: dvander@498: static cell_t sm_SetConVarString(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: dvander@498: char *value; dvander@498: pContext->LocalToString(params[2], &value); dvander@498: ds@576: pConVar->SetValue(value); dvander@498: dvander@498: return 1; dvander@498: } dvander@498: dvander@498: static cell_t sm_GetConVarFlags(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: ds@576: return pConVar->GetFlags(); dvander@498: } dvander@498: dvander@498: static cell_t sm_SetConVarFlags(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: ds@576: pConVar->SetFlags(params[2]); dvander@498: dvander@498: return 1; dvander@498: } dvander@498: dvander@498: static cell_t sm_GetConVarMin(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: dvander@498: cell_t *addr; dvander@498: bool hasMin; dvander@498: float min; dvander@498: dvander@498: pContext->LocalToPhysAddr(params[2], &addr); dvander@498: ds@576: hasMin = pConVar->GetMin(min); dvander@498: *addr = sp_ftoc(min); dvander@498: dvander@498: return hasMin; dvander@498: } dvander@498: dvander@498: static cell_t sm_GetConVarMax(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: dvander@498: cell_t *addr; dvander@498: bool hasMax; dvander@498: float max; dvander@498: dvander@498: pContext->LocalToPhysAddr(params[2], &addr); dvander@498: ds@576: hasMax = pConVar->GetMax(max); dvander@498: *addr = sp_ftoc(max); dvander@498: dvander@498: return hasMax; dvander@498: } dvander@498: dvander@498: static cell_t sm_GetConVarName(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: ds@576: pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetName(), NULL); dvander@498: dvander@498: return 1; dvander@498: } dvander@498: dvander@498: static cell_t sm_ResetConVar(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: Handle_t hndl = static_cast(params[1]); dvander@498: HandleError err; ds@576: ConVar *pConVar; dvander@498: ds@576: if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar)) dvander@498: != HandleError_None) dvander@498: { ds@581: return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); dvander@498: } dvander@498: ds@576: pConVar->Revert(); dvander@498: dvander@498: return 1; dvander@498: } dvander@498: dvander@498: static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params) dvander@498: { dvander@498: char *name,*help; dvander@498: IPluginFunction *pFunction; dvander@498: dvander@498: pContext->LocalToString(params[1], &name); dvander@498: pContext->LocalToString(params[3], &help); dvander@498: pFunction = pContext->GetFunctionById(params[2]); dvander@498: dvander@498: if (!pFunction) dvander@498: { dvander@498: return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); dvander@498: } dvander@498: ds@579: if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4])) ds@579: { ds@579: return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name); ds@579: } dvander@498: dvander@498: return 1; dvander@498: } dvander@498: dvander@500: static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params) dvander@500: { dvander@500: char *name,*help; dvander@500: IPluginFunction *pFunction; dvander@500: dvander@500: pContext->LocalToString(params[1], &name); dvander@500: pContext->LocalToString(params[3], &help); dvander@500: pFunction = pContext->GetFunctionById(params[2]); dvander@500: dvander@500: if (!pFunction) dvander@500: { dvander@500: return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); dvander@500: } dvander@500: ds@579: if (!g_ConCmds.AddConsoleCommand(pFunction, name, help, params[4])) ds@579: { ds@579: return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name); ds@579: } dvander@500: dvander@500: return 1; dvander@500: } dvander@500: dvander@514: static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params) dvander@514: { dvander@514: char *name,*help; dvander@514: const char *group; dvander@514: IPluginFunction *pFunction; dvander@514: FlagBits flags = params[3]; dvander@514: int cmdflags = params[6]; dvander@514: dvander@514: pContext->LocalToString(params[1], &name); dvander@514: pContext->LocalToString(params[4], &help); dvander@514: pContext->LocalToString(params[5], (char **)&group); dvander@514: pFunction = pContext->GetFunctionById(params[2]); dvander@514: dvander@514: if (group[0] == '\0') dvander@514: { dvander@514: CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext()); dvander@514: group = pPlugin->GetFilename(); dvander@514: } dvander@514: dvander@514: if (!pFunction) dvander@514: { dvander@514: return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); dvander@514: } dvander@514: ds@579: if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags)) ds@579: { ds@579: return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name); ds@579: } dvander@514: dvander@514: return 1; dvander@514: } dvander@514: dvander@517: static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params) dvander@517: { dvander@517: return engine->Cmd_Argc() - 1; dvander@517: } dvander@517: dvander@517: static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params) dvander@517: { dvander@517: const char *arg = engine->Cmd_Argv(params[1]); dvander@517: dvander@517: pContext->StringToLocalUTF8(params[2], params[3], arg, NULL); dvander@517: dvander@517: return 1; dvander@517: } dvander@517: dvander@517: static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params) dvander@517: { dvander@517: const char *args = engine->Cmd_Args(); dvander@517: dvander@633: if (!args) dvander@633: { dvander@633: args = ""; dvander@633: } dvander@633: dvander@517: pContext->StringToLocalUTF8(params[1], params[2], args, NULL); dvander@517: dvander@517: return 1; dvander@517: } dvander@517: dvander@518: static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params) dvander@518: { dvander@518: char buffer[1024]; dvander@518: char *fmt; dvander@518: int arg = 2; dvander@518: dvander@518: pCtx->LocalToString(params[1], &fmt); dvander@518: size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg); dvander@518: dvander@518: buffer[res++] = '\n'; dvander@518: buffer[res] = '\0'; dvander@518: dvander@518: META_CONPRINT(buffer); dvander@518: dvander@518: return 1; dvander@518: } dvander@518: dvander@518: static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params) dvander@518: { dvander@518: int index = params[1]; dvander@520: if ((index < 0) || (index > g_Players.GetMaxClients())) dvander@518: { dvander@518: return pCtx->ThrowNativeError("Invalid client index %d", index); dvander@518: } dvander@518: dvander@520: CPlayer *pPlayer = NULL; dvander@520: if (index != 0) dvander@518: { dvander@520: pPlayer = g_Players.GetPlayerByIndex(index); dvander@520: if (!pPlayer->IsInGame()) dvander@520: { dvander@520: return pCtx->ThrowNativeError("Client %d is not in game", index); dvander@520: } dvander@520: dvander@520: /* Silent fail on bots, engine will crash */ dvander@520: if (pPlayer->IsFakeClient()) dvander@520: { dvander@520: return 0; dvander@520: } dvander@519: } dvander@518: dvander@518: char buffer[1024]; dvander@518: char *fmt; dvander@518: int arg = 3; dvander@518: dvander@518: pCtx->LocalToString(params[2], &fmt); dvander@518: size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg); dvander@518: dvander@518: buffer[res++] = '\n'; dvander@518: buffer[res] = '\0'; dvander@518: dvander@520: if (index != 0) dvander@520: { dvander@520: engine->ClientPrintf(pPlayer->GetEdict(), buffer); dvander@520: } else { dvander@520: META_CONPRINT(buffer); dvander@520: } dvander@518: dvander@518: return 1; dvander@518: } dvander@518: dvander@522: static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params) dvander@522: { dvander@522: char buffer[1024]; dvander@522: size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1); dvander@522: dvander@522: /* One byte for null terminator, one for newline */ dvander@522: buffer[len++] = '\n'; dvander@522: buffer[len] = '\0'; dvander@522: dvander@522: engine->ServerCommand(buffer); dvander@522: dvander@522: return 1; dvander@522: } dvander@522: dvander@522: static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params) dvander@522: { dvander@522: char buffer[1024]; dvander@522: size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1); dvander@522: dvander@522: /* One byte for null terminator, one for newline */ dvander@522: buffer[len++] = '\n'; dvander@522: buffer[len] = '\0'; dvander@522: dvander@522: engine->InsertServerCommand(buffer); dvander@522: dvander@522: return 1; dvander@522: } dvander@522: dvander@522: static cell_t sm_ServerExecute(IPluginContext *pContext, const cell_t *params) dvander@522: { dvander@522: engine->ServerExecute(); dvander@522: dvander@522: return 1; dvander@522: } dvander@522: dvander@532: static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params) dvander@532: { dvander@532: CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]); dvander@532: dvander@532: if (!pPlayer) dvander@532: { dvander@532: return pContext->ThrowNativeError("Player %d is not a valid player", params[1]); dvander@532: } dvander@532: dvander@532: if (!pPlayer->IsConnected()) dvander@532: { dvander@532: return pContext->ThrowNativeError("Player %d is not connected", params[1]); dvander@532: } dvander@532: dvander@532: char buffer[256]; dvander@532: g_SourceMod.FormatString(buffer, sizeof(buffer)-1, pContext, params, 2); dvander@532: dvander@532: engine->ClientCommand(pPlayer->GetEdict(), "%s", buffer); dvander@532: dvander@532: return 1; dvander@532: } dvander@532: dvander@518: REGISTER_NATIVES(consoleNatives) dvander@498: { dvander@498: {"CreateConVar", sm_CreateConVar}, dvander@498: {"FindConVar", sm_FindConVar}, dvander@498: {"HookConVarChange", sm_HookConVarChange}, dvander@498: {"UnhookConVarChange", sm_UnhookConVarChange}, dvander@498: {"GetConVarBool", sm_GetConVarBool}, dvander@498: {"SetConVarBool", sm_SetConVarNum}, dvander@498: {"GetConVarInt", sm_GetConVarInt}, dvander@498: {"SetConVarInt", sm_SetConVarNum}, dvander@498: {"GetConVarFloat", sm_GetConVarFloat}, dvander@498: {"SetConVarFloat", sm_SetConVarFloat}, dvander@498: {"GetConVarString", sm_GetConVarString}, dvander@498: {"SetConVarString", sm_SetConVarString}, dvander@498: {"GetConVarFlags", sm_GetConVarFlags}, dvander@498: {"SetConVarFlags", sm_SetConVarFlags}, dvander@498: {"GetConVarName", sm_GetConVarName}, dvander@498: {"GetConVarMin", sm_GetConVarMin}, dvander@498: {"GetConVarMax", sm_GetConVarMax}, dvander@498: {"ResetConVar", sm_ResetConVar}, dvander@498: {"RegServerCmd", sm_RegServerCmd}, dvander@500: {"RegConsoleCmd", sm_RegConsoleCmd}, dvander@517: {"GetCmdArgString", sm_GetCmdArgString}, dvander@517: {"GetCmdArgs", sm_GetCmdArgs}, dvander@517: {"GetCmdArg", sm_GetCmdArg}, dvander@518: {"PrintToServer", sm_PrintToServer}, dvander@518: {"PrintToConsole", sm_PrintToConsole}, dvander@520: {"RegAdminCmd", sm_RegAdminCmd}, dvander@522: {"ServerCommand", sm_ServerCommand}, dvander@522: {"InsertServerCommand", sm_InsertServerCommand}, dvander@522: {"ServerExecute", sm_ServerExecute}, dvander@532: {"ClientCommand", sm_ClientCommand}, dvander@498: {NULL, NULL} dvander@498: };