UNPKG

@jsprismarine/prismarine

Version:

Dedicated Minecraft Bedrock Edition server written in TypeScript

172 lines (169 loc) 20.3 kB
import { withCwd } from '../utils/cwd.es.js'; import '@jsprismarine/nbt'; import '@jsprismarine/bedrock-data'; import '@jsprismarine/jsbinaryutils'; import 'zlib'; import '@jsprismarine/math'; import { GeneratorManager } from './GeneratorManager.es.js'; import { World } from './World.es.js'; import Anvil from './providers/anvil/Anvil.es.js'; import Filesystem from './providers/filesystem/Filesystem.es.js'; import fs from 'node:fs'; const WORLDS_FOLDER = "worlds"; const DEFAULT_WORLD_PROVIDER = "Filesystem"; class WorldManager { worlds = /* @__PURE__ */ new Map(); defaultWorld; genManager; server; providers = /* @__PURE__ */ new Map(); // TODO: this should be a manager constructor(server) { this.server = server; this.genManager = new GeneratorManager(server); if (!fs.existsSync(withCwd(WORLDS_FOLDER))) { fs.mkdirSync(withCwd(WORLDS_FOLDER), { recursive: true }); } } /** * On enable hook, enables the manager and load all worlds. * @group Lifecycle */ async enable() { this.addProvider("Anvil", Anvil); this.addProvider("Filesystem", Filesystem); const defaultWorld = this.server.getConfig().getLevelName(); if (!defaultWorld) { this.server.getLogger().warn(`Invalid world!`); return; } const worldData = this.server.getConfig().getWorlds()[defaultWorld]; if (!worldData) throw new Error(`Invalid level-name`); await this.loadWorld(worldData, defaultWorld); } /** * On disable hook. * * Signifies that the manager is being disabled and all worlds should be unloaded. * @group Lifecycle */ async disable() { await Promise.all(this.getWorlds().map(async (world) => this.unloadWorld(world.getName()))); this.providers.clear(); } /** * Add a provider to the internal providers map. * * @param name - the name of the provider CASE SENSITIVE * @param provider - the provider */ addProvider(name, provider) { this.providers.set(name, provider); } /** * Remove a provider from the internal providers map. * * @param name - the name of the provider CASE SENSITIVE */ removeProvider(name) { this.providers.delete(name); } /** * Get all providers. */ getProviders() { return this.providers; } /** * Save the world to disk. */ async save() { this.server.getLogger().info("Saving worlds"); for (const world of this.getWorlds()) { await world.save(); } } /** * Load a world * * @param worldData - the world data including provider key, generator * @param folderName - the name of the folder containing the world */ async loadWorld(worldData, folderName) { if (!worldData) throw new Error("Invalid world data"); if (this.isWorldLoaded(folderName)) { throw new Error(`World ${folderName} has already been loaded`); } const levelPath = withCwd(WORLDS_FOLDER, folderName); const provider = this.providers.get(worldData.provider ?? DEFAULT_WORLD_PROVIDER); const generator = this.getGeneratorManager().getGenerator(worldData.generator ?? "Flat"); if (!provider) { throw new Error(`invalid provider with id ${worldData.provider}`); } const world = new World({ name: folderName, path: levelPath, server: this.server, provider: new provider(levelPath, this.server), seed: worldData.seed, generator, config: worldData }); this.worlds.set(world.getUUID(), world); if (!this.defaultWorld) { this.defaultWorld = this.worlds.get(world.getUUID()); this.server.getLogger().info(`Loading ${world.getFormattedName()} as default world!`); } await world.enable(); this.server.getLogger().verbose(`World ${world.getFormattedName()} successfully loaded!`); return world; } /** * Unloads a level by its folder name. */ async unloadWorld(folderName) { if (!this.isWorldLoaded(folderName)) { this.server.getLogger().error(`Cannot unload a not loaded world with name §b${folderName}`); return; } const world = this.getWorldByName(folderName); if (!world) { this.server.getLogger().error(`Cannot unload world ${folderName}`); return; } await world.disable(); this.worlds.delete(world.getUUID()); this.server.getLogger().verbose(`Successfully unloaded world ${world.getFormattedName()}!`); } /** * Returns whatever the world is loaded or not. * @returns {boolean} true if the world is loaded, false otherwise */ isWorldLoaded(folderName) { const world = Array.from(this.worlds.values()).find( (world2) => world2.getName().toLowerCase() === folderName.toLowerCase() ); if (world) return true; return false; } /** * Returns a world by its folder name. */ getWorldByName(folderName) { return this.getWorlds().find((world) => world.getName().toLowerCase() === folderName.toLowerCase()) ?? null; } /** * Returns an array with all worlds. */ getWorlds() { return Array.from(this.worlds.values()); } getDefaultWorld() { return this.defaultWorld ?? this.getWorlds()[0]; } getGeneratorManager() { return this.genManager; } } export { WorldManager as default }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV29ybGRNYW5hZ2VyLmVzLmpzIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd29ybGQvV29ybGRNYW5hZ2VyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgU2VydmVyLCBTZXJ2aWNlIH0gZnJvbSAnLi4vJztcbmltcG9ydCB7IHdpdGhDd2QgfSBmcm9tICcuLi91dGlscy9jd2QnO1xuaW1wb3J0IHsgR2VuZXJhdG9yTWFuYWdlciB9IGZyb20gJy4vJztcbmltcG9ydCB7IFdvcmxkIH0gZnJvbSAnLi9Xb3JsZCc7XG5pbXBvcnQgdHlwZSBQcm92aWRlciBmcm9tICcuL3Byb3ZpZGVycy9Qcm92aWRlcic7XG5cbmltcG9ydCBBbnZpbCBmcm9tICcuL3Byb3ZpZGVycy9hbnZpbC9BbnZpbCc7XG5pbXBvcnQgRmlsZXN5c3RlbSBmcm9tICcuL3Byb3ZpZGVycy9maWxlc3lzdGVtL0ZpbGVzeXN0ZW0nO1xuXG5pbXBvcnQgZnMgZnJvbSAnbm9kZTpmcyc7XG5cbi8qKlxuICogU3RhbmRhcmQgd29ybGQgZGF0YS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXb3JsZERhdGEge1xuICAgIHNlZWQ6IG51bWJlcjtcbiAgICBwcm92aWRlcj86IHN0cmluZztcbiAgICBnZW5lcmF0b3I/OiBzdHJpbmc7XG59XG5cbmNvbnN0IFdPUkxEU19GT0xERVIgPSAnd29ybGRzJztcbmNvbnN0IERFRkFVTFRfV09STERfUFJPVklERVIgPSAnRmlsZXN5c3RlbSc7XG5cbi8qKlxuICogVGhlIHdvcmxkIG1hbmFnZXIgaXMgcmVzcG9uc2libGUgbGV2ZWwgbG9hZGluZywgdW5sb2FkaW5nLCBhbmQgZ2VuZXJhbCBsZXZlbCBtYW5hZ2VtZW50LlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBXb3JsZE1hbmFnZXIgaW1wbGVtZW50cyBTZXJ2aWNlIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHdvcmxkczogTWFwPHN0cmluZywgV29ybGQ+ID0gbmV3IE1hcCgpIGFzIE1hcDxzdHJpbmcsIFdvcmxkPjtcbiAgICBwcml2YXRlIGRlZmF1bHRXb3JsZDogV29ybGQgfCB1bmRlZmluZWQ7XG4gICAgcHJpdmF0ZSByZWFkb25seSBnZW5NYW5hZ2VyOiBHZW5lcmF0b3JNYW5hZ2VyO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgc2VydmVyOiBTZXJ2ZXI7XG4gICAgcHJpdmF0ZSBwcm92aWRlcnM6IE1hcDxzdHJpbmcsIGFueT4gPSBuZXcgTWFwKCkgYXMgTWFwPHN0cmluZywgYW55PjsgLy8gVE9ETzogdGhpcyBzaG91bGQgYmUgYSBtYW5hZ2VyXG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3Ioc2VydmVyOiBTZXJ2ZXIpIHtcbiAgICAgICAgdGhpcy5zZXJ2ZXIgPSBzZXJ2ZXI7XG4gICAgICAgIHRoaXMuZ2VuTWFuYWdlciA9IG5ldyBHZW5lcmF0b3JNYW5hZ2VyKHNlcnZlcik7XG5cbiAgICAgICAgLy8gQ3JlYXRlIHRoZSB3b3JsZHMgZGlyZWN0b3J5IGlmIGl0IGRvZXNuJ3QgZXhpc3QuXG4gICAgICAgIGlmICghZnMuZXhpc3RzU3luYyh3aXRoQ3dkKFdPUkxEU19GT0xERVIpKSkge1xuICAgICAgICAgICAgZnMubWtkaXJTeW5jKHdpdGhDd2QoV09STERTX0ZPTERFUiksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT24gZW5hYmxlIGhvb2ssIGVuYWJsZXMgdGhlIG1hbmFnZXIgYW5kIGxvYWQgYWxsIHdvcmxkcy5cbiAgICAgKiBAZ3JvdXAgTGlmZWN5Y2xlXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGVuYWJsZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhpcy5hZGRQcm92aWRlcignQW52aWwnLCBBbnZpbCk7XG4gICAgICAgIHRoaXMuYWRkUHJvdmlkZXIoJ0ZpbGVzeXN0ZW0nLCBGaWxlc3lzdGVtKTtcblxuICAgICAgICBjb25zdCBkZWZhdWx0V29ybGQgPSB0aGlzLnNlcnZlci5nZXRDb25maWcoKS5nZXRMZXZlbE5hbWUoKTtcbiAgICAgICAgaWYgKCFkZWZhdWx0V29ybGQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLndhcm4oYEludmFsaWQgd29ybGQhYCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB3b3JsZERhdGEgPSB0aGlzLnNlcnZlci5nZXRDb25maWcoKS5nZXRXb3JsZHMoKVtkZWZhdWx0V29ybGRdO1xuICAgICAgICBpZiAoIXdvcmxkRGF0YSkgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGxldmVsLW5hbWVgKTtcblxuICAgICAgICBhd2FpdCB0aGlzLmxvYWRXb3JsZCh3b3JsZERhdGEsIGRlZmF1bHRXb3JsZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT24gZGlzYWJsZSBob29rLlxuICAgICAqXG4gICAgICogU2lnbmlmaWVzIHRoYXQgdGhlIG1hbmFnZXIgaXMgYmVpbmcgZGlzYWJsZWQgYW5kIGFsbCB3b3JsZHMgc2hvdWxkIGJlIHVubG9hZGVkLlxuICAgICAqIEBncm91cCBMaWZlY3ljbGVcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgZGlzYWJsZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwodGhpcy5nZXRXb3JsZHMoKS5tYXAoYXN5bmMgKHdvcmxkKSA9PiB0aGlzLnVubG9hZFdvcmxkKHdvcmxkLmdldE5hbWUoKSkpKTtcbiAgICAgICAgdGhpcy5wcm92aWRlcnMuY2xlYXIoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBwcm92aWRlciB0byB0aGUgaW50ZXJuYWwgcHJvdmlkZXJzIG1hcC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBuYW1lIC0gdGhlIG5hbWUgb2YgdGhlIHByb3ZpZGVyIENBU0UgU0VOU0lUSVZFXG4gICAgICogQHBhcmFtIHByb3ZpZGVyIC0gdGhlIHByb3ZpZGVyXG4gICAgICovXG4gICAgcHVibGljIGFkZFByb3ZpZGVyKG5hbWU6IHN0cmluZywgcHJvdmlkZXI6IGFueSkge1xuICAgICAgICB0aGlzLnByb3ZpZGVycy5zZXQobmFtZSwgcHJvdmlkZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSBhIHByb3ZpZGVyIGZyb20gdGhlIGludGVybmFsIHByb3ZpZGVycyBtYXAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbmFtZSAtIHRoZSBuYW1lIG9mIHRoZSBwcm92aWRlciBDQVNFIFNFTlNJVElWRVxuICAgICAqL1xuICAgIHB1YmxpYyByZW1vdmVQcm92aWRlcihuYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5wcm92aWRlcnMuZGVsZXRlKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgcHJvdmlkZXJzLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRQcm92aWRlcnMoKTogTWFwPHN0cmluZywgUHJvdmlkZXI+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvdmlkZXJzIGFzIE1hcDxzdHJpbmcsIFByb3ZpZGVyPjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTYXZlIHRoZSB3b3JsZCB0byBkaXNrLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzYXZlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS5pbmZvKCdTYXZpbmcgd29ybGRzJyk7XG4gICAgICAgIGZvciAoY29uc3Qgd29ybGQgb2YgdGhpcy5nZXRXb3JsZHMoKSkge1xuICAgICAgICAgICAgYXdhaXQgd29ybGQuc2F2ZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIHdvcmxkXG4gICAgICpcbiAgICAgKiBAcGFyYW0gd29ybGREYXRhIC0gdGhlIHdvcmxkIGRhdGEgaW5jbHVkaW5nIHByb3ZpZGVyIGtleSwgZ2VuZXJhdG9yXG4gICAgICogQHBhcmFtIGZvbGRlck5hbWUgLSB0aGUgbmFtZSBvZiB0aGUgZm9sZGVyIGNvbnRhaW5pbmcgdGhlIHdvcmxkXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGxvYWRXb3JsZCh3b3JsZERhdGE6IFdvcmxkRGF0YSwgZm9sZGVyTmFtZTogc3RyaW5nKTogUHJvbWlzZTxXb3JsZD4ge1xuICAgICAgICBpZiAoISh3b3JsZERhdGEgYXMgYW55KSkgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHdvcmxkIGRhdGEnKTtcblxuICAgICAgICBpZiAodGhpcy5pc1dvcmxkTG9hZGVkKGZvbGRlck5hbWUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFdvcmxkICR7Zm9sZGVyTmFtZX0gaGFzIGFscmVhZHkgYmVlbiBsb2FkZWRgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGxldmVsUGF0aCA9IHdpdGhDd2QoV09STERTX0ZPTERFUiwgZm9sZGVyTmFtZSk7XG4gICAgICAgIGNvbnN0IHByb3ZpZGVyID0gdGhpcy5wcm92aWRlcnMuZ2V0KHdvcmxkRGF0YS5wcm92aWRlciA/PyBERUZBVUxUX1dPUkxEX1BST1ZJREVSKTtcbiAgICAgICAgY29uc3QgZ2VuZXJhdG9yID0gdGhpcy5nZXRHZW5lcmF0b3JNYW5hZ2VyKCkuZ2V0R2VuZXJhdG9yKHdvcmxkRGF0YS5nZW5lcmF0b3IgPz8gJ0ZsYXQnKTtcblxuICAgICAgICBpZiAoIXByb3ZpZGVyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgcHJvdmlkZXIgd2l0aCBpZCAke3dvcmxkRGF0YS5wcm92aWRlcn1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHdvcmxkID0gbmV3IFdvcmxkKHtcbiAgICAgICAgICAgIG5hbWU6IGZvbGRlck5hbWUsXG4gICAgICAgICAgICBwYXRoOiBsZXZlbFBhdGgsXG4gICAgICAgICAgICBzZXJ2ZXI6IHRoaXMuc2VydmVyLFxuICAgICAgICAgICAgcHJvdmlkZXI6IG5ldyBwcm92aWRlcihsZXZlbFBhdGgsIHRoaXMuc2VydmVyKSxcblxuICAgICAgICAgICAgc2VlZDogd29ybGREYXRhLnNlZWQsXG4gICAgICAgICAgICBnZW5lcmF0b3IsXG4gICAgICAgICAgICBjb25maWc6IHdvcmxkRGF0YVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy53b3JsZHMuc2V0KHdvcmxkLmdldFVVSUQoKSwgd29ybGQpO1xuXG4gICAgICAgIC8vIEZpcnN0IGxldmVsIHRvIGJlIGxvYWRlZCBpcyBhbHNvIHRoZSBkZWZhdWx0IG9uZVxuICAgICAgICBpZiAoIXRoaXMuZGVmYXVsdFdvcmxkKSB7XG4gICAgICAgICAgICB0aGlzLmRlZmF1bHRXb3JsZCA9IHRoaXMud29ybGRzLmdldCh3b3JsZC5nZXRVVUlEKCkpITtcbiAgICAgICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLmluZm8oYExvYWRpbmcgJHt3b3JsZC5nZXRGb3JtYXR0ZWROYW1lKCl9IGFzIGRlZmF1bHQgd29ybGQhYCk7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB3b3JsZC5lbmFibGUoKTtcbiAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkudmVyYm9zZShgV29ybGQgJHt3b3JsZC5nZXRGb3JtYXR0ZWROYW1lKCl9IHN1Y2Nlc3NmdWxseSBsb2FkZWQhYCk7XG5cbiAgICAgICAgcmV0dXJuIHdvcmxkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVubG9hZHMgYSBsZXZlbCBieSBpdHMgZm9sZGVyIG5hbWUuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHVubG9hZFdvcmxkKGZvbGRlck5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoIXRoaXMuaXNXb3JsZExvYWRlZChmb2xkZXJOYW1lKSkge1xuICAgICAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkuZXJyb3IoYENhbm5vdCB1bmxvYWQgYSBub3QgbG9hZGVkIHdvcmxkIHdpdGggbmFtZSDCp2Ike2ZvbGRlck5hbWV9YCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB3b3JsZCA9IHRoaXMuZ2V0V29ybGRCeU5hbWUoZm9sZGVyTmFtZSk7XG4gICAgICAgIGlmICghd29ybGQpIHtcbiAgICAgICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLmVycm9yKGBDYW5ub3QgdW5sb2FkIHdvcmxkICR7Zm9sZGVyTmFtZX1gKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IHdvcmxkLmRpc2FibGUoKTtcbiAgICAgICAgdGhpcy53b3JsZHMuZGVsZXRlKHdvcmxkLmdldFVVSUQoKSk7XG4gICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLnZlcmJvc2UoYFN1Y2Nlc3NmdWxseSB1bmxvYWRlZCB3b3JsZCAke3dvcmxkLmdldEZvcm1hdHRlZE5hbWUoKX0hYCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB3aGF0ZXZlciB0aGUgd29ybGQgaXMgbG9hZGVkIG9yIG5vdC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiB0aGUgd29ybGQgaXMgbG9hZGVkLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBwdWJsaWMgaXNXb3JsZExvYWRlZChmb2xkZXJOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3Qgd29ybGQgPSBBcnJheS5mcm9tKHRoaXMud29ybGRzLnZhbHVlcygpKS5maW5kKFxuICAgICAgICAgICAgKHdvcmxkKSA9PiB3b3JsZC5nZXROYW1lKCkudG9Mb3dlckNhc2UoKSA9PT0gZm9sZGVyTmFtZS50b0xvd2VyQ2FzZSgpXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKHdvcmxkKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSB3b3JsZCBieSBpdHMgZm9sZGVyIG5hbWUuXG4gICAgICovXG4gICAgcHVibGljIGdldFdvcmxkQnlOYW1lKGZvbGRlck5hbWU6IHN0cmluZyk6IFdvcmxkIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFdvcmxkcygpLmZpbmQoKHdvcmxkKSA9PiB3b3JsZC5nZXROYW1lKCkudG9Mb3dlckNhc2UoKSA9PT0gZm9sZGVyTmFtZS50b0xvd2VyQ2FzZSgpKSA/PyBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYW4gYXJyYXkgd2l0aCBhbGwgd29ybGRzLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRXb3JsZHMoKTogV29ybGRbXSB7XG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMud29ybGRzLnZhbHVlcygpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0RGVmYXVsdFdvcmxkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kZWZhdWx0V29ybGQgPz8gdGhpcy5nZXRXb3JsZHMoKVswXTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0R2VuZXJhdG9yTWFuYWdlcigpOiBHZW5lcmF0b3JNYW5hZ2VyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2VuTWFuYWdlcjtcbiAgICB9XG59XG4iXSwibmFtZXMiOlsid29ybGQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQW9CQSxNQUFNLGFBQWdCLEdBQUEsUUFBQTtBQUN0QixNQUFNLHNCQUF5QixHQUFBLFlBQUE7QUFLL0IsTUFBcUIsWUFBZ0MsQ0FBQTtBQUFBLEVBQ2hDLE1BQUEsdUJBQWlDLEdBQUksRUFBQTtBQUFBLEVBQzlDLFlBQUE7QUFBQSxFQUNTLFVBQUE7QUFBQSxFQUNBLE1BQUE7QUFBQSxFQUNULFNBQUEsdUJBQWtDLEdBQUksRUFBQTtBQUFBO0FBQUEsRUFFdkMsWUFBWSxNQUFnQixFQUFBO0FBQy9CLElBQUEsSUFBQSxDQUFLLE1BQVMsR0FBQSxNQUFBO0FBQ2QsSUFBSyxJQUFBLENBQUEsVUFBQSxHQUFhLElBQUksZ0JBQUEsQ0FBaUIsTUFBTSxDQUFBO0FB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