@jsprismarine/prismarine
Version:
Dedicated Minecraft Bedrock Edition server written in TypeScript
578 lines (572 loc) • 87.9 kB
JavaScript
'use strict';
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const BedrockData = require('@jsprismarine/bedrock-data');
const minecraft = require('@jsprismarine/minecraft');
const Heap = require('heap');
const command_CommandArguments = require('../command/CommandArguments.cjs.cjs');
const inventory_WindowIds = require('../inventory/WindowIds.cjs.cjs');
const item_Item = require('../item/Item.cjs.cjs');
const utils_UUID = require('../utils/UUID.cjs.cjs');
const world_BlockPosition = require('../world/BlockPosition.cjs.cjs');
const world_CoordinateUtils = require('../world/CoordinateUtils.cjs.cjs');
const world_chunk_Chunk = require('../world/chunk/Chunk.cjs.cjs');
require('./packet/ActorFallPacket.cjs.cjs');
require('./packet/AddActorPacket.cjs.cjs');
require('./packet/AddItemActorPacket.cjs.cjs');
const network_packet_AddPlayerPacket = require('./packet/AddPlayerPacket.cjs.cjs');
require('./packet/AnimatePacket.cjs.cjs');
require('./packet/AvailableActorIdentifiersPacket.cjs.cjs');
const network_packet_AvailableCommandsPacket = require('./packet/AvailableCommandsPacket.cjs.cjs');
const network_packet_BatchPacket = require('./packet/BatchPacket.cjs.cjs');
require('./packet/BiomeDefinitionListPacket.cjs.cjs');
require('./packet/ChangeDimensionPacket.cjs.cjs');
const network_packet_ChunkRadiusUpdatedPacket = require('./packet/ChunkRadiusUpdatedPacket.cjs.cjs');
require('./packet/CommandRequestPacket.cjs.cjs');
require('./packet/ContainerClosePacket.cjs.cjs');
require('./packet/ContainerOpenPacket.cjs.cjs');
const network_packet_CreativeContentPacket = require('./packet/CreativeContentPacket.cjs.cjs');
require('@jsprismarine/jsbinaryutils');
const network_packet_DisconnectPacket = require('./packet/DisconnectPacket.cjs.cjs');
require('./packet/EmoteListPacket.cjs.cjs');
require('./packet/InteractPacket.cjs.cjs');
const network_packet_InventoryContentPacket = require('./packet/InventoryContentPacket.cjs.cjs');
require('./packet/InventoryTransactionPacket.cjs.cjs');
require('./packet/ItemComponentPacket.cjs.cjs');
require('./packet/ItemStackRequestPacket.cjs.cjs');
require('./packet/ItemStackResponsePacket.cjs.cjs');
const network_packet_LevelChunkPacket = require('./packet/LevelChunkPacket.cjs.cjs');
require('./packet/LevelSoundEventPacket.cjs.cjs');
require('./packet/LoginPacket.cjs.cjs');
const network_packet_MobEquipmentPacket = require('./packet/MobEquipmentPacket.cjs.cjs');
require('./packet/MoveActorAbsolutePacket.cjs.cjs');
const network_packet_MovePlayerPacket = require('./packet/MovePlayerPacket.cjs.cjs');
const network_packet_NetworkChunkPublisherUpdatePacket = require('./packet/NetworkChunkPublisherUpdatePacket.cjs.cjs');
require('./packet/OnScreenTextureAnimationPacket.cjs.cjs');
require('./packet/PacketViolationWarningPacket.cjs.cjs');
require('./packet/PlaySoundPacket.cjs.cjs');
const network_packet_PlayStatusPacket = require('./packet/PlayStatusPacket.cjs.cjs');
require('./packet/PlayerActionPacket.cjs.cjs');
const network_packet_PlayerListPacket = require('./packet/PlayerListPacket.cjs.cjs');
require('./packet/PlayerSkinPacket.cjs.cjs');
const network_packet_RemoveActorPacket = require('./packet/RemoveActorPacket.cjs.cjs');
require('./packet/RequestChunkRadiusPacket.cjs.cjs');
require('./packet/RequestNetworkSettingsPacket.cjs.cjs');
require('./packet/ResourcePackResponsePacket.cjs.cjs');
require('./packet/ResourcePackStackPacket.cjs.cjs');
require('./packet/ResourcePacksInfoPacket.cjs.cjs');
require('./packet/ServerSettingsRequestPacket.cjs.cjs');
const network_packet_SetActorDataPacket = require('./packet/SetActorDataPacket.cjs.cjs');
require('./packet/SetDefaultGametypePacket.cjs.cjs');
require('./packet/SetHealthPacket.cjs.cjs');
require('./packet/SetLocalPlayerAsInitializedPacket.cjs.cjs');
const network_packet_SetPlayerGametypePacket = require('./packet/SetPlayerGametypePacket.cjs.cjs');
const network_packet_SetTimePacket = require('./packet/SetTimePacket.cjs.cjs');
require('./packet/ShowProfilePacket.cjs.cjs');
require('./packet/StartGamePacket.cjs.cjs');
const network_packet_TextPacket = require('./packet/TextPacket.cjs.cjs');
require('./packet/TickSyncPacket.cjs.cjs');
require('./packet/TransferPacket.cjs.cjs');
const network_packet_UpdateAdventureSettingsPacket = require('./packet/UpdateAdventureSettingsPacket.cjs.cjs');
const network_packet_UpdateAttributesPacket = require('./packet/UpdateAttributesPacket.cjs.cjs');
require('./packet/UpdateBlockPacket.cjs.cjs');
require('./packet/WorldEventPacket.cjs.cjs');
const network_packet_UpdateAbilitiesPacket = require('./packet/UpdateAbilitiesPacket.cjs.cjs');
const network_type_CommandData = require('./type/CommandData.cjs.cjs');
const network_type_CommandEnum = require('./type/CommandEnum.cjs.cjs');
const network_type_CommandParameter = require('./type/CommandParameter.cjs.cjs');
const network_type_MovementType = require('./type/MovementType.cjs.cjs');
const network_type_PermissionType = require('./type/PermissionType.cjs.cjs');
const network_type_PlayerPermissionType = require('./type/PlayerPermissionType.cjs.cjs');
const network_type_TextType = require('./type/TextType.cjs.cjs');
const _interopDefault = e => e && e.__esModule ? e : { default: e };
const Heap__default = /*#__PURE__*/_interopDefault(Heap);
class PlayerSession {
connection;
server;
player;
chunkSendQueue = [];
loadedChunks = /* @__PURE__ */ new Set();
loadingChunks = /* @__PURE__ */ new Set();
constructor(server, connection, player) {
this.server = server;
this.connection = connection;
this.player = player;
}
async update(_tick) {
if (this.chunkSendQueue.length > 0) {
const chunksToSend = this.chunkSendQueue.splice(0, Math.min(this.chunkSendQueue.length, 50));
const batch = new network_packet_BatchPacket.default();
for (const chunk of chunksToSend) {
const pk = new network_packet_LevelChunkPacket.default();
pk.chunkX = chunk.getX();
pk.chunkZ = chunk.getZ();
pk.clientSubChunkRequestsEnabled = false;
pk.subChunkCount = chunk.getTopEmpty() + 4;
pk.data = chunk.networkSerialize();
batch.addPacket(pk);
const hash = world_chunk_Chunk.default.packXZ(chunk.getX(), chunk.getZ());
this.loadedChunks.add(hash);
this.loadingChunks.delete(hash);
}
this.connection.sendBatch(batch, false);
}
this.player.viewDistance && await this.needNewChunks();
}
async send(packet) {
this.connection.sendDataPacket(packet);
}
/**
* Notify a client about change(s) to the adventure settings.
*
* @param player - The client-controlled entity
*/
async sendSettings(player) {
const target = player ?? this.player;
const packet = new network_packet_UpdateAdventureSettingsPacket.default();
packet.worldImmutable = target.gamemode === minecraft.Gametype.SPECTATOR;
packet.noAttackingPlayers = target.gamemode === minecraft.Gametype.SPECTATOR;
packet.noAttackingMobs = target.gamemode === minecraft.Gametype.SPECTATOR;
packet.autoJump = true;
packet.showNameTags = true;
await this.connection.sendDataPacket(packet);
}
async sendAbilities(player) {
const target = player ?? this.player;
const mainLayer = new network_packet_UpdateAbilitiesPacket.AbilityLayer();
mainLayer.layerType = network_packet_UpdateAbilitiesPacket.AbilityLayerType.BASE;
mainLayer.layerFlags = /* @__PURE__ */ new Map([
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.FLY_SPEED, true],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.WALK_SPEED, true],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.MAY_FLY, target.metadata.canFly],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.FLYING, target.isFlying()],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.NO_CLIP, target.gamemode === minecraft.Gametype.SPECTATOR],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.OPERATOR_COMMANDS, target.isOp()],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.TELEPORT, target.isOp()],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.INVULNERABLE, target.gamemode === minecraft.Gametype.SPECTATOR],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.MUTED, false],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.WORLD_BUILDER, false],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.INSTABUILD, target.gamemode === minecraft.Gametype.SPECTATOR],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.LIGHTNING, false],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.BUILD, target.gamemode !== minecraft.Gametype.SPECTATOR],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.MINE, target.gamemode !== minecraft.Gametype.SPECTATOR],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.DOORS_AND_SWITCHES, target.gamemode !== minecraft.Gametype.SPECTATOR],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.OPEN_CONTAINERS, target.gamemode !== minecraft.Gametype.SPECTATOR],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.ATTACK_PLAYERS, target.gamemode !== minecraft.Gametype.SPECTATOR],
[network_packet_UpdateAbilitiesPacket.AbilityLayerFlag.ATTACK_MOBS, target.gamemode !== minecraft.Gametype.SPECTATOR]
]);
mainLayer.flySpeed = 0.05;
mainLayer.walkSpeed = 0.1;
const packet = new network_packet_UpdateAbilitiesPacket.default();
packet.commandPermission = target.isOp() ? network_type_PermissionType.default.Operator : network_type_PermissionType.default.Normal;
packet.playerPermission = target.isOp() ? network_type_PlayerPermissionType.default.Operator : network_type_PlayerPermissionType.default.Member;
packet.targetActorUniqueId = target.getRuntimeId();
packet.abilityLayers = [mainLayer];
await this.send(packet);
}
async needNewChunks(forceResend = false, dist) {
const currentXChunk = world_CoordinateUtils.default.fromBlockToChunk(this.player.getX());
const currentZChunk = world_CoordinateUtils.default.fromBlockToChunk(this.player.getZ());
const viewDistance = this.player.viewDistance || dist || 0;
const chunksToSendHeap = new Heap__default.default((a, b) => {
const distXFirst = Math.abs(a[0] - currentXChunk);
const distXSecond = Math.abs(b[0] - currentXChunk);
const distZFirst = Math.abs(a[1] - currentZChunk);
const distZSecond = Math.abs(b[1] - currentZChunk);
return distXFirst + distZFirst > distXSecond + distZSecond ? 1 : -1;
});
for (let sendXChunk = -viewDistance; sendXChunk <= viewDistance; sendXChunk++) {
for (let sendZChunk = -viewDistance; sendZChunk <= viewDistance; sendZChunk++) {
if (sendXChunk * sendXChunk + sendZChunk * sendZChunk > viewDistance * viewDistance) continue;
const newChunk = [currentXChunk + sendXChunk, currentZChunk + sendZChunk];
const hash = world_chunk_Chunk.default.packXZ(newChunk[0], newChunk[1]);
if (forceResend) {
chunksToSendHeap.push(newChunk);
} else if (!this.loadedChunks.has(hash) && !this.loadingChunks.has(hash)) {
chunksToSendHeap.push(newChunk);
}
}
}
while (chunksToSendHeap.size() > 0) {
const closestChunk = chunksToSendHeap.pop();
const hash = world_chunk_Chunk.default.packXZ(closestChunk[0], closestChunk[1]);
if (forceResend) {
if (!this.loadedChunks.has(hash) && !this.loadingChunks.has(hash)) {
this.loadingChunks.add(hash);
await this.requestChunk(closestChunk[0], closestChunk[1]);
} else {
const loadedChunk = await this.player.getWorld().getChunk(closestChunk[0], closestChunk[1]);
await this.sendChunk(loadedChunk);
}
} else {
this.loadingChunks.add(hash);
await this.requestChunk(closestChunk[0], closestChunk[1]);
}
}
let unloaded = false;
for (const hash of this.loadedChunks) {
const [x, z] = world_chunk_Chunk.default.unpackXZ(hash);
if (Math.abs(x - currentXChunk) > viewDistance || Math.abs(z - currentZChunk) > viewDistance) {
unloaded = true;
this.loadedChunks.delete(hash);
}
}
for (const hash of this.loadingChunks) {
const [x, z] = world_chunk_Chunk.default.unpackXZ(hash);
if (Math.abs(x - currentXChunk) > viewDistance || Math.abs(z - currentZChunk) > viewDistance) {
this.loadingChunks.delete(hash);
}
}
if (!unloaded && this.chunkSendQueue.length !== 0) {
await this.sendNetworkChunkPublisher(dist ?? viewDistance, []);
}
}
async requestChunk(x, z) {
const chunk = await this.player.getWorld().getChunk(x, z);
this.chunkSendQueue.push(chunk);
}
/**
* Clear the currently loaded and loading chunks.
*
* @remarks
* Usually used for changing dimension, world, etc.
*/
async clearChunks() {
this.loadedChunks.clear();
this.loadingChunks.clear();
}
/**
* @TODO: Implement this.
*/
async sendInventory() {
const pk = new network_packet_InventoryContentPacket.default();
pk.items = this.player.getInventory().getItems(true);
pk.windowId = inventory_WindowIds.WindowIds.INVENTORY;
}
async sendCreativeContents(empty = false) {
const pk = new network_packet_CreativeContentPacket.default();
if (empty) {
await this.connection.sendDataPacket(pk);
return;
}
const entries = [
...this.player.getServer().getBlockManager().getBlocks(),
...this.player.getServer().getItemManager().getItems()
];
BedrockData.creativeitems.forEach((item) => {
pk.items.push(
...entries.filter((entry) => {
return entry.meta === (item.damage ?? 0) && entry.getId() === item.id;
}).map(
(entry) => new item_Item.Item({
id: entry.getId(),
name: entry.getName(),
meta: entry.meta
})
)
);
});
await this.connection.sendDataPacket(pk);
}
/**
* Sets the item in the player hand.
* @param {Item} item - The entity.
*/
async sendHandItem(item) {
const pk = new network_packet_MobEquipmentPacket.default();
pk.runtimeEntityId = this.player.getRuntimeId();
pk.item = item;
pk.inventorySlot = this.player.getInventory().getHandSlotIndex();
pk.hotbarSlot = this.player.getInventory().getHandSlotIndex();
pk.windowId = 0;
await this.connection.sendDataPacket(pk);
}
/**
* Send the current tick to a client.
* @param {number} tick - The tick
*/
async sendTime(tick) {
const pk = new network_packet_SetTimePacket.default();
pk.time = tick;
await this.connection.sendDataPacket(pk);
}
/**
* Send gamemode to a client.
* @param {Gametype} gamemode - the numeric gamemode ID.
*/
async sendGamemode(gamemode) {
const packet = new network_packet_SetPlayerGametypePacket.default();
packet.gametype = gamemode ?? this.player.gamemode;
await this.connection.sendDataPacket(packet);
}
async sendNetworkChunkPublisher(distance, savedChunks) {
const pk = new network_packet_NetworkChunkPublisherUpdatePacket.default();
pk.position = world_BlockPosition.default.fromVector3(this.player.getPosition());
pk.radius = distance << 4;
pk.savedChunks = savedChunks;
await this.connection.sendDataPacket(pk);
}
async sendAvailableCommands() {
const playerEnum = new network_type_CommandEnum.CommandEnum();
playerEnum.soft = true;
playerEnum.name = "Player";
playerEnum.values = this.player.getServer().getSessionManager().getAllPlayers().map((player) => player.getName());
const pk = new network_packet_AvailableCommandsPacket.default();
pk.softEnums = [playerEnum];
this.server.getCommandManager().getCommandsList().forEach((command) => {
const commandClass = Array.from(this.server.getCommandManager().getCommands().values()).find(
(cmd2) => cmd2.name === command[0]
);
if (!commandClass) {
this.player.getServer().getLogger().warn(`Can't find corresponding command class for "${command[0]}"`);
return;
}
if (!this.player.getServer().getPermissionManager().can(this.player).execute(commandClass.permission))
return;
const cmd = new network_type_CommandData.default();
cmd.commandName = command[0];
cmd.commandDescription = commandClass.description;
if (commandClass.aliases.length > 0) {
const cmdAliases = new network_type_CommandEnum.CommandEnum();
cmdAliases.name = `${command[0]}Aliases`;
cmdAliases.values = commandClass.aliases.concat(command[0]);
cmd.aliases = cmdAliases;
}
command[2].forEach((arg, index) => {
const parameters = arg.map((parameter) => {
if (!parameter || !parameter?.getParameters) return [];
const parameters2 = parameter.getParameters(this.server);
if (parameters2) return Array.from(parameters2.values());
if (parameter instanceof command_CommandArguments.CommandArgumentEntity)
return [
new network_type_CommandParameter.default({
paramName: "target",
paramType: network_type_CommandParameter.CommandParameterType.Target
})
];
if (parameter instanceof command_CommandArguments.CommandArgumentGamemode)
return [
new network_type_CommandParameter.default({
paramName: "gamemode",
paramType: network_type_CommandParameter.CommandParameterType.String
})
];
if (parameter.constructor.name === "StringArgumentType")
return [
new network_type_CommandParameter.default({
paramName: "value",
paramType: network_type_CommandParameter.CommandParameterType.String
})
];
if (parameter.constructor.name === "IntegerArgumentType")
return [
new network_type_CommandParameter.default({
paramName: "number",
paramType: network_type_CommandParameter.CommandParameterType.Int
})
];
this.server.getLogger().warn(`Invalid parameter ${parameter.constructor.name}`);
return [
new network_type_CommandParameter.default({
paramName: "value",
paramType: network_type_CommandParameter.CommandParameterType.String
})
];
}).flat();
cmd.overloads[index] = parameters;
});
pk.commandData.push(cmd);
});
await this.getConnection().sendDataPacket(pk);
}
/**
* Set the client's maximum view distance.
*
* @param distance - The view distance
*/
async setViewDistance(distance) {
const packet = new network_packet_ChunkRadiusUpdatedPacket.default();
packet.radius = this.player.viewDistance = distance;
await this.connection.sendDataPacket(packet);
}
async sendAttributes(attributes) {
const value = attributes?.getAttributes() ?? this.player.attributes.getAttributes();
const packet = new network_packet_UpdateAttributesPacket.default();
packet.runtimeEntityId = this.player.getRuntimeId();
packet.attributes = value.length > 0 ? value : this.player.attributes.getDefaults();
packet.tick = BigInt(this.player.getServer().getTick());
await this.connection.sendDataPacket(packet);
}
async sendMetadata(metadata) {
const packet = new network_packet_SetActorDataPacket.default();
packet.runtimeEntityId = this.player.getRuntimeId();
packet.metadata = metadata ?? this.player.metadata;
packet.tick = BigInt(this.player.getServer().getTick());
await this.connection.sendDataPacket(packet);
}
/**
* Send a chat message to the client.
* @param {object} options - The options for the message.
* @param {string} options.message - The message to send.
* @param {string} [options.sourceName=''] - The source of the message.
* @param {string} [options.xuid=''] - The XUID of the player.
* @param {string} [options.platformChatId=''] - The platform chat ID.
* @param {string[]} [options.parameters=[]] - The parameters for the message.
* @param {boolean} [options.needsTranslation=false] - Whether the message needs translation.
* @param {TextType} [options.type=TextType.Raw] - The type of the message.
* @returns {Promise<void>} A promise that resolves when the message is sent.
*/
async sendMessage({
message,
sourceName = "",
xuid = "",
platformChatId = "",
parameters = [],
needsTranslation = false,
type = network_type_TextType.default.Raw
}) {
if (!message) throw new Error("A message is required");
const pk = new network_packet_TextPacket.default();
pk.message = message;
pk.filtered = message;
pk.sourceName = sourceName;
pk.xuid = xuid;
pk.platformChatId = platformChatId;
pk.parameters = parameters;
pk.needsTranslation = needsTranslation;
pk.type = type;
await this.connection.sendDataPacket(pk);
}
async sendChunk(chunk) {
const hash = world_chunk_Chunk.default.packXZ(chunk.getX(), chunk.getZ());
const packet = new network_packet_LevelChunkPacket.default();
packet.chunkX = chunk.getX();
packet.chunkZ = chunk.getZ();
packet.clientSubChunkRequestsEnabled = false;
packet.subChunkCount = chunk.getTopEmpty() + 4;
packet.data = chunk.networkSerialize();
await this.send(packet);
this.loadingChunks.delete(hash);
this.loadedChunks.add(hash);
}
/**
* Broadcast the movement to a defined player
*/
async broadcastMove(player, mode = network_type_MovementType.default.Normal) {
const packet = new network_packet_MovePlayerPacket.default();
packet.runtimeEntityId = player.getRuntimeId();
packet.position = player.getPosition();
packet.pitch = player.pitch;
packet.yaw = player.yaw;
packet.headYaw = player.headYaw;
packet.mode = mode;
packet.onGround = player.isOnGround();
if (mode === network_type_MovementType.default.Teleport) {
packet.teleportCause = 0;
packet.teleportItemId = 0;
}
packet.ridingEntityRuntimeId = BigInt(0);
packet.tick = BigInt(this.player.getServer().getTick());
await this.send(packet);
}
/**
* Adds the client to the player list of every player inside
* the server and also to the player itself.
*/
async addToPlayerList() {
const entry = new network_packet_PlayerListPacket.PlayerListEntry({
uuid: utils_UUID.default.fromString(this.player.getUUID()),
runtimeId: this.player.getRuntimeId(),
name: this.player.getName(),
xuid: this.player.xuid,
platformChatId: this.player.platformChatId,
buildPlatform: this.player.device?.os ?? -1,
skin: this.player.skin,
isTeacher: false,
isHost: false
});
this.server.getSessionManager().getPlayerList().set(this.player.getUUID(), entry);
const packet = new network_packet_PlayerListPacket.default();
packet.type = network_packet_PlayerListPacket.PlayerListAction.TYPE_ADD;
packet.entries.push(entry);
await this.server.broadcastPacket(packet);
}
/**
* Removes a player from other players list
*/
async removeFromPlayerList() {
const entry = new network_packet_PlayerListPacket.PlayerListEntry({
uuid: utils_UUID.default.fromString(this.player.getUUID())
});
this.server.getSessionManager().getPlayerList().delete(this.player.getUUID());
const packet = new network_packet_PlayerListPacket.default();
packet.type = network_packet_PlayerListPacket.PlayerListAction.TYPE_REMOVE;
packet.entries.push(entry);
await this.server.broadcastPacket(packet);
}
/**
* Sends the full player list to the player.
*/
async sendPlayerList() {
const packet = new network_packet_PlayerListPacket.default();
packet.type = network_packet_PlayerListPacket.PlayerListAction.TYPE_ADD;
packet.entries = Array.from(this.server.getSessionManager().getPlayerList().values());
await this.send(packet);
}
/**
* Spawn the player for another player
*
* @param player - the player to send the AddPlayerPacket to
*/
async sendSpawn(player) {
if (!player.getUUID()) {
this.server.getLogger().error(`UUID for player ${player.getName()} is undefined`);
return;
}
const pk = new network_packet_AddPlayerPacket.default();
pk.uuid = utils_UUID.default.fromString(this.player.getUUID());
pk.runtimeEntityId = this.player.getRuntimeId();
pk.name = this.player.getName();
pk.positionX = this.player.getX();
pk.positionY = this.player.getY();
pk.positionZ = this.player.getZ();
pk.motionX = 0;
pk.motionY = 0;
pk.motionZ = 0;
pk.pitch = this.player.pitch;
pk.yaw = this.player.yaw;
pk.headYaw = this.player.headYaw;
pk.gamemode = this.player.gamemode;
pk.item = this.player.getInventory().getItemInHand();
pk.deviceId = this.player.device?.id ?? "";
pk.metadata = this.player.metadata;
await player.getNetworkSession().send(pk);
await this.sendSettings(player);
}
/**
* Despawn the player entity from another player
*/
async sendDespawn(player) {
const pk = new network_packet_RemoveActorPacket.default();
pk.uniqueEntityId = this.player.getRuntimeId();
await player.getNetworkSession().getConnection().sendDataPacket(pk);
}
async sendPlayStatus(status) {
const pk = new network_packet_PlayStatusPacket.default();
pk.status = status;
await this.connection.sendDataPacket(pk, true);
}
async kick(reason = "unknown reason") {
const pk = new network_packet_DisconnectPacket.default();
pk.skipMessage = false;
pk.message = reason;
await this.connection.sendDataPacket(pk, true);
}
getConnection() {
return this.connection;
}
getPlayer() {
return this.player;
}
}
exports.default = PlayerSession;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGxheWVyU2Vzc2lvbi5janMuY2pzIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbmV0d29yay9QbGF5ZXJTZXNzaW9uLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0aXZlaXRlbXMgYXMgQ3JlYXRpdmVJdGVtcyB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvYmVkcm9jay1kYXRhJztcbmltcG9ydCB7IEdhbWV0eXBlIH0gZnJvbSAnQGpzcHJpc21hcmluZS9taW5lY3JhZnQnO1xuaW1wb3J0IEhlYXAgZnJvbSAnaGVhcCc7XG5pbXBvcnQgdHlwZSBQbGF5ZXIgZnJvbSAnLi4vUGxheWVyJztcbmltcG9ydCB0eXBlIFNlcnZlciBmcm9tICcuLi9TZXJ2ZXInO1xuaW1wb3J0IHR5cGUgeyBDb21tYW5kQXJndW1lbnQgfSBmcm9tICcuLi9jb21tYW5kL0NvbW1hbmRBcmd1bWVudHMnO1xuaW1wb3J0IHsgQ29tbWFuZEFyZ3VtZW50RW50aXR5LCBDb21tYW5kQXJndW1lbnRHYW1lbW9kZSB9IGZyb20gJy4uL2NvbW1hbmQvQ29tbWFuZEFyZ3VtZW50cyc7XG5pbXBvcnQgdHlwZSB7IEF0dHJpYnV0ZXMgfSBmcm9tICcuLi9lbnRpdHkvQXR0cmlidXRlJztcbmltcG9ydCB0eXBlIHsgTWV0YWRhdGEgfSBmcm9tICcuLi9lbnRpdHkvTWV0YWRhdGEnO1xuaW1wb3J0IHsgV2luZG93SWRzIH0gZnJvbSAnLi4vaW52ZW50b3J5L1dpbmRvd0lkcyc7XG5pbXBvcnQgeyBJdGVtIH0gZnJvbSAnLi4vaXRlbS9JdGVtJztcbmltcG9ydCBVVUlEIGZyb20gJy4uL3V0aWxzL1VVSUQnO1xuaW1wb3J0IEJsb2NrUG9zaXRpb24gZnJvbSAnLi4vd29ybGQvQmxvY2tQb3NpdGlvbic7XG5pbXBvcnQgQ29vcmRpbmF0ZVV0aWxzIGZyb20gJy4uL3dvcmxkL0Nvb3JkaW5hdGVVdGlscyc7XG5pbXBvcnQgQ2h1bmsgZnJvbSAnLi4vd29ybGQvY2h1bmsvQ2h1bmsnO1xuaW1wb3J0IHR5cGUgQ2xpZW50Q29ubmVjdGlvbiBmcm9tICcuL0NsaWVudENvbm5lY3Rpb24nO1xuaW1wb3J0IHR5cGUgeyBEYXRhUGFja2V0IH0gZnJvbSAnLi9QYWNrZXRzJztcbmltcG9ydCB7IEJhdGNoUGFja2V0IH0gZnJvbSAnLi9QYWNrZXRzJztcbmltcG9ydCBBZGRQbGF5ZXJQYWNrZXQgZnJvbSAnLi9wYWNrZXQvQWRkUGxheWVyUGFja2V0JztcbmltcG9ydCBBdmFpbGFibGVDb21tYW5kc1BhY2tldCBmcm9tICcuL3BhY2tldC9BdmFpbGFibGVDb21tYW5kc1BhY2tldCc7XG5pbXBvcnQgQ2h1bmtSYWRpdXNVcGRhdGVkUGFja2V0IGZyb20gJy4vcGFja2V0L0NodW5rUmFkaXVzVXBkYXRlZFBhY2tldCc7XG5pbXBvcnQgQ3JlYXRpdmVDb250ZW50UGFja2V0IGZyb20gJy4vcGFja2V0L0NyZWF0aXZlQ29udGVudFBhY2tldCc7XG5pbXBvcnQgRGlzY29ubmVjdFBhY2tldCBmcm9tICcuL3BhY2tldC9EaXNjb25uZWN0UGFja2V0JztcbmltcG9ydCBJbnZlbnRvcnlDb250ZW50UGFja2V0IGZyb20gJy4vcGFja2V0L0ludmVudG9yeUNvbnRlbnRQYWNrZXQnO1xuaW1wb3J0IExldmVsQ2h1bmtQYWNrZXQgZnJvbSAnLi9wYWNrZXQvTGV2ZWxDaHVua1BhY2tldCc7XG5pbXBvcnQgTW9iRXF1aXBtZW50UGFja2V0IGZyb20gJy4vcGFja2V0L01vYkVxdWlwbWVudFBhY2tldCc7XG5pbXBvcnQgTW92ZVBsYXllclBhY2tldCBmcm9tICcuL3BhY2tldC9Nb3ZlUGxheWVyUGFja2V0JztcbmltcG9ydCB0eXBlIHsgQ2h1bmtDb29yZCB9IGZyb20gJy4vcGFja2V0L05ldHdvcmtDaHVua1B1Ymxpc2hlclVwZGF0ZVBhY2tldCc7XG5pbXBvcnQgTmV0d29ya0NodW5rUHVibGlzaGVyVXBkYXRlUGFja2V0IGZyb20gJy4vcGFja2V0L05ldHdvcmtDaHVua1B1Ymxpc2hlclVwZGF0ZVBhY2tldCc7XG5pbXBvcnQgUGxheVN0YXR1c1BhY2tldCBmcm9tICcuL3BhY2tldC9QbGF5U3RhdHVzUGFja2V0JztcbmltcG9ydCBQbGF5ZXJMaXN0UGFja2V0LCB7IFBsYXllckxpc3RBY3Rpb24sIFBsYXllckxpc3RFbnRyeSB9IGZyb20gJy4vcGFja2V0L1BsYXllckxpc3RQYWNrZXQnO1xuaW1wb3J0IFJlbW92ZUFjdG9yUGFja2V0IGZyb20gJy4vcGFja2V0L1JlbW92ZUFjdG9yUGFja2V0JztcbmltcG9ydCBTZXRBY3RvckRhdGFQYWNrZXQgZnJvbSAnLi9wYWNrZXQvU2V0QWN0b3JEYXRhUGFja2V0JztcbmltcG9ydCBTZXRQbGF5ZXJHYW1ldHlwZVBhY2tldCBmcm9tICcuL3BhY2tldC9TZXRQbGF5ZXJHYW1ldHlwZVBhY2tldCc7XG5pbXBvcnQgU2V0VGltZVBhY2tldCBmcm9tICcuL3BhY2tldC9TZXRUaW1lUGFja2V0JztcbmltcG9ydCBUZXh0UGFja2V0IGZyb20gJy4vcGFja2V0L1RleHRQYWNrZXQnO1xuaW1wb3J0IFVwZGF0ZUFiaWxpdGllc1BhY2tldCwge1xuICAgIEFiaWxpdHlMYXllcixcbiAgICBBYmlsaXR5TGF5ZXJGbGFnLFxuICAgIEFiaWxpdHlMYXllclR5cGVcbn0gZnJvbSAnLi9wYWNrZXQvVXBkYXRlQWJpbGl0aWVzUGFja2V0JztcbmltcG9ydCBVcGRhdGVBZHZlbnR1cmVTZXR0aW5nc1BhY2tldCBmcm9tICcuL3BhY2tldC9VcGRhdGVBZHZlbnR1cmVTZXR0aW5nc1BhY2tldCc7XG5pbXBvcnQgVXBkYXRlQXR0cmlidXRlc1BhY2tldCBmcm9tICcuL3BhY2tldC9VcGRhdGVBdHRyaWJ1dGVzUGFja2V0JztcbmltcG9ydCBDb21tYW5kRGF0YSBmcm9tICcuL3R5cGUvQ29tbWFuZERhdGEnO1xuaW1wb3J0IHsgQ29tbWFuZEVudW0gfSBmcm9tICcuL3R5cGUvQ29tbWFuZEVudW0nO1xuaW1wb3J0IENvbW1hbmRQYXJhbWV0ZXIsIHsgQ29tbWFuZFBhcmFtZXRlclR5cGUgfSBmcm9tICcuL3R5cGUvQ29tbWFuZFBhcmFtZXRlcic7XG5pbXBvcnQgTW92ZW1lbnRUeXBlIGZyb20gJy4vdHlwZS9Nb3ZlbWVudFR5cGUnO1xuaW1wb3J0IFBlcm1pc3Npb25UeXBlIGZyb20gJy4vdHlwZS9QZXJtaXNzaW9uVHlwZSc7XG5pbXBvcnQgUGxheWVyUGVybWlzc2lvblR5cGUgZnJvbSAnLi90eXBlL1BsYXllclBlcm1pc3Npb25UeXBlJztcbmltcG9ydCBUZXh0VHlwZSBmcm9tICcuL3R5cGUvVGV4dFR5cGUnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQbGF5ZXJTZXNzaW9uIHtcbiAgICBwcml2YXRlIGNvbm5lY3Rpb246IENsaWVudENvbm5lY3Rpb247XG4gICAgcHJpdmF0ZSByZWFkb25seSBzZXJ2ZXI6IFNlcnZlcjtcbiAgICBwcml2YXRlIHBsYXllcjogUGxheWVyO1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBjaHVua1NlbmRRdWV1ZTogQ2h1bmtbXSA9IFtdO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgbG9hZGVkQ2h1bmtzOiBTZXQ8YmlnaW50PiA9IG5ldyBTZXQoKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGxvYWRpbmdDaHVua3M6IFNldDxiaWdpbnQ+ID0gbmV3IFNldCgpO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHNlcnZlcjogU2VydmVyLCBjb25uZWN0aW9uOiBDbGllbnRDb25uZWN0aW9uLCBwbGF5ZXI6IFBsYXllcikge1xuICAgICAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgdGhpcy5wbGF5ZXIgPSBwbGF5ZXI7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHVwZGF0ZShfdGljazogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLmNodW5rU2VuZFF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGNodW5rc1RvU2VuZCA9IHRoaXMuY2h1bmtTZW5kUXVldWUuc3BsaWNlKDAsIE1hdGgubWluKHRoaXMuY2h1bmtTZW5kUXVldWUubGVuZ3RoLCA1MCkpO1xuICAgICAgICAgICAgY29uc3QgYmF0Y2ggPSBuZXcgQmF0Y2hQYWNrZXQoKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzVG9TZW5kKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGsgPSBuZXcgTGV2ZWxDaHVua1BhY2tldCgpO1xuICAgICAgICAgICAgICAgIHBrLmNodW5rWCA9IGNodW5rLmdldFgoKTtcbiAgICAgICAgICAgICAgICBway5jaHVua1ogPSBjaHVuay5nZXRaKCk7XG4gICAgICAgICAgICAgICAgcGsuY2xpZW50U3ViQ2h1bmtSZXF1ZXN0c0VuYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBway5zdWJDaHVua0NvdW50ID0gY2h1bmsuZ2V0VG9wRW1wdHkoKSArIDQ7XG4gICAgICAgICAgICAgICAgcGsuZGF0YSA9IGNodW5rLm5ldHdvcmtTZXJpYWxpemUoKTtcbiAgICAgICAgICAgICAgICBiYXRjaC5hZGRQYWNrZXQocGspO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgaGFzaCA9IENodW5rLnBhY2tYWihjaHVuay5nZXRYKCksIGNodW5rLmdldFooKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2FkZWRDaHVua3MuYWRkKGhhc2gpO1xuICAgICAgICAgICAgICAgIHRoaXMubG9hZGluZ0NodW5rcy5kZWxldGUoaGFzaCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc2VuZEJhdGNoKGJhdGNoLCBmYWxzZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnBsYXllci52aWV3RGlzdGFuY2UgJiYgKGF3YWl0IHRoaXMubmVlZE5ld0NodW5rcygpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgc2VuZChwYWNrZXQ6IERhdGFQYWNrZXQpIHtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uLnNlbmREYXRhUGFja2V0KHBhY2tldCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTm90aWZ5IGEgY2xpZW50IGFib3V0IGNoYW5nZShzKSB0byB0aGUgYWR2ZW50dXJlIHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHBsYXllciAtIFRoZSBjbGllbnQtY29udHJvbGxlZCBlbnRpdHlcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2VuZFNldHRpbmdzKHBsYXllcj86IFBsYXllcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSBwbGF5ZXIgPz8gdGhpcy5wbGF5ZXI7XG5cbiAgICAgICAgY29uc3QgcGFja2V0ID0gbmV3IFVwZGF0ZUFkdmVudHVyZVNldHRpbmdzUGFja2V0KCk7XG4gICAgICAgIHBhY2tldC53b3JsZEltbXV0YWJsZSA9IHRhcmdldC5nYW1lbW9kZSA9PT0gR2FtZXR5cGUuU1BFQ1RBVE9SO1xuICAgICAgICBwYWNrZXQubm9BdHRhY2tpbmdQbGF5ZXJzID0gdGFyZ2V0LmdhbWVtb2RlID09PSBHYW1ldHlwZS5TUEVDVEFUT1I7XG4gICAgICAgIHBhY2tldC5ub0F0dGFja2luZ01vYnMgPSB0YXJnZXQuZ2FtZW1vZGUgPT09IEdhbWV0eXBlLlNQRUNUQVRPUjtcbiAgICAgICAgcGFja2V0LmF1dG9KdW1wID0gdHJ1ZTtcbiAgICAgICAgcGFja2V0LnNob3dOYW1lVGFncyA9IHRydWU7XG4gICAgICAgIGF3YWl0IHRoaXMuY29ubmVjdGlvbi5zZW5kRGF0YVBhY2tldChwYWNrZXQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBzZW5kQWJpbGl0aWVzKHBsYXllcj86IFBsYXllcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSBwbGF5ZXIgPz8gdGhpcy5wbGF5ZXI7XG5cbiAgICAgICAgY29uc3QgbWFpbkxheWVyID0gbmV3IEFiaWxpdHlMYXllcigpO1xuICAgICAgICBtYWluTGF5ZXIubGF5ZXJUeXBlID0gQWJpbGl0eUxheWVyVHlwZS5CQVNFO1xuICAgICAgICBtYWluTGF5ZXIubGF5ZXJGbGFncyA9IG5ldyBNYXAoW1xuICAgICAgICAgICAgW0FiaWxpdHlMYXllckZsYWcuRkxZX1NQRUVELCB0cnVlXSxcbiAgICAgICAgICAgIFtBYmlsaXR5TGF5ZXJGbGFnLldBTEtfU1BFRUQsIHRydWVdLFxuICAgICAgICAgICAgW0FiaWxpdHlMYXllckZsYWcuTUFZX0ZMWSwgdGFyZ2V0Lm1ldGFkYXRhLmNhbkZseV0sXG4gICAgICAgICAgICBbQWJpbGl0eUxheWVyRmxhZy5GTFlJTkcsIHRhcmdldC5pc0ZseWluZygpXSxcbiAgICAgICAgICAgIFtBYmlsaXR5TGF5ZXJGbGFnLk5PX0NMSVAsIHRhcmdldC5nYW1lbW9kZSA9PT0gR2FtZXR5cGUuU1BFQ1RBVE9SXSxcbiAgICAgICAgICAgIFtBYmlsaXR5TGF5ZXJGbGFnLk9QRVJBVE9SX0NPTU1BTkRTLCB0YXJnZXQuaXNPcCgpXSxcbiAgICAgICAgICAgIFtBYmlsaXR5TGF5ZXJGbGFnLlRFTEVQT1JULCB0YXJnZXQuaXNPcCgpXSxcbiAgICAgICAgICAgIFtBYmlsaXR5TGF5ZXJGbGFnLklOVlVMTkVSQUJMRSwgdGFyZ2V0LmdhbWVtb2RlID09PSBHYW1ldHlwZS5TUEVDVEFUT1JdLFxuICAgICAgICAgICAgW0FiaWxpdHlMYXllckZsYWcuTVVURUQsIGZhbHNlXSxcbiAgICAgICAgICAgIFtBYmlsaXR5TGF5ZXJGbGFnLldPUkxEX0JVSUxERVIsIGZhbHNlXSxcbiAgICAgICAgICAgIFtBYmlsaXR5TGF5ZXJGbGFnLklOU1RBQlVJTEQsIHRhcmdldC5nYW1lbW9kZSA9PT0gR2FtZXR5cGUuU1BFQ1RBVE9SXSxcbiAgICAgICAgICAgIFtBYmlsaXR5TGF5ZXJGbGFnLkxJR0hUTklORywgZmFsc2VdLFxuICAgICAgICAgICAgW0FiaWxpdHlMYXllckZsYWcuQlVJTEQsIHRhcmdldC5nYW1lbW9kZSAhPT0gR2FtZXR5cGUuU1BFQ1RBVE9SXSxcbiAgICAgICAgICAgIFtBYmlsaXR5TGF5ZXJGbGFnLk1JTkUsIHRhcmdldC5nYW1lbW9kZSAhPT0gR2FtZXR5cGUuU1BFQ1RBVE9SXSxcbiAgICAgICAgICAgIFtBYmlsaXR5TGF5ZXJGbGFnLkRPT1JTX0FORF9TV0lUQ0hFUywgdGFyZ2V0LmdhbWVtb2RlICE9PSBHYW1ldHlwZS5TUEVDVEFUT1JdLFxuICAgICAgICAgICAgW0FiaWxpdHlMYXllckZsYWcuT1BFTl9DT05UQUlORVJTLCB0YXJnZXQuZ2FtZW1vZGUgIT09IEdhbWV0eXBlLlNQRUNUQVRPUl0sXG4gICAgICAgICAgICBbQWJpbGl0eUxheWVyRmxhZy5BVFRBQ0tfUExBWUVSUywgdGFyZ2V0LmdhbWVtb2RlICE9PSBHYW1ldHlwZS5TUEVDVEFUT1JdLFxuICAgICAgICAgICAgW0FiaWxpdHlMYXllckZsYWcuQVRUQUNLX01PQlMsIHRhcmdldC5nYW1lbW9kZSAhPT0gR2FtZXR5cGUuU1BFQ1RBVE9SXVxuICAgICAgICBdKTtcbiAgICAgICAgbWFpbkxheWVyLmZseVNwZWVkID0gMC4wNTtcbiAgICAgICAgbWFpbkxheWVyLndhbGtTcGVlZCA9IDAuMTtcblxuICAgICAgICBjb25zdCBwYWNrZXQgPSBuZXcgVXBkYXRlQWJpbGl0aWVzUGFja2V0KCk7XG4gICAgICAgIHBhY2tldC5jb21tYW5kUGVybWlzc2lvbiA9IHRhcmdldC5pc09wKCkgPyBQZXJtaXNzaW9uVHlwZS5PcGVyYXRvciA6IFBlcm1pc3Npb25UeXBlLk5vcm1hbDtcbiAgICAgICAgcGFja2V0LnBsYXllclBlcm1pc3Npb24gPSB0YXJnZXQuaXNPcCgpID8gUGxheWVyUGVybWlzc2lvblR5cGUuT3BlcmF0b3IgOiBQbGF5ZXJQZXJtaXNzaW9uVHlwZS5NZW1iZXI7XG4gICAgICAgIHBhY2tldC50YXJnZXRBY3RvclVuaXF1ZUlkID0gdGFyZ2V0LmdldFJ1bnRpbWVJZCgpO1xuICAgICAgICBwYWNrZXQuYWJpbGl0eUxheWVycyA9IFttYWluTGF5ZXJdO1xuICAgICAgICBhd2FpdCB0aGlzLnNlbmQocGFja2V0KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgbmVlZE5ld0NodW5rcyhmb3JjZVJlc2VuZCA9IGZhbHNlLCBkaXN0PzogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRYQ2h1bmsgPSBDb29yZGluYXRlVXRpbHMuZnJvbUJsb2NrVG9DaHVuayh0aGlzLnBsYXllci5nZXRYKCkpO1xuICAgICAgICBjb25zdCBjdXJyZW50WkNodW5rID0gQ29vcmRpbmF0ZVV0aWxzLmZyb21CbG9ja1RvQ2h1bmsodGhpcy5wbGF5ZXIuZ2V0WigpKTtcblxuICAgICAgICBjb25zdCB2aWV3RGlzdGFuY2UgPSB0aGlzLnBsYXllci52aWV3RGlzdGFuY2UgfHwgZGlzdCB8fCAwO1xuXG4gICAgICAgIGNvbnN0IGNodW5rc1RvU2VuZEhlYXAgPSBuZXcgSGVhcCgoYTogbnVtYmVyW10sIGI6IG51bWJlcltdKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBkaXN0WEZpcnN0ID0gTWF0aC5hYnMoYVswXSEgLSBjdXJyZW50WENodW5rKTtcbiAgICAgICAgICAgIGNvbnN0IGRpc3RYU2Vjb25kID0gTWF0aC5hYnMoYlswXSEgLSBjdXJyZW50WENodW5rKTtcblxuICAgICAgICAgICAgY29uc3QgZGlzdFpGaXJzdCA9IE1hdGguYWJzKGFbMV0hIC0gY3VycmVudFpDaHVuayk7XG4gICAgICAgICAgICBjb25zdCBkaXN0WlNlY29uZCA9IE1hdGguYWJzKGJbMV0hIC0gY3VycmVudFpDaHVuayk7XG5cbiAgICAgICAgICAgIHJldHVybiBkaXN0WEZpcnN0ICsgZGlzdFpGaXJzdCA+IGRpc3RYU2Vjb25kICsgZGlzdFpTZWNvbmQgPyAxIDogLTE7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGZvciAobGV0IHNlbmRYQ2h1bmsgPSAtdmlld0Rpc3RhbmNlOyBzZW5kWENodW5rIDw9IHZpZXdEaXN0YW5jZTsgc2VuZFhDaHVuaysrKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBzZW5kWkNodW5rID0gLXZpZXdEaXN0YW5jZTsgc2VuZFpDaHVuayA8PSB2aWV3RGlzdGFuY2U7IHNlbmRaQ2h1bmsrKykge1xuICAgICAgICAgICAgICAgIGlmIChzZW5kWENodW5rICogc2VuZFhDaHVuayArIHNlbmRaQ2h1bmsgKiBzZW5kWkNodW5rID4gdmlld0Rpc3RhbmNlICogdmlld0Rpc3RhbmNlKSBjb250aW51ZTsgLy8gZWFybHkgZXhpdCBpZiBjaHVuayBpcyBvdXRzaWRlIG9mIHZpZXcgZGlzdGFuY2VcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdDaHVuayA9IFtjdXJyZW50WENodW5rICsgc2VuZFhDaHVuaywgY3VycmVudFpDaHVuayArIHNlbmRaQ2h1bmtdO1xuICAgICAgICAgICAgICAgIGNvbnN0IGhhc2ggPSBDaHVuay5wYWNrWFoobmV3Q2h1bmtbMF0hLCBuZXdDaHVua1sxXSEpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGZvcmNlUmVzZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIGNodW5rc1RvU2VuZEhlYXAucHVzaChuZXdDaHVuayk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5sb2FkZWRDaHVua3MuaGFzKGhhc2gpICYmICF0aGlzLmxvYWRpbmdDaHVua3MuaGFzKGhhc2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNodW5rc1RvU2VuZEhlYXAucHVzaChuZXdDaHVuayk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgd2hpbGUgKGNodW5rc1RvU2VuZEhlYXAuc2l6ZSgpID4gMCkge1xuICAgICAgICAgICAgY29uc3QgY2xvc2VzdENodW5rID0gY2h1bmtzVG9TZW5kSGVhcC5wb3AoKSE7XG4gICAgICAgICAgICBjb25zdCBoYXNoID0gQ2h1bmsucGFja1haKGNsb3Nlc3RDaHVua1swXSEsIGNsb3Nlc3RDaHVua1sxXSEpO1xuICAgICAgICAgICAgaWYgKGZvcmNlUmVzZW5kKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmxvYWRlZENodW5rcy5oYXMoaGFzaCkgJiYgIXRoaXMubG9hZGluZ0NodW5rcy5oYXMoaGFzaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkaW5nQ2h1bmtzLmFkZChoYXNoKTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5yZXF1ZXN0Q2h1bmsoY2xvc2VzdENodW5rWzBdISwgY2xvc2VzdENodW5rWzFdISk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9hZGVkQ2h1bmsgPSBhd2FpdCB0aGlzLnBsYXllci5nZXRXb3JsZCgpLmdldENodW5rKGNsb3Nlc3RDaHVua1swXSEsIGNsb3Nlc3RDaHVua1sxXSEpO1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnNlbmRDaHVuayhsb2FkZWRDaHVuayk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRpbmdDaHVua3MuYWRkKGhhc2gpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucmVxdWVzdENodW5rKGNsb3Nlc3RDaHVua1swXSEsIGNsb3Nlc3RDaHVua1sxXSEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHVubG9hZGVkID0gZmFsc2U7XG5cbiAgICAgICAgZm9yIChjb25zdCBoYXNoIG9mIHRoaXMubG9hZGVkQ2h1bmtzKSB7XG4gICAgICAgICAgICBjb25zdCBbeCwgel0gPSBDaHVuay51bnBhY2tYWihoYXNoKTtcblxuICAgICAgICAgICAgaWYgKE1hdGguYWJzKHghIC0gY3VycmVudFhDaHVuaykgPiB2aWV3RGlzdGFuY2UgfHwgTWF0aC5hYnMoeiEgLSBjdXJyZW50WkNodW5rKSA+IHZpZXdEaXN0YW5jZSkge1xuICAgICAgICAgICAgICAgIHVubG9hZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRlZENodW5rcy5kZWxldGUoaGFzaCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IGhhc2ggb2YgdGhpcy5sb2FkaW5nQ2h1bmtzKSB7XG4gICAgICAgICAgICBjb25zdCBbeCwgel0gPSBDaHVuay51bnBhY2tYWihoYXNoKTtcblxuICAgICAgICAgICAgaWYgKE1hdGguYWJzKHghIC0gY3VycmVudFhDaHVuaykgPiB2aWV3RGlzdGFuY2UgfHwgTWF0aC5hYnMoeiEgLSBjdXJyZW50WkNodW5rKSA+IHZpZXdEaXN0YW5jZSkge1xuICAgICAgICAgICAgICAgIHRoaXMubG9hZGluZ0NodW5rcy5kZWxldGUoaGFzaCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXVubG9hZGVkICYmIHRoaXMuY2h1bmtTZW5kUXVldWUubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNlbmROZXR3b3JrQ2h1bmtQdWJsaXNoZXIoZGlzdCA/PyB2aWV3RGlzdGFuY2UsIFtdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZXF1ZXN0Q2h1bmsoeDogbnVtYmVyLCB6OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgY2h1bmsgPSBhd2FpdCB0aGlzLnBsYXllci5nZXRXb3JsZCgpLmdldENodW5rKHgsIHopO1xuICAgICAgICB0aGlzLmNodW5rU2VuZFF1ZXVlLnB1c2goY2h1bmspO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsZWFyIHRoZSBjdXJyZW50bHkgbG9hZGVkIGFuZCBsb2FkaW5nIGNodW5rcy5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzXG4gICAgICogVXN1YWxseSB1c2VkIGZvciBjaGFuZ2luZyBkaW1lbnNpb24sIHdvcmxkLCBldGMuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGNsZWFyQ2h1bmtzKCkge1xuICAgICAgICB0aGlzLmxvYWRlZENodW5rcy5jbGVhcigpO1xuICAgICAgICB0aGlzLmxvYWRpbmdDaHVua3MuY2xlYXIoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAVE9ETzogSW1wbGVtZW50IHRoaXMuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNlbmRJbnZlbnRvcnkoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHBrID0gbmV3IEludmVudG9yeUNvbnRlbnRQYWNrZXQoKTtcbiAgICAgICAgcGsuaXRlbXMgPSB0aGlzLnBsYXllci5nZXRJbnZlbnRvcnkoKS5nZXRJdGVtcyh0cnVlKTtcbiAgICAgICAgcGsud2luZG93SWQgPSBXaW5kb3dJZHMuSU5WRU5UT1JZOyAvLyBJbnZlbnRvcnkgd2luZG93XG4gICAgICAgIC8vYXdhaXQgdGhpcy5jb25uZWN0aW9uLnNlbmREYXRhUGFja2V0KHBrKTtcbiAgICAgICAgLy9hd2FpdCB0aGlzLnNlbmRIYW5kSXRlbSh0aGlzLnBsYXllci5nZXRJbnZlbnRvcnkoKS5nZXRJdGVtSW5IYW5kKCkpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBzZW5kQ3JlYXRpdmVDb250ZW50cyhlbXB0eSA9IGZhbHNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHBrID0gbmV3IENyZWF0aXZlQ29udGVudFBhY2tldCgpO1xuICAgICAgICBpZiAoZW1wdHkpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY29ubmVjdGlvbi5zZW5kRGF0YVBhY2tldChwayk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBlbnRyaWVzID0gW1xuICAgICAgICAgICAgLi4udGhpcy5wbGF5ZXIuZ2V0U2VydmVyKCkuZ2V0QmxvY2tNYW5hZ2VyKCkuZ2V0QmxvY2tzKCksXG4gICAgICAgICAgICAuLi50aGlzLnBsYXllci5nZXRTZXJ2ZXIoKS5nZXRJdGVtTWFuYWdlcigpLmdldEl0ZW1zKClcbiAgICAgICAgXTtcblxuICAgICAgICAvLyBTb3J0IGJhc2VkIG9uIFBtbVAgQmVkcm9jay1kYXRhXG4gICAgICAgIENyZWF0aXZlSXRlbXMuZm9yRWFjaCgoaXRlbTogYW55KSA9PiB7XG4gICAgICAgICAgICBway5pdGVtcy5wdXNoKFxuICAgICAgICAgICAgICAgIC4uLmVudHJpZXNcbiAgICAgICAgICAgICAgICAgICAgLmZpbHRlcigoZW50cnk6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVudHJ5Lm1ldGEgPT09IChpdGVtLmRhbWFnZSA/PyAwKSAmJiBlbnRyeS5nZXRJZCgpID09PSBpdGVtLmlkO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAubWFwKFxuICAgICAgICAgICAgICAgICAgICAgICAgKGVudHJ5KSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBJdGVtKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IGVudHJ5LmdldElkKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IGVudHJ5LmdldE5hbWUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YTogZW50cnkubWV0YVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuY29ubmVjdGlvbi5zZW5kRGF0YVBhY2tldChwayk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgaXRlbSBpbiB0aGUgcGxheWVyIGhhbmQuXG4gICAgICogQHBhcmFtIHtJdGVtfSBpdGVtIC0gVGhlIGVudGl0eS5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2VuZEhhbmRJdGVtKGl0ZW06IEl0ZW0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgcGsgPSBuZXcgTW9iRXF1aXBtZW50UGFja2V0KCk7XG4gICAgICAgIHBrLnJ1bnRpbWVFbnRpdHlJZCA9IHRoaXMucGxheWVyLmdldFJ1bnRpbWVJZCgpO1xuICAgICAgICBway5pdGVtID0gaXRlbTtcbiAgICAgICAgcGsuaW52ZW50b3J5U2xvdCA9IHRoaXMucGxheWVyLmdldEludmVudG9yeSgpLmdldEhhbmRTbG90SW5kZXgoKTtcbiAgICAgICAgcGsuaG90YmFyU2xvdCA9IHRoaXMucGxheWVyLmdldEludmVudG9yeSgpLmdldEhhbmRTbG90SW5kZXgoKTtcbiAgICAgICAgcGsud2luZG93SWQgPSAwOyAvLyBJbnZlbnRvcnkgSURcbiAgICAgICAgYXdhaXQgdGhpcy5jb25uZWN0aW9uLnNlbmREYXRhUGFja2V0KHBrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIHRoZSBjdXJyZW50IHRpY2sgdG8gYSBjbGllbnQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHRpY2sgLSBUaGUgdGlja1xuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZW5kVGltZSh0aWNrOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgcGsgPSBuZXcgU2V0VGltZVBhY2tldCgpO1xuICAgICAgICBway50aW1lID0gdGljaztcbiAgICAgICAgYXdhaXQgdGhpcy5jb25uZWN0aW9uLnNlbmREYXRhUGFja2V0KHBrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIGdhbWVtb2RlIHRvIGEgY2xpZW50LlxuICAgICAqIEBwYXJhbSB7R2FtZXR5cGV9IGdhbWVtb2RlIC0gdGhlIG51bWVyaWMgZ2FtZW1vZGUgSUQuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHNlbmRHYW1lbW9kZShnYW1lbW9kZT86IEdhbWV0eXBlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHBhY2tldCA9IG5ldyBTZXRQbGF5ZXJHYW1ldHlwZVBhY2tldCgpO1xuICAgICAgICBwYWNrZXQuZ2FtZXR5cGUgPSBnYW1lbW9kZSA/PyB0aGlzLnBsYXllci5nYW1lbW9kZTtcbiAgICAgICAgYXdhaXQgdGhpcy5jb25uZWN0aW9uLnNlbmREYXRhUGFja2V0KHBhY2tldCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNlbmROZXR3b3JrQ2h1bmtQdWJsaXNoZXIoZGlzdGFuY2U6IG51bWJlciwgc2F2ZWRDaHVua3M6IENodW5rQ29vcmRbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBwayA9IG5ldyBOZXR3b3JrQ2h1bmtQdWJsaXNoZXJVcGRhdGVQYWNrZXQoKTtcbiAgICAgICAgcGsucG9zaXRpb24gPSBCbG9ja1Bvc2l0aW9uLmZyb21WZWN0b3IzKHRoaXMucGxheWVyLmdldFBvc2l0aW9uKCkpO1xuICAgICAgICBway5yYWRpdXMgPSBkaXN0YW5jZSA8PCA0O1xuICAgICAgICBway5zYXZlZENodW5rcyA9IHNhdmVkQ2h1bmtzO1xuICAgICAgICBhd2FpdCB0aGlzLmNvbm5lY3Rpb24uc2VuZERhdGFQYWNrZXQocGspO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBzZW5kQXZhaWxhYmxlQ29tbWFuZHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHBsYXllckVudW0gPSBuZXcgQ29tbWFuZEVudW0oKTtcbiAgICAgICAgcGxheWVyRW51bS5zb2Z0ID0gdHJ1ZTtcbiAgICAgICAgcGxheWVyRW51bS5uYW1lID0gJ1BsYXllcic7XG4gICAgICAgIHBsYXllckVudW0udmFsdWVzID0gdGhpcy5wbGF5ZXJcbiAgICAgICAgICAgIC5nZXRTZXJ2ZXIoKVxuICAgICAgICAgICAgLmdldFNlc3Npb25NYW5hZ2VyKClcbiAgICAgICAgICAgIC5nZXRBbGxQbGF5ZXJzKClcbiAgICAgICAgICAgIC5tYXAoKHBsYXllcikgPT4gcGxheWVyLmdldE5hbWUoKSk7XG5cbiAgICAgICAgY29uc3QgcGsgPSBuZXcgQXZhaWxhYmxlQ29tbWFuZHNQYWNrZXQoKTtcbiAgICAgICAgcGsuc29mdEVudW1zID0gW3BsYXllckVudW1dO1xuICAgICAgICB0aGlzLnNlcnZlclxuICAgICAgICAgICAgLmdldENvbW1hbmRNYW5hZ2VyKClcbiAgICAgICAgICAgIC5nZXRDb21tYW5kc0xpc3QoKVxuICAgICAgICAgICAgLmZvckVhY2goKGNvbW1hbmQpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb21tYW5kQ2xhc3MgPSBBcnJheS5mcm9tKHRoaXMuc2VydmVyLmdldENvbW1hbmRNYW5hZ2VyKCkuZ2V0Q29tbWFuZHMoKS52YWx1ZXMoKSkuZmluZChcbiAgICAgICAgICAgICAgICAgICAgKGNtZCkgPT4gY21kLm5hbWUgPT09IGNvbW1hbmRbMF1cbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjb21tYW5kQ2xhc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbGF5ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIC5nZXRTZXJ2ZXIoKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmdldExvZ2dlcigpXG4gICAgICAgICAgICAgICAgICAgICAgICAud2FybihgQ2FuJ3QgZmluZCBjb3JyZXNwb25kaW5nIGNvbW1hbmQgY2xhc3MgZm9yIFwiJHtjb21tYW5kWzBdfVwiYCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMucGxheWVyLmdldFNlcnZlcigpLmdldFBlcm1pc3Npb25NYW5hZ2VyKCkuY2FuKHRoaXMucGxheWVyKS5leGVjdXRlKGNvbW1hbmRDbGFzcy5wZXJtaXNzaW9uKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgY21kID0gbmV3IENvbW1hbmREYXRhKCk7XG4gICAgICAgICAgICAgICAgY21kLmNvbW1hbmROYW1lID0gY29tbWFuZFswXTtcbiAgICAgICAgICAgICAgICBjbWQuY29tbWFuZERlc2NyaXB0aW9uID0gY29tbWFuZENsYXNzLmRlc2NyaXB0aW9uO1xuICAgICAgICAgICAgICAgIGlmIChjb21tYW5kQ2xhc3MuYWxpYXNlcyEubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjbWRBbGlhc2VzID0gbmV3IENvbW1hbmRFbnVtKCk7XG4gICAgICAgICAgICAgICAgICAgIGNtZEFsaWFzZXMubmFtZSA9IGAke2NvbW1hbmRbMF19QWxpYXNlc2A7XG4gICAgICAgICAgICAgICAgICAgIGNtZEFsaWFzZXMudmFsdWVzID0gY29tbWFuZENsYXNzLmFsaWFzZXMhLmNvbmNhdChjb21tYW5kWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgY21kLmFsaWFzZXMgPSBjbWRBbGlhc2VzO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbW1hbmRbMl0uZm9yRWFjaCgoYXJnLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJhbWV0ZXJzID0gYXJnXG4gICAgICAgICAgICAgICAgICAgICAgICAubWFwKChwYXJhbWV0ZXI6IENvbW1hbmRBcmd1bWVudCB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcmFtZXRlciB8fCAhKHBhcmFtZXRlciBhcyBhbnkpPy5nZXRQYXJhbWV0ZXJzKSByZXR1cm4gW107XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJhbWV0ZXJzID0gcGFyYW1ldGVyLmdldFBhcmFtZXRlcnModGhpcy5zZXJ2ZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXJhbWV0ZXJzKSByZXR1cm4gQXJyYXkuZnJvbShwYXJhbWV0ZXJzLnZhbHVlcygpKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXJhbWV0ZXIgaW5zdGFuY2VvZiBDb21tYW5kQXJndW1lbnRFbnRpdHkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgQ29tbWFuZFBhcmFtZXRlcih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1OYW1lOiAndGFyZ2V0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJhbVR5cGU6IENvbW1hbmRQYXJhbWV0ZXJUeXBlLlRhcmdldFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFyYW1ldGVyIGluc3RhbmNlb2YgQ29tbWFuZEFyZ3VtZW50R2FtZW1vZGUpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgQ29tbWFuZFBhcmFtZXRlcih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1OYW1lOiAnZ2FtZW1vZGUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtVHlwZTogQ29tbWFuZFBhcmFtZXRlclR5cGUuU3RyaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXJhbWV0ZXIuY29uc3RydWN0b3IubmFtZSA9PT0gJ1N0cmluZ0FyZ3VtZW50VHlwZScpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgQ29tbWFuZFBhcmFtZXRlcih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1OYW1lOiAndmFsdWUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtVHlwZTogQ29tbWFuZFBhcmFtZXRlclR5cGUuU3RyaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXJhbWV0ZXIuY29uc3RydWN0b3IubmFtZSA9PT0gJ0ludGVnZXJBcmd1bWVudFR5cGUnKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3IENvbW1hbmRQYXJhbWV0ZXIoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtTmFtZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1UeXBlOiBDb21tYW5kUGFyYW1ldGVyVHlwZS5JbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS53YXJuKGBJbnZhbGlkIHBhcmFtZXRlciAke3BhcmFtZXRlci5