Browse Source

Track NPC clones

Manual state management in python was kind of fiddly, so let's track all
avatar clones in the NetApp and unload them as needed. This also seems to
fix a potential bug in plNPCSpawnMod (is that even used?).
Adam Johnson 13 years ago
parent
commit
3b69a4aee3
  1. 2
      Sources/Plasma/FeatureLib/pfPython/cyMisc.cpp
  2. 3
      Sources/Plasma/FeatureLib/pfPython/cyMiscGlue.cpp
  3. 28
      Sources/Plasma/PubUtilLib/plAvatar/plAvatarMgr.cpp
  4. 12
      Sources/Plasma/PubUtilLib/plAvatar/plAvatarMgr.h
  5. 11
      Sources/Plasma/PubUtilLib/plAvatar/plNPCSpawnMod.cpp
  6. 1
      Sources/Plasma/PubUtilLib/plAvatar/plNPCSpawnMod.h
  7. 1
      Sources/Plasma/PubUtilLib/plNetClient/plNetCliAgeLeaver.cpp
  8. 53
      Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp
  9. 11
      Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.h
  10. 11
      Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgrLoad.cpp

2
Sources/Plasma/FeatureLib/pfPython/cyMisc.cpp

@ -2700,7 +2700,7 @@ PyObject* cyMisc::LoadAvatarModel(const char* modelName, pyKey& spawnPoint, cons
void cyMisc::UnLoadAvatarModel(pyKey& avatar) void cyMisc::UnLoadAvatarModel(pyKey& avatar)
{ {
plAvatarMgr::GetInstance()->UnLoadAvatar(avatar.getKey(), false); plAvatarMgr::GetInstance()->UnLoadAvatar(avatar.getKey(), false, true);
} }
void cyMisc::ForceCursorHidden() void cyMisc::ForceCursorHidden()

3
Sources/Plasma/FeatureLib/pfPython/cyMiscGlue.cpp

@ -374,7 +374,8 @@ PYTHON_GLOBAL_METHOD_DEFINITION(PtLoadAvatarModel, args, "Params: modelName, spa
return cyMisc::LoadAvatarModel(modelName, *key, userStr.c_str()); return cyMisc::LoadAvatarModel(modelName, *key, userStr.c_str());
} }
PYTHON_GLOBAL_METHOD_DEFINITION(PtUnLoadAvatarModel, args, "Params: avatarKey\nUnloads the specified avatar model") PYTHON_GLOBAL_METHOD_DEFINITION(PtUnLoadAvatarModel, args, "Params: avatarKey\nForcibly unloads the specified avatar model.\n"
"Do not use this method unless you require fine-grained control of avatar unloading.")
{ {
PyObject* keyObj = NULL; PyObject* keyObj = NULL;
if (!PyArg_ParseTuple(args, "O", &keyObj)) if (!PyArg_ParseTuple(args, "O", &keyObj))

28
Sources/Plasma/PubUtilLib/plAvatar/plAvatarMgr.cpp

@ -217,11 +217,17 @@ plKey plAvatarMgr::LoadAvatar(const char *name, const char *accountName, bool is
return result; return result;
} }
void plAvatarMgr::UnLoadAvatar(plKey avatarKey, bool isPlayer) void plAvatarMgr::UnLoadAvatar(const plKey& avatarKey, bool isPlayer, bool netPropagate) const
{ {
hsBool isLoading = false; if (avatarKey)
plLoadAvatarMsg *msg = new plLoadAvatarMsg(avatarKey, GetKey(), 0, isPlayer, isLoading); {
plKey requestor = GetKey();
plLoadAvatarMsg* msg = new plLoadAvatarMsg(avatarKey, requestor, 0, isPlayer, false);
// only netprop if the user has a death wish
msg->SetBCastFlag(plMessage::kNetPropagate, netPropagate);
msg->Send(); msg->Send();
}
} }
// our player's already loaded locally, but we've just linked into an age and others there need to be // our player's already loaded locally, but we've just linked into an age and others there need to be
@ -271,22 +277,6 @@ bool plAvatarMgr::UnPropagateLocalPlayer()
return false; return false;
} }
// UNLOADREMOTEPLAYER
void plAvatarMgr::UnLoadRemotePlayer(plKey remotePlayer)
{
if(remotePlayer)
{
plKey requestor = GetKey();
bool isPlayer = true;
hsBool isLoading = false;
plLoadAvatarMsg * msg = new plLoadAvatarMsg(remotePlayer, requestor, 0, isPlayer, isLoading);
// don't propagate over the network. this is just for removing our local version
msg->SetBCastFlag(plMessage::kNetPropagate, false);
msg->Send();
}
}
// UNLOADLOCALPLAYER // UNLOADLOCALPLAYER
void plAvatarMgr::UnLoadLocalPlayer() void plAvatarMgr::UnLoadLocalPlayer()
{ {

12
Sources/Plasma/PubUtilLib/plAvatar/plAvatarMgr.h

@ -115,15 +115,21 @@ public:
plKey LoadPlayer(const char* name, const char *account); plKey LoadPlayer(const char* name, const char *account);
plKey LoadPlayer(const char* name, const char *account, const char *linkName); plKey LoadPlayer(const char* name, const char *account, const char *linkName);
plKey LoadAvatar(const char *name, const char *accountName, bool isPlayer, plKey spawnPoint, plAvTask *initialTask, const char *userStr = nil); plKey LoadAvatar(const char *name, const char *accountName, bool isPlayer, plKey spawnPoint, plAvTask *initialTask, const char *userStr = nil);
/** Unload an avatar - player or npc - both locally and remotely. */
void UnLoadAvatar(plKey avKey, bool isPlayer); /**
* Unload an avatar clone
*
* This unloads the clone of an avatar (remote player or NPC) from our local game.
* The avatar clone can be unloaded globally by setting netPropagate; however, this
* is highly discouraged.
*/
void UnLoadAvatar(const plKey& avKey, bool isPlayer, bool netPropagate=false) const;
/** send our (already loaded) local player to newly-associated clients - used when linking */ /** send our (already loaded) local player to newly-associated clients - used when linking */
void PropagateLocalPlayer(int spawnPoint = -1); void PropagateLocalPlayer(int spawnPoint = -1);
/** Unload our local player on other machines because we're leaving this age. /** Unload our local player on other machines because we're leaving this age.
The player will stay around on our local machine, though. */ The player will stay around on our local machine, though. */
bool UnPropagateLocalPlayer(); bool UnPropagateLocalPlayer();
void UnLoadRemotePlayer(plKey playerKey);
void UnLoadLocalPlayer(); void UnLoadLocalPlayer();
void AddAvatar(plArmatureMod *avatar); void AddAvatar(plArmatureMod *avatar);

11
Sources/Plasma/PubUtilLib/plAvatar/plNPCSpawnMod.cpp

@ -99,16 +99,6 @@ void plNPCSpawnMod::AddTarget(plSceneObject* so)
Trigger(); Trigger();
} }
void plNPCSpawnMod::RemoveTarget(plSceneObject *so)
{
plSingleModifier::RemoveTarget(so);
if(fSpawnedKey)
{
plAvatarMgr::GetInstance()->UnLoadAvatar(fSpawnedKey, false);
}
}
// TRIGGER // TRIGGER
bool plNPCSpawnMod::Trigger() bool plNPCSpawnMod::Trigger()
{ {
@ -123,6 +113,7 @@ bool plNPCSpawnMod::Trigger()
// spawn the NPC // spawn the NPC
plKey spawnPoint = GetTarget(0)->GetKey(); plKey spawnPoint = GetTarget(0)->GetKey();
// Note: we will be unloaded by the NetApp's NPC magick
fSpawnedKey = plAvatarMgr::GetInstance()->LoadAvatar(fModelName, fAccountName, false, spawnPoint, nil); fSpawnedKey = plAvatarMgr::GetInstance()->LoadAvatar(fModelName, fAccountName, false, spawnPoint, nil);
ISendNotify(fSpawnedKey); ISendNotify(fSpawnedKey);

1
Sources/Plasma/PubUtilLib/plAvatar/plNPCSpawnMod.h

@ -58,7 +58,6 @@ public:
GETINTERFACE_ANY( plNPCSpawnMod, plSingleModifier ); GETINTERFACE_ANY( plNPCSpawnMod, plSingleModifier );
virtual void AddTarget(plSceneObject* so); virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject *so);
// hsBool MsgReceive(plMessage* msg); // hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream *stream, hsResMgr *mgr); virtual void Read(hsStream *stream, hsResMgr *mgr);

1
Sources/Plasma/PubUtilLib/plNetClient/plNetCliAgeLeaver.cpp

@ -223,6 +223,7 @@ void plNCAgeLeaver::ExecNextOp () {
plAgeLoader::GetInstance()->UnloadAge(); // unload age plAgeLoader::GetInstance()->UnloadAge(); // unload age
nc->ISendCameraReset(false/*leaving age*/); // reset camera nc->ISendCameraReset(false/*leaving age*/); // reset camera
nc->IUnloadRemotePlayers(); // unload other players nc->IUnloadRemotePlayers(); // unload other players
nc->IUnloadNPCs(); // unload non-player clones
if (NetCommNeedToLoadAvatar()) if (NetCommNeedToLoadAvatar())
am->UnLoadLocalPlayer(); am->UnLoadLocalPlayer();

53
Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp

@ -181,13 +181,9 @@ void plNetClientMgr::Shutdown()
plNetLinkingMgr::GetInstance()->LeaveAge(true); plNetLinkingMgr::GetInstance()->LeaveAge(true);
// release existing remote players // release all avatar clones
int i; IUnloadRemotePlayers();
for (i=0;i<RemotePlayerKeys().size();i++) IUnloadNPCs();
{
plKey k=RemotePlayerKeys()[i];
plAvatarMgr::GetInstance()->UnLoadRemotePlayer(k);
}
// Finally, pump the dispatch system so all the new refs get delivered. // Finally, pump the dispatch system so all the new refs get delivered.
plgDispatch::Dispatch()->MsgQueueProcess(); plgDispatch::Dispatch()->MsgQueueProcess();
@ -197,7 +193,7 @@ void plNetClientMgr::Shutdown()
delete fMsgRecorder; delete fMsgRecorder;
fMsgRecorder = nil; fMsgRecorder = nil;
} }
for (i = 0; i < fMsgPlayers.size(); i++) for (int i = 0; i < fMsgPlayers.size(); i++)
delete fMsgPlayers[i]; delete fMsgPlayers[i];
fMsgPlayers.clear(); fMsgPlayers.clear();
@ -424,9 +420,19 @@ int plNetClientMgr::IPrepMsg(plNetMessage* msg)
// //
void plNetClientMgr::IUnloadRemotePlayers() void plNetClientMgr::IUnloadRemotePlayers()
{ {
for(int i=RemotePlayerKeys().size()-1;i>=0;i--) for (size_t i = fRemotePlayerKeys.size(); i > 0; --i)
plAvatarMgr::GetInstance()->UnLoadRemotePlayer(RemotePlayerKeys()[i]); plAvatarMgr::GetInstance()->UnLoadAvatar(fRemotePlayerKeys[i-1], true);
hsAssert(!RemotePlayerKeys().size(),"Still remote players left when linking out"); hsAssert(fRemotePlayerKeys.empty(), "Still remote players left when linking out");
}
//
// unload NPCs since we're leaving the age
//
void plNetClientMgr::IUnloadNPCs()
{
for (size_t i = fNPCKeys.size(); i > 0; --i)
plAvatarMgr::GetInstance()->UnLoadAvatar(fNPCKeys[i-1], false);
hsAssert(fNPCKeys.empty(), "Still npcs left when linking out");
} }
// //
@ -853,6 +859,31 @@ plSynchedObject* plNetClientMgr::GetLocalPlayer(hsBool forceLoad) const
plSynchedObject::ConvertNoRef(fLocalPlayerKey->ObjectIsLoaded()) : nil; plSynchedObject::ConvertNoRef(fLocalPlayerKey->ObjectIsLoaded()) : nil;
} }
plSynchedObject* plNetClientMgr::GetNPC(uint32_t i) const
{
return fNPCKeys[i] ? plSynchedObject::ConvertNoRef(fNPCKeys[i]->ObjectIsLoaded()) : nil;
}
void plNetClientMgr::AddNPCKey(const plKey& npc)
{
// note: npc keys have little sanity checking...
hsAssert(npc, "adding nil npc key? naughty, naughty...");
fNPCKeys.push_back(npc);
}
bool plNetClientMgr::IsNPCKey(const plKey& npc, int* idx) const
{
if (npc)
{
plKeyVec::const_iterator it = std::find(fNPCKeys.begin(), fNPCKeys.end(), npc);
bool found = it != fNPCKeys.end();
if (idx)
*idx = found ? (it - fNPCKeys.begin()) : -1;
return found;
}
return false;
}
// //
// return a ptr to a remote player // return a ptr to a remote player
// //

