var CUNICULUM_LOBBY_DIMENSION = 'cuniculum:spawn_void';
var CUNICULUM_LOBBY_FIRST_TP_TAG = 'cuniculum_spawn_void_first_tp_v1075';
var CUNICULUM_LOBBY_PREPARED_TAG = 'cuniculum_spawn_void_platform_prepared_v1084';
var CUNICULUM_LOBBY_X = 0;
var CUNICULUM_LOBBY_Y = 81;
var CUNICULUM_LOBBY_Z = 0;
var CUNICULUM_LOBBY_PLATFORM_Y = 80;
var CUNICULUM_LOBBY_PLATFORM_MIN = -47;
var CUNICULUM_LOBBY_PLATFORM_MAX = 46;
var CUNICULUM_LOBBY_BORDER_DIAMETER = 20000;
var CUNICULUM_MAIN_WORLD_BORDER_RADIUS = 10000;
var CUNICULUM_MAIN_WORLD_BORDER_DIAMETER = CUNICULUM_MAIN_WORLD_BORDER_RADIUS * 2;
var CUNICULUM_RTP_NPC_UUID = 'adb87f79-ec70-4253-aa36-8853e9c81703';
var CUNICULUM_RTP_MIN_RANGE = 400;
var CUNICULUM_RTP_MAX_RANGE = 6500;
var CUNICULUM_RTP_SPREAD_RANGE = 24;
var CUNICULUM_RTP_LOCK_TAG = 'cuniculum_rtp_lock_until_tick_v1';
var CUNICULUM_RTP_LOCK_TICKS = 25;
var CUNICULUM_RTP_WARMUP_TICKS = 5;
var CUNICULUM_RTP_MOVE_CANCEL_DISTANCE = 0.35;
var CUNICULUM_PORTAL_PAD_MIN_X = -6;
var CUNICULUM_PORTAL_PAD_MAX_X = 6;
var CUNICULUM_PORTAL_PAD_MIN_Z = 20;
var CUNICULUM_PORTAL_PAD_MAX_Z = 30;
var CUNICULUM_TEXT_DISPLAY_TAG = 'cuniculum_spawn_display_v1';
var CUNICULUM_LOBBY_REPAIR_MS_TAG = 'cuniculum_lobby_repair_ms_v1';
var CUNICULUM_LOBBY_BLOCKED_SPAWN_TYPES = ['NATURAL', 'CHUNK_GENERATION', 'PATROL', 'RAID', 'REINFORCEMENT'];
var CUNICULUM_DIRECTAUTH_CLASS = null;

try {
  CUNICULUM_DIRECTAUTH_CLASS = Java.loadClass('com.marcp.directauth.DirectAuth');
} catch (ignored) {
  CUNICULUM_DIRECTAUTH_CLASS = null;
}

function cuniculumLobbyJson(text, color) {
  return JSON.stringify({ text: text, color: color || 'gold', italic: false });
}

function cuniculumLobbySafeString(value) {
  try {
    return String(value);
  } catch (ignored) {
    return '';
  }
}

function cuniculumLobbySafeName(name) {
  var text = cuniculumLobbySafeString(name).trim();
  return /^[A-Za-z0-9_]{1,16}$/.test(text) ? text : '';
}

function cuniculumLobbyIsAuthenticated(player) {
  if (!player || !CUNICULUM_DIRECTAUTH_CLASS) {
    return true;
  }

  var manager = null;
  try {
    manager = CUNICULUM_DIRECTAUTH_CLASS.getLoginManager();
  } catch (ignored) {
    return true;
  }

  if (!manager) {
    return true;
  }

  var candidates = [player];
  try { candidates.push(player.minecraftEntity); } catch (ignored) { }
  try { candidates.push(player.entity); } catch (ignored) { }
  try { candidates.push(player.getEntity()); } catch (ignored) { }

  for (var i = 0; i < candidates.length; i++) {
    if (!candidates[i]) {
      continue;
    }
    try {
      return !!manager.isAuthenticated(candidates[i]);
    } catch (ignored) { }
  }

  return true;
}

function cuniculumLobbyDimensionFromLevel(level) {
  var values = [];

  try { values.push(level.dimension); } catch (ignored) { }
  try { values.push(level.dimension()); } catch (ignored) { }
  try { values.push(level.getDimension()); } catch (ignored) { }
  try { values.push(level.dimension().location()); } catch (ignored) { }

  for (var i = 0; i < values.length; i++) {
    var text = cuniculumLobbySafeString(values[i]);
    if (text.indexOf(CUNICULUM_LOBBY_DIMENSION) !== -1) {
      return CUNICULUM_LOBBY_DIMENSION;
    }
    if (text.indexOf('minecraft:overworld') !== -1) {
      return 'minecraft:overworld';
    }
    if (text.indexOf('minecraft:the_nether') !== -1) {
      return 'minecraft:the_nether';
    }
    if (text.indexOf('minecraft:the_end') !== -1) {
      return 'minecraft:the_end';
    }
    if (text.indexOf(':') !== -1 && text.indexOf('ResourceKey') === -1) {
      return text;
    }
  }

  return '';
}

function cuniculumLobbyDimensionFromEntity(entity) {
  if (!entity) {
    return '';
  }

  var values = [];
  try { values.push(entity.level); } catch (ignored) { }
  try { values.push(entity.getLevel()); } catch (ignored) { }

  for (var i = 0; i < values.length; i++) {
    var dimension = cuniculumLobbyDimensionFromLevel(values[i]);
    if (dimension) {
      return dimension;
    }
  }

  return '';
}

function cuniculumLobbyCommand(server, dimension, command) {
  if (!server || !dimension || !command) {
    return;
  }
  server.runCommandSilent('execute in ' + dimension + ' run ' + command);
}

function cuniculumLobbyTell(server, target, text, color) {
  var safeTarget = cuniculumLobbySafeName(target);
  if (!server || !safeTarget) {
    return;
  }
  server.runCommandSilent('tellraw ' + safeTarget + ' ' + cuniculumLobbyJson(text, color));
}

function cuniculumLobbyTitle(server, target, mode, text, color) {
  var safeTarget = cuniculumLobbySafeName(target);
  if (!server || !safeTarget || !mode || !text) {
    return;
  }
  server.runCommandSilent('title ' + safeTarget + ' ' + mode + ' ' + cuniculumLobbyJson(text, color || 'gold'));
}

