From beccc5eac5c672fa5784f54559cae56a5ed63786 Mon Sep 17 00:00:00 2001 From: danij Date: Sun, 28 Apr 2013 12:22:59 +0100 Subject: [PATCH] Server: Investigating non identifiable sound emitters --- doomsday/client/include/map/gamemap.h | 6 ++++ doomsday/client/include/map/polyobj.h | 8 +++++ doomsday/client/src/map/gamemap.cpp | 33 ++++++++++++++++++++ doomsday/client/src/map/polyobj.cpp | 10 +++++++ doomsday/client/src/map/r_world.cpp | 40 +++++++++++++++++++++++++ doomsday/server/src/server/sv_sound.cpp | 34 +++++---------------- 6 files changed, 105 insertions(+), 26 deletions(-) diff --git a/doomsday/client/include/map/gamemap.h b/doomsday/client/include/map/gamemap.h index 42326395ac..96b1489fd6 100644 --- a/doomsday/client/include/map/gamemap.h +++ b/doomsday/client/include/map/gamemap.h @@ -217,6 +217,12 @@ class GameMap */ Surface *surfaceBySoundEmitter(ddmobj_base_t const &soundEmitter) const; +//#ifdef __SERVER__ + /// @return @c true iff @a emitter is an identifiable map element. + bool identifySoundEmitter(ddmobj_base_t const &emitter, Sector **sector, + Polyobj **poly, Plane **plane, Surface **surface) const; +//#endif + /** * Provides access to the list of polyobjs for efficient traversal. */ diff --git a/doomsday/client/include/map/polyobj.h b/doomsday/client/include/map/polyobj.h index 531da7dd4c..4eeb89df7f 100644 --- a/doomsday/client/include/map/polyobj.h +++ b/doomsday/client/include/map/polyobj.h @@ -55,6 +55,14 @@ typedef struct polyobj_s /// @note: Does nothing about the user data section. ~polyobj_s(); + /** + * Returns the sound emitter for the polyobj. + */ + ddmobj_base_t &soundEmitter(); + + /// @copydoc soundEmitter() + ddmobj_base_t const &soundEmitter() const; + /** * Provides access to the list of Lines for the polyobj. */ diff --git a/doomsday/client/src/map/gamemap.cpp b/doomsday/client/src/map/gamemap.cpp index 959f4a869a..c722b5f2cf 100644 --- a/doomsday/client/src/map/gamemap.cpp +++ b/doomsday/client/src/map/gamemap.cpp @@ -759,6 +759,39 @@ Surface *GameMap::surfaceBySoundEmitter(ddmobj_base_t const &soundEmitter) const return 0; // Not found. } +//#ifdef __SERVER__ +bool GameMap::identifySoundEmitter(ddmobj_base_t const &emitter, Sector **sector, + Polyobj **poly, Plane **plane, Surface **surface) const +{ + *sector = 0; + *poly = 0; + *plane = 0; + *surface = 0; + + /// @todo Optimize: All sound emitters in a sector are linked together forming + /// a chain. Make use of the chains instead. + + *poly = polyobjByBase(emitter); + if(!*poly) + { + // Not a polyobj. Try the sectors next. + *sector = sectorBySoundEmitter(emitter); + if(!*sector) + { + // Not a sector. Try the planes next. + *plane = planeBySoundEmitter(emitter); + if(!*plane) + { + // Not a plane. Try the surfaces next. + *surface = surfaceBySoundEmitter(emitter); + } + } + } + + return (!*sector || !*poly || !*plane || !*surface); +} +//#endif // __SERVER__ + Polyobj *GameMap::polyobjByTag(int tag) const { foreach(Polyobj *polyobj, _polyobjs) diff --git a/doomsday/client/src/map/polyobj.cpp b/doomsday/client/src/map/polyobj.cpp index baa4adc878..a8f8a869f0 100644 --- a/doomsday/client/src/map/polyobj.cpp +++ b/doomsday/client/src/map/polyobj.cpp @@ -109,6 +109,16 @@ void Polyobj::setCollisionCallback(void (*func) (mobj_t *mobj, void *line, void collisionCallback = func; } +ddmobj_base_t &Polyobj::soundEmitter() +{ + return *reinterpret_cast(this); +} + +ddmobj_base_t const &Polyobj::soundEmitter() const +{ + return const_cast(const_cast(*this).soundEmitter()); +} + Polyobj::Lines const &Polyobj::lines() const { return *static_cast(_lines); diff --git a/doomsday/client/src/map/r_world.cpp b/doomsday/client/src/map/r_world.cpp index 4616767114..733270417a 100644 --- a/doomsday/client/src/map/r_world.cpp +++ b/doomsday/client/src/map/r_world.cpp @@ -735,6 +735,41 @@ static void updateAllMapSectors(GameMap &map) } } +#if /*defined(__SERVER__) &&*/ defined(DENG_DEBUG) +static void verifyAllSoundEmitters() +{ + DENG_ASSERT(theMap != 0); + + Sector *emSec; + Plane *emPln; + Polyobj *emPoly; + Surface *emSuf; + foreach(Sector *sector, theMap->sectors()) + { + DENG_ASSERT(theMap->identifySoundEmitter(sector->soundEmitter(), &emSec, &emPoly, &emPln, &emSuf)); + + foreach(Plane *plane, sector->planes()) + { + DENG_ASSERT(theMap->identifySoundEmitter(plane->soundEmitter(), &emSec, &emPoly, &emPln, &emSuf)); + } + } + foreach(Polyobj *polyobj, theMap->polyobjs()) + { + DENG_ASSERT(theMap->identifySoundEmitter(polyobj->soundEmitter(), &emSec, &emPoly, &emPln, &emSuf)); + } + foreach(Line *line, theMap->lines()) + for(int i = 0; i < 2; ++i) + { + Line::Side &side = line->side(i); + if(!side.hasSections()) continue; + + DENG_ASSERT(theMap->identifySoundEmitter(side.middleSoundEmitter(), &emSec, &emPoly, &emPln, &emSuf)); + DENG_ASSERT(theMap->identifySoundEmitter(side.bottomSoundEmitter(), &emSec, &emPoly, &emPln, &emSuf)); + DENG_ASSERT(theMap->identifySoundEmitter(side.topSoundEmitter(), &emSec, &emPoly, &emPln, &emSuf)); + } +} +#endif // defined(__SERVER__) && defined(DENG_DEBUG) + #undef R_SetupMap DENG_EXTERN_C void R_SetupMap(int mode, int flags) { @@ -808,6 +843,11 @@ DENG_EXTERN_C void R_SetupMap(int mode, int flags) // Map setup has been completed. +#if /*defined(__SERVER__) &&*/ defined(DENG_DEBUG) + // Ensure all sound emitters are identifiable. + verifyAllSoundEmitters(); +#endif + // Run any commands specified in Map Info. de::Uri mapUri = theMap->uri(); ded_mapinfo_t *mapInfo = Def_GetMapInfo(reinterpret_cast(&mapUri)); diff --git a/doomsday/server/src/server/sv_sound.cpp b/doomsday/server/src/server/sv_sound.cpp index 16a22215cf..934df8b1ff 100644 --- a/doomsday/server/src/server/sv_sound.cpp +++ b/doomsday/server/src/server/sv_sound.cpp @@ -35,7 +35,7 @@ static inline boolean isRealMobj(const mobj_t* base) /** * Find the map object to whom @a base belongs. */ -static void Sv_IdentifySoundBase(mobj_t **base, Sector **sector, Polyobj **poly, +static void identifySoundEmitter(mobj_t **base, Sector **sector, Polyobj **poly, Plane **plane, Surface **surface) { *sector = 0; @@ -45,31 +45,13 @@ static void Sv_IdentifySoundBase(mobj_t **base, Sector **sector, Polyobj **poly, if(!*base || isRealMobj(*base)) return; - /// @todo Optimize: All sound emitters in a sector are linked together forming - /// a chain. Make use of the chains instead. + theMap->identifySoundEmitter(*reinterpret_cast(*base), + sector, poly, plane, surface); - // No mobj ID => it's not a real mobj. - *poly = theMap->polyobjByBase(*reinterpret_cast(base)); - if(!*poly) - { - // Not a polyobj. Try the sectors next. - *sector = theMap->sectorBySoundEmitter(*reinterpret_cast(base)); - if(!*sector) - { - // Not a sector. Try the planes next. - *plane = theMap->planeBySoundEmitter(*reinterpret_cast(base)); - if(!*plane) - { - // Not a plane. Try the surfaces next. - *surface = theMap->surfaceBySoundEmitter(*reinterpret_cast(base)); - } - } - } - -#ifdef _DEBUG +#ifdef DENG_DEBUG if(!*sector && !*poly && !*plane && !*surface) { - Con_Error("Sv_IdentifySoundBase: Bad sound base.\n"); + throw de::Error("Sv_IdentifySoundBase", "Bad sound base."); } #endif @@ -81,7 +63,7 @@ void Sv_Sound(int soundId, mobj_t* origin, int toPlr) Sv_SoundAtVolume(soundId, origin, 1, toPlr); } -void Sv_SoundAtVolume(int soundIDAndFlags, mobj_t* origin, float volume, int toPlr) +void Sv_SoundAtVolume(int soundIDAndFlags, mobj_t *origin, float volume, int toPlr) { if(isClient) return; @@ -92,7 +74,7 @@ void Sv_SoundAtVolume(int soundIDAndFlags, mobj_t* origin, float volume, int toP Polyobj *poly; Plane *plane; Surface *surface; - Sv_IdentifySoundBase(&origin, §or, &poly, &plane, &surface); + identifySoundEmitter(&origin, §or, &poly, &plane, &surface); int targetPlayers = 0; if(toPlr & SVSF_TO_ALL) @@ -128,7 +110,7 @@ void Sv_StopSound(int soundId, mobj_t *origin) Polyobj *poly; Plane *plane; Surface *surface; - Sv_IdentifySoundBase(&origin, §or, &poly, &plane, &surface); + identifySoundEmitter(&origin, §or, &poly, &plane, &surface); LOG_TRACE("Sv_StopSound: id: #%i origin: %i(%p) sec: %p poly: %p plane: %p surface: %p") << soundId << (origin? origin->thinker.id : 0)