11
Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.h

@ -153,7 +153,7 @@ private:
// cached char info // cached char info
plKey fLocalPlayerKey; plKey fLocalPlayerKey;
plKeyVec fRemotePlayerKeys; plKeyVec fRemotePlayerKeys;
// plKeyVec fNPCKeys; plKeyVec fNPCKeys;
class plNetClientMgrMsg * fDisableMsg; class plNetClientMgrMsg * fDisableMsg;
@ -222,6 +222,7 @@ private:
void IRemoveCloneRoom(); void IRemoveCloneRoom();
void IUnloadRemotePlayers(); void IUnloadRemotePlayers();
void IUnloadNPCs();
plKey ILoadClone(plLoadCloneMsg *cloneMsg); plKey ILoadClone(plLoadCloneMsg *cloneMsg);
@ -310,8 +311,14 @@ public:
// avatar vault actions // avatar vault actions
int UploadPlayerVault(uint32_t vaultFlags); int UploadPlayerVault(uint32_t vaultFlags);
// npc clones
const plKeyVec& NPCKeys() const { return fNPCKeys; }
plSynchedObject* GetNPC(uint32_t i) const;
void AddNPCKey(const plKey& npc);
bool IsNPCKey(const plKey& npc, int* idx=nil) const;
// remote players // remote players
const std::vector<plKey>& RemotePlayerKeys() const { return fRemotePlayerKeys; } const plKeyVec& RemotePlayerKeys() const { return fRemotePlayerKeys; }
plSynchedObject* GetRemotePlayer(int i) const; plSynchedObject* GetRemotePlayer(int i) const;
void AddRemotePlayerKey(plKey p); void AddRemotePlayerKey(plKey p);
hsBool IsRemotePlayerKey(const plKey p, int* idx=nil); hsBool IsRemotePlayerKey(const plKey p, int* idx=nil);