function cuniculumLobbyKeepDay(server) {
  return false;
}
function cuniculumLobbyPreparePortal(server) {
  return;
}
function cuniculumLobbyTextDisplayNbt(text, color, bold) {
  var component = JSON.stringify({ text: text, color: color || 'gold', bold: bold !== false, italic: false });
  component = component.replace(/'/g, "\\'");
  return '{Tags:["' + CUNICULUM_TEXT_DISPLAY_TAG + '"],billboard:"center",alignment:"center",see_through:1b,shadow:1b,background:0,text:\'' + component + '\'}';
}

function cuniculumLobbySummonText(server, x, y, z, text, color, bold) {
  if (!server) {
    return;
  }
  cuniculumLobbyCommand(server, CUNICULUM_LOBBY_DIMENSION, 'summon minecraft:text_display ' + x + ' ' + y + ' ' + z + ' ' + cuniculumLobbyTextDisplayNbt(text, color, bold));
}

function cuniculumLobbyPrepareTextDisplays(server) {
  if (!server) {
    return;
  }
  cuniculumLobbyCommand(server, CUNICULUM_LOBBY_DIMENSION, 'kill @e[type=minecraft:text_display,tag=' + CUNICULUM_TEXT_DISPLAY_TAG + ']');
  cuniculumLobbySummonText(server, 0, CUNICULUM_LOBBY_PLATFORM_Y + 7, 11, 'Bienvenido a CUNICULUM', 'gold', true);
  cuniculumLobbySummonText(server, 0, CUNICULUM_LOBBY_PLATFORM_Y + 6, 11, 'Usa /rtp para iniciar tu aventura', 'yellow', false);
  cuniculumLobbySummonText(server, 0, CUNICULUM_LOBBY_PLATFORM_Y + 5, 11, '/reglas  /comandos  /ayuda  /discord', 'white', false);
  cuniculumLobbySummonText(server, 0, CUNICULUM_LOBBY_PLATFORM_Y + 8, -38, 'Recepcion de Viajeros', 'aqua', true);
  cuniculumLobbySummonText(server, -28, CUNICULUM_LOBBY_PLATFORM_Y + 8, -28, 'Taller Arcano', 'light_purple', true);
  cuniculumLobbySummonText(server, 28, CUNICULUM_LOBBY_PLATFORM_Y + 8, -28, 'Armeria del Prado', 'red', true);
  cuniculumLobbySummonText(server, -28, CUNICULUM_LOBBY_PLATFORM_Y + 8, 28, 'Mercado de la Madriguera', 'green', true);
  cuniculumLobbySummonText(server, 28, CUNICULUM_LOBBY_PLATFORM_Y + 8, 28, 'Tablon de Aventuras', 'yellow', true);
  cuniculumLobbySummonText(server, -39, CUNICULUM_LOBBY_PLATFORM_Y + 3, 39, 'Jardin Norte', 'dark_aqua', false);
  cuniculumLobbySummonText(server, 39, CUNICULUM_LOBBY_PLATFORM_Y + 3, 39, 'Jardin Sur', 'dark_aqua', false);
}

function cuniculumLobbyAddHouse(commands, y, minX, minZ, maxX, maxZ, wall, roof, floor, accent, openSide) {
  commands.push('fill ' + (minX - 2) + ' ' + (y + 1) + ' ' + (minZ - 2) + ' ' + (maxX + 2) + ' ' + (y + 11) + ' ' + (maxZ + 2) + ' minecraft:air replace');
  commands.push('fill ' + minX + ' ' + (y + 1) + ' ' + minZ + ' ' + maxX + ' ' + (y + 1) + ' ' + maxZ + ' ' + floor + ' replace');
  commands.push('fill ' + minX + ' ' + (y + 2) + ' ' + minZ + ' ' + maxX + ' ' + (y + 5) + ' ' + minZ + ' ' + wall + ' replace');
  commands.push('fill ' + minX + ' ' + (y + 2) + ' ' + maxZ + ' ' + maxX + ' ' + (y + 5) + ' ' + maxZ + ' ' + wall + ' replace');
  commands.push('fill ' + minX + ' ' + (y + 2) + ' ' + minZ + ' ' + minX + ' ' + (y + 5) + ' ' + maxZ + ' ' + wall + ' replace');
  commands.push('fill ' + maxX + ' ' + (y + 2) + ' ' + minZ + ' ' + maxX + ' ' + (y + 5) + ' ' + maxZ + ' ' + wall + ' replace');
  commands.push('fill ' + (minX + 1) + ' ' + (y + 2) + ' ' + (minZ + 1) + ' ' + (maxX - 1) + ' ' + (y + 5) + ' ' + (maxZ - 1) + ' minecraft:air replace');
  commands.push('fill ' + minX + ' ' + (y + 2) + ' ' + minZ + ' ' + minX + ' ' + (y + 7) + ' ' + minZ + ' minecraft:stripped_spruce_log replace');
  commands.push('fill ' + maxX + ' ' + (y + 2) + ' ' + minZ + ' ' + maxX + ' ' + (y + 7) + ' ' + minZ + ' minecraft:stripped_spruce_log replace');
  commands.push('fill ' + minX + ' ' + (y + 2) + ' ' + maxZ + ' ' + minX + ' ' + (y + 7) + ' ' + maxZ + ' minecraft:stripped_spruce_log replace');
  commands.push('fill ' + maxX + ' ' + (y + 2) + ' ' + maxZ + ' ' + maxX + ' ' + (y + 7) + ' ' + maxZ + ' minecraft:stripped_spruce_log replace');
  commands.push('fill ' + (minX - 2) + ' ' + (y + 6) + ' ' + (minZ - 2) + ' ' + (maxX + 2) + ' ' + (y + 6) + ' ' + (maxZ + 2) + ' ' + roof + ' replace');
  commands.push('fill ' + (minX - 1) + ' ' + (y + 7) + ' ' + (minZ - 1) + ' ' + (maxX + 1) + ' ' + (y + 7) + ' ' + (maxZ + 1) + ' ' + roof + ' replace');
  commands.push('fill ' + (minX + 2) + ' ' + (y + 8) + ' ' + (minZ + 2) + ' ' + (maxX - 2) + ' ' + (y + 8) + ' ' + (maxZ - 2) + ' ' + roof + ' replace');
  commands.push('fill ' + (minX + 4) + ' ' + (y + 9) + ' ' + (minZ + 4) + ' ' + (maxX - 4) + ' ' + (y + 9) + ' ' + (maxZ - 4) + ' minecraft:spruce_slab[type=top] replace');
  commands.push('fill ' + (minX + 2) + ' ' + (y + 2) + ' ' + (minZ + 2) + ' ' + (maxX - 2) + ' ' + (y + 2) + ' ' + (maxZ - 2) + ' ' + accent + ' replace');

  var midX = Math.floor((minX + maxX) / 2);
  var midZ = Math.floor((minZ + maxZ) / 2);
  if (openSide !== 'north') {
    commands.push('fill ' + (midX - 1) + ' ' + (y + 3) + ' ' + minZ + ' ' + (midX + 1) + ' ' + (y + 4) + ' ' + minZ + ' minecraft:glass_pane replace');
  }
  if (openSide !== 'south') {
    commands.push('fill ' + (midX - 1) + ' ' + (y + 3) + ' ' + maxZ + ' ' + (midX + 1) + ' ' + (y + 4) + ' ' + maxZ + ' minecraft:glass_pane replace');
  }
  if (openSide !== 'west') {
    commands.push('fill ' + minX + ' ' + (y + 3) + ' ' + (midZ - 1) + ' ' + minX + ' ' + (y + 4) + ' ' + (midZ + 1) + ' minecraft:glass_pane replace');
  }
  if (openSide !== 'east') {
    commands.push('fill ' + maxX + ' ' + (y + 3) + ' ' + (midZ - 1) + ' ' + maxX + ' ' + (y + 4) + ' ' + (midZ + 1) + ' minecraft:glass_pane replace');
  }

  if (openSide === 'south') {
    commands.push('fill ' + (minX + 4) + ' ' + (y + 2) + ' ' + maxZ + ' ' + (maxX - 4) + ' ' + (y + 4) + ' ' + maxZ + ' minecraft:air replace');
    commands.push('fill ' + (minX + 3) + ' ' + (y + 1) + ' ' + (maxZ + 1) + ' ' + (maxX - 3) + ' ' + (y + 1) + ' ' + (maxZ + 3) + ' ' + floor + ' replace');
    commands.push('setblock ' + (minX + 3) + ' ' + (y + 3) + ' ' + maxZ + ' minecraft:lantern replace');
    commands.push('setblock ' + (maxX - 3) + ' ' + (y + 3) + ' ' + maxZ + ' minecraft:lantern replace');
  } else if (openSide === 'north') {
    commands.push('fill ' + (minX + 4) + ' ' + (y + 2) + ' ' + minZ + ' ' + (maxX - 4) + ' ' + (y + 4) + ' ' + minZ + ' minecraft:air replace');
    commands.push('fill ' + (minX + 3) + ' ' + (y + 1) + ' ' + (minZ - 3) + ' ' + (maxX - 3) + ' ' + (y + 1) + ' ' + (minZ - 1) + ' ' + floor + ' replace');
    commands.push('setblock ' + (minX + 3) + ' ' + (y + 3) + ' ' + minZ + ' minecraft:lantern replace');
    commands.push('setblock ' + (maxX - 3) + ' ' + (y + 3) + ' ' + minZ + ' minecraft:lantern replace');
  } else if (openSide === 'east') {
    commands.push('fill ' + maxX + ' ' + (y + 2) + ' ' + (minZ + 4) + ' ' + maxX + ' ' + (y + 4) + ' ' + (maxZ - 4) + ' minecraft:air replace');
    commands.push('fill ' + (maxX + 1) + ' ' + (y + 1) + ' ' + (minZ + 3) + ' ' + (maxX + 3) + ' ' + (y + 1) + ' ' + (maxZ - 3) + ' ' + floor + ' replace');
    commands.push('setblock ' + maxX + ' ' + (y + 3) + ' ' + (minZ + 3) + ' minecraft:lantern replace');
    commands.push('setblock ' + maxX + ' ' + (y + 3) + ' ' + (maxZ - 3) + ' minecraft:lantern replace');
  } else {
    commands.push('fill ' + minX + ' ' + (y + 2) + ' ' + (minZ + 4) + ' ' + minX + ' ' + (y + 4) + ' ' + (maxZ - 4) + ' minecraft:air replace');
    commands.push('fill ' + (minX - 3) + ' ' + (y + 1) + ' ' + (minZ + 3) + ' ' + (minX - 1) + ' ' + (y + 1) + ' ' + (maxZ - 3) + ' ' + floor + ' replace');
    commands.push('setblock ' + minX + ' ' + (y + 3) + ' ' + (minZ + 3) + ' minecraft:lantern replace');
    commands.push('setblock ' + minX + ' ' + (y + 3) + ' ' + (maxZ - 3) + ' minecraft:lantern replace');
  }

  commands.push('setblock ' + midX + ' ' + (y + 5) + ' ' + midZ + ' minecraft:lantern replace');
}

function cuniculumLobbyAddTree(commands, y, x, z) {
  commands.push('fill ' + x + ' ' + (y + 1) + ' ' + z + ' ' + x + ' ' + (y + 4) + ' ' + z + ' minecraft:oak_log replace');
  commands.push('fill ' + (x - 2) + ' ' + (y + 4) + ' ' + (z - 2) + ' ' + (x + 2) + ' ' + (y + 5) + ' ' + (z + 2) + ' minecraft:azalea_leaves replace');
  commands.push('fill ' + (x - 1) + ' ' + (y + 6) + ' ' + (z - 1) + ' ' + (x + 1) + ' ' + (y + 6) + ' ' + (z + 1) + ' minecraft:flowering_azalea_leaves replace');
  commands.push('setblock ' + x + ' ' + (y + 7) + ' ' + z + ' minecraft:flowering_azalea_leaves replace');
}

function cuniculumLobbyAddLamp(commands, y, x, z) {
  commands.push('fill ' + x + ' ' + (y + 1) + ' ' + z + ' ' + x + ' ' + (y + 4) + ' ' + z + ' minecraft:spruce_fence replace');
  commands.push('setblock ' + x + ' ' + (y + 5) + ' ' + z + ' minecraft:lantern replace');
}

function cuniculumLobbyAddPlanter(commands, y, x, z, plant) {
  commands.push('setblock ' + x + ' ' + (y + 1) + ' ' + z + ' minecraft:moss_block replace');
  commands.push('setblock ' + x + ' ' + (y + 2) + ' ' + z + ' ' + plant + ' replace');
}

function cuniculumLobbyAddBench(commands, y, x, z, facing) {
  commands.push('setblock ' + x + ' ' + (y + 1) + ' ' + z + ' minecraft:spruce_stairs[facing=' + facing + '] replace');
  commands.push('setblock ' + (x + 1) + ' ' + (y + 1) + ' ' + z + ' minecraft:spruce_stairs[facing=' + facing + '] replace');
}

function cuniculumLobbyPrepareDecor(server) {
  if (!server) {
    return;
  }

  var y = CUNICULUM_LOBBY_PLATFORM_Y;
  var min = CUNICULUM_LOBBY_PLATFORM_MIN;
  var max = CUNICULUM_LOBBY_PLATFORM_MAX;
  var commands = [
    'fill ' + min + ' ' + (y - 3) + ' ' + min + ' ' + max + ' ' + (y - 1) + ' ' + max + ' minecraft:cobbled_deepslate replace',
    'fill ' + min + ' ' + y + ' ' + min + ' ' + max + ' ' + y + ' ' + max + ' minecraft:deepslate_tiles replace',
    'fill -7 ' + y + ' ' + min + ' 7 ' + y + ' ' + max + ' minecraft:polished_deepslate replace',
    'fill ' + min + ' ' + y + ' -7 ' + max + ' ' + y + ' 7 minecraft:polished_deepslate replace',
    'fill -1 ' + y + ' ' + min + ' 1 ' + y + ' ' + max + ' minecraft:chiseled_deepslate replace',
    'fill ' + min + ' ' + y + ' -1 ' + max + ' ' + y + ' 1 minecraft:chiseled_deepslate replace',
    'fill -16 ' + y + ' -16 16 ' + y + ' 16 minecraft:stone_bricks replace',
    'fill -12 ' + y + ' -12 12 ' + y + ' 12 minecraft:smooth_stone replace',
    'fill -6 ' + y + ' -6 6 ' + y + ' 6 minecraft:smooth_quartz replace',
    'fill -3 ' + (y + 1) + ' -3 3 ' + (y + 4) + ' 3 minecraft:air replace',
    'setblock 0 ' + y + ' 0 minecraft:smooth_quartz replace',
    'fill -15 ' + (y + 1) + ' -15 -13 ' + (y + 1) + ' -13 minecraft:spruce_fence replace',
    'fill 13 ' + (y + 1) + ' -15 15 ' + (y + 1) + ' -13 minecraft:spruce_fence replace',
    'fill -15 ' + (y + 1) + ' 13 -13 ' + (y + 1) + ' 15 minecraft:spruce_fence replace',
    'fill 13 ' + (y + 1) + ' 13 15 ' + (y + 1) + ' 15 minecraft:spruce_fence replace',
    'setblock -14 ' + (y + 2) + ' -14 minecraft:lantern replace',
    'setblock 14 ' + (y + 2) + ' -14 minecraft:lantern replace',
    'setblock -14 ' + (y + 2) + ' 14 minecraft:lantern replace',
    'setblock 14 ' + (y + 2) + ' 14 minecraft:lantern replace',
    'fill -43 ' + y + ' -43 -34 ' + y + ' -34 minecraft:moss_block replace',
    'fill 34 ' + y + ' -43 43 ' + y + ' -34 minecraft:moss_block replace',
    'fill -43 ' + y + ' 34 -34 ' + y + ' 43 minecraft:moss_block replace',
    'fill 34 ' + y + ' 34 43 ' + y + ' 43 minecraft:moss_block replace',
    'fill -41 ' + (y + 1) + ' -41 -36 ' + (y + 1) + ' -36 minecraft:moss_carpet replace',
    'fill 36 ' + (y + 1) + ' -41 41 ' + (y + 1) + ' -36 minecraft:moss_carpet replace',
    'fill -41 ' + (y + 1) + ' 36 -36 ' + (y + 1) + ' 41 minecraft:moss_carpet replace',
    'fill 36 ' + (y + 1) + ' 36 41 ' + (y + 1) + ' 41 minecraft:moss_carpet replace',
    'fill -42 ' + y + ' 30 -34 ' + y + ' 32 minecraft:dark_prismarine replace',
    'fill 34 ' + y + ' 30 42 ' + y + ' 32 minecraft:dark_prismarine replace',
    'fill -41 ' + (y + 1) + ' 31 -35 ' + (y + 1) + ' 31 minecraft:water replace',
    'fill 35 ' + (y + 1) + ' 31 41 ' + (y + 1) + ' 31 minecraft:water replace',
    'setblock -38 ' + (y + 2) + ' 31 minecraft:lily_pad replace',
    'setblock 38 ' + (y + 2) + ' 31 minecraft:lily_pad replace'
  ];

  cuniculumLobbyAddHouse(commands, y, -38, -38, -18, -18, 'minecraft:amethyst_block', 'minecraft:dark_prismarine', 'minecraft:polished_deepslate', 'minecraft:purple_carpet', 'south');
  cuniculumLobbyAddHouse(commands, y, 18, -38, 38, -18, 'minecraft:polished_blackstone_bricks', 'minecraft:nether_bricks', 'minecraft:polished_deepslate', 'minecraft:red_carpet', 'south');
  cuniculumLobbyAddHouse(commands, y, -38, 18, -18, 38, 'minecraft:mossy_stone_bricks', 'minecraft:spruce_planks', 'minecraft:polished_deepslate', 'minecraft:green_carpet', 'north');
  cuniculumLobbyAddHouse(commands, y, 18, 18, 38, 38, 'minecraft:smooth_sandstone', 'minecraft:birch_planks', 'minecraft:polished_deepslate', 'minecraft:yellow_carpet', 'north');
  cuniculumLobbyAddHouse(commands, y, -10, -46, 10, -32, 'minecraft:stone_bricks', 'minecraft:dark_oak_planks', 'minecraft:polished_deepslate', 'minecraft:cyan_carpet', 'south');

  cuniculumLobbyAddTree(commands, y, -39, -40);
  cuniculumLobbyAddTree(commands, y, 39, -40);
  cuniculumLobbyAddTree(commands, y, -39, 40);
  cuniculumLobbyAddTree(commands, y, 39, 40);
  cuniculumLobbyAddTree(commands, y, -11, -18);
  cuniculumLobbyAddTree(commands, y, 11, -18);
  cuniculumLobbyAddTree(commands, y, -11, 18);
  cuniculumLobbyAddTree(commands, y, 11, 18);

  cuniculumLobbyAddLamp(commands, y, -10, -10);
  cuniculumLobbyAddLamp(commands, y, 10, -10);
  cuniculumLobbyAddLamp(commands, y, -10, 10);
  cuniculumLobbyAddLamp(commands, y, 10, 10);
  cuniculumLobbyAddLamp(commands, y, -17, -17);
  cuniculumLobbyAddLamp(commands, y, 17, -17);
  cuniculumLobbyAddLamp(commands, y, -17, 17);
  cuniculumLobbyAddLamp(commands, y, 17, 17);
  cuniculumLobbyAddLamp(commands, y, -2, -28);
  cuniculumLobbyAddLamp(commands, y, 2, -28);

  cuniculumLobbyAddPlanter(commands, y, -7, 13, 'minecraft:flowering_azalea');
  cuniculumLobbyAddPlanter(commands, y, 7, 13, 'minecraft:azalea');
  cuniculumLobbyAddPlanter(commands, y, -7, -13, 'minecraft:azalea');
  cuniculumLobbyAddPlanter(commands, y, 7, -13, 'minecraft:flowering_azalea');
  cuniculumLobbyAddBench(commands, y, -5, 12, 'south');
  cuniculumLobbyAddBench(commands, y, 3, 12, 'south');
  cuniculumLobbyAddBench(commands, y, -5, -14, 'north');
  cuniculumLobbyAddBench(commands, y, 3, -14, 'north');

  commands.push('setblock -28 ' + (y + 2) + ' -28 minecraft:enchanting_table replace');
  commands.push('fill -34 ' + (y + 2) + ' -34 -34 ' + (y + 4) + ' -22 minecraft:bookshelf replace');
  commands.push('fill -22 ' + (y + 2) + ' -34 -22 ' + (y + 4) + ' -22 minecraft:bookshelf replace');
  commands.push('setblock -28 ' + (y + 2) + ' -20 minecraft:lectern[facing=south] replace');
  commands.push('setblock -20 ' + (y + 2) + ' -20 minecraft:barrel[facing=south] replace');

  commands.push('setblock 28 ' + (y + 2) + ' -28 minecraft:smithing_table replace');
  commands.push('setblock 32 ' + (y + 2) + ' -28 minecraft:anvil replace');
  commands.push('setblock 24 ' + (y + 2) + ' -28 minecraft:grindstone[face=floor,facing=south] replace');
  commands.push('setblock 28 ' + (y + 2) + ' -20 minecraft:barrel[facing=south] replace');
  commands.push('setblock 34 ' + (y + 2) + ' -20 minecraft:chest[facing=south] replace');

  commands.push('setblock -28 ' + (y + 2) + ' 28 minecraft:barrel[facing=north] replace');
  commands.push('setblock -32 ' + (y + 2) + ' 28 minecraft:chest[facing=north] replace');
  commands.push('setblock -24 ' + (y + 2) + ' 28 minecraft:crafting_table replace');
  commands.push('setblock -28 ' + (y + 2) + ' 22 minecraft:cauldron replace');
  commands.push('setblock -34 ' + (y + 2) + ' 22 minecraft:fletching_table replace');

  commands.push('setblock 28 ' + (y + 2) + ' 28 minecraft:lectern[facing=north] replace');
  commands.push('fill 22 ' + (y + 2) + ' 34 34 ' + (y + 3) + ' 34 minecraft:bookshelf replace');
  commands.push('setblock 22 ' + (y + 2) + ' 22 minecraft:cartography_table replace');
  commands.push('setblock 34 ' + (y + 2) + ' 22 minecraft:barrel[facing=north] replace');

  commands.push('setblock -4 ' + (y + 2) + ' -40 minecraft:lectern[facing=south] replace');
  commands.push('setblock 4 ' + (y + 2) + ' -40 minecraft:bell[attachment=floor,facing=south] replace');
  commands.push('setblock 0 ' + (y + 2) + ' -36 minecraft:lodestone replace');
  commands.push('setblock -7 ' + (y + 2) + ' -34 minecraft:cartography_table replace');
  commands.push('setblock 7 ' + (y + 2) + ' -34 minecraft:barrel[facing=south] replace');

  commands.push('fill -3 ' + (y + 1) + ' -3 3 ' + (y + 4) + ' 3 minecraft:air replace');
  commands.push('setblock 0 ' + y + ' 0 minecraft:smooth_quartz replace');

  for (var i = 0; i < commands.length; i++) {
    cuniculumLobbyCommand(server, CUNICULUM_LOBBY_DIMENSION, commands[i]);
  }
}
function cuniculumLobbyIsPortalPad(player) {
  if (!player) {
    return false;
  }
  var x = Number(player.x);
  var y = Number(player.y);
  var z = Number(player.z);
  if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z)) {
    return false;
  }
  return x >= CUNICULUM_PORTAL_PAD_MIN_X && x <= CUNICULUM_PORTAL_PAD_MAX_X && z >= CUNICULUM_PORTAL_PAD_MIN_Z && z <= CUNICULUM_PORTAL_PAD_MAX_Z && y >= CUNICULUM_LOBBY_PLATFORM_Y && y <= CUNICULUM_LOBBY_PLATFORM_Y + 5;
}

