Skip to content
This repository has been archived by the owner on Aug 22, 2024. It is now read-only.

Commit

Permalink
Fix client crash onTransmit
Browse files Browse the repository at this point in the history
  • Loading branch information
marqdevx committed Feb 29, 2024
1 parent e8afe90 commit 99bca95
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 565 deletions.
295 changes: 4 additions & 291 deletions src/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,47 +303,6 @@ void ClientPrint(CBasePlayerController *player, int hud_dest, const char *msg, .
ConMsg("%s\n", buf);
}

bool g_bEnableStopSound = false;

FAKE_BOOL_CVAR(cs2f_stopsound_enable, "Whether to enable stopsound", g_bEnableStopSound, false, false)

CON_COMMAND_CHAT(stopsound, "- toggle weapon sounds")
{
if (!g_bEnableStopSound)
return;

if (!player)
{
ClientPrint(player, HUD_PRINTCONSOLE, CHAT_PREFIX "You cannot use this command from the server console.");
return;
}

int iPlayer = player->GetPlayerSlot();
bool bStopSet = g_playerManager->IsPlayerUsingStopSound(iPlayer);
bool bSilencedSet = g_playerManager->IsPlayerUsingSilenceSound(iPlayer);

g_playerManager->SetPlayerStopSound(iPlayer, bSilencedSet);
g_playerManager->SetPlayerSilenceSound(iPlayer, !bSilencedSet && !bStopSet);

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "You have %s weapon sounds.", bSilencedSet ? "disabled" : !bSilencedSet && !bStopSet ? "silenced" : "enabled");
}

CON_COMMAND_CHAT(toggledecals, "- toggle world decals, if you're into having 10 fps in ZE")
{
if (!player)
{
ClientPrint(player, HUD_PRINTCONSOLE, CHAT_PREFIX "You cannot use this command from the server console.");
return;
}

int iPlayer = player->GetPlayerSlot();
bool bSet = !g_playerManager->IsPlayerUsingStopDecals(iPlayer);

g_playerManager->SetPlayerStopDecals(iPlayer, bSet);

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "You have %s world decals.", bSet ? "disabled" : "enabled");
}

bool g_bEnableHide = false;
static int g_iDefaultHideDistance = 250;
static int g_iMaxHideDistance = 2000;
Expand Down Expand Up @@ -630,259 +589,13 @@ CON_COMMAND_CHAT(last, "Teleport to the last thrown grenade")
return;
}

ZEPlayer *pPlayer = g_playerManager->GetPlayer(player->GetPlayerSlot());

player->GetPawn()->Teleport(&pPlayer->lastThrow_position, &pPlayer->lastThrow_rotation, nullptr);
}

//DEBUG
#if _DEBUG
CON_COMMAND_CHAT(myuid, "- test")
{
if (!player)
return;

int iPlayer = player->GetPlayerSlot();

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Your userid is %i, slot: %i, retrieved slot: %i", g_pEngineServer2->GetPlayerUserId(iPlayer).Get(), iPlayer, g_playerManager->GetSlotFromUserId(g_pEngineServer2->GetPlayerUserId(iPlayer).Get()));
}

CON_COMMAND_CHAT(myhandle, "test")
{
if (!player)
return;

int entry = player->GetHandle().GetEntryIndex();
int serial = player->GetHandle().GetSerialNumber();

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "entry index: %d serial number: %d", entry, serial);
}


CON_COMMAND_CHAT(message, "<id> <message> - message someone")
{
if (!player)
return;

// Note that the engine will treat this as a player slot number, not an entity index
int uid = atoi(args[1]);

CCSPlayerController* pTarget = CCSPlayerController::FromSlot(uid);

if (!pTarget)
return;

// skipping the id and space, it's dumb but w/e
const char *pMessage = args.ArgS() + V_strlen(args[1]) + 1;

ClientPrint(pTarget, HUD_PRINTTALK, CHAT_PREFIX "Private message from %s to %s: \5%s", player->GetPlayerName(), pTarget->GetPlayerName(), pMessage);
}

