You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4808 lines
151 KiB
4808 lines
151 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
/***************************************************************************** |
|
* |
|
* $/Plasma20/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp |
|
* |
|
***/ |
|
|
|
|
|
#include "Pch.h" |
|
#pragma hdrstop |
|
|
|
#ifdef CLIENT |
|
|
|
/***************************************************************************** |
|
* |
|
* Private |
|
* |
|
***/ |
|
|
|
struct IVaultCallback { |
|
LINK(IVaultCallback) link; |
|
VaultCallback * cb; |
|
}; |
|
|
|
struct INotifyAfterDownload : THashKeyVal<unsigned> { |
|
HASHLINK(INotifyAfterDownload) link; |
|
unsigned parentId; |
|
unsigned childId; |
|
|
|
INotifyAfterDownload (unsigned parentId, unsigned childId) |
|
: THashKeyVal<unsigned>(childId) |
|
, parentId(parentId) |
|
, childId(childId) |
|
{} |
|
}; |
|
|
|
// A RelVaultNodeLink may be either stored in the global table, |
|
// or stored in an IRelVaultNode's parents or children table. |
|
struct RelVaultNodeLink : THashKeyVal<unsigned> { |
|
HASHLINK(RelVaultNodeLink) link; |
|
hsRef<RelVaultNode> node; |
|
unsigned ownerId; |
|
bool seen; |
|
|
|
RelVaultNodeLink (bool seen, unsigned ownerId, unsigned nodeId, RelVaultNode * node) |
|
: THashKeyVal<unsigned>(nodeId) |
|
, node(node) |
|
, ownerId(ownerId) |
|
, seen(seen) |
|
{ |
|
} |
|
}; |
|
|
|
|
|
struct IRelVaultNode { |
|
RelVaultNode * node; // MUST be a weak ref! |
|
|
|
HASHTABLEDECL( |
|
RelVaultNodeLink, |
|
THashKeyVal<unsigned>, |
|
link |
|
) parents; |
|
|
|
HASHTABLEDECL( |
|
RelVaultNodeLink, |
|
THashKeyVal<unsigned>, |
|
link |
|
) children; |
|
|
|
IRelVaultNode (RelVaultNode * node); |
|
~IRelVaultNode (); |
|
|
|
// Unlink our node from all our parent and children |
|
void UnlinkFromRelatives (); |
|
|
|
// Unlink the node from our parent and children lists |
|
void Unlink (RelVaultNode * other); |
|
}; |
|
|
|
|
|
struct VaultCreateNodeTrans { |
|
FVaultCreateNodeCallback callback; |
|
void * state; |
|
void * param; |
|
|
|
unsigned nodeId; |
|
hsRef<RelVaultNode> node; |
|
|
|
VaultCreateNodeTrans () |
|
: callback(nil), state(nil), param(nil), nodeId(0), node(nil) { } |
|
|
|
VaultCreateNodeTrans (FVaultCreateNodeCallback _callback, |
|
void * _state, void * _param) |
|
: callback(_callback), state(_state), param(_param), |
|
nodeId(0), node(nil) { } |
|
|
|
static void VaultNodeCreated ( |
|
ENetError result, |
|
void * param, |
|
unsigned nodeId |
|
); |
|
static void VaultNodeFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNode * node |
|
); |
|
|
|
void Complete (ENetError result); |
|
}; |
|
|
|
|
|
struct VaultFindNodeTrans { |
|
FVaultFindNodeCallback callback; |
|
void * param; |
|
|
|
VaultFindNodeTrans () : callback(nil), param(nil) { } |
|
|
|
VaultFindNodeTrans (FVaultFindNodeCallback _callback, void * _param) |
|
: callback(_callback), param(_param) { } |
|
|
|
static void VaultNodeFound ( |
|
ENetError result, |
|
void * param, |
|
unsigned nodeIdCount, |
|
const unsigned nodeIds[] |
|
); |
|
}; |
|
|
|
|
|
struct VaultDownloadTrans { |
|
FVaultDownloadCallback callback; |
|
void * cbParam; |
|
FVaultProgressCallback progressCallback; |
|
void * cbProgressParam; |
|
|
|
wchar_t tag[MAX_PATH]; |
|
unsigned nodeCount; |
|
unsigned nodesLeft; |
|
unsigned vaultId; |
|
ENetError result; |
|
|
|
VaultDownloadTrans () |
|
: callback(nil), cbParam(nil), progressCallback(nil), cbProgressParam(nil), |
|
nodeCount(0), nodesLeft(0), vaultId(0), result(kNetSuccess) |
|
{ |
|
memset(tag, 0, sizeof(tag)); |
|
} |
|
|
|
VaultDownloadTrans (const wchar_t * _tag, FVaultDownloadCallback _callback, |
|
void * _cbParam, FVaultProgressCallback _progressCallback, |
|
void * _cbProgressParam, unsigned _vaultId) |
|
: callback(_callback), cbParam(_cbParam), progressCallback(_progressCallback), |
|
cbProgressParam(_cbProgressParam), nodeCount(0), nodesLeft(0), |
|
vaultId(_vaultId), result(kNetSuccess) |
|
{ |
|
wcsncpy(tag, _tag, arrsize(tag)); |
|
tag[arrsize(tag)-1] = 0; |
|
} |
|
|
|
|
|
static void VaultNodeFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNode * node |
|
); |
|
static void VaultNodeRefsFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNodeRef * refs, |
|
unsigned refCount |
|
); |
|
}; |
|
|
|
struct VaultAgeInitTrans { |
|
FVaultInitAgeCallback callback; |
|
void * cbState; |
|
void * cbParam; |
|
|
|
VaultAgeInitTrans() |
|
: callback(nil), cbState(nil), cbParam(nil) { } |
|
|
|
VaultAgeInitTrans(FVaultInitAgeCallback _callback, |
|
void * state, void * param) |
|
: callback(_callback), cbState(state), cbParam(param) { } |
|
|
|
static void AgeInitCallback ( |
|
ENetError result, |
|
void * param, |
|
unsigned ageVaultId, |
|
unsigned ageInfoVaultId |
|
); |
|
}; |
|
|
|
struct AddChildNodeFetchTrans { |
|
FVaultAddChildNodeCallback callback; |
|
void * cbParam; |
|
ENetError result; |
|
std::atomic<long> opCount; |
|
|
|
AddChildNodeFetchTrans() |
|
: callback(nil), cbParam(nil), result(kNetSuccess), opCount(0) { } |
|
|
|
AddChildNodeFetchTrans(FVaultAddChildNodeCallback _callback, void * _param) |
|
: callback(_callback), cbParam(_param), result(kNetSuccess), opCount(0) { } |
|
|
|
static void VaultNodeFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNode * node |
|
); |
|
static void VaultNodeRefsFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNodeRef * refs, |
|
unsigned refCount |
|
); |
|
}; |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* Private data |
|
* |
|
***/ |
|
|
|
static bool s_running; |
|
|
|
static HASHTABLEDECL( |
|
RelVaultNodeLink, |
|
THashKeyVal<unsigned>, |
|
link |
|
) s_nodes; |
|
|
|
static LISTDECL( |
|
IVaultCallback, |
|
link |
|
) s_callbacks; |
|
|
|
static HASHTABLEDECL( |
|
INotifyAfterDownload, |
|
THashKeyVal<unsigned>, |
|
link |
|
) s_notifyAfterDownload; |
|
|
|
static std::unordered_map<plString, plString, plString::hash> s_ageDeviceInboxes; |
|
|
|
static bool s_processPlayerInbox = false; |
|
|
|
/***************************************************************************** |
|
* |
|
* Local functions |
|
* |
|
***/ |
|
|
|
static void VaultProcessVisitNote(RelVaultNode * rvnVisit); |
|
static void VaultProcessUnvisitNote(RelVaultNode * rvnUnVisit); |
|
|
|
static void VaultNodeFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNode * node |
|
); |
|
static void VaultNodeFound ( |
|
ENetError result, |
|
void * param, |
|
unsigned nodeIdCount, |
|
const unsigned nodeIds[] |
|
); |
|
|
|
//============================================================================ |
|
static void VaultNodeAddedDownloadCallback(ENetError result, void * param) { |
|
unsigned childId = (unsigned)((uintptr_t)param); |
|
|
|
INotifyAfterDownload* notify = s_notifyAfterDownload.Find(childId); |
|
|
|
if (notify) { |
|
if (IS_NET_SUCCESS(result)) { |
|
RelVaultNodeLink* parentLink = s_nodes.Find(notify->parentId); |
|
RelVaultNodeLink* childLink = s_nodes.Find(notify->childId); |
|
|
|
if (parentLink && childLink) { |
|
if (childLink->node->GetNodeType() == plVault::kNodeType_TextNote) { |
|
VaultTextNoteNode textNote(childLink->node); |
|
if (textNote.GetNoteType() == plVault::kNoteType_Visit) |
|
VaultProcessVisitNote(childLink->node); |
|
else if (textNote.GetNoteType() == plVault::kNoteType_UnVisit) |
|
VaultProcessUnvisitNote(childLink->node); |
|
} |
|
|
|
for (IVaultCallback * cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) |
|
cb->cb->AddedChildNode(parentLink->node, childLink->node); |
|
} |
|
} |
|
|
|
delete notify; |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static void CDECL LogDumpProc ( |
|
void * , |
|
const wchar_t fmt[], |
|
... |
|
) { |
|
va_list args; |
|
va_start(args, fmt); |
|
LogMsgV(kLogDebug, fmt, args); |
|
va_end(args); |
|
} |
|
|
|
//============================================================================ |
|
// Returns ids of nodes that had to be created (so we can fetch them) |
|
static void BuildNodeTree ( |
|
const NetVaultNodeRef refs[], |
|
unsigned refCount, |
|
ARRAY(unsigned) * newNodeIds, |
|
ARRAY(unsigned) * existingNodeIds, |
|
bool notifyNow = true |
|
) { |
|
for (unsigned i = 0; i < refCount; ++i) { |
|
// Find/Create global links |
|
RelVaultNodeLink * parentLink = s_nodes.Find(refs[i].parentId); |
|
if (!parentLink) { |
|
newNodeIds->Add(refs[i].parentId); |
|
parentLink = new RelVaultNodeLink(false, 0, refs[i].parentId, new RelVaultNode); |
|
parentLink->node->SetNodeId_NoDirty(refs[i].parentId); |
|
s_nodes.Add(parentLink); |
|
} |
|
else { |
|
existingNodeIds->Add(refs[i].parentId); |
|
} |
|
RelVaultNodeLink * childLink = s_nodes.Find(refs[i].childId); |
|
if (!childLink) { |
|
newNodeIds->Add(refs[i].childId); |
|
childLink = new RelVaultNodeLink(refs[i].seen, refs[i].ownerId, refs[i].childId, new RelVaultNode); |
|
childLink->node->SetNodeId_NoDirty(refs[i].childId); |
|
s_nodes.Add(childLink); |
|
} |
|
else { |
|
existingNodeIds->Add(refs[i].childId); |
|
if (unsigned ownerId = refs[i].ownerId) |
|
childLink->ownerId = ownerId; |
|
} |
|
|
|
hsRef<RelVaultNode> parentNode = parentLink->node; |
|
hsRef<RelVaultNode> childNode = childLink->node; |
|
|
|
bool isImmediateParent = parentNode->IsParentOf(refs[i].childId, 1); |
|
bool isImmediateChild = childNode->IsChildOf(refs[i].parentId, 1); |
|
|
|
if (!isImmediateParent) { |
|
// Add parent to child's parents table |
|
parentLink = new RelVaultNodeLink(false, 0, parentNode->GetNodeId(), parentNode); |
|
childNode->state->parents.Add(parentLink); |
|
LogMsg(kLogDebug, L"Added relationship: p:%u,c:%u", refs[i].parentId, refs[i].childId); |
|
} |
|
|
|
if (!isImmediateChild) { |
|
// Add child to parent's children table |
|
childLink = new RelVaultNodeLink(refs[i].seen, refs[i].ownerId, childNode->GetNodeId(), childNode); |
|
parentNode->state->children.Add(childLink); |
|
|
|
if (notifyNow || childNode->GetNodeType() != 0) { |
|
// We made a new link, so make the callbacks |
|
for (IVaultCallback * cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) |
|
cb->cb->AddedChildNode(parentNode, childNode); |
|
} |
|
else { |
|
INotifyAfterDownload* notify = new INotifyAfterDownload(parentNode->GetNodeId(), childNode->GetNodeId()); |
|
s_notifyAfterDownload.Add(notify); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static void InitFetchedNode (RelVaultNode * rvn) { |
|
|
|
switch (rvn->GetNodeType()) { |
|
case plVault::kNodeType_SDL: { |
|
VaultSDLNode access(rvn); |
|
if (!access.GetSDLData() || !access.GetSDLDataLength()) |
|
access.InitStateDataRecord(access.GetSDLName()); |
|
} |
|
break; |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static void FetchRefOwners ( |
|
NetVaultNodeRef * refs, |
|
unsigned refCount |
|
) { |
|
ARRAY(unsigned) ownerIds; |
|
{ for (unsigned i = 0; i < refCount; ++i) |
|
if (unsigned ownerId = refs[i].ownerId) |
|
ownerIds.Add(ownerId); |
|
} |
|
QSORT(unsigned, ownerIds.Ptr(), ownerIds.Count(), elem1 < elem2); |
|
hsRef<RelVaultNode> templateNode = new RelVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_PlayerInfo); |
|
{ unsigned prevId = 0; |
|
for (unsigned i = 0; i < ownerIds.Count(); ++i) { |
|
if (ownerIds[i] != prevId) { |
|
prevId = ownerIds[i]; |
|
VaultPlayerInfoNode access(templateNode); |
|
access.SetPlayerId(refs[i].ownerId); |
|
if (VaultGetNode(templateNode)) |
|
continue; |
|
NetCliAuthVaultNodeFind( |
|
templateNode, |
|
VaultNodeFound, |
|
nil |
|
); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static void FetchNodesFromRefs ( |
|
NetVaultNodeRef * refs, |
|
unsigned refCount, |
|
FNetCliAuthVaultNodeFetched fetchCallback, |
|
void * fetchParam, |
|
unsigned * fetchCount |
|
|
|
) { |
|
// On the side, start downloading PlayerInfo nodes of ref owners we don't already have locally |
|
FetchRefOwners(refs, refCount); |
|
|
|
*fetchCount = 0; |
|
|
|
ARRAY(unsigned) newNodeIds; |
|
ARRAY(unsigned) existingNodeIds; |
|
|
|
BuildNodeTree(refs, refCount, &newNodeIds, &existingNodeIds); |
|
|
|
ARRAY(unsigned) nodeIds; |
|
nodeIds.Add(newNodeIds.Ptr(), newNodeIds.Count()); |
|
nodeIds.Add(existingNodeIds.Ptr(), existingNodeIds.Count()); |
|
QSORT(unsigned, nodeIds.Ptr(), nodeIds.Count(), elem1 < elem2); |
|
|
|
// Fetch the nodes that do not yet have a nodetype |
|
unsigned prevId = 0; |
|
for (unsigned i = 0; i < nodeIds.Count(); ++i) { |
|
RelVaultNodeLink * link = s_nodes.Find(nodeIds[i]); |
|
if (link->node->GetNodeType() != 0) |
|
continue; |
|
// filter duplicates |
|
if (link->node->GetNodeId() == prevId) |
|
continue; |
|
prevId = link->node->GetNodeId(); |
|
NetCliAuthVaultNodeFetch( |
|
nodeIds[i], |
|
fetchCallback, |
|
fetchParam |
|
); |
|
++(*fetchCount); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static void VaultNodeFound ( |
|
ENetError result, |
|
void * , |
|
unsigned nodeIdCount, |
|
const unsigned nodeIds[] |
|
) { |
|
// TODO: Support some sort of optional transaction object/callback state |
|
|
|
// error? |
|
if (IS_NET_ERROR(result)) |
|
return; |
|
|
|
for (unsigned i = 0; i < nodeIdCount; ++i) { |
|
|
|
// See if we already have this node |
|
if (RelVaultNodeLink * link = s_nodes.Find(nodeIds[i])) |
|
return; |
|
|
|
// Start fetching the node |
|
NetCliAuthVaultNodeFetch(nodeIds[i], VaultNodeFetched, nil); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static void VaultNodeFetched ( |
|
ENetError result, |
|
void * , |
|
NetVaultNode * node |
|
) { |
|
if (IS_NET_ERROR(result)) { |
|
LogMsg(kLogDebug, L"VaultNodeFetched failed: %u (%s)", result, NetErrorToString(result)); |
|
return; |
|
} |
|
|
|
// Add to global node table |
|
RelVaultNodeLink * link = s_nodes.Find(node->GetNodeId()); |
|
if (!link) { |
|
link = new RelVaultNodeLink(false, 0, node->GetNodeId(), new RelVaultNode()); |
|
link->node->SetNodeId_NoDirty(node->GetNodeId()); |
|
s_nodes.Add(link); |
|
} |
|
link->node->CopyFrom(node); |
|
InitFetchedNode(link->node); |
|
|
|
link->node->Print(L"Fetched", LogDumpProc, 0); |
|
} |
|
|
|
//============================================================================ |
|
static void ChangedVaultNodeFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNode * node |
|
) { |
|
if (IS_NET_ERROR(result)) { |
|
LogMsg(kLogDebug, L"ChangedVaultNodeFetched failed: %u (%s)", result, NetErrorToString(result)); |
|
return; |
|
} |
|
|
|
VaultNodeFetched(result, param, node); |
|
|
|
RelVaultNodeLink* savedLink = s_nodes.Find(node->GetNodeId()); |
|
|
|
if (savedLink) { |
|
for (IVaultCallback * cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) |
|
cb->cb->ChangedNode(savedLink->node); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static void VaultNodeChanged ( |
|
unsigned nodeId, |
|
const plUUID& revisionId |
|
) { |
|
LogMsg(kLogDebug, L"Notify: Node changed: %u", nodeId); |
|
|
|
RelVaultNodeLink * link = s_nodes.Find(nodeId); |
|
|
|
// We don't have the node, so we don't care that it changed (we actually |
|
// shouldn't have been notified) |
|
if (!link) { |
|
LogMsg(kLogDebug, L"rcvd change notification for node %u, but node doesn't exist locally.", nodeId); |
|
return; |
|
} |
|
|
|
// We are the party responsible for the change, so we already have the |
|
// latest version of the node; no need to fetch it. |
|
if (link->node->GetRevision() == revisionId) |
|
return; |
|
|
|
// We have the node and we weren't the one that changed it, so fetch it. |
|
NetCliAuthVaultNodeFetch( |
|
nodeId, |
|
ChangedVaultNodeFetched, |
|
nil |
|
); |
|
} |
|
|
|
//============================================================================ |
|
static void VaultNodeAdded ( |
|
unsigned parentId, |
|
unsigned childId, |
|
unsigned ownerId |
|
) { |
|
LogMsg(kLogDebug, L"Notify: Node added: p:%u,c:%u", parentId, childId); |
|
|
|
unsigned inboxId = 0; |
|
if (hsRef<RelVaultNode> rvnInbox = VaultGetPlayerInboxFolder()) |
|
inboxId = rvnInbox->GetNodeId(); |
|
|
|
// Build the relationship locally |
|
NetVaultNodeRef refs[] = { |
|
{ parentId, childId, ownerId } |
|
}; |
|
ARRAY(unsigned) newNodeIds; |
|
ARRAY(unsigned) existingNodeIds; |
|
|
|
BuildNodeTree(refs, arrsize(refs), &newNodeIds, &existingNodeIds, false); |
|
|
|
ARRAY(unsigned) nodeIds; |
|
nodeIds.Add(newNodeIds.Ptr(), newNodeIds.Count()); |
|
nodeIds.Add(existingNodeIds.Ptr(), existingNodeIds.Count()); |
|
QSORT(unsigned, nodeIds.Ptr(), nodeIds.Count(), elem1 < elem2); |
|
|
|
// Fetch the nodes that do not yet have a nodetype |
|
unsigned prevId = 0; |
|
unsigned i = 0; |
|
for (; i < nodeIds.Count(); ++i) { |
|
RelVaultNodeLink * link = s_nodes.Find(nodeIds[i]); |
|
if (link->node->GetNodeType() != 0) |
|
continue; |
|
// filter duplicates |
|
if (link->node->GetNodeId() == prevId) |
|
continue; |
|
prevId = link->node->GetNodeId(); |
|
VaultDownload( |
|
L"NodeAdded", |
|
nodeIds[i], |
|
VaultNodeAddedDownloadCallback, |
|
(void*)nodeIds[i], |
|
nil, |
|
nil |
|
); |
|
} |
|
|
|
if (parentId == inboxId) { |
|
if (i > 0) |
|
s_processPlayerInbox = true; |
|
else |
|
VaultProcessPlayerInbox(); |
|
} |
|
|
|
// if the added element is already downloaded then send the callbacks now |
|
RelVaultNodeLink* parentLink = s_nodes.Find(parentId); |
|
RelVaultNodeLink* childLink = s_nodes.Find(childId); |
|
|
|
if (childLink->node->GetNodeType() != 0) { |
|
for (IVaultCallback * cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) |
|
cb->cb->AddedChildNode(parentLink->node, childLink->node); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static void VaultNodeRemoved ( |
|
unsigned parentId, |
|
unsigned childId |
|
) { |
|
LogMsg(kLogDebug, L"Notify: Node removed: p:%u,c:%u", parentId, childId); |
|
for (;;) { |
|
// Unlink 'em locally, if we can |
|
RelVaultNodeLink * parentLink = s_nodes.Find(parentId); |
|
if (!parentLink) |
|
break; |
|
|
|
RelVaultNodeLink * childLink = s_nodes.Find(childId); |
|
if (!childLink) |
|
break; |
|
|
|
if (parentLink->node->IsParentOf(childId, 1)) { |
|
// We have the relationship, so make the callbacks |
|
for (IVaultCallback * cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) |
|
cb->cb->RemovingChildNode(parentLink->node, childLink->node); |
|
} |
|
|
|
parentLink->node->state->Unlink(childLink->node); |
|
childLink->node->state->Unlink(parentLink->node); |
|
break; |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static void VaultNodeDeleted ( |
|
unsigned nodeId |
|
) { |
|
LogMsg(kLogDebug, L"Notify: Node deleted: %u", nodeId); |
|
VaultCull(nodeId); |
|
} |
|
|
|
//============================================================================ |
|
static void SaveDirtyNodes () { |
|
// Save a max of 5Kb every quarter second |
|
static const unsigned kSaveUpdateIntervalMs = 250; |
|
static const unsigned kMaxBytesPerSaveUpdate = 5 * 1024; |
|
static unsigned s_nextSaveMs; |
|
unsigned currTimeMs = hsTimer::GetMilliSeconds<uint32_t>() | 1; |
|
if (!s_nextSaveMs || signed(s_nextSaveMs - currTimeMs) <= 0) { |
|
s_nextSaveMs = (currTimeMs + kSaveUpdateIntervalMs) | 1; |
|
unsigned bytesWritten = 0; |
|
for (RelVaultNodeLink * link = s_nodes.Head(); link; link = s_nodes.Next(link)) { |
|
if (bytesWritten >= kMaxBytesPerSaveUpdate) |
|
break; |
|
if (link->node->IsDirty()) { |
|
if (unsigned bytes = NetCliAuthVaultNodeSave(link->node, nil, nil)) { |
|
bytesWritten += bytes; |
|
link->node->Print(L"Saving", LogDumpProc, 0); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static hsRef<RelVaultNode> GetChildFolderNode ( |
|
RelVaultNode * parent, |
|
unsigned folderType, |
|
unsigned maxDepth |
|
) { |
|
if (!parent) |
|
return nullptr; |
|
|
|
return parent->GetChildFolderNode(folderType, maxDepth); |
|
} |
|
|
|
//============================================================================ |
|
static hsRef<RelVaultNode> GetChildPlayerInfoListNode ( |
|
RelVaultNode * parent, |
|
unsigned folderType, |
|
unsigned maxDepth |
|
) { |
|
if (!parent) |
|
return nullptr; |
|
|
|
return parent->GetChildPlayerInfoListNode(folderType, maxDepth); |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* VaultCreateNodeTrans |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
void VaultCreateNodeTrans::VaultNodeCreated ( |
|
ENetError result, |
|
void * param, |
|
unsigned nodeId |
|
) { |
|
VaultCreateNodeTrans * trans = (VaultCreateNodeTrans *)param; |
|
if (IS_NET_ERROR(result)) { |
|
trans->Complete(result); |
|
} |
|
else { |
|
trans->nodeId = nodeId; |
|
NetCliAuthVaultNodeFetch( |
|
nodeId, |
|
VaultCreateNodeTrans::VaultNodeFetched, |
|
trans |
|
); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void VaultCreateNodeTrans::VaultNodeFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNode * node |
|
) { |
|
::VaultNodeFetched(result, param, node); |
|
|
|
VaultCreateNodeTrans * trans = (VaultCreateNodeTrans *)param; |
|
|
|
if (IS_NET_SUCCESS(result)) |
|
trans->node = s_nodes.Find(node->GetNodeId())->node; |
|
else |
|
trans->node = nil; |
|
|
|
trans->Complete(result); |
|
} |
|
|
|
//============================================================================ |
|
void VaultCreateNodeTrans::Complete (ENetError result) { |
|
|
|
if (callback) |
|
callback( |
|
result, |
|
state, |
|
param, |
|
node |
|
); |
|
|
|
delete this; |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* VaultFindNodeTrans |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
void VaultFindNodeTrans::VaultNodeFound ( |
|
ENetError result, |
|
void * param, |
|
unsigned nodeIdCount, |
|
const unsigned nodeIds[] |
|
) { |
|
VaultFindNodeTrans * trans = (VaultFindNodeTrans*)param; |
|
if (trans->callback) |
|
trans->callback( |
|
result, |
|
trans->param, |
|
nodeIdCount, |
|
nodeIds |
|
); |
|
delete trans; |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* VaultDownloadTrans |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
void VaultDownloadTrans::VaultNodeFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNode * node |
|
) { |
|
::VaultNodeFetched(result, param, node); |
|
|
|
VaultDownloadTrans * trans = (VaultDownloadTrans *)param; |
|
if (IS_NET_ERROR(result)) { |
|
trans->result = result; |
|
//LogMsg(kLogError, L"Error fetching node...most likely trying to fetch a nodeid of 0"); |
|
} |
|
|
|
--trans->nodesLeft; |
|
// LogMsg(kLogDebug, L"(Download) %u of %u nodes fetched", trans->nodeCount - trans->nodesLeft, trans->nodeCount); |
|
|
|
if (trans->progressCallback) { |
|
trans->progressCallback( |
|
trans->nodeCount, |
|
trans->nodeCount - trans->nodesLeft, |
|
trans->cbProgressParam |
|
); |
|
} |
|
|
|
if (!trans->nodesLeft) { |
|
VaultDump(trans->tag, trans->vaultId, LogDumpProc); |
|
|
|
if (trans->callback) |
|
trans->callback( |
|
trans->result, |
|
trans->cbParam |
|
); |
|
|
|
delete trans; |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void VaultDownloadTrans::VaultNodeRefsFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNodeRef * refs, |
|
unsigned refCount |
|
) { |
|
VaultDownloadTrans * trans = (VaultDownloadTrans *)param; |
|
|
|
if (IS_NET_ERROR(result)) { |
|
LogMsg(kLogDebug, L"VaultNodeRefsFetched failed: %u (%s)", result, NetErrorToString(result)); |
|
trans->result = result; |
|
trans->nodesLeft = 0; |
|
} |
|
else { |
|
if (refCount) { |
|
FetchNodesFromRefs( |
|
refs, |
|
refCount, |
|
VaultDownloadTrans::VaultNodeFetched, |
|
param, |
|
&trans->nodeCount |
|
); |
|
trans->nodesLeft = trans->nodeCount; |
|
} |
|
else { |
|
// root node has no child heirarchy? Make sure we still d/l the root node if necessary. |
|
RelVaultNodeLink* rootNodeLink = s_nodes.Find(trans->vaultId); |
|
if (!rootNodeLink || rootNodeLink->node->GetNodeType() == 0) { |
|
NetCliAuthVaultNodeFetch( |
|
trans->vaultId, |
|
VaultDownloadTrans::VaultNodeFetched, |
|
trans |
|
); |
|
trans->nodesLeft = 1; |
|
} |
|
} |
|
} |
|
|
|
// Make the callback now if there are no nodes to fetch, or if error |
|
if (!trans->nodesLeft) { |
|
if (trans->callback) |
|
trans->callback( |
|
trans->result, |
|
trans->cbParam |
|
); |
|
|
|
delete trans; |
|
} |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* VaultAgeInitTrans |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
void VaultAgeInitTrans::AgeInitCallback ( |
|
ENetError result, |
|
void * param, |
|
unsigned ageVaultId, |
|
unsigned ageInfoVaultId |
|
) { |
|
VaultAgeInitTrans * trans = (VaultAgeInitTrans *)param; |
|
|
|
if (trans->callback) |
|
trans->callback( |
|
result, |
|
trans->cbState, |
|
trans->cbParam, |
|
ageVaultId, |
|
ageInfoVaultId |
|
); |
|
|
|
delete trans; |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* AddChildNodeFetchTrans |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
void AddChildNodeFetchTrans::VaultNodeRefsFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNodeRef * refs, |
|
unsigned refCount |
|
) { |
|
AddChildNodeFetchTrans * trans = (AddChildNodeFetchTrans *)param; |
|
|
|
if (IS_NET_ERROR(result)) { |
|
trans->result = result; |
|
} |
|
else { |
|
unsigned incFetchCount = 0; |
|
FetchNodesFromRefs( |
|
refs, |
|
refCount, |
|
AddChildNodeFetchTrans::VaultNodeFetched, |
|
param, |
|
&incFetchCount |
|
); |
|
trans->opCount += incFetchCount; |
|
} |
|
|
|
// Make the callback now if there are no nodes to fetch, or if error |
|
if (!(--trans->opCount)) { |
|
if (trans->callback) |
|
trans->callback( |
|
trans->result, |
|
trans->cbParam |
|
); |
|
delete trans; |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void AddChildNodeFetchTrans::VaultNodeFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNode * node |
|
) { |
|
::VaultNodeFetched(result, param, node); |
|
|
|
AddChildNodeFetchTrans * trans = (AddChildNodeFetchTrans *)param; |
|
|
|
if (IS_NET_ERROR(result)) |
|
trans->result = result; |
|
|
|
if (!(--trans->opCount)) { |
|
if (trans->callback) |
|
trans->callback( |
|
trans->result, |
|
trans->cbParam |
|
); |
|
delete trans; |
|
} |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* IRelVaultNode |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
IRelVaultNode::IRelVaultNode (RelVaultNode * node) |
|
: node(node) |
|
{ |
|
} |
|
|
|
//============================================================================ |
|
IRelVaultNode::~IRelVaultNode () { |
|
ASSERT(!parents.Head()); |
|
ASSERT(!children.Head()); |
|
} |
|
|
|
//============================================================================ |
|
void IRelVaultNode::UnlinkFromRelatives () { |
|
|
|
RelVaultNodeLink * link, * next; |
|
for (link = parents.Head(); link; link = next) { |
|
next = parents.Next(link); |
|
|
|
// We have the relationship, so make the callbacks |
|
for (IVaultCallback * cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) |
|
cb->cb->RemovingChildNode(link->node, this->node); |
|
|
|
link->node->state->Unlink(node); |
|
} |
|
for (link = children.Head(); link; link = next) { |
|
next = children.Next(link); |
|
link->node->state->Unlink(node); |
|
} |
|
|
|
ASSERT(!parents.Head()); |
|
ASSERT(!children.Head()); |
|
} |
|
|
|
|
|
//============================================================================ |
|
void IRelVaultNode::Unlink (RelVaultNode * other) { |
|
ASSERT(other != node); |
|
|
|
RelVaultNodeLink * link; |
|
if (nil != (link = parents.Find(other->GetNodeId()))) { |
|
// make them non-findable in our parents table |
|
link->link.Unlink(); |
|
// remove us from other's tables. |
|
link->node->state->Unlink(node); |
|
delete link; |
|
} |
|
if (nil != (link = children.Find(other->GetNodeId()))) { |
|
// make them non-findable in our children table |
|
link->link.Unlink(); |
|
// remove us from other's tables. |
|
link->node->state->Unlink(node); |
|
delete link; |
|
} |
|
} |
|
|
|
/***************************************************************************** |
|
* |
|
* RelVaultNode |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
RelVaultNode::RelVaultNode () { |
|
state = new IRelVaultNode(this); |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode::~RelVaultNode () { |
|
delete state; |
|
} |
|
|
|
//============================================================================ |
|
bool RelVaultNode::IsParentOf (unsigned childId, unsigned maxDepth) { |
|
if (GetNodeId() == childId) |
|
return false; |
|
if (maxDepth == 0) |
|
return false; |
|
if (state->children.Find(childId)) |
|
return true; |
|
RelVaultNodeLink * link = state->children.Head(); |
|
for (; link; link = state->children.Next(link)) |
|
if (link->node->IsParentOf(childId, maxDepth - 1)) |
|
return true; |
|
return false; |
|
} |
|
|
|
//============================================================================ |
|
bool RelVaultNode::IsChildOf (unsigned parentId, unsigned maxDepth) { |
|
if (GetNodeId() == parentId) |
|
return false; |
|
if (maxDepth == 0) |
|
return false; |
|
if (state->parents.Find(parentId)) |
|
return true; |
|
RelVaultNodeLink * link = state->parents.Head(); |
|
for (; link; link = state->parents.Next(link)) |
|
if (link->node->IsChildOf(parentId, maxDepth - 1)) |
|
return true; |
|
return false; |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::GetRootIds (ARRAY(unsigned) * nodeIds) { |
|
RelVaultNodeLink * link = state->parents.Head(); |
|
if (!link) { |
|
nodeIds->Add(GetNodeId()); |
|
} |
|
else { |
|
for (; link; link = state->parents.Next(link)) |
|
link->node->GetRootIds(nodeIds); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
unsigned RelVaultNode::RemoveChildNodes (unsigned maxDepth) { |
|
hsAssert(false, "eric, implement me."); |
|
return 0; |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::GetChildNodeIds ( |
|
ARRAY(unsigned) * nodeIds, |
|
unsigned maxDepth |
|
) { |
|
if (!maxDepth) |
|
return; |
|
RelVaultNodeLink * link = state->children.Head(); |
|
for (; link; link = state->children.Next(link)) { |
|
nodeIds->Add(link->node->GetNodeId()); |
|
link->node->GetChildNodeIds(nodeIds, maxDepth-1); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::GetParentNodeIds ( |
|
ARRAY(unsigned) * nodeIds, |
|
unsigned maxDepth |
|
) { |
|
if (!maxDepth) |
|
return; |
|
RelVaultNodeLink * link = state->parents.Head(); |
|
for (; link; link = state->parents.Next(link)) { |
|
nodeIds->Add(link->node->GetNodeId()); |
|
link->node->GetParentNodeIds(nodeIds, maxDepth-1); |
|
} |
|
} |
|
|
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> RelVaultNode::GetParentNode ( |
|
NetVaultNode * templateNode, |
|
unsigned maxDepth |
|
) { |
|
if (maxDepth == 0) |
|
return nullptr; |
|
|
|
RelVaultNodeLink * link; |
|
link = state->parents.Head(); |
|
for (; link; link = state->parents.Next(link)) { |
|
if (link->node->Matches(templateNode)) |
|
return link->node; |
|
} |
|
|
|
link = state->parents.Head(); |
|
for (; link; link = state->parents.Next(link)) { |
|
if (hsRef<RelVaultNode> node = link->node->GetParentNode(templateNode, maxDepth - 1)) |
|
return node; |
|
} |
|
|
|
return nullptr; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> RelVaultNode::GetChildNode ( |
|
NetVaultNode * templateNode, |
|
unsigned maxDepth |
|
) { |
|
if (maxDepth == 0) |
|
return nullptr; |
|
|
|
RelVaultNodeLink * link; |
|
link = state->children.Head(); |
|
for (; link; link = state->children.Next(link)) { |
|
if (link->node->Matches(templateNode)) |
|
return link->node; |
|
} |
|
|
|
link = state->children.Head(); |
|
for (; link; link = state->children.Next(link)) { |
|
if (hsRef<RelVaultNode> node = link->node->GetChildNode(templateNode, maxDepth-1)) |
|
return node; |
|
} |
|
|
|
return nullptr; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> RelVaultNode::GetChildNode ( |
|
unsigned nodeType, |
|
unsigned maxDepth |
|
) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(nodeType); |
|
return GetChildNode(templateNode, maxDepth); |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> RelVaultNode::GetChildFolderNode ( |
|
unsigned folderType, |
|
unsigned maxDepth |
|
) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_Folder); |
|
VaultFolderNode folder(templateNode); |
|
folder.SetFolderType(folderType); |
|
return GetChildNode(templateNode, maxDepth); |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> RelVaultNode::GetChildPlayerInfoListNode ( |
|
unsigned folderType, |
|
unsigned maxDepth |
|
) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_PlayerInfoList); |
|
VaultPlayerInfoListNode access(templateNode); |
|
access.SetFolderType(folderType); |
|
return GetChildNode(templateNode, maxDepth); |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> RelVaultNode::GetChildAgeInfoListNode ( |
|
unsigned folderType, |
|
unsigned maxDepth |
|
) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfoList); |
|
VaultAgeInfoListNode access(templateNode); |
|
access.SetFolderType(folderType); |
|
return GetChildNode(templateNode, maxDepth); |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::GetChildNodes ( |
|
unsigned maxDepth, |
|
RelVaultNode::RefList * nodes |
|
) { |
|
if (maxDepth == 0) |
|
return; |
|
|
|
RelVaultNodeLink * link; |
|
link = state->children.Head(); |
|
for (; link; link = state->children.Next(link)) { |
|
nodes->push_back(link->node); |
|
link->node->GetChildNodes( |
|
maxDepth - 1, |
|
nodes |
|
); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::GetChildNodes ( |
|
NetVaultNode * templateNode, |
|
unsigned maxDepth, |
|
RelVaultNode::RefList * nodes |
|
) { |
|
RelVaultNodeLink * link; |
|
link = state->children.Head(); |
|
for (; link; link = state->children.Next(link)) { |
|
if (link->node->Matches(templateNode)) |
|
nodes->push_back(link->node); |
|
|
|
link->node->GetChildNodes( |
|
templateNode, |
|
maxDepth - 1, |
|
nodes |
|
); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::GetChildNodes ( |
|
unsigned nodeType, |
|
unsigned maxDepth, |
|
RelVaultNode::RefList * nodes |
|
) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(nodeType); |
|
GetChildNodes( |
|
templateNode, |
|
maxDepth, |
|
nodes |
|
); |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::GetChildFolderNodes ( |
|
unsigned folderType, |
|
unsigned maxDepth, |
|
RelVaultNode::RefList * nodes |
|
) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_Folder); |
|
VaultFolderNode fldr(templateNode); |
|
fldr.SetFolderType(folderType); |
|
GetChildNodes( |
|
templateNode, |
|
maxDepth, |
|
nodes |
|
); |
|
} |
|
|
|
//============================================================================ |
|
unsigned RelVaultNode::GetRefOwnerId (unsigned parentId) { |
|
// find our parents' link to us and return its ownerId |
|
if (RelVaultNodeLink * parentLink = state->parents.Find(parentId)) |
|
if (RelVaultNodeLink * childLink = parentLink->node->state->children.Find(GetNodeId())) |
|
return childLink->ownerId; |
|
return 0; |
|
} |
|
|
|
//============================================================================ |
|
bool RelVaultNode::BeenSeen (unsigned parentId) const { |
|
// find our parents' link to us and return its seen flag |
|
if (RelVaultNodeLink * parentLink = state->parents.Find(parentId)) |
|
if (RelVaultNodeLink * childLink = parentLink->node->state->children.Find(GetNodeId())) |
|
return childLink->seen; |
|
return true; |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::SetSeen (unsigned parentId, bool seen) { |
|
// find our parents' link to us and set its seen flag |
|
if (RelVaultNodeLink * parentLink = state->parents.Find(parentId)) |
|
if (RelVaultNodeLink * childLink = parentLink->node->state->children.Find(GetNodeId())) |
|
if (childLink->seen != seen) { |
|
childLink->seen = seen; |
|
NetCliAuthVaultSetSeen(parentId, GetNodeId(), seen); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
template <typename T> |
|
static bool IStrSqlEscape (const T src[], T * dst, unsigned dstChars) { |
|
// count the number of ' chars |
|
unsigned ticks = 0; |
|
{ |
|
const T * cur = src; |
|
while (*cur) { |
|
if (*cur == L'\'') |
|
++ticks; |
|
cur++; |
|
} |
|
} |
|
|
|
unsigned reqChars = StrLen(src) + ticks + 1; |
|
|
|
if (dstChars < reqChars) |
|
// failure! |
|
return false; |
|
|
|
T * cur = dst; |
|
|
|
// copy src to dst, escaping ' chars |
|
while (*src) { |
|
if (*src == L'\'') { |
|
*cur++ = L'\''; |
|
*cur++ = *src++; |
|
continue; |
|
} |
|
*cur++ = *src++; |
|
} |
|
|
|
// null-terminate dst string |
|
*cur = 0; |
|
|
|
// success! |
|
return true; |
|
} |
|
|
|
static void IGetStringFieldValue ( |
|
const plString & value, |
|
wchar_t * dst, |
|
size_t dstChars |
|
) { |
|
wchar_t * tmp = (wchar_t*)malloc(sizeof(wchar_t) * dstChars); |
|
IStrSqlEscape(value.ToWchar().GetData(), tmp, dstChars); |
|
swprintf(dst, dstChars, L"'%s'", tmp); |
|
free(tmp); |
|
} |
|
|
|
static void IGetUuidFieldValue ( |
|
const plUUID & value, |
|
wchar_t * dst, |
|
size_t dstChars |
|
) { |
|
swprintf(dst, dstChars, L"hextoraw('%S')", value.AsString().c_str()); |
|
} |
|
|
|
static void IGetUintFieldValue ( |
|
uint32_t value, |
|
wchar_t * dst, |
|
size_t dstChars |
|
) { |
|
swprintf(dst, dstChars, L"%u", value); |
|
} |
|
|
|
static void IGetIntFieldValue ( |
|
int32_t value, |
|
wchar_t * dst, |
|
size_t dstChars |
|
) { |
|
swprintf(dst, dstChars, L"%d", value); |
|
} |
|
|
|
void RelVaultNode::Print (const wchar_t tag[], FStateDump dumpProc, unsigned level) { |
|
wchar_t str[1024]; |
|
StrPrintf( |
|
str, |
|
arrsize(str), |
|
L"%s%*s%*s%u, %S", |
|
tag ? tag : L"", |
|
tag ? 1 : 0, |
|
" ", |
|
level * 2, |
|
" ", |
|
GetNodeId(), |
|
plVault::NodeTypeStr(GetNodeType(), false) |
|
); |
|
|
|
for (uint64_t bit = 1; bit; bit <<= 1) { |
|
if (!(GetFieldFlags() & bit)) |
|
continue; |
|
if (bit > GetFieldFlags()) |
|
break; |
|
|
|
#define STPRINT(flag, func) case k##flag: { \ |
|
wcsncat(str, L", " L ## #flag L"=", arrsize(str)); \ |
|
const size_t chars = wcslen(str); \ |
|
func(Get##flag(), str + chars, arrsize(str) - chars * sizeof(str[0])); \ |
|
}; break |
|
#define STNAME(flag) case k##flag: { \ |
|
wcsncat(str, L", " L ## #flag, arrsize(str)); \ |
|
}; break |
|
switch (bit) { |
|
STPRINT(NodeId, IGetUintFieldValue); |
|
STPRINT(CreateTime, IGetUintFieldValue); |
|
STPRINT(ModifyTime, IGetUintFieldValue); |
|
STPRINT(CreateAgeName, IGetStringFieldValue); |
|
STPRINT(CreateAgeUuid, IGetUuidFieldValue); |
|
STPRINT(CreatorAcct, IGetUuidFieldValue); |
|
STPRINT(CreatorId, IGetUintFieldValue); |
|
STPRINT(NodeType, IGetUintFieldValue); |
|
STPRINT(Int32_1, IGetIntFieldValue); |
|
STPRINT(Int32_2, IGetIntFieldValue); |
|
STPRINT(Int32_3, IGetIntFieldValue); |
|
STPRINT(Int32_4, IGetIntFieldValue); |
|
STPRINT(UInt32_1, IGetUintFieldValue); |
|
STPRINT(UInt32_2, IGetUintFieldValue); |
|
STPRINT(UInt32_3, IGetUintFieldValue); |
|
STPRINT(UInt32_4, IGetUintFieldValue); |
|
STPRINT(Uuid_1, IGetUuidFieldValue); |
|
STPRINT(Uuid_2, IGetUuidFieldValue); |
|
STPRINT(Uuid_3, IGetUuidFieldValue); |
|
STPRINT(Uuid_4, IGetUuidFieldValue); |
|
STPRINT(String64_1, IGetStringFieldValue); |
|
STPRINT(String64_2, IGetStringFieldValue); |
|
STPRINT(String64_3, IGetStringFieldValue); |
|
STPRINT(String64_4, IGetStringFieldValue); |
|
STPRINT(String64_5, IGetStringFieldValue); |
|
STPRINT(String64_6, IGetStringFieldValue); |
|
STPRINT(IString64_1, IGetStringFieldValue); |
|
STPRINT(IString64_2, IGetStringFieldValue); |
|
STNAME(Text_1); |
|
STNAME(Text_2); |
|
STNAME(Blob_1); |
|
STNAME(Blob_2); |
|
DEFAULT_FATAL(bit); |
|
} |
|
#undef STPRINT |
|
} |
|
|
|
dumpProc(nil, str); |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::PrintTree (FStateDump dumpProc, unsigned level) { |
|
Print(L"", dumpProc, level); |
|
for (RelVaultNodeLink * link = state->children.Head(); link; link = state->children.Next(link)) |
|
link->node->PrintTree(dumpProc, level + 1); |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> RelVaultNode::GetParentAgeLink () { |
|
|
|
// this function only makes sense when called on age info nodes |
|
ASSERT(GetNodeType() == plVault::kNodeType_AgeInfo); |
|
|
|
hsRef<RelVaultNode> result; |
|
|
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
|
|
// Get our parent AgeLink node |
|
if (hsRef<RelVaultNode> rvnLink = GetParentNode(templateNode, 1)) { |
|
// Get the next AgeLink node in our parent tree |
|
result = rvnLink->GetParentNode(templateNode, 3); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Callbacks |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
void VaultRegisterCallback (VaultCallback * cb) { |
|
IVaultCallback * internal = new IVaultCallback; |
|
internal->cb = cb; |
|
cb->internal = internal; |
|
s_callbacks.Link(internal); |
|
} |
|
|
|
//============================================================================ |
|
void VaultUnregisterCallback (VaultCallback * cb) { |
|
ASSERT(cb->internal); |
|
delete cb->internal; |
|
cb->internal = nil; |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Initialize |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
void VaultInitialize () { |
|
s_running = true; |
|
|
|
NetCliAuthVaultSetRecvNodeChangedHandler(VaultNodeChanged); |
|
NetCliAuthVaultSetRecvNodeAddedHandler(VaultNodeAdded); |
|
NetCliAuthVaultSetRecvNodeRemovedHandler(VaultNodeRemoved); |
|
NetCliAuthVaultSetRecvNodeDeletedHandler(VaultNodeDeleted); |
|
} |
|
|
|
//============================================================================ |
|
void VaultDestroy () { |
|
s_running = false; |
|
|
|
NetCliAuthVaultSetRecvNodeChangedHandler(nil); |
|
NetCliAuthVaultSetRecvNodeAddedHandler(nil); |
|
NetCliAuthVaultSetRecvNodeRemovedHandler(nil); |
|
NetCliAuthVaultSetRecvNodeDeletedHandler(nil); |
|
|
|
VaultClearDeviceInboxMap(); |
|
|
|
RelVaultNodeLink * next, * link = s_nodes.Head(); |
|
for (; link; link = next) { |
|
next = s_nodes.Next(link); |
|
link->node->state->UnlinkFromRelatives(); |
|
delete link; |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void VaultUpdate () { |
|
SaveDirtyNodes(); |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Generic Vault Access |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetNode ( |
|
NetVaultNode * templateNode |
|
) { |
|
ASSERT(templateNode); |
|
RelVaultNodeLink * link = s_nodes.Head(); |
|
while (link) { |
|
if (link->node->Matches(templateNode)) |
|
return link->node; |
|
link = s_nodes.Next(link); |
|
} |
|
return nullptr; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetNode ( |
|
unsigned nodeId |
|
) { |
|
if (RelVaultNodeLink * link = s_nodes.Find(nodeId)) |
|
return link->node; |
|
return nullptr; |
|
} |
|
|
|
//============================================================================ |
|
void VaultAddChildNode ( |
|
unsigned parentId, |
|
unsigned childId, |
|
unsigned ownerId, |
|
FVaultAddChildNodeCallback callback, |
|
void * param |
|
) { |
|
// Make sure we only do the callback once |
|
bool madeCallback = false; |
|
|
|
// Too much of the client relies on the assumption that the node will be immediately |
|
// associated with its parent. THIS SUCKS, because there's no way to guarantee the |
|
// association won't be circular (the db checks this in a comprehensive way). |
|
// Because the client depends on this so much, we just link 'em together here if |
|
// we have both of them present locally. |
|
// This directly affects: New clothing items added to the avatar outfit folder, |
|
// new chronicle entries in some ages, and I'm sure several other situations. |
|
|
|
if (RelVaultNodeLink * parentLink = s_nodes.Find(parentId)) { |
|
RelVaultNodeLink * childLink = s_nodes.Find(childId); |
|
if (!childLink) { |
|
childLink = new RelVaultNodeLink(false, ownerId, childId, new RelVaultNode); |
|
childLink->node->SetNodeId_NoDirty(childId); |
|
s_nodes.Add(childLink); |
|
} |
|
else if (ownerId) { |
|
childLink->ownerId = ownerId; |
|
} |
|
|
|
// We can do a sanity check for a would-be circular link, but it isn't |
|
// authoritative. The db will prevent circular links from entering into |
|
// the persistent state, but because we are hacking in the association |
|
// before the authoritative check, we're risking the local client operating |
|
// on bad, possibly harmful vault state. Not harmful in a national security |
|
// kinda way, but still harmful. |
|
if (parentLink->node->IsChildOf(childId, 255)) { |
|
LogMsg(kLogDebug, L"Node relationship would be circular: p:%u, c:%u", parentId, childId); |
|
// callback now with error code |
|
if (callback) |
|
callback(kNetErrCircularReference, param); |
|
} |
|
else if (childLink->node->IsParentOf(parentId, 255)) { |
|
LogMsg(kLogDebug, L"Node relationship would be circular: p:%u, c:%u", parentId, childId); |
|
// callback now with error code |
|
if (callback) |
|
callback(kNetErrCircularReference, param); |
|
} |
|
else { |
|
NetVaultNodeRef refs[] = { |
|
{ parentId, childId, ownerId } |
|
}; |
|
|
|
ARRAY(unsigned) newNodeIds; |
|
ARRAY(unsigned) existingNodeIds; |
|
|
|
BuildNodeTree(refs, arrsize(refs), &newNodeIds, &existingNodeIds); |
|
|
|
if (!childLink->node->GetNodeType() || !parentLink->node->GetNodeType()) { |
|
// One or more nodes need to be fetched before the callback is made |
|
AddChildNodeFetchTrans * trans = new AddChildNodeFetchTrans(callback, param); |
|
if (!childLink->node->GetNodeType()) { |
|
++trans->opCount; |
|
NetCliAuthVaultNodeFetch( |
|
childId, |
|
AddChildNodeFetchTrans::VaultNodeFetched, |
|
trans |
|
); |
|
++trans->opCount; |
|
NetCliAuthVaultFetchNodeRefs( |
|
childId, |
|
AddChildNodeFetchTrans::VaultNodeRefsFetched, |
|
trans |
|
); |
|
} |
|
if (!parentLink->node->GetNodeType()) { |
|
++trans->opCount; |
|
NetCliAuthVaultNodeFetch( |
|
parentId, |
|
AddChildNodeFetchTrans::VaultNodeFetched, |
|
trans |
|
); |
|
++trans->opCount; |
|
NetCliAuthVaultFetchNodeRefs( |
|
parentId, |
|
AddChildNodeFetchTrans::VaultNodeRefsFetched, |
|
trans |
|
); |
|
} |
|
} |
|
else { |
|
// We have both nodes already, so make the callback now. |
|
if (callback) { |
|
callback(kNetSuccess, param); |
|
madeCallback = true; |
|
} |
|
} |
|
} |
|
} |
|
else { |
|
// Parent doesn't exist locally (and we may not want it to), just make the callback now. |
|
if (callback) { |
|
callback(kNetSuccess, param); |
|
madeCallback = true; |
|
} |
|
} |
|
|
|
// Send it on up to the vault. The db server filters out duplicate and |
|
// circular node relationships. We send the request up even if we think |
|
// the relationship would be circular since the db does a universal |
|
// check and is the only real authority in this matter. |
|
NetCliAuthVaultNodeAdd( |
|
parentId, |
|
childId, |
|
ownerId, |
|
madeCallback ? nil : callback, |
|
madeCallback ? nil : param |
|
); |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultAddChildNodeAndWait { |
|
|
|
struct _AddChildNodeParam { |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _AddChildNodeCallback ( |
|
ENetError result, |
|
void * vparam |
|
) { |
|
_AddChildNodeParam * param = (_AddChildNodeParam *)vparam; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
|
|
} // namespace _VaultAddChildNodeAndWait |
|
|
|
//============================================================================ |
|
void VaultAddChildNodeAndWait ( |
|
unsigned parentId, |
|
unsigned childId, |
|
unsigned ownerId |
|
) { |
|
using namespace _VaultAddChildNodeAndWait; |
|
|
|
_AddChildNodeParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultAddChildNode( |
|
parentId, |
|
childId, |
|
ownerId, |
|
_AddChildNodeCallback, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) |
|
LogMsg(kLogError, L"VaultAddChildNodeAndWait: Failed to add child node: p:%u,c:%u. %s", parentId, childId, NetErrorToString(param.result)); |
|
} |
|
|
|
//============================================================================ |
|
void VaultRemoveChildNode ( |
|
unsigned parentId, |
|
unsigned childId, |
|
FVaultRemoveChildNodeCallback callback, |
|
void * param |
|
) { |
|
for (;;) { |
|
// Unlink 'em locally, if we can |
|
RelVaultNodeLink * parentLink = s_nodes.Find(parentId); |
|
if (!parentLink) |
|
break; |
|
|
|
RelVaultNodeLink * childLink = s_nodes.Find(childId); |
|
if (!childLink) |
|
break; |
|
|
|
if (parentLink->node->IsParentOf(childId, 1)) { |
|
// We have the relationship, so make the callbacks |
|
for (IVaultCallback * cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) |
|
cb->cb->RemovingChildNode(parentLink->node, childLink->node); |
|
} |
|
|
|
parentLink->node->state->Unlink(childLink->node); |
|
childLink->node->state->Unlink(parentLink->node); |
|
break; |
|
} |
|
|
|
// Send it on up to the vault |
|
NetCliAuthVaultNodeRemove( |
|
parentId, |
|
childId, |
|
callback, |
|
param |
|
); |
|
} |
|
|
|
//============================================================================ |
|
void VaultSetNodeSeen ( |
|
unsigned nodeId, |
|
bool seen |
|
) { |
|
hsAssert(false, "eric, implement me"); |
|
} |
|
|
|
//============================================================================ |
|
void VaultDeleteNode ( |
|
unsigned nodeId |
|
) { |
|
// Send request up to vault. We will remove it locally upon notification of deletion. |
|
NetCliAuthVaultNodeDelete(nodeId); |
|
} |
|
|
|
//============================================================================ |
|
void VaultPublishNode ( |
|
unsigned nodeId, |
|
const plString& deviceName |
|
) { |
|
hsRef<RelVaultNode> rvn; |
|
|
|
rvn = VaultAgeGetDeviceInbox(deviceName); |
|
if (!rvn) { |
|
LogMsg(kLogDebug, L"Failed to find inbox for device %S, adding it on-the-fly", deviceName.c_str()); |
|
VaultAgeSetDeviceInboxAndWait(deviceName, DEFAULT_DEVICE_INBOX); |
|
|
|
rvn = VaultAgeGetDeviceInbox(deviceName); |
|
if (!rvn) { |
|
LogMsg(kLogDebug, L"Failed to add inbox to device %S on-the-fly", deviceName.c_str()); |
|
return; |
|
} |
|
} |
|
|
|
VaultAddChildNode(rvn->GetNodeId(), nodeId, VaultGetPlayerId(), nil, nil); |
|
} |
|
|
|
//============================================================================ |
|
void VaultSendNode ( |
|
RelVaultNode* srcNode, |
|
unsigned dstPlayerId |
|
) { |
|
NetCliAuthVaultNodeSave(srcNode, nil, nil); |
|
NetCliAuthVaultSendNode(srcNode->GetNodeId(), dstPlayerId); |
|
} |
|
|
|
//============================================================================ |
|
void VaultCreateNode ( |
|
NetVaultNode * templateNode, |
|
FVaultCreateNodeCallback callback, |
|
void * state, |
|
void * param |
|
) { |
|
VaultCreateNodeTrans * trans = new VaultCreateNodeTrans(callback, state, param); |
|
|
|
if (hsRef<RelVaultNode> age = VaultGetAgeNode()) { |
|
VaultAgeNode access(age); |
|
templateNode->SetCreateAgeName(access.GetAgeName()); |
|
templateNode->SetCreateAgeUuid(access.GetAgeInstanceGuid()); |
|
} |
|
|
|
NetCliAuthVaultNodeCreate( |
|
templateNode, |
|
VaultCreateNodeTrans::VaultNodeCreated, |
|
trans |
|
); |
|
} |
|
|
|
//============================================================================ |
|
void VaultCreateNode ( |
|
plVault::NodeTypes nodeType, |
|
FVaultCreateNodeCallback callback, |
|
void * state, |
|
void * param |
|
) { |
|
hsRef<RelVaultNode> templateNode = new RelVaultNode; |
|
templateNode->SetNodeType(nodeType); |
|
|
|
VaultCreateNode( |
|
templateNode, |
|
callback, |
|
state, |
|
param |
|
); |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultCreateNodeAndWait { |
|
|
|
struct _CreateNodeParam { |
|
RelVaultNode * node; |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _CreateNodeCallback ( |
|
ENetError result, |
|
void * , |
|
void * vparam, |
|
RelVaultNode * node |
|
) { |
|
_CreateNodeParam * param = (_CreateNodeParam *)vparam; |
|
param->node = node; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
|
|
} // namespace _VaultCreateNodeAndWait |
|
|
|
hsRef<RelVaultNode> VaultCreateNodeAndWait ( |
|
NetVaultNode * templateNode, |
|
ENetError * result |
|
) { |
|
using namespace _VaultCreateNodeAndWait; |
|
|
|
_CreateNodeParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultCreateNode( |
|
templateNode, |
|
_CreateNodeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
*result = param.result; |
|
return param.node; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultCreateNodeAndWait ( |
|
plVault::NodeTypes nodeType, |
|
ENetError * result |
|
) { |
|
hsRef<RelVaultNode> node; |
|
hsRef<RelVaultNode> templateNode = new RelVaultNode; |
|
templateNode->SetNodeType(nodeType); |
|
|
|
return VaultCreateNodeAndWait(templateNode, result); |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultForceSaveNodeAndWait { |
|
|
|
struct _SaveNodeParam { |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _SaveNodeCallback ( |
|
ENetError result, |
|
void * vparam |
|
) { |
|
_SaveNodeParam * param = (_SaveNodeParam *)vparam; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
|
|
} // namespace _VaultForceSaveNodeAndWait |
|
|
|
void VaultForceSaveNodeAndWait ( |
|
NetVaultNode * node |
|
) { |
|
using namespace _VaultForceSaveNodeAndWait; |
|
|
|
_SaveNodeParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
NetCliAuthVaultNodeSave( |
|
node, |
|
_SaveNodeCallback, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void VaultFindNodes ( |
|
NetVaultNode * templateNode, |
|
FVaultFindNodeCallback callback, |
|
void * param |
|
) { |
|
VaultFindNodeTrans * trans = new VaultFindNodeTrans(callback, param); |
|
|
|
NetCliAuthVaultNodeFind( |
|
templateNode, |
|
VaultFindNodeTrans::VaultNodeFound, |
|
trans |
|
); |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultFindNodesAndWait { |
|
struct _FindNodeParam { |
|
ARRAY(unsigned) nodeIds; |
|
ENetError result; |
|
bool complete; |
|
|
|
_FindNodeParam() |
|
: result(kNetPending), complete(false) |
|
{ } |
|
}; |
|
static void _FindNodeCallback ( |
|
ENetError result, |
|
void * vparam, |
|
unsigned nodeIdCount, |
|
const unsigned nodeIds[] |
|
) { |
|
_FindNodeParam * param = (_FindNodeParam *)vparam; |
|
param->nodeIds.Set(nodeIds, nodeIdCount); |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
|
|
} // namespace _VaultFindNodesAndWait |
|
|
|
void VaultFindNodesAndWait ( |
|
NetVaultNode * templateNode, |
|
ARRAY(unsigned) * nodeIds |
|
) { |
|
using namespace _VaultFindNodesAndWait; |
|
|
|
_FindNodeParam param; |
|
NetCliAuthVaultNodeFind( |
|
templateNode, |
|
_FindNodeCallback, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_SUCCESS(param.result)) |
|
nodeIds->Add(param.nodeIds.Ptr(), param.nodeIds.Count()); |
|
} |
|
|
|
//============================================================================ |
|
void VaultLocalFindNodes ( |
|
NetVaultNode * templateNode, |
|
ARRAY(unsigned) * nodeIds |
|
) { |
|
for (RelVaultNodeLink * link = s_nodes.Head(); link != nil; link = s_nodes.Next(link)) { |
|
if (link->node->Matches(templateNode)) |
|
nodeIds->Add(link->node->GetNodeId()); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultFetchNodesAndWait { |
|
|
|
static void _VaultNodeFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNode * node |
|
) { |
|
::VaultNodeFetched(result, nil, node); |
|
|
|
--(*reinterpret_cast<std::atomic<unsigned>*>(param)); |
|
} |
|
|
|
} // namespace _VaultFetchNodesAndWait |
|
|
|
void VaultFetchNodesAndWait ( |
|
const unsigned nodeIds[], |
|
unsigned count, |
|
bool force |
|
) { |
|
using namespace _VaultFetchNodesAndWait; |
|
|
|
std::atomic<unsigned> nodeCount(count); |
|
|
|
for (unsigned i = 0; i < count; ++i) { |
|
|
|
if (!force) { |
|
// See if we already have this node |
|
if (RelVaultNodeLink * link = s_nodes.Find(nodeIds[i])) { |
|
--nodeCount; |
|
continue; |
|
} |
|
} |
|
|
|
// Start fetching the node |
|
NetCliAuthVaultNodeFetch(nodeIds[i], _VaultNodeFetched, |
|
reinterpret_cast<void *>(&nodeCount)); |
|
} |
|
|
|
while (nodeCount) { |
|
NetClientUpdate(); |
|
AsyncSleep(10); |
|
} |
|
} |
|
|
|
|
|
//============================================================================ |
|
void VaultInitAge ( |
|
const plAgeInfoStruct * info, |
|
const plUUID parentAgeInstId, // optional |
|
FVaultInitAgeCallback callback, |
|
void * state, |
|
void * param |
|
) { |
|
VaultAgeInitTrans * trans = new VaultAgeInitTrans(callback, state, param); |
|
|
|
wchar_t ageFilename[MAX_PATH]; |
|
wchar_t ageInstName[MAX_PATH]; |
|
wchar_t ageUserName[MAX_PATH]; |
|
wchar_t ageDesc[1024]; |
|
|
|
StrToUnicode(ageFilename, info->GetAgeFilename(), arrsize(ageFilename)); |
|
StrToUnicode(ageInstName, info->GetAgeInstanceName(), arrsize(ageInstName)); |
|
StrToUnicode(ageUserName, info->GetAgeUserDefinedName(), arrsize(ageUserName)); |
|
StrToUnicode(ageDesc, info->GetAgeDescription(), arrsize(ageDesc)); |
|
|
|
NetCliAuthVaultInitAge( |
|
*info->GetAgeInstanceGuid(), |
|
parentAgeInstId, |
|
ageFilename, |
|
ageInstName, |
|
ageUserName, |
|
ageDesc, |
|
info->GetAgeSequenceNumber(), |
|
info->GetAgeLanguage(), |
|
VaultAgeInitTrans::AgeInitCallback, |
|
trans |
|
); |
|
} |
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Player Vault Access |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
static hsRef<RelVaultNode> GetPlayerNode () { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_VNodeMgrPlayer); |
|
if (NetCommGetPlayer()) |
|
templateNode->SetNodeId(NetCommGetPlayer()->playerInt); |
|
return VaultGetNode(templateNode); |
|
} |
|
|
|
//============================================================================ |
|
unsigned VaultGetPlayerId () { |
|
if (hsRef<RelVaultNode> rvn = GetPlayerNode()) |
|
return rvn->GetNodeId(); |
|
return 0; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetPlayerNode () { |
|
if (hsRef<RelVaultNode> rvnPlr = GetPlayerNode()) |
|
return rvnPlr; |
|
return nullptr; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetPlayerInfoNode () { |
|
hsRef<RelVaultNode> rvnPlr = VaultGetPlayerNode(); |
|
if (!rvnPlr) |
|
return nullptr; |
|
|
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_PlayerInfo); |
|
VaultPlayerInfoNode plrInfo(templateNode); |
|
plrInfo.SetPlayerId(rvnPlr->GetNodeId()); |
|
|
|
hsRef<RelVaultNode> result; |
|
if (hsRef<RelVaultNode> rvnPlrInfo = rvnPlr->GetChildNode(templateNode, 1)) |
|
result = rvnPlrInfo; |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAvatarOutfitFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetPlayerNode()) |
|
return rvn->GetChildFolderNode(plVault::kAvatarOutfitFolder, 1); |
|
return nullptr; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAvatarClosetFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetPlayerNode()) |
|
return rvn->GetChildFolderNode(plVault::kAvatarClosetFolder, 1); |
|
return nullptr; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetChronicleFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetPlayerNode()) |
|
return rvn->GetChildFolderNode(plVault::kChronicleFolder, 1); |
|
return nullptr; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAgesIOwnFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetPlayerNode()) |
|
return rvn->GetChildAgeInfoListNode(plVault::kAgesIOwnFolder, 1); |
|
return nullptr; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAgesICanVisitFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetPlayerNode()) |
|
return rvn->GetChildAgeInfoListNode(plVault::kAgesICanVisitFolder, 1); |
|
return nullptr; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetPlayerInboxFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetPlayerNode()) |
|
return rvn->GetChildFolderNode(plVault::kInboxFolder, 1); |
|
return nullptr; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetLinkToMyNeighborhood (plAgeLinkStruct * link) { |
|
hsRef<RelVaultNode> rvnFldr = VaultGetAgesIOwnFolder(); |
|
if (!rvnFldr) |
|
return false; |
|
|
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
|
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
VaultAgeInfoNode ageInfo(templateNode); |
|
ageInfo.SetAgeFilename(kNeighborhoodAgeFilename); |
|
|
|
hsRef<RelVaultNode> node; |
|
if (node = rvnFldr->GetChildNode(templateNode, 2)) { |
|
VaultAgeInfoNode info(node); |
|
info.CopyTo(link->GetAgeInfo()); |
|
} |
|
|
|
return node != nil; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetLinkToMyPersonalAge (plAgeLinkStruct * link) { |
|
hsRef<RelVaultNode> rvnFldr = VaultGetAgesIOwnFolder(); |
|
if (!rvnFldr) |
|
return false; |
|
|
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
|
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
VaultAgeInfoNode ageInfo(templateNode); |
|
ageInfo.SetAgeFilename(kPersonalAgeFilename); |
|
|
|
hsRef<RelVaultNode> node; |
|
if (node = rvnFldr->GetChildNode(templateNode, 2)) { |
|
VaultAgeInfoNode info(node); |
|
info.CopyTo(link->GetAgeInfo()); |
|
} |
|
|
|
return node != nil; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetLinkToCity (plAgeLinkStruct * link) { |
|
hsRef<RelVaultNode> rvnFldr = VaultGetAgesIOwnFolder(); |
|
if (!rvnFldr) |
|
return false; |
|
|
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
ageInfo.SetAgeFilename(kCityAgeFilename); |
|
|
|
hsRef<RelVaultNode> node; |
|
if (node = rvnFldr->GetChildNode(templateNode, 2)) { |
|
VaultAgeInfoNode info(node); |
|
info.CopyTo(link->GetAgeInfo()); |
|
} |
|
|
|
return node != nil; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetOwnedAgeLink (const plAgeInfoStruct * info) { |
|
|
|
hsRef<RelVaultNode> rvnLink; |
|
|
|
if (hsRef<RelVaultNode> rvnFldr = VaultGetAgesIOwnFolder()) { |
|
|
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
if (info->HasAgeFilename()) { |
|
ageInfo.SetAgeFilename(info->GetAgeFilename()); |
|
} |
|
if (info->HasAgeInstanceGuid()) { |
|
ageInfo.SetAgeInstanceGuid(*info->GetAgeInstanceGuid()); |
|
} |
|
|
|
if (hsRef<RelVaultNode> rvnInfo = rvnFldr->GetChildNode(templateNode, 2)) { |
|
templateNode->Clear(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
rvnLink = rvnInfo->GetParentNode(templateNode, 1); |
|
} |
|
} |
|
|
|
return rvnLink; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetOwnedAgeInfo (const plAgeInfoStruct * info) { |
|
|
|
hsRef<RelVaultNode> rvnInfo; |
|
if (hsRef<RelVaultNode> rvnFldr = VaultGetAgesIOwnFolder()) { |
|
|
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
if (info->HasAgeFilename()) { |
|
ageInfo.SetAgeFilename(info->GetAgeFilename()); |
|
} |
|
if (info->HasAgeInstanceGuid()) { |
|
ageInfo.SetAgeInstanceGuid(*info->GetAgeInstanceGuid()); |
|
} |
|
|
|
rvnInfo = rvnFldr->GetChildNode(templateNode, 2); |
|
} |
|
return rvnInfo; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetOwnedAgeLink (const plAgeInfoStruct * info, plAgeLinkStruct * link) { |
|
bool result = false; |
|
if (hsRef<RelVaultNode> rvnLink = VaultGetOwnedAgeLink(info)) { |
|
if (hsRef<RelVaultNode> rvnInfo = rvnLink->GetChildNode(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode ageInfo(rvnInfo); |
|
ageInfo.CopyTo(link->GetAgeInfo()); |
|
result = true; |
|
} |
|
} |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultFindOrCreateChildAgeLinkAndWait (const wchar_t ownedAgeName[], const plAgeInfoStruct * info, plAgeLinkStruct * link) { |
|
hsAssert(false, "eric, implement me"); |
|
return false; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAddOwnedAgeSpawnPoint (const plUUID& ageInstId, const plSpawnPointInfo & spawnPt) { |
|
|
|
hsRef<RelVaultNode> fldr, link; |
|
|
|
for (;;) { |
|
if (spawnPt.GetName().IsEmpty()) |
|
break; |
|
if (spawnPt.GetTitle().IsEmpty()) |
|
break; |
|
|
|
fldr = VaultGetAgesIOwnFolder(); |
|
if (!fldr) |
|
break; |
|
|
|
ARRAY(unsigned) nodeIds; |
|
fldr->GetChildNodeIds(&nodeIds, 1); |
|
|
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
VaultAgeInfoNode access(templateNode); |
|
access.SetAgeInstanceGuid(ageInstId); |
|
|
|
for (unsigned i = 0; i < nodeIds.Count(); ++i) { |
|
link = VaultGetNode(nodeIds[i]); |
|
if (!link) |
|
continue; |
|
if (link->GetChildNode(templateNode, 1)) { |
|
VaultAgeLinkNode access(link); |
|
access.AddSpawnPoint(spawnPt); |
|
link = nullptr; |
|
break; |
|
} |
|
} |
|
|
|
break; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultSetOwnedAgePublicAndWait (const plAgeInfoStruct * info, bool publicOrNot) { |
|
if (hsRef<RelVaultNode> rvnLink = VaultGetOwnedAgeLink(info)) { |
|
if (hsRef<RelVaultNode> rvnInfo = rvnLink->GetChildNode(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultSetAgePublicAndWait(rvnInfo, publicOrNot); |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultSetAgePublicAndWait (NetVaultNode * ageInfoNode, bool publicOrNot) { |
|
NetCliAuthSetAgePublic(ageInfoNode->GetNodeId(), publicOrNot); |
|
|
|
VaultAgeInfoNode access(ageInfoNode); |
|
|
|
plVaultNotifyMsg * msg = new plVaultNotifyMsg; |
|
if (publicOrNot) |
|
msg->SetType(plVaultNotifyMsg::kPublicAgeCreated); |
|
else |
|
msg->SetType(plVaultNotifyMsg::kPublicAgeRemoved); |
|
msg->SetResultCode(true); |
|
msg->GetArgs()->AddString(plNetCommon::VaultTaskArgs::kAgeFilename, access.GetAgeFilename().c_str()); |
|
msg->Send(); |
|
return true; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetVisitAgeLink (const plAgeInfoStruct * info) { |
|
hsRef<RelVaultNode> rvnLink; |
|
|
|
if (hsRef<RelVaultNode> rvnFldr = VaultGetAgesICanVisitFolder()) { |
|
|
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
if (info->HasAgeFilename()) { |
|
ageInfo.SetAgeFilename(info->GetAgeFilename()); |
|
} |
|
if (info->HasAgeInstanceGuid()) { |
|
ageInfo.SetAgeInstanceGuid(*info->GetAgeInstanceGuid()); |
|
} |
|
|
|
if (hsRef<RelVaultNode> rvnInfo = rvnFldr->GetChildNode(templateNode, 2)) { |
|
templateNode->Clear(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
rvnLink = rvnInfo->GetParentNode(templateNode, 1); |
|
} |
|
} |
|
|
|
return rvnLink; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetVisitAgeLink (const plAgeInfoStruct * info, class plAgeLinkStruct * link) { |
|
hsRef<RelVaultNode> rvn = VaultGetVisitAgeLink(info); |
|
if (!rvn) |
|
return false; |
|
|
|
VaultAgeLinkNode ageLink(rvn); |
|
ageLink.CopyTo(link); |
|
return true; |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultRegisterOwnedAgeAndWait { |
|
|
|
struct _InitAgeParam { |
|
ENetError result; |
|
bool complete; |
|
unsigned ageInfoId; |
|
}; |
|
static void _InitAgeCallback ( |
|
ENetError result, |
|
void * , |
|
void * vparam, |
|
unsigned ageVaultId, |
|
unsigned ageInfoVaultId |
|
) { |
|
_InitAgeParam * param = (_InitAgeParam *)vparam; |
|
param->ageInfoId = ageInfoVaultId; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _FetchVaultParam { |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _FetchVaultCallback ( |
|
ENetError result, |
|
void * vparam |
|
) { |
|
_FetchVaultParam * param = (_FetchVaultParam *)vparam; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _CreateNodeParam { |
|
ENetError result; |
|
bool complete; |
|
unsigned nodeId; |
|
}; |
|
static void _CreateNodeCallback ( |
|
ENetError result, |
|
void * , |
|
void * vparam, |
|
RelVaultNode * node |
|
) { |
|
_CreateNodeParam * param = (_CreateNodeParam *)vparam; |
|
if (IS_NET_SUCCESS(result)) |
|
param->nodeId = node->GetNodeId(); |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _AddChildNodeParam { |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _AddChildNodeCallback ( |
|
ENetError result, |
|
void * vparam |
|
) { |
|
_AddChildNodeParam * param = (_AddChildNodeParam *)vparam; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
|
|
} // namespace _VaultRegisterOwnedAgeAndWait |
|
|
|
//============================================================================ |
|
bool VaultRegisterOwnedAgeAndWait (const plAgeLinkStruct * link) { |
|
using namespace _VaultRegisterOwnedAgeAndWait; |
|
|
|
unsigned ageLinkId = 0; |
|
unsigned ageInfoId; |
|
unsigned agesIOwnId; |
|
|
|
bool result = false; |
|
|
|
for (;;) { |
|
if (hsRef<RelVaultNode> rvn = VaultGetAgesIOwnFolder()) |
|
agesIOwnId = rvn->GetNodeId(); |
|
else { |
|
LogMsg(kLogError, L"RegisterOwnedAge: Failed to get player's AgesIOwnFolder"); |
|
break; |
|
} |
|
|
|
// Check for existing link to this age |
|
plAgeLinkStruct existing; |
|
if (VaultGetOwnedAgeLink(link->GetAgeInfo(), &existing)) { |
|
result = true; |
|
break; |
|
} |
|
|
|
{ // Init age vault |
|
_InitAgeParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultInitAge( |
|
link->GetAgeInfo(), |
|
kNilUuid, |
|
_InitAgeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, "RegisterOwnedAge: Failed to init age %s", link->GetAgeInfo()->GetAgeFilename().c_str()); |
|
break; |
|
} |
|
|
|
ageInfoId = param.ageInfoId; |
|
} |
|
|
|
{ // Create age link |
|
_CreateNodeParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultCreateNode( |
|
plVault::kNodeType_AgeLink, |
|
_CreateNodeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"RegisterOwnedAge: Failed create age link node"); |
|
break; |
|
} |
|
|
|
ageLinkId = param.nodeId; |
|
} |
|
|
|
{ // Fetch age info node tree |
|
_FetchVaultParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultDownload( |
|
L"RegisterOwnedAge", |
|
ageInfoId, |
|
_FetchVaultCallback, |
|
¶m, |
|
nil, |
|
nil |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"RegisterOwnedAge: Failed to download age info vault"); |
|
break; |
|
} |
|
} |
|
|
|
{ // Link: |
|
// ageLink to player's bookshelf folder |
|
// ageInfo to ageLink |
|
// playerInfo to ageOwners |
|
_AddChildNodeParam param1; |
|
_AddChildNodeParam param2; |
|
_AddChildNodeParam param3; |
|
memset(¶m1, 0, sizeof(param1)); |
|
memset(¶m2, 0, sizeof(param2)); |
|
memset(¶m3, 0, sizeof(param3)); |
|
|
|
unsigned ageOwnersId = 0; |
|
if (hsRef<RelVaultNode> rvnAgeInfo = VaultGetNode(ageInfoId)) { |
|
if (hsRef<RelVaultNode> rvnAgeOwners = rvnAgeInfo->GetChildPlayerInfoListNode(plVault::kAgeOwnersFolder, 1)) |
|
ageOwnersId = rvnAgeOwners->GetNodeId(); |
|
} |
|
|
|
unsigned playerInfoId = 0; |
|
if (hsRef<RelVaultNode> rvnPlayerInfo = VaultGetPlayerInfoNode()) |
|
playerInfoId = rvnPlayerInfo->GetNodeId(); |
|
|
|
VaultAddChildNode( |
|
agesIOwnId, |
|
ageLinkId, |
|
0, |
|
_AddChildNodeCallback, |
|
¶m1 |
|
); |
|
|
|
VaultAddChildNode( |
|
ageLinkId, |
|
ageInfoId, |
|
0, |
|
_AddChildNodeCallback, |
|
¶m2 |
|
); |
|
|
|
VaultAddChildNode( |
|
ageOwnersId, |
|
playerInfoId, |
|
0, |
|
_AddChildNodeCallback, |
|
¶m3 |
|
); |
|
|
|
while (!param1.complete && !param2.complete && !param3.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param1.result)) { |
|
LogMsg(kLogError, L"RegisterOwnedAge: Failed to add link to player's bookshelf"); |
|
break; |
|
} |
|
if (IS_NET_ERROR(param2.result)) { |
|
LogMsg(kLogError, L"RegisterOwnedAge: Failed to add info to link"); |
|
break; |
|
} |
|
if (IS_NET_ERROR(param3.result)) { |
|
LogMsg(kLogError, L"RegisterOwnedAge: Failed to add playerInfo to ageOwners"); |
|
break; |
|
} |
|
} |
|
|
|
// Copy the link spawn point to the link node |
|
if (hsRef<RelVaultNode> node = VaultGetNode(ageLinkId)) { |
|
VaultAgeLinkNode access(node); |
|
access.AddSpawnPoint(link->SpawnPoint()); |
|
} |
|
|
|
result = true; |
|
break; |
|
} |
|
|
|
plVaultNotifyMsg * msg = new plVaultNotifyMsg; |
|
msg->SetType(plVaultNotifyMsg::kRegisteredOwnedAge); |
|
msg->SetResultCode(result); |
|
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, ageLinkId); |
|
msg->Send(); |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultRegisterOwnedAge { |
|
struct _Params { |
|
plSpawnPointInfo* fSpawn; |
|
void* fAgeInfoId; |
|
|
|
~_Params() { |
|
delete 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)"); |
|
delete (_Params*)param; |
|
return; |
|
} |
|
|
|
// Grab our params |
|
_Params* p = (_Params*)param; |
|
|
|
// Set swpoint |
|
VaultAgeLinkNode aln(node); |
|
aln.AddSpawnPoint(*(p->fSpawn)); |
|
|
|
// Make some refs |
|
hsRef<RelVaultNode> agesIOwn = VaultGetAgesIOwnFolder(); |
|
hsRef<RelVaultNode> plyrInfo = VaultGetPlayerInfoNode(); |
|
VaultAddChildNode(agesIOwn->GetNodeId(), node->GetNodeId(), 0, (FVaultAddChildNodeCallback)_AddAgeLinkNode, nil); |
|
VaultAddChildNode(node->GetNodeId(), (uint32_t)((uintptr_t)p->fAgeInfoId), 0, (FVaultAddChildNodeCallback)_AddAgeInfoNode, nil); |
|
|
|
// Add our PlayerInfo to important places |
|
if (hsRef<RelVaultNode> rvnAgeInfo = VaultGetNode((uint32_t)((uintptr_t)p->fAgeInfoId))) { |
|
if (hsRef<RelVaultNode> rvnAgeOwners = rvnAgeInfo->GetChildPlayerInfoListNode(plVault::kAgeOwnersFolder, 1)) |
|
VaultAddChildNode(rvnAgeOwners->GetNodeId(), plyrInfo->GetNodeId(), 0, (FVaultAddChildNodeCallback)_AddPlayerInfoNode, nil); |
|
} |
|
|
|
// Fire off vault callbacks |
|
plVaultNotifyMsg* msg = new plVaultNotifyMsg; |
|
msg->SetType(plVaultNotifyMsg::kRegisteredOwnedAge); |
|
msg->SetResultCode(result); |
|
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->GetNodeId()); |
|
msg->Send(); |
|
|
|
// Don't leak memory |
|
delete p; |
|
} |
|
|
|
void _DownloadCallback(ENetError result, void* param) { |
|
if (IS_NET_ERROR(result)) { |
|
LogMsg(kLogError, "VaultRegisterOwnedAge: Failed to download age vault (async)"); |
|
delete (_Params*)param; |
|
} else |
|
VaultCreateNode(plVault::kNodeType_AgeLink, (FVaultCreateNodeCallback)_CreateAgeLinkNode, nil, param); |
|
} |
|
|
|
void _InitAgeCallback(ENetError result, void* state, void* param, uint32_t ageVaultId, uint32_t ageInfoVaultId) { |
|
if (IS_NET_SUCCESS(result)) { |
|
_Params* p = 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; |
|
|
|
hsRef<RelVaultNode> agesIOwn = VaultGetAgesIOwnFolder(); |
|
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(), |
|
kNilUuid, |
|
(FVaultInitAgeCallback)_InitAgeCallback, |
|
nil, |
|
new plSpawnPointInfo(link->SpawnPoint())); |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultRegisterVisitAgeAndWait { |
|
|
|
struct _InitAgeParam { |
|
ENetError result; |
|
bool complete; |
|
unsigned ageInfoId; |
|
}; |
|
static void _InitAgeCallback ( |
|
ENetError result, |
|
void * , |
|
void * vparam, |
|
unsigned ageVaultId, |
|
unsigned ageInfoVaultId |
|
) { |
|
_InitAgeParam * param = (_InitAgeParam *)vparam; |
|
param->ageInfoId = ageInfoVaultId; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _FetchVaultParam { |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _FetchVaultCallback ( |
|
ENetError result, |
|
void * vparam |
|
) { |
|
_FetchVaultParam * param = (_FetchVaultParam *)vparam; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _CreateNodeParam { |
|
ENetError result; |
|
bool complete; |
|
unsigned nodeId; |
|
}; |
|
static void _CreateNodeCallback ( |
|
ENetError result, |
|
void * , |
|
void * vparam, |
|
RelVaultNode * node |
|
) { |
|
_CreateNodeParam * param = (_CreateNodeParam *)vparam; |
|
if (IS_NET_SUCCESS(result)) |
|
param->nodeId = node->GetNodeId(); |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _AddChildNodeParam { |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _AddChildNodeCallback ( |
|
ENetError result, |
|
void * vparam |
|
) { |
|
_AddChildNodeParam * param = (_AddChildNodeParam *)vparam; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
|
|
} // namespace _VaultRegisterVisitAgeAndWait |
|
|
|
//============================================================================ |
|
bool VaultRegisterVisitAgeAndWait (const plAgeLinkStruct * link) { |
|
using namespace _VaultRegisterVisitAgeAndWait; |
|
|
|
unsigned ageLinkId = 0; |
|
unsigned ageInfoId; |
|
unsigned agesICanVisitId; |
|
|
|
bool result = false; |
|
for (;;) { |
|
if (hsRef<RelVaultNode> rvn = VaultGetAgesICanVisitFolder()) |
|
agesICanVisitId = rvn->GetNodeId(); |
|
else { |
|
LogMsg(kLogError, L"RegisterVisitAge: Failed to get player's AgesICanVisitFolder"); |
|
break; |
|
} |
|
|
|
// Check for existing link to this age |
|
plAgeLinkStruct existing; |
|
if (VaultGetVisitAgeLink(link->GetAgeInfo(), &existing)) { |
|
result = true; |
|
break; |
|
} |
|
|
|
|
|
{ // Init age vault |
|
_InitAgeParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultInitAge( |
|
link->GetAgeInfo(), |
|
kNilUuid, |
|
_InitAgeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, "RegisterVisitAge: Failed to init age %s", link->GetAgeInfo()->GetAgeFilename().c_str()); |
|
break; |
|
} |
|
|
|
ageInfoId = param.ageInfoId; |
|
} |
|
|
|
{ // Create age link |
|
_CreateNodeParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultCreateNode( |
|
plVault::kNodeType_AgeLink, |
|
_CreateNodeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"RegisterVisitAge: Failed create age link node"); |
|
break; |
|
} |
|
|
|
ageLinkId = param.nodeId; |
|
} |
|
|
|
{ // Fetch age info node tree |
|
_FetchVaultParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultDownload( |
|
L"RegisterVisitAge", |
|
ageInfoId, |
|
_FetchVaultCallback, |
|
¶m, |
|
nil, |
|
nil |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"RegisterVisitAge: Failed to download age info vault"); |
|
break; |
|
} |
|
} |
|
|
|
{ // Link: |
|
// ageLink to player's "can visit" folder |
|
// ageInfo to ageLink |
|
_AddChildNodeParam param1; |
|
_AddChildNodeParam param2; |
|
_AddChildNodeParam param3; |
|
memset(¶m1, 0, sizeof(param1)); |
|
memset(¶m2, 0, sizeof(param2)); |
|
memset(¶m3, 0, sizeof(param3)); |
|
|
|
unsigned ageVisitorsId = 0; |
|
if (hsRef<RelVaultNode> rvnAgeInfo = VaultGetNode(ageInfoId)) { |
|
if (hsRef<RelVaultNode> rvnAgeVisitors = rvnAgeInfo->GetChildPlayerInfoListNode(plVault::kCanVisitFolder, 1)) |
|
ageVisitorsId = rvnAgeVisitors->GetNodeId(); |
|
} |
|
|
|
unsigned playerInfoId = 0; |
|
if (hsRef<RelVaultNode> rvnPlayerInfo = VaultGetPlayerInfoNode()) |
|
playerInfoId = rvnPlayerInfo->GetNodeId(); |
|
|
|
VaultAddChildNode( |
|
agesICanVisitId, |
|
ageLinkId, |
|
0, |
|
_AddChildNodeCallback, |
|
¶m1 |
|
); |
|
|
|
VaultAddChildNode( |
|
ageLinkId, |
|
ageInfoId, |
|
0, |
|
_AddChildNodeCallback, |
|
¶m2 |
|
); |
|
|
|
VaultAddChildNode( |
|
ageVisitorsId, |
|
playerInfoId, |
|
0, |
|
_AddChildNodeCallback, |
|
¶m3 |
|
); |
|
|
|
while (!param1.complete && !param2.complete && !param3.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param1.result)) { |
|
LogMsg(kLogError, L"RegisterVisitAge: Failed to add link to folder"); |
|
break; |
|
} |
|
if (IS_NET_ERROR(param2.result)) { |
|
LogMsg(kLogError, L"RegisterVisitAge: Failed to add info to link"); |
|
break; |
|
} |
|
if (IS_NET_ERROR(param3.result)) { |
|
LogMsg(kLogError, L"RegisterVisitAge: Failed to add playerInfo to canVisit folder"); |
|
break; |
|
} |
|
} |
|
|
|
// Copy the link spawn point to the link node |
|
if (hsRef<RelVaultNode> node = VaultGetNode(ageLinkId)) { |
|
VaultAgeLinkNode access(node); |
|
access.AddSpawnPoint(link->SpawnPoint()); |
|
} |
|
|
|
result = true; |
|
break; |
|
} |
|
|
|
plVaultNotifyMsg * msg = new plVaultNotifyMsg; |
|
msg->SetType(plVaultNotifyMsg::kRegisteredVisitAge); |
|
msg->SetResultCode(result); |
|
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, ageLinkId); |
|
msg->Send(); |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultRegisterVisitAge { |
|
struct _Params { |
|
|
|
plSpawnPointInfo* fSpawn; |
|
void* fAgeInfoId; |
|
|
|
~_Params() { |
|
delete fSpawn; |
|
} |
|
}; |
|
|
|
void _CreateAgeLinkNode(ENetError result, void* state, void* param, RelVaultNode* node) { |
|
if (IS_NET_ERROR(result)) { |
|
LogMsg(kLogError, "RegisterVisitAge: Failed to create AgeLink (async)"); |
|
delete (_Params*)param; |
|
return; |
|
} |
|
|
|
_Params* p = (_Params*)param; |
|
hsRef<RelVaultNode> ageInfo = VaultGetNode((uint32_t)((uintptr_t)p->fAgeInfoId)); |
|
|
|
// Add ourselves to the Can Visit folder of the age |
|
if (hsRef<RelVaultNode> playerInfo = VaultGetPlayerInfoNode()) { |
|
if (hsRef<RelVaultNode> canVisit = ageInfo->GetChildPlayerInfoListNode(plVault::kCanVisitFolder, 1)) |
|
VaultAddChildNode(canVisit->GetNodeId(), playerInfo->GetNodeId(), 0, nil, nil); |
|
} |
|
|
|
// Get our AgesICanVisit folder |
|
if (hsRef<RelVaultNode> iCanVisit = VaultGetAgesICanVisitFolder()) { |
|
VaultAddChildNode(node->GetNodeId(), ageInfo->GetNodeId(), 0, nil, nil); |
|
VaultAddChildNode(iCanVisit->GetNodeId(), node->GetNodeId(), 0, nil, nil); |
|
} |
|
|
|
// Update the AgeLink with a spawn point |
|
VaultAgeLinkNode access(node); |
|
access.AddSpawnPoint(*p->fSpawn); |
|
|
|
// Send out the VaultNotify msg |
|
plVaultNotifyMsg * msg = new plVaultNotifyMsg; |
|
msg->SetType(plVaultNotifyMsg::kRegisteredVisitAge); |
|
msg->SetResultCode(true); |
|
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->GetNodeId()); |
|
msg->Send(); |
|
|
|
//Don't leak memory |
|
delete (_Params*)param; |
|
} |
|
|
|
void _DownloadCallback(ENetError result, void* param) { |
|
if (IS_NET_ERROR(result)) { |
|
LogMsg(kLogError, "RegisterVisitAge: Failed to download age vault (async)"); |
|
delete (_Params*)param; |
|
return; |
|
} |
|
|
|
// Create the AgeLink node |
|
VaultCreateNode(plVault::kNodeType_AgeLink, (FVaultCreateNodeCallback)_CreateAgeLinkNode, nil, param); |
|
} |
|
|
|
void _InitAgeCallback(ENetError result, void* state, void* param, uint32_t ageVaultId, uint32_t ageInfoId) { |
|
if (IS_NET_ERROR(result)) { |
|
LogMsg(kLogError, "RegisterVisitAge: Failed to init age vault (async)"); |
|
delete (_Params*)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 = new _Params; |
|
p->fSpawn = 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(), |
|
kNilUuid, |
|
(FVaultInitAgeCallback)_InitAgeCallback, |
|
nil, |
|
p |
|
); |
|
} |
|
|
|
//============================================================================ |
|
bool VaultUnregisterOwnedAgeAndWait (const plAgeInfoStruct * info) { |
|
|
|
unsigned ageLinkId = 0; |
|
unsigned agesIOwnId; |
|
|
|
bool result = false; |
|
for (;;) { |
|
hsRef<RelVaultNode> rvnLink = VaultGetOwnedAgeLink(info); |
|
if (!rvnLink) { |
|
result = true; |
|
break; // we aren't an owner of the age, just return true |
|
} |
|
|
|
if (hsRef<RelVaultNode> rvn = VaultGetAgesIOwnFolder()) |
|
agesIOwnId = rvn->GetNodeId(); |
|
else { |
|
LogMsg(kLogError, L"UnregisterOwnedAge: Failed to get player's AgesIOwnFolder"); |
|
break; // something's wrong with the player vault, it doesn't have a required folder node |
|
} |
|
|
|
ageLinkId = rvnLink->GetNodeId(); |
|
|
|
unsigned ageOwnersId = 0; |
|
if (hsRef<RelVaultNode> rvnAgeInfo = rvnLink->GetChildNode(plVault::kNodeType_AgeInfo, 1)) { |
|
if (hsRef<RelVaultNode> rvnAgeOwners = rvnAgeInfo->GetChildPlayerInfoListNode(plVault::kAgeOwnersFolder, 1)) |
|
ageOwnersId = rvnAgeOwners->GetNodeId(); |
|
} |
|
|
|
unsigned playerInfoId = 0; |
|
if (hsRef<RelVaultNode> rvnPlayerInfo = VaultGetPlayerInfoNode()) |
|
playerInfoId = rvnPlayerInfo->GetNodeId(); |
|
|
|
// remove our playerInfo from the ageOwners folder |
|
VaultRemoveChildNode(ageOwnersId, playerInfoId, nil, nil); |
|
|
|
// remove the link from AgesIOwn folder |
|
VaultRemoveChildNode(agesIOwnId, ageLinkId, nil, nil); |
|
|
|
// delete the link node since link nodes aren't shared with anyone else |
|
// VaultDeleteNode(ageLinkId); |
|
|
|
result = true; |
|
break; |
|
} |
|
|
|
plVaultNotifyMsg * msg = new plVaultNotifyMsg; |
|
msg->SetType(plVaultNotifyMsg::kUnRegisteredOwnedAge); |
|
msg->SetResultCode(result); |
|
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, ageLinkId); |
|
msg->Send(); |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultUnregisterVisitAgeAndWait (const plAgeInfoStruct * info) { |
|
|
|
unsigned ageLinkId = 0; |
|
unsigned agesICanVisitId; |
|
|
|
bool result = false; |
|
for (;;) { |
|
hsRef<RelVaultNode> rvnLink = VaultGetVisitAgeLink(info); |
|
if (!rvnLink) { |
|
result = true; |
|
break; // we aren't an owner of the age, just return true |
|
} |
|
|
|
if (hsRef<RelVaultNode> rvn = VaultGetAgesICanVisitFolder()) |
|
agesICanVisitId = rvn->GetNodeId(); |
|
else { |
|
LogMsg(kLogError, L"UnregisterOwnedAge: Failed to get player's AgesICanVisitFolder"); |
|
break; // something's wrong with the player vault, it doesn't have a required folder node |
|
} |
|
|
|
ageLinkId = rvnLink->GetNodeId(); |
|
|
|
unsigned ageVisitorsId = 0; |
|
if (hsRef<RelVaultNode> rvnAgeInfo = rvnLink->GetChildNode(plVault::kNodeType_AgeInfo, 1)) { |
|
if (hsRef<RelVaultNode> rvnAgeVisitors = rvnAgeInfo->GetChildPlayerInfoListNode(plVault::kCanVisitFolder, 1)) |
|
ageVisitorsId = rvnAgeVisitors->GetNodeId(); |
|
} |
|
|
|
unsigned playerInfoId = 0; |
|
if (hsRef<RelVaultNode> rvnPlayerInfo = VaultGetPlayerInfoNode()) |
|
playerInfoId = rvnPlayerInfo->GetNodeId(); |
|
|
|
// remove our playerInfo from the ageVisitors folder |
|
VaultRemoveChildNode(ageVisitorsId, playerInfoId, nil, nil); |
|
|
|
// remove the link from AgesICanVisit folder |
|
VaultRemoveChildNode(agesICanVisitId, ageLinkId, nil, nil); |
|
|
|
// delete the link node since link nodes aren't shared with anyone else |
|
// VaultDeleteNode(ageLinkId); |
|
|
|
result = true; |
|
break; |
|
} |
|
|
|
plVaultNotifyMsg * msg = new plVaultNotifyMsg; |
|
msg->SetType(plVaultNotifyMsg::kUnRegisteredVisitAge); |
|
msg->SetResultCode(result); |
|
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, ageLinkId); |
|
msg->Send(); |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultFindChronicleEntry (const plString& entryName, int entryType) { |
|
|
|
hsRef<RelVaultNode> result; |
|
if (hsRef<RelVaultNode> rvnFldr = GetChildFolderNode(GetPlayerNode(), plVault::kChronicleFolder, 1)) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_Chronicle); |
|
VaultChronicleNode chrn(templateNode); |
|
chrn.SetEntryName(entryName); |
|
if (entryType >= 0) |
|
chrn.SetEntryType(entryType); |
|
if (hsRef<RelVaultNode> rvnChrn = rvnFldr->GetChildNode(templateNode, 255)) |
|
result = rvnChrn; |
|
} |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultHasChronicleEntry (const plString& entryName, int entryType) { |
|
if (VaultFindChronicleEntry(entryName, entryType)) |
|
return true; |
|
return false; |
|
} |
|
|
|
//============================================================================ |
|
void VaultAddChronicleEntryAndWait ( |
|
const plString& entryName, |
|
int entryType, |
|
const plString& entryValue |
|
) { |
|
if (hsRef<RelVaultNode> rvnChrn = VaultFindChronicleEntry(entryName, entryType)) { |
|
VaultChronicleNode chrnNode(rvnChrn); |
|
chrnNode.SetEntryValue(entryValue); |
|
} |
|
else if (hsRef<RelVaultNode> rvnFldr = GetChildFolderNode(GetPlayerNode(), plVault::kChronicleFolder, 1)) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_Chronicle); |
|
VaultChronicleNode chrnNode(templateNode); |
|
chrnNode.SetEntryName(entryName); |
|
chrnNode.SetEntryType(entryType); |
|
chrnNode.SetEntryValue(entryValue); |
|
ENetError result; |
|
if (hsRef<RelVaultNode> rvnChrn = VaultCreateNodeAndWait(templateNode, &result)) |
|
VaultAddChildNode(rvnFldr->GetNodeId(), rvnChrn->GetNodeId(), 0, nil, nil); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmIgnoringPlayer (unsigned playerId) { |
|
bool retval = false; |
|
if (hsRef<RelVaultNode> rvnFldr = GetChildPlayerInfoListNode(GetPlayerNode(), plVault::kIgnoreListFolder, 1)) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_PlayerInfo); |
|
VaultPlayerInfoNode pinfoNode(templateNode); |
|
pinfoNode.SetPlayerId(playerId); |
|
|
|
if (rvnFldr->GetChildNode(templateNode, 1)) |
|
retval = true; |
|
} |
|
|
|
return retval; |
|
} |
|
|
|
//============================================================================ |
|
unsigned VaultGetKILevel () { |
|
hsAssert(false, "eric, implement me"); |
|
return pfKIMsg::kNanoKI; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetCCRStatus () { |
|
bool retval = false; |
|
if (hsRef<RelVaultNode> rvnSystem = VaultGetSystemNode()) { |
|
VaultSystemNode sysNode(rvnSystem); |
|
retval = (sysNode.GetCCRStatus() != 0); |
|
} |
|
|
|
return retval; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultSetCCRStatus (bool online) { |
|
bool retval = false; |
|
if (hsRef<RelVaultNode> rvnSystem = VaultGetSystemNode()) { |
|
VaultSystemNode sysNode(rvnSystem); |
|
sysNode.SetCCRStatus(online ? 1 : 0); |
|
|
|
retval = true; |
|
} |
|
|
|
return retval; |
|
} |
|
|
|
//============================================================================ |
|
void VaultDump (const wchar_t tag[], unsigned vaultId, FStateDump dumpProc) { |
|
LogMsg(kLogDebug, L"<---- ID:%u, Begin Vault%*s%s ---->", vaultId, tag ? 1 : 0, L" ", tag); |
|
|
|
if (hsRef<RelVaultNode> rvn = VaultGetNode(vaultId)) |
|
rvn->PrintTree(dumpProc, 0); |
|
|
|
LogMsg(kLogDebug, L"<---- ID:%u, End Vault%*s%s ---->", vaultId, tag ? 1 : 0, L" ", tag); |
|
} |
|
|
|
//============================================================================ |
|
void VaultDump (const wchar_t tag[], unsigned vaultId) { |
|
VaultDump (tag, vaultId, LogDumpProc); |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmInMyPersonalAge () { |
|
bool result = false; |
|
|
|
plAgeInfoStruct info; |
|
info.SetAgeFilename(kPersonalAgeFilename); |
|
|
|
if (hsRef<RelVaultNode> rvnLink = VaultGetOwnedAgeLink(&info)) { |
|
if (hsRef<RelVaultNode> rvnInfo = rvnLink->GetChildNode(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode ageInfo(rvnInfo); |
|
|
|
if (hsRef<RelVaultNode> currentAgeInfoNode = VaultGetAgeInfoNode()) { |
|
VaultAgeInfoNode curAgeInfo(currentAgeInfoNode); |
|
|
|
if (ageInfo.GetAgeInstanceGuid() == curAgeInfo.GetAgeInstanceGuid()) |
|
result = true; |
|
} |
|
} |
|
} |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmInMyNeighborhoodAge () { |
|
bool result = false; |
|
|
|
plAgeInfoStruct info; |
|
info.SetAgeFilename(kNeighborhoodAgeFilename); |
|
|
|
if (hsRef<RelVaultNode> rvnLink = VaultGetOwnedAgeLink(&info)) { |
|
if (hsRef<RelVaultNode> rvnInfo = rvnLink->GetChildNode(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode ageInfo(rvnInfo); |
|
|
|
if (hsRef<RelVaultNode> currentAgeInfoNode = VaultGetAgeInfoNode()) { |
|
VaultAgeInfoNode curAgeInfo(currentAgeInfoNode); |
|
|
|
if (ageInfo.GetAgeInstanceGuid() == curAgeInfo.GetAgeInstanceGuid()) |
|
result = true; |
|
} |
|
} |
|
} |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmOwnerOfCurrentAge () { |
|
bool result = false; |
|
|
|
if (hsRef<RelVaultNode> currentAgeInfoNode = VaultGetAgeInfoNode()) { |
|
VaultAgeInfoNode curAgeInfo(currentAgeInfoNode); |
|
|
|
plAgeInfoStruct info; |
|
info.SetAgeFilename(curAgeInfo.GetAgeFilename()); |
|
|
|
if (hsRef<RelVaultNode> rvnLink = VaultGetOwnedAgeLink(&info)) { |
|
|
|
if (hsRef<RelVaultNode> rvnInfo = rvnLink->GetChildNode(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode ageInfo(rvnInfo); |
|
|
|
if (ageInfo.GetAgeInstanceGuid() == curAgeInfo.GetAgeInstanceGuid()) |
|
result = true; |
|
} |
|
} |
|
} |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmCzarOfCurrentAge () { |
|
hsAssert(false, "eric, implement me"); |
|
return true; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmOwnerOfAge (const plUUID& ageInstId) { |
|
hsAssert(false, "eric, implement me"); |
|
return true; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmCzarOfAge (const plUUID& ageInstId) { |
|
// hsAssert(false, "eric, implement me"); |
|
return false; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultRegisterMTStationAndWait ( |
|
const wchar_t stationName[], |
|
const wchar_t linkBackSpawnPtObjName[] |
|
) { |
|
plAgeInfoStruct info; |
|
info.SetAgeFilename(kCityAgeFilename); |
|
if (hsRef<RelVaultNode> rvn = VaultGetOwnedAgeLink(&info)) { |
|
char title[MAX_PATH], spawnPt[MAX_PATH]; |
|
StrToAnsi(title, stationName, arrsize(title)); |
|
StrToAnsi(spawnPt, linkBackSpawnPtObjName, arrsize(spawnPt)); |
|
VaultAgeLinkNode link(rvn); |
|
link.AddSpawnPoint(plSpawnPointInfo(title, spawnPt)); |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
//============================================================================ |
|
void VaultProcessVisitNote(RelVaultNode * rvnVisit) { |
|
if (hsRef<RelVaultNode> rvnInbox = VaultGetPlayerInboxFolder()) { |
|
VaultTextNoteNode visitAcc(rvnVisit); |
|
plAgeLinkStruct link; |
|
if (visitAcc.GetVisitInfo(link.GetAgeInfo())) { |
|
// Add it to our "ages i can visit" folder |
|
VaultRegisterVisitAge(&link); |
|
} |
|
// remove it from the inbox |
|
VaultRemoveChildNode(rvnInbox->GetNodeId(), rvnVisit->GetNodeId(), nil, nil); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void VaultProcessUnvisitNote(RelVaultNode * rvnUnVisit) { |
|
if (hsRef<RelVaultNode> rvnInbox = VaultGetPlayerInboxFolder()) { |
|
VaultTextNoteNode unvisitAcc(rvnUnVisit); |
|
plAgeInfoStruct info; |
|
if (unvisitAcc.GetVisitInfo(&info)) { |
|
// Remove it from our "ages i can visit" folder |
|
VaultUnregisterVisitAgeAndWait(&info); |
|
} |
|
// remove it from the inbox |
|
VaultRemoveChildNode(rvnInbox->GetNodeId(), rvnUnVisit->GetNodeId(), nil, nil); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void VaultProcessPlayerInbox () { |
|
if (hsRef<RelVaultNode> rvnInbox = VaultGetPlayerInboxFolder()) { |
|
{ // Process new visit requests |
|
RelVaultNode::RefList visits; |
|
hsRef<RelVaultNode> templateNode = new RelVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_TextNote); |
|
VaultTextNoteNode tmpAcc(templateNode); |
|
tmpAcc.SetNoteType(plVault::kNoteType_Visit); |
|
rvnInbox->GetChildNodes(templateNode, 1, &visits); |
|
|
|
for (const hsRef<RelVaultNode> &rvnVisit : visits) { |
|
VaultTextNoteNode visitAcc(rvnVisit); |
|
plAgeLinkStruct link; |
|
if (visitAcc.GetVisitInfo(link.GetAgeInfo())) { |
|
// Add it to our "ages i can visit" folder |
|
VaultRegisterVisitAge(&link); |
|
} |
|
// remove it from the inbox |
|
VaultRemoveChildNode(rvnInbox->GetNodeId(), rvnVisit->GetNodeId(), nil, nil); |
|
} |
|
} |
|
{ // Process new unvisit requests |
|
RelVaultNode::RefList unvisits; |
|
hsRef<RelVaultNode> templateNode = new RelVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_TextNote); |
|
VaultTextNoteNode tmpAcc(templateNode); |
|
tmpAcc.SetNoteType(plVault::kNoteType_UnVisit); |
|
rvnInbox->GetChildNodes(templateNode, 1, &unvisits); |
|
|
|
for (const hsRef<RelVaultNode> &rvnUnVisit : unvisits) { |
|
VaultTextNoteNode unvisitAcc(rvnUnVisit); |
|
plAgeInfoStruct info; |
|
if (unvisitAcc.GetVisitInfo(&info)) { |
|
// Remove it from our "ages i can visit" folder |
|
VaultUnregisterVisitAgeAndWait(&info); |
|
} |
|
// remove it from the inbox |
|
VaultRemoveChildNode(rvnInbox->GetNodeId(), rvnUnVisit->GetNodeId(), nil, nil); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Age Vault Access |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
static hsRef<RelVaultNode> GetAgeNode () { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_VNodeMgrAge); |
|
if (NetCommGetAge()) |
|
templateNode->SetNodeId(NetCommGetAge()->ageVaultId); |
|
return VaultGetNode(templateNode); |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAgeNode () { |
|
hsRef<RelVaultNode> result; |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_VNodeMgrAge); |
|
if (NetCommGetAge()) |
|
templateNode->SetNodeId(NetCommGetAge()->ageVaultId); |
|
if (hsRef<RelVaultNode> rvnAge = VaultGetNode(templateNode)) |
|
result = rvnAge; |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
static hsRef<RelVaultNode> GetAgeInfoNode () { |
|
hsRef<RelVaultNode> rvnAge = VaultGetAgeNode(); |
|
if (!rvnAge) |
|
return nullptr; |
|
|
|
hsRef<RelVaultNode> result; |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
|
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
templateNode->SetCreatorId(rvnAge->GetNodeId()); |
|
|
|
if (hsRef<RelVaultNode> rvnAgeInfo = rvnAge->GetChildNode(templateNode, 1)) |
|
result = rvnAgeInfo; |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAgeInfoNode () { |
|
hsRef<RelVaultNode> rvnAge = VaultGetAgeNode(); |
|
if (!rvnAge) |
|
return nullptr; |
|
|
|
hsRef<RelVaultNode> result; |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
templateNode->SetCreatorId(rvnAge->GetNodeId()); |
|
|
|
if (hsRef<RelVaultNode> rvnAgeInfo = rvnAge->GetChildNode(templateNode, 1)) |
|
result = rvnAgeInfo; |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAgeChronicleFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetAgeNode()) |
|
return rvn->GetChildFolderNode(plVault::kChronicleFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAgeDevicesFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetAgeNode()) |
|
return rvn->GetChildFolderNode(plVault::kAgeDevicesFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAgeAgeOwnersFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetAgeInfoNode()) |
|
return rvn->GetChildPlayerInfoListNode(plVault::kAgeOwnersFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAgeCanVisitFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetAgeInfoNode()) |
|
return rvn->GetChildPlayerInfoListNode(plVault::kCanVisitFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAgePeopleIKnowAboutFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetAgeNode()) |
|
return rvn->GetChildPlayerInfoListNode(plVault::kPeopleIKnowAboutFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAgeSubAgesFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetAgeNode()) |
|
return rvn->GetChildAgeInfoListNode(plVault::kSubAgesFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetAgePublicAgesFolder () { |
|
hsAssert(false, "eric, implement me"); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultAgeGetBookshelfFolder () { |
|
if (hsRef<RelVaultNode> rvn = GetAgeNode()) |
|
return rvn->GetChildAgeInfoListNode(plVault::kAgesIOwnFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultFindAgeSubAgeLink (const plAgeInfoStruct * info) { |
|
hsRef<RelVaultNode> rvnLink; |
|
|
|
if (hsRef<RelVaultNode> rvnFldr = VaultGetAgeSubAgesFolder()) { |
|
|
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
ageInfo.SetAgeFilename(info->GetAgeFilename()); |
|
|
|
if (hsRef<RelVaultNode> rvnInfo = rvnFldr->GetChildNode(templateNode, 2)) { |
|
templateNode->Clear(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
rvnLink = rvnInfo->GetParentNode(templateNode, 1); |
|
} |
|
} |
|
|
|
return rvnLink; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultFindAgeChronicleEntry (const wchar_t entryName[], int entryType) { |
|
hsAssert(false, "eric, implement me"); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
void VaultAddAgeChronicleEntry ( |
|
const wchar_t entryName[], |
|
int entryType, |
|
const wchar_t entryValue[] |
|
) { |
|
hsAssert(false, "eric, implement me"); |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultAgeAddDeviceAndWait (const plString& deviceName) { |
|
if (hsRef<RelVaultNode> existing = VaultAgeGetDevice(deviceName)) |
|
return existing; |
|
|
|
hsRef<RelVaultNode> device, folder; |
|
|
|
for (;;) { |
|
folder = VaultGetAgeDevicesFolder(); |
|
if (!folder) |
|
break; |
|
|
|
ENetError result; |
|
device = VaultCreateNodeAndWait(plVault::kNodeType_TextNote, &result); |
|
if (!device) |
|
break; |
|
|
|
VaultTextNoteNode access(device); |
|
access.SetNoteType(plVault::kNoteType_Device); |
|
access.SetNoteTitle(deviceName); |
|
|
|
VaultAddChildNodeAndWait(folder->GetNodeId(), device->GetNodeId(), 0); |
|
break; |
|
} |
|
|
|
return device; |
|
} |
|
|
|
//============================================================================ |
|
void VaultAgeRemoveDevice (const plString& deviceName) { |
|
if (hsRef<RelVaultNode> folder = VaultGetAgeDevicesFolder()) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_TextNote); |
|
VaultTextNoteNode access(templateNode); |
|
access.SetNoteTitle(deviceName); |
|
if (hsRef<RelVaultNode> device = folder->GetChildNode(templateNode, 1)) { |
|
VaultRemoveChildNode(folder->GetNodeId(), device->GetNodeId(), nil, nil); |
|
|
|
auto it = s_ageDeviceInboxes.find(deviceName); |
|
if (it != s_ageDeviceInboxes.end()) |
|
s_ageDeviceInboxes.erase(it); |
|
} |
|
} |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAgeHasDevice (const plString& deviceName) { |
|
bool found = false; |
|
if (hsRef<RelVaultNode> folder = VaultGetAgeDevicesFolder()) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_TextNote); |
|
VaultTextNoteNode access(templateNode); |
|
access.SetNoteTitle(deviceName); |
|
if (folder->GetChildNode(templateNode, 1)) |
|
found = true; |
|
} |
|
return found; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultAgeGetDevice (const plString& deviceName) { |
|
hsRef<RelVaultNode> result; |
|
if (hsRef<RelVaultNode> folder = VaultGetAgeDevicesFolder()) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_TextNote); |
|
VaultTextNoteNode access(templateNode); |
|
access.SetNoteTitle(deviceName); |
|
if (hsRef<RelVaultNode> device = folder->GetChildNode(templateNode, 1)) |
|
result = device; |
|
} |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultAgeSetDeviceInboxAndWait (const plString& deviceName, const plString& inboxName) { |
|
s_ageDeviceInboxes[deviceName] = inboxName; |
|
|
|
// if we found the inbox or its a global inbox then return here, otherwise if its the default inbox and |
|
// it wasn't found then continue on and create the inbox |
|
hsRef<RelVaultNode> existing = VaultAgeGetDeviceInbox(deviceName); |
|
if (existing || inboxName == DEFAULT_DEVICE_INBOX) |
|
return existing; |
|
|
|
hsRef<RelVaultNode> device, inbox; |
|
|
|
for (;;) { |
|
device = VaultAgeGetDevice(deviceName); |
|
if (!device) |
|
break; |
|
|
|
ENetError result; |
|
inbox = VaultCreateNodeAndWait(plVault::kNodeType_Folder, &result); |
|
if (!inbox) |
|
break; |
|
|
|
VaultFolderNode access(inbox); |
|
access.SetFolderName(inboxName); |
|
access.SetFolderType(plVault::kDeviceInboxFolder); |
|
|
|
VaultAddChildNodeAndWait(device->GetNodeId(), inbox->GetNodeId(), 0); |
|
break; |
|
} |
|
|
|
return inbox; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultAgeGetDeviceInbox (const plString& deviceName) { |
|
hsRef<RelVaultNode> result; |
|
auto it = s_ageDeviceInboxes.find(deviceName); |
|
|
|
if (it != s_ageDeviceInboxes.end()) { |
|
hsRef<RelVaultNode> parentNode; |
|
const wchar_t * inboxName = nil; |
|
|
|
//if (StrCmp(devInbox->inboxName, DEFAULT_DEVICE_INBOX) == 0) { |
|
if (it->second == DEFAULT_DEVICE_INBOX) |
|
parentNode = VaultAgeGetDevice(deviceName); |
|
else |
|
parentNode = VaultGetGlobalInbox(); |
|
|
|
if (parentNode) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_Folder); |
|
VaultFolderNode access(templateNode); |
|
access.SetFolderType(plVault::kDeviceInboxFolder); |
|
access.SetFolderName(it->second); |
|
result = parentNode->GetChildNode(templateNode, 1); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
void VaultClearDeviceInboxMap () { |
|
s_ageDeviceInboxes.clear(); |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAgeGetAgeSDL (plStateDataRecord * out) { |
|
bool result = false; |
|
if (hsRef<RelVaultNode> rvn = VaultGetAgeInfoNode()) { |
|
if (hsRef<RelVaultNode> rvnSdl = rvn->GetChildNode(plVault::kNodeType_SDL, 1)) { |
|
VaultSDLNode sdl(rvnSdl); |
|
result = sdl.GetStateDataRecord(out, plSDL::kKeepDirty); |
|
if (!result) { |
|
sdl.InitStateDataRecord(sdl.GetSDLName()); |
|
result = sdl.GetStateDataRecord(out, plSDL::kKeepDirty); |
|
} |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
void VaultAgeUpdateAgeSDL (const plStateDataRecord * rec) { |
|
if (hsRef<RelVaultNode> rvn = VaultGetAgeInfoNode()) { |
|
if (hsRef<RelVaultNode> rvnSdl = rvn->GetChildNode(plVault::kNodeType_SDL, 1)) { |
|
VaultSDLNode sdl(rvnSdl); |
|
sdl.SetStateDataRecord(rec, plSDL::kDirtyOnly | plSDL::kTimeStampOnRead); |
|
} |
|
} |
|
} |
|
|
|
//============================================================================ |
|
unsigned VaultAgeGetAgeTime () { |
|
hsAssert(false, "eric, implement me"); |
|
return 0; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetSubAgeLink (const plAgeInfoStruct * info) { |
|
|
|
hsRef<RelVaultNode> rvnLink; |
|
|
|
if (hsRef<RelVaultNode> rvnFldr = VaultGetAgeSubAgesFolder()) { |
|
|
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
ageInfo.SetAgeFilename(info->GetAgeFilename()); |
|
|
|
if (hsRef<RelVaultNode> rvnInfo = rvnFldr->GetChildNode(templateNode, 2)) { |
|
templateNode->Clear(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
rvnLink = rvnInfo->GetParentNode(templateNode, 1); |
|
} |
|
} |
|
|
|
return rvnLink; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAgeGetSubAgeLink (const plAgeInfoStruct * info, plAgeLinkStruct * link) { |
|
bool result = false; |
|
if (hsRef<RelVaultNode> rvnLink = VaultGetSubAgeLink(info)) { |
|
if (hsRef<RelVaultNode> rvnInfo = rvnLink->GetChildNode(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode ageInfo(rvnInfo); |
|
ageInfo.CopyTo(link->GetAgeInfo()); |
|
result = true; |
|
} |
|
} |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultCreateSubAgeAndWait { |
|
|
|
struct _InitAgeParam { |
|
ENetError result; |
|
bool complete; |
|
unsigned ageInfoId; |
|
}; |
|
static void _InitAgeCallback ( |
|
ENetError result, |
|
void * , |
|
void * vparam, |
|
unsigned ageVaultId, |
|
unsigned ageInfoVaultId |
|
) { |
|
_InitAgeParam * param = (_InitAgeParam *)vparam; |
|
param->ageInfoId = ageInfoVaultId; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _FetchVaultParam { |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _FetchVaultCallback ( |
|
ENetError result, |
|
void * vparam |
|
) { |
|
_FetchVaultParam * param = (_FetchVaultParam *)vparam; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _CreateNodeParam { |
|
ENetError result; |
|
bool complete; |
|
unsigned nodeId; |
|
}; |
|
static void _CreateNodeCallback ( |
|
ENetError result, |
|
void * , |
|
void * vparam, |
|
RelVaultNode * node |
|
) { |
|
_CreateNodeParam * param = (_CreateNodeParam *)vparam; |
|
if (IS_NET_SUCCESS(result)) |
|
param->nodeId = node->GetNodeId(); |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _AddChildNodeParam { |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _AddChildNodeCallback ( |
|
ENetError result, |
|
void * vparam |
|
) { |
|
_AddChildNodeParam * param = (_AddChildNodeParam *)vparam; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
|
|
} // namespace _VaultCreateSubAgeAndWait |
|
|
|
//============================================================================ |
|
bool VaultAgeFindOrCreateSubAgeLinkAndWait ( |
|
const plAgeInfoStruct * info, |
|
plAgeLinkStruct * link, |
|
const plUUID& parentAgeInstId |
|
) { |
|
if (hsRef<RelVaultNode> rvnLink = VaultFindAgeSubAgeLink(info)) { |
|
VaultAgeLinkNode linkAcc(rvnLink); |
|
linkAcc.CopyTo(link); |
|
if (hsRef<RelVaultNode> rvnInfo = rvnLink->GetChildNode(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode infoAcc(rvnInfo); |
|
infoAcc.CopyTo(link->GetAgeInfo()); |
|
return true; |
|
} |
|
} |
|
|
|
using namespace _VaultCreateSubAgeAndWait; |
|
|
|
unsigned subAgesId; |
|
unsigned ageInfoId; |
|
unsigned ageLinkId; |
|
|
|
if (hsRef<RelVaultNode> rvnSubAges = VaultGetAgeSubAgesFolder()) |
|
subAgesId = rvnSubAges->GetNodeId(); |
|
else { |
|
LogMsg(kLogError, L"CreateSubAge: Failed to get ages's SubAges folder"); |
|
return false; |
|
} |
|
|
|
{ // Init age vault |
|
_InitAgeParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultInitAge( |
|
info, |
|
parentAgeInstId, |
|
_InitAgeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, "CreateSubAge: Failed to init age %s", link->GetAgeInfo()->GetAgeFilename().c_str()); |
|
return false; |
|
} |
|
|
|
ageInfoId = param.ageInfoId; |
|
} |
|
|
|
{ // Create age link |
|
_CreateNodeParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultCreateNode( |
|
plVault::kNodeType_AgeLink, |
|
_CreateNodeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"CreateSubAge: Failed create age link node"); |
|
return false; |
|
} |
|
|
|
ageLinkId = param.nodeId; |
|
} |
|
|
|
{ // Fetch age info node tree |
|
_FetchVaultParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultDownload( |
|
L"CreateSubAge", |
|
ageInfoId, |
|
_FetchVaultCallback, |
|
¶m, |
|
nil, |
|
nil |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"CreateSubAge: Failed to download age info vault"); |
|
return false; |
|
} |
|
} |
|
|
|
{ // Link: |
|
// ageLink to ages's subages folder |
|
// ageInfo to ageLink |
|
_AddChildNodeParam param1; |
|
_AddChildNodeParam param2; |
|
memset(¶m1, 0, sizeof(param1)); |
|
memset(¶m2, 0, sizeof(param2)); |
|
|
|
VaultAddChildNode( |
|
subAgesId, |
|
ageLinkId, |
|
0, |
|
_AddChildNodeCallback, |
|
¶m1 |
|
); |
|
|
|
VaultAddChildNode( |
|
ageLinkId, |
|
ageInfoId, |
|
0, |
|
_AddChildNodeCallback, |
|
¶m2 |
|
); |
|
|
|
while (!param1.complete && !param2.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param1.result)) { |
|
LogMsg(kLogError, L"CreateSubAge: Failed to add link to ages's subages"); |
|
return false; |
|
} |
|
if (IS_NET_ERROR(param2.result)) { |
|
LogMsg(kLogError, L"CreateSubAge: Failed to add info to link"); |
|
return false; |
|
} |
|
} |
|
|
|
if (hsRef<RelVaultNode> rvnLink = VaultGetNode(ageLinkId)) { |
|
VaultAgeLinkNode linkAcc(rvnLink); |
|
linkAcc.CopyTo(link); |
|
} |
|
|
|
if (hsRef<RelVaultNode> rvnInfo = VaultGetNode(ageInfoId)) { |
|
VaultAgeInfoNode infoAcc(rvnInfo); |
|
infoAcc.CopyTo(link->GetAgeInfo()); |
|
} |
|
|
|
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->GetNodeId(), (uint32_t)((uintptr_t)param), 0, nil, nil); |
|
if (hsRef<RelVaultNode> saFldr = VaultGetAgeSubAgesFolder()) |
|
VaultAddChildNode(saFldr->GetNodeId(), node->GetNodeId(), 0, nil, nil); |
|
else |
|
LogMsg(kLogError, "CreateSubAge: Couldn't find SubAges folder (async)"); |
|
|
|
// Send the VaultNotify that the plNetLinkingMgr wants... |
|
plVaultNotifyMsg * msg = new plVaultNotifyMsg; |
|
msg->SetType(plVaultNotifyMsg::kRegisteredSubAgeLink); |
|
msg->SetResultCode(result); |
|
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->GetNodeId()); |
|
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_t ageVaultId, uint32_t 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 plUUID& parentUuid) { |
|
using namespace _VaultCreateSubAge; |
|
|
|
// First, try to find an already existing subage |
|
if (hsRef<RelVaultNode> rvnLink = VaultGetSubAgeLink(info)) { |
|
VaultAgeLinkNode accLink(rvnLink); |
|
accLink.CopyTo(link); |
|
|
|
if (hsRef<RelVaultNode> rvnInfo = rvnLink->GetChildNode(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode accInfo(rvnInfo); |
|
accInfo.CopyTo(link->GetAgeInfo()); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
VaultInitAge(info, |
|
parentUuid, |
|
(FVaultInitAgeCallback)_InitAgeCallback, |
|
nil, |
|
nil |
|
); |
|
|
|
return false; |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultCreateChildAgeAndWait { |
|
|
|
struct _InitAgeParam { |
|
ENetError result; |
|
bool complete; |
|
unsigned ageInfoId; |
|
}; |
|
static void _InitAgeCallback ( |
|
ENetError result, |
|
void * , |
|
void * vparam, |
|
unsigned ageVaultId, |
|
unsigned ageInfoVaultId |
|
) { |
|
_InitAgeParam * param = (_InitAgeParam *)vparam; |
|
param->ageInfoId = ageInfoVaultId; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _FetchVaultParam { |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _FetchVaultCallback ( |
|
ENetError result, |
|
void * vparam |
|
) { |
|
_FetchVaultParam * param = (_FetchVaultParam *)vparam; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _CreateNodeParam { |
|
ENetError result; |
|
bool complete; |
|
unsigned nodeId; |
|
}; |
|
static void _CreateNodeCallback ( |
|
ENetError result, |
|
void * , |
|
void * vparam, |
|
RelVaultNode * node |
|
) { |
|
_CreateNodeParam * param = (_CreateNodeParam *)vparam; |
|
if (IS_NET_SUCCESS(result)) |
|
param->nodeId = node->GetNodeId(); |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
struct _AddChildNodeParam { |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _AddChildNodeCallback ( |
|
ENetError result, |
|
void * vparam |
|
) { |
|
_AddChildNodeParam * param = (_AddChildNodeParam *)vparam; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
|
|
} // namespace _VaultCreateChildAgeAndWait |
|
|
|
//============================================================================ |
|
bool VaultAgeFindOrCreateChildAgeLinkAndWait ( |
|
const wchar_t parentAgeName[], |
|
const plAgeInfoStruct * info, |
|
plAgeLinkStruct * link |
|
) { |
|
using namespace _VaultCreateChildAgeAndWait; |
|
|
|
unsigned childAgesId; |
|
unsigned ageInfoId; |
|
unsigned ageLinkId; |
|
|
|
{ // Get id of child ages folder |
|
hsRef<RelVaultNode> rvnAgeInfo; |
|
if (parentAgeName) { |
|
char ansi[MAX_PATH]; |
|
StrToAnsi(ansi, parentAgeName, arrsize(ansi)); |
|
plAgeInfoStruct pinfo; |
|
pinfo.SetAgeFilename(ansi); |
|
if (hsRef<RelVaultNode> rvnAgeLink = VaultGetOwnedAgeLink(&pinfo)) |
|
rvnAgeInfo = rvnAgeLink->GetChildNode(plVault::kNodeType_AgeInfo, 1); |
|
} |
|
else { |
|
rvnAgeInfo = VaultGetAgeInfoNode(); |
|
} |
|
|
|
if (!rvnAgeInfo) { |
|
LogMsg(kLogError, L"CreateChildAge: Failed to get ages's AgeInfo node"); |
|
return false; |
|
} |
|
|
|
hsRef<RelVaultNode> rvnChildAges; |
|
if (rvnChildAges = rvnAgeInfo->GetChildAgeInfoListNode(plVault::kChildAgesFolder, 1)) { |
|
childAgesId = rvnChildAges->GetNodeId(); |
|
} |
|
else { |
|
LogMsg(kLogError, L"CreateChildAge: Failed to get ages's ChildAges folder"); |
|
return false; |
|
} |
|
|
|
// Check for existing child age in folder |
|
hsRef<RelVaultNode> rvnLink; |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
ageInfo.SetAgeFilename(info->GetAgeFilename()); |
|
|
|
if (hsRef<RelVaultNode> rvnInfo = rvnChildAges->GetChildNode(templateNode, 2)) { |
|
templateNode->Clear(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
rvnLink = rvnInfo->GetParentNode(templateNode, 1); |
|
} |
|
|
|
if (rvnLink) { |
|
VaultAgeLinkNode access(rvnLink); |
|
access.CopyTo(link); |
|
return true; |
|
} |
|
} |
|
|
|
{ // Init age vault |
|
_InitAgeParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
plUUID parentAgeInstId; |
|
if (hsRef<RelVaultNode> rvnAge = VaultGetAgeNode()) { |
|
VaultAgeNode access(rvnAge); |
|
parentAgeInstId = access.GetAgeInstanceGuid(); |
|
} |
|
|
|
VaultInitAge( |
|
info, |
|
parentAgeInstId, |
|
_InitAgeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, "CreateChildAge: Failed to init age %s", link->GetAgeInfo()->GetAgeFilename().c_str()); |
|
return false; |
|
} |
|
|
|
ageInfoId = param.ageInfoId; |
|
} |
|
|
|
{ // Create age link |
|
_CreateNodeParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultCreateNode( |
|
plVault::kNodeType_AgeLink, |
|
_CreateNodeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"CreateChildAge: Failed create age link node"); |
|
return false; |
|
} |
|
|
|
ageLinkId = param.nodeId; |
|
} |
|
|
|
{ // Fetch age info node tree |
|
_FetchVaultParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultDownload( |
|
L"CreateChildAge", |
|
ageInfoId, |
|
_FetchVaultCallback, |
|
¶m, |
|
nil, |
|
nil |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"CreateChildAge: Failed to download age info vault"); |
|
return false; |
|
} |
|
} |
|
|
|
{ // Link: |
|
// ageLink to ages's subages folder |
|
// ageInfo to ageLink |
|
_AddChildNodeParam param1; |
|
_AddChildNodeParam param2; |
|
memset(¶m1, 0, sizeof(param1)); |
|
memset(¶m2, 0, sizeof(param2)); |
|
|
|
VaultAddChildNode( |
|
childAgesId, |
|
ageLinkId, |
|
0, |
|
_AddChildNodeCallback, |
|
¶m1 |
|
); |
|
|
|
VaultAddChildNode( |
|
ageLinkId, |
|
ageInfoId, |
|
0, |
|
_AddChildNodeCallback, |
|
¶m2 |
|
); |
|
|
|
while (!param1.complete && !param2.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param1.result)) { |
|
LogMsg(kLogError, L"CreateChildAge: Failed to add link to ages's subages"); |
|
return false; |
|
} |
|
if (IS_NET_ERROR(param2.result)) { |
|
LogMsg(kLogError, L"CreateChildAge: Failed to add info to link"); |
|
return false; |
|
} |
|
} |
|
|
|
if (hsRef<RelVaultNode> rvnLink = VaultGetNode(ageLinkId)) { |
|
VaultAgeLinkNode linkAcc(rvnLink); |
|
linkAcc.CopyTo(link); |
|
} |
|
|
|
if (hsRef<RelVaultNode> rvnInfo = VaultGetNode(ageInfoId)) { |
|
VaultAgeInfoNode infoAcc(rvnInfo); |
|
infoAcc.CopyTo(link->GetAgeInfo()); |
|
} |
|
|
|
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)"); |
|
delete (_Params*)param; |
|
return; |
|
} |
|
|
|
_Params* p = (_Params*)param; |
|
|
|
// Add the children to the right places |
|
VaultAddChildNode(node->GetNodeId(), (uint32_t)((uintptr_t)p->fAgeInfoId), 0, nil, nil); |
|
VaultAddChildNode((uint32_t)((uintptr_t)p->fChildAgesFldr), node->GetNodeId(), 0, nil, nil); |
|
|
|
// Send the VaultNotify that the plNetLinkingMgr wants... |
|
plVaultNotifyMsg * msg = new plVaultNotifyMsg; |
|
msg->SetType(plVaultNotifyMsg::kRegisteredChildAgeLink); |
|
msg->SetResultCode(result); |
|
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, node->GetNodeId()); |
|
msg->Send(); |
|
|
|
delete (_Params*)param; |
|
} |
|
|
|
void _DownloadCallback(ENetError result, void* param) { |
|
if (IS_NET_ERROR(result)) { |
|
LogMsg(kLogError, "CreateChildAge: Failed to download age vault (async)"); |
|
delete (_Params*)param; |
|
return; |
|
} |
|
|
|
// Create the AgeLink node |
|
VaultCreateNode(plVault::kNodeType_AgeLink, |
|
(FVaultCreateNodeCallback)_CreateNodeCallback, |
|
nil, |
|
param |
|
); |
|
} |
|
|
|
void _InitAgeCallback(ENetError result, void* state, void* param, uint32_t ageVaultId, uint32_t ageInfoId) { |
|
if (IS_NET_ERROR(result)) { |
|
LogMsg(kLogError, "CreateChildAge: Failed to init age (async)"); |
|
delete (_Params*)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_t VaultAgeFindOrCreateChildAgeLink( |
|
const wchar_t 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(name)); |
|
plAgeInfoStruct search; |
|
search.SetAgeFilename(name); |
|
|
|
hsRef<RelVaultNode> rvnParentInfo; |
|
if (hsRef<RelVaultNode> rvnParentLink = VaultGetOwnedAgeLink(&search)) |
|
rvnParentInfo = rvnParentLink->GetChildNode(plVault::kNodeType_AgeInfo, 1); |
|
else // Fallback to current age |
|
rvnParentInfo = VaultGetAgeInfoNode(); |
|
|
|
// 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_t retval = hsFail; |
|
if (hsRef<RelVaultNode> rvnChildAges = rvnParentInfo->GetChildAgeInfoListNode(plVault::kChildAgesFolder, 1)) { |
|
// Search for our age |
|
hsRef<NetVaultNode> temp = new NetVaultNode; |
|
temp->SetNodeType(plVault::kNodeType_AgeInfo); |
|
VaultAgeInfoNode theAge(temp); |
|
theAge.SetAgeFilename(info->GetAgeFilename()); |
|
|
|
if (hsRef<RelVaultNode> rvnAgeInfo = rvnChildAges->GetChildNode(temp, 2)) { |
|
hsRef<RelVaultNode> rvnAgeLink = rvnAgeInfo->GetParentAgeLink(); |
|
|
|
VaultAgeLinkNode accAgeLink(rvnAgeLink); |
|
accAgeLink.CopyTo(link); |
|
VaultAgeInfoNode accAgeInfo(rvnAgeInfo); |
|
accAgeInfo.CopyTo(link->GetAgeInfo()); |
|
|
|
retval = true; |
|
} else { |
|
_Params* p = new _Params; |
|
p->fChildAgesFldr = (void*)rvnChildAges->GetNodeId(); |
|
|
|
VaultAgeInfoNode accParentInfo(rvnParentInfo); |
|
VaultInitAge(info, |
|
accParentInfo.GetAgeInstanceGuid(), |
|
(FVaultInitAgeCallback)_InitAgeCallback, |
|
nil, |
|
p |
|
); |
|
retval = false; |
|
} |
|
} |
|
|
|
return retval; |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* CCR Vault Access |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
void VaultCCRDumpPlayers() { |
|
hsAssert(false, "eric, implement me"); |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Vault download |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
void VaultDownload ( |
|
const wchar_t tag[], |
|
unsigned vaultId, |
|
FVaultDownloadCallback callback, |
|
void * cbParam, |
|
FVaultProgressCallback progressCallback, |
|
void * cbProgressParam |
|
) { |
|
VaultDownloadTrans * trans = new VaultDownloadTrans(tag, callback, cbParam, |
|
progressCallback, cbProgressParam, vaultId); |
|
|
|
NetCliAuthVaultFetchNodeRefs( |
|
vaultId, |
|
VaultDownloadTrans::VaultNodeRefsFetched, |
|
trans |
|
); |
|
} |
|
|
|
//============================================================================ |
|
struct _DownloadVaultParam { |
|
ENetError result; |
|
bool complete; |
|
}; |
|
static void _DownloadVaultCallback ( |
|
ENetError result, |
|
void * vparam |
|
) { |
|
_DownloadVaultParam * param = (_DownloadVaultParam *)vparam; |
|
param->result = result; |
|
param->complete = true; |
|
} |
|
|
|
void VaultDownloadAndWait ( |
|
const wchar_t tag[], |
|
unsigned vaultId, |
|
FVaultProgressCallback progressCallback, |
|
void * cbProgressParam |
|
) { |
|
_DownloadVaultParam param; |
|
memset(¶m, 0, sizeof(param)); |
|
|
|
VaultDownload( |
|
tag, |
|
vaultId, |
|
_DownloadVaultCallback, |
|
¶m, |
|
progressCallback, |
|
cbProgressParam |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void VaultCull (unsigned vaultId) { |
|
// Remove the node from the global table |
|
if (RelVaultNodeLink * link = s_nodes.Find(vaultId)) { |
|
LogMsg(kLogDebug, L"Vault: Culling node %u", link->node->GetNodeId()); |
|
link->node->state->UnlinkFromRelatives(); |
|
delete link; |
|
} |
|
|
|
// Remove all orphaned nodes from the global table |
|
for (RelVaultNodeLink * next, * link = s_nodes.Head(); link; link = next) { |
|
next = s_nodes.Next(link); |
|
|
|
if (link->node->GetNodeType() > plVault::kNodeType_VNodeMgrLow && link->node->GetNodeType() < plVault::kNodeType_VNodeMgrHigh) |
|
continue; |
|
|
|
ARRAY(unsigned) nodeIds; |
|
link->node->GetRootIds(&nodeIds); |
|
bool foundRoot = false; |
|
for (unsigned i = 0; i < nodeIds.Count(); ++i) { |
|
RelVaultNodeLink * root = s_nodes.Find(nodeIds[i]); |
|
if (root && root->node->GetNodeType() > plVault::kNodeType_VNodeMgrLow && root->node->GetNodeType() < plVault::kNodeType_VNodeMgrHigh) { |
|
foundRoot = true; |
|
break; |
|
} |
|
} |
|
if (!foundRoot) { |
|
LogMsg(kLogDebug, L"Vault: Culling node %u", link->node->GetNodeId()); |
|
link->node->state->UnlinkFromRelatives(); |
|
delete link; |
|
} |
|
} |
|
} |
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Vault global node handling |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetSystemNode () { |
|
hsRef<RelVaultNode> result; |
|
if (hsRef<RelVaultNode> player = VaultGetPlayerNode()) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_System); |
|
if (hsRef<RelVaultNode> systemNode = player->GetChildNode(templateNode, 1)) |
|
result = systemNode; |
|
} |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
hsRef<RelVaultNode> VaultGetGlobalInbox () { |
|
hsRef<RelVaultNode> result; |
|
if (hsRef<RelVaultNode> system = VaultGetSystemNode()) { |
|
hsRef<NetVaultNode> templateNode = new NetVaultNode; |
|
templateNode->SetNodeType(plVault::kNodeType_Folder); |
|
VaultFolderNode folder(templateNode); |
|
folder.SetFolderType(plVault::kGlobalInboxFolder); |
|
if (hsRef<RelVaultNode> inbox = system->GetChildNode(templateNode, 1)) |
|
result = inbox; |
|
} |
|
return result; |
|
} |
|
|
|
#endif // def CLIENT
|
|
|