1.1 --- a/core/ConCmdManager.cpp Fri Jul 11 06:51:21 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,991 +0,0 @@
1.4 -/**
1.5 - * vim: set ts=4 :
1.6 - * =============================================================================
1.7 - * SourceMod
1.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 - * =============================================================================
1.10 - *
1.11 - * This program is free software; you can redistribute it and/or modify it under
1.12 - * the terms of the GNU General Public License, version 3.0, as published by the
1.13 - * Free Software Foundation.
1.14 - *
1.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 - * details.
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License along with
1.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 - *
1.23 - * As a special exception, AlliedModders LLC gives you permission to link the
1.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 - * by the Valve Corporation. You must obey the GNU General Public License in
1.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 - * this exception to all derivative works. AlliedModders LLC defines further
1.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 - * or <http://www.sourcemod.net/license.php>.
1.31 - *
1.32 - * Version: $Id$
1.33 - */
1.34 -
1.35 -#include "ConCmdManager.h"
1.36 -#include "sm_srvcmds.h"
1.37 -#include "AdminCache.h"
1.38 -#include "sm_stringutil.h"
1.39 -#include "PlayerManager.h"
1.40 -#include "Translator.h"
1.41 -#include "HalfLife2.h"
1.42 -#include "ChatTriggers.h"
1.43 -
1.44 -ConCmdManager g_ConCmds;
1.45 -
1.46 -#if defined ORANGEBOX_BUILD
1.47 - SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
1.48 -#else
1.49 - SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
1.50 -#endif
1.51 -
1.52 -SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int);
1.53 -
1.54 -struct PlCmdInfo
1.55 -{
1.56 - ConCmdInfo *pInfo;
1.57 - CmdHook *pHook;
1.58 - CmdType type;
1.59 -};
1.60 -typedef List<PlCmdInfo> CmdList;
1.61 -
1.62 -void AddToPlCmdList(CmdList *pList, const PlCmdInfo &info);
1.63 -
1.64 -ConCmdManager::ConCmdManager() : m_Strings(1024)
1.65 -{
1.66 - m_pCmds = sm_trie_create();
1.67 - m_pCmdGrps = sm_trie_create();
1.68 - m_CmdClient = 0;
1.69 -}
1.70 -
1.71 -ConCmdManager::~ConCmdManager()
1.72 -{
1.73 - sm_trie_destroy(m_pCmds);
1.74 - sm_trie_destroy(m_pCmdGrps);
1.75 -}
1.76 -
1.77 -void ConCmdManager::OnSourceModAllInitialized()
1.78 -{
1.79 - g_PluginSys.AddPluginsListener(this);
1.80 - g_RootMenu.AddRootConsoleCommand("cmds", "List console commands", this);
1.81 - SH_ADD_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, serverClients, this, &ConCmdManager::SetCommandClient, false);
1.82 -}
1.83 -
1.84 -void ConCmdManager::OnSourceModShutdown()
1.85 -{
1.86 - /* All commands should already be removed by the time we're done */
1.87 - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, serverClients, this, &ConCmdManager::SetCommandClient, false);
1.88 - g_RootMenu.RemoveRootConsoleCommand("cmds", this);
1.89 -}
1.90 -
1.91 -void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
1.92 -{
1.93 - /* Whoa, first get its information struct */
1.94 - ConCmdInfo *pInfo;
1.95 -
1.96 - if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
1.97 - {
1.98 - return;
1.99 - }
1.100 -
1.101 - RemoveConCmds(pInfo->srvhooks);
1.102 - RemoveConCmds(pInfo->conhooks);
1.103 -
1.104 - RemoveConCmd(pInfo, name, is_read_safe, false);
1.105 -}
1.106 -
1.107 -void ConCmdManager::RemoveConCmds(List<CmdHook *> &cmdlist)
1.108 -{
1.109 - List<CmdHook *>::iterator iter = cmdlist.begin();
1.110 -
1.111 - while (iter != cmdlist.end())
1.112 - {
1.113 - CmdHook *pHook = (*iter);
1.114 - IPluginContext *pContext = pHook->pf->GetParentContext();
1.115 - IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
1.116 - CmdList *pList = NULL;
1.117 -
1.118 - //gaben
1.119 - if (!pPlugin->GetProperty("CommandList", (void **)&pList, false) || !pList)
1.120 - {
1.121 - continue;
1.122 - }
1.123 -
1.124 - CmdList::iterator p_iter = pList->begin();
1.125 - while (p_iter != pList->end())
1.126 - {
1.127 - PlCmdInfo &cmd = (*p_iter);
1.128 - if (cmd.pHook == pHook)
1.129 - {
1.130 - p_iter = pList->erase(p_iter);
1.131 - }
1.132 - else
1.133 - {
1.134 - p_iter++;
1.135 - }
1.136 - }
1.137 -
1.138 - delete pHook->pAdmin;
1.139 - delete pHook;
1.140 -
1.141 - iter = cmdlist.erase(iter);
1.142 - }
1.143 -}
1.144 -
1.145 -void ConCmdManager::RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext)
1.146 -{
1.147 - List<CmdHook *>::iterator iter = cmdlist.begin();
1.148 - CmdHook *pHook;
1.149 -
1.150 - while (iter != cmdlist.end())
1.151 - {
1.152 - pHook = (*iter);
1.153 - if (pHook->pf->GetParentContext() == pContext)
1.154 - {
1.155 - delete pHook->pAdmin;
1.156 - delete pHook;
1.157 - iter = cmdlist.erase(iter);
1.158 - }
1.159 - else
1.160 - {
1.161 - iter++;
1.162 - }
1.163 - }
1.164 -}
1.165 -
1.166 -void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
1.167 -{
1.168 - CmdList *pList;
1.169 - List<ConCmdInfo *> removed;
1.170 - if (plugin->GetProperty("CommandList", (void **)&pList, true))
1.171 - {
1.172 - IPluginContext *pContext = plugin->GetBaseContext();
1.173 - CmdList::iterator iter;
1.174 - /* First pass!
1.175 - * Only bother if there's an actual command list on this plugin...
1.176 - */
1.177 - for (iter=pList->begin();
1.178 - iter!=pList->end();
1.179 - iter++)
1.180 - {
1.181 - PlCmdInfo &cmd = (*iter);
1.182 - ConCmdInfo *pInfo = cmd.pInfo;
1.183 -
1.184 - /* Has this chain already been fully cleaned/removed? */
1.185 - if (removed.find(pInfo) != removed.end())
1.186 - {
1.187 - continue;
1.188 - }
1.189 -
1.190 - /* Remove any hooks from us on this command */
1.191 - RemoveConCmds(pInfo->conhooks, pContext);
1.192 - RemoveConCmds(pInfo->srvhooks, pContext);
1.193 -
1.194 - /* See if there are still hooks */
1.195 - if (pInfo->srvhooks.size())
1.196 - {
1.197 - continue;
1.198 - }
1.199 - if (pInfo->conhooks.size())
1.200 - {
1.201 - continue;
1.202 - }
1.203 -
1.204 - /* Remove the command, it should be safe now */
1.205 - RemoveConCmd(pInfo, pInfo->pCmd->GetName(), true, true);
1.206 - removed.push_back(pInfo);
1.207 - }
1.208 - delete pList;
1.209 - }
1.210 -}
1.211 -#if defined ORANGEBOX_BUILD
1.212 -void CommandCallback(const CCommand &command)
1.213 -{
1.214 -#else
1.215 -void CommandCallback()
1.216 -{
1.217 - CCommand command;
1.218 -#endif
1.219 -
1.220 - g_HL2.PushCommandStack(&command);
1.221 -
1.222 - g_ConCmds.InternalDispatch(command);
1.223 -
1.224 - g_HL2.PopCommandStack();
1.225 -}
1.226 -
1.227 -void ConCmdManager::SetCommandClient(int client)
1.228 -{
1.229 - m_CmdClient = client + 1;
1.230 -}
1.231 -
1.232 -ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int args, ResultType type)
1.233 -{
1.234 - ConCmdInfo *pInfo;
1.235 - if (sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
1.236 - {
1.237 - cell_t result = type;
1.238 - cell_t tempres = result;
1.239 - List<CmdHook *>::iterator iter;
1.240 - CmdHook *pHook;
1.241 - for (iter=pInfo->conhooks.begin();
1.242 - iter!=pInfo->conhooks.end();
1.243 - iter++)
1.244 - {
1.245 - pHook = (*iter);
1.246 - if (!pHook->pf->IsRunnable())
1.247 - {
1.248 - continue;
1.249 - }
1.250 - if (pHook->pAdmin && !CheckAccess(client, cmd, pHook->pAdmin))
1.251 - {
1.252 - if (result < Pl_Handled)
1.253 - {
1.254 - result = Pl_Handled;
1.255 - }
1.256 - continue;
1.257 - }
1.258 - pHook->pf->PushCell(client);
1.259 - pHook->pf->PushCell(args);
1.260 - if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
1.261 - {
1.262 - if (tempres > result)
1.263 - {
1.264 - result = tempres;
1.265 - }
1.266 - if (result == Pl_Stop)
1.267 - {
1.268 - break;
1.269 - }
1.270 - }
1.271 - }
1.272 - type = (ResultType)result;
1.273 - }
1.274 -
1.275 - return type;
1.276 -}
1.277 -
1.278 -void ConCmdManager::InternalDispatch(const CCommand &command)
1.279 -{
1.280 - int client = m_CmdClient;
1.281 -
1.282 - if (client)
1.283 - {
1.284 - CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1.285 - if (!pPlayer || !pPlayer->IsConnected())
1.286 - {
1.287 - return;
1.288 - }
1.289 - }
1.290 -
1.291 - /**
1.292 - * Note: Console commands will EITHER go through IServerGameDLL::ClientCommand,
1.293 - * OR this dispatch. They will NEVER go through both.
1.294 - * --
1.295 - * Whether or not it goes through the callback is determined by FCVAR_GAMEDLL
1.296 - */
1.297 - const char *cmd = g_HL2.CurrentCommandName();
1.298 -
1.299 - ConCmdInfo *pInfo;
1.300 - if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
1.301 - {
1.302 - return;
1.303 - }
1.304 -
1.305 - /* This is a hack to prevent say triggers from firing on messages that were
1.306 - * blocked because of flooding. We won't remove this, but the hack will get
1.307 - * "nicer" when we expose explicit say hooks.
1.308 - */
1.309 - if (g_ChatTriggers.WasFloodedMessage())
1.310 - {
1.311 - return;
1.312 - }
1.313 -
1.314 - cell_t result = Pl_Continue;
1.315 - int args = command.ArgC() - 1;
1.316 -
1.317 - List<CmdHook *>::iterator iter;
1.318 - CmdHook *pHook;
1.319 -
1.320 - /* Execute server-only commands if viable */
1.321 - if (client == 0 && pInfo->srvhooks.size())
1.322 - {
1.323 - cell_t tempres = result;
1.324 - for (iter=pInfo->srvhooks.begin();
1.325 - iter!=pInfo->srvhooks.end();
1.326 - iter++)
1.327 - {
1.328 - pHook = (*iter);
1.329 - if (!pHook->pf->IsRunnable())
1.330 - {
1.331 - continue;
1.332 - }
1.333 - pHook->pf->PushCell(args);
1.334 - if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
1.335 - {
1.336 - if (tempres > result)
1.337 - {
1.338 - result = tempres;
1.339 - }
1.340 - if (result == Pl_Stop)
1.341 - {
1.342 - break;
1.343 - }
1.344 - }
1.345 - }
1.346 -
1.347 - /* Check if there's an early stop */
1.348 - if (result >= Pl_Stop)
1.349 - {
1.350 - if (!pInfo->sourceMod)
1.351 - {
1.352 - RETURN_META(MRES_SUPERCEDE);
1.353 - }
1.354 - return;
1.355 - }
1.356 - }
1.357 -
1.358 - /* Execute console commands */
1.359 - if (pInfo->conhooks.size())
1.360 - {
1.361 - cell_t tempres = result;
1.362 - for (iter=pInfo->conhooks.begin();
1.363 - iter!=pInfo->conhooks.end();
1.364 - iter++)
1.365 - {
1.366 - pHook = (*iter);
1.367 - if (!pHook->pf->IsRunnable())
1.368 - {
1.369 - continue;
1.370 - }
1.371 - if (client
1.372 - && pHook->pAdmin
1.373 - && !CheckAccess(client, cmd, pHook->pAdmin))
1.374 - {
1.375 - if (result < Pl_Handled)
1.376 - {
1.377 - result = Pl_Handled;
1.378 - }
1.379 - continue;
1.380 - }
1.381 -
1.382 - /* On a listen server, sometimes the server host's client index can be set as 0.
1.383 - * So index 1 is passed to the command callback to correct this potential problem.
1.384 - */
1.385 - if (!engine->IsDedicatedServer())
1.386 - {
1.387 - client = g_Players.ListenClient();
1.388 - }
1.389 -
1.390 - pHook->pf->PushCell(client);
1.391 - pHook->pf->PushCell(args);
1.392 -
1.393 - if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
1.394 - {
1.395 - if (tempres > result)
1.396 - {
1.397 - result = tempres;
1.398 - }
1.399 - if (result == Pl_Stop)
1.400 - {
1.401 - break;
1.402 - }
1.403 - }
1.404 - }
1.405 - }
1.406 -
1.407 - if (result >= Pl_Handled)
1.408 - {
1.409 - if (!pInfo->sourceMod)
1.410 - {
1.411 - RETURN_META(MRES_SUPERCEDE);
1.412 - }
1.413 - return;
1.414 - }
1.415 -}
1.416 -
1.417 -bool ConCmdManager::CheckCommandAccess(int client, const char *cmd, FlagBits cmdflags)
1.418 -{
1.419 - if (cmdflags == 0 || client == 0)
1.420 - {
1.421 - return true;
1.422 - }
1.423 -
1.424 - /* If running listen server, then client 1 is the server host and should have 'root' access */
1.425 - if (client == 1 && !engine->IsDedicatedServer())
1.426 - {
1.427 - return true;
1.428 - }
1.429 -
1.430 - CPlayer *player = g_Players.GetPlayerByIndex(client);
1.431 - if (!player
1.432 - || player->GetEdict() == NULL
1.433 - || player->IsFakeClient())
1.434 - {
1.435 - return false;
1.436 - }
1.437 -
1.438 - AdminId adm = player->GetAdminId();
1.439 - if (adm != INVALID_ADMIN_ID)
1.440 - {
1.441 - FlagBits bits = g_Admins.GetAdminFlags(adm, Access_Effective);
1.442 -
1.443 - /* root knows all, WHOA */
1.444 - if ((bits & ADMFLAG_ROOT) == ADMFLAG_ROOT)
1.445 - {
1.446 - return true;
1.447 - }
1.448 -
1.449 - /* Check for overrides
1.450 - * :TODO: is it worth optimizing this?
1.451 - */
1.452 - unsigned int groups = g_Admins.GetAdminGroupCount(adm);
1.453 - GroupId gid;
1.454 - OverrideRule rule;
1.455 - bool override = false;
1.456 - for (unsigned int i=0; i<groups; i++)
1.457 - {
1.458 - gid = g_Admins.GetAdminGroup(adm, i, NULL);
1.459 - /* First get group-level override */
1.460 - override = g_Admins.GetGroupCommandOverride(gid, cmd, Override_CommandGroup, &rule);
1.461 - /* Now get the specific command override */
1.462 - if (g_Admins.GetGroupCommandOverride(gid, cmd, Override_Command, &rule))
1.463 - {
1.464 - override = true;
1.465 - }
1.466 - if (override)
1.467 - {
1.468 - if (rule == Command_Allow)
1.469 - {
1.470 - return true;
1.471 - }
1.472 - else if (rule == Command_Deny)
1.473 - {
1.474 - return false;
1.475 - }
1.476 - }
1.477 - }
1.478 -
1.479 - /* See if our other flags match */
1.480 - if ((bits & cmdflags) == cmdflags)
1.481 - {
1.482 - return true;
1.483 - }
1.484 - }
1.485 -
1.486 - return false;
1.487 -}
1.488 -
1.489 -bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin)
1.490 -{
1.491 - if (CheckCommandAccess(client, cmd, pAdmin->eflags))
1.492 - {
1.493 - return true;
1.494 - }
1.495 -
1.496 - edict_t *pEdict = engine->PEntityOfEntIndex(client);
1.497 -
1.498 - /* If we got here, the command failed... */
1.499 - char buffer[128];
1.500 - if (!CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client))
1.501 - {
1.502 - UTIL_Format(buffer, sizeof(buffer), "You do not have access to this command");
1.503 - }
1.504 -
1.505 - unsigned int replyto = g_ChatTriggers.GetReplyTo();
1.506 - if (replyto == SM_REPLY_CONSOLE)
1.507 - {
1.508 - char fullbuffer[192];
1.509 - UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s.\n", buffer);
1.510 - engine->ClientPrintf(pEdict, fullbuffer);
1.511 - }
1.512 - else if (replyto == SM_REPLY_CHAT)
1.513 - {
1.514 - char fullbuffer[192];
1.515 - UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s.", buffer);
1.516 - g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);
1.517 - }
1.518 -
1.519 - return false;
1.520 -}
1.521 -
1.522 -bool ConCmdManager::AddConsoleCommand(IPluginFunction *pFunction,
1.523 - const char *name,
1.524 - const char *description,
1.525 - int flags)
1.526 -{
1.527 - ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
1.528 -
1.529 - if (!pInfo)
1.530 - {
1.531 - return false;
1.532 - }
1.533 -
1.534 - CmdHook *pHook = new CmdHook();
1.535 -
1.536 - pHook->pf = pFunction;
1.537 - if (description && description[0])
1.538 - {
1.539 - pHook->helptext.assign(description);
1.540 - }
1.541 - pInfo->conhooks.push_back(pHook);
1.542 -
1.543 - /* Add to the plugin */
1.544 - CmdList *pList;
1.545 - IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
1.546 - if (!pPlugin->GetProperty("CommandList", (void **)&pList))
1.547 - {
1.548 - pList = new CmdList();
1.549 - pPlugin->SetProperty("CommandList", pList);
1.550 - }
1.551 - PlCmdInfo info;
1.552 - info.pInfo = pInfo;
1.553 - info.type = Cmd_Console;
1.554 - info.pHook = pHook;
1.555 - AddToPlCmdList(pList, info);
1.556 -
1.557 - return true;
1.558 -}
1.559 -
1.560 -bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
1.561 - const char *name,
1.562 - const char *group,
1.563 - int adminflags,
1.564 - const char *description,
1.565 - int flags)
1.566 -{
1.567 - ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
1.568 -
1.569 - if (!pInfo)
1.570 - {
1.571 - return false;
1.572 - }
1.573 -
1.574 - CmdHook *pHook = new CmdHook();
1.575 - AdminCmdInfo *pAdmin = new AdminCmdInfo();
1.576 -
1.577 - pHook->pf = pFunction;
1.578 - if (description && description[0])
1.579 - {
1.580 - pHook->helptext.assign(description);
1.581 - }
1.582 - pHook->pAdmin = pAdmin;
1.583 -
1.584 - void *object;
1.585 - int grpid;
1.586 - if (!sm_trie_retrieve(m_pCmdGrps, group, (void **)&object))
1.587 - {
1.588 - grpid = m_Strings.AddString(group);
1.589 - sm_trie_insert(m_pCmdGrps, group, (void *)grpid);
1.590 - }
1.591 - else
1.592 - {
1.593 - grpid = (int)object;
1.594 - }
1.595 -
1.596 - pAdmin->cmdGrpId = grpid;
1.597 - pAdmin->flags = adminflags;
1.598 -
1.599 - /* First get the command group override, if any */
1.600 - bool override = g_Admins.GetCommandOverride(group,
1.601 - Override_CommandGroup,
1.602 - &(pAdmin->eflags));
1.603 -
1.604 - /* Next get the command override, if any */
1.605 - if (g_Admins.GetCommandOverride(name,
1.606 - Override_Command,
1.607 - &(pAdmin->eflags)))
1.608 - {
1.609 - override = true;
1.610 - }
1.611 -
1.612 - /* Assign normal flags if there were no overrides */
1.613 - if (!override)
1.614 - {
1.615 - pAdmin->eflags = pAdmin->flags;
1.616 - }
1.617 -
1.618 - /* Finally, add the hook */
1.619 - pInfo->conhooks.push_back(pHook);
1.620 - pInfo->admin = *(pHook->pAdmin);
1.621 - pInfo->is_admin_set = true;
1.622 -
1.623 - /* Now add to the plugin */
1.624 - CmdList *pList;
1.625 - IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
1.626 - if (!pPlugin->GetProperty("CommandList", (void **)&pList))
1.627 - {
1.628 - pList = new CmdList();
1.629 - pPlugin->SetProperty("CommandList", pList);
1.630 - }
1.631 - PlCmdInfo info;
1.632 - info.pInfo = pInfo;
1.633 - info.type = Cmd_Admin;
1.634 - info.pHook = pHook;
1.635 - AddToPlCmdList(pList, info);
1.636 -
1.637 - return true;
1.638 -}
1.639 -
1.640 -bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction,
1.641 - const char *name,
1.642 - const char *description,
1.643 - int flags)
1.644 -
1.645 -{
1.646 - ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
1.647 -
1.648 - if (!pInfo)
1.649 - {
1.650 - return false;
1.651 - }
1.652 -
1.653 - CmdHook *pHook = new CmdHook();
1.654 -
1.655 - pHook->pf = pFunction;
1.656 - if (description && description[0])
1.657 - {
1.658 - pHook->helptext.assign(description);
1.659 - }
1.660 -
1.661 - pInfo->srvhooks.push_back(pHook);
1.662 -
1.663 - /* Add to the plugin */
1.664 - CmdList *pList;
1.665 - IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
1.666 - if (!pPlugin->GetProperty("CommandList", (void **)&pList))
1.667 - {
1.668 - pList = new CmdList();
1.669 - pPlugin->SetProperty("CommandList", pList);
1.670 - }
1.671 - PlCmdInfo info;
1.672 - info.pInfo = pInfo;
1.673 - info.type = Cmd_Server;
1.674 - info.pHook = pHook;
1.675 - AddToPlCmdList(pList, info);
1.676 -
1.677 - return true;
1.678 -}
1.679 -
1.680 -void AddToPlCmdList(CmdList *pList, const PlCmdInfo &info)
1.681 -{
1.682 - CmdList::iterator iter = pList->begin();
1.683 - bool inserted = false;
1.684 - const char *orig = NULL;
1.685 -
1.686 - orig = info.pInfo->pCmd->GetName();
1.687 -
1.688 - /* Insert this into the help list, SORTED alphabetically. */
1.689 - while (iter != pList->end())
1.690 - {
1.691 - PlCmdInfo &obj = (*iter);
1.692 - const char *cmd = obj.pInfo->pCmd->GetName();
1.693 - if (strcmp(orig, cmd) < 0)
1.694 - {
1.695 - pList->insert(iter, info);
1.696 - inserted = true;
1.697 - break;
1.698 - }
1.699 - iter++;
1.700 - }
1.701 -
1.702 - if (!inserted)
1.703 - {
1.704 - pList->push_back(info);
1.705 - }
1.706 -}
1.707 -
1.708 -void ConCmdManager::AddToCmdList(ConCmdInfo *info)
1.709 -{
1.710 - List<ConCmdInfo *>::iterator iter = m_CmdList.begin();
1.711 - ConCmdInfo *pInfo;
1.712 - bool inserted = false;
1.713 - const char *orig = NULL;
1.714 -
1.715 - orig = info->pCmd->GetName();
1.716 -
1.717 - /* Insert this into the help list, SORTED alphabetically. */
1.718 - while (iter != m_CmdList.end())
1.719 - {
1.720 - const char *cmd = NULL;
1.721 - pInfo = (*iter);
1.722 - cmd = pInfo->pCmd->GetName();
1.723 - if (strcmp(orig, cmd) < 0)
1.724 - {
1.725 - m_CmdList.insert(iter, info);
1.726 - inserted = true;
1.727 - break;
1.728 - }
1.729 - iter++;
1.730 - }
1.731 -
1.732 - if (!inserted)
1.733 - {
1.734 - m_CmdList.push_back(info);
1.735 - }
1.736 -}
1.737 -
1.738 -void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove)
1.739 -{
1.740 - ConCmdInfo *pInfo;
1.741 -
1.742 - if (type == Override_Command)
1.743 - {
1.744 - if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
1.745 - {
1.746 - return;
1.747 - }
1.748 -
1.749 - List<CmdHook *>::iterator iter;
1.750 - CmdHook *pHook;
1.751 -
1.752 - for (iter=pInfo->conhooks.begin(); iter!=pInfo->conhooks.end(); iter++)
1.753 - {
1.754 - pHook = (*iter);
1.755 - if (pHook->pAdmin)
1.756 - {
1.757 - if (!remove)
1.758 - {
1.759 - pHook->pAdmin->eflags = bits;
1.760 - } else {
1.761 - pHook->pAdmin->eflags = pHook->pAdmin->flags;
1.762 - }
1.763 - pInfo->admin = *(pHook->pAdmin);
1.764 - }
1.765 - }
1.766 - pInfo->is_admin_set = true;
1.767 - }
1.768 - else if (type == Override_CommandGroup)
1.769 - {
1.770 - void *object;
1.771 - if (!sm_trie_retrieve(m_pCmdGrps, cmd, &object))
1.772 - {
1.773 - return;
1.774 - }
1.775 - int grpid = (int)object;
1.776 -
1.777 - /* This is bad :( loop through all commands */
1.778 - List<ConCmdInfo *>::iterator iter;
1.779 - CmdHook *pHook;
1.780 - for (iter=m_CmdList.begin(); iter!=m_CmdList.end(); iter++)
1.781 - {
1.782 - pInfo = (*iter);
1.783 - for (List<CmdHook *>::iterator citer=pInfo->conhooks.begin();
1.784 - citer!=pInfo->conhooks.end();
1.785 - citer++)
1.786 - {
1.787 - pHook = (*citer);
1.788 - if (pHook->pAdmin && pHook->pAdmin->cmdGrpId == grpid)
1.789 - {
1.790 - if (remove)
1.791 - {
1.792 - pHook->pAdmin->eflags = bits;
1.793 - } else {
1.794 - pHook->pAdmin->eflags = pHook->pAdmin->flags;
1.795 - }
1.796 - pInfo->admin = *(pHook->pAdmin);
1.797 - }
1.798 - }
1.799 - }
1.800 - pInfo->is_admin_set = true;
1.801 - }
1.802 -}
1.803 -
1.804 -void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_read_safe, bool untrack)
1.805 -{
1.806 - /* Remove from the trie */
1.807 - sm_trie_delete(m_pCmds, name);
1.808 -
1.809 - /* Remove console-specific information
1.810 - * This should always be true as of right now
1.811 - */
1.812 - if (info->pCmd)
1.813 - {
1.814 - if (info->sourceMod)
1.815 - {
1.816 - /* Unlink from SourceMM */
1.817 - g_SMAPI->UnregisterConCommandBase(g_PLAPI, info->pCmd);
1.818 - /* Delete the command's memory */
1.819 - char *new_help = const_cast<char *>(info->pCmd->GetHelpText());
1.820 - char *new_name = const_cast<char *>(info->pCmd->GetName());
1.821 - delete [] new_help;
1.822 - delete [] new_name;
1.823 - delete info->pCmd;
1.824 - }
1.825 - else
1.826 - {
1.827 - if (is_read_safe)
1.828 - {
1.829 - /* Remove the external hook */
1.830 - SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, info->pCmd, CommandCallback, false);
1.831 - }
1.832 - if (untrack)
1.833 - {
1.834 - UntrackConCommandBase(info->pCmd, this);
1.835 - }
1.836 - }
1.837 - }
1.838 -
1.839 - /* Remove from list */
1.840 - m_CmdList.remove(info);
1.841 -
1.842 - delete info;
1.843 -}
1.844 -
1.845 -bool ConCmdManager::LookForSourceModCommand(const char *cmd)
1.846 -{
1.847 - ConCmdInfo *pInfo;
1.848 -
1.849 - if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
1.850 - {
1.851 - return false;
1.852 - }
1.853 -
1.854 - return pInfo->sourceMod && (pInfo->conhooks.size() > 0);
1.855 -}
1.856 -
1.857 -bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
1.858 -{
1.859 - ConCmdInfo *pInfo;
1.860 -
1.861 - if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
1.862 - {
1.863 - return false;
1.864 - }
1.865 -
1.866 - *pFlags = pInfo->admin.eflags;
1.867 -
1.868 - return pInfo->is_admin_set;
1.869 -}
1.870 -
1.871 -ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags)
1.872 -{
1.873 - ConCmdInfo *pInfo;
1.874 - if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
1.875 - {
1.876 - pInfo = new ConCmdInfo();
1.877 - /* Find the commandopan */
1.878 - ConCommandBase *pBase = icvar->GetCommands();
1.879 - ConCommand *pCmd = NULL;
1.880 - while (pBase)
1.881 - {
1.882 - if (strcmp(pBase->GetName(), name) == 0)
1.883 - {
1.884 - /* Don't want to return convar with same name */
1.885 - if (!pBase->IsCommand())
1.886 - {
1.887 - return NULL;
1.888 - }
1.889 -
1.890 - pCmd = (ConCommand *)pBase;
1.891 - break;
1.892 - }
1.893 - pBase = const_cast<ConCommandBase *>(pBase->GetNext());
1.894 - }
1.895 -
1.896 - if (!pCmd)
1.897 - {
1.898 - /* Note that we have to duplicate because the source might not be
1.899 - * a static string, and these expect static memory.
1.900 - */
1.901 - if (!description)
1.902 - {
1.903 - description = "";
1.904 - }
1.905 - char *new_name = sm_strdup(name);
1.906 - char *new_help = sm_strdup(description);
1.907 - pCmd = new ConCommand(new_name, CommandCallback, new_help, flags);
1.908 - pInfo->sourceMod = true;
1.909 - }
1.910 - else
1.911 - {
1.912 - TrackConCommandBase(pCmd, this);
1.913 - SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pCmd, CommandCallback, false);
1.914 - }
1.915 -
1.916 - pInfo->pCmd = pCmd;
1.917 - pInfo->is_admin_set = false;
1.918 -
1.919 - sm_trie_insert(m_pCmds, name, pInfo);
1.920 - AddToCmdList(pInfo);
1.921 - }
1.922 -
1.923 - return pInfo;
1.924 -}
1.925 -
1.926 -void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
1.927 -{
1.928 - if (command.ArgC() >= 3)
1.929 - {
1.930 - const char *text = command.Arg(2);
1.931 -
1.932 - CPlugin *pPlugin = g_PluginSys.FindPluginByConsoleArg(text);
1.933 -
1.934 - if (!pPlugin)
1.935 - {
1.936 - g_RootMenu.ConsolePrint("[SM] Plugin \"%s\" was not found.", text);
1.937 - return;
1.938 - }
1.939 -
1.940 - const sm_plugininfo_t *plinfo = pPlugin->GetPublicInfo();
1.941 - const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : pPlugin->GetFilename();
1.942 -
1.943 - CmdList *pList;
1.944 - if (!pPlugin->GetProperty("CommandList", (void **)&pList))
1.945 - {
1.946 - g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
1.947 - return;
1.948 - }
1.949 - if (!pList->size())
1.950 - {
1.951 - g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
1.952 - return;
1.953 - }
1.954 -
1.955 - CmdList::iterator iter;
1.956 - const char *type = NULL;
1.957 - const char *name;
1.958 - const char *help;
1.959 - g_RootMenu.ConsolePrint("[SM] Listing %d commands for: %s", pList->size(), plname);
1.960 - g_RootMenu.ConsolePrint(" %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]");
1.961 - for (iter=pList->begin();
1.962 - iter!=pList->end();
1.963 - iter++)
1.964 - {
1.965 - PlCmdInfo &cmd = (*iter);
1.966 - if (cmd.type == Cmd_Server)
1.967 - {
1.968 - type = "server";
1.969 - }
1.970 - else if (cmd.type == Cmd_Console)
1.971 - {
1.972 - type = "console";
1.973 - }
1.974 - else if (cmd.type == Cmd_Admin)
1.975 - {
1.976 - type = "admin";
1.977 - }
1.978 - name = cmd.pInfo->pCmd->GetName();
1.979 - if (cmd.pHook->helptext.size())
1.980 - {
1.981 - help = cmd.pHook->helptext.c_str();
1.982 - }
1.983 - else
1.984 - {
1.985 - help = cmd.pInfo->pCmd->GetHelpText();
1.986 - }
1.987 - g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
1.988 - }
1.989 -
1.990 - return;
1.991 - }
1.992 -
1.993 - g_RootMenu.ConsolePrint("[SM] Usage: sm cmds <plugin #>");
1.994 -}