CON_COMMAND_CHAT(say, "<message> - say something using console")
{
ClientPrintAll(HUD_PRINTTALK, "%s", args.ArgS());
}

CON_COMMAND_CHAT(takemoney, "<amount> - take your money")
{
if (!player)
return;

int amount = atoi(args[1]);
int money = player->m_pInGameMoneyServices->m_iAccount;

player->m_pInGameMoneyServices->m_iAccount = money - amount;
}

CON_COMMAND_CHAT(sethealth, "<health> - set your health")
{
if (!player)
return;

int health = atoi(args[1]);

Z_CBaseEntity *pEnt = (Z_CBaseEntity *)player->GetPawn();

pEnt->m_iHealth = health;

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Your health is now %d", health);
}

CON_COMMAND_CHAT(test_target, "<name> - test string targetting")
{
if (!player)
return;

int iCommandPlayer = player->GetPlayerSlot();
int iNumClients = 0;
int pSlots[MAXPLAYERS];

g_playerManager->TargetPlayerString(iCommandPlayer, args[1], iNumClients, pSlots);

for (int i = 0; i < iNumClients; i++)
{
CCSPlayerController* pTarget = CCSPlayerController::FromSlot(pSlots[i]);

if (!pTarget)
continue;

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Targeting %s", pTarget->GetPlayerName());
Message("Targeting %s\n", pTarget->GetPlayerName());
}
}

CON_COMMAND_CHAT(getorigin, "get your origin")
{
if (!player)
return;

Vector vecAbsOrigin = player->GetPawn()->GetAbsOrigin();

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Your origin is %f %f %f", vecAbsOrigin.x, vecAbsOrigin.y, vecAbsOrigin.z);
}

CON_COMMAND_CHAT(setorigin, "<vector> - set your origin")
{
if (!player)
return;

CBasePlayerPawn *pPawn = player->GetPawn();
Vector vecNewOrigin;
V_StringToVector(args.ArgS(), vecNewOrigin);

pPawn->SetAbsOrigin(vecNewOrigin);

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Your origin is now %f %f %f", vecNewOrigin.x, vecNewOrigin.y, vecNewOrigin.z);
}



CON_COMMAND_CHAT(emitsound, "emit a sound from the entity under crosshair")
{
if (!player)
return;

Z_CBaseEntity *pEntity = UTIL_FindPickerEntity(player);
ZEPlayer *pPlayer = g_playerManager->GetPlayer(player->GetPlayerSlot());

if (!pEntity)
{
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "No entity found");
if(pPlayer->lastThrow_position.x == 0 && pPlayer->lastThrow_position.y == 0 && pPlayer->lastThrow_position.z== 0){
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "No saved thrown yet");
return;
}

pEntity->EmitSound(args[1]);

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Playing %s on %s", args[1], pEntity->GetClassname());
Message("Playing %s on %s", args[1], pEntity->GetClassname());
}

CON_COMMAND_CHAT(getstats, "- get your stats")
{
if (!player)
return;

CSMatchStats_t *stats = &player->m_pActionTrackingServices->m_matchStats();

ClientPrint(player, HUD_PRINTCENTER,
"Kills: %i\n"
"Deaths: %i\n"
"Assists: %i\n"
"Damage: %i"
, stats->m_iKills.Get(), stats->m_iDeaths.Get(), stats->m_iAssists.Get(), stats->m_iDamage.Get());

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Kills: %d", stats->m_iKills.Get());
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Deaths: %d", stats->m_iDeaths.Get());
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Assists: %d", stats->m_iAssists.Get());
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"Damage: %d", stats->m_iDamage.Get());
}

CON_COMMAND_CHAT(setkills, "- set your kills")
{
if (!player)
return;

player->m_pActionTrackingServices->m_matchStats().m_iKills = atoi(args[1]);

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX"You have set your kills to %d.", atoi(args[1]));
}