function cuniculumLobbyBypassesTeleportWarmup(player) {
  try {
    if (player.hasPermissions(2)) {
      return true;
    }
  } catch (ignored) { }

  try {
    if (player.hasPermission('cuniculum.rank.owner') || player.hasPermission('cuniculum.rank.admin')) {
      return true;
    }
  } catch (ignored) { }

  try {
    if (Number(player.permissionLevel) >= 2) {
      return true;
    }
  } catch (ignored) { }

  return false;
}

function cuniculumLobbyCanForceRtp(source) {
  try {
    if (source && source.hasPermission(2)) {
      return true;
    }
  } catch (ignored) { }

  var player = null;
  try { player = source.getPlayer(); } catch (ignored) { }
  if (!player) {
    return true;
  }

  return cuniculumLobbyBypassesTeleportWarmup(player);
}

function cuniculumLobbyOnlinePlayer(server, playerName) {
  var safeName = cuniculumLobbySafeName(playerName);
  if (!server || !safeName) {
    return null;
  }

  var candidates = [];
  try { candidates.push(server.getPlayer(safeName)); } catch (ignored) { }
  try { candidates.push(server.players); } catch (ignored) { }
  try { candidates.push(server.getPlayerList().getPlayers()); } catch (ignored) { }

  for (var i = 0; i < candidates.length; i++) {
    var candidate = candidates[i];
    if (!candidate) {
      continue;
    }

    try {
      if (cuniculumLobbySafeName(candidate.username).toLowerCase() === safeName.toLowerCase()) {
        return candidate;
      }
    } catch (ignored) { }

    try {
      for (var j = 0; j < candidate.length; j++) {
        var player = candidate[j];
        if (player && cuniculumLobbySafeName(player.username).toLowerCase() === safeName.toLowerCase()) {
          return player;
        }
      }
    } catch (ignored) { }
  }

  return null;
}

