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.
564 lines
14 KiB
564 lines
14 KiB
4 years ago
|
/*==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 "plNetMsgHelpers.h"
|
||
|
#include "plNetMessage.h"
|
||
|
#include "../plCompression/plZlibCompress.h"
|
||
|
#include "../pnNetCommon/plNetServers.h"
|
||
|
#include "../pnNetCommon/plNetApp.h"
|
||
|
#include "../pnKeyedObject/plKey.h"
|
||
|
#include "../pnMessage/plMessage.h"
|
||
|
#include "hsStream.h"
|
||
|
#include <algorithm>
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
// plNetMsgStreamableHelper
|
||
|
|
||
|
plNetMsgStreamableHelper & plNetMsgStreamableHelper::operator =(hsStreamable * value)
|
||
|
{
|
||
|
fObject = value;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
int plNetMsgStreamableHelper::Poke(hsStream* stream, UInt32 peekOptions)
|
||
|
{
|
||
|
hsAssert(fObject, "plNetMsgStreamableHelper::Poke: fObject not set.");
|
||
|
fObject->Write(stream);
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
int plNetMsgStreamableHelper::Peek(hsStream* stream, UInt32 peekOptions)
|
||
|
{
|
||
|
hsAssert(fObject, "plNetMsgStreamableHelper::Peek: fObject not set.");
|
||
|
fObject->Read(stream);
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
// plNetMsgCreatableHelper
|
||
|
|
||
|
plNetMsgCreatableHelper::plNetMsgCreatableHelper(plCreatable * object)
|
||
|
:fCreatable(object)
|
||
|
,fWeCreatedIt(false)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
plNetMsgCreatableHelper::~plNetMsgCreatableHelper()
|
||
|
{
|
||
|
if (fWeCreatedIt)
|
||
|
hsRefCnt_SafeUnRef(fCreatable);
|
||
|
}
|
||
|
|
||
|
plNetMsgCreatableHelper & plNetMsgCreatableHelper::operator =(plCreatable * value)
|
||
|
{
|
||
|
SetObject(value);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
plNetMsgCreatableHelper::operator plCreatable*()
|
||
|
{
|
||
|
return GetObject();
|
||
|
}
|
||
|
|
||
|
plNetMsgCreatableHelper::operator const plCreatable*()
|
||
|
{
|
||
|
return GetObject();
|
||
|
}
|
||
|
|
||
|
void plNetMsgCreatableHelper::SetObject(plCreatable * object)
|
||
|
{
|
||
|
if (fWeCreatedIt)
|
||
|
hsRefCnt_SafeUnRef(fCreatable);
|
||
|
fCreatable = object;
|
||
|
fWeCreatedIt = false;
|
||
|
}
|
||
|
|
||
|
plCreatable * plNetMsgCreatableHelper::GetObject()
|
||
|
{
|
||
|
return fCreatable;
|
||
|
}
|
||
|
|
||
|
int plNetMsgCreatableHelper::Poke(hsStream * s, UInt32 peekOptions)
|
||
|
{
|
||
|
hsAssert(fCreatable,"plNetMsgCreatableHelper::Poke: fCreatable not set");
|
||
|
UInt16 classIndex = fCreatable->ClassIndex();
|
||
|
s->WriteSwap(classIndex);
|
||
|
fCreatable->Write(s,nil);
|
||
|
return s->GetPosition();
|
||
|
}
|
||
|
|
||
|
int plNetMsgCreatableHelper::Peek(hsStream * s, UInt32 peekOptions)
|
||
|
{
|
||
|
UInt16 classIndex;
|
||
|
s->LogSubStreamStart("push me");
|
||
|
s->LogReadSwap(&classIndex,"ClassIdx");
|
||
|
SetObject(plFactory::Create(classIndex));
|
||
|
fWeCreatedIt = true;
|
||
|
hsAssert(fCreatable,"plNetMsgCreatableHelper::Peek: Failed to create plCreatable. Invalid ClassIndex?");
|
||
|
fCreatable->Read(s,nil);
|
||
|
s->LogSubStreamEnd();
|
||
|
return s->GetPosition();
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////
|
||
|
// NOT A MSG
|
||
|
// PL STREAM MSG - HELPER class
|
||
|
/////////////////////////////////////////////////////////
|
||
|
plNetMsgStreamHelper::plNetMsgStreamHelper() : fStreamBuf(nil), fStreamType(-1), fStreamLen(0),
|
||
|
fCompressionType(plNetMessage::kCompressionNone), fUncompressedSize(0),
|
||
|
fCompressionThreshold( kDefaultCompressionThreshold )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void plNetMsgStreamHelper::Clear()
|
||
|
{
|
||
|
delete [] fStreamBuf;
|
||
|
fStreamBuf = nil;
|
||
|
fStreamType = 0xff;
|
||
|
fStreamLen = 0;
|
||
|
fCompressionType = plNetMessage::kCompressionNone;
|
||
|
fCompressionThreshold = kDefaultCompressionThreshold;
|
||
|
}
|
||
|
|
||
|
int plNetMsgStreamHelper::Poke(hsStream* stream, UInt32 peekOptions)
|
||
|
{
|
||
|
if ( !(peekOptions & plNetMessage::kDontCompress) )
|
||
|
Compress();
|
||
|
stream->WriteSwap(fUncompressedSize);
|
||
|
stream->WriteSwap(fCompressionType);
|
||
|
stream->WriteSwap(fStreamLen);
|
||
|
stream->Write(fStreamLen, fStreamBuf);
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
int plNetMsgStreamHelper::Peek(hsStream* stream, const UInt32 peekOptions)
|
||
|
{
|
||
|
stream->LogSubStreamStart("Stream Helper");
|
||
|
stream->LogReadSwap(&fUncompressedSize,"UncompressedSize");
|
||
|
stream->LogReadSwap(&fCompressionType,"CompressionType");
|
||
|
stream->LogReadSwap(&fStreamLen,"StreamLen");
|
||
|
|
||
|
if (fStreamLen) // stream data exists
|
||
|
{
|
||
|
if (!(peekOptions & plNetMessage::kSkipStream))
|
||
|
{
|
||
|
if (!fStreamBuf)
|
||
|
IAllocStream(fStreamLen);
|
||
|
stream->LogRead(fStreamLen, fStreamBuf,"StreamData");
|
||
|
if ( !(peekOptions & plNetMessage::kDontCompress) )
|
||
|
Uncompress();
|
||
|
fStreamType = *(Int16*)fStreamBuf; // grab from start fo stream
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
stream->ReadSwap(&fStreamType); // never compressed, set by reading directly from stream
|
||
|
stream->LogSkip(fStreamLen-sizeof(fStreamType),"SkippedStreamHelper");
|
||
|
}
|
||
|
}
|
||
|
stream->LogSubStreamEnd();
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
void plNetMsgStreamHelper::ReadVersion(hsStream* s, hsResMgr* mgr)
|
||
|
{
|
||
|
hsBitVector contentFlags;
|
||
|
contentFlags.Read(s);
|
||
|
|
||
|
if (contentFlags.IsBitSet(kUncompressedSize))
|
||
|
s->ReadSwap(&fUncompressedSize);
|
||
|
if (contentFlags.IsBitSet(kCompressionType))
|
||
|
s->ReadSwap(&fCompressionType);
|
||
|
if (contentFlags.IsBitSet(kStreamLen))
|
||
|
s->ReadSwap(&fStreamLen);
|
||
|
if (contentFlags.IsBitSet(kStreamBuf))
|
||
|
{
|
||
|
if (!fStreamBuf)
|
||
|
IAllocStream(fStreamLen);
|
||
|
s->Read(fStreamLen,fStreamBuf);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void plNetMsgStreamHelper::WriteVersion(hsStream* s, hsResMgr* mgr)
|
||
|
{
|
||
|
hsBitVector contentFlags;
|
||
|
contentFlags.SetBit(kUncompressedSize);
|
||
|
contentFlags.SetBit(kCompressionType);
|
||
|
contentFlags.SetBit(kStreamLen);
|
||
|
contentFlags.SetBit(kStreamBuf);
|
||
|
contentFlags.Write(s);
|
||
|
|
||
|
s->WriteSwap(fUncompressedSize);
|
||
|
s->WriteSwap(fCompressionType);
|
||
|
s->WriteSwap(fStreamLen);
|
||
|
s->Write(fStreamLen,fStreamBuf);
|
||
|
}
|
||
|
|
||
|
void plNetMsgStreamHelper::IAllocStream(UInt32 len)
|
||
|
{
|
||
|
delete [] fStreamBuf;
|
||
|
fStreamBuf=nil;
|
||
|
fStreamLen=len;
|
||
|
if (len)
|
||
|
fStreamBuf = TRACKED_NEW UInt8[len];
|
||
|
}
|
||
|
|
||
|
void plNetMsgStreamHelper::CopyStream(hsStream* ssStream)
|
||
|
{
|
||
|
UInt32 len=ssStream->GetEOF();
|
||
|
IAllocStream(len);
|
||
|
ssStream->CopyToMem(fStreamBuf);
|
||
|
fStreamType = *(Int16*)fStreamBuf;
|
||
|
}
|
||
|
|
||
|
void plNetMsgStreamHelper::CopyStream(Int32 len, const void* buf)
|
||
|
{
|
||
|
IAllocStream(len);
|
||
|
memcpy(fStreamBuf, buf, len);
|
||
|
fStreamType = *(Int16*)fStreamBuf;
|
||
|
}
|
||
|
|
||
|
void plNetMsgStreamHelper::CopyFrom(const plNetMsgStreamHelper* other)
|
||
|
{
|
||
|
fUncompressedSize = other->GetUncompressedSize();
|
||
|
fCompressionType = other->GetCompressionType();
|
||
|
CopyStream(other->GetStreamLen(), other->GetStreamBuf());
|
||
|
}
|
||
|
|
||
|
bool plNetMsgStreamHelper::Compress(int offset)
|
||
|
{
|
||
|
if ( !IsCompressable() )
|
||
|
return true;
|
||
|
|
||
|
plZlibCompress compressor;
|
||
|
UInt8* buf = (UInt8*)GetStreamBuf(); // skip creatable index
|
||
|
UInt32 bufLen = GetStreamLen();
|
||
|
UInt32 uncompressedSize = bufLen;
|
||
|
SetUncompressedSize( uncompressedSize );
|
||
|
if ( compressor.Compress( &buf, &bufLen, offset) )
|
||
|
{
|
||
|
SetCompressionType( plNetMessage::kCompressionZlib );
|
||
|
SetStreamLen(bufLen);
|
||
|
SetStreamBuf(buf);
|
||
|
Int32 diff = uncompressedSize-bufLen;
|
||
|
#if 0
|
||
|
plNetApp::StaticDebugMsg( "\tCompressed stream: %lu->%lu bytes, (%s %d bytes, %.1f%%)",
|
||
|
uncompressedSize, bufLen, (diff>=0)?"shrunk":"GREW?!?", diff, (diff/(float)uncompressedSize)*100 );
|
||
|
#endif
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hsAssert( false, "plNetMsgStreamHelper: Compression failed" );
|
||
|
SetCompressionType( plNetMessage::kCompressionFailed );
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool plNetMsgStreamHelper::Uncompress(int offset)
|
||
|
{
|
||
|
if ( !IsCompressed() )
|
||
|
return true;
|
||
|
|
||
|
UInt32 origLen = GetStreamLen();
|
||
|
plZlibCompress compressor;
|
||
|
UInt8* buf = (UInt8*)GetStreamBuf();
|
||
|
UInt32 bufLen = origLen;
|
||
|
if ( compressor.Uncompress( &buf, &bufLen, GetUncompressedSize(), offset ) )
|
||
|
{
|
||
|
SetCompressionType( plNetMessage::kCompressionNone );
|
||
|
SetStreamLen(bufLen);
|
||
|
SetStreamBuf(buf);
|
||
|
Int32 diff = bufLen-origLen;
|
||
|
#if 0
|
||
|
plNetApp::StaticDebugMsg( "\tUncompressed stream: %lu->%lu bytes, (%s %d bytes, %.1f%%)",
|
||
|
origLen, bufLen, (diff>=0)?"grew":"SHRUNK?!?", diff, (diff/(float)bufLen)*100 );
|
||
|
#endif
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hsAssert( false, "plNetMsgStreamHelper: Uncompression failed" );
|
||
|
SetCompressionType( plNetMessage::kCompressionFailed );
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool plNetMsgStreamHelper::IsCompressed() const
|
||
|
{
|
||
|
return ( fCompressionType==plNetMessage::kCompressionZlib );
|
||
|
}
|
||
|
|
||
|
bool plNetMsgStreamHelper::IsCompressable() const
|
||
|
{
|
||
|
return ( fCompressionType==plNetMessage::kCompressionNone
|
||
|
&& fStreamLen>fCompressionThreshold );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////
|
||
|
// NOT A MSG
|
||
|
// plNetMsgObject - HELPER class
|
||
|
////////////////////////////////////////////////////////
|
||
|
|
||
|
plNetMsgObjectHelper & plNetMsgObjectHelper::operator =(const plNetMsgObjectHelper & other)
|
||
|
{
|
||
|
fUoid = other.GetUoid();
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
int plNetMsgObjectHelper::Poke(hsStream* stream, UInt32 peekOptions)
|
||
|
{
|
||
|
fUoid.Write(stream);
|
||
|
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
int plNetMsgObjectHelper::Peek(hsStream* stream, const UInt32 peekOptions)
|
||
|
{
|
||
|
stream->LogSubStreamStart("push me");
|
||
|
fUoid.Read(stream);
|
||
|
stream->LogSubStreamEnd();
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
hsBool plNetMsgObjectHelper::SetFromKey(const plKey &key)
|
||
|
{
|
||
|
if (!key || !key->GetName())
|
||
|
return false;
|
||
|
|
||
|
fUoid = key->GetUoid();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void plNetMsgObjectHelper::ReadVersion(hsStream* s, hsResMgr* mgr)
|
||
|
{
|
||
|
hsBitVector contentFlags;
|
||
|
contentFlags.Read(s);
|
||
|
|
||
|
if (contentFlags.IsBitSet(kObjHelperUoid))
|
||
|
fUoid.Read(s);
|
||
|
}
|
||
|
|
||
|
void plNetMsgObjectHelper::WriteVersion(hsStream* s, hsResMgr* mgr)
|
||
|
{
|
||
|
hsBitVector contentFlags;
|
||
|
contentFlags.SetBit(kObjHelperUoid);
|
||
|
contentFlags.Write(s);
|
||
|
|
||
|
// kObjHelperUoid
|
||
|
fUoid.Write(s);
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////
|
||
|
// NOT A MSG
|
||
|
// plNetMsgObjectList - HELPER class
|
||
|
////////////////////////////////////////////////////////
|
||
|
plNetMsgObjectListHelper::~plNetMsgObjectListHelper()
|
||
|
{
|
||
|
Reset();
|
||
|
}
|
||
|
|
||
|
void plNetMsgObjectListHelper::Reset()
|
||
|
{
|
||
|
int i;
|
||
|
for( i=0 ; i<GetNumObjects() ; i++ )
|
||
|
{
|
||
|
delete GetObject(i);
|
||
|
fObjects[i] = nil;
|
||
|
} // for
|
||
|
fObjects.clear();
|
||
|
}
|
||
|
|
||
|
int plNetMsgObjectListHelper::Poke(hsStream* stream, UInt32 peekOptions)
|
||
|
{
|
||
|
Int16 num = GetNumObjects();
|
||
|
stream->WriteSwap(num);
|
||
|
int i;
|
||
|
for( i=0 ;i<num ;i++ )
|
||
|
{
|
||
|
GetObject(i)->Poke(stream, peekOptions);
|
||
|
} // for
|
||
|
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
int plNetMsgObjectListHelper::Peek(hsStream* stream, const UInt32 peekOptions)
|
||
|
{
|
||
|
Reset();
|
||
|
|
||
|
stream->LogSubStreamStart("push me");
|
||
|
Int16 num;
|
||
|
stream->LogReadSwap(&num,"ObjectListHelper Num");
|
||
|
|
||
|
int i;
|
||
|
for( i=0 ;i<num ;i++ )
|
||
|
{
|
||
|
fObjects.push_back(TRACKED_NEW plNetMsgObjectHelper);
|
||
|
GetObject(i)->Peek(stream, peekOptions);
|
||
|
} // for
|
||
|
stream->LogSubStreamEnd();
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////
|
||
|
// NOT A MSG
|
||
|
// plNetMsgMemberInfoHelper - HELPER class
|
||
|
////////////////////////////////////////////////////////
|
||
|
plNetMsgMemberInfoHelper::plNetMsgMemberInfoHelper()
|
||
|
: fFlags(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
int plNetMsgMemberInfoHelper::Peek(hsStream* s, const UInt32 peekOptions)
|
||
|
{
|
||
|
s->LogSubStreamStart("push me");
|
||
|
s->LogReadSwap(&fFlags,"MemberInfoHelper Flags");
|
||
|
fClientGuid.Read( s, nil );
|
||
|
fAvatarUoid.Read(s);
|
||
|
s->LogSubStreamEnd();
|
||
|
return s->GetPosition();
|
||
|
}
|
||
|
|
||
|
int plNetMsgMemberInfoHelper::Poke(hsStream* s, const UInt32 peekOptions)
|
||
|
{
|
||
|
s->WriteSwap(fFlags);
|
||
|
fClientGuid.Write( s, nil );
|
||
|
fAvatarUoid.Write(s);
|
||
|
return s->GetPosition();
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////
|
||
|
// NOT A MSG
|
||
|
// plNetMsgMemberListHelper - HELPER class
|
||
|
////////////////////////////////////////////////////////
|
||
|
plNetMsgMemberListHelper::~plNetMsgMemberListHelper()
|
||
|
{
|
||
|
int i;
|
||
|
for(i=0;i<GetNumMembers();i++)
|
||
|
delete fMembers[i];
|
||
|
}
|
||
|
|
||
|
int plNetMsgMemberListHelper::Peek(hsStream* stream, const UInt32 peekOptions)
|
||
|
{
|
||
|
Int16 numMembers;
|
||
|
stream->LogSubStreamStart("push me");
|
||
|
stream->LogReadSwap(&numMembers,"MemberListHelper NumMembers");
|
||
|
fMembers.clear();
|
||
|
int i;
|
||
|
for(i=0;i<numMembers;i++)
|
||
|
{
|
||
|
plNetMsgMemberInfoHelper* addr=TRACKED_NEW plNetMsgMemberInfoHelper;
|
||
|
addr->Peek(stream, peekOptions);
|
||
|
AddMember(addr);
|
||
|
}
|
||
|
stream->LogSubStreamEnd();
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
int plNetMsgMemberListHelper::Poke(hsStream* stream, const UInt32 peekOptions)
|
||
|
{
|
||
|
Int16 numMembers = (Int16)GetNumMembers();
|
||
|
stream->WriteSwap(numMembers);
|
||
|
|
||
|
int i;
|
||
|
for(i=0;i<numMembers;i++)
|
||
|
{
|
||
|
fMembers[i]->GetClientGuid()->SetClientKey("");
|
||
|
fMembers[i]->GetClientGuid()->SetAccountUUID(plUUID());
|
||
|
fMembers[i]->Poke(stream, peekOptions);
|
||
|
}
|
||
|
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////
|
||
|
// NOT A MSG
|
||
|
// plNetMsgReceiversListHelper - HELPER class
|
||
|
////////////////////////////////////////////////////////
|
||
|
|
||
|
int plNetMsgReceiversListHelper::Peek(hsStream* stream, const UInt32 peekOptions)
|
||
|
{
|
||
|
UInt8 numIDs;
|
||
|
stream->LogSubStreamStart("push me");
|
||
|
stream->LogReadSwap(&numIDs,"ReceiversListHelper NumIDs");
|
||
|
|
||
|
fPlayerIDList.clear();
|
||
|
int i;
|
||
|
for(i=0;i<numIDs;i++)
|
||
|
{
|
||
|
UInt32 ID;
|
||
|
stream->LogReadSwap(&ID,"ReceiversListHelper ID");
|
||
|
AddReceiverPlayerID(ID);
|
||
|
}
|
||
|
stream->LogSubStreamEnd();
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
int plNetMsgReceiversListHelper::Poke(hsStream* stream, const UInt32 peekOptions)
|
||
|
{
|
||
|
UInt8 numIDs = (UInt8)GetNumReceivers();
|
||
|
stream->WriteSwap(numIDs);
|
||
|
|
||
|
int i;
|
||
|
for(i=0;i<numIDs;i++)
|
||
|
stream->WriteSwap(GetReceiverPlayerID(i));
|
||
|
|
||
|
return stream->GetPosition();
|
||
|
}
|
||
|
|
||
|
|
||
|
bool plNetMsgReceiversListHelper::RemoveReceiverPlayerID(UInt32 n)
|
||
|
{
|
||
|
std::vector<UInt32>::iterator res = std::find(fPlayerIDList.begin(), fPlayerIDList.end(), n);
|
||
|
if (res != fPlayerIDList.end())
|
||
|
{
|
||
|
fPlayerIDList.erase(res);
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|