diff --git a/Sources/Plasma/FeatureLib/pfPython/pyVault.cpp b/Sources/Plasma/FeatureLib/pfPython/pyVault.cpp index 076a6a0d..b68a1b8b 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyVault.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyVault.cpp @@ -60,7 +60,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plSDL/plSDL.h" - //============================================================================ static PyObject * GetFolder (unsigned folderType) { PyObject * result = nil; @@ -349,7 +348,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); @@ -362,7 +361,9 @@ void pyVault::SendToDevice( pyVaultNode& node, const char * deviceName ) return; wchar wDevName[256]; - StrToUnicode(wDevName, deviceName, arrsize(wDevName)); + StrToUnicode(wDevName, deviceName, arrsize(wDevName)); + + // Note: This actually blocks (~Hoikas) VaultPublishNode(node.GetNode()->nodeId, wDevName); } @@ -528,12 +529,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 ) @@ -545,7 +548,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 ) @@ -557,22 +560,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; @@ -588,30 +601,29 @@ 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 + // Note: This doesn't actually block (~Hoikas) plAgeInfoStruct info; info.SetAgeFilename(kNeighborhoodAgeFilename); VaultUnregisterOwnedAgeAndWait(&info); @@ -640,11 +652,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/pyVault.h b/Sources/Plasma/FeatureLib/pfPython/pyVault.h index 8187b578..881ac592 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyVault.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyVault.h @@ -54,7 +54,6 @@ class pyAgeLinkStruct; class pySDLStateDataRecord; - class pyVault { #ifndef BUILDING_PYPLASMA diff --git a/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.cpp b/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.cpp index e5dc76c2..42b54a0a 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.cpp @@ -92,6 +92,7 @@ pyVaultNode::pyVaultNodeOperationCallback::~pyVaultNodeOperationCallback() void pyVaultNode::pyVaultNodeOperationCallback::VaultOperationStarted( UInt32 context ) { + fContext = context; if ( fCbObject ) { // Call the callback. @@ -391,6 +392,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); @@ -421,21 +430,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 + PyObject* nodeRef = cb->fPyNodeRef = pyVaultNodeRef::New(fNode, pynode->fNode); + Py_INCREF(nodeRef); // The callback steals the ref, according to Eric... 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 @@ -451,15 +465,19 @@ 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 103c2dc5..79c23c70 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyVaultNode.h @@ -69,12 +69,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/PubUtilLib/plMessage/plVaultNotifyMsg.h b/Sources/Plasma/PubUtilLib/plMessage/plVaultNotifyMsg.h index 2732739a..438a6002 100644 --- a/Sources/Plasma/PubUtilLib/plMessage/plVaultNotifyMsg.h +++ b/Sources/Plasma/PubUtilLib/plMessage/plVaultNotifyMsg.h @@ -45,7 +45,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 f8bf6ebc..27a6dcd7 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp @@ -68,6 +68,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" @@ -336,6 +337,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 baf11788..ae515474 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.cpp @@ -46,7 +46,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" /***************************************************************************** @@ -314,6 +313,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; } @@ -347,37 +353,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. @@ -391,6 +379,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(); @@ -443,6 +468,50 @@ bool plNetLinkingMgr::IProcessLinkingMgrMsg( plLinkingMgrMsg * msg ) } +//////////////////////////////////////////////////////////////////// + +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; +} + //////////////////////////////////////////////////////////////////// bool plNetLinkingMgr::IDispatchMsg( plMessage * msg, UInt32 playerID ) @@ -512,7 +581,7 @@ void plNetLinkingMgr::LinkToMyPersonalAge( UInt32 playerID ) hsLogEntry( plNetClientMgr::GetInstance()->DebugMsg( "Not linking. Linking is disabled." ) ); return; } - plNetClientMgr * nc = plNetClientMgr::GetInstance(); + plNetClientMgr* nc = plNetClientMgr::GetInstance(); plAgeLinkStruct link; link.GetAgeInfo()->SetAgeFilename( kPersonalAgeFilename ); @@ -665,23 +734,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()) { + 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. @@ -689,15 +762,17 @@ void plNetLinkingMgr::IPostProcessLink( void ) break; { // Ensure we're in the AgeOwners folder - RelVaultNode * fldr = VaultGetAgeAgeOwnersFolderIncRef(); - RelVaultNode * info = VaultGetPlayerInfoNodeIncRef(); + RelVaultNode* fldr = VaultGetAgeAgeOwnersFolderIncRef(); + RelVaultNode* info = VaultGetPlayerInfoNodeIncRef(); if (fldr && info) if (!fldr->IsParentOf(info->nodeId, 1)) - VaultAddChildNodeAndWait( + VaultAddChildNode( fldr->nodeId, info->nodeId, - NetCommGetPlayer()->playerInt + NetCommGetPlayer()->playerInt, + nil, + nil ); if (fldr) @@ -714,15 +789,17 @@ void plNetLinkingMgr::IPostProcessLink( void ) break; { // Ensure we're in the CanVisit folder - RelVaultNode * fldr = VaultGetAgeCanVisitFolderIncRef(); - RelVaultNode * info = VaultGetPlayerInfoNodeIncRef(); + RelVaultNode* fldr = VaultGetAgeCanVisitFolderIncRef(); + RelVaultNode* info = VaultGetPlayerInfoNodeIncRef(); if (fldr && info) if (!fldr->IsParentOf(info->nodeId, 1)) - VaultAddChildNodeAndWait( + VaultAddChildNode( fldr->nodeId, info->nodeId, - NetCommGetPlayer()->playerInt + NetCommGetPlayer()->playerInt, + nil, + nil ); if (fldr) @@ -736,7 +813,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; } @@ -744,16 +821,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 @@ -771,7 +851,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); @@ -781,50 +861,44 @@ bool plNetLinkingMgr::IPreProcessLink( void ) //------------------------------------------------------------------------ // Fixup empty fields - if ( GetAgeLink()->GetAgeInfo()->HasAgeFilename() ) + if (info->HasAgeFilename()) { - GetAgeLink()->GetAgeInfo()->SetAgeFilename( plNetLinkingMgr::GetProperAgeName( GetAgeLink()->GetAgeInfo()->GetAgeFilename() ).c_str() ); + info->SetAgeFilename(plNetLinkingMgr::GetProperAgeName(info->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() ) ) ); + hsLogEntry(nc->DebugMsg( "plNetLinkingMgr: Pre-Process: Linking with %s rules...", + plNetCommon::LinkingRules::LinkingRuleStr(link->GetLinkingRules()))); //------------------------------------------------------------------------ // SPECIAL CASE: StartUp: force basic link - if ( stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kStartUpAgeFilename )==0 ) - { - GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kBasicLink ); - } + if (stricmp(info->GetAgeFilename(), kStartUpAgeFilename) == 0) + link->SetLinkingRules( plNetCommon::LinkingRules::kBasicLink ); //------------------------------------------------------------------------ // SPECIAL CASE: Nexus: force original link - if ( stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kNexusAgeFilename )==0 ) - { - GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kOriginalBook ); - } + if (stricmp(info->GetAgeFilename(), kNexusAgeFilename) == 0) + link->SetLinkingRules(plNetCommon::LinkingRules::kOriginalBook); //------------------------------------------------------------------------ // SPECIAL CASE: ACA: force original link - if ( stricmp( GetAgeLink()->GetAgeInfo()->GetAgeFilename(), kAvCustomizationFilename )==0 ) - { - GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kOriginalBook ); - } + if (stricmp(info->GetAgeFilename(), kAvCustomizationFilename ) == 0) + link->SetLinkingRules(plNetCommon::LinkingRules::kOriginalBook); - hsLogEntry( nc->DebugMsg( "plNetLinkingMgr: Process: Linking with %s rules...", - plNetCommon::LinkingRules::LinkingRuleStr( GetAgeLink()->GetLinkingRules() ) ) ); + hsLogEntry(nc->DebugMsg("plNetLinkingMgr: Process: Linking with %s rules...", + 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; //-------------------------------------------------------------------- @@ -835,89 +909,98 @@ 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; unsigned nameLen = StrLen(nc->GetPlayerName()); if (nc->GetPlayerName()[nameLen - 1] == 's' || nc->GetPlayerName()[nameLen - 1] == 'S') - xtl::format( title, "%s'", nc->GetPlayerName() ); + xtl::format(title, "%s'", nc->GetPlayerName()); else - xtl::format( title, "%s's", nc->GetPlayerName() ); - GetAgeLink()->GetAgeInfo()->SetAgeUserDefinedName( title.c_str() ); + xtl::format(title, "%s's", nc->GetPlayerName()); + 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)) { + else if (RelVaultNode* linkNode = VaultGetOwnedAgeLinkIncRef(&ageInfo)) { // We have the age in our AgesIOwnFolder. If its volatile, dump it for the new one. VaultAgeLinkNode linkAcc(linkNode); 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; unsigned nameLen = StrLen(nc->GetPlayerName()); if (nc->GetPlayerName()[nameLen - 1] == 's' || nc->GetPlayerName()[nameLen - 1] == 'S') - xtl::format( title, "%s'", nc->GetPlayerName() ); + xtl::format(title, "%s'", nc->GetPlayerName()); else - xtl::format( title, "%s's", nc->GetPlayerName() ); - GetAgeLink()->GetAgeInfo()->SetAgeUserDefinedName( title.c_str() ); + xtl::format(title, "%s's", nc->GetPlayerName()); + 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; } } linkNode->DecRef(); } } - GetAgeLink()->SetLinkingRules( plNetCommon::LinkingRules::kOwnedBook ); + + link->SetLinkingRules(plNetCommon::LinkingRules::kOwnedBook); // falls thru to OWNED BOOK case... //-------------------------------------------------------------------- @@ -925,14 +1008,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; @@ -942,10 +1025,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; @@ -955,10 +1038,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; @@ -969,28 +1052,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() ) ) ); + hsLogEntry(nc->DebugMsg( "plNetLinkingMgr: Post-Process: Linking with %s rules...", + 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 af0fb0cb..8b5d5b90 100644 --- a/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.h +++ b/Sources/Plasma/PubUtilLib/plNetClient/plNetLinkingMgr.h @@ -34,6 +34,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plMessage/plLinkToAgeMsg.h" class plMessage; +class plVaultNotifyMsg; struct plNCAgeJoiner; struct plNCAgeLeaver; @@ -75,10 +76,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 4313fe7e..ccb4f470 100644 --- a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp +++ b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp @@ -2786,6 +2786,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 { @@ -3042,6 +3159,112 @@ bool VaultRegisterVisitAgeAndWait (const plAgeLinkStruct * link) { return result; } +//============================================================================ +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 + ); +} //============================================================================ bool VaultUnregisterOwnedAgeAndWait (const plAgeInfoStruct * info) { @@ -3199,6 +3422,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[], @@ -3436,7 +3691,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); @@ -3483,7 +3738,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); @@ -4174,6 +4429,88 @@ bool VaultAgeFindOrCreateSubAgeLinkAndWait ( return true; } +//============================================================================ +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 { @@ -4451,6 +4788,145 @@ 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 89184ee1..2887202b 100644 --- a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.h +++ b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.h @@ -332,12 +332,16 @@ bool VaultSetOwnedAgePublicAndWait (const plAgeInfoStruct * info, boo 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, @@ -404,6 +408,7 @@ void VaultAgeUpdateAgeSDL (const class plStateDataRecord * rec); unsigned VaultAgeGetAgeTime (); +RelVaultNode * VaultGetSubAgeLinkIncRef (const plAgeInfoStruct * info); bool VaultAgeGetSubAgeLink ( const plAgeInfoStruct * info, plAgeLinkStruct * link @@ -413,11 +418,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);