function cuniculumLobbyForceRtp(ctx, targetName) {
  var source = ctx.getSource();
  var server = source.getServer();
  var safeTarget = cuniculumLobbySafeName(targetName);
  if (!server || !safeTarget) {
    return 0;
  }

  if (!cuniculumLobbyCanForceRtp(source)) {
    try {
      var deniedPlayer = source.getPlayer();
      cuniculumLobbyTell(server, deniedPlayer.username, '[CUNICULUM] No tienes permiso para forzar RTP a otros jugadores.', 'red');
    } catch (ignored) { }
    return 0;
  }

  var target = cuniculumLobbyOnlinePlayer(server, safeTarget);
  if (!target) {
    try {
      var actor = source.getPlayer();
      cuniculumLobbyTell(server, actor.username, '[CUNICULUM] Jugador no encontrado o no esta conectado: ' + safeTarget + '.', 'red');
    } catch (ignored) { }
    return 0;
  }

  cuniculumLobbyRtpOverworld(server, target, '[CUNICULUM] Un miembro del staff te envio a una ubicacion aleatoria.', true);
  try {
    var actorName = cuniculumLobbySafeName(source.getPlayer().username);
    if (actorName) {
      cuniculumLobbyTell(server, actorName, '[CUNICULUM] RTP forzado aplicado a ' + safeTarget + '.', 'gold');
    }
  } catch (ignored) { }
  return 1;
}

