From e0540c6b3720304d5c2f01c4c940b6863dbacab3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 6 Jan 2017 10:33:58 +0100 Subject: [PATCH 01/11] - fixed uninitialized variable warning in codegen.cpp --- src/scripting/codegeneration/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index ed0c272700..7a6997746a 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3980,7 +3980,7 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build) } else { - int cast; + int cast = 0; strng = ExpEmit(build, REGT_STRING); if (op1.Konst) { From 9ed2da176ebfde0949f667d8dbc8ce05bc668c58 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 5 Jan 2017 15:45:15 +0200 Subject: [PATCH 02/11] Fixed signed/unsigned mismatch in comparisons No more 'comparison of integers of different signs' warnings reported by GCC/Clang --- src/gl/data/gl_setup.cpp | 6 +++--- src/gl/dynlights/gl_glow.cpp | 8 ++++---- src/gl/renderer/gl_colormap.h | 2 +- src/gl/renderer/gl_lightdata.h | 4 ++-- src/gl/renderer/gl_postprocess.cpp | 2 +- src/gl/renderer/gl_renderbuffers.cpp | 4 ++-- src/gl/scene/gl_scene.cpp | 2 +- src/gl/scene/gl_walls.cpp | 2 +- src/gl/system/gl_debug.cpp | 2 +- src/gl/textures/gl_material.cpp | 2 +- src/p_setup.cpp | 4 ++-- src/p_udmf.cpp | 6 +++--- 12 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/gl/data/gl_setup.cpp b/src/gl/data/gl_setup.cpp index 376b4aa6d2..3b72c98635 100644 --- a/src/gl/data/gl_setup.cpp +++ b/src/gl/data/gl_setup.cpp @@ -302,9 +302,9 @@ static void PrepareSectorData() static void PrepareTransparentDoors(sector_t * sector) { bool solidwall=false; - int notextures=0; - int nobtextures=0; - int selfref=0; + unsigned int notextures=0; + unsigned int nobtextures=0; + unsigned int selfref=0; sector_t * nextsec=NULL; #ifdef _DEBUG diff --git a/src/gl/dynlights/gl_glow.cpp b/src/gl/dynlights/gl_glow.cpp index e0ed6d0f66..aaf3930e6b 100644 --- a/src/gl/dynlights/gl_glow.cpp +++ b/src/gl/dynlights/gl_glow.cpp @@ -125,7 +125,7 @@ int gl_CheckSpriteGlow(sector_t *sector, int lightlevel, const DVector3 &pos) } } } - else if (c != -1) + else if (uint32(-1) != c) { bottomglowcolor[0] = c.r / 255.f; bottomglowcolor[1] = c.g / 255.f; @@ -171,7 +171,7 @@ bool gl_GetWallGlow(sector_t *sector, float *topglowcolor, float *bottomglowcolo } } } - else if (c != -1) + else if (uint32(-1) != c) { topglowcolor[0] = c.r / 255.f; topglowcolor[1] = c.g / 255.f; @@ -195,7 +195,7 @@ bool gl_GetWallGlow(sector_t *sector, float *topglowcolor, float *bottomglowcolo } } } - else if (c != -1) + else if (uint32(-1) != c) { bottomglowcolor[0] = c.r / 255.f; bottomglowcolor[1] = c.g / 255.f; @@ -214,4 +214,4 @@ CCMD(setglow) auto s = players[0].mo->Sector; s->planes[sector_t::floor].GlowHeight = 128; s->planes[sector_t::floor].GlowColor = 0xff0000; -} \ No newline at end of file +} diff --git a/src/gl/renderer/gl_colormap.h b/src/gl/renderer/gl_colormap.h index 8bee402c9e..2c9fb91a4c 100644 --- a/src/gl/renderer/gl_colormap.h +++ b/src/gl/renderer/gl_colormap.h @@ -5,7 +5,7 @@ #include "v_palette.h" #include "r_data/colormaps.h" -extern DWORD gl_fixedcolormap; +extern int gl_fixedcolormap; struct lightlist_t; diff --git a/src/gl/renderer/gl_lightdata.h b/src/gl/renderer/gl_lightdata.h index a1abf8c823..7af5e7a4f8 100644 --- a/src/gl/renderer/gl_lightdata.h +++ b/src/gl/renderer/gl_lightdata.h @@ -35,7 +35,7 @@ inline bool gl_isWhite(PalEntry color) return color.r + color.g + color.b == 3*0xff; } -extern DWORD gl_fixedcolormap; +extern int gl_fixedcolormap; inline bool gl_isFullbright(PalEntry color, int lightlevel) { @@ -61,4 +61,4 @@ inline void FColormap::CopyFrom3DLight(lightlist_t *light) -#endif \ No newline at end of file +#endif diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index f35071854f..30c0000d33 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -323,7 +323,7 @@ void FGLRenderer::UpdateCameraExposure() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Find the average value: - for (int i = 0; i + 1 < mBuffers->ExposureLevels.Size(); i++) + for (unsigned int i = 0; i + 1 < mBuffers->ExposureLevels.Size(); i++) { const auto &level = mBuffers->ExposureLevels[i]; const auto &next = mBuffers->ExposureLevels[i + 1]; diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index b14ee98525..77e77bf5b5 100644 --- a/src/gl/renderer/gl_renderbuffers.cpp +++ b/src/gl/renderer/gl_renderbuffers.cpp @@ -448,7 +448,7 @@ void FGLRenderBuffers::CreateExposureLevels(int width, int height) void FGLRenderBuffers::CreateEyeBuffers(int eye) { - if (mEyeFBs.Size() > eye) + if (mEyeFBs.Size() > unsigned(eye)) return; GLint activeTex, textureBinding, frameBufferBinding; @@ -457,7 +457,7 @@ void FGLRenderBuffers::CreateEyeBuffers(int eye) glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBufferBinding); - while (mEyeFBs.Size() <= eye) + while (mEyeFBs.Size() <= unsigned(eye)) { GLuint texture = Create2DTexture("EyeTexture", GL_RGBA16F, mWidth, mHeight); mEyeTextures.Push(texture); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index bedd7a7e7f..b4efe736ee 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -88,7 +88,7 @@ extern int viewpitch; extern bool NoInterpolateView; extern bool r_showviewer; -DWORD gl_fixedcolormap; +int gl_fixedcolormap; area_t in_area; TArray currentmapsection; int camtexcount; diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index 4d258b3a03..5ac29dcad6 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -1245,7 +1245,7 @@ void GLWall::ClipFFloors(seg_t * seg, F3DFloor * ffloor, sector_t * frontsector, { TArray & frontffloors = frontsector->e->XFloor.ffloors; - int flags = ffloor->flags & (FF_SWIMMABLE | FF_TRANSLUCENT); + const unsigned int flags = ffloor->flags & (FF_SWIMMABLE | FF_TRANSLUCENT); for (unsigned int i = 0; i < frontffloors.Size(); i++) { diff --git a/src/gl/system/gl_debug.cpp b/src/gl/system/gl_debug.cpp index a8b1bab5dd..25651721e3 100644 --- a/src/gl/system/gl_debug.cpp +++ b/src/gl/system/gl_debug.cpp @@ -143,7 +143,7 @@ void FGLDebug::SetupBreakpointMode() void FGLDebug::UpdateLoggingLevel() { - int level = gl_debug_level; + const GLenum level = gl_debug_level; if (level != mCurrentLevel) { glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr, level > 0); diff --git a/src/gl/textures/gl_material.cpp b/src/gl/textures/gl_material.cpp index 4be2e96198..8bb8ee6f0a 100644 --- a/src/gl/textures/gl_material.cpp +++ b/src/gl/textures/gl_material.cpp @@ -285,7 +285,7 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla if (translation <= 0) translation = -translation; else { - alphatrans = (gl.legacyMode && translation == TRANSLATION(TRANSLATION_Standard, 8)); + alphatrans = (gl.legacyMode && DWORD(translation) == TRANSLATION(TRANSLATION_Standard, 8)); translation = GLTranslationPalette::GetInternalTranslation(translation); } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index de83577642..a1422236ad 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3088,7 +3088,7 @@ line_t** linebuffer; static void P_GroupLines (bool buildmap) { cycle_t times[16]; - int* linesDoneInEachSector; + unsigned int* linesDoneInEachSector; int i; int total; line_t* li; @@ -3156,7 +3156,7 @@ static void P_GroupLines (bool buildmap) times[3].Clock(); linebuffer = new line_t *[total]; line_t **lineb_p = linebuffer; - linesDoneInEachSector = new int[numsectors]; + linesDoneInEachSector = new unsigned int[numsectors]; memset (linesDoneInEachSector, 0, sizeof(int)*numsectors); for (sector = sectors, i = 0; i < numsectors; i++, sector++) diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 51bd780f5b..9f920d2254 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1695,7 +1695,7 @@ public: sec->ceilingplane.set(n.X, n.Y, n.Z, cp[3]); } - if (lightcolor == -1 && fadecolor == -1 && desaturation == -1 && fogdensity == -1) + if (lightcolor == uint32(-1) && fadecolor == uint32(-1) && desaturation == -1 && fogdensity == -1) { // [RH] Sectors default to white light with the default fade. // If they are outside (have a sky ceiling), they use the outside fog. @@ -1714,8 +1714,8 @@ public: } else { - if (lightcolor == -1) lightcolor = PalEntry(255,255,255); - if (fadecolor == -1) + if (uint32(-1) == lightcolor) lightcolor = PalEntry(255,255,255); + if (uint32(-1) == fadecolor) { if (level.outsidefog != 0xff000000 && (sec->GetTexture(sector_t::ceiling) == skyflatnum || (sec->special & 0xff) == Sector_Outside)) fadecolor = level.outsidefog; From d77718d4223e218b9b3b7eee64b9628cd37c6b80 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 5 Jan 2017 15:47:16 +0200 Subject: [PATCH 03/11] Fixed harmless uninitialized variables warnings No more 'variable is used uninitialized whenever switch default is taken' warnings reported by GCC/Clang --- src/gl/renderer/gl_renderbuffers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index 77e77bf5b5..fad79767c6 100644 --- a/src/gl/renderer/gl_renderbuffers.cpp +++ b/src/gl/renderer/gl_renderbuffers.cpp @@ -482,7 +482,7 @@ GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int glBindTexture(GL_TEXTURE_2D, handle); FGLDebug::LabelObject(GL_TEXTURE, handle, name); - GLenum dataformat, datatype; + GLenum dataformat = 0, datatype = 0; switch (format) { case GL_RGBA8: dataformat = GL_RGBA; datatype = GL_UNSIGNED_BYTE; break; From 0e9f52f9e55cb8cc1099c3fe0c47f3e80b4f94f9 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 5 Jan 2017 15:48:23 +0200 Subject: [PATCH 04/11] Added virtual destructor to FPresentShaderBase class No more 'delete called on non-final class that has virtual functions but non-virtual destructor' warnings reported by GCC/Clang --- src/gl/shaders/gl_presentshader.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gl/shaders/gl_presentshader.h b/src/gl/shaders/gl_presentshader.h index 6f9e1bfd7d..dcf42cdf8b 100644 --- a/src/gl/shaders/gl_presentshader.h +++ b/src/gl/shaders/gl_presentshader.h @@ -6,6 +6,7 @@ class FPresentShaderBase { public: + virtual ~FPresentShaderBase() {} virtual void Bind() = 0; FBufferedUniform1f InvGamma; @@ -26,4 +27,4 @@ public: FBufferedUniformSampler InputTexture; }; -#endif \ No newline at end of file +#endif From 1a0d8dffd9a753e0cbf1865c99d4873868522b6d Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 5 Jan 2017 15:50:10 +0200 Subject: [PATCH 05/11] Fixed harmless initialization order mismatch No more 'field ... will be initialized after field ...' warnings reported by GCC/Clang --- src/p_pspr.cpp | 2 +- src/textures/warptexture.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 238412bb6d..a6a5812289 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -136,10 +136,10 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id) : x(.0), y(.0), oldx(.0), oldy(.0), firstTic(true), - Sprite(0), Flags(0), Caller(caller), Owner(owner), + Sprite(0), ID(id), processPending(true) { diff --git a/src/textures/warptexture.cpp b/src/textures/warptexture.cpp index a8a2ddb9e1..ee08148d20 100644 --- a/src/textures/warptexture.cpp +++ b/src/textures/warptexture.cpp @@ -42,7 +42,7 @@ FWarpTexture::FWarpTexture (FTexture *source, int warptype) -: GenTime (0), SourcePic (source), Pixels (0), Spans (0), Speed (1.f) +: GenTime (0), Speed (1.f), SourcePic (source), Pixels (0), Spans (0) { CopyInfo(source); if (warptype == 2) SetupMultipliers(256, 128); From b29704706023a78c7fd4381d1e90ef74df364fa4 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 5 Jan 2017 15:52:13 +0200 Subject: [PATCH 06/11] Removed useless integer type size expansion Fixed Apple's Clang warnings: absolute value function 'abs' given an argument of type 'long long' but has parameter of type 'int' which may cause truncation of value --- src/gl/hqnx/common.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gl/hqnx/common.h b/src/gl/hqnx/common.h index c3e7005717..fa807df771 100644 --- a/src/gl/hqnx/common.h +++ b/src/gl/hqnx/common.h @@ -48,9 +48,9 @@ static inline uint32_t rgb_to_yuv(uint32_t c) /* Test if there is difference in color */ static inline int yuv_diff(uint32_t yuv1, uint32_t yuv2) { - return (( abs((int64_t)(yuv1 & Ymask) - (int64_t)(yuv2 & Ymask)) > trY ) || - ( abs((int64_t)(yuv1 & Umask) - (int64_t)(yuv2 & Umask)) > trU ) || - ( abs((int64_t)(yuv1 & Vmask) - (int64_t)(yuv2 & Vmask)) > trV ) ); + return (( abs((int32_t)(yuv1 & Ymask) - (int32_t)(yuv2 & Ymask)) > trY ) || + ( abs((int32_t)(yuv1 & Umask) - (int32_t)(yuv2 & Umask)) > trU ) || + ( abs((int32_t)(yuv1 & Vmask) - (int32_t)(yuv2 & Vmask)) > trV ) ); } static inline int Diff(uint32_t c1, uint32_t c2) From 44ad55602d145661944060f18f8437a2b5073f04 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 6 Jan 2017 11:43:27 +0100 Subject: [PATCH 07/11] - got rid of uint32(-1) casts. --- src/gl/dynlights/gl_glow.cpp | 6 +++--- src/p_udmf.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gl/dynlights/gl_glow.cpp b/src/gl/dynlights/gl_glow.cpp index aaf3930e6b..2e324b63e0 100644 --- a/src/gl/dynlights/gl_glow.cpp +++ b/src/gl/dynlights/gl_glow.cpp @@ -125,7 +125,7 @@ int gl_CheckSpriteGlow(sector_t *sector, int lightlevel, const DVector3 &pos) } } } - else if (uint32(-1) != c) + else if (c != ~0u) { bottomglowcolor[0] = c.r / 255.f; bottomglowcolor[1] = c.g / 255.f; @@ -171,7 +171,7 @@ bool gl_GetWallGlow(sector_t *sector, float *topglowcolor, float *bottomglowcolo } } } - else if (uint32(-1) != c) + else if (c != ~0u) { topglowcolor[0] = c.r / 255.f; topglowcolor[1] = c.g / 255.f; @@ -195,7 +195,7 @@ bool gl_GetWallGlow(sector_t *sector, float *topglowcolor, float *bottomglowcolo } } } - else if (uint32(-1) != c) + else if (c != ~0u) { bottomglowcolor[0] = c.r / 255.f; bottomglowcolor[1] = c.g / 255.f; diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 9f920d2254..1650a33b72 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1695,7 +1695,7 @@ public: sec->ceilingplane.set(n.X, n.Y, n.Z, cp[3]); } - if (lightcolor == uint32(-1) && fadecolor == uint32(-1) && desaturation == -1 && fogdensity == -1) + if (lightcolor == ~0u && fadecolor == ~0u && desaturation == -1 && fogdensity == -1) { // [RH] Sectors default to white light with the default fade. // If they are outside (have a sky ceiling), they use the outside fog. @@ -1714,8 +1714,8 @@ public: } else { - if (uint32(-1) == lightcolor) lightcolor = PalEntry(255,255,255); - if (uint32(-1) == fadecolor) + if (lightcolor == ~0u) lightcolor = PalEntry(255,255,255); + if (fadecolor == ~0u) { if (level.outsidefog != 0xff000000 && (sec->GetTexture(sector_t::ceiling) == skyflatnum || (sec->special & 0xff) == Sector_Outside)) fadecolor = level.outsidefog; From b11c8fef57e4475cfb69dc01e9909f3c546b793b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 6 Jan 2017 11:56:17 +0100 Subject: [PATCH 08/11] - renamed a few variables for clarity. --- src/actor.h | 4 ++-- src/gl/scene/gl_bsp.cpp | 2 +- src/gl/scene/gl_sprite.cpp | 2 +- src/p_map.cpp | 24 ++++++++++++------------ src/p_sectors.cpp | 2 +- src/p_setup.cpp | 2 +- src/p_udmf.cpp | 2 +- src/portal.h | 2 +- src/r_defs.h | 2 +- wadsrc/static/zscript/base.txt | 2 +- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/actor.h b/src/actor.h index 5445c92be7..ffe3cc1a41 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1148,8 +1148,8 @@ public: // a linked list of sectors where this object appears struct msecnode_t *touching_sectorlist; // phares 3/14/98 - struct msecnode_t *render_sectorlist; // same for cross-sectorportal rendering - struct portnode_t *render_portallist; // and for cross-lineportal + struct msecnode_t *touching_sectorportallist; // same for cross-sectorportal rendering + struct portnode_t *touching_lineportallist; // and for cross-lineportal struct msecnode_t *touching_rendersectors; // this is the list of sectors that this thing interesects with it's max(radius, renderradius). int validcount; diff --git a/src/gl/scene/gl_bsp.cpp b/src/gl/scene/gl_bsp.cpp index 9e5ea258d7..d646daa53f 100644 --- a/src/gl/scene/gl_bsp.cpp +++ b/src/gl/scene/gl_bsp.cpp @@ -383,7 +383,7 @@ static inline void RenderThings(subsector_t * sub, sector_t * sector) GLRenderer->ProcessSprite(thing, sector, false); } - for (msecnode_t *node = sec->render_thinglist; node; node = node->m_snext) + for (msecnode_t *node = sec->sectorportal_thinglist; node; node = node->m_snext) { AActor *thing = node->m_thing; FIntCVar *cvar = thing->GetClass()->distancecheck; diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 102337eccc..7ed4199a13 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -1189,7 +1189,7 @@ void gl_RenderActorsInPortal(FGLLinePortal *glport) if (port2 != nullptr && port->mDestination == port2->mOrigin && port->mOrigin == port2->mDestination) { - for (portnode_t *node = port->render_thinglist; node != nullptr; node = node->m_snext) + for (portnode_t *node = port->lineportal_thinglist; node != nullptr; node = node->m_snext) { AActor *th = node->m_thing; diff --git a/src/p_map.cpp b/src/p_map.cpp index 5bbb9c3f92..bb3f63f4ed 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -6728,7 +6728,7 @@ portnode_t *P_DelPortalnode(portnode_t *node) if (sp) sp->m_snext = sn; else - node->m_portal->render_thinglist = sn; + node->m_portal->lineportal_thinglist = sn; if (sn) sn->m_sprev = sp; @@ -6770,10 +6770,10 @@ portnode_t *P_AddPortalnode(FLinePortal *s, AActor *thing, portnode_t *nextnode) // Add new node at head of portal thread starting at s->touching_thinglist node->m_sprev = NULL; // prev node on portal thread - node->m_snext = s->render_thinglist; // next node on portal thread - if (s->render_thinglist) + node->m_snext = s->lineportal_thinglist; // next node on portal thread + if (s->lineportal_thinglist) node->m_snext->m_sprev = node; - s->render_thinglist = node; + s->lineportal_thinglist = node; return node; } @@ -6805,7 +6805,7 @@ void AActor::UpdateRenderSectorList() if (p.mType == PORTT_VISUAL) continue; if (bb.inRange(p.mOrigin) && bb.BoxOnLineSide(p.mOrigin)) { - render_portallist = P_AddPortalnode(&p, this, render_portallist); + touching_lineportallist = P_AddPortalnode(&p, this, touching_lineportallist); } } } @@ -6821,7 +6821,7 @@ void AActor::UpdateRenderSectorList() lasth = planeh; DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::ceiling); sec = P_PointInSector(newpos); - render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist); + touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist); } sec = Sector; lasth = FLT_MAX; @@ -6833,25 +6833,25 @@ void AActor::UpdateRenderSectorList() lasth = planeh; DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::floor); sec = P_PointInSector(newpos); - render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist); + touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist); } } } void AActor::ClearRenderSectorList() { - msecnode_t *node = render_sectorlist; + msecnode_t *node = touching_sectorportallist; while (node) - node = P_DelSecnode(node, §or_t::render_thinglist); - render_sectorlist = NULL; + node = P_DelSecnode(node, §or_t::sectorportal_thinglist); + touching_sectorportallist = NULL; } void AActor::ClearRenderLineList() { - portnode_t *node = render_portallist; + portnode_t *node = touching_lineportallist; while (node) node = P_DelPortalnode(node); - render_portallist = NULL; + touching_lineportallist = NULL; } diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 2850f22645..c2488b9988 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -1337,7 +1337,7 @@ DEFINE_FIELD_X(Sector, sector_t, bottommap) DEFINE_FIELD_X(Sector, sector_t, midmap) DEFINE_FIELD_X(Sector, sector_t, topmap) DEFINE_FIELD_X(Sector, sector_t, touching_thinglist) -DEFINE_FIELD_X(Sector, sector_t, render_thinglist) +DEFINE_FIELD_X(Sector, sector_t, sectorportal_thinglist) DEFINE_FIELD_X(Sector, sector_t, gravity) DEFINE_FIELD_X(Sector, sector_t, damagetype) DEFINE_FIELD_X(Sector, sector_t, damageamount) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index a1422236ad..00e854c54a 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1508,7 +1508,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex) tagManager.AddSectorTag(i, LittleShort(ms->tag)); ss->thinglist = nullptr; ss->touching_thinglist = nullptr; // phares 3/14/98 - ss->render_thinglist = nullptr; + ss->sectorportal_thinglist = nullptr; ss->touching_renderthings = nullptr; ss->seqType = defSeqType; ss->SeqName = NAME_None; diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 1650a33b72..256385c65d 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1297,7 +1297,7 @@ public: sec->SetAlpha(sector_t::ceiling, 1.); sec->thinglist = nullptr; sec->touching_thinglist = nullptr; // phares 3/14/98 - sec->render_thinglist = nullptr; + sec->sectorportal_thinglist = nullptr; sec->touching_renderthings = nullptr; sec->seqType = (level.flags & LEVEL_SNDSEQTOTALCTRL) ? 0 : -1; sec->nextsec = -1; //jff 2/26/98 add fields to support locking out diff --git a/src/portal.h b/src/portal.h index 44d636e4bd..f5c8f8c885 100644 --- a/src/portal.h +++ b/src/portal.h @@ -191,7 +191,7 @@ struct FLinePortal DAngle mAngleDiff; double mSinRot; double mCosRot; - portnode_t *render_thinglist; + portnode_t *lineportal_thinglist; }; extern TArray linePortals; diff --git a/src/r_defs.h b/src/r_defs.h index c8a6cc96c8..44f0428200 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -1049,7 +1049,7 @@ public: // list of mobjs that are at least partially in the sector // thinglist is a subset of touching_thinglist struct msecnode_t *touching_thinglist; // phares 3/14/98 - struct msecnode_t *render_thinglist; // for cross-portal rendering. + struct msecnode_t *sectorportal_thinglist; // for cross-portal rendering. struct msecnode_t *touching_renderthings; // this is used to allow wide things to be rendered not only from their main sector. double gravity; // [RH] Sector gravity (1.0 is normal) diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 38fa79b768..23a8305375 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -283,7 +283,7 @@ struct Sector native native uint bottommap, midmap, topmap; //struct msecnode_t *touching_thinglist; - //struct msecnode_t *render_thinglist; + //struct msecnode_t *sectorportal_thinglist; native double gravity; native Name damagetype; From ed25cf61c532eb08e685100704d55c17bdc32710 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 6 Jan 2017 12:54:01 +0100 Subject: [PATCH 09/11] - moved the msecnode code to its own file. Note that this originates from Boom so it needs to keep the Doom license. --- src/CMakeLists.txt | 1 + src/p_blockmap.h | 7 + src/p_local.h | 4 - src/p_map.cpp | 407 ------------------------------------------ src/p_secnodes.cpp | 434 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 442 insertions(+), 411 deletions(-) create mode 100644 src/p_secnodes.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 64e865a215..5d5d52c0f3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1106,6 +1106,7 @@ set (PCH_SOURCES p_pusher.cpp p_saveg.cpp p_scroll.cpp + p_secnodes.cpp p_sectors.cpp p_setup.cpp p_sight.cpp diff --git a/src/p_blockmap.h b/src/p_blockmap.h index b2cee1bdda..e6474b4ea2 100644 --- a/src/p_blockmap.h +++ b/src/p_blockmap.h @@ -31,6 +31,13 @@ extern double bmaporgx; extern double bmaporgy; // origin of block map extern FBlockNode** blocklinks; // for thing chains + // mapblocks are used to check movement + // against lines and things +enum +{ + MAPBLOCKUNITS = 128 +}; + inline int GetBlockX(double xpos) { return int((xpos - bmaporgx) / MAPBLOCKUNITS); diff --git a/src/p_local.h b/src/p_local.h index c66792549c..93875df2f8 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -48,10 +48,6 @@ struct FTranslatedLineTarget; #define BONUSADD 6 -// mapblocks are used to check movement -// against lines and things -#define MAPBLOCKUNITS 128 - // Inspired by Maes extern int bmapnegx; extern int bmapnegy; diff --git a/src/p_map.cpp b/src/p_map.cpp index bb3f63f4ed..7f6a47b66f 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -6448,413 +6448,6 @@ bool P_ChangeSector(sector_t *sector, int crunch, double amt, int floorOrCeil, b return cpos.nofit; } -//============================================================================= -// phares 3/21/98 -// -// Maintain a freelist of msecnode_t's to reduce memory allocs and frees. -//============================================================================= - -msecnode_t *headsecnode = NULL; - -//============================================================================= -// -// P_GetSecnode -// -// Retrieve a node from the freelist. The calling routine -// should make sure it sets all fields properly. -// -//============================================================================= - -msecnode_t *P_GetSecnode() -{ - msecnode_t *node; - - if (headsecnode) - { - node = headsecnode; - headsecnode = headsecnode->m_snext; - } - else - { - node = (msecnode_t *)M_Malloc(sizeof(*node)); - } - return node; -} - -//============================================================================= -// -// P_PutSecnode -// -// Returns a node to the freelist. -// -//============================================================================= - -void P_PutSecnode(msecnode_t *node) -{ - node->m_snext = headsecnode; - headsecnode = node; -} - -//============================================================================= -// phares 3/16/98 -// -// P_AddSecnode -// -// Searches the current list to see if this sector is -// already there. If not, it adds a sector node at the head of the list of -// sectors this object appears in. This is called when creating a list of -// nodes that will get linked in later. Returns a pointer to the new node. -// -//============================================================================= - -msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist) -{ - msecnode_t *node; - - if (s == 0) - { - I_FatalError("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars()); - } - - node = nextnode; - while (node) - { - if (node->m_sector == s) // Already have a node for this sector? - { - node->m_thing = thing; // Yes. Setting m_thing says 'keep it'. - return nextnode; - } - node = node->m_tnext; - } - - // Couldn't find an existing node for this sector. Add one at the head - // of the list. - - node = P_GetSecnode(); - - // killough 4/4/98, 4/7/98: mark new nodes unvisited. - node->visited = 0; - - node->m_sector = s; // sector - node->m_thing = thing; // mobj - node->m_tprev = NULL; // prev node on Thing thread - node->m_tnext = nextnode; // next node on Thing thread - if (nextnode) - nextnode->m_tprev = node; // set back link on Thing - - // Add new node at head of sector thread starting at s->touching_thinglist - - node->m_sprev = NULL; // prev node on sector thread - node->m_snext = sec_thinglist; // next node on sector thread - if (sec_thinglist) - node->m_snext->m_sprev = node; - sec_thinglist = node; - return node; -} - -//============================================================================= -// -// P_DelSecnode -// -// Deletes a sector node from the list of -// sectors this object appears in. Returns a pointer to the next node -// on the linked list, or NULL. -// -//============================================================================= - -msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead) -{ - msecnode_t* tp; // prev node on thing thread - msecnode_t* tn; // next node on thing thread - msecnode_t* sp; // prev node on sector thread - msecnode_t* sn; // next node on sector thread - - if (node) - { - // Unlink from the Thing thread. The Thing thread begins at - // sector_list and not from AActor->touching_sectorlist. - - tp = node->m_tprev; - tn = node->m_tnext; - if (tp) - tp->m_tnext = tn; - if (tn) - tn->m_tprev = tp; - - // Unlink from the sector thread. This thread begins at - // sector_t->touching_thinglist. - - sp = node->m_sprev; - sn = node->m_snext; - if (sp) - sp->m_snext = sn; - else - node->m_sector->*listhead = sn; - if (sn) - sn->m_sprev = sp; - - // Return this node to the freelist - - P_PutSecnode(node); - return tn; - } - return NULL; -} // phares 3/13/98 - -//============================================================================= -// -// P_DelSeclist -// -// Delete an entire sector list -// -//============================================================================= - -void P_DelSeclist(msecnode_t *node, msecnode_t *sector_t::*sechead) -{ - while (node) - node = P_DelSecnode(node, sechead); -} - -//============================================================================= -// phares 3/14/98 -// -// P_CreateSecNodeList -// -// Alters/creates the sector_list that shows what sectors the object resides in -// -//============================================================================= - -msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead) -{ - msecnode_t *node; - - // First, clear out the existing m_thing fields. As each node is - // added or verified as needed, m_thing will be set properly. When - // finished, delete all nodes where m_thing is still NULL. These - // represent the sectors the Thing has vacated. - - node = sector_list; - while (node) - { - node->m_thing = NULL; - node = node->m_tnext; - } - - FBoundingBox box(thing->X(), thing->Y(), radius); - FBlockLinesIterator it(box); - line_t *ld; - - while ((ld = it.Next())) - { - if (!box.inRange(ld) || box.BoxOnLineSide(ld) != -1) - continue; - - // This line crosses through the object. - - // Collect the sector(s) from the line and add to the - // sector_list you're examining. If the Thing ends up being - // allowed to move to this position, then the sector_list - // will be attached to the Thing's AActor at touching_sectorlist. - - sector_list = P_AddSecnode(ld->frontsector, thing, sector_list, ld->frontsector->*seclisthead); - - // Don't assume all lines are 2-sided, since some Things - // like MT_TFOG are allowed regardless of whether their radius takes - // them beyond an impassable linedef. - - // killough 3/27/98, 4/4/98: - // Use sidedefs instead of 2s flag to determine two-sidedness. - - if (ld->backsector) - sector_list = P_AddSecnode(ld->backsector, thing, sector_list, ld->backsector->*seclisthead); - } - - // Add the sector of the (x,y) point to sector_list. - - sector_list = P_AddSecnode(thing->Sector, thing, sector_list, thing->Sector->*seclisthead); - - // Now delete any nodes that won't be used. These are the ones where - // m_thing is still NULL. - - node = sector_list; - while (node) - { - if (node->m_thing == NULL) - { - if (node == sector_list) - sector_list = node->m_tnext; - node = P_DelSecnode(node, seclisthead); - } - else - { - node = node->m_tnext; - } - } - return sector_list; -} - -//============================================================================= -// -// P_DelPortalnode -// -// Same for line portal nodes -// -//============================================================================= - -portnode_t *P_DelPortalnode(portnode_t *node) -{ - portnode_t* tp; // prev node on thing thread - portnode_t* tn; // next node on thing thread - portnode_t* sp; // prev node on sector thread - portnode_t* sn; // next node on sector thread - - if (node) - { - // Unlink from the Thing thread. The Thing thread begins at - // sector_list and not from AActor->touching_sectorlist. - - tp = node->m_tprev; - tn = node->m_tnext; - if (tp) - tp->m_tnext = tn; - if (tn) - tn->m_tprev = tp; - - // Unlink from the sector thread. This thread begins at - // sector_t->touching_thinglist. - - sp = node->m_sprev; - sn = node->m_snext; - if (sp) - sp->m_snext = sn; - else - node->m_portal->lineportal_thinglist = sn; - if (sn) - sn->m_sprev = sp; - - // Return this node to the freelist (use the same one as for msecnodes, since both types are the same size.) - P_PutSecnode(reinterpret_cast(node)); - return tn; - } - return NULL; -} - - -//============================================================================= -// -// P_AddPortalnode -// -//============================================================================= - -portnode_t *P_AddPortalnode(FLinePortal *s, AActor *thing, portnode_t *nextnode) -{ - portnode_t *node; - - if (s == 0) - { - I_FatalError("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars()); - } - - node = reinterpret_cast(P_GetSecnode()); - - // killough 4/4/98, 4/7/98: mark new nodes unvisited. - node->visited = 0; - - node->m_portal = s; // portal - node->m_thing = thing; // mobj - node->m_tprev = NULL; // prev node on Thing thread - node->m_tnext = nextnode; // next node on Thing thread - if (nextnode) - nextnode->m_tprev = node; // set back link on Thing - - // Add new node at head of portal thread starting at s->touching_thinglist - - node->m_sprev = NULL; // prev node on portal thread - node->m_snext = s->lineportal_thinglist; // next node on portal thread - if (s->lineportal_thinglist) - node->m_snext->m_sprev = node; - s->lineportal_thinglist = node; - return node; -} - - -//========================================================================== -// -// Handle the lists used to render actors from other portal areas -// -//========================================================================== - -void AActor::UpdateRenderSectorList() -{ - static const double SPRITE_SPACE = 64.; - if (Pos() != OldRenderPos && !(flags & MF_NOSECTOR)) - { - // Only check if the map contains line portals - ClearRenderLineList(); - if (PortalBlockmap.containsLines && Pos().XY() != OldRenderPos.XY()) - { - int bx = GetBlockX(X()); - int by = GetBlockY(Y()); - FBoundingBox bb(X(), Y(), MIN(radius*1.5, 128.)); // Don't go further than 128 map units, even for large actors - // Are there any portals near the actor's position? - if (bx >= 0 && by >= 0 && bx < bmapwidth && by < bmapheight && PortalBlockmap(bx, by).neighborContainsLines) - { - // Go through the entire list. In most cases this is faster than setting up a blockmap iterator - for (auto &p : linePortals) - { - if (p.mType == PORTT_VISUAL) continue; - if (bb.inRange(p.mOrigin) && bb.BoxOnLineSide(p.mOrigin)) - { - touching_lineportallist = P_AddPortalnode(&p, this, touching_lineportallist); - } - } - } - } - sector_t *sec = Sector; - double lasth = -FLT_MAX; - ClearRenderSectorList(); - while (!sec->PortalBlocksMovement(sector_t::ceiling)) - { - double planeh = sec->GetPortalPlaneZ(sector_t::ceiling); - if (planeh <= lasth) break; // broken setup. - if (Top() + SPRITE_SPACE < planeh) break; - lasth = planeh; - DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::ceiling); - sec = P_PointInSector(newpos); - touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist); - } - sec = Sector; - lasth = FLT_MAX; - while (!sec->PortalBlocksMovement(sector_t::floor)) - { - double planeh = sec->GetPortalPlaneZ(sector_t::floor); - if (planeh >= lasth) break; // broken setup. - if (Z() - SPRITE_SPACE > planeh) break; - lasth = planeh; - DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::floor); - sec = P_PointInSector(newpos); - touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist); - } - } -} - -void AActor::ClearRenderSectorList() -{ - msecnode_t *node = touching_sectorportallist; - while (node) - node = P_DelSecnode(node, §or_t::sectorportal_thinglist); - touching_sectorportallist = NULL; -} - -void AActor::ClearRenderLineList() -{ - portnode_t *node = touching_lineportallist; - while (node) - node = P_DelPortalnode(node); - touching_lineportallist = NULL; -} - - //========================================================================== // // diff --git a/src/p_secnodes.cpp b/src/p_secnodes.cpp new file mode 100644 index 0000000000..14d354a7f8 --- /dev/null +++ b/src/p_secnodes.cpp @@ -0,0 +1,434 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// $Id:$ +// +// Copyright (C) 1998-1996 by id Software, Inc. +// +// This source is available for distribution and/or modification +// only under the terms of the DOOM Source Code License as +// published by id Software. All rights reserved. +// +// The source is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License +// for more details. +// +// $Log:$ +// +// DESCRIPTION: +// Boom secnodes +// +//----------------------------------------------------------------------------- + +#include "r_state.h" +#include "p_maputl.h" +#include "p_blockmap.h" + +//============================================================================= +// phares 3/21/98 +// +// Maintain a freelist of msecnode_t's to reduce memory allocs and frees. +//============================================================================= + +msecnode_t *headsecnode = NULL; + +//============================================================================= +// +// P_GetSecnode +// +// Retrieve a node from the freelist. The calling routine +// should make sure it sets all fields properly. +// +//============================================================================= + +msecnode_t *P_GetSecnode() +{ + msecnode_t *node; + + if (headsecnode) + { + node = headsecnode; + headsecnode = headsecnode->m_snext; + } + else + { + node = (msecnode_t *)M_Malloc(sizeof(*node)); + } + return node; +} + +//============================================================================= +// +// P_PutSecnode +// +// Returns a node to the freelist. +// +//============================================================================= + +void P_PutSecnode(msecnode_t *node) +{ + node->m_snext = headsecnode; + headsecnode = node; +} + +//============================================================================= +// phares 3/16/98 +// +// P_AddSecnode +// +// Searches the current list to see if this sector is +// already there. If not, it adds a sector node at the head of the list of +// sectors this object appears in. This is called when creating a list of +// nodes that will get linked in later. Returns a pointer to the new node. +// +//============================================================================= + +msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist) +{ + msecnode_t *node; + + if (s == 0) + { + I_FatalError("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars()); + } + + node = nextnode; + while (node) + { + if (node->m_sector == s) // Already have a node for this sector? + { + node->m_thing = thing; // Yes. Setting m_thing says 'keep it'. + return nextnode; + } + node = node->m_tnext; + } + + // Couldn't find an existing node for this sector. Add one at the head + // of the list. + + node = P_GetSecnode(); + + // killough 4/4/98, 4/7/98: mark new nodes unvisited. + node->visited = 0; + + node->m_sector = s; // sector + node->m_thing = thing; // mobj + node->m_tprev = NULL; // prev node on Thing thread + node->m_tnext = nextnode; // next node on Thing thread + if (nextnode) + nextnode->m_tprev = node; // set back link on Thing + + // Add new node at head of sector thread starting at s->touching_thinglist + + node->m_sprev = NULL; // prev node on sector thread + node->m_snext = sec_thinglist; // next node on sector thread + if (sec_thinglist) + node->m_snext->m_sprev = node; + sec_thinglist = node; + return node; +} + +//============================================================================= +// +// P_DelSecnode +// +// Deletes a sector node from the list of +// sectors this object appears in. Returns a pointer to the next node +// on the linked list, or NULL. +// +//============================================================================= + +msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead) +{ + msecnode_t* tp; // prev node on thing thread + msecnode_t* tn; // next node on thing thread + msecnode_t* sp; // prev node on sector thread + msecnode_t* sn; // next node on sector thread + + if (node) + { + // Unlink from the Thing thread. The Thing thread begins at + // sector_list and not from AActor->touching_sectorlist. + + tp = node->m_tprev; + tn = node->m_tnext; + if (tp) + tp->m_tnext = tn; + if (tn) + tn->m_tprev = tp; + + // Unlink from the sector thread. This thread begins at + // sector_t->touching_thinglist. + + sp = node->m_sprev; + sn = node->m_snext; + if (sp) + sp->m_snext = sn; + else + node->m_sector->*listhead = sn; + if (sn) + sn->m_sprev = sp; + + // Return this node to the freelist + + P_PutSecnode(node); + return tn; + } + return NULL; +} // phares 3/13/98 + +//============================================================================= +// +// P_DelSeclist +// +// Delete an entire sector list +// +//============================================================================= + +void P_DelSeclist(msecnode_t *node, msecnode_t *sector_t::*sechead) +{ + while (node) + node = P_DelSecnode(node, sechead); +} + +//============================================================================= +// phares 3/14/98 +// +// P_CreateSecNodeList +// +// Alters/creates the sector_list that shows what sectors the object resides in +// +//============================================================================= + +msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead) +{ + msecnode_t *node; + + // First, clear out the existing m_thing fields. As each node is + // added or verified as needed, m_thing will be set properly. When + // finished, delete all nodes where m_thing is still NULL. These + // represent the sectors the Thing has vacated. + + node = sector_list; + while (node) + { + node->m_thing = NULL; + node = node->m_tnext; + } + + FBoundingBox box(thing->X(), thing->Y(), radius); + FBlockLinesIterator it(box); + line_t *ld; + + while ((ld = it.Next())) + { + if (!box.inRange(ld) || box.BoxOnLineSide(ld) != -1) + continue; + + // This line crosses through the object. + + // Collect the sector(s) from the line and add to the + // sector_list you're examining. If the Thing ends up being + // allowed to move to this position, then the sector_list + // will be attached to the Thing's AActor at touching_sectorlist. + + sector_list = P_AddSecnode(ld->frontsector, thing, sector_list, ld->frontsector->*seclisthead); + + // Don't assume all lines are 2-sided, since some Things + // like MT_TFOG are allowed regardless of whether their radius takes + // them beyond an impassable linedef. + + // killough 3/27/98, 4/4/98: + // Use sidedefs instead of 2s flag to determine two-sidedness. + + if (ld->backsector) + sector_list = P_AddSecnode(ld->backsector, thing, sector_list, ld->backsector->*seclisthead); + } + + // Add the sector of the (x,y) point to sector_list. + + sector_list = P_AddSecnode(thing->Sector, thing, sector_list, thing->Sector->*seclisthead); + + // Now delete any nodes that won't be used. These are the ones where + // m_thing is still NULL. + + node = sector_list; + while (node) + { + if (node->m_thing == NULL) + { + if (node == sector_list) + sector_list = node->m_tnext; + node = P_DelSecnode(node, seclisthead); + } + else + { + node = node->m_tnext; + } + } + return sector_list; +} + +//============================================================================= +// +// P_DelPortalnode +// +// Same for line portal nodes +// +//============================================================================= + +portnode_t *P_DelPortalnode(portnode_t *node) +{ + portnode_t* tp; // prev node on thing thread + portnode_t* tn; // next node on thing thread + portnode_t* sp; // prev node on sector thread + portnode_t* sn; // next node on sector thread + + if (node) + { + // Unlink from the Thing thread. The Thing thread begins at + // sector_list and not from AActor->touching_sectorlist. + + tp = node->m_tprev; + tn = node->m_tnext; + if (tp) + tp->m_tnext = tn; + if (tn) + tn->m_tprev = tp; + + // Unlink from the sector thread. This thread begins at + // sector_t->touching_thinglist. + + sp = node->m_sprev; + sn = node->m_snext; + if (sp) + sp->m_snext = sn; + else + node->m_portal->lineportal_thinglist = sn; + if (sn) + sn->m_sprev = sp; + + // Return this node to the freelist (use the same one as for msecnodes, since both types are the same size.) + P_PutSecnode(reinterpret_cast(node)); + return tn; + } + return NULL; +} + + +//============================================================================= +// +// P_AddPortalnode +// +//============================================================================= + +portnode_t *P_AddPortalnode(FLinePortal *s, AActor *thing, portnode_t *nextnode) +{ + portnode_t *node; + + if (s == 0) + { + I_FatalError("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars()); + } + + node = reinterpret_cast(P_GetSecnode()); + + // killough 4/4/98, 4/7/98: mark new nodes unvisited. + node->visited = 0; + + node->m_portal = s; // portal + node->m_thing = thing; // mobj + node->m_tprev = NULL; // prev node on Thing thread + node->m_tnext = nextnode; // next node on Thing thread + if (nextnode) + nextnode->m_tprev = node; // set back link on Thing + + // Add new node at head of portal thread starting at s->touching_thinglist + + node->m_sprev = NULL; // prev node on portal thread + node->m_snext = s->lineportal_thinglist; // next node on portal thread + if (s->lineportal_thinglist) + node->m_snext->m_sprev = node; + s->lineportal_thinglist = node; + return node; +} + + +//========================================================================== +// +// Handle the lists used to render actors from other portal areas +// +//========================================================================== + +void AActor::UpdateRenderSectorList() +{ + static const double SPRITE_SPACE = 64.; + if (Pos() != OldRenderPos && !(flags & MF_NOSECTOR)) + { + // Only check if the map contains line portals + ClearRenderLineList(); + if (PortalBlockmap.containsLines && Pos().XY() != OldRenderPos.XY()) + { + int bx = GetBlockX(X()); + int by = GetBlockY(Y()); + FBoundingBox bb(X(), Y(), MIN(radius*1.5, 128.)); // Don't go further than 128 map units, even for large actors + // Are there any portals near the actor's position? + if (bx >= 0 && by >= 0 && bx < bmapwidth && by < bmapheight && PortalBlockmap(bx, by).neighborContainsLines) + { + // Go through the entire list. In most cases this is faster than setting up a blockmap iterator + for (auto &p : linePortals) + { + if (p.mType == PORTT_VISUAL) continue; + if (bb.inRange(p.mOrigin) && bb.BoxOnLineSide(p.mOrigin)) + { + touching_lineportallist = P_AddPortalnode(&p, this, touching_lineportallist); + } + } + } + } + sector_t *sec = Sector; + double lasth = -FLT_MAX; + ClearRenderSectorList(); + while (!sec->PortalBlocksMovement(sector_t::ceiling)) + { + double planeh = sec->GetPortalPlaneZ(sector_t::ceiling); + if (planeh <= lasth) break; // broken setup. + if (Top() + SPRITE_SPACE < planeh) break; + lasth = planeh; + DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::ceiling); + sec = P_PointInSector(newpos); + touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist); + } + sec = Sector; + lasth = FLT_MAX; + while (!sec->PortalBlocksMovement(sector_t::floor)) + { + double planeh = sec->GetPortalPlaneZ(sector_t::floor); + if (planeh >= lasth) break; // broken setup. + if (Z() - SPRITE_SPACE > planeh) break; + lasth = planeh; + DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::floor); + sec = P_PointInSector(newpos); + touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist); + } + } +} + +void AActor::ClearRenderSectorList() +{ + msecnode_t *node = touching_sectorportallist; + while (node) + node = P_DelSecnode(node, §or_t::sectorportal_thinglist); + touching_sectorportallist = NULL; +} + +void AActor::ClearRenderLineList() +{ + portnode_t *node = touching_lineportallist; + while (node) + node = P_DelPortalnode(node); + touching_lineportallist = NULL; +} + + From c52bc06e9bdbacb0a9f80e9caa889438437d904f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 6 Jan 2017 13:09:58 +0100 Subject: [PATCH 10/11] - use a memory arena to allocate msecnodes. These are rather small and extremely frequently allocated, so they are prime candidates for memory arena, because it not only avoids fragmentation and internal overhead due to mass allocation of small memory blocks but it also makes it a lot faster to free the memory when finishing a level. --- src/p_secnodes.cpp | 5 ++++- src/p_setup.cpp | 15 ++++----------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/p_secnodes.cpp b/src/p_secnodes.cpp index 14d354a7f8..38a9a5babd 100644 --- a/src/p_secnodes.cpp +++ b/src/p_secnodes.cpp @@ -24,6 +24,7 @@ #include "r_state.h" #include "p_maputl.h" #include "p_blockmap.h" +#include "memarena.h" //============================================================================= // phares 3/21/98 @@ -32,6 +33,7 @@ //============================================================================= msecnode_t *headsecnode = NULL; +FMemArena secnodearena; //============================================================================= // @@ -53,7 +55,8 @@ msecnode_t *P_GetSecnode() } else { - node = (msecnode_t *)M_Malloc(sizeof(*node)); + node = + node = (msecnode_t *)secnodearena.Alloc(sizeof(*node)); } return node; } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 00e854c54a..88694a8cfa 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3552,6 +3552,7 @@ void P_FreeLevelData () P_ClearUDMFKeys(); } +extern FMemArena secnodearena; extern msecnode_t *headsecnode; void P_FreeExtraLevelData() @@ -3569,19 +3570,11 @@ void P_FreeExtraLevelData() } FBlockNode::FreeBlocks = NULL; } - { - msecnode_t *node = headsecnode; - - while (node != NULL) - { - msecnode_t *next = node->m_snext; - M_Free (node); - node = next; - } - headsecnode = NULL; - } + secnodearena.FreeAllBlocks(); + headsecnode = nullptr; } + // // P_SetupLevel // From 62ea83a35ac893dd1062c793e1bbdd72fa16b8e3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 6 Jan 2017 15:06:17 +0100 Subject: [PATCH 11/11] - let the prediction code handle all 4 threaded lists an actor gets linked into. This is mostly a straight refactoring of the existing code to work independently of specific member variables in the involved classes, using a bit of template magic to avoid redundancy and moving the work code into subfunctions. It still needs some testing to see if it a) helps fix the crash issues and b) doesn't break anything- --- src/p_local.h | 12 ++- src/p_secnodes.cpp | 77 +++++++++-------- src/p_user.cpp | 209 ++++++++++++++++++++++++++------------------- src/r_defs.h | 2 +- 4 files changed, 173 insertions(+), 127 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 93875df2f8..6bb65ad977 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -38,9 +38,11 @@ class APlayerPawn; struct line_t; struct sector_t; struct msecnode_t; +struct portnode_t; struct secplane_t; struct FCheckPosition; struct FTranslatedLineTarget; +struct FLinePortal; #include @@ -389,8 +391,14 @@ int P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, FName damageType, int flags, int fulldamagedistance=0); void P_DelSeclist(msecnode_t *, msecnode_t *sector_t::*seclisthead); -msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist); -msecnode_t* P_DelSecnode(msecnode_t *, msecnode_t *sector_t::*head); +void P_DelSeclist(portnode_t *, portnode_t *FLinePortal::*seclisthead); + +template +nodetype *P_AddSecnode(linktype *s, AActor *thing, nodetype *nextnode, nodetype *&sec_thinglist); + +template +nodetype* P_DelSecnode(nodetype *, nodetype *linktype::*head); + msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead); double P_GetMoveFactor(const AActor *mo, double *frictionp); // phares 3/6/98 double P_GetFriction(const AActor *mo, double *frictionfactor); diff --git a/src/p_secnodes.cpp b/src/p_secnodes.cpp index 38a9a5babd..8edfc0c700 100644 --- a/src/p_secnodes.cpp +++ b/src/p_secnodes.cpp @@ -32,7 +32,7 @@ // Maintain a freelist of msecnode_t's to reduce memory allocs and frees. //============================================================================= -msecnode_t *headsecnode = NULL; +msecnode_t *headsecnode = nullptr; FMemArena secnodearena; //============================================================================= @@ -55,7 +55,6 @@ msecnode_t *P_GetSecnode() } else { - node = node = (msecnode_t *)secnodearena.Alloc(sizeof(*node)); } return node; @@ -87,9 +86,10 @@ void P_PutSecnode(msecnode_t *node) // //============================================================================= -msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist) +template +nodetype *P_AddSecnode(linktype *s, AActor *thing, nodetype *nextnode, nodetype *&sec_thinglist) { - msecnode_t *node; + nodetype *node; if (s == 0) { @@ -110,21 +110,21 @@ msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecn // Couldn't find an existing node for this sector. Add one at the head // of the list. - node = P_GetSecnode(); + node = (nodetype*)P_GetSecnode(); // killough 4/4/98, 4/7/98: mark new nodes unvisited. node->visited = 0; node->m_sector = s; // sector node->m_thing = thing; // mobj - node->m_tprev = NULL; // prev node on Thing thread + node->m_tprev = nullptr; // prev node on Thing thread node->m_tnext = nextnode; // next node on Thing thread if (nextnode) nextnode->m_tprev = node; // set back link on Thing // Add new node at head of sector thread starting at s->touching_thinglist - node->m_sprev = NULL; // prev node on sector thread + node->m_sprev = nullptr; // prev node on sector thread node->m_snext = sec_thinglist; // next node on sector thread if (sec_thinglist) node->m_snext->m_sprev = node; @@ -132,22 +132,26 @@ msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecn return node; } +template msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist); +template portnode_t *P_AddSecnode(FLinePortal *s, AActor *thing, portnode_t *nextnode, portnode_t *&sec_thinglist); + //============================================================================= // // P_DelSecnode // // Deletes a sector node from the list of // sectors this object appears in. Returns a pointer to the next node -// on the linked list, or NULL. +// on the linked list, or nullptr. // //============================================================================= -msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead) +template +nodetype *P_DelSecnode(nodetype *node, nodetype *linktype::*listhead) { - msecnode_t* tp; // prev node on thing thread - msecnode_t* tn; // next node on thing thread - msecnode_t* sp; // prev node on sector thread - msecnode_t* sn; // next node on sector thread + nodetype* tp; // prev node on thing thread + nodetype* tn; // next node on thing thread + nodetype* sp; // prev node on sector thread + nodetype* sn; // next node on sector thread if (node) { @@ -175,12 +179,15 @@ msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead) // Return this node to the freelist - P_PutSecnode(node); + P_PutSecnode((msecnode_t*)node); return tn; } - return NULL; + return nullptr; } // phares 3/13/98 +template msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead); +template portnode_t *P_DelSecnode(portnode_t *node, portnode_t *FLinePortal::*listhead); + //============================================================================= // // P_DelSeclist @@ -195,6 +202,13 @@ void P_DelSeclist(msecnode_t *node, msecnode_t *sector_t::*sechead) node = P_DelSecnode(node, sechead); } +void P_DelSeclist(portnode_t *node, portnode_t *FLinePortal::*sechead) +{ + while (node) + node = P_DelSecnode(node, sechead); +} + + //============================================================================= // phares 3/14/98 // @@ -210,13 +224,13 @@ msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector // First, clear out the existing m_thing fields. As each node is // added or verified as needed, m_thing will be set properly. When - // finished, delete all nodes where m_thing is still NULL. These + // finished, delete all nodes where m_thing is still nullptr. These // represent the sectors the Thing has vacated. node = sector_list; while (node) { - node->m_thing = NULL; + node->m_thing = nullptr; node = node->m_tnext; } @@ -254,12 +268,12 @@ msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector sector_list = P_AddSecnode(thing->Sector, thing, sector_list, thing->Sector->*seclisthead); // Now delete any nodes that won't be used. These are the ones where - // m_thing is still NULL. + // m_thing is still nullptr. node = sector_list; while (node) { - if (node->m_thing == NULL) + if (node->m_thing == nullptr) { if (node == sector_list) sector_list = node->m_tnext; @@ -308,7 +322,7 @@ portnode_t *P_DelPortalnode(portnode_t *node) if (sp) sp->m_snext = sn; else - node->m_portal->lineportal_thinglist = sn; + node->m_sector->lineportal_thinglist = sn; if (sn) sn->m_sprev = sp; @@ -316,7 +330,7 @@ portnode_t *P_DelPortalnode(portnode_t *node) P_PutSecnode(reinterpret_cast(node)); return tn; } - return NULL; + return nullptr; } @@ -340,16 +354,16 @@ portnode_t *P_AddPortalnode(FLinePortal *s, AActor *thing, portnode_t *nextnode) // killough 4/4/98, 4/7/98: mark new nodes unvisited. node->visited = 0; - node->m_portal = s; // portal + node->m_sector = s; // portal node->m_thing = thing; // mobj - node->m_tprev = NULL; // prev node on Thing thread + node->m_tprev = nullptr; // prev node on Thing thread node->m_tnext = nextnode; // next node on Thing thread if (nextnode) nextnode->m_tprev = node; // set back link on Thing // Add new node at head of portal thread starting at s->touching_thinglist - node->m_sprev = NULL; // prev node on portal thread + node->m_sprev = nullptr; // prev node on portal thread node->m_snext = s->lineportal_thinglist; // next node on portal thread if (s->lineportal_thinglist) node->m_snext->m_sprev = node; @@ -357,7 +371,6 @@ portnode_t *P_AddPortalnode(FLinePortal *s, AActor *thing, portnode_t *nextnode) return node; } - //========================================================================== // // Handle the lists used to render actors from other portal areas @@ -420,18 +433,12 @@ void AActor::UpdateRenderSectorList() void AActor::ClearRenderSectorList() { - msecnode_t *node = touching_sectorportallist; - while (node) - node = P_DelSecnode(node, §or_t::sectorportal_thinglist); - touching_sectorportallist = NULL; + P_DelSeclist(touching_sectorportallist, §or_t::sectorportal_thinglist); + touching_sectorportallist = nullptr; } void AActor::ClearRenderLineList() { - portnode_t *node = touching_lineportallist; - while (node) - node = P_DelPortalnode(node); - touching_lineportallist = NULL; + P_DelSeclist(touching_lineportallist, &FLinePortal::lineportal_thinglist); + touching_lineportallist = nullptr; } - - diff --git a/src/p_user.cpp b/src/p_user.cpp index 6db4a57f5b..3ea9f451fd 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -95,9 +95,19 @@ static int PredictionLerptics; static player_t PredictionPlayerBackup; static BYTE PredictionActorBackup[sizeof(APlayerPawn)]; -static TArray PredictionTouchingSectorsBackup; static TArray PredictionSectorListBackup; -static TArray PredictionSector_sprev_Backup; + +static TArray PredictionTouchingSectorsBackup; +static TArray PredictionTouchingSectors_sprev_Backup; + +static TArray PredictionRenderSectorsBackup; +static TArray PredictionRenderSectors_sprev_Backup; + +static TArray PredictionPortalSectorsBackup; +static TArray PredictionPortalSectors_sprev_Backup; + +static TArray PredictionPortalLinesBackup; +static TArray PredictionPortalLines_sprev_Backup; // [GRB] Custom player classes TArray PlayerClasses; @@ -2775,6 +2785,100 @@ bool P_LerpCalculate(AActor *pmo, PredictPos from, PredictPos to, PredictPos &re return (delta.LengthSquared() > cl_predict_lerpthreshold && scale <= 1.00f); } +template +void BackupNodeList(AActor *act, nodetype *head, nodetype *linktype::*otherlist, TArray &prevbackup, TArray &otherbackup) +{ + // The ordering of the touching_sectorlist needs to remain unchanged + // Also store a copy of all previous sector_thinglist nodes + prevbackup.Clear(); + otherbackup.Clear(); + + for (auto mnode = head; mnode != nullptr; mnode = mnode->m_tnext) + { + otherbackup.Push(mnode->m_sector); + + for (auto snode = mnode->m_sector->*otherlist; snode; snode = snode->m_snext) + { + if (snode->m_thing == act) + { + prevbackup.Push(snode->m_sprev); + break; + } + } + } +} + +template +nodetype *RestoreNodeList(AActor *act, nodetype *head, nodetype *linktype::*otherlist, TArray &prevbackup, TArray &otherbackup) +{ + // Destroy old refrences + nodetype *node = head; + while (node) + { + node->m_thing = NULL; + node = node->m_tnext; + } + + // Make the sector_list match the player's touching_sectorlist before it got predicted. + P_DelSeclist(head, otherlist); + head = NULL; + for (auto i = otherbackup.Size(); i-- > 0;) + { + head = P_AddSecnode(otherbackup[i], act, head, otherbackup[i]->*otherlist); + } + //act->touching_sectorlist = ctx.sector_list; // Attach to thing + //ctx.sector_list = NULL; // clear for next time + + // In the old code this block never executed because of the commented-out NULL assignment above. Needs to be checked + node = head; + while (node) + { + if (node->m_thing == NULL) + { + if (node == head) + head = node->m_tnext; + node = P_DelSecnode(node, otherlist); + } + else + { + node = node->m_tnext; + } + } + + nodetype *snode; + + // Restore sector thinglist order + for (auto i = otherbackup.Size(); i-- > 0;) + { + // If we were already the head node, then nothing needs to change + if (prevbackup[i] == NULL) + continue; + + for (snode = otherbackup[i]->*otherlist; snode; snode = snode->m_snext) + { + if (snode->m_thing == act) + { + if (snode->m_sprev) + snode->m_sprev->m_snext = snode->m_snext; + else + snode->m_sector->*otherlist = snode->m_snext; + if (snode->m_snext) + snode->m_snext->m_sprev = snode->m_sprev; + + snode->m_sprev = prevbackup[i]; + + // At the moment, we don't exist in the list anymore, but we do know what our previous node is, so we set its current m_snext->m_sprev to us. + if (snode->m_sprev->m_snext) + snode->m_sprev->m_snext->m_sprev = snode; + snode->m_snext = snode->m_sprev->m_snext; + snode->m_sprev->m_snext = snode; + break; + } + } + } + return head; +} + void P_PredictPlayer (player_t *player) { int maxtic; @@ -2809,28 +2913,10 @@ void P_PredictPlayer (player_t *player) act->flags2 &= ~MF2_PUSHWALL; player->cheats |= CF_PREDICTING; - // The ordering of the touching_sectorlist needs to remain unchanged - // Also store a copy of all previous sector_thinglist nodes - msecnode_t *mnode = act->touching_sectorlist; - msecnode_t *snode; - PredictionSector_sprev_Backup.Clear(); - PredictionTouchingSectorsBackup.Clear (); - - while (mnode != NULL) - { - PredictionTouchingSectorsBackup.Push (mnode->m_sector); - - for (snode = mnode->m_sector->touching_thinglist; snode; snode = snode->m_snext) - { - if (snode->m_thing == act) - { - PredictionSector_sprev_Backup.Push(snode->m_sprev); - break; - } - } - - mnode = mnode->m_tnext; - } + BackupNodeList(act, act->touching_sectorlist, §or_t::touching_thinglist, PredictionTouchingSectors_sprev_Backup, PredictionTouchingSectorsBackup); + BackupNodeList(act, act->touching_rendersectors, §or_t::touching_renderthings, PredictionRenderSectors_sprev_Backup, PredictionRenderSectorsBackup); + BackupNodeList(act, act->touching_sectorportallist, §or_t::sectorportal_thinglist, PredictionPortalSectors_sprev_Backup, PredictionPortalSectorsBackup); + BackupNodeList(act, act->touching_lineportallist, &FLinePortal::lineportal_thinglist, PredictionPortalLines_sprev_Backup, PredictionPortalLinesBackup); // Keep an ordered list off all actors in the linked sector. PredictionSectorListBackup.Clear(); @@ -2940,6 +3026,12 @@ void P_UnPredictPlayer () player->camera = savedcamera; FLinkContext ctx; + // Unlink from all list, includeing those which are not being handled by UnlinkFromWorld. + auto sectorportal_list = act->touching_sectorportallist; + auto lineportal_list = act->touching_lineportallist; + act->touching_sectorportallist = nullptr; + act->touching_lineportallist = nullptr; + act->UnlinkFromWorld(&ctx); memcpy(&act->snext, PredictionActorBackup, sizeof(APlayerPawn) - ((BYTE *)&act->snext - (BYTE *)act)); @@ -2968,71 +3060,10 @@ void P_UnPredictPlayer () *link = me; } - // Destroy old refrences - msecnode_t *node = ctx.sector_list; - while (node) - { - node->m_thing = NULL; - node = node->m_tnext; - } - - // Make the sector_list match the player's touching_sectorlist before it got predicted. - P_DelSeclist(ctx.sector_list, §or_t::touching_thinglist); - ctx.sector_list = NULL; - for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;) - { - ctx.sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, ctx.sector_list, PredictionTouchingSectorsBackup[i]->touching_thinglist); - } - act->touching_sectorlist = ctx.sector_list; // Attach to thing - ctx.sector_list = NULL; // clear for next time - - // Huh??? - node = ctx.sector_list; - while (node) - { - if (node->m_thing == NULL) - { - if (node == ctx.sector_list) - ctx.sector_list = node->m_tnext; - node = P_DelSecnode(node, §or_t::touching_thinglist); - } - else - { - node = node->m_tnext; - } - } - - msecnode_t *snode; - - // Restore sector thinglist order - for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;) - { - // If we were already the head node, then nothing needs to change - if (PredictionSector_sprev_Backup[i] == NULL) - continue; - - for (snode = PredictionTouchingSectorsBackup[i]->touching_thinglist; snode; snode = snode->m_snext) - { - if (snode->m_thing == act) - { - if (snode->m_sprev) - snode->m_sprev->m_snext = snode->m_snext; - else - snode->m_sector->touching_thinglist = snode->m_snext; - if (snode->m_snext) - snode->m_snext->m_sprev = snode->m_sprev; - - snode->m_sprev = PredictionSector_sprev_Backup[i]; - - // At the moment, we don't exist in the list anymore, but we do know what our previous node is, so we set its current m_snext->m_sprev to us. - if (snode->m_sprev->m_snext) - snode->m_sprev->m_snext->m_sprev = snode; - snode->m_snext = snode->m_sprev->m_snext; - snode->m_sprev->m_snext = snode; - break; - } - } - } + act->touching_sectorlist = RestoreNodeList(act, ctx.sector_list, §or_t::touching_thinglist, PredictionTouchingSectors_sprev_Backup, PredictionTouchingSectorsBackup); + act->touching_rendersectors = RestoreNodeList(act, ctx.render_list, §or_t::touching_renderthings, PredictionRenderSectors_sprev_Backup, PredictionRenderSectorsBackup); + act->touching_sectorportallist = RestoreNodeList(act, sectorportal_list, §or_t::sectorportal_thinglist, PredictionPortalSectors_sprev_Backup, PredictionPortalSectorsBackup); + act->touching_lineportallist = RestoreNodeList(act, lineportal_list, &FLinePortal::lineportal_thinglist, PredictionPortalLines_sprev_Backup, PredictionPortalLinesBackup); } // Now fix the pointers in the blocknode chain diff --git a/src/r_defs.h b/src/r_defs.h index 44f0428200..4b820a3a0a 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -1372,7 +1372,7 @@ struct msecnode_t // use the same memory layout as msecnode_t so both can be used from the same freelist. struct portnode_t { - FLinePortal *m_portal; // a portal containing this object + FLinePortal *m_sector; // a portal containing this object (no, this isn't a sector, but if we want to use templates it needs the same variable names as msecnode_t.) AActor *m_thing; // this object struct portnode_t *m_tprev; // prev msecnode_t for this thing struct portnode_t *m_tnext; // next msecnode_t for this thing