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.
 
 
 
 
 

1376 lines
37 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/>.
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.