mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-13 07:57:52 +00:00
- moved P_OpenMapData and related content out of p_setup.cpp.
This commit is contained in:
parent
3291d8e9ac
commit
0faa9111b9
5 changed files with 478 additions and 430 deletions
|
@ -963,6 +963,7 @@ set (PCH_SOURCES
|
||||||
p_map.cpp
|
p_map.cpp
|
||||||
p_maputl.cpp
|
p_maputl.cpp
|
||||||
p_mobj.cpp
|
p_mobj.cpp
|
||||||
|
p_openmap.cpp
|
||||||
p_pillar.cpp
|
p_pillar.cpp
|
||||||
p_plats.cpp
|
p_plats.cpp
|
||||||
p_pspr.cpp
|
p_pspr.cpp
|
||||||
|
|
|
@ -46,7 +46,54 @@
|
||||||
#include "r_data/r_sections.h"
|
#include "r_data/r_sections.h"
|
||||||
#include "r_data/r_canvastexture.h"
|
#include "r_data/r_canvastexture.h"
|
||||||
|
|
||||||
struct FLevelLocals
|
|
||||||
|
struct FLevelData
|
||||||
|
{
|
||||||
|
TArray<vertex_t> vertexes;
|
||||||
|
TArray<sector_t> sectors;
|
||||||
|
TArray<line_t*> linebuffer; // contains the line lists for the sectors.
|
||||||
|
TArray<line_t> lines;
|
||||||
|
TArray<side_t> sides;
|
||||||
|
TArray<seg_t> segs;
|
||||||
|
TArray<subsector_t> subsectors;
|
||||||
|
TArray<node_t> nodes;
|
||||||
|
TArray<subsector_t> gamesubsectors;
|
||||||
|
TArray<node_t> gamenodes;
|
||||||
|
node_t *headgamenode;
|
||||||
|
TArray<uint8_t> rejectmatrix;
|
||||||
|
TArray<zone_t> Zones;
|
||||||
|
|
||||||
|
TArray<FSectorPortal> sectorPortals;
|
||||||
|
TArray<FLinePortal> linePortals;
|
||||||
|
|
||||||
|
// Portal information.
|
||||||
|
FDisplacementTable Displacements;
|
||||||
|
FPortalBlockmap PortalBlockmap;
|
||||||
|
TArray<FLinePortal*> linkedPortals; // only the linked portals, this is used to speed up looking for them in P_CollectConnectedGroups.
|
||||||
|
TArray<FSectorPortalGroup *> portalGroups;
|
||||||
|
TArray<FLinePortalSpan> linePortalSpans;
|
||||||
|
FSectionContainer sections;
|
||||||
|
FCanvasTextureInfo canvasTextureInfo;
|
||||||
|
|
||||||
|
// [ZZ] Destructible geometry information
|
||||||
|
TMap<int, FHealthGroup> 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<sector_t> loadsectors;
|
||||||
|
TArray<line_t> loadlines;
|
||||||
|
TArray<side_t> loadsides;
|
||||||
|
|
||||||
|
// Maintain single and multi player starting spots.
|
||||||
|
TArray<FPlayerStart> deathmatchstarts;
|
||||||
|
FPlayerStart playerstarts[MAXPLAYERS];
|
||||||
|
TArray<FPlayerStart> AllPlayerStarts;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FLevelLocals : public FLevelData
|
||||||
{
|
{
|
||||||
void Tick();
|
void Tick();
|
||||||
void Mark();
|
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)
|
uint64_t ShaderStartTime = 0; // tell the shader system when we started the level (forces a timer restart)
|
||||||
|
|
||||||
TArray<vertex_t> vertexes;
|
|
||||||
TArray<sector_t> sectors;
|
|
||||||
TArray<line_t*> linebuffer; // contains the line lists for the sectors.
|
|
||||||
TArray<line_t> lines;
|
|
||||||
TArray<side_t> sides;
|
|
||||||
TArray<seg_t> segs;
|
|
||||||
TArray<subsector_t> subsectors;
|
|
||||||
TArray<node_t> nodes;
|
|
||||||
TArray<subsector_t> gamesubsectors;
|
|
||||||
TArray<node_t> gamenodes;
|
|
||||||
node_t *headgamenode;
|
|
||||||
TArray<uint8_t> rejectmatrix;
|
|
||||||
|
|
||||||
static const int BODYQUESIZE = 32;
|
static const int BODYQUESIZE = 32;
|
||||||
TObjPtr<AActor*> bodyque[BODYQUESIZE];
|
TObjPtr<AActor*> bodyque[BODYQUESIZE];
|
||||||
int bodyqueslot;
|
int bodyqueslot;
|
||||||
|
|
||||||
|
|
||||||
TArray<FSectorPortal> sectorPortals;
|
|
||||||
TArray<FLinePortal> linePortals;
|
|
||||||
|
|
||||||
// Portal information.
|
|
||||||
FDisplacementTable Displacements;
|
|
||||||
FPortalBlockmap PortalBlockmap;
|
|
||||||
TArray<FLinePortal*> linkedPortals; // only the linked portals, this is used to speed up looking for them in P_CollectConnectedGroups.
|
|
||||||
TArray<FSectorPortalGroup *> portalGroups;
|
|
||||||
TArray<FLinePortalSpan> linePortalSpans;
|
|
||||||
FSectionContainer sections;
|
|
||||||
FCanvasTextureInfo canvasTextureInfo;
|
|
||||||
|
|
||||||
int NumMapSections;
|
int NumMapSections;
|
||||||
|
|
||||||
TArray<zone_t> Zones;
|
|
||||||
|
|
||||||
// [ZZ] Destructible geometry information
|
|
||||||
TMap<int, FHealthGroup> 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<sector_t> loadsectors;
|
|
||||||
TArray<line_t> loadlines;
|
|
||||||
TArray<side_t> loadsides;
|
|
||||||
|
|
||||||
// Maintain single and multi player starting spots.
|
|
||||||
TArray<FPlayerStart> deathmatchstarts;
|
|
||||||
FPlayerStart playerstarts[MAXPLAYERS];
|
|
||||||
TArray<FPlayerStart> AllPlayerStarts;
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t flags2;
|
uint32_t flags2;
|
||||||
uint32_t flags3;
|
uint32_t flags3;
|
||||||
|
@ -224,6 +226,8 @@ struct FLevelLocals
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef NO_DEFINE_LEVEL
|
||||||
|
|
||||||
extern FLevelLocals level;
|
extern FLevelLocals level;
|
||||||
|
|
||||||
inline int vertex_t::Index() const
|
inline int vertex_t::Index() const
|
||||||
|
@ -350,3 +354,4 @@ inline bool line_t::hitSkyWall(AActor* mo) const
|
||||||
backsector->GetTexture(sector_t::ceiling) == skyflatnum &&
|
backsector->GetTexture(sector_t::ceiling) == skyflatnum &&
|
||||||
mo->Z() >= backsector->ceilingplane.ZatPoint(mo->PosRelative(this));
|
mo->Z() >= backsector->ceilingplane.ZatPoint(mo->PosRelative(this));
|
||||||
}
|
}
|
||||||
|
#endif
|
413
src/p_openmap.cpp
Normal file
413
src/p_openmap.cpp
Normal file
|
@ -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;i<countof(check);i++)
|
||||||
|
{
|
||||||
|
if (!strnicmp(lumpname, check[i].lumpname, 8))
|
||||||
|
return (int)i;
|
||||||
|
|
||||||
|
if (check[i].required)
|
||||||
|
{
|
||||||
|
if (needrequired)
|
||||||
|
{
|
||||||
|
I_Error("'%s' not found in %s\n", check[i].lumpname, mapname);
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1; // End of map reached
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Opens a map for reading
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
MapData *P_OpenMapData(const char * mapname, bool justcheck)
|
||||||
|
{
|
||||||
|
MapData * map = new MapData;
|
||||||
|
FileReader * wadReader = nullptr;
|
||||||
|
bool externalfile = !strnicmp(mapname, "file:", 5);
|
||||||
|
|
||||||
|
if (externalfile)
|
||||||
|
{
|
||||||
|
mapname += 5;
|
||||||
|
if (!FileExists(mapname))
|
||||||
|
{
|
||||||
|
delete map;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
map->resource = 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);
|
||||||
|
}
|
384
src/p_setup.cpp
384
src/p_setup.cpp
|
@ -136,11 +136,6 @@ CVAR (Bool, showloadtimes, false, 0);
|
||||||
|
|
||||||
static void P_Shutdown ();
|
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)
|
inline bool P_LoadBuildMap(uint8_t *mapdata, size_t len, FMapThing **things, int *numthings)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -168,385 +163,6 @@ bool ForceNodeBuild;
|
||||||
|
|
||||||
static void P_AllocateSideDefs (MapData *map, int count);
|
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;i<countof(check);i++)
|
|
||||||
{
|
|
||||||
if (!strnicmp(lumpname, check[i].lumpname, 8))
|
|
||||||
return (int)i;
|
|
||||||
|
|
||||||
if (check[i].required)
|
|
||||||
{
|
|
||||||
if (needrequired)
|
|
||||||
{
|
|
||||||
I_Error("'%s' not found in %s\n", check[i].lumpname, mapname);
|
|
||||||
}
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1; // End of map reached
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// Opens a map for reading
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
MapData *P_OpenMapData(const char * mapname, bool justcheck)
|
|
||||||
{
|
|
||||||
MapData * map = new MapData;
|
|
||||||
FileReader * wadReader = nullptr;
|
|
||||||
bool externalfile = !strnicmp(mapname, "file:", 5);
|
|
||||||
|
|
||||||
if (externalfile)
|
|
||||||
{
|
|
||||||
mapname += 5;
|
|
||||||
if (!FileExists(mapname))
|
|
||||||
{
|
|
||||||
delete map;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
map->resource = 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.
|
// Sets a sidedef's texture and prints a message if it's not present.
|
||||||
|
|
|
@ -2506,6 +2506,19 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, GetUDMFString, ZGetUDMFString)
|
||||||
ACTION_RETURN_STRING(GetUDMFString(type, index, key));
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
//=====================================================================================
|
//=====================================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in a new issue