11
Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgrLoad.cpp

@ -113,13 +113,16 @@ plKey plNetClientMgr::ILoadClone(plLoadCloneMsg *pCloneMsg)
// check if local or remote player before loading // check if local or remote player before loading
plLoadAvatarMsg* loadAvMsg=plLoadAvatarMsg::ConvertNoRef(pCloneMsg); plLoadAvatarMsg* loadAvMsg=plLoadAvatarMsg::ConvertNoRef(pCloneMsg);
if (loadAvMsg && loadAvMsg->GetIsPlayer()) if (loadAvMsg)
{ {
bool originating = ( pCloneMsg->GetOriginatingPlayerID() == this->GetPlayerID() ); bool originating = ( pCloneMsg->GetOriginatingPlayerID() == this->GetPlayerID() );
if (loadAvMsg->GetIsPlayer())
if (originating) if (originating)
fLocalPlayerKey = cloneKey; fLocalPlayerKey = cloneKey;
else else
AddRemotePlayerKey(cloneKey); AddRemotePlayerKey(cloneKey);
else // hey, we got a quab or yeesha... or some other such devilry...
AddNPCKey(cloneKey);
} }
plKey cloneNodeKey = hsgResMgr::ResMgr()->FindKey(kNetClientCloneRoom_KEY); plKey cloneNodeKey = hsgResMgr::ResMgr()->FindKey(kNetClientCloneRoom_KEY);
@ -139,6 +142,12 @@ plKey plNetClientMgr::ILoadClone(plLoadCloneMsg *pCloneMsg)
return cloneKey; return cloneKey;
} }
// need to drop our ref if it's an NPC
// remote players handled by plPlayerPageMsg--don't sweat that
plKeyVec::iterator it = std::find(fNPCKeys.begin(), fNPCKeys.end(), cloneKey);
if (it != fNPCKeys.end())
fNPCKeys.erase(it);
ICheckPendingStateLoad(hsTimer::GetSysSeconds()); ICheckPendingStateLoad(hsTimer::GetSysSeconds());
plSynchEnabler p(false); // turn off dirty tracking while in this function plSynchEnabler p(false); // turn off dirty tracking while in this function

Loading…
Cancel
Save