diff --git a/core/PlayerManager.cpp b/core/PlayerManager.cpp index b49437aa..59939603 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -48,6 +48,7 @@ PlayerManager g_Players; bool g_OnMapStarted = false; IForward *PreAdminCheck = NULL; IForward *PostAdminCheck = NULL; +const unsigned int *g_NumPlayersToAuth = NULL; SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char *, const char *, char *, int); SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, const char *); @@ -86,6 +87,8 @@ PlayerManager::PlayerManager() PlayerManager::~PlayerManager() { + g_NumPlayersToAuth = NULL; + delete [] m_AuthQueue; delete [] m_UserIdLookUp; } @@ -187,6 +190,8 @@ void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int cl m_FirstPass = false; memset(m_AuthQueue, 0, sizeof(unsigned int) * (m_maxClients + 1)); + + g_NumPlayersToAuth = &m_AuthQueue[0]; } m_onActivate->Execute(NULL); m_onActivate2->Execute(NULL); @@ -318,7 +323,6 @@ void PlayerManager::RunAuthChecks() m_AuthQueue[0] -= removed; } else { m_AuthQueue[0] = 0; - g_SourceMod.SetAuthChecking(false); } } } @@ -351,7 +355,6 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const if (!m_Players[client].IsAuthorized()) { m_AuthQueue[++m_AuthQueue[0]] = client; - g_SourceMod.SetAuthChecking(true); } } else { RETURN_META_VALUE(MRES_SUPERCEDE, false); diff --git a/core/PlayerManager.h b/core/PlayerManager.h index 6a69ee07..c058f0d7 100644 --- a/core/PlayerManager.h +++ b/core/PlayerManager.h @@ -168,5 +168,6 @@ private: extern PlayerManager g_Players; extern bool g_OnMapStarted; +extern const unsigned int *g_NumPlayersToAuth; #endif //_INCLUDE_SOURCEMOD_CPLAYERMANAGER_H_ diff --git a/core/TimerSys.cpp b/core/TimerSys.cpp index 5c07edff..b07a95b4 100644 --- a/core/TimerSys.cpp +++ b/core/TimerSys.cpp @@ -31,13 +31,20 @@ #include #include "TimerSys.h" +#include "ForwardSys.h" #include "sourcemm_api.h" +#include "frame_hooks.h" TimerSystem g_Timers; +float g_fUniversalTime = 0.0f; +const float *g_pUniversalTime = &g_fUniversalTime; ConVar sm_time_adjustment("sm_time_adjustment", "0", 0, "Adjusts the server time in seconds"); -__BUILD_INTENTIONALLY_BROKEN_BY_BAIL__ +inline float GetSimulatedTime() +{ + return g_fUniversalTime; +} time_t GetAdjustedTime(time_t *buf) { @@ -49,11 +56,6 @@ time_t GetAdjustedTime(time_t *buf) return val; } -inline float GetSimulatedTime() -{ - return engine->Time(); -} - void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, void *pData, int flags) { m_Listener = pCallbacks; @@ -68,6 +70,9 @@ void ITimer::Initialize(ITimedEvent *pCallbacks, float fInterval, float fToExec, TimerSystem::TimerSystem() { m_fnTimeLeft = NULL; + m_bHasMapTickedYet = false; + m_fLastTickedTime = 0.0f; + m_LastExecTime = 0.0f; } TimerSystem::~TimerSystem() @@ -83,6 +88,12 @@ TimerSystem::~TimerSystem() void TimerSystem::OnSourceModAllInitialized() { g_ShareSys.AddInterface(NULL, this); + m_pOnGameFrame = g_Forwards.CreateForward("OnGameFrame", ET_Ignore, 0, NULL); +} + +void TimerSystem::OnSourceModShutdown() +{ + g_Forwards.ReleaseForward(m_pOnGameFrame); } void TimerSystem::OnSourceModLevelChange(const char *mapName) @@ -90,6 +101,38 @@ void TimerSystem::OnSourceModLevelChange(const char *mapName) MapChange(true); } +void TimerSystem::OnSourceModLevelEnd() +{ + m_bHasMapTickedYet = false; +} + +void TimerSystem::GameFrame(bool simulating) +{ + if (simulating && m_bHasMapTickedYet) + { + g_fUniversalTime += gpGlobals->curtime - m_fLastTickedTime; + } + else + { + g_fUniversalTime += gpGlobals->interval_per_tick; + } + + m_fLastTickedTime = gpGlobals->curtime; + m_bHasMapTickedYet = true; + + if (g_fUniversalTime - m_LastExecTime >= 0.1) + { + RunFrame(); + } + + RunFrameHooks(); + + if (m_pOnGameFrame->GetFunctionCount()) + { + m_pOnGameFrame->Execute(NULL); + } +} + void TimerSystem::RunFrame() { ITimer *pTimer; @@ -299,8 +342,6 @@ void TimerSystem::MapChange(bool real_mapchange) if (real_mapchange && (pTimer->m_Flags & TIMER_FLAG_NO_MAPCHANGE)) { s_tokill.push(pTimer); - } else { - pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + GetSimulatedTime(); } } @@ -310,8 +351,6 @@ void TimerSystem::MapChange(bool real_mapchange) if (real_mapchange && (pTimer->m_Flags & TIMER_FLAG_NO_MAPCHANGE)) { s_tokill.push(pTimer); - } else { - pTimer->m_ToExec = pTimer->m_ToExec - m_LastExecTime + GetSimulatedTime(); } } @@ -329,8 +368,6 @@ void TimerSystem::MapChange(bool real_mapchange) KillTimer(s_tokill.front()); s_tokill.pop(); } - - m_LastExecTime = GetSimulatedTime(); } SM_TIMELEFT_FUNCTION TimerSystem::SetTimeLeftFunction(SM_TIMELEFT_FUNCTION fn) diff --git a/core/TimerSys.h b/core/TimerSys.h index dd8a6379..7c841f5f 100644 --- a/core/TimerSys.h +++ b/core/TimerSys.h @@ -67,6 +67,8 @@ public: public: //SMGlobalClass void OnSourceModAllInitialized(); void OnSourceModLevelChange(const char *mapName); + void OnSourceModLevelEnd(); + void OnSourceModShutdown(); public: //ITimerSystem ITimer *CreateTimer(ITimedEvent *pCallbacks, float fInterval, void *pData, int flags); void KillTimer(ITimer *pTimer); @@ -75,6 +77,7 @@ public: //ITimerSystem public: void RunFrame(); void MapChange(bool real_mapchange); + void GameFrame(bool simulating); private: List m_SingleTimers; List m_LoopTimers; @@ -82,10 +85,19 @@ private: CStack m_FreeTimers; float m_LastExecTime; SM_TIMELEFT_FUNCTION m_fnTimeLeft; + + /* This is stuff for our manual ticking escapades. */ + bool m_bHasMapTickedYet; /** Has the map ticked yet? */ + float m_fLastTickedTime; /** Last time that the game currently gave + us while ticking. + */ + + IForward *m_pOnGameFrame; }; time_t GetAdjustedTime(time_t *buf = NULL); +extern const float *g_pUniversalTime; extern TimerSystem g_Timers; #endif //_INCLUDE_SOURCEMOD_CTIMERSYS_H_ diff --git a/core/frame_hooks.cpp b/core/frame_hooks.cpp new file mode 100644 index 00000000..5603e881 --- /dev/null +++ b/core/frame_hooks.cpp @@ -0,0 +1,63 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ +#include "frame_hooks.h" +#include "TimerSys.h" +#include "Database.h" +#include "HalfLife2.h" +#include "MenuStyle_Valve.h" +#include "MenuStyle_Radio.h" +#include "PlayerManager.h" + +float g_LastMenuTime = 0.0f; +float g_LastAuthCheck = 0.0f; + +void RunFrameHooks() +{ + /* Frame based hooks */ + g_DBMan.RunFrame(); + g_HL2.ProcessFakeCliCmdQueue(); + + float curtime = *g_pUniversalTime; + + if (curtime - g_LastMenuTime >= 1.0f) + { + g_ValveMenuStyle.ProcessWatchList(); + g_RadioMenuStyle.ProcessWatchList(); + g_LastMenuTime = curtime; + } + + if (*g_NumPlayersToAuth && curtime - g_LastAuthCheck >= 0.7f) + { + g_Players.RunAuthChecks(); + g_LastAuthCheck = curtime; + } +} + diff --git a/core/frame_hooks.h b/core/frame_hooks.h new file mode 100644 index 00000000..098ff428 --- /dev/null +++ b/core/frame_hooks.h @@ -0,0 +1,37 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_ +#define _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_ + +void RunFrameHooks(); + +#endif //_INCLUDE_SOURCEMOD_FRAME_HOOKS_H_ diff --git a/core/msvc8/sourcemod_mm.vcproj b/core/msvc8/sourcemod_mm.vcproj index 92ac6164..4eca4566 100644 --- a/core/msvc8/sourcemod_mm.vcproj +++ b/core/msvc8/sourcemod_mm.vcproj @@ -307,6 +307,10 @@ RelativePath="..\EventManager.cpp" > + + @@ -453,6 +457,10 @@ RelativePath="..\EventManager.h" > + + diff --git a/core/smn_timers.cpp b/core/smn_timers.cpp index 0b7aae97..27f2f1c9 100644 --- a/core/smn_timers.cpp +++ b/core/smn_timers.cpp @@ -255,8 +255,7 @@ static cell_t smn_TriggerTimer(IPluginContext *pCtx, const cell_t *params) static cell_t smn_GetTickedTime(IPluginContext *pContext, const cell_t *params) { - float t = engine->Time(); - return sp_ftoc(t); + return sp_ftoc(*g_pUniversalTime); } REGISTER_NATIVES(timernatives) diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index e77c8f5f..ada6343f 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -46,10 +46,6 @@ #include "Translator.h" #include "ForwardSys.h" #include "TimerSys.h" -#include "MenuStyle_Valve.h" -#include "MenuStyle_Radio.h" -#include "Database.h" -#include "HalfLife2.h" #include "GameConfigs.h" SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool); @@ -65,10 +61,6 @@ SourceHook::String g_BaseDir; ISourcePawnEngine *g_pSourcePawn = &g_SourcePawn; IVirtualMachine *g_pVM; IdentityToken_t *g_pCoreIdent = NULL; -float g_LastTime = 0.0f; -float g_LastMenuTime = 0.0f; -float g_LastAuthCheck = 0.0f; -IForward *g_pOnGameFrame = NULL; IForward *g_pOnMapEnd = NULL; bool g_Loaded = false; IExtension *g_pGameExt = NULL; @@ -286,7 +278,7 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late void SourceModBase::StartSourceMod(bool late) { SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, this, &SourceModBase::LevelShutdown, false); - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameFrame, gamedll, this, &SourceModBase::GameFrame, false); + SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameFrame, gamedll, &g_Timers, &TimerSystem::GameFrame, false); enginePatch = SH_GET_CALLCLASS(engine); gamedllPatch = SH_GET_CALLCLASS(gamedll); @@ -330,9 +322,6 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch m_IsMapLoading = true; m_ExecPluginReload = true; m_ExecOnMapEnd = true; - g_LastTime = 0.0f; - g_LastMenuTime = 0.0f; - g_LastAuthCheck = 0.0f; /* Notify! */ SMGlobalClass *pBase = SMGlobalClass::head; @@ -354,11 +343,6 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch pBase = pBase->m_pGlobalClassNext; } - if (!g_pOnGameFrame) - { - g_pOnGameFrame = g_Forwards.CreateForward("OnGameFrame", ET_Ignore, 0, NULL); - } - if (!g_pOnMapEnd) { g_pOnMapEnd = g_Forwards.CreateForward("OnMapEnd", ET_Ignore, 0, NULL); @@ -369,43 +353,6 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch RETURN_META_VALUE(MRES_IGNORED, true); } -void SourceModBase::GameFrame(bool simulating) -{ - g_DBMan.RunFrame(); - g_HL2.ProcessFakeCliCmdQueue(); - - /** - * Note: This is all hardcoded rather than delegated to save - * precious CPU cycles. - */ - float curtime = engine->Time(); - - if (curtime - g_LastTime >= 0.1f) - { - if (m_CheckingAuth - && (gpGlobals->curtime - g_LastAuthCheck > 0.7f)) - { - g_LastAuthCheck = gpGlobals->curtime; - g_Players.RunAuthChecks(); - } - - g_Timers.RunFrame(); - g_LastTime = curtime; - } - - if (gpGlobals->curtime - g_LastMenuTime >= 1.0f) - { - g_ValveMenuStyle.ProcessWatchList(); - g_RadioMenuStyle.ProcessWatchList(); - g_LastMenuTime = curtime; - } - - if (g_pOnGameFrame && g_pOnGameFrame->GetFunctionCount()) - { - g_pOnGameFrame->Execute(NULL); - } -} - void SourceModBase::LevelShutdown() { if (g_LevelEndBarrier) @@ -521,11 +468,6 @@ void SourceModBase::CloseSourceMod() if (g_Loaded) { - if (g_pOnGameFrame) - { - g_Forwards.ReleaseForward(g_pOnGameFrame); - } - if (g_pOnMapEnd) { g_Forwards.ReleaseForward(g_pOnMapEnd); @@ -570,7 +512,7 @@ void SourceModBase::CloseSourceMod() } SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, this, &SourceModBase::LevelShutdown, false); - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GameFrame, gamedll, this, &SourceModBase::GameFrame, false); + SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GameFrame, gamedll, &g_Timers, &TimerSystem::GameFrame, false); } /* Rest In Peace */ @@ -641,11 +583,6 @@ void SourceModBase::SetGlobalTarget(unsigned int index) m_target = index; } -void SourceModBase::SetAuthChecking(bool set) -{ - m_CheckingAuth = set; -} - unsigned int SourceModBase::GetGlobalTarget() const { return m_target; diff --git a/core/sourcemod.h b/core/sourcemod.h index e677dae2..6a5f85de 100644 --- a/core/sourcemod.h +++ b/core/sourcemod.h @@ -89,11 +89,6 @@ public: * @brief Returns the global target index. */ unsigned int GetGlobalTarget() const; - - /** - * @brief Sets whether if SoureMod needs to check player auths. - */ - void SetAuthChecking(bool set); public: // SMGlobalClass ConfigResult OnSourceModConfigChanged(const char *key, const char *value, @@ -121,11 +116,6 @@ private: * @brief Loading plugins */ void DoGlobalPluginLoads(); - - /** - * @brief GameFrame hook - */ - void GameFrame(bool simulating); private: CStack m_freepacks; char m_SMBaseDir[PLATFORM_MAX_PATH]; @@ -135,7 +125,6 @@ private: bool m_ExecPluginReload; bool m_ExecOnMapEnd; unsigned int m_target; - bool m_CheckingAuth; bool m_GotBasePath; }; diff --git a/plugins/include/timers.inc b/plugins/include/timers.inc index e11030de..a49dea1d 100644 --- a/plugins/include/timers.inc +++ b/plugins/include/timers.inc @@ -108,15 +108,17 @@ native KillTimer(Handle:timer, bool:autoClose=false); native TriggerTimer(Handle:timer, bool:reset=false); /** - * Returns the simulated game time. + * Returns the simulated game time. + * + * This time is internally maintained by SourceMod and is based on the game + * tick count and tick rate. Unlike GetGameTime(), it will increment past + * map changes and while no players are connected. Unlike GetEngineTime(), + * it will not increment based on the system clock (i.e. it is still bound + * to the ticking process). * - * @param simulated Retrieves whether or not the tick count - * is being manually simulated by SourceMod. - * This is the case if no players have joined - * the map yet. * @return Time based on the game tick count. */ -native Float:GetTickedTime(&bool:simulated); +native Float:GetTickedTime(); /** * Creates a timer associated with a new data pack, and returns the datapack.