Skip to content

Commit

Permalink
Fixed: Crash warping to a map without MapInfo data
Browse files Browse the repository at this point in the history
Added fallback MapInfo data to be used as a last resort, when no def
is defined for the current map and the game does not provide its own
fallback definition (associated with URI "Maps:*").

One can now assume that effective MapInfo data is always available,
irrespective of whether its explicitly defined.

IssueID #1982
  • Loading branch information
danij-deng committed Mar 2, 2015
1 parent c295277 commit 8e6b656
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 207 deletions.
7 changes: 7 additions & 0 deletions doomsday/client/include/world/map.h
Expand Up @@ -166,6 +166,13 @@ class Map
*/
void setDef(MapDef *newMapDefinition);

/**
* Returns the effective map-info definition Record for the map.
*
* @see WorldSystem::mapInfoForMapUri()
*/
de::Record const &mapInfo() const;

/**
* Returns the points which describe the boundary of the map coordinate
* space, which, are defined by the minimal and maximal vertex coordinates
Expand Down
15 changes: 14 additions & 1 deletion doomsday/client/include/world/worldsystem.h
Expand Up @@ -93,7 +93,7 @@ class WorldSystem : public de::System
void update();

/**
* Returns @c true iff a map is currently loaded.
* Returns @c true if a map is currently loaded.
*/
bool hasMap() const;

Expand All @@ -104,6 +104,11 @@ class WorldSystem : public de::System
*/
Map &map() const;

/**
* Returns a pointer to the currently loaded map, if any.
*/
inline Map *mapPtr() const { return hasMap()? &map() : nullptr; }

/**
* @param uri Universal resource identifier (URI) for the map to change to.
* If an empty URI is specified the current map will be unloaded.
Expand All @@ -119,6 +124,14 @@ class WorldSystem : public de::System
*/
inline void unloadMap() { changeMap(Uri()); }

/**
* Returns the effective map-info definition Record associated with the given
* @a mapUri (which may be the default definition, if invalid/unknown).
*
* @param mapUri Unique identifier for the map to lookup map-info data for.
*/
Record const &mapInfoForMapUri(Uri const &mapUri) const;

