diff --git a/README.md b/README.md index b4070a9..ff45f34 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,13 @@ Bugfixed version of rehlds contains an additional cvars:
  • sv_rehlds_attachedentities_playeranimationspeed_fix // Fixes bug with gait animation speed increase when player has some attached entities (aiments). Can cause animation lags when cl_updaterate is low. Default: 0 +## Commands +Bugfixed version of rehlds contains an additional commands: + + ## Build instructions There are several software requirements for building rehlds:
      diff --git a/rehlds/HLTV/common/net_internal.h b/rehlds/HLTV/common/net_internal.h index bb304d7..e2af351 100644 --- a/rehlds/HLTV/common/net_internal.h +++ b/rehlds/HLTV/common/net_internal.h @@ -44,7 +44,7 @@ // Response details about each player on the server #define S2A_PLAYERS 'D' -// Response as multi-packeted the rules the server is using +// Number of rules + string key and string value pairs #define S2A_RULES 'E' /* ------ S2C_* - Server to client ------ */ diff --git a/rehlds/engine/host_cmd.cpp b/rehlds/engine/host_cmd.cpp index c3580a1..e1edcbb 100644 --- a/rehlds/engine/host_cmd.cpp +++ b/rehlds/engine/host_cmd.cpp @@ -2662,7 +2662,7 @@ void Host_Kill_f(void) Cmd_ForwardToServer(); return; } - + if (sv_player->v.health <= 0.0f #ifdef REHLDS_FIXES || sv_player->v.deadflag != DEAD_NO @@ -2985,6 +2985,76 @@ NOXREF void Host_Crash_f(void) *p = 0xffffffff; } +#ifdef REHLDS_FIXES +void Host_ResourcesCount_f() +{ + if (g_psv.num_resources <= 0) { + Con_Printf("--------------\nNo precached resources.\n\n"); + return; + } + + Con_Printf("\n %-4s : %-5s %-5s\n\n", "Type", "Total", "Limit"); + Con_Printf(" model : %-5d %-5d\n", SV_CountResourceByType(t_model), MAX_MODELS - 2); // CL_LoadModel expects last model slot is empty + Con_Printf(" sound : %-5d %-5d\n", SV_CountResourceByType(t_sound), MAX_SOUNDS - 1); + Con_Printf(" generic : %-5d %-5d\n", SV_CountResourceByType(t_generic), ARRAYSIZE(g_rehlds_sv.precachedGenericResourceNames)); + Con_Printf(" event : %-5d %-5d\n", SV_CountResourceByType(t_eventscript), MAX_EVENTS - 1); + Con_Printf(" decal : %-5d %-5d\n", SV_CountResourceByType(t_decal), MAX_DECALS - 1); + Con_Printf("------------------------\n%d Total of precached resource count\n\n", g_psv.num_resources, RESOURCE_MAX_COUNT); +} + +void Host_ResourcesList_f() +{ + const char *pszType = Cmd_Argv(1); + if (Cmd_Argc() == 1 + || (pszType[0] + && Q_stricmp(pszType, "sound") + && Q_stricmp(pszType, "model") + && Q_stricmp(pszType, "decal") + && Q_stricmp(pszType, "generic") + && Q_stricmp(pszType, "event"))) + { + Con_Printf("Usage: reslist \n"); + return; + } + + resourcetype_t type; + switch (pszType[0]) + { + default: + case 's': type = t_sound; break; + case 'm': type = t_model; break; + case 'd': type = t_decal; break; + case 'g': type = t_generic; break; + case 'e': type = t_eventscript; break; + } + + size_t nWidthFileName = 8; + resource_t *pResourseList[RESOURCE_MAX_COUNT]; + size_t nCountRes = SV_CountResourceByType(type, pResourseList, ARRAYSIZE(pResourseList), &nWidthFileName); + + char szMD5Hash[9], szFlags[32]; + Con_Printf("\n%4s %-4s : %-*s %-10s %-8s %-26s\n\n", "#", "Index", nWidthFileName, "FileName", "Size", "MD5", "Flags"); + for (size_t i = 0; i < nCountRes; i++) + { + szFlags[0] = '\0'; + if (pResourseList[i]->ucFlags & RES_CHECKFILE) { + Q_strlcat(szFlags, "CHECKFILE"); + } + if (pResourseList[i]->ucFlags & RES_FATALIFMISSING) { + Q_strlcat(szFlags, " FATALIFMISSING"); + } + + TrimSpace(szFlags, szFlags); + + // copy only 4 bytes + Q_strlcpy(szMD5Hash, MD5_Print(pResourseList[i]->rgucMD5_hash)); + Con_Printf("%4d. %-4d : %-*s %-10s %-8s %-26s\n", i + 1, pResourseList[i]->nIndex, nWidthFileName, pResourseList[i]->szFileName, va("%.2fK", pResourseList[i]->nDownloadSize / 1024.0f), szMD5Hash, (szFlags[0] == '\0') ? "-" : szFlags); + } + + Con_Printf("--------------\n%d Total %s's\n\n", nCountRes, pszType); +} +#endif + void Host_InitCommands(void) { #ifdef HOOK_ENGINE @@ -3100,6 +3170,11 @@ void Host_InitCommands(void) Cmd_AddCommand("heartbeat", Master_Heartbeat_f); #endif // HOOK_ENGINE +#ifdef REHLDS_FIXES + Cmd_AddCommand("rescount", Host_ResourcesCount_f); + Cmd_AddCommand("reslist", Host_ResourcesList_f); +#endif + Cvar_RegisterVariable(&gHostMap); Cvar_RegisterVariable(&voice_recordtofile); Cvar_RegisterVariable(&voice_inputfromfile); diff --git a/rehlds/engine/host_cmd.h b/rehlds/engine/host_cmd.h index ec9b3b2..49cdf30 100644 --- a/rehlds/engine/host_cmd.h +++ b/rehlds/engine/host_cmd.h @@ -205,6 +205,12 @@ void Host_KillServer_f(void); void Host_VoiceRecordStart_f(void); void Host_VoiceRecordStop_f(void); void Host_Crash_f(void); + +#ifdef REHLDS_FIXES +void Host_ResourcesList_f(); +void Host_ResourcesCount_f(); +#endif + void Host_InitCommands(void); void SV_CheckBlendingInterface(void); void SV_CheckSaveGameCommentInterface(void); diff --git a/rehlds/engine/net.h b/rehlds/engine/net.h index 9f3fa98..151f0cd 100644 --- a/rehlds/engine/net.h +++ b/rehlds/engine/net.h @@ -57,7 +57,7 @@ const char M2S_REQUESTRESTART = 'O'; // Response details about each player on the server const char S2A_PLAYERS = 'D'; -// Response as multi-packeted the rules the server is using +// Number of rules + string key and string value pairs const char S2A_RULES = 'E'; // info request diff --git a/rehlds/engine/server.h b/rehlds/engine/server.h index a92163e..1b81492 100644 --- a/rehlds/engine/server.h +++ b/rehlds/engine/server.h @@ -748,6 +748,7 @@ void SV_SendClientMessages(void); void SV_ExtractFromUserinfo(client_t *cl); int SV_ModelIndex(const char *name); void SV_AddResource(resourcetype_t type, const char *name, int size, unsigned char flags, int index); +size_t SV_CountResourceByType(resourcetype_t type, resource_t **pResourceList = nullptr, size_t nListMax = 0, size_t *nWidthFileNameMax = nullptr); void SV_CreateGenericResources(void); void SV_CreateResourceList(void); void SV_ClearCaches(void); diff --git a/rehlds/engine/sv_main.cpp b/rehlds/engine/sv_main.cpp index a5cc56f..5882001 100644 --- a/rehlds/engine/sv_main.cpp +++ b/rehlds/engine/sv_main.cpp @@ -5105,26 +5105,63 @@ void EXT_FUNC SV_AddResource(resourcetype_t type, const char *name, int size, un resource_t *r; #ifdef REHLDS_FIXES if (g_psv.num_resources >= ARRAYSIZE(g_rehlds_sv.resources)) -#else // REHLDS_FIXES +#else if (g_psv.num_resources >= MAX_RESOURCE_LIST) -#endif // REHLDS_FIXES +#endif { Sys_Error("%s: Too many resources on server.", __func__); } #ifdef REHLDS_FIXES r = &g_rehlds_sv.resources[g_psv.num_resources++]; - Q_memset(r, 0, sizeof(*r)); -#else // REHLDS_FIXES +#else r = &g_psv.resourcelist[g_psv.num_resources++]; #endif + r->type = type; - Q_strncpy(r->szFileName, name, sizeof(r->szFileName) - 1); - r->szFileName[sizeof(r->szFileName) - 1] = 0; r->ucFlags = flags; r->nDownloadSize = size; r->nIndex = index; + + Q_strlcpy(r->szFileName, name); +} + +size_t SV_CountResourceByType(resourcetype_t type, resource_t **pResourceList, size_t nListMax, size_t *nWidthFileNameMax) +{ + if (type < t_sound || type >= rt_max) + return 0; + + if (pResourceList && nListMax <= 0) + return 0; + + resource_t *r; +#ifdef REHLDS_FIXES + r = &g_rehlds_sv.resources[0]; +#else + r = &g_psv.resourcelist[0]; +#endif + + size_t nCount = 0; + for (int i = 0; i < g_psv.num_resources; i++, r++) + { + if (r->type != type) + continue; + + if (r->type == t_decal && r->nIndex >= MAX_DECALS) + continue; + + if (pResourceList) + pResourceList[nCount] = r; + + if (nWidthFileNameMax) + *nWidthFileNameMax = Q_max(*nWidthFileNameMax, Q_strlen(r->szFileName)); + + if (++nCount >= nListMax && nListMax > 0) + break; + } + + return nCount; } #ifdef REHLDS_FIXES