Plugins: Added a callback for when a client is done connecting to a server

This commit is contained in:
Marco Cawthorne 2021-02-14 21:05:10 +01:00
parent 23edd47438
commit ce2185ff02
4 changed files with 119 additions and 33 deletions

View file

@ -83,6 +83,8 @@ int g_dmg_iHitBody;
int g_dmg_iFlags; int g_dmg_iFlags;
int g_dmg_iWeapon; int g_dmg_iWeapon;
var int g_ents_initialized = FALSE;
/* main is a qcc leftover */ /* main is a qcc leftover */
void main(void) void main(void)
{ {

View file

@ -21,14 +21,19 @@ StartFrame
Called once every single frame. Called once every single frame.
================= =================
*/ */
void StartFrame(void) void
StartFrame(void)
{ {
/* For entity parenting to work, we need to go through and run on every
* this method on every CBaseEntity class */
for (entity a = world; (a = findfloat(a, ::identity, 1));) { for (entity a = world; (a = findfloat(a, ::identity, 1));) {
CBaseEntity ent = (CBaseEntity)a; CBaseEntity ent = (CBaseEntity)a;
ent.ParentUpdate(); ent.ParentUpdate();
} }
g_grMode.FrameStart(); if (g_ents_initialized)
g_grMode.FrameStart();
Vote_Frame(); Vote_Frame();
} }
@ -43,7 +48,8 @@ loading or receiving packets.
The 'self' global is the connecting client in question. The 'self' global is the connecting client in question.
================= =================
*/ */
void ClientConnect(float csqc_active) void
ClientConnect(float csqc_active)
{ {
int playercount = 0; int playercount = 0;
@ -58,11 +64,13 @@ void ClientConnect(float csqc_active)
spawnfunc_player(); spawnfunc_player();
} }
g_grMode.PlayerConnect((base_player)self); if (g_ents_initialized)
g_grMode.PlayerConnect((base_player)self);
for (entity a = world; (a = find(a, ::classname, "player"));) for (entity a = world; (a = find(a, ::classname, "player"));)
playercount++; playercount++;
/* we're the only one. respawn all entities */ /* we're the only one. respawn all entities */
if (playercount == 1) { if (playercount == 1) {
for (entity a = world; (a = findfloat(a, ::identity, 1));) { for (entity a = world; (a = findfloat(a, ::identity, 1));) {
CBaseEntity caw = (CBaseEntity)a; CBaseEntity caw = (CBaseEntity)a;
@ -81,9 +89,11 @@ client slot referred to by the 'self' global will be cleared.
This means the fields will still be accessible inside of this function. This means the fields will still be accessible inside of this function.
================= =================
*/ */
void ClientDisconnect(void) void
ClientDisconnect(void)
{ {
g_grMode.PlayerDisconnect((base_player)self); if (g_ents_initialized)
g_grMode.PlayerDisconnect((base_player)self);
} }
/* /*
@ -94,9 +104,11 @@ Called by the 'kill' command.
The 'self' global is the client issueing the command. The 'self' global is the client issueing the command.
================= =================
*/ */
void ClientKill(void) void
ClientKill(void)
{ {
g_grMode.PlayerKill((base_player)self); if (g_ents_initialized)
g_grMode.PlayerKill((base_player)self);
} }
/* /*
@ -107,7 +119,8 @@ Run every frame on every spectator.
The 'self' global refers to one of any given amount of spectators. The 'self' global refers to one of any given amount of spectators.
================= =================
*/ */
void SpectatorThink(void) void
SpectatorThink(void)
{ {
Game_SpectatorThink(); Game_SpectatorThink();
} }
@ -120,7 +133,8 @@ Called when a spectator joins the server.
The 'self' global is the connecting spectator in question. The 'self' global is the connecting spectator in question.
================= =================
*/ */
void SpectatorConnect(void) void
SpectatorConnect(void)
{ {
Game_SpectatorConnect(); Game_SpectatorConnect();
} }
@ -134,7 +148,8 @@ The 'self' global is the leaving spectator in question.
Attributes cleared when this function is done executing. Attributes cleared when this function is done executing.
================= =================
*/ */
void SpectatorDisconnect(void) void
SpectatorDisconnect(void)
{ {
Game_SpectatorDisconnect(); Game_SpectatorDisconnect();
} }
@ -150,9 +165,13 @@ The 'parmX' globals are also populated with any data carried over from
past levels for the player in question. past levels for the player in question.
================= =================
*/ */
void PutClientInServer(void) void
PutClientInServer(void)
{ {
g_grMode.PlayerSpawn((base_player)self); if (g_ents_initialized)
g_grMode.PlayerSpawn((base_player)self);
Plugin_PlayerEntered((base_player)self);
/* activate all game_playerspawn entities */ /* activate all game_playerspawn entities */
for (entity a = world; (a = find(a, ::targetname, "game_playerspawn"));) { for (entity a = world; (a = find(a, ::targetname, "game_playerspawn"));) {
@ -172,7 +191,8 @@ The 'self' global refers to a single client, as this function is called
times the amount of players in a given game. times the amount of players in a given game.
================= =================
*/ */
void PlayerPreThink(void) void
PlayerPreThink(void)
{ {
if (self.classname != "player") { if (self.classname != "player") {
return; return;
@ -184,7 +204,8 @@ void PlayerPreThink(void)
} }
#endif #endif
g_grMode.PlayerPreFrame((base_player)self); if (g_ents_initialized)
g_grMode.PlayerPreFrame((base_player)self);
} }
/* /*
@ -196,7 +217,8 @@ The 'self' global refers to a single client, as this function is called
times the amount of players in a given game. times the amount of players in a given game.
================= =================
*/ */
void PlayerPostThink(void) void
PlayerPostThink(void)
{ {
if (self.classname != "player") { if (self.classname != "player") {
return; return;
@ -208,7 +230,8 @@ void PlayerPostThink(void)
} }
#endif #endif
g_grMode.PlayerPostFrame((base_player)self); if (g_ents_initialized)
g_grMode.PlayerPostFrame((base_player)self);
} }
/* /*
@ -220,10 +243,13 @@ change ever having taken place.
The 'self' global does not refer to anything. The 'self' global does not refer to anything.
================= =================
*/ */
void SetNewParms(void) void
SetNewParms(void)
{ {
iprint("Setting New Level Parameters"); iprint("Setting New Level Parameters");
g_grMode.LevelNewParms();
if (g_ents_initialized)
g_grMode.LevelNewParms();
} }
/* /*
@ -238,10 +264,13 @@ Make sure we're saving important fields/attributes in the 'parmX' globals
allocated for every client. allocated for every client.
================= =================
*/ */
void SetChangeParms(void) void
SetChangeParms(void)
{ {
iprint("Setting Level-Change Parameters"); iprint("Setting Level-Change Parameters");
g_grMode.LevelChangeParms((base_player)self);
if (g_ents_initialized)
g_grMode.LevelChangeParms((base_player)self);
} }
/* /*
@ -254,7 +283,8 @@ The 'self' global is the entity having sent the input packet,
with the input_X globals being set to the appropriate data. with the input_X globals being set to the appropriate data.
================= =================
*/ */
void SV_RunClientCommand(void) void
SV_RunClientCommand(void)
{ {
if (self.classname != "player") { if (self.classname != "player") {
return; return;
@ -283,7 +313,8 @@ take over, you need to pass the string 'cmd' over via clientcommand().
Notable examples of client cmd's involve the chat system. Notable examples of client cmd's involve the chat system.
================= =================
*/ */
void SV_ParseClientCommand(string cmd) void
SV_ParseClientCommand(string cmd)
{ {
string newcmd = Plugin_ParseClientCommand(cmd); string newcmd = Plugin_ParseClientCommand(cmd);
@ -300,7 +331,8 @@ init
Called when the QC module gets loaded. No entities exist yet. Called when the QC module gets loaded. No entities exist yet.
================= =================
*/ */
void init(float prevprogs) void
init(float prevprogs)
{ {
iprint("Initializing Server-Module"); iprint("Initializing Server-Module");
Plugin_Init(); Plugin_Init();
@ -314,10 +346,13 @@ Called inside initents() to make sure the entities have their Respawn()
method called at the beginning of them having spawned. method called at the beginning of them having spawned.
================= =================
*/ */
void init_respawn(void) void
init_respawn(void)
{ {
iprint("Respawning Entities"); iprint("Respawning Entities");
g_grMode.InitPostEnts();
if (g_ents_initialized)
g_grMode.InitPostEnts();
for (entity a = world; (a = findfloat(a, ::identity, 1));) { for (entity a = world; (a = findfloat(a, ::identity, 1));) {
CBaseEntity ent = (CBaseEntity)a; CBaseEntity ent = (CBaseEntity)a;
@ -333,7 +368,8 @@ initents
??? ???
================= =================
*/ */
void initents(void) void
initents(void)
{ {
iprint("Initializing Entities"); iprint("Initializing Entities");
@ -426,6 +462,8 @@ void initents(void)
Plugin_InitEnts(); Plugin_InitEnts();
Mapcycle_Init(); Mapcycle_Init();
Vote_Init(); Vote_Init();
g_ents_initialized = TRUE;
} }
/* /*
@ -440,7 +478,8 @@ as they do not exist yet. Keep this in mind.
================= =================
*/ */
var int autocvar_sv_levelexec = 1; var int autocvar_sv_levelexec = 1;
void worldspawn(void) void
worldspawn(void)
{ {
iprint("Initializing World"); iprint("Initializing World");
lightstyle(0, "m"); lightstyle(0, "m");
@ -472,7 +511,8 @@ When returning FALSE the server will interpret the command.
Returning TRUE will mark the command as 'resolved'. Returning TRUE will mark the command as 'resolved'.
================= =================
*/ */
float ConsoleCmd(string cmd) float
ConsoleCmd(string cmd)
{ {
player pl; player pl;
@ -488,8 +528,9 @@ float ConsoleCmd(string cmd)
pl = (player)self; pl = (player)self;
/* give the game-mode a chance to override us */ /* give the game-mode a chance to override us */
if (g_grMode.ConsoleCommand(pl, cmd) == TRUE) if (g_ents_initialized)
return TRUE; if (g_grMode.ConsoleCommand(pl, cmd) == TRUE)
return TRUE;
/* time to handle commands that apply to all games */ /* time to handle commands that apply to all games */
tokenize(cmd); tokenize(cmd);
@ -506,6 +547,12 @@ float ConsoleCmd(string cmd)
t.Trigger(self, TRIG_TOGGLE); t.Trigger(self, TRIG_TOGGLE);
} }
break; break;
case "respawn_ents":
for (entity a = world; (a = findfloat(a, ::identity, 1));) {
CBaseEntity ent = (CBaseEntity)a;
ent.Respawn();
}
break;
#ifdef BOT_INCLUDED #ifdef BOT_INCLUDED
case "way": case "way":
Way_Cmd(); Way_Cmd();
@ -525,7 +572,8 @@ Returns TRUE if the server should pause the game-logic when the 'pause' command
is being executed. is being executed.
================= =================
*/ */
float SV_ShouldPause(float newstatus) float
SV_ShouldPause(float newstatus)
{ {
if (serverkeyfloat("background") == 1) if (serverkeyfloat("background") == 1)
return FALSE; return FALSE;

View file

@ -25,4 +25,5 @@ int Plugin_RunClientCommand(void);
string Plugin_ParseClientCommand(string); string Plugin_ParseClientCommand(string);
int Plugin_PlayerConnect(base_player); int Plugin_PlayerConnect(base_player);
int Plugin_PlayerDisconnect(base_player); int Plugin_PlayerDisconnect(base_player);
int Plugin_PlayerEntered(base_player);
void Plugin_PlayerObituary(entity, entity, int, int, int); void Plugin_PlayerObituary(entity, entity, int, int, int);

View file

@ -264,6 +264,41 @@ Plugin_PlayerDisconnect(base_player cl)
return rval; return rval;
} }
/*
=================
Plugin_PlayerEntered
Called when a player has fully connected and entered the server
=================
*/
int
Plugin_PlayerEntered(base_player cl)
{
int rval;
int tval;
int(entity) vFunc;
if (g_plugins_enabled == 0)
return FALSE;
/* rval = final return value, tval = temporary return value.
if at least one of the plugins returns TRUE, then RunClientCommand
will not be called by the engine, as it should be */
rval = FALSE;
tval = FALSE;
for (int i = 0; i < g_plugincount; i++) {
vFunc = externvalue(g_plugindb[i].m_flProgsID, "FMX_PlayerEntered");
if (vFunc) {
tval = vFunc(cl);
rval |= tval;
}
}
return rval;
}
/* /*
================= =================
Plugin_PlayerObituary Plugin_PlayerObituary