function cuniculumLobbyPlayerMoved(player, startDimension, startX, startY, startZ) {
  if (!player || cuniculumLobbyDimensionFromEntity(player) !== startDimension) {
    return true;
  }
  var dx = Number(player.x) - startX;
  var dy = Number(player.y) - startY;
  var dz = Number(player.z) - startZ;
  if (!Number.isFinite(dx) || !Number.isFinite(dy) || !Number.isFinite(dz)) {
    return true;
  }
  return (dx * dx + dz * dz) > (CUNICULUM_RTP_MOVE_CANCEL_DISTANCE * CUNICULUM_RTP_MOVE_CANCEL_DISTANCE) || Math.abs(dy) > 0.75;
}

function cuniculumLobbyRtpWarmup(server, player, reasonText) {
  if (!server || !player) {
    return false;
  }

  var name = cuniculumLobbySafeName(player.username);
  if (!name) {
    return false;
  }

  cuniculumLobbyPrepareMainWorldBorders(server);

  if (cuniculumLobbyBypassesTeleportWarmup(player)) {
    return cuniculumLobbyRtpOverworld(server, player, reasonText);
  }

  if (!cuniculumLobbyRtpAcquireLock(player, CUNICULUM_RTP_WARMUP_TICKS + CUNICULUM_RTP_LOCK_TICKS)) {
    cuniculumLobbyTitle(server, name, 'actionbar', 'Espera antes de volver a usar /rtp.', 'red');
    return false;
  }

  var startDimension = cuniculumLobbyDimensionFromEntity(player);
  var startX = Number(player.x);
  var startY = Number(player.y);
  var startZ = Number(player.z);

  cuniculumLobbyTitle(server, name, 'title', 'Quedate quieto', 'gold');
  cuniculumLobbyTitle(server, name, 'subtitle', 'Buscando zona segura...', 'yellow');
  cuniculumLobbyTitle(server, name, 'actionbar', 'RTP casi inmediato. No te muevas.', 'aqua');
  server.scheduleInTicks(CUNICULUM_RTP_WARMUP_TICKS, function () {
    if (cuniculumLobbyPlayerMoved(player, startDimension, startX, startY, startZ)) {
      cuniculumLobbyTitle(server, name, 'title', 'RTP cancelado', 'red');
      cuniculumLobbyTitle(server, name, 'subtitle', 'Te moviste durante la espera.', 'gray');
      return;
    }
    cuniculumLobbyRtpOverworld(server, player, reasonText, true);
  });

  return true;
}
function cuniculumLobbyPrepared(server) {
  try {
    return !!server.persistentData[CUNICULUM_LOBBY_PREPARED_TAG];
  } catch (ignored) {
    return false;
  }
}