CON_COMMAND_CHAT(setcollisiongroup, "<group> - set a player's collision group")
{
int iNumClients = 0;
int pSlots[MAXPLAYERS];

g_playerManager->TargetPlayerString(player->GetPlayerSlot(), args[1], iNumClients, pSlots);

for (int i = 0; i < iNumClients; i++)
{
CCSPlayerController* pTarget = CCSPlayerController::FromSlot(pSlots[i]);

if (!pTarget)
continue;

uint8 group = atoi(args[2]);
uint8 oldgroup = pTarget->m_hPawn->m_pCollision->m_CollisionGroup;

pTarget->m_hPawn->m_pCollision->m_CollisionGroup = group;
pTarget->m_hPawn->m_pCollision->m_collisionAttribute().m_nCollisionGroup = group;
pTarget->GetPawn()->CollisionRulesChanged();

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Setting collision group on %s from %d to %d.", pTarget->GetPlayerName(), oldgroup, group);
}
}

CON_COMMAND_CHAT(setsolidtype, "<solidtype> - set a player's solid type")
{
int iNumClients = 0;
int pSlots[MAXPLAYERS];

g_playerManager->TargetPlayerString(player->GetPlayerSlot(), args[1], iNumClients, pSlots);

for (int i = 0; i < iNumClients; i++)
{
CCSPlayerController* pTarget = CCSPlayerController::FromSlot(pSlots[i]);

if (!pTarget)
continue;

uint8 type = atoi(args[2]);
uint8 oldtype = pTarget->m_hPawn->m_pCollision->m_nSolidType;

pTarget->m_hPawn->m_pCollision->m_nSolidType = (SolidType_t)type;
pTarget->GetPawn()->CollisionRulesChanged();

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Setting solid type on %s from %d to %d.", pTarget->GetPlayerName(), oldtype, type);
}
}

CON_COMMAND_CHAT(setinteraction, "<flags> - set a player's interaction flags")
{
int iNumClients = 0;
int pSlots[MAXPLAYERS];

g_playerManager->TargetPlayerString(player->GetPlayerSlot(), args[1], iNumClients, pSlots);

for (int i = 0; i < iNumClients; i++)
{
CCSPlayerController* pTarget = CCSPlayerController::FromSlot(pSlots[i]);

if (!pTarget)
continue;

uint64 oldInteractAs = pTarget->m_hPawn->m_pCollision->m_collisionAttribute().m_nInteractsAs;
uint64 newInteract = oldInteractAs | ((uint64)1 << 53);

pTarget->m_hPawn->m_pCollision->m_collisionAttribute().m_nInteractsAs = newInteract;
pTarget->m_hPawn->m_pCollision->m_collisionAttribute().m_nInteractsExclude = newInteract;
pTarget->GetPawn()->CollisionRulesChanged();

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "Setting interaction flags on %s from %llx to %llx.", pTarget->GetPlayerName(), oldInteractAs, newInteract);
}
}

void HttpCallback(HTTPRequestHandle request, json response)
{
ClientPrintAll(HUD_PRINTTALK, response.dump().c_str());
player->GetPawn()->Teleport(&pPlayer->lastThrow_position, &pPlayer->lastThrow_rotation, nullptr);
}

#endif // _DEBUG
56 changes: 3 additions & 53 deletions src/cs2fixes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ SH_DECL_HOOK6(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, CPlayerSl
SH_DECL_HOOK8_void(IGameEventSystem, PostEventAbstract, SH_NOATTRIB, 0, CSplitScreenSlot, bool, int, const uint64*,
INetworkSerializable*, const void*, unsigned long, NetChannelBufType_t)
SH_DECL_HOOK3_void(INetworkServerService, StartupServer, SH_NOATTRIB, 0, const GameSessionConfiguration_t&, ISource2WorldSession*, const char*);
SH_DECL_HOOK6_void(ISource2GameEntities, CheckTransmit, SH_NOATTRIB, 0, CCheckTransmitInfo **, int, CBitVec<16384> &, const Entity2Networkable_t **, const uint16 *, int);

SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, CPlayerSlot, const CCommand &);
SH_DECL_HOOK3_void(ICvar, DispatchConCommand, SH_NOATTRIB, 0, ConCommandHandle, const CCommandContext&, const CCommand&);

