forked from OpenWF/SpaceNinjaServer
		
	Closes #1074 Based on what I could find, apparently only rooms need 2 hours to destroy and decos are removed instantly. Reviewed-on: OpenWF/SpaceNinjaServer#1089
		
			
				
	
	
		
			91 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { RequestHandler } from "express";
 | 
						|
import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
 | 
						|
import { logger } from "@/src/utils/logger";
 | 
						|
import { IDojoComponentDatabase } from "@/src/types/guildTypes";
 | 
						|
import { Types } from "mongoose";
 | 
						|
 | 
						|
export const changeDojoRootController: RequestHandler = async (req, res) => {
 | 
						|
    const guild = await getGuildForRequest(req);
 | 
						|
    // At this point, we know that a member of the guild is making this request. Assuming they are allowed to change the root.
 | 
						|
 | 
						|
    const idToNode: Record<string, INode> = {};
 | 
						|
    guild.DojoComponents.forEach(x => {
 | 
						|
        idToNode[x._id.toString()] = {
 | 
						|
            component: x,
 | 
						|
            parent: undefined,
 | 
						|
            children: []
 | 
						|
        };
 | 
						|
    });
 | 
						|
 | 
						|
    let oldRoot: INode | undefined;
 | 
						|
    guild.DojoComponents.forEach(x => {
 | 
						|
        const node = idToNode[x._id.toString()];
 | 
						|
        if (x.pi) {
 | 
						|
            idToNode[x.pi.toString()].children.push(node);
 | 
						|
            node.parent = idToNode[x.pi.toString()];
 | 
						|
        } else {
 | 
						|
            oldRoot = node;
 | 
						|
        }
 | 
						|
    });
 | 
						|
    logger.debug("Old tree:\n" + treeToString(oldRoot!));
 | 
						|
 | 
						|
    const newRoot = idToNode[req.query.newRoot as string];
 | 
						|
    recursivelyTurnParentsIntoChildren(newRoot);
 | 
						|
    newRoot.component.pi = undefined;
 | 
						|
    newRoot.component.op = undefined;
 | 
						|
    newRoot.component.pp = undefined;
 | 
						|
    newRoot.parent = undefined;
 | 
						|
 | 
						|
    // Don't even ask me why this is needed because I don't know either
 | 
						|
    const stack: INode[] = [newRoot];
 | 
						|
    let i = 0;
 | 
						|
    const idMap: Record<string, Types.ObjectId> = {};
 | 
						|
    while (stack.length != 0) {
 | 
						|
        const top = stack.shift()!;
 | 
						|
        idMap[top.component._id.toString()] = new Types.ObjectId(
 | 
						|
            (++i).toString(16).padStart(8, "0") + top.component._id.toString().substr(8)
 | 
						|
        );
 | 
						|
        top.children.forEach(x => stack.push(x));
 | 
						|
    }
 | 
						|
    guild.DojoComponents.forEach(x => {
 | 
						|
        x._id = idMap[x._id.toString()];
 | 
						|
        if (x.pi) {
 | 
						|
            x.pi = idMap[x.pi.toString()];
 | 
						|
        }
 | 
						|
    });
 | 
						|
 | 
						|
    logger.debug("New tree:\n" + treeToString(newRoot));
 | 
						|
 | 
						|
    await guild.save();
 | 
						|
 | 
						|
    res.json(await getDojoClient(guild, 0));
 | 
						|
};
 | 
						|
 | 
						|
interface INode {
 | 
						|
    component: IDojoComponentDatabase;
 | 
						|
    parent: INode | undefined;
 | 
						|
    children: INode[];
 | 
						|
}
 | 
						|
 | 
						|
const treeToString = (root: INode, depth: number = 0): string => {
 | 
						|
    let str = " ".repeat(depth * 4) + root.component.pf + " (" + root.component._id.toString() + ")\n";
 | 
						|
    root.children.forEach(x => {
 | 
						|
        str += treeToString(x, depth + 1);
 | 
						|
    });
 | 
						|
    return str;
 | 
						|
};
 | 
						|
 | 
						|
const recursivelyTurnParentsIntoChildren = (node: INode): void => {
 | 
						|
    if (node.parent!.parent) {
 | 
						|
        recursivelyTurnParentsIntoChildren(node.parent!);
 | 
						|
    }
 | 
						|
 | 
						|
    node.parent!.component.pi = node.component._id;
 | 
						|
    node.parent!.component.op = node.component.pp;
 | 
						|
    node.parent!.component.pp = node.component.op;
 | 
						|
 | 
						|
    node.parent!.parent = node;
 | 
						|
    node.parent!.children.splice(node.parent!.children.indexOf(node), 1);
 | 
						|
    node.children.push(node.parent!);
 | 
						|
};
 |