You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1393 lines
38 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsWindows.h"
#include "hsResMgr.h"
#include "plNetMessage.h"
#include "plNetCommonMessage.h"
#include "plNetMsgVersion.h"
#include "plCreatableIndex.h"
#include "pnKeyedObject/plKeyImp.h"
#include "pnKeyedObject/plKey.h"
#include "pnNetCommon/plNetSharedState.h"
#include "pnMessage/plMessage.h"
#include "pnNetCommon/pnNetCommon.h"
#include "pnNetCommon/plGenericVar.h"
#include "pnFactory/plFactory.h"
#include "plVault/plVault.h"
#include "plNetCommon/plNetCommon.h"
#include "plSDL/plSDL.h"
#if defined(HS_BUILD_FOR_UNIX)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include <algorithm>
//
// static
//
// see plNetMsgVersion.h
const UInt8 plNetMessage::kVerMajor = PLASMA2_NETMSG_MAJOR_VERSION;
const UInt8 plNetMessage::kVerMinor = PLASMA2_NETMSG_MINOR_VERSION;
////////////////////////////////////////////////////////
// plNetMessage
////////////////////////////////////////////////////////
plNetMessage::plNetMessage() :
fTimeRecvd(0),
fBytesRead(0),
fNetCoreMsg(nil),
fContext(0),
fPeekStatus(0),
fTransactionID(0),
fPlayerID(kInvalidPlayerID),
fFlags(0),
fProtocolVerMajor(0),
fProtocolVerMinor(0)
{
}
plNetMessage::~plNetMessage()
{
}
void plNetMessage::Read(hsStream* s, hsResMgr* mgr)
{
IPeekBuffer(s);
}
void plNetMessage::Write(hsStream* s, hsResMgr* mgr)
{
IPokeBuffer(s);
}
void plNetMessage::InitReplyFieldsFrom(plNetMessage * msg)
{
bool hasContext = msg->GetHasContext();
SetHasContext(hasContext);
if (hasContext)
SetContext(msg->GetContext());
bool hasTransactionID = msg->GetHasTransactionID();
SetHasTransactionID(hasTransactionID);
if (hasTransactionID)
SetTransactionID(msg->GetTransactionID());
bool hasPlayerID = msg->GetHasPlayerID();
if ( hasPlayerID )
SetPlayerID( msg->GetPlayerID() );
bool hasAcctUUID = msg->GetHasAcctUUID();
if ( hasAcctUUID )
SetAcctUUID( msg->GetAcctUUID() );
bool hasTimeSent = msg->GetHasTimeSent();
if ( hasTimeSent )
SetTimeSent( msg->GetTimeSent() );
#if 0 // I don't think the version should be copied
if (msg->IsBitSet(kHasVersion))
SetVersion();
#endif
}
//
// STATIC
// create and READ from lowlevel net buffer
//
plNetMessage* plNetMessage::CreateAndRead(const plNetCommonMessage* msg, plStreamLogger::EventList* el)
{
// create
plNetMessage* pHdr = Create(msg);
if (!pHdr)
return nil;
// read
pHdr->PeekBuffer(msg->GetData(), msg->GetLen(), 0, false, el);
return pHdr;
}
//
// STATIC
// create from lowlevel net buffer
//
plNetMessage* plNetMessage::Create(const plNetCommonMessage* msg)
{
if (msg)
{
hsReadOnlyStream readStream;
ClassIndexType classIndex;
readStream.Init(sizeof(classIndex), msg->GetData());
readStream.ReadSwap(&classIndex);
if (!plFactory::IsValidClassIndex(classIndex))
return nil;
plNetMessage* pnm = plNetMessage::ConvertNoRef(plFactory::Create(classIndex));
if (pnm)
pnm->SetNetCoreMsg(msg);
else
{
char str[256];
sprintf(str, "Factory create failed, class index=%d, garbage msg?", classIndex);
hsAssert(false, str);
}
return pnm;
}
return nil;
}
int plNetMessage::PokeBuffer(char* bufIn, int bufLen, UInt32 peekOptions)
{
fPeekStatus = 0;
if (!bufIn)
return 0;
if (! (peekOptions & kDontClearBuffer))
memset(bufIn, 0, bufLen);
ValidatePoke();
hsWriteOnlyStream writeStream;
writeStream.Init(bufLen, bufIn);
int ret;
if (peekOptions & kBaseClassOnly)
{
ret=plNetMessage::IPokeBuffer(&writeStream, peekOptions);
}
else
{
ret=IPokeBuffer(&writeStream, peekOptions);
}
return ret;
}
int plNetMessage::PeekBuffer(const char* bufIn, int bufLen, UInt32 peekOptions, bool forcePeek, plStreamLogger::EventList* el)
{
if(!bufLen || bufLen < 1)
return 0;
UInt32 partialPeekOptions = (peekOptions & kPartialPeekMask);
if (!forcePeek && (fPeekStatus & partialPeekOptions) )
return 0; // already peeked, fully or partially
if (!bufIn)
return 0;
// set peek status based on peekOptions
fPeekStatus = partialPeekOptions ? partialPeekOptions : kFullyPeeked;
hsReadOnlyLoggingStream readStream;
readStream.LogSetList(el);
readStream.Init(bufLen, bufIn);
readStream.LogSubStreamStart("plNetMessage");
readStream.LogStringString(xtl::format("ClassName: %s",this->ClassName()).c_str());
int ret;
if (peekOptions & kBaseClassOnly)
{
ret=plNetMessage::IPeekBuffer(&readStream, peekOptions);
plNetMessage::ValidatePeek();
}
else
{
ret=IPeekBuffer(&readStream, peekOptions);
ValidatePeek();
}
readStream.LogSubStreamEnd();
return ret;
}
void plNetMessage::IWriteClassIndex(hsStream* stream)
{
ClassIndexType classIndex=ClassIndex();
hsAssert(sizeof(classIndex)==sizeof(plNetMessageClassIndex), "somebody changed the size of plCreatable::ClassIndex");
stream->WriteSwap(classIndex);
}
// put in buffer
int plNetMessage::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
IWriteClassIndex(stream);
stream->WriteSwap32(fFlags);
if (IsBitSet(kHasVersion))
{
stream->WriteByte(fProtocolVerMajor);
stream->WriteByte(fProtocolVerMinor);
}
if (IsBitSet(kHasTimeSent))
fTimeSent.Write(stream);
if (IsBitSet(kHasContext))
stream->WriteSwap(fContext);
if (IsBitSet(kHasTransactionID))
stream->WriteSwap(fTransactionID);
if (IsBitSet(kHasPlayerID))
stream->WriteSwap(fPlayerID);
if (IsBitSet(kHasAcctUUID))
fAcctUUID.Write(stream);
return stream->GetPosition();
}
void plNetMessage::IReadClassIndex(hsStream* stream)
{
ClassIndexType classIndex;
hsAssert(sizeof(classIndex)==sizeof(plNetMessageClassIndex), "somebody changed the size of plCreatable::ClassIndex");
stream->LogReadSwap(&classIndex,"ClassIndex");
}
// get out of buffer
int plNetMessage::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
IReadClassIndex(stream);
stream->LogReadSwap(&fFlags,"Flags");
// verify version first
if (IsBitSet(kHasVersion))
{
stream->LogReadSwap(&fProtocolVerMajor, "Protocol major version");
stream->LogReadSwap(&fProtocolVerMinor, "Protocol minor version");
if (fProtocolVerMajor != kVerMajor || fProtocolVerMinor != kVerMinor)
return 0; // this will cause derived classes to stop reading
}
if (!(IsBitSet(kHasVersion)) && (peekOptions & kWantVersion))
{
return 0;
}
if (IsBitSet(kHasTimeSent))
fTimeSent.Read(stream);
if (IsBitSet(kHasContext))
stream->LogReadSwap(&fContext,"Context");
if (IsBitSet(kHasTransactionID))
stream->LogReadSwap(&fTransactionID,"TransactionID");
if (IsBitSet(kHasPlayerID))
stream->LogReadSwap(&fPlayerID,"PlayerID");
if (IsBitSet(kHasAcctUUID))
fAcctUUID.Read( stream );
return stream->GetPosition();
}
void plNetMessage::ReadVersion(hsStream* s, hsResMgr* mgr)
{
hsBitVector contentFlags;
contentFlags.Read(s);
if (contentFlags.IsBitSet(kNetMsgFlags))
s->LogReadSwap(&fFlags,"Flags");
if (contentFlags.IsBitSet(kNetMsgVersion))
{
if (IsBitSet(kHasVersion))
{
s->LogReadSwap(&fProtocolVerMajor, "Protocol major version");
s->LogReadSwap(&fProtocolVerMinor, "Protocol minor version");
}
}
if (contentFlags.IsBitSet(kNetMsgTimeSent))
{
if (IsBitSet(kHasTimeSent))
fTimeSent.Read(s);
}
if (contentFlags.IsBitSet(kNetMsgContext))
{
if (IsBitSet(kHasContext))
s->LogReadSwap(&fContext,"Context");
}
if (contentFlags.IsBitSet(kNetMsgTransactionID))
{
if (IsBitSet(kHasTransactionID))
s->LogReadSwap(&fTransactionID,"TransactionID");
}
if (contentFlags.IsBitSet(kNetMsgPlayerID))
{
if (IsBitSet(kHasPlayerID))
s->LogReadSwap(&fPlayerID,"PlayerID");
}
}
void plNetMessage::WriteVersion(hsStream* s, hsResMgr* mgr)
{
hsBitVector contentFlags;
contentFlags.SetBit(kNetMsgFlags);
contentFlags.SetBit(kNetMsgTimeSent);
contentFlags.SetBit(kNetMsgContext);
contentFlags.SetBit(kNetMsgTransactionID);
contentFlags.SetBit(kNetMsgPlayerID);
contentFlags.SetBit(kNetMsgVersion);
contentFlags.Write(s);
// kNetMsgFlags
s->WriteSwap32(fFlags);
// version
if (IsBitSet(kHasVersion))
{
s->WriteByte(fProtocolVerMajor);
s->WriteByte(fProtocolVerMinor);
}
// kNetMsgTimeSent
if (IsBitSet(kHasTimeSent))
fTimeSent.Write(s);
// kNetMsgContext
if (IsBitSet(kHasContext))
s->WriteSwap(fContext);
// kNetMsgTransactionID
if (IsBitSet(kHasTransactionID))
s->WriteSwap(fTransactionID);
// kNetMsgPlayerID
if (IsBitSet(kHasPlayerID))
s->WriteSwap(fPlayerID);
}
// Get the Packed Size
int plNetMessage::GetPackSize()
{
hsNullStream nullStream;
return IPokeBuffer(&nullStream);
}
UInt32 plNetMessage::GetNetCoreMsgLen() const
{
return fNetCoreMsg ? fNetCoreMsg->GetLen() : 0;
}
void plNetMessage::ValidatePeek() const
{
}
void plNetMessage::ValidatePoke() const
{
}
////////////////////////////////////////////////////////
// plNetMsgStream
////////////////////////////////////////////////////////
int plNetMsgStream::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMessage::IPokeBuffer(stream, peekOptions);
if (bytes)
{
stream->LogSubStreamPushDesc("StreamHelper");
fStreamHelper.Poke(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgStream::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMessage::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogSubStreamPushDesc("MsgStreamStream");
fStreamHelper.Peek(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
////////////////////////////////////////////////////////
// plNetMsgGameMessage
////////////////////////////////////////////////////////
int plNetMsgGameMessage::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgStream::IPokeBuffer(stream, peekOptions);
if (bytes)
{
if (fDeliveryTime.AtEpoch())
{
stream->WriteByte(0); // not sending
}
else
{
stream->WriteByte(1); // sending
fDeliveryTime.Write(stream);
}
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgGameMessage::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgStream::IPeekBuffer(stream, peekOptions);
if (bytes)
{
if (stream->ReadByte())
{
stream->LogSubStreamPushDesc("GameMessage DeliveryTime");
fDeliveryTime.Read(stream);
}
bytes=stream->GetPosition();
}
return bytes;
}
plMessage* plNetMsgGameMessage::GetContainedMsg(hsResMgr* resmgr)
{
hsReadOnlyStream s(StreamInfo()->GetStreamLen(), StreamInfo()->GetStreamBuf());
return plMessage::ConvertNoRef((resmgr?resmgr:hsgResMgr::ResMgr())->ReadCreatable(&s));
}
void plNetMsgGameMessage::ReadVersion(hsStream* s, hsResMgr* mgr)
{
plNetMessage::ReadVersion(s, mgr);
hsBitVector contentFlags;
contentFlags.Read(s);
if (contentFlags.IsBitSet(kNetGameMsgDeliveryTime))
{
if (s->ReadByte())
fDeliveryTime.Read(s);
}
if (contentFlags.IsBitSet(kNetGameMsgGameMsg))
{
plMessage* gameMsg = plMessage::ConvertNoRef(mgr->ReadCreatableVersion(s));
// write message (and label) to ram stream
hsRAMStream ramStream;
mgr->WriteCreatable(&ramStream, gameMsg);
// put stream in net msg wrapper
StreamInfo()->CopyStream(&ramStream);
hsRefCnt_SafeUnRef(gameMsg);
}
}
void plNetMsgGameMessage::WriteVersion(hsStream* s, hsResMgr* mgr)
{
plNetMessage::WriteVersion(s, mgr);
hsBitVector contentFlags;
contentFlags.SetBit(kNetGameMsgDeliveryTime);
contentFlags.SetBit(kNetGameMsgGameMsg);
contentFlags.Write(s);
// kNetGameMsgDeliveryTime
if (fDeliveryTime.AtEpoch())
{
s->WriteByte(0); // not sending
}
else
{
s->WriteByte(1); // sending
fDeliveryTime.Write(s);
}
// kNetGameMsgGameMsg
plMessage* gameMsg = GetContainedMsg();
mgr->WriteCreatableVersion(s, gameMsg);
hsRefCnt_SafeUnRef(gameMsg);
}
////////////////////////////////////////////////////////
// plNetMsgGameMessageDirected
////////////////////////////////////////////////////////
int plNetMsgGameMessageDirected::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgGameMessage::IPokeBuffer(stream, peekOptions);
if (bytes)
{
fReceivers.Poke(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgGameMessageDirected::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgGameMessage::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogSubStreamPushDesc("GameMessageDirected Receivers");
fReceivers.Peek(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
void plNetMsgGameMessageDirected::ReadVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgGameMessage::ReadVersion(s,mgr);
hsBitVector contentFlags;
contentFlags.Read(s);
if (contentFlags.IsBitSet(kRecievers))
fReceivers.ReadVersion(s,mgr);
}
void plNetMsgGameMessageDirected::WriteVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgGameMessage::WriteVersion(s,mgr);
hsBitVector contentFlags;
contentFlags.SetBit(kRecievers);
contentFlags.Write(s);
fReceivers.WriteVersion(s,mgr);
}
////////////////////////////////////////////////////////
// plNetMsgObject
////////////////////////////////////////////////////////
int plNetMsgObject::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMessage::IPokeBuffer(stream, peekOptions);
if (bytes)
{
fObjectHelper.Poke(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgObject::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMessage::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogSubStreamPushDesc("MsgObject");
fObjectHelper.Peek(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
void plNetMsgObject::ReadVersion(hsStream* s, hsResMgr* mgr)
{
plNetMessage::ReadVersion(s, mgr);
hsBitVector contentFlags;
contentFlags.Read(s);
if (contentFlags.IsBitSet(kNetMsgObjectHelper))
fObjectHelper.ReadVersion(s, mgr);
}
void plNetMsgObject::WriteVersion(hsStream* s, hsResMgr* mgr)
{
plNetMessage::WriteVersion(s, mgr);
hsBitVector contentFlags;
contentFlags.SetBit(kNetMsgObjectHelper);
contentFlags.Write(s);
// kNetMsgObjectHelper
fObjectHelper.WriteVersion(s, mgr);
}
////////////////////////////////////////////////////////
// plNetMsgStreamedObject
////////////////////////////////////////////////////////
int plNetMsgStreamedObject::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgObject::IPokeBuffer(stream, peekOptions);
if (bytes)
{
fStreamHelper.Poke(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgStreamedObject::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgObject::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogSubStreamPushDesc("StreamedObject");
fStreamHelper.Peek(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
void plNetMsgStreamedObject::ReadVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgObject::ReadVersion(s,mgr);
hsBitVector contentFlags;
contentFlags.Read(s);
if (contentFlags.IsBitSet(kStreamHelper))
fStreamHelper.ReadVersion(s,mgr);
}
void plNetMsgStreamedObject::WriteVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgObject::WriteVersion(s,mgr);
hsBitVector contentFlags;
contentFlags.SetBit(kStreamHelper);
contentFlags.Write(s);
fStreamHelper.WriteVersion(s,mgr);
}
////////////////////////////////////////////////////////////////////
// debug
std::string plNetMsgSDLState::AsStdString() const
{
std::string s;
ISetDescName(); // set desc name for debug if necessary
// xtl::format(s,"object:%s, SDL:%s, initial:%d, %s",
// ObjectInfo()->GetObjectName(), fDescName.c_str(), fIsInitialState, plNetMsgStreamedObject::AsStdString().c_str() );
xtl::format(s,"object:%s, initial:%d, %s",
ObjectInfo()->GetObjectName(), fIsInitialState, plNetMsgStreamedObject::AsStdString().c_str() );
return s;
}
//
// fill out descName for debugging if needed
// fDescName; // for debugging output only, not read/written
//
void plNetMsgSDLState::ISetDescName() const
{
if (fDescName.empty() && StreamInfo()->GetStreamLen() && !StreamInfo()->IsCompressed())
{
hsReadOnlyStream stream(StreamInfo()->GetStreamLen(), StreamInfo()->GetStreamBuf());
/* This code can crash the game server sometimes -eap
char* descName = nil;
int ver;
if (plStateDataRecord::ReadStreamHeader(&stream, &descName, &ver))
fDescName = descName;
delete [] descName;
*/
}
}
int plNetMsgSDLState::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
ISetDescName(); // stash away the descName before poke/compress
plNetMsgStreamedObject::IPokeBuffer(stream, peekOptions);
stream->WriteSwap( fIsInitialState );
stream->WriteSwap(fPersistOnServer);
stream->WriteSwap(fIsAvatarState);
return stream->GetPosition();
}
int plNetMsgSDLState::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
plNetMsgStreamedObject::IPeekBuffer(stream, peekOptions);
stream->LogReadSwap( &fIsInitialState, "IsInitialAgeState" );
stream->LogReadSwap(&fPersistOnServer, "SDLState PersistOnServer");
stream->LogReadSwap(&fIsAvatarState, "SDLState IsAvatarState");
ISetDescName(); // stash away the descName after peek/uncompress
return stream->GetPosition();
}
void plNetMsgSDLState::ReadVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgStreamedObject::ReadVersion(s, mgr);
hsBitVector contentFlags;
contentFlags.Read(s);
if (contentFlags.IsBitSet(kSDLStateStream))
{
UInt32 len;
s->LogReadSwap(&len,"SDLState StreamLen");
UInt8* buf = TRACKED_NEW UInt8[len];
s->LogRead(len, buf,"SDLState StreamData");
StreamInfo()->SetStreamLen(len);
StreamInfo()->SetStreamBuf(buf);
}
if (contentFlags.IsBitSet(kSDLIsInitialState))
s->LogReadSwap( &fIsInitialState, "IsInitialAgeState" );
if (contentFlags.IsBitSet(kSDLPersist))
s->ReadSwap(&fPersistOnServer);
if (contentFlags.IsBitSet(kSDLAvatarState))
s->ReadSwap(&fIsAvatarState);
}
void plNetMsgSDLState::WriteVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgStreamedObject::WriteVersion(s, mgr);
hsBitVector contentFlags;
contentFlags.SetBit(kSDLStateStream);
contentFlags.SetBit(kSDLIsInitialState);
contentFlags.SetBit(kSDLPersist);
contentFlags.SetBit(kSDLAvatarState);
contentFlags.Write(s);
// kSDLStateStream
s->WriteSwap32(StreamInfo()->GetStreamLen());
s->Write(StreamInfo()->GetStreamLen(), StreamInfo()->GetStreamBuf());
s->WriteSwap( fIsInitialState );
s->WriteSwap(fPersistOnServer);
s->WriteSwap(fIsAvatarState);
}
////////////////////////////////////////////////////////
// plNetMsgSDLStateBCast
////////////////////////////////////////////////////////
int plNetMsgSDLStateBCast::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes = plNetMsgSDLState::IPokeBuffer(stream, peekOptions);
if (bytes)
{
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgSDLStateBCast::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgSDLState::IPeekBuffer(stream, peekOptions);
if (bytes)
{
bytes=stream->GetPosition();
}
return bytes;
}
void plNetMsgSDLStateBCast::ReadVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgSDLState::ReadVersion(s, mgr);
}
void plNetMsgSDLStateBCast::WriteVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgSDLState::WriteVersion(s, mgr);
}
////////////////////////////////////////////////////////
// plNetMsgRoomsList
////////////////////////////////////////////////////////
plNetMsgRoomsList::~plNetMsgRoomsList()
{
int i;
for(i=0;i<GetNumRooms();i++)
delete [] fRoomNames[i];
}
int plNetMsgRoomsList::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMessage::IPokeBuffer(stream, peekOptions);
if (bytes)
{
int i, numRooms=fRooms.size();
stream->WriteSwap(numRooms);
for(i=0;i<numRooms;i++)
{
fRooms[i].Write(stream);
// write room name for debugging
plMsgCStringHelper::Poke(fRoomNames[i],stream,peekOptions);
}
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgRoomsList::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMessage::IPeekBuffer(stream, peekOptions);
if (bytes)
{
int i, numRooms;
stream->LogReadSwap(&numRooms,"RoomList NumRooms");
fRooms.resize(numRooms);
int oldSize = fRoomNames.size();
fRoomNames.resize(numRooms);
for(i=0;i<numRooms;i++)
{
plLocation loc;
loc.Read(stream);
fRooms[i]=loc;
// read room name for debugging
delete [] fRoomNames[i];
stream->LogSubStreamPushDesc("RoomList");
plMsgCStringHelper::Peek(fRoomNames[i],stream,peekOptions);
}
bytes=stream->GetPosition();
}
return bytes;
}
void plNetMsgRoomsList::AddRoom(plKey rmKey)
{
fRooms.push_back(rmKey->GetUoid().GetLocation());
fRoomNames.push_back(hsStrcpy(rmKey->GetName()));
}
void plNetMsgRoomsList::AddRoomLocation(plLocation loc, const char* rmName)
{
fRooms.push_back(loc);
fRoomNames.push_back(rmName ? hsStrcpy(rmName) : nil);
}
int plNetMsgRoomsList::FindRoomLocation(plLocation loc)
{
std::vector<plLocation>::iterator result = std::find(fRooms.begin(), fRooms.end(), loc);
return result==fRooms.end() ? -1 : result-fRooms.begin();
}
////////////////////////////////////////////////////////
// plNetMsgPagingRoom
////////////////////////////////////////////////////////
int plNetMsgPagingRoom::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgRoomsList::IPokeBuffer(stream, peekOptions);
if (bytes)
{
stream->WriteSwap(fPageFlags);
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgPagingRoom::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgRoomsList::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogReadSwap(&fPageFlags,"PageFlags");
bytes=stream->GetPosition();
}
return bytes;
}
////////////////////////////////////////////////////////
// plNetMsgGroupOwner
////////////////////////////////////////////////////////
int plNetMsgGroupOwner::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgServerToClient::IPokeBuffer(stream, peekOptions);
if (bytes)
{
int i, numGroups=fGroups.size();
stream->WriteSwap(numGroups);
for(i=0;i<numGroups;i++)
fGroups[i].Write(stream);
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgGroupOwner::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgServerToClient::IPeekBuffer(stream, peekOptions);
if (bytes)
{
int i, num;
stream->LogReadSwap(&num,"GroupOwnerNum");
fGroups.resize(num);
for(i=0;i<num;i++)
{
GroupInfo gr;
gr.Read(stream);
fGroups[i]=gr;
}
bytes=stream->GetPosition();
}
return bytes;
}
////////////////////////////////////////////////////////
// plNetMsgSharedState
////////////////////////////////////////////////////////
void plNetMsgSharedState::CopySharedState(plNetSharedState* ss)
{
hsRAMStream stream;
ss->Write(&stream);
StreamInfo()->CopyStream(&stream);
}
int plNetMsgSharedState::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgStreamedObject::IPokeBuffer(stream, peekOptions);
if (bytes)
{
stream->WriteSwap(fLockRequest);
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgSharedState::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgStreamedObject::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogReadSwap(&fLockRequest,"SharedState LockRequest");
bytes=stream->GetPosition();
}
return bytes;
}
void plNetMsgSharedState::ReadVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgStreamedObject::ReadVersion(s,mgr);
hsBitVector contentFlags;
contentFlags.Read(s);
if (contentFlags.IsBitSet(kLockRequest))
s->ReadSwap(&fLockRequest);
}
void plNetMsgSharedState::WriteVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgStreamedObject::WriteVersion(s,mgr);
hsBitVector contentFlags;
contentFlags.SetBit(kLockRequest);
contentFlags.Write(s);
s->WriteSwap(fLockRequest);
}
////////////////////////////////////////////////////////
// plNetMsgGetSharedState
////////////////////////////////////////////////////////
int plNetMsgGetSharedState::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgObject::IPokeBuffer(stream, peekOptions);
if (bytes)
{
plMsgCArrayHelper::Poke(fSharedStateName,sizeof(fSharedStateName),stream,peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgGetSharedState::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgObject::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogSubStreamPushDesc("SharedStateName");
plMsgCArrayHelper::Peek(fSharedStateName,sizeof(fSharedStateName),stream,peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
////////////////////////////////////////////////////////
// plNetMsgObject
////////////////////////////////////////////////////////
int plNetMsgObjectUpdateFilter::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMessage::IPokeBuffer(stream, peekOptions);
if (bytes)
{
fObjectListHelper.Poke(stream, peekOptions);
stream->WriteSwap(fMaxUpdateFreq);
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgObjectUpdateFilter::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMessage::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogSubStreamPushDesc("ObjectUpdateFilter");
fObjectListHelper.Peek(stream, peekOptions);
stream->LogReadSwap(&fMaxUpdateFreq,"MsgObjectUpdateFilter MaxUpdateFreq");
bytes=stream->GetPosition();
}
return bytes;
}
////////////////////////////////////////////////////////
// plNetMsgMembersList
////////////////////////////////////////////////////////
int plNetMsgMembersList::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgServerToClient::IPokeBuffer(stream, peekOptions);
if (bytes)
{
fMemberListHelper.Poke(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgMembersList::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgServerToClient::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogSubStreamPushDesc("MembersList");
fMemberListHelper.Peek(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
////////////////////////////////////////////////////////
// plNetMsgMemberUpdate
////////////////////////////////////////////////////////
int plNetMsgMemberUpdate::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgServerToClient::IPokeBuffer(stream, peekOptions);
if (bytes)
{
// FIX ME to something nice
fMemberInfo.GetClientGuid()->SetClientKey("");
fMemberInfo.GetClientGuid()->SetAccountUUID(plUUID());
fMemberInfo.Poke(stream, peekOptions);
stream->WriteByte(fAddMember);
bytes=stream->GetPosition();
}
return bytes;
}
int plNetMsgMemberUpdate::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMsgServerToClient::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogSubStreamPushDesc("MemberUpdate");
fMemberInfo.Peek(stream, peekOptions);
fAddMember = stream->ReadByte();
bytes=stream->GetPosition();
}
return bytes;
}
////////////////////////////////////////////////////////
// plNetMsgVoice
////////////////////////////////////////////////////////
int plNetMsgVoice::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
plNetMessage::IPokeBuffer(stream, peekOptions);
stream->WriteSwap(fFlags);
stream->WriteSwap(fNumFrames);
plMsgStdStringHelper::Poke(fVoiceData, stream, peekOptions);
fReceivers.Poke(stream, peekOptions);
return stream->GetPosition();
}
int plNetMsgVoice::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMessage::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogReadSwap(&fFlags,"Voice Flags");
stream->LogReadSwap(&fNumFrames, "Number of encoded frames");
stream->LogSubStreamPushDesc("Voice Data");
plMsgStdStringHelper::Peek(fVoiceData, stream, peekOptions);
stream->LogSubStreamPushDesc("Voice Receivers");
fReceivers.Peek(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
void plNetMsgVoice::ReadVersion(hsStream* s, hsResMgr* mgr)
{
plNetMessage::ReadVersion(s,mgr);
UInt16 old = 0;
hsBitVector contentFlags;
contentFlags.Read(s);
if (contentFlags.IsBitSet(kDead_FrameSize))
s->ReadSwap(&old);
if (contentFlags.IsBitSet(kReceivers))
fReceivers.ReadVersion(s,mgr);
if (contentFlags.IsBitSet(kVoiceFlags))
s->ReadSwap(&fFlags);
if(contentFlags.IsBitSet(kVoiceData))
plMsgStdStringHelper::Peek(fVoiceData, s);
}
void plNetMsgVoice::WriteVersion(hsStream* s, hsResMgr* mgr)
{
plNetMessage::WriteVersion(s,mgr);
hsBitVector contentFlags;
contentFlags.SetBit(kReceivers);
contentFlags.SetBit(kVoiceFlags);
contentFlags.SetBit(kVoiceData);
contentFlags.Write(s);
fReceivers.WriteVersion(s,mgr);
s->WriteSwap(fFlags);
plMsgStdStringHelper::Poke(fVoiceData, s);
}
void plNetMsgVoice::SetVoiceData(char *data, int len)
{
fVoiceData.resize( len );
memcpy((void *)fVoiceData.data(), data, len );
}
const char *plNetMsgVoice::GetVoiceData() const
{
return fVoiceData.c_str();
}
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
// plNetMsgListenListUpdate
////////////////////////////////////////////////////////
int plNetMsgListenListUpdate::IPokeBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMessage::IPokeBuffer(stream, peekOptions);
stream->WriteSwap(fAdding);
fReceivers.Poke(stream, peekOptions);
return stream->GetPosition();
}
int plNetMsgListenListUpdate::IPeekBuffer(hsStream* stream, UInt32 peekOptions)
{
int bytes=plNetMessage::IPeekBuffer(stream, peekOptions);
if (bytes)
{
stream->LogReadSwap(&fAdding,"ListenListUpdate Adding");
stream->LogSubStreamPushDesc("ListenListUpdate Reveivers");
fReceivers.Peek(stream, peekOptions);
bytes=stream->GetPosition();
}
return bytes;
}
////////////////////////////////////////////////////////////////////
// plNetMsgPlayerPage
////////////////////////////////////////////////////////////////////
int plNetMsgPlayerPage::IPokeBuffer( hsStream* stream, UInt32 peekOptions )
{
plNetMessage::IPokeBuffer( stream, peekOptions );
stream->WriteSwap( fUnload );
fUoid.Write(stream);
return stream->GetPosition();
}
int plNetMsgPlayerPage::IPeekBuffer( hsStream* stream, UInt32 peekOptions )
{
int bytes = plNetMessage::IPeekBuffer(stream, peekOptions );
if ( bytes )
{
stream->LogReadSwap( &fUnload,"PlayersPage Unload");
fUoid.Read(stream);
bytes = stream->GetPosition();
}
return bytes;
}
////////////////////////////////////////////////////////////////////
// plNetMsgLoadClone
////////////////////////////////////////////////////////////////////
int plNetMsgLoadClone::IPokeBuffer( hsStream* stream, UInt32 peekOptions )
{
int bytes = plNetMsgGameMessage::IPokeBuffer( stream, peekOptions );
if ( bytes )
{
fObjectHelper.Poke(stream, peekOptions);
stream->WriteSwap( fIsPlayer );
stream->WriteSwap( fIsLoading );
stream->WriteSwap( fIsInitialState );
bytes = stream->GetPosition();
}
return bytes;
}
int plNetMsgLoadClone::IPeekBuffer( hsStream* stream, UInt32 peekOptions )
{
stream->LogSubStreamPushDesc("LoadClone");
int bytes = plNetMsgGameMessage::IPeekBuffer(stream, peekOptions );
if ( bytes )
{
stream->LogSubStreamPushDesc("MsgObject");
fObjectHelper.Peek(stream, peekOptions);
stream->LogReadSwap( &fIsPlayer,"LoadClone IsPlayer");
stream->LogReadSwap( &fIsLoading,"LoadClone IsLoading");
stream->LogReadSwap( &fIsInitialState, "LoadClone IsInitialState" );
bytes = stream->GetPosition();
}
return bytes;
}
void plNetMsgLoadClone::ReadVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgGameMessage::ReadVersion(s,mgr);
hsBitVector contentFlags;
contentFlags.Read(s);
if (contentFlags.IsBitSet(kObjectHelper))
fObjectHelper.ReadVersion(s,mgr);
if (contentFlags.IsBitSet(kIsPlayer))
s->ReadSwap(&fIsPlayer);
if (contentFlags.IsBitSet(kIsLoading))
s->ReadSwap(&fIsLoading);
if (contentFlags.IsBitSet(kIsInitialState))
s->ReadSwap(&fIsInitialState);
}
void plNetMsgLoadClone::WriteVersion(hsStream* s, hsResMgr* mgr)
{
plNetMsgGameMessage::WriteVersion(s,mgr);
hsBitVector contentFlags;
contentFlags.SetBit(kObjectHelper);
contentFlags.SetBit(kIsPlayer);
contentFlags.SetBit(kIsLoading);
contentFlags.SetBit(kIsInitialState);
contentFlags.Write(s);
fObjectHelper.WriteVersion(s,mgr);
s->WriteSwap(fIsPlayer);
s->WriteSwap(fIsLoading);
s->WriteSwap(fIsInitialState);
}
////////////////////////////////////////////////////////////////////
int plNetMsgInitialAgeStateSent::IPokeBuffer( hsStream* stream, UInt32 peekOptions )
{
plNetMessage::IPokeBuffer( stream, peekOptions );
stream->WriteSwap( fNumInitialSDLStates );
return stream->GetPosition();
}
int plNetMsgInitialAgeStateSent::IPeekBuffer( hsStream* stream, UInt32 peekOptions )
{
stream->LogSubStreamPushDesc("InitialAgeStateSent");
int bytes=plNetMessage::IPeekBuffer(stream, peekOptions );
if (bytes)
{
stream->LogReadSwap( &fNumInitialSDLStates, "NumInitialSDLStates" );
bytes=stream->GetPosition();
}
return bytes;
}
////////////////////////////////////////////////////////////////////
// plNetMsgRelevanceRegions
////////////////////////////////////////////////////////////////////
int plNetMsgRelevanceRegions::IPokeBuffer( hsStream* stream, UInt32 peekOptions )
{
plNetMessage::IPokeBuffer( stream, peekOptions );
fRegionsICareAbout.Write(stream);
fRegionsImIn.Write(stream);
return stream->GetPosition();
}
int plNetMsgRelevanceRegions::IPeekBuffer( hsStream* stream, UInt32 peekOptions )
{
stream->LogSubStreamPushDesc("RelevanceRegions");
int bytes=plNetMessage::IPeekBuffer(stream, peekOptions );
if (bytes)
{
fRegionsICareAbout.Read(stream);
fRegionsImIn.Read(stream);
bytes=stream->GetPosition();
}
return bytes;
}
////////////////////////////////////////////////////////////////////
// End.