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.
4608 lines
123 KiB
4608 lines
123 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/>. |
|
|
|
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) |
|
{} |
|
}; |
|
|
|
struct DeviceInbox : CHashKeyStr { |
|
HASHLINK(DeviceInbox) link; |
|
wchar inboxName[kMaxVaultNodeStringLength]; |
|
|
|
DeviceInbox (const wchar device[], const wchar inbox[]) |
|
: CHashKeyStr(device) |
|
{ |
|
StrCopy(inboxName, inbox, arrsize(inboxName)); |
|
} |
|
}; |
|
|
|
// 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; |
|
RelVaultNode * node; |
|
unsigned ownerId; |
|
bool seen; |
|
|
|
RelVaultNodeLink (bool seen, unsigned ownerId, unsigned nodeId, RelVaultNode * node) |
|
: THashKeyVal<unsigned>(nodeId) |
|
, seen(seen) |
|
, ownerId(ownerId) |
|
, node(node) |
|
{ |
|
node->IncRef(); |
|
} |
|
~RelVaultNodeLink () { |
|
node->DecRef(); |
|
} |
|
}; |
|
|
|
|
|
struct IRelVaultNode { |
|
RelVaultNode * node; |
|
|
|
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; |
|
RelVaultNode * node; |
|
|
|
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; |
|
|
|
static void VaultNodeFound ( |
|
ENetError result, |
|
void * param, |
|
unsigned nodeIdCount, |
|
const unsigned nodeIds[] |
|
); |
|
}; |
|
|
|
|
|
struct VaultDownloadTrans { |
|
FVaultDownloadCallback callback; |
|
void * cbParam; |
|
FVaultProgressCallback progressCallback; |
|
void * cbProgressParam; |
|
|
|
wchar tag[MAX_PATH]; |
|
unsigned nodeCount; |
|
unsigned nodesLeft; |
|
unsigned vaultId; |
|
ENetError result; |
|
|
|
VaultDownloadTrans (); |
|
|
|
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; |
|
|
|
static void AgeInitCallback ( |
|
ENetError result, |
|
void * param, |
|
unsigned ageVaultId, |
|
unsigned ageInfoVaultId |
|
); |
|
}; |
|
|
|
struct AddChildNodeFetchTrans { |
|
FVaultAddChildNodeCallback callback; |
|
void * cbParam; |
|
ENetError result; |
|
long opCount; |
|
|
|
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 HASHTABLEDECL( |
|
DeviceInbox, |
|
CHashKeyStr, |
|
link |
|
) 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)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->nodeType == plVault::kNodeType_TextNote) { |
|
VaultTextNoteNode textNote(childLink->node); |
|
if (textNote.noteType == plVault::kNoteType_Visit) |
|
VaultProcessVisitNote(childLink->node); |
|
else if (textNote.noteType == 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); |
|
} |
|
} |
|
|
|
DEL(notify); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static void __cdecl LogDumpProc ( |
|
void * , |
|
const wchar 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 = NEWZERO(RelVaultNodeLink)(false, 0, refs[i].parentId, NEWZERO(RelVaultNode)); |
|
parentLink->node->nodeId = refs[i].parentId; // set directly so that the field's dirty flag isn't set |
|
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 = NEWZERO(RelVaultNodeLink)(refs[i].seen, refs[i].ownerId, refs[i].childId, NEWZERO(RelVaultNode)); |
|
childLink->node->nodeId = refs[i].childId; // set directly so that the field's dirty flag isn't set |
|
s_nodes.Add(childLink); |
|
} |
|
else { |
|
existingNodeIds->Add(refs[i].childId); |
|
if (unsigned ownerId = refs[i].ownerId) |
|
childLink->ownerId = ownerId; |
|
} |
|
|
|
RelVaultNode * parentNode = parentLink->node; |
|
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 = NEWZERO(RelVaultNodeLink)(false, 0, parentNode->nodeId, 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 = NEWZERO(RelVaultNodeLink)(refs[i].seen, refs[i].ownerId, childNode->nodeId, childNode); |
|
parentNode->state->children.Add(childLink); |
|
|
|
if (notifyNow || childNode->nodeType != 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 = NEWZERO(INotifyAfterDownload)(parentNode->nodeId, childNode->nodeId); |
|
s_notifyAfterDownload.Add(notify); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static void InitFetchedNode (RelVaultNode * rvn) { |
|
|
|
switch (rvn->nodeType) { |
|
case plVault::kNodeType_SDL: { |
|
VaultSDLNode access(rvn); |
|
if (!access.sdlData || !access.sdlDataLen) |
|
access.InitStateDataRecord(access.sdlName); |
|
} |
|
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); |
|
RelVaultNode * templateNode = NEWZERO(RelVaultNode); |
|
templateNode->IncRef(); |
|
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 (RelVaultNode * rvn = VaultGetNodeIncRef(templateNode)) { |
|
rvn->DecRef(); |
|
continue; |
|
} |
|
NetCliAuthVaultNodeFind( |
|
templateNode, |
|
VaultNodeFound, |
|
nil |
|
); |
|
} |
|
} |
|
} |
|
templateNode->DecRef(); |
|
} |
|
|
|
//============================================================================ |
|
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->nodeType != 0) |
|
continue; |
|
// filter duplicates |
|
if (link->node->nodeId == prevId) |
|
continue; |
|
prevId = link->node->nodeId; |
|
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->nodeId); |
|
if (!link) { |
|
link = NEWZERO(RelVaultNodeLink)(false, 0, node->nodeId, NEWZERO(RelVaultNode)); |
|
link->node->nodeId = node->nodeId; // set directly so that the field's dirty flag isn't set |
|
s_nodes.Add(link); |
|
} |
|
link->node->CopyFrom(node, NetVaultNode::kCopyOverwrite); |
|
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->nodeId); |
|
|
|
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 Uuid & 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->revisionId == 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 (RelVaultNode * rvnInbox = VaultGetPlayerInboxFolderIncRef()) { |
|
inboxId = rvnInbox->nodeId; |
|
rvnInbox->DecRef(); |
|
} |
|
|
|
// 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->nodeType != 0) |
|
continue; |
|
// filter duplicates |
|
if (link->node->nodeId == prevId) |
|
continue; |
|
prevId = link->node->nodeId; |
|
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->nodeType != 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 = TimeGetMs() | 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->dirtyFlags) { |
|
|
|
// Auth server needs the name of the sdl record |
|
if (link->node->nodeType == plVault::kNodeType_SDL) |
|
link->node->dirtyFlags |= VaultSDLNode::kSDLName; |
|
|
|
if (unsigned bytes = NetCliAuthVaultNodeSave(link->node, nil, nil)) { |
|
bytesWritten += bytes; |
|
link->node->Print(L"Saving", LogDumpProc, 0); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
//============================================================================ |
|
static RelVaultNode * GetChildFolderNode ( |
|
RelVaultNode * parent, |
|
unsigned folderType, |
|
unsigned maxDepth |
|
) { |
|
if (!parent) |
|
return nil; |
|
|
|
RelVaultNode * rvn = parent->GetChildFolderNodeIncRef(folderType, maxDepth); |
|
if (rvn) |
|
rvn->DecRef(); |
|
|
|
return rvn; |
|
} |
|
|
|
//============================================================================ |
|
static RelVaultNode * GetChildPlayerInfoListNode ( |
|
RelVaultNode * parent, |
|
unsigned folderType, |
|
unsigned maxDepth |
|
) { |
|
if (!parent) |
|
return nil; |
|
|
|
RelVaultNode * rvn = parent->GetChildPlayerInfoListNodeIncRef(folderType, maxDepth); |
|
if (rvn) |
|
rvn->DecRef(); |
|
|
|
return rvn; |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* 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->nodeId)->node; |
|
else |
|
trans->node = nil; |
|
|
|
trans->Complete(result); |
|
} |
|
|
|
//============================================================================ |
|
void VaultCreateNodeTrans::Complete (ENetError result) { |
|
|
|
if (callback) |
|
callback( |
|
result, |
|
state, |
|
param, |
|
node |
|
); |
|
|
|
DEL(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 |
|
); |
|
DEL(trans); |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* VaultDownloadTrans |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
VaultDownloadTrans::VaultDownloadTrans () { |
|
ASSERT(!nodeCount); // must be alloced with |
|
} |
|
|
|
//============================================================================ |
|
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 |
|
); |
|
|
|
DEL(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->nodeType == 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 |
|
); |
|
|
|
DEL(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 |
|
); |
|
|
|
DEL(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 |
|
); |
|
AtomicAdd(&trans->opCount, incFetchCount); |
|
} |
|
|
|
// Make the callback now if there are no nodes to fetch, or if error |
|
AtomicAdd(&trans->opCount, -1); |
|
if (!trans->opCount) { |
|
if (trans->callback) |
|
trans->callback( |
|
trans->result, |
|
trans->cbParam |
|
); |
|
DEL(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; |
|
|
|
AtomicAdd(&trans->opCount, -1); |
|
if (!trans->opCount) { |
|
if (trans->callback) |
|
trans->callback( |
|
trans->result, |
|
trans->cbParam |
|
); |
|
DEL(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->nodeId))) { |
|
// make them non-findable in our parents table |
|
link->link.Unlink(); |
|
// remove us from other's tables. |
|
link->node->state->Unlink(node); |
|
DEL(link); |
|
} |
|
if (nil != (link = children.Find(other->nodeId))) { |
|
// make them non-findable in our children table |
|
link->link.Unlink(); |
|
// remove us from other's tables. |
|
link->node->state->Unlink(node); |
|
DEL(link); |
|
} |
|
} |
|
|
|
/***************************************************************************** |
|
* |
|
* RelVaultNode |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
RelVaultNode::RelVaultNode () { |
|
state = NEWZERO(IRelVaultNode)(this); |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode::~RelVaultNode () { |
|
DEL(state); |
|
} |
|
|
|
//============================================================================ |
|
bool RelVaultNode::IsParentOf (unsigned childId, unsigned maxDepth) { |
|
if (nodeId == 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 (nodeId == 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(nodeId); |
|
} |
|
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->nodeId); |
|
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->nodeId); |
|
link->node->GetParentNodeIds(nodeIds, maxDepth-1); |
|
} |
|
} |
|
|
|
|
|
//============================================================================ |
|
RelVaultNode * RelVaultNode::GetParentNodeIncRef ( |
|
NetVaultNode * templateNode, |
|
unsigned maxDepth |
|
) { |
|
if (maxDepth == 0) |
|
return false; |
|
|
|
RelVaultNodeLink * link; |
|
link = state->parents.Head(); |
|
for (; link; link = state->parents.Next(link)) { |
|
if (link->node->Matches(templateNode)) { |
|
link->node->IncRef("Found"); |
|
return link->node; |
|
} |
|
} |
|
|
|
link = state->parents.Head(); |
|
for (; link; link = state->parents.Next(link)) { |
|
if (RelVaultNode * node = link->node->GetParentNodeIncRef(templateNode, maxDepth-1)) |
|
return node; |
|
} |
|
|
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * RelVaultNode::GetChildNodeIncRef ( |
|
NetVaultNode * templateNode, |
|
unsigned maxDepth |
|
) { |
|
if (maxDepth == 0) |
|
return false; |
|
|
|
RelVaultNodeLink * link; |
|
link = state->children.Head(); |
|
for (; link; link = state->children.Next(link)) { |
|
if (link->node->Matches(templateNode)) { |
|
link->node->IncRef("Found"); |
|
return link->node; |
|
} |
|
} |
|
|
|
link = state->children.Head(); |
|
for (; link; link = state->children.Next(link)) { |
|
if (RelVaultNode * node = link->node->GetChildNodeIncRef(templateNode, maxDepth-1)) |
|
return node; |
|
} |
|
|
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * RelVaultNode::GetChildNodeIncRef ( |
|
unsigned nodeType, |
|
unsigned maxDepth |
|
) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(nodeType); |
|
RelVaultNode * result = GetChildNodeIncRef(templateNode, maxDepth); |
|
templateNode->DecRef(); |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * RelVaultNode::GetChildFolderNodeIncRef ( |
|
unsigned folderType, |
|
unsigned maxDepth |
|
) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_Folder); |
|
VaultFolderNode folder(templateNode); |
|
folder.SetFolderType(folderType); |
|
RelVaultNode * result = GetChildNodeIncRef(templateNode, maxDepth); |
|
templateNode->DecRef(); |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * RelVaultNode::GetChildPlayerInfoListNodeIncRef ( |
|
unsigned folderType, |
|
unsigned maxDepth |
|
) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_PlayerInfoList); |
|
VaultPlayerInfoListNode access(templateNode); |
|
access.SetFolderType(folderType); |
|
RelVaultNode * result = GetChildNodeIncRef(templateNode, maxDepth); |
|
templateNode->DecRef(); |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * RelVaultNode::GetChildAgeInfoListNodeIncRef ( |
|
unsigned folderType, |
|
unsigned maxDepth |
|
) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfoList); |
|
VaultAgeInfoListNode access(templateNode); |
|
access.SetFolderType(folderType); |
|
RelVaultNode * result = GetChildNodeIncRef(templateNode, maxDepth); |
|
templateNode->DecRef(); |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::GetChildNodesIncRef ( |
|
unsigned maxDepth, |
|
ARRAY(RelVaultNode*) * nodes |
|
) { |
|
if (maxDepth == 0) |
|
return; |
|
|
|
RelVaultNodeLink * link; |
|
link = state->children.Head(); |
|
for (; link; link = state->children.Next(link)) { |
|
nodes->Add(link->node); |
|
link->node->IncRef(); |
|
link->node->GetChildNodesIncRef( |
|
maxDepth - 1, |
|
nodes |
|
); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::GetChildNodesIncRef ( |
|
NetVaultNode * templateNode, |
|
unsigned maxDepth, |
|
ARRAY(RelVaultNode*) * nodes |
|
) { |
|
RelVaultNodeLink * link; |
|
link = state->children.Head(); |
|
for (; link; link = state->children.Next(link)) { |
|
if (link->node->Matches(templateNode)) { |
|
nodes->Add(link->node); |
|
link->node->IncRef(); |
|
} |
|
link->node->GetChildNodesIncRef( |
|
templateNode, |
|
maxDepth - 1, |
|
nodes |
|
); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::GetChildNodesIncRef ( |
|
unsigned nodeType, |
|
unsigned maxDepth, |
|
ARRAY(RelVaultNode*) * nodes |
|
) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(nodeType); |
|
GetChildNodesIncRef( |
|
templateNode, |
|
maxDepth, |
|
nodes |
|
); |
|
templateNode->DecRef(); |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::GetChildFolderNodesIncRef ( |
|
unsigned folderType, |
|
unsigned maxDepth, |
|
ARRAY(RelVaultNode*) * nodes |
|
) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_Folder); |
|
VaultFolderNode fldr(templateNode); |
|
fldr.SetFolderType(folderType); |
|
GetChildNodesIncRef( |
|
templateNode, |
|
maxDepth, |
|
nodes |
|
); |
|
templateNode->DecRef(); |
|
} |
|
|
|
//============================================================================ |
|
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(nodeId)) |
|
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(nodeId)) |
|
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(nodeId)) |
|
if (childLink->seen != seen) { |
|
childLink->seen = seen; |
|
NetCliAuthVaultSetSeen(parentId, nodeId, seen); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void RelVaultNode::Print (const wchar tag[], FStateDump dumpProc, unsigned level) { |
|
wchar str[1024]; |
|
StrPrintf( |
|
str, |
|
arrsize(str), |
|
L"%s%*s%*s%u, %S", |
|
tag ? tag : L"", |
|
tag ? 1 : 0, |
|
" ", |
|
level * 2, |
|
" ", |
|
nodeId, |
|
plVault::NodeTypeStr(nodeType, false) |
|
); |
|
|
|
NetVaultNodeFieldArray fields(this); |
|
for (qword bit = 1; bit; bit <<= 1) { |
|
if (!(fieldFlags & bit)) |
|
continue; |
|
if (bit > fieldFlags) |
|
break; |
|
|
|
StrPack(str, L", ", arrsize(str)); |
|
StrPack(str, fields.GetFieldName(bit), arrsize(str)); |
|
if (fields.GetFieldAddress(bit)) { |
|
StrPack(str, L"=", arrsize(str)); |
|
const unsigned chars = StrLen(str); |
|
fields.GetFieldValueString_LCS(bit, str + chars, arrsize(str) - chars * sizeof(str[0])); |
|
} |
|
} |
|
|
|
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); |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * RelVaultNode::GetParentAgeLinkIncRef () { |
|
|
|
// this function only makes sense when called on age info nodes |
|
ASSERT(nodeType == plVault::kNodeType_AgeInfo); |
|
|
|
RelVaultNode * result = nil; |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
|
|
// Get our parent AgeLink node |
|
if (RelVaultNode * rvnLink = GetParentNodeIncRef(templateNode, 1)) { |
|
// Get the next AgeLink node in our parent tree |
|
result = rvnLink->GetParentNodeIncRef(templateNode, 3); |
|
} |
|
|
|
templateNode->DecRef(); |
|
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); |
|
DEL(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(); |
|
DEL(link); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void VaultUpdate () { |
|
SaveDirtyNodes(); |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Generic Vault Access |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
static RelVaultNode * GetNode ( |
|
unsigned id |
|
) { |
|
RelVaultNodeLink * link = s_nodes.Find(id); |
|
if (link) |
|
return link->node; |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
static RelVaultNode * GetNode ( |
|
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 nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetNodeIncRef ( |
|
NetVaultNode * templateNode |
|
) { |
|
if (RelVaultNode * node = GetNode(templateNode)) { |
|
node->IncRef(); |
|
return node; |
|
} |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetNodeIncRef ( |
|
unsigned nodeId |
|
) { |
|
if (RelVaultNode * node = GetNode(nodeId)) { |
|
node->IncRef(); |
|
return node; |
|
} |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetNodeIncRef ( |
|
unsigned nodeId, |
|
const char reftag[] |
|
) { |
|
if (RelVaultNodeLink * link = s_nodes.Find(nodeId)) { |
|
link->node->IncRef(reftag); |
|
return link->node; |
|
} |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
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 = NEWZERO(RelVaultNodeLink)(false, ownerId, childId, NEWZERO(RelVaultNode)); |
|
childLink->node->nodeId = childId; // set directly so that the field's dirty flag isn't set |
|
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->nodeType || !parentLink->node->nodeType) { |
|
// One or more nodes need to be fetched before the callback is made |
|
AddChildNodeFetchTrans * trans = NEWZERO(AddChildNodeFetchTrans); |
|
trans->callback = callback; |
|
trans->cbParam = param; |
|
if (!childLink->node->nodeType) { |
|
AtomicAdd(&trans->opCount, 1); |
|
NetCliAuthVaultNodeFetch( |
|
childId, |
|
AddChildNodeFetchTrans::VaultNodeFetched, |
|
trans |
|
); |
|
AtomicAdd(&trans->opCount, 1); |
|
NetCliAuthVaultFetchNodeRefs( |
|
childId, |
|
AddChildNodeFetchTrans::VaultNodeRefsFetched, |
|
trans |
|
); |
|
} |
|
if (!parentLink->node->nodeType) { |
|
AtomicAdd(&trans->opCount, 1); |
|
NetCliAuthVaultNodeFetch( |
|
parentId, |
|
AddChildNodeFetchTrans::VaultNodeFetched, |
|
trans |
|
); |
|
AtomicAdd(&trans->opCount, 1); |
|
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; |
|
ZERO(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 wchar deviceName[] |
|
) { |
|
RelVaultNode * rvn; |
|
|
|
rvn = VaultAgeGetDeviceInboxIncRef(deviceName); |
|
if (!rvn) { |
|
LogMsg(kLogDebug, L"Failed to find inbox for device %s, adding it on-the-fly", deviceName); |
|
VaultAgeSetDeviceInboxAndWaitIncRef(deviceName, DEFAULT_DEVICE_INBOX); |
|
|
|
rvn = VaultAgeGetDeviceInboxIncRef(deviceName); |
|
if (!rvn) { |
|
LogMsg(kLogDebug, L"Failed to add inbox to device %s on-the-fly", deviceName); |
|
return; |
|
} |
|
} |
|
|
|
VaultAddChildNode(rvn->nodeId, nodeId, VaultGetPlayerId(), nil, nil); |
|
rvn->DecRef(); |
|
} |
|
|
|
//============================================================================ |
|
void VaultSendNode ( |
|
RelVaultNode* srcNode, |
|
unsigned dstPlayerId |
|
) { |
|
NetCliAuthVaultNodeSave(srcNode, nil, nil); |
|
NetCliAuthVaultSendNode(srcNode->nodeId, dstPlayerId); |
|
} |
|
|
|
//============================================================================ |
|
void VaultCreateNode ( |
|
NetVaultNode * templateNode, |
|
FVaultCreateNodeCallback callback, |
|
void * state, |
|
void * param |
|
) { |
|
VaultCreateNodeTrans * trans = NEWZERO(VaultCreateNodeTrans); |
|
trans->callback = callback; |
|
trans->state = state; |
|
trans->param = param; |
|
|
|
if (RelVaultNode * age = VaultGetAgeNodeIncRef()) { |
|
VaultAgeNode access(age); |
|
if (!(templateNode->fieldFlags & NetVaultNode::kCreateAgeName)) |
|
templateNode->SetCreateAgeName(access.ageName); |
|
if (!(templateNode->fieldFlags & NetVaultNode::kCreateAgeUuid)) |
|
templateNode->SetCreateAgeUuid(access.ageInstUuid); |
|
age->DecRef(); |
|
} |
|
|
|
NetCliAuthVaultNodeCreate( |
|
templateNode, |
|
VaultCreateNodeTrans::VaultNodeCreated, |
|
trans |
|
); |
|
} |
|
|
|
//============================================================================ |
|
void VaultCreateNode ( |
|
plVault::NodeTypes nodeType, |
|
FVaultCreateNodeCallback callback, |
|
void * state, |
|
void * param |
|
) { |
|
RelVaultNode * templateNode = NEWZERO(RelVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(nodeType); |
|
|
|
VaultCreateNode( |
|
templateNode, |
|
callback, |
|
state, |
|
param |
|
); |
|
|
|
templateNode->DecRef(); |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultCreateNodeAndWaitIncRef { |
|
|
|
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 _VaultCreateNodeAndWaitIncRef |
|
|
|
RelVaultNode * VaultCreateNodeAndWaitIncRef ( |
|
NetVaultNode * templateNode, |
|
ENetError * result |
|
) { |
|
using namespace _VaultCreateNodeAndWaitIncRef; |
|
|
|
_CreateNodeParam param; |
|
ZERO(param); |
|
|
|
VaultCreateNode( |
|
templateNode, |
|
_CreateNodeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
*result = param.result; |
|
if (IS_NET_SUCCESS(param.result)) |
|
param.node->IncRef(); |
|
return param.node; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultCreateNodeAndWaitIncRef ( |
|
plVault::NodeTypes nodeType, |
|
ENetError * result |
|
) { |
|
RelVaultNode * node; |
|
RelVaultNode * templateNode = NEWZERO(RelVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(nodeType); |
|
|
|
node = VaultCreateNodeAndWaitIncRef(templateNode, result); |
|
|
|
templateNode->DecRef(); |
|
return node; |
|
} |
|
|
|
//============================================================================ |
|
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; |
|
ZERO(param); |
|
|
|
NetCliAuthVaultNodeSave( |
|
node, |
|
_SaveNodeCallback, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void VaultFindNodes ( |
|
NetVaultNode * templateNode, |
|
FVaultFindNodeCallback callback, |
|
void * param |
|
) { |
|
VaultFindNodeTrans * trans = NEWZERO(VaultFindNodeTrans); |
|
trans->callback = callback; |
|
trans->param = param; |
|
|
|
NetCliAuthVaultNodeFind( |
|
templateNode, |
|
VaultFindNodeTrans::VaultNodeFound, |
|
trans |
|
); |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultFindNodesAndWait { |
|
struct _FindNodeParam { |
|
ARRAY(unsigned) nodeIds; |
|
ENetError result; |
|
bool complete; |
|
}; |
|
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; |
|
ZERO(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->nodeId); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
namespace _VaultFetchNodesAndWait { |
|
|
|
static void _VaultNodeFetched ( |
|
ENetError result, |
|
void * param, |
|
NetVaultNode * node |
|
) { |
|
::VaultNodeFetched(result, nil, node); |
|
|
|
long * nodeCount = (long *)param; |
|
AtomicAdd(nodeCount, -1); |
|
} |
|
|
|
} // namespace _VaultFetchNodesAndWait |
|
|
|
void VaultFetchNodesAndWait ( |
|
const unsigned nodeIds[], |
|
unsigned count, |
|
bool force |
|
) { |
|
using namespace _VaultFetchNodesAndWait; |
|
|
|
long nodeCount = (long)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])) { |
|
AtomicAdd(&nodeCount, -1); |
|
continue; |
|
} |
|
} |
|
|
|
// Start fetching the node |
|
NetCliAuthVaultNodeFetch(nodeIds[i], _VaultNodeFetched, (void *)&nodeCount); |
|
} |
|
|
|
while (nodeCount) { |
|
NetClientUpdate(); |
|
AsyncSleep(10); |
|
} |
|
} |
|
|
|
|
|
//============================================================================ |
|
void VaultInitAge ( |
|
const plAgeInfoStruct * info, |
|
const Uuid & parentAgeInstId, // optional |
|
FVaultInitAgeCallback callback, |
|
void * state, |
|
void * param |
|
) { |
|
VaultAgeInitTrans * trans = NEWZERO(VaultAgeInitTrans); |
|
trans->callback = callback; |
|
trans->cbState = state; |
|
trans->cbParam = param; |
|
|
|
wchar ageFilename[MAX_PATH]; |
|
wchar ageInstName[MAX_PATH]; |
|
wchar ageUserName[MAX_PATH]; |
|
wchar 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( |
|
(Uuid)*info->GetAgeInstanceGuid(), |
|
parentAgeInstId, |
|
ageFilename, |
|
ageInstName, |
|
ageUserName, |
|
ageDesc, |
|
info->GetAgeSequenceNumber(), |
|
info->GetAgeLanguage(), |
|
VaultAgeInitTrans::AgeInitCallback, |
|
trans |
|
); |
|
} |
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Player Vault Access |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
static RelVaultNode * GetPlayerNode () { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_VNodeMgrPlayer); |
|
if (NetCommGetPlayer()) |
|
templateNode->SetNodeId(NetCommGetPlayer()->playerInt); |
|
RelVaultNode * result = GetNode(templateNode); |
|
templateNode->DecRef(); |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
unsigned VaultGetPlayerId () { |
|
if (RelVaultNode * rvn = GetPlayerNode()) |
|
return rvn->nodeId; |
|
return 0; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetPlayerNodeIncRef () { |
|
if (RelVaultNode * rvnPlr = GetPlayerNode()) { |
|
rvnPlr->IncRef(); |
|
return rvnPlr; |
|
} |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetPlayerInfoNodeIncRef () { |
|
RelVaultNode * rvnPlr = VaultGetPlayerNodeIncRef(); |
|
if (!rvnPlr) |
|
return nil; |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_PlayerInfo); |
|
VaultPlayerInfoNode plrInfo(templateNode); |
|
plrInfo.SetPlayerId(rvnPlr->nodeId); |
|
|
|
rvnPlr->DecRef(); |
|
|
|
RelVaultNode * result = nil; |
|
if (RelVaultNode * rvnPlrInfo = rvnPlr->GetChildNodeIncRef(templateNode, 1)) |
|
result = rvnPlrInfo; |
|
|
|
templateNode->DecRef(); |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAvatarOutfitFolderIncRef () { |
|
if (RelVaultNode * rvn = GetPlayerNode()) |
|
return rvn->GetChildFolderNodeIncRef(plVault::kAvatarOutfitFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAvatarClosetFolderIncRef () { |
|
if (RelVaultNode * rvn = GetPlayerNode()) |
|
return rvn->GetChildFolderNodeIncRef(plVault::kAvatarClosetFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetChronicleFolderIncRef () { |
|
if (RelVaultNode * rvn = GetPlayerNode()) |
|
return rvn->GetChildFolderNodeIncRef(plVault::kChronicleFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAgesIOwnFolderIncRef () { |
|
if (RelVaultNode * rvn = GetPlayerNode()) |
|
return rvn->GetChildAgeInfoListNodeIncRef(plVault::kAgesIOwnFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAgesICanVisitFolderIncRef () { |
|
if (RelVaultNode * rvn = GetPlayerNode()) |
|
return rvn->GetChildAgeInfoListNodeIncRef(plVault::kAgesICanVisitFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetPlayerInboxFolderIncRef () { |
|
if (RelVaultNode * rvn = GetPlayerNode()) |
|
return rvn->GetChildFolderNodeIncRef(plVault::kInboxFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetLinkToMyNeighborhood (plAgeLinkStruct * link) { |
|
RelVaultNode * rvnFldr = VaultGetAgesIOwnFolderIncRef(); |
|
if (!rvnFldr) |
|
return false; |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
|
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
VaultAgeInfoNode ageInfo(templateNode); |
|
wchar str[MAX_PATH]; |
|
StrToUnicode(str, kNeighborhoodAgeFilename, arrsize(str)); |
|
ageInfo.SetAgeFilename(str); |
|
|
|
RelVaultNode * node; |
|
if (nil != (node = rvnFldr->GetChildNodeIncRef(templateNode, 2))) { |
|
VaultAgeInfoNode info(node); |
|
info.CopyTo(link->GetAgeInfo()); |
|
node->DecRef(); |
|
} |
|
templateNode->DecRef(); |
|
rvnFldr->DecRef(); |
|
|
|
return node != nil; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetLinkToMyPersonalAge (plAgeLinkStruct * link) { |
|
RelVaultNode * rvnFldr = VaultGetAgesIOwnFolderIncRef(); |
|
if (!rvnFldr) |
|
return false; |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
|
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
VaultAgeInfoNode ageInfo(templateNode); |
|
wchar str[MAX_PATH]; |
|
StrToUnicode(str, kPersonalAgeFilename, arrsize(str)); |
|
ageInfo.SetAgeFilename(str); |
|
|
|
RelVaultNode * node; |
|
if (nil != (node = rvnFldr->GetChildNodeIncRef(templateNode, 2))) { |
|
VaultAgeInfoNode info(node); |
|
info.CopyTo(link->GetAgeInfo()); |
|
node->DecRef(); |
|
} |
|
templateNode->DecRef(); |
|
rvnFldr->DecRef(); |
|
|
|
return node != nil; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetLinkToCity (plAgeLinkStruct * link) { |
|
RelVaultNode * rvnFldr = VaultGetAgesIOwnFolderIncRef(); |
|
if (!rvnFldr) |
|
return false; |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
wchar str[MAX_PATH]; |
|
StrToUnicode(str, kCityAgeFilename, arrsize(str)); |
|
ageInfo.SetAgeFilename(str); |
|
|
|
RelVaultNode * node; |
|
if (nil != (node = rvnFldr->GetChildNodeIncRef(templateNode, 2))) { |
|
VaultAgeInfoNode info(node); |
|
info.CopyTo(link->GetAgeInfo()); |
|
node->DecRef(); |
|
} |
|
templateNode->DecRef(); |
|
rvnFldr->DecRef(); |
|
|
|
return node != nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetOwnedAgeLinkIncRef (const plAgeInfoStruct * info) { |
|
|
|
RelVaultNode * rvnLink = nil; |
|
|
|
if (RelVaultNode * rvnFldr = VaultGetAgesIOwnFolderIncRef()) { |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
if (info->HasAgeFilename()) { |
|
wchar str[MAX_PATH]; |
|
StrToUnicode(str, info->GetAgeFilename(), arrsize(str)); |
|
ageInfo.SetAgeFilename(str); |
|
} |
|
if (info->HasAgeInstanceGuid()) { |
|
ageInfo.SetAgeInstGuid(*info->GetAgeInstanceGuid()); |
|
} |
|
|
|
if (RelVaultNode * rvnInfo = rvnFldr->GetChildNodeIncRef(templateNode, 2)) { |
|
templateNode->fieldFlags = 0; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
rvnLink = rvnInfo->GetParentNodeIncRef(templateNode, 1); |
|
rvnInfo->DecRef(); |
|
} |
|
|
|
templateNode->DecRef(); |
|
rvnFldr->DecRef(); |
|
} |
|
|
|
return rvnLink; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetOwnedAgeInfoIncRef (const plAgeInfoStruct * info) { |
|
|
|
RelVaultNode * rvnInfo = nil; |
|
|
|
if (RelVaultNode * rvnFldr = VaultGetAgesIOwnFolderIncRef()) { |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
if (info->HasAgeFilename()) { |
|
wchar str[MAX_PATH]; |
|
StrToUnicode(str, info->GetAgeFilename(), arrsize(str)); |
|
ageInfo.SetAgeFilename(str); |
|
} |
|
if (info->HasAgeInstanceGuid()) { |
|
ageInfo.SetAgeInstGuid(*info->GetAgeInstanceGuid()); |
|
} |
|
|
|
rvnInfo = rvnFldr->GetChildNodeIncRef(templateNode, 2); |
|
|
|
templateNode->DecRef(); |
|
rvnFldr->DecRef(); |
|
} |
|
|
|
return rvnInfo; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetOwnedAgeLink (const plAgeInfoStruct * info, plAgeLinkStruct * link) { |
|
bool result = false; |
|
if (RelVaultNode * rvnLink = VaultGetOwnedAgeLinkIncRef(info)) { |
|
if (RelVaultNode * rvnInfo = rvnLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode ageInfo(rvnInfo); |
|
ageInfo.CopyTo(link->GetAgeInfo()); |
|
rvnInfo->DecRef(); |
|
result = true; |
|
} |
|
|
|
rvnLink->DecRef(); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultFindOrCreateChildAgeLinkAndWait (const wchar ownedAgeName[], const plAgeInfoStruct * info, plAgeLinkStruct * link) { |
|
hsAssert(false, "eric, implement me"); |
|
return false; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAddOwnedAgeSpawnPoint (const Uuid & ageInstId, const plSpawnPointInfo & spawnPt) { |
|
|
|
RelVaultNode * fldr = nil; |
|
RelVaultNode * link = nil; |
|
|
|
for (;;) { |
|
if (!spawnPt.GetName()) |
|
break; |
|
if (!spawnPt.GetTitle()) |
|
break; |
|
if (!StrLen(spawnPt.GetName())) |
|
break; |
|
if (!StrLen(spawnPt.GetTitle())) |
|
break; |
|
|
|
fldr = VaultGetAgesIOwnFolderIncRef(); |
|
if (!fldr) |
|
break; |
|
|
|
ARRAY(unsigned) nodeIds; |
|
fldr->GetChildNodeIds(&nodeIds, 1); |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
VaultAgeInfoNode access(templateNode); |
|
access.SetAgeInstGuid(ageInstId); |
|
|
|
for (unsigned i = 0; i < nodeIds.Count(); ++i) { |
|
link = VaultGetNodeIncRef(nodeIds[i]); |
|
if (!link) |
|
continue; |
|
if (RelVaultNode * info = link->GetChildNodeIncRef(templateNode, 1)) { |
|
VaultAgeLinkNode access(link); |
|
access.AddSpawnPoint(spawnPt); |
|
info->DecRef(); |
|
link->DecRef(); |
|
link = nil; |
|
break; |
|
} |
|
} |
|
templateNode->DecRef(); |
|
|
|
break; |
|
} |
|
|
|
if (fldr) |
|
fldr->DecRef(); |
|
if (link) |
|
link->DecRef(); |
|
|
|
return true; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultSetOwnedAgePublicAndWait (const plAgeInfoStruct * info, bool publicOrNot) { |
|
if (RelVaultNode * rvnLink = VaultGetOwnedAgeLinkIncRef(info)) { |
|
if (RelVaultNode * rvnInfo = rvnLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) { |
|
NetCliAuthSetAgePublic(rvnInfo->nodeId, publicOrNot); |
|
|
|
VaultAgeInfoNode access(rvnInfo); |
|
char ageName[MAX_PATH]; |
|
StrToAnsi(ageName, access.ageFilename, arrsize(ageName)); |
|
|
|
plVaultNotifyMsg * msg = NEWZERO(plVaultNotifyMsg); |
|
if (publicOrNot) |
|
msg->SetType(plVaultNotifyMsg::kPublicAgeCreated); |
|
else |
|
msg->SetType(plVaultNotifyMsg::kPublicAgeRemoved); |
|
msg->SetResultCode(true); |
|
msg->GetArgs()->AddString(plNetCommon::VaultTaskArgs::kAgeFilename, ageName); |
|
msg->Send(); |
|
|
|
rvnInfo->DecRef(); |
|
} |
|
rvnLink->DecRef(); |
|
} |
|
return true; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetVisitAgeLinkIncRef (const plAgeInfoStruct * info) { |
|
RelVaultNode * rvnLink = nil; |
|
|
|
if (RelVaultNode * rvnFldr = VaultGetAgesICanVisitFolderIncRef()) { |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
if (info->HasAgeFilename()) { |
|
wchar str[MAX_PATH]; |
|
StrToUnicode(str, info->GetAgeFilename(), arrsize(str)); |
|
ageInfo.SetAgeFilename(str); |
|
} |
|
if (info->HasAgeInstanceGuid()) { |
|
ageInfo.SetAgeInstGuid(*info->GetAgeInstanceGuid()); |
|
} |
|
|
|
if (RelVaultNode * rvnInfo = rvnFldr->GetChildNodeIncRef(templateNode, 2)) { |
|
templateNode->fieldFlags = 0; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
rvnLink = rvnInfo->GetParentNodeIncRef(templateNode, 1); |
|
rvnInfo->DecRef(); |
|
} |
|
|
|
templateNode->DecRef(); |
|
rvnFldr->DecRef(); |
|
} |
|
|
|
return rvnLink; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetVisitAgeLink (const plAgeInfoStruct * info, class plAgeLinkStruct * link) { |
|
RelVaultNode * rvn = VaultGetVisitAgeLinkIncRef(info); |
|
if (!rvn) |
|
return false; |
|
|
|
VaultAgeLinkNode ageLink(rvn); |
|
ageLink.CopyTo(link); |
|
|
|
rvn->DecRef(); |
|
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->nodeId; |
|
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 (RelVaultNode * rvn = VaultGetAgesIOwnFolderIncRef()) { |
|
agesIOwnId = rvn->nodeId; |
|
rvn->DecRef(); |
|
} |
|
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; |
|
ZERO(param); |
|
|
|
VaultInitAge( |
|
link->GetAgeInfo(), |
|
kNilGuid, |
|
_InitAgeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"RegisterOwnedAge: Failed to init age %S", link->GetAgeInfo()->GetAgeFilename()); |
|
break; |
|
} |
|
|
|
ageInfoId = param.ageInfoId; |
|
} |
|
|
|
{ // Create age link |
|
_CreateNodeParam param; |
|
ZERO(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; |
|
ZERO(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; |
|
ZERO(param1); |
|
ZERO(param2); |
|
ZERO(param3); |
|
|
|
unsigned ageOwnersId = 0; |
|
if (RelVaultNode * rvnAgeInfo = VaultGetNodeIncRef(ageInfoId)) { |
|
if (RelVaultNode * rvnAgeOwners = rvnAgeInfo->GetChildPlayerInfoListNodeIncRef(plVault::kAgeOwnersFolder, 1)) { |
|
ageOwnersId = rvnAgeOwners->nodeId; |
|
rvnAgeOwners->DecRef(); |
|
} |
|
rvnAgeInfo->DecRef(); |
|
} |
|
|
|
unsigned playerInfoId = 0; |
|
if (RelVaultNode * rvnPlayerInfo = VaultGetPlayerInfoNodeIncRef()) { |
|
playerInfoId = rvnPlayerInfo->nodeId; |
|
rvnPlayerInfo->DecRef(); |
|
} |
|
|
|
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 (RelVaultNode * node = VaultGetNodeIncRef(ageLinkId)) { |
|
VaultAgeLinkNode access(node); |
|
access.AddSpawnPoint(link->SpawnPoint()); |
|
node->DecRef(); |
|
} |
|
|
|
result = true; |
|
break; |
|
} |
|
|
|
plVaultNotifyMsg * msg = NEWZERO(plVaultNotifyMsg); |
|
msg->SetType(plVaultNotifyMsg::kRegisteredOwnedAge); |
|
msg->SetResultCode(result); |
|
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, ageLinkId); |
|
msg->Send(); |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
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->nodeId; |
|
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 (RelVaultNode * rvn = VaultGetAgesICanVisitFolderIncRef()) { |
|
agesICanVisitId = rvn->nodeId; |
|
rvn->DecRef(); |
|
} |
|
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; |
|
ZERO(param); |
|
|
|
VaultInitAge( |
|
link->GetAgeInfo(), |
|
kNilGuid, |
|
_InitAgeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"RegisterVisitAge: Failed to init age %S", link->GetAgeInfo()->GetAgeFilename()); |
|
break; |
|
} |
|
|
|
ageInfoId = param.ageInfoId; |
|
} |
|
|
|
{ // Create age link |
|
_CreateNodeParam param; |
|
ZERO(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; |
|
ZERO(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; |
|
ZERO(param1); |
|
ZERO(param2); |
|
ZERO(param3); |
|
|
|
unsigned ageVisitorsId = 0; |
|
if (RelVaultNode * rvnAgeInfo = VaultGetNodeIncRef(ageInfoId)) { |
|
if (RelVaultNode * rvnAgeVisitors = rvnAgeInfo->GetChildPlayerInfoListNodeIncRef(plVault::kCanVisitFolder, 1)) { |
|
ageVisitorsId = rvnAgeVisitors->nodeId; |
|
rvnAgeVisitors->DecRef(); |
|
} |
|
rvnAgeInfo->DecRef(); |
|
} |
|
|
|
unsigned playerInfoId = 0; |
|
if (RelVaultNode * rvnPlayerInfo = VaultGetPlayerInfoNodeIncRef()) { |
|
playerInfoId = rvnPlayerInfo->nodeId; |
|
rvnPlayerInfo->DecRef(); |
|
} |
|
|
|
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 (RelVaultNode * node = VaultGetNodeIncRef(ageLinkId)) { |
|
VaultAgeLinkNode access(node); |
|
access.AddSpawnPoint(link->SpawnPoint()); |
|
node->DecRef(); |
|
} |
|
|
|
result = true; |
|
break; |
|
} |
|
|
|
plVaultNotifyMsg * msg = NEWZERO(plVaultNotifyMsg); |
|
msg->SetType(plVaultNotifyMsg::kRegisteredVisitAge); |
|
msg->SetResultCode(result); |
|
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, ageLinkId); |
|
msg->Send(); |
|
|
|
return result; |
|
} |
|
|
|
|
|
//============================================================================ |
|
bool VaultUnregisterOwnedAgeAndWait (const plAgeInfoStruct * info) { |
|
|
|
unsigned ageLinkId = 0; |
|
unsigned agesIOwnId; |
|
|
|
bool result = false; |
|
for (;;) { |
|
RelVaultNode * rvnLink = VaultGetOwnedAgeLinkIncRef(info); |
|
if (!rvnLink) { |
|
result = true; |
|
break; // we aren't an owner of the age, just return true |
|
} |
|
|
|
if (RelVaultNode * rvn = VaultGetAgesIOwnFolderIncRef()) { |
|
agesIOwnId = rvn->nodeId; |
|
rvn->DecRef(); |
|
} |
|
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->nodeId; |
|
|
|
unsigned ageOwnersId = 0; |
|
if (RelVaultNode * rvnAgeInfo = rvnLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) { |
|
if (RelVaultNode * rvnAgeOwners = rvnAgeInfo->GetChildPlayerInfoListNodeIncRef(plVault::kAgeOwnersFolder, 1)) { |
|
ageOwnersId = rvnAgeOwners->nodeId; |
|
rvnAgeOwners->DecRef(); |
|
} |
|
rvnAgeInfo->DecRef(); |
|
} |
|
|
|
unsigned playerInfoId = 0; |
|
if (RelVaultNode * rvnPlayerInfo = VaultGetPlayerInfoNodeIncRef()) { |
|
playerInfoId = rvnPlayerInfo->nodeId; |
|
rvnPlayerInfo->DecRef(); |
|
} |
|
|
|
rvnLink->DecRef(); |
|
|
|
// 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 = NEWZERO(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 (;;) { |
|
RelVaultNode * rvnLink = VaultGetVisitAgeLinkIncRef(info); |
|
if (!rvnLink) { |
|
result = true; |
|
break; // we aren't an owner of the age, just return true |
|
} |
|
|
|
if (RelVaultNode * rvn = VaultGetAgesICanVisitFolderIncRef()) { |
|
agesICanVisitId = rvn->nodeId; |
|
rvn->DecRef(); |
|
} |
|
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->nodeId; |
|
|
|
unsigned ageVisitorsId = 0; |
|
if (RelVaultNode * rvnAgeInfo = rvnLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) { |
|
if (RelVaultNode * rvnAgeVisitors = rvnAgeInfo->GetChildPlayerInfoListNodeIncRef(plVault::kCanVisitFolder, 1)) { |
|
ageVisitorsId = rvnAgeVisitors->nodeId; |
|
rvnAgeVisitors->DecRef(); |
|
} |
|
rvnAgeInfo->DecRef(); |
|
} |
|
|
|
unsigned playerInfoId = 0; |
|
if (RelVaultNode * rvnPlayerInfo = VaultGetPlayerInfoNodeIncRef()) { |
|
playerInfoId = rvnPlayerInfo->nodeId; |
|
rvnPlayerInfo->DecRef(); |
|
} |
|
|
|
rvnLink->DecRef(); |
|
|
|
// 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 = NEWZERO(plVaultNotifyMsg); |
|
msg->SetType(plVaultNotifyMsg::kUnRegisteredVisitAge); |
|
msg->SetResultCode(result); |
|
msg->GetArgs()->AddInt(plNetCommon::VaultTaskArgs::kAgeLinkNode, ageLinkId); |
|
msg->Send(); |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultFindChronicleEntryIncRef (const wchar entryName[], int entryType) { |
|
|
|
RelVaultNode * result = nil; |
|
if (RelVaultNode * rvnFldr = GetChildFolderNode(GetPlayerNode(), plVault::kChronicleFolder, 1)) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_Chronicle); |
|
VaultChronicleNode chrn(templateNode); |
|
chrn.SetEntryName(entryName); |
|
if (entryType >= 0) |
|
chrn.SetEntryType(entryType); |
|
if (RelVaultNode * rvnChrn = rvnFldr->GetChildNodeIncRef(templateNode, 255)) |
|
result = rvnChrn; |
|
templateNode->DecRef(); |
|
} |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultHasChronicleEntry (const wchar entryName[], int entryType) { |
|
if (RelVaultNode * rvn = VaultFindChronicleEntryIncRef(entryName, entryType)) { |
|
rvn->DecRef(); |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
//============================================================================ |
|
void VaultAddChronicleEntryAndWait ( |
|
const wchar entryName[], |
|
int entryType, |
|
const wchar entryValue[] |
|
) { |
|
if (RelVaultNode * rvnChrn = VaultFindChronicleEntryIncRef(entryName, entryType)) { |
|
VaultChronicleNode chrnNode(rvnChrn); |
|
chrnNode.SetEntryValue(entryValue); |
|
} |
|
else if (RelVaultNode * rvnFldr = GetChildFolderNode(GetPlayerNode(), plVault::kChronicleFolder, 1)) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_Chronicle); |
|
VaultChronicleNode chrnNode(templateNode); |
|
chrnNode.SetEntryName(entryName); |
|
chrnNode.SetEntryType(entryType); |
|
chrnNode.SetEntryValue(entryValue); |
|
ENetError result; |
|
if (RelVaultNode * rvnChrn = VaultCreateNodeAndWaitIncRef(templateNode, &result)) { |
|
VaultAddChildNode(rvnFldr->nodeId, rvnChrn->nodeId, 0, nil, nil); |
|
rvnChrn->DecRef(); |
|
} |
|
templateNode->DecRef(); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmIgnoringPlayer (unsigned playerId) { |
|
bool retval = false; |
|
if (RelVaultNode * rvnFldr = GetChildPlayerInfoListNode(GetPlayerNode(), plVault::kIgnoreListFolder, 1)) { |
|
rvnFldr->IncRef(); |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_PlayerInfo); |
|
VaultPlayerInfoNode pinfoNode(templateNode); |
|
pinfoNode.SetPlayerId(playerId); |
|
|
|
if (RelVaultNode * rvnPlayerInfo = rvnFldr->GetChildNodeIncRef(templateNode, 1)) { |
|
retval = true; |
|
rvnPlayerInfo->DecRef(); |
|
} |
|
|
|
templateNode->DecRef(); |
|
rvnFldr->DecRef(); |
|
} |
|
|
|
return retval; |
|
} |
|
|
|
//============================================================================ |
|
unsigned VaultGetKILevel () { |
|
hsAssert(false, "eric, implement me"); |
|
return pfKIMsg::kNanoKI; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultGetCCRStatus () { |
|
bool retval = false; |
|
if (RelVaultNode * rvnSystem = VaultGetSystemNodeIncRef()) { |
|
VaultSystemNode sysNode(rvnSystem); |
|
retval = (sysNode.ccrStatus != 0); |
|
|
|
rvnSystem->DecRef(); |
|
} |
|
|
|
return retval; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultSetCCRStatus (bool online) { |
|
bool retval = false; |
|
if (RelVaultNode * rvnSystem = VaultGetSystemNodeIncRef()) { |
|
VaultSystemNode sysNode(rvnSystem); |
|
sysNode.SetCCRStatus(online ? 1 : 0); |
|
|
|
rvnSystem->DecRef(); |
|
retval = true; |
|
} |
|
|
|
return retval; |
|
} |
|
|
|
//============================================================================ |
|
void VaultDump (const wchar tag[], unsigned vaultId, FStateDump dumpProc) { |
|
LogMsg(kLogDebug, L"<---- ID:%u, Begin Vault%*s%s ---->", vaultId, tag ? 1 : 0, L" ", tag); |
|
|
|
if (RelVaultNode * rvn = GetNode(vaultId)) |
|
rvn->PrintTree(dumpProc, 0); |
|
|
|
LogMsg(kLogDebug, L"<---- ID:%u, End Vault%*s%s ---->", vaultId, tag ? 1 : 0, L" ", tag); |
|
} |
|
|
|
//============================================================================ |
|
void VaultDump (const wchar tag[], unsigned vaultId) { |
|
VaultDump (tag, vaultId, LogDumpProc); |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmInMyPersonalAge () { |
|
bool result = false; |
|
|
|
plAgeInfoStruct info; |
|
info.SetAgeFilename(kPersonalAgeFilename); |
|
|
|
if (RelVaultNode * rvnLink = VaultGetOwnedAgeLinkIncRef(&info)) { |
|
if (RelVaultNode * rvnInfo = rvnLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode ageInfo(rvnInfo); |
|
|
|
if (RelVaultNode* currentAgeInfoNode = VaultGetAgeInfoNodeIncRef()) { |
|
VaultAgeInfoNode curAgeInfo(currentAgeInfoNode); |
|
|
|
if (ageInfo.ageInstUuid == curAgeInfo.ageInstUuid) |
|
result = true; |
|
|
|
currentAgeInfoNode->DecRef(); |
|
} |
|
|
|
rvnInfo->DecRef(); |
|
} |
|
|
|
rvnLink->DecRef(); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmInMyNeighborhoodAge () { |
|
bool result = false; |
|
|
|
plAgeInfoStruct info; |
|
info.SetAgeFilename(kNeighborhoodAgeFilename); |
|
|
|
if (RelVaultNode * rvnLink = VaultGetOwnedAgeLinkIncRef(&info)) { |
|
if (RelVaultNode * rvnInfo = rvnLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode ageInfo(rvnInfo); |
|
|
|
if (RelVaultNode* currentAgeInfoNode = VaultGetAgeInfoNodeIncRef()) { |
|
VaultAgeInfoNode curAgeInfo(currentAgeInfoNode); |
|
|
|
if (ageInfo.ageInstUuid == curAgeInfo.ageInstUuid) |
|
result = true; |
|
|
|
currentAgeInfoNode->DecRef(); |
|
} |
|
|
|
rvnInfo->DecRef(); |
|
} |
|
|
|
rvnLink->DecRef(); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmOwnerOfCurrentAge () { |
|
bool result = false; |
|
|
|
if (RelVaultNode* currentAgeInfoNode = VaultGetAgeInfoNodeIncRef()) { |
|
VaultAgeInfoNode curAgeInfo(currentAgeInfoNode); |
|
|
|
char* ageFilename = StrDupToAnsi(curAgeInfo.ageFilename); |
|
|
|
plAgeInfoStruct info; |
|
info.SetAgeFilename(ageFilename); |
|
|
|
FREE(ageFilename); |
|
|
|
if (RelVaultNode * rvnLink = VaultGetOwnedAgeLinkIncRef(&info)) { |
|
|
|
if (RelVaultNode * rvnInfo = rvnLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode ageInfo(rvnInfo); |
|
|
|
if (ageInfo.ageInstUuid == curAgeInfo.ageInstUuid) |
|
result = true; |
|
|
|
rvnInfo->DecRef(); |
|
} |
|
|
|
rvnLink->DecRef(); |
|
} |
|
|
|
currentAgeInfoNode->DecRef(); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmCzarOfCurrentAge () { |
|
hsAssert(false, "eric, implement me"); |
|
return true; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmOwnerOfAge (const Uuid & ageInstId) { |
|
hsAssert(false, "eric, implement me"); |
|
return true; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAmCzarOfAge (const Uuid & ageInstId) { |
|
// hsAssert(false, "eric, implement me"); |
|
return false; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultRegisterMTStationAndWait ( |
|
const wchar stationName[], |
|
const wchar linkBackSpawnPtObjName[] |
|
) { |
|
plAgeInfoStruct info; |
|
info.SetAgeFilename(kCityAgeFilename); |
|
if (RelVaultNode * rvn = VaultGetOwnedAgeLinkIncRef(&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)); |
|
rvn->DecRef(); |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
//============================================================================ |
|
void VaultProcessVisitNote(RelVaultNode * rvnVisit) { |
|
if (RelVaultNode * rvnInbox = VaultGetPlayerInboxFolderIncRef()) { |
|
rvnVisit->IncRef(); |
|
|
|
VaultTextNoteNode visitAcc(rvnVisit); |
|
plAgeLinkStruct link; |
|
if (visitAcc.GetVisitInfo(link.GetAgeInfo())) { |
|
// Add it to our "ages i can visit" folder |
|
VaultRegisterVisitAgeAndWait(&link); |
|
} |
|
// remove it from the inbox |
|
VaultRemoveChildNode(rvnInbox->nodeId, rvnVisit->nodeId, nil, nil); |
|
rvnVisit->DecRef(); |
|
|
|
rvnInbox->DecRef(); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void VaultProcessUnvisitNote(RelVaultNode * rvnUnVisit) { |
|
if (RelVaultNode * rvnInbox = VaultGetPlayerInboxFolderIncRef()) { |
|
rvnUnVisit->IncRef(); |
|
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->nodeId, rvnUnVisit->nodeId, nil, nil); |
|
rvnUnVisit->DecRef(); |
|
|
|
rvnInbox->DecRef(); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
void VaultProcessPlayerInbox () { |
|
if (RelVaultNode * rvnInbox = VaultGetPlayerInboxFolderIncRef()) { |
|
{ // Process new visit requests |
|
ARRAY(RelVaultNode*) visits; |
|
RelVaultNode * templateNode = NEWZERO(RelVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_TextNote); |
|
VaultTextNoteNode tmpAcc(templateNode); |
|
tmpAcc.SetNoteType(plVault::kNoteType_Visit); |
|
rvnInbox->GetChildNodesIncRef(templateNode, 1, &visits); |
|
templateNode->DecRef(); |
|
|
|
for (unsigned i = 0; i < visits.Count(); ++i) { |
|
RelVaultNode * rvnVisit = visits[i]; |
|
VaultTextNoteNode visitAcc(rvnVisit); |
|
plAgeLinkStruct link; |
|
if (visitAcc.GetVisitInfo(link.GetAgeInfo())) { |
|
// Add it to our "ages i can visit" folder |
|
VaultRegisterVisitAgeAndWait(&link); |
|
} |
|
// remove it from the inbox |
|
VaultRemoveChildNode(rvnInbox->nodeId, rvnVisit->nodeId, nil, nil); |
|
rvnVisit->DecRef(); |
|
} |
|
} |
|
{ // Process new unvisit requests |
|
ARRAY(RelVaultNode*) unvisits; |
|
RelVaultNode * templateNode = NEWZERO(RelVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_TextNote); |
|
VaultTextNoteNode tmpAcc(templateNode); |
|
tmpAcc.SetNoteType(plVault::kNoteType_UnVisit); |
|
rvnInbox->GetChildNodesIncRef(templateNode, 1, &unvisits); |
|
templateNode->DecRef(); |
|
|
|
for (unsigned i = 0; i < unvisits.Count(); ++i) { |
|
RelVaultNode * rvnUnVisit = unvisits[i]; |
|
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->nodeId, rvnUnVisit->nodeId, nil, nil); |
|
rvnUnVisit->DecRef(); |
|
} |
|
} |
|
|
|
rvnInbox->DecRef(); |
|
} |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Age Vault Access |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
static RelVaultNode * GetAgeNode () { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_VNodeMgrAge); |
|
if (NetCommGetAge()) |
|
templateNode->SetNodeId(NetCommGetAge()->ageVaultId); |
|
RelVaultNode * result = GetNode(templateNode); |
|
templateNode->DecRef(); |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAgeNodeIncRef () { |
|
RelVaultNode * result = nil; |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_VNodeMgrAge); |
|
if (NetCommGetAge()) |
|
templateNode->SetNodeId(NetCommGetAge()->ageVaultId); |
|
if (RelVaultNode * rvnAge = VaultGetNodeIncRef(templateNode)) |
|
result = rvnAge; |
|
templateNode->DecRef(); |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
static RelVaultNode * GetAgeInfoNode () { |
|
RelVaultNode * rvnAge = VaultGetAgeNodeIncRef(); |
|
if (!rvnAge) |
|
return nil; |
|
|
|
RelVaultNode * result = nil; |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
|
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
templateNode->SetCreatorId(rvnAge->nodeId); |
|
|
|
if (RelVaultNode * rvnAgeInfo = rvnAge->GetChildNodeIncRef(templateNode, 1)) { |
|
rvnAgeInfo->DecRef(); |
|
result = rvnAgeInfo; |
|
} |
|
|
|
templateNode->DecRef(); |
|
rvnAge->DecRef(); |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAgeInfoNodeIncRef () { |
|
RelVaultNode * rvnAge = VaultGetAgeNodeIncRef(); |
|
if (!rvnAge) |
|
return nil; |
|
|
|
RelVaultNode * result = nil; |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
templateNode->SetCreatorId(rvnAge->nodeId); |
|
|
|
if (RelVaultNode * rvnAgeInfo = rvnAge->GetChildNodeIncRef(templateNode, 1)) |
|
result = rvnAgeInfo; |
|
|
|
templateNode->DecRef(); |
|
rvnAge->DecRef(); |
|
|
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAgeChronicleFolderIncRef () { |
|
if (RelVaultNode * rvn = GetAgeNode()) |
|
return rvn->GetChildFolderNodeIncRef(plVault::kChronicleFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAgeDevicesFolderIncRef () { |
|
if (RelVaultNode * rvn = GetAgeNode()) |
|
return rvn->GetChildFolderNodeIncRef(plVault::kAgeDevicesFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAgeAgeOwnersFolderIncRef () { |
|
if (RelVaultNode * rvn = GetAgeInfoNode()) |
|
return rvn->GetChildPlayerInfoListNodeIncRef(plVault::kAgeOwnersFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAgeCanVisitFolderIncRef () { |
|
if (RelVaultNode * rvn = GetAgeInfoNode()) |
|
return rvn->GetChildPlayerInfoListNodeIncRef(plVault::kCanVisitFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAgePeopleIKnowAboutFolderIncRef () { |
|
if (RelVaultNode * rvn = GetAgeNode()) |
|
return rvn->GetChildPlayerInfoListNodeIncRef(plVault::kPeopleIKnowAboutFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAgeSubAgesFolderIncRef () { |
|
if (RelVaultNode * rvn = GetAgeNode()) |
|
return rvn->GetChildAgeInfoListNodeIncRef(plVault::kSubAgesFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetAgePublicAgesFolderIncRef () { |
|
hsAssert(false, "eric, implement me"); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultAgeGetBookshelfFolderIncRef () { |
|
if (RelVaultNode * rvn = GetAgeNode()) |
|
return rvn->GetChildAgeInfoListNodeIncRef(plVault::kAgesIOwnFolder, 1); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultFindAgeSubAgeLinkIncRef (const plAgeInfoStruct * info) { |
|
RelVaultNode * rvnLink = nil; |
|
|
|
if (RelVaultNode * rvnFldr = VaultGetAgeSubAgesFolderIncRef()) { |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
wchar str[MAX_PATH]; |
|
StrToUnicode(str, info->GetAgeFilename(), arrsize(str)); |
|
ageInfo.SetAgeFilename(str); |
|
|
|
if (RelVaultNode * rvnInfo = rvnFldr->GetChildNodeIncRef(templateNode, 2)) { |
|
templateNode->fieldFlags = 0; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
rvnLink = rvnInfo->GetParentNodeIncRef(templateNode, 1); |
|
rvnInfo->DecRef(); |
|
} |
|
|
|
templateNode->DecRef(); |
|
rvnFldr->DecRef(); |
|
} |
|
|
|
return rvnLink; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultFindAgeChronicleEntryIncRef (const wchar entryName[], int entryType) { |
|
hsAssert(false, "eric, implement me"); |
|
return nil; |
|
} |
|
|
|
//============================================================================ |
|
void VaultAddAgeChronicleEntry ( |
|
const wchar entryName[], |
|
int entryType, |
|
const wchar entryValue[] |
|
) { |
|
hsAssert(false, "eric, implement me"); |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultAgeAddDeviceAndWaitIncRef (const wchar deviceName[]) { |
|
if (RelVaultNode * existing = VaultAgeGetDeviceIncRef(deviceName)) |
|
return existing; |
|
|
|
RelVaultNode * device = nil; |
|
RelVaultNode * folder = nil; |
|
|
|
for (;;) { |
|
folder = VaultGetAgeDevicesFolderIncRef(); |
|
if (!folder) |
|
break; |
|
|
|
ENetError result; |
|
device = VaultCreateNodeAndWaitIncRef(plVault::kNodeType_TextNote, &result); |
|
if (!device) |
|
break; |
|
|
|
VaultTextNoteNode access(device); |
|
access.SetNoteType(plVault::kNoteType_Device); |
|
access.SetNoteTitle(deviceName); |
|
|
|
VaultAddChildNodeAndWait(folder->nodeId, device->nodeId, 0); |
|
break; |
|
} |
|
|
|
if (folder) |
|
folder->DecRef(); |
|
|
|
return device; |
|
} |
|
|
|
//============================================================================ |
|
void VaultAgeRemoveDevice (const wchar deviceName[]) { |
|
if (RelVaultNode * folder = VaultGetAgeDevicesFolderIncRef()) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_TextNote); |
|
VaultTextNoteNode access(templateNode); |
|
access.SetNoteTitle(deviceName); |
|
if (RelVaultNode * device = folder->GetChildNodeIncRef(templateNode, 1)) { |
|
VaultRemoveChildNode(folder->nodeId, device->nodeId, nil, nil); |
|
device->DecRef(); |
|
|
|
if (DeviceInbox * deviceInbox = s_ageDeviceInboxes.Find(CHashKeyStr(deviceName))) |
|
DEL(device); |
|
} |
|
templateNode->DecRef(); |
|
folder->DecRef(); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAgeHasDevice (const wchar deviceName[]) { |
|
bool found = false; |
|
if (RelVaultNode * folder = VaultGetAgeDevicesFolderIncRef()) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_TextNote); |
|
VaultTextNoteNode access(templateNode); |
|
access.SetNoteTitle(deviceName); |
|
if (RelVaultNode * device = folder->GetChildNodeIncRef(templateNode, 1)) { |
|
found = true; |
|
device->DecRef(); |
|
} |
|
templateNode->DecRef(); |
|
folder->DecRef(); |
|
} |
|
return found; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultAgeGetDeviceIncRef (const wchar deviceName[]) { |
|
RelVaultNode * result = nil; |
|
if (RelVaultNode * folder = VaultGetAgeDevicesFolderIncRef()) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_TextNote); |
|
VaultTextNoteNode access(templateNode); |
|
access.SetNoteTitle(deviceName); |
|
if (RelVaultNode * device = folder->GetChildNodeIncRef(templateNode, 1)) |
|
result = device; |
|
templateNode->DecRef(); |
|
folder->DecRef(); |
|
} |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultAgeSetDeviceInboxAndWaitIncRef (const wchar deviceName[], const wchar inboxName[]) { |
|
DeviceInbox * devInbox = s_ageDeviceInboxes.Find(CHashKeyStr(deviceName)); |
|
if (devInbox) { |
|
StrCopy(devInbox->inboxName, inboxName, arrsize(devInbox->inboxName)); |
|
} |
|
else { |
|
devInbox = NEWZERO(DeviceInbox)(deviceName, inboxName); |
|
s_ageDeviceInboxes.Add(devInbox); |
|
} |
|
|
|
// 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 |
|
RelVaultNode * existing = VaultAgeGetDeviceInboxIncRef(deviceName); |
|
if (existing || StrCmp(inboxName, DEFAULT_DEVICE_INBOX) != 0) |
|
return existing; |
|
|
|
RelVaultNode * device = nil; |
|
RelVaultNode * inbox = nil; |
|
|
|
for (;;) { |
|
device = VaultAgeGetDeviceIncRef(deviceName); |
|
if (!device) |
|
break; |
|
|
|
ENetError result; |
|
inbox = VaultCreateNodeAndWaitIncRef(plVault::kNodeType_Folder, &result); |
|
if (!inbox) |
|
break; |
|
|
|
VaultFolderNode access(inbox); |
|
access.SetFolderName(inboxName); |
|
access.SetFolderType(plVault::kDeviceInboxFolder); |
|
|
|
VaultAddChildNodeAndWait(device->nodeId, inbox->nodeId, 0); |
|
break; |
|
} |
|
|
|
return inbox; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultAgeGetDeviceInboxIncRef (const wchar deviceName[]) { |
|
RelVaultNode * result = nil; |
|
DeviceInbox * devInbox = s_ageDeviceInboxes.Find(CHashKeyStr(deviceName)); |
|
|
|
if (devInbox) |
|
{ |
|
RelVaultNode * parentNode = nil; |
|
const wchar * inboxName = nil; |
|
|
|
if (StrCmp(devInbox->inboxName, DEFAULT_DEVICE_INBOX) == 0) { |
|
parentNode = VaultAgeGetDeviceIncRef(deviceName); |
|
} |
|
else { |
|
parentNode = VaultGetGlobalInboxIncRef(); |
|
} |
|
|
|
if (parentNode) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_Folder); |
|
VaultFolderNode access(templateNode); |
|
access.SetFolderType(plVault::kDeviceInboxFolder); |
|
access.SetFolderName(devInbox->inboxName); |
|
result = parentNode->GetChildNodeIncRef(templateNode, 1); |
|
templateNode->DecRef(); |
|
parentNode->DecRef(); |
|
} |
|
} |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
void VaultClearDeviceInboxMap () { |
|
while (DeviceInbox * inbox = s_ageDeviceInboxes.Head()) { |
|
DEL(inbox); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAgeGetAgeSDL (plStateDataRecord * out) { |
|
bool result = false; |
|
if (RelVaultNode * rvn = VaultGetAgeInfoNodeIncRef()) { |
|
if (RelVaultNode * rvnSdl = rvn->GetChildNodeIncRef(plVault::kNodeType_SDL, 1)) { |
|
VaultSDLNode sdl(rvnSdl); |
|
result = sdl.GetStateDataRecord(out, plSDL::kKeepDirty); |
|
if (!result) { |
|
sdl.InitStateDataRecord(sdl.sdlName); |
|
result = sdl.GetStateDataRecord(out, plSDL::kKeepDirty); |
|
} |
|
rvnSdl->DecRef(); |
|
} |
|
rvn->DecRef(); |
|
} |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
void VaultAgeUpdateAgeSDL (const plStateDataRecord * rec) { |
|
if (RelVaultNode * rvn = VaultGetAgeInfoNodeIncRef()) { |
|
if (RelVaultNode * rvnSdl = rvn->GetChildNodeIncRef(plVault::kNodeType_SDL, 1)) { |
|
VaultSDLNode sdl(rvnSdl); |
|
sdl.SetStateDataRecord(rec, plSDL::kDirtyOnly | plSDL::kTimeStampOnRead); |
|
rvnSdl->DecRef(); |
|
} |
|
rvn->DecRef(); |
|
} |
|
} |
|
|
|
//============================================================================ |
|
unsigned VaultAgeGetAgeTime () { |
|
hsAssert(false, "eric, implement me"); |
|
return 0; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetSubAgeLinkIncRef (const plAgeInfoStruct * info) { |
|
|
|
RelVaultNode * rvnLink = nil; |
|
|
|
if (RelVaultNode * rvnFldr = VaultGetAgeSubAgesFolderIncRef()) { |
|
|
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
wchar str[MAX_PATH]; |
|
StrToUnicode(str, info->GetAgeFilename(), arrsize(str)); |
|
ageInfo.SetAgeFilename(str); |
|
|
|
if (RelVaultNode * rvnInfo = rvnFldr->GetChildNodeIncRef(templateNode, 2)) { |
|
templateNode->fieldFlags = 0; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
rvnLink = rvnInfo->GetParentNodeIncRef(templateNode, 1); |
|
rvnInfo->DecRef(); |
|
} |
|
|
|
templateNode->DecRef(); |
|
rvnFldr->DecRef(); |
|
} |
|
|
|
return rvnLink; |
|
} |
|
|
|
//============================================================================ |
|
bool VaultAgeGetSubAgeLink (const plAgeInfoStruct * info, plAgeLinkStruct * link) { |
|
bool result = false; |
|
if (RelVaultNode * rvnLink = VaultGetSubAgeLinkIncRef(info)) { |
|
if (RelVaultNode * rvnInfo = rvnLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode ageInfo(rvnInfo); |
|
ageInfo.CopyTo(link->GetAgeInfo()); |
|
rvnInfo->DecRef(); |
|
result = true; |
|
} |
|
|
|
rvnLink->DecRef(); |
|
} |
|
|
|
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->nodeId; |
|
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 Uuid & parentAgeInstId |
|
) { |
|
if (RelVaultNode * rvnLink = VaultFindAgeSubAgeLinkIncRef(info)) { |
|
VaultAgeLinkNode linkAcc(rvnLink); |
|
linkAcc.CopyTo(link); |
|
if (RelVaultNode * rvnInfo = rvnLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1)) { |
|
VaultAgeInfoNode infoAcc(rvnInfo); |
|
infoAcc.CopyTo(link->GetAgeInfo()); |
|
rvnInfo->DecRef(); |
|
rvnLink->DecRef(); |
|
return true; |
|
} |
|
} |
|
|
|
using namespace _VaultCreateSubAgeAndWait; |
|
|
|
unsigned subAgesId; |
|
unsigned ageInfoId; |
|
unsigned ageLinkId; |
|
|
|
if (RelVaultNode * rvnSubAges = VaultGetAgeSubAgesFolderIncRef()) { |
|
subAgesId = rvnSubAges->nodeId; |
|
rvnSubAges->DecRef(); |
|
} |
|
else { |
|
LogMsg(kLogError, L"CreateSubAge: Failed to get ages's SubAges folder"); |
|
return false; |
|
} |
|
|
|
{ // Init age vault |
|
_InitAgeParam param; |
|
ZERO(param); |
|
|
|
VaultInitAge( |
|
info, |
|
parentAgeInstId, |
|
_InitAgeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"CreateSubAge: Failed to init age %S", link->GetAgeInfo()->GetAgeFilename()); |
|
return false; |
|
} |
|
|
|
ageInfoId = param.ageInfoId; |
|
} |
|
|
|
{ // Create age link |
|
_CreateNodeParam param; |
|
ZERO(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; |
|
ZERO(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; |
|
ZERO(param1); |
|
ZERO(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 (RelVaultNode * rvnLink = VaultGetNodeIncRef(ageLinkId)) { |
|
VaultAgeLinkNode linkAcc(rvnLink); |
|
linkAcc.CopyTo(link); |
|
rvnLink->DecRef(); |
|
} |
|
|
|
if (RelVaultNode * rvnInfo = VaultGetNodeIncRef(ageInfoId)) { |
|
VaultAgeInfoNode infoAcc(rvnInfo); |
|
infoAcc.CopyTo(link->GetAgeInfo()); |
|
rvnInfo->DecRef(); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
//============================================================================ |
|
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->nodeId; |
|
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 parentAgeName[], |
|
const plAgeInfoStruct * info, |
|
plAgeLinkStruct * link |
|
) { |
|
using namespace _VaultCreateChildAgeAndWait; |
|
|
|
unsigned childAgesId; |
|
unsigned ageInfoId; |
|
unsigned ageLinkId; |
|
|
|
{ // Get id of child ages folder |
|
RelVaultNode * rvnAgeInfo = nil; |
|
if (parentAgeName) { |
|
char ansi[MAX_PATH]; |
|
StrToAnsi(ansi, parentAgeName, arrsize(ansi)); |
|
plAgeInfoStruct pinfo; |
|
pinfo.SetAgeFilename(ansi); |
|
if (RelVaultNode * rvnAgeLink = VaultGetOwnedAgeLinkIncRef(&pinfo)) { |
|
rvnAgeInfo = rvnAgeLink->GetChildNodeIncRef(plVault::kNodeType_AgeInfo, 1); |
|
rvnAgeLink->DecRef(); |
|
} |
|
} |
|
else { |
|
rvnAgeInfo = VaultGetAgeInfoNodeIncRef(); |
|
} |
|
|
|
if (!rvnAgeInfo) { |
|
LogMsg(kLogError, L"CreateChildAge: Failed to get ages's AgeInfo node"); |
|
return false; |
|
} |
|
|
|
RelVaultNode * rvnChildAges; |
|
if (nil != (rvnChildAges = rvnAgeInfo->GetChildAgeInfoListNodeIncRef(plVault::kChildAgesFolder, 1))) { |
|
childAgesId = rvnChildAges->nodeId; |
|
} |
|
else { |
|
rvnAgeInfo->DecRef(); |
|
LogMsg(kLogError, L"CreateChildAge: Failed to get ages's ChildAges folder"); |
|
return false; |
|
} |
|
rvnAgeInfo->DecRef(); |
|
|
|
// Check for existing child age in folder |
|
RelVaultNode * rvnLink = nil; |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_AgeInfo); |
|
|
|
VaultAgeInfoNode ageInfo(templateNode); |
|
wchar str[MAX_PATH]; |
|
StrToUnicode(str, info->GetAgeFilename(), arrsize(str)); |
|
ageInfo.SetAgeFilename(str); |
|
|
|
if (RelVaultNode * rvnInfo = rvnChildAges->GetChildNodeIncRef(templateNode, 2)) { |
|
templateNode->fieldFlags = 0; |
|
templateNode->SetNodeType(plVault::kNodeType_AgeLink); |
|
rvnLink = rvnInfo->GetParentNodeIncRef(templateNode, 1); |
|
rvnInfo->DecRef(); |
|
} |
|
|
|
templateNode->DecRef(); |
|
rvnChildAges->DecRef(); |
|
|
|
if (rvnLink) { |
|
VaultAgeLinkNode access(rvnLink); |
|
access.CopyTo(link); |
|
rvnLink->DecRef(); |
|
return true; |
|
} |
|
} |
|
|
|
{ // Init age vault |
|
_InitAgeParam param; |
|
ZERO(param); |
|
|
|
Uuid parentAgeInstId; |
|
ZERO(parentAgeInstId); |
|
if (RelVaultNode * rvnAge = VaultGetAgeNodeIncRef()) { |
|
VaultAgeNode access(rvnAge); |
|
parentAgeInstId = access.ageInstUuid; |
|
rvnAge->DecRef(); |
|
} |
|
|
|
VaultInitAge( |
|
info, |
|
parentAgeInstId, |
|
_InitAgeCallback, |
|
nil, |
|
¶m |
|
); |
|
|
|
while (!param.complete) { |
|
NetClientUpdate(); |
|
plgDispatch::Dispatch()->MsgQueueProcess(); |
|
AsyncSleep(10); |
|
} |
|
|
|
if (IS_NET_ERROR(param.result)) { |
|
LogMsg(kLogError, L"CreateChildAge: Failed to init age %S", link->GetAgeInfo()->GetAgeFilename()); |
|
return false; |
|
} |
|
|
|
ageInfoId = param.ageInfoId; |
|
} |
|
|
|
{ // Create age link |
|
_CreateNodeParam param; |
|
ZERO(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; |
|
ZERO(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; |
|
ZERO(param1); |
|
ZERO(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 (RelVaultNode * rvnLink = VaultGetNodeIncRef(ageLinkId)) { |
|
VaultAgeLinkNode linkAcc(rvnLink); |
|
linkAcc.CopyTo(link); |
|
rvnLink->DecRef(); |
|
} |
|
|
|
if (RelVaultNode * rvnInfo = VaultGetNodeIncRef(ageInfoId)) { |
|
VaultAgeInfoNode infoAcc(rvnInfo); |
|
infoAcc.CopyTo(link->GetAgeInfo()); |
|
rvnInfo->DecRef(); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* CCR Vault Access |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
void VaultCCRDumpPlayers() { |
|
hsAssert(false, "eric, implement me"); |
|
} |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Vault download |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
void VaultDownload ( |
|
const wchar tag[], |
|
unsigned vaultId, |
|
FVaultDownloadCallback callback, |
|
void * cbParam, |
|
FVaultProgressCallback progressCallback, |
|
void * cbProgressParam |
|
) { |
|
VaultDownloadTrans * trans = NEWZERO(VaultDownloadTrans); |
|
StrCopy(trans->tag, tag, arrsize(trans->tag)); |
|
trans->callback = callback; |
|
trans->cbParam = cbParam; |
|
trans->progressCallback = progressCallback; |
|
trans->cbProgressParam = cbProgressParam; |
|
trans->vaultId = 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 tag[], |
|
unsigned vaultId, |
|
FVaultProgressCallback progressCallback, |
|
void * cbProgressParam |
|
) { |
|
_DownloadVaultParam param; |
|
ZERO(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->nodeId); |
|
link->node->state->UnlinkFromRelatives(); |
|
DEL(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->nodeType > plVault::kNodeType_VNodeMgrLow && link->node->nodeType < 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->nodeType > plVault::kNodeType_VNodeMgrLow && root->node->nodeType < plVault::kNodeType_VNodeMgrHigh) { |
|
foundRoot = true; |
|
break; |
|
} |
|
} |
|
if (!foundRoot) { |
|
LogMsg(kLogDebug, L"Vault: Culling node %u", link->node->nodeId); |
|
link->node->state->UnlinkFromRelatives(); |
|
DEL(link); |
|
} |
|
} |
|
} |
|
|
|
/***************************************************************************** |
|
* |
|
* Exports - Vault global node handling |
|
* |
|
***/ |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetSystemNodeIncRef () { |
|
RelVaultNode * result = nil; |
|
if (RelVaultNode * player = VaultGetPlayerNodeIncRef()) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_System); |
|
if (RelVaultNode * systemNode = player->GetChildNodeIncRef(templateNode, 1)) |
|
result = systemNode; |
|
templateNode->DecRef(); |
|
player->DecRef(); |
|
} |
|
return result; |
|
} |
|
|
|
//============================================================================ |
|
RelVaultNode * VaultGetGlobalInboxIncRef () { |
|
RelVaultNode * result = nil; |
|
if (RelVaultNode * system = VaultGetSystemNodeIncRef()) { |
|
NetVaultNode * templateNode = NEWZERO(NetVaultNode); |
|
templateNode->IncRef(); |
|
templateNode->SetNodeType(plVault::kNodeType_Folder); |
|
VaultFolderNode folder(templateNode); |
|
folder.SetFolderType(plVault::kGlobalInboxFolder); |
|
if (RelVaultNode * inbox = system->GetChildNodeIncRef(templateNode, 1)) |
|
result = inbox; |
|
templateNode->DecRef(); |
|
system->DecRef(); |
|
} |
|
return result; |
|
} |
|
|
|
#endif // def CLIENT
|
|
|