/**
* Advance time in the world.
*
Expand Down
5 changes: 4 additions & 1 deletion doomsday/client/src/audio/s_main.cpp
Expand Up @@ -493,7 +493,10 @@ int S_StartMusic(char const *musicID, dd_bool looped)
int idx = Def_GetMusicNum(musicID);
if(idx < 0)
{
LOG_AUDIO_WARNING("Song \"%s\" not defined, cannot start playback") << musicID;
if(musicID && qstrlen(musicID))
{
LOG_AUDIO_WARNING("Song \"%s\" not defined, cannot start playback") << musicID;
}
return false;
}
return S_StartMusicNum(idx, looped);
Expand Down
9 changes: 1 addition & 8 deletions doomsday/client/src/dd_main.cpp
Expand Up @@ -2503,14 +2503,7 @@ int DD_GetInteger(int ddvalue)
case DD_MAP_MUSIC:
if(App_WorldSystem().hasMap())
{
if(MapDef *mapDef = App_WorldSystem().map().def())
{
int idx = defs.getMapInfoNum(mapDef->composeUri());
if(idx >= 0)
{
return Def_GetMusicNum(defs.mapInfos[idx].gets("music").toUtf8().constData());
}
}
return Def_GetMusicNum(App_WorldSystem().map().mapInfo().gets("music").toUtf8().constData());
}
return -1;

Expand Down
14 changes: 2 additions & 12 deletions doomsday/client/src/gl/gl_main.cpp
Expand Up @@ -648,18 +648,8 @@ void GL_TotalRestore()
//Con_Resize();

// Restore the fog settings.
Record const *mapInfo = 0;
if(App_WorldSystem().hasMap())
{
Map &map = App_WorldSystem().map();
mapInfo = defs.mapInfos.tryFind("id", map.def()->composeUri());
if(!mapInfo)
{
// Use the default def instead.
mapInfo = defs.mapInfos.tryFind("id", de::Uri("Maps", Path("*")));
}
}
GL_SetupFogFromMapInfo(mapInfo);
Map const *map = App_WorldSystem().mapPtr();
GL_SetupFogFromMapInfo(map? &map->mapInfo() : nullptr);

#if _DEBUG
Z_CheckHeap();
Expand Down
68 changes: 25 additions & 43 deletions doomsday/client/src/world/map.cpp
Expand Up @@ -96,14 +96,17 @@ static int lgMXSample = 1; ///< 5 samples per block. Cvar.
#define CLMOBJ_TIMEOUT 4000
#endif

namespace de {

#ifdef __CLIENT__
static inline WorldSystem &worldSys()
namespace internal
{
return App_WorldSystem();
}
#endif
static inline de::WorldSystem &worldSys()
{
return App_WorldSystem();
}

} // namespace internal
using namespace internal;

namespace de {

struct EditableElements
{
Expand Down Expand Up @@ -1581,6 +1584,11 @@ void Map::setDef(MapDef *newMapDefinition)
d->def = newMapDefinition;
}

Record const &Map::mapInfo() const
{
return worldSys().mapInfoForMapUri(def()? def()->composeUri() : de::Uri("Maps:", RC_NULL));
}

Mesh const &Map::mesh() const
{
return d->mesh;
Expand Down Expand Up @@ -3132,51 +3140,25 @@ void Map::update()
#endif // __CLIENT__

// Reapply values defined in MapInfo (they may have changed).
defn::MapInfo mapInfo;
Record const &inf = mapInfo();

if(MapDef *mapDef = d->def)
{
int idx = defs.getMapInfoNum(mapDef->composeUri());
if(idx >= 0) mapInfo = defs.mapInfos[idx];
}

if(!mapInfo)
{
// Use the default def instead.
int idx = defs.getMapInfoNum(Uri("Maps", Path("*")));
if(idx >= 0) mapInfo = defs.mapInfos[idx];
}

if(mapInfo)
{
_globalGravity = mapInfo.getf("gravity");
_ambientLightLevel = mapInfo.getf("ambient") * 255;
}
else
{
// No map info found -- apply defaults.
_globalGravity = 1.0f;
_ambientLightLevel = 0;
}

_effectiveGravity = _globalGravity;
_ambientLightLevel = inf.getf("ambient") * 255;
_globalGravity = inf.getf("gravity");
_effectiveGravity = _globalGravity;

#ifdef __CLIENT__
// Reconfigure the sky.
/// @todo Sky needs breaking up into multiple components. There should be
/// a representation on server side and a logical entity which the renderer
/// visualizes. We also need multiple concurrent skies for BOOM support.
defn::Sky skyDef;
if(mapInfo)
if(Record const *def = defs.skies.tryFind("id", inf.gets("skyId")))
{
if(Record const *def = defs.skies.tryFind("id", mapInfo.gets("skyId")))
{
skyDef = *def;
}
else
{
skyDef = mapInfo.subrecord("sky");
}
skyDef = *def;
}
else
{
skyDef = inf.subrecord("sky");
}
sky().configure(&skyDef);
#endif
Expand Down
85 changes: 38 additions & 47 deletions doomsday/client/src/world/worldsystem.cpp
Expand Up @@ -285,14 +285,19 @@ namespace de {
DENG2_PIMPL(WorldSystem)
{
Map *map = nullptr; ///< Current map.
Record fallbackMapInfo; ///< Used when no effective MapInfo definition.

timespan_t time = 0; ///< World-wide time.
#ifdef __CLIENT__
std::unique_ptr<Hand> hand; ///< For map editing/manipulation.
SkyDrawable::Animator skyAnimator;
#endif

Instance(Public *i) : Base(i)
{}
{
// One time init of the fallback MapInfo definition.
defn::MapInfo(fallbackMapInfo).resetToDefaults();
}

/**
* Compose the relative path (relative to the runtime directory) to the
Expand Down Expand Up @@ -457,48 +462,22 @@ DENG2_PIMPL(WorldSystem)
LOG_MAP_NOTE("%s") << map->elementSummaryAsStyledText();

// See what MapInfo says about this map.
defn::MapInfo mapInfo;

if(MapDef *mapDef = map->def())
{
int idx = defs.getMapInfoNum(mapDef->composeUri());
if(idx >= 0) mapInfo = defs.mapInfos[idx];
}

if(!mapInfo)
{
// Use the default def instead.
int idx = defs.getMapInfoNum(Uri("Maps", Path("*")));
if(idx >= 0) mapInfo = defs.mapInfos[idx];
}

if(mapInfo)
{
map->_globalGravity = mapInfo.getf("gravity");
map->_ambientLightLevel = mapInfo.getf("ambient") * 255;
}
else
{
// No map info found -- apply defaults.
map->_globalGravity = 1.0f;
map->_ambientLightLevel = 0;
}
Record const &mapInfo = map->mapInfo();

map->_effectiveGravity = map->_globalGravity;
map->_ambientLightLevel = mapInfo.getf("ambient") * 255;
map->_globalGravity = mapInfo.getf("gravity");
map->_effectiveGravity = map->_globalGravity;

#ifdef __CLIENT__
// Reconfigure the sky.
defn::Sky skyDef;
if(mapInfo)
if(Record const *def = defs.skies.tryFind("id", mapInfo.gets("skyId")))
{
if(Record const *def = defs.skies.tryFind("id", mapInfo.gets("skyId")))
{
skyDef = *def;
}
else
{
skyDef = mapInfo.subrecord("sky");
}
skyDef = *def;
}
else
{
skyDef = mapInfo.subrecord("sky");
}
map->sky().configure(&skyDef);

Expand Down Expand Up @@ -526,10 +505,9 @@ DENG2_PIMPL(WorldSystem)

// The game may need to perform it's own finalization now that the
// "current" map has changed.
de::Uri const mapUri = (map->def()? map->def()->composeUri() : de::Uri("Maps:", RC_NULL));
if(gx.FinalizeMapChange)
{
de::Uri mapUri("Maps:", RC_NULL);
if(map->def()) mapUri = map->def()->composeUri();
gx.FinalizeMapChange(reinterpret_cast<uri_s const *>(&mapUri));
}

Expand Down Expand Up @@ -641,20 +619,17 @@ DENG2_PIMPL(WorldSystem)
*/