function cuniculumLobbyMarkPrepared(server) {
  try {
    server.persistentData[CUNICULUM_LOBBY_PREPARED_TAG] = true;
  } catch (ignored) { }
}

function cuniculumLobbyRepairWithCooldown(server, cooldownMs) {
  if (!server) {
    return false;
  }
  var now = Date.now();
  var delay = Math.max(5000, Number(cooldownMs || 30000));
  try {
    var last = Number(server.persistentData[CUNICULUM_LOBBY_REPAIR_MS_TAG] || 0);
    if (last + delay > now) {
      return false;
    }
    server.persistentData[CUNICULUM_LOBBY_REPAIR_MS_TAG] = now;
  } catch (ignored) { }
  return cuniculumLobbyPrepare(server, false);
}

function cuniculumLobbyPrepare(server, force) {
  if (!server || (!force && cuniculumLobbyPrepared(server))) {
    return false;
  }

  var min = CUNICULUM_LOBBY_PLATFORM_MIN;
  var max = CUNICULUM_LOBBY_PLATFORM_MAX;
  var y = CUNICULUM_LOBBY_PLATFORM_Y;
  var commands = [
    'forceload add -96 -96 95 95',
    'worldborder center 0 0',
    'worldborder set ' + CUNICULUM_LOBBY_BORDER_DIAMETER,
    'gamerule spawnRadius 0',
    'setworldspawn ' + CUNICULUM_LOBBY_X + ' ' + CUNICULUM_LOBBY_Y + ' ' + CUNICULUM_LOBBY_Z,
    'fill -96 ' + y + ' -96 96 ' + (y + 3) + ' -48 minecraft:air replace',
    'fill -96 ' + y + ' 47 96 ' + (y + 3) + ' 96 minecraft:air replace',
    'fill -96 ' + y + ' -47 -48 ' + (y + 3) + ' 46 minecraft:air replace',
    'fill 47 ' + y + ' -47 96 ' + (y + 3) + ' 46 minecraft:air replace',
    'fill ' + min + ' ' + (y + 1) + ' ' + min + ' ' + max + ' ' + (y + 14) + ' ' + max + ' minecraft:air replace',
    'fill ' + min + ' ' + y + ' ' + min + ' ' + max + ' ' + y + ' ' + max + ' minecraft:deepslate_tiles replace',
    'fill ' + min + ' ' + (y + 1) + ' ' + min + ' ' + max + ' ' + (y + 1) + ' ' + min + ' minecraft:polished_blackstone_wall replace',
    'fill ' + min + ' ' + (y + 1) + ' ' + max + ' ' + max + ' ' + (y + 1) + ' ' + max + ' minecraft:polished_blackstone_wall replace',
    'fill ' + min + ' ' + (y + 1) + ' ' + (min + 1) + ' ' + min + ' ' + (y + 1) + ' ' + (max - 1) + ' minecraft:polished_blackstone_wall replace',
    'fill ' + max + ' ' + (y + 1) + ' ' + (min + 1) + ' ' + max + ' ' + (y + 1) + ' ' + (max - 1) + ' minecraft:polished_blackstone_wall replace',
    'setblock 0 ' + y + ' 0 minecraft:smooth_quartz replace',
    'fill -3 ' + (y + 1) + ' -3 3 ' + (y + 4) + ' 3 minecraft:air replace',
    'setblock ' + min + ' ' + (y + 1) + ' ' + min + ' minecraft:lantern replace',
    'setblock ' + max + ' ' + (y + 1) + ' ' + min + ' minecraft:lantern replace',
    'setblock ' + min + ' ' + (y + 1) + ' ' + max + ' minecraft:lantern replace',
    'setblock ' + max + ' ' + (y + 1) + ' ' + max + ' minecraft:lantern replace',
    'kill @e[type=minecraft:item,x=0,y=' + y + ',z=0,distance=..128]'
  ];

  for (var i = 0; i < commands.length; i++) {
    cuniculumLobbyCommand(server, CUNICULUM_LOBBY_DIMENSION, commands[i]);
  }

  cuniculumLobbyKeepDay(server);
  cuniculumLobbyPreparePortal(server);
  cuniculumLobbyPrepareDecor(server);
  cuniculumLobbyPrepareTextDisplays(server);
  cuniculumLobbyMarkPrepared(server);
  return true;
}

function cuniculumLobbyPrepareMainWorldBorders(server) {
  if (!server) {
    return;
  }

  cuniculumLobbyCommand(server, 'minecraft:overworld', 'worldborder center 0 0');
  cuniculumLobbyCommand(server, 'minecraft:overworld', 'worldborder set ' + CUNICULUM_MAIN_WORLD_BORDER_DIAMETER);
  cuniculumLobbyCommand(server, 'minecraft:the_nether', 'worldborder center 0 0');
  cuniculumLobbyCommand(server, 'minecraft:the_nether', 'worldborder set ' + CUNICULUM_MAIN_WORLD_BORDER_DIAMETER);
}
function cuniculumLobbySetPlayerSpawn(server, player) {
  if (!server || !player) {
    return;
  }
  var name = cuniculumLobbySafeName(player.username);
  if (!name) {
    return;
  }
  cuniculumLobbyCommand(server, CUNICULUM_LOBBY_DIMENSION, 'spawnpoint ' + name + ' ' + CUNICULUM_LOBBY_X + ' ' + CUNICULUM_LOBBY_Y + ' ' + CUNICULUM_LOBBY_Z);
}

function cuniculumLobbyTeleport(server, player, reasonText) {
  if (!server || !player) {
    return;
  }
  var name = cuniculumLobbySafeName(player.username);
  if (!name) {
    return;
  }
  cuniculumLobbyCommand(server, CUNICULUM_LOBBY_DIMENSION, 'tp ' + name + ' ' + CUNICULUM_LOBBY_X + ' ' + CUNICULUM_LOBBY_Y + ' ' + CUNICULUM_LOBBY_Z);
  if (reasonText) {
    cuniculumLobbyTell(server, name, reasonText, 'gold');
  }
}

function cuniculumLobbyTryFirstTeleport(server, player) {
  if (!server || !player) {
    return false;
  }

  try {
    if (player.persistentData[CUNICULUM_LOBBY_FIRST_TP_TAG]) {
      return false;
    }
  } catch (ignored) { }

  if (!cuniculumLobbyIsAuthenticated(player)) {
    return false;
  }

  cuniculumLobbyPrepareMainWorldBorders(server);
  cuniculumLobbyPrepare(server, false);
  cuniculumLobbySetPlayerSpawn(server, player);

  try {
    player.persistentData[CUNICULUM_LOBBY_FIRST_TP_TAG] = true;
  } catch (ignored) { }

  var name = cuniculumLobbySafeName(player.username);
  if (name) {
    server.runCommandSilent('effect give ' + name + ' minecraft:slow_falling 10 0 true');
    server.runCommandSilent('effect give ' + name + ' minecraft:resistance 10 4 true');
  }

  cuniculumLobbyTeleport(server, player, '');
  return true;
}

function cuniculumLobbyRandomInt(min, max) {
  return Math.floor(min + Math.random() * (max - min + 1));
}

