2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 02:27:40 -04:00

CWE Directory Reorganization

Rearrange directory structure of CWE to be loosely equivalent to
the H'uru Plasma repository.

Part 1: Movement of directories and files.
This commit is contained in:
rarified
2021-05-15 12:49:46 -06:00
parent c3f4a640a3
commit 96903e8dca
4002 changed files with 159 additions and 644 deletions

View File

@ -0,0 +1,610 @@
/*==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 "hsTypes.h"
#include "../pnKeyedObject/plKey.h"
#include "hsTemplates.h"
#include "hsStream.h"
#include "plLinkEffectsMgr.h"
#include "../pnMessage/plEventCallbackMsg.h"
#include "../pnMessage/plTimeMsg.h"
#include "../pnMessage/plPlayerPageMsg.h"
#include "../plMessage/plLinkToAgeMsg.h"
#include "../plMessage/plTransitionMsg.h"
#include "plgDispatch.h"
#include "hsResMgr.h"
#include "hsTimer.h"
#include "../pnNetCommon/plNetApp.h"
#include "../plNetClient/plNetClientMgr.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plNetTransport/plNetTransportMember.h"
#include "../plVault/plVault.h"
#include "../plNetClient/plNetLinkingMgr.h"
#include "../plAgeLoader/plAgeLoader.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnMessage/plWarpMsg.h"
#include "../pnKeyedObject/plFixedKey.h"
// chronicle var
#define kCleftSolved L"CleftSolved"
#include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvatarTasks.h"
#include "../plAvatar/plAGAnim.h"
#include "../plMessage/plAvatarMsg.h"
#include "../plMessage/plLoadAgeMsg.h"
plLinkEffectsMgr::plLinkEffectsMgr()
{
}
plLinkEffectsMgr::~plLinkEffectsMgr()
{
int i;
for( i = 0; i < fLinks.GetCount(); i++ )
{
hsRefCnt_SafeUnRef(fLinks[i]);
}
for( i = 0; i < fWaitlist.GetCount(); i++ )
{
hsRefCnt_SafeUnRef(fWaitlist[i]);
}
for( i = 0; i < fDeadlist.GetCount(); i++ )
{
hsRefCnt_SafeUnRef(fDeadlist[i]);
}
}
void plLinkEffectsMgr::Init()
{
plgDispatch::Dispatch()->RegisterForExactType(plPlayerPageMsg::Index(), GetKey());
plgDispatch::Dispatch()->RegisterForExactType(plPseudoLinkEffectMsg::Index(), GetKey());
}
plLinkEffectsTriggerMsg *plLinkEffectsMgr::IFindLinkTriggerMsg(plKey linkKey)
{
int i;
for (i = 0; i < fLinks.GetCount(); i++)
{
if (fLinks[i]->GetLinkKey() == linkKey)
return fLinks[i];
}
return nil;
}
void plLinkEffectsMgr::IAddLink(plLinkEffectsTriggerMsg *msg)
{
hsRefCnt_SafeRef(msg);
fLinks.Append(msg);
}
void plLinkEffectsMgr::IAddWait(plLinkEffectsTriggerMsg *msg)
{
hsRefCnt_SafeRef(msg);
fWaitlist.Append(msg);
}
void plLinkEffectsMgr::IAddDead(plLinkEffectsTriggerMsg *msg)
{
hsRefCnt_SafeRef(msg);
fDeadlist.Append(msg);
}
void plLinkEffectsMgr::IAddPsuedo(plPseudoLinkEffectMsg *msg)
{
hsRefCnt_SafeRef(msg);
fPseudolist.Append(msg);
}
hsBool plLinkEffectsMgr::IHuntWaitlist(plLinkEffectsTriggerMsg *msg)
{
int i;
hsBool found = false;
for (i = fWaitlist.GetCount() - 1; i >= 0; i--)
{
if (fWaitlist[i] == msg)
{
found = true;
hsRefCnt_SafeUnRef(fWaitlist[i]);
fWaitlist.Remove(i);
plNetApp::GetInstance()->DebugMsg("Received backup LinkEffectsTriggerMsg. Never got remote trigger!\n");
}
}
return found || IHuntWaitlist(msg->GetLinkKey());
}
hsBool plLinkEffectsMgr::IHuntWaitlist(plKey linkKey)
{
int i;
hsBool found = false;
for (i = fWaitlist.GetCount() - 1; i >= 0; i--)
{
if (fWaitlist[i]->GetLinkKey() == linkKey)
{
found = true;
IAddDead(fWaitlist[i]);
hsRefCnt_SafeUnRef(fWaitlist[i]);
fWaitlist.Remove(i);
plNetApp::GetInstance()->DebugMsg("Received remote LinkEffectsTriggerMsg. Awaiting backup.\n");
}
}
return found;
}
hsBool plLinkEffectsMgr::IHuntDeadlist(plLinkEffectsTriggerMsg *msg)
{
int i;
hsBool found = false;
for (i = fDeadlist.GetCount() - 1; i >= 0; i--)
{
if (fDeadlist[i] == msg)
{
found = true;
hsRefCnt_SafeUnRef(fDeadlist[i]);
fDeadlist.Remove(i);
plNetApp::GetInstance()->DebugMsg("Received backup LinkEffectsTriggerMsg. Cleanly ignoring since we received remote trigger.\n");
}
}
return found;
}
void plLinkEffectsMgr::ISendAllReadyCallbacks()
{
int i;
for (i = fLinks.GetCount() - 1; i >= 0; i--)
{
if (fLinks[i]->fEffects <= 0)
{
if (fLinks[i]->IsLeavingAge())
{
if (fLinks[i]->GetLinkKey() == plNetClientApp::GetInstance()->GetLocalPlayerKey())
{
plLinkOutUnloadMsg* lam = TRACKED_NEW plLinkOutUnloadMsg; // derived from LoadAgeMsg
lam->SetAgeFilename( NetCommGetAge()->ageDatasetName );
lam->AddReceiver(plNetClientMgr::GetInstance()->GetKey());
lam->SetPlayerID(plNetClientMgr::GetInstance()->GetPlayerID());
lam->Send();
}
}
else
{
plLinkInDoneMsg* lid = TRACKED_NEW plLinkInDoneMsg;
lid->AddReceiver(fLinks[i]->GetLinkKey());
lid->SetBCastFlag(plMessage::kPropagateToModifiers);
lid->Send();
if (fLinks[i]->GetLinkKey() == plNetClientApp::GetInstance()->GetLocalPlayerKey())
{
plLinkInDoneMsg* lid = TRACKED_NEW plLinkInDoneMsg;
lid->AddReceiver(plNetClientMgr::GetInstance()->GetKey());
lid->Send();
}
}
hsRefCnt_SafeUnRef(fLinks[i]);
fLinks.Remove(i);
hsStatusMessage("Done - removing link FX msg\n");
}
}
}
hsBool plLinkEffectsMgr::MsgReceive(plMessage *msg)
{
plNetClientMgr* nc = plNetClientMgr::GetInstance();
plNetLinkingMgr* lm = plNetLinkingMgr::GetInstance();
plPseudoLinkEffectMsg* pSeudoMsg = plPseudoLinkEffectMsg::ConvertNoRef(msg);
if (pSeudoMsg)
{
// verify valid avatar and "link" objects
if (!pSeudoMsg->fAvatarKey)
return true;
if (!pSeudoMsg->fLinkObjKey)
return true;
if (!pSeudoMsg->fLinkObjKey->ObjectIsLoaded())
return true;
if (!plNetClientMgr::GetInstance()->IsAPlayerKey(pSeudoMsg->fAvatarKey))
return true;
// send the trigger message to the avatar...
plPseudoLinkAnimTriggerMsg* pMsg = TRACKED_NEW plPseudoLinkAnimTriggerMsg(true, pSeudoMsg->fAvatarKey);
pMsg->SetSender(GetKey());
pMsg->Send();
IAddPsuedo(pSeudoMsg);
}
plPseudoLinkAnimCallbackMsg* pSeudoCallback = plPseudoLinkAnimCallbackMsg::ConvertNoRef(msg);
if (pSeudoCallback)
{
// warp the avatar to his new position
plPseudoLinkEffectMsg* pMsg = IFindPseudo(pSeudoCallback->fAvatarKey);
if (pMsg)
{
plSceneObject* pObj = plSceneObject::ConvertNoRef(pMsg->fLinkObjKey->ObjectIsLoaded());
if (pObj && pObj->GetCoordinateInterface())
{
hsMatrix44 mat = pObj->GetCoordinateInterface()->GetLocalToWorld();
// create message
plWarpMsg* pMsg = TRACKED_NEW plWarpMsg(mat);
pMsg->SetWarpFlags(plWarpMsg::kFlushTransform);
pMsg->AddReceiver(pSeudoCallback->fAvatarKey);
plUoid U(kVirtualCamera1_KEY);
plKey pCamKey = hsgResMgr::ResMgr()->FindKey(U);
if (pCamKey)
{
pMsg->AddReceiver(pCamKey);
}
plgDispatch::MsgSend( pMsg ); // whoosh... off it goes
// now make him re-appear
plPseudoLinkAnimTriggerMsg* pTrigMsg = TRACKED_NEW plPseudoLinkAnimTriggerMsg(false, pSeudoCallback->fAvatarKey);
pTrigMsg->SetSender(GetKey());
pTrigMsg->Send();
IRemovePseudo(pSeudoCallback->fAvatarKey);
}
}
}
plLinkEffectsTriggerPrepMsg *tpMsg = plLinkEffectsTriggerPrepMsg::ConvertNoRef(msg);
if (tpMsg)
{
plNetApp::GetInstance()->DebugMsg("Received LinkEffectsTriggerPREPMsg\n");
IAddWait(tpMsg->GetTrigger());
plLinkEffectPrepBCMsg *bcpMsg = TRACKED_NEW plLinkEffectPrepBCMsg;
bcpMsg->fLeavingAge = tpMsg->fLeavingAge;
bcpMsg->fLinkKey = tpMsg->fLinkKey;
bcpMsg->Send();
return true;
}
plLinkEffectsTriggerMsg* pTriggerMsg = plLinkEffectsTriggerMsg::ConvertNoRef(msg);
if (pTriggerMsg)
{
plNetApp::GetInstance()->DebugMsg("Received LinkEffectsTriggerMsg, local=%d, linkingIn=%d, stealth=%d",
!msg->HasBCastFlag(plMessage::kNetNonLocal),
!pTriggerMsg->IsLeavingAge(), pTriggerMsg->GetInvisLevel());
plKey linkKey = pTriggerMsg->GetLinkKey();
if (linkKey == nil)
return true;
if ((linkKey != nc->GetLocalPlayerKey()) &&
(!pTriggerMsg->IsLeavingAge()))
{
if (IHuntDeadlist(pTriggerMsg)) // Just an obselete safety trigger
return true;
if (!IHuntWaitlist(pTriggerMsg))
{
plNetApp::GetInstance()->DebugMsg("Unexpected linkEffectsTriggerMsg. Ignoring\n");
return true;
}
}
plSceneObject *avatar = plSceneObject::ConvertNoRef(linkKey->ObjectIsLoaded());
if (avatar == nil)
{
plNetApp::GetInstance()->DebugMsg("Can't find avatar, mod=%s\n", linkKey->GetName());
return true;
}
// This is not the right place to catch this problem.
// if (IFindLinkTriggerMsg(linkKey) != nil)
// {
// hsAssert(false, "Trying to link an Avatar already in the process of linking.");
// return true;
// }
if (pTriggerMsg->GetInvisLevel() && linkKey != nc->GetLocalPlayerKey())
{
#ifdef PLASMA_EXTERNAL_RELEASE
// Verify that the server told us that the invisible avatar is a CCR
plNetTransportMember* mbr=nc->TransportMgr().GetMember(nc->TransportMgr().FindMember(linkKey));
if (!mbr || mbr->GetCCRLevel()<pTriggerMsg->GetInvisLevel())
{
plNetApp::StaticErrorMsg("Remote Avatar trying to be stealthy - REJECTING since he's not a CCR");
}
else
#endif
{
plNetApp::StaticDebugMsg("Remote Avatar is in stealth mode - making invisible");
nc->MakeCCRInvisible(pTriggerMsg->GetLinkKey(), pTriggerMsg->GetInvisLevel());
}
}
if (pTriggerMsg->IsLeavingAge())
hsStatusMessage("Starting LinkOut FX\n");
else
hsStatusMessage("Starting LinkIn FX\n");
plLinkEffectBCMsg *BCMsg = TRACKED_NEW plLinkEffectBCMsg();
BCMsg->fLinkKey = linkKey;
BCMsg->SetLinkFlag(plLinkEffectBCMsg::kLeavingAge, pTriggerMsg->IsLeavingAge());
BCMsg->SetLinkFlag(plLinkEffectBCMsg::kSendCallback, true);
// Check if you have a Yeesha book, and mute sound if you don't.
// 'CleftSolved' gets set when you click on the linking panel in the cleft,
// so we use that instead of checking KILevel.
// Also, check if you're going to/from the ACA, or through the fissure, and mute sound if you are.
if (linkKey == nc->GetLocalPlayerKey())
{
if(lm) {
const char *ageName = lm->GetAgeLink()->GetAgeInfo()->GetAgeFilename();
const char *prevAgeName = lm->GetPrevAgeLink()->GetAgeInfo()->GetAgeFilename();
bool linkToStartup = ageName && !stricmp(ageName, kStartUpAgeFilename ); // To Startup
bool linkFromStartup = prevAgeName && !stricmp(prevAgeName, kStartUpAgeFilename); // Leaving Startup
bool cleftSolved = VaultHasChronicleEntry( kCleftSolved );
bool linkToACA = ageName && !stricmp(ageName, kAvCustomizationFilename);
bool linkFromACA = prevAgeName && !stricmp(prevAgeName, kAvCustomizationFilename);
bool linkToFissureDrop = lm &&
lm->GetAgeLink()->HasSpawnPt() &&
lm->GetAgeLink()->SpawnPoint().GetName() &&
!stricmp(lm->GetAgeLink()->SpawnPoint().GetName(), kCleftAgeLinkInPointFissureDrop);
bool linkToDsntFromShell = lm &&
lm->GetAgeLink()->HasSpawnPt() &&
lm->GetAgeLink()->SpawnPoint().GetTitle() &&
!stricmp(lm->GetAgeLink()->SpawnPoint().GetTitle(), kDescentLinkFromShell);
if ( linkToACA || linkFromACA || linkToStartup || linkFromStartup || linkToFissureDrop || linkToDsntFromShell)
{
BCMsg->SetLinkFlag(plLinkEffectBCMsg::kMute);
}
}
}
BCMsg->SetSender(GetKey());
if (msg->HasBCastFlag(plMessage::kNetNonLocal))
// terminate the remote cascade and start a new (local) cascade, since the rcvr is localOnly and will reject remote msgs
BCMsg->SetBCastFlag(plMessage::kNetStartCascade);
plgDispatch::MsgSend(BCMsg);
if (!pTriggerMsg->IsLeavingAge()) // Avatar is currently entering a new age
{
plATCAnim *linkInAnim = nil;
plKey linkInAnimKey = nil;
const plArmatureMod *avMod = plArmatureMod::ConvertNoRef(avatar->GetModifierByType(plArmatureMod::Index()));
if (pTriggerMsg->HasBCastFlag(plMessage::kNetNonLocal))
{
// Remote trigger, they should tell us how they linked in.
linkInAnimKey = pTriggerMsg->GetLinkInAnimKey();
}
else
{
// this is our backup trigger we send ourselves. We've already received the remote player's SDL.
linkInAnimKey = avMod ? avMod->GetLinkInAnimKey() : nil;
}
linkInAnim = plATCAnim::ConvertNoRef(linkInAnimKey ? linkInAnimKey->ObjectIsLoaded() : nil);
if (avMod && linkInAnim)
{
plAvOneShotTask *task = TRACKED_NEW plAvOneShotTask(linkInAnim->GetName(), false, false, nil);
task->fBackwards = true;
task->fDisableLooping = true;
task->fDisablePhysics = false;
(TRACKED_NEW plAvTaskMsg(GetKey(), avMod->GetKey(), task))->Send();
}
}
IAddLink(pTriggerMsg); // refs the avatarMod
// Dummy msg sent after the broadcast. This guarantees we have a callback to actually trigger the
// link, plus we know any effect broadcast messages will have processed before this (and therefore
// have told us to wait for them.)
pTriggerMsg->fEffects++;
plLinkCallbackMsg *dummyMsg = TRACKED_NEW plLinkCallbackMsg();
dummyMsg->AddReceiver(GetKey());
dummyMsg->fLinkKey = linkKey;
plgDispatch::MsgSend(dummyMsg);
return true;
}
// callbacks from linkout events
plLinkCallbackMsg* pLinkCallbackMsg = plLinkCallbackMsg::ConvertNoRef(msg);
if (pLinkCallbackMsg)
{
plNetApp::GetInstance()->DebugMsg("Received pLinkCallbackMsg, localmsg=%d\n",
!msg->HasBCastFlag(plMessage::kNetNonLocal));
static char str[ 128 ];
plLinkEffectsTriggerMsg *pTriggerMsg = IFindLinkTriggerMsg(pLinkCallbackMsg->fLinkKey);
if (pTriggerMsg == nil)
{
hsAssert(true, "Received a callback for an avatar that isn't linking.");
return true;
}
if (--pTriggerMsg->fEffects == 0)
{
plNetApp::GetInstance()->DebugMsg("All link callbacks received.\n" );
plgDispatch::Dispatch()->RegisterForExactType(plTimeMsg::Index(), GetKey());
}
else if (pTriggerMsg->fEffects < 0 )
{
plNetApp::GetInstance()->DebugMsg("Too many link callbacks received for avatar %s. Ignoring extras.\n",
pTriggerMsg->GetLinkKey()->GetName());
}
else
{
plNetApp::GetInstance()->DebugMsg("%d link callbacks left until avatar %s links...\n",
pTriggerMsg->fEffects, pTriggerMsg->GetLinkKey()->GetName());
}
return true;
}
plTimeMsg *time = plTimeMsg::ConvertNoRef(msg);
if (time) // This is how we know we're out of the render function, and it's safe to pageIn/Out nodes
{
plgDispatch::Dispatch()->UnRegisterForExactType(plTimeMsg::Index(), GetKey());
ISendAllReadyCallbacks();
return true;
}
plPlayerPageMsg *pageMsg = plPlayerPageMsg::ConvertNoRef(msg);
if (pageMsg)
{
if (pageMsg->fUnload)
{
IHuntWaitlist(pageMsg->fPlayer);
return true;
}
const hsScalar kMaxTimeForLinkTrigger = 30.f;
// If we're not loading state, we're in the age. So this avatar coming in must be linking in.
// If the player is us, no prep is necessary.
if (!plNetClientApp::GetInstance()->IsLoadingInitialAgeState() &&
(pageMsg->fPlayer != nc->GetLocalPlayerKey()))
{
plLinkEffectsTriggerMsg *trigMsg = TRACKED_NEW plLinkEffectsTriggerMsg;
trigMsg->SetLeavingAge(false);
trigMsg->SetLinkKey(pageMsg->fPlayer);
// Send off the prep message right away
plLinkEffectsTriggerPrepMsg *trigPrepMsg = TRACKED_NEW plLinkEffectsTriggerPrepMsg;
trigPrepMsg->fLinkKey = pageMsg->fPlayer;
trigPrepMsg->SetTrigger(trigMsg);
trigPrepMsg->Send(GetKey());
// Send off a delayed safety trigger. If things are going along properly,
// we'll get a trigger from the player linking in before this message is
// received, and we'll ignore it.
double timeToDeliver = hsTimer::GetSysSeconds() + kMaxTimeForLinkTrigger;
trigMsg->SetTimeStamp(timeToDeliver);
trigMsg->Send(GetKey());
}
return true;
}
return hsKeyedObject::MsgReceive(msg);
}
void plLinkEffectsMgr::WaitForEffect(plKey linkKey, hsScalar time)
{
plLinkEffectsTriggerMsg *msg = IFindLinkTriggerMsg(linkKey);
if (msg == nil)
{
hsAssert(true, "Request to wait on an effect for an avatar that isn't linking.");
return;
}
msg->fEffects++;
plLinkCallbackMsg *callback = TRACKED_NEW plLinkCallbackMsg();
callback->fEvent = kStop;
callback->fRepeats = 0;
callback->fLinkKey = linkKey;
double timeToDeliver = hsTimer::GetSysSeconds() + time;
callback->SetTimeStamp( timeToDeliver );
callback->Send( GetKey() );
}
plMessage *plLinkEffectsMgr::WaitForEffect(plKey linkKey)
{
plLinkEffectsTriggerMsg *msg = IFindLinkTriggerMsg(linkKey);
if (msg == nil)
{
hsAssert(true, "Request to wait on an effect for an avatar that isn't linking.");
return nil;
}
msg->fEffects++;
plLinkCallbackMsg *callback = TRACKED_NEW plLinkCallbackMsg();
callback->fEvent = kStop;
callback->fRepeats = 0;
callback->fLinkKey = linkKey;
callback->AddReceiver( GetKey() );
return callback;
}
void plLinkEffectsMgr::WaitForPseudoEffect(plKey linkKey, hsScalar time)
{
plPseudoLinkEffectMsg* msg = IFindPseudo(linkKey);
if (msg == nil)
{
hsAssert(true, "Request to wait on an fake effect for an avatar that isn't fake linking.");
return;
}
plPseudoLinkAnimCallbackMsg* callback = TRACKED_NEW plPseudoLinkAnimCallbackMsg();
callback->fAvatarKey = linkKey;
double timeToDeliver = hsTimer::GetSysSeconds() + time;
callback->SetTimeStamp( timeToDeliver );
callback->Send( GetKey() );
}
plPseudoLinkEffectMsg* plLinkEffectsMgr::IFindPseudo(plKey avatarKey)
{
int i;
for (i = 0; i < fPseudolist.GetCount(); i++)
{
if (fPseudolist[i]->fAvatarKey == avatarKey)
return fPseudolist[i];
}
return nil;
}
void plLinkEffectsMgr::IRemovePseudo(plKey avatarKey)
{
int i;
for (i = 0; i < fPseudolist.GetCount(); i++)
{
if (fPseudolist[i]->fAvatarKey == avatarKey)
{
fPseudolist.Remove(i);
return;
}
}
}

View File

@ -0,0 +1,97 @@
/*==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==*/
#ifndef plLinkEffectsMgr_inc
#define plLinkEffectsMgr_inc
#include "../pnKeyedObject/hsKeyedObject.h"
class plLinkEffectsTriggerMsg;
class plPseudoLinkEffectMsg;
class plLinkEffectsMgr : public hsKeyedObject
{
protected:
// Collection of links in progress (in or out)
hsTArray<plLinkEffectsTriggerMsg *> fLinks;
// Players we know exist, but aren't ready to link yet
hsTArray<plLinkEffectsTriggerMsg *> fWaitlist;
// Queue of delayed messages from people linking in that
// we haven't received yet but are no longer necessary,
// because we either received the trigger from them, or
// they're no longer in the age.
hsTArray<plLinkEffectsTriggerMsg *> fDeadlist;
// queue of pseudo link messages
hsTArray<plPseudoLinkEffectMsg *> fPseudolist;
plLinkEffectsTriggerMsg *IFindLinkTriggerMsg(plKey avatarKey);
void IAddLink(plLinkEffectsTriggerMsg *msg);
void IAddWait(plLinkEffectsTriggerMsg *msg);
void IAddDead(plLinkEffectsTriggerMsg *msg);
void IAddPsuedo(plPseudoLinkEffectMsg *msg);
void IRemovePseudo(plKey avatarKey);
plPseudoLinkEffectMsg* IFindPseudo(plKey avatarKey);
hsBool IHuntWaitlist(plLinkEffectsTriggerMsg *msg);
hsBool IHuntWaitlist(plKey linkKey);
hsBool IHuntDeadlist(plLinkEffectsTriggerMsg *msg);
void ISendAllReadyCallbacks();
public:
plLinkEffectsMgr();
~plLinkEffectsMgr();
void Init();
CLASSNAME_REGISTER( plLinkEffectsMgr );
GETINTERFACE_ANY( plLinkEffectsMgr, hsKeyedObject );
void WaitForEffect(plKey linkKey, hsScalar time);
void WaitForPseudoEffect(plKey linkKey, hsScalar time);
plMessage *WaitForEffect(plKey linkKey);
virtual hsBool MsgReceive(plMessage *msg);
};
#endif // plLinkEffectsMgr_inc

