Always check external levels for connectivity errors
Players keep reporting errors that trace to the game rejecting invalid data from user-made maps. In this case, asymmetric connectivity in _Descent Vignettes_[1] level _Stalactite Volcano_ (level 15 in Descent, level 14 in Descent 2) caused an exception when trying to render part of the first big room. The debug build shipped with function `check_segment_connections` to detect some types of connectivity errors. Expose this function to release builds, and call it for user-made maps. It already checked for asymmetric segment links. Extend that to hotfix those links by breaking the asymmetric connection. Log an URGENT class message when this happens, so that users are aware that the level was modified at load. Move the `NDEBUG` guards into `check_segment_connections` so that non-debug builds check only for segment symmetry, but do not check for normals and face count errors. [1] http://www.enspiar.com/dmdb/viewMission.php?id=724 ``` sha1sum vignette.hog vignette.msn 3cd659e6dd5927b41157dfb7d1dd87d90e781f01 vignette.hog 1f7d140ffab11816364040dd6da71a1568393a16 vignette.msn stat -c '%s %Y %n' vignette.hog vignette.msn 5717889 1251643308 vignette.hog 956 1250212930 vignette.msn ``` Reported-by: MegaDescent <http://forum.dxx-rebirth.com/showthread.php?tid=970>
This commit is contained in:
parent
e8d82d7d85
commit
c816a79c47
|
@ -1434,13 +1434,18 @@ int load_level(const char * filename_passed)
|
|||
editor_status_fmt("Loaded NEW mine %s, \"%s\"", filename, static_cast<const char *>(Current_level_name));
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG) && !defined(COMPACT_SEGS)
|
||||
#ifdef NDEBUG
|
||||
if (!PLAYING_BUILTIN_MISSION)
|
||||
#endif
|
||||
if (check_segment_connections())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
nm_messagebox( "ERROR", 1, "Ok",
|
||||
"Connectivity errors detected in\n"
|
||||
"mine. See monochrome screen for\n"
|
||||
"details, and contact Matt or Mike." );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if defined(DXX_BUILD_DESCENT_II)
|
||||
|
|
|
@ -486,18 +486,21 @@ static int check_norms(const vcsegptr_t segp,int sidenum,int facenum,const vcseg
|
|||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
//heavy-duty error checking
|
||||
int check_segment_connections(void)
|
||||
{
|
||||
int errors=0;
|
||||
|
||||
range_for (const auto &&seg, vcsegptridx)
|
||||
range_for (const auto &&seg, vmsegptridx)
|
||||
{
|
||||
for (int sidenum=0;sidenum<6;sidenum++) {
|
||||
#ifndef NDEBUG
|
||||
const auto v = create_abs_vertex_lists(seg, sidenum);
|
||||
const auto &num_faces = v.first;
|
||||
const auto &vertex_list = v.second;
|
||||
#endif
|
||||
auto csegnum = seg->children[sidenum];
|
||||
if (IS_CHILD(csegnum)) {
|
||||
auto cseg = vcsegptr(csegnum);
|
||||
|
@ -505,15 +508,22 @@ int check_segment_connections(void)
|
|||
|
||||
if (csidenum == side_none)
|
||||
{
|
||||
auto &rseg = *seg;
|
||||
auto &rcseg = *cseg;
|
||||
const unsigned segi = seg.get_unchecked_index();
|
||||
LevelError("Segment #%u side %u has asymmetric link to segment %u. Coercing to segment_none; Segments[%u].children={%hu, %hu, %hu, %hu, %hu, %hu}, Segments[%u].children={%hu, %hu, %hu, %hu, %hu, %hu}.", segi, sidenum, csegnum, segi, rseg.children[0], rseg.children[1], rseg.children[2], rseg.children[3], rseg.children[4], rseg.children[5], csegnum, rcseg.children[0], rcseg.children[1], rcseg.children[2], rcseg.children[3], rcseg.children[4], rcseg.children[5]);
|
||||
rseg.children[sidenum] = segment_none;
|
||||
errors = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
const auto cv = create_abs_vertex_lists(cseg, csidenum);
|
||||
const auto &con_num_faces = cv.first;
|
||||
const auto &con_vertex_list = cv.second;
|
||||
|
||||
if (con_num_faces != num_faces) {
|
||||
LevelError("Segment #%u side %u: wrong faces: con_num_faces=%lu num_faces=%lu.", seg.get_unchecked_index(), sidenum, con_num_faces, num_faces);
|
||||
errors = 1;
|
||||
}
|
||||
else
|
||||
|
@ -527,6 +537,7 @@ int check_segment_connections(void)
|
|||
vertex_list[1] != con_vertex_list[(t+3)%4] ||
|
||||
vertex_list[2] != con_vertex_list[(t+2)%4] ||
|
||||
vertex_list[3] != con_vertex_list[(t+1)%4]) {
|
||||
LevelError("Segment #%u side %u: bad vertices.", seg.get_unchecked_index(), sidenum);
|
||||
errors = 1;
|
||||
}
|
||||
else
|
||||
|
@ -565,14 +576,12 @@ int check_segment_connections(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
// Used to become a constant based on editor, but I wanted to be able to set
|
||||
// this for omega blob find_point_seg calls.
|
||||
|
|
Loading…
Reference in a new issue