I decided to hook
ClientPutInServer
which runs when the player enters the game, but unfortunately it is too early to send messages from here.
void ClientPutInServer( edict_t *pEntity ) {
const char* playername = STRING(pEntity->v.netname);
char* modelname = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pEntity ), "model" );
char modelfile[256];
snprintf(modelfile, sizeof(modelfile), "models/player/%s/%s.mdl", modelname, modelname);
LOG_MESSAGE(PLID, "Player %s is using model %s", playername, modelname);
if (fileExists( modelfile )) {
LOG_MESSAGE(PLID, "Model %s is present on server", modelname);
SAY(pEntity, "Your model is present on the server, it will be precached for the next round!");
if (addPrecacheEntry( playername, modelname ))
LOG_MESSAGE(PLID, "Added model %s to precache list", modelname);
else
LOG_MESSAGE(PLID, "Model %s will not be precached - reduntant or precache list is full", modelname);
}
else {
LOG_MESSAGE(PLID, "Unable to precache due to FILE MISSING: %s!", modelfile);
SAY(pEntity, "Your model is not present on the server, can't distribute for other players!");
}
RETURN_META(MRES_IGNORED);
}
If I send a message to other players who are already in game, or all players, they receive the message, so it's not that
SAY()
doesn't work. I think somehow I should add some timing, so the message would be sent several seconds later when they are already playing. (Just an irrelevant sidenote: the log message "
Model %s will not be precached - reduntant or precache list is full
" is confusing, because if the model is already added to the list, it WILL be precached for the next round, but won't if the list is full.)
SAY()
is a macro I defined to send raw messages – I remember there are other methods I tried, but all of them effectively do this at their core.
#define SAY(pEntity, text) {\
MESSAGE_BEGIN( MSG_ONE, GET_USER_MSG_ID(PLID, "SayText", NULL), NULL, pEntity );\
WRITE_BYTE( ENTINDEX(pEntity) );\
WRITE_STRING( text );\
MESSAGE_END();\
}
And
fileExists()
here is just a wrapper for calling
access()
(this is the other thing I have problem with):
bool fileExists(const char* path) {
char fullpath[256];
snprintf(fullpath, sizeof(fullpath), "%s/%s", &gGamedir[0], path);
return access(fullpath, R_OK) == 0;
}
I highly doubt that
LoadFileForMe()
would
mmap()
the file – it would be somewhat better because it's faster and the kernel could at least unload it if it's not used, but it would still be better to not load files in the middle of a game when they are not needed in memory.
IFileSystem
in
public/FileSystem.h
is interesting, I think it would do what I need but I have no idea what it links to.