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.

377 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();
}