View File

@ -0,0 +1,492 @@
/*==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==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/PubUtilLib/plNetClient/plNetCliAgeJoiner.cpp
*
* Encapsulates all of the horrible ugliness that the age load process has become
*
***/
#include "plNetCliAgeJoiner.h"
#include "plNetClientMgr.h"
#include "plNetLinkingMgr.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnMessage/plPlayerPageMsg.h"
#include "../pnMessage/plTimeMsg.h"
#include "../plNetClientComm/plNetClientComm.h"
#include "../plAgeLoader/plAgeLoader.h"
#include "../plAgeLoader/plBackgroundDownloader.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plVault/plVault.h"
#include "../plNetMessage/plNetMessage.h"
#include "../plMessage/plNetCommMsgs.h"
#include "../plMessage/plAgeLoadedMsg.h"
#include "../plMessage/plInputIfaceMgrMsg.h"
#include "../plMessage/plNetClientMgrMsg.h"
#include "../plProgressMgr/plProgressMgr.h"
#include "../pnDispatch/plDispatch.h"
#include "../plResMgr/plResManager.h"
/*****************************************************************************
*
* Private
*
***/
struct plNCAgeJoiner {
enum NextOp {
kNoOp,
kLoadAge,
kLoadPlayer,
kRequestAgeState,
kPropagatePlayer,
kDestroyProgressBar,
kEnableClickables,
kSimStateRcvd,
kNotifyAgeLoaded,
};
NextOp nextOp;
NetCommAge age;
FNCAgeJoinerCallback callback;
void * userState;
bool complete;
plOperationProgress* progressBar;
plNCAgeJoiner (
const NetCommAge & age,
FNCAgeJoinerCallback callback,
void * userState
);
~plNCAgeJoiner ();
void Start ();
void Complete (bool success, const char msg[]);
bool MsgReceive (plMessage * msg);
void Update ();
void ExecNextOp ();
static void IDispatchMsgReceiveCallback ();
static void IResMgrProgressBarCallback (plKey key);
static plNCAgeJoiner* s_instance;
};
plNCAgeJoiner* plNCAgeJoiner::s_instance = nil;
/*****************************************************************************
*
* Local functions
*
***/
//============================================================================
void AgeVaultDownloadCallback (
ENetError result,
void * param
) {
plNCAgeJoiner * joiner = (plNCAgeJoiner *)param;
if (IS_NET_ERROR(result)) {
joiner->Complete(false, "Failed to download age vault");
}
else {
// vault downloaded. start loading age data
LogMsg(kLogPerf, L"AgeJoiner: Next:kLoadAge (vault downloaded)");
joiner->nextOp = plNCAgeJoiner::kLoadAge;
}
}
/*****************************************************************************
*
* plNCAgeJoiner
*
***/
//============================================================================
plNCAgeJoiner::plNCAgeJoiner (
const NetCommAge & age,
FNCAgeJoinerCallback callback,
void * userState
) : nextOp(kNoOp)
, age(age)
, callback(callback)
, userState(userState)
, progressBar(nil)
{
}
//============================================================================
plNCAgeJoiner::~plNCAgeJoiner () {
}
//============================================================================
void plNCAgeJoiner::IDispatchMsgReceiveCallback () {
if (s_instance)
s_instance->progressBar->Increment(1);
}
//============================================================================
void plNCAgeJoiner::IResMgrProgressBarCallback (plKey key) {
#ifndef PLASMA_EXTERNAL_RELEASE
if (s_instance)
s_instance->progressBar->SetStatusText(key->GetName());
#endif
}
//============================================================================
void plNCAgeJoiner::Complete (bool success, const char msg[]) {
if (!complete) {
complete = true;
s_instance = nil;
NCAgeJoinerCompleteNotify notify;
notify.success = success;
notify.msg = msg;
callback(this, kAgeJoinerComplete, &notify, userState);
DEL(this);
}
if (plBackgroundDownloader::GetInstance())
plBackgroundDownloader::GetInstance()->UnPause();
}
//============================================================================
void plNCAgeJoiner::Start () {
s_instance = this;
plNetClientMgr * nc = plNetClientMgr::GetInstance();
nc->SetFlagsBit(plNetClientMgr::kPlayingGame, false);
nc->fServerTimeOffset = 0; // reset since we're connecting to a new server
nc->fRequiredNumInitialSDLStates = 0;
nc->fNumInitialSDLStates = 0;
nc->SetFlagsBit(plNetClientApp::kNeedInitialAgeStateCount);
nc->SetFlagsBit(plNetClientApp::kLoadingInitialAgeState);
// if we're linking to startup then set the OfflineAge flag
// so we by-pass the game server
if (StrLen(age.ageDatasetName) == 0 || StrCmpI(age.ageDatasetName, "StartUp") == 0)
nc->SetFlagsBit(plNetClientApp::kLinkingToOfflineAge);
else
nc->SetFlagsBit(plNetClientApp::kLinkingToOfflineAge, false);
plAgeLoader* al = plAgeLoader::GetInstance();
al->UpdateAge(age.ageDatasetName);
nc->ResetServerTimeOffset();
NetCommLinkToAge(
age,
this
);
}
//============================================================================
void plNCAgeJoiner::ExecNextOp () {
plNetClientMgr * nc = plNetClientMgr::GetInstance();
plAvatarMgr * am = plAvatarMgr::GetInstance();
plAgeLoader * al = plAgeLoader::GetInstance();
NextOp next = nextOp;
nextOp = kNoOp;
switch (next) {
//====================================================================
case kNoOp: {
}
break;
//====================================================================
case kLoadAge: {
LogMsg(kLogPerf, L"AgeJoiner: Exec:kLoadAge");
// Start progress bar
char str[256];
#ifdef PLASMA_EXTERNAL_RELEASE
StrCopy(str, "Loading age...", arrsize(str));
#else
StrPrintf(str, arrsize(str), "Loading age %s...", age.ageDatasetName);
#endif
progressBar = plProgressMgr::GetInstance()->RegisterOperation(0, str, plProgressMgr::kNone, false, true);
plDispatch::SetMsgRecieveCallback(IDispatchMsgReceiveCallback);
((plResManager*)hsgResMgr::ResMgr())->SetProgressBarProc(IResMgrProgressBarCallback);
// Start loading age data
al->LoadAge(age.ageDatasetName);
}
break;
//====================================================================
case kLoadPlayer: {
LogMsg(kLogPerf, L"AgeJoiner: Exec:kLoadPlayer");
// Start loading local player
const char * avatarName;
if (NetCommNeedToLoadAvatar()) {
if (nc->GetFlagsBit(plNetClientApp::kLinkingToOfflineAge))
avatarName = "Male";
else
avatarName = NetCommGetPlayer()->avatarDatasetName;
const char * linkInName = plNetLinkingMgr::GetInstance()->GetAgeLink()->SpawnPoint().GetName();
am->LoadPlayer( avatarName, nil, linkInName );
}
else {
LogMsg(kLogPerf, L"AgeJoiner: Next:kPropagatePlayer");
nextOp = kPropagatePlayer;
}
}
break;
//====================================================================
case kPropagatePlayer: {
LogMsg(kLogPerf, L"AgeJoiner: Exec:kPropagatePlayer");
// Add our avatar to the scene
int spawnPt = am->FindSpawnPoint(age.spawnPtName);
nc->IPlayerChangeAge(false /*not exiting*/, spawnPt);
if (!nc->GetFlagsBit(plNetClientApp::kLinkingToOfflineAge))
// Add our avatar to the game state
am->PropagateLocalPlayer(spawnPt);
LogMsg(kLogPerf, L"AgeJoiner: Next:kRequestAgeState");
nextOp = kRequestAgeState;
}
break;
//============================================================================
case kRequestAgeState: {
LogMsg(kLogPerf, L"AgeJoiner: Exec:kRequestAgeState");
if (nc->GetFlagsBit(plNetClientApp::kLinkingToOfflineAge)) {
LogMsg(kLogPerf, L"AgeJoiner: Next:kSimStateRcvd");
nextOp = kSimStateRcvd;
}
else {
// Request age player list
nc->ISendMembersListRequest();
// Request initial SDL state
plNetMsgGameStateRequest gsmsg;
gsmsg.SetNetProtocol(kNetProtocolCli2Game);
gsmsg.SetBit(plNetMessage::kInitialAgeStateRequest);
nc->SendMsg(&gsmsg);
// Send our avatar settings
nc->SendLocalPlayerAvatarCustomizations();
}
}
break;
//====================================================================
case kSimStateRcvd: {
nc->NotifyRcvdAllSDLStates();
}
break;
//============================================================================
case kDestroyProgressBar: {
plDispatch::SetMsgRecieveCallback(nil);
((plResManager*)hsgResMgr::ResMgr())->SetProgressBarProc(nil);
delete progressBar;
progressBar = nil;
nextOp = kEnableClickables;
}
break;
//====================================================================
case kEnableClickables: {
LogMsg(kLogPerf, L"AgeJoiner: Exec:kEnableClickables");
// Enable scene clickables
(void)(TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kEnableClickables))->Send();
LogMsg(kLogPerf, L"AgeJoiner: Next:kNotifyAgeLoaded");
nextOp = kNotifyAgeLoaded;
}
break;
//====================================================================
case kNotifyAgeLoaded: {
LogMsg(kLogPerf, L"AgeJoiner: Exec:kNotifyAgeLoaded");
nc->SetFlagsBit(plNetClientApp::kPlayingGame);
nc->SetFlagsBit(plNetClientApp::kNeedToSendInitialAgeStateLoadedMsg);
plAgeLoader::GetInstance()->NotifyAgeLoaded(true);
Complete(true, "Age joined");
}
break;
DEFAULT_FATAL(nextOp);
}
}
//============================================================================
bool plNCAgeJoiner::MsgReceive (plMessage * msg) {
plNetClientMgr * nc = plNetClientMgr::GetInstance();
plAvatarMgr * am = plAvatarMgr::GetInstance();
plAgeLoader * al = plAgeLoader::GetInstance();
//========================================================================
// Connected to age instance
//========================================================================
if (plNetCommLinkToAgeMsg * linkToAgeMsg = plNetCommLinkToAgeMsg::ConvertNoRef(msg)) {
if (IS_NET_ERROR(linkToAgeMsg->result)) {
Complete(false, "LinkToAge failed");
}
else if (unsigned ageVaultId = NetCommGetAge()->ageVaultId) {
// Download the age vault
VaultDownload(
L"AgeJoin",
ageVaultId,
AgeVaultDownloadCallback,
this,
nil, // FVaultDownloadProgressCallback
this
);
}
else {
// not vault to downloaded, just start loading age data
LogMsg(kLogPerf, L"AgeJoiner: Next:kLoadAge (no vault)");
nextOp = kLoadAge;
}
return true;
}
//========================================================================
// All age data paged in
//========================================================================
if (plAgeLoaded2Msg * ageLoaded2Msg = plAgeLoaded2Msg::ConvertNoRef(msg)) {
// Exec custom age settings
al->ExecPendingAgeFniFiles();
al->ExecPendingAgeCsvFiles();
LogMsg(kLogPerf, L"AgeJoiner: Next:kLoadPlayer");
nextOp = kLoadPlayer;
return true;
}
//========================================================================
// Local avatar loaded
//========================================================================
plPlayerPageMsg * playerPageMsg = plPlayerPageMsg::ConvertNoRef(msg);
if (playerPageMsg && !playerPageMsg->fUnload && playerPageMsg->fPlayer && playerPageMsg->fLocallyOriginated) {
if (NetCommNeedToLoadAvatar())
NetCommSetAvatarLoaded();
LogMsg(kLogPerf, L"AgeJoiner: Next:kPropagatePlayer");
nextOp = kPropagatePlayer;
return false; // NetClientMgr must also handle this message
}
//========================================================================
// Received all SDL states
//========================================================================
plNetClientMgrMsg * netClientMgrMsg = plNetClientMgrMsg::ConvertNoRef(msg);
if (netClientMgrMsg && netClientMgrMsg->type == plNetClientMgrMsg::kNotifyRcvdAllSDLStates) {
LogMsg(kLogPerf, L"AgeJoiner: Next:kEnableClickables");
nextOp = kDestroyProgressBar;
return true;
}
return false;
}
//============================================================================
void plNCAgeJoiner::Update () {
ExecNextOp();
}
/*****************************************************************************
*
* Exports
*
***/
//============================================================================
void NCAgeJoinerCreate (
plNCAgeJoiner ** pjoiner,
const NetCommAge & age,
FNCAgeJoinerCallback callback,
void * userState
) {
ASSERT(pjoiner);
ASSERT(callback);
plNCAgeJoiner * joiner;
*pjoiner = joiner = NEWZERO(plNCAgeJoiner)(
age,
callback,
userState
);
joiner->Start();
}
//============================================================================
bool NCAgeJoinerMsgReceive (
plNCAgeJoiner * joiner,
plMessage * msg
) {
ASSERT(joiner);
return joiner->MsgReceive(msg);
}
//============================================================================
void NCAgeJoinerUpdate (
plNCAgeJoiner * joiner
) {
ASSERT(joiner);
joiner->Update();
}

View File

@ -0,0 +1,101 @@
/*==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==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/PubUtilLib/plNetClient/plNetCliAgeJoiner.h
*
***/
#ifndef PLASMA20_SOURCES_PLASMA_PUBUTILLIB_PLNETCLIENT_PLNETCLIAGEJOINER_H
#define PLASMA20_SOURCES_PLASMA_PUBUTILLIB_PLNETCLIENT_PLNETCLIAGEJOINER_H
#include "HeadSpin.h"
#include "../pnUtils/pnUtils.h"
#include "../plNetClientComm/plNetClientComm.h"
/*****************************************************************************
*
*
*
***/
class plMessage;
struct plNCAgeJoiner;
enum ENCAgeJoinerNotify {
kAgeJoinerComplete, // notify --> NCAgeJoinerCompleteNotify *, after callback, joiner is destroyed
kNumAgeJoinerNotifications
};
struct NCAgeJoinerCompleteNotify {
bool success;
const char * msg;
};
typedef void (* FNCAgeJoinerCallback)(
plNCAgeJoiner * joiner,
unsigned type, // ENCAgeJoinerNotify
void * notify,
void * userState
);
void NCAgeJoinerCreate (
plNCAgeJoiner ** joiner,
const NetCommAge & age,
FNCAgeJoinerCallback callback,
void * userState
);
bool NCAgeJoinerMsgReceive ( // returns true of message was processed
plNCAgeJoiner * joiner,
plMessage * msg
);
void NCAgeJoinerUpdate (
plNCAgeJoiner * joiner
);
#endif // PLASMA20_SOURCES_PLASMA_PUBUTILLIB_PLNETCLIENT_PLNETCLIAGEJOINER_H

View File

@ -0,0 +1,300 @@
/*==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==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/PubUtilLib/plNetClient/plNetCliAgeLeaver.cpp
*
***/
#include "plNetCliAgeLeaver.h"
#include "plNetClientMgr.h"
#include "plNetLinkingMgr.h"
#include "../pnMessage/plTimeMsg.h"
#include "../plNetClientComm/plNetClientComm.h"
#include "../plNetGameLib/plNetGameLib.h"
#include "../plAgeLoader/plAgeLoader.h"
#include "../plAgeLoader/plBackgroundDownloader.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plVault/plVault.h"
#include "../plMessage/plLoadAgeMsg.h"
#include "../plMessage/plAgeLoadedMsg.h"
#include "../plMessage/plInputIfaceMgrMsg.h"
/*****************************************************************************
*
* Private
*
***/
struct plNCAgeLeaver {
enum NextOp {
kNoOp,
kDisableClickables,
kLinkOutFX,
kUnloadAge,
kNotifyAgeUnloaded,
};
NextOp nextOp;
bool quitting;
bool complete;
FNCAgeLeaverCallback callback;
void * userState;
plNCAgeLeaver (
bool quitting,
FNCAgeLeaverCallback callback,
void * userState
);
~plNCAgeLeaver ();
void Start ();
void Complete (bool success, const char msg[]);
bool MsgReceive (plMessage * msg);
void Update ();
void ExecNextOp ();
};
/*****************************************************************************
*
* plNCAgeLeaver
*
***/
//============================================================================
plNCAgeLeaver::plNCAgeLeaver (
bool quitting,
FNCAgeLeaverCallback callback,
void * userState
) : nextOp(kNoOp)
, quitting(quitting)
, complete(false)
, callback(callback)
, userState(userState)
{
}
//============================================================================
plNCAgeLeaver::~plNCAgeLeaver () {
}
//============================================================================
void plNCAgeLeaver::Start () {
if (plBackgroundDownloader::GetInstance())
plBackgroundDownloader::GetInstance()->Pause();
nextOp = kLinkOutFX;
}
//============================================================================
void plNCAgeLeaver::Complete (bool success, const char msg[]) {
if (!complete) {
complete = true;
NCAgeLeaveCompleteNotify notify;
notify.success = success;
notify.msg = msg;
callback(this, kAgeLeaveComplete, &notify, userState);
DEL(this);
}
}
//============================================================================
bool plNCAgeLeaver::MsgReceive (plMessage * msg) {
plNetClientMgr * nc = plNetClientMgr::GetInstance();
plAvatarMgr * am = plAvatarMgr::GetInstance();
plAgeLoader * al = plAgeLoader::GetInstance();
//========================================================================
// Done with link out effects
//========================================================================
if (plLinkOutUnloadMsg * linkOutUnloadMsg = plLinkOutUnloadMsg::ConvertNoRef(msg))
{
if (!linkOutUnloadMsg->HasBCastFlag(plMessage::kNetNonLocal)
&& linkOutUnloadMsg->GetPlayerID() == NetCommGetPlayer()->playerInt
) {
nextOp = kUnloadAge;
}
return true;
}
//========================================================================
// Age data unloaded
//========================================================================
if (plAgeLoadedMsg * ageLoadedMsg = plAgeLoadedMsg::ConvertNoRef(msg)) {
if (!ageLoadedMsg->fLoaded) {
nextOp = kNotifyAgeUnloaded;
return true;
}
return false;
}
return false;
}
//============================================================================
void plNCAgeLeaver::ExecNextOp () {
plNetClientMgr * nc = plNetClientMgr::GetInstance();
plAvatarMgr * am = plAvatarMgr::GetInstance();
plAgeLoader * al = plAgeLoader::GetInstance();
NextOp next = nextOp;
nextOp = kNoOp;
switch (next) {
//====================================================================
case kNoOp: {
}
break;
//====================================================================
case kDisableClickables: {
(TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kDisableClickables))->Send();
nextOp = kLinkOutFX;
}
break;
//====================================================================
case kLinkOutFX: {
nc->StartLinkOutFX();
}
break;
//====================================================================
case kUnloadAge: {
NetCliGameDisconnect();
// Cull nodes that were part of this age vault (but not shared by the player's vault)
VaultCull(NetCommGetAge()->ageVaultId);
// remove the age device inbox mappings
VaultClearDeviceInboxMap();
// Tell our local player that he's unspawning (if that is indeed the case)
nc->IPlayerChangeAge(true /* exiting */, 0/* respawn */);
// disconnect age vault
// @@@ TODO: Unload age vault here
plAgeLoader::GetInstance()->UnloadAge(); // unload age
nc->ISendCameraReset(false/*leaving age*/); // reset camera
nc->IUnloadRemotePlayers(); // unload other players
if (NetCommNeedToLoadAvatar())
am->UnLoadLocalPlayer();
}
break;
//====================================================================
case kNotifyAgeUnloaded: {
// Set "Playing Game" bit to false
nc->SetFlagsBit(plNetClientMgr::kPlayingGame, false);
// Release AgeSDL object, if any
if (nc->fAgeSDLObjectKey)
nc->GetKey()->Release(nc->fAgeSDLObjectKey);
// All done leaving age
Complete(true, "Age unloaded");
}
break;
DEFAULT_FATAL(nextOp);
}
}
//============================================================================
void plNCAgeLeaver::Update () {
ExecNextOp();
}
/*****************************************************************************
*
* Exports
*
***/
//============================================================================
void NCAgeLeaverCreate (
plNCAgeLeaver ** pleaver,
bool quitting,
FNCAgeLeaverCallback callback,
void * userState
) {
ASSERT(pleaver);
ASSERT(callback);
plNCAgeLeaver * leaver;
*pleaver = leaver = NEWZERO(plNCAgeLeaver)(
quitting,
callback,
userState
);
leaver->Start();
}
//============================================================================
bool NCAgeLeaverMsgReceive (
plNCAgeLeaver * leaver,
plMessage * msg
) {
ASSERT(leaver);
return leaver->MsgReceive(msg);
}
//============================================================================
void NCAgeLeaverUpdate (
plNCAgeLeaver * leaver
) {
ASSERT(leaver);
leaver->Update();
}