// Run any commands specified in MapInfo.
if(mapInfo)
String execute = mapInfo.gets("execute");
if(!execute.isEmpty())
{
String execute = mapInfo.gets("execute");
if(!execute.isEmpty())
{
Con_Execute(CMDS_SCRIPT, execute.toUtf8().constData(), true, false);
}
Con_Execute(CMDS_SCRIPT, execute.toUtf8().constData(), true, false);
}

// Run the special map setup command, which the user may alias to do
// something useful.
if(MapDef *mapDef = map->def())
if(!mapUri.isEmpty())
{
String cmd = String("init-") + mapDef->composeUri().path();
String cmd = String("init-") + mapUri.path();
if(Con_IsValidCommand(cmd.toUtf8().constData()))
{
Con_Executef(CMDS_SCRIPT, false, "%s", cmd.toUtf8().constData());
Expand Down Expand Up @@ -893,6 +868,22 @@ void WorldSystem::update()
}
}

Record const &WorldSystem::mapInfoForMapUri(de::Uri const &mapUri) const
{
// Is there a MapInfo definition for the given URI?
if(Record const *def = defs.mapInfos.tryFind("id", mapUri.compose()))
{
return *def;
}
// Is there is a default definition (for all maps)?
if(Record const *def = defs.mapInfos.tryFind("id", de::Uri("Maps", Path("*")).compose()))
{
return *def;
}
// Use the fallback.
return d->fallbackMapInfo;
}

void WorldSystem::advanceTime(timespan_t delta)
{
#ifdef __CLIENT__
Expand Down
6 changes: 3 additions & 3 deletions doomsday/libcore/include/de/game/session.h
Expand Up @@ -74,7 +74,7 @@ class DENG2_PUBLIC Session
* Determines whether the currently configured game session is in progress. Usually this
* will not be the case during title sequences (for example).
*/
virtual bool hasBegun() = 0;
virtual bool hasBegun() const = 0;

/**
* Determines whether the game state currently allows the session to be saved.
Expand Down Expand Up @@ -102,7 +102,7 @@ class DENG2_PUBLIC Session
*/
virtual void load(String const &saveName) = 0;

protected: // Saved session management -------------------------------------------------------
protected: // Saved session management: ---------------------------------------------------

/**
* Makes a copy of the saved session specified.
Expand All @@ -117,7 +117,7 @@ class DENG2_PUBLIC Session
*/
static void removeSaved(String const &path);

public: // Saved session index ---------------------------------------------------------------
public: // Saved session index: -----------------------------------------------------------

/// @todo Integrate this functionality into the filesystem.
class DENG2_PUBLIC SavedIndex
Expand Down
10 changes: 10 additions & 0 deletions doomsday/plugins/common/include/g_common.h
Expand Up @@ -84,6 +84,16 @@ void G_SetGameActionMapCompleted(de::Uri const &nextMapUri, uint nextMapEntryPoi
*/
de::String G_EpisodeTitle(de::String episodeId);

/**
* Returns the effective map-info definition Record associated with the given
* @a mapUri (which may be the default definition, if invalid/unknown).
*
* @param mapUri Unique identifier for the map to lookup map-info data for.
*
* @todo: Should use WorldSystem::mapInfoForMapUri() instead.
*/
de::Record const &G_MapInfoForMapUri(de::Uri const &mapUri);

/**
* @param mapUri Identifier of the map to lookup the author of.
*/
Expand Down

0 comments on commit 8e6b656

Please sign in to comment.