UNPKG

@jsprismarine/prismarine

Version:

Dedicated Minecraft Bedrock Edition server written in TypeScript

319 lines (316 loc) 37.6 kB
import { CommandDispatcher, CommandSyntaxException } from '@jsprismarine/brigadier'; import { CommandRegisterClassMalformedOrMissingError, GenericNamespaceInvalidError, CommandUnknownCommandError, Error } from '@jsprismarine/errors'; import 'node:fs'; import 'confbox'; import '@jsprismarine/jsbinaryutils'; import 'node:assert'; import 'node:path'; import 'node:process'; import '../block/BlockToolType.es.js'; import '@jsprismarine/bedrock-data'; import Timer from '../utils/Timer.es.js'; import '@jsprismarine/nbt'; import 'zlib'; import '@jsprismarine/math'; import '@jsprismarine/minecraft'; import '../network/packet/AddActorPacket.es.js'; import '../network/packet/MoveActorAbsolutePacket.es.js'; import '../network/packet/RemoveActorPacket.es.js'; import 'node:crypto'; import '../network/packet/ActorFallPacket.es.js'; import '../network/packet/AddItemActorPacket.es.js'; import '../network/packet/AddPlayerPacket.es.js'; import '../network/packet/AnimatePacket.es.js'; import '../network/packet/AvailableActorIdentifiersPacket.es.js'; import '../network/packet/AvailableCommandsPacket.es.js'; import '../network/CompressionProvider.es.js'; import '../network/packet/NetworkSettingsPacket.es.js'; import '../network/packet/BiomeDefinitionListPacket.es.js'; import '../network/packet/ChangeDimensionPacket.es.js'; import '../network/packet/ChunkRadiusUpdatedPacket.es.js'; import '../network/packet/CommandRequestPacket.es.js'; import '../network/packet/ContainerClosePacket.es.js'; import '../network/packet/ContainerOpenPacket.es.js'; import '../network/packet/CreativeContentPacket.es.js'; import '../network/packet/DisconnectPacket.es.js'; import '../network/packet/EmoteListPacket.es.js'; import '../network/packet/InteractPacket.es.js'; import '../network/packet/InventoryContentPacket.es.js'; import '../network/packet/InventoryTransactionPacket.es.js'; import '../network/packet/ItemComponentPacket.es.js'; import '../network/packet/ItemStackRequestPacket.es.js'; import '../network/packet/ItemStackResponsePacket.es.js'; import '../network/packet/LevelChunkPacket.es.js'; import '../network/packet/LevelSoundEventPacket.es.js'; import '../network/packet/LoginPacket.es.js'; import '../network/packet/MobEquipmentPacket.es.js'; import '../network/packet/MovePlayerPacket.es.js'; import '../network/packet/NetworkChunkPublisherUpdatePacket.es.js'; import '../network/packet/OnScreenTextureAnimationPacket.es.js'; import '../network/packet/PacketViolationWarningPacket.es.js'; import '../network/packet/PlaySoundPacket.es.js'; import '../network/packet/PlayStatusPacket.es.js'; import '../network/packet/PlayerActionPacket.es.js'; import '../network/packet/PlayerListPacket.es.js'; import '../network/packet/PlayerSkinPacket.es.js'; import '../network/packet/RequestChunkRadiusPacket.es.js'; import '../network/packet/RequestNetworkSettingsPacket.es.js'; import '../network/packet/ResourcePackResponsePacket.es.js'; import '../network/packet/ResourcePackStackPacket.es.js'; import '../network/packet/ResourcePacksInfoPacket.es.js'; import '../network/packet/ServerSettingsRequestPacket.es.js'; import '../network/packet/SetActorDataPacket.es.js'; import '../network/packet/SetDefaultGametypePacket.es.js'; import '../network/packet/SetHealthPacket.es.js'; import '../network/packet/SetLocalPlayerAsInitializedPacket.es.js'; import '../network/packet/SetPlayerGametypePacket.es.js'; import '../network/packet/SetTimePacket.es.js'; import '../network/packet/ShowProfilePacket.es.js'; import '../network/packet/StartGamePacket.es.js'; import '../network/packet/TextPacket.es.js'; import '../network/packet/TickSyncPacket.es.js'; import '../network/packet/TransferPacket.es.js'; import '../network/packet/UpdateAdventureSettingsPacket.es.js'; import '../network/packet/UpdateAttributesPacket.es.js'; import '../network/packet/UpdateBlockPacket.es.js'; import '../network/packet/WorldEventPacket.es.js'; import * as command_Commands from './Commands.es.js'; import '../config/Config.es.js'; import CommandRegisterEvent from '../events/command/CommandRegisterEvent.es.js'; import '../network/handler/AnimateHandler.es.js'; import '../network/handler/CommandRequestHandler.es.js'; import '../network/handler/ContainerCloseHandler.es.js'; import '../network/handler/EmoteListHandler.es.js'; import '../network/handler/InteractHandler.es.js'; import '../network/handler/InventoryTransactionHandler.es.js'; import '../network/handler/LevelSoundEventHandler.es.js'; import '../network/handler/LoginHandler.es.js'; import '../network/handler/MobEquipmentHandler.es.js'; import '../network/handler/MovePlayerHandler.es.js'; import '../network/handler/PacketViolationWarningHandler.es.js'; import '../network/handler/PlayerActionHandler.es.js'; import '../network/handler/RequestChunkRadiusHandler.es.js'; import '../network/handler/RequestNetworkSettingsHandler.es.js'; import '../network/handler/ResourcePackResponseHandler.es.js'; import '../network/handler/ServerSettingsRequestHandler.es.js'; import '../network/handler/SetDefaultGametypeHandler.es.js'; import '../network/handler/SetLocalPlayerAsInitializedHandler.es.js'; import '../network/handler/SetPlayerGametypeHandler.es.js'; import '../network/handler/TextHandler.es.js'; import '../network/handler/TickSyncHandler.es.js'; import 'node:readline'; import { Chat } from '../chat/Chat.es.js'; import 'heap'; import '../network/packet/UpdateAbilitiesPacket.es.js'; import '@jsprismarine/raknet'; import 'evt'; import 'assert'; class CommandManager { commands = /* @__PURE__ */ new Map(); server; dispatcher; constructor(server) { this.server = server; this.dispatcher = new CommandDispatcher(); } /** * On enable hook. * @group Lifecycle */ async enable() { const timer = new Timer(); const commands = Object.keys(command_Commands).map((key) => command_Commands[key]); await Promise.all( commands.map(async (Command) => { const command = new Command({}); const event = new CommandRegisterEvent(command); await this.server.emit("commandRegister", event); if (event.isCancelled()) return; try { await this.registerCommand(command); } catch (error) { this.server.getLogger().error(error); this.server.getLogger().warn(`Failed to register command ${command.id}`); } }) ); this.server.getLogger().verbose(`Registered §b${this.commands.size}§r commands(s) (took §e${timer.stop()} ms§r)!`); } /** * On disable hook. * @group Lifecycle */ async disable() { this.commands.clear(); } /** * Register a command into command manager by class. * @param {Command} [command] - The command class to register */ async registerCommand(command) { if (!command || !command.id) throw new CommandRegisterClassMalformedOrMissingError(); if (command.id.split(":").length !== 2) throw new GenericNamespaceInvalidError(); if (!command.register) this.server.getLogger().warn(`Command is missing "register" member. This is unsupported!`); else await command.register(this.dispatcher); this.commands.set(command.id, command); await Promise.all( this.server.getSessionManager().getAllPlayers().map(async (player) => player.getNetworkSession().sendAvailableCommands()) ); this.server.getLogger().debug(`Command with id §b${command.id}§r registered`); } /** * Get a registered command by ID. * @remarks This is case-insensitive, works with or without namespace, and also with aliases. * @param {string} id - The command ID. * @returns {Command} The command if found, otherwise undefined. */ getCommand(id) { const command = Array.from(this.commands.values()).find( (command2) => ( // Check if it matches ID without namespace. command2.name === id || // Check if it's an alias. command2.aliases?.includes(id) || // Last check if it's the whole ID (this is uncommon so, // it's last to avoid the most checks). command2.id === id ) ); if (!command) throw new CommandUnknownCommandError(); return command; } /** * Get all enabled commands. */ getCommands() { return this.commands; } /** * Get a list of all command variants. * * @remarks * This is EXCLUDING legacy commands. */ getCommandsList() { const parseNode = (node) => { if (node.getChildrenCount() <= 0) { return [ { item: node.getType(), children: [] } ]; } const res2 = Array.from(node.getChildren()).map((node2) => parseNode(node2)).reverse(); return [ node.getCommand() ? { item: node.getType(), children: [] } : void 0, ...res2.map((children) => ({ item: node.getType(), children: [...children] })) ].filter((a) => a); }; const traverse = (node, path = [], result = []) => { if (!node.children.length) result.push(path.concat(node.item)); for (const child of node.children) traverse(child, path.concat(node.item), result); return result; }; const res = Array.from(this.server.getCommandManager().getDispatcher().getRoot().getChildren()).flatMap((command) => { const branches = []; if (command.getCommand()) branches.push([]); Array.from(command.getChildren()).forEach((node) => { const parsed = parseNode(node); parsed.forEach((branch) => { branches.push(traverse(branch)); }); }); return branches.map((branch) => [command.getName(), command, branch]); }).filter((a) => a); res.toString = () => { return `${this.getCommandsList().map((item) => { if (!item[2].length) return `/${item[0]}`; return item[2].map( (entries) => `/${item[0]} ${entries.flat(Number.POSITIVE_INFINITY).map((argument) => argument.getReadableType?.() ?? argument.constructor.name).join(" ")}` ).join(` `); }).join("\n")}`; }; return res; } /** * Get dispatcher */ getDispatcher() { return this.dispatcher; } /** * Dispatches a command and executes them. * * @param sender - the player/console who executed the command * @param target - the Player/entity/console who should execute the command * @param input - the command input including arguments */ async dispatchCommand(sender, target, input = "") { try { if (input.startsWith("/")) input = input.slice(1); const parsed = this.dispatcher.parse(input.trim(), target); const id = parsed.getReader().getString().split(" ")[0]; if (!sender.isConsole()) { this.server.getLogger().debug( `Entity with §b${sender.getRuntimeId()}§r is dispatching command: ${input} (id: ${id})`, "CommandManager/dispatchCommand" ); } const command = this.getCommand(id); if (!this.server.getPermissionManager().can(sender).execute(command.permission)) { await sender.sendMessage( "§cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error." ); return; } let res = []; if (command.name !== id) { await this.dispatchCommand(sender, target, input.replace(id, command.name)); return; } res = await Promise.all(this.dispatcher.execute(parsed)); const feedback = sender.getWorld().getGameruleManager().getGamerule("sendCommandFeedback"); if (!feedback) return; await Promise.all( res.map(async (res2) => { const chat = new Chat({ sender: this.server.getConsole(), message: `§o§7[${target.getName()}: ${res2 ?? `issued server command: /${input}`}]§r`, channel: "*.ops" }); await this.server.getChatManager().send(chat); }) ); } catch (error) { switch (true) { case error instanceof CommandSyntaxException: await sender.sendMessage(`§c${error.getMessage()}`); return; case error instanceof CommandUnknownCommandError: await sender.sendMessage(`§cUnknown command. Type "/help" for help.`); return; case error instanceof Error: await sender.sendMessage(`§c${error.message}`); return; default: this.server.getLogger().error(error); break; } await sender.sendMessage(`§c${error}`); this.server.getLogger().debug( `Player ${target.getFormattedUsername()} tried to execute ${input}, but it failed with the error: ${error}`, "CommandManager/dispatchCommand" ); this.server.getLogger().error(error); } } } export { CommandManager }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tbWFuZE1hbmFnZXIuZXMuanMiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kL0NvbW1hbmRNYW5hZ2VyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgQXJndW1lbnRDb21tYW5kTm9kZSB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvYnJpZ2FkaWVyJztcbmltcG9ydCB7IENvbW1hbmREaXNwYXRjaGVyLCBDb21tYW5kU3ludGF4RXhjZXB0aW9uIH0gZnJvbSAnQGpzcHJpc21hcmluZS9icmlnYWRpZXInO1xuaW1wb3J0IHtcbiAgICBDb21tYW5kUmVnaXN0ZXJDbGFzc01hbGZvcm1lZE9yTWlzc2luZ0Vycm9yLFxuICAgIENvbW1hbmRVbmtub3duQ29tbWFuZEVycm9yLFxuICAgIEVycm9yLFxuICAgIEdlbmVyaWNOYW1lc3BhY2VJbnZhbGlkRXJyb3Jcbn0gZnJvbSAnQGpzcHJpc21hcmluZS9lcnJvcnMnO1xuXG5pbXBvcnQgdHlwZSB7IENvbW1hbmQsIENvbW1hbmRBcmd1bWVudCwgRW50aXR5LCBQbGF5ZXIsIFNlcnZlciwgU2VydmljZSB9IGZyb20gJy4uLyc7XG5pbXBvcnQgeyBDaGF0IH0gZnJvbSAnLi4vJztcbmltcG9ydCBDb21tYW5kUmVnaXN0ZXJFdmVudCBmcm9tICcuLi9ldmVudHMvY29tbWFuZC9Db21tYW5kUmVnaXN0ZXJFdmVudCc7XG5pbXBvcnQgVGltZXIgZnJvbSAnLi4vdXRpbHMvVGltZXInO1xuaW1wb3J0IHsgQ29tbWFuZHMgfSBmcm9tICcuLyc7XG5cbmV4cG9ydCBjbGFzcyBDb21tYW5kTWFuYWdlciBpbXBsZW1lbnRzIFNlcnZpY2Uge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY29tbWFuZHM6IE1hcDxzdHJpbmcsIENvbW1hbmQ+ID0gbmV3IE1hcCgpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgc2VydmVyOiBTZXJ2ZXI7XG4gICAgcHJpdmF0ZSBkaXNwYXRjaGVyITogQ29tbWFuZERpc3BhdGNoZXI8UGxheWVyPjtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihzZXJ2ZXI6IFNlcnZlcikge1xuICAgICAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyID0gbmV3IENvbW1hbmREaXNwYXRjaGVyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT24gZW5hYmxlIGhvb2suXG4gICAgICogQGdyb3VwIExpZmVjeWNsZVxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBlbmFibGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHRpbWVyID0gbmV3IFRpbWVyKCk7XG5cbiAgICAgICAgY29uc3QgY29tbWFuZHMgPSBPYmplY3Qua2V5cyhDb21tYW5kcykubWFwKChrZXkpID0+IChDb21tYW5kcyBhcyBhbnkpW2tleV0gYXMgdHlwZW9mIENvbW1hbmQpO1xuXG4gICAgICAgIC8vIFJlZ2lzdGVyIGpzcHJpc21hcmluZSBjb21tYW5kc1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgIGNvbW1hbmRzLm1hcChhc3luYyAoQ29tbWFuZCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbW1hbmQ6IENvbW1hbmQgPSBuZXcgQ29tbWFuZCh7fSBhcyBhbnkpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnQgPSBuZXcgQ29tbWFuZFJlZ2lzdGVyRXZlbnQoY29tbWFuZCk7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXJ2ZXIuZW1pdCgnY29tbWFuZFJlZ2lzdGVyJywgZXZlbnQpO1xuICAgICAgICAgICAgICAgIGlmIChldmVudC5pc0NhbmNlbGxlZCgpKSByZXR1cm47XG5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyQ29tbWFuZChjb21tYW5kKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLndhcm4oYEZhaWxlZCB0byByZWdpc3RlciBjb21tYW5kICR7Y29tbWFuZC5pZH1gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuc2VydmVyXG4gICAgICAgICAgICAuZ2V0TG9nZ2VyKClcbiAgICAgICAgICAgIC52ZXJib3NlKGBSZWdpc3RlcmVkIMKnYiR7dGhpcy5jb21tYW5kcy5zaXplfcKnciBjb21tYW5kcyhzKSAodG9vayDCp2Uke3RpbWVyLnN0b3AoKX0gbXPCp3IpIWApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9uIGRpc2FibGUgaG9vay5cbiAgICAgKiBAZ3JvdXAgTGlmZWN5Y2xlXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGRpc2FibGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMuY29tbWFuZHMuY2xlYXIoKTtcbiAgICAgICAgLy8gVE9ETzogY2xlYXIgY29tbWFuZHMgaW4gZGlzcGF0Y2hlclxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIGEgY29tbWFuZCBpbnRvIGNvbW1hbmQgbWFuYWdlciBieSBjbGFzcy5cbiAgICAgKiBAcGFyYW0ge0NvbW1hbmR9IFtjb21tYW5kXSAtIFRoZSBjb21tYW5kIGNsYXNzIHRvIHJlZ2lzdGVyXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHJlZ2lzdGVyQ29tbWFuZChjb21tYW5kPzogQ29tbWFuZCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoIWNvbW1hbmQgfHwgIWNvbW1hbmQuaWQpIHRocm93IG5ldyBDb21tYW5kUmVnaXN0ZXJDbGFzc01hbGZvcm1lZE9yTWlzc2luZ0Vycm9yKCk7XG4gICAgICAgIGlmIChjb21tYW5kLmlkLnNwbGl0KCc6JykubGVuZ3RoICE9PSAyKSB0aHJvdyBuZXcgR2VuZXJpY05hbWVzcGFjZUludmFsaWRFcnJvcigpO1xuXG4gICAgICAgIGlmICghKGNvbW1hbmQgYXMgYW55KS5yZWdpc3RlcilcbiAgICAgICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLndhcm4oYENvbW1hbmQgaXMgbWlzc2luZyBcInJlZ2lzdGVyXCIgbWVtYmVyLiBUaGlzIGlzIHVuc3VwcG9ydGVkIWApO1xuICAgICAgICBlbHNlIGF3YWl0IGNvbW1hbmQucmVnaXN0ZXIodGhpcy5kaXNwYXRjaGVyKTtcbiAgICAgICAgdGhpcy5jb21tYW5kcy5zZXQoY29tbWFuZC5pZCwgY29tbWFuZCk7XG5cbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICB0aGlzLnNlcnZlclxuICAgICAgICAgICAgICAgIC5nZXRTZXNzaW9uTWFuYWdlcigpXG4gICAgICAgICAgICAgICAgLmdldEFsbFBsYXllcnMoKVxuICAgICAgICAgICAgICAgIC5tYXAoYXN5bmMgKHBsYXllcikgPT4gcGxheWVyLmdldE5ldHdvcmtTZXNzaW9uKCkuc2VuZEF2YWlsYWJsZUNvbW1hbmRzKCkpXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkuZGVidWcoYENvbW1hbmQgd2l0aCBpZCDCp2Ike2NvbW1hbmQuaWR9wqdyIHJlZ2lzdGVyZWRgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSByZWdpc3RlcmVkIGNvbW1hbmQgYnkgSUQuXG4gICAgICogQHJlbWFya3MgVGhpcyBpcyBjYXNlLWluc2Vuc2l0aXZlLCB3b3JrcyB3aXRoIG9yIHdpdGhvdXQgbmFtZXNwYWNlLCBhbmQgYWxzbyB3aXRoIGFsaWFzZXMuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGNvbW1hbmQgSUQuXG4gICAgICogQHJldHVybnMge0NvbW1hbmR9IFRoZSBjb21tYW5kIGlmIGZvdW5kLCBvdGhlcndpc2UgdW5kZWZpbmVkLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRDb21tYW5kKGlkOiBzdHJpbmcpOiBDb21tYW5kIHtcbiAgICAgICAgY29uc3QgY29tbWFuZCA9IEFycmF5LmZyb20odGhpcy5jb21tYW5kcy52YWx1ZXMoKSkuZmluZChcbiAgICAgICAgICAgIChjb21tYW5kKSA9PlxuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGl0IG1hdGNoZXMgSUQgd2l0aG91dCBuYW1lc3BhY2UuXG4gICAgICAgICAgICAgICAgY29tbWFuZC5uYW1lID09PSBpZCB8fFxuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGl0J3MgYW4gYWxpYXMuXG4gICAgICAgICAgICAgICAgY29tbWFuZC5hbGlhc2VzPy5pbmNsdWRlcyhpZCkgfHxcbiAgICAgICAgICAgICAgICAvLyBMYXN0IGNoZWNrIGlmIGl0J3MgdGhlIHdob2xlIElEICh0aGlzIGlzIHVuY29tbW9uIHNvLFxuICAgICAgICAgICAgICAgIC8vICBpdCdzIGxhc3QgdG8gYXZvaWQgdGhlIG1vc3QgY2hlY2tzKS5cbiAgICAgICAgICAgICAgICBjb21tYW5kLmlkID09PSBpZFxuICAgICAgICApO1xuXG4gICAgICAgIGlmICghY29tbWFuZCkgdGhyb3cgbmV3IENvbW1hbmRVbmtub3duQ29tbWFuZEVycm9yKCk7XG4gICAgICAgIHJldHVybiBjb21tYW5kO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgZW5hYmxlZCBjb21tYW5kcy5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0Q29tbWFuZHMoKTogTWFwPHN0cmluZywgQ29tbWFuZD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jb21tYW5kcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBsaXN0IG9mIGFsbCBjb21tYW5kIHZhcmlhbnRzLlxuICAgICAqXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBUaGlzIGlzIEVYQ0xVRElORyBsZWdhY3kgY29tbWFuZHMuXG4gICAgICovXG4gICAgcHVibGljIGdldENvbW1hbmRzTGlzdCgpOiBBcnJheTxbc3RyaW5nLCAvKiBDb21tYW5kTm9kZTxQbGF5ZXI+ICovIGFueSwgQ29tbWFuZEFyZ3VtZW50W11bXV0+IHtcbiAgICAgICAgY29uc3QgcGFyc2VOb2RlID0gKG5vZGU6IC8qIENvbW1hbmROb2RlPFBsYXllcj4gKi8gYW55KTogYW55W10gPT4ge1xuICAgICAgICAgICAgaWYgKG5vZGUuZ2V0Q2hpbGRyZW5Db3VudCgpIDw9IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpdGVtOiAobm9kZSBhcyBBcmd1bWVudENvbW1hbmROb2RlPGFueSwgYW55PikuZ2V0VHlwZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCByZXMgPSBBcnJheS5mcm9tKG5vZGUuZ2V0Q2hpbGRyZW4oKSlcbiAgICAgICAgICAgICAgICAubWFwKChub2RlKSA9PiBwYXJzZU5vZGUobm9kZSkpXG4gICAgICAgICAgICAgICAgLnJldmVyc2UoKTtcblxuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICBub2RlLmdldENvbW1hbmQoKVxuICAgICAgICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbTogKG5vZGUgYXMgQXJndW1lbnRDb21tYW5kTm9kZTxhbnksIGFueT4pLmdldFR5cGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAuLi5yZXMubWFwKChjaGlsZHJlbjogYW55KSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICBpdGVtOiAobm9kZSBhcyBBcmd1bWVudENvbW1hbmROb2RlPGFueSwgYW55PikuZ2V0VHlwZSgpLFxuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogWy4uLmNoaWxkcmVuXVxuICAgICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgXS5maWx0ZXIoKGEpID0+IGEpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHRyYXZlcnNlID0gKG5vZGU6IGFueSwgcGF0aDogYW55W10gPSBbXSwgcmVzdWx0OiBhbnlbXSA9IFtdKSA9PiB7XG4gICAgICAgICAgICBpZiAoIW5vZGUuY2hpbGRyZW4ubGVuZ3RoKSByZXN1bHQucHVzaChwYXRoLmNvbmNhdChub2RlLml0ZW0pKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgY2hpbGQgb2Ygbm9kZS5jaGlsZHJlbikgdHJhdmVyc2UoY2hpbGQsIHBhdGguY29uY2F0KG5vZGUuaXRlbSksIHJlc3VsdCk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHJlcyA9IEFycmF5LmZyb20odGhpcy5zZXJ2ZXIuZ2V0Q29tbWFuZE1hbmFnZXIoKS5nZXREaXNwYXRjaGVyKCkuZ2V0Um9vdCgpLmdldENoaWxkcmVuKCkpXG4gICAgICAgICAgICAuZmxhdE1hcCgoY29tbWFuZCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJyYW5jaGVzOiBhbnlbXSA9IFtdO1xuICAgICAgICAgICAgICAgIGlmIChjb21tYW5kLmdldENvbW1hbmQoKSkgYnJhbmNoZXMucHVzaChbXSk7XG5cbiAgICAgICAgICAgICAgICBBcnJheS5mcm9tKGNvbW1hbmQuZ2V0Q2hpbGRyZW4oKSkuZm9yRWFjaCgobm9kZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZU5vZGUobm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIHBhcnNlZC5mb3JFYWNoKChicmFuY2gpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyYW5jaGVzLnB1c2godHJhdmVyc2UoYnJhbmNoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGJyYW5jaGVzLm1hcCgoYnJhbmNoKSA9PiBbY29tbWFuZC5nZXROYW1lKCksIGNvbW1hbmQsIGJyYW5jaF0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5maWx0ZXIoKGEpID0+IGEgYXMgYW55KTtcblxuICAgICAgICByZXMudG9TdHJpbmcgPSAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gYCR7dGhpcy5nZXRDb21tYW5kc0xpc3QoKVxuICAgICAgICAgICAgICAgIC5tYXAoKGl0ZW0pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpdGVtWzJdLmxlbmd0aCkgcmV0dXJuIGAvJHtpdGVtWzBdfWA7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpdGVtWzJdXG4gICAgICAgICAgICAgICAgICAgICAgICAubWFwKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChlbnRyaWVzKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgLyR7aXRlbVswXX0gJHtlbnRyaWVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZmxhdChOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAubWFwKChhcmd1bWVudDogYW55KSA9PiBhcmd1bWVudC5nZXRSZWFkYWJsZVR5cGU/LigpID8/IGFyZ3VtZW50LmNvbnN0cnVjdG9yLm5hbWUpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuam9pbignICcpfWBcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5qb2luKGBcXG5gKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5qb2luKCdcXG4nKX1gO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gcmVzIGFzIGFueTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgZGlzcGF0Y2hlclxuICAgICAqL1xuICAgIHB1YmxpYyBnZXREaXNwYXRjaGVyKCk6IENvbW1hbmREaXNwYXRjaGVyPFBsYXllcj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5kaXNwYXRjaGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERpc3BhdGNoZXMgYSBjb21tYW5kIGFuZCBleGVjdXRlcyB0aGVtLlxuICAgICAqXG4gICAgICogQHBhcmFtIHNlbmRlciAtIHRoZSBwbGF5ZXIvY29uc29sZSB3aG8gZXhlY3V0ZWQgdGhlIGNvbW1hbmRcbiAgICAgKiBAcGFyYW0gdGFyZ2V0IC0gdGhlIFBsYXllci9lbnRpdHkvY29uc29sZSB3aG8gc2hvdWxkIGV4ZWN1dGUgdGhlIGNvbW1hbmRcbiAgICAgKiBAcGFyYW0gaW5wdXQgLSB0aGUgY29tbWFuZCBpbnB1dCBpbmNsdWRpbmcgYXJndW1lbnRzXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGRpc3BhdGNoQ29tbWFuZChzZW5kZXI6IFBsYXllciwgdGFyZ2V0OiBFbnRpdHkgfCBQbGF5ZXIsIGlucHV0ID0gJycpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChpbnB1dC5zdGFydHNXaXRoKCcvJykpIGlucHV0ID0gaW5wdXQuc2xpY2UoMSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZGlzcGF0Y2hlci5wYXJzZShpbnB1dC50cmltKCksIHRhcmdldCBhcyBQbGF5ZXIpO1xuICAgICAgICAgICAgY29uc3QgaWQgPSBwYXJzZWQuZ2V0UmVhZGVyKCkuZ2V0U3RyaW5nKCkuc3BsaXQoJyAnKVswXSE7XG5cbiAgICAgICAgICAgIGlmICghc2VuZGVyLmlzQ29uc29sZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgLmdldExvZ2dlcigpXG4gICAgICAgICAgICAgICAgICAgIC5kZWJ1ZyhcbiAgICAgICAgICAgICAgICAgICAgICAgIGBFbnRpdHkgd2l0aCDCp2Ike3NlbmRlci5nZXRSdW50aW1lSWQoKX3Cp3IgaXMgZGlzcGF0Y2hpbmcgY29tbWFuZDogJHtpbnB1dH0gKGlkOiAke2lkfSlgLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ0NvbW1hbmRNYW5hZ2VyL2Rpc3BhdGNoQ29tbWFuZCdcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gR2V0IGNvbW1hbmQgZnJvbSBwYXJzZWQgc3RyaW5nLlxuICAgICAgICAgICAgY29uc3QgY29tbWFuZCA9IHRoaXMuZ2V0Q29tbWFuZChpZCk7XG5cbiAgICAgICAgICAgIC8vIFZhbGlkYXRlIHBlcm1pc3Npb25zLlxuICAgICAgICAgICAgaWYgKCF0aGlzLnNlcnZlci5nZXRQZXJtaXNzaW9uTWFuYWdlcigpLmNhbihzZW5kZXIpLmV4ZWN1dGUoY29tbWFuZC5wZXJtaXNzaW9uKSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHNlbmRlci5zZW5kTWVzc2FnZShcbiAgICAgICAgICAgICAgICAgICAgXCLCp2NJJ20gc29ycnksIGJ1dCB5b3UgZG8gbm90IGhhdmUgcGVybWlzc2lvbiB0byBwZXJmb3JtIHRoaXMgY29tbWFuZC4gXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJ1BsZWFzZSBjb250YWN0IHRoZSBzZXJ2ZXIgYWRtaW5pc3RyYXRvcnMgaWYgeW91IGJlbGlldmUgdGhhdCB0aGlzIGlzIGluIGVycm9yLidcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHJlczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgICAgIC8vIEhhbmRsZSBhbGlhc2VzIGFuZCBJRHMuXG4gICAgICAgICAgICBpZiAoY29tbWFuZC5uYW1lICE9PSBpZCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2hDb21tYW5kKHNlbmRlciwgdGFyZ2V0LCBpbnB1dC5yZXBsYWNlKGlkLCBjb21tYW5kLm5hbWUpKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJlcyA9IGF3YWl0IFByb21pc2UuYWxsKHRoaXMuZGlzcGF0Y2hlci5leGVjdXRlKHBhcnNlZCkpO1xuXG4gICAgICAgICAgICBjb25zdCBmZWVkYmFjayA9IChzZW5kZXIgYXMgYW55IGFzIEVudGl0eSlcbiAgICAgICAgICAgICAgICAuZ2V0V29ybGQoKVxuICAgICAgICAgICAgICAgIC5nZXRHYW1lcnVsZU1hbmFnZXIoKVxuICAgICAgICAgICAgICAgIC5nZXRHYW1lcnVsZSgnc2VuZENvbW1hbmRGZWVkYmFjaycpO1xuXG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgd2UgZG9uJ3Qgc2VuZCBmZWVkYmFjayBpZiBzZW5kQ29tbWFuZEZlZWRiYWNrIGlzIHNldCB0byBmYWxzZVxuICAgICAgICAgICAgaWYgKCFmZWVkYmFjaykgcmV0dXJuO1xuXG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgICByZXMubWFwKGFzeW5jIChyZXM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGF0ID0gbmV3IENoYXQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZGVyOiB0aGlzLnNlcnZlci5nZXRDb25zb2xlKCkhLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogYMKnb8KnN1ske3RhcmdldC5nZXROYW1lKCl9OiAke3JlcyA/PyBgaXNzdWVkIHNlcnZlciBjb21tYW5kOiAvJHtpbnB1dH1gfV3Cp3JgLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2hhbm5lbDogJyoub3BzJ1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBzaG91bGQgdGhpcyBiZSBicm9hZGNhc3RlZCB0byB0aGUgZXhlY3V0ZXI/XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VydmVyLmdldENoYXRNYW5hZ2VyKCkuc2VuZChjaGF0KTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgICAgIHN3aXRjaCAodHJ1ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgZXJyb3IgaW5zdGFuY2VvZiBDb21tYW5kU3ludGF4RXhjZXB0aW9uOlxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBzZW5kZXIuc2VuZE1lc3NhZ2UoYMKnYyR7ZXJyb3IuZ2V0TWVzc2FnZSgpfWApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgY2FzZSBlcnJvciBpbnN0YW5jZW9mIENvbW1hbmRVbmtub3duQ29tbWFuZEVycm9yOlxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBzZW5kZXIuc2VuZE1lc3NhZ2UoYMKnY1Vua25vd24gY29tbWFuZC4gVHlwZSBcIi9oZWxwXCIgZm9yIGhlbHAuYCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICBjYXNlIGVycm9yIGluc3RhbmNlb2YgRXJyb3I6XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHNlbmRlci5zZW5kTWVzc2FnZShgwqdjJHtlcnJvci5tZXNzYWdlfWApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYXdhaXQgc2VuZGVyLnNlbmRNZXNzYWdlKGDCp2Mke2Vycm9yfWApO1xuICAgICAgICAgICAgdGhpcy5zZXJ2ZXJcbiAgICAgICAgICAgICAgICAuZ2V0TG9nZ2VyKClcbiAgICAgICAgICAgICAgICAuZGVidWcoXG4gICAgICAgICAgICAgICAgICAgIGBQbGF5ZXIgJHt0YXJnZXQuZ2V0Rm9ybWF0dGVkVXNlcm5hbWUoKX0gdHJpZWQgdG8gZXhlY3V0ZSAke2lucHV0fSwgYnV0IGl0IGZhaWxlZCB3aXRoIHRoZSBlcnJvcjogJHtlcnJvcn1gLFxuICAgICAgICAgICAgICAgICAgICAnQ29tbWFuZE1hbmFnZXIvZGlzcGF0Y2hDb21tYW5kJ1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS5lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXSwibmFtZXMiOlsiQ29tbWFuZHMiLCJjb21tYW5kIiwicmVzIiwibm9kZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZU8sTUFBTSxjQUFrQyxDQUFBO0FBQUEsRUFDMUIsUUFBQSx1QkFBcUMsR0FBSSxFQUFBO0FBQUEsRUFDekMsTUFBQTtBQUFBLEVBQ1QsVUFBQTtBQUFBLEVBRUQsWUFBWSxNQUFnQixFQUFBO0FBQy9CLElBQUEsSUFBQSxDQUFLLE1BQVMsR0FBQSxNQUFBO0FBQ2QsSUFBSyxJQUFBLENBQUEsVUFBQSxHQUFhLElBQUksaUJBQWtCLEVBQUE7QUFBQTtBQUM1QztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBTUEsTUFBYSxNQUF3QixHQUFBO0FBQ2pDLElBQU0sTUFBQSxLQUFBLEdBQVEsSUFBSSxLQUFN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