View File

@ -0,0 +1,100 @@
/*==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==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/PubUtilLib/plNetClient/plNetCliAgeLeaver.h
*
***/
#ifndef PLASMA20_SOURCES_PLASMA_PUBUTILLIB_PLNETCLIENT_PLNETCLIAGELEAVER_H
#define PLASMA20_SOURCES_PLASMA_PUBUTILLIB_PLNETCLIENT_PLNETCLIAGELEAVER_H
#include "HeadSpin.h"
#include "../pnUtils/pnUtils.h"
#include "../pnNetBase/pnNetBase.h"
/*****************************************************************************
*
*
*
***/
class plMessage;
struct plNCAgeLeaver;
enum ENCAgeLeaverNotify {
kAgeLeaveComplete, // notify --> NCAgeLeaveCompleteNotify *, after callback, leaver is destroyed
kNumAgeLeaverNotifications
};
struct NCAgeLeaveCompleteNotify {
bool success;
const char * msg;
};
typedef void (* FNCAgeLeaverCallback)(
plNCAgeLeaver * leaver,
unsigned type, // ENCAgeLeaverNotify
void * notify,
void * userState
);
void NCAgeLeaverCreate (
plNCAgeLeaver ** leaver,
bool quitting,
FNCAgeLeaverCallback callback,
void * userState
);
bool NCAgeLeaverMsgReceive ( // returns true of message was processed
plNCAgeLeaver * leaver,
plMessage * msg
);
void NCAgeLeaverUpdate (
plNCAgeLeaver * leaver
);
#endif // PLASMA20_SOURCES_PLASMA_PUBUTILLIB_PLNETCLIENT_PLNETCLIAGELEAVER_H

View File

@ -0,0 +1,84 @@
/*==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 "hsTimer.h"
#include "plNetClientMgr.h"
#include "plNetLinkingMgr.h"
#include "../plNetClientRecorder/plNetClientRecorder.h"
#include "../plNetMessage/plNetMessage.h"
#include "plgDispatch.h"
//
// Code for interfacing with plNetClientComm library, which in turn
// handles most client-server communication
//
int plNetClientCommMsgHandler::HandleMessage( plNetMessage* msg )
{
plNetClientMgr* nc=plNetClientMgr::GetInstance();
int ret = nc->fMsgHandler.ReceiveMsg(msg);
return ret;
}
int plNetClientMgr::IInitNetClientComm()
{
NetCommActivatePostInitErrorHandler();
ASSERT(!GetFlagsBit(kNetClientCommInited));
fNetClientComm.SetDefaultHandler(&fNetClientCommMsgHandler);
SetFlagsBit(kNetClientCommInited);
return hsOK;
}
//
// Cleanup netClientComm related stuff
//
int plNetClientMgr::IDeInitNetClientComm()
{
SetFlagsBit(kNetClientCommInited, false);
return hsOK;
}

View File

@ -0,0 +1,57 @@
/*==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==*/
#ifndef plNetClientCreatable_inc
#define plNetClientCreatable_inc
#include "../pnFactory/plCreator.h"
#include "plNetClientMgr.h"
REGISTER_CREATABLE( plNetClientMgr );
#include "../plNetTransport/plNetTransportMember.h"
REGISTER_CREATABLE( plNetTransportMember );
#include "plLinkEffectsMgr.h"
REGISTER_CREATABLE( plLinkEffectsMgr );
#endif // plNetClientCreatable_inc

View File

@ -0,0 +1,71 @@
/*==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 "hsResMgr.h"
#include "plNetClientGroup.h"
#include "../plResMgr/plKeyFinder.h"
#include "../plResMgr/plPageInfo.h"
//
// cache room desc string, from fID
//
void plNetClientGroups::ISetGroupDesc(plNetGroupId& grpId)
{
if (grpId.Room() == plNetGroup::kNetGroupUnknown.Room())
grpId.SetDesc("Unknown");
else
if (grpId.Room()== plNetGroup::kNetGroupLocalPlayer.Room())
grpId.SetDesc("LocalPlayer");
else
if (grpId.Room()== plNetGroup::kNetGroupRemotePlayer.Room())
grpId.SetDesc("RemotePlayer");
else
if (grpId.Room()== plNetGroup::kNetGroupLocalPhysicals.Room())
grpId.SetDesc("LocalPhysicals");
else
if (grpId.Room()== plNetGroup::kNetGroupRemotePhysicals.Room())
grpId.SetDesc("RemotePhysicals");
else
{
const plPageInfo* pageInfo=plKeyFinder::Instance().GetLocationInfo(grpId.Room());
grpId.SetDesc(pageInfo->GetPage());
}
}

View File

@ -0,0 +1,141 @@
/*==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==*/
#ifndef plNetClientGroup_h
#define plNetClientGroup_h
#include "hsStlUtils.h"
#include "../../NucleusLib/pnNetCommon/plNetGroup.h"
//
// represents a collection of net groups.
// abstracted so that we can switch to a different container structure if necessary
//
class plNetClientGroups
{
friend class plNetClientMgr;
private:
struct OwnedGroup
{
plNetGroupId fGroup;
bool fOwnIt;
bool operator<(const OwnedGroup& other) const { return other.fGroup<fGroup; }
bool operator==(const OwnedGroup& other) const { return (other.fGroup==fGroup && other.fOwnIt==fOwnIt); }
OwnedGroup(plNetGroupId g, bool o) : fGroup(g),fOwnIt(o) { fGroup.SetDesc(g.GetDesc()); }
OwnedGroup() : fOwnIt(false) {}
};
std::set<OwnedGroup> fGroups;
std::set<OwnedGroup>::iterator IFind(const plNetGroupId& grpId)
{
std::set<OwnedGroup>::iterator it=fGroups.begin();
for( ; it != fGroups.end(); it++)
if ((*it).fGroup==grpId)
break;
return it;
}
// const version
std::set<OwnedGroup>::const_iterator IFind(const plNetGroupId& grpId) const
{
std::set<OwnedGroup>::const_iterator it=fGroups.begin();
for( ; it != fGroups.end(); it++)
if ((*it).fGroup==grpId)
break;
return it;
}
void ISetGroupDesc(plNetGroupId& grpId);
public:
void Reset()
{
ClearGroups();
SetGroup(plNetGroup::kNetGroupLocalPlayer, true /*ownit*/);
SetGroup(plNetGroup::kNetGroupRemotePlayer, false /*ownit*/);
SetGroup(plNetGroup::kNetGroupLocalPhysicals, true /*ownit*/);
SetGroup(plNetGroup::kNetGroupRemotePhysicals, false /*ownit*/);
}
void SetGroup(plNetGroupId& grpId, bool ownIt)
{
std::set<OwnedGroup>::iterator it=IFind(grpId);
if (it != fGroups.end())
{
fGroups.erase(it);
fGroups.insert(OwnedGroup(grpId, ownIt));
}
else
{
ISetGroupDesc(grpId);
fGroups.insert(OwnedGroup(grpId, ownIt));
}
}
#if 0
void RemoveGroup(const plNetGroupId& grpId)
{
std::set<OwnedGroup>::iterator it=IFind(grpId);
if (it != fGroups.end())
fGroups.erase(it);
}
#else
void ClearGroups()
{
fGroups.clear();
}
#endif
int IsGroupLocal(const plNetGroupId& grpId) const
{
std::set<OwnedGroup>::const_iterator it=IFind(grpId);
if (it != fGroups.end())
{
if ((*it).fOwnIt)
return 1; // yes
return 0; // no
}
return -1; // don't know about it
}
};
#endif // plNetClientGroup_h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,414 @@
/*==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==*/
#ifndef PL_NET_CLIENT_inc
#define PL_NET_CLIENT_inc
#include "hsConfig.h"
#include "hsUtils.h"
#include "hsStlUtils.h"
#include "plNetClientGroup.h"
#include "plNetVoiceList.h"
#include "plNetClientMsgHandler.h"
#include "plNetClientStats.h" // STATS Counters
#include "../pnNetCommon/plNetApp.h"
#include "../plNetTransport/plNetTransport.h"
#include "../plEncryption/plChecksum.h"
#include "../plNetCommon/plNetServerSessionInfo.h"
#include "../plNetClientComm/plNetClientComm.h"
#include "../plUnifiedTime/plUnifiedTime.h"
#pragma warning(disable: 4284)
////////////////////////////////////////////////////////////////////
class plUoid;
class hsStream;
class plKey;
class plNetMessage;
class plSynchedObject;
struct DistSqInfo;
class plStatusLog;
class plOperationProgress;
class plIDataServer;
class plPlate;
class plLoadCloneMsg;
class plPlayerPageMsg;
class plNetClientRecorder;
class plVaultPlayerNode;
class plVaultAgeNode;
class plNetVoiceListMsg;
class plStateDataRecord;
class plCCRPetitionMsg;
class plNetMsgPagingRoom;
struct plNetClientCommMsgHandler : plNetClientComm::MsgHandler {
int HandleMessage( plNetMessage* msg );
};
class plNetClientMgr : public plNetClientApp
{
private:
typedef std::vector<plKey> plKeyVec;
public:
enum NetChannels
{
kNetChanDefault,
kNetChanVoice,
kNetChanListenListUpdate,
kNetChanDirectedMsg,
kNetNumChannels
};
enum DirectedSendFlags
{
kInterAgeMsg = 0x1
};
enum ListenListMode
{
kListenList_Distance = 0,
kListenList_Forced,
kListenList_End,
};
enum RefContext
{
kVaultImage = 0,
kAgeSDLHook = 1
};
struct PendingLoad
{
// must be set by user
plStateDataRecord* fSDRec; // the sdl data record
plUoid fUoid; // the object it's meant for
UInt32 fPlayerID; // the player that originally sent the state
// set by NetClient
plKey fKey; // the key of the object it's meant for
double fQueuedTime;
int fQueueTimeResets;
PendingLoad() : fSDRec(nil),fPlayerID(0),fKey(nil),fQueuedTime(0.0),fQueueTimeResets(0) {}
~PendingLoad();
};
private:
// plOperationProgress *fProgressBar;
plOperationProgress *fTaskProgBar;
typedef std::list<PendingLoad*> PendingLoadsList;
PendingLoadsList fPendingLoads;
// pending room page msgs
std::vector<plNetMsgPagingRoom*> fPendingPagingRoomMsgs;
plNetTransport fTransport;
// groups of objects in the game. Each group is mastered by a single client.
plNetClientGroups fNetGroups;
// cached char info
plKey fLocalPlayerKey;
plKeyVec fRemotePlayerKeys;
// plKeyVec fNPCKeys;
class plNetClientMgrMsg * fDisableMsg;
// ini info
std::string fIniAccountName;
std::string fIniAccountPass;
std::string fIniAuthServer;
UInt32 fIniPlayerID; // the player we want to load from vault.
std::string fSPDesiredPlayerName; // SP: the player we want to load from vault.
// server info
double fServerTimeOffset; // diff between our unified time and server's unified time
UInt32 fTimeSamples;
double fLastTimeUpdate;
UInt8 fJoinOrder; // returned by the server
// voice lists
int fListenListMode; // how we are generating our listen list
plNetListenList fListenList; // other players I'm listening to
plNetTalkList fTalkList; // other players I'm talking to
plNetClientMsgHandler fMsgHandler;
// recorder support
plNetClientRecorder* fMsgRecorder;
std::vector<plNetClientRecorder*> fMsgPlayers;
plKey fAgeSDLObjectKey;
UInt8 fExperimentalLevel;
plNetClientStats fNetClientStats;
UInt8 fPingServerType; // non-zero if we're pinging someone
float fOverrideAgeTimeOfDayPercent; // for console debugging
int fNumInitialSDLStates;
int fRequiredNumInitialSDLStates;
// simplification of object ownership...one player owns all non-physical objects in the world
// physical objects are owned by whoever touched them most recently (or the "owner" if nobody
// has touched it yet)
bool fIsOwner;
//
void ICheckPendingStateLoad(double secs);
int IDeduceLocallyOwned(const plUoid& loc) const;
bool IHandlePlayerPageMsg(plPlayerPageMsg *playerMsg); // ***
void IShowLists();
void IShowRooms();
void IShowAvatars();
void IShowRelevanceRegions();
int ISendDirtyState(double secs);
int ISendMembersListRequest();
int ISendRoomsReset();
void ISendCCRPetition(plCCRPetitionMsg* petMsg);
void ISendCameraReset(hsBool bEnteringAge);
hsBool IUpdateListenList(double secs);
void IHandleNetVoiceListMsg(plNetVoiceListMsg* msg);
hsBool IApplyNewListenList(std::vector<DistSqInfo>& newListenList, hsBool forceSynch);
int IPrepMsg(plNetMessage* msg);
void IPlayerChangeAge(hsBool exiting, Int32 spawnPt);
void IAddCloneRoom();
void IRemoveCloneRoom();
void IUnloadRemotePlayers();
plKey ILoadClone(plLoadCloneMsg *cloneMsg);
bool IFindModifier(plSynchedObject* obj, Int16 classIdx);
void IClearPendingLoads();
// recorder
bool IIsRecordableMsg(plNetMessage* msg);
void IPlaybackMsgs();
void IRequestAgeState();
void IDumpOSVersionInfo() const;
int ISendGameMessage(plMessage* msg);
void IDisableNet ();
public:
plNetClientMgr();
~plNetClientMgr();
CLASSNAME_REGISTER( plNetClientMgr );
GETINTERFACE_ANY( plNetClientMgr, plNetClientApp );
static plNetClientMgr* GetInstance() { return plNetClientMgr::ConvertNoRef(fInstance); }
void StartLinkOutFX();
void StartLinkInFX();
hsBool MsgReceive(plMessage* msg);
void Shutdown();
int Init();
void QueueDisableNet (bool showDlg, const char msg[]);
int SendMsg(plNetMessage* msg);
int Update(double secs);
int IsLocallyOwned(const plSynchedObject* obj) const; // returns yes/no/maybe
int IsLocallyOwned(const plUoid&) const; // for special cases, like sceneNodes. returns yes/no/maybe
plNetGroupId GetEffectiveNetGroup(const plSynchedObject*& obj) const;
plNetGroupId SelectNetGroup(plSynchedObject* objIn, plKey groupKey);
void SendLocalPlayerAvatarCustomizations();
void SendApplyAvatarCustomizationsMsg(const plKey msgReceiver, bool netPropagate=true, bool localPropagate=true);
// plLoggable
bool Log(const char* str) const;
// setters
void SetIniAuthServer(const char * value) { fIniAuthServer=value;}
void SetIniAccountName(const char * value) { fIniAccountName=value;}
void SetIniAccountPass(const char * value) { fIniAccountPass=value;}
void SetIniPlayerID(UInt32 value) { fIniPlayerID=value;}
void SetSPDesiredPlayerName( const char * value ) { fSPDesiredPlayerName=value;}
const char * GetSPDesiredPlayerName() const { return fSPDesiredPlayerName.c_str(); }
void SetLocalPlayerKey(plKey l, hsBool pageOut=false);
void SetNullSend(hsBool on); // turn null send on/off
void SetPingServer(UInt8 serverType) { fPingServerType = serverType; }
// getters
UInt32 GetPlayerID( void ) const;
const char * GetPlayerName( const plKey avKey=nil ) const;
const char * GetPlayerNameById (unsigned playerId) const;
unsigned GetPlayerIdByName(const char name[]) const;
UInt8 GetJoinOrder() const { return fJoinOrder; } // only valid at join time
plKey GetLocalPlayerKey() const { return fLocalPlayerKey; }
plSynchedObject* GetLocalPlayer(hsBool forceLoad=false) const;
hsBool IsPeerToPeer() const { return false; }
hsBool IsConnected() const { return true; }
void IncNumInitialSDLStates();
void ResetNumInitialSDLStates() { fNumInitialSDLStates=0; }
int GetNumInitialSDLStates() const { return fNumInitialSDLStates; }
void SetRequiredNumInitialSDLStates( int v ) { fRequiredNumInitialSDLStates=v; }
int GetRequiredNumInitialSDLStates() const { return fRequiredNumInitialSDLStates; }
// Linking progress
void StartTaskProgress( const char *msg, int numSteps );
void IncTaskProgress( const char *msg );
// avatar vault actions
int UploadPlayerVault(UInt32 vaultFlags);
// remote players
const std::vector<plKey>& RemotePlayerKeys() const { return fRemotePlayerKeys; }
plSynchedObject* GetRemotePlayer(int i) const;
void AddRemotePlayerKey(plKey p);
hsBool IsRemotePlayerKey(const plKey p, int* idx=nil);
bool IsAPlayerKey(const plKey pKey) { return (pKey==GetLocalPlayerKey() || IsRemotePlayerKey(pKey)); }
void SetConsoleOutput( bool b ) { SetFlagsBit(kConsoleOutput, b); }
bool GetConsoleOutput() const { return GetFlagsBit(kConsoleOutput); }
// Net groups
const plNetClientGroups* GetNetGroups() const { return &fNetGroups; }
plNetClientGroups* GetNetGroups() { return &fNetGroups; }
// Voice Lists
plNetListenList* GetListenList() { return &fListenList; }
plNetTalkList* GetTalkList() { return &fTalkList; }
void SetListenListMode (int i);
void SynchTalkList();
int GetListenListMode() { return fListenListMode; }
// network activity-generated events, passed to current task
bool CanSendMsg(plNetMessage * msg);
const plNetTransport& TransportMgr() const { return fTransport; }
plNetTransport& TransportMgr() { return fTransport; }
bool ObjectInLocalAge(const plSynchedObject* obj) const;
// time converters
plUnifiedTime GetServerTime() const;
const char* GetServerLogTimeAsString(std::string& ts) const;
double GetCurrentAgeElapsedSeconds() const;
float GetCurrentAgeTimeOfDayPercent() const;
bool RecordMsgs(const char* recType, const char* recName);
bool PlaybackMsgs(const char* recName);
void MakeCCRInvisible(plKey avKey, int level);
bool CCRVaultConnected() const { return GetFlagsBit(kCCRVaultConnected); }
UInt8 GetExperimentalLevel() const { return fExperimentalLevel; }
void AddPendingLoad(PendingLoad *pl);
const plKey& GetAgeSDLObjectKey() const { return fAgeSDLObjectKey; }
plUoid GetAgeSDLObjectUoid(const char* ageName) const;
plNetClientComm& GetNetClientComm() { return fNetClientComm; }
const char* plNetClientMgr::GetNextAgeFilename();
plNetClientStats& GetNetClientStats() { return fNetClientStats; }
void SetOverrideAgeTimeOfDayPercent(float f) { fOverrideAgeTimeOfDayPercent=f; }
void AddPendingPagingRoomMsg( plNetMsgPagingRoom * msg );
void MaybeSendPendingPagingRoomMsgs();
void SendPendingPagingRoomMsgs();
void ClearPendingPagingRoomMsgs();
void NotifyRcvdAllSDLStates();
plOperationProgress* GetTaskProgBar() { return fTaskProgBar; }
bool DebugMsgV(const char* fmt, va_list args) const;
bool ErrorMsgV(const char* fmt, va_list args) const;
bool WarningMsgV(const char* fmt, va_list args) const;
bool AppMsgV(const char* fmt, va_list args) const;
bool IsObjectOwner();
void SetObjectOwner(bool own);
void StoreSDLState(const plStateDataRecord* sdRec, const plUoid& uoid, UInt32 sendFlags, UInt32 writeOptions);
void UpdateServerTimeOffset(plNetMessage* msg);
void ResetServerTimeOffset();
private:
plNetClientComm fNetClientComm;
plNetClientCommMsgHandler fNetClientCommMsgHandler;
int IInitNetClientComm();
int IDeInitNetClientComm();
void INetClientCommOpStarted(UInt32 context);
void INetClientCommOpComplete(UInt32 context, int resultCode);
friend struct plNCAgeJoiner;
friend struct plNCAgeLeaver;
friend class plNetDniInfoSource;
friend class plNetTalkList;
friend class plNetClientMsgHandler;
friend struct plNetClientCommMsgHandler;
};
#define plCheckNetMgrResult_VoidReturn(r,s) if (hsFailed(r)) { ErrorMsg(s); hsAssert(false,s); return; }
// returns int
#define plCheckNetMgrResult_ValReturn(r,s) if (hsFailed(r)) { ErrorMsg(s); hsAssert(false,s); return r; }
// returns bool
#define plCheckNetMgrResult_BoolReturn(r,s) if (hsFailed(r)) { ErrorMsg(s); hsAssert(false,s); return false; }
#endif // PL_NET_CLIENT_inc

View File

