/*==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==*/
#pragma warning(disable: 4786)
#include "hsTimer.h"
#include "plNetTransport.h"
#include "plNetTransportMember.h"
#include "../plNetMessage/plNetMessage.h"
#include "../plNetClient/plNetClientMgr.h"
#include
plNetTransport::~plNetTransport()
{
ClearMembers();
}
//
// add a member to the master list if not already there
//
int plNetTransport::AddMember(plNetTransportMember* mbr)
{
if (FindMember(mbr)==-1)
{
fMembers.push_back(mbr);
hsLogEntry( plNetClientMgr::GetInstance()->DebugMsg("Adding member %s", mbr->AsStdString().c_str()) );
plNetClientMgr::GetInstance()->GetListenList()->AddMember(mbr);
plNetClientMgr::GetInstance()->GetTalkList()->AddMember(mbr);
DumpState();
return fMembers.size()-1;
}
return -1;
}
void plNetTransport::IUnSubscribeToAllChannelGrps(plNetTransportMember* mbr)
{
int i;
for( i=mbr->GetNumSubscriptions()-1; i>=0 ; i-- )
{
int chan=mbr->GetSubscription(i);
hsBool ok=UnSubscribeToChannelGrp(mbr, chan);
hsAssert(ok, "can't find supposed subscription to remove");
} // for
}
void plNetTransport::IRemoveMember(plNetTransportMember* mbr)
{
if (!mbr)
return;
hsLogEntry( plNetClientMgr::GetInstance()->DebugMsg("Removing member %s", mbr->AsStdString().c_str()) );
// plNetClientMgr::GetInstance()->GetNetCore()->RemovePeer(mbr->GetPeerID());
plNetClientMgr::GetInstance()->GetTalkList()->RemoveMember(mbr);
plNetClientMgr::GetInstance()->GetListenList()->RemoveMember(mbr);
// remove member from subscription lists
IUnSubscribeToAllChannelGrps(mbr);
plMembersList::iterator it=std::find(fMembers.begin(),fMembers.end(),mbr);
// remove member from master list
fMembers.erase(it);
hsLogEntry( plNetClientMgr::GetInstance()->DebugMsg("Done Removing member %s", mbr->AsStdString().c_str()) );
DumpState();
delete mbr;
}
//
// remove member from master list, and all subscription channels.
// return true on success.
//
hsBool plNetTransport::RemoveMember(int idx)
{
if (idx>=0)
{
plNetTransportMember* mbr=GetMember(idx);
IRemoveMember(mbr);
return true;
}
return false;
}
//
// remove member from master list, and all subscription channels.
// return true on success.
//
hsBool plNetTransport::RemoveMember(plNetTransportMember* mbr)
{
IRemoveMember(mbr);
return true;
}
//
// return array index or -1
//
int plNetTransport::FindMember(const plNetTransportMember* mbr)
{
plMembersList::iterator it = std::find(fMembers.begin(), fMembers.end(), mbr);
return (it==fMembers.end()) ? -1 : (it-fMembers.begin());
}
//
// add this member to the given channel grp
//
void plNetTransport::SubscribeToChannelGrp(plNetTransportMember* mbr, int channel)
{
// hsAssert(FindMember(mbr) != -1, "must add member before subscribing to channel");
if (mbr->AddSubscription(channel))
{
hsAssert(channel=0 && chanbegin(), mList->end(), mbr);
if (it != mList->end())
{
mList->erase(it);
hsBool ret=mbr->RemoveSubscription(chan);
hsAssert(ret, "error removing subscription");
return true;
}
return false;
}
//
// copy list of members channelGrp subscriptions
//
void plNetTransport::GetSubscriptions(plNetTransportMember* mbr, std::vector* channels) const
{
mbr->CopySubscriptions(channels);
}
//
// Send Msg to all members in the given channelGrp.
// Here's where multicasting would be used.
// Returns neg number (NetCore::RetCode) on send error, 1, if not sent, and 0 if sent
//
int plNetTransport::SendMsg(int chan, plNetMessage* netMsg) const
{
NetCommSendMsg(netMsg);
return hsOK;
plNetClientMgr* nc=plNetClientMgr::GetInstance();
int ret=1; // didn't send
if (chan < fChannelGroups.size())
{
const plMembersList* mList = &fChannelGroups[chan];
// does this msg have a list of receivers
plNetMsgReceiversListHelper* rl = plNetMsgReceiversListHelper::ConvertNoRef(netMsg);
#if 0
// send msg to all subscribers to this channel
int size=mList->size();
for( int i=0 ; iGetPeerID();
// hsAssert(peerID>=0, "queing message to invalid peer");
// if ((ncRet=nc->GetNetClientComm().SendMsg(netMsg, peerID, sendFlags, msgSize)) != plNetCore::kNetOK)
NetCommSendMsg(netMsg);
if (rl)
{
hsBool ok=rl->RemoveReceiverPlayerID(tm->GetPlayerID());
hsAssert(ok, "couldn't find rcvr to remove?");
}
ret=0; // sent ok
} // for
#endif
// if there are rcvrs left that we couldn't send to, send via server
if (rl && rl->GetNumReceivers())
{
// if ((ncRet=nc->GetNetClientComm().SendMsg(netMsg, nc->GetServerPeerID(), sendFlags, msgSize)) != plNetCore::kNetOK)
NetCommSendMsg(netMsg);
ret=0; // sent
}
}
else
{
hsStatusMessage("EMPTY TRANSPORT GROUP\n");
}
return ret;
}
void plNetTransport::ClearMembers()
{
int i;
for( i=0 ;iGetPlayerID()==playerID)
return i;
}
return -1;
}
//
// return array index or -1
//
int plNetTransport::FindMember(const plKey avKey) const
{
int i;
for( i=0 ;iGetAvatarKey()==avKey)
return i;
}
return -1;
}
//
// clear channel and unsubscribe all members to that channel
//
void plNetTransport::ClearChannelGrp(int channel)
{
const plMembersList* mList = &fChannelGroups[channel];
int i, size=mList->size();
for( i=0 ; iRemoveSubscription(channel);
hsAssert(ok, "error removing subscription");
}
fChannelGroups[channel].clear();
}
void plNetTransport::DumpState()
{
plNetClientMgr* nc=plNetClientMgr::GetInstance();
hsLogEntry( nc->DebugMsg("-------------------\n") );
hsLogEntry( nc->DebugMsg("Num Channels=%d\n", fChannelGroups.size()) );
int i;
for(i=0;iDebugMsg("\tChannel %d, num mbrs=%d\n", i, mList->size()) );
int j;
for(j=0; jsize();j++)
{
plNetTransportMember * mbr = (*mList)[j];
hsLogEntry( nc->DebugMsg("\t\tMbr %s\n",(*mList)[j]->AsStdString().c_str()) );
}
}
nc->DebugMsg("Num Mbrs=%d\n", GetNumMembers());
for(i=0;iDebugMsg("\tMbr %d, name=%s, plyrID=%lu, subs=%d",
i,mbr->AsStdString().c_str(),mbr->GetPlayerID(),mbr->GetNumSubscriptions()) );
int j;
for(j=0;jGetNumSubscriptions();j++)
{
hsLogEntry( nc->DebugMsg("\t\tSub %d, chan=%d\n", j, mbr->GetSubscription(j)) );
}
}
hsLogEntry( nc->DebugMsg("\n") );
}
void plNetTransport::SetNumChannels(int n)
{
if (n>fChannelGroups.size())
fChannelGroups.resize(n);
}
int compare( const void* arg1, const void *arg2 )
{
plNetTransportMember** m1 = (plNetTransportMember**)arg1;
plNetTransportMember** m2 = (plNetTransportMember**)arg2;
float d1=m1 ? (*m1)->GetDistSq() : hsScalarMax;
float d2=m2 ? (*m2)->GetDistSq() : hsScalarMax;
return (int)(d1-d2);
}
//
// create a members list sorted by dist.
// caller must delete this when done
//
void plNetTransport::GetMemberListDistSorted(plNetTransportMember**& listIn) const
{
// copy members list
listIn = TRACKED_NEW plNetTransportMember* [fMembers.size()];
int i;
for (i=0; i