correct map issues clientside
but be loud about it instead of I_Error´ing most of those would be fatal anyways, so screw vanilla desyncing if they crash eitherways
This commit is contained in:
1 parent
99d49adad5
commit
36d1f59114
4 files changed
+74
-50
No files matched your search
@@ -1309,6 +1309,7 @@ static void G_DoLoadLevel(boolean resetplayer)
|
||||
{
|
||||
// fail so reset game stuff
|
||||
Command_ExitGame_f();
|
||||
P_FreeCorruptMapWarnings();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1342,6 +1343,8 @@ static void G_DoLoadLevel(boolean resetplayer)
|
||||
|
||||
// clear hud messages remains (usually from game startup)
|
||||
CON_ClearHUD();
|
||||
// print any map errors now due to clearhud above :chaosleep:
|
||||
P_PrintCorruptMapWarnings();
|
||||
|
||||
server_lagless = !cv_gentlemens.value;
|
||||
|
||||
|
||||
@@ -3590,8 +3590,11 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool
|
||||
if (!P_SetupLevel(true, reloading))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n"));
|
||||
P_FreeCorruptMapWarnings();
|
||||
return false;
|
||||
}
|
||||
|
||||
P_PrintCorruptMapWarnings();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+65
-50
@@ -188,6 +188,57 @@ FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg)
|
||||
I_Error("Invalid or corrupt map.\nLook in log file or text console for technical details.");
|
||||
}
|
||||
|
||||
static char **mapwarnings = NULL;
|
||||
static size_t nummapwarnings = 0;
|
||||
|
||||
// collect map errors we can fix clientside
|
||||
// we then can print em when the map finishes loading
|
||||
// so they actually appear and raise awareness shits fucked
|
||||
// see G_DoLoadLevel as to why :chaosleep:
|
||||
static void CorruptMapWarning(const char *msg)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
// just error out
|
||||
I_Error("%sThis WILL crash Vanilla clients!\n", msg);
|
||||
#endif
|
||||
nummapwarnings++;
|
||||
mapwarnings = Z_Realloc(mapwarnings, nummapwarnings * sizeof(*mapwarnings), PU_STATIC, NULL);
|
||||
mapwarnings[nummapwarnings-1] = Z_StrDup(msg);
|
||||
}
|
||||
|
||||
void P_PrintCorruptMapWarnings(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!nummapwarnings)
|
||||
return;
|
||||
|
||||
for (i = 0; i < nummapwarnings; i++)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "%sAttempting to fix... This WILL crash Vanilla clients!\n", mapwarnings[i]);
|
||||
}
|
||||
|
||||
P_FreeCorruptMapWarnings();
|
||||
}
|
||||
|
||||
void P_FreeCorruptMapWarnings(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!nummapwarnings)
|
||||
return;
|
||||
|
||||
for (i = 0; i < nummapwarnings; i++)
|
||||
{
|
||||
Z_Free(mapwarnings[i]);
|
||||
mapwarnings[i] = NULL;
|
||||
}
|
||||
|
||||
Z_Free(mapwarnings);
|
||||
mapwarnings = NULL;
|
||||
nummapwarnings = 0;
|
||||
}
|
||||
|
||||
#define NUMLAPS_DEFAULT 3
|
||||
|
||||
static void P_ClearMapHeaderLighting(mapheader_lighting_t *lighting)
|
||||
@@ -448,16 +499,10 @@ static void P_LoadSegs(UINT8 *data)
|
||||
// http://www.doomworld.com/idgames/index.php?id=12647
|
||||
if ((unsigned)v1 >= numvertexes || (unsigned)v2 >= numvertexes)
|
||||
{
|
||||
#ifdef COMPAT_VANILLA
|
||||
if ((unsigned)v1 >= numvertexes)
|
||||
I_Error("P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v1);
|
||||
CorruptMapWarning(va("P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v1));
|
||||
if ((unsigned)v2 >= numvertexes)
|
||||
I_Error("P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v2);
|
||||
#else
|
||||
if ((unsigned)v1 >= numvertexes)
|
||||
CONS_Debug(DBG_SETUP, "P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v1);
|
||||
if ((unsigned)v2 >= numvertexes)
|
||||
CONS_Debug(DBG_SETUP, "P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v2);
|
||||
CorruptMapWarning(va("P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v2));
|
||||
|
||||
if (li->sidedef == &sides[li->linedef->sidenum[0]])
|
||||
{
|
||||
@@ -469,7 +514,6 @@ static void P_LoadSegs(UINT8 *data)
|
||||
li->v1 = lines[ml->linedef].v2;
|
||||
li->v2 = lines[ml->linedef].v1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -507,12 +551,8 @@ static void P_LoadSegs(UINT8 *data)
|
||||
//e6y: fix wrong side index
|
||||
if (rawside != 0 && rawside != 1)
|
||||
{
|
||||
#ifdef COMPAT_VANILLA
|
||||
I_Error("P_LoadSegs: seg %s contains wrong side index %d.\n", sizeu1(i), rawside);
|
||||
#else
|
||||
CorruptMapWarning(va("P_LoadSegs: seg %s contains wrong side index %d.\n", sizeu1(i), rawside));
|
||||
rawside = 1;
|
||||
CONS_Debug(DBG_SETUP, "P_LoadSegs: seg %s contains wrong side index %d, replaced with 1.\n", sizeu1(i), rawside);
|
||||
#endif
|
||||
}
|
||||
|
||||
//e6y: check for wrong indexes
|
||||
@@ -530,12 +570,8 @@ static void P_LoadSegs(UINT8 *data)
|
||||
* referencing the back of a 1S line */
|
||||
if (ldef->sidenum[rawside] == NO_INDEX)
|
||||
{
|
||||
#ifdef COMPAT_VANILLA
|
||||
I_Error("P_LoadSegs: front of seg %s has no sidedef\n", sizeu1(i));
|
||||
#else
|
||||
CorruptMapWarning(va("P_LoadSegs: front of seg %s has no sidedef\n", sizeu1(i)));
|
||||
li->frontsector = NULL;
|
||||
CONS_Debug(DBG_SETUP, "P_LoadSegs: front of seg %s has no sidedef\n", sizeu1(i));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -546,12 +582,8 @@ static void P_LoadSegs(UINT8 *data)
|
||||
{
|
||||
if (ldef->sidenum[rawside^1] == NO_INDEX)
|
||||
{
|
||||
#ifdef COMPAT_VANILLA
|
||||
I_Error("P_LoadSegs: back of seg %s has no sidedef while being marked as double sided\n", sizeu1(i));
|
||||
#else
|
||||
CorruptMapWarning(va("P_LoadSegs: back of seg %s has no sidedef while being marked as double sided\n", sizeu1(i)));
|
||||
li->backsector = NULL;
|
||||
CONS_Debug(DBG_SETUP, "P_LoadSegs: back of seg %s has no sidedef while being marked as double sided\n", sizeu1(i));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -845,25 +877,17 @@ static void P_LoadNodes(UINT8 *data)
|
||||
// haleyjd 11/06/10: check for invalid subsector reference
|
||||
if (child >= numsubsectors)
|
||||
{
|
||||
#ifdef COMPAT_VANILLA
|
||||
I_Error("P_LoadNodes: BSP tree %s references invalid subsector %d\n", sizeu1(i), child);
|
||||
#else
|
||||
CorruptMapWarning(va("P_LoadNodes: BSP tree %s references invalid subsector %d\n", sizeu1(i), child));
|
||||
child = 0;
|
||||
CONS_Debug(DBG_SETUP, "P_LoadNodes: BSP tree %s references invalid subsector %d\n", sizeu1(i), child);
|
||||
#endif
|
||||
}
|
||||
|
||||
child |= NF_SUBSECTOR;
|
||||
}
|
||||
else if (child >= numnodes)
|
||||
{
|
||||
#ifdef COMPAT_VANILLA
|
||||
I_Error("P_LoadNodes: BSP node %s references invalid node.\n", sizeu1(i));
|
||||
CorruptMapWarning(va("P_LoadNodes: BSP node %s references invalid node.\n", sizeu1(i)));
|
||||
//I_Error("P_LoadNodes: BSP node %d references invalid node %d.\n", sizeu1(i), Index(((node_t *)no->children[j])));
|
||||
#else
|
||||
child = 0;
|
||||
CONS_Debug(DBG_SETUP, "P_LoadNodes: BSP node %s references invalid node.\n", sizeu1(i));
|
||||
#endif
|
||||
}
|
||||
|
||||
no->children[j] = child;
|
||||
@@ -1876,19 +1900,11 @@ static boolean P_LoadRawBlockMap(UINT8 *data, size_t count)
|
||||
// http://www.doomworld.com/idgames/index.php?id=12935
|
||||
if (!P_VerifyBlockMap(count))
|
||||
{
|
||||
#ifdef COMPAT_VANILLA
|
||||
#ifdef PARANOIA
|
||||
I_Error("P_LoadBlockMap: erroneous BLOCKMAP lump may cause crashes.\n");
|
||||
#endif
|
||||
CONS_Alert(CONS_ERROR, "P_LoadBlockMap: erroneous BLOCKMAP lump may cause crashes.\n");
|
||||
#else
|
||||
CONS_Debug(DBG_SETUP, "P_LoadBlockMap: corrupted or invalid BLOCKMAP lump!\nRebuilding...\n");
|
||||
CorruptMapWarning(va("P_LoadBlockMap: corrupted or invalid BLOCKMAP lump! Check the log for more information.\n"));
|
||||
// vanilla WILL crash here anyways so just rebuild it ourselves
|
||||
Z_Free(blockmaplump);
|
||||
blockmaplump = NULL;
|
||||
return false; // ideally we would just let the game rebuild the blockmap
|
||||
// but this has a chance of desynching vanilla clients
|
||||
// not sure whats worse honestly and i do not want to decide that :chaosleep:
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// clear out mobj chains
|
||||
@@ -2031,14 +2047,13 @@ static void P_LoadReject(UINT8 *data, size_t rejectsize)
|
||||
{
|
||||
if (rejectsize < neededsize)
|
||||
{
|
||||
CorruptMapWarning(va("P_LoadReject: REJECT is %s byte%s too small. REJECT might be invalid!\n", sizeu1(neededsize - rejectsize), (neededsize - rejectsize) == 1 ? "" : "s"));
|
||||
#ifdef COMPAT_VANILLA
|
||||
#ifdef PARANOIA
|
||||
I_Error("P_LoadReject: REJECT is %s byte%s too small. REJECT might be invalid and crash vanilla clients!\n", sizeu1(neededsize - rejectsize), (neededsize - rejectsize) == 1 ? "" : "s");
|
||||
#endif
|
||||
CONS_Alert(CONS_ERROR, "P_LoadReject: REJECT is %s byte%s too small. REJECT might be invalid and crash vanilla clients!\n", sizeu1(neededsize - rejectsize), (neededsize - rejectsize) == 1 ? "" : "s");
|
||||
// we can pad this and somewhat prevent desyncs
|
||||
// probs not cool if the reject is from a completely different map
|
||||
// but whatever
|
||||
allocsize = neededsize;
|
||||
#else
|
||||
CONS_Debug(DBG_SETUP, "P_LoadReject: REJECT is %s byte%s too small and might be invalid, will not be loaded\n", sizeu1(neededsize - rejectsize), (neededsize - rejectsize) == 1 ? "" : "s");
|
||||
rejectmatrix = NULL;
|
||||
return;
|
||||
#endif
|
||||
|
||||
@@ -114,6 +114,9 @@ size_t P_PrecacheLevelFlats(void);
|
||||
|
||||
void P_AllocMapHeader(INT16 i);
|
||||
|
||||
void P_PrintCorruptMapWarnings(void);
|
||||
void P_FreeCorruptMapWarnings(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
Reference in new issue
Block a user