@ -0,0 +1,187 @@
/*==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==*/
#if 1 // for debugging
#include "plCreatableIndex.h"
#include "../plModifier/plResponderModifier.h"
#include "../plSurface/plLayerAnimation.h"
#endif
#include "hsStream.h"
#include "plNetClientMgr.h"
#include "plgDispatch.h"
#include "hsResMgr.h"
#include "hsTimer.h"
#include "../plNetMessage/plNetMessage.h"
#include "../pnKeyedObject/plKey.h"
#include "../pnKeyedObject/plFixedKey.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnModifier/plModifier.h"
#include "../pnMessage/plNodeRefMsg.h"
#include "../pnMessage/plClientMsg.h"
#include "../pnMessage/plNodeChangeMsg.h"
#include "../pnMessage/plPlayerPageMsg.h"
#include "../plScene/plSceneNode.h"
#include "../plScene/plRelevanceMgr.h"
#include "../plNetTransport/plNetTransportMember.h"
#include "../plResMgr/plKeyFinder.h"
#include "../plAgeDescription/plAgeDescription.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plSDL/plSDL.h"
/// TEMP HACK TO LOAD CONSOLE INIT FILES ON AGE LOAD
#include "../plMessage/plConsoleMsg.h"
#include "../plMessage/plLoadAvatarMsg.h"
#include "../plMessage/plAgeLoadedMsg.h"
#include "../plAgeLoader/plResPatcher.h"
#include "../plProgressMgr/plProgressMgr.h"
#include "../plResMgr/plRegistryHelpers.h"
#include "../plResMgr/plRegistryNode.h"
#include "../plResMgr/plResManager.h"
#include "process.h" // for getpid()
extern hsBool gDataServerLocal;
// Load Player object
// a clone will be created if cloneNum>0
// returns the playerKey if successful.
//
// Don't call this directly. Send a clone message to the NetClientManager instead.
// Load an object, optionally cloning if necessary.
plKey plNetClientMgr::ILoadClone(plLoadCloneMsg *pCloneMsg)
{
plKey cloneKey = pCloneMsg->GetCloneKey();
if(pCloneMsg->GetIsLoading())
{
if (cloneKey->ObjectIsLoaded())
{
char tmp[256];
DebugMsg("ILoadClone: object %s is already loaded, ignoring", cloneKey->GetUoid().StringIze(tmp));
return cloneKey;
}
// check if local or remote player before loading
plLoadAvatarMsg* loadAvMsg=plLoadAvatarMsg::ConvertNoRef(pCloneMsg);
if (loadAvMsg && loadAvMsg->GetIsPlayer())
{
bool originating = ( pCloneMsg->GetOriginatingPlayerID() == this->GetPlayerID() );
if (originating)
fLocalPlayerKey = cloneKey;
else
AddRemotePlayerKey(cloneKey);
}
plKey cloneNodeKey = hsgResMgr::ResMgr()->FindKey(kNetClientCloneRoom_KEY);
// Put the clone into the room, which also forces it to load.
plNodeRefMsg* nodeRefCloneMsg = TRACKED_NEW plNodeRefMsg(cloneNodeKey, plNodeRefMsg::kOnRequest, -1, plNodeRefMsg::kObject);
hsgResMgr::ResMgr()->AddViaNotify(cloneKey, nodeRefCloneMsg, plRefFlags::kActiveRef);
// Finally, pump the dispatch system so all the new refs get delivered. ?
plgDispatch::Dispatch()->MsgQueueProcess();
}
else // we're unloading a clone
{
if (!cloneKey->ObjectIsLoaded())
{
DebugMsg("ILoadClone: object %s is already unloaded, ignoring", cloneKey->GetName());
return cloneKey;
}
ICheckPendingStateLoad(hsTimer::GetSysSeconds());
plSynchEnabler p(false); // turn off dirty tracking while in this function
GetKey()->Release(cloneKey); // undo the active ref we took in ILoadClone
// send message to scene object to remove him from the room
plNodeChangeMsg* nodeChange = TRACKED_NEW plNodeChangeMsg(GetKey(), cloneKey, nil);
plgDispatch::MsgSend(nodeChange);
}
plKey requestorKey = pCloneMsg->GetRequestorKey();
// Readdress the message to the requestor and send it again
plKey myKey = GetKey();
pCloneMsg->SetBCastFlag(plMessage::kNetPropagate, false);
pCloneMsg->ClearReceivers();
pCloneMsg->AddReceiver(requestorKey);
pCloneMsg->Ref(); // each message send unrefs once
pCloneMsg->Send();
return cloneKey;
}
//
// Cause a player to respawn. This is typically called on the local player when he links to a new age.
// or for unspawn:
//
void plNetClientMgr::IPlayerChangeAge(hsBool exitAge, Int32 spawnPt)
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar)
{
plSynchEnabler ps(false); // disable state change tracking while we change ages
if (exitAge)
avatar->LeaveAge();
else
{
hsBool validSpawn = (spawnPt >= 0);
avatar->EnterAge(!validSpawn);
if (validSpawn)
avatar->SpawnAt(spawnPt, hsTimer::GetSysSeconds());
}
}
else if (fLocalPlayerKey)
{
ErrorMsg("Can't find avatarMod %s", fLocalPlayerKey->GetName());
}
}

View File

@ -0,0 +1,133 @@
/*==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 "plgDispatch.h"
#include "plNetClientMgr.h"
#include "../pnNetCommon/pnNetCommon.h"
#include "../pnMessage/plTimeMsg.h"
#include "../plNetClientRecorder/plNetClientRecorder.h"
//
// make a recording of current play
//
bool plNetClientMgr::RecordMsgs(const char* recType, const char* recName)
{
if (!fMsgRecorder)
{
if (stricmp(recType,"stream") == 0)
fMsgRecorder = TRACKED_NEW plNetClientStreamRecorder;
if (stricmp(recType,"stressstream") == 0)
fMsgRecorder = TRACKED_NEW plNetClientStressStreamRecorder;
if (stricmp(recType,"stats") == 0)
fMsgRecorder = TRACKED_NEW plNetClientStatsRecorder;
if (stricmp(recType,"streamandstats") == 0)
fMsgRecorder = TRACKED_NEW plNetClientStreamAndStatsRecorder(TRACKED_NEW plNetClientStreamRecorder(), TRACKED_NEW plNetClientStatsRecorder());
if (stricmp(recType,"stressstreamandstats") == 0)
fMsgRecorder = TRACKED_NEW plNetClientStreamAndStatsRecorder(TRACKED_NEW plNetClientStressStreamRecorder(), TRACKED_NEW plNetClientStatsRecorder());
if (!fMsgRecorder || !fMsgRecorder->BeginRecording(recName))
{
delete fMsgRecorder;
fMsgRecorder = nil;
return false;
}
return true;
}
return false;
}
//
// play a recording
//
bool plNetClientMgr::PlaybackMsgs(const char* recName)
{
hsLogEntry(DebugMsg("DEMO: Beginning Playback"));
plNetClientRecorder* player = TRACKED_NEW plNetClientStreamRecorder;
if (player->BeginPlayback(recName))
{
fMsgPlayers.push_back(player);
// plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
return true;
}
else
{
delete player;
return false;
}
}
//
//
//
void plNetClientMgr::IPlaybackMsgs()
{
for (int i = 0; i < fMsgPlayers.size(); i++)
{
plNetClientRecorder* recorder = fMsgPlayers[i];
if (recorder->IsQueueEmpty())
{
delete recorder;
fMsgPlayers.erase(fMsgPlayers.begin()+i);
i--;
if (fMsgPlayers.empty())
{
// plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
}
}
else
{
while (plNetMessage* msg = recorder->GetNextMessage())
{
hsLogEntry(DebugMsg("<Recorded Msg>"));
fMsgHandler.ReceiveMsg(msg);
}
}
}
}

View File

@ -0,0 +1,476 @@
/*==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 "hsTimer.h"
#include "hsResMgr.h"
#include "plNetClientMgr.h"
#include "plCreatableIndex.h"
#include "plNetObjectDebugger.h"
#include "plNetClientMsgScreener.h"
#include "../pnNetCommon/plSynchedObject.h"
#include "../pnNetCommon/plSDLTypes.h"
#include "../pnMessage/plCameraMsg.h"
#include "../plNetClientRecorder/plNetClientRecorder.h"
#include "../plMessage/plLoadCloneMsg.h"
#include "../plMessage/plLoadAvatarMsg.h"
#include "../plAvatar/plAvatarClothing.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plNetMessage/plNetMessage.h"
#include "../plMessage/plCCRMsg.h"
#include "../plVault/plVault.h"
#include "../plContainer/plConfigInfo.h"
#include "../plDrawable/plMorphSequence.h"
#include "../plParticleSystem/plParticleSystem.h"
#include "../plParticleSystem/plParticleSDLMod.h"
#include "../plResMgr/plLocalization.h"
#include "../../FeatureLib/pfMessage/pfKIMsg.h" // TMP
#include "../plNetGameLib/plNetGameLib.h"
#include "../plSDL/plSDL.h"
//
// request members list from server
//
int plNetClientMgr::ISendMembersListRequest()
{
plNetMsgMembersListReq msg;
msg.SetNetProtocol(kNetProtocolCli2Game);
return SendMsg(&msg);
}
//
// reset paged in rooms list on server
//
int plNetClientMgr::ISendRoomsReset()
{
plNetMsgPagingRoom msg;
msg.SetPageFlags(plNetMsgPagingRoom::kResetList);
msg.SetNetProtocol(kNetProtocolCli2Game);
return SendMsg(&msg);
}
//
// Make sure all dirty objects save their state.
// Mark those objects as clean and clear the dirty list.
//
int plNetClientMgr::ISendDirtyState(double secs)
{
std::vector<plSynchedObject::StateDefn> carryOvers;
Int32 num=plSynchedObject::GetNumDirtyStates();
#if 0
if (num)
{
DebugMsg("%d dirty sdl state msgs queued, t=%f", num, secs);
}
#endif
Int32 i;
for(i=0;i<num;i++)
{
plSynchedObject::StateDefn* state=plSynchedObject::GetDirtyState(i);
plSynchedObject* obj=state->GetObject();
if (!obj)
continue; // could add to carryOvers
if (!(state->fSendFlags & plSynchedObject::kSkipLocalOwnershipCheck))
{
int localOwned=obj->IsLocallyOwned();
if (localOwned==plSynchedObject::kNo)
{
DebugMsg("Late rejection of queued SDL state, obj %s, sdl %s",
state->fObjKey->GetName(), state->fSDLName.c_str());
continue;
}
}
obj->CallDirtyNotifiers();
obj->SendSDLStateMsg(state->fSDLName.c_str(), state->fSendFlags);
}
plSynchedObject::ClearDirtyState(carryOvers);
return hsOK;
}
//
// Given a plasma petition msg, send a petition text node to the vault
// vault will detect and fwd to CCR system.
//
void plNetClientMgr::ISendCCRPetition(plCCRPetitionMsg* petMsg)
{
// petition msg info
UInt8 type = petMsg->GetType();
const char* title = petMsg->GetTitle();
const char* note = petMsg->GetNote();
std::string work = note;
std::replace( work.begin(), work.end(), '\n', '\t' );
note = work.c_str();
// stuff petition info fields into a config info object
plConfigInfo info;
info.AddValue( "Petition", "Type", type );
info.AddValue( "Petition", "Content", note );
info.AddValue( "Petition", "Title", title );
info.AddValue( "Petition", "Language", plLocalization::GetLanguageName( plLocalization::GetLanguage() ) );
info.AddValue( "Petition", "AcctName", NetCommGetAccount()->accountNameAnsi );
char buffy[20];
sprintf( buffy, "%lu", GetPlayerID() );
info.AddValue( "Petition", "PlayerID", buffy );
info.AddValue( "Petition", "PlayerName", GetPlayerName() );
// write config info formatted like an ini file to a buffer
hsRAMStream ram;
info.WriteTo( &plIniStreamConfigSource( &ram ) );
int size = ram.GetPosition();
ram.Rewind();
std::string buf;
buf.resize( size );
ram.CopyToMem( (void*)buf.data() );
wchar * wStr = StrDupToUnicode(buf.c_str());
NetCliAuthSendCCRPetition(wStr);
FREE(wStr);
}
//
// send a msg to reset the camera in a new age
//
void plNetClientMgr::ISendCameraReset(hsBool bEnteringAge)
{
plCameraMsg* pCamMsg = TRACKED_NEW plCameraMsg;
if (bEnteringAge)
pCamMsg->SetCmd(plCameraMsg::kResetOnEnter);
else
pCamMsg->SetCmd(plCameraMsg::kResetOnExit);
pCamMsg->SetBCastFlag(plMessage::kBCastByExactType, false);
plUoid U2(kVirtualCamera1_KEY);
plKey pCamKey = hsgResMgr::ResMgr()->FindKey(U2);
if (pCamKey)
pCamMsg->AddReceiver(pCamKey);
pCamMsg->Send();
}
//
// When we link in to a new age, we need to send our avatar state up to the gameserver
//
void plNetClientMgr::SendLocalPlayerAvatarCustomizations()
{
plSynchEnabler ps(true); // make sure synching is enabled, since this happens during load
const plArmatureMod * avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
hsAssert(avMod,"Failed to get local avatar armature modifier.");
avMod->GetClothingOutfit()->DirtySynchState(kSDLClothing, plSynchedObject::kBCastToClients | plSynchedObject::kForceFullSend);
plSceneObject* pObj = (const_cast<plArmatureMod*>(avMod))->GetFollowerParticleSystemSO();
if (pObj)
{
const plParticleSystem* sys = plParticleSystem::ConvertNoRef(pObj->GetModifierByType(plParticleSystem::Index()));
if (sys)
(const_cast<plParticleSystem*>(sys))->GetSDLMod()->SendState(plSynchedObject::kBCastToClients | plSynchedObject::kForceFullSend);
}
// may want to do this all the time, but for now stealthmode is the only extra avatar state we care about
// don't bcast this to other clients, the invis level is contained in the linkIn msg which will synch other clients
if (avMod->IsInStealthMode() && avMod->GetTarget(0))
avMod->GetTarget(0)->DirtySynchState(kSDLAvatar, plSynchedObject::kForceFullSend);
hsTArray<const plMorphSequence*> morphs;
plMorphSequence::FindMorphMods(avMod->GetTarget(0), morphs);
int i;
for (i = 0; i < morphs.GetCount(); i++)
if (morphs[i]->GetTarget(0))
morphs[i]->GetTarget(0)->DirtySynchState(kSDLMorphSequence, plSynchedObject::kBCastToClients);
}
//
// Called to send a plasma msg out over the network. Called by the dispatcher.
// return hsOK if ok
//
int plNetClientMgr::ISendGameMessage(plMessage* msg)
{
if (GetFlagsBit(kDisabled))
return hsOK;
static plNetClientMsgScreener screener; // make static so that there's only 1 log per session
if (!screener.AllowMessage(msg))
{
if (GetFlagsBit(kScreenMessages))
return hsOK; // filter out illegal messages
}
// TEMP
if (GetFlagsBit(kSilencePlayer))
{
pfKIMsg* kiMsg = pfKIMsg::ConvertNoRef(msg);
if (kiMsg && kiMsg->GetCommand()==pfKIMsg::kHACKChatMsg)
return hsOK;
}
plNetPlayerIDList* dstIDs = msg->GetNetReceivers();
#ifdef HS_DEBUGGING
if ( dstIDs )
{
DebugMsg( "Preparing to send %s to specific players.", msg->ClassName() );
}
#endif
// get sender object
plSynchedObject* synchedObj = msg->GetSender() ? plSynchedObject::ConvertNoRef(msg->GetSender()->ObjectIsLoaded()) : nil;
// if sender is flagged as localOnly, he shouldn't talk to the network
if (synchedObj && !synchedObj->IsNetSynched() )
return hsOK;
// choose appropriate type of net game msg wrapper
plNetMsgGameMessage* netMsgWrap=nil;
plLoadCloneMsg* loadClone = plLoadCloneMsg::ConvertNoRef(msg);
if (loadClone)
{
plLoadAvatarMsg* lam=plLoadAvatarMsg::ConvertNoRef(msg);
netMsgWrap = TRACKED_NEW plNetMsgLoadClone;
plNetMsgLoadClone* netLoadClone=plNetMsgLoadClone::ConvertNoRef(netMsgWrap);
netLoadClone->SetIsPlayer(lam && lam->GetIsPlayer());
netLoadClone->SetIsLoading(loadClone->GetIsLoading()!=0);
netLoadClone->ObjectInfo()->SetFromKey(loadClone->GetCloneKey());
}
else
if (dstIDs)
{
netMsgWrap = TRACKED_NEW plNetMsgGameMessageDirected;
int i;
for(i=0;i<dstIDs->size();i++)
{
UInt32 playerID = (*dstIDs)[i];
if (playerID == NetCommGetPlayer()->playerInt)
continue;
hsLogEntry( DebugMsg( "\tAdding receiver: %lu" , playerID ) );
((plNetMsgGameMessageDirected*)netMsgWrap)->Receivers()->AddReceiverPlayerID( playerID );
}
}
else
netMsgWrap = TRACKED_NEW plNetMsgGameMessage;
// check delivery timestamp
if (msg->GetTimeStamp()<=hsTimer::GetSysSeconds())
msg->SetTimeStamp(0);
else
netMsgWrap->GetDeliveryTime().SetFromGameTime(msg->GetTimeStamp(), hsTimer::GetSysSeconds());
// write message (and label) to ram stream
hsRAMStream stream;
hsgResMgr::ResMgr()->WriteCreatable(&stream, msg);
// put stream in net msg wrapper
netMsgWrap->StreamInfo()->CopyStream(&stream);
// hsLogEntry( DebugMsg(plDispatchLog::GetInstance()->MakeMsgInfoString(msg, "\tActionMsg:",0)) );
// check if this msg uses direct communication (sent to specific rcvrs)
// if so the server can filter it
hsBool bCast = msg->HasBCastFlag(plMessage::kBCastByExactType) ||
msg->HasBCastFlag(plMessage::kBCastByType);
hsBool directCom = msg->GetNumReceivers()>0;
if( directCom )
{
// It's direct if we have receivers AND any of them are in non-virtual locations
int i;
for( i = 0, directCom = false; i < msg->GetNumReceivers(); i++ )
{
if( !msg->GetReceiver( i )->GetUoid().GetLocation().IsVirtual() &&
!msg->GetReceiver( i )->GetUoid().GetLocation().IsReserved()
// && !IsBuiltIn
)
{
directCom = true;
break;
}
}
if (!directCom)
bCast = true;
}
if (!directCom && !bCast && !dstIDs)
WarningMsg("Msg %s has no rcvrs or bcast instructions?", msg->ClassName());
hsAssert(!(directCom && bCast), "msg has both rcvrs and bcast instructions, rcvrs ignored");
if (directCom && !bCast)
{
netMsgWrap->SetBit(plNetMessage::kHasGameMsgRcvrs); // for quick server filtering
netMsgWrap->StreamInfo()->SetCompressionType(plNetMessage::kCompressionDont);
}
//
// check for net propagated plasma msgs which should be filtered by relevance regions.
// currently only avatar control messages.
//
if (msg->HasBCastFlag(plMessage::kNetUseRelevanceRegions))
{
netMsgWrap->SetBit(plNetMessage::kUseRelevanceRegions);
}
//
// CCRs can route a plMessage to all online players.
//
hsBool ccrSendToAllPlayers = false;
#ifndef PLASMA_EXTERNAL_RELEASE
if ( AmCCR() )
{
ccrSendToAllPlayers = msg->HasBCastFlag( plMessage::kCCRSendToAllPlayers );
if ( ccrSendToAllPlayers )
netMsgWrap->SetBit( plNetMessage::kRouteToAllPlayers );
}
#endif
//
// check for inter-age routing. if set, online rcvrs not in current age will receive
// this msg courtesy of pls routing.
//
if ( !ccrSendToAllPlayers )
{
hsBool allowInterAge = msg->HasBCastFlag( plMessage::kNetAllowInterAge );
if ( allowInterAge )
netMsgWrap->SetBit(plNetMessage::kInterAgeRouting);
}
// check for reliable send
if (msg->HasBCastFlag(plMessage::kNetSendUnreliable) &&
!(synchedObj && (synchedObj->GetSynchFlags() & plSynchedObject::kSendReliably)) )
netMsgWrap->SetBit(plNetMessage::kNeedsReliableSend, 0); // clear reliable net send bit
#ifdef HS_DEBUGGING
Int16 type=*(Int16*)netMsgWrap->StreamInfo()->GetStreamBuf();
hsAssert(type>=0 && type<plCreatableIndex::plNumClassIndices, "garbage type out");
#endif
netMsgWrap->SetPlayerID(GetPlayerID());
netMsgWrap->SetNetProtocol(kNetProtocolCli2Game);
int ret = SendMsg(netMsgWrap);
if (plNetObjectDebugger::GetInstance()->IsDebugObject(msg->GetSender() ? msg->GetSender()->ObjectIsLoaded() : nil))
{
#if 0
hsLogEntry(plNetObjectDebugger::GetInstance()->LogMsg(
xtl::format("<SND> object:%s, rcvr %s %s",
msg->GetSender(),
msg->GetNumReceivers() ? msg->GetReceiver(0)->GetName() : "?",
netMsgWrap->AsStdString().c_str()).c_str()));
#endif
}
delete netMsgWrap;
return ret;
}
//
// Send a net msg. Delivers to transport mgr who sends p2p or to server
//
int plNetClientMgr::SendMsg(plNetMessage* msg)
{
if (GetFlagsBit(kDisabled))
return hsOK;
if (!CanSendMsg(msg))
return hsOK;
// If we're recording messages, set an identifying flag and echo the message back to ourselves
if (fMsgRecorder && fMsgRecorder->IsRecordableMsg(msg))
{
msg->SetBit(plNetMessage::kEchoBackToSender, true);
}
msg->SetTimeSent(plUnifiedTime::GetCurrentTime());
int channel = IPrepMsg(msg);
// hsLogEntry( DebugMsg( "<SND> %s %s", msg->ClassName(), msg->AsStdString().c_str()) );
int ret=fTransport.SendMsg(channel, msg);
// Debug
if (plNetMsgVoice::ConvertNoRef(msg))
SetFlagsBit(kSendingVoice);
if (plNetMsgGameMessage::ConvertNoRef(msg))
SetFlagsBit(kSendingActions);
plCheckNetMgrResult_ValReturn(ret,(char*)xtl::format("Failed to send %s, NC ret=%d",
msg->ClassName(), ret).c_str());
return ret;
}
void plNetClientMgr::StoreSDLState(const plStateDataRecord* sdRec, const plUoid& uoid,
UInt32 sendFlags, UInt32 writeOptions)
{
// send to server
plNetMsgSDLState* msg = sdRec->PrepNetMsg(0, writeOptions);
msg->SetNetProtocol(kNetProtocolCli2Game);
msg->ObjectInfo()->SetUoid(uoid);
if (sendFlags & plSynchedObject::kNewState)
msg->SetBit(plNetMessage::kNewSDLState);
if (sendFlags & plSynchedObject::kUseRelevanceRegions)
msg->SetBit(plNetMessage::kUseRelevanceRegions);
if (sendFlags & plSynchedObject::kDontPersistOnServer)
msg->SetPersistOnServer(false);
if (sendFlags & plSynchedObject::kIsAvatarState)
msg->SetIsAvatarState(true);
bool broadcast = (sendFlags & plSynchedObject::kBCastToClients) != 0;
if (broadcast && plNetClientApp::GetInstance())
{
msg->SetPlayerID(plNetClientApp::GetInstance()->GetPlayerID());
}
SendMsg(msg);
DEL(msg);
}

View File

@ -0,0 +1,391 @@
/*==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 "plNetClientMgr.h"
#include "plNetLinkingMgr.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plPipeline/plPlates.h"
#include "../plPipeline/plDebugText.h"
#include "../plNetTransport/plNetTransportMember.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plScene/plRelevanceMgr.h"
//
// Code which displays stuff on the screen
//
//
// show lists of members, listenList, and talkList
//
void plNetClientMgr::IShowLists()
{
plNetLinkingMgr * lm = plNetLinkingMgr::GetInstance();
plDebugText &txt = plDebugText::Instance();
int y,x,i;
const int yOff=10, xOff=300, startY=70, startX=10;
char str[256];
// My player info
x=startX;
y=startY;
plSceneObject *player = plSceneObject::ConvertNoRef(GetLocalPlayer());
hsPoint3 pos = (player ? player->GetLocalToWorld() * hsPoint3(0, 0, 0) : hsPoint3(0, 0, 0));
sprintf(str, "%s%s PlyrName=%s PlyrID=%d AcctID=%d P2P=%d Join#=%d Peers=%d %.1f,%.1f,%.1f",
GetFlagsBit(kSendingVoice) ? "V" : " ",
GetFlagsBit(kSendingActions) ? "A" : " ",
GetPlayerName(), GetPlayerID(), 0,
IsPeerToPeer(), GetJoinOrder(), 0,
pos.fX, pos.fY, pos.fZ);
txt.DrawString(x,y,str,255,255,255,255);
SetFlagsBit(kSendingVoice, 0);
SetFlagsBit(kSendingActions, 0);
y+=yOff;
sprintf(str, " Server=%s ILIAS=%d", "foo",
IsLoadingInitialAgeState());
txt.DrawString(x,y,str,255,255,255,255);
// MEMBERS
y+=yOff;
int baseY=y;
txt.DrawString(x,y," Members",255,255,255,255,plDebugText::kStyleBold);
y+=yOff;
plNetTransportMember** members=nil;
fTransport.GetMemberListDistSorted(members);
for(i=0;i<fTransport.GetNumMembers();i++)
{
plNetTransportMember* mbr=members[i];
hsAssert(mbr, "ShowLists: nil member?");
if (mbr->IsServer())
continue;
player = (mbr->GetAvatarKey() ? plSceneObject::ConvertNoRef(mbr->GetAvatarKey()->ObjectIsLoaded()) : nil);
sprintf(str, "%s%s %s p2p=%d dist=%.1f",
mbr->GetTransportFlags() & plNetTransportMember::kSendingVoice ? "V" : " ",
mbr->GetTransportFlags() & plNetTransportMember::kSendingActions ? "A" : " ",
mbr->AsStdString().c_str(),
mbr->IsPeerToPeer(),
mbr->GetDistSq() != hsScalarMax ? hsSquareRoot(mbr->GetDistSq()) :-1.f);
txt.DrawString(x,y,str);
y+=yOff;
mbr->SetTransportFlags(mbr->GetTransportFlags() &
~(plNetTransportMember::kSendingVoice|plNetTransportMember::kSendingActions));
}
delete [] members;
// LISTENLIST
x+=xOff;
y=baseY;
txt.DrawString(x,y,"ListenList",255,255,255,255,plDebugText::kStyleBold);
y+=yOff;
for(i=0;i<GetListenList()->GetNumMembers();i++)
{
sprintf(str, "name=%s", GetListenList()->GetMember(i)->AsStdString().c_str());
txt.DrawString(x,y,str);
y+=yOff;
}
// TALKLIST
x+=xOff;
y=baseY;
txt.DrawString(x,y,"TalkList",255,255,255,255,plDebugText::kStyleBold);
y+=yOff;
for(i=0;i<GetTalkList()->GetNumMembers();i++)
{
sprintf(str, "name=%s", GetTalkList()->GetMember(i)->AsStdString().c_str());
txt.DrawString(x,y,str);
y+=yOff;
}
}
//
// show lists of members, listenList, and talkList
//
void plNetClientMgr::IShowRooms()
{
plDebugText &txt = plDebugText::Instance();
int y,x;
const int yOff=10, xOff=300, startY=70, startX=10;
char str[256];
// OWNEDLIST
x=startX;
y=startY;
txt.DrawString(x,y,"RoomsOwned",255,255,255,255,plDebugText::kStyleBold);
y+=yOff;
std::set<plNetClientGroups::OwnedGroup>::iterator it=GetNetGroups()->fGroups.begin();
for(;it != GetNetGroups()->fGroups.end(); it++)
{
if ((*it).fOwnIt)
{
sprintf(str, "%s", (*it).fGroup.GetDesc());
txt.DrawString(x,y,str);
y+=yOff;
}
}
// NOTOWNEDLIST
x+=xOff;
y=startY;
txt.DrawString(x,y,"RoomsNotOwned",255,255,255,255,plDebugText::kStyleBold);
y+=yOff;
it=GetNetGroups()->fGroups.begin();
for(;it != GetNetGroups()->fGroups.end(); it++)
{
if (!(*it).fOwnIt)
{
sprintf(str, "%s", (*it).fGroup.GetDesc());
txt.DrawString(x,y,str);
y+=yOff;
}
}
}
UInt32 IPrintRelRegion(const hsBitVector& region, int x, int y, const hsBitVector* cmpRegion)
{
char buf[256];
int maxBits = 255;
UInt32 num = plRelevanceMgr::Instance()->GetNumRegions();
if (num > maxBits)
num = maxBits;
bool orTrue = false;
int i;
for (i = 0; i < num; i++)
{
buf[i] = (region.IsBitSet(i) ? '1' : '0');
if (cmpRegion && cmpRegion->IsBitSet(i) && region.IsBitSet(i))
orTrue = true;
}
buf[i] = '\0';
plDebugText& txt = plDebugText::Instance() ;
if (orTrue)
txt.DrawString(x, y, buf, 0, 255, 0);
else
txt.DrawString(x, y, buf);
return txt.CalcStringWidth(buf);
}
void plNetClientMgr::IShowRelevanceRegions()
{
plDebugText& txt = plDebugText::Instance();
const int yOff = 12, xOff = 20, startY=70, startX=10;
int x = startX, y = startY;
const char* title = "Name / In / Care";
txt.DrawString(x, y - yOff, title, 255, 255, 255, 255, plDebugText::kStyleBold);
plNetTransportMember** members = nil;
fTransport.GetMemberListDistSorted(members);
//
// Print out the player names in the first column
//
UInt32 maxPlayerName = 0;
txt.DrawString(x, y, GetPlayerName());
maxPlayerName = hsMaximum(maxPlayerName, txt.CalcStringWidth(GetPlayerName()));
y += yOff;
int i;
for (i = 0; i < fTransport.GetNumMembers(); i++)
{
plNetTransportMember* mbr = members[i];
hsAssert(mbr, "ShowLists: nil member?");
if (mbr->IsServer())
continue;
const char* name = mbr->GetPlayerName();
txt.DrawString(x, y, name);
maxPlayerName = hsMaximum(maxPlayerName, txt.CalcStringWidth(name));
y += yOff;
}
x = startX + maxPlayerName + xOff;
y = startY;
//
// Print out the regions
//
const hsBitVector* ourCare = nil;
const hsBitVector* ourIn = nil;
plSceneObject* player = plSceneObject::ConvertNoRef(GetLocalPlayer());
if (player)
{
const plArmatureMod *avMod = plArmatureMod::ConvertNoRef(player->GetModifierByType(plArmatureMod::Index()));
if (avMod)
{
ourIn = &avMod->GetRelRegionImIn();
UInt32 width = IPrintRelRegion(*ourIn, x, y, nil);
ourCare = &avMod->GetRelRegionCareAbout();
IPrintRelRegion(*ourCare, x + width + xOff, y, nil);
y += yOff;
}
}
for (i = 0; i < fTransport.GetNumMembers(); i++)
{
plNetTransportMember* mbr = members[i];
if (mbr->IsServer())
continue;
player = (mbr->GetAvatarKey() ? plSceneObject::ConvertNoRef(mbr->GetAvatarKey()->ObjectIsLoaded()) : nil);
if (player)
{
const plArmatureMod* avMod = plArmatureMod::ConvertNoRef(player->GetModifierByType(plArmatureMod::Index()));
if (avMod)
{
const hsBitVector& in = avMod->GetRelRegionImIn();
UInt32 width = IPrintRelRegion(in, x, y, ourCare);
const hsBitVector& care = avMod->GetRelRegionCareAbout();
IPrintRelRegion(care, x + width + xOff, y, ourIn);
y += yOff;
}
}
}
delete [] members;
}
void plNetClientMgr::IShowAvatars()
{
plDebugText &txt = plDebugText::Instance();
txt.SetFont( "Courier New", 6 );
int y,x,i;
const int yOff=10, xOff=285, startY=100, startX=10;
char str[256];
// Me
x=startX;
y=startY-yOff*3;
plSceneObject *player = plSceneObject::ConvertNoRef(GetLocalPlayer());
hsPoint3 pos = (player ? player->GetLocalToWorld() * hsPoint3(0, 0, 0) : hsPoint3(0, 0, 0));
hsVector3 ori = (player ? player->GetLocalToWorld() * hsVector3(0, -1, 0) : hsVector3(0, 0, 0));
sprintf(str, "%s: pos(%.2f, %.2f, %.2f) ori(%.2f, %.2f, %.2f)",
GetPlayerName(), pos.fX, pos.fY, pos.fZ, ori.fX, ori.fY, ori.fZ);
txt.DrawString(x,y,str,255,255,255,255);
if (player)
{
const plArmatureMod *avMod = plArmatureMod::ConvertNoRef(player->GetModifierByType(plArmatureMod::Index()));
if (avMod)
{
plArmatureMod* pNonConstArm = const_cast<plArmatureMod*>(avMod);
plSceneObject* pObj = pNonConstArm->GetFollowerParticleSystemSO();
if (pObj)
{
y+=yOff;
y+=yOff;
hsPoint3 pos = (pObj ? pObj->GetLocalToWorld() * hsPoint3(0, 0, 0) : hsPoint3(0, 0, 0));
hsVector3 ori = (pObj ? pObj->GetLocalToWorld() * hsVector3(0, -1, 0) : hsVector3(0, 0, 0));
sprintf(str, "%s: pos(%.2f, %.2f, %.2f) ori(%.2f, %.2f, %.2f)",
pObj->GetKeyName(), pos.fX, pos.fY, pos.fZ, ori.fX, ori.fY, ori.fZ);
txt.DrawString(x,y,str,255,255,255,255);
}
}
}
// Others
y=startY;
x=startX;
plNetTransportMember** members=nil;
fTransport.GetMemberListDistSorted(members);
for(i=0;i<fTransport.GetNumMembers();i++)
{
plNetTransportMember* mbr=members[i];
hsAssert(mbr, "ShowLists: nil member?");
if (mbr->IsServer())
continue;
player = (mbr->GetAvatarKey() ? plSceneObject::ConvertNoRef(mbr->GetAvatarKey()->ObjectIsLoaded()) : nil);
pos = (player ? player->GetLocalToWorld() * hsPoint3(0, 0, 0) : hsPoint3(0, 0, 0));
ori = (player ? player->GetLocalToWorld() * hsVector3(0, -1, 0) : hsVector3(0, 0, 0));
sprintf(str, "%s: pos(%.2f, %.2f, %.2f) ori(%.2f, %.2f, %.2f)",
mbr->AsStdString().c_str(), pos.fX, pos.fY, pos.fZ, ori.fX, ori.fY, ori.fZ);
txt.DrawString(x,y,str);
y+=yOff;
if (player)
{
const plArmatureMod *avMod = plArmatureMod::ConvertNoRef(player->GetModifierByType(plArmatureMod::Index()));
if (avMod)
{
plArmatureMod* pNonConstArm = const_cast<plArmatureMod*>(avMod);
plSceneObject* pObj = pNonConstArm->GetFollowerParticleSystemSO();
if (pObj)
{
y+=yOff;
y+=yOff;
hsPoint3 pos = (pObj ? pObj->GetLocalToWorld() * hsPoint3(0, 0, 0) : hsPoint3(0, 0, 0));
hsVector3 ori = (pObj ? pObj->GetLocalToWorld() * hsVector3(0, -1, 0) : hsVector3(0, 0, 0));
sprintf(str, "%s: pos(%.2f, %.2f, %.2f) ori(%.2f, %.2f, %.2f)",
pObj->GetKeyName(), pos.fX, pos.fY, pos.fZ, ori.fX, ori.fY, ori.fZ);
txt.DrawString(x,y,str,255,255,255,255);
}
}
}
}
delete [] members;
txt.SetFont( "Courier New", 8 );
}

View File

@ -0,0 +1,41 @@
/*==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==*/

