@jsprismarine/prismarine
Version:
Dedicated Minecraft Bedrock Edition server written in TypeScript
188 lines (187 loc) • 27.9 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
require("../_virtual/_rolldown/runtime.cjs.cjs");
const require_utils_Timer = require("../utils/Timer.cjs.cjs");
const require_events_command_CommandRegisterEvent = require("../events/command/CommandRegisterEvent.cjs.cjs");
const require_chat_Chat = require("../chat/Chat.cjs.cjs");
const require_command_Commands = require("./Commands.cjs.cjs");
let _jsprismarine_errors = require("@jsprismarine/errors");
let _jsprismarine_brigadier = require("@jsprismarine/brigadier");
//#region src/command/CommandManager.ts
var CommandManager = class {
commands = /* @__PURE__ */ new Map();
server;
dispatcher;
constructor(server) {
this.server = server;
this.dispatcher = new _jsprismarine_brigadier.CommandDispatcher();
}
/**
* On enable hook.
* @group Lifecycle
*/
async enable() {
const timer = new require_utils_Timer.default();
const commands = Object.keys(require_command_Commands.Commands_exports).map((key) => require_command_Commands.Commands_exports[key]);
await Promise.all(commands.map(async (Command) => {
const command = new Command({});
const event = new require_events_command_CommandRegisterEvent.default(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 _jsprismarine_errors.CommandRegisterClassMalformedOrMissingError();
if (command.id.split(":").length !== 2) throw new _jsprismarine_errors.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((command) => command.name === id || command.aliases?.includes(id) || command.id === id);
if (!command) throw new _jsprismarine_errors.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 res = Array.from(node.getChildren()).map((node) => parseNode(node)).reverse();
return [node.getCommand() ? {
item: node.getType(),
children: []
} : void 0, ...res.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) => {
parseNode(node).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(`\n`);
}).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));
if (!sender.getWorld().getGameruleManager().getGamerule("sendCommandFeedback")) return;
await Promise.all(res.map(async (res) => {
const chat = new require_chat_Chat.Chat({
sender: this.server.getConsole(),
message: `§o§7[${target.getName()}: ${res ?? `issued server command: /${input}`}]§r`,
channel: "*.ops"
});
await this.server.getChatManager().send(chat);
}));
} catch (error) {
switch (true) {
case error instanceof _jsprismarine_brigadier.CommandSyntaxException:
await sender.sendMessage(`§c${error.getMessage()}`);
return;
case error instanceof _jsprismarine_errors.CommandUnknownCommandError:
await sender.sendMessage(`§cUnknown command. Type "/help" for help.`);
return;
case error instanceof _jsprismarine_errors.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);
}
}
};
//#endregion
exports.CommandManager = CommandManager;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tbWFuZE1hbmFnZXIuY2pzLmNqcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZC9Db21tYW5kTWFuYWdlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IEFyZ3VtZW50Q29tbWFuZE5vZGUgfSBmcm9tICdAanNwcmlzbWFyaW5lL2JyaWdhZGllcic7XG5pbXBvcnQgeyBDb21tYW5kRGlzcGF0Y2hlciwgQ29tbWFuZFN5bnRheEV4Y2VwdGlvbiB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvYnJpZ2FkaWVyJztcbmltcG9ydCB7XG4gICAgQ29tbWFuZFJlZ2lzdGVyQ2xhc3NNYWxmb3JtZWRPck1pc3NpbmdFcnJvcixcbiAgICBDb21tYW5kVW5rbm93bkNvbW1hbmRFcnJvcixcbiAgICBFcnJvcixcbiAgICBHZW5lcmljTmFtZXNwYWNlSW52YWxpZEVycm9yXG59IGZyb20gJ0Bqc3ByaXNtYXJpbmUvZXJyb3JzJztcblxuaW1wb3J0IHR5cGUgeyBDb21tYW5kLCBDb21tYW5kQXJndW1lbnQsIEVudGl0eSwgUGxheWVyLCBTZXJ2ZXIsIFNlcnZpY2UgfSBmcm9tICcuLi8nO1xuaW1wb3J0IHsgQ2hhdCB9IGZyb20gJy4uLyc7XG5pbXBvcnQgQ29tbWFuZFJlZ2lzdGVyRXZlbnQgZnJvbSAnLi4vZXZlbnRzL2NvbW1hbmQvQ29tbWFuZFJlZ2lzdGVyRXZlbnQnO1xuaW1wb3J0IFRpbWVyIGZyb20gJy4uL3V0aWxzL1RpbWVyJztcbmltcG9ydCB7IENvbW1hbmRzIH0gZnJvbSAnLi8nO1xuXG5leHBvcnQgY2xhc3MgQ29tbWFuZE1hbmFnZXIgaW1wbGVtZW50cyBTZXJ2aWNlIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNvbW1hbmRzOiBNYXA8c3RyaW5nLCBDb21tYW5kPiA9IG5ldyBNYXAoKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNlcnZlcjogU2VydmVyO1xuICAgIHByaXZhdGUgZGlzcGF0Y2hlciE6IENvbW1hbmREaXNwYXRjaGVyPFBsYXllcj47XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3Ioc2VydmVyOiBTZXJ2ZXIpIHtcbiAgICAgICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlciA9IG5ldyBDb21tYW5kRGlzcGF0Y2hlcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9uIGVuYWJsZSBob29rLlxuICAgICAqIEBncm91cCBMaWZlY3ljbGVcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgZW5hYmxlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCB0aW1lciA9IG5ldyBUaW1lcigpO1xuXG4gICAgICAgIGNvbnN0IGNvbW1hbmRzID0gT2JqZWN0LmtleXMoQ29tbWFuZHMpLm1hcCgoa2V5KSA9PiAoQ29tbWFuZHMgYXMgYW55KVtrZXldIGFzIHR5cGVvZiBDb21tYW5kKTtcblxuICAgICAgICAvLyBSZWdpc3RlciBqc3ByaXNtYXJpbmUgY29tbWFuZHNcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICBjb21tYW5kcy5tYXAoYXN5bmMgKENvbW1hbmQpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb21tYW5kOiBDb21tYW5kID0gbmV3IENvbW1hbmQoe30gYXMgYW55KTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50ID0gbmV3IENvbW1hbmRSZWdpc3RlckV2ZW50KGNvbW1hbmQpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VydmVyLmVtaXQoJ2NvbW1hbmRSZWdpc3RlcicsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnQuaXNDYW5jZWxsZWQoKSkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5yZWdpc3RlckNvbW1hbmQoY29tbWFuZCk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS53YXJuKGBGYWlsZWQgdG8gcmVnaXN0ZXIgY29tbWFuZCAke2NvbW1hbmQuaWR9YCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLnNlcnZlclxuICAgICAgICAgICAgLmdldExvZ2dlcigpXG4gICAgICAgICAgICAudmVyYm9zZShgUmVnaXN0ZXJlZCDCp2Ike3RoaXMuY29tbWFuZHMuc2l6ZX3Cp3IgY29tbWFuZHMocykgKHRvb2sgwqdlJHt0aW1lci5zdG9wKCl9IG1zwqdyKSFgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBPbiBkaXNhYmxlIGhvb2suXG4gICAgICogQGdyb3VwIExpZmVjeWNsZVxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBkaXNhYmxlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLmNvbW1hbmRzLmNsZWFyKCk7XG4gICAgICAgIC8vIFRPRE86IGNsZWFyIGNvbW1hbmRzIGluIGRpc3BhdGNoZXJcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhIGNvbW1hbmQgaW50byBjb21tYW5kIG1hbmFnZXIgYnkgY2xhc3MuXG4gICAgICogQHBhcmFtIHtDb21tYW5kfSBbY29tbWFuZF0gLSBUaGUgY29tbWFuZCBjbGFzcyB0byByZWdpc3RlclxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyByZWdpc3RlckNvbW1hbmQoY29tbWFuZD86IENvbW1hbmQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCFjb21tYW5kIHx8ICFjb21tYW5kLmlkKSB0aHJvdyBuZXcgQ29tbWFuZFJlZ2lzdGVyQ2xhc3NNYWxmb3JtZWRPck1pc3NpbmdFcnJvcigpO1xuICAgICAgICBpZiAoY29tbWFuZC5pZC5zcGxpdCgnOicpLmxlbmd0aCAhPT0gMikgdGhyb3cgbmV3IEdlbmVyaWNOYW1lc3BhY2VJbnZhbGlkRXJyb3IoKTtcblxuICAgICAgICBpZiAoIShjb21tYW5kIGFzIGFueSkucmVnaXN0ZXIpXG4gICAgICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS53YXJuKGBDb21tYW5kIGlzIG1pc3NpbmcgXCJyZWdpc3RlclwiIG1lbWJlci4gVGhpcyBpcyB1bnN1cHBvcnRlZCFgKTtcbiAgICAgICAgZWxzZSBhd2FpdCBjb21tYW5kLnJlZ2lzdGVyKHRoaXMuZGlzcGF0Y2hlcik7XG4gICAgICAgIHRoaXMuY29tbWFuZHMuc2V0KGNvbW1hbmQuaWQsIGNvbW1hbmQpO1xuXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgICAgdGhpcy5zZXJ2ZXJcbiAgICAgICAgICAgICAgICAuZ2V0U2Vzc2lvbk1hbmFnZXIoKVxuICAgICAgICAgICAgICAgIC5nZXRBbGxQbGF5ZXJzKClcbiAgICAgICAgICAgICAgICAubWFwKGFzeW5jIChwbGF5ZXIpID0+IHBsYXllci5nZXROZXR3b3JrU2Vzc2lvbigpLnNlbmRBdmFpbGFibGVDb21tYW5kcygpKVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLmRlYnVnKGBDb21tYW5kIHdpdGggaWQgwqdiJHtjb21tYW5kLmlkfcKnciByZWdpc3RlcmVkYCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGEgcmVnaXN0ZXJlZCBjb21tYW5kIGJ5IElELlxuICAgICAqIEByZW1hcmtzIFRoaXMgaXMgY2FzZS1pbnNlbnNpdGl2ZSwgd29ya3Mgd2l0aCBvciB3aXRob3V0IG5hbWVzcGFjZSwgYW5kIGFsc28gd2l0aCBhbGlhc2VzLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFRoZSBjb21tYW5kIElELlxuICAgICAqIEByZXR1cm5zIHtDb21tYW5kfSBUaGUgY29tbWFuZCBpZiBmb3VuZCwgb3RoZXJ3aXNlIHVuZGVmaW5lZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0Q29tbWFuZChpZDogc3RyaW5nKTogQ29tbWFuZCB7XG4gICAgICAgIGNvbnN0IGNvbW1hbmQgPSBBcnJheS5mcm9tKHRoaXMuY29tbWFuZHMudmFsdWVzKCkpLmZpbmQoXG4gICAgICAgICAgICAoY29tbWFuZCkgPT5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBpdCBtYXRjaGVzIElEIHdpdGhvdXQgbmFtZXNwYWNlLlxuICAgICAgICAgICAgICAgIGNvbW1hbmQubmFtZSA9PT0gaWQgfHxcbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBpdCdzIGFuIGFsaWFzLlxuICAgICAgICAgICAgICAgIGNvbW1hbmQuYWxpYXNlcz8uaW5jbHVkZXMoaWQpIHx8XG4gICAgICAgICAgICAgICAgLy8gTGFzdCBjaGVjayBpZiBpdCdzIHRoZSB3aG9sZSBJRCAodGhpcyBpcyB1bmNvbW1vbiBzbyxcbiAgICAgICAgICAgICAgICAvLyAgaXQncyBsYXN0IHRvIGF2b2lkIHRoZSBtb3N0IGNoZWNrcykuXG4gICAgICAgICAgICAgICAgY29tbWFuZC5pZCA9PT0gaWRcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoIWNvbW1hbmQpIHRocm93IG5ldyBDb21tYW5kVW5rbm93bkNvbW1hbmRFcnJvcigpO1xuICAgICAgICByZXR1cm4gY29tbWFuZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIGVuYWJsZWQgY29tbWFuZHMuXG4gICAgICovXG4gICAgcHVibGljIGdldENvbW1hbmRzKCk6IE1hcDxzdHJpbmcsIENvbW1hbmQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29tbWFuZHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGEgbGlzdCBvZiBhbGwgY29tbWFuZCB2YXJpYW50cy5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzXG4gICAgICogVGhpcyBpcyBFWENMVURJTkcgbGVnYWN5IGNvbW1hbmRzLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRDb21tYW5kc0xpc3QoKTogQXJyYXk8W3N0cmluZywgLyogQ29tbWFuZE5vZGU8UGxheWVyPiAqLyBhbnksIENvbW1hbmRBcmd1bWVudFtdW11dPiB7XG4gICAgICAgIGNvbnN0IHBhcnNlTm9kZSA9IChub2RlOiAvKiBDb21tYW5kTm9kZTxQbGF5ZXI+ICovIGFueSk6IGFueVtdID0+IHtcbiAgICAgICAgICAgIGlmIChub2RlLmdldENoaWxkcmVuQ291bnQoKSA8PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbTogKG5vZGUgYXMgQXJndW1lbnRDb21tYW5kTm9kZTxhbnksIGFueT4pLmdldFR5cGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBbXVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcmVzID0gQXJyYXkuZnJvbShub2RlLmdldENoaWxkcmVuKCkpXG4gICAgICAgICAgICAgICAgLm1hcCgobm9kZSkgPT4gcGFyc2VOb2RlKG5vZGUpKVxuICAgICAgICAgICAgICAgIC5yZXZlcnNlKCk7XG5cbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgbm9kZS5nZXRDb21tYW5kKClcbiAgICAgICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW06IChub2RlIGFzIEFyZ3VtZW50Q29tbWFuZE5vZGU8YW55LCBhbnk+KS5nZXRUeXBlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBbXVxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgLi4ucmVzLm1hcCgoY2hpbGRyZW46IGFueSkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgaXRlbTogKG5vZGUgYXMgQXJndW1lbnRDb21tYW5kTm9kZTxhbnksIGFueT4pLmdldFR5cGUoKSxcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IFsuLi5jaGlsZHJlbl1cbiAgICAgICAgICAgICAgICB9KSlcbiAgICAgICAgICAgIF0uZmlsdGVyKChhKSA9PiBhKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB0cmF2ZXJzZSA9IChub2RlOiBhbnksIHBhdGg6IGFueVtdID0gW10sIHJlc3VsdDogYW55W10gPSBbXSkgPT4ge1xuICAgICAgICAgICAgaWYgKCFub2RlLmNoaWxkcmVuLmxlbmd0aCkgcmVzdWx0LnB1c2gocGF0aC5jb25jYXQobm9kZS5pdGVtKSk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIG5vZGUuY2hpbGRyZW4pIHRyYXZlcnNlKGNoaWxkLCBwYXRoLmNvbmNhdChub2RlLml0ZW0pLCByZXN1bHQpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCByZXMgPSBBcnJheS5mcm9tKHRoaXMuc2VydmVyLmdldENvbW1hbmRNYW5hZ2VyKCkuZ2V0RGlzcGF0Y2hlcigpLmdldFJvb3QoKS5nZXRDaGlsZHJlbigpKVxuICAgICAgICAgICAgLmZsYXRNYXAoKGNvbW1hbmQpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBicmFuY2hlczogYW55W10gPSBbXTtcbiAgICAgICAgICAgICAgICBpZiAoY29tbWFuZC5nZXRDb21tYW5kKCkpIGJyYW5jaGVzLnB1c2goW10pO1xuXG4gICAgICAgICAgICAgICAgQXJyYXkuZnJvbShjb21tYW5kLmdldENoaWxkcmVuKCkpLmZvckVhY2goKG5vZGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2VOb2RlKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBwYXJzZWQuZm9yRWFjaCgoYnJhbmNoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmFuY2hlcy5wdXNoKHRyYXZlcnNlKGJyYW5jaCkpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBicmFuY2hlcy5tYXAoKGJyYW5jaCkgPT4gW2NvbW1hbmQuZ2V0TmFtZSgpLCBjb21tYW5kLCBicmFuY2hdKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuZmlsdGVyKChhKSA9PiBhIGFzIGFueSk7XG5cbiAgICAgICAgcmVzLnRvU3RyaW5nID0gKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGAke3RoaXMuZ2V0Q29tbWFuZHNMaXN0KClcbiAgICAgICAgICAgICAgICAubWFwKChpdGVtKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXRlbVsyXS5sZW5ndGgpIHJldHVybiBgLyR7aXRlbVswXX1gO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXRlbVsyXVxuICAgICAgICAgICAgICAgICAgICAgICAgLm1hcChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZW50cmllcykgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYC8ke2l0ZW1bMF19ICR7ZW50cmllc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmZsYXQoTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLm1hcCgoYXJndW1lbnQ6IGFueSkgPT4gYXJndW1lbnQuZ2V0UmVhZGFibGVUeXBlPy4oKSA/PyBhcmd1bWVudC5jb25zdHJ1Y3Rvci5uYW1lKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmpvaW4oJyAnKX1gXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAuam9pbihgXFxuYCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuam9pbignXFxuJyl9YDtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHJlcyBhcyBhbnk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGRpc3BhdGNoZXJcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0RGlzcGF0Y2hlcigpOiBDb21tYW5kRGlzcGF0Y2hlcjxQbGF5ZXI+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGlzcGF0Y2hlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEaXNwYXRjaGVzIGEgY29tbWFuZCBhbmQgZXhlY3V0ZXMgdGhlbS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBzZW5kZXIgLSB0aGUgcGxheWVyL2NvbnNvbGUgd2hvIGV4ZWN1dGVkIHRoZSBjb21tYW5kXG4gICAgICogQHBhcmFtIHRhcmdldCAtIHRoZSBQbGF5ZXIvZW50aXR5L2NvbnNvbGUgd2hvIHNob3VsZCBleGVjdXRlIHRoZSBjb21tYW5kXG4gICAgICogQHBhcmFtIGlucHV0IC0gdGhlIGNvbW1hbmQgaW5wdXQgaW5jbHVkaW5nIGFyZ3VtZW50c1xuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBkaXNwYXRjaENvbW1hbmQoc2VuZGVyOiBQbGF5ZXIsIHRhcmdldDogRW50aXR5IHwgUGxheWVyLCBpbnB1dCA9ICcnKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoaW5wdXQuc3RhcnRzV2l0aCgnLycpKSBpbnB1dCA9IGlucHV0LnNsaWNlKDEpO1xuXG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSB0aGlzLmRpc3BhdGNoZXIucGFyc2UoaW5wdXQudHJpbSgpLCB0YXJnZXQgYXMgUGxheWVyKTtcbiAgICAgICAgICAgIGNvbnN0IGlkID0gcGFyc2VkLmdldFJlYWRlcigpLmdldFN0cmluZygpLnNwbGl0KCcgJylbMF0hO1xuXG4gICAgICAgICAgICBpZiAoIXNlbmRlci5pc0NvbnNvbGUoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2VydmVyXG4gICAgICAgICAgICAgICAgICAgIC5nZXRMb2dnZXIoKVxuICAgICAgICAgICAgICAgICAgICAuZGVidWcoXG4gICAgICAgICAgICAgICAgICAgICAgICBgRW50aXR5IHdpdGggwqdiJHtzZW5kZXIuZ2V0UnVudGltZUlkKCl9wqdyIGlzIGRpc3BhdGNoaW5nIGNvbW1hbmQ6ICR7aW5wdXR9IChpZDogJHtpZH0pYCxcbiAgICAgICAgICAgICAgICAgICAgICAgICdDb21tYW5kTWFuYWdlci9kaXNwYXRjaENvbW1hbmQnXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEdldCBjb21tYW5kIGZyb20gcGFyc2VkIHN0cmluZy5cbiAgICAgICAgICAgIGNvbnN0IGNvbW1hbmQgPSB0aGlzLmdldENvbW1hbmQoaWQpO1xuXG4gICAgICAgICAgICAvLyBWYWxpZGF0ZSBwZXJtaXNzaW9ucy5cbiAgICAgICAgICAgIGlmICghdGhpcy5zZXJ2ZXIuZ2V0UGVybWlzc2lvbk1hbmFnZXIoKS5jYW4oc2VuZGVyKS5leGVjdXRlKGNvbW1hbmQucGVybWlzc2lvbikpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBzZW5kZXIuc2VuZE1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgICAgIFwiwqdjSSdtIHNvcnJ5LCBidXQgeW91IGRvIG5vdCBoYXZlIHBlcm1pc3Npb24gdG8gcGVyZm9ybSB0aGlzIGNvbW1hbmQuIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICdQbGVhc2UgY29udGFjdCB0aGUgc2VydmVyIGFkbWluaXN0cmF0b3JzIGlmIHlvdSBiZWxpZXZlIHRoYXQgdGhpcyBpcyBpbiBlcnJvci4nXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCByZXM6IHN0cmluZ1tdID0gW107XG4gICAgICAgICAgICAvLyBIYW5kbGUgYWxpYXNlcyBhbmQgSURzLlxuICAgICAgICAgICAgaWYgKGNvbW1hbmQubmFtZSAhPT0gaWQpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmRpc3BhdGNoQ29tbWFuZChzZW5kZXIsIHRhcmdldCwgaW5wdXQucmVwbGFjZShpZCwgY29tbWFuZC5uYW1lKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXMgPSBhd2FpdCBQcm9taXNlLmFsbCh0aGlzLmRpc3BhdGNoZXIuZXhlY3V0ZShwYXJzZWQpKTtcblxuICAgICAgICAgICAgY29uc3QgZmVlZGJhY2sgPSAoc2VuZGVyIGFzIGFueSBhcyBFbnRpdHkpXG4gICAgICAgICAgICAgICAgLmdldFdvcmxkKClcbiAgICAgICAgICAgICAgICAuZ2V0R2FtZXJ1bGVNYW5hZ2VyKClcbiAgICAgICAgICAgICAgICAuZ2V0R2FtZXJ1bGUoJ3NlbmRDb21tYW5kRmVlZGJhY2snKTtcblxuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHdlIGRvbid0IHNlbmQgZmVlZGJhY2sgaWYgc2VuZENvbW1hbmRGZWVkYmFjayBpcyBzZXQgdG8gZmFsc2VcbiAgICAgICAgICAgIGlmICghZmVlZGJhY2spIHJldHVybjtcblxuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICAgICAgcmVzLm1hcChhc3luYyAocmVzOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hhdCA9IG5ldyBDaGF0KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRlcjogdGhpcy5zZXJ2ZXIuZ2V0Q29uc29sZSgpISxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGDCp2/CpzdbJHt0YXJnZXQuZ2V0TmFtZSgpfTogJHtyZXMgPz8gYGlzc3VlZCBzZXJ2ZXIgY29tbWFuZDogLyR7aW5wdXR9YH1dwqdyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoYW5uZWw6ICcqLm9wcydcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogc2hvdWxkIHRoaXMgYmUgYnJvYWRjYXN0ZWQgdG8gdGhlIGV4ZWN1dGVyP1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnNlcnZlci5nZXRDaGF0TWFuYWdlcigpLnNlbmQoY2hhdCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRydWUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIGVycm9yIGluc3RhbmNlb2YgQ29tbWFuZFN5bnRheEV4Y2VwdGlvbjpcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgc2VuZGVyLnNlbmRNZXNzYWdlKGDCp2Mke2Vycm9yLmdldE1lc3NhZ2UoKX1gKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIGNhc2UgZXJyb3IgaW5zdGFuY2VvZiBDb21tYW5kVW5rbm93bkNvbW1hbmRFcnJvcjpcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgc2VuZGVyLnNlbmRNZXNzYWdlKGDCp2NVbmtub3duIGNvbW1hbmQuIFR5cGUgXCIvaGVscFwiIGZvciBoZWxwLmApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgY2FzZSBlcnJvciBpbnN0YW5jZW9mIEVycm9yOlxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBzZW5kZXIuc2VuZE1lc3NhZ2UoYMKnYyR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGF3YWl0IHNlbmRlci5zZW5kTWVzc2FnZShgwqdjJHtlcnJvcn1gKTtcbiAgICAgICAgICAgIHRoaXMuc2VydmVyXG4gICAgICAgICAgICAgICAgLmdldExvZ2dlcigpXG4gICAgICAgICAgICAgICAgLmRlYnVnKFxuICAgICAgICAgICAgICAgICAgICBgUGxheWVyICR7dGFyZ2V0LmdldEZvcm1hdHRlZFVzZXJuYW1lKCl9IHRyaWVkIHRvIGV4ZWN1dGUgJHtpbnB1dH0sIGJ1dCBpdCBmYWlsZWQgd2l0aCB0aGUgZXJyb3I6ICR7ZXJyb3J9YCxcbiAgICAgICAgICAgICAgICAgICAgJ0NvbW1hbmRNYW5hZ2VyL2Rpc3BhdGNoQ29tbWFuZCdcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkuZXJyb3IoZXJyb3IpO1xuICAgICAgICB9XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBZUEsSUFBYSxpQkFBYixNQUErQztDQUMzQywyQkFBa0QsSUFBSSxJQUFJO0NBQzFEO0NBQ0E7Q0FFQSxZQUFtQixRQUFnQjtFQUMvQixLQUFLLFNBQVM7RUFDZCxLQUFLLGFBQWEsSUFBSSx3QkFBQSxrQkFBa0I7Q0FDNUM7Ozs7O0NBTUEsTUFBYSxTQUF3QjtFQUNqQyxNQUFNLFFBQVEsSUFBSSxvQkFBQSxRQUFNO0VBRXhCLE1BQU0sV0FBVyxPQUFPLEtBQUsseUJBQUEsZ0JBQVEsRUFBRSxLQUFLLFFBQVMseUJBQUEsaUJBQWlCLElBQXNCO0VBRzVGLE1BQU0sUUFBUSxJQUNWLFNBQVMsSUFBSSxPQUFPLFlBQVk7R0FDNUIsTUFBTSxVQUFtQixJQUFJLFFBQVEsQ0FBQyxDQUFRO0dBRTlDLE1BQU0sUUFBUSxJQUFJLDRDQUFBLFFBQXFCLE9BQU87R0FDOUMsTUFBTSxLQUFLLE9BQU8sS0FBSyxtQkFBbUIsS0FBSztHQUMv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