function cuniculumLobbyRtpCenter() {
  var angle = Math.random() * Math.PI * 2;
  var distance = cuniculumLobbyRandomInt(CUNICULUM_RTP_MIN_RANGE, CUNICULUM_RTP_MAX_RANGE);
  return {
    x: Math.round(Math.cos(angle) * distance),
    z: Math.round(Math.sin(angle) * distance)
  };
}

function cuniculumLobbyRtpAcquireLock(player, lockTicks) {
  try {
    var now = Number(player.age) || 0;
    var lockedUntil = Number(player.persistentData[CUNICULUM_RTP_LOCK_TAG]) || 0;
    if (now > 0 && lockedUntil > now) {
      return false;
    }
    player.persistentData[CUNICULUM_RTP_LOCK_TAG] = now + (Number(lockTicks) || CUNICULUM_RTP_LOCK_TICKS);
  } catch (ignored) { }
  return true;
}
function cuniculumLobbyRtpOverworld(server, player, reasonText, skipLock) {
  if (!server || !player) {
    return false;
  }

  var name = cuniculumLobbySafeName(player.username);
  if (!name) {
    return false;
  }

  if (!skipLock && !cuniculumLobbyRtpAcquireLock(player)) {
    return false;
  }

  cuniculumLobbyPrepareMainWorldBorders(server);

  var center = cuniculumLobbyRtpCenter();
  cuniculumLobbyCommand(server, 'minecraft:overworld', 'spreadplayers ' + center.x + ' ' + center.z + ' 1 ' + CUNICULUM_RTP_SPREAD_RANGE + ' false ' + name);
  if (reasonText) {
    cuniculumLobbyTell(server, name, reasonText, 'aqua');
  }
  return true;
}

function cuniculumLobbyEntityUuid(entity) {
  var values = [];
  try { values.push(entity.uuid); } catch (ignored) { }
  try { values.push(entity.stringUUID); } catch (ignored) { }
  try { values.push(entity.getUUID()); } catch (ignored) { }
  try { values.push(entity.getStringUUID()); } catch (ignored) { }

  for (var i = 0; i < values.length; i++) {
    var text = cuniculumLobbySafeString(values[i]).toLowerCase();
    if (text === CUNICULUM_RTP_NPC_UUID) {
      return text;
    }
  }
  return '';
}
function cuniculumLobbySpawnType(event) {
  var values = [];
  try { values.push(event.type); } catch (ignored) { }
  try { values.push(event.getType()); } catch (ignored) { }

  for (var i = 0; i < values.length; i++) {
    var text = cuniculumLobbySafeString(values[i]).toUpperCase();
    if (text) {
      return text;
    }
  }

  return '';
}

function cuniculumLobbyBlocksNaturalSpawn(spawnType) {
  if (!spawnType) {
    return false;
  }
  for (var i = 0; i < CUNICULUM_LOBBY_BLOCKED_SPAWN_TYPES.length; i++) {
    if (spawnType.indexOf(CUNICULUM_LOBBY_BLOCKED_SPAWN_TYPES[i]) !== -1) {
      return true;
    }
  }
  return false;
}

function cuniculumLobbyIsPlayer(entity) {
  if (!entity) {
    return false;
  }
  try {
    if (entity.isPlayer()) {
      return true;
    }
  } catch (ignored) { }
  try {
    return cuniculumLobbySafeString(entity.type) === 'minecraft:player';
  } catch (ignored) {
    return false;
  }
}

function cuniculumLobbyDamageAttacker(event) {
  var source = null;
  var values = [];
  try { source = event.source; } catch (ignored) { }
  if (!source) {
    return null;
  }

  try { values.push(source.actual); } catch (ignored) { }
  try { values.push(source.entity); } catch (ignored) { }
  try { values.push(source.player); } catch (ignored) { }
  try { values.push(source.getEntity()); } catch (ignored) { }
  try { values.push(source.getDirectEntity()); } catch (ignored) { }

  for (var i = 0; i < values.length; i++) {
    if (cuniculumLobbyIsPlayer(values[i])) {
      return values[i];
    }
  }

  return null;
}

function cuniculumLobbyDimensionFromEvent(event) {
  var dimension = '';
  try { dimension = cuniculumLobbyDimensionFromLevel(event.level); } catch (ignored) { }
  if (dimension) {
    return dimension;
  }

  try { dimension = cuniculumLobbyDimensionFromLevel(event.block.level); } catch (ignored) { }
  if (dimension) {
    return dimension;
  }

  try { dimension = cuniculumLobbyDimensionFromEntity(event.player); } catch (ignored) { }
  if (dimension) {
    return dimension;
  }

  return '';
}

function cuniculumLobbyRepairProtectedBuild(event) {
  var server = null;
  try { server = event.server; } catch (ignored) { }
  try { if (!server && event.player) { server = event.player.server; } } catch (ignored) { }
  if (!server) {
    return;
  }

  server.scheduleInTicks(1, function () {
    cuniculumLobbyPrepare(server, true);
  });
}

function cuniculumLobbyCancelBuild(event, message, repair) {
  if (!event || cuniculumLobbyDimensionFromEvent(event) !== CUNICULUM_LOBBY_DIMENSION) {
    return;
  }

  try { event.cancel(); } catch (ignored) { }
  if (repair) {
    cuniculumLobbyRepairProtectedBuild(event);
  }

  try {
    var player = event.player;
    var name = player ? cuniculumLobbySafeName(player.username) : '';
    var server = event.server || (player ? player.server : null);
    if (server && name) {
      cuniculumLobbyTitle(server, name, 'actionbar', message || 'El lobby esta protegido.', 'yellow');
    }
  } catch (ignored) { }
}

BlockEvents.leftClicked(function (event) {
  cuniculumLobbyCancelBuild(event, 'El lobby esta protegido: no puedes romper bloques aqui.');
});

BlockEvents.broken(function (event) {
  cuniculumLobbyCancelBuild(event, 'El lobby esta protegido: no puedes romper bloques aqui.', false);
});

BlockEvents.placed(function (event) {
  cuniculumLobbyCancelBuild(event, 'El lobby esta protegido: no puedes colocar bloques aqui.', false);
});

