diff --git a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationDataMgr.cpp b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationDataMgr.cpp index 5507db20..5be240b7 100644 --- a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationDataMgr.cpp +++ b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationDataMgr.cpp @@ -278,10 +278,7 @@ void XMLCALL LocalizationXMLFile::HandleData(void *userData, const XML_Char *dat // This gets all data between tags, including indentation and newlines // so we'll have to ignore data when we aren't expecting it (not in a translation tag) - std::wstring wData = L""; - - for (int i = 0; i < stringLength; i++) - wData += data[i]; + std::wstring wData = std::wstring(data, stringLength); // we must be in a translation tag since that's the only tag that doesn't ignore the contents file->fData[file->fCurrentAge][file->fCurrentSet][file->fCurrentElement][file->fCurrentTranslation] += wData; diff --git a/Sources/Plasma/FeatureLib/pfPython/pyVault.cpp b/Sources/Plasma/FeatureLib/pfPython/pyVault.cpp index 46707a9e..1c40f4f1 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyVault.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyVault.cpp @@ -365,7 +365,7 @@ void pyVault::AddChronicleEntry( const char * name, UInt32 type, const char * va wchar * wEntryName = StrDupToUnicode(name); wchar * wEntryValue = StrDupToUnicode(value); - VaultAddChronicleEntryAndWait(wEntryName, type, wEntryValue); + VaultAddChronicleEntry(wEntryName, type, wEntryValue); FREE(wEntryName); FREE(wEntryValue); @@ -379,6 +379,8 @@ void pyVault::SendToDevice( pyVaultNode& node, const char * deviceName ) wchar wDevName[256]; StrToUnicode(wDevName, deviceName, arrsize(wDevName)); + + // Note: This actually blocks (~Hoikas) VaultPublishNode(node.GetNode()->nodeId, wDevName); } @@ -544,12 +546,14 @@ void pyVault::RegisterMTStation( const char * stationName, const char * backLink wchar wSpawnPt[256]; StrToUnicode(wStationName, stationName, arrsize(wStationName)); StrToUnicode(wSpawnPt, backLinkSpawnPtObjName, arrsize(wSpawnPt)); + + // Note: This doesn't actually block (~Hoikas) VaultRegisterMTStationAndWait( wStationName, wSpawnPt); } void pyVault::RegisterOwnedAge( const pyAgeLinkStruct & link ) { - VaultRegisterOwnedAgeAndWait(link.GetAgeLink()); + VaultRegisterOwnedAge(link.GetAgeLink()); } void pyVault::UnRegisterOwnedAge( const char * ageFilename ) @@ -561,7 +565,7 @@ void pyVault::UnRegisterOwnedAge( const char * ageFilename ) void pyVault::RegisterVisitAge( const pyAgeLinkStruct & link ) { - VaultRegisterVisitAgeAndWait(link.GetAgeLink()); + VaultRegisterVisitAge(link.GetAgeLink()); } void pyVault::UnRegisterVisitAge( const char * guidstr ) @@ -573,22 +577,32 @@ void pyVault::UnRegisterVisitAge( const char * guidstr ) VaultUnregisterVisitAgeAndWait(&info); } +//============================================================================ +void _InvitePlayerToAge(ENetError result, void* state, void* param, RelVaultNode* node) +{ + if (result == kNetSuccess) + VaultSendNode(node, (UInt32)param); +} + void pyVault::InvitePlayerToAge( const pyAgeLinkStruct & link, UInt32 playerID ) { - ENetError error; NetVaultNode * templateNode = NEWZERO(NetVaultNode); templateNode->IncRef(); templateNode->SetNodeType(plVault::kNodeType_TextNote); VaultTextNoteNode visitAcc(templateNode); visitAcc.SetNoteType(plVault::kNoteType_Visit); visitAcc.SetVisitInfo(*link.GetAgeLink()->GetAgeInfo()); - if (RelVaultNode * rvn = VaultCreateNodeAndWaitIncRef(templateNode, &error)) { - VaultSendNode(rvn, playerID); - rvn->DecRef(); - } + VaultCreateNode(templateNode, (FVaultCreateNodeCallback)_InvitePlayerToAge, nil, (void*)playerID); templateNode->DecRef(); } +//============================================================================ +void _UninvitePlayerToAge(ENetError result, void* state, void* param, RelVaultNode* node) +{ + if (result == kNetSuccess) + VaultSendNode(node, (UInt32)param); +} + void pyVault::UnInvitePlayerToAge( const char * str, UInt32 playerID ) { plAgeInfoStruct info; @@ -604,32 +618,32 @@ void pyVault::UnInvitePlayerToAge( const char * str, UInt32 playerID ) rvnLink->DecRef(); } - ENetError error; NetVaultNode * templateNode = NEWZERO(NetVaultNode); templateNode->IncRef(); templateNode->SetNodeType(plVault::kNodeType_TextNote); VaultTextNoteNode visitAcc(templateNode); visitAcc.SetNoteType(plVault::kNoteType_UnVisit); visitAcc.SetVisitInfo(info); - if (RelVaultNode * rvn = VaultCreateNodeAndWaitIncRef(templateNode, &error)) { - VaultSendNode(rvn, playerID); - rvn->DecRef(); - } + VaultCreateNode(templateNode, (FVaultCreateNodeCallback)_UninvitePlayerToAge, nil, (void*)playerID); templateNode->DecRef(); } +//============================================================================ void pyVault::OfferLinkToPlayer( const pyAgeLinkStruct & link, UInt32 playerID ) { hsAssert(false, "eric, port me"); } +//============================================================================ void pyVault::CreateNeighborhood() { plNetClientMgr * nc = plNetClientMgr::GetInstance(); - // Unregister old hood + // Unregister old hood plAgeInfoStruct info; info.SetAgeFilename(kNeighborhoodAgeFilename); + + // Note: This doesn't actually block (~Hoikas) VaultUnregisterOwnedAgeAndWait(&info); // Register new hood @@ -656,11 +670,12 @@ void pyVault::CreateNeighborhood() link.GetAgeInfo()->SetAgeUserDefinedName( title.c_str() ); link.GetAgeInfo()->SetAgeDescription( desc.c_str() ); - VaultRegisterOwnedAgeAndWait(&link); + VaultRegisterOwnedAge(&link); } bool pyVault::SetAgePublic( const pyAgeInfoStruct * ageInfo, bool makePublic ) { + // Note: This doesn't actually block (~Hoikas) return VaultSetOwnedAgePublicAndWait(ageInfo->GetAgeInfo(), makePublic); } diff --git a/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.cpp b/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.cpp index 6dfa886c..15ab3ea6 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.cpp @@ -108,6 +108,7 @@ pyVaultNode::pyVaultNodeOperationCallback::~pyVaultNodeOperationCallback() void pyVaultNode::pyVaultNodeOperationCallback::VaultOperationStarted( UInt32 context ) { + fContext = context; if ( fCbObject ) { // Call the callback. @@ -407,6 +408,14 @@ void pyVaultNode::SetCreateAgeGuid( const char * v ) // Vault Node API // Add child node +void _AddNodeCallback(ENetError result, void* param) { + pyVaultNode::pyVaultNodeOperationCallback* cb = (pyVaultNode::pyVaultNodeOperationCallback*)param; + if (IS_NET_SUCCESS(result)) + cb->VaultOperationComplete(hsOK); + else + cb->VaultOperationComplete(hsFail); +} + PyObject* pyVaultNode::AddNode(pyVaultNode* pynode, PyObject* cbObject, UInt32 cbContext) { pyVaultNodeOperationCallback * cb = NEWZERO(pyVaultNodeOperationCallback)(cbObject); @@ -437,21 +446,26 @@ PyObject* pyVaultNode::AddNode(pyVaultNode* pynode, PyObject* cbObject, UInt32 c } } - // Block here until we have the child node =( - VaultAddChildNodeAndWait(fNode->nodeId, pynode->fNode->nodeId, NetCommGetPlayer()->playerInt); - PyObject * nodeRef = cb->fPyNodeRef = pyVaultNodeRef::New(fNode, pynode->fNode); Py_INCREF(nodeRef); // incref it, because we MUST return a new PyObject, and the callback "steals" the ref from us cb->SetNode(pynode->fNode); - cb->VaultOperationComplete(cbContext, hsResult); - + + VaultAddChildNode(fNode->nodeId, + pynode->fNode->nodeId, + NetCommGetPlayer()->playerInt, + (FVaultAddChildNodeCallback)_AddNodeCallback, + cb + ); + + // Evil undocumented functionality that some fool + // decided to use in xKI.py. Really??? return nodeRef; } else { // manually make the callback cb->VaultOperationStarted( cbContext ); - cb->VaultOperationComplete( cbContext, hsFail ); + cb->VaultOperationComplete(hsFail); } // just return a None object @@ -468,14 +482,18 @@ void pyVaultNode::LinkToNode(int nodeID, PyObject* cbObject, UInt32 cbContext) // Hack the callbacks until vault notification is in place cb->VaultOperationStarted( cbContext ); - VaultAddChildNodeAndWait(fNode->nodeId, nodeID, NetCommGetPlayer()->playerInt); if (RelVaultNode * rvn = VaultGetNodeIncRef(nodeID)) { cb->SetNode(rvn); cb->fPyNodeRef = pyVaultNodeRef::New(fNode, rvn); rvn->DecRef(); } - cb->VaultOperationComplete( cbContext, hsOK ); + VaultAddChildNode(fNode->nodeId, + nodeID, + NetCommGetPlayer()->playerInt, + (FVaultAddChildNodeCallback)_AddNodeCallback, + cb + ); } else { diff --git a/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.h b/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.h index 3ff37972..193317aa 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.h @@ -85,12 +85,14 @@ public: PyObject * fCbObject; RelVaultNode * fNode; PyObject * fPyNodeRef; + UInt32 fContext; pyVaultNodeOperationCallback(PyObject * cbObject); ~pyVaultNodeOperationCallback(); void VaultOperationStarted(UInt32 context); void VaultOperationComplete(UInt32 context, int resultCode); + void VaultOperationComplete(int resultCode) { VaultOperationComplete(fContext, resultCode); } void SetNode (RelVaultNode * rvn); RelVaultNode * GetNode (); diff --git a/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNode.cpp b/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNode.cpp index 914c62a0..7e1cfb1d 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNode.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNode.cpp @@ -92,15 +92,22 @@ hsBool pyVaultPlayerInfoListNode::HasPlayer( UInt32 playerID ) return (rvn != nil); } -hsBool pyVaultPlayerInfoListNode::AddPlayer( UInt32 playerID ) +//================================================================== + +static void IAddPlayer_NodesFound(ENetError result, void* param, unsigned nodeIdCount, const unsigned nodeIds[]) { - if (HasPlayer(playerID)) - return true; - - if (!fNode) - return false; - - NetVaultNode * templateNode = NEWZERO(NetVaultNode); + NetVaultNode* parent = static_cast(param); + if (nodeIdCount) + VaultAddChildNode(parent->GetNodeId(), nodeIds[0], VaultGetPlayerId(), nullptr, nullptr); + parent->DecRef(); +} + +void pyVaultPlayerInfoListNode::AddPlayer( UInt32 playerID ) +{ + if (HasPlayer(playerID) || !fNode) + return; + + NetVaultNode* templateNode = new NetVaultNode(); templateNode->IncRef(); templateNode->SetNodeType(plVault::kNodeType_PlayerInfo); VaultPlayerInfoNode access(templateNode); @@ -108,15 +115,14 @@ hsBool pyVaultPlayerInfoListNode::AddPlayer( UInt32 playerID ) ARRAY(unsigned) nodeIds; VaultLocalFindNodes(templateNode, &nodeIds); - - if (!nodeIds.Count()) - VaultFindNodesAndWait(templateNode, &nodeIds); - + + // So, if we know about this node, we can take it easy. If not, we lazy load it. if (nodeIds.Count()) - VaultAddChildNodeAndWait(fNode->nodeId, nodeIds[0], VaultGetPlayerId()); - - templateNode->DecRef(); - return nodeIds.Count() != 0; + VaultAddChildNode(fNode->GetNodeId(), nodeIds[0], VaultGetPlayerId(), nullptr, nullptr); + else { + fNode->IncRef(); + VaultFindNodes(templateNode, IAddPlayer_NodesFound, fNode); + } } void pyVaultPlayerInfoListNode::RemovePlayer( UInt32 playerID ) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNode.h b/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNode.h index bf3c8bef..8bb46476 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNode.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNode.h @@ -82,8 +82,8 @@ public: //================================================================== // class RelVaultNode : public plVaultFolderNode // - virtual hsBool HasPlayer( UInt32 playerID ); - hsBool AddPlayer( UInt32 playerID ); + hsBool HasPlayer( UInt32 playerID ); + void AddPlayer( UInt32 playerID ); void RemovePlayer( UInt32 playerID ); PyObject * GetPlayer( UInt32 playerID ); // returns pyVaultPlayerInfoNode diff --git a/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNodeGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNodeGlue.cpp index 27fc381f..ac675fe2 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNodeGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyVaultPlayerInfoListNodeGlue.cpp @@ -81,7 +81,8 @@ PYTHON_METHOD_DEFINITION(ptVaultPlayerInfoListNode, playerlistAddPlayer, args) PyErr_SetString(PyExc_TypeError, "playerlistAddPlayer expects an unsigned long"); PYTHON_RETURN_ERROR; } - PYTHON_RETURN_BOOL(self->fThis->AddPlayer(playerID)); + self->fThis->AddPlayer(playerID); + PYTHON_RETURN_NONE; } PYTHON_METHOD_DEFINITION(ptVaultPlayerInfoListNode, playerlistRemovePlayer, args) @@ -126,7 +127,8 @@ PYTHON_METHOD_DEFINITION(ptVaultPlayerInfoListNode, addPlayer, args) PyErr_SetString(PyExc_TypeError, "addPlayer expects an unsigned long"); PYTHON_RETURN_ERROR; } - PYTHON_RETURN_BOOL(self->fThis->AddPlayer(playerID)); + self->fThis->AddPlayer(playerID); + PYTHON_RETURN_NONE; } PYTHON_METHOD_DEFINITION(ptVaultPlayerInfoListNode, removePlayer, args) diff --git a/Sources/Plasma/PubUtilLib/plMessage/plVaultNotifyMsg.h b/Sources/Plasma/PubUtilLib/plMessage/plVaultNotifyMsg.h index 65430305..6dff96d3 100644 --- a/Sources/Plasma/PubUtilLib/plMessage/plVaultNotifyMsg.h +++ b/Sources/Plasma/PubUtilLib/plMessage/plVaultNotifyMsg.h @@ -61,7 +61,9 @@ public: kUnRegisteredOwnedAge = plNetCommon::VaultTasks::kUnRegisterOwnedAge, kUnRegisteredVisitAge = plNetCommon::VaultTasks::kUnRegisterVisitAge, kPublicAgeCreated, - kPublicAgeRemoved + kPublicAgeRemoved, + kRegisteredSubAgeLink, + kRegisteredChildAgeLink, }; plVaultNotifyMsg(); diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp index b03b5d31..dc5d4e12 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp @@ -84,6 +84,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../plMessage/plNetVoiceListMsg.h" #include "../plMessage/plNetCommMsgs.h" #include "../plMessage/plNetClientMgrMsg.h" +#include "../plMessage/plVaultNotifyMsg.h" #include "../plResMgr/plKeyFinder.h" #include "../plResMgr/plPageInfo.h" #include "../plNetTransport/plNetTransportMember.h" @@ -352,6 +353,9 @@ int plNetClientMgr::Init() plgDispatch::Dispatch()->RegisterForExactType(plNetCommActivePlayerMsg::Index(), GetKey()); plgDispatch::Dispatch()->RegisterForExactType(plNetCommLinkToAgeMsg::Index(), GetKey()); + // We need plVaultNotifyMsgs for the NetLinkingMgr + plgDispatch::Dispatch()->RegisterForType(plVaultNotifyMsg::Index(), GetKey()); + IInitNetClientComm(); return ret; diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.cpp b/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.cpp index 9ee48c4b..15c8cea2 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.cpp @@ -62,7 +62,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../plAvatar/plArmatureMod.h" #include "../plFile/hsFiles.h" #include "../plMessage/plNCAgeJoinerMsg.h" -#include "../plVault/plVault.h" /***************************************************************************** @@ -330,6 +329,13 @@ hsBool plNetLinkingMgr::MsgReceive( plMessage *msg ) return true; } + // If a link was deferred in order to register an owned age, we will + // get a VaultNotify about the registration + if (plVaultNotifyMsg* vaultMsg = plVaultNotifyMsg::ConvertNoRef(msg)) { + IProcessVaultNotifyMsg(vaultMsg); + return true; + } + return false; } @@ -363,37 +369,19 @@ bool plNetLinkingMgr::IProcessLinkToAgeMsg( plLinkToAgeMsg * msg ) GetPrevAgeLink()->CopyFrom( GetAgeLink() ); GetAgeLink()->CopyFrom( msg->GetAgeLink() ); - if ( IPreProcessLink() ) + // Actually do stuff... + UInt8 pre = IPreProcessLink(); + if (pre == kLinkImmediately) { - GetAgeLink()->SetSpawnPoint(msg->GetAgeLink()->SpawnPoint()); - - if (fLinkedIn) { - // Set the link out animation we should use - if (plSceneObject *localSO = plSceneObject::ConvertNoRef(nc->GetLocalPlayer())) { - plArmatureMod *avMod = const_cast(plArmatureMod::ConvertNoRef(localSO->GetModifierByType(plArmatureMod::Index()))); - avMod->SetLinkInAnim(msg->GetLinkInAnimName()); - } - // Queue leave op - NlmLeaveAgeOp * leaveAgeOp = NEWZERO(NlmLeaveAgeOp); - QueueOp(leaveAgeOp); - } - - // Queue join op - NlmJoinAgeOp * joinAgeOp = NEWZERO(NlmJoinAgeOp); - joinAgeOp->age.ageInstId = (Uuid) *GetAgeLink()->GetAgeInfo()->GetAgeInstanceGuid(); - StrCopy( - joinAgeOp->age.ageDatasetName, - GetAgeLink()->GetAgeInfo()->GetAgeFilename(), - arrsize(joinAgeOp->age.ageDatasetName) - ); - StrCopy( - joinAgeOp->age.spawnPtName, - GetAgeLink()->SpawnPoint().GetName(), - arrsize(joinAgeOp->age.spawnPtName) - ); - QueueOp(joinAgeOp); + msg->Ref(); + IDoLink(msg); } - else + else if (pre == kLinkDeferred) + { + msg->Ref(); + fDeferredLink = msg; + } + else if (pre == kLinkFailed) { hsLogEntry( nc->ErrorMsg( "IPreProcessLink failed. Not linking." ) ); // Restore previous age info state. @@ -407,6 +395,43 @@ bool plNetLinkingMgr::IProcessLinkToAgeMsg( plLinkToAgeMsg * msg ) //////////////////////////////////////////////////////////////////// +void plNetLinkingMgr::IDoLink(plLinkToAgeMsg* msg) +{ + plNetClientMgr* nc = plNetClientMgr::GetInstance(); + GetAgeLink()->SetSpawnPoint(msg->GetAgeLink()->SpawnPoint()); + + if (fLinkedIn) { + // Set the link out animation we should use + if (plSceneObject *localSO = plSceneObject::ConvertNoRef(nc->GetLocalPlayer())) { + plArmatureMod *avMod = const_cast(plArmatureMod::ConvertNoRef(localSO->GetModifierByType(plArmatureMod::Index()))); + avMod->SetLinkInAnim(msg->GetLinkInAnimName()); + } + // Queue leave op + NlmLeaveAgeOp * leaveAgeOp = NEWZERO(NlmLeaveAgeOp); + QueueOp(leaveAgeOp); + } + + // Queue join op + NlmJoinAgeOp * joinAgeOp = NEWZERO(NlmJoinAgeOp); + joinAgeOp->age.ageInstId = (Uuid) *GetAgeLink()->GetAgeInfo()->GetAgeInstanceGuid(); + StrCopy( + joinAgeOp->age.ageDatasetName, + GetAgeLink()->GetAgeInfo()->GetAgeFilename(), + arrsize(joinAgeOp->age.ageDatasetName) + ); + StrCopy( + joinAgeOp->age.spawnPtName, + GetAgeLink()->SpawnPoint().GetName(), + arrsize(joinAgeOp->age.spawnPtName) + ); + QueueOp(joinAgeOp); + + // UnRef + msg->UnRef(); +} + +//////////////////////////////////////////////////////////////////// + bool plNetLinkingMgr::IProcessLinkingMgrMsg( plLinkingMgrMsg * msg ) { plNetClientMgr * nc = plNetClientMgr::GetInstance(); @@ -458,6 +483,49 @@ bool plNetLinkingMgr::IProcessLinkingMgrMsg( plLinkingMgrMsg * msg ) return result; } +//////////////////////////////////////////////////////////////////// + +bool plNetLinkingMgr::IProcessVaultNotifyMsg(plVaultNotifyMsg* msg) +{ + // No deferred link? Bye bye. + if (fDeferredLink == nil) + return false; + + plAgeLinkStruct* cur = GetAgeLink(); + RelVaultNode* cVaultLink = nil; + switch (msg->GetType()) + { + case plVaultNotifyMsg::kRegisteredChildAgeLink: + case plVaultNotifyMsg::kRegisteredOwnedAge: + case plVaultNotifyMsg::kRegisteredSubAgeLink: + cVaultLink = VaultGetNodeIncRef(msg->GetArgs()->GetInt(plNetCommon::VaultTaskArgs::kAgeLinkNode)); + break; + default: + return false; + } + + if (cVaultLink != nil) + { + // This is something that Cyan does... >.< + // It's very useful though... + VaultAgeLinkNode accLink(cVaultLink); + accLink.CopyTo(cur); + if (RelVaultNode* rvnInfo = cVaultLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) + { + VaultAgeInfoNode accInfo(rvnInfo); + accInfo.CopyTo(cur->GetAgeInfo()); + rvnInfo->DecRef(); + } + + IDoLink(fDeferredLink); + fDeferredLink = nil; + return true; + + cVaultLink->DecRef(); + } + + return false; +} //////////////////////////////////////////////////////////////////// @@ -681,23 +749,27 @@ void plNetLinkingMgr::OfferLinkToPlayer( const plAgeInfoStruct * inInfo, UInt32 void plNetLinkingMgr::IPostProcessLink( void ) { - bool city = (0 == stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kCityAgeFilename )); - bool hood = (0 == stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kNeighborhoodAgeFilename )); - bool psnl = (0 == stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kPersonalAgeFilename )); + // Grab some useful things... + plAgeLinkStruct* link = GetAgeLink(); + plAgeInfoStruct* info = link->GetAgeInfo(); + + bool city = (stricmp(info->GetAgeFilename(), kCityAgeFilename) == 0); + bool hood = (stricmp(info->GetAgeFilename(), kNeighborhoodAgeFilename) == 0); + bool psnl = (stricmp(info->GetAgeFilename(), kPersonalAgeFilename) == 0); // Update our online status if (RelVaultNode * rvnInfo = VaultGetPlayerInfoNodeIncRef()) { VaultPlayerInfoNode accInfo(rvnInfo); wchar ageInstName[MAX_PATH]; - Uuid ageInstGuid = *GetAgeLink()->GetAgeInfo()->GetAgeInstanceGuid(); - StrToUnicode(ageInstName, GetAgeLink()->GetAgeInfo()->GetAgeInstanceName(), arrsize(ageInstName)); + Uuid ageInstGuid = *info->GetAgeInstanceGuid(); + StrToUnicode(ageInstName, info->GetAgeInstanceName(), arrsize(ageInstName)); accInfo.SetAgeInstName(ageInstName); accInfo.SetAgeInstUuid(ageInstGuid); accInfo.SetOnline(true); rvnInfo->DecRef(); } - switch (GetAgeLink()->GetLinkingRules()) { + switch (link->GetLinkingRules()) { case plNetCommon::LinkingRules::kOwnedBook: { // SPECIAL CASE: City: Every player ever created would be in the list; avoid that. @@ -710,10 +782,12 @@ void plNetLinkingMgr::IPostProcessLink( void ) if (fldr && info) if (!fldr->IsParentOf(info->nodeId, 1)) - VaultAddChildNodeAndWait( + VaultAddChildNode( fldr->nodeId, info->nodeId, - NetCommGetPlayer()->playerInt + NetCommGetPlayer()->playerInt, + nil, + nil ); if (fldr) @@ -735,10 +809,12 @@ void plNetLinkingMgr::IPostProcessLink( void ) if (fldr && info) if (!fldr->IsParentOf(info->nodeId, 1)) - VaultAddChildNodeAndWait( + VaultAddChildNode( fldr->nodeId, info->nodeId, - NetCommGetPlayer()->playerInt + NetCommGetPlayer()->playerInt, + nil, + nil ); if (fldr) @@ -752,7 +828,7 @@ void plNetLinkingMgr::IPostProcessLink( void ) case plNetCommon::LinkingRules::kSubAgeBook: { // Register the previous age as a sub age of the current one so that we can link back to that instance plAgeLinkStruct subAgeLink; - VaultAgeFindOrCreateSubAgeLinkAndWait(GetPrevAgeLink()->GetAgeInfo(), &subAgeLink, NetCommGetAge()->ageInstId); + VaultAgeFindOrCreateSubAgeLink(GetPrevAgeLink()->GetAgeInfo(), &subAgeLink, NetCommGetAge()->ageInstId); } break; } @@ -760,16 +836,19 @@ void plNetLinkingMgr::IPostProcessLink( void ) //////////////////////////////////////////////////////////////////// -bool plNetLinkingMgr::IPreProcessLink( void ) +UInt8 plNetLinkingMgr::IPreProcessLink( void ) { - plNetClientMgr * nc = plNetClientMgr::GetInstance(); + // Grab some stuff we're gonna use extensively + plNetClientMgr* nc = plNetClientMgr::GetInstance(); + plAgeLinkStruct* link = GetAgeLink(); + plAgeInfoStruct* info = link->GetAgeInfo(); - bool success = true; + PreProcessResult success = kLinkImmediately; if ( nc->GetFlagsBit( plNetClientMgr::kNullSend ) ) { hsLogEntry( nc->DebugMsg( "NetClientMgr nullsend. Not linking." ) ); - return false; + return kLinkFailed; } #if 0 @@ -787,7 +866,7 @@ bool plNetLinkingMgr::IPreProcessLink( void ) VaultPlayerInfoNode accInfo(rvnInfo); wchar ageInstName[MAX_PATH]; Uuid ageInstGuid = *GetAgeLink()->GetAgeInfo()->GetAgeInstanceGuid(); - StrToUnicode(ageInstName, GetAgeLink()->GetAgeInfo()->GetAgeInstanceName(), arrsize(ageInstName)); + StrToUnicode(ageInstName, info->GetAgeInstanceName(), arrsize(ageInstName)); accInfo.SetAgeInstName(ageInstName); accInfo.SetAgeInstUuid(ageInstGuid); accInfo.SetOnline(true); @@ -797,50 +876,50 @@ bool plNetLinkingMgr::IPreProcessLink( void ) //------------------------------------------------------------------------ // Fixup empty fields - if ( GetAgeLink()->GetAgeInfo()->HasAgeFilename() ) + if (info->HasAgeFilename()) { GetAgeLink()->GetAgeInfo()->SetAgeFilename( plNetLinkingMgr::GetProperAgeName( GetAgeLink()->GetAgeInfo()->GetAgeFilename() ).c_str() ); - if ( !GetAgeLink()->GetAgeInfo()->HasAgeInstanceName() ) + if (!info->HasAgeInstanceName()) { - GetAgeLink()->GetAgeInfo()->SetAgeInstanceName( GetAgeLink()->GetAgeInfo()->GetAgeFilename() ); + info->SetAgeInstanceName(info->GetAgeFilename()); } } hsLogEntry( nc->DebugMsg( "plNetLinkingMgr: Pre-Process: Linking with %s rules...", - plNetCommon::LinkingRules::LinkingRuleStr( GetAgeLink()->GetLinkingRules() ) ) ); + plNetCommon::LinkingRules::LinkingRuleStr( link->GetLinkingRules() ) ) ); //------------------------------------------------------------------------ // SPECIAL CASE: StartUp: force basic link - if ( stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kStartUpAgeFilename )==0 ) + if (stricmp(info->GetAgeFilename(), kStartUpAgeFilename) == 0) { - GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kBasicLink ); + link->SetLinkingRules( plNetCommon::LinkingRules::kBasicLink ); } //------------------------------------------------------------------------ // SPECIAL CASE: Nexus: force original link - if ( stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kNexusAgeFilename )==0 ) + if (stricmp(info->GetAgeFilename(), kNexusAgeFilename) == 0) { - GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kOriginalBook ); + link->SetLinkingRules(plNetCommon::LinkingRules::kOriginalBook); } //------------------------------------------------------------------------ // SPECIAL CASE: ACA: force original link - if ( stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kAvCustomizationFilename )==0 ) + if (stricmp(info->GetAgeFilename(), kAvCustomizationFilename ) == 0) { - GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kOriginalBook ); + link->SetLinkingRules(plNetCommon::LinkingRules::kOriginalBook); } hsLogEntry( nc->DebugMsg( "plNetLinkingMgr: Process: Linking with %s rules...", - plNetCommon::LinkingRules::LinkingRuleStr( GetAgeLink()->GetLinkingRules() ) ) ); + plNetCommon::LinkingRules::LinkingRuleStr( link->GetLinkingRules() ) ) ); - switch ( GetAgeLink()->GetLinkingRules() ) + switch ( link->GetLinkingRules() ) { //-------------------------------------------------------------------- // BASIC LINK. Link to a unique instance of the age, if no instance specified. case plNetCommon::LinkingRules::kBasicLink: - if (!GetAgeLink()->GetAgeInfo()->HasAgeInstanceGuid()) - GetAgeLink()->GetAgeInfo()->SetAgeInstanceGuid(&plUUID(GuidGenerate())); + if (!info->HasAgeInstanceGuid()) + info->SetAgeInstanceGuid(&plUUID(GuidGenerate())); break; //-------------------------------------------------------------------- @@ -851,12 +930,12 @@ bool plNetLinkingMgr::IPreProcessLink( void ) // we just want to find out if we own *any* link to the age, not the specific // link that we're linking through plAgeInfoStruct ageInfo; - ageInfo.SetAgeFilename(GetAgeLink()->GetAgeInfo()->GetAgeFilename()); + ageInfo.SetAgeFilename(info->GetAgeFilename()); plAgeLinkStruct ownedLink; if (!VaultGetOwnedAgeLink(&ageInfo, &ownedLink)) { // Fill in fields for new age create. - if ( !GetAgeLink()->GetAgeInfo()->HasAgeUserDefinedName() ) + if (!info->HasAgeUserDefinedName()) { // set user-defined name std::string title; @@ -865,25 +944,28 @@ bool plNetLinkingMgr::IPreProcessLink( void ) xtl::format( title, "%s'", nc->GetPlayerName() ); else xtl::format( title, "%s's", nc->GetPlayerName() ); - GetAgeLink()->GetAgeInfo()->SetAgeUserDefinedName( title.c_str() ); + info->SetAgeUserDefinedName(title.c_str()); } - if ( !GetAgeLink()->GetAgeInfo()->HasAgeDescription() ) + if (!info->HasAgeDescription()) { // set description std::string desc; unsigned nameLen = StrLen(nc->GetPlayerName()); if (nc->GetPlayerName()[nameLen - 1] == 's' || nc->GetPlayerName()[nameLen - 1] == 'S') - xtl::format( desc, "%s' %s", nc->GetPlayerName(), GetAgeLink()->GetAgeInfo()->GetAgeInstanceName() ); + xtl::format( desc, "%s' %s", nc->GetPlayerName(), info->GetAgeInstanceName() ); else - xtl::format( desc, "%s's %s", nc->GetPlayerName(), GetAgeLink()->GetAgeInfo()->GetAgeInstanceName() ); - GetAgeLink()->GetAgeInfo()->SetAgeDescription( desc.c_str() ); + xtl::format( desc, "%s's %s", nc->GetPlayerName(), info->GetAgeInstanceName() ); + info->SetAgeDescription( desc.c_str() ); } - if (!GetAgeLink()->GetAgeInfo()->HasAgeInstanceGuid()) { - GetAgeLink()->GetAgeInfo()->SetAgeInstanceGuid(&plUUID(GuidGenerate())); + if (!info->HasAgeInstanceGuid()) { + info->SetAgeInstanceGuid(&plUUID(GuidGenerate())); } // register this as an owned age now before we link to it. - VaultRegisterOwnedAgeAndWait(GetAgeLink()); + // Note: We MUST break or the OwnedBook code will fail! + VaultRegisterOwnedAge(link); + success = kLinkDeferred; + break; } else if (RelVaultNode * linkNode = VaultGetOwnedAgeLinkIncRef(&ageInfo)) { // We have the age in our AgesIOwnFolder. If its volatile, dump it for the new one. @@ -891,7 +973,7 @@ bool plNetLinkingMgr::IPreProcessLink( void ) if (linkAcc.volat) { if (VaultUnregisterOwnedAgeAndWait(&ageInfo)) { // Fill in fields for new age create. - if ( !GetAgeLink()->GetAgeInfo()->HasAgeUserDefinedName() ) + if ( !info->HasAgeUserDefinedName() ) { // set user-defined name std::string title; @@ -900,32 +982,36 @@ bool plNetLinkingMgr::IPreProcessLink( void ) xtl::format( title, "%s'", nc->GetPlayerName() ); else xtl::format( title, "%s's", nc->GetPlayerName() ); - GetAgeLink()->GetAgeInfo()->SetAgeUserDefinedName( title.c_str() ); + info->SetAgeUserDefinedName( title.c_str() ); } - if ( !GetAgeLink()->GetAgeInfo()->HasAgeDescription() ) + if ( !info->HasAgeDescription() ) { // set description std::string desc; unsigned nameLen = StrLen(nc->GetPlayerName()); if (nc->GetPlayerName()[nameLen - 1] == 's' || nc->GetPlayerName()[nameLen - 1] == 'S') - xtl::format( desc, "%s' %s", nc->GetPlayerName(), GetAgeLink()->GetAgeInfo()->GetAgeInstanceName() ); + xtl::format( desc, "%s' %s", nc->GetPlayerName(), info->GetAgeInstanceName() ); else - xtl::format( desc, "%s's %s", nc->GetPlayerName(), GetAgeLink()->GetAgeInfo()->GetAgeInstanceName() ); - GetAgeLink()->GetAgeInfo()->SetAgeDescription( desc.c_str() ); + xtl::format( desc, "%s's %s", nc->GetPlayerName(), info->GetAgeInstanceName() ); + info->SetAgeDescription( desc.c_str() ); } - if (!GetAgeLink()->GetAgeInfo()->HasAgeInstanceGuid()) { - GetAgeLink()->GetAgeInfo()->SetAgeInstanceGuid(&plUUID(GuidGenerate())); + if (!info->HasAgeInstanceGuid()) { + info->SetAgeInstanceGuid(&plUUID(GuidGenerate())); } - VaultRegisterOwnedAgeAndWait(GetAgeLink()); + VaultRegisterOwnedAge(link); + + // Note: We MUST break or the OwnedBook code will fail! + success = kLinkDeferred; + break; } } else { - if (stricmp(GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kNeighborhoodAgeFilename) == 0) { - // if we get here then its because we're linking to a neighborhood that we don't belong to + if (stricmp(info->GetAgeFilename(), kNeighborhoodAgeFilename) == 0) { + // if we get here then it's because we're linking to a neighborhood that we don't belong to // and our own neighborhood book is not volatile, so really we want to basic link - GetAgeLink()->SetLinkingRules(plNetCommon::LinkingRules::kBasicLink); - success = true; + link->SetLinkingRules(plNetCommon::LinkingRules::kBasicLink); + success = kLinkImmediately; break; } @@ -933,7 +1019,7 @@ bool plNetLinkingMgr::IPreProcessLink( void ) linkNode->DecRef(); } } - GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kOwnedBook ); + link->SetLinkingRules( plNetCommon::LinkingRules::kOwnedBook ); // falls thru to OWNED BOOK case... //-------------------------------------------------------------------- @@ -941,14 +1027,14 @@ bool plNetLinkingMgr::IPreProcessLink( void ) case plNetCommon::LinkingRules::kOwnedBook: { plAgeLinkStruct ownedLink; - if (VaultGetOwnedAgeLink(GetAgeLink()->GetAgeInfo(), &ownedLink)) { - GetAgeLink()->GetAgeInfo()->CopyFrom(ownedLink.GetAgeInfo()); + if (VaultGetOwnedAgeLink(info, &ownedLink)) { + info->CopyFrom(ownedLink.GetAgeInfo()); // Remember spawn point (treasure book support) - plSpawnPointInfo theSpawnPt = GetAgeLink()->SpawnPoint(); - VaultAddOwnedAgeSpawnPoint(*GetAgeLink()->GetAgeInfo()->GetAgeInstanceGuid(), theSpawnPt); + plSpawnPointInfo theSpawnPt = link->SpawnPoint(); + VaultAddOwnedAgeSpawnPoint(*info->GetAgeInstanceGuid(), theSpawnPt); } else { - success = false; + success = kLinkFailed; } } break; @@ -958,10 +1044,10 @@ bool plNetLinkingMgr::IPreProcessLink( void ) case plNetCommon::LinkingRules::kVisitBook: { plAgeLinkStruct visitLink; - if (VaultGetVisitAgeLink(GetAgeLink()->GetAgeInfo(), &visitLink)) - GetAgeLink()->GetAgeInfo()->CopyFrom(visitLink.GetAgeInfo()); + if (VaultGetVisitAgeLink(info, &visitLink)) + info->CopyFrom(visitLink.GetAgeInfo()); else - success = false; + success = kLinkFailed; } break; @@ -971,10 +1057,10 @@ bool plNetLinkingMgr::IPreProcessLink( void ) case plNetCommon::LinkingRules::kSubAgeBook: { plAgeLinkStruct subAgeLink; - if (VaultAgeFindOrCreateSubAgeLinkAndWait(GetAgeLink()->GetAgeInfo(), &subAgeLink, NetCommGetAge()->ageInstId)) - GetAgeLink()->GetAgeInfo()->CopyFrom(subAgeLink.GetAgeInfo()); + if (VaultAgeFindOrCreateSubAgeLink(info, &subAgeLink, NetCommGetAge()->ageInstId)) + info->CopyFrom(subAgeLink.GetAgeInfo()); else - success = false; + success = kLinkDeferred; } break; @@ -985,28 +1071,38 @@ bool plNetLinkingMgr::IPreProcessLink( void ) { plAgeLinkStruct childLink; wchar parentAgeName[MAX_PATH]; - if (GetAgeLink()->HasParentAgeFilename()) { - StrToUnicode(parentAgeName, GetAgeLink()->GetParentAgeFilename(), arrsize(parentAgeName)); - success = VaultAgeFindOrCreateChildAgeLinkAndWait(parentAgeName, GetAgeLink()->GetAgeInfo(), &childLink); - } - else { - success = VaultAgeFindOrCreateChildAgeLinkAndWait(nil, GetAgeLink()->GetAgeInfo(), &childLink); + if (link->HasParentAgeFilename()) + StrToUnicode(parentAgeName, link->GetParentAgeFilename(), arrsize(parentAgeName)); + + switch(VaultAgeFindOrCreateChildAgeLink( + (link->HasParentAgeFilename() ? parentAgeName : nil), + info, + &childLink)) + { + case hsFail: + success = kLinkFailed; + break; + case FALSE: + success = kLinkDeferred; + break; + case TRUE: + success = kLinkImmediately; } - if (success) - GetAgeLink()->GetAgeInfo()->CopyFrom(childLink.GetAgeInfo()); + if (success == kLinkImmediately) + info->CopyFrom(childLink.GetAgeInfo()); } break; //-------------------------------------------------------------------- // ??? - DEFAULT_FATAL(GetAgeLink()->GetLinkingRules()); + DEFAULT_FATAL(link->GetLinkingRules()); } hsLogEntry( nc->DebugMsg( "plNetLinkingMgr: Post-Process: Linking with %s rules...", - plNetCommon::LinkingRules::LinkingRuleStr( GetAgeLink()->GetLinkingRules() ) ) ); + plNetCommon::LinkingRules::LinkingRuleStr( link->GetLinkingRules() ) ) ); - hsAssert( GetAgeLink()->GetAgeInfo()->HasAgeFilename(), "AgeLink has no AgeFilename. Link will fail." ); + hsAssert( info->HasAgeFilename(), "AgeLink has no AgeFilename. Link will fail." ); return success; } diff --git a/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.h b/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.h index 1f905c09..1ec7bd50 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.h +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.h @@ -50,6 +50,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../plMessage/plLinkToAgeMsg.h" class plMessage; +class plVaultNotifyMsg; struct plNCAgeJoiner; struct plNCAgeLeaver; @@ -91,10 +92,23 @@ class plNetLinkingMgr kLinkPlayerToPrevAge }; - bool IPreProcessLink( void ); + plLinkToAgeMsg* fDeferredLink; + + enum PreProcessResult { + // Old style IPreProcessLink style "false" result + kLinkFailed, + // Old style IPreProcessLink style "true" result + kLinkImmediately, + // Defer the link until later, don't trash the structs + kLinkDeferred, + }; + + UInt8 IPreProcessLink( void ); void IPostProcessLink( void ); bool IProcessLinkingMgrMsg( plLinkingMgrMsg * msg ); bool IProcessLinkToAgeMsg( plLinkToAgeMsg * msg ); + void IDoLink(plLinkToAgeMsg* link); + bool IProcessVaultNotifyMsg(plVaultNotifyMsg* msg); bool IDispatchMsg( plMessage * msg, UInt32 playerID ); diff --git a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp index a8e4a5dc..b1943163 100644 --- a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp +++ b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp @@ -2550,6 +2550,113 @@ bool VaultGetVisitAgeLink (const plAgeInfoStruct * info, class plAgeLinkStruct * return true; } +//============================================================================ +namespace _VaultRegisterVisitAge { + struct _Params { + + plSpawnPointInfo* fSpawn; + void* fAgeInfoId; + + ~_Params() { + DEL(fSpawn); + } + }; + + void _CreateAgeLinkNode(ENetError result, void* state, void* param, RelVaultNode* node) { + if (IS_NET_ERROR(result)) { + LogMsg(kLogError, "RegisterVisitAge: Failed to create AgeLink (async)"); + DEL(param); + return; + } + + _Params* p = (_Params*)param; + RelVaultNode* ageInfo = VaultGetNodeIncRef((UInt32)p->fAgeInfoId); + + // Add ourselves to the Can Visit folder of the age + if (RelVaultNode * playerInfo = VaultGetPlayerInfoNodeIncRef()) { + if (RelVaultNode* canVisit = ageInfo->GetChildPlayerInfoListNodeIncRef(plVault::kCanVisitFolder, 1)) { + VaultAddChildNode(canVisit->nodeId, playerInfo->nodeId, 0, nil, nil); + canVisit->DecRef(); + } + + playerInfo->DecRef(); + } + + // Get our AgesICanVisit folder + if (RelVaultNode* iCanVisit = VaultGetAgesICanVisitFolderIncRef()) { + VaultAddChildNode(node->nodeId, ageInfo->nodeId, 0, nil, nil); + VaultAddChildNode(iCanVisit->nodeId, node->nodeId, 0, nil, nil); + } + + // Update the AgeLink with a spawn point + VaultAgeLinkNode access(node); + access.AddSpawnPoint(*p->fSpawn); + + // Send out the VaultNotify msg + plVaultNotifyMsg * msg = NEWZERO(plVaultNotifyMsg); + msg->SetType(plVaultNotifyMsg::kRegisteredVisitAge); + msg->SetResultCode(true); + msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->nodeId); + msg->Send(); + + //Don't leak memory + DEL(param); + } + + void _DownloadCallback(ENetError result, void* param) { + if (IS_NET_ERROR(result)) { + LogMsg(kLogError, "RegisterVisitAge: Failed to download age vault (async)"); + DEL(param); + return; + } + + // Create the AgeLink node + VaultCreateNode(plVault::kNodeType_AgeLink, (FVaultCreateNodeCallback)_CreateAgeLinkNode, nil, param); + } + + void _InitAgeCallback(ENetError result, void* state, void* param, UInt32 ageVaultId, UInt32 ageInfoId) { + if (IS_NET_ERROR(result)) { + LogMsg(kLogError, "RegisterVisitAge: Failed to init age vault (async)"); + DEL(param); + return; + } + + // Save the AgeInfo nodeID, then download the age vault + _Params* p = (_Params*)param; + p->fAgeInfoId = (void*)ageInfoId; + + VaultDownload(L"RegisterVisitAge", + ageInfoId, + (FVaultDownloadCallback)_DownloadCallback, + param, + nil, + nil + ); + } +}; + +void VaultRegisterVisitAge(const plAgeLinkStruct* link) { + using namespace _VaultRegisterVisitAge; + + // Test to see if we already have this visit age... + plAgeLinkStruct existing; + if (VaultGetVisitAgeLink(link->GetAgeInfo(), &existing)) + return; + + // Still here? We need to actually do some work, then. + _Params* p = TRACKED_NEW _Params; + p->fSpawn = TRACKED_NEW plSpawnPointInfo(link->SpawnPoint()); + + // This doesn't actually *create* a new age but rather fetches the + // already existing age vault. Weird? Yes... + VaultInitAge(link->GetAgeInfo(), + kNilGuid, + (FVaultInitAgeCallback)_InitAgeCallback, + nil, + p + ); +} + //============================================================================ namespace _VaultRegisterOwnedAgeAndWait { @@ -2807,6 +2914,123 @@ bool VaultRegisterOwnedAgeAndWait (const plAgeLinkStruct * link) { return result; } +//============================================================================ +namespace _VaultRegisterOwnedAge { + struct _Params { + plSpawnPointInfo* fSpawn; + void* fAgeInfoId; + + ~_Params() { + DEL(fSpawn); + } + }; + + void _AddAgeInfoNode(ENetError result, void* param) { + if (IS_NET_ERROR(result)) + LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to add info to link (async)"); + } + + void _AddAgeLinkNode(ENetError result, void* param) { + if (IS_NET_ERROR(result)) + LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to add age to bookshelf (async)"); + } + + void _AddPlayerInfoNode(ENetError result, void* param) { + if (IS_NET_ERROR(result)) + LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to add playerInfo to ageOwners (async)"); + } + + void _CreateAgeLinkNode(ENetError result, void* state, void* param, RelVaultNode* node) { + if (IS_NET_ERROR(result)) { + LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to create AgeLink (async)"); + DEL(param); + return; + } + + // Grab our params + _Params* p = (_Params*)param; + + // Set swpoint + VaultAgeLinkNode aln(node); + aln.AddSpawnPoint(*(p->fSpawn)); + + // Make some refs + RelVaultNode* agesIOwn = VaultGetAgesIOwnFolderIncRef(); + RelVaultNode* plyrInfo = VaultGetPlayerInfoNodeIncRef(); + VaultAddChildNode(agesIOwn->nodeId, node->nodeId, 0, (FVaultAddChildNodeCallback)_AddAgeLinkNode, nil); + VaultAddChildNode(node->nodeId, (UInt32)p->fAgeInfoId, 0, (FVaultAddChildNodeCallback)_AddAgeInfoNode, nil); + + // Add our PlayerInfo to important places + if (RelVaultNode* rvnAgeInfo = VaultGetNodeIncRef((UInt32)p->fAgeInfoId)) { + if (RelVaultNode* rvnAgeOwners = rvnAgeInfo->GetChildPlayerInfoListNodeIncRef(plVault::kAgeOwnersFolder, 1)) { + VaultAddChildNode(rvnAgeOwners->nodeId, plyrInfo->nodeId, 0, (FVaultAddChildNodeCallback)_AddPlayerInfoNode, nil); + rvnAgeOwners->DecRef(); + } + + rvnAgeInfo->DecRef(); + } + + // Fire off vault callbacks + plVaultNotifyMsg* msg = NEWZERO(plVaultNotifyMsg); + msg->SetType(plVaultNotifyMsg::kRegisteredOwnedAge); + msg->SetResultCode(result); + msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->nodeId); + msg->Send(); + + // Don't leak memory + agesIOwn->DecRef(); + plyrInfo->DecRef(); + DEL(p); + } + + void _DownloadCallback(ENetError result, void* param) { + if (IS_NET_ERROR(result)) { + LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to download age vault (async)"); + DEL(param); + } else + VaultCreateNode(plVault::kNodeType_AgeLink, (FVaultCreateNodeCallback)_CreateAgeLinkNode, nil, param); + } + + void _InitAgeCallback(ENetError result, void* state, void* param, UInt32 ageVaultId, UInt32 ageInfoVaultId) { + if (IS_NET_SUCCESS(result)) { + _Params* p = TRACKED_NEW _Params(); + p->fAgeInfoId = (void*)ageInfoVaultId; + p->fSpawn = (plSpawnPointInfo*)param; + + VaultDownload( + L"RegisterOwnedAge", + ageInfoVaultId, + (FVaultDownloadCallback)_DownloadCallback, + p, + nil, + nil); + } else + LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to init age (async)"); + } +}; // namespace _VaultRegisterOwnedAge + +void VaultRegisterOwnedAge(const plAgeLinkStruct* link) { + using namespace _VaultRegisterOwnedAge; + + RelVaultNode* agesIOwn = VaultGetAgesIOwnFolderIncRef(); + if (agesIOwn == nil) { + LogMsg(kLogError, "VaultRegisterOwnedAge: Couldn't find the stupid AgesIOwnfolder!"); + return; + } + + // Make sure we don't already have the age + plAgeLinkStruct existing; + if (VaultGetOwnedAgeLink(link->GetAgeInfo(), &existing)) + return; + + // Let's go async, my friend :) + VaultInitAge(link->GetAgeInfo(), + kNilGuid, + (FVaultInitAgeCallback)_InitAgeCallback, + nil, + TRACKED_NEW plSpawnPointInfo(link->SpawnPoint())); +} + //============================================================================ namespace _VaultRegisterVisitAgeAndWait { @@ -3220,6 +3444,38 @@ bool VaultHasChronicleEntry (const wchar entryName[], int entryType) { return false; } +//============================================================================ +void VaultAddChronicleEntry (const wchar entryName[], int entryType, const wchar entryValue[]) { + // Sometimes we try to create chrons in StartUp. + // This is bad... + if (GetPlayerNode() == nil) + return; + + if (RelVaultNode* rvnChrn = VaultFindChronicleEntryIncRef(entryName, entryType)) { + VaultChronicleNode chrnNode(rvnChrn); + chrnNode.SetEntryValue(entryValue); + rvnChrn->DecRef(); + } else { + NetVaultNode* templateNode = NEWZERO(NetVaultNode); + templateNode->IncRef(); + templateNode->SetNodeType(plVault::kNodeType_Chronicle); + VaultChronicleNode chrnNode(templateNode); + chrnNode.SetEntryName(entryName); + chrnNode.SetEntryType(entryType); + chrnNode.SetEntryValue(entryValue); + VaultCreateNode(templateNode, (FVaultCreateNodeCallback)(_VaultAddChronicleEntryCB), nil, nil); + templateNode->DecRef(); + } +} + +void _VaultAddChronicleEntryCB(ENetError result, void* state, void * param, RelVaultNode* node) { + if (result == ENetError::kNetSuccess) { + RelVaultNode* rvnFldr = GetChildFolderNode(GetPlayerNode(), plVault::kChronicleFolder, 1); + if (rvnFldr != nil) + VaultAddChildNode(rvnFldr->nodeId, node->nodeId, 0, nil, nil); + } +} + //============================================================================ void VaultAddChronicleEntryAndWait ( const wchar entryName[], @@ -3457,7 +3713,7 @@ void VaultProcessVisitNote(RelVaultNode * rvnVisit) { plAgeLinkStruct link; if (visitAcc.GetVisitInfo(link.GetAgeInfo())) { // Add it to our "ages i can visit" folder - VaultRegisterVisitAgeAndWait(&link); + VaultRegisterVisitAge(&link); } // remove it from the inbox VaultRemoveChildNode(rvnInbox->nodeId, rvnVisit->nodeId, nil, nil); @@ -3504,7 +3760,7 @@ void VaultProcessPlayerInbox () { plAgeLinkStruct link; if (visitAcc.GetVisitInfo(link.GetAgeInfo())) { // Add it to our "ages i can visit" folder - VaultRegisterVisitAgeAndWait(&link); + VaultRegisterVisitAge(&link); } // remove it from the inbox VaultRemoveChildNode(rvnInbox->nodeId, rvnVisit->nodeId, nil, nil); @@ -4196,6 +4452,89 @@ bool VaultAgeFindOrCreateSubAgeLinkAndWait ( } +//============================================================================ +namespace _VaultCreateSubAge { + void _CreateNodeCallback(ENetError result, void* state, void* param, RelVaultNode* node) { + if (IS_NET_ERROR(result)) { + LogMsg(kLogError, "CreateSubAge: Failed to create AgeLink (async)"); + return; + } + + // Add the children to the right places + VaultAddChildNode(node->nodeId, (UInt32)param, 0, nil, nil); + if (RelVaultNode* saFldr = VaultGetAgeSubAgesFolderIncRef()) { + VaultAddChildNode(saFldr->nodeId, node->nodeId, 0, nil, nil); + saFldr->DecRef(); + } else + LogMsg(kLogError, "CreateSubAge: Couldn't find SubAges folder (async)"); + + // Send the VaultNotify that the plNetLinkingMgr wants... + plVaultNotifyMsg * msg = NEWZERO(plVaultNotifyMsg); + msg->SetType(plVaultNotifyMsg::kRegisteredSubAgeLink); + msg->SetResultCode(result); + msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->nodeId); + msg->Send(); + } + + void _DownloadCallback(ENetError result, void* param) { + if (IS_NET_ERROR(result)) { + LogMsg(kLogError, "CreateSubAge: Failed to download age vault (async)"); + return; + } + + // Create the AgeLink node + VaultCreateNode(plVault::kNodeType_AgeLink, + (FVaultCreateNodeCallback)_CreateNodeCallback, + nil, + param + ); + } + + void _InitAgeCallback(ENetError result, void* state, void* param, UInt32 ageVaultId, UInt32 ageInfoId) { + if (IS_NET_ERROR(result)) { + LogMsg(kLogError, "CreateSubAge: Failed to init age (async)"); + return; + } + + // Download age vault + VaultDownload(L"CreateSubAge", + ageInfoId, + (FVaultDownloadCallback)_DownloadCallback, + (void*)ageInfoId, + nil, + nil + ); + } +}; // namespace _VaultCreateSubAge + +bool VaultAgeFindOrCreateSubAgeLink(const plAgeInfoStruct* info, plAgeLinkStruct* link, const Uuid& parentUuid) { + using namespace _VaultCreateSubAge; + + // First, try to find an already existing subage + if (RelVaultNode* rvnLink = VaultGetSubAgeLinkIncRef(info)) { + VaultAgeLinkNode accLink(rvnLink); + accLink.CopyTo(link); + + if (RelVaultNode* rvnInfo = rvnLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) { + VaultAgeInfoNode accInfo(rvnInfo); + accInfo.CopyTo(link->GetAgeInfo()); + rvnInfo->DecRef(); + } + + rvnLink->DecRef(); + return true; + } + + VaultInitAge(info, + parentUuid, + (FVaultInitAgeCallback)_InitAgeCallback, + nil, + nil + ); + + return false; +} + //============================================================================ namespace _VaultCreateChildAgeAndWait { @@ -4472,6 +4811,144 @@ bool VaultAgeFindOrCreateChildAgeLinkAndWait ( return true; } +//============================================================================ +namespace _VaultCreateChildAge { + struct _Params { + void* fChildAgesFldr; + void* fAgeInfoId; + }; + + void _CreateNodeCallback(ENetError result, void* state, void* param, RelVaultNode* node) { + if (IS_NET_ERROR(result)) { + LogMsg(kLogError, "CreateChildAge: Failed to create AgeLink (async)"); + DEL(param); + return; + } + + _Params* p = (_Params*)param; + + // Add the children to the right places + VaultAddChildNode(node->nodeId, (UInt32)p->fAgeInfoId, 0, nil, nil); + VaultAddChildNode((UInt32)p->fChildAgesFldr, node->nodeId, 0, nil, nil); + + // Send the VaultNotify that the plNetLinkingMgr wants... + plVaultNotifyMsg * msg = NEWZERO(plVaultNotifyMsg); + msg->SetType(plVaultNotifyMsg::kRegisteredChildAgeLink); + msg->SetResultCode(result); + msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->nodeId); + msg->Send(); + + DEL(param); + } + + void _DownloadCallback(ENetError result, void* param) { + if (IS_NET_ERROR(result)) { + LogMsg(kLogError, "CreateChildAge: Failed to download age vault (async)"); + DEL(param); + return; + } + + // Create the AgeLink node + VaultCreateNode(plVault::kNodeType_AgeLink, + (FVaultCreateNodeCallback)_CreateNodeCallback, + nil, + param + ); + } + + void _InitAgeCallback(ENetError result, void* state, void* param, UInt32 ageVaultId, UInt32 ageInfoId) { + if (IS_NET_ERROR(result)) { + LogMsg(kLogError, "CreateChildAge: Failed to init age (async)"); + DEL(param); + return; + } + + _Params* p = (_Params*)param; + p->fAgeInfoId = (void*)ageInfoId; + + // Download age vault + VaultDownload(L"CreateChildAge", + ageInfoId, + (FVaultDownloadCallback)_DownloadCallback, + param, + nil, + nil + ); + } +}; // namespace _VaultCreateAge + +UInt8 VaultAgeFindOrCreateChildAgeLink( + const wchar parentAgeName[], + const plAgeInfoStruct* info, + plAgeLinkStruct* link) +{ + using namespace _VaultCreateChildAge; + + // First, try to find an already existing ChildAge + char name[MAX_PATH]; + StrToAnsi(name, parentAgeName, arrsize(parentAgeName)); + plAgeInfoStruct search; + search.SetAgeFilename(name); + + RelVaultNode* rvnParentInfo = nil; + if (RelVaultNode* rvnParentLink = VaultGetOwnedAgeLinkIncRef(&search)) { + rvnParentInfo = rvnParentLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1); + rvnParentLink->DecRef(); + } else // Fallback to current age + rvnParentInfo = VaultGetAgeInfoNodeIncRef(); + + // Test to make sure nothing went horribly wrong... + if (rvnParentInfo == nil) { + LogMsg(kLogError, "CreateChildAge: Couldn't find the parent ageinfo (async)"); + return hsFail; + } + + // Still here? Try to find the Child Ages folder + UInt8 retval = hsFail; + if (RelVaultNode* rvnChildAges = rvnParentInfo->GetChildAgeInfoListNodeIncRef(plVault::kChildAgesFolder, 1)) { + const char* ageName = info->GetAgeFilename(); + wchar hack[MAX_PATH]; + StrToUnicode(hack, ageName, arrsize(ageName)); + + // Search for our age + NetVaultNode* temp = NEWZERO(NetVaultNode); + temp->SetNodeType(plVault::kNodeType_AgeInfo); + VaultAgeInfoNode theAge(temp); + theAge.SetAgeFilename(hack); + + if (RelVaultNode* rvnAgeInfo = rvnChildAges->GetChildNodeIncRef(temp, 2)) { + RelVaultNode* rvnAgeLink = rvnAgeInfo->GetParentAgeLinkIncRef(); + + VaultAgeLinkNode accAgeLink(rvnAgeLink); + accAgeLink.CopyTo(link); + VaultAgeInfoNode accAgeInfo(rvnAgeInfo); + accAgeInfo.CopyTo(link->GetAgeInfo()); + + rvnAgeLink->DecRef(); + rvnAgeInfo->DecRef(); + + retval = TRUE; + } else { + _Params* p = TRACKED_NEW _Params; + p->fChildAgesFldr = (void*)rvnChildAges->nodeId; + + VaultAgeInfoNode accParentInfo(rvnParentInfo); + VaultInitAge(info, + accParentInfo.ageInstUuid, + (FVaultInitAgeCallback)_InitAgeCallback, + nil, + p + ); + } + + temp->DecRef(); + rvnChildAges->DecRef(); + retval = FALSE; + } + + rvnParentInfo->DecRef(); + return retval; +} /***************************************************************************** * diff --git a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.h b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.h index 4efe1a68..0505b808 100644 --- a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.h +++ b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.h @@ -349,12 +349,16 @@ bool VaultSetAgePublicAndWait (NetVaultNode * ageInfoNode, bool publicOrNot); RelVaultNode * VaultGetVisitAgeLinkIncRef (const plAgeInfoStruct * info); bool VaultGetVisitAgeLink (const plAgeInfoStruct * info, class plAgeLinkStruct * link); bool VaultRegisterOwnedAgeAndWait (const plAgeLinkStruct * link); +void VaultRegisterOwnedAge(const plAgeLinkStruct* link); bool VaultRegisterVisitAgeAndWait (const plAgeLinkStruct * link); +void VaultRegisterVisitAge (const plAgeLinkStruct* link); bool VaultUnregisterOwnedAgeAndWait (const plAgeInfoStruct * info); bool VaultUnregisterVisitAgeAndWait (const plAgeInfoStruct * info); RelVaultNode * VaultFindChronicleEntryIncRef (const wchar entryName[], int entryType = -1); bool VaultHasChronicleEntry (const wchar entryName[], int entryType = -1); // if entry of same name and type already exists, value is updated +void VaultAddChronicleEntry (const wchar entryName[], int entryType, const wchar entryValue[]); +void _VaultAddChronicleEntryCB(ENetError result, void* state, void * param, RelVaultNode* node); void VaultAddChronicleEntryAndWait ( const wchar entryName[], int entryType, @@ -421,6 +425,7 @@ void VaultAgeUpdateAgeSDL (const class plStateDataRecord * rec); unsigned VaultAgeGetAgeTime (); +RelVaultNode * VaultGetSubAgeLinkIncRef (const plAgeInfoStruct * info); bool VaultAgeGetSubAgeLink ( const plAgeInfoStruct * info, plAgeLinkStruct * link @@ -430,12 +435,13 @@ bool VaultAgeFindOrCreateSubAgeLinkAndWait ( plAgeLinkStruct * link, const Uuid & parentAgeInstId ); +bool VaultAgeFindOrCreateSubAgeLink(const plAgeInfoStruct* info, plAgeLinkStruct* link, const Uuid& parentUuid); bool VaultAgeFindOrCreateChildAgeLinkAndWait ( const wchar parentAgeName[], // nil --> current age, non-nil --> owned age by given name const plAgeInfoStruct * info, plAgeLinkStruct * link ); - +UInt8 VaultAgeFindOrCreateChildAgeLink(const wchar parentAgeName[], const plAgeInfoStruct* info, plAgeLinkStruct* link); /*****************************************************************************