View File

@ -0,0 +1,41 @@
/*==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==*/

View File

@ -0,0 +1,410 @@
/*==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 <algorithm>
#include "hsMatrix44.h"
#include "hsGeometry3.h"
#include "plNetClientMgr.h"
#include "../plNetMessage/plNetMessage.h"
#include "../pnNetCommon/plNetServers.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnKeyedObject/plKey.h"
#include "../plNetTransport/plNetTransportMember.h"
#include "../plMessage/plMemberUpdateMsg.h"
#include "../plMessage/plNetVoiceListMsg.h"
#include "../plStatusLog/plStatusLog.h"
#include "../plVault/plVault.h"
#define SAME_TALK_AND_LISTEN
struct DistSqInfo
{
plNetTransportMember* fMbr;
float fDistSq;
DistSqInfo(plNetTransportMember* m, float d) : fMbr(m),fDistSq(d) {}
};
bool lessComp(DistSqInfo a, DistSqInfo b)
{
return (a.fDistSq<b.fDistSq);
}
//
// see if new listen list differs from current one
// apply new list if there's a difference
// send listenList update msgs to old and new members in the list
// return true if the new list is different
//
hsBool plNetClientMgr::IApplyNewListenList(std::vector<DistSqInfo>& newListenList, hsBool forceSynch)
{
hsBool changed=false;
int i;
// see if new listen list differs from current one
if (forceSynch || newListenList.size() != GetListenList()->GetNumMembers())
changed=true;
else
{
for(i=0;i<newListenList.size(); i++)
{
if (GetListenList()->FindMember(newListenList[i].fMbr)==-1)
{
changed=true;
break;
}
}
}
// set as new listen list
if (changed)
{
DebugMsg("ListenList changed, forceSynch=%d\n", forceSynch);
plNetMsgListenListUpdate llu;
llu.SetPlayerID(GetPlayerID());
llu.SetNetProtocol(kNetProtocolCli2Game);
//
// for each client in the old list, if not in the new list, send a ListenList remove msg
//
llu.Receivers()->Clear();
llu.SetAdding(false);
for(i=0;i<GetListenList()->GetNumMembers(); i++)
{
hsBool found=false;
if (!forceSynch)
{
int j;
for(j=0;j<newListenList.size(); j++)
{
if (newListenList[j].fMbr==GetListenList()->GetMember(i))
{
found=true;
break;
}
}
}
if (found==false)
{
llu.Receivers()->AddReceiverPlayerID(GetListenList()->GetMember(i)->GetPlayerID());
}
}
#ifndef SAME_TALK_AND_LISTEN
if (llu.Receivers()->GetNumReceivers())
{
// DEBUGGING
int i;
for(i=0;i<llu.Receivers()->GetNumReceivers(); i++)
{
int idx=fTransport.FindMember(llu.Receivers()->GetReceiverClientNum(i));
plNetTransportMember* mbr=fTransport.GetMember(idx);
DebugMsg("<SEND %s> ListenListUpdate msg, adding=%d\n",
mbr->AsStdString().c_str(), llu.GetAdding());
}
SendMsg(&llu);
}
#endif
//
// for each client in the new list, [if not in the old list,] send a ListenList add msg
//
llu.Receivers()->Clear();
llu.SetAdding(true);
for(i=0;i<newListenList.size(); i++)
{
if (forceSynch || GetListenList()->FindMember(newListenList[i].fMbr)==-1)
{
// if not in the old list, send a ListenList add msg
llu.Receivers()->AddReceiverPlayerID(newListenList[i].fMbr->GetPlayerID());
}
}
#ifndef SAME_TALK_AND_LISTEN
if (llu.Receivers()->GetNumReceivers())
{
// DEBUGGING
int i;
for(i=0;i<llu.Receivers()->GetNumReceivers(); i++)
{
int cNum=llu.Receivers()->GetReceiverClientNum(i);
int idx=fTransport.FindMember(cNum);
plNetTransportMember* mbr=fTransport.GetMember(idx);
DebugMsg("<SEND %s> ListenListUpdate msg, adding=%d, cNum=%d\n",
mbr->AsStdString().c_str(), llu.GetAdding(), cNum);
}
SendMsg(&llu);
}
#endif
//
// set as new listen list
//
GetListenList()->Clear();
#ifdef HS_DEBUGGING
DebugMsg("New ListenList, size=%d\n", newListenList.size());
#endif
for(i=0;i<newListenList.size(); i++)
{
GetListenList()->AddMember(newListenList[i].fMbr);
#ifdef HS_DEBUGGING
DebugMsg("\tLL Member %d, name=%s, cNum=%d, dist=%f\n",
i, newListenList[i].fMbr->AsStdString().c_str(),
newListenList[i].fMbr->GetPlayerID(), newListenList[i].fDistSq);
#endif
}
}
return changed;
}
//
// Periodically updates the list of what remote players I'm listening to.
// Used to filter voice streams.
// Returns true if the listenList was changed.
// Note: Updates distSq to each member. Other things rely on this so we must do it even if p2p is disabled.
//
hsBool plNetClientMgr::IUpdateListenList(double secs)
{
if (GetFlagsBit(kDisabled))
return false;
if (!fLocalPlayerKey || !fLocalPlayerKey->ObjectIsLoaded())
return false;
hsBool changed = false;
if (secs - GetListenList()->GetLastUpdateTime()>plNetListenList::kUpdateInterval)
{
GetListenList()->SetLastUpdateTime(secs);
std::vector<DistSqInfo> newListenList;
switch (fListenListMode)
{
case kListenList_Forced:
{
#ifdef SAME_TALK_AND_LISTEN
SynchTalkList();
#endif
}
return true;
case kListenList_Distance:
{
// Finds the 3 closest players to our local player
// Search is unoptimized for now...
// compute our players pos
plSceneObject* locPlayer = plSceneObject::ConvertNoRef(fLocalPlayerKey->ObjectIsLoaded());
hsAssert(locPlayer, "local player is not a sceneObject?");
hsAssert(locPlayer->GetCoordinateInterface(), "locPlayer has no coordInterface");
hsMatrix44 l2w=locPlayer->GetCoordinateInterface()->GetLocalToWorld();
hsPoint3 locPlayerPos=l2w.GetTranslate();
int i;
for(i=0;i<fTransport.GetNumMembers();i++)
{
fTransport.GetMember(i)->SetDistSq(hsScalarMax);
if (fTransport.GetMember(i)->IsServer())
continue;
if(VaultAmIgnoringPlayer(fTransport.GetMember(i)->GetPlayerID()))
{
continue;
}
plKey k=fTransport.GetMember(i)->GetAvatarKey();
#if 0
if (!k)
{
DebugMsg("UpdateListenList: Nil avatar key on member %s\n",
fTransport.GetMember(i)->AsStdString().c_str());
}
#endif
plSceneObject* obj=plSceneObject::ConvertNoRef(k ? k->ObjectIsLoaded() : nil);
if (obj && obj->GetCoordinateInterface())
{
#if 1
// compute distSq to me
l2w=obj->GetCoordinateInterface()->GetLocalToWorld();
hsPoint3 pos=l2w.GetTranslate();
float distSq = hsVector3(&pos, &locPlayerPos).MagnitudeSquared();
fTransport.GetMember(i)->SetDistSq(distSq);
// I can't listen to players that are more than 50 ft away
if (distSq>plNetListenList::kMaxListenDistSq)
continue;
// if we are p2p and member isn't, skip them.
if ( IsPeerToPeer() && !fTransport.GetMember(i)->IsPeerToPeer() )
continue;
// otherwise, we aren't p2p so just update the listen list
// normally so it will update in the gui as distance changes.
#else
float distSq=1;
#endif
// if we have < 3 elements in the list, grow the list, or,
// if obj is closer than item 3, add it to the list.
// keep the list (3) elements sorted.
if (plNetListenList::kMaxListenListSize==-1 ||
newListenList.size()<plNetListenList::kMaxListenListSize ||
(distSq<newListenList[plNetListenList::kMaxListenListSize-1].fDistSq) )
{
DistSqInfo dsi(fTransport.GetMember(i), distSq);
if (plNetListenList::kMaxListenListSize==-1 ||
newListenList.size()<plNetListenList::kMaxListenListSize)
{
newListenList.push_back(dsi);
}
else
{
newListenList[plNetListenList::kMaxListenListSize-1]=dsi;
}
if (plNetListenList::kMaxListenListSize!=-1) // don't need to sort every time in this case
{
std::sort(newListenList.begin(), newListenList.end(), lessComp);
}
}
}
if (plNetListenList::kMaxListenListSize==-1 && newListenList.size())
{
std::sort(newListenList.begin(), newListenList.end(), lessComp);
}
}
}
break;
default:
break;
}
hsAssert(plNetListenList::kMaxListenListSize==-1 || newListenList.size()<=plNetListenList::kMaxListenListSize,
"illegal new listenlist size");
changed = IApplyNewListenList(newListenList,
#ifdef SAME_TALK_AND_LISTEN
false
#else
GetListenList()->CheckForceSynch()
#endif
);
}
// update talkList based on listenList
if (changed)
{
#ifdef SAME_TALK_AND_LISTEN
SynchTalkList();
#endif
// notify KI, member distances have been updated
plMemberUpdateMsg* mu = TRACKED_NEW plMemberUpdateMsg;
mu->Send();
}
return changed;
}
void plNetClientMgr::SynchTalkList()
{
GetTalkList()->Clear();
int i;
for(i=0;i<GetListenList()->GetNumMembers(); i++)
GetTalkList()->AddMember(GetListenList()->GetMember(i));
}
void plNetClientMgr::SetListenListMode(int i)
{
// set new mode, clear list and force update
fListenListMode = i;
GetListenList()->Clear();
GetListenList()->SetLastUpdateTime(0.f);
}
void plNetClientMgr::IHandleNetVoiceListMsg(plNetVoiceListMsg* msg)
{
if (msg->GetCmd() == plNetVoiceListMsg::kForcedListenerMode)
{
// first make sure this message applies to us:
int i;
bool included = false;
for (i = 0; i < msg->GetClientList()->Count(); i++)
{
if (msg->GetClientList()->AcquireArray()[i] == NetCommGetPlayer()->playerInt)
{
included = true;
break;
}
}
if (!included)
return;
SetListenListMode(kListenList_Forced);
// add in the members we receive from python
for (i = 0; i < msg->GetClientList()->Count(); i++)
{
plNetTransportMember **members = nil;
plNetClientMgr::GetInstance()->TransportMgr().GetMemberListDistSorted( members );
if( members != nil)
{
for(int j= 0; j < plNetClientMgr::GetInstance()->TransportMgr().GetNumMembers(); j++ )
{
plNetTransportMember *mbr = members[ j ];
if( mbr != nil && mbr->GetAvatarKey() != nil && mbr->GetPlayerID() == msg->GetClientList()->AcquireArray()[i])
{
plNetClientMgr::GetInstance()->GetListenList()->AddMember(mbr);
}
}
}
delete [] members;
}
}
else
if (msg->GetCmd() == plNetVoiceListMsg::kDistanceMode)
{
// again, see that it is us that we care about:
if (msg->GetRemovedKey() == GetLocalPlayerKey())
SetListenListMode(kListenList_Distance);
}
}

View File

@ -0,0 +1,609 @@
/*==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 "hsTimer.h"
#include "plNetClientMgr.h"
#include "plNetClientMsgHandler.h"
#include "hsResMgr.h"
#include "plCreatableIndex.h"
#include "plgDispatch.h"
#include "plNetLinkingMgr.h"
#include "plCCRMgrBase.h"
#include "../pnKeyedObject/plKey.h"
#include "../pnKeyedObject/plFixedKey.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plObjInterface.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnMessage/plObjRefMsg.h"
#include "../pnMessage/plNodeRefMsg.h"
#include "../pnMessage/plClientMsg.h"
//#include "../pnMessage/plWarpMsg.h"
#include "../pnMessage/plTimeMsg.h"
#include "../pnMessage/plCameraMsg.h"
#include "../pnMessage/plPlayerPageMsg.h"
#include "../pnFactory/plCreator.h"
#include "../pnSceneObject/plAudioInterface.h"
#include "../pnNetCommon/plSDLTypes.h"
#include "../plAudible/plWinAudible.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plNetTransport/plNetTransportMember.h"
#include "../plMessage/plMemberUpdateMsg.h"
#include "../plMessage/plNetOwnershipMsg.h"
#include "../plMessage/plCCRMsg.h"
#include "../plVault/plVault.h"
#include "../plSDL/plSDL.h"
#include "../plNetCommon/plNetCommonConstants.h"
#include "../plNetMessage/plNetMessage.h"
#include "../plNetMessage/plNetCommonMessage.h"
#include "../../FeatureLib/pfMessage/pfKIMsg.h" // Should be moved to PubUtil level
////////////////////////////////////////////////////////////////////////
plNetClientMsgHandler::plNetClientMsgHandler(plNetClientMgr * mgr)
{
SetNetApp(mgr);
}
plNetClientMsgHandler::~plNetClientMsgHandler()
{
}
plNetClientMgr * plNetClientMsgHandler::IGetNetClientMgr()
{
return plNetClientMgr::ConvertNoRef(GetNetApp());
}
int plNetClientMsgHandler::PeekMsg(plNetMessage * netMsg)
{
plNetClientMgr * nc = IGetNetClientMgr();
int cnt = -1;
if (netMsg->GetNetCoreMsg()) // && !netMsg->Peeked()) // not needed
{
cnt = netMsg->PeekBuffer(netMsg->GetNetCoreMsg()->GetData(), netMsg->GetNetCoreMsg()->GetLen());
hsAssert(cnt,"0 length message");
}
return cnt;
}
void plNetClientMsgHandler::IFillInTransportMember(const plNetMsgMemberInfoHelper* mbi, plNetTransportMember* mbr)
{
const plNetClientMgr* nc=IGetNetClientMgr();
UInt16 port = mbi->GetClientGuid()->GetSrcPort();
UInt32 addr = mbi->GetClientGuid()->GetSrcAddr();
UInt32 flags = mbi->GetFlags();
UInt32 plrID = mbi->GetClientGuid()->GetPlayerID();
plUoid avUoid = mbi->GetAvatarUoid();
plKey avKey=hsgResMgr::ResMgr()->FindKey(avUoid);
mbr->SetPlayerName(mbi->GetClientGuid()->GetPlayerName());
mbr->SetFlags(flags);
mbr->SetPlayerID(plrID);
mbr->SetCCRLevel(mbi->GetClientGuid()->GetCCRLevel());
if (avKey)
mbr->SetAvatarKey(avKey);
}
int plNetClientMsgHandler::ReceiveMsg(plNetMessage *& netMsg)
{
#ifdef HS_DEBUGGING
//plNetClientMgr::GetInstance()->DebugMsg("<RCV> %s", netMsg->ClassName());
#endif
plNetClientMgr::GetInstance()->UpdateServerTimeOffset(netMsg);
switch(netMsg->ClassIndex())
{
default:
plNetClientMgr::GetInstance()->ErrorMsg( "Unknown msg: %s", netMsg->ClassName() );
return hsFail;
MSG_HANDLER_CASE(plNetMsgTerminated)
MSG_HANDLER_CASE(plNetMsgGroupOwner)
case CLASS_INDEX_SCOPED(plNetMsgSDLStateBCast):
MSG_HANDLER_CASE(plNetMsgSDLState)
case CLASS_INDEX_SCOPED(plNetMsgGameMessageDirected):
case CLASS_INDEX_SCOPED(plNetMsgLoadClone):
MSG_HANDLER_CASE(plNetMsgGameMessage)
MSG_HANDLER_CASE(plNetMsgVoice)
MSG_HANDLER_CASE(plNetMsgMembersList)
MSG_HANDLER_CASE(plNetMsgMemberUpdate)
MSG_HANDLER_CASE(plNetMsgListenListUpdate)
MSG_HANDLER_CASE(plNetMsgInitialAgeStateSent)
}
}
////////////////////////////////////////////////////////////////////
MSG_HANDLER_DEFN(plNetClientMsgHandler,plNetMsgTerminated)
{
return hsOK;
}
MSG_HANDLER_DEFN(plNetClientMsgHandler,plNetMsgGroupOwner)
{
plNetClientMgr* nc = IGetNetClientMgr();
plNetMsgGroupOwner* m = plNetMsgGroupOwner::ConvertNoRef(netMsg);
PeekMsg(m);
/* !!! THIS LOG MSG CRASHES THE CLIENT SOMETIMES! -eap
hsLogEntry( nc->DebugMsg("<RCV> %s, %s, sz=%d",
m->ClassName(), m->AsStdString().c_str(), m->GetNetCoreMsgLen()) );
*/
/*
plNetOwnershipMsg* netOwnMsg = TRACKED_NEW plNetOwnershipMsg;
int i;
for(i=0;i<m->GetNumGroups();i++)
{
plNetMsgGroupOwner::GroupInfo gr=m->GetGroupInfo(i);
netOwnMsg->AddGroupInfo(gr);
nc->GetNetGroups()->SetGroup(gr.fGroupID, gr.fOwnIt!=0 ? true : false);
hsLogEntry( nc->DebugMsg("\tGroup 0x%x, ownIt=%d\n", (const char*)gr.fGroupID.Room().GetSequenceNumber(), gr.fOwnIt) );
}
if (netOwnMsg->GetNumGroups())
netOwnMsg->Send();
else
delete netOwnMsg;
*/
nc->SetObjectOwner(m->IsOwner());
return hsOK;
}
MSG_HANDLER_DEFN(plNetClientMsgHandler,plNetMsgSDLState)
{
plNetClientMgr* nc = IGetNetClientMgr();
plNetMsgSDLState* m = plNetMsgSDLState::ConvertNoRef(netMsg);
PeekMsg(m);
/* !!! THIS LOG MSG CRASHES THE CLIENT SOMETIMES! -eap
hsLogEntry( nc->DebugMsg("<RCV> %s, %s, sz=%d",
m->ClassName(), m->AsStdString().c_str(), m->GetNetCoreMsgLen()) );
*/
UInt32 rwFlags = 0;
if ( m->IsInitialState() )
{
nc->IncNumInitialSDLStates();
rwFlags |= plSDL::kMakeDirty; // if initial state, we want all vars.
}
else if ( nc->GetFlagsBit( plNetClientApp::kLoadingInitialAgeState ) )
{
if ( nc->GetFlagsBit( plNetClientApp::kNeedInitialAgeStateCount ) )
{
hsLogEntry( nc->DebugMsg( "Ignoring SDL state because we are still joining age and don't have initial age state count yet." ) );
return hsOK;
}
if ( nc->GetNumInitialSDLStates()<nc->GetRequiredNumInitialSDLStates() )
{
hsLogEntry( nc->DebugMsg( "Ignoring SDL state because we are still joining age and have not received all initial state yet." ) );
return hsOK;
}
hsLogEntry( nc->DebugMsg( "We are still joining age, but have all initial states. Accepting this state (risky?)." ) );
}
// extract stateDataRecord from msg
hsReadOnlyStream stream(m->StreamInfo()->GetStreamLen(), m->StreamInfo()->GetStreamBuf());
char* descName = nil;
int ver;
plStateDataRecord::ReadStreamHeader(&stream, &descName, &ver);
plStateDescriptor* des = plSDLMgr::GetInstance()->FindDescriptor(descName, ver);
if (strcmpi(descName, kSDLAvatarPhysical) == 0)
rwFlags |= plSDL::kKeepDirty;
//
// ERROR CHECK SDL FILE
//
plStateDataRecord* sdRec = des ? TRACKED_NEW plStateDataRecord(des) : nil;
if (!sdRec || sdRec->GetDescriptor()->GetVersion()!=ver)
{
std::string err;
if (!sdRec)
err = xtl::format( "SDL descriptor %s missing, v=%d", descName, ver);
else
err = xtl::format( "SDL descriptor %s, version mismatch, server v=%d, client v=%d",
descName, ver, sdRec->GetDescriptor()->GetVersion());
hsAssert(false, err.c_str());
nc->ErrorMsg(const_cast<char*>(err.c_str()));
// Post Quit message
nc->QueueDisableNet(true, "SDL Desc Problem");
delete sdRec;
}
else if( sdRec->Read( &stream, 0, rwFlags ) )
{
plStateDataRecord* stateRec = nil;
if (m->IsInitialState())
{
stateRec = TRACKED_NEW plStateDataRecord(des);
stateRec->SetFromDefaults(false);
stateRec->UpdateFrom(*sdRec, rwFlags);
delete sdRec;
}
else
stateRec = sdRec;
plNetClientMgr::PendingLoad* pl = TRACKED_NEW plNetClientMgr::PendingLoad();
pl->fSDRec = stateRec; // will be deleted when PendingLoad is processed
if (m->GetHasPlayerID())
pl->fPlayerID = m->GetPlayerID(); // copy originating playerID if we have it
pl->fUoid = m->ObjectInfo()->GetUoid();
// queue up state
nc->fPendingLoads.push_back(pl);
hsLogEntry( nc->DebugMsg( "Added pending SDL delivery for %s:%s", m->ObjectInfo()->GetObjectName(), des->GetName() ) );
}
else
delete sdRec;
delete [] descName; // We've only used descName for a lookup (via SDR, and some error strings. Must delete now.
return hsOK;
}
MSG_HANDLER_DEFN(plNetClientMsgHandler,plNetMsgGameMessage)
{
plNetClientMgr* nc = IGetNetClientMgr();
plNetMsgGameMessage* m = plNetMsgGameMessage::ConvertNoRef(netMsg);
if (m)
{
PeekMsg(m);
plNetMsgLoadClone * lcMsg = plNetMsgLoadClone::ConvertNoRef( m );
if ( lcMsg )
{
if ( lcMsg->GetIsInitialState() )
{
nc->IncNumInitialSDLStates();
}
}
hsReadOnlyStream stream(m->StreamInfo()->GetStreamLen(), m->StreamInfo()->GetStreamBuf());
plMessage* gameMsg = plMessage::ConvertNoRef(hsgResMgr::ResMgr()->ReadCreatable(&stream));
hsAssert(gameMsg, "nil game msg?");
if (gameMsg)
{
/* !!! THIS LOG MSG CRASHES THE CLIENT SOMETIMES!!! -eap
hsLogEntry( nc->DebugMsg("<RCV> %s, %s, sndr %s rcvr %s sz=%d",
m->ClassName(), m->AsStdString().c_str(),
gameMsg->GetSender() ? gameMsg->GetSender()->GetName() : "?",
gameMsg->GetNumReceivers() ? gameMsg->GetReceiver(0)->GetName() : "?",
m->GetNetCoreMsgLen()) );
*/
if (lcMsg)
{
if (!lcMsg->GetIsLoading())
{
plLoadAvatarMsg* unloadClone = plLoadAvatarMsg::ConvertNoRef(gameMsg);
if (unloadClone)
{
plLoadAvatarMsg* unloadMsg = TRACKED_NEW plLoadAvatarMsg(unloadClone->GetCloneKey(), unloadClone->GetRequestorKey(), unloadClone->GetUserData(), unloadClone->GetIsPlayer(), false);
unloadMsg->SetOriginatingPlayerID(unloadClone->GetOriginatingPlayerID());
gameMsg = unloadMsg;
}
}
else
{
plLoadCloneMsg* loadClone = plLoadCloneMsg::ConvertNoRef(gameMsg);
if (loadClone)
{
int idx = nc->fTransport.FindMember(loadClone->GetOriginatingPlayerID());
if (idx == -1)
{
hsLogEntry( nc->DebugMsg( "Ignoring load clone because player isn't in our players list: %d", loadClone->GetOriginatingPlayerID()) );
return hsOK;
}
}
}
}
plNetClientApp::UnInheritNetMsgFlags(gameMsg);
gameMsg->SetBCastFlag(plMessage::kNetCreatedRemotely);
if (!m->GetDeliveryTime().AtEpoch())
{
double timeStamp;
double secs=hsTimer::GetSysSeconds();
m->GetDeliveryTime().ConvertToGameTime(&timeStamp, secs);
hsAssert(timeStamp>=secs, "invalid future timeStamp");
gameMsg->SetTimeStamp(timeStamp);
nc->DebugMsg("Converting game msg future timeStamp, curT=%f, futT=%f", secs, timeStamp);
}
plgDispatch::Dispatch()->MsgSend(gameMsg);
// Debug
if (m->GetHasPlayerID())
{
int idx=nc->fTransport.FindMember(m->GetPlayerID());
plNetTransportMember* mbr = idx != -1 ? nc->fTransport.GetMember(idx) : nil;
if (mbr)
mbr->SetTransportFlags(mbr->GetTransportFlags() | plNetTransportMember::kSendingActions);
}
return hsOK;
}
}
return hsFail;
}
MSG_HANDLER_DEFN(plNetClientMsgHandler,plNetMsgVoice)
{
plNetClientMgr* nc = IGetNetClientMgr();
plNetMsgVoice* m = plNetMsgVoice::ConvertNoRef(netMsg);
PeekMsg(m);
/* !!! THIS LOG MSG CRASHES THE CLIENT SOMETIMES! -eap
hsLogEntry( nc->DebugMsg("<RCV> %s, %s, sz=%d",
m->ClassName(), m->AsStdString().c_str(), m->GetNetCoreMsgLen()) );
*/
int bufLen = m->GetVoiceDataLen();
const char* buf = m->GetVoiceData();
BYTE flags = m->GetFlags();
BYTE numFrames = m->GetNumFrames();
plKey key = NULL;
// plKey key=hsgResMgr::ResMgr()->FindKey(m->ObjectInfo()->GetUoid());
// Filter ignored sender
if ( VaultAmIgnoringPlayer( m->GetPlayerID() ) )
{
hsLogEntry( nc->DebugMsg( "Ignoring voice chat from ignored player %lu", m->GetPlayerID() ) );
return hsOK;
}
int idx=nc->fTransport.FindMember(m->GetPlayerID());
plNetTransportMember* mbr = idx != -1 ? nc->fTransport.GetMember(idx) : nil;
if (mbr)
{
key = mbr->GetAvatarKey();
// filter based on listen/talk list (for forced mode)
if (nc->GetListenListMode() == plNetClientMgr::kListenList_Forced)
{
if (nc->GetListenList()->FindMember( mbr ))
{
hsLogEntry( nc->DebugMsg( "Ignoring voice chat from ignored player %lu", m->GetPlayerID() ) );
return hsOK;
}
}
mbr->SetTransportFlags(mbr->GetTransportFlags() | plNetTransportMember::kSendingVoice);
}
// hsKeyedObject* obj = key ? key->ObjectIsLoaded() : nil;
plSceneObject* avObj = key ? plSceneObject::ConvertNoRef( key->ObjectIsLoaded() ) : nil;
// if (obj)
if (avObj)
{
plAudible * aud = avObj->GetAudioInterface()->GetAudible();
pl2WayWinAudible* pAud = pl2WayWinAudible::ConvertNoRef(aud);
if (pAud)
pAud->PlayNetworkedSpeech(buf, bufLen, numFrames, flags);
else
{
nc->ErrorMsg("\tObject doesn't have audible");
}
}
else
{
nc->DebugMsg("\tCan't find loaded object\n");
}
return hsOK;
}
MSG_HANDLER_DEFN(plNetClientMsgHandler,plNetMsgMembersList)
{
plNetClientMgr* nc = IGetNetClientMgr();
plNetMsgMembersList* m = plNetMsgMembersList::ConvertNoRef(netMsg);
PeekMsg(m);
/* !!! THIS LOG MSG CRASHES THE CLIENT SOMETIMES! -eap
hsLogEntry( nc->DebugMsg("<RCV> %s, %s, sz=%d",
m->ClassName(), m->AsStdString().c_str(), m->GetNetCoreMsgLen()) );
*/
int i;
// remove existing members, except server
for( i=nc->fTransport.GetNumMembers()-1 ; i>=0; i-- )
{
if (!nc->fTransport.GetMember(i)->IsServer())
{
nc->fTransport.RemoveMember(i);
}
} // for
// update the members list from the msg.
// this app is not one of the members in the msg
for( i=0 ;i<m->MemberListInfo()->GetNumMembers() ;i++ )
{
plNetTransportMember* mbr = TRACKED_NEW plNetTransportMember(nc);
IFillInTransportMember(m->MemberListInfo()->GetMember(i), mbr);
hsLogEntry(nc->DebugMsg("\tAdding transport member, name=%s, p2p=%d, plrID=%d\n", mbr->AsStdString().c_str(), mbr->IsPeerToPeer(), mbr->GetPlayerID()));
int idx=nc->fTransport.AddMember(mbr);
hsAssert(idx>=0, "Failed adding member?");
} // for
// new player has been aded send local MembersUpdate msg
plMemberUpdateMsg* mu = TRACKED_NEW plMemberUpdateMsg;
mu->Send();
return hsOK;
}
MSG_HANDLER_DEFN(plNetClientMsgHandler,plNetMsgMemberUpdate)
{
plNetClientMgr* nc = IGetNetClientMgr();
plNetMsgMemberUpdate* m = plNetMsgMemberUpdate::ConvertNoRef(netMsg);
PeekMsg(m);
/* !!! THIS LOG MSG CRASHES THE CLIENT SOMETIMES! -eap
hsLogEntry( nc->DebugMsg("<RCV> %s, %s, sz=%d",
m->ClassName(), m->AsStdString().c_str(), m->GetNetCoreMsgLen()) );
*/
if (m->AddingMember())
{
plNetTransportMember* mbr=nil;
int idx = nc->fTransport.FindMember(m->MemberInfo()->GetClientGuid()->GetPlayerID());
if ( idx>=0 )
mbr = nc->fTransport.GetMember(idx);
else
mbr = TRACKED_NEW plNetTransportMember(nc);
hsAssert(mbr, "nil xport member");
IFillInTransportMember(m->MemberInfo(), mbr);
if ( idx<0 )
{ // didn't find him
if ( nc->fTransport.AddMember(mbr)<0 )
delete mbr; // delete newly created member
}
}
else
{
int idx=nc->fTransport.FindMember(m->MemberInfo()->GetClientGuid()->GetPlayerID());
if (idx<0)
{
hsLogEntry( nc->DebugMsg("\tCan't find member to remove.") );
}
else
{
nc->fTransport.RemoveMember(idx);
}
}
// new player has been aded send local MembersUpdate msg
plMemberUpdateMsg* mu = TRACKED_NEW plMemberUpdateMsg;
mu->Send();
return hsOK;
}
MSG_HANDLER_DEFN(plNetClientMsgHandler,plNetMsgListenListUpdate)
{
plNetClientMgr* nc = IGetNetClientMgr();
plNetMsgListenListUpdate* m = plNetMsgListenListUpdate::ConvertNoRef(netMsg);
PeekMsg(m);
/* !!! THIS LOG MSG CRASHES THE CLIENT SOMETIMES! -eap
hsLogEntry( nc->DebugMsg("<RCV> %s, %s, sz=%d",
m->ClassName(), m->AsStdString().c_str(), m->GetNetCoreMsgLen()) );
*/
int idx=nc->fTransport.FindMember(m->GetPlayerID());
plNetTransportMember* tm = (idx==-1 ? nil : nc->fTransport.GetMember(idx));
if(!tm)
{
#if 0
tm = TRACKED_NEW plNetTransportMember(nc);
tm->SetClientNum(m->GetSenderClientNum());
int idx=nc->fTransport.AddMember(tm);
hsAssert(idx>=0, "Failed adding member?");
nc->DebugMsg("ListenListUpdate msg: Adding member on the fly\n");
#endif
return hsOK;
}
if (m->GetAdding())
{
// add the sender to my talk list
nc->GetTalkList()->AddMember(tm);
}
else
{
// remove the sender from my talk list
nc->GetTalkList()->RemoveMember(tm);
}
return hsOK;
}
MSG_HANDLER_DEFN(plNetClientMsgHandler,plNetMsgInitialAgeStateSent)
{
plNetClientMgr * nc = IGetNetClientMgr();
plNetMsgInitialAgeStateSent* msg = plNetMsgInitialAgeStateSent::ConvertNoRef(netMsg);
PeekMsg(msg);
/* !!! THIS LOG MSG CRASHES THE CLIENT SOMETIMES! -eap
hsLogEntry( nc->DebugMsg("<RCV> %s, %s, sz=%d",
netMsg->ClassName(), netMsg->AsStdString().c_str(), netMsg->GetNetCoreMsgLen()) );
*/
nc->DebugMsg( "Initial age SDL count: %d", msg->GetNumInitialSDLStates( ) );
nc->SetRequiredNumInitialSDLStates( msg->GetNumInitialSDLStates() );
nc->SetFlagsBit( plNetClientApp::kNeedInitialAgeStateCount, false );
if (nc->GetNumInitialSDLStates() >= nc->GetRequiredNumInitialSDLStates()) {
nc->ICheckPendingStateLoad(hsTimer::GetSysSeconds());
nc->NotifyRcvdAllSDLStates();
}
return hsOK;
}
////////////////////////////////////////////////////////////////////
// End.

