XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 0 Star 0
UTF-8
import type { RequestHandler } from "express";
import {
    getDojoClient,
    getGuildForRequestEx,
    hasAccessToDojo,
    hasGuildPermission
} from "../../services/guildService.ts";
import { logger } from "../../utils/logger.ts";
import type { IDojoComponentDatabase } from "../../types/guildTypes.ts";
import { eGuildPermission } from "../../types/guildTypes.ts";
import { Types } from "mongoose";
import { getAccountForRequest, getBuildLabel } from "../../services/loginService.ts";
import { getInventory } from "../../services/inventoryService.ts";

export const changeDojoRootController: RequestHandler = async (req, res) => {
    const account = await getAccountForRequest(req);
    const inventory = await getInventory(account._id, "GuildId LevelKeys");
    const guild = await getGuildForRequestEx(req, inventory);
    if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, account._id, eGuildPermission.Architect))) {
        res.json({ DojoRequestStatus: -1 });
        return;
    }

    // Example POST body: {"pivot":[0, 0, -64],"components":"{\"670429301ca0a63848ccc467\":{\"R\":[0,0,0],\"P\":[0,3,32]},\"6704254a1ca0a63848ccb33c\":{\"R\":[0,0,0],\"P\":[0,9.25,-32]},\"670429461ca0a63848ccc731\":{\"R\":[-90,0,0],\"P\":[-47.999992370605,3,16]}}"}
    if (req.body && req.body != "") {
        logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
        throw new Error("dojo reparent operation should not need deco repositioning"); // because we always provide SortId
    }

    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;

    // Set/update SortId in top-to-bottom order
    const stack: INode[] = [newRoot];
    while (stack.length != 0) {
        const top = stack.shift()!;
        top.component.SortId = new Types.ObjectId();
        top.children.forEach(x => stack.push(x));
    }

    logger.debug("New tree:\n" + treeToString(newRoot));

    await guild.save();

    const buildLabel = getBuildLabel(req, account);
    res.json(await getDojoClient(guild, 0, undefined, buildLabel));
};

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!);
};