aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <for.oliver.kirkham@gmail.com>2023-02-14 14:16:35 +0000
committerunknown <for.oliver.kirkham@gmail.com>2023-02-14 14:16:35 +0000
commitb66871c8c826058e5da2d5ab3ecf1cdca1cdf9fc (patch)
treecedb12739f00611df7ea0186377de079f62624d9
parent263af88bb67349b5193dea6dac33664fc70bfede (diff)
parent95b41b6f8cc612953eafd7f8b6b40124e1590bc7 (diff)
downloadNorthstarLauncher-b66871c8c826058e5da2d5ab3ecf1cdca1cdf9fc.tar.gz
NorthstarLauncher-b66871c8c826058e5da2d5ab3ecf1cdca1cdf9fc.zip
Merge remote-tracking branch 'origin/main' into functionat-pr
-rw-r--r--NorthstarDLL/core/filesystem/rpakfilesystem.cpp6
-rw-r--r--NorthstarDLL/dedicated/dedicated.cpp14
-rw-r--r--NorthstarDLL/engine/r2engine.cpp4
-rw-r--r--NorthstarDLL/engine/r2engine.h60
-rw-r--r--NorthstarDLL/logging/crashhandler.cpp2
-rw-r--r--NorthstarDLL/logging/logging.cpp8
-rw-r--r--NorthstarDLL/logging/logging.h2
-rw-r--r--NorthstarDLL/mods/modmanager.cpp28
-rw-r--r--NorthstarDLL/mods/modmanager.h3
-rw-r--r--NorthstarDLL/server/auth/bansystem.cpp3
-rw-r--r--NorthstarDLL/server/auth/serverauthentication.cpp3
-rw-r--r--NorthstarDLL/server/buildainfile.cpp10
-rw-r--r--NorthstarDLL/shared/exploit_fixes/ns_limits.cpp44
-rw-r--r--NorthstarDLL/shared/keyvalues.cpp19
-rw-r--r--NorthstarDLL/shared/playlist.cpp3
-rw-r--r--NorthstarDLL/squirrel/squirrel.cpp28
-rw-r--r--NorthstarDLL/util/printmaps.cpp4
17 files changed, 189 insertions, 52 deletions
diff --git a/NorthstarDLL/core/filesystem/rpakfilesystem.cpp b/NorthstarDLL/core/filesystem/rpakfilesystem.cpp
index b46218e0..c3463781 100644
--- a/NorthstarDLL/core/filesystem/rpakfilesystem.cpp
+++ b/NorthstarDLL/core/filesystem/rpakfilesystem.cpp
@@ -267,6 +267,9 @@ void*, __fastcall, (const char* pPath, void* pCallback))
if (path.extension() == ".stbsp")
{
+ if (IsDedicatedServer())
+ return nullptr;
+
NS::log::rpak->info("LoadStreamBsp: {}", filename.string());
// resolve modded stbsp path so we can load mod stbsps
@@ -279,6 +282,9 @@ void*, __fastcall, (const char* pPath, void* pCallback))
}
else if (path.extension() == ".starpak")
{
+ if (IsDedicatedServer())
+ return nullptr;
+
// code for this is mostly stolen from above
// unfortunately I can't find a way to get the rpak that is causing this function call, so I have to
diff --git a/NorthstarDLL/dedicated/dedicated.cpp b/NorthstarDLL/dedicated/dedicated.cpp
index 33a3f034..e58900b7 100644
--- a/NorthstarDLL/dedicated/dedicated.cpp
+++ b/NorthstarDLL/dedicated/dedicated.cpp
@@ -48,18 +48,15 @@ void RunServer(CDedicatedExports* dedicated)
// initialise engine
g_pEngine->Frame();
- // add +map if not present
+ // add +map if no map loading command is present
// don't manually execute this from cbuf as users may have it in their startup args anyway, easier just to run from stuffcmds if present
- if (!Tier0::CommandLine()->CheckParm("+map"))
+ if (!Tier0::CommandLine()->CheckParm("+map") && !Tier0::CommandLine()->CheckParm("+launchplaylist"))
Tier0::CommandLine()->AppendParm("+map", g_pCVar->FindVar("match_defaultMap")->GetString());
// re-run commandline
Cbuf_AddText(Cbuf_GetCurrentPlayer(), "stuffcmds", cmd_source_t::kCommandSrcCode);
Cbuf_Execute();
- // get tickinterval
- ConVar* Cvar_base_tickinterval_mp = g_pCVar->FindVar("base_tickinterval_mp");
-
// main loop
double frameTitle = 0;
while (g_pEngine->m_nQuitting == EngineQuitState::QUIT_NOTQUITTING)
@@ -67,8 +64,8 @@ void RunServer(CDedicatedExports* dedicated)
double frameStart = Tier0::Plat_FloatTime();
g_pEngine->Frame();
- std::this_thread::sleep_for(std::chrono::duration<double, std::ratio<1>>(
- Cvar_base_tickinterval_mp->GetFloat() - fmin(Tier0::Plat_FloatTime() - frameStart, 0.25)));
+ std::this_thread::sleep_for(
+ std::chrono::duration<double, std::ratio<1>>(g_pGlobals->m_flTickInterval - fmin(Tier0::Plat_FloatTime() - frameStart, 0.25)));
}
}
@@ -278,7 +275,10 @@ void, __fastcall, (void* sqvm))
// atm, this will crash if not aborted, so this just closes more gracefully
static ConVar* Cvar_fatal_script_errors = g_pCVar->FindVar("fatal_script_errors");
if (Cvar_fatal_script_errors->GetBool())
+ {
+ NS::log::FlushLoggers();
abort();
+ }
}
ON_DLL_LOAD_DEDI("server.dll", DedicatedServerGameDLL, (CModule module))
diff --git a/NorthstarDLL/engine/r2engine.cpp b/NorthstarDLL/engine/r2engine.cpp
index 22884a73..eaa392c8 100644
--- a/NorthstarDLL/engine/r2engine.cpp
+++ b/NorthstarDLL/engine/r2engine.cpp
@@ -21,6 +21,8 @@ namespace R2
char* g_pModName =
nullptr; // we cant set this up here atm since we dont have an offset to it in engine, instead we store it in IsRespawnMod
+
+ CGlobalVars* g_pGlobals;
} // namespace R2
ON_DLL_LOAD("engine.dll", R2Engine, (CModule module))
@@ -37,4 +39,6 @@ ON_DLL_LOAD("engine.dll", R2Engine, (CModule module))
g_pClientArray = module.Offset(0x12A53F90).As<CBaseClient*>();
g_pServerState = module.Offset(0x12A53D48).As<server_state_t*>();
+
+ g_pGlobals = module.Offset(0x7C6F70).As<CGlobalVars*>();
}
diff --git a/NorthstarDLL/engine/r2engine.h b/NorthstarDLL/engine/r2engine.h
index bc242201..ff8876b8 100644
--- a/NorthstarDLL/engine/r2engine.h
+++ b/NorthstarDLL/engine/r2engine.h
@@ -201,4 +201,64 @@ namespace R2
extern server_state_t* g_pServerState;
extern char* g_pModName;
+
+ // clang-format off
+ OFFSET_STRUCT(CGlobalVars)
+ {
+ FIELD(0x0,
+ // Absolute time (per frame still - Use Plat_FloatTime() for a high precision real time
+ // perf clock, but not that it doesn't obey host_timescale/host_framerate)
+ double m_flRealTime);
+
+ FIELDS(0x8,
+ // Absolute frame counter - continues to increase even if game is paused
+ int m_nFrameCount;
+
+ // Non-paused frametime
+ float m_flAbsoluteFrameTime;
+
+ // Current time
+ //
+ // On the client, this (along with tickcount) takes a different meaning based on what
+ // piece of code you're in:
+ //
+ // - While receiving network packets (like in PreDataUpdate/PostDataUpdate and proxies),
+ // this is set to the SERVER TICKCOUNT for that packet. There is no interval between
+ // the server ticks.
+ // [server_current_Tick * tick_interval]
+ //
+ // - While rendering, this is the exact client clock
+ // [client_current_tick * tick_interval + interpolation_amount]
+ //
+ // - During prediction, this is based on the client's current tick:
+ // [client_current_tick * tick_interval]
+ float m_flCurTime;
+ )
+
+ FIELDS(0x30,
+ // Time spent on last server or client frame (has nothing to do with think intervals)
+ float m_flFrameTime;
+
+ // current maxplayers setting
+ int m_nMaxClients;
+ )
+
+ FIELDS(0x3C,
+ // Simulation ticks - does not increase when game is paused
+ uint32_t m_nTickCount; // this is weird and doesn't seem to increase once per frame?
+
+ // Simulation tick interval
+ float m_flTickInterval;
+ )
+
+ FIELDS(0x60,
+ const char* m_pMapName;
+ int m_nMapVersion;
+ )
+
+ //FIELD(0x98, double m_flRealTime); // again?
+ };
+ // clang-format on
+
+ extern CGlobalVars* g_pGlobals;
} // namespace R2
diff --git a/NorthstarDLL/logging/crashhandler.cpp b/NorthstarDLL/logging/crashhandler.cpp
index d4a54169..1e9bf4b3 100644
--- a/NorthstarDLL/logging/crashhandler.cpp
+++ b/NorthstarDLL/logging/crashhandler.cpp
@@ -72,6 +72,8 @@ void PrintExceptionLog(ExceptionLog& exc)
"Northstar has crashed! Crash info can be found in R2Northstar/logs",
"Northstar has crashed!",
MB_ICONERROR | MB_OK | MB_SYSTEMMODAL);
+
+ NS::log::FlushLoggers();
}
std::string GetExceptionName(ExceptionLog& exc)
diff --git a/NorthstarDLL/logging/logging.cpp b/NorthstarDLL/logging/logging.cpp
index 6bb57170..8b906911 100644
--- a/NorthstarDLL/logging/logging.cpp
+++ b/NorthstarDLL/logging/logging.cpp
@@ -203,3 +203,11 @@ void InitialiseLogging()
loggers.push_back(NS::log::rpak);
loggers.push_back(NS::log::echo);
}
+
+void NS::log::FlushLoggers()
+{
+ for (auto& logger : loggers)
+ logger->flush();
+
+ spdlog::default_logger()->flush();
+}
diff --git a/NorthstarDLL/logging/logging.h b/NorthstarDLL/logging/logging.h
index b710915e..2cccdde6 100644
--- a/NorthstarDLL/logging/logging.h
+++ b/NorthstarDLL/logging/logging.h
@@ -100,6 +100,8 @@ namespace NS::log
extern std::shared_ptr<ColoredLogger> echo;
extern std::shared_ptr<ColoredLogger> NORTHSTAR;
+
+ void FlushLoggers();
}; // namespace NS::log
void RegisterCustomSink(std::shared_ptr<CustomSink> sink);
diff --git a/NorthstarDLL/mods/modmanager.cpp b/NorthstarDLL/mods/modmanager.cpp
index 6310b7ec..e37df6e5 100644
--- a/NorthstarDLL/mods/modmanager.cpp
+++ b/NorthstarDLL/mods/modmanager.cpp
@@ -11,7 +11,7 @@
#include "rapidjson/error/en.h"
#include "rapidjson/document.h"
#include "rapidjson/ostreamwrapper.h"
-#include "rapidjson/writer.h"
+#include "rapidjson/prettywriter.h"
#include <filesystem>
#include <fstream>
#include <string>
@@ -198,6 +198,9 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
if (scriptObj["ServerCallback"].HasMember("After") && scriptObj["ServerCallback"]["After"].IsString())
callback.AfterCallback = scriptObj["ServerCallback"]["After"].GetString();
+ if (scriptObj["ServerCallback"].HasMember("Destroy") && scriptObj["ServerCallback"]["Destroy"].IsString())
+ callback.DestroyCallback = scriptObj["ServerCallback"]["Destroy"].GetString();
+
script.Callbacks.push_back(callback);
}
@@ -212,6 +215,9 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
if (scriptObj["ClientCallback"].HasMember("After") && scriptObj["ClientCallback"]["After"].IsString())
callback.AfterCallback = scriptObj["ClientCallback"]["After"].GetString();
+ if (scriptObj["ClientCallback"].HasMember("Destroy") && scriptObj["ClientCallback"]["Destroy"].IsString())
+ callback.DestroyCallback = scriptObj["ClientCallback"]["Destroy"].GetString();
+
script.Callbacks.push_back(callback);
}
@@ -226,6 +232,9 @@ Mod::Mod(fs::path modDir, char* jsonBuf)
if (scriptObj["UICallback"].HasMember("After") && scriptObj["UICallback"]["After"].IsString())
callback.AfterCallback = scriptObj["UICallback"]["After"].GetString();
+ if (scriptObj["UICallback"].HasMember("Destroy") && scriptObj["UICallback"]["Destroy"].IsString())
+ callback.DestroyCallback = scriptObj["UICallback"]["Destroy"].GetString();
+
script.Callbacks.push_back(callback);
}
@@ -354,6 +363,7 @@ void ModManager::LoadMods()
// ensure dirs exist
fs::remove_all(GetCompiledAssetsPath());
fs::create_directories(GetModFolderPath());
+ fs::create_directories(GetRemoteModFolderPath());
m_DependencyConstants.clear();
@@ -374,9 +384,13 @@ void ModManager::LoadMods()
}
// get mod directories
- for (fs::directory_entry dir : fs::directory_iterator(GetModFolderPath()))
- if (fs::exists(dir.path() / "mod.json"))
- modDirs.push_back(dir.path());
+ std::filesystem::directory_iterator classicModsDir = fs::directory_iterator(GetModFolderPath());
+ std::filesystem::directory_iterator remoteModsDir = fs::directory_iterator(GetRemoteModFolderPath());
+
+ for (std::filesystem::directory_iterator modIterator : {classicModsDir, remoteModsDir})
+ for (fs::directory_entry dir : modIterator)
+ if (fs::exists(dir.path() / "mod.json"))
+ modDirs.push_back(dir.path());
for (fs::path modDir : modDirs)
{
@@ -750,7 +764,7 @@ void ModManager::UnloadMods()
std::ofstream writeStream(GetNorthstarPrefix() + "/enabledmods.json");
rapidjson::OStreamWrapper writeStreamWrapper(writeStream);
- rapidjson::Writer<rapidjson::OStreamWrapper> writer(writeStreamWrapper);
+ rapidjson::PrettyWriter<rapidjson::OStreamWrapper> writer(writeStreamWrapper);
m_EnabledModsCfg.Accept(writer);
// do we need to dealloc individual entries in m_loadedMods? idk, rework
@@ -805,6 +819,10 @@ fs::path GetModFolderPath()
{
return fs::path(GetNorthstarPrefix() + MOD_FOLDER_SUFFIX);
}
+fs::path GetRemoteModFolderPath()
+{
+ return fs::path(GetNorthstarPrefix() + REMOTE_MOD_FOLDER_SUFFIX);
+}
fs::path GetCompiledAssetsPath()
{
return fs::path(GetNorthstarPrefix() + COMPILED_ASSETS_SUFFIX);
diff --git a/NorthstarDLL/mods/modmanager.h b/NorthstarDLL/mods/modmanager.h
index ded6ff06..369eb07b 100644
--- a/NorthstarDLL/mods/modmanager.h
+++ b/NorthstarDLL/mods/modmanager.h
@@ -41,6 +41,8 @@ struct ModScriptCallback
std::string BeforeCallback;
// called after the codecallback has finished executing
std::string AfterCallback;
+ // called right before the vm is destroyed.
+ std::string DestroyCallback;
};
struct ModScript
@@ -161,6 +163,7 @@ class ModManager
};
fs::path GetModFolderPath();
+fs::path GetRemoteModFolderPath();
fs::path GetCompiledAssetsPath();
extern ModManager* g_pModManager;
diff --git a/NorthstarDLL/server/auth/bansystem.cpp b/NorthstarDLL/server/auth/bansystem.cpp
index 56719ed9..47df495d 100644
--- a/NorthstarDLL/server/auth/bansystem.cpp
+++ b/NorthstarDLL/server/auth/bansystem.cpp
@@ -2,7 +2,6 @@
#include "pch.h"
#include "bansystem.h"
#include "serverauthentication.h"
-#include "shared/maxplayers.h"
#include "core/convar/concommand.h"
#include "server/r2server.h"
#include "engine/r2engine.h"
@@ -184,7 +183,7 @@ void ConCommand_ban(const CCommand& args)
if (args.ArgC() < 2)
return;
- for (int i = 0; i < R2::GetMaxPlayers(); i++)
+ for (int i = 0; i < R2::g_pGlobals->m_nMaxClients; i++)
{
R2::CBaseClient* player = &R2::g_pClientArray[i];
diff --git a/NorthstarDLL/server/auth/serverauthentication.cpp b/NorthstarDLL/server/auth/serverauthentication.cpp
index f8180469..2f06f60f 100644
--- a/NorthstarDLL/server/auth/serverauthentication.cpp
+++ b/NorthstarDLL/server/auth/serverauthentication.cpp
@@ -6,7 +6,6 @@
#include "masterserver/masterserver.h"
#include "server/serverpresence.h"
#include "engine/hoststate.h"
-#include "shared/maxplayers.h"
#include "bansystem.h"
#include "core/convar/concommand.h"
#include "dedicated/dedicated.h"
@@ -154,7 +153,7 @@ bool ServerAuthenticationManager::IsDuplicateAccount(R2::CBaseClient* pPlayer, c
return false;
bool bHasUidPlayer = false;
- for (int i = 0; i < R2::GetMaxPlayers(); i++)
+ for (int i = 0; i < R2::g_pGlobals->m_nMaxClients; i++)
if (&R2::g_pClientArray[i] != pPlayer && !strcmp(pPlayerUid, R2::g_pClientArray[i].m_UID))
return true;
diff --git a/NorthstarDLL/server/buildainfile.cpp b/NorthstarDLL/server/buildainfile.cpp
index f6dc4717..d1150a6b 100644
--- a/NorthstarDLL/server/buildainfile.cpp
+++ b/NorthstarDLL/server/buildainfile.cpp
@@ -174,14 +174,12 @@ struct CAI_Network
};
#pragma pack(pop)
-char** pUnkServerMapversionGlobal;
-
ConVar* Cvar_ns_ai_dumpAINfileFromLoad;
void DumpAINInfo(CAI_Network* aiNetwork)
{
fs::path writePath(fmt::format("{}/maps/graphs", R2::g_pModName));
- writePath /= R2::g_pHostState->m_levelName;
+ writePath /= R2::g_pGlobals->m_pMapName;
writePath += ".ain";
// dump from memory
@@ -196,9 +194,8 @@ void DumpAINInfo(CAI_Network* aiNetwork)
spdlog::info("writing ainet version: {}", AINET_VERSION_NUMBER);
writeStream.write((char*)&AINET_VERSION_NUMBER, sizeof(int));
- // could probably be cleaner but whatever
- int mapVersion = *(int*)(*pUnkServerMapversionGlobal + 104);
- spdlog::info("writing map version: {}", mapVersion); // temp
+ int mapVersion = R2::g_pGlobals->m_nMapVersion;
+ spdlog::info("writing map version: {}", mapVersion);
writeStream.write((char*)&mapVersion, sizeof(int));
spdlog::info("writing placeholder crc: {}", PLACEHOLDER_CRC);
writeStream.write((char*)&PLACEHOLDER_CRC, sizeof(int));
@@ -396,5 +393,4 @@ ON_DLL_LOAD("server.dll", BuildAINFile, (CModule module))
pppUnkNodeStruct0s = module.Offset(0x1063BE0).As<UnkNodeStruct0***>();
pUnkLinkStruct1Count = module.Offset(0x1063AA8).As<int*>();
pppUnkStruct1s = module.Offset(0x1063A90).As<UnkLinkStruct1***>();
- pUnkServerMapversionGlobal = module.Offset(0xBFBE08).As<char**>();
}
diff --git a/NorthstarDLL/shared/exploit_fixes/ns_limits.cpp b/NorthstarDLL/shared/exploit_fixes/ns_limits.cpp
index 49f80bab..135cfb83 100644
--- a/NorthstarDLL/shared/exploit_fixes/ns_limits.cpp
+++ b/NorthstarDLL/shared/exploit_fixes/ns_limits.cpp
@@ -4,7 +4,6 @@
#include "client/r2client.h"
#include "engine/r2engine.h"
#include "server/r2server.h"
-#include "shared/maxplayers.h"
#include "core/tier0.h"
#include "core/math/vector.h"
#include "server/auth/serverauthentication.h"
@@ -13,22 +12,26 @@ AUTOHOOK_INIT()
ServerLimitsManager* g_pServerLimits;
+float (*CEngineServer__GetTimescale)();
+
// todo: make this work on higher timescales, also possibly disable when sv_cheats is set
void ServerLimitsManager::RunFrame(double flCurrentTime, float flFrameTime)
{
if (Cvar_sv_antispeedhack_enable->GetBool())
{
// for each player, set their usercmd processing budget for the frame to the last frametime for the server
- for (int i = 0; i < R2::GetMaxPlayers(); i++)
+ for (int i = 0; i < R2::g_pGlobals->m_nMaxClients; i++)
{
R2::CBaseClient* player = &R2::g_pClientArray[i];
if (m_PlayerLimitData.find(player) != m_PlayerLimitData.end())
{
PlayerLimitData* pLimitData = &g_pServerLimits->m_PlayerLimitData[player];
- if (pLimitData->flFrameUserCmdBudget < 0.016666667 * Cvar_sv_antispeedhack_maxtickbudget->GetFloat())
- pLimitData->flFrameUserCmdBudget +=
- fmax(flFrameTime, 0.016666667) * g_pServerLimits->Cvar_sv_antispeedhack_budgetincreasemultiplier->GetFloat();
+ if (pLimitData->flFrameUserCmdBudget < R2::g_pGlobals->m_flTickInterval * Cvar_sv_antispeedhack_maxtickbudget->GetFloat())
+ {
+ pLimitData->flFrameUserCmdBudget += g_pServerLimits->Cvar_sv_antispeedhack_budgetincreasemultiplier->GetFloat() *
+ fmax(flFrameTime, R2::g_pGlobals->m_flFrameTime * CEngineServer__GetTimescale());
+ }
}
}
}
@@ -37,7 +40,8 @@ void ServerLimitsManager::RunFrame(double flCurrentTime, float flFrameTime)
void ServerLimitsManager::AddPlayer(R2::CBaseClient* player)
{
PlayerLimitData limitData;
- limitData.flFrameUserCmdBudget = 0.016666667 * Cvar_sv_antispeedhack_maxtickbudget->GetFloat();
+ limitData.flFrameUserCmdBudget =
+ R2::g_pGlobals->m_flTickInterval * CEngineServer__GetTimescale() * Cvar_sv_antispeedhack_maxtickbudget->GetFloat();
m_PlayerLimitData.insert(std::make_pair(player, limitData));
}
@@ -53,10 +57,10 @@ bool ServerLimitsManager::CheckStringCommandLimits(R2::CBaseClient* player)
if (CVar_sv_quota_stringcmdspersecond->GetInt() != -1)
{
// note: this isn't super perfect, legit clients can trigger it in lobby if they try, mostly good enough tho imo
- if (Tier0::Plat_FloatTime() - m_PlayerLimitData[player].lastClientCommandQuotaStart >= 1.0)
+ if (R2::g_pGlobals->m_flCurTime - m_PlayerLimitData[player].lastClientCommandQuotaStart >= 1.0)
{
// reset quota
- m_PlayerLimitData[player].lastClientCommandQuotaStart = Tier0::Plat_FloatTime();
+ m_PlayerLimitData[player].lastClientCommandQuotaStart = R2::g_pGlobals->m_flCurTime;
m_PlayerLimitData[player].numClientCommandsInQuota = 0;
}
@@ -73,9 +77,9 @@ bool ServerLimitsManager::CheckStringCommandLimits(R2::CBaseClient* player)
bool ServerLimitsManager::CheckChatLimits(R2::CBaseClient* player)
{
- if (Tier0::Plat_FloatTime() - m_PlayerLimitData[player].lastSayTextLimitStart >= 1.0)
+ if (R2::g_pGlobals->m_flCurTime - m_PlayerLimitData[player].lastSayTextLimitStart >= 1.0)
{
- m_PlayerLimitData[player].lastSayTextLimitStart = Tier0::Plat_FloatTime();
+ m_PlayerLimitData[player].lastSayTextLimitStart = R2::g_pGlobals->m_flCurTime;
m_PlayerLimitData[player].sayTextLimitCount = 0;
}
@@ -97,7 +101,7 @@ char, __fastcall, (void* self, void* buf))
NETCHANLIMIT_KICK
};
- double startTime = Tier0::Plat_FloatTime();
+ double startTime = R2::g_pGlobals->m_flCurTime;
char ret = CNetChan__ProcessMessages(self, buf);
// check processing limits, unless we're in a level transition
@@ -118,7 +122,7 @@ char, __fastcall, (void* self, void* buf))
g_pServerLimits->m_PlayerLimitData[sender].lastNetChanProcessingLimitStart = startTime;
g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime = 0.0;
}
- g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime += (Tier0::Plat_FloatTime() * 1000) - (startTime * 1000);
+ g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime += (R2::g_pGlobals->m_flCurTime * 1000) - (startTime * 1000);
if (g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime >=
g_pServerLimits->Cvar_net_chan_limit_msec_per_sec->GetInt())
@@ -169,12 +173,12 @@ bool, , (void* a1, R2::netpacket_t* packet))
memcpy(sendData->ip, packet->adr.ip, 16);
}
- if (Tier0::Plat_FloatTime() < sendData->timeoutEnd)
+ if (R2::g_pGlobals->m_flCurTime < sendData->timeoutEnd)
return false;
- if (Tier0::Plat_FloatTime() - sendData->lastQuotaStart >= 1.0)
+ if (R2::g_pGlobals->m_flCurTime - sendData->lastQuotaStart >= 1.0)
{
- sendData->lastQuotaStart = Tier0::Plat_FloatTime();
+ sendData->lastQuotaStart = R2::g_pGlobals->m_flCurTime;
sendData->packetCount = 0;
}
@@ -188,7 +192,7 @@ bool, , (void* a1, R2::netpacket_t* packet))
packet->data[4]);
// timeout for a minute
- sendData->timeoutEnd = Tier0::Plat_FloatTime() + 60.0;
+ sendData->timeoutEnd = R2::g_pGlobals->m_flCurTime + 60.0;
return false;
}
}
@@ -250,8 +254,6 @@ void, __fastcall, (void* self, R2::CBasePlayer* player, SV_CUserCmd* pUserCmd, u
spdlog::warn("player {} went over usercmd budget ({})", pClient->m_Name, pLimitData->flFrameUserCmdBudget);
return;
}
- // else
- // spdlog::info("{}: {}", pClient->m_Name, pLimitData->flFrameUserCmdBudget);
}
}
@@ -284,12 +286,14 @@ ON_DLL_LOAD_RELIESON("engine.dll", ServerLimits, ConVar, (CModule module))
"sv_antispeedhack_maxtickbudget",
"64",
FCVAR_GAMEDLL,
- "Maximum number of client-issued usercmd ticks that can be replayed in packet loss conditions, 0 to allow no restrictions");
+ "Maximum number of client-issued usercmd ticks that can be replayed in packet loss conditions");
g_pServerLimits->Cvar_sv_antispeedhack_budgetincreasemultiplier = new ConVar(
"sv_antispeedhack_budgetincreasemultiplier",
- "1.2",
+ "1",
FCVAR_GAMEDLL,
"Increase usercmd processing budget by tickinterval * value per tick");
+
+ CEngineServer__GetTimescale = module.Offset(0x240840).As<float (*)()>();
}
ON_DLL_LOAD("server.dll", ServerLimitsServer, (CModule module))
diff --git a/NorthstarDLL/shared/keyvalues.cpp b/NorthstarDLL/shared/keyvalues.cpp
index fe7d6299..25155dde 100644
--- a/NorthstarDLL/shared/keyvalues.cpp
+++ b/NorthstarDLL/shared/keyvalues.cpp
@@ -211,8 +211,15 @@ KeyValues* KeyValues::FindKey(const char* pszKeyName, bool bCreate)
return this;
const char* pSubStr = strchr(pszKeyName, '/');
+ const char* pSearchStr = pszKeyName;
+ if (pSubStr && !*(pSubStr + 1))
+ {
+ // if key name is just '/', then use it as a key directly
+ pSearchStr = pSubStr;
+ pSubStr = nullptr;
+ }
- HKeySymbol iSearchStr = KeyValuesSystem()->m_pVtable->GetSymbolForString(KeyValuesSystem(), pszKeyName, bCreate);
+ HKeySymbol iSearchStr = KeyValuesSystem()->m_pVtable->GetSymbolForString(KeyValuesSystem(), pSearchStr, bCreate);
if (iSearchStr == INVALID_KEY_SYMBOL)
{
// not found, couldn't possibly be in key value list
@@ -222,7 +229,7 @@ KeyValues* KeyValues::FindKey(const char* pszKeyName, bool bCreate)
KeyValues* pLastKVs = nullptr;
KeyValues* pCurrentKVs;
// find the searchStr in the current peer list
- for (pCurrentKVs = m_pSub; pCurrentKVs != NULL; pCurrentKVs = pCurrentKVs->m_pPeer)
+ for (pCurrentKVs = m_pSub; pCurrentKVs != nullptr; pCurrentKVs = pCurrentKVs->m_pPeer)
{
pLastKVs = pCurrentKVs; // record the last item looked at (for if we need to append to the end of the list)
@@ -232,7 +239,7 @@ KeyValues* KeyValues::FindKey(const char* pszKeyName, bool bCreate)
}
if (!pCurrentKVs && m_pChain)
- pCurrentKVs = m_pChain->FindKey(pszKeyName, false);
+ pCurrentKVs = m_pChain->FindKey(pSearchStr, false);
// make sure a key was found
if (!pCurrentKVs)
@@ -240,7 +247,7 @@ KeyValues* KeyValues::FindKey(const char* pszKeyName, bool bCreate)
if (bCreate)
{
// we need to create a new key
- pCurrentKVs = new KeyValues(pszKeyName);
+ pCurrentKVs = new KeyValues(pSearchStr);
// Assert(dat != NULL);
// insert new key at end of list
@@ -249,7 +256,7 @@ KeyValues* KeyValues::FindKey(const char* pszKeyName, bool bCreate)
else
m_pSub = pCurrentKVs;
- pCurrentKVs->m_pPeer = NULL;
+ pCurrentKVs->m_pPeer = nullptr;
// a key graduates to be a submsg as soon as it's m_pSub is set
// this should be the only place m_pSub is set
@@ -257,7 +264,7 @@ KeyValues* KeyValues::FindKey(const char* pszKeyName, bool bCreate)
}
else
{
- return NULL;
+ return nullptr;
}
}
diff --git a/NorthstarDLL/shared/playlist.cpp b/NorthstarDLL/shared/playlist.cpp
index 0f20a957..dbd18e14 100644
--- a/NorthstarDLL/shared/playlist.cpp
+++ b/NorthstarDLL/shared/playlist.cpp
@@ -4,6 +4,7 @@
#include "core/convar/convar.h"
#include "squirrel/squirrel.h"
#include "engine/hoststate.h"
+#include "engine/r2engine.h"
#include "server/serverpresence.h"
AUTOHOOK_INIT()
@@ -26,7 +27,7 @@ char, __fastcall, (void* a1, void* a2))
{
// the private_match playlist on mp_lobby is the only situation where there should be any legitimate sending of this netmessage
if (!Cvar_ns_use_clc_SetPlaylistVarOverride->GetBool() || strcmp(R2::GetCurrentPlaylistName(), "private_match") ||
- strcmp(R2::g_pHostState->m_levelName, "mp_lobby"))
+ strcmp(R2::g_pGlobals->m_pMapName, "mp_lobby"))
return 1;
return clc_SetPlaylistVarOverride__Process(a1, a2);
diff --git a/NorthstarDLL/squirrel/squirrel.cpp b/NorthstarDLL/squirrel/squirrel.cpp
index 4771bf3f..25fb90d5 100644
--- a/NorthstarDLL/squirrel/squirrel.cpp
+++ b/NorthstarDLL/squirrel/squirrel.cpp
@@ -1,5 +1,6 @@
#include "pch.h"
#include "squirrel.h"
+#include "logging/logging.h"
#include "core/convar/concommand.h"
#include "mods/modmanager.h"
#include "dedicated/dedicated.h"
@@ -212,7 +213,34 @@ template <ScriptContext context> void SquirrelManager<context>::VMCreated(CSquir
template <ScriptContext context> void SquirrelManager<context>::VMDestroyed()
{
+ // Call all registered mod Destroy callbacks.
+ if (g_pModManager)
+ {
+ NS::log::squirrel_logger<context>()->info("Calling Destroy callbacks for all loaded mods.");
+
+ for (const Mod& loadedMod : g_pModManager->m_LoadedMods)
+ {
+ for (const ModScript& script : loadedMod.Scripts)
+ {
+ for (const ModScriptCallback& callback : script.Callbacks)
+ {
+ if (callback.Context != context || callback.DestroyCallback.length() == 0)
+ {
+ continue;
+ }
+
+ Call(callback.DestroyCallback.c_str());
+ NS::log::squirrel_logger<context>()->info("Executed Destroy callback {}.", callback.DestroyCallback);
+ }
+ }
+ }
+ }
+
+ // Discard the previous vm and delete the message buffer.
m_pSQVM = nullptr;
+
+ delete g_pSquirrel<context>->messageBuffer;
+ g_pSquirrel<context>->messageBuffer = nullptr;
}
template <ScriptContext context> void SquirrelManager<context>::ExecuteCode(const char* pCode)
diff --git a/NorthstarDLL/util/printmaps.cpp b/NorthstarDLL/util/printmaps.cpp
index e0192d69..0a5f73f2 100644
--- a/NorthstarDLL/util/printmaps.cpp
+++ b/NorthstarDLL/util/printmaps.cpp
@@ -115,10 +115,10 @@ int, __fastcall, (const char const* cmdname, const char const* partial, char com
// don't update our map list often from this func, only refresh every 10 seconds so we avoid constantly reading fs
static double flLastAutocompleteRefresh = -999;
- if (flLastAutocompleteRefresh + 10.0 < Tier0::Plat_FloatTime())
+ if (flLastAutocompleteRefresh + 10.0 < R2::g_pGlobals->m_flRealTime)
{
RefreshMapList();
- flLastAutocompleteRefresh = Tier0::Plat_FloatTime();
+ flLastAutocompleteRefresh = R2::g_pGlobals->m_flRealTime;
}
// use a custom autocomplete func for all map loading commands