Torque3D Documentation / _generateds / gameConnectionEvents.cpp

gameConnectionEvents.cpp

Engine/source/T3D/gameBase/gameConnectionEvents.cpp

More...

Public Defines

define
DebugChecksum() 0xF00DBAAD

Public Functions

ConsoleDocClass(SetMissionCRCEvent , "@brief Use by <a href="/coding/class/classgameconnection/">GameConnection</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> send <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3D sound event over the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">network.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, internal use only, but does expose <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameConnection::setMissionCRC.\n\n</a> " " @internal" )
ConsoleDocClass(Sim2DAudioEvent , "@brief Use by <a href="/coding/class/classgameconnection/">GameConnection</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> send <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 2D sound event over the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">network.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, internal use only, but does expose <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameConnection::play2D.\n\n</a> " " @internal" )
ConsoleDocClass(Sim3DAudioEvent , "@brief Use by <a href="/coding/class/classgameconnection/">GameConnection</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> send <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3D sound event over the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">network.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, internal use only, but does expose <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameConnection::play3D.\n\n</a> " " @internal" )
ConsoleDocClass(SimDataBlockEvent , "@brief Use by <a href="/coding/class/classgameconnection/">GameConnection</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> process incoming <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablocks.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, internal use only, but does expose <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">onDataBlockObjectReceived.\n\n</a> " " @internal" )

Detailed Description

Public Defines

DebugChecksum() 0xF00DBAAD

Public Variables

F32 SoundPosAccuracy 
S32 SoundRotBits 

Public Functions

ConsoleDocClass(SetMissionCRCEvent , "@brief Use by <a href="/coding/class/classgameconnection/">GameConnection</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> send <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3D sound event over the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">network.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, internal use only, but does expose <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameConnection::setMissionCRC.\n\n</a> " " @internal" )

ConsoleDocClass(Sim2DAudioEvent , "@brief Use by <a href="/coding/class/classgameconnection/">GameConnection</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> send <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 2D sound event over the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">network.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, internal use only, but does expose <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameConnection::play2D.\n\n</a> " " @internal" )

ConsoleDocClass(Sim3DAudioEvent , "@brief Use by <a href="/coding/class/classgameconnection/">GameConnection</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> send <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3D sound event over the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">network.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, internal use only, but does expose <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GameConnection::play3D.\n\n</a> " " @internal" )

ConsoleDocClass(SimDataBlockEvent , "@brief Use by <a href="/coding/class/classgameconnection/">GameConnection</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> process incoming <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablocks.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, internal use only, but does expose <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">onDataBlockObjectReceived.\n\n</a> " " @internal" )

IMPLEMENT_CO_CLIENTEVENT_V1(SetMissionCRCEvent )

IMPLEMENT_CO_CLIENTEVENT_V1(Sim2DAudioEvent )

IMPLEMENT_CO_CLIENTEVENT_V1(Sim3DAudioEvent )

IMPLEMENT_CO_CLIENTEVENT_V1(SimDataBlockEvent )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 25// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
 26// Copyright (C) 2015 Faust Logic, Inc.
 27//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 28
 29#include "platform/platform.h"
 30#include "core/dnet.h"
 31#include "core/stream/bitStream.h"
 32#include "console/consoleTypes.h"
 33#include "console/simBase.h"
 34#include "scene/pathManager.h"
 35#include "scene/sceneManager.h"
 36#include "sfx/sfxSystem.h"
 37#include "sfx/sfxDescription.h"
 38#include "app/game.h"
 39#include "T3D/gameBase/gameConnection.h"
 40#include "T3D/gameBase/gameConnectionEvents.h"
 41#include "console/engineAPI.h"
 42
 43#define DebugChecksum 0xF00DBAAD
 44
 45
 46//#define DEBUG_SPEW
 47
 48
 49//--------------------------------------------------------------------------
 50IMPLEMENT_CO_CLIENTEVENT_V1(SimDataBlockEvent);
 51IMPLEMENT_CO_CLIENTEVENT_V1(Sim2DAudioEvent);
 52IMPLEMENT_CO_CLIENTEVENT_V1(Sim3DAudioEvent);
 53IMPLEMENT_CO_CLIENTEVENT_V1(SetMissionCRCEvent);
 54
 55ConsoleDocClass( SimDataBlockEvent,
 56            "@brief Use by GameConnection to process incoming datablocks.\n\n"
 57            "Not intended for game development, internal use only, but does expose onDataBlockObjectReceived.\n\n "
 58            "@internal");
 59
 60ConsoleDocClass( Sim2DAudioEvent,
 61            "@brief Use by GameConnection to send a 2D sound event over the network.\n\n"
 62            "Not intended for game development, internal use only, but does expose GameConnection::play2D.\n\n "
 63            "@internal");
 64
 65ConsoleDocClass( Sim3DAudioEvent,
 66            "@brief Use by GameConnection to send a 3D sound event over the network.\n\n"
 67            "Not intended for game development, internal use only, but does expose GameConnection::play3D.\n\n "
 68            "@internal");
 69
 70ConsoleDocClass( SetMissionCRCEvent,
 71            "@brief Use by GameConnection to send a 3D sound event over the network.\n\n"
 72            "Not intended for game development, internal use only, but does expose GameConnection::setMissionCRC.\n\n "
 73            "@internal");
 74
 75//----------------------------------------------------------------------------
 76
 77SimDataBlockEvent::SimDataBlockEvent(SimDataBlock* obj, U32 index, U32 total, U32 missionSequence)
 78{
 79   mObj = NULL;
 80   mIndex = index;
 81   mTotal = total;
 82   mMissionSequence = missionSequence;
 83   mProcess = false;
 84
 85   if(obj)
 86   {
 87      id = obj->getId();
 88      AssertFatal(id >= DataBlockObjectIdFirst && id <= DataBlockObjectIdLast,
 89                  "Out of range event data block id... check simBase.h");
 90      
 91      #ifdef DEBUG_SPEW
 92      Con::printf("queuing data block: %d", mIndex);
 93      #endif
 94   }
 95}
 96
 97SimDataBlockEvent::~SimDataBlockEvent()
 98{
 99   if( mObj )
100      delete mObj;
101}
102
103#ifdef TORQUE_DEBUG_NET
104const char *SimDataBlockEvent::getDebugName()
105{
106   SimObject *obj = Sim::findObject(id);
107   static char buffer[256];
108   dSprintf(buffer, sizeof(buffer), "%s [%s - %s]",
109            getClassName(),
110            obj ? obj->getName() : "",
111            obj ? obj->getClassName() : "NONE");
112   return buffer;
113}
114#endif // TORQUE_DEBUG_NET
115
116void SimDataBlockEvent::notifyDelivered(NetConnection *conn, bool )
117{
118   // if the modified key for this event is not the current one,
119   // we've already resorted and resent some blocks, so fall out.
120   if(conn->isRemoved())
121      return;
122   
123   GameConnection *gc = (GameConnection *) conn;
124   if(gc->getDataBlockSequence() != mMissionSequence)
125      return;
126
127   U32 nextIndex = mIndex + DataBlockQueueCount;
128   SimDataBlockGroup *g = Sim::getDataBlockGroup();
129
130   if(mIndex == g->size() - 1)
131   {
132      gc->setDataBlockModifiedKey(gc->getMaxDataBlockModifiedKey());
133      gc->sendConnectionMessage(GameConnection::DataBlocksDone, mMissionSequence);
134   }
135
136   if(g->size() <= nextIndex)
137      return;
138
139   SimDataBlock *blk = (SimDataBlock *) (*g)[nextIndex];
140   gc->postNetEvent(new SimDataBlockEvent(blk, nextIndex, g->size(), mMissionSequence));
141}
142
143void SimDataBlockEvent::pack(NetConnection *conn, BitStream *bstream)
144{
145#ifdef AFX_CAP_DATABLOCK_CACHE 
146   ((GameConnection *)conn)->tempDisableStringBuffering(bstream);
147#endif 
148   SimDataBlock* obj;
149   Sim::findObject(id,obj);
150   GameConnection *gc = (GameConnection *) conn;
151   if(bstream->writeFlag(gc->getDataBlockModifiedKey() < obj->getModifiedKey()))
152   {
153      if(obj->getModifiedKey() > gc->getMaxDataBlockModifiedKey())
154         gc->setMaxDataBlockModifiedKey(obj->getModifiedKey());
155
156      AssertFatal(obj,
157                  "SimDataBlockEvent:: Data blocks cannot be deleted");
158      bstream->writeInt(id - DataBlockObjectIdFirst,DataBlockObjectIdBitSize);
159
160      S32 classId = obj->getClassId(conn->getNetClassGroup());
161      bstream->writeClassId(classId, NetClassTypeDataBlock, conn->getNetClassGroup());
162      bstream->writeInt(mIndex, DataBlockObjectIdBitSize);
163      bstream->writeInt(mTotal, DataBlockObjectIdBitSize + 1);
164      obj->packData(bstream);
165#ifdef TORQUE_DEBUG_NET
166      bstream->writeInt(classId ^ DebugChecksum, 32);
167#endif
168   }
169#ifdef AFX_CAP_DATABLOCK_CACHE 
170   ((GameConnection *)conn)->restoreStringBuffering(bstream);
171#endif 
172}
173
174void SimDataBlockEvent::unpack(NetConnection *cptr, BitStream *bstream)
175{
176#ifdef AFX_CAP_DATABLOCK_CACHE 
177   // stash the stream position prior to unpacking
178   S32 start_pos = bstream->getCurPos();
179   ((GameConnection *)cptr)->tempDisableStringBuffering(bstream);
180#endif
181   if(bstream->readFlag())
182   {
183      mProcess = true;
184      id = bstream->readInt(DataBlockObjectIdBitSize) + DataBlockObjectIdFirst;
185      S32 classId = bstream->readClassId(NetClassTypeDataBlock, cptr->getNetClassGroup());
186      mIndex = bstream->readInt(DataBlockObjectIdBitSize);
187      mTotal = bstream->readInt(DataBlockObjectIdBitSize + 1);
188      
189      SimObject* ptr;
190      if( Sim::findObject( id, ptr ) )
191      {
192         // An object with the given ID already exists.  Make sure it has the right class.
193         
194         AbstractClassRep* classRep = AbstractClassRep::findClassRep( cptr->getNetClassGroup(), NetClassTypeDataBlock, classId );
195         if( classRep && String::compare( classRep->getClassName(), ptr->getClassName() ) != 0 )
196         {
197            Con::warnf( "A '%s' datablock with id: %d already existed. "
198                        "Clobbering it with new '%s' datablock from server.",
199                        ptr->getClassName(), id, classRep->getClassName() );
200            ptr->deleteObject();
201            ptr = NULL;
202         }
203      }
204      
205      if( !ptr )
206         ptr = ( SimObject* ) ConsoleObject::create( cptr->getNetClassGroup(), NetClassTypeDataBlock, classId );
207         
208      mObj = dynamic_cast< SimDataBlock* >( ptr );
209      if( mObj != NULL )
210      {
211         #ifdef DEBUG_SPEW
212         Con::printf(" - SimDataBlockEvent: unpacking event of type: %s", mObj->getClassName());
213         #endif
214         
215         mObj->unpackData( bstream );
216      }
217      else
218      {
219         #ifdef DEBUG_SPEW
220         Con::printf(" - SimDataBlockEvent: INVALID PACKET!  Could not create class with classID: %d", classId);
221         #endif
222         
223         delete ptr;
224         cptr->setLastError("Invalid packet in SimDataBlockEvent::unpack()");
225      }
226
227#ifdef TORQUE_DEBUG_NET
228      U32 checksum = bstream->readInt(32);
229      AssertISV( (checksum ^ DebugChecksum) == (U32)classId,
230         avar("unpack did not match pack for event of class %s.",
231            mObj->getClassName()) );
232#endif
233
234   }
235#ifdef AFX_CAP_DATABLOCK_CACHE
236   // rewind to stream position and then process raw bytes for caching
237   ((GameConnection *)cptr)->repackClientDatablock(bstream, start_pos);
238   ((GameConnection *)cptr)->restoreStringBuffering(bstream);
239#endif
240}
241
242void SimDataBlockEvent::write(NetConnection *cptr, BitStream *bstream)
243{
244   if(bstream->writeFlag(mProcess))
245   {
246      bstream->writeInt(id - DataBlockObjectIdFirst,DataBlockObjectIdBitSize);
247      S32 classId = mObj->getClassId(cptr->getNetClassGroup());
248      bstream->writeClassId(classId, NetClassTypeDataBlock, cptr->getNetClassGroup());
249      bstream->writeInt(mIndex, DataBlockObjectIdBitSize);
250      bstream->writeInt(mTotal, DataBlockObjectIdBitSize + 1);
251      mObj->packData(bstream);
252   }
253}
254
255void SimDataBlockEvent::process(NetConnection *cptr)
256{
257   if(mProcess)
258   {
259      //call the console function to set the number of blocks to be sent
260      Con::executef("onDataBlockObjectReceived", mIndex, mTotal);
261
262      String &errorBuffer = NetConnection::getErrorBuffer();
263                     
264      // Register the datablock object if this is a new DB
265      // and not for a modified datablock event.
266         
267      if( !mObj->isProperlyAdded() )
268      {
269         // This is a fresh datablock object.
270         // Perform preload on datablock and register
271         // the object.
272
273         GameConnection* conn = dynamic_cast< GameConnection* >( cptr );
274         if( conn )
275            conn->preloadDataBlock( mObj );
276         
277         if( mObj->registerObject(id) )
278         {
279            cptr->addObject( mObj );
280            mObj = NULL;
281         }
282      }
283      else
284      {
285         // This is an update to an existing datablock.  Preload
286         // to finish this.
287
288         mObj->preload( false, errorBuffer );
289         mObj = NULL;
290      }
291   }
292}
293
294
295//----------------------------------------------------------------------------
296
297
298Sim2DAudioEvent::Sim2DAudioEvent(SFXProfile *profile)
299{
300   mProfile = profile;
301}
302
303void Sim2DAudioEvent::pack(NetConnection *, BitStream *bstream)
304{
305   bstream->writeInt( mProfile->getId() - DataBlockObjectIdFirst, DataBlockObjectIdBitSize);
306}
307
308void Sim2DAudioEvent::write(NetConnection *, BitStream *bstream)
309{
310   bstream->writeInt( mProfile->getId() - DataBlockObjectIdFirst, DataBlockObjectIdBitSize);
311}
312
313void Sim2DAudioEvent::unpack(NetConnection *, BitStream *bstream)
314{
315   SimObjectId id = bstream->readInt(DataBlockObjectIdBitSize) + DataBlockObjectIdFirst;
316   Sim::findObject(id, mProfile);
317}
318
319void Sim2DAudioEvent::process(NetConnection *)
320{
321   if (mProfile)
322      SFX->playOnce( mProfile );
323}
324
325//----------------------------------------------------------------------------
326
327static F32 SoundPosAccuracy = 0.5;
328static S32 SoundRotBits = 8;
329
330Sim3DAudioEvent::Sim3DAudioEvent(SFXProfile *profile,const MatrixF* mat)
331{
332   mProfile = profile;
333   if (mat)
334      mTransform = *mat;
335}
336
337void Sim3DAudioEvent::pack(NetConnection *con, BitStream *bstream)
338{
339   bstream->writeInt(mProfile->getId() - DataBlockObjectIdFirst, DataBlockObjectIdBitSize);
340
341   // If the sound has cone parameters, the orientation is
342   // transmitted as well.
343   SFXDescription* ad = mProfile->getDescription();
344   if ( bstream->writeFlag( ad->mConeInsideAngle || ad->mConeOutsideAngle ) ) 
345   {
346      QuatF q(mTransform);
347      q.normalize();
348
349      // LH - we can get a valid quat that's very slightly over 1 in and so
350      // this fails (barely) check against zero.  So use some error-
351      AssertFatal((1.0 - ((q.x * q.x) + (q.y * q.y) + (q.z * q.z))) >= (0.0 - 0.001),
352                  "QuatF::normalize() is broken in Sim3DAudioEvent");
353
354      bstream->writeSignedFloat(q.x,SoundRotBits);
355      bstream->writeSignedFloat(q.y,SoundRotBits);
356      bstream->writeSignedFloat(q.z,SoundRotBits);
357      bstream->writeFlag(q.w < 0.0);
358   }
359
360   Point3F pos;
361   mTransform.getColumn(3,&pos);
362   bstream->writeCompressedPoint(pos,SoundPosAccuracy);
363}
364
365void Sim3DAudioEvent::write(NetConnection *con, BitStream *bstream)
366{
367   // Just do the normal pack...
368   pack(con,bstream);
369}
370
371void Sim3DAudioEvent::unpack(NetConnection *con, BitStream *bstream)
372{
373   SimObjectId id = bstream->readInt(DataBlockObjectIdBitSize) + DataBlockObjectIdFirst;
374   Sim::findObject(id, mProfile);
375
376   if (bstream->readFlag()) {
377      QuatF q;
378      q.x = bstream->readSignedFloat(SoundRotBits);
379      q.y = bstream->readSignedFloat(SoundRotBits);
380      q.z = bstream->readSignedFloat(SoundRotBits);
381      F32 value = ((q.x * q.x) + (q.y * q.y) + (q.z * q.z));
382// #ifdef __linux
383      // Hmm, this should never happen, but it does...
384      if ( value > 1.f )
385         value = 1.f;
386// #endif
387      q.w = mSqrt(1.f - value);
388      if (bstream->readFlag())
389         q.w = -q.w;
390      q.setMatrix(&mTransform);
391   }
392   else
393      mTransform.identity();
394
395   Point3F pos;
396   bstream->readCompressedPoint(&pos,SoundPosAccuracy);
397   mTransform.setColumn(3, pos);
398}
399
400void Sim3DAudioEvent::process(NetConnection *)
401{
402   if (mProfile)
403      SFX->playOnce( mProfile, &mTransform );
404}
405
406