engine/game/gameConnectionEvents.cc
2024-01-07 04:36:33 +00:00

302 lines
9.5 KiB
C++

//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "core/dnet.h"
#include "console/consoleTypes.h"
#include "console/simBase.h"
#include "game/gameConnection.h"
#include "game/shapeBase.h"
#include "core/bitStream.h"
#include "sim/pathManager.h"
#include "audio/audio.h"
#include "game/targetManager.h"
#include "game/netDispatch.h"
#include "game/game.h"
#include "scenegraph/sceneGraph.h"
#include "game/gameConnectionEvents.h"
//--------------------------------------------------------------------------
IMPLEMENT_CO_NETEVENT_V1(SetSensorGroupEvent);
//--------------------------------------------------------------------------
IMPLEMENT_CO_NETEVENT_V1(SetServerTargetEvent);
//--------------------------------------------------------------------------
IMPLEMENT_CO_NETEVENT_V1(TargetToEvent);
IMPLEMENT_CO_CLIENTEVENT_V1(SimDataBlockEvent);
IMPLEMENT_CO_CLIENTEVENT_V1(Sim2DAudioEvent);
IMPLEMENT_CO_CLIENTEVENT_V1(Sim3DAudioEvent);
IMPLEMENT_CO_NETEVENT_V1(SetObjectActiveImageEvent);
IMPLEMENT_CO_CLIENTEVENT_V1(SetMissionCRCEvent);
//----------------------------------------------------------------------------
SimDataBlockEvent::~SimDataBlockEvent()
{
delete mObj;
}
SimDataBlockEvent::SimDataBlockEvent(SimDataBlock* obj, U32 index, U32 total, U32 missionSequence)
{
mObj = NULL;
mIndex = index;
mTotal = total;
mMissionSequence = missionSequence;
mProcess = false;
if(obj)
{
id = obj->getId();
AssertFatal(id >= DataBlockObjectIdFirst && id <= DataBlockObjectIdLast,
"Out of range event data block id... check simBase.h");
// Con::printf("queuing data block: %d", mIndex);
}
}
#ifdef DEBUG_NET
const char *SimDataBlockEvent::getDebugName()
{
SimObject *obj = Sim::findObject(id);
static char buffer[256];
dSprintf(buffer, sizeof(buffer), "%s [%s - %s]",
getClassName(),
obj ? obj->getName() : "",
obj ? obj->getClassName() : "NONE");
return buffer;
}
#endif // DEBUG_NET
void SimDataBlockEvent::notifyDelivered(NetConnection *conn, bool )
{
// if the modified key for this event is not the current one,
// we've already resorted and resent some blocks, so fall out.
if(conn->isRemoved())
return;
GameConnection *gc = (GameConnection *) conn;
if(gc->getDataBlockSequence() != mMissionSequence)
return;
U32 nextIndex = mIndex + DataBlockQueueCount;
SimDataBlockGroup *g = Sim::getDataBlockGroup();
// Con::printf("datablock delivered: %d, %d, %d", mIndex, mTotal, g->size());
if(mIndex == g->size() - 1)
{
gc->setDataBlockModifiedKey(gc->getMaxDataBlockModifiedKey());
Con::executef(gc, 2, "dataBlocksDone", Con::getIntArg(mMissionSequence));
}
if(g->size() <= nextIndex)
{
return;
}
SimDataBlock *blk = (SimDataBlock *) (*g)[nextIndex];
gc->postNetEvent(new SimDataBlockEvent(blk, nextIndex, g->size(), mMissionSequence));
}
void SimDataBlockEvent::pack(NetConnection *conn, BitStream *bstream)
{
SimDataBlock* obj;
Sim::findObject(id,obj);
GameConnection *gc = (GameConnection *) conn;
if(bstream->writeFlag(gc->getDataBlockModifiedKey() < obj->getModifiedKey()))
{
if(obj->getModifiedKey() > gc->getMaxDataBlockModifiedKey())
gc->setMaxDataBlockModifiedKey(obj->getModifiedKey());
AssertFatal(obj,
"SimDataBlockEvent:: Data blocks cannot be deleted");
bstream->writeInt(id - DataBlockObjectIdFirst,DataBlockObjectIdBitSize);
S32 classId = obj->getClassId();
AssertFatal(classId >= DataBlockClassFirst && classId <= DataBlockClassLast,
"Out of range event class id... check consoleObject.h");
bstream->writeInt(classId - DataBlockClassFirst, DataBlockClassBitSize);
bstream->writeInt(mIndex, DataBlockObjectIdBitSize);
bstream->writeInt(mTotal, DataBlockObjectIdBitSize + 1);
obj->packData(bstream);
}
}
void SimDataBlockEvent::unpack(NetConnection *cptr, BitStream *bstream)
{
if(bstream->readFlag())
{
mProcess = true;
id = bstream->readInt(DataBlockObjectIdBitSize) + DataBlockObjectIdFirst;
S32 classId = bstream->readInt(DataBlockClassBitSize) + DataBlockClassFirst;
mIndex = bstream->readInt(DataBlockObjectIdBitSize);
mTotal = bstream->readInt(DataBlockObjectIdBitSize + 1);
SimObject* ptr = (SimObject *) ConsoleObject::create(classId);
if ((mObj = dynamic_cast<SimDataBlock*>(ptr)) != 0) {
//Con::printf(" - SimDataBlockEvent: unpacking event of type: %s", mObj->getClassName());
mObj->unpackData(bstream);
}
else
{
//Con::printf(" - SimDataBlockEvent: INVALID PACKET! Could not create class with classID: %d", classId);
delete ptr;
cptr->setLastError("Invalid packet in SimDataBlockEvent::unpack()");
}
}
}
void SimDataBlockEvent::write(NetConnection *, BitStream *bstream)
{
if(bstream->writeFlag(mProcess))
{
bstream->writeInt(id - DataBlockObjectIdFirst,DataBlockObjectIdBitSize);
S32 classId = mObj->getClassId();
bstream->writeInt(classId - DataBlockClassFirst, DataBlockClassBitSize);
bstream->writeInt(mIndex, DataBlockObjectIdBitSize);
bstream->writeInt(mTotal, DataBlockObjectIdBitSize + 1);
mObj->packData(bstream);
}
}
void SimDataBlockEvent::process(NetConnection *cptr)
{
if(mProcess)
{
//call the console function to set the number of blocks to be sent
Con::executef(3, "clientReceivedDataBlock", Con::getIntArg(mIndex), Con::getIntArg(mTotal));
SimDataBlock* obj;
char *errorBuffer = NetConnection::getErrorBuffer();
if (Sim::findObject(id,obj))
{
U8 buf[1500];
BitStream stream(buf, 1500);
mObj->packData(&stream);
stream.setPosition(0);
obj->unpackData(&stream);
obj->preload(false, errorBuffer);
AssertFatal(errorBuffer[0] == 0, errorBuffer);
}
else
{
bool reg = mObj->registerObject(id);
cptr->addObject(mObj);
bool load = mObj->preload(false, errorBuffer);
mObj = NULL;
AssertFatal(errorBuffer[0] == 0, errorBuffer);
}
}
}
//----------------------------------------------------------------------------
Sim2DAudioEvent::Sim2DAudioEvent(const AudioProfile *profile)
{
mProfile = profile;
}
void Sim2DAudioEvent::pack(NetConnection *, BitStream *bstream)
{
bstream->writeInt( mProfile->getId() - DataBlockObjectIdFirst, DataBlockObjectIdBitSize);
}
void Sim2DAudioEvent::write(NetConnection *, BitStream *bstream)
{
bstream->writeInt( mProfile->getId() - DataBlockObjectIdFirst, DataBlockObjectIdBitSize);
}
void Sim2DAudioEvent::unpack(NetConnection *, BitStream *bstream)
{
SimObjectId id = bstream->readInt(DataBlockObjectIdBitSize) + DataBlockObjectIdFirst;
Sim::findObject(id, mProfile);
}
void Sim2DAudioEvent::process(NetConnection *)
{
if (mProfile)
alxPlay(mProfile);
}
//----------------------------------------------------------------------------
static F32 SoundPosAccuracy = 0.5;
static S32 SoundRotBits = 8;
Sim3DAudioEvent::Sim3DAudioEvent(const AudioProfile *profile,const MatrixF* mat)
{
mProfile = profile;
if (mat)
mTransform = *mat;
}
void Sim3DAudioEvent::pack(NetConnection *con, BitStream *bstream)
{
bstream->writeInt(mProfile->getId() - DataBlockObjectIdFirst, DataBlockObjectIdBitSize);
// If the sound has cone paramaters, the orientation is
// transmitted as well.
Audio::Description* ad = &mProfile->mDescriptionObject->mDescription;
if (bstream->writeFlag(ad->mConeInsideAngle || ad->mConeOutsideAngle)) {
QuatF q(mTransform);
q.normalize();
// LH - we can get a valid quat that's very slightly over 1 in and so
// this fails (barely) check against zero. So use some error-
AssertFatal((1.0 - ((q.x * q.x) + (q.y * q.y) + (q.z * q.z))) >= (0.0 - 0.001),
"QuatF::normalize() is broken in Sim3DAudioEvent");
bstream->writeFloat(q.x,SoundRotBits);
bstream->writeFloat(q.y,SoundRotBits);
bstream->writeFloat(q.z,SoundRotBits);
bstream->writeFlag(q.w < 0.0);
}
Point3F pos;
mTransform.getColumn(3,&pos);
con->writeCompressed(bstream,pos,SoundPosAccuracy);
}
void Sim3DAudioEvent::write(NetConnection *con, BitStream *bstream)
{
// Just do the normal pack...
pack(con,bstream);
}
void Sim3DAudioEvent::unpack(NetConnection *con, BitStream *bstream)
{
SimObjectId id = bstream->readInt(DataBlockObjectIdBitSize) + DataBlockObjectIdFirst;
Sim::findObject(id, mProfile);
if (bstream->readFlag()) {
QuatF q;
q.x = bstream->readFloat(SoundRotBits);
q.y = bstream->readFloat(SoundRotBits);
q.z = bstream->readFloat(SoundRotBits);
F32 value = ((q.x * q.x) + (q.y * q.y) + (q.z * q.z));
// #ifdef __linux
// Hmm, this should never happen, but it does...
if ( value > 1.f )
value = 1.f;
// #endif
q.w = mSqrt(1.f - value);
if (bstream->readFlag())
q.w = -q.w;
q.setMatrix(&mTransform);
}
else
mTransform.identity();
Point3F pos;
con->readCompressed(bstream,&pos,SoundPosAccuracy);
mTransform.setColumn(3, pos);
}
void Sim3DAudioEvent::process(NetConnection *)
{
if (mProfile)
alxPlay(mProfile, &mTransform);
}