ServerEvents.loaded(function (event) {
  var server = event.server;
  server.scheduleInTicks(1, function () {
    cuniculumLobbyPrepareMainWorldBorders(server);
    cuniculumLobbyCommand(server, CUNICULUM_LOBBY_DIMENSION, 'gamerule spawnRadius 0');
    cuniculumLobbyPrepare(server, false);
  });
  server.scheduleInTicks(20, function () {
    cuniculumLobbyPrepareMainWorldBorders(server);
    cuniculumLobbyPrepare(server, false);
  });
  server.scheduleInTicks(100, function () {
    cuniculumLobbyPrepareMainWorldBorders(server);
    cuniculumLobbyCommand(server, CUNICULUM_LOBBY_DIMENSION, 'gamerule spawnRadius 0');
    cuniculumLobbyPrepare(server, false);
  });
  server.scheduleInTicks(300, function () {
    cuniculumLobbyPrepareMainWorldBorders(server);
    cuniculumLobbyPrepare(server, false);
  });
});
ServerEvents.commandRegistry(function (event) {
  var commands = event.commands;
  var args = event.arguments;

  event.register(
    commands.literal('cunispawn')
      .requires(function (source) { return source.hasPermission(2); })
      .then(commands.literal('prepare')
        .executes(function (ctx) {
          var server = ctx.getSource().getServer();
          cuniculumLobbyPrepareMainWorldBorders(server);
          cuniculumLobbyPrepare(server, true);
          server.runCommandSilent('tellraw @a ' + cuniculumLobbyJson('[CUNICULUM] Mundo spawn vacio preparado: plataforma 94x94, Overworld/Nether radio 10000.', 'gold'));
          return 1;
        }))
      .then(commands.literal('tp')
        .executes(function (ctx) {
          var source = ctx.getSource();
          var server = source.getServer();
          var player = source.getPlayer();
          cuniculumLobbyPrepare(server, false);
          cuniculumLobbyTeleport(server, player, '[CUNICULUM] Te movi al lobby seguro.');
          return 1;
        }))
  );

  event.register(
    commands.literal('spawn')
      .executes(function (ctx) {
        var source = ctx.getSource();
        var server = source.getServer();
        var player = source.getPlayer();
        cuniculumLobbyPrepare(server, false);
        cuniculumLobbyTeleport(server, player, '[CUNICULUM] Volviste al spawn seguro.');
        return 1;
      })
  );

  event.register(
    commands.literal('rtp')
      .executes(function (ctx) {
        var source = ctx.getSource();
        var server = source.getServer();
        var player = source.getPlayer();
        var dimension = cuniculumLobbyDimensionFromEntity(player);

        if (dimension === 'minecraft:the_nether') {
          cuniculumLobbyTell(server, player.username, '[CUNICULUM] /rtp solo funciona desde spawn u Overworld. En Nether esta deshabilitado.', 'red');
          return 0;
        }

        if (dimension === 'minecraft:the_end') {
          cuniculumLobbyTeleport(server, player, '[CUNICULUM] The End sigue bloqueado. Volviste al lobby seguro.');
          return 0;
        }

        cuniculumLobbyRtpWarmup(server, player, '[CUNICULUM] Viaje aleatorio al Overworld iniciado.');
        return 1;
      })
      .then(commands.argument('jugador', args.STRING.create(event))
        .requires(function (source) { return cuniculumLobbyCanForceRtp(source); })
        .executes(function (ctx) {
          return cuniculumLobbyForceRtp(ctx, args.STRING.getResult(ctx, 'jugador'));
        }))
  );
});
PlayerEvents.loggedIn(function (event) {
  var player = event.player;
  var server = event.server;
  if (!player || !server) {
    return;
  }

  cuniculumLobbyPrepareMainWorldBorders(server);
  cuniculumLobbyPrepare(server, false);
  cuniculumLobbySetPlayerSpawn(server, player);
  var loginName = cuniculumLobbySafeName(player.username);
  if (loginName) {
    server.runCommandSilent('effect give ' + loginName + ' minecraft:slow_falling 12 0 true');
    server.runCommandSilent('effect give ' + loginName + ' minecraft:resistance 12 4 true');
  }
  server.scheduleInTicks(10, function () {
    cuniculumLobbyPrepareMainWorldBorders(server);
    cuniculumLobbyPrepare(server, false);
    cuniculumLobbySetPlayerSpawn(server, player);
  });
  server.scheduleInTicks(40, function () {
    cuniculumLobbyPrepareMainWorldBorders(server);
    cuniculumLobbyPrepare(server, false);
    cuniculumLobbySetPlayerSpawn(server, player);
  });
  server.scheduleInTicks(80, function () {
    cuniculumLobbyTryFirstTeleport(server, player);
  });
  server.scheduleInTicks(160, function () {
    cuniculumLobbyTryFirstTeleport(server, player);
  });
  server.scheduleInTicks(300, function () {
    cuniculumLobbyTryFirstTeleport(server, player);
  });
  server.scheduleInTicks(600, function () {
    cuniculumLobbyTryFirstTeleport(server, player);
  });
  server.scheduleInTicks(1200, function () {
    cuniculumLobbyTryFirstTeleport(server, player);
  });
});

PlayerEvents.respawned(function (event) {
  var player = event.player;
  var server = event.server;
  if (!player || !server) {
    return;
  }
  server.scheduleInTicks(20, function () {
    cuniculumLobbyPrepareMainWorldBorders(server);
    cuniculumLobbySetPlayerSpawn(server, player);
  });
});

PlayerEvents.tick(function (event) {
  var player = event.player;
  var server = event.server;
  if (!player || !server || player.age % 5 !== 0) {
    return;
  }

  var dimension = cuniculumLobbyDimensionFromEntity(player);

        if (dimension === 'minecraft:the_end') {
    cuniculumLobbyTeleport(server, player, '[CUNICULUM] The End sigue bloqueado. Volviste al lobby seguro.');
    return;
  }

  try {
    if (!player.persistentData[CUNICULUM_LOBBY_FIRST_TP_TAG] && player.age % 20 === 0) {
      cuniculumLobbyTryFirstTeleport(server, player);
    }
  } catch (ignored) { }

  if (dimension !== CUNICULUM_LOBBY_DIMENSION) {
    return;
  }

  if (player.age % 20 === 0) {
    cuniculumLobbyPrepare(server, false);
  }

  if (player.age % 200 === 0) {
    cuniculumLobbyRepairWithCooldown(server, 30000);
  }

  if (player.age % 200 === 0) {
    cuniculumLobbyKeepDay(server);
  }

  if (player.age % 80 === 0) {
    var name = cuniculumLobbySafeName(player.username);
    server.runCommandSilent('effect give ' + name + ' minecraft:regeneration 5 1 true');
    server.runCommandSilent('effect give ' + name + ' minecraft:saturation 5 1 true');
  }

  try {
    if (Number(player.y) < CUNICULUM_LOBBY_PLATFORM_Y - 4) {
      cuniculumLobbyPrepare(server, false);
      cuniculumLobbyTeleport(server, player, '[CUNICULUM] Piso del lobby regenerado. Te devolvi al spawn seguro.');
    }
  } catch (ignored) { }
});

ItemEvents.entityInteracted(function (event) {
  var player = event.player;
  var server = event.server;
  var target = null;

  try { target = event.target; } catch (ignored) { }
  try { if (!target) { target = event.entity; } } catch (ignored) { }
  try { if (!target) { target = event.getTarget(); } } catch (ignored) { }
  try { if (!server && player) { server = player.server; } } catch (ignored) { }

  if (!player || !server || cuniculumLobbyEntityUuid(target) !== CUNICULUM_RTP_NPC_UUID) {
    return;
  }

  cuniculumLobbyRtpOverworld(server, player, '[CUNICULUM] El guia abrio una ruta aleatoria al Overworld.');
  try { event.cancel(); } catch (ignored) { }
});
EntityEvents.checkSpawn(function (event) {
  var entity = event.entity;
  if (!entity || cuniculumLobbyDimensionFromEntity(entity) !== CUNICULUM_LOBBY_DIMENSION) {
    return;
  }

  if (cuniculumLobbyBlocksNaturalSpawn(cuniculumLobbySpawnType(event))) {
    event.cancel();
  }
});

EntityEvents.beforeHurt(function (event) {
  var target = event.entity;
  if (cuniculumLobbyDimensionFromEntity(target) !== CUNICULUM_LOBBY_DIMENSION) {
    return;
  }

  event.cancel();
});
