2025-02-12 14:06:48 -08:00
import { RequestHandler } from "express" ;
2025-03-14 07:09:28 -07:00
import { getDojoClient , getGuildForRequestEx , hasAccessToDojo , hasGuildPermission } from "@/src/services/guildService" ;
2025-02-12 14:06:48 -08:00
import { logger } from "@/src/utils/logger" ;
2025-03-14 07:09:28 -07:00
import { GuildPermission , IDojoComponentDatabase } from "@/src/types/guildTypes" ;
2025-02-12 14:06:48 -08:00
import { Types } from "mongoose" ;
2025-03-14 07:09:28 -07:00
import { getAccountIdForRequest } from "@/src/services/loginService" ;
import { getInventory } from "@/src/services/inventoryService" ;
2025-02-12 14:06:48 -08:00
export const changeDojoRootController : RequestHandler = async ( req , res ) = > {
2025-03-14 07:09:28 -07:00
const accountId = await getAccountIdForRequest ( req ) ;
const inventory = await getInventory ( accountId , "GuildId LevelKeys" ) ;
const guild = await getGuildForRequestEx ( req , inventory ) ;
if ( ! hasAccessToDojo ( inventory ) || ! ( await hasGuildPermission ( guild , accountId , GuildPermission . Architect ) ) ) {
res . json ( { DojoRequestStatus : - 1 } ) ;
return ;
}
2025-02-12 14:06:48 -08:00
2025-04-09 15:41:21 +02:00
// 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 ) {
2025-04-09 15:49:49 +02:00
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
2025-04-09 15:41:21 +02:00
}
2025-02-12 14:06:48 -08:00
const idToNode : Record < string , INode > = { } ;
2025-03-03 05:46:16 -08:00
guild . DojoComponents . forEach ( x = > {
2025-02-12 14:06:48 -08:00
idToNode [ x . _id . toString ( ) ] = {
component : x ,
parent : undefined ,
children : [ ]
} ;
} ) ;
let oldRoot : INode | undefined ;
2025-03-03 05:46:16 -08:00
guild . DojoComponents . forEach ( x = > {
2025-02-12 14:06:48 -08:00
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 ;
2025-04-09 15:41:21 +02:00
// Set/update SortId in top-to-bottom order
2025-02-12 14:06:48 -08:00
const stack : INode [ ] = [ newRoot ] ;
while ( stack . length != 0 ) {
const top = stack . shift ( ) ! ;
2025-04-09 15:41:21 +02:00
top . component . SortId = new Types . ObjectId ( ) ;
2025-02-12 14:06:48 -08:00
top . children . forEach ( x = > stack . push ( x ) ) ;
}
logger . debug ( "New tree:\n" + treeToString ( newRoot ) ) ;
await guild . save ( ) ;
2025-03-06 07:19:01 -08:00
res . json ( await getDojoClient ( guild , 0 ) ) ;
2025-02-12 14:06:48 -08:00
} ;
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 ! ) ;
} ;