- Added ForceChangeLevel and Map History to nextmap api

- Changed base plugins to use new api
- Added sm_maphistory command to nextmap.sp

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402413
This commit is contained in:
Matt Woodrow
2008-07-13 05:13:37 +00:00
parent 8126aa6bb8
commit c75d607a00
10 changed files with 329 additions and 11 deletions
+135
View File
@@ -33,13 +33,26 @@
#include "Logger.h"
#include "sourcemm_api.h"
#include "sm_stringutil.h"
#include "sourcehook.h"
#include "sm_srvcmds.h"
NextMapManager g_NextMap;
SH_DECL_HOOK2_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *);
#if defined ORANGEBOX_BUILD
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#else
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
#endif
ConCommand *changeLevelCmd = NULL;
ConVar sm_nextmap("sm_nextmap", "", FCVAR_NOTIFY);
bool g_forcedChange = false;
void NextMapManager::OnSourceModAllInitialized_Post()
{
#if defined ORANGEBOX_BUILD
@@ -47,6 +60,30 @@ void NextMapManager::OnSourceModAllInitialized_Post()
#else
SH_ADD_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false);
#endif
ConCommandBase *pBase = icvar->GetCommands();
ConCommand *pCmd = NULL;
while (pBase)
{
if (strcmp(pBase->GetName(), "changelevel") == 0)
{
/* Don't want to return convar with same name */
if (!pBase->IsCommand())
{
break;
}
pCmd = (ConCommand *)pBase;
break;
}
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
}
if (pCmd != NULL)
{
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pCmd, CmdChangeLevelCallback, false);
changeLevelCmd = pCmd;
}
}
void NextMapManager::OnSourceModShutdown()
@@ -56,6 +93,20 @@ void NextMapManager::OnSourceModShutdown()
#else
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false);
#endif
if (changeLevelCmd != NULL)
{
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, changeLevelCmd, CmdChangeLevelCallback, false);
}
SourceHook::List<MapChangeData *>::iterator iter;
iter = m_mapHistory.begin();
while (iter != m_mapHistory.end())
{
delete (MapChangeData *)*iter;
iter = m_mapHistory.erase(iter);
}
}
const char *NextMapManager::GetNextMap()
@@ -77,6 +128,12 @@ bool NextMapManager::SetNextMap(const char *map)
void NextMapManager::HookChangeLevel(const char *map, const char *unknown)
{
if (g_forcedChange)
{
g_Logger.LogMessage("[SM] Changed map to \"%s\"", map);
RETURN_META(MRES_IGNORED);
}
const char *newmap = sm_nextmap.GetString();
if (newmap[0] == 0 || !engine->IsMapValid(newmap))
@@ -86,5 +143,83 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown)
g_Logger.LogMessage("[SM] Changed map to \"%s\"", newmap);
UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown));
}
void NextMapManager::OnSourceModLevelChange( const char *mapName )
{
/* Skip the first 'mapchange' when the server starts up */
if (m_tempChangeInfo.startTime != 0)
{
if (strcmp(mapName, m_tempChangeInfo.m_mapName) == 0)
{
/* The map change was as we expected */
m_mapHistory.push_back(new MapChangeData(lastMap, m_tempChangeInfo.m_changeReason, m_tempChangeInfo.startTime));
}
else
{
/* Something intercepted the mapchange */
char newReason[255];
UTIL_Format(newReason, sizeof(newReason), "%s (Map overridden)", m_tempChangeInfo.m_changeReason);
m_mapHistory.push_back(new MapChangeData(lastMap, newReason, m_tempChangeInfo.startTime));
}
/* TODO: Should this be customizable? */
if (m_mapHistory.size() > 20)
{
SourceHook::List<MapChangeData *>::iterator iter;
iter = m_mapHistory.begin();
delete (MapChangeData *)*iter;
m_mapHistory.erase(iter);
}
}
m_tempChangeInfo.m_mapName[0] ='\0';
m_tempChangeInfo.m_changeReason[0] = '\0';
m_tempChangeInfo.startTime = time(NULL);
UTIL_Format(lastMap, sizeof(lastMap), mapName);
}
void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeReason )
{
/* Store the mapname and reason */
UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), mapName);
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), changeReason);
/* Change level and skip our hook */
g_forcedChange = true;
engine->ChangeLevel(mapName, NULL);
g_forcedChange = false;
}
NextMapManager::NextMapManager()
{
m_tempChangeInfo = MapChangeData();
m_mapHistory = SourceHook::List<MapChangeData *>();
}
#if defined ORANGEBOX_BUILD
void CmdChangeLevelCallback(const CCommand &command)
{
#else
void CmdChangeLevelCallback()
{
CCommand command;
#endif
if (command.ArgC() < 2)
{
return;
}
if (g_NextMap.m_tempChangeInfo.m_mapName[0] == '\0')
{
UTIL_Format(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1));
UTIL_Format(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command");
}
}
+41
View File
@@ -34,17 +34,58 @@
#include "sm_globals.h"
#include "eiface.h"
#include "sh_list.h"
#include "sm_stringutil.h"
struct MapChangeData
{
MapChangeData(const char *mapName, const char *changeReason, time_t time)
{
UTIL_Format(m_mapName, sizeof(m_mapName), mapName);
UTIL_Format(m_changeReason, sizeof(m_changeReason), changeReason);
startTime = time;
}
MapChangeData()
{
m_mapName[0] = '\0';
m_changeReason[0] = '\0';
startTime = 0;
}
char m_mapName[32];
char m_changeReason[100];
time_t startTime;
};
class NextMapManager : public SMGlobalClass
{
public:
NextMapManager();
#if defined ORANGEBOX_BUILD
friend void CmdChangeLevelCallback(const CCommand &command);
#else
friend void CmdChangeLevelCallback();
#endif
void OnSourceModAllInitialized_Post();
void OnSourceModShutdown();
void OnSourceModLevelChange(const char *mapName);
const char *GetNextMap();
bool SetNextMap(const char *map);
void ForceChangeLevel(const char *mapName, const char* changeReason);
void HookChangeLevel(const char *map, const char *unknown);
public:
SourceHook::List<MapChangeData *> m_mapHistory;
private:
MapChangeData m_tempChangeInfo;
char lastMap[32];
};
extern NextMapManager g_NextMap;
+51 -3
View File
@@ -54,10 +54,58 @@ static cell_t sm_SetNextMap(IPluginContext *pCtx, const cell_t *params)
return g_NextMap.SetNextMap(map);
}
static cell_t sm_ForceChangeLevel(IPluginContext *pCtx, const cell_t *params)
{
char *map;
char *changeReason;
pCtx->LocalToString(params[1], &map);
pCtx->LocalToString(params[2], &changeReason);
g_NextMap.ForceChangeLevel(map, changeReason);
return 0;
}
static cell_t sm_GetMapHistorySize(IPluginContext *pCtx, const cell_t *params)
{
return g_NextMap.m_mapHistory.size();
}
static cell_t sm_GetMapHistory(IPluginContext *pCtx, const cell_t *params)
{
if (params[1] < 0 || params[1] >= (int)g_NextMap.m_mapHistory.size())
{
return pCtx->ThrowNativeError("Invalid Map History Index");
}
SourceHook::List<MapChangeData *>::iterator iter;
iter = g_NextMap.m_mapHistory.end();
iter--;
for (int i=0; i<params[1]; i++)
{
iter--;
}
MapChangeData *data = (MapChangeData *)*iter;
pCtx->StringToLocal(params[2], params[3], data->m_mapName);
pCtx->StringToLocal(params[4], params[5], data->m_changeReason);
cell_t *startTime;
pCtx->LocalToPhysAddr(params[6], &startTime);
*startTime = data->startTime;
return 0;
}
REGISTER_NATIVES(nextmapnatives)
{
{"GetNextMap", sm_GetNextMap},
{"SetNextMap", sm_SetNextMap},
{NULL, NULL},
{"GetNextMap", sm_GetNextMap},
{"SetNextMap", sm_SetNextMap},
{"ForceChangeLevel", sm_ForceChangeLevel},
{"GetMapHistorySize", sm_GetMapHistorySize},
{"GetMapHistory", sm_GetMapHistory},
{NULL, NULL},
};