View File

@ -0,0 +1,88 @@
/*==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==*/
#ifndef plNetClientMsgHandler_inc
#define plNetClientMsgHandler_inc
#include "../plNetCommon/plNetMsgHandler.h"
#include "hsStlUtils.h"
///////////////////////////////////////////////////////////////////
//
// define msg handler fxn for netClient msgs
//
class plNetClientMgr;
class plNetMsgMemberInfoHelper;
class plNetTransportMember;
///////////////////////////////////////////////////////////////////
class plNetClientMsgHandler : public plNetMsgHandler
{
//protected:
enum // SendOrTimeOut return values and meanings
{
kTimedOutNoRetry = -1,
kDoNothing = 0,
kSend = 1,
};
plNetClientMgr * IGetNetClientMgr();
void IFillInTransportMember(const plNetMsgMemberInfoHelper* mbi, plNetTransportMember* mbr);
public:
plNetClientMsgHandler(plNetClientMgr * mgr);
~plNetClientMsgHandler();
int ReceiveMsg(plNetMessage *& netMsg);
int PeekMsg(plNetMessage * netMsg); // return msgsize on success. -1 on error.
MSG_HANDLER_DECL(plNetMsgTerminated)
MSG_HANDLER_DECL(plNetMsgGroupOwner)
MSG_HANDLER_DECL(plNetMsgSDLState)
MSG_HANDLER_DECL(plNetMsgGameMessage)
MSG_HANDLER_DECL(plNetMsgVoice)
MSG_HANDLER_DECL(plNetMsgMembersList)
MSG_HANDLER_DECL(plNetMsgMemberUpdate)
MSG_HANDLER_DECL(plNetMsgListenListUpdate)
MSG_HANDLER_DECL(plNetMsgInitialAgeStateSent)
};
#endif // plNetClientMsgHandler_inc

