diff --git a/inc/common/cmodel.h b/inc/common/cmodel.h index c237c4737..739ada533 100644 --- a/inc/common/cmodel.h +++ b/inc/common/cmodel.h @@ -40,7 +40,7 @@ void CM_Init(void); void CM_FreeMap(cm_t *cm); int CM_LoadMap(cm_t *cm, const char *name); -void CM_LoadOverrides(cm_t *cm, char *server, size_t server_size); +void CM_LoadOverride(cm_t *cm, char *server, size_t server_size); const mnode_t *CM_NodeNum(const cm_t *cm, int number); const mleaf_t *CM_LeafNum(const cm_t *cm, int number); diff --git a/src/common/cmodel.c b/src/common/cmodel.c index 5f4303b69..36d89cdbf 100644 --- a/src/common/cmodel.c +++ b/src/common/cmodel.c @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/cmd.h" #include "common/cmodel.h" #include "common/common.h" +#include "common/crc.h" #include "common/cvar.h" #include "common/files.h" #include "common/math.h" @@ -50,20 +51,43 @@ enum { OVERRIDE_ALL = MASK(3) }; -static void load_entstring_override(cm_t *cm, const char *server) +static void load_entstring_override(cm_t *cm) { - char buffer[MAX_QPATH], *data = NULL; - int ret; + char buffer[MAX_QPATH], name[MAX_QPATH], *data = NULL; + const bsp_t *bsp = cm->cache; + const char *path = map_override_path->string; + int ret, crc = 0; + + if (!*path) + return; + + if (!Com_ParseMapName(name, bsp->name, sizeof(name))) + return; - if (Q_snprintf(buffer, sizeof(buffer), "%s/%s.ent", map_override_path->string, server) >= sizeof(buffer)) { + // last byte is excluded from CRC (why?) + if (bsp->numentitychars > 0) + crc = CRC_Block((const byte *)bsp->entitystring, bsp->numentitychars - 1); + + // load entity string from `@.ent' + if (Q_snprintf(buffer, sizeof(buffer), "%s/%s@%04x.ent", path, name, crc) >= sizeof(buffer)) { ret = Q_ERR(ENAMETOOLONG); goto fail; } - ret = FS_LoadFileEx(buffer, (void **)&data, 0, TAG_CMODEL); - if (!data) { - if (ret == Q_ERR(ENOENT)) - return; + + // fall back to no hash + if (ret == Q_ERR(ENOENT)) { + Q_snprintf(buffer, sizeof(buffer), "%s/%s.ent", path, name); + ret = FS_LoadFileEx(buffer, (void **)&data, 0, TAG_CMODEL); + } + if (ret == Q_ERR(ENOENT)) + return; + + if (ret < 0) + goto fail; + + if (ret < 2) { + ret = Q_ERR_FILE_TOO_SMALL; goto fail; } @@ -77,7 +101,18 @@ static void load_entstring_override(cm_t *cm, const char *server) Com_EPrintf("Couldn't load entity string from %s: %s\n", buffer, Q_ErrorString(ret)); } -static void load_binary_override(cm_t *cm, char *server, size_t server_size) +/* +================== +CM_LoadOverride + +Load R1Q2-style binary override file. + +Must be called before CM_LoadMap(). +May modify server buffer if name override is in effect. +May allocate enstring, must be freed with CM_FreeMap(). +================== +*/ +void CM_LoadOverride(cm_t *cm, char *server, size_t server_size) { sizebuf_t sz; char buffer[MAX_QPATH]; @@ -85,6 +120,9 @@ static void load_binary_override(cm_t *cm, char *server, size_t server_size) int ret, bits, len; char *buf, name_buf[MAX_QPATH]; + if (!*map_override_path->string) + return; + if (Q_snprintf(buffer, sizeof(buffer), "%s/%s.bsp.override", map_override_path->string, server) >= sizeof(buffer)) { ret = Q_ERR(ENAMETOOLONG); goto fail; @@ -141,28 +179,6 @@ static void load_binary_override(cm_t *cm, char *server, size_t server_size) FS_FreeFile(data); } -/* -================== -CM_LoadOverrides - -Ugly hack to override entstring and other parameters. - -Must be called before CM_LoadMap. -May modify server buffer if name override is in effect. -May allocate enstring, must be freed with CM_FreeMap(). -================== -*/ -void CM_LoadOverrides(cm_t *cm, char *server, size_t server_size) -{ - if (!*map_override_path->string) - return; - - load_binary_override(cm, server, server_size); - - if (!(cm->override_bits & OVERRIDE_ENTS)) - load_entstring_override(cm, server); -} - /* ================== CM_FreeMap @@ -196,6 +212,9 @@ int CM_LoadMap(cm_t *cm, const char *name) if (!cm->cache) return ret; + if (!(cm->override_bits & OVERRIDE_ENTS)) + load_entstring_override(cm); + if (!(cm->override_bits & OVERRIDE_CSUM)) cm->checksum = cm->cache->checksum; diff --git a/src/server/init.c b/src/server/init.c index 9dfc8421f..4150460b7 100644 --- a/src/server/init.c +++ b/src/server/init.c @@ -286,7 +286,7 @@ static bool parse_and_check_server(mapcmd_t *cmd, const char *server, bool nexts break; default: - CM_LoadOverrides(&cmd->cm, cmd->server, sizeof(cmd->server)); // may override server! + CM_LoadOverride(&cmd->cm, cmd->server, sizeof(cmd->server)); // may override server! if (Q_concat(expanded, sizeof(expanded), "maps/", cmd->server, ".bsp") < sizeof(expanded)) ret = CM_LoadMap(&cmd->cm, expanded); if (ret < 0)