Expand Down Expand Up @@ -170,7 +170,7 @@ bool CS2Fixes::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool
SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientCommand, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientCommand, false);
SH_ADD_HOOK_MEMFUNC(IGameEventSystem, PostEventAbstract, g_gameEventSystem, this, &CS2Fixes::Hook_PostEvent, false);
SH_ADD_HOOK_MEMFUNC(INetworkServerService, StartupServer, g_pNetworkServerService, this, &CS2Fixes::Hook_StartupServer, true);
SH_ADD_HOOK_MEMFUNC(ISource2GameEntities, CheckTransmit, g_pSource2GameEntities, this, &CS2Fixes::Hook_CheckTransmit, true);

SH_ADD_HOOK_MEMFUNC(ICvar, DispatchConCommand, g_pCVar, this, &CS2Fixes::Hook_DispatchConCommand, false);

META_CONPRINTF( "All hooks started!\n" );
Expand Down Expand Up @@ -286,7 +286,7 @@ bool CS2Fixes::Unload(char *error, size_t maxlen)
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientCommand, g_pSource2GameClients, this, &CS2Fixes::Hook_ClientCommand, false);
SH_REMOVE_HOOK_MEMFUNC(IGameEventSystem, PostEventAbstract, g_gameEventSystem, this, &CS2Fixes::Hook_PostEvent, false);
SH_REMOVE_HOOK_MEMFUNC(INetworkServerService, StartupServer, g_pNetworkServerService, this, &CS2Fixes::Hook_StartupServer, true);
SH_REMOVE_HOOK_MEMFUNC(ISource2GameEntities, CheckTransmit, g_pSource2GameEntities, this, &CS2Fixes::Hook_CheckTransmit, true);

SH_REMOVE_HOOK_MEMFUNC(ICvar, DispatchConCommand, g_pCVar, this, &CS2Fixes::Hook_DispatchConCommand, false);

ConVar_Unregister();
Expand Down Expand Up @@ -578,56 +578,6 @@ void CS2Fixes::Hook_GameFrame( bool simulating, bool bFirstTick, bool bLastTick
VPROF_EXIT_SCOPE();
}

void CS2Fixes::Hook_CheckTransmit(CCheckTransmitInfo **ppInfoList, int infoCount, CBitVec<16384> &unionTransmitEdicts,
const Entity2Networkable_t **pNetworkables, const uint16 *pEntityIndicies, int nEntities)
{
if (!g_pEntitySystem)
return;

VPROF_ENTER_SCOPE(__FUNCTION__);

for (int i = 0; i < infoCount; i++)
{
auto &pInfo = ppInfoList[i];

// the offset happens to have a player index here,
// though this is probably part of the client class that contains the CCheckTransmitInfo
static int offset = g_GameConfig->GetOffset("CheckTransmitPlayerSlot");
int iPlayerSlot = (int)*((uint8 *)pInfo + offset);

CCSPlayerController* pSelfController = CCSPlayerController::FromSlot(iPlayerSlot);

if (!pSelfController || !pSelfController->IsConnected())
continue;

auto pSelfZEPlayer = g_playerManager->GetPlayer(iPlayerSlot);

if (!pSelfZEPlayer)
continue;

for (int j = 0; j < gpGlobals->maxClients; j++)
{
CCSPlayerController* pController = CCSPlayerController::FromSlot(j);

// Always transmit to themselves
if (!pController || !pController->IsConnected() || j == iPlayerSlot)
continue;

auto pPawn = pController->GetPawn();

if (!pPawn)
continue;

// Hide players marked as hidden or ANY dead player, it seems that a ragdoll of a previously hidden player can crash?
// TODO: Revert this if/when valve fixes the issue?
if (pSelfZEPlayer->ShouldBlockTransmit(j) || pPawn->m_lifeState != LIFE_ALIVE)
pInfo->m_pTransmitEntity->Clear(pPawn->entindex());
}
}

VPROF_EXIT_SCOPE();
}

// Potentially might not work
void CS2Fixes::OnLevelInit( char const *pMapName,
char const *pMapEntities,
Expand Down
Loading

0 comments on commit 99bca95

Please sign in to comment.