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.
376 lines
9.8 KiB
376 lines
9.8 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 "hsTypes.h" |
|
#define PLMESSAGE_PRIVATE |
|
#include "plMessage.h" |
|
#include "hsStream.h" |
|
#include "pnKeyedObject/plKey.h" |
|
#include "hsResMgr.h" |
|
#include "hsTimer.h" |
|
#include "hsTemplates.h" |
|
#include "plgDispatch.h" |
|
#include "hsBitVector.h" |
|
#include <algorithm> |
|
#include <iterator> |
|
|
|
plMessage::plMessage() |
|
: fSender(nil), |
|
fBCastFlags(kLocalPropagate), |
|
fTimeStamp(0), |
|
fNetRcvrPlayerIDs(nil), |
|
dispatchBreak(false) |
|
{ |
|
} |
|
|
|
plMessage::plMessage(const plKey &s, |
|
const plKey &r, |
|
const double* t) |
|
: fSender(s), |
|
fBCastFlags(kLocalPropagate), |
|
fNetRcvrPlayerIDs(nil), |
|
dispatchBreak(false) |
|
{ |
|
if( r ) |
|
{ |
|
fReceivers.SetCount(1); |
|
fReceivers[0] = r; |
|
} |
|
fTimeStamp = t ? *t : hsTimer::GetSysSeconds(); |
|
} |
|
|
|
plMessage::~plMessage() |
|
{ |
|
delete fNetRcvrPlayerIDs; |
|
} |
|
|
|
plMessage& plMessage::SetNumReceivers(int n) { fReceivers.SetCount(n); return *this; } |
|
UInt32 plMessage::GetNumReceivers() const { return fReceivers.GetCount(); } |
|
const plKey& plMessage::GetReceiver(int i) const { return fReceivers[i]; } |
|
plMessage& plMessage::RemoveReceiver(int i) { fReceivers.Remove(i); return *this; } |
|
|
|
plMessage& plMessage::ClearReceivers() { fReceivers.SetCount(0); return *this; } |
|
plMessage& plMessage::AddReceiver(const plKey &r) { fReceivers.Append(r); return *this; } |
|
|
|
plMessage& plMessage::AddReceivers(const hsTArray<plKey>& rList) |
|
{ |
|
int i; |
|
for( i = 0; i < rList.GetCount(); i++ ) |
|
AddReceiver(rList[i]); |
|
|
|
return *this; |
|
} |
|
|
|
hsBool plMessage::Send(const plKey r, hsBool async) |
|
{ |
|
if( r ) |
|
AddReceiver(r); |
|
return plgDispatch::MsgSend(this,async); |
|
} |
|
|
|
hsBool plMessage::SendAndKeep(const plKey r, hsBool async) |
|
{ |
|
Ref(); |
|
return Send(r, async); |
|
} |
|
|
|
void plMessage::IMsgRead(hsStream* s, hsResMgr* mgr) |
|
{ |
|
plCreatable::Read(s, mgr); |
|
|
|
fSender = mgr->ReadKey(s); |
|
int n; |
|
s->LogReadSwap(&n,"NumberOfReceivers"); |
|
fReceivers.SetCount(n); |
|
int i; |
|
for( i = 0; i < fReceivers.GetCount(); i++ ) |
|
fReceivers[i] = mgr->ReadKey(s); |
|
|
|
s->LogReadSwap(&fTimeStamp,"TimeStamp"); // read as double |
|
s->LogReadSwap(&fBCastFlags, "BCastFlags"); |
|
} |
|
|
|
void plMessage::IMsgWrite(hsStream* s, hsResMgr* mgr) |
|
{ |
|
plCreatable::Write(s, mgr); |
|
|
|
mgr->WriteKey(s,fSender); |
|
s->WriteSwap32(fReceivers.GetCount()); |
|
int i; |
|
for( i = 0; i < fReceivers.GetCount(); i++ ) |
|
mgr->WriteKey(s,fReceivers[i]); |
|
|
|
s->WriteSwap(fTimeStamp); // write as double |
|
s->WriteSwap32(fBCastFlags); |
|
} |
|
|
|
enum MsgFlags |
|
{ |
|
kMsgSender, |
|
kMsgReceivers, |
|
kMsgTimeStamp, |
|
kMsgBCastFlags, |
|
}; |
|
|
|
void plMessage::IMsgReadVersion(hsStream* s, hsResMgr* mgr) |
|
{ |
|
hsBitVector contentFlags; |
|
contentFlags.Read(s); |
|
|
|
if (contentFlags.IsBitSet(kMsgSender)) |
|
fSender = mgr->ReadKey(s); |
|
|
|
if (contentFlags.IsBitSet(kMsgReceivers)) |
|
{ |
|
int n = s->ReadSwap32(); |
|
fReceivers.SetCount(n); |
|
int i; |
|
for( i = 0; i < fReceivers.GetCount(); i++ ) |
|
fReceivers[i] = mgr->ReadKey(s); |
|
} |
|
|
|
if (contentFlags.IsBitSet(kMsgTimeStamp)) |
|
s->ReadSwap(&fTimeStamp); // read as double |
|
|
|
if (contentFlags.IsBitSet(kMsgBCastFlags)) |
|
fBCastFlags = s->ReadSwap32(); |
|
} |
|
|
|
void plMessage::IMsgWriteVersion(hsStream* s, hsResMgr* mgr) |
|
{ |
|
hsBitVector contentFlags; |
|
contentFlags.SetBit(kMsgSender); |
|
contentFlags.SetBit(kMsgReceivers); |
|
contentFlags.SetBit(kMsgTimeStamp); |
|
contentFlags.SetBit(kMsgBCastFlags); |
|
contentFlags.Write(s); |
|
|
|
// kMsgSender |
|
mgr->WriteKey(s,fSender); |
|
|
|
// kMsgReceivers |
|
s->WriteSwap32(fReceivers.GetCount()); |
|
int i; |
|
for( i = 0; i < fReceivers.GetCount(); i++ ) |
|
mgr->WriteKey(s,fReceivers[i]); |
|
|
|
// kMsgTimeStamp |
|
s->WriteSwap(fTimeStamp); // write as double |
|
|
|
// kMsgBCastFlags |
|
s->WriteSwap32(fBCastFlags); |
|
} |
|
|
|
void plMessage::AddNetReceiver( UInt32 plrID ) |
|
{ |
|
if ( !fNetRcvrPlayerIDs ) |
|
fNetRcvrPlayerIDs = TRACKED_NEW std::vector<UInt32>; |
|
fNetRcvrPlayerIDs->push_back( plrID ); |
|
} |
|
|
|
void plMessage::AddNetReceivers( const std::vector<UInt32> & plrIDs ) |
|
{ |
|
if ( !fNetRcvrPlayerIDs ) |
|
fNetRcvrPlayerIDs = TRACKED_NEW std::vector<UInt32>; |
|
std::copy( plrIDs.begin(), plrIDs.end(), std::back_inserter( *fNetRcvrPlayerIDs ) ); |
|
} |
|
|
|
///////////////////////////////////////////////////////////////// |
|
|
|
// STATIC |
|
int plMsgStdStringHelper::Poke(const std::string & stringref, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
plMessage::plStrLen strlen; |
|
hsAssert( stringref.length()<0xFFFF, "buf too big for plMsgStdStringHelper" ); |
|
strlen = stringref.length(); |
|
stream->WriteSwap(strlen); |
|
if (strlen) |
|
stream->Write(strlen,stringref.data()); |
|
return stream->GetPosition(); |
|
} |
|
|
|
int plMsgStdStringHelper::PokeBig(const std::string & stringref, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
UInt32 strlen = stringref.length(); |
|
stream->WriteSwap(strlen); |
|
if (strlen) |
|
stream->Write(strlen,stringref.data()); |
|
return stream->GetPosition(); |
|
} |
|
|
|
int plMsgStdStringHelper::Poke(const char * buf, UInt32 bufsz, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
plMessage::plStrLen strlen; |
|
hsAssert( bufsz<0xFFFF, "buf too big for plMsgStdStringHelper" ); |
|
strlen = (plMessage::plStrLen)bufsz; |
|
stream->WriteSwap(strlen); |
|
if (strlen) |
|
stream->Write(strlen,buf); |
|
return stream->GetPosition(); |
|
} |
|
|
|
int plMsgStdStringHelper::PokeBig(const char * buf, UInt32 bufsz, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
stream->WriteSwap(bufsz); |
|
if (bufsz) |
|
stream->Write(bufsz,buf); |
|
return stream->GetPosition(); |
|
} |
|
|
|
// STATIC |
|
int plMsgStdStringHelper::Peek(std::string & stringref, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
plMessage::plStrLen strlen; |
|
stream->LogSubStreamStart("push this"); |
|
stream->LogReadSwap(&strlen,"StrLen"); |
|
stringref.erase(); |
|
if (strlen <= stream->GetSizeLeft()) |
|
{ |
|
stringref.resize(strlen); |
|
if (strlen){ |
|
stream->LogRead(strlen,(void*)stringref.data(),"StdString"); |
|
stream->LogStringString(xtl::format("Value: %s", stringref.data()).c_str()); |
|
} |
|
} |
|
else |
|
{ |
|
hsAssert( false, "plMsgStdStringHelper::Peek: overflow peeking string." ); |
|
} |
|
stream->LogSubStreamEnd(); |
|
return stream->GetPosition(); |
|
} |
|
|
|
int plMsgStdStringHelper::PeekBig(std::string & stringref, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
UInt32 bufsz; |
|
stream->LogSubStreamStart("push this"); |
|
stream->LogReadSwap(&bufsz,"Bufsz"); |
|
stringref.erase(); |
|
if (bufsz <= stream->GetSizeLeft()) |
|
{ |
|
stringref.resize(bufsz); |
|
if (bufsz){ |
|
stream->LogRead(bufsz,(void*)stringref.data(),"StdString"); |
|
stream->LogStringString(xtl::format("Value: %s", stringref.data()).c_str()); |
|
} |
|
} |
|
else |
|
{ |
|
hsAssert( false, "plMsgStdStringHelper::PeekBig: overflow peeking string." ); |
|
} |
|
stream->LogSubStreamEnd(); |
|
return stream->GetPosition(); |
|
} |
|
|
|
///////////////////////////////////////////////////////////////// |
|
|
|
// STATIC |
|
int plMsgXtlStringHelper::Poke(const xtl::istring & stringref, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
plMessage::plStrLen strlen; |
|
strlen = stringref.length(); |
|
stream->WriteSwap(strlen); |
|
if (strlen) |
|
stream->Write(strlen,stringref.data()); |
|
return stream->GetPosition(); |
|
} |
|
|
|
// STATIC |
|
int plMsgXtlStringHelper::Peek(xtl::istring & stringref, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
plMessage::plStrLen strlen; |
|
stream->LogSubStreamStart("push me"); |
|
stream->LogReadSwap(&strlen,"StrLen"); |
|
stringref.erase(); |
|
if (strlen <= stream->GetSizeLeft()) |
|
{ |
|
stringref.resize(strlen); |
|
if (strlen){ |
|
stream->LogRead(strlen,(void*)stringref.data(),"XtlString"); |
|
stream->LogStringString(xtl::format("Value: %s", stringref.data()).c_str()); |
|
} |
|
} |
|
stream->LogSubStreamEnd(); |
|
return stream->GetPosition(); |
|
} |
|
|
|
|
|
///////////////////////////////////////////////////////////////// |
|
|
|
// STATIC |
|
int plMsgCStringHelper::Poke(const char * str, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
plMessage::plStrLen strlen; |
|
strlen = (str)?hsStrlen(str):0; |
|
stream->WriteSwap(strlen); |
|
if (strlen) |
|
stream->Write(strlen,str); |
|
return stream->GetPosition(); |
|
} |
|
|
|
// STATIC |
|
int plMsgCStringHelper::Peek(char *& str, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
plMessage::plStrLen strlen; |
|
stream->LogSubStreamStart("push me"); |
|
stream->LogReadSwap(&strlen,"StrLen"); |
|
delete [] str; |
|
str = nil; |
|
if (strlen <= stream->GetSizeLeft()) |
|
{ |
|
if (strlen) |
|
{ |
|
str = TRACKED_NEW char[strlen+1]; |
|
str[strlen] = '\0'; |
|
if (strlen) { |
|
stream->LogRead(strlen,str,"CString"); |
|
stream->LogStringString(xtl::format("Value: %s",str).c_str()); |
|
} |
|
} |
|
} |
|
stream->LogSubStreamEnd(); |
|
return stream->GetPosition(); |
|
} |
|
|
|
|
|
///////////////////////////////////////////////////////////////// |
|
|
|
// STATIC |
|
int plMsgCArrayHelper::Poke(const void * buf, UInt32 bufsz, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
stream->Write(bufsz,buf); |
|
return stream->GetPosition(); |
|
} |
|
|
|
// STATIC |
|
int plMsgCArrayHelper::Peek(void * buf, UInt32 bufsz, hsStream* stream, const UInt32 peekOptions) |
|
{ |
|
stream->LogSubStreamStart("push me"); |
|
stream->LogRead(bufsz,buf,"CArray"); |
|
stream->LogSubStreamEnd(); |
|
return stream->GetPosition(); |
|
} |
|
|
|
|