View File

@ -0,0 +1,125 @@
/*==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 "plNetClientMsgScreener.h"
#include "plNetLinkingMgr.h"
#include "../pnNetCommon/plNetApp.h"
#include "../pnMessage/plMessage.h"
#include "../plStatusLog/plStatusLog.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plArmatureMod.h"
///////////////////////////////////////////////////////////////
// CLIENT Version
///////////////////////////////////////////////////////////////
plNetClientMsgScreener::plNetClientMsgScreener()
{
DebugMsg("created");
}
//
// For plLoggable base
//
void plNetClientMsgScreener::ICreateStatusLog() const
{
fStatusLog = plStatusLogMgr::GetInstance().CreateStatusLog(40, "NetScreener.log",
plStatusLog::kTimestamp | plStatusLog::kFilledBackground | plStatusLog::kAlignToTop);
}
//
// return cur age name
//
const char* plNetClientMsgScreener::IGetAgeName() const
{
plNetLinkingMgr *lm = plNetLinkingMgr::GetInstance();
return lm && lm->GetAgeLink()->GetAgeInfo() ? lm->GetAgeLink()->GetAgeInfo()->GetAgeFilename() : "?";
}
//
// Check if key is local avatar
//
bool plNetClientMsgScreener::IIsLocalAvatarKey(plKey key, const plNetGameMember* gm) const
{
return (!key || key==plNetClientApp::GetInstance()->GetLocalPlayerKey());
}
bool plNetClientMsgScreener::IIsLocalArmatureModKey(plKey key, const plNetGameMember* gm) const
{
plKey playerKey = plNetClientApp::GetInstance()->GetLocalPlayerKey();
plArmatureMod* aMod = playerKey ? plAvatarMgr::GetInstance()->FindAvatar(playerKey) : nil;
return (!key || key==(aMod ? aMod->GetKey() : nil));
}
//
// Check if CCR
//
bool plNetClientMsgScreener::IIsSenderCCR(const plNetGameMember* gm) const
{
return plNetClientApp::GetInstance()->AmCCR();
}
//
// return true if msg is allowed/accepted as a net msg
//
bool plNetClientMsgScreener::AllowMessage(const plMessage* msg) const
{
if (!msg)
return false;
Answer ans=IAllowMessageType(msg->ClassIndex());
if (ans==kYes)
return true;
if (ans==kNo)
{
// WarningMsg("Quick-reject net propagated msg %s", msg->ClassName());
return false;
}
if (!IValidateMessage(msg))
{
// WarningMsg("Validation failed. Blocking net propagated msg %s", msg->ClassName());
return false;
}
return true;
}

View File

@ -0,0 +1,68 @@
/*==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==*/
#ifndef plNetClientMsgScreener_h
#define plNetClientMsgScreener_h
#include "../plNetCommon/plNetMsgScreener.h"
//
// Client-side version
//
class plNetClientMsgScreener : public plNetMsgScreener
{
protected:
void ICreateStatusLog() const;
const char* IGetSenderName(const plNetGameMember* gm) const { return "local"; }
const char* IGetAgeName() const;
bool IIsLocalAvatarKey(plKey key, const plNetGameMember* gm) const;
bool IIsLocalArmatureModKey(plKey key, const plNetGameMember* gm) const;
bool IIsSenderCCR(const plNetGameMember* gm=nil) const;
bool IAmClient() const { return true; }
public:
plNetClientMsgScreener();
bool AllowMessage(const plMessage* msg) const;
};
#endif // plNetClientMsgScreener_h

View File

@ -0,0 +1,107 @@
/*==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 "plNetClientStats.h"
#include "plNetClientMgr.h"
#include "hsTimer.h"
plNetClientStats::plNetClientStats() :
fNumVaultMsgsSent(0),
fNumVaultMsgsRcvd(0),
fVaultMsgSentBytes(0),
fVaultMsgRcvdBytes(0),
fAgeStatsULBits(0),
fAgeStatsDLBits(0),
fAgeStatsLinkInTime(0)
{
}
//
// return the avg UL bps used so far in this age
//
float plNetClientStats::GetAgeStatsULBitsPerSec() const
{
double elapsedAgeTime = hsTimer::GetSeconds() - fAgeStatsLinkInTime;
return (float)(fAgeStatsULBits/elapsedAgeTime);
}
//
// return the acks that were conpressed so far
//
UInt32 plNetClientStats::GetRecvdMultipleAcks() const
{
return fRecvdMultipleAcks;
}
//
// return the avg DL bps used so far in this age
//
float plNetClientStats::GetAgeStatsDLBitsPerSec() const
{
double elapsedAgeTime = hsTimer::GetSeconds() - fAgeStatsLinkInTime;
return (float)(fAgeStatsDLBits/elapsedAgeTime);
}
//
// Accumulate the UL/DL bits & acks used from the netCore state
//
void plNetClientStats::UpdateAgeStats()
{
plNetClientMgr* nc=plNetClientMgr::GetInstance();
#if 0
fAgeStatsDLBits += nc->GetNetCore()->GetStats()->GetDLBits();
fAgeStatsULBits += nc->GetNetCore()->GetStats()->GetULBits();
fRecvdMultipleAcks += nc->GetNetCore()->GetStats()->GetRecvdMultipleAcks();
#endif
}
//
// Call when you join an age
//
void plNetClientStats::ResetAgeStats()
{
fAgeStatsDLBits = fAgeStatsULBits = 0;
fRecvdMultipleAcks = 0;
fAgeStatsLinkInTime = hsTimer::GetSeconds();
}

View File

@ -0,0 +1,92 @@
/*==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==*/
#ifndef plNetClientStats_h
#define plNetClientStats_h
#include "hsTypes.h"
//
// Holds stats counters used by the Net Client
//
class plNetClientStats
{
public:
plNetClientStats();
//
// Vault Stats
//
private:
// Vault msg counters
UInt32 fNumVaultMsgsSent;
UInt32 fNumVaultMsgsRcvd;
UInt32 fVaultMsgSentBytes;
UInt32 fVaultMsgRcvdBytes;
public:
// msg counters
UInt32 GetNumVaultMsgsSent() const { return fNumVaultMsgsSent; }
UInt32 GetNumVaultMsgsRcvd() const { return fNumVaultMsgsRcvd; }
UInt32 GetVaultMsgSentBytes() const { return fVaultMsgSentBytes; }
UInt32 GetVaultMsgRcvdBytes() const { return fVaultMsgRcvdBytes; }
void TallyVaultMsgSent( int size ) { fNumVaultMsgsSent++; fVaultMsgSentBytes+=size; }
void TallyVaultMsgRcvd( int size ) { fNumVaultMsgsRcvd++; fVaultMsgRcvdBytes+=size; }
void ResetVaultMsgCounters() { fNumVaultMsgsSent=fNumVaultMsgsRcvd=fVaultMsgSentBytes=fVaultMsgRcvdBytes=0; }
//
// NetClient BW Stats, kept per age
//
private:
int fAgeStatsULBits, fAgeStatsDLBits;
UInt32 fRecvdMultipleAcks;
double fAgeStatsLinkInTime;
public:
void UpdateAgeStats();
void ResetAgeStats();
float GetAgeStatsULBitsPerSec() const;
float GetAgeStatsDLBitsPerSec() const;
UInt32 GetRecvdMultipleAcks() const;
};
#endif // plNetClientStats_h

View File

@ -0,0 +1,180 @@
/*==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 "plNetClientMgr.h"
#include "plNetClientVNodeMgr.h"
#include "../plNetMessage/plNetMessage.h"
#include "../plGImage/plMipmap.h"
#include "../plJPEG/plJPEG.h"
#include "../plVault/plVault.h"
#include "hsResMgr.h"
#include "../pnMessage/plRefMsg.h"
#include "../plVault/plDniCoordinateInfo.h"
#include "../plVault/plAgeInfoSource.h"
#include "plNetLinkingMgr.h"
#include "../plStatusLog/plStatusLog.h"
#include "../plClientState/plClientStateMgr.h"
#include "../plSDL/plSDL.h"
#include "../plAgeLoader/plAgeLoader.h"
#include "../../FeatureLib/pfMessage/pfKIMsg.h"
////////////////////////////////////////////////////////////////////
class plNetClientAgeInfoSource : public plAgeInfoSource
{
plDniCoordinateInfo fNilCoords; // TEMPORARY
public:
const plDniCoordinateInfo * GetAgeCoords( void ) const
{
return &fNilCoords; // tmp
}
const plUnifiedTime * GetAgeTime( void ) const
{
static plUnifiedTime ut;
ut.SetSecsDouble(plNetClientMgr::GetInstance()->GetCurrentAgeElapsedSeconds());
return &ut;
}
const char * GetAgeName( void ) const
{
return plNetLinkingMgr::GetInstance()->GetAgeLink()->GetAgeInfo()->GetAgeInstanceName();
}
const plUUID * GetAgeGuid( void ) const
{
return plNetLinkingMgr::GetInstance()->GetAgeLink()->GetAgeInfo()->GetAgeInstanceGuid();
}
static plNetClientAgeInfoSource * GetInstance( void )
{
static plNetClientAgeInfoSource Me;
return &Me;
}
};
//// Image/Mipmap Conversion //////////////////////////////////////////////////
hsBool StuffImageIntoNode( plMipmap * src, RelVaultNode * dst )
{
VaultImageNode image(dst);
hsRAMStream ramStream;
// Create our JPEG stream
plJPEG::Instance().SetWriteQuality( 30 ); // In percent quality
if( !plJPEG::Instance().WriteToStream( &ramStream, src ) )
return false;
unsigned bytes = ramStream.GetEOF();
byte * buffer = (byte *)ALLOC(bytes);
ramStream.CopyToMem(buffer);
image.SetImageData(buffer, bytes);
image.SetImageType( VaultImageNode::kJPEG );
// possibly make a plKey for the mipmap.
return ExtractImageFromNode( dst );
}
hsBool ExtractImageFromNode( RelVaultNode * src)
{
// no id? exit now. we will be called again when element is given an id.
if ( src->nodeId == 0 )
return false;
VaultCliImageNode image(src);
// already have a mipmap and it has a key? release it
if ( image.fMipmap && image.fMipmap->GetKey()!=nil )
{
plNetClientMgr::GetInstance()->GetKey()->Release( image.fMipmap->GetKey() );
image.fMipmap = nil;
}
// convert image data to a plMipmap
switch( image.imgType )
{
case VaultImageNode::kJPEG:
{
// Copy to a RAM stream so the JPEG class is happy
hsRAMStream ramStream;
ramStream.Write( image.imgDataLen, image.imgData );
ramStream.Rewind();
// create mipmap from image data
image.fMipmap = plJPEG::Instance().ReadFromStream( &ramStream );
}
break;
default:
{
hsAssert( false, "ExtractImageFromNode: Invalid image type" );
return false; // Invalid image type
}
}
if ( !image.fMipmap )
{
hsAssert( false, "ExtractImageFromNode failed" );
return false;
}
// we now have a mipmap, but it doesn't have a key. make a key for it
static int UniqueIdentifier = 0;
char keyName[512];
sprintf( keyName, "VaultImage_%lu_%d", src->nodeId, UniqueIdentifier++ );
// create a key for the mipmap
plKey imageKey = hsgResMgr::ResMgr()->NewKey( keyName, image.fMipmap, plLocation::kGlobalFixedLoc );
// ref the image key
hsgResMgr::ResMgr()->AddViaNotify( imageKey, TRACKED_NEW plGenRefMsg(
plNetClientMgr::GetInstance()->GetKey(), plRefMsg::kOnCreate, 0, plNetClientMgr::kVaultImage ),
plRefFlags::kActiveRef );
return ( image.fMipmap->GetKey()!=nil );
}
////////////////////////////////////////////////////////////////////
// End.

View File

@ -0,0 +1,250 @@
/*==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 "plNetClientMgr.h"
#include "plNetClientVault.h"
#include "../pnNetCommon/plNetMsg.h"
#include "../plGImage/plMipmap.h"
#include "../plJPEG/plJPEG.h"
#include "../plVault/plVaultTasks.h"
#include "hsResMgr.h"
#include "../pnMessage/plRefMsg.h"
#include "../plVault/plDniCoordinateInfo.h"
#include "../plVault/plAgeInfoSource.h"
////////////////////////////////////////////////////////////////////
class plNetClientAgeInfoSource : public plAgeInfoSource
{
plDniCoordinateInfo fNilCoords; // TEMPORARY
public:
const plDniCoordinateInfo * GetAgeCoords( void ) const
{
return &fNilCoords; // tmp
}
const plUnifiedTime * GetAgeTime( void ) const
{
static plUnifiedTime ut;
ut.SetSecsDouble(plNetClientMgr::GetInstance()->GetCurrentAgeElapsedSeconds());
return &ut;
}
const char * GetAgeName( void ) const
{
return plNetClientMgr::GetInstance()->GetAgeName();
}
const plServerGuid * GetAgeGuid( void ) const
{
return plNetClientMgr::GetInstance()->GetCurrSessionInfo()->GetServerGuid();
}
static plNetClientAgeInfoSource * GetInstance( void )
{
static plNetClientAgeInfoSource Me;
return &Me;
}
};
////////////////////////////////////////////////////////////////////
plNetClientVault::plNetClientVault()
{
}
plNetApp * plNetClientVault::GetNetApp( void ) const
{
return plNetClientMgr::GetInstance();
}
plAgeInfoSource * plNetClientVault::GetAgeInfo( void ) const
{
return plNetClientAgeInfoSource::GetInstance();
}
void plNetClientVault::IInitNode( plVaultNode * node )
{
plVaultImageNode * IMG = plVaultImageNode::ConvertNoRef( node );
if ( IMG )
{
plNetClientVault::ExtractImageFromNode( IMG );
}
}
void plNetClientVault::IFiniNode( plVaultNode * node )
{
plVaultImageNode * IMG = plVaultImageNode::ConvertNoRef( node );
if ( IMG && IMG->GetMipmap() )
{
plNetClientMgr::GetInstance()->GetKey()->Release( IMG->GetMipmap()->GetKey() );
IMG->ISetMipmap( nil );
}
}
int plNetClientVault::ISendNetMsg( plNetMsgVault * msg, UInt32 sendFlags )
{
return plNetClientMgr::GetInstance()->SendMsg( msg, sendFlags );
}
void plNetClientVault::IOnTaskTimedOut( plVaultTask * task )
{
std::string msg;
xtl::format( msg, "KI task timed out: %s", task->ClassName() );
plNetClientMgr::GetInstance()->OnNetFailure( msg.c_str(), true );
}
bool plNetClientVault::IAmOnline( void ) const
{
return plNetClientMgr::GetInstance()->IsEnabled()!=0;
}
//// Image/Mipmap Conversion //////////////////////////////////////////////////
hsBool plNetClientVault::StuffImageIntoNode( plMipmap * src, plVaultImageNode * dst )
{
hsRAMStream ramStream;
// Create our JPEG stream
plJPEG::Instance().SetWriteQuality( 50 ); // In percent quality
if( !plJPEG::Instance().WriteToStream( &ramStream, src ) )
return false;
// Copy the stream to the image element now
void * buffer = dst->AllocBuffer( ramStream.GetEOF() );
if( buffer == nil )
return false;
ramStream.CopyToMem( buffer );
dst->SetImageType( plVaultImageNode::kJPEG );
// possibly make a plKey for the mipmap.
return plNetClientVault::ExtractImageFromNode( dst );
}
hsBool plNetClientVault::ExtractImageFromNode( plVaultImageNode * src)
{
// no id? exit now. we will be called again when element is given an id.
if ( src->GetID()==0 )
return false;
// already have a mipmap and it has a key? release it
if ( src->GetMipmap() && src->GetMipmap()->GetKey()!=nil )
{
plNetClientMgr::GetInstance()->GetKey()->Release( src->GetMipmap()->GetKey() );
src->ISetMipmap( nil );
}
// convert image data to a plMipmap
switch( src->GetImageType() )
{
case plVaultImageNode::kJPEG:
{
// Copy to a RAM stream so the JPEG class is happy
hsRAMStream ramStream;
ramStream.Write( src->GetBufSize(), src->GetBuffer() );
ramStream.Rewind();
// create mipmap from image data
src->ISetMipmap( plJPEG::Instance().ReadFromStream( &ramStream ) );
}
break;
default:
{
hsAssert( false, "ExtractImageFromNode: Invalid image type" );
return false; // Invalid image type
}
}
if ( !src->GetMipmap() )
{
hsAssert( false, "ExtractImageFromNode failed" );
return false;
}
// we now have a mipmap, but it doesn't have a key. make a key for it
static int UniqueIdentifier = 0;
char keyName[512];
sprintf( keyName, "VaultImage_%lu_%d", src->GetID(), UniqueIdentifier++ );
// create a key for the mipmap
plKey imageKey = hsgResMgr::ResMgr()->NewKey( keyName, src->IGetMipmap(),
plLocation::kGlobalFixedLoc );
// ref the image key
hsgResMgr::ResMgr()->AddViaNotify( imageKey, new plGenRefMsg(
plNetClientMgr::GetInstance()->GetKey(), plRefMsg::kOnCreate, 0, 0 ),
plRefFlags::kActiveRef );
return ( src->GetMipmap()->GetKey()!=nil );
}
////////////////////////////////////////////////////////////////////
plNetPlayerVault::plNetPlayerVault()
{
}
bool plNetPlayerVault::IIsThisMe( plVaultPlayerInfoNode * node ) const
{
return GetPlayer()->GetPlayerInfo()->GetID()==node->GetID();
}
plVaultPlayerNode * plNetPlayerVault::GetPlayer( void ) const
{
return plVaultPlayerNode::ConvertNoRef( GetRootNode() );
}
void plNetPlayerVault::IFillOutConnectFields( plNetMsgVault * msg ) const
{
msg->AddInt( plVault::kArg_VaultClientType, plVault::kNodeType_VaultPlayer );
msg->AddInt( plVault::kArg_VaultClientID, plNetClientMgr::GetInstance()->GetDesiredPlayerID() );
}
bool plNetPlayerVault::IIsThisMsgMine( plNetMsgVault * msg ) const
{
if ( plVaultClient::IIsThisMsgMine( msg ) )
return true;
return ( msg->GetInt( plVault::kArg_VaultClientID )==plNetClientMgr::GetInstance()->GetDesiredPlayerID() );
}
////////////////////////////////////////////////////////////////////
// End.

View File

@ -0,0 +1,87 @@
/*==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==*/
#ifndef plNetClientVault_h_inc
#define plNetClientVault_h_inc
#include "../plVault/plVaultClient.h"
class plMipmap;
class plVaultImageNode;
////////////////////////////////////////////////////////////////////
class plNetClientVault : public plVaultClient
{
protected:
void IInitNode( plVaultNode * node );
void IFiniNode( plVaultNode * node );
int ISendNetMsg( plNetMsgVault * msg, UInt32 sendFlags=0 );
void IOnTaskTimedOut( plVaultTask * task );
bool IAmOnline( void ) const;
public:
plNetClientVault();
plNetApp * GetNetApp( void ) const;
plAgeInfoSource * GetAgeInfo( void ) const;
// static helpers to convert between plMipmap and plVaultImageNode
static hsBool StuffImageIntoNode( plMipmap * src, plVaultImageNode * dst );
static hsBool ExtractImageFromNode( plVaultImageNode * src );
};
////////////////////////////////////////////////////////////////////
class plNetPlayerVault : public plNetClientVault
{
protected:
bool IIsThisMe( plVaultPlayerInfoNode * node ) const;
void IFillOutConnectFields( plNetMsgVault * msg ) const;
bool IIsThisMsgMine( plNetMsgVault * msg ) const;
public:
plNetPlayerVault();
plVaultPlayerNode * GetPlayer( void ) const;
};
#endif // plNetClientVault_h_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,164 @@
/*==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==*/
#ifndef plNetLinkingMgr_h_inc
#define plNetLinkingMgr_h_inc
#include "hsTypes.h"
#include "hsStlUtils.h"
#include "hsBitVector.h"
#include "../plNetCommon/plNetServerSessionInfo.h"
#include "../plNetCommon/plNetCommon.h"
#include "../plMessage/plLinkToAgeMsg.h"
class plMessage;
struct plNCAgeJoiner;
struct plNCAgeLeaver;
class plNetLinkingMgr
{
static void NCAgeJoinerCallback (
plNCAgeJoiner * joiner,
unsigned type,
void * notify,
void * userState
);
static void NCAgeLeaverCallback (
plNCAgeLeaver * leaver,
unsigned type,
void * notify,
void * userState
);
friend struct NCAgeJoinerCallback;
friend struct NCAgeLeaverCallback;
static void ExecNextOp ();
plNetLinkingMgr();
plNetLinkingMgr(const plNetLinkingMgr &);
enum Cmds
{
kNilCmd,
// Sent to a player to have them call us back with info for linking to their age.
kLinkPlayerHere,
// Offer link to player.
kOfferLinkToPlayer,
// Offer link to another player from a public linking book (to my instance of the age w/out going through personal age)
kOfferLinkFromPublicBook,
// Sent to a player to have them link to their last age
kLinkPlayerToPrevAge
};
bool IPreProcessLink( void );
void IPostProcessLink( void );
bool IProcessLinkingMgrMsg( plLinkingMgrMsg * msg );
bool IProcessLinkToAgeMsg( plLinkToAgeMsg * msg );
bool IDispatchMsg( plMessage * msg, UInt32 playerID );
public:
static plNetLinkingMgr * GetInstance();
hsBool MsgReceive( plMessage *msg ); // TODO: Make this a hsKeyedObject so we can really handle messages.
void Update();
bool IsEnabled( void ) const { return fLinkingEnabled;}
void SetEnabled( bool b );
bool LinkedIn () const { return fLinkedIn && fLinkingEnabled; }
bool Linking () const { return !fLinkedIn && !fLinkingEnabled; }
// Link to an age.
void LinkToAge( plAgeLinkStruct * link, UInt32 playerID=kInvalidPlayerID );
void LinkToAge( plAgeLinkStruct * link, const char* linkAnim, UInt32 playerID=kInvalidPlayerID );
// Link to my last age.
void LinkToPrevAge( UInt32 playerID=kInvalidPlayerID );
// Link to my Personal Age
void LinkToMyPersonalAge( UInt32 playerID=kInvalidPlayerID );
// Link to my Neighborhood Age
void LinkToMyNeighborhoodAge( UInt32 playerID=kInvalidPlayerID );
// Link a player here.
void LinkPlayerHere( UInt32 playerID );
// Link player to specified age
void LinkPlayerToAge( plAgeLinkStruct * link, UInt32 playerID );
// Link player back to his last age
void LinkPlayerToPrevAge( UInt32 playerID );
// Link us to a players age.
void LinkToPlayersAge( UInt32 playerID );
// Offer a link to player.
void OfferLinkToPlayer( const plAgeLinkStruct * info, UInt32 playerID, plKey replyKey );
void OfferLinkToPlayer( const plAgeInfoStruct * info, UInt32 playerID );
void OfferLinkToPlayer( const plAgeLinkStruct * info, UInt32 playerID );
// Leave the current age
void LeaveAge (bool quitting);
// link info
plAgeLinkStruct * GetAgeLink() { return &fAgeLink; }
plAgeLinkStruct * GetPrevAgeLink() { return &fPrevAgeLink; }
// lobby info
void SetLobbyAddr( const char * ipaddr ) { fLobbyInfo.SetServerAddr( ipaddr );}
void SetLobbyPort( int port ) { fLobbyInfo.SetServerPort( port );}
const plNetServerSessionInfo * GetLobbyServerInfo( void ) const { return &fLobbyInfo;}
// helpers
static std::string GetProperAgeName( const char * ageName ); // attempt to fix wrong case age name.
private:
bool fLinkingEnabled;
bool fLinkedIn;
// The age we are either joining or are joined with.
plAgeLinkStruct fAgeLink;
// The age we just left.
plAgeLinkStruct fPrevAgeLink;
// The lobby we want to talk to.
plNetServerSessionInfo fLobbyInfo;
};
#endif // plNetLinkingMgr_h_inc

