diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 46fa671b0..450c14b1e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -891,7 +891,6 @@ set (PCH_SOURCES c_functions.cpp cmdlib.cpp colormatcher.cpp - compatibility.cpp configfile.cpp ct_chat.cpp cycler.cpp @@ -1081,6 +1080,7 @@ set (PCH_SOURCES maploader/udmf.cpp maploader/polyobjects.cpp maploader/renderinfo.cpp + maploader/compatibility.cpp menu/joystickmenu.cpp menu/loadsavemenu.cpp menu/menu.cpp diff --git a/src/compatibility.h b/src/compatibility.h deleted file mode 100644 index e219f5d0a..000000000 --- a/src/compatibility.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef COMPATIBILITY_H -#define COMPATIBILITY_H - -#include "doomtype.h" -#include "tarray.h" -#include "p_setup.h" - -union FMD5Holder -{ - uint8_t Bytes[16]; - uint32_t DWords[4]; - hash_t Hash; -}; - -struct FCompatValues -{ - int CompatFlags[3]; - unsigned int ExtCommandIndex; -}; - -struct FMD5HashTraits -{ - hash_t Hash(const FMD5Holder key) - { - return key.Hash; - } - int Compare(const FMD5Holder left, const FMD5Holder right) - { - return left.DWords[0] != right.DWords[0] || - left.DWords[1] != right.DWords[1] || - left.DWords[2] != right.DWords[2] || - left.DWords[3] != right.DWords[3]; - } -}; - -extern TMap BCompatMap; - -void ParseCompatibility(); -FName CheckCompatibility(MapData *map); -void SetCompatibilityParams(FName); - -#endif diff --git a/src/d_main.cpp b/src/d_main.cpp index 78f5401b2..c13138fe8 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -89,7 +89,6 @@ #include "d_event.h" #include "d_netinf.h" #include "m_cheat.h" -#include "compatibility.h" #include "m_joy.h" #include "po_man.h" #include "r_renderer.h" @@ -2432,8 +2431,6 @@ void D_DoomMain (void) StartScreen = new FStartupScreen(0); } - ParseCompatibility(); - CheckCmdLine(); // [RH] Load sound environments diff --git a/src/compatibility.cpp b/src/maploader/compatibility.cpp similarity index 81% rename from src/compatibility.cpp rename to src/maploader/compatibility.cpp index 6fe4bf313..5340921de 100644 --- a/src/compatibility.cpp +++ b/src/maploader/compatibility.cpp @@ -39,7 +39,6 @@ // HEADER FILES ------------------------------------------------------------ -#include "compatibility.h" #include "sc_man.h" #include "doomstat.h" #include "c_dispatch.h" @@ -52,11 +51,41 @@ #include "g_levellocals.h" #include "vm.h" #include "actor.h" +#include "p_setup.h" +#include "maploader/maploader.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- +union FMD5Holder +{ + uint8_t Bytes[16]; + uint32_t DWords[4]; + hash_t Hash; +}; + +struct FCompatValues +{ + int CompatFlags[3]; + unsigned int ExtCommandIndex; +}; + +struct FMD5HashTraits +{ + hash_t Hash(const FMD5Holder key) + { + return key.Hash; + } + int Compare(const FMD5Holder left, const FMD5Holder right) + { + return left.DWords[0] != right.DWords[0] || + left.DWords[1] != right.DWords[1] || + left.DWords[2] != right.DWords[2] || + left.DWords[3] != right.DWords[3]; + } +}; + struct FCompatOption { const char *Name; @@ -81,7 +110,7 @@ enum // PUBLIC DATA DEFINITIONS ------------------------------------------------- -TMap BCompatMap; +static TMap BCompatMap; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -242,11 +271,13 @@ void ParseCompatibility() // //========================================================================== -FName CheckCompatibility(MapData *map) +FName MapLoader::CheckCompatibility(MapData *map) { FMD5Holder md5; FCompatValues *flags; + if (BCompatMap.CountUsed() == 0) ParseCompatibility(); + ii_compatflags = 0; ii_compatflags2 = 0; ib_compatflags = 0; @@ -254,7 +285,7 @@ FName CheckCompatibility(MapData *map) // When playing Doom IWAD levels force COMPAT_SHORTTEX and COMPATF_LIGHT. // I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt. // TNT's MAP31 also needs COMPATF_STAIRINDEX but that only gets activated for TNT.WAD. - if (Wads.GetLumpFile(map->lumpnum) == Wads.GetIwadNum() && (gameinfo.flags & GI_COMPATSHORTTEX) && level.maptype == MAPTYPE_DOOM) + if (Wads.GetLumpFile(map->lumpnum) == Wads.GetIwadNum() && (gameinfo.flags & GI_COMPATSHORTTEX) && Level->maptype == MAPTYPE_DOOM) { ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT; if (gameinfo.flags & GI_COMPATSTAIRS) ii_compatflags |= COMPATF_STAIRINDEX; @@ -296,7 +327,7 @@ FName CheckCompatibility(MapData *map) compatflags.Callback(); compatflags2.Callback(); // Set floatbob compatibility for all maps with an original Hexen MAPINFO. - if (level.flags2 & LEVEL2_HEXENHACK) + if (Level->flags2 & LEVEL2_HEXENHACK) { ib_compatflags |= BCOMPATF_FLOATBOB; } @@ -309,18 +340,33 @@ FName CheckCompatibility(MapData *map) // //========================================================================== -void SetCompatibilityParams(FName checksum) +class DLevelCompatibility : public DObject +{ + DECLARE_ABSTRACT_CLASS(DLevelCompatibility, DObject) +public: + MapLoader *loader; + FLevelLocals *Level; +}; +IMPLEMENT_CLASS(DLevelCompatibility, true, false); + + +void MapLoader::SetCompatibilityParams(FName checksum) { if (checksum != NAME_None) { - PClass *const cls = PClass::FindClass("LevelCompatibility"); - if (cls != nullptr) + auto lc = Create(); + lc->loader = this; + lc->Level = Level; + for(auto cls : PClass::AllClasses) { - PFunction *const func = dyn_cast(cls->FindSymbol("Apply", true)); - if (func != nullptr) + if (cls->IsDescendantOf(RUNTIME_CLASS(DLevelCompatibility))) { - VMValue param = { (int)checksum }; - VMCall(func->Variants[0].Implementation, ¶m, 1, nullptr, 0); + PFunction *const func = dyn_cast(cls->FindSymbol("Apply", false)); + if (func != nullptr) + { + VMValue param[] = { lc, (int)checksum }; + VMCall(func->Variants[0].Implementation, param, 2, nullptr, 0); + } } } } @@ -328,12 +374,12 @@ void SetCompatibilityParams(FName checksum) DEFINE_ACTION_FUNCTION(DLevelCompatibility, OffsetSectorPlane) { - PARAM_PROLOGUE; + PARAM_SELF_PROLOGUE(DLevelCompatibility); PARAM_INT(sector); PARAM_INT(planeval); PARAM_FLOAT(delta); - sector_t *sec = &level.sectors[sector]; + sector_t *sec = &self->Level->sectors[sector]; secplane_t& plane = sector_t::floor == planeval? sec->floorplane : sec->ceilingplane; plane.ChangeHeight(delta); sec->ChangePlaneTexZ(planeval, delta); @@ -342,7 +388,7 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, OffsetSectorPlane) DEFINE_ACTION_FUNCTION(DLevelCompatibility, ClearSectorTags) { - PARAM_PROLOGUE; + PARAM_SELF_PROLOGUE(DLevelCompatibility); PARAM_INT(sector); tagManager.RemoveSectorTags(sector); return 0; @@ -350,7 +396,7 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, ClearSectorTags) DEFINE_ACTION_FUNCTION(DLevelCompatibility, AddSectorTag) { - PARAM_PROLOGUE; + PARAM_SELF_PROLOGUE(DLevelCompatibility); PARAM_INT(sector); PARAM_INT(tag); tagManager.AddSectorTag(sector, tag); @@ -359,27 +405,27 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, AddSectorTag) DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingSkills) { - PARAM_PROLOGUE; + PARAM_SELF_PROLOGUE(DLevelCompatibility); PARAM_INT(thing); PARAM_INT(skillmask); - if ((unsigned)thing < MapThingsConverted.Size()) + if ((unsigned)thing < self->loader->MapThingsConverted.Size()) { - MapThingsConverted[thing].SkillFilter = skillmask; + self->loader->MapThingsConverted[thing].SkillFilter = skillmask; } return 0; } DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingXY) { - PARAM_PROLOGUE; + PARAM_SELF_PROLOGUE(DLevelCompatibility); PARAM_INT(thing); PARAM_FLOAT(x); PARAM_FLOAT(y); - if ((unsigned)thing < MapThingsConverted.Size()) + if ((unsigned)thing < self->loader->MapThingsConverted.Size()) { - auto& pos = MapThingsConverted[thing].pos; + auto& pos = self->loader->MapThingsConverted[thing].pos; pos.X = x; pos.Y = y; } @@ -388,74 +434,76 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingXY) DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingZ) { - PARAM_PROLOGUE; + PARAM_SELF_PROLOGUE(DLevelCompatibility); PARAM_INT(thing); PARAM_FLOAT(z); - if ((unsigned)thing < MapThingsConverted.Size()) + if ((unsigned)thing < self->loader->MapThingsConverted.Size()) { - MapThingsConverted[thing].pos.Z = z; + self->loader->MapThingsConverted[thing].pos.Z = z; } return 0; } DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingFlags) { - PARAM_PROLOGUE; + PARAM_SELF_PROLOGUE(DLevelCompatibility); PARAM_INT(thing); PARAM_INT(flags); - if ((unsigned)thing < MapThingsConverted.Size()) + if ((unsigned)thing < self->loader->MapThingsConverted.Size()) { - MapThingsConverted[thing].flags = flags; + self->loader->MapThingsConverted[thing].flags = flags; } return 0; } DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetVertex) { - PARAM_PROLOGUE; + PARAM_SELF_PROLOGUE(DLevelCompatibility); PARAM_UINT(vertex); PARAM_FLOAT(x); PARAM_FLOAT(y); - if (vertex < level.vertexes.Size()) + if (vertex < self->Level->vertexes.Size()) { - level.vertexes[vertex].p = DVector2(x, y); + self->Level->vertexes[vertex].p = DVector2(x, y); } - ForceNodeBuild = true; + self->loader->ForceNodeBuild = true; return 0; } DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetLineSectorRef) { - PARAM_PROLOGUE; + PARAM_SELF_PROLOGUE(DLevelCompatibility); PARAM_UINT(lineidx); PARAM_UINT(sideidx); PARAM_UINT(sectoridx); if ( sideidx < 2 - && lineidx < level.lines.Size() - && sectoridx < level.sectors.Size()) + && lineidx < self->Level->lines.Size() + && sectoridx < self->Level->sectors.Size()) { - line_t *line = &level.lines[lineidx]; + line_t *line = &self->Level->lines[lineidx]; side_t *side = line->sidedef[sideidx]; - side->sector = &level.sectors[sectoridx]; + side->sector = &self->Level->sectors[sectoridx]; if (sideidx == 0) line->frontsector = side->sector; else line->backsector = side->sector; } - ForceNodeBuild = true; + self->loader->ForceNodeBuild = true; return 0; } DEFINE_ACTION_FUNCTION(DLevelCompatibility, GetDefaultActor) { - PARAM_PROLOGUE; + PARAM_SELF_PROLOGUE(DLevelCompatibility); PARAM_NAME(actorclass); ACTION_RETURN_OBJECT(GetDefaultByName(actorclass)); } +DEFINE_FIELD(DLevelCompatibility, Level); + //========================================================================== // // CCMD mapchecksum diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index d9b857004..39e435bec 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -85,7 +85,6 @@ #include "r_sky.h" #include "cmdlib.h" #include "md5.h" -#include "compatibility.h" #include "po_man.h" #include "r_renderer.h" #include "p_blockmap.h" @@ -103,9 +102,6 @@ #include "fragglescript/t_fs.h" #include "maploader.h" -TArray MapThingsConverted; -bool ForceNodeBuild; - void PO_Init(); diff --git a/src/maploader/maploader.h b/src/maploader/maploader.h index 14cf61b81..02ab1bbe2 100644 --- a/src/maploader/maploader.h +++ b/src/maploader/maploader.h @@ -1,5 +1,7 @@ #pragma once +#include "nodebuild.h" + struct EDMapthing { int recordnum; @@ -88,6 +90,7 @@ struct FMissingCount typedef TMap FMissingTextureTracker; struct FLevelLocals; +struct MapData; class MapLoader { @@ -105,6 +108,10 @@ class MapLoader int sidecount = 0; TArray linemap; TArray sidetemp; +public: // for the scripted compatibility system these two members need to be public. + TArray MapThingsConverted; + bool ForceNodeBuild = false; +private: // Extradata loader TMap EDLines; @@ -114,6 +121,9 @@ class MapLoader // Polyobject init TArray KnownPolySides; + FName CheckCompatibility(MapData *map); + void SetCompatibilityParams(FName checksum); + // Slopes void SlopeLineToPoint(int lineid, const DVector3 &pos, bool slopeCeil); void CopyPlane(int tag, sector_t *dest, bool copyCeil); diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index 19fda0e90..a66a2a67f 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -122,13 +122,8 @@ enum // namespace for each game }; -extern bool ForceNodeBuild; -extern TArray MapThingsConverted; - - #define CHECK_N(f) if (!(namespace_bits&(f))) break; - //=========================================================================== // // Common parsing routines @@ -2055,7 +2050,7 @@ public: { Printf ("Removing 0-length line %d\n", i+skipped); ParsedLines.Delete(i); - ForceNodeBuild = true; + loader->ForceNodeBuild = true; skipped++; } else @@ -2218,10 +2213,10 @@ public: FMapThing th; unsigned userdatastart = loader->MapThingsUserData.Size(); ParseThing(&th); - MapThingsConverted.Push(th); + loader->MapThingsConverted.Push(th); if (userdatastart < loader->MapThingsUserData.Size()) { // User data added - loader->MapThingsUserDataIndex[MapThingsConverted.Size()-1] = userdatastart; + loader->MapThingsUserDataIndex[loader->MapThingsConverted.Size()-1] = userdatastart; // Mark end of the user data for this map thing FUDMFKey ukey; ukey.Key = NAME_None; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 3c5306677..1ec59093d 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -55,7 +55,6 @@ #include "r_sky.h" #include "cmdlib.h" #include "md5.h" -#include "compatibility.h" #include "po_man.h" #include "r_renderer.h" #include "p_blockmap.h" @@ -227,7 +226,6 @@ void P_FreeLevelData () // [ZZ] delete per-map event handlers E_Shutdown(true); - MapThingsConverted.Clear(); R_FreePastViewers(); P_ClearUDMFKeys(); @@ -481,7 +479,6 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame) } P_ResetSightCounters(true); - MapThingsConverted.Clear(); // Create a backup of the map data so the savegame code can toss out all fields that haven't changed in order to reduce processing time and file size. // Note that we want binary identity here, so assignment is not sufficient because it won't initialize any padding bytes. diff --git a/src/p_setup.h b/src/p_setup.h index 5973a4fcb..1cd67c2ad 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -168,9 +168,4 @@ void FixMinisegReferences(); void FixHoles(); void ReportUnpairedMinisegs(); -// To be moved to maploader later! - -extern TArray MapThingsConverted; -extern bool ForceNodeBuild; - #endif diff --git a/src/sc_man.h b/src/sc_man.h index c76fb724f..8b3d02f12 100644 --- a/src/sc_man.h +++ b/src/sc_man.h @@ -1,6 +1,8 @@ #ifndef __SC_MAN_H__ #define __SC_MAN_H__ +#include "doomtype.h" + class FScanner { public: diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt index 170b98ed5..1be5f3941 100644 --- a/wadsrc/static/zscript/level_compatibility.txt +++ b/wadsrc/static/zscript/level_compatibility.txt @@ -1,7 +1,9 @@ -class LevelCompatibility play +class LevelCompatibility native play { - private static void Apply(Name checksum) + native LevelLocals level; + + protected void Apply(Name checksum) { switch (checksum) { @@ -1165,43 +1167,43 @@ class LevelCompatibility play } } - private static native void ClearSectorTags(int sector); - private static native void AddSectorTag(int sector, int tag); - private static native void OffsetSectorPlane(int sector, int plane, double offset); - private static native void SetThingSkills(int thing, int skills); - private static native void SetThingXY(int thing, double x, double y); - private static native void SetThingZ(int thing, double z); - private static native void SetThingFlags(int thing, int flags); - private static native void SetVertex(uint vertex, double x, double y); - private static native void SetLineSectorRef(uint line, uint side, uint sector); - private static native Actor GetDefaultActor(Name actorclass); + protected native void ClearSectorTags(int sector); + protected native void AddSectorTag(int sector, int tag); + protected native void OffsetSectorPlane(int sector, int plane, double offset); + protected native void SetThingSkills(int thing, int skills); + protected native void SetThingXY(int thing, double x, double y); + protected native void SetThingZ(int thing, double z); + protected native void SetThingFlags(int thing, int flags); + protected native void SetVertex(uint vertex, double x, double y); + protected native void SetLineSectorRef(uint line, uint side, uint sector); + protected native Actor GetDefaultActor(Name actorclass); - private static void SetWallTexture(int line, int side, int texpart, String texture) + protected void SetWallTexture(int line, int side, int texpart, String texture) { SetWallTextureID(line, side, texpart, TexMan.CheckForTexture(texture, TexMan.Type_Wall)); } - private static void SetWallTextureID(int line, int side, int texpart, TextureID texture) + protected void SetWallTextureID(int line, int side, int texpart, TextureID texture) { level.Lines[line].sidedef[side].SetTexture(texpart, texture); } - private static void SetLineFlags(int line, int setflags, int clearflags = 0) + protected void SetLineFlags(int line, int setflags, int clearflags = 0) { level.Lines[line].flags = (level.Lines[line].flags & ~clearflags) | setflags; } - private static void SetLineActivation(int line, int acttype) + protected void SetLineActivation(int line, int acttype) { level.Lines[line].activation = acttype; } - private static void ClearLineSpecial(int line) + protected void ClearLineSpecial(int line) { level.Lines[line].special = 0; } - private static void SetLineSpecial(int line, int special, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0, int arg5 = 0) + protected void SetLineSpecial(int line, int special, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0, int arg5 = 0) { level.Lines[line].special = special; level.Lines[line].args[0] = arg1; @@ -1211,27 +1213,27 @@ class LevelCompatibility play level.Lines[line].args[4] = arg5; } - private static void SetSectorSpecial(int sectornum, int special) + protected void SetSectorSpecial(int sectornum, int special) { level.sectors[sectornum].special = special; } - private static void SetSectorTextureID(int sectornum, int plane, TextureID texture) + protected void SetSectorTextureID(int sectornum, int plane, TextureID texture) { level.sectors[sectornum].SetTexture(plane, texture); } - private static void SetSectorTexture(int sectornum, int plane, String texture) + protected void SetSectorTexture(int sectornum, int plane, String texture) { SetSectorTextureID(sectornum, plane, TexMan.CheckForTexture(texture, TexMan.Type_Flat)); } - private static void SetSectorLight(int sectornum, int newval) + protected void SetSectorLight(int sectornum, int newval) { level.sectors[sectornum].SetLightLevel(newval); } - private static void SetWallYScale(int line, int side, int texpart, double scale) + protected void SetWallYScale(int line, int side, int texpart, double scale) { level.lines[line].sidedef[side].SetTextureYScale(texpart, scale); }