/** * Performs a depth first traversal of the character tree, summing the container * and inventory contents on the way up the tree */ export default function linkInventory(forest, dependencyGraph){ // The stack of properties to still navigate const stack = [...forest]; // The current containers we are inside of const containerStack = []; while(stack.length){ const top = stack[stack.length - 1]; const prop = top.node; if (prop._computationDetails.inventoryChildrenVisited){ if (prop.type === 'container') containerStack.pop(); stack.pop(); handleProp(prop, containerStack, dependencyGraph); } else { // Add all containers to the stack when we first visit them if (prop.type === 'container'){ containerStack.push(top.node); } // Push children onto the stack and mark this as children are visited stack.push(...top.children); prop._computationDetails.inventoryChildrenVisited = true; } } } function handleProp(prop, containerStack, dependencyGraph){ // Skip props that aren't part of the inventory if (prop.type !== 'item' && prop.type !== 'container') return; // Determine if this property is carried, items are carried by default let carried = prop.type === 'container' ? prop.carried : true; // Item-specific links if (prop.type === 'item'){ if (prop.attuned){ dependencyGraph.addLink('itemsAttuned', prop._id, 'attunedItem'); } if (prop.equipped){ dependencyGraph.addLink('weightEquipment', prop._id, 'equippedItem'); dependencyGraph.addLink('valueEquipment', prop._id, 'equippedItem'); } } // Get the parent container const container = containerStack[containerStack.length - 1]; if (container){ // The container depends on this prop for its contents data dependencyGraph.addLink(container._id, prop._id, 'containerContents'); } else { // There is no parent container, the character totals depend on this prop dependencyGraph.addLink('weightTotal', prop._id, 'inventoryStats'); dependencyGraph.addLink('valueTotal', prop._id, 'inventoryStats'); if (carried){ dependencyGraph.addLink('weightCarried', prop._id, 'inventoryStats'); dependencyGraph.addLink('valueCarried', prop._id, 'inventoryStats'); } } }