/*==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 . 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 #include 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& 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; fNetRcvrPlayerIDs->push_back( plrID ); } void plMessage::AddNetReceivers( const std::vector & plrIDs ) { if ( !fNetRcvrPlayerIDs ) fNetRcvrPlayerIDs = TRACKED_NEW std::vector; 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(); }