From 0faa9111b9d8795c87567b1697c8495fe4ae80c0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 19 Dec 2018 18:41:53 +0100 Subject: [PATCH] - moved P_OpenMapData and related content out of p_setup.cpp. --- src/CMakeLists.txt | 1 + src/g_levellocals.h | 97 ++++----- src/p_openmap.cpp | 413 +++++++++++++++++++++++++++++++++++++ src/p_setup.cpp | 384 ---------------------------------- src/scripting/vmthunks.cpp | 13 ++ 5 files changed, 478 insertions(+), 430 deletions(-) create mode 100644 src/p_openmap.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6d39692e5..4fb943691 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -963,6 +963,7 @@ set (PCH_SOURCES p_map.cpp p_maputl.cpp p_mobj.cpp + p_openmap.cpp p_pillar.cpp p_plats.cpp p_pspr.cpp diff --git a/src/g_levellocals.h b/src/g_levellocals.h index c9eceabb6..ee9cbbe9c 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -46,7 +46,54 @@ #include "r_data/r_sections.h" #include "r_data/r_canvastexture.h" -struct FLevelLocals + +struct FLevelData +{ + TArray vertexes; + TArray sectors; + TArray linebuffer; // contains the line lists for the sectors. + TArray lines; + TArray sides; + TArray segs; + TArray subsectors; + TArray nodes; + TArray gamesubsectors; + TArray gamenodes; + node_t *headgamenode; + TArray rejectmatrix; + TArray Zones; + + TArray sectorPortals; + TArray linePortals; + + // Portal information. + FDisplacementTable Displacements; + FPortalBlockmap PortalBlockmap; + TArray linkedPortals; // only the linked portals, this is used to speed up looking for them in P_CollectConnectedGroups. + TArray portalGroups; + TArray linePortalSpans; + FSectionContainer sections; + FCanvasTextureInfo canvasTextureInfo; + + // [ZZ] Destructible geometry information + TMap healthGroups; + + FBlockmap blockmap; + + // These are copies of the loaded map data that get used by the savegame code to skip unaltered fields + // Without such a mechanism the savegame format would become too slow and large because more than 80-90% are normally still unaltered. + TArray loadsectors; + TArray loadlines; + TArray loadsides; + + // Maintain single and multi player starting spots. + TArray deathmatchstarts; + FPlayerStart playerstarts[MAXPLAYERS]; + TArray AllPlayerStarts; + +}; + +struct FLevelLocals : public FLevelData { void Tick(); void Mark(); @@ -76,57 +123,12 @@ struct FLevelLocals uint64_t ShaderStartTime = 0; // tell the shader system when we started the level (forces a timer restart) - TArray vertexes; - TArray sectors; - TArray linebuffer; // contains the line lists for the sectors. - TArray lines; - TArray sides; - TArray segs; - TArray subsectors; - TArray nodes; - TArray gamesubsectors; - TArray gamenodes; - node_t *headgamenode; - TArray rejectmatrix; - static const int BODYQUESIZE = 32; TObjPtr bodyque[BODYQUESIZE]; int bodyqueslot; - - TArray sectorPortals; - TArray linePortals; - - // Portal information. - FDisplacementTable Displacements; - FPortalBlockmap PortalBlockmap; - TArray linkedPortals; // only the linked portals, this is used to speed up looking for them in P_CollectConnectedGroups. - TArray portalGroups; - TArray linePortalSpans; - FSectionContainer sections; - FCanvasTextureInfo canvasTextureInfo; - int NumMapSections; - TArray Zones; - - // [ZZ] Destructible geometry information - TMap healthGroups; - - FBlockmap blockmap; - - // These are copies of the loaded map data that get used by the savegame code to skip unaltered fields - // Without such a mechanism the savegame format would become too slow and large because more than 80-90% are normally still unaltered. - TArray loadsectors; - TArray loadlines; - TArray loadsides; - - // Maintain single and multi player starting spots. - TArray deathmatchstarts; - FPlayerStart playerstarts[MAXPLAYERS]; - TArray AllPlayerStarts; - - uint32_t flags; uint32_t flags2; uint32_t flags3; @@ -224,6 +226,8 @@ struct FLevelLocals } }; +#ifndef NO_DEFINE_LEVEL + extern FLevelLocals level; inline int vertex_t::Index() const @@ -350,3 +354,4 @@ inline bool line_t::hitSkyWall(AActor* mo) const backsector->GetTexture(sector_t::ceiling) == skyflatnum && mo->Z() >= backsector->ceilingplane.ZatPoint(mo->PosRelative(this)); } +#endif \ No newline at end of file diff --git a/src/p_openmap.cpp b/src/p_openmap.cpp new file mode 100644 index 000000000..9331dca72 --- /dev/null +++ b/src/p_openmap.cpp @@ -0,0 +1,413 @@ +/* +** p_openmap.cpp +** +** creates the data structures needed to load a map from the resource files. +** +**--------------------------------------------------------------------------- +** Copyright 2005-2018 Christoph Oelckers +** Copyright 2005-2016 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "p_setup.h" +#include "i_system.h" +#include "cmdlib.h" +#include "w_wad.h" +#include "md5.h" +#include "g_levellocals.h" + +inline bool P_IsBuildMap(MapData *map) +{ + return false; +} + +//=========================================================================== +// +// GetMapIndex +// +// Gets the type of map lump or -1 if invalid or -2 if required and not found. +// +//=========================================================================== + +struct checkstruct +{ + const char lumpname[9]; + bool required; +}; + +static int GetMapIndex(const char *mapname, int lastindex, const char *lumpname, bool needrequired) +{ + static const checkstruct check[] = + { + {"", true}, + {"THINGS", true}, + {"LINEDEFS", true}, + {"SIDEDEFS", true}, + {"VERTEXES", true}, + {"SEGS", false}, + {"SSECTORS", false}, + {"NODES", false}, + {"SECTORS", true}, + {"REJECT", false}, + {"BLOCKMAP", false}, + {"BEHAVIOR", false}, + //{"SCRIPTS", false}, + }; + + if (lumpname==NULL) lumpname=""; + + for(size_t i=lastindex+1;iresource = FResourceFile::OpenResourceFile(mapname, true); + wadReader = map->resource->GetReader(); + } + else + { + FString fmt; + int lump_wad; + int lump_map; + int lump_name = -1; + + // Check for both *.wad and *.map in order to load Build maps + // as well. The higher one will take precedence. + // Names with more than 8 characters will only be checked as .wad and .map. + if (strlen(mapname) <= 8) lump_name = Wads.CheckNumForName(mapname); + fmt.Format("maps/%s.wad", mapname); + lump_wad = Wads.CheckNumForFullName(fmt); + fmt.Format("maps/%s.map", mapname); + lump_map = Wads.CheckNumForFullName(fmt); + + if (lump_name > lump_wad && lump_name > lump_map && lump_name != -1) + { + int lumpfile = Wads.GetLumpFile(lump_name); + int nextfile = Wads.GetLumpFile(lump_name+1); + + map->lumpnum = lump_name; + + if (lumpfile != nextfile) + { + // The following lump is from a different file so whatever this is, + // it is not a multi-lump Doom level so let's assume it is a Build map. + map->MapLumps[0].Reader = Wads.ReopenLumpReader(lump_name); + if (!P_IsBuildMap(map)) + { + delete map; + return NULL; + } + return map; + } + + // This case can only happen if the lump is inside a real WAD file. + // As such any special handling for other types of lumps is skipped. + map->MapLumps[0].Reader = Wads.ReopenLumpReader(lump_name); + strncpy(map->MapLumps[0].Name, Wads.GetLumpFullName(lump_name), 8); + map->Encrypted = Wads.IsEncryptedFile(lump_name); + map->InWad = true; + + if (map->Encrypted) + { // If it's encrypted, then it's a Blood file, presumably a map. + if (!P_IsBuildMap(map)) + { + delete map; + return NULL; + } + return map; + } + + int index = 0; + + if (stricmp(Wads.GetLumpFullName(lump_name + 1), "TEXTMAP") != 0) + { + for(int i = 1;; i++) + { + // Since levels must be stored in WADs they can't really have full + // names and for any valid level lump this always returns the short name. + const char * lumpname = Wads.GetLumpFullName(lump_name + i); + try + { + index = GetMapIndex(mapname, index, lumpname, !justcheck); + } + catch(...) + { + delete map; + throw; + } + if (index == -2) + { + delete map; + return NULL; + } + if (index == ML_BEHAVIOR) map->HasBehavior = true; + + // The next lump is not part of this map anymore + if (index < 0) break; + + map->MapLumps[index].Reader = Wads.ReopenLumpReader(lump_name + i); + strncpy(map->MapLumps[index].Name, lumpname, 8); + } + } + else + { + map->isText = true; + map->MapLumps[1].Reader = Wads.ReopenLumpReader(lump_name + 1); + for(int i = 2;; i++) + { + const char * lumpname = Wads.GetLumpFullName(lump_name + i); + + if (lumpname == NULL) + { + I_Error("Invalid map definition for %s", mapname); + } + else if (!stricmp(lumpname, "ZNODES")) + { + index = ML_GLZNODES; + } + else if (!stricmp(lumpname, "BLOCKMAP")) + { + // there is no real point in creating a blockmap but let's use it anyway + index = ML_BLOCKMAP; + } + else if (!stricmp(lumpname, "REJECT")) + { + index = ML_REJECT; + } + else if (!stricmp(lumpname, "DIALOGUE")) + { + index = ML_CONVERSATION; + } + else if (!stricmp(lumpname, "BEHAVIOR")) + { + index = ML_BEHAVIOR; + map->HasBehavior = true; + } + else if (!stricmp(lumpname, "ENDMAP")) + { + break; + } + else continue; + map->MapLumps[index].Reader = Wads.ReopenLumpReader(lump_name + i); + strncpy(map->MapLumps[index].Name, lumpname, 8); + } + } + return map; + } + else + { + if (lump_map > lump_wad) + { + lump_wad = lump_map; + } + if (lump_wad == -1) + { + delete map; + return NULL; + } + map->lumpnum = lump_wad; + auto reader = Wads.ReopenLumpReader(lump_wad); + map->resource = FResourceFile::OpenResourceFile(Wads.GetLumpFullName(lump_wad), reader, true); + wadReader = map->resource->GetReader(); + } + } + uint32_t id; + + // Although we're using the resource system, we still want to be sure we're + // reading from a wad file. + wadReader->Seek(0, FileReader::SeekSet); + wadReader->Read(&id, sizeof(id)); + + if (id == IWAD_ID || id == PWAD_ID) + { + char maplabel[9]=""; + int index=0; + + map->MapLumps[0].Reader = map->resource->GetLump(0)->NewReader(); + strncpy(map->MapLumps[0].Name, map->resource->GetLump(0)->Name, 8); + + for(uint32_t i = 1; i < map->resource->LumpCount(); i++) + { + const char* lumpname = map->resource->GetLump(i)->Name; + + if (i == 1 && !strnicmp(lumpname, "TEXTMAP", 8)) + { + map->isText = true; + map->MapLumps[ML_TEXTMAP].Reader = map->resource->GetLump(i)->NewReader(); + strncpy(map->MapLumps[ML_TEXTMAP].Name, lumpname, 8); + for(int i = 2;; i++) + { + lumpname = map->resource->GetLump(i)->Name; + if (!strnicmp(lumpname, "ZNODES",8)) + { + index = ML_GLZNODES; + } + else if (!strnicmp(lumpname, "BLOCKMAP",8)) + { + // there is no real point in creating a blockmap but let's use it anyway + index = ML_BLOCKMAP; + } + else if (!strnicmp(lumpname, "REJECT",8)) + { + index = ML_REJECT; + } + else if (!strnicmp(lumpname, "DIALOGUE",8)) + { + index = ML_CONVERSATION; + } + else if (!strnicmp(lumpname, "BEHAVIOR",8)) + { + index = ML_BEHAVIOR; + map->HasBehavior = true; + } + else if (!strnicmp(lumpname, "ENDMAP",8)) + { + return map; + } + else continue; + map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); + strncpy(map->MapLumps[index].Name, lumpname, 8); + } + } + + if (i>0) + { + try + { + index = GetMapIndex(maplabel, index, lumpname, !justcheck); + } + catch(...) + { + delete map; + throw; + } + if (index == -2) + { + delete map; + return NULL; + } + if (index == ML_BEHAVIOR) map->HasBehavior = true; + + // The next lump is not part of this map anymore + if (index < 0) break; + } + else + { + strncpy(maplabel, lumpname, 8); + maplabel[8]=0; + } + + map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); + strncpy(map->MapLumps[index].Name, lumpname, 8); + } + } + else + { + // This is a Build map and not subject to WAD consistency checks. + //map->MapLumps[0].Size = wadReader->GetLength(); + if (!P_IsBuildMap(map)) + { + delete map; + return NULL; + } + } + return map; +} + +bool P_CheckMapData(const char *mapname) +{ + MapData *mapd = P_OpenMapData(mapname, true); + if (mapd == NULL) return false; + delete mapd; + return true; +} + +//=========================================================================== +// +// MapData :: GetChecksum +// +// Hashes a map based on its header, THINGS, LINEDEFS, SIDEDEFS, SECTORS, +// and BEHAVIOR lumps. Node-builder generated lumps are not included. +// +//=========================================================================== + +void MapData::GetChecksum(uint8_t cksum[16]) +{ + MD5Context md5; + + if (isText) + { + md5.Update(Reader(ML_TEXTMAP), Size(ML_TEXTMAP)); + } + else + { + md5.Update(Reader(ML_LABEL), Size(ML_LABEL)); + md5.Update(Reader(ML_THINGS), Size(ML_THINGS)); + md5.Update(Reader(ML_LINEDEFS), Size(ML_LINEDEFS)); + md5.Update(Reader(ML_SIDEDEFS), Size(ML_SIDEDEFS)); + md5.Update(Reader(ML_SECTORS), Size(ML_SECTORS)); + } + if (HasBehavior) + { + md5.Update(Reader(ML_BEHAVIOR), Size(ML_BEHAVIOR)); + } + md5.Final(cksum); +} diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 16f609152..7dc77bf85 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -136,11 +136,6 @@ CVAR (Bool, showloadtimes, false, 0); static void P_Shutdown (); -inline bool P_IsBuildMap(MapData *map) -{ - return false; -} - inline bool P_LoadBuildMap(uint8_t *mapdata, size_t len, FMapThing **things, int *numthings) { return false; @@ -168,385 +163,6 @@ bool ForceNodeBuild; static void P_AllocateSideDefs (MapData *map, int count); -//=========================================================================== -// -// GetMapIndex -// -// Gets the type of map lump or -1 if invalid or -2 if required and not found. -// -//=========================================================================== - -struct checkstruct -{ - const char lumpname[9]; - bool required; -}; - -static int GetMapIndex(const char *mapname, int lastindex, const char *lumpname, bool needrequired) -{ - static const checkstruct check[] = - { - {"", true}, - {"THINGS", true}, - {"LINEDEFS", true}, - {"SIDEDEFS", true}, - {"VERTEXES", true}, - {"SEGS", false}, - {"SSECTORS", false}, - {"NODES", false}, - {"SECTORS", true}, - {"REJECT", false}, - {"BLOCKMAP", false}, - {"BEHAVIOR", false}, - //{"SCRIPTS", false}, - }; - - if (lumpname==NULL) lumpname=""; - - for(size_t i=lastindex+1;iresource = FResourceFile::OpenResourceFile(mapname, true); - wadReader = map->resource->GetReader(); - } - else - { - FString fmt; - int lump_wad; - int lump_map; - int lump_name = -1; - - // Check for both *.wad and *.map in order to load Build maps - // as well. The higher one will take precedence. - // Names with more than 8 characters will only be checked as .wad and .map. - if (strlen(mapname) <= 8) lump_name = Wads.CheckNumForName(mapname); - fmt.Format("maps/%s.wad", mapname); - lump_wad = Wads.CheckNumForFullName(fmt); - fmt.Format("maps/%s.map", mapname); - lump_map = Wads.CheckNumForFullName(fmt); - - if (lump_name > lump_wad && lump_name > lump_map && lump_name != -1) - { - int lumpfile = Wads.GetLumpFile(lump_name); - int nextfile = Wads.GetLumpFile(lump_name+1); - - map->lumpnum = lump_name; - - if (lumpfile != nextfile) - { - // The following lump is from a different file so whatever this is, - // it is not a multi-lump Doom level so let's assume it is a Build map. - map->MapLumps[0].Reader = Wads.ReopenLumpReader(lump_name); - if (!P_IsBuildMap(map)) - { - delete map; - return NULL; - } - return map; - } - - // This case can only happen if the lump is inside a real WAD file. - // As such any special handling for other types of lumps is skipped. - map->MapLumps[0].Reader = Wads.ReopenLumpReader(lump_name); - strncpy(map->MapLumps[0].Name, Wads.GetLumpFullName(lump_name), 8); - map->Encrypted = Wads.IsEncryptedFile(lump_name); - map->InWad = true; - - if (map->Encrypted) - { // If it's encrypted, then it's a Blood file, presumably a map. - if (!P_IsBuildMap(map)) - { - delete map; - return NULL; - } - return map; - } - - int index = 0; - - if (stricmp(Wads.GetLumpFullName(lump_name + 1), "TEXTMAP") != 0) - { - for(int i = 1;; i++) - { - // Since levels must be stored in WADs they can't really have full - // names and for any valid level lump this always returns the short name. - const char * lumpname = Wads.GetLumpFullName(lump_name + i); - try - { - index = GetMapIndex(mapname, index, lumpname, !justcheck); - } - catch(...) - { - delete map; - throw; - } - if (index == -2) - { - delete map; - return NULL; - } - if (index == ML_BEHAVIOR) map->HasBehavior = true; - - // The next lump is not part of this map anymore - if (index < 0) break; - - map->MapLumps[index].Reader = Wads.ReopenLumpReader(lump_name + i); - strncpy(map->MapLumps[index].Name, lumpname, 8); - } - } - else - { - map->isText = true; - map->MapLumps[1].Reader = Wads.ReopenLumpReader(lump_name + 1); - for(int i = 2;; i++) - { - const char * lumpname = Wads.GetLumpFullName(lump_name + i); - - if (lumpname == NULL) - { - I_Error("Invalid map definition for %s", mapname); - } - else if (!stricmp(lumpname, "ZNODES")) - { - index = ML_GLZNODES; - } - else if (!stricmp(lumpname, "BLOCKMAP")) - { - // there is no real point in creating a blockmap but let's use it anyway - index = ML_BLOCKMAP; - } - else if (!stricmp(lumpname, "REJECT")) - { - index = ML_REJECT; - } - else if (!stricmp(lumpname, "DIALOGUE")) - { - index = ML_CONVERSATION; - } - else if (!stricmp(lumpname, "BEHAVIOR")) - { - index = ML_BEHAVIOR; - map->HasBehavior = true; - } - else if (!stricmp(lumpname, "ENDMAP")) - { - break; - } - else continue; - map->MapLumps[index].Reader = Wads.ReopenLumpReader(lump_name + i); - strncpy(map->MapLumps[index].Name, lumpname, 8); - } - } - return map; - } - else - { - if (lump_map > lump_wad) - { - lump_wad = lump_map; - } - if (lump_wad == -1) - { - delete map; - return NULL; - } - map->lumpnum = lump_wad; - auto reader = Wads.ReopenLumpReader(lump_wad); - map->resource = FResourceFile::OpenResourceFile(Wads.GetLumpFullName(lump_wad), reader, true); - wadReader = map->resource->GetReader(); - } - } - uint32_t id; - - // Although we're using the resource system, we still want to be sure we're - // reading from a wad file. - wadReader->Seek(0, FileReader::SeekSet); - wadReader->Read(&id, sizeof(id)); - - if (id == IWAD_ID || id == PWAD_ID) - { - char maplabel[9]=""; - int index=0; - - map->MapLumps[0].Reader = map->resource->GetLump(0)->NewReader(); - strncpy(map->MapLumps[0].Name, map->resource->GetLump(0)->Name, 8); - - for(uint32_t i = 1; i < map->resource->LumpCount(); i++) - { - const char* lumpname = map->resource->GetLump(i)->Name; - - if (i == 1 && !strnicmp(lumpname, "TEXTMAP", 8)) - { - map->isText = true; - map->MapLumps[ML_TEXTMAP].Reader = map->resource->GetLump(i)->NewReader(); - strncpy(map->MapLumps[ML_TEXTMAP].Name, lumpname, 8); - for(int i = 2;; i++) - { - lumpname = map->resource->GetLump(i)->Name; - if (!strnicmp(lumpname, "ZNODES",8)) - { - index = ML_GLZNODES; - } - else if (!strnicmp(lumpname, "BLOCKMAP",8)) - { - // there is no real point in creating a blockmap but let's use it anyway - index = ML_BLOCKMAP; - } - else if (!strnicmp(lumpname, "REJECT",8)) - { - index = ML_REJECT; - } - else if (!strnicmp(lumpname, "DIALOGUE",8)) - { - index = ML_CONVERSATION; - } - else if (!strnicmp(lumpname, "BEHAVIOR",8)) - { - index = ML_BEHAVIOR; - map->HasBehavior = true; - } - else if (!strnicmp(lumpname, "ENDMAP",8)) - { - return map; - } - else continue; - map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); - strncpy(map->MapLumps[index].Name, lumpname, 8); - } - } - - if (i>0) - { - try - { - index = GetMapIndex(maplabel, index, lumpname, !justcheck); - } - catch(...) - { - delete map; - throw; - } - if (index == -2) - { - delete map; - return NULL; - } - if (index == ML_BEHAVIOR) map->HasBehavior = true; - - // The next lump is not part of this map anymore - if (index < 0) break; - } - else - { - strncpy(maplabel, lumpname, 8); - maplabel[8]=0; - } - - map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); - strncpy(map->MapLumps[index].Name, lumpname, 8); - } - } - else - { - // This is a Build map and not subject to WAD consistency checks. - //map->MapLumps[0].Size = wadReader->GetLength(); - if (!P_IsBuildMap(map)) - { - delete map; - return NULL; - } - } - return map; -} - -bool P_CheckMapData(const char *mapname) -{ - MapData *mapd = P_OpenMapData(mapname, true); - if (mapd == NULL) return false; - delete mapd; - return true; -} - -//=========================================================================== -// -// MapData :: GetChecksum -// -// Hashes a map based on its header, THINGS, LINEDEFS, SIDEDEFS, SECTORS, -// and BEHAVIOR lumps. Node-builder generated lumps are not included. -// -//=========================================================================== - -void MapData::GetChecksum(uint8_t cksum[16]) -{ - MD5Context md5; - - if (isText) - { - md5.Update(Reader(ML_TEXTMAP), Size(ML_TEXTMAP)); - } - else - { - md5.Update(Reader(ML_LABEL), Size(ML_LABEL)); - md5.Update(Reader(ML_THINGS), Size(ML_THINGS)); - md5.Update(Reader(ML_LINEDEFS), Size(ML_LINEDEFS)); - md5.Update(Reader(ML_SIDEDEFS), Size(ML_SIDEDEFS)); - md5.Update(Reader(ML_SECTORS), Size(ML_SECTORS)); - } - if (HasBehavior) - { - md5.Update(Reader(ML_BEHAVIOR), Size(ML_BEHAVIOR)); - } - md5.Final(cksum); -} - -DEFINE_ACTION_FUNCTION(FLevelLocals, GetChecksum) -{ - PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); - char md5string[33]; - - for(int j = 0; j < 16; ++j) - { - sprintf(md5string + j * 2, "%02x", level.md5[j]); - } - - ACTION_RETURN_STRING((const char*)md5string); -} - //=========================================================================== // // Sets a sidedef's texture and prints a message if it's not present. diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index ad44203b1..b29af9f9c 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -2506,6 +2506,19 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, GetUDMFString, ZGetUDMFString) ACTION_RETURN_STRING(GetUDMFString(type, index, key)); } +DEFINE_ACTION_FUNCTION(FLevelLocals, GetChecksum) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + char md5string[33]; + + for (int j = 0; j < 16; ++j) + { + sprintf(md5string + j * 2, "%02x", level.md5[j]); + } + + ACTION_RETURN_STRING((const char*)md5string); +} + //===================================================================================== // //