View File

@ -0,0 +1,322 @@
/*==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 "plNetObjectDebugger.h"
#include "hsResMgr.h"
#include "hsTemplates.h"
#include "../pnUtils/pnUtils.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "../plStatusLog/plStatusLog.h"
#include "../plResMgr/plKeyFinder.h"
#include "../plNetClient/plNetClientMgr.h"
#include "../plAgeLoader/plAgeLoader.h"
plNetObjectDebugger::DebugObject::DebugObject(const char* objName, plLocation& loc, UInt32 flags) :
fLoc(loc),
fFlags(flags)
{
std::string tmp = objName;
hsStrLower((char*)tmp.c_str());
fObjName = tmp;
}
//
// return true if string matches objName according to flags
//
bool plNetObjectDebugger::DebugObject::StringMatches(const char* str) const
{
if (!str)
return false;
if (fFlags & kExactStringMatch)
return !stricmp(str, fObjName.c_str());
if (fFlags & kEndStringMatch)
{
int len=strlen(str);
if (len>fObjName.size())
return false;
return !stricmp(str, fObjName.c_str()+fObjName.size()-len);
}
if (fFlags & kStartStringMatch)
{
int len=strlen(str);
if (len>fObjName.size())
return false;
return !strnicmp(str, fObjName.c_str(), strlen(str));
}
if (fFlags & kSubStringMatch)
{
std::string tmp = str;
hsStrLower((char*)tmp.c_str());
return (strstr(tmp.c_str(), fObjName.c_str()) != nil);
}
hsAssert(false, "missing flags");
return false;
}
//
// if both objName and pageName are provided, and this object has page info,
// return true if object matches both string and location.
// else just return true if object matches string
//
bool plNetObjectDebugger::DebugObject::ObjectMatches(const char* objName, const char* pageName)
{
if (!objName)
return false;
if (!pageName || (fFlags & kPageMatch)==0)
{
// only have enough info to match by objName
return StringMatches(objName);
}
plLocation loc;
loc = plKeyFinder::Instance().FindLocation(NetCommGetAge()->ageDatasetName, pageName);
return (StringMatches(objName) && loc==fLoc);
}
//
// try to match by plLocation
//
bool plNetObjectDebugger::DebugObject::ObjectMatches(const hsKeyedObject* obj)
{
if (!obj || !obj->GetKey())
return false;
if ((fFlags & kPageMatch)==0)
{
// match based on object name only
return StringMatches(obj->GetKeyName());
}
return (obj->GetKey()->GetUoid().GetLocation()==fLoc);
}
/////////////////////////////////////////////////////////////////
// plNetObjectDebugger
/////////////////////////////////////////////////////////////////
plNetObjectDebugger::plNetObjectDebugger() : fStatusLog(nil), fDebugging(false)
{
}
plNetObjectDebugger::~plNetObjectDebugger()
{
ClearAllDebugObjects();
delete fStatusLog;
}
//
// STATIC
//
plNetObjectDebugger* plNetObjectDebugger::GetInstance()
{
static plNetObjectDebugger gNetObjectDebugger;
if (plNetObjectDebuggerBase::GetInstance()==nil)
plNetObjectDebuggerBase::SetInstance(&gNetObjectDebugger);
return &gNetObjectDebugger;
}
//
// create StatusLog if necessary
//
void plNetObjectDebugger::ICreateStatusLog() const
{
if (!fStatusLog)
{
fStatusLog = plStatusLogMgr::GetInstance().CreateStatusLog(40, "NetObject.log",
plStatusLog::kFilledBackground | plStatusLog::kAlignToTop | plStatusLog::kTimestamp );
}
}
bool plNetObjectDebugger::AddDebugObject(const char* objName, const char* pageName)
{
if (!objName)
return false;
int size=strlen(objName)+1;
hsTempArray<char> tmpObjName(size);
memset(tmpObjName, 0, size);
//
// set string matching flags
//
int len = strlen(objName);
UInt32 flags=0;
if (objName[0]=='*')
{
if (objName[len-1]=='*')
{
flags = kSubStringMatch; // *foo*
strncpy(tmpObjName, objName+1, strlen(objName)-2);
}
else
{
flags = kEndStringMatch; // *foo
strncpy(tmpObjName, objName+1, strlen(objName)-1);
}
}
if (!flags && objName[len-1]=='*')
{
flags = kStartStringMatch; // foo*
strncpy(tmpObjName, objName, strlen(objName)-1);
}
if (!flags)
{
flags = kExactStringMatch;
strcpy(tmpObjName, objName);
}
//
// set plLocation
//
plLocation loc;
if (pageName)
{
loc = plKeyFinder::Instance().FindLocation(NetCommGetAge()->ageDatasetName, pageName);
flags |= kPageMatch;
}
fDebugObjects.push_back(TRACKED_NEW DebugObject(tmpObjName, loc, flags));
ICreateStatusLog();
return true;
}
bool plNetObjectDebugger::RemoveDebugObject(const char* objName, const char* pageName)
{
bool didIt=false;
if (!pageName)
{
DebugObjectList::iterator it =fDebugObjects.begin();
for( ; it != fDebugObjects.end(); )
{
if ( (*it) && (*it)->ObjectMatches(objName, pageName))
{
delete *it;
it = fDebugObjects.erase(it);
didIt=true;
}
else
it++;
}
}
return didIt;
}
void plNetObjectDebugger::ClearAllDebugObjects()
{
DebugObjectList::iterator it =fDebugObjects.begin();
for( ; it != fDebugObjects.end(); it++)
{
delete *it;
}
fDebugObjects.clear();
}
//
// write to status log if there's a string match
//
void plNetObjectDebugger::LogMsgIfMatch(const char* msg) const
{
if (GetNumDebugObjects()==0 || !msg)
return;
// extract object name from msg, expects '...object:foo,...'
std::string tmp = msg;
hsStrLower((char*)tmp.c_str());
std::string objTag="object";
const char* c=strstr(tmp.c_str(), objTag.c_str());
if (c && c != tmp.c_str())
{
c+=objTag.size();
// move past spaces
while ( *c || *c==' ' )
c++;
char objName[128];
int i=0;
// copy objName token
while(*c && *c != ',' && *c != ' ' && i<127)
objName[i++] = *c++;
objName[i]=0;
DebugObjectList::const_iterator it = fDebugObjects.begin();
for( objName[0]; it != fDebugObjects.end(); it++)
{
if ((*it) && (*it)->StringMatches(objName))
{
LogMsg(msg);
break;
}
}
}
}
void plNetObjectDebugger::LogMsg(const char* msg) const
{
DEBUG_MSG(msg);
}
bool plNetObjectDebugger::IsDebugObject(const hsKeyedObject* obj) const
{
DebugObjectList::const_iterator it =fDebugObjects.begin();
for( ; it != fDebugObjects.end(); it++)
if ((*it) && (*it)->ObjectMatches(obj))
{
return true;
}
return false;
}

View File

@ -0,0 +1,101 @@
/*==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==*/
#ifndef plNetObjectDebugger_inc
#define plNetObjectDebugger_inc
#include "hsTypes.h"
#include "hsStlUtils.h"
#include "../pnKeyedObject/plUoid.h"
#include "../pnNetCommon/plNetApp.h"
class hsKeyedObject;
class plStatusLog;
class plNetObjectDebugger : public plNetObjectDebuggerBase
{
public:
enum Flags
{
kExactStringMatch = 0x1,
kEndStringMatch = 0x2,
kStartStringMatch = 0x4,
kSubStringMatch = 0x8,
kPageMatch = 0x10 // has page info specified
};
private:
struct DebugObject
{
std::string fObjName;
plLocation fLoc;
UInt32 fFlags;
bool StringMatches(const char* str) const; // return true if string matches objName according to flags
bool ObjectMatches(const hsKeyedObject* obj);
bool ObjectMatches(const char* objName, const char* pageName);
DebugObject(const char* objName, plLocation& loc, UInt32 flags);
};
typedef std::vector<DebugObject*> DebugObjectList;
DebugObjectList fDebugObjects;
mutable plStatusLog* fStatusLog;
bool fDebugging;
void ICreateStatusLog() const;
public:
plNetObjectDebugger();
~plNetObjectDebugger();
static plNetObjectDebugger* GetInstance();
bool GetDebugging() const { return fDebugging; }
void SetDebugging(bool b) { fDebugging=b; }
// object fxns
bool AddDebugObject(const char* objName, const char* pageName=nil);
bool RemoveDebugObject(const char* objName, const char* pageName=nil);
void ClearAllDebugObjects();
int GetNumDebugObjects() const { return fDebugObjects.size(); }
bool IsDebugObject(const hsKeyedObject* obj) const;
void LogMsgIfMatch(const char* msg) const; // write to status log if there's a string match
void LogMsg(const char* msg) const;
};
#endif // plNetObjectDebugger_inc

View File

@ -0,0 +1,161 @@
/*==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 <algorithm>
#include "plgDispatch.h"
#include "plNetClientMgr.h"
#include "plNetVoiceList.h"
#include "../plNetTransport/plNetTransportMember.h"
#include "../pnMessage/plSoundMsg.h"
#include "../pnKeyedObject/plKey.h"
#include "../plStatusLog/plStatusLog.h"
// statics
float plNetListenList::kUpdateInterval=0.5f;
int plNetListenList::kMaxListenListSize=-1; // -1 is unlimited
float plNetListenList::kMaxListenDistSq=75.0f*75.0f;
int plNetVoiceList::FindMember(plNetTransportMember* e)
{
VoiceListType::iterator result = std::find(fMembers.begin(), fMembers.end(), e);
return result!=fMembers.end() ? result-fMembers.begin() : -1;
}
/*****************************************************************************
*
* plNetTalkList
*
***/
void plNetTalkList::UpdateTransportGroup(plNetClientMgr* nc)
{
if (fFlags & kDirty)
{
nc->fTransport.ClearChannelGrp(plNetClientMgr::kNetChanVoice);
if (nc->IsPeerToPeer())
{
int i;
for(i=0;i<GetNumMembers();i++)
{
if (GetMember(i)->IsPeerToPeer())
nc->fTransport.SubscribeToChannelGrp(GetMember(i), plNetClientMgr::kNetChanVoice);
}
}
fFlags &= ~kDirty;
}
}
void plNetTalkList::AddMember(plNetTransportMember* e)
{
if (FindMember(e)==-1)
{
plStatusLog::AddLineS("voice.log", "Adding %s to talk list", e->AsStdString().c_str());
fMembers.push_back(e);
}
fFlags |= kDirty;
}
void plNetTalkList::RemoveMember(plNetTransportMember* e)
{
int idx=FindMember(e);
if (idx!=-1)
{
plStatusLog::AddLineS("voice.log", "Removing %s from talklist", e->AsStdString().c_str());
fMembers.erase(fMembers.begin()+idx);
}
fFlags |= kDirty;
}
void plNetTalkList::Clear()
{
plNetVoiceList::Clear();
fFlags |= kDirty;
}
/*****************************************************************************
*
* plNetListenList
*
***/
void plNetListenList::AddMember(plNetTransportMember* e)
{
if (FindMember(e)==-1)
{
plStatusLog::AddLineS("voice.log", "Adding %s to listen list ", e->AsStdString().c_str());
fMembers.push_back(e);
#if 0
// call the new member's win audible and set talk icon parameters
plSoundMsg* pMsg = TRACKED_NEW plSoundMsg;
plArmatureMod* pMod = plArmatureMod::ConvertNoRef(e->GetAvatarKey()->GetObjectPtr());
if (pMod)
pMsg->AddReceiver(pMod->GetTarget(0)->GetKey());
pMsg->SetCmd(plSoundMsg::kSetTalkIcon);
pMsg->fIndex = GetNumMembers();
pMsg->fNameStr = (UInt32)e->GetName();
plgDispatch::MsgSend(pMsg);
#endif
}
}
void plNetListenList::RemoveMember(plNetTransportMember* e)
{
int idx=FindMember(e);
if (idx!=-1)
{
fMembers.erase(fMembers.begin()+idx);
plStatusLog::AddLineS("voice.log", "Removing %s from listen list", e->AsStdString().c_str());
#if 0
// call the new member's win audible and set talk icon parameters
plSoundMsg* pMsg = TRACKED_NEW plSoundMsg;
plArmatureMod* pMod = plArmatureMod::ConvertNoRef(e->GetAvatarKey()->GetObjectPtr());
if (pMod)
pMsg->AddReceiver(pMod->GetTarget(0)->GetKey());
pMsg->SetCmd(plSoundMsg::kClearTalkIcon);
plgDispatch::MsgSend(pMsg);
#endif
}
}

View File

@ -0,0 +1,123 @@
/*==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==*/
#ifndef plNetVoiceList_h
#define plNetVoiceList_h
#include "hsTypes.h"
#include "hsStlUtils.h"
//
// a simple class used by the net client code to hold listenLists and talkLists
// for voice filtering.
//
class plNetTransportMember;
class plNetVoiceList
{
protected:
typedef std::vector<plNetTransportMember*> VoiceListType;
protected:
VoiceListType fMembers;
public:
plNetVoiceList() {}
virtual ~plNetVoiceList() {}
int GetNumMembers() const { return fMembers.size(); }
plNetTransportMember* GetMember(int i) const { return fMembers[i]; }
virtual void AddMember(plNetTransportMember* e) = 0;
virtual void RemoveMember(plNetTransportMember* e) = 0;
virtual void Clear() { fMembers.clear(); }
int FindMember(plNetTransportMember* e); // return index or -1
};
//
// Specialized version for listen list
// a list of other player I am listening to
//
class plNetListenList : public plNetVoiceList
{
private:
double fLastUpdateTime;
int fNumUpdates;
public:
plNetListenList() : fNumUpdates(0) {}
~plNetListenList() {}
static float kUpdateInterval;
static int kMaxListenListSize;
static float kMaxListenDistSq;
void SetLastUpdateTime(double t) { fLastUpdateTime=t; fNumUpdates++; }
double GetLastUpdateTime() { return fLastUpdateTime; }
hsBool CheckForceSynch() { if (fNumUpdates>10) { fNumUpdates=0; return true;} return false; }
virtual void AddMember(plNetTransportMember* e);
virtual void RemoveMember(plNetTransportMember* e);
};
//
// Specialized version for talk list
// a list of other players I am talking to
//
class plNetClientMgr;
class plNetTalkList : public plNetVoiceList
{
private:
enum
{
kDirty = 0x1
};
UInt32 fFlags;
public:
plNetTalkList() : fFlags(0) {}
~plNetTalkList() {}
void UpdateTransportGroup(plNetClientMgr* nc);
void AddMember(plNetTransportMember* e);
void RemoveMember(plNetTransportMember* e);
void Clear();
};
#endif // plNetVoiceList_h