Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/sgame/client/lifecycle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,10 @@ to be placed into the game. This will happen every level load.
============
*/
void ClientBegin(gentity_t *ent) {
// Null-ent guard; same engine teardown class as ClientThink/ClientDisconnect.
if (!ent)
return;

ent->client = game.clients + (ent - g_entities - 1);
ent->client->awaiting_respawn = false;
ent->client->respawn_timeout = 0_ms;
Expand Down Expand Up @@ -1499,6 +1503,10 @@ loadgames will.
============
*/
bool ClientConnect(gentity_t *ent, char *userinfo, const char *social_id, bool is_bot) {
// Null-ent guard; same engine teardown class as ClientThink/ClientDisconnect.
if (!ent)
return false;

ent->client->sess.team = deathmatch->integer ? TEAM_NONE : TEAM_FREE;

// they can connect
Expand Down Expand Up @@ -1607,7 +1615,10 @@ Will not be called between levels.
============
*/
void ClientDisconnect(gentity_t *ent) {
if (!ent->client)
// The engine calls this with a null ent when a kick lands on an empty or
// still-connecting slot (crash observed at ClientDisconnect+0x1E: access
// violation reading offset 0x78, rcx = 0).
if (!ent || !ent->client)
return;

G_ClearLagCompensationHistory(ent);
Expand Down Expand Up @@ -1984,6 +1995,11 @@ void ClientThink(gentity_t *ent, usercmd_t *ucmd) {
uint32_t i;
pmove_t pm;

// The engine can dispatch a think for a client slot whose entity is
// already torn down (kick/disconnect race), passing a null ent.
if (!ent || !ent->client)
return;

level.current_entity = ent;
client = ent->client;

Expand Down
3 changes: 3 additions & 0 deletions src/sgame/client/userinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,5 +231,8 @@ unsigned int P_GetLobbyUserNum(const gentity_t *player)

void ClientUserinfoChanged(gentity_t *ent, const char *userinfo)
{
// Null-ent guard; same engine teardown class as ClientThink/ClientDisconnect.
if (!ent)
return;
muffmode::player::ApplyUserinfoChanged(ent, userinfo);
}
4 changes: 2 additions & 2 deletions src/sgame/core/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2455,8 +2455,8 @@ void ClientCommand(gentity_t *ent) {
cmds_t *cc;
const char *cmd;

if (!ent->client)
return; // not fully in game yet
if (!ent || !ent->client)
return; // not fully in game yet (null ent: engine teardown, see ClientDisconnect)

#if 0
// check if client is 888, print what is being sent and prevent any further processing
Expand Down
Loading