package com.lifeknight.relaymchub.player; import com.lifeknight.relaymchub.ExtraListeners; import com.lifeknight.relaymchub.Main; import com.lifeknight.relaymchub.commands.menu.KitCommand; import com.lifeknight.relaymchub.cosmetics.Cosmetics; import com.lifeknight.relaymchub.cosmetics.DefinedLobbyCosmetic; import com.lifeknight.relaymchub.miscellaneous.Cooldown; import com.lifeknight.relaymchub.miscellaneous.GameKit; import com.lifeknight.relaymchub.miscellaneous.SmartGUIUtils; import com.lifeknight.relaymchub.statistics.StatisticsLeaderboard; import com.lifeknight.relaymcutils.RelayMCUtils; import com.lifeknight.relaymcutils.network.ServerCommunicator; import com.lifeknight.relaymcutils.player.*; import com.lifeknight.relaymcutils.player.commands.CommandUtilities; import com.lifeknight.relaymcutils.player.settings.GameSettings; import com.lifeknight.relaymcutils.utilities.Parkour; import com.lifeknight.relayutils.RelayUtils; import com.lifeknight.relayutils.basic.Miscellaneous; import com.lifeknight.relayutils.basic.SwearUtils; import com.lifeknight.relayutils.basic.Text; import com.lifeknight.relayutils.data.PartyData; import com.lifeknight.relayutils.data.QueueData; import com.lifeknight.relayutils.filter.*; import com.lifeknight.relayutils.game.*; import com.lifeknight.relayutils.network.Command; import com.lifeknight.relayutils.player.ExtraData; import com.lifeknight.relayutils.player.Group; import com.lifeknight.relayutils.player.cosmetics.*; import com.lifeknight.relayutils.player.data.GamePlayerDataColumn; import com.lifeknight.relayutils.player.data.ProfileColumn; import com.lifeknight.relayutils.player.data.SmartDatabase; import com.lifeknight.relayutils.utilities.ComponentBuilder; import com.lifeknight.relayutils.utilities.ItemUtilities; import com.lifeknight.relayutils.utilities.PlayerUtilities; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import net.kyori.adventure.inventory.Book; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.json.JSONComponentSerializer; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.HoverEvent; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagString; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.craftbukkit.v1_20_R1.CraftServer; import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionType; import org.bukkit.util.Vector; import java.sql.ResultSet; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import static com.lifeknight.relaymchub.miscellaneous.SmartGUIUtils.*; import static com.lifeknight.relaymchub.player.EditCustomKitGUI.getKitItemsForCategory; import static net.md_5.bungee.api.ChatColor.AQUA; import static net.md_5.bungee.api.ChatColor.GOLD; import static net.md_5.bungee.api.ChatColor.GREEN; import static net.md_5.bungee.api.ChatColor.YELLOW; import static org.bukkit.ChatColor.BLUE; import static org.bukkit.ChatColor.BOLD; import static org.bukkit.ChatColor.DARK_AQUA; import static org.bukkit.ChatColor.DARK_GRAY; import static org.bukkit.ChatColor.DARK_RED; import static org.bukkit.ChatColor.GRAY; import static org.bukkit.ChatColor.ITALIC; import static org.bukkit.ChatColor.LIGHT_PURPLE; import static org.bukkit.ChatColor.RED; import static org.bukkit.ChatColor.UNDERLINE; import static org.bukkit.ChatColor.WHITE; public class HubPlayer { public static final Map<UUID, HubPlayer> HUB_PLAYERS = new HashMap<>(); private final SmartPlayer smartPlayer; private final List<DefinedLobbyCosmetic> purchasedLobbyCosmetics = new ArrayList<>(); private final List<DefinedLobbyCosmetic> lobbyCosmetics = new ArrayList<>(); private final List<DefinedLobbyCosmetic> activeLobbyCosmetics = new ArrayList<>(); private final Map<String, Long> cooldowns = new HashMap<>(); public long connectTime = 0; private Map<GameAction, Number> overallStatistics = new HashMap<>(); private Map<SpecificGameAction, Number> specificStatistics = new HashMap<>(); private final List<Kit> kitConfigurations = new ArrayList<>(); private final List<CustomDuelsKit> customDuelKits = new ArrayList<>(); private boolean hasNoKits = false; private boolean hasNoMaps = false; private final List<CustomMap> customMaps = new ArrayList<>(); private EditCustomKitGUI lastEditKitGui = null; private boolean isVanished = false; private boolean isHidingOthers = false; private int points = 0; private double pvpArenaHealth = -1; private long experience = 0; private DynamicScoreboard dynamicScoreboard; private DynamicScoreboard queueScoreboard; private DynamicScoreboard arenaScoreboard; private int queuePosition = 0; private int queueSize = 0; private int specificPosition = 0; private int specificSize = 0; private QueueData queueData = null; public List<Map<GameAction, Number>> previousLeaderboardStats = new ArrayList<>(); public List<Map<String, Number>> previousLeaderboardExtraStats = new ArrayList<>(); public boolean firstDataRetrieve = false; private boolean beingSentToHell; private Location lastLocation; private GameType queueType; private int typeSize; private long lastArenaDamage; private PartyData partyData; private boolean serverAvailable; private GameType duelGameType; private boolean isCreatingCustomKitCreative; public boolean isCreatingCustomKit = false; private boolean reOpeningCustomKit; private boolean isCreatingCustomMap; public boolean teleportedToCustomMap = false; public Kit lobbyKit = Kits.DUELS_LOBBY_SWORD; private Kit nextKit = null; private boolean inCombat; private CustomDuelsKit selectedCustomDuelsKit; public Location customMapCenter; private int customMapSize = 35; private int customMapHeight = 50; private List<Block> customMapBlocks; private CustomMap customMapEdited; private Location customMapSpawnA; private Location customMapSpawnB; private String customMapName; private Material customMapRepresentative; private boolean newCustomMap; private boolean customMapVisibility; private Map<String, Number> arenaStats = new HashMap<>(); private boolean canRequeue = false; private boolean canSeePlayers = true; private long lastMovementTime = 0; public boolean AFKAgain = false; public boolean hasAFKMoved = false; private String limboQueuePosition = "Loading..."; private String limboQueueSize = ""; private Location previewCenter = null; public boolean isPreviewingMap = false; public boolean teleportedToPreviewMap = false; private final List<Block> previewMapBlocks = new ArrayList<>(); private UUID previewQueueOwner = null; private CustomDuelsKit previewKit = null; private PreviewCustomKitGUI previewCustomKitGUI = null; CustomMap previewMap = null; private CustomDuelsKit previewLibraryKit = null; private UUID queuedAgainst = null; private final int nickLevel = Miscellaneous.getRandomIntBetweenRange(1, 8); private final List<CustomDuelsKit> recentKits = new ArrayList<>(); private final List<CustomMap> recentMaps = new ArrayList<>(); private final Map<String, CustomMap> publicCustomMaps = new HashMap<>(); private final List<String> votedIDs = new ArrayList<>(); private QueuePreferences queuePreferences = new QueuePreferences(); private int timeFrame = 0; public List<HubPlayer> collaborationInvites = new ArrayList<>(); private Map<GameType, Long> eloMap = new HashMap<>(); private Map<GameType, Long> timeMap = new HashMap<>(); public HubPlayer(SmartPlayer smartPlayer) { this.smartPlayer = smartPlayer; this.smartPlayer.setOnRetrieveData(this::onDataRetrieve); this.smartPlayer.setOnParkourStart(this::onParkour); HUB_PLAYERS.put(this.getUUID(), this); } private void onParkour(Boolean end) { if (!end) { if (!this.getInventory().contains(Material.RED_BED)) { this.disableAllCosmetics(); this.smartPlayer.clear(); this.giveParkourItems(); } } else { this.spawn(false); } } private void giveParkourItems() { this.giveSmartItem(2, SmartGUIUtils.RESET); this.giveSmartItem(4, SmartGUIUtils.CHECKPOINT); this.giveSmartItem(6, SmartGUIUtils.EXIT); this.getInventory().setHeldItemSlot(4); } public static void onPlayerJoin(SmartPlayer smartPlayer) { if (smartPlayer == null) { Main.error("No player found on join"); } else { Main.synchronous(() -> getHubPlayer(smartPlayer).onJoin()); } } public static void onPlayerQuit(SmartPlayer smartPlayer) { getHubPlayer(smartPlayer).onDisconnect(); } public static HubPlayer getHubPlayer(Player player) { if (player == null) return null; return getHubPlayer(SmartPlayer.getSmartPlayer(player)); } public static HubPlayer getHubPlayer(SmartPlayer smartPlayer) { if (smartPlayer == null) return null; HubPlayer hubPlayer = getHubPlayer(smartPlayer.getUUID()); if (hubPlayer == null) return new HubPlayer(smartPlayer); return hubPlayer; } public static HubPlayer getHubPlayer(UUID uuid) { return HUB_PLAYERS.get(uuid); } public static HubPlayer getHubPlayer(String name) { if (name.length() > 16) { return getHubPlayer(UUID.fromString(name)); } return getHubPlayer(Bukkit.getPlayer(name)); } public static Collection<HubPlayer> getHubPlayers() { return HUB_PLAYERS.values(); } public static Collection<HubPlayer> getOnlineHubPlayers() { Collection<HubPlayer> hubPlayers = getHubPlayers(); hubPlayers.removeIf(hubPlayer -> !hubPlayer.smartPlayer.isOnline()); return hubPlayers; } public static void removeUnneededHubPlayers() { for (HubPlayer value : getHubPlayers()) { if (!SmartPlayer.getSmartPlayers().contains(value.smartPlayer)) { HUB_PLAYERS.remove(value.getUUID()); RelayMCUtils.info("Removed HubPlayer %s for inactivity.", value.getName()); } } } public static void onTick() { for (HubPlayer onlineHubPlayer : getOnlineHubPlayers()) { onlineHubPlayer.tick(); } } public void tick() { if (Main.ticks % 20 == 0 && Main.isLimbo()) { this.updateScoreboard(); } if (Main.ticks % 20 * 4 == 0) { if (this.isCreatingCustomMap) { this.renderCustomMapBorder(); } if (this.isPreviewingMap) { this.smartPlayer.sendActionBar("%sMap Code: %s%s%s", GOLD, AQUA, UNDERLINE, this.previewMap.getId()); } } if (this.hasNoMaps) { this.hasNoMaps = this.customMaps.isEmpty(); } if (this.hasNoKits) { this.hasNoKits = this.customDuelKits.isEmpty(); } if (Main.ticks % 30 == 0) { if (this.isVanished) { this.getPlayer().sendActionBar(WHITE + "You are " + BLUE + "VANISHED"); } else if (ExtraListeners.isInArena(this.getPlayer())) { this.getPlayer().sendActionBar(AQUA + (Main.isDuelsLobby() ? "Kills: " : "Points: ") + WHITE + this.points); } if (this.inArena() && this.getInventory().contains(Material.TRIDENT) && (this.lobbyKit != null && this.lobbyKit != Kits.DUELS_LOBBY_RETIARIUS)) { this.getInventory().remove(Material.TRIDENT); } } if (Main.ticks % 30 == 15) { if (Main.isLimbo() && !this.getPlayer().getCanPickupItems()) { this.getPlayer().sendActionBar(AQUA + "Move to join"); } else if (this.inArena()) { this.getPlayer().sendActionBar(YELLOW + "/spawn" + WHITE + " to return back to spawn"); } } if (Main.isDuelsLobby() && this.inArena() && this.lobbyKit == Kits.DUELS_LOBBY_NINJA) { this.addPotionEffect(PotionEffectType.SPEED, 1, 1); } for (DefinedLobbyCosmetic activeCosmetic : this.activeLobbyCosmetics) { activeCosmetic.tick(this); } lastLocation = getLocation(); if (this.isLastLeague(this.queueType)) { if (this.queueScoreboard != null) { this.queueScoreboard.update(); } if (this.dynamicScoreboard != null) { this.dynamicScoreboard.update(); } if (this.arenaScoreboard != null) { this.arenaScoreboard.update(); } } if (this.beingSentToHell && Main.ticks % 5 == 0) { this.playSound(Sound.BLOCK_NOTE_BLOCK_SNARE); } if (this.isCreatingCustomKitCreative || this.isCreatingCustomMap || this.isCreatingCustomKit || this.isInQueue()) { this.updateLastMovementTime(); } if (!Main.isLimbo()) { if (Main.ticks % 5 == 0 && this.lastMovementTime != 0 && Miscellaneous.enoughTimeHasPassed(this.lastMovementTime, 5, TimeUnit.MINUTES)) { if (Main.isLimbo() && !this.AFKAgain) { /* this.afkagain = true; ServerCommunicator.sendToProxy(Command.OTHER, "afkagain", this.getUUID()); this.sendErrorMessage("You have been removed from the queue due to being AFK."); */ } else { this.updateLastMovementTime(); this.sendErrorMessage("You have been sent to limbo for being AFK. Move to return to the lobby."); this.sendToServer("afk"); } } } } private boolean isInQueue() { return this.queueScoreboard != null; } public void getHistory() { if (Main.isLimbo()) return; Main.async(() -> { List<String> kits = Text.separateCSV((String) this.smartPlayer.getGamePlayerData(GamePlayerDataColumn.RECENT_DUELS_KITS)); this.recentKits.clear(); for (String kit : kits) { CustomDuelsKit customDuelsKit = CustomDuelsKit.getCustomDuelsKit(kit); if (customDuelsKit != null) { this.recentKits.add(customDuelsKit); } } this.recentMaps.clear(); for (String s : Text.separateCSV((String) this.smartPlayer.getGamePlayerData(GamePlayerDataColumn.RECENT_DUELS_MAPS))) { CustomMap customMap = CustomMap.getCustomMap(s); if (customMap != null) { this.recentMaps.add(customMap); } } this.votedIDs.clear(); this.votedIDs.addAll(Text.separateCSV((String) this.smartPlayer.getGamePlayerData(GamePlayerDataColumn.VOTED_IDS))); for (CustomDuelsKit customDuelsKit : Miscellaneous.getList(this.smartPlayer.getCustomDuelsKits())) { if (customDuelsKit.getPublicCustomMap() != null && !customDuelsKit.getPublicCustomMap().isEmpty()) { CustomMap customMap = CustomMap.getCustomMap(customDuelsKit.getPublicCustomMap()); this.publicCustomMaps.put(customDuelsKit.getPublicCustomMap(), customMap); } else { customDuelsKit.setPublicCustomMap(null); } } }); } public void onJoin() { Main.schedule(() -> this.hasAFKMoved = false, 2); this.lastMovementTime = System.currentTimeMillis(); this.limboQueuePosition = "Loading..."; this.isCreatingCustomKit = false; this.points = 0; this.canRequeue = false; for (HubPlayer onlineHubPlayer : getOnlineHubPlayers()) { if (onlineHubPlayer.isHidingOthers && !(this.smartPlayer.isStaff() && !this.isAndHasNick())) { onlineHubPlayer.hidePlayer(this); } if (this.isVanished && !onlineHubPlayer.isStaff()) { onlineHubPlayer.hidePlayer(this); } if (onlineHubPlayer.isVanished && !this.isStaff()) { this.hidePlayer(onlineHubPlayer); } } this.getPlayer().setCanPickupItems(false); for (int i = 0; i < 3; i++) { this.previousLeaderboardStats.add(new LinkedHashMap<>()); this.previousLeaderboardExtraStats.add(new LinkedHashMap<>()); } if (Main.isAboutToRestart) { this.playSound(Sound.BLOCK_NOTE_BLOCK_SNARE); this.sendMessage(new ComponentBuilder(ComponentBuilder.RED_ORANGE).line().newLine().color(ComponentBuilder.RED).append("This lobby will be restarting in %s.", Text.getShortTextualFormattedTime(RelayMCUtils.getShouldStartRealizeTime() + 60 * 1000L - System.currentTimeMillis())).newLine().color(ComponentBuilder.RED_ORANGE).line()); } if (Main.isLimbo()) { this.updateScoreboard(); this.getPlayer().setInvisible(true); this.getPlayer().setCustomNameVisible(true); } } public BaseComponent getComponentFormattedName() { return this.smartPlayer.getComponentFormattedName(); } public void broadcastLobbyJoinMessage() { ComponentBuilder message = new ComponentBuilder(); message.append("%s> %s> %s> ", GOLD, YELLOW, AQUA); message.append(this.getComponentFormattedName()).color(ComponentBuilder.AQUA).append(" has joined the lobby!"); message.append(" %s< %s< %s<", AQUA, YELLOW, GOLD); BaseComponent messageResult = message.getResult(); for (HubPlayer onlineHubPlayer : getOnlineHubPlayers()) { onlineHubPlayer.sendMessage(messageResult); } } public void onDataRetrieve() { getHistory(); this.updateExperienceBar(); this.updateScoreboard(); if (!this.isCreatingCustomMap) { Main.scheduleSyncDelayedTask(() -> this.smartPlayer.setAllowFlight(this.smartPlayer.isInGroupOrHigher(Group.TIERI)), 0.2); } this.getGameData(); if (this.arenaStats == null || this.arenaStats.isEmpty()) { this.arenaStats = this.smartPlayer.getArenaStats(); } if (!this.firstDataRetrieve && !Main.isLimbo()) { this.giveCosmetics(); if (getExtraData().has("vanish")) { this.setVanished(getExtraData().getBoolean("vanish", false)); if (this.isVanished) { this.vanish(); } } if (getExtraData().has("hideOthers")) { this.setHidingOthers(getExtraData().getBoolean("hideOthers", false)); } this.queuePreferences = new QueuePreferences(getExtraData()); if (getExtraData().has("lobbyKit")) { switch (getExtraData().getString("lobbyKit", "default")) { case "axe" -> this.lobbyKit = Kits.DUELS_LOBBY_AXE; case "ninja" -> this.lobbyKit = Kits.DUELS_LOBBY_NINJA; case "retiarius" -> this.lobbyKit = Kits.DUELS_LOBBY_RETIARIUS; case "archer" -> this.lobbyKit = Kits.DUELS_LOBBY_ARCHER; default -> this.lobbyKit = Kits.DUELS_LOBBY_SWORD; } } if (!Main.isLimbo() && this.isInGroupOrHigher(Group.CHAMPION) && !this.isAndHasNick() && !this.isVanished) { this.broadcastLobbyJoinMessage(); } } if (this.canRequeue) { } this.firstDataRetrieve = true; } private boolean inLimboQueue() { return !this.limboQueuePosition.equalsIgnoreCase("Loading..."); } public void updateScoreboard() { if (!this.isOnline()) { return; } if (this.dynamicScoreboard == null) { if (Main.isLimbo()) { this.dynamicScoreboard = new DynamicScoreboard(GRAY + BOLD.toString() + "LIMBO"); this.dynamicScoreboard.addPreLine(); this.dynamicScoreboard.addDynamicScore(() -> { if (this.inLimboQueue()) { return new ComponentBuilder("%s%s/%s%s", GREEN, this.limboQueuePosition, WHITE, this.limboQueueSize); } return new ComponentBuilder().append(RED).bold().append("AFK"); }); this.dynamicScoreboard.addDynamicScore(() -> { if (this.inLimboQueue()) { return new ComponentBuilder().color(ComponentBuilder.AQUA).append("Queue Position: "); } return new ComponentBuilder().color(ComponentBuilder.AQUA).append("Status:"); }); this.dynamicScoreboard.addPostLine(); } else { this.dynamicScoreboard = new DynamicScoreboard(GREEN + BOLD.toString() + Main.getScoreboardName()); this.dynamicScoreboard.addPreLine(); this.dynamicScoreboard.addDynamicScore(() -> new ComponentBuilder(RelayUtils.format("%sTokens: %s%s", GOLD, WHITE, Text.addCommasToNumber(this.smartPlayer.credits)))); this.dynamicScoreboard.addDynamicScore(() -> new ComponentBuilder("%sLevel: %s%s [%s%s%s/%s]", AQUA, WHITE, Text.addCommasToNumber(this.getLevel()), AQUA, Text.addCommasToNumber(this.getXpAfterLevels(), true), WHITE, Text.addCommasToNumber(this.getNextLevelXp(), true))); this.dynamicScoreboard.addBlankSpace(); this.dynamicScoreboard.addDynamicScore(() -> { ComponentBuilder componentBuilder; if (this.getHighestGroup() == Group.CHAMPION) { componentBuilder = new ComponentBuilder(this.smartPlayer.getChampionTier() > 1000 ? ComponentBuilder.PURPLE : RelayUtils.getChampionTierColor(this.smartPlayer.getChampionTier())); } else { componentBuilder = new ComponentBuilder(this.getHighestGroup().getOther()); } return componentBuilder.bold().append(this.getRealName()).append("!"); }); this.dynamicScoreboard.addScore("Welcome,"); this.dynamicScoreboard.addPostLine(); } } else { this.dynamicScoreboard.update(); } if (this.queueScoreboard == null) { this.dynamicScoreboard.applyToPlayer(this.getPlayer()); } } public void getGameData() { if (Main.isGameLobby()) { Main.info("Loading data for %s", this.getName()); this.getLeaderboardStats(); this.kitConfigurations.clear(); String kitConfigurations = (String) this.smartPlayer.getGamePlayerData(GamePlayerDataColumn.KIT_CONFIGURATIONS); if (!kitConfigurations.equalsIgnoreCase("default")) { for (String s : Text.separateSSV(kitConfigurations)) { Kit kit = Kit.fromJson(RelayUtils.parseJsonObject(s)); if (kit != null) { this.kitConfigurations.add(kit); } else { Main.error("Couldn't process kit from json: \n%s", s); } } } if (this.smartPlayer.getGamePlayerData(GamePlayerDataColumn.DUELS_CUSTOM_KITS).equals("")) { this.customDuelKits.clear(); } else { for (CustomDuelsKit customDuelsKit : this.smartPlayer.getCustomDuelsKits()) { if (!this.customDuelKits.contains(customDuelsKit)) { this.customDuelKits.add(customDuelsKit); } } List<String> ids = Text.separateCSV((String) this.smartPlayer.getGamePlayerData(GamePlayerDataColumn.DUELS_CUSTOM_KITS)); this.customDuelKits.removeIf(customDuelsKit -> !ids.contains(customDuelsKit.getId())); } if (this.smartPlayer.getGamePlayerData(GamePlayerDataColumn.DUELS_CUSTOM_MAPS).equals("")) { this.customMaps.clear(); } else { for (CustomMap customMap : this.smartPlayer.getCustomMaps()) { if (!this.customMaps.contains(customMap)) { this.customMaps.add(customMap); } } List<String> ids = Text.separateCSV((String) this.smartPlayer.getGamePlayerData(GamePlayerDataColumn.DUELS_CUSTOM_MAPS)); this.customMaps.removeIf(customMap -> !ids.contains(customMap.getId())); } if (this.getExtraData().has("selectedCustomKit")) { if (this.customDuelKits.isEmpty()) { this.selectedCustomDuelsKit = null; } String selectedKit = this.getExtraData().getString("selectedCustomKit", "null"); for (CustomDuelsKit customDuelsKit : this.customDuelKits) { if (Text.comparablyContains(customDuelsKit.getId(), selectedKit)) { this.selectedCustomDuelsKit = customDuelsKit; break; } } } else if (!customDuelKits.isEmpty()) { RelayMCUtils.warn("No kit selected, returning random"); this.selectedCustomDuelsKit = Miscellaneous.getFirstEntry(customDuelKits); } else { RelayMCUtils.error("Attempted to get selected custom duels kit, no custom duels kits listed; %s", this.getRealName()); this.selectedCustomDuelsKit = null; } Statistics statistics = this.smartPlayer.getStatistics(Main.getMainGame()); if (statistics != null) { this.experience = statistics.getXp(); this.eloMap = statistics.getEloMap(); this.timeMap = statistics.getTimeMap(); if (!this.isOnline()) { Main.scheduleSyncDelayedTask(this::updateExperienceBar, 1); } else { Main.synchronous(this::updateExperienceBar); } this.overallStatistics = statistics.getOverallData(); this.specificStatistics = statistics.getSpecificData(); } this.dynamicScoreboard.update(); } } public void getLeaderboardStats() { List<String> leaderboardNames = Miscellaneous.getList("leaderboard", "leaderboard_weekly", "leaderboard_daily"); this.previousLeaderboardStats.clear(); this.previousLeaderboardExtraStats.clear(); for (int i = 0; i < 3; i++) { this.previousLeaderboardStats.add(new LinkedHashMap<>()); this.previousLeaderboardExtraStats.add(new LinkedHashMap<>()); } Main.async(() -> { for (int i = 0; i < leaderboardNames.size(); i++) { String leaderboardName = leaderboardNames.get(i); try { ResultSet resultSet = SmartDatabase.getAllFrom(leaderboardName, ProfileColumn.ID.getName(), this.getUUID()).get(5, TimeUnit.SECONDS); if (resultSet.first()) { for (GameAction gameAction : GameAction.getGameActions(Main.getMainGame())) { if (gameAction.isLeaderboard() && !gameAction.isCalculated()) { try { long value = resultSet.getLong(gameAction.getLeaderboardName(Main.getMainGame())); this.previousLeaderboardStats.get(i).put(gameAction, value); } catch (Exception exception) { Main.warn("No column found: %s | %s | %s", leaderboardName, gameAction.getLeaderboardName(Main.getMainGame()), exception.getMessage()); } } } Map<String, Number> extraStats = this.previousLeaderboardExtraStats.get(i); extraStats.put("experience", resultSet.getLong(Main.getMainGame().specifyName("experience"))); extraStats.put("elo", resultSet.getLong(Main.getMainGame().specifyName("elo"))); extraStats.put("time_played", resultSet.getLong(Main.getMainGame().specifyName("time_played"))); } } catch (Exception exception) { Main.error("An error occurred while trying to update the leaderboard statistics: %s | %s | %s", leaderboardName, this.getName(), exception.getMessage()); } } }); } public void addValueToOverallStatistic(SpecificGameAction specificGameAction, Long value) { GameAction overallGameAction = specificGameAction.getGameAction(); if (!this.overallStatistics.containsKey(overallGameAction)) { this.overallStatistics.put(overallGameAction, value); } else { double current = this.overallStatistics.get(overallGameAction).doubleValue(); this.overallStatistics.put(overallGameAction, current + value); } } public void onDisconnect() { this.smartPlayer.clear(); this.connectTime = 0; this.smartPlayer.activeCosmetics.clear(); for (DefinedLobbyCosmetic activeCosmetic : this.activeLobbyCosmetics) { this.smartPlayer.activeCosmetics.add(activeCosmetic.getOriginal()); } this.updateProfile(ProfileColumn.ACTIVE_COSMETICS); this.disableAllCosmetics(); this.arenaStats.forEach((s, number) -> this.smartPlayer.getArenaStats().put(s, number)); this.smartPlayer.updateArenaStats(); if (this.isCreatingOwnedCustomMap()) { this.saveCustomMap(true); } else if (this.isCreatingCustomMap) { this.leaveCustomMap(); } this.pvpArenaHealth = -1F; this.arenaStats = new HashMap<>(); this.cancelKit(false); } public void disableAllCosmetics() { while (!this.activeLobbyCosmetics.isEmpty()) { this.activeLobbyCosmetics.get(0).disable(this, false); } } public void giveCosmetics() { this.purchasedLobbyCosmetics.clear(); this.activeLobbyCosmetics.clear(); this.lobbyCosmetics.addAll(Cosmetics.getDefaultCosmeticItemsForPlayer(this)); for (Cosmetic cosmeticName : this.smartPlayer.cosmetics) { DefinedLobbyCosmetic cosmetic = DefinedLobbyCosmetic.getCosmetic(cosmeticName); if (cosmetic != null) { Miscellaneous.addIfAbsent(this.purchasedLobbyCosmetics, cosmetic); } } for (DefinedLobbyCosmetic purchasedLobbyCosmetic : this.purchasedLobbyCosmetics) { Miscellaneous.addIfAbsent(this.lobbyCosmetics, purchasedLobbyCosmetic); } for (Cosmetic activeCosmetic : this.smartPlayer.activeCosmetics) { DefinedLobbyCosmetic cosmetic = DefinedLobbyCosmetic.getCosmetic(activeCosmetic); if (cosmetic != null && this.lobbyCosmetics.contains(cosmetic)) { cosmetic.enable(this, false); } } } public void sendMessage(String format, Object... data) { this.smartPlayer.sendMessage(format, data); } public void sendInfoMessage(String format, Object... data) { this.smartPlayer.sendInfoMessage(format, data); } public void sendErrorMessage(String format, Object... data) { this.smartPlayer.sendErrorMessage(format, data); } public void sendSuccessMessage(String format, Object... data) { this.smartPlayer.sendSuccessMessage(format, data); } public void sendUsageMessage(String format, Object... data) { this.smartPlayer.sendUsageMessage(format, data); } public Player getPlayer() { return this.smartPlayer.getPlayer(); } public void sendToHubType(MainGame mainGame) { this.sendToServer(mainGame.getComparableName()); } public void sendToMainHub() { if (Main.mainGame == null) { spawn(true); } else { this.sendToServer("main"); } } public void sendToServer(String serverName) { this.smartPlayer.sendToServer(serverName); } public void queue(GameType gameType) { this.smartPlayer.queue(gameType); } public void queue(GameType gameType, QueueData queueData) { if (this.isInParty()) { queueData.setParty(); } this.smartPlayer.queue(gameType, queueData); } public void partyQueue(GameType gameType) { this.smartPlayer.partyQueue(gameType); } public void sendChampionPurchaseMessage() { this.smartPlayer.sendChampionPurchaseMessage(); } public void cancel(GameType gameType) { this.smartPlayer.cancel(gameType); } public Location getLocation() { return this.smartPlayer.getLocation(); } public Location getLastLocation() { return lastLocation; } public void showSettingsGui() { AtomicReference<ChatFilter> chatFilterLevelShown = new AtomicReference<>(this.smartPlayer.chatFilter); AtomicReference<MessageFilter> messageFilterShown = new AtomicReference<>(this.smartPlayer.messageFilter); AtomicReference<FriendFilter> friendFilterShown = new AtomicReference<>(this.smartPlayer.friendFilter); AtomicReference<PartyFilter> partyFilterShown = new AtomicReference<>(this.smartPlayer.partyFilter); AtomicReference<DuelFilter> duelFilterShown = new AtomicReference<>(this.smartPlayer.duelFilter); SmartGUI settingsGUI = new SmartGUI("Settings", 1, false) { @Override public void onClose() { boolean shouldUpdate = false; smartPlayer.set(chatFilterLevelShown.get()); smartPlayer.set(messageFilterShown.get()); smartPlayer.set(friendFilterShown.get()); smartPlayer.set(partyFilterShown.get()); smartPlayer.set(duelFilterShown.get()); } }; ItemStack chatFilter = SmartGUIUtils.getItemStackForSettingName(this.smartPlayer.chatFilter.name()); settingsGUI.add(0, chatFilter, (player1, rightClick, shift) -> { ChatFilter next = rightClick ? chatFilterLevelShown.get().getPrevious() : chatFilterLevelShown.get().getNext(); chatFilterLevelShown.set(next); settingsGUI.setItem(0, ItemUtilities.edit(next.itemStack, ChatFilter.getName(), next.getDescriptionForItem())); playSuccessSoundVariation(); }, ChatFilter.getName(), this.smartPlayer.chatFilter.getDescriptionForItem()); ItemStack messageFilter = SmartGUIUtils.getItemStackForSettingName(this.smartPlayer.messageFilter.name()); settingsGUI.add(1, messageFilter, (player1, rightClick, shift) -> { MessageFilter next = rightClick ? messageFilterShown.get().getPrevious() : messageFilterShown.get().getNext(); messageFilterShown.set(next); settingsGUI.setItem(1, ItemUtilities.edit(next.itemStack, MessageFilter.getName(), next.getDescriptionForItem())); playSuccessSound(); }, MessageFilter.getName(), this.smartPlayer.messageFilter.getDescriptionForItem()); ItemStack friendFilter = SmartGUIUtils.getItemStackForSettingName(this.smartPlayer.friendFilter.name()); settingsGUI.add(2, friendFilter, (player1, rightClick, shift) -> { FriendFilter next = rightClick ? friendFilterShown.get().getPrevious() : friendFilterShown.get().getNext(); friendFilterShown.set(next); settingsGUI.setItem(2, ItemUtilities.edit(next.itemStack, FriendFilter.getName(), next.getDescriptionForItem())); playSuccessSoundVariation(); }, FriendFilter.getName(), this.smartPlayer.friendFilter.getDescriptionForItem()); ItemStack partyFilter = SmartGUIUtils.getItemStackForSettingName(this.smartPlayer.partyFilter.name()); settingsGUI.add(3, partyFilter, (player1, rightClick, shift) -> { PartyFilter next = rightClick ? partyFilterShown.get().getPrevious() : partyFilterShown.get().getPrevious(); partyFilterShown.set(next); settingsGUI.setItem(3, ItemUtilities.edit(next.itemStack, PartyFilter.getName(), next.getDescriptionForItem())); playSuccessSoundVariation(); }, PartyFilter.getName(), this.smartPlayer.partyFilter.getDescriptionForItem()); ItemStack duelFilter = SmartGUIUtils.getItemStackForSettingName(this.smartPlayer.duelFilter.name()); settingsGUI.add(4, duelFilter, (player1, rightClick, shift) -> { DuelFilter next = rightClick ? duelFilterShown.get().getPrevious() : duelFilterShown.get().getNext(); duelFilterShown.set(next); settingsGUI.setItem(4, ItemUtilities.edit(next.itemStack, DuelFilter.getName(), next.getDescriptionForItem())); playSuccessSoundVariation(); }, DuelFilter.getName(), this.smartPlayer.duelFilter.getDescriptionForItem()); this.openGui(settingsGUI); } public World getWorld() { return this.smartPlayer.getWorld(); } public Vector getDirection() { return this.smartPlayer.getDirection(); } public boolean isAdministrator() { return this.smartPlayer.isAdministrator(); } public boolean lobbyHasGameCosmeticTypes() { return Main.getMainGame() != null && !Miscellaneous.filter(GameCosmeticType.values(), type -> !GameCosmetic.getGameCosmetics(type).isEmpty()).isEmpty(); } public void openCosmeticsGui() { if (!this.lobbyHasGameCosmeticTypes()) { this.openLobbyCosmeticsGui(); return; } SmartGUI smartGUI = new SmartGUI("Cosmetics", 1, false); smartGUI.add(3, Material.IRON_SWORD, (player, b, b2) -> this.openGameCosmeticsGui(), GREEN + Main.getMainGame().getName() + " Cosmetics"); smartGUI.add(5, Material.PAPER, (player, b, b2) -> this.openLobbyCosmeticsGui(), BLUE + "Lobby Cosmetics"); /* smartGUI.add(40, Material.ARROW, (player, b, b2) -> { if (this.hasMenu()) { this.openMenu(); } else { this.closeInventory(); } }, this.hasMenu() ? RED + "Cancel" : RED + "Close"); */ smartGUI.fillEmptySpots(); this.openGui(smartGUI); } public void openMenu() { this.openGui(SmartGUIUtils.MENU); } public void openLobbyCosmeticsGui() { SmartGUI smartGUI = new SmartGUI("Cosmetics", 4, false); List<CosmeticType> options = Miscellaneous.filter(CosmeticType.values(), type -> !Cosmetic.getCosmeticsOfType(type).isEmpty()); if (options.size() % 2 == 0) { int startingIndex = 13 - options.size() / 2 + 1; for (int i = 0; i < options.size() - 1; i++) { CosmeticType cosmeticType = options.get(i); smartGUI.add(startingIndex + i, cosmeticType.getRepresentative(), (player, b, b2) -> this.openLobbyCosmeticsGui(cosmeticType), WHITE + cosmeticType.getPrettyName()); } int i = options.size() - 1; CosmeticType cosmeticType = options.get(i); smartGUI.add(22, cosmeticType.getRepresentative(), (player, b, b2) -> this.openLobbyCosmeticsGui(cosmeticType), WHITE + cosmeticType.getPrettyName()); } else { int startingIndex = 13 - options.size() / 2; for (int i = 0; i < options.size(); i++) { CosmeticType cosmeticType = options.get(i); smartGUI.add(startingIndex + i, cosmeticType.getRepresentative(), (player, b, b2) -> this.openLobbyCosmeticsGui(cosmeticType), WHITE + cosmeticType.getPrettyName()); } } smartGUI.add(31, Material.BARRIER, (player, b, b2) -> { if (this.lobbyHasGameCosmeticTypes()) { this.openCosmeticsGui(); } else { if (this.hasMenu()) { this.openMenu(); } else { this.closeInventory(); } } }, RED + "Cancel"); smartGUI.fillEmptySpots(); this.openGui(smartGUI); } public boolean hasMenu() { return Main.hasKits(); } public void openLobbyCosmeticsGui(CosmeticType cosmeticType) { this.openLobbyCosmeticsGui(cosmeticType, 1); } public void openLobbyCosmeticsGui(CosmeticType cosmeticType, int page) { List<DefinedLobbyCosmetic> ofType = DefinedLobbyCosmetic.getCosmeticItems(cosmeticType); SmartGUI cosmeticsGUI = new SmartGUI(ChatColor.stripColor(cosmeticType.getPrettyName()), 5, false); int itemIndex = 3 * 7 * (page - 1); Map<DefinedLobbyCosmetic, Integer> cosmeticToIndex = new HashMap<>(); for (int row = 1; row < 4 && itemIndex < ofType.size(); row++) { for (int i = 1; i < 8 && itemIndex < ofType.size(); i++) { DefinedLobbyCosmetic cosmetic = ofType.get(itemIndex++); final int currentIndex = row * 9 + i; cosmeticToIndex.put(cosmetic, currentIndex); } } for (DefinedLobbyCosmetic cosmetic : cosmeticToIndex.keySet()) { int index = cosmeticToIndex.get(cosmetic); cosmeticsGUI.add(index, cosmetic.getItemStack(this), (player, b, b2) -> { if (cosmetic.onClick(this)) { this.playSuccessSound(); } else { if (cosmetic.isPurchasable()) { this.showPurchaseGUI(cosmeticsGUI, cosmetic); } else { this.sendErrorMessage("This cosmetic cannot be purchased!"); this.playErrorSound(); } } for (DefinedLobbyCosmetic other : cosmeticToIndex.keySet()) { cosmeticsGUI.setItem(cosmeticToIndex.get(other), other.getItemStack(this)); } }); } cosmeticsGUI.add(8, Material.PAPER, (player, b, b2) -> this.showStore(), BLUE + "Store", GRAY + "Don't have enough tokens?"); if (page != 1) { cosmeticsGUI.add(4 * 9 + 3, Material.FEATHER, (player, b, b2) -> this.openLobbyCosmeticsGui(cosmeticType, page - 1), YELLOW + "Previous"); } if (itemIndex != ofType.size()) { cosmeticsGUI.add(4 * 9 + 5, Material.EMERALD_BLOCK, (player, b, b2) -> this.openLobbyCosmeticsGui(cosmeticType, page + 1), YELLOW + "Next"); } cosmeticsGUI.add(4 * 9 + 4, Material.BARRIER, (player, b, b2) -> this.openLobbyCosmeticsGui(), RED + "Close"); int start = 10; int end = 17; for (int i = 0; i < 3; i++) { for (int j = start; j < end; j++) { if (cosmeticsGUI.getGui().getItem(j) == null) { cosmeticsGUI.addImmutable(j, Material.WHITE_STAINED_GLASS_PANE, ChatColor.RESET.toString()); } } start += 9; end += 9; } cosmeticsGUI.fillEmptySpots(); this.openGui(cosmeticsGUI); } public void showPurchaseGUI(SmartGUI previous, DefinedLobbyCosmetic cosmetic) { SmartGUI gui = new SmartGUI("Purchase", 1, false); gui.add(3, this.canPurchaseCosmetic(cosmetic) ? Material.GREEN_TERRACOTTA : Material.BARRIER, (player, b, b2) -> this.tryPurchase(cosmetic, previous), GREEN + "Purchase " + cosmetic.getPrettyName(), GOLD.toString() + cosmetic.getCost() + " Tokens"); gui.add(5, Material.RED_TERRACOTTA, (player, b, b2) -> this.openGui(previous), RED + "Return"); this.openGui(gui); } public void tryPurchase(DefinedLobbyCosmetic cosmetic, SmartGUI previous) { if (this.purchasedLobbyCosmetics.contains(cosmetic)) { this.sendErrorMessage("You already own this cosmetic!"); this.playErrorSound(); } else if (this.smartPlayer.credits < cosmetic.getCost()) { int difference = (int) (cosmetic.getCost() - this.smartPlayer.credits); this.sendErrorMessage("You need %s%d%s more token%s to purchase this cosmetic!", YELLOW, difference, RED, difference == 1 ? "" : "s"); this.playErrorSound(); } else { this.purchasedLobbyCosmetics.add(cosmetic); Miscellaneous.addIfAbsent(this.lobbyCosmetics, cosmetic); this.smartPlayer.credits -= cosmetic.getCost(); this.smartPlayer.cosmetics.add(cosmetic.getOriginal()); this.updateProfile(ProfileColumn.CREDITS); this.updateProfile(ProfileColumn.COSMETICS); this.sendSuccessMessage("Purchased %s%s.", cosmetic.getPrettyName(), GREEN); cosmetic.enable(this, true); this.playSuccessSound(); this.openLobbyCosmeticsGui(cosmetic.getOriginal().getType()); } } public boolean canPurchaseCosmetic(DefinedLobbyCosmetic cosmetic) { return !(this.purchasedLobbyCosmetics.contains(cosmetic) || this.smartPlayer.credits < cosmetic.getCost()); } public boolean hasLobbyCosmeticActive(DefinedLobbyCosmetic cosmetic) { return this.activeLobbyCosmetics.contains(cosmetic); } public boolean hasLobbyCosmeticUnlocked(DefinedLobbyCosmetic cosmetic) { return this.lobbyCosmetics.contains(cosmetic) || this.purchasedLobbyCosmetics.contains(cosmetic); } public void openGameCosmeticsGui() { SmartGUI smartGUI = new SmartGUI(Main.getMainGame().getName() + " Cosmetics", 5, false); List<GameCosmeticType> options = Miscellaneous.filter(GameCosmeticType.values(), type -> !GameCosmetic.getGameCosmetics(Main.getMainGame(), type).isEmpty()); options.remove(GameCosmeticType.TRAIL); options.remove(GameCosmeticType.KILL_EFFECT); if (options.size() == 2) { boolean f = false; for (GameCosmeticType option : options) { smartGUI.add(f ? 14 : 12, option.getRepresentative(), (player, b, b2) -> this.openGameCosmeticsGui(option), WHITE + option.getPrettyName()); f = true; } } else if (options.size() % 2 == 0) { int startingIndex = 13 - options.size() / 2 + 1; for (int i = 0; i < options.size() - 1; i++) { GameCosmeticType gameCosmeticType = options.get(i); smartGUI.add(startingIndex + i, gameCosmeticType.getRepresentative(), (player, b, b2) -> this.openGameCosmeticsGui(gameCosmeticType), WHITE + gameCosmeticType.getPrettyName()); } int i = options.size() - 1; GameCosmeticType gameCosmeticType = options.get(i); smartGUI.add(22, gameCosmeticType.getRepresentative(), (player, b, b2) -> this.openGameCosmeticsGui(gameCosmeticType), WHITE + gameCosmeticType.getPrettyName()); } else { int startingIndex = 13 - options.size() / 2; for (int i = 0; i < options.size(); i++) { GameCosmeticType gameCosmeticType = options.get(i); smartGUI.add(startingIndex + i, gameCosmeticType.getRepresentative(), (player, b, b2) -> this.openGameCosmeticsGui(gameCosmeticType), WHITE + gameCosmeticType.getPrettyName()); } } smartGUI.add(40, Material.BARRIER, (player, b, b2) -> this.openCosmeticsGui(), RED + "Cancel"); smartGUI.fillEmptySpots(); this.openGui(smartGUI); } public void openGameCosmeticsGui(GameCosmeticType gameCosmeticType) { this.openGameCosmeticsGui(gameCosmeticType, 1); } public void openGameCosmeticsGui(GameCosmeticType gameCosmeticType, int page) { List<GameCosmetic> ofType = GameCosmetic.getGameCosmetics(Main.getMainGame(), gameCosmeticType); SmartGUI gameCosmeticsGUI = new SmartGUI(ChatColor.stripColor(gameCosmeticType.getPrettyName()), 5, false); int itemIndex = 3 * 7 * (page - 1); Map<GameCosmetic, Integer> gameCosmeticToIndex = new HashMap<>(); for (int row = 1; row < 4 && itemIndex < ofType.size(); row++) { for (int i = 1; i < 8 && itemIndex < ofType.size(); i++) { GameCosmetic gameCosmetic = ofType.get(itemIndex++); final int currentIndex = row * 9 + i; gameCosmeticToIndex.put(gameCosmetic, currentIndex); } } for (GameCosmetic gameCosmetic : gameCosmeticToIndex.keySet()) { int index = gameCosmeticToIndex.get(gameCosmetic); gameCosmeticsGUI.add(index, gameCosmetic.getItemStack(this.hasGameCosmetic(gameCosmetic), this.hasGameCosmeticActive(gameCosmetic)), (player, b, b2) -> { if (!this.onClickGameCosmetic(gameCosmetic)) { if (gameCosmetic.isPurchasable()) { this.showPurchaseGUI(gameCosmeticsGUI, gameCosmetic); } else { this.sendErrorMessage("This cosmetic cannot be purchased!"); this.playErrorSound(); } } for (GameCosmetic other : gameCosmeticToIndex.keySet()) { gameCosmeticsGUI.setItem(gameCosmeticToIndex.get(other), other.getItemStack(this.hasGameCosmetic(other), this.hasGameCosmeticActive(other))); } }); } gameCosmeticsGUI.add(8, Material.PAPER, (player, b, b2) -> this.showStore(), BLUE + "Store", GRAY + "Don't have enough tokens?"); if (page != 1) { gameCosmeticsGUI.add(4 * 9 + 3, Material.FEATHER, (player, b, b2) -> this.openGameCosmeticsGui(gameCosmeticType, page - 1), YELLOW + "Previous"); } if (itemIndex != ofType.size()) { gameCosmeticsGUI.add(4 * 9 + 5, Material.EMERALD_BLOCK, (player, b, b2) -> this.openGameCosmeticsGui(gameCosmeticType, page + 1), YELLOW + "Next"); } gameCosmeticsGUI.add(4 * 9 + 4, Material.BARRIER, (player, b, b2) -> this.openGameCosmeticsGui(), RED + "Close"); int start = 10; int end = 17; for (int i = 0; i < 3; i++) { for (int j = start; j < end; j++) { if (gameCosmeticsGUI.getGui().getItem(j) == null) { gameCosmeticsGUI.addImmutable(j, Material.WHITE_STAINED_GLASS_PANE, ChatColor.RESET.toString()); } } start += 9; end += 9; } gameCosmeticsGUI.fillEmptySpots(); this.openGui(gameCosmeticsGUI); } public boolean hasGameCosmetic(GameCosmetic gameCosmetic) { return this.getGameCosmetics().contains(gameCosmetic); } public boolean hasGameCosmeticActive(GameCosmetic gameCosmetic) { return this.getActiveGameCosmetics().contains(gameCosmetic); } public List<GameCosmetic> getGameCosmetics() { return this.smartPlayer.getGameCosmeticList(Main.getMainGame()); } public List<GameCosmetic> getActiveGameCosmetics() { return this.smartPlayer.getActiveGameCosmeticList(Main.getMainGame()); } public boolean onClickGameCosmetic(GameCosmetic gameCosmetic) { if (this.hasGameCosmetic(gameCosmetic)) { if (this.hasGameCosmeticActive(gameCosmetic)) { this.disableGameCosmetic(gameCosmetic); } else { this.enableGameCosmetic(gameCosmetic); } return true; } else { this.sendErrorMessage("You do not have this cosmetic!"); } return false; } public void disableGameCosmetic(GameCosmetic gameCosmetic) { this.getActiveGameCosmetics().remove(gameCosmetic); this.playSuccessSound(); this.sendInfoMessage("Disabled %s%s.", gameCosmetic.getPrettyName(), YELLOW); this.updateProfile(ProfileColumn.ACTIVE_GAME_COSMETICS); } public void updateProfile(ProfileColumn profileColumn) { this.smartPlayer.updateProfile(profileColumn); if (this.dynamicScoreboard != null) { this.dynamicScoreboard.update(); } } public void enableGameCosmetic(GameCosmetic gameCosmetic) { this.getActiveGameCosmetics().removeIf(gameCosmetic1 -> gameCosmetic.isOfGame(Main.getMainGame()) && gameCosmetic1.getType() == gameCosmetic.getType()); this.getActiveGameCosmetics().add(gameCosmetic); this.updateProfile(ProfileColumn.ACTIVE_GAME_COSMETICS); this.playSuccessSound(); this.sendSuccessMessage("Enabled %s%s.", gameCosmetic.getPrettyName(), GREEN); } public void showStore() { this.closeInventory(); ComponentBuilder componentBuilder = new ComponentBuilder(); componentBuilder.gradientLine(ComponentBuilder.GREEN.darker(), ComponentBuilder.GREEN, ComponentBuilder.GREEN.darker()).newLine(); componentBuilder.color(ComponentBuilder.BLUE).append("Store: ").link("https://store.relaymc.net").newLine(); componentBuilder.gradientLine(ComponentBuilder.GREEN.darker(), ComponentBuilder.GREEN, ComponentBuilder.GREEN.darker()); this.sendMessage(componentBuilder); this.playSuccessSoundVariation(); } public void sendMessage(ComponentBuilder componentBuilder) { this.smartPlayer.sendMessage(componentBuilder); } public void sendMessage(BaseComponent baseComponent) { this.smartPlayer.sendMessage(baseComponent); } public void closeInventory() { this.getPlayer().closeInventory(); } public void showPurchaseGUI(SmartGUI previous, GameCosmetic gameCosmetic) { SmartGUI gui = new SmartGUI("Purchase", 1, false); gui.add(3, this.canPurchaseCosmetic(gameCosmetic) ? Material.GREEN_TERRACOTTA : Material.BARRIER, (player, b, b2) -> this.tryPurchase(gameCosmetic, previous), GREEN + "Purchase " + gameCosmetic.getPrettyName(), GOLD.toString() + gameCosmetic.getCost() + " Tokens"); gui.add(5, Material.RED_TERRACOTTA, (player, b, b2) -> this.openGui(previous), RED + "Return"); this.openGui(gui); } public void tryPurchase(GameCosmetic gameCosmetic, SmartGUI previous) { if (this.hasGameCosmetic(gameCosmetic)) { this.sendErrorMessage("You already own this cosmetic!"); this.playErrorSound(); } else if (this.smartPlayer.credits < gameCosmetic.getCost()) { int difference = (int) (gameCosmetic.getCost() - this.smartPlayer.credits); this.sendErrorMessage("You need %s%d%s more token%s to purchase this cosmetic!", YELLOW, difference, RED, difference == 1 ? "" : "s"); this.playErrorSound(); } else { this.getGameCosmetics().add(gameCosmetic); this.smartPlayer.credits -= gameCosmetic.getCost(); this.updateProfile(ProfileColumn.CREDITS); this.updateProfile(ProfileColumn.GAME_COSMETICS); this.sendSuccessMessage("Purchased %s%s.", gameCosmetic.getPrettyName(), GREEN); this.enableGameCosmetic(gameCosmetic); this.playSuccessSound(); this.openGameCosmeticsGui(gameCosmetic.getType()); } } public boolean canPurchaseCosmetic(GameCosmetic gameCosmetic) { return !(this.hasGameCosmetic(gameCosmetic) || this.smartPlayer.credits < gameCosmetic.getCost()); } public void playSound(Sound sound) { this.smartPlayer.playSound(sound); } public void playSuccessSound() { this.smartPlayer.playSuccessSound(); } public void playSuccessSoundVariation() { this.smartPlayer.playSuccessSoundVariation(); } public void playErrorSound() { this.smartPlayer.playErrorSound(); } public void playClickSound() { this.smartPlayer.playClickSound(); } public void playClickSoundVariation() { this.smartPlayer.playClickSoundVariation(); } public void openGui(SmartGUI smartGUI) { if (smartGUI == null) return; smartGUI.fillEmptySpots(); this.smartPlayer.openGui(smartGUI); } public void giveSmartItem(SmartItem smartItem) { this.smartPlayer.giveItem(smartItem); } public void giveSmartItem(int index, SmartItem smartItem) { this.smartPlayer.giveItem(index, smartItem); } public PlayerInventory getInventory() { return this.smartPlayer.getInventory(); } public Group getHighestGroup() { return this.smartPlayer.getHighestGroup(); } public boolean isInGroupOrHigher(Group group) { return this.smartPlayer.isInGroupOrHigher(group); } public boolean hasRankOrHigher(Group group) { if (this.isAdministrator()) return true; return this.getHighestRank().isEqualOrHigherThan(group); } public EntityEquipment getEquipment() { return this.getPlayer().getEquipment(); } public void setWalkSpeed(float walkSpeed) { this.getPlayer().setWalkSpeed(walkSpeed); } public Group getHighestRank() { if (this.isInGroup(Group.CHAMPION)) { return Group.CHAMPION; } else if (this.isInGroup(Group.TIERIII)) { return Group.TIERIII; } else if (this.isInGroup(Group.TIERII)) { return Group.TIERII; } else if (this.isInGroup(Group.TIERI)) { return Group.TIERI; } return Group.DEFAULT; } public boolean isInGroup(Group group) { return this.smartPlayer.isInGroup(group); } public void giveItem(int index, ItemStack itemStack) { this.getInventory().setItem(index, itemStack); } public boolean isGliding() { return this.getPlayer().isGliding(); } public void boostElytra(ItemStack firework) { this.getPlayer().boostElytra(firework); } public void hidePlayers() { if (this.enoughSecondsHaveElapsed(Cooldown.HIDE_SHOW_PLAYERS)) { //this.giveSmartItem(6, SmartGUIUtils.SHOW_PLAYERS); this.hideOthers(); this.canSeePlayers = false; this.sendSuccessMessage("Hiding players."); this.updateCooldown(Cooldown.HIDE_SHOW_PLAYERS); this.playSuccessSound(); } else { this.showCooldownWarning(Cooldown.HIDE_SHOW_PLAYERS); } } public void showPlayers() { if (this.enoughSecondsHaveElapsed(Cooldown.HIDE_SHOW_PLAYERS)) { //this.giveSmartItem(6, SmartGUIUtils.HIDE_PLAYERS); this.showOthers(); this.canSeePlayers = true; this.sendSuccessMessage("Showing players."); this.updateCooldown(Cooldown.HIDE_SHOW_PLAYERS); this.playSuccessSound(); } else { this.showCooldownWarning(Cooldown.HIDE_SHOW_PLAYERS); } } public void updateCooldown(String codeName) { this.cooldowns.put(codeName, System.currentTimeMillis()); } public void updateCooldown(Cooldown cooldown) { this.updateCooldown(cooldown.codeName); } public long getLastTime(String codeName) { return this.cooldowns.getOrDefault(codeName, 0L); } public long getLastTime(Cooldown cooldown) { return this.getLastTime(cooldown.codeName); } public boolean enoughSecondsHaveElapsed(String codeName, double seconds) { if (this.isAdministrator()) { return true; } long lastTime = this.getLastTime(codeName); return lastTime == 0 || System.currentTimeMillis() - lastTime >= seconds * 1000L; } public boolean enoughSecondsHaveElapsed(Cooldown cooldown) { if (this.isAdministrator()) { return true; } long lastTime = this.getLastTime(cooldown); return cooldown.enoughTimeHasPassed(lastTime); } public void showCooldownWarning(Cooldown cooldown) { long timeRemaining = cooldown.time - (System.currentTimeMillis() - this.getLastTime(cooldown)); int secondsRemaining = (int) Math.ceil(timeRemaining / 1000D); this.sendErrorMessage("You must wait %ds to do this!", secondsRemaining); } public void showCooldownWarning(String cooldown, double seconds) { long timeRemaining = (long) (seconds * 1000L - (System.currentTimeMillis() - this.getLastTime(cooldown))); int secondsRemaining = (int) Math.ceil(timeRemaining / 1000D); this.sendErrorMessage("You must wait %ds to do this!", secondsRemaining); } public void vanish() { this.isVanished = true; this.hideFromOthers(); this.sendSuccessMessage("You are now vanished."); this.getExtraData().setBoolean("vanish", true); this.smartPlayer.updateProfile(ProfileColumn.EXTRA); } public void hideFromOthers() { for (SmartPlayer player : SmartPlayer.getOnlineSmartPlayers()) { if (player != this.smartPlayer && !player.isStaff()) { player.hidePlayer(this.smartPlayer); } } } public void unVanish() { this.isVanished = false; this.smartPlayer.showForOthers(); this.smartPlayer.sendActionBar("You are no longer %sVANISHED", RED); this.sendSuccessMessage("You are no longer vanished."); this.getExtraData().setBoolean("vanish", false); this.smartPlayer.updateProfile(ProfileColumn.EXTRA); } public void showOthers() { this.isHidingOthers = false; for (HubPlayer hubPlayer : getHubPlayers()) { if (!hubPlayer.isVanished) { this.showPlayer(hubPlayer); } } this.getExtraData().setBoolean("hidingOthers", false); } public ExtraData getExtraData() { return (ExtraData) this.smartPlayer.getProfileData(ProfileColumn.EXTRA); } public void setExtraData(String name, Object value) { this.getExtraData().setString(name, String.valueOf(value)); this.updateProfile(ProfileColumn.EXTRA); } public void hideOthers() { this.isHidingOthers = true; for (HubPlayer hubPlayer : getHubPlayers()) { if (!(hubPlayer.isStaff() && !hubPlayer.isAndHasNick())) { this.hidePlayer(hubPlayer); } } this.getExtraData().setBoolean("hidingOthers", true); } public void hidePlayer(HubPlayer hubPlayer) { this.smartPlayer.hidePlayer(hubPlayer.smartPlayer); } public void showPlayer(HubPlayer hubPlayer) { this.smartPlayer.showPlayer(hubPlayer.smartPlayer); } public String getFormattedName() { return this.smartPlayer.getFormattedName(); } public ChatColor getFormattedNameColor() { return this.smartPlayer.getFormattedNameColor(); } public ChatColor getRealFormattedNameColor() { return this.smartPlayer.getRealFormattedNameColor(); } public String getName() { return this.smartPlayer.getName(); } public boolean isStaff() { return this.smartPlayer.isStaff(); } public boolean isAndHasNick() { return this.smartPlayer.isAndHasNick(); } public void givePvPItems() { PlayerInventory inventory = this.getInventory(); inventory.clear(); if (Main.isDuelsLobby()) { if (this.nextKit != null) { this.lobbyKit = this.nextKit; this.nextKit = null; } this.lobbyKit.giveItemsToPlayer(this.getPlayer(), true); this.giveSmartItem(8, SmartGUIUtils.KIT_SELECTOR); this.giveSmartItem(7, SPAWN); } else { inventory.setItem(0, ItemUtilities.unbreakable(Material.DIAMOND_AXE)); inventory.setItem(1, ItemUtilities.unbreakable(Material.DIAMOND_SWORD)); inventory.setHelmet(ItemUtilities.unbreakable(Material.DIAMOND_HELMET)); inventory.setChestplate(ItemUtilities.unbreakable(Material.DIAMOND_CHESTPLATE)); inventory.setLeggings(ItemUtilities.unbreakable(Material.DIAMOND_LEGGINGS)); inventory.setBoots(ItemUtilities.unbreakable(Material.DIAMOND_BOOTS)); inventory.setItemInOffHand(ItemUtilities.unbreakable(Material.SHIELD)); } } public void onKillPlayer(HubPlayer killed) { if (Main.isDuelsLobby()) { this.getPlayer().setHealth(20F); this.points++; if (this.lobbyKit == Kits.DUELS_LOBBY_ARCHER) { this.getInventory().addItem(new ItemStack(Material.ARROW, 6)); } this.arenaStats.put("kills", this.arenaStats.getOrDefault("kills", 0).intValue() + 1); this.arenaStats.put("killstreak", this.arenaStats.getOrDefault("killstreak", 0).intValue() + 1); if (this.arenaStats.get("killstreak").intValue() > this.arenaStats.getOrDefault("max_killstreak", 0).intValue()) { this.arenaStats.put("max_killstreak", this.arenaStats.get("killstreak").intValue()); } this.arenaStats.put("kdr", this.arenaStats.get("kills").doubleValue() / (Math.max(0, this.arenaStats.get("deaths").doubleValue()))); } else { int killedKilled = killed.points; int previousPoints = this.points; int gained; if (previousPoints < 10) { gained = Math.max(1, (int) (0.7 * killedKilled)); } else { gained = (int) Math.max(1, 6 * Math.log(killedKilled)); } this.points += gained; this.sendSuccessMessage("You gained %s%d point%s!", AQUA + BOLD.toString(), gained, gained == 1 ? "" : "s"); if (this.points >= 1) { this.addPotionEffect(PotionEffectType.REGENERATION, 5, 1); } if (this.points >= 3) { this.addPotionEffect(PotionEffectType.ABSORPTION, 60, 1); } if (this.points >= 5) { this.addPotionEffect(PotionEffectType.INCREASE_DAMAGE, 10, 1); } if (this.points >= 7) { this.addPotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 60, 0); } if (this.points >= 10 && previousPoints < 10) { Main.broadcastMessage("%s%s is now a juggernaut!", this.getFormattedName(), AQUA + BOLD.toString()); } if (this.points >= 10) { int degree = this.points / 10; this.addPotionEffect(PotionEffectType.ABSORPTION, 10, (int) (degree * 1.25)); this.addPotionEffect(PotionEffectType.REGENERATION, 10, 1); this.addPotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 10, 1); this.addPotionEffect(PotionEffectType.SPEED, 10, 1); this.addPotionEffect(PotionEffectType.GLOWING, 300); this.addPotionEffect(PotionEffectType.HEALTH_BOOST, 10, (int) (degree / 2D)); this.addPotionEffect(PotionEffectType.INCREASE_DAMAGE, 10, 1); this.addPotionEffect(PotionEffectType.FAST_DIGGING, 60, 1); } for (int i = 1; i < 10; i++) { if (this.points >= i * 10 && previousPoints < i * 10) { this.doForStage(i); break; } } } this.inCombat = false; } public void doForStage(int stage) { if (stage >= 1) this.addRandomEnchantmentToArmor(stage); if (stage >= 2) this.addRandomEnchantToWeapon(stage); if (stage >= 3) this.addPotionEffect(PotionEffectType.BLINDNESS, 600, stage); if (stage >= 4) this.addPotionEffect(PotionEffectType.SLOW, 600, stage); if (stage >= 5) this.addPotionEffect(PotionEffectType.CONFUSION, 600, stage); if (stage >= 6) this.addPotionEffect(PotionEffectType.WEAKNESS, 600, stage); if (stage >= 7) { this.addPotionEffect(PotionEffectType.WITHER, 600, stage); this.addPotionEffect(PotionEffectType.POISON, 600, stage); } } public void addPotionEffect(PotionEffectType potionEffectType, double duration, int amplifier) { PotionEffect potionEffect = new PotionEffect(potionEffectType, (int) (duration * 20), amplifier); this.getPlayer().addPotionEffect(potionEffect.withIcon(false).withAmbient(false).withParticles(false)); } public void addPotionEffect(PotionEffectType potionEffectType, double duration) { this.addPotionEffect(potionEffectType, duration, 0); } public void addPotionEffect(PotionEffectType potionEffectType) { this.addPotionEffect(potionEffectType, 99999); } public ItemStack getRandomEquipment() { EntityEquipment entityEquipment = this.getEquipment(); switch (Miscellaneous.getRandomIntBetweenRange(0, 3)) { case 0: return entityEquipment.getHelmet(); case 1: return entityEquipment.getChestplate(); case 2: return entityEquipment.getLeggings(); } return entityEquipment.getBoots(); } public void addRandomEnchantmentToArmor(int degree) { ItemUtilities.edit(this.getRandomEquipment(), itemMeta -> { Enchantment enchantment = getRandomArmorEnchantment(); if (itemMeta.hasEnchant(enchantment)) { itemMeta.addEnchant(enchantment, itemMeta.getEnchantLevel(enchantment) + degree, true); } else { itemMeta.addEnchant(enchantment, Miscellaneous.getRandomIntBetweenRange(enchantment.getStartLevel(), enchantment.getMaxLevel()), true); } }); } public void addRandomEnchantToWeapon(int degree) { ItemStack axe = null; for (ItemStack itemStack : this.getInventory()) { if (itemStack != null && itemStack.getType() == Material.DIAMOND_AXE) { axe = itemStack; break; } } if (axe == null) return; ItemUtilities.edit(axe, itemMeta -> { Enchantment enchantment = getRandomAxeEnchantment(); if (itemMeta.hasEnchant(enchantment)) { itemMeta.addEnchant(enchantment, itemMeta.getEnchantLevel(enchantment) + degree, true); } else { itemMeta.addEnchant(enchantment, Miscellaneous.getRandomIntBetweenRange(enchantment.getStartLevel(), enchantment.getMaxLevel()), true); } }); } public static Enchantment getRandomArmorEnchantment() { return Miscellaneous.getRandomEntry(Miscellaneous.getList(Enchantment.PROTECTION_ENVIRONMENTAL, Enchantment.THORNS)); } public static Enchantment getRandomAxeEnchantment() { return Miscellaneous.getRandomEntry(Miscellaneous.getList(Enchantment.DAMAGE_ALL, Enchantment.KNOCKBACK, Enchantment.FIRE_ASPECT)); } public static Enchantment getRandomBowEnchantment() { return Miscellaneous.getRandomEntry(Miscellaneous.getList(Enchantment.ARROW_DAMAGE, Enchantment.ARROW_FIRE, Enchantment.ARROW_KNOCKBACK)); } public void showStatistics() { if (!Main.isGameLobby()) { this.playErrorSound(); this.sendErrorMessage("Statistics for a game are only available in that game lobby!"); return; } this.openStatisticsGui(); } public void openStatisticsGui() { if (this.specificStatistics.isEmpty()) { this.sendErrorMessage("There are no statistics to display."); } else { this.getStatisticsGui().open(this.getPlayer()); } } public SmartGUI getStatisticsGui() { List<GameType> gameTypes = Main.getMainGame().getGameTypes(); gameTypes.removeIf(gameType -> gameType.isExplicitParty() || !gameType.isEnabled()); SmartGUI smartGUI = new SmartGUI((Main.isGameLobby() ? Main.getMainGame().getName() : "Other") + " Statistics", 3 + gameTypes.size() / 9, false); if (Main.isDuelsLobby()) { gameTypes.add(MainGame.DUELS.getPartyGameType()); } smartGUI.add(gameTypes.size() % 2 == 0 ? 13 : 22, ItemUtilities.enchanted(Material.BOOK), null, GOLD + "Overall", this.getOverallStatistics()); int i = 13 - (gameTypes.size() / 2); for (GameType gameType : gameTypes) { String text = GOLD + (gameType.hasSuffix() ? gameType.getSuffix() : gameType.getFullPrettyName()); List<ComponentBuilder> desc = this.getSpecificStatistics(gameType); if (gameType == MainGame.DUELS.getPartyGameType()) { text = GOLD + "Arena"; List<ComponentBuilder> statisticsList = new ArrayList<>(); final boolean[] darkAqua = {false}; this.arenaStats.forEach((specificGameAction, number) -> { boolean isRatio = specificGameAction.equalsIgnoreCase("kdr"); statisticsList.add(new ComponentBuilder((darkAqua[0] ? DARK_AQUA : AQUA) + ("kdr".equalsIgnoreCase(specificGameAction) ? "K/D" : Text.prettify(specificGameAction)) + ": " + WHITE + (isRatio ? shortenNumber(number) : Text.addCommasToNumber(number.longValue())))); if (Text.comparablyContains(specificGameAction, "kdr", "streak")) { statisticsList.add(new ComponentBuilder("")); } darkAqua[0] = !darkAqua[0]; }); desc = statisticsList; } if (gameTypes.size() % 2 == 0) { smartGUI.addImmutable(i % 9 > 3 ? i + 1 : i, ItemUtilities.editComponentBuilder(gameType.getRepresentative(), text, desc)); i++; } else { smartGUI.addImmutable(i++, ItemUtilities.editComponentBuilder(gameType.getRepresentative(), text, desc)); } } smartGUI.fillEmptySpots(); return smartGUI; } public static String shortenNumber(Number number) { if (number.intValue() == number.doubleValue()) { return String.valueOf(Math.max(0, number.intValue())); } return Text.shortenDouble(number.doubleValue(), 2); } public static final List<GameAction> NEW_LINE = Miscellaneous.getList(GameActions.GAMES_PLAYED, GameActions.WINSTREAK, GameActions.LOSSES, GameActions.DEATHS); public static boolean shouldNewLine(GameAction gameAction) { return NEW_LINE.contains(gameAction); } public static boolean shouldNewLine(SpecificGameAction specificGameAction) { return shouldNewLine(specificGameAction.getGameAction()); } public List<String> getOverallStatistics() { List<String> overallStatistics = new ArrayList<>(); overallStatistics.add(AQUA + "Time Played: " + WHITE + Text.getShortTextualFormattedTime(this.timeMap.get(null))); final boolean[] darkAqua = {true}; this.overallStatistics.forEach((gameAction, value) -> { boolean isRatio = gameAction.isCalculated(); overallStatistics.add((darkAqua[0] ? DARK_AQUA : AQUA) + gameAction.getPluralPrettyName() + ": " + WHITE + (isRatio ? Main.shortenNumber(value) : Text.addCommasToNumber(value.longValue()))); if (shouldNewLine(gameAction)) { overallStatistics.add(""); } darkAqua[0] = !darkAqua[0]; }); return overallStatistics; } public List<ComponentBuilder> getSpecificStatistics(GameType gameType) { List<ComponentBuilder> statistics = new ArrayList<>(); boolean darkAqua = true; statistics.add(SmartPlayer.getEloComponent(this.eloMap.getOrDefault(gameType, 0L), true)); //statistics.add(new ComponentBuilder(GOLD.toString()).append("Total Elo: ").color(WHITE).append(this.eloMap.getOrDefault(gameType, 0L))); statistics.add(new ComponentBuilder(ChatColor.AQUA + "Time Played: " + WHITE + Text.getShortTextualFormattedTime(this.timeMap.getOrDefault(gameType, 0L)))); for (SpecificGameAction specificGameAction : this.specificStatistics.keySet()) { GameAction gameAction = specificGameAction.getGameAction(); boolean isRatio = gameAction.isCalculated(); if (this.specificStatistics.containsKey(specificGameAction) && specificGameAction.getGameType() == gameType) { Number value = this.specificStatistics.get(specificGameAction); statistics.add(new ComponentBuilder((darkAqua ? DARK_AQUA : AQUA) + gameAction.getPluralPrettyName() + ": " + WHITE + (isRatio ? Main.shortenNumber(value) : Text.addCommasToNumber(value.longValue())))); darkAqua = !darkAqua; if (shouldNewLine(specificGameAction)) { statistics.add(new ComponentBuilder("")); } } } return statistics; } public UUID getUUID() { return this.smartPlayer.getUUID(); } public void hideEntity(Entity entity) { this.smartPlayer.hideEntity(entity); } public void showEntity(Entity entity) { this.smartPlayer.showEntity(entity); } public void setEntityNameVisible(Entity entity, boolean visible) { this.smartPlayer.setEntityNameVisible(entity, visible); } public String getRealFormattedName() { return this.smartPlayer.getRealFormattedName(); } public String getRealName() { return this.smartPlayer.getRealName(); } public int getLevel() { return RelayUtils.calculateLevel(null, this.getXp()); } public long getXp() { if (true/*!Main.isGameLobby()*/) { return this.smartPlayer.xp; } return this.experience; } public long getNextLevelXp() { return RelayUtils.getXpRequired(/*Main.getMainGame()*/null, this.getLevel()); } public long getXpAfterLevels() { return RelayUtils.getXpAfterLevels(/*Main.getMainGame()*/null, this.getXp()); } public double getNetworkLevelPercentage() { return this.getNetworkXpAfterLevels() / (double) this.getNextNetworkLevelXp(); } public long getNetworkXpAfterLevels() { return RelayUtils.getXpAfterLevels(null, this.smartPlayer.xp); } public long getNextNetworkLevelXp() { return RelayUtils.getXpRequired(null, this.getNetworkLevel()); } public int getNetworkLevel() { return RelayUtils.calculateLevel(null, this.smartPlayer.xp); } public void updateExperienceBar() { if (this.isOnline()) { Main.synchronous(() -> { Player player = this.getPlayer(); player.setExp(0F); player.setLevel(this.getNetworkLevel()); player.giveExp((int) (this.getNetworkLevelPercentage() * player.getExpToLevel())); if (this.queueScoreboard == null) { this.displayDefaultScoreboard(); } }); } } public boolean isOnline() { return this.smartPlayer.isOnline(); } public void displayDefaultScoreboard() { this.queueScoreboard = null; Main.synchronous(this::updateScoreboard); if (!this.isInQueue()) { this.getInventory().remove(SmartGUIUtils.LEAVE_QUEUE.getItemStack()); } } public void spawn(boolean teleport) { if (teleport) { Location location = PlayerUtilities.getLocationNear(this.getWorld().getSpawnLocation(), Main.isLimbo() ? 7 : 3); location.setYaw(Main.yaw); this.teleport(location); this.getPlayer().setVelocity(new Vector(0, 0, 0)); } if (this.isCreatingOwnedCustomMap()) { this.saveCustomMap(true); } else if (this.isCreatingCustomMap) { this.leaveCustomMap(true); } this.disableAllCosmetics(); this.smartPlayer.clear(); this.smartPlayer.setInvulnerable(true); this.getPlayer().setFireTicks(-1); this.smartPlayer.setAllowFlight(this.isInGroupOrHigher(Group.TIERI)); this.updateExperienceBar(); ExtraListeners.giveItems(this.getPlayer()); if (this.isInQueue()) { this.giveSmartItem(LEAVE_QUEUE); } for (DefinedLobbyCosmetic activeLobbyCosmetic : this.activeLobbyCosmetics) { activeLobbyCosmetic.enable(this, false); } Main.scheduleSyncDelayedTask(() -> StatisticsLeaderboard.showLeaderboards(this), 1); } public void leaveCustomMap(boolean alreadySpawned) { HubPlayer owner = HubPlayer.getHubPlayer(this.customMapEdited.getOwner()); if (owner != null) { owner.sendInfoMessage("%s%s has left your custom map.", this.getRealFormattedName(), YELLOW); owner.mapCollaborators.remove(this); } this.isCreatingCustomMap = false; if (!alreadySpawned) { sendSuccessMessage("Sent you back to spawn."); spawn(true); } } public void leaveCustomMap() { this.leaveCustomMap(false); } public void teleport(Location location) { this.smartPlayer.teleport(location); } public String getLevelPrefix(boolean color) { return RelayUtils.getLevelPrefix(null, this.isAndHasNick() ? this.nickLevel : this.getLevel(), color); } public String getLevelPrefix() { return this.getLevelPrefix(true); } public void sendChatMessage(HubPlayer hubPlayer, String message) { this.smartPlayer.sendChatMessage(hubPlayer.getChatName().append(WHITE + ": "), hubPlayer.smartPlayer, message); } public ComponentBuilder getChatName() { ComponentBuilder componentBuilder = new ComponentBuilder(); //if (Main.isGameLobby()) { //componentBuilder.append(this.getLevelPrefix()).append(" "); NamePrefixCosmetic namePrefixCosmetic = this.getNamePrefixCosmetic(); if (namePrefixCosmetic != null) { componentBuilder.appendComponent(namePrefixCosmetic.getPrefix()).append(" "); } //} return componentBuilder.append(this.smartPlayer.getComponentFormattedName()); } public NamePrefixCosmetic getNamePrefixCosmetic() { return this.smartPlayer.getActiveGameCosmeticOfType(Main.getMainGame(), GameCosmeticType.NAME_PREFIX); } public void openDefaultKitListGui() { if (Main.getMainGame() == MainGame.DUELS) { //this.openDuelsKitGui(); this.openDuelsCustomKitsListGui(1); } else { this.openDefaultKitListGui(1); } } public void openDefaultKitListGui(int page) { List<GameKit> gameKits = GameKit.getKitsForGame(Main.getMainGame()); SmartGUI kitGUI = new SmartGUI("Kits", 5, false); int itemIndex = 3 * 7 * (page - 1); Map<GameKit, Integer> gameKitToIndex = new HashMap<>(); for (int row = 1; row < 4 && itemIndex < gameKits.size(); row++) { for (int i = 1; i < 8 && itemIndex < gameKits.size(); i++) { GameKit gameKit = gameKits.get(itemIndex++); final int currentIndex = row * 9 + i; gameKitToIndex.put(gameKit, currentIndex); } } for (GameKit gameKit : gameKitToIndex.keySet()) { int index = gameKitToIndex.get(gameKit); kitGUI.add(index, gameKit.kit.representative.itemStack, (player, b, b2) -> this.openEditKitGui(gameKit, kitGUI), AQUA + gameKit.kit.name, DARK_GRAY + "Edit " + gameKit.kit.name + "."); } if (page != 1) { kitGUI.add(4 * 9 + 3, Material.FEATHER, (player, b, b2) -> this.openDefaultKitListGui(page - 1), YELLOW + "Previous"); } if (itemIndex != gameKits.size()) { kitGUI.add(4 * 9 + 5, Material.EMERALD_BLOCK, (player, b, b2) -> this.openDefaultKitListGui(page + 1), YELLOW + "Next"); } kitGUI.add(40, Material.BARRIER, (player, b, b2) -> { if (this.hasMenu()) { if (Main.getMainGame() == MainGame.DUELS) { this.openDefaultKitListGui(); } else { this.openMenu(); } } else { this.closeInventory(); } }, this.hasMenu() ? RED + "Cancel" : RED + "Close"); this.openGui(kitGUI); } public void openEditKitGui(GameKit gameKit, SmartGUI previousGui) { Kit toEdit = gameKit.kit; Kit match = Miscellaneous.match(this.kitConfigurations, kit -> kit.name.equalsIgnoreCase(toEdit.name)); this.openEditKitGui(match == null ? toEdit : match, previousGui); } public void openEditKitGui(Kit kit, SmartGUI previousGui) { SmartGUI smartGUI = new SmartGUI("Edit " + kit.name, 6, false); for (int i = 45; i < 54; i++) { if (!(i == 45 || i == 49 || i == 53)) { smartGUI.add(i, Material.GRAY_STAINED_GLASS_PANE, (OnPlayerClick) null, ""); } } smartGUI.add(45, Material.EMERALD_BLOCK, (player, b, b2) -> { List<KitItem> editedKitItems = new ArrayList<>(); for (int i = 36; i < 45; i++) { ItemStack itemStack = smartGUI.getGui().getItem(i); if (itemStack != null) { editedKitItems.add(new KitItem(itemStack, i - 36)); } } for (int i = 0; i < 27; i++) { ItemStack itemStack = smartGUI.getGui().getItem(i); if (itemStack != null) { int j; if (i < 9) { j = i + 27; } else if (i < 18) { j = i % 9 + 18; } else { j = i % 9 + 9; } editedKitItems.add(new KitItem(itemStack, j)); } } for (KitItem item : kit.items) { if (item.slot == 40) { editedKitItems.add(item); break; } } Kit editedKit = new Kit(kit, editedKitItems); this.kitConfigurations.removeIf(kit1 -> kit1.name.equals(kit.name)); this.kitConfigurations.add(editedKit); this.smartPlayer.editGamePlayerColumn(GamePlayerDataColumn.KIT_CONFIGURATIONS, Text.toSSV(this.kitConfigurations)); this.playSuccessSound(); this.sendSuccessMessage("Kit saved."); this.openGui(previousGui); }, GREEN + "Save"); smartGUI.add(49, Material.NETHERITE_SCRAP, (player, b, b2) -> this.openEditKitGui(Kit.getKit(kit.name), previousGui), YELLOW + "Reset"); smartGUI.add(53, Material.BARRIER, (player, b, b2) -> this.openGui(previousGui), RED + "Cancel"); for (int i = 27; i < 36; i++) { smartGUI.addImmutable(i, Material.GREEN_STAINED_GLASS_PANE, GRAY + "↑ Inventory", GRAY + "↓ Hotbar"); } int nextStart = 0; for (KitItem item : kit.items) { if (item.slot != 40) { if (item.slot < 9) { if (item.slot < 0) { smartGUI.add(item.slot + 36 + ++nextStart, item.itemStack); } else { smartGUI.add(item.slot + 36, item.itemStack); } } else { if (item.slot < 18) { smartGUI.add(item.slot % 9 + 18, item.itemStack); } else if (item.slot < 27) { smartGUI.add(item.slot % 9 + 9, item.itemStack); } else { smartGUI.add(item.slot % 9, item.itemStack); } } } } this.openGui(smartGUI); } public void openDuelsKitGui() { SmartGUI smartGUI = new SmartGUI("Kits", 5, false); smartGUI.add(12, Material.IRON_SWORD, (player, b, b2) -> this.openDefaultKitListGui(1), GREEN + "Default Kits"); smartGUI.add(14, Material.NETHERITE_SWORD, (player, b, b2) -> this.openDuelsCustomKitsListGui(1), BLUE + "Custom Kits"); smartGUI.add(40, Material.BARRIER, (player, b, b2) -> { if (this.hasMenu()) { this.openMenu(); } else { this.closeInventory(); } }, this.hasMenu() ? RED + "Cancel" : RED + "Close"); this.smartPlayer.openGui(smartGUI); } public void openDuelsCustomKitsListGui() { this.openDuelsCustomKitsListGui(1); } public void openDuelsCustomKitsListGui(int page) { this.updateCustomKitList(); SmartGUI kitGUI; if (this.customDuelKits.isEmpty()) { kitGUI = new SmartGUI("Kits", 3, false); kitGUI.add(13, Material.OAK_BUTTON, (player, b, b1) -> this.openCustomKitGui(null, b), GREEN + ChatColor.BOLD.toString() + "CREATE KIT", GRAY + ITALIC.toString() + "Select to create a custom kit!"); kitGUI.fillEmptySpots(); } else { kitGUI = new SmartGUI("Kits", 5, false); int itemIndex = 3 * 7 * (page - 1); int row = 1; Main.info("Selected kit: %s", this.selectedCustomDuelsKit != null ? this.selectedCustomDuelsKit.getId() : "null"); for (int i = 0; i < 7; i++) { int j = i + 1; List<CustomDuelsKit> kits = Miscellaneous.filter(this.customDuelKits, customDuelsKit -> customDuelsKit.getOwner().equals(this.getUUID()) && customDuelsKit != this.getNonOwnedKit()); if (i < kits.size()) { CustomDuelsKit kit = kits.get(i); kitGUI.add(j + 9, kit.getKit().representative.itemStack, (player, b, b2) -> this.openCustomKitGui(kit, b), AQUA + kit.getKit().name); kitGUI.add(j + 18, this.selectedCustomDuelsKit == kit ? Material.LIME_DYE : Material.GRAY_DYE, (player, b, b1) -> { if (this.selectedCustomDuelsKit == kit) { this.playErrorSound(); } else { if (this.isInQueue() && this.queueType == GameType.DUELS_CUSTOM) { this.sendErrorMessage("You cannot change your selected kit while queued!"); this.playErrorSound(); } else { this.selectedCustomDuelsKit = kit; this.openDuelsCustomKitsListGui(); this.updateSelectedCustomDuelsKit(); this.playSuccessSound(); } } }, this.selectedCustomDuelsKit == kit ? GREEN + "Selected" : GRAY + "Click to Select"); } else { if (j < this.getMaxCustomKits() + 1) { kitGUI.add(row * 9 + j, Material.OAK_BUTTON, (player, b, b1) -> this.openCustomKitGui(null, b), ChatColor.GREEN + ChatColor.BOLD.toString() + "CREATE KIT", GRAY + ITALIC.toString() + "Select to create a custom kit!"); } else { kitGUI.add(row * 9 + j, Material.STONE_BUTTON, (player, b, b1) -> this.playErrorSound(), ChatColor.RED + ChatColor.BOLD.toString() + "CREATE KIT", GRAY + ITALIC.toString() + "Upgrade to Premium to unlock this slot."); } kitGUI.add(row * 9 + j + 9, Material.GRAY_DYE, (player, b, b1) -> this.playErrorSound(), GRAY + "You cannot select a kit you don't have."); } } CustomDuelsKit customDuelsKit = this.getNonOwnedKit(); if (customDuelsKit != null) { boolean isSelected = this.selectedCustomDuelsKit == customDuelsKit; List<String> description = new ArrayList<>(); description.add(GRAY + "Owner: " + SmartPlayer.getOrCreate(customDuelsKit.getOwner()).getRealFormattedName()); if (isSelected) { description.add(GREEN + "Selected"); description.add(DARK_GRAY + "Left-Click to remove."); } else { description.add(DARK_GRAY + "Left-Click to select."); } description.add(DARK_GRAY + "Right-Click to preview."); kitGUI.add(39, isSelected ? ItemUtilities.enchanted(customDuelsKit.getKit().representative.itemStack) : new ItemStack(customDuelsKit.getKit().representative.itemStack), (player, b, b1) -> { if (b) { this.selectPublicCustomKit(customDuelsKit, true, false); } else { if (isSelected) { this.customDuelKits.remove(customDuelsKit); this.selectedCustomDuelsKit = Miscellaneous.getFirstEntry(this.customDuelKits); this.updateSelectedCustomDuelsKit(); } else { this.selectedCustomDuelsKit = customDuelsKit; this.updateSelectedCustomDuelsKit(); } this.openDuelsCustomKitsListGui(); this.playSuccessSound(); } }, AQUA + customDuelsKit.getKit().name, description); } else { kitGUI.add(39, Material.POLISHED_BLACKSTONE_BUTTON, (player, b, b1) -> enterCustomKitCode(), YELLOW + "Enter Code", GRAY + "Enter the code to a custom kit."); } kitGUI.add(40, Material.EMERALD, (player, b, b1) -> this.viewCustomKitHistory(), GREEN + "History", GRAY + "View your recently played kits."); kitGUI.add(41, Material.CLOCK, (player, b, b1) -> this.browsePublicKits(false), GOLD + "Browse Public Kits", GRAY + "Choose a public kit."); /* if (page != 1) { kitGUI.add(3 * 9 + 3, Material.FEATHER, (player, b, b2) -> this.openDuelsCustomKitsListGui(page - 1), YELLOW + "Previous"); } if (itemIndex != this.customDuelKits.size()) { kitGUI.add(3 * 9 + 5, Material.EMERALD_BLOCK, (player, b, b2) -> this.openDuelsCustomKitsListGui(page + 1), YELLOW + "Next"); } */ // kitGUI.add(3 * 9 + 4, Material.BARRIER, (player, b, b2) -> this.closeInventory(), RED + "Close"); /* kitGUI.add(3 * 9 + 8, Material.PAPER, (player, b, b2) -> { if (this.canCreateCustomDuelKit()) { this.openCustomKitGui(null, b); } else { this.playErrorSound(); } }, BLUE + "New Custom Kit", !this.canCreateCustomDuelKit() ? RED + "You have reached the maximum kits for your rank! Upgrade to unlock more!" : WHITE + "Create a new kit."); */ } kitGUI.fillEmptySpots(); this.openGui(kitGUI); } public void browsePublicKits(boolean recent) { SmartGUI smartGUI = new SmartGUI("Public Kits", 6, false); List<CustomDuelsKit> orderedMaps = Main.getCustomKits(recent, timeFrame); for (int i = 0; i < orderedMaps.size(); i++) { CustomDuelsKit customDuelsKit = orderedMaps.get(i); int plays = customDuelsKit.getPlays(recent ? 0 : timeFrame); smartGUI.add(i, customDuelsKit.getRepresentative(), (player, b, b1) -> this.selectPublicCustomKit(customDuelsKit, true, true), WHITE + customDuelsKit.getName(), String.format("%sCreator: %s", GRAY, SmartPlayer.getOrCreate(customDuelsKit.getOwner()).getRealFormattedName()), RelayUtils.format("%s%d Play%s", AQUA, plays, plays == 1 ? "" : "s"), DARK_GRAY + "Click to preview"); } smartGUI.add(45, Material.ARROW, (player, b, b1) -> this.openDuelsCustomKitsListGui(), RED + "Back"); if (!recent) { smartGUI.add(52, Material.CLOCK, (p, b, b1) -> { this.cycleTimeFrame(); this.browsePublicKits(recent); this.playClickSoundVariation(); }, AQUA + this.getTimeFrame(), DARK_GRAY + "Click to cycle."); } smartGUI.add(53, Material.ANVIL, (player, b, b1) -> { this.playClickSoundVariation(); this.browsePublicKits(!recent); }, GOLD + (recent ? "Recent" : "Popular"), DARK_GRAY + "Click to toggle."); smartGUI.fillEmptySpots(); this.openGui(smartGUI); } private void cycleTimeFrame() { this.timeFrame++; if (this.timeFrame > 3) { this.timeFrame = 0; } } public String getTimeFrame() { return switch (this.timeFrame) { case 1 -> "Daily"; case 2 -> "Weekly"; case 3 -> "Monthly"; default -> "All Time"; }; } public void viewCustomKitHistory() { SmartGUI smartGUI = new SmartGUI("History", 3, false); for (int i = 0; i < this.recentKits.size(); ) { CustomDuelsKit customDuelsKit = this.recentKits.get(i); if (customDuelsKit != null) { int plays = customDuelsKit.getPlays(0); smartGUI.add(i++, customDuelsKit.getRepresentative(), (player, b, b1) -> this.selectPublicCustomKit(customDuelsKit, true, false), WHITE + customDuelsKit.getName(), RelayUtils.format("%sCreator: %s", GRAY, SmartPlayer.getOrCreate(customDuelsKit.getOwner()).getRealFormattedName()), RelayUtils.format("%s%d Play%s", AQUA, plays, plays == 1 ? "" : "s"), DARK_GRAY + "Click to preview"); } } smartGUI.add(22, Material.ARROW, (player, b, b1) -> this.openDuelsCustomKitsListGui(), RED + "Back"); smartGUI.fillEmptySpots(); this.openGui(smartGUI); } private synchronized void selectPublicCustomKit(CustomDuelsKit customDuelsKit, boolean rightClick, boolean browsing) { if (rightClick) { this.previewKit = customDuelsKit; this.openPreviewKitGUI(true, browsing); } else { if (this.customDuelKits.contains(customDuelsKit)) { this.playErrorSound(); this.sendErrorMessage("You already have this kit!"); return; } this.playSuccessSound(); this.customDuelKits.remove(this.getNonOwnedKit()); this.customDuelKits.add(customDuelsKit); this.updateCustomKitList(); this.openDuelsCustomKitsListGui(); } } private void enterCustomKitCode() { new TextGUI(getPlayer(), "Custom Code", "") { @Override public void process(ItemStack itemStack) { String s = itemStack.getItemMeta().getDisplayName(); if (!s.isEmpty()) { sendInfoMessage("Downloading map..."); Main.async(() -> { CustomDuelsKit duelsKit = CustomDuelsKit.getCustomDuelsKit(s); if (duelsKit != null) { customDuelKits.add(duelsKit); playSuccessSound(); } else { playErrorSound(); sendErrorMessage("No kit by the code %s%s%s found.", YELLOW, s, RED); } }); } openDuelsCustomKitsListGui(); } @Override public void onClose() { openDuelsCustomKitsListGui(); } }.openInventory(); } public CustomDuelsKit getNonOwnedKit() { for (CustomDuelsKit customDuelKit : this.customDuelKits) { if (!customDuelKit.getOwner().equals(this.getUUID())) { return customDuelKit; } } if (this.customDuelKits.size() > this.getMaxCustomKits()) { return Miscellaneous.getLastEntry(this.customDuelKits); } return null; } public static ItemStack getCustomKitRepresentative(int i) { Material material; switch (i % 11) { case 0 -> material = Material.RED_BANNER; case 1 -> material = Material.ORANGE_BANNER; case 2 -> material = Material.YELLOW_BANNER; case 3 -> material = Material.LIME_BANNER; case 4 -> material = Material.GREEN_BANNER; case 5 -> material = Material.CYAN_BANNER; case 6 -> material = Material.LIGHT_BLUE_BANNER; case 7 -> material = Material.BLUE_BANNER; case 8 -> material = Material.PURPLE_BANNER; case 9 -> material = Material.MAGENTA_BANNER; case 10 -> material = Material.PINK_BANNER; default -> material = Material.WHITE_BANNER; } return new ItemStack(material); } public boolean canCreateCustomDuelKit() { return this.customDuelKits.size() < this.getMaxCustomKits(); } public void openCustomKitGui(CustomDuelsKit original, boolean rightClick) { if (this.isInQueue() && this.queueType == GameType.DUELS_CUSTOM) { this.sendErrorMessage("You cannot change your selected kit while queued!"); this.playErrorSound(); return; } EditCustomKitGUI editKitGUI = new EditCustomKitGUI(original, this, this.customDuelKits.size()); this.openGui(editKitGUI); /* this.getInventory().clear(); this.closeInventory(); this.sendSuccessMessage("Open your inventory to begin editing your kit. This is now your selected kit."); this.smartPlayer.setGameMode(GameMode.CREATIVE); this.selectedCustomDuelsKit = original; this.isCreatingCustomKit = true; if (original != null) { original.getKit().giveItemsToPlayer(this.getPlayer(), true); } */ } public void openDuelsSettingsGui(CustomDuelsKit kit) { GameSettings gameSettings = getDefaultCustomDuelsGameSettings(); gameSettings.applyFromJson(kit.getGameSettings()); SmartGUI smartGUI = gameSettings.getGUI(this.getHighestGroup(), false); smartGUI.add(0, Material.ARROW, (player, b, b1) -> { kit.updateGameSettings(gameSettings); this.sendSuccessMessage("Game settings updated."); this.saveCustomKit(kit, kit.getId()); this.openDuelsCustomKitsListGui(); }, RED + "Back"); this.openGui(smartGUI); } public static HubGameSettings getDefaultCustomDuelsGameSettings() { HubGameSettings gameSettings = new HubGameSettings(); gameSettings.addInteger(Group.DEFAULT, "time", Material.CLOCK, BLUE + "Round Duration", "How long each round lasts (minutes).", 20, 1, 60).addDefaultOptions(1, 5, 15, 30, 60); gameSettings.addInteger(Group.DEFAULT, "rounds_to_win", Material.GOLD_INGOT, GOLD + "Rounds To Win", "How many rounds are needed to win.", 2, 1, 10).addDefaultOptions(1, 2, 10); gameSettings.addBoolean(Group.DEFAULT, "break", Material.IRON_PICKAXE, RED + "Break Blocks", "Players can break blocks", true); gameSettings.addBoolean(Group.DEFAULT, "place", Material.COBBLESTONE, GREEN + "Place Blocks", "Players can place blocks.", true); gameSettings.addBoolean(Group.DEFAULT, "auto_tnt", Material.TNT, RED + "Auto TNT-Ignite", "TNT is ignited as it is placed.", false); gameSettings.addBoolean(Group.DEFAULT, "explosion_griefing", Material.CREEPER_SPAWN_EGG, RED + "Explosion Griefing", "Explosions destroy the terrain.", true); gameSettings.addBoolean(Group.DEFAULT, "explosion_damage", Material.TNT_MINECART, RED + "Explosion Damage", "Explosions deal damage.", true); gameSettings.addBoolean(Group.DEFAULT, "block_drops", Material.GRASS_BLOCK, ChatColor.GREEN + "Block Drops", "Blocks drop when broken.", true); gameSettings.addBoolean(Group.DEFAULT, "round_map_reset", Material.ITEM_FRAME, ChatColor.AQUA + "Round Map Reset", "The map is reset every round.", true); gameSettings.addInteger(Group.DEFAULT, "deathmatch_delay", Material.IRON_SWORD, DARK_RED + "Deathmatch Delay", "After this amount of time everyone will gain glowing and the border will close in (minutes).", 15, 0, 60).addDefaultOptions(0, 15, 60); gameSettings.addInteger(Group.DEFAULT, "deathmatch_border", Material.RED_STAINED_GLASS, DARK_RED + "Deathmatch Border Size", "The size of the deathmatch border.", 10, 0, 100).addDefaultOptions(0, 10, 100); gameSettings.addBoolean(Group.DEFAULT, "durability", Material.IRON_LEGGINGS, YELLOW + "Durability", "Items will take damage as they are used.", true); gameSettings.addBoolean(Group.DEFAULT, "crafting", Material.CRAFTING_TABLE, ChatColor.AQUA + "Crafting", "Players can craft.", true); gameSettings.addBoolean(Group.DEFAULT, "hunger", Material.COOKED_BEEF, ChatColor.GREEN + "Hunger", "Hunger.", true); gameSettings.addInteger(Group.DEFAULT, "health", Material.RED_TERRACOTTA, RED + "Health", "Amount of health players can have.", 20, 1, 200).addDefaultOptions(1, 10, 20, 50, 100, 200); gameSettings.addBoolean(Group.DEFAULT, "natural_regen", Material.GOLDEN_APPLE, ChatColor.GOLD + "Natural Regeneration", "Players regenerate health naturally.", true); gameSettings.addBoolean(Group.DEFAULT, "fall_damage", Material.IRON_BOOTS, ChatColor.GREEN + "Fall Damage", "Players take damage from falling.", true); gameSettings.addBoolean(Group.DEFAULT, "fly", Material.FEATHER, ChatColor.GOLD + "Flight", "Players can fly.", false); gameSettings.addCycle(Group.DEFAULT, "gamemode", Material.STONE_PICKAXE, ChatColor.BLUE + "Gamemode", "The gamemode players are in.", 0, "Survival", "Adventure"); //gameSettings.addCycle(Group.DEFAULT, "weather", Material.SNOWBALL, LIGHT_PURPLE + "Weather", "The weather you play in.", 0, "Clear", "Rain", "Thunder"); //gameSettings.addCycle(Group.DEFAULT, "world_time", Material.LANTERN, DARK_PURPLE + "Time", "The time you play at.", 1, "Dusk", "Morning", "Noon", "Evening", "Midnight"); //gameSettings.addBoolean(Group.DEFAULT, "mob_drops", Material.BONE, ChatColor.YELLOW + "Mob Drops", "Mobs drop items.", true); gameSettings.addInteger(Group.DEFAULT, "max_build_height", Material.BARRIER, "Max Build Height", "The Maximum height players can build to.", 128, 1, 128).addDefaultOptions(0, 16, 32, 64, 128, 256); gameSettings.addBoolean(Group.DEFAULT, "arrow_pickup", Material.ARROW, "Arrow Pickup", "Players can pickup arrows.", true); gameSettings.addBoolean(Group.DEFAULT, "drop_items", Material.IRON_INGOT, "Drop Items", "Players drop items upon death.", false); gameSettings.addString(Group.DEFAULT, "effects", Material.POTION, LIGHT_PURPLE + "Effects", "Set the effects that will be active during the duel.", PotionEffectType.NIGHT_VISION.getName() + ":-1"); return gameSettings; } public SmartPlayer getSmartPlayer() { return this.smartPlayer; } public List<DefinedLobbyCosmetic> getPurchasedLobbyCosmetics() { return this.purchasedLobbyCosmetics; } public List<DefinedLobbyCosmetic> getLobbyCosmetics() { return this.lobbyCosmetics; } public List<DefinedLobbyCosmetic> getActiveLobbyCosmetics() { return this.activeLobbyCosmetics; } public Map<String, Long> getCooldowns() { return this.cooldowns; } public Map<SpecificGameAction, Number> getSpecificStatistics() { return this.specificStatistics; } public List<Kit> getKitConfigurations() { return this.kitConfigurations; } public List<CustomDuelsKit> getCustomDuelKits() { return this.customDuelKits; } public EditCustomKitGUI getLastCustomKitGui() { return this.lastEditKitGui; } public boolean isVanished() { return this.isVanished; } public boolean isHidingOthers() { return this.isHidingOthers; } public int getPoints() { return this.points; } public double getPvpArenaHealth() { return this.pvpArenaHealth; } public void setLastCustomKitGui(EditCustomKitGUI lastEditKitGui) { this.lastEditKitGui = lastEditKitGui; } public void setVanished(boolean vanished) { isVanished = vanished; } public void setHidingOthers(boolean hidingOthers) { isHidingOthers = hidingOthers; } public void setPoints(int points) { this.points = points; } public void setPvpArenaHealth(double pvpArenaHealth) { this.pvpArenaHealth = pvpArenaHealth; } public void setXp(long xp) { this.experience = xp; } public League getLeague(GameType gameType) { return League.getLeague(this.eloMap.getOrDefault(gameType, 0L)); } public Location getEyeLocation() { return this.smartPlayer.getEyeLocation(); } public Entity rayTraceEntity(double blocks) { return this.smartPlayer.rayTraceEntity(blocks); } public Block rayTraceBlocks(double blocks) { return this.smartPlayer.rayTraceBlocks(blocks); } public double distance(Location location) { return this.getLocation().distance(location); } public void updateQueuePosition(int position, int size, int specificPosition, int specificSize, int typeSize, boolean serverAvailable) { this.queuePosition = position; this.queueSize = size; this.specificPosition = specificPosition; this.specificSize = specificSize; this.typeSize = typeSize; this.serverAvailable = serverAvailable; if (this.queueScoreboard != null) { this.queueScoreboard.update(); if (this.getPlayer().getScoreboard() != this.queueScoreboard.scoreboard) { this.queueScoreboard.applyToPlayer(this.getPlayer()); } } } public void updateQueueScoreboard(GameType gameType, int position, int size, int specificPosition, int specificSize, int typeSize, boolean fastQueue, boolean serverAvailable, QueueData queueData) { this.queuePosition = position; this.queueSize = size; this.specificPosition = specificPosition; this.specificSize = specificSize; this.queueType = gameType; this.typeSize = typeSize; this.serverAvailable = serverAvailable; this.queueData = queueData; if (this.queueScoreboard == null && this.queueType != null) { this.onEnterQueue(); this.queueScoreboard = new DynamicScoreboard(GREEN + BOLD.toString() + gameType.getPrefix().toUpperCase()); boolean ranked = gameType.isRankedType(); this.queueScoreboard.addPreLine(); if (this.isInParty()) { this.queueScoreboard.addDynamicScore(() -> new ComponentBuilder(DARK_AQUA.toString()).append("Party Size: ").append(this.isInParty() ? WHITE.toString() + this.getPartySize() : GRAY + "None")); this.queueScoreboard.addBlankSpace(); } this.queueScoreboard.addDynamicScore(this::getPositionLine); this.queueScoreboard.addBlankSpace(); if (ranked) { //this.queueScoreboard.addDynamicScore(this::getLeagueLine); } else { this.queueScoreboard.addScore("%s%s%s", LIGHT_PURPLE, BOLD, this.queueType.getDisplaySuffix().toUpperCase()); } this.queueScoreboard.addScore(fastQueue ? GOLD + "Fast Queue" : AQUA + "Normal Queue"); this.queueScoreboard.addPostLine(); this.queueScoreboard.applyToPlayer(this.getPlayer()); } else { this.updateQueuePosition(position, size, specificPosition, specificSize, typeSize, serverAvailable); } } public boolean isLastLeague(GameType g) { if (g == null) { return false; } return this.getLeague(g).getNext() == null; } public ComponentBuilder getLeagueLine(GameType g) { return SmartPlayer.getEloComponent(this.eloMap.getOrDefault(g, 0L), true); } public ComponentBuilder getPositionLine() { if (!this.serverAvailable) { if (this.specificPosition <= this.queueType.getTotalPlayerCount()) { return new ComponentBuilder("%sWaiting for open server", YELLOW); } else { return new ComponentBuilder("%sPosition: %s%d%s/%d", AQUA, GREEN, this.specificPosition, WHITE, this.specificSize); } } return new ComponentBuilder("%sWaiting for players", YELLOW); } public void setVelocity(Vector velocity) { this.getPlayer().setVelocity(velocity); } public boolean isSneaking() { return this.getPlayer().isSneaking(); } public boolean isSprinting() { return this.getPlayer().isSprinting(); } public Number getStatistic(int type, String statisticName) { GameAction gameAction = GameAction.getGameAction(statisticName); if (this.previousLeaderboardStats.size() < type + 1) { return 0; } if (gameAction != null) { return this.previousLeaderboardStats.get(type).getOrDefault(gameAction, 0L); } return this.previousLeaderboardExtraStats.get(type).getOrDefault(statisticName, 0L); } public void sendToHell() { this.beingSentToHell = true; this.sendErrorMessage("You are being sent to hell."); Main.scheduleSyncDelayedTask(() -> { for (int i = 0; i < 5; i++) { int finalI = i; Main.scheduleSyncDelayedTask(() -> { double hellValue = this.getHellValue(finalI); this.sendInfoMessage("Sending you to hell at %s%s%s.", RED, hellValue, YELLOW); this.smartPlayer.crash(hellValue); if (finalI == 4) { this.beingSentToHell = false; } }, i * 2); } }, 1); } private double getHellValue(int i) { switch (i) { case 0: return 0.05; case 1: return 0.1; case 2: return 0.25; case 3: return 0.5; } return 1; } public void openPartyModes() { SmartGUIUtils.PARTY_MODES.open(this.getPlayer()); } public void showPlayerGui(HubPlayer clicked) { this.openGui(clicked.getClickGui(this.smartPlayer)); } public SmartGUI getClickGui(SmartPlayer clicker) { SmartGUI smartGUI = new SmartGUI(this.getName(), 3, false); if (Main.isGameLobby()) { smartGUI.add(0, Material.PAPER, (player, b, b1) -> SmartPlayer.getSmartPlayer(player).openGui(this.smartPlayer.getStatisticsGui(Main.getMainGame())), AQUA + "View Statistics", GRAY + "View statistics for " + this.smartPlayer.getFormattedName() + GRAY + "."); } smartGUI.add(4, this.smartPlayer.getHead(), (player, b, b1) -> SmartPlayer.getSmartPlayer(player).openGui(this.smartPlayer.getProfileGui(true, SmartPlayer.getSmartPlayer(player))), this.smartPlayer.getFormattedName(), GRAY + "View profile for " + this.smartPlayer.getFormattedName() + GRAY + "."); smartGUI.add(21, Material.EMERALD, (player, b, b1) -> HubPlayer.getHubPlayer(player).inviteToParty(this), GOLD + "Invite To Party", GRAY + "Invite " + this.smartPlayer.getFormattedName() + GRAY + " to your party."); smartGUI.add(22, Material.IRON_SWORD, ((player, b, b1) -> HubPlayer.getHubPlayer(player).duelPlayer(this.getName())), AQUA + "Send Duel Request", GRAY + "Send " + this.smartPlayer.getFormattedName() + GRAY + " a duel request."); smartGUI.add(23, Material.ITEM_FRAME, (player, b, b1) -> HubPlayer.getHubPlayer(player).sendFriendRequest(this), GREEN + "Send Friend Request", GRAY + "Send a friend request to " + this.smartPlayer.getFormattedName() + GRAY + "."); smartGUI.fillEmptySpots(); return this.smartPlayer.getProfileGui(clicker); } public void inviteToParty(HubPlayer hubPlayer) { ServerCommunicator.sendToProxy(Command.OTHER, "partyinvite", this.getUUID(), hubPlayer.getName()); } public void sendFriendRequest(HubPlayer hubPlayer) { ServerCommunicator.sendToProxy(Command.OTHER, "friendrequest", this.getUUID(), hubPlayer.getName()); } public void resetPvpArenaHealth() { this.setPvpArenaHealth(-1); } public void onArenaDamage() { this.lastArenaDamage = System.currentTimeMillis(); } public void hubCommand() { long timeRemaining = 8000 - (System.currentTimeMillis() - this.lastArenaDamage); if (this.inArena() && timeRemaining > 0) { int secondsRemaining = (int) Math.ceil(timeRemaining / 1000D); this.sendErrorMessage("You must wait %ds to exit combat!", secondsRemaining); } else { ExtraListeners.spawnPlayer(this.getPlayer()); } } public boolean inArena() { return ExtraListeners.isInArena(this.getLocation()); } public void updatePartyInfo(PartyData partyData) { this.partyData = partyData; } public boolean isInParty() { return this.partyData != null; } public void leaveParty() { this.partyData = null; } public int getPartySize() { return this.isInParty() ? Miscellaneous.without(Miscellaneous.with(this.partyData.others, this.partyData.owner), this.getUUID()).size() + 1 : 1; } public void teleportToParkourCheckpoint() { if (this.hasParkour()) { this.getParkour().teleportToCheckpoint(this.smartPlayer); } else { this.sendErrorMessage("shouldn't be possible"); } } public boolean hasParkour() { return this.smartPlayer.selectedParkour != null; } public Parkour getParkour() { return this.smartPlayer.selectedParkour; } public void resetParkour() { if (this.hasParkour()) { this.smartPlayer.restartParkour(); } else { this.sendErrorMessage("what"); } } public void exitParkour() { if (this.hasParkour()) { this.getParkour().exitParkour(this.smartPlayer); this.smartPlayer.sendActionBar("%sUse %s/spawn%s to return to spawn.", GREEN, YELLOW, GREEN); } else { this.sendErrorMessage("no"); } } public void duelPlayer(String name, GameType gameType) { if (gameType == null) { ServerCommunicator.sendToProxy(Command.OTHER, "duelrequest", this.getUUID(), name); } else { this.selectDuelType(name, gameType); } } public void duelPlayer(String name) { this.duelPlayer(name, null); } public void showDuelPlayerSearch() { new TextGUI(this.smartPlayer, "Enter Player to Duel") { @Override public void process(ItemStack itemStack) { duelPlayer(itemStack.getItemMeta().getDisplayName()); HubPlayer.this.closeInventory(); } }.openInventory(); } public void showDuelGui(String playerName) { SmartGUI menu = new SmartGUI("Duel Type", 4, true); List<GameType> types = Miscellaneous.getList(GameType.DUELS_CUSTOM, GameType.DUELS_AXE, GameType.DUELS_SWORD, GameType.DUELS_CRYSTAL, GameType.DUELS_NETHERITE_POT, GameType.DUELS_DIAMOND_POT, GameType.DUELS_UHC, GameType.DUELS_BOW, GameType.DUELS_SUMO, GameType.DUELS_INDEPENDENT_CUSTOM, GameType.DUELS_SMP, GameType.DUELS_OP); for (int i = 0; i < types.size(); i++) { GameType gameType = types.get(i); menu.add(9 + i/*13 - types.size() / 2 + i + (i >= 4 ? 1 : 0)*/, gameType.getRepresentative(), (player, b, b1) -> this.selectDuelType(playerName, gameType), AQUA + BOLD.toString() + gameType.getDisplaySuffix().toUpperCase()); } menu.fillEmptySpots(); this.openGui(menu); } private void selectDuelType(String playerName, GameType gameType) { ServerCommunicator.sendToProxy(Command.OTHER, "duelrequest", this.getUUID(), playerName, gameType); } public void nickname(String[] args) { ServerCommunicator.sendToProxy(Command.OTHER, "nickname", this.getUUID(), Text.toCSV(args)); } public boolean isCreatingCustomKitCreative() { return this.isCreatingCustomKitCreative; } public void showCustomKitEnchant(ItemStack currentItem) { this.changeEnchantments(currentItem); } public void changeEnchantments(ItemStack itemStack) { List<Enchantment> applicableEnchantments = Miscellaneous.getList(Enchantment.values()); applicableEnchantments.removeIf(enchantment -> !enchantment.canEnchantItem(itemStack)); Miscellaneous.addIfAbsent(applicableEnchantments, Enchantment.DAMAGE_ALL); Miscellaneous.addIfAbsent(applicableEnchantments, Enchantment.KNOCKBACK); if (applicableEnchantments.isEmpty()) { this.playErrorSound(); this.sendErrorMessage("This item cannot be enchanted."); } else { this.selectEnchantment(itemStack, applicableEnchantments); } } public void selectEnchantment(ItemStack itemStack, List<Enchantment> options) { SmartGUI smartGUI = new SmartGUI("Enchantments", 5, false); int itemIndex = 0; Map<Enchantment, Integer> kitToIndex = new HashMap<>(); for (int row = 1; row < 4 && itemIndex < options.size(); row++) { for (int i = 1; i < 8 && itemIndex < options.size(); i++) { Enchantment enchantment = options.get(itemIndex++); final int currentIndex = row * 9 + i; kitToIndex.put(enchantment, currentIndex); } } for (Enchantment enchantment : kitToIndex.keySet()) { int index = kitToIndex.get(enchantment); smartGUI.add(index, ItemUtilities.edit(Material.ENCHANTED_BOOK, itemMeta -> itemMeta.addEnchant(enchantment, 1, true)), (player, b, b2) -> this.enchant(itemStack, enchantment), ""); } smartGUI.add(39, Material.GRAY_STAINED_GLASS_PANE, (player, b, b2) -> this.removeEnchants(itemStack), YELLOW + "Clear Enchants"); smartGUI.add(41, Material.BARRIER, (player, b, b2) -> this.continueEditingCustomKit(), RED + "Cancel"); this.openGui(smartGUI); } private void continueEditingCustomKit() { this.reOpeningCustomKit = true; this.closeInventory(); this.sendInfoMessage("Open your inventory to continue editing your kit."); } public void enchant(ItemStack itemStack, Enchantment enchantment) { int max = this.getMaxEnchantLevel(enchantment); this.getStringInput("Enchantment (1 - " + max + ")", "0", s -> { try { int i = Integer.parseInt(s); i = Math.max(1, Math.min(max, i)); ItemStack changed = itemStack.clone(); int finalI = i; ItemUtilities.edit(changed, itemMeta -> itemMeta.addEnchant(enchantment, finalI, true)); this.updateItem(changed); } catch (Exception exception) { this.onInvalidInput(); } this.customKitBack(); }); } private void customKitBack() { this.continueEditingCustomKit(); } private void onInvalidInput() { this.playErrorSound(); this.sendErrorMessage("Invalid input!"); } private void updateItem(ItemStack changed) { this.getInventory().addItem(changed); } public int getMaxEnchantLevel(Enchantment enchantment) { if (this.isAdministrator()) { return 32767; } if (this.isStaff()) { return 16383; } if (this.isInGroupOrHigher(Group.YOUTUBE)) { return 255; } return enchantment.getMaxLevel(); } public void removeEnchants(ItemStack itemStack) { SmartGUI smartGUI = new SmartGUI("Clear Enchants?", 5, false); if (itemStack.getItemMeta().getEnchants().isEmpty()) { this.playErrorSound(); this.sendErrorMessage("No enchantments to clear."); return; } smartGUI.add(13, itemStack, null); smartGUI.add(30, Material.EMERALD_BLOCK, (player, b, b2) -> { ItemStack changed = itemStack.clone(); ItemUtilities.edit(changed, itemMeta -> { for (Enchantment enchantment : itemMeta.getEnchants().keySet()) { itemMeta.removeEnchant(enchantment); } }); this.updateItem(changed); }, RED + "Confirm", YELLOW + "Remove all enchantments on item."); smartGUI.add(32, Material.BARRIER, (player, b, b2) -> this.customKitBack(), YELLOW + "Cancel"); this.openGui(smartGUI); } public boolean reOpeningCustomKit() { return this.reOpeningCustomKit; } public void getStringInput(String title, String originalText, Consumer<String> process) { new TextGUI(getPlayer(), title, originalText) { @Override public void process(ItemStack itemStack) { process.accept(itemStack.getItemMeta().getDisplayName()); } @Override public void onClose() { if (isCreatingCustomKitCreative) { customKitBack(); } } }.openInventory(); } public void selectLobbyKit(Kit kit) { if (this.inCombat()) { this.playSuccessSound(); this.sendSuccessMessage("You will receive your kit when you respawn."); this.nextKit = kit; } else { this.lobbyKit = kit; this.playSuccessSoundVariation(); this.getInventory().clear(); kit.giveItemsToPlayer(this.getPlayer(), true); this.sendSuccessMessage("Changed kit."); this.giveSmartItem(8, SmartGUIUtils.KIT_SELECTOR); this.giveSmartItem(7, SPAWN); } this.getExtraData().setString("kit", kit.name.toLowerCase()); this.smartPlayer.updateProfile(ProfileColumn.EXTRA); } public void showLobbyKitSelect() { SmartGUI kitSelector = new SmartGUI("Kit Selector", 1); for (int i = 0; i < KitCommand.KITS.size(); i++) { Kit kit = KitCommand.KITS.get(i); kitSelector.add(i * 2, kit == this.lobbyKit ? ItemUtilities.enchanted(kit.representative.itemStack) : kit.representative.itemStack, (player, b, b1) -> HubPlayer.getHubPlayer(player).selectLobbyKit(kit), ChatColor.AQUA + ChatColor.BOLD.toString() + kit.name, Miscellaneous.processList(Miscellaneous.getList(kit.description.split(",")), s -> GRAY + s)); kitSelector.fillEmptySpots(); } this.openGui(kitSelector); } public boolean inCombat() { long timeRemaining = 8000 - (System.currentTimeMillis() - this.lastArenaDamage); return this.inArena() && timeRemaining > 0; } public void reQueue() { ServerCommunicator.sendToProxy(Command.OTHER, "requeue", this.getUUID()); } public void enterArena() { for (Entity passenger : this.getPlayer().getPassengers()) { this.getPlayer().removePassenger(passenger); } this.sendInfoMessage("Use /spawn to leave the PVP Arena."); if (this.hasParkour()) { this.teleportToParkourCheckpoint(); } else { this.setPoints(0); double health = this.getPvpArenaHealth() == -1 ? 20 : this.getPvpArenaHealth(); this.getPlayer().setHealth(Math.max(0F, health)); this.getPlayer().setSaturation(0F); this.getPlayer().setUnsaturatedRegenRate(160); this.getPlayer().setSaturatedRegenRate(160); this.disableAllCosmetics(); this.givePvPItems(); this.smartPlayer.setAllowFlight(false); this.smartPlayer.setInvulnerable(false); this.smartPlayer.setGameMode(GameMode.SURVIVAL); if (this.isHidingOthers()) { this.showOthers(); } if (this.isVanished()) { this.unVanish(); } } } public void showCustomDuelsQueueGui(boolean other) { SmartGUI smartGUI = new SmartGUI("Queue", 1, true); smartGUI.add( 3, Material.DIAMOND_AXE, (player, rightClick, shift) -> HubPlayer.getHubPlayer(player).queue(GameType.DUELS_CUSTOM, new QueueData().attachData("other", other)), ChatColor.AQUA + ChatColor.BOLD.toString() + (other ? "ANOTHER'S" : "YOUR" + " KIT"), GRAY + "Play duels with " + (other ? "someone else's" : "your") + " custom kit."); smartGUI.add( 5, Material.FEATHER, (player, rightClick, shift) -> HubPlayer.getHubPlayer(player).cancel(GameType.DUELS_CUSTOM), RED + "Leave Queue", GRAY + RelayUtils.format("Leave the %s queue.", GameType.DUELS_CUSTOM.getFullPrettyName())); this.openGui(smartGUI); } public synchronized void saveCustomKit(CustomDuelsKit kit, String originalID) { int i = this.customDuelKits.indexOf(Miscellaneous.match(this.customDuelKits, customDuelsKit -> Text.comparablyEquals(customDuelsKit.getId(), originalID))); if (i != -1) { this.customDuelKits.remove(i); } this.customDuelKits.removeIf(customDuelsKit -> Text.comparablyEquals(kit.getId(), customDuelsKit.getId())); this.smartPlayer.getCustomDuelsKits().removeIf(customDuelsKit -> Text.comparablyEquals(customDuelsKit.getId(), originalID)); this.smartPlayer.getCustomDuelsKits().removeIf(customDuelsKit -> Text.comparablyEquals(kit.getId(), customDuelsKit.getId())); if (i != -1) { this.customDuelKits.add(Math.min(i, customDuelKits.size()), kit); } else { this.customDuelKits.add(kit); } CustomDuelsKit.insertIntoDatabase(kit); this.smartPlayer.getCustomDuelsKits().add(kit); this.selectedCustomDuelsKit = kit; this.updateSelectedCustomDuelsKit(); this.updateCustomKitList(); } public void updateSelectedCustomDuelsKit() { if (!Main.isDuelsLobby()) { return; } if (this.customDuelKits.isEmpty()) { this.selectedCustomDuelsKit = null; } else if (this.selectedCustomDuelsKit != null && !this.customDuelKits.contains(this.selectedCustomDuelsKit)) { this.selectedCustomDuelsKit = Miscellaneous.getFirstEntry(this.customDuelKits); } this.getExtraData().setString("selectedCustomKit", this.selectedCustomDuelsKit == null ? null : this.selectedCustomDuelsKit.getId()); this.smartPlayer.updateProfile(ProfileColumn.EXTRA); } public static final List<String> BLACKLISTED_ITEMS = Miscellaneous.getList("boat", "redstone", "piston", "button", "pressureplate", "lever", "chest", "jukebox", "shulkerbox", "barrel", "stand", "dropper", "hopper", "dispenser"); public Kit getInventoryAsKit() { List<KitItem> items = new ArrayList<>(); Inventory inventory = this.getInventory(); boolean blacklistedItem = false; for (int i = 0; i <= 40; i++) { if (i < 36 || i > 39) { ItemStack itemStack = inventory.getItem(i); if (itemStack != null && !itemStack.getType().isAir()) { if (!blacklistedNBT(itemStack)) { if (!Text.comparablyContains(itemStack.getType(), BLACKLISTED_ITEMS.toArray()) || Text.comparablyContains(itemStack.getType(), "chestplate")) { items.add(new KitItem(itemStack, i)); } else { blacklistedItem = true; } } else { this.sendErrorMessage("Your item %s had an NBT tag and was removed.", Text.prettify(itemStack.getType())); } } } } if (blacklistedItem) { this.sendErrorMessage("Your inventory contained one or more blacklisted items which were removed."); } ItemStack helmetItem = inventory.getItem(39); ItemStack chestplateItem = inventory.getItem(38); ItemStack leggingsItem = inventory.getItem(37); ItemStack bootsItem = inventory.getItem(36); KitItem helmet = helmetItem == null ? null : new KitItem(helmetItem); KitItem chestplate = chestplateItem == null ? null : new KitItem(chestplateItem); KitItem leggings = leggingsItem == null ? null : new KitItem(leggingsItem); KitItem boots = bootsItem == null ? null : new KitItem(bootsItem); return new Kit(UUID.randomUUID().toString(), "Custom Kit.", null, helmet, chestplate, leggings, boots, items.toArray(new KitItem[0])); } public void onHitTargetWithArrow() { if (Main.isDuelsLobby() && this.lobbyKit == Kits.DUELS_LOBBY_ARCHER && this.inArena()) { this.getInventory().addItem(new ItemStack(Material.ARROW)); } } public void inventoryClose() { if (this.isCreatingCustomKitCreative) { this.returnToKitEditor(); } } public void returnToKitEditor() { this.lastEditKitGui.setFromKit(this.getInventoryAsKit()); this.isCreatingCustomKitCreative = false; spawn(false); this.smartPlayer.openGui(this.lastEditKitGui); } public void setCreatingCustomKitCreative(boolean b) { this.isCreatingCustomKitCreative = b; } public List<CustomMap> getCustomMaps() { return this.customMaps; } public void editCustomMap(CustomMap customMap, boolean newMap) { this.customMapEdited = customMap; this.teleportedToCustomMap = false; this.customMapCenter = getAvailableCenter(customMap); this.customMapBlocks = new ArrayList<>(); this.customMapSpawnA = customMap.getSpawnA().clone(); this.customMapSpawnB = customMap.getSpawnB().clone(); this.customMapSpawnA.setWorld(this.getWorld()); this.customMapSpawnB.setWorld(this.getWorld()); this.customMapVisibility = customMap.isVisible(); if (newMap) { customMap.setName("Map #" + (this.customMaps.size() + 1)); } this.customMapName = customMap.getName(); this.customMapRepresentative = customMap.getRepresentative(); this.customMapSize = customMap.getSize(); this.allCollaborators = customMap.getContributors(); this.customMapEdited.setCreators(customMap.getCreators()); this.customMapEdited.setContributors(customMap.getContributors()); checkCustomMapCenter(); World world = Main.getWorld(); this.newCustomMap = newMap; if (this.newCustomMap) { if (Main.hasWallTemplate()) { this.applyTemplate(Main.getWallTemplate()); } else { this.setFloor(Material.BEDROCK); } } else { for (CustomMap.Block block : customMap.getMap()) { Vector position = block.getPosition(); int x = (int) (this.customMapCenter.getX() + position.getX()); int y = (int) (this.customMapCenter.getY() + position.getY()); if (y < 0) { Main.error("(Loading Map) CustomMap Block is lower than 0 blocks: %s (%s)", this.customMapEdited.getId(), Text.shortenDouble(position.getY(), 2)); } int z = (int) (this.customMapCenter.getZ() + position.getZ()); Block worldBlock = world.getBlockAt(x, y, z); worldBlock.setType(block.material()); worldBlock.setBlockData(block.blockData()); this.customMapBlocks.add(worldBlock); } } this.sendSuccessMessage("Teleported you to your custom map."); this.closeInventory(); this.smartPlayer.clear(); this.teleportToCustomMap(); this.smartPlayer.setGameMode(GameMode.CREATIVE); this.smartPlayer.setAllowFlight(true); this.getPlayer().setFlying(true); this.isCreatingCustomMap = true; this.giveSmartItem(8, CUSTOM_MAP_MENU); } public void teleportToCustomMap() { if (this.customMapCenter != null) { Location toTeleport = PlayerUtilities.getNearestTwoBlockSpaceAbove(this.customMapCenter); toTeleport.add(0, 3, 0); if (toTeleport.getY() >= 130) { toTeleport.setY(5); } Location location = this.customMapCenter.clone().add(customMapSpawnA.toVector()); if (!this.inCustomMapBoundingBox(location)) { this.teleport(toTeleport); } else { this.teleport(location); } Main.synchronous(() -> this.teleportedToCustomMap = true); Main.scheduleSyncDelayedTask(() -> this.addPotionEffect(PotionEffectType.NIGHT_VISION), 1); } } public void inviteCollaborator() { this.getStringInput("Invite Collaborator", null, s -> { HubPlayer hubPlayer = getHubPlayer(SmartPlayer.getPlayerOrNick(s)); if (hubPlayer != null) { this.inviteCollaborator(hubPlayer); } else { CommandUtilities.noPlayerFound(this.getPlayer(), s); } this.closeInventory(); }); } public void showCustomMapMenu() { SmartGUI smartGUI = new SmartGUI("Menu", 5, false); smartGUI.add(0, Material.LEAD, (p, b, b1) -> this.inviteCollaborator(), GOLD + "Invite Collaborator", GRAY + "Invite a player to help you edit this custom map."); smartGUI.add(11, Material.EMERALD_BLOCK, (player, b, b1) -> this.saveCustomMap(true), GREEN + "Save and Exit", GRAY + "Save your custom map and return to the lobby."); smartGUI.add(13, Material.NAME_TAG, (player, b, b1) -> this.editCustomMapLabel(false, false), YELLOW + "Label", GRAY + "Change the name and icon of this custom map."); smartGUI.add(15, Material.BOOK, (player, b, b1) -> this.shareCustomMap(this.customMapEdited), AQUA + "Share Map", GRAY + "Share your custom map with your friends!"); smartGUI.add(29, Material.SLIME_BALL, (player, b, b1) -> this.showCustomMapSpawns(), YELLOW + "Spawnpoints", GRAY + "Set where players will spawn on the map."); smartGUI.add(30, Material.OAK_SIGN, (player, b, b1) -> this.setCustomMapSize(), GOLD + "Plot Size", GRAY + "Change custom map dimensions."); smartGUI.add(31, Material.ITEM_FRAME, (player, b, b1) -> this.chooseCustomMapTemplate(), DARK_AQUA + "Choose Template", GRAY + "Create a custom map from a template."); smartGUI.add(32, Material.WHITE_CARPET, (player, b, b1) -> { if (b && b1) { this.setFloor(Material.AIR); } }, YELLOW + "Floor", GRAY + "Drag and drop an item here to change the floor block.", GRAY + "Shift-right-click to set floor to air."); //smartGUI.add(33, Material.COMPARATOR, (player, b, b1) -> this.showCustomMapSettings(), RED + "Map Settings", GRAY + "Change settings."); smartGUI.add(33, Material.TNT, (player, b, b1) -> this.deleteMap(true), RED + "Delete Map", GRAY + "Delete this custom map."); smartGUI.fillEmptySpots(); this.openGui(smartGUI); } private void shareCustomMap(CustomMap customMap) { if (this.enoughSecondsHaveElapsed(Cooldown.SHARE_MAP)) { this.updateCooldown(Cooldown.SHARE_MAP); } else { this.showCooldownWarning(Cooldown.SHARE_MAP); return; } ComponentBuilder componentBuilder = new ComponentBuilder(); componentBuilder.color(ComponentBuilder.BLUE).line().newLine(); String code = customMap.getId(); componentBuilder.copy("/setmap " + code, GOLD + UNDERLINE.toString() + "/setmap " + code, "Click to copy.").newLine(); componentBuilder.copy(code, GOLD + UNDERLINE.toString() + code, "Click to copy.").newLine(); componentBuilder.color(ComponentBuilder.GREEN).append("This map has been shared publicly.").newLine(); componentBuilder.color(ComponentBuilder.BLUE).line(); this.sendMessage(componentBuilder); this.playSuccessSound(); customMap.setVisible(); if (customMap.getMap().isEmpty()) { this.sendInfoMessage("Your custom map is empty!"); } CustomMap.insertIntoDatabase(customMap); } private void editCustomMapLabel(boolean autoSave, boolean fromMapList) { SmartGUI smartGUI = new SmartGUI("Label", 1, false); smartGUI.add(2, Material.NAME_TAG, (player, b, b2) -> this.renameMap(autoSave), AQUA + "Change Name", GRAY + this.customMapEdited.getName()); smartGUI.add(4, Material.BARRIER, (player, b, b1) -> { if (autoSave) { if (fromMapList) { this.openDuelsCustomMapsListGui(); } else { this.selectMap(); } } else { this.showCustomMapMenu(); } }, RED + "Back"); if (autoSave) { smartGUI.add(6, this.customMapEdited.getRepresentative(), (player, b, b2) -> this.chooseMapIcon(true), RED + "Kit Icon", GRAY + "Browse items to change your representative."); } else { smartGUI.add(6, this.customMapEdited.getRepresentative(), (player, b, b2) -> this.showCustomMapMenu(), RED + "Kit Icon", GRAY + "Drop an item here to change your map representative."); } smartGUI.fillEmptySpots(); this.openGui(smartGUI); this.playClickSound(); } private void selectMap() { if (this.lastEditKitGui != null) { this.lastEditKitGui.selectMap(); } else { this.closeInventory(); } } private void showCustomMapSpawns() { SmartGUI spawns = new SmartGUI("Spawns", 3, false); spawns.add(12, Material.BLUE_TERRACOTTA, (player, b, b1) -> this.setCustomMapSpawn(this.getLocation(), false), AQUA + "Set Spawn A", GRAY + "Set the first spawn to where you are currently."); spawns.add(14, Material.RED_TERRACOTTA, (player, b, b1) -> this.setCustomMapSpawn(this.getLocation(), true), RED + "Set Spawn B", GRAY + "Set the second spawn to where you are currently."); spawns.add(0, Material.ARROW, (player, b, b1) -> this.showCustomMapMenu(), RED + "Cancel"); spawns.fillEmptySpots(); this.openGui(spawns); } private void chooseCustomMapTemplate() { SmartGUI presetGUI = new SmartGUI("Templates", this.isAdministrator() ? 6 : 3, false); List<String> templateNames = Miscellaneous.getList("walled", "island", "cave", "lake", "bedrock"); for (int i = 0; i < 5; i++) { String name = templateNames.get(i) + "template"; CustomMap template = Miscellaneous.match(Main.CUSTOM_MAP_TEMPLATES, customMap -> customMap.getId().equalsIgnoreCase(name)); if (template != null) { presetGUI.add(11 + i, template.getRepresentative(), (player, b, b1) -> this.confirmTemplate(template), template.getName()); } } if (this.isAdministrator()) { int index = 27; for (CustomMap template : Main.CUSTOM_MAP_TEMPLATES) { if (!Text.comparablyContains(template.getId(), "template")) { presetGUI.add(index++, template.getRepresentative(), (player, b, b1) -> this.confirmTemplate(template), template.getName()); } } } presetGUI.add(0, Material.ARROW, (player, b, b1) -> this.showCustomMapMenu(), RED + "Cancel"); presetGUI.fillEmptySpots(); this.openGui(presetGUI); } public void applyTemplate(CustomMap customMap) { this.closeInventory(); for (Block customMapBlock : this.getCustomMapBlocks(this.customMapSize)) { customMapBlock.setType(Material.AIR); } this.sendSuccessMessage("Applied %s%s%s template to your custom map.", YELLOW, customMap.getName(), GREEN); this.playSuccessSound(); this.customMapBlocks.clear(); this.customMapSpawnA = customMap.getSpawnA(); this.customMapSpawnB = customMap.getSpawnB(); this.customMapSpawnA.setWorld(this.getWorld()); this.customMapSpawnB.setWorld(this.getWorld()); this.customMapRepresentative = customMap.getRepresentative(); this.teleport(this.customMapCenter.clone().add(0, 5, 0).add(this.customMapSpawnA.toVector())); for (HubPlayer mapCollaborator : this.mapCollaborators) { mapCollaborator.teleport(this.customMapCenter.clone().add(0, 5, 0).add(this.customMapSpawnA.toVector())); } this.customMapSize = Math.max(this.customMapSize, customMap.getSize()); checkCustomMapCenter(); World world = Main.getWorld(); for (CustomMap.Block block : customMap.getMap()) { Vector position = block.getPosition(); int x = (int) (this.customMapCenter.getX() + position.getX()); int y = (int) (this.customMapCenter.getY() + position.getY()); int z = (int) (this.customMapCenter.getZ() + position.getZ()); Block worldBlock = world.getBlockAt(x, y, z); worldBlock.setType(block.material()); worldBlock.setBlockData(block.blockData()); this.customMapBlocks.add(worldBlock); } } private void confirmTemplate(CustomMap template) { SmartGUI confirm = new SmartGUI("Confirm", 1, false); confirm.add(3, Material.GREEN_TERRACOTTA, (player, b, b1) -> this.applyTemplate(template), GREEN + "Confirm", GRAY + "Delete your current map and replace it with this template."); confirm.add(5, Material.RED_TERRACOTTA, (player, b, b1) -> this.chooseCustomMapTemplate(), RED + "Cancel", GRAY + "Cancel and return to menu."); confirm.fillEmptySpots(); this.openGui(confirm); } private void guideInfo() { } public void sendSetSpawnMessage() { this.sendInfoMessage("Use /setspawn [id] to update your spawnpoints!"); } public void setFloor(Material material) { World world = this.customMapCenter.getWorld(); if (material == Material.BEDROCK || (material.isBlock() && ((material.isSolid() && material.isCollidable()) || material == Material.AIR) && !material.hasGravity() && !Text.comparablyContains(material, "door", "dripstone", "bed", "cact", "enchanting"))) { int startX = this.getCustomMapMin().getBlockX(); int startZ = this.getCustomMapMin().getBlockZ(); int endX = this.getCustomMapMax().getBlockX(); int endZ = this.getCustomMapMax().getBlockZ(); for (int x = startX; x < endX; x++) { for (int z = startZ; z < endZ; z++) { Block block = world.getBlockAt(x + 1, CUSTOM_MAP_Y, z + 1); if (!this.collidesWithCustomSpawn(block)) { block.setType(material); } Miscellaneous.addIfAbsent(this.customMapBlocks, block); } } this.playSuccessSound(); this.sendSuccessMessage("Updated floor."); } else { this.sendErrorMessage("That is not a valid block!"); this.playErrorSound(); } } public List<Block> getCustomMapBlocks() { return this.getCustomMapBlocks(this.customMapSize); } public List<Block> getCustomMapBlocks(int size) { List<Block> blocks = new ArrayList<>(); World world = this.customMapCenter.getWorld(); int startX = this.getCustomMapMin(size).getBlockX(); int startZ = this.getCustomMapMin(size).getBlockZ(); int endX = this.getCustomMapMax(size).getBlockX(); int endZ = this.getCustomMapMax(size).getBlockZ(); for (int x = startX; x < endX; x++) { for (int z = startZ; z < endZ; z++) { for (int y = CUSTOM_MAP_Y; y < MAX_CUSTOM_MAP_Y; y++) { Block block = world.getBlockAt(x + 1, y, z + 1); if (!block.getType().isAir()) { blocks.add(block); } } } } return blocks; } private void setCustomMapHeight() { this.getStringInput("Max Height", String.valueOf(this.customMapHeight), s -> { try { int val = Integer.parseInt(s); val = Math.max(1, Math.min(val, 100)); this.customMapHeight = val; this.playSuccessSound(); } catch (Exception e) { this.onInvalidInput(); } this.closeInventory(); }); } private void deleteMap(boolean fromEditMap) { SmartGUI confirm = new SmartGUI("Confirm", 1, true); confirm.add(3, Material.GREEN_TERRACOTTA, ((player, b, b1) -> { this.isCreatingCustomMap = false; this.customMaps.removeIf(customMap -> customMap.getId().equals(this.customMapEdited.getId())); this.smartPlayer.getCustomMaps().removeIf(customMap -> customMap.getId().equals(this.customMapEdited.getId())); for (CustomDuelsKit customDuelKit : Miscellaneous.getList(this.customDuelKits)) { if (customDuelKit.getMaps().contains(this.customMapEdited.getId())) { customDuelKit.getMaps().clear(); customDuelKit.getMaps().add(DuelMap.ARENA.getCodeName()); this.saveCustomKit(customDuelKit, customDuelKit.getId()); } } this.updateCustomMapList(); this.playSuccessSound(); this.sendSuccessMessage("Custom map deleted."); if (fromEditMap) { this.spawn(true); } else { if (this.lastEditKitGui != null) { this.openCustomKitGui(this.lastEditKitGui.customDuelsKit, false); } } }), RED + "Confirm", GRAY + "Delete this map permanently."); confirm.add(5, Material.RED_TERRACOTTA, ((player, b, b1) -> { if (fromEditMap) { this.closeInventory(); } else { this.showCustomMapMenu(); } }), YELLOW + "Cancel"); hasNoMaps = this.customMaps.isEmpty(); this.openGui(confirm); } private synchronized void updateCustomMapList() { if (!Main.isDuelsLobby() || !Miscellaneous.enoughSecondsHavePassed(this.smartPlayer.getConnectTime(), 5)) { return; } if (this.customMaps.isEmpty() && !hasNoMaps) { return; } this.smartPlayer.updateGamePlayerDataDatabase(GamePlayerDataColumn.DUELS_CUSTOM_MAPS, Text.toCSV(Miscellaneous.processList(this.customMaps, CustomMap::getId))); } public synchronized void updateCustomKitList() { if (!Main.isDuelsLobby() || !Miscellaneous.enoughSecondsHavePassed(this.smartPlayer.getConnectTime(), 5)) { return; } if (this.customDuelKits.isEmpty() && !hasNoKits) { return; } List<CustomDuelsKit> copy = new ArrayList<>(); for (CustomDuelsKit customDuelKit : this.customDuelKits) { Miscellaneous.addIfAbsent(copy, customDuelKit); } this.customDuelKits.clear(); this.customDuelKits.addAll(copy); this.smartPlayer.updateGamePlayerDataDatabase(GamePlayerDataColumn.DUELS_CUSTOM_KITS, Text.toCSV(Miscellaneous.processList(this.customDuelKits, CustomDuelsKit::getId))); } private void chooseMapIcon(boolean autoSave) { this.showCategorySelect(autoSave); } public void showCategorySelect(boolean autoSave) { SmartGUI smartGUI = new SmartGUI("Categories", 5, false); List<EditCustomKitGUI.ItemCategory> itemCategories = Miscellaneous.getList(EditCustomKitGUI.ItemCategory.values()); smartGUI.add(31, Material.BARRIER, (player, b, b2) -> { if (autoSave) { this.editSocialSettings(this.customMapEdited, true); } else { this.showCustomMapMenu(); } }, RED + "Cancel"); if (itemCategories.size() % 2 == 0) { int startingIndex = 13 - itemCategories.size() / 2 + 1; for (int i = 0; i < itemCategories.size() - 1; i++) { EditCustomKitGUI.ItemCategory itemCategory = itemCategories.get(i); smartGUI.add(startingIndex + i, itemCategory.representative, (player, b, b2) -> this.showItemCategorySelect(itemCategory, autoSave), AQUA + itemCategory.name); } int i = itemCategories.size() - 1; EditCustomKitGUI.ItemCategory itemCategory = itemCategories.get(i); smartGUI.add(22, itemCategory.representative, (player, b, b2) -> this.showItemCategorySelect(itemCategory, autoSave), AQUA + itemCategory.name); } else { int startingIndex = 13 - itemCategories.size() / 2; for (int i = 0; i < itemCategories.size(); i++) { EditCustomKitGUI.ItemCategory itemCategory = itemCategories.get(i); smartGUI.add(startingIndex + i, itemCategory.representative, (player, b, b2) -> this.showItemCategorySelect(itemCategory, autoSave), AQUA + itemCategory.name); } } this.openGui(smartGUI); } public void showItemCategorySelect(EditCustomKitGUI.ItemCategory itemCategory, boolean autoSave) { if (itemCategory == EditCustomKitGUI.ItemCategory.POTION) { this.showPotionSelect(autoSave); } else { List<KitItem> options = getKitItemsForCategory(itemCategory); this.showItemSelect(options, itemCategory, autoSave); } } public void showItemSelect(List<KitItem> options, EditCustomKitGUI.ItemCategory itemCategory, boolean autoSave) { SmartGUI smartGUI = new SmartGUI("Select", 6, false); smartGUI.add(49, Material.BARRIER, (player, b, b2) -> this.showCategorySelect(autoSave), RED + "Cancel"); for (int index = 0; index < options.size(); index++) { KitItem kitItem = options.get(index); Material material = kitItem.itemStack.getType(); if (kitItem.itemStack.getType() != Material.AIR) { if (index < 54) { smartGUI.add(index, kitItem.itemStack, (player, b, b2) -> this.setCustomMapRepresentative(kitItem.itemStack.getType(), autoSave)); } else { Main.warn("Invalid index! (i = %d, index = %d)!", index, index); } } } this.openGui(smartGUI); } public void setCustomMapRepresentative(Material type, boolean autoSave) { this.customMapRepresentative = type; this.customMapEdited.setRepresentative(type); this.playSuccessSound(); this.sendSuccessMessage("Updated custom map representative."); if (autoSave) { this.saveCustomMap(false); } else { this.closeInventory(); } } public void showPotionSelect(boolean autoSave) { List<KitItem.PotionKitItem> options = new ArrayList<>(); for (PotionEffectType value : PotionEffectType.values()) { if (PotionType.getByEffect(value) != null) { options.add(new KitItem.PotionKitItem(value, Material.POTION, false, false, -1)); } } SmartGUI smartGUI = new SmartGUI("Select", 6, false); smartGUI.add(40, Material.BARRIER, (player, b, b2) -> { if (autoSave) { this.editSocialSettings(this.customMapEdited, true); } else { this.showCustomMapMenu(); } }, RED + "Cancel"); int rowLength = 7; for (int i = 0; i < options.size(); i++) { // i = 7 int row = i / rowLength; // 1 int positionInRow = i % rowLength; // 0 int remainingAfterLength = options.size() % rowLength; // 1 int reduce = (i + 1) < (9 * options.size() / rowLength) ? rowLength / 2 : ((remainingAfterLength == 0 ? rowLength : remainingAfterLength) / 2); // 15 - 7 > 7 + 1 ? 7 / 2 : ((1 == 1 ? 7 : remainingAfterLength) / 2) int startingPositionInRow = 13 + (9 * row) - reduce; int index = startingPositionInRow + positionInRow; KitItem.PotionKitItem potionKitItem = options.get(i); if (index < 54) { PotionMeta potionMeta = (PotionMeta) potionKitItem.itemStack.getItemMeta(); if (potionMeta.getCustomEffects().isEmpty()) { smartGUI.add(index, potionKitItem.itemStack, (player, b, b2) -> this.showPotionSelect(((PotionMeta) potionKitItem.itemStack.getItemMeta()).getBasePotionData().getType().getEffectType(), autoSave)); } else { smartGUI.add(index, potionKitItem.itemStack, (player, b, b2) -> this.showPotionSelect(((PotionMeta) potionKitItem.itemStack.getItemMeta()).getCustomEffects().get(0).getType(), autoSave)); } } else { Main.warn("Invalid index! (i = %d; index = %d)", i, index); } } this.openGui(smartGUI); } public void showPotionSelect(PotionEffectType type, boolean autoSave) { List<KitItem> options = new ArrayList<>(); for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { for (int k = 0; k < 2; k++) { boolean extended = j == 1; boolean upgraded = k == 1; Material material = switch (i) { case 0 -> Material.POTION; case 1 -> Material.SPLASH_POTION; default -> Material.LINGERING_POTION; }; PotionType potionType = PotionType.getByEffect(type); if (potionType != null) { if (!((!potionType.isExtendable() && extended) || (!potionType.isUpgradeable() && upgraded) || (upgraded && extended))) { options.add(new KitItem.PotionKitItem(type, material, extended, upgraded, -1)); } } else { Main.error("Potion Type is null for %s", type); } } } } this.showItemSelect(options, EditCustomKitGUI.ItemCategory.POTION, autoSave); } public void showItemSelect(List<Material> options, boolean autoSave) { int rowsize = 9; int totalRows = (int) (Math.ceil(options.size() / (double) rowsize)) + 1; SmartGUI smartGUI = new SmartGUI("Select", totalRows, false); smartGUI.add((totalRows - 1) * 9 + 4, Material.BARRIER, (player, b, b2) -> this.showCustomMapMenu(), RED + "Cancel"); for (int i = 0; i < options.size(); i++) { Material material = options.get(i); if (material != null) { smartGUI.add(i, material, ((player, b, b1) -> this.setCustomMapRepresentative(material, autoSave))); } } this.openGui(smartGUI); } public static List<KitItem> turnIntoKitItems(Material... materials) { return Miscellaneous.processList(Miscellaneous.getList(materials), KitItem::new); } private void renameMap(boolean autoSave) { this.getStringInput("Rename...", this.customMapName, s -> { if (s.isBlank() || s.length() > 32 || !SwearUtils.canSendMessageAtLevel(s, ChatFilter.HIGH)) { this.playErrorSound(); this.sendErrorMessage("Invalid name!"); } else { if (this.isInGroupOrHigher(Group.CHAMPION)) { s = ChatColor.translateAlternateColorCodes('&', s); } this.customMapName = s; this.playSuccessSound(); this.sendSuccessMessage("Your custom map has been renamed."); if (autoSave) { this.saveCustomMap(false); } else { this.closeInventory(); } } }); } private void getPlayerHead() { this.getStringInput("Player Head", "Enter player name...", s -> { if (s.length() > 2 && s.length() < 17) { ItemStack itemStack = new ItemStack(Material.PLAYER_HEAD); SkullMeta skullMeta = (SkullMeta) itemStack.getItemMeta(); UUID uuid = RelayUtils.getUUID(s); if (uuid == null) { this.playErrorSound(); this.closeInventory(); this.sendErrorMessage("Could not find a player by the name of %s%s%s.", YELLOW, s, RED); } else { GameProfile gameProfile = new GameProfile(uuid, s); String[] textures = RelayUtils.getTextureFromUUID(this.getUUID()); if (textures != null) { gameProfile.getProperties().put("textures", new Property(textures[0], textures[1])); } OfflinePlayer offlinePlayer = ((CraftServer) Bukkit.getServer()).getOfflinePlayer(gameProfile); skullMeta.setOwningPlayer(offlinePlayer); itemStack.setItemMeta(skullMeta); this.closeInventory(); this.getInventory().addItem(itemStack); this.playSuccessSound(); } } else { this.playErrorSound(); this.closeInventory(); } }); } private synchronized void saveCustomMap(boolean fromMapEditor) { if (fromMapEditor) { this.customMapEdited.setMap(Miscellaneous.processList(this.getCustomMapBlocks(), block -> { Vector val = block.getLocation().toVector().subtract(getCustomMapSaveCenter()); CustomMap.Block b = new CustomMap.Block((float) val.getX(), (float) val.getY(), (float) val.getZ(), block.getType(), block.getBlockData()); if (b.getPosition().getY() < 0) { Main.error("(Saving) Custommap block is lower than 0: %s | %s | (Block: %s Center: %s)", Text.shortenDouble(b.getPosition().getY(), 2), this.customMapEdited.getId(), block.getLocation().toVector(), getCustomMapSaveCenter()); } return b; })); this.customMapEdited.setSpawnA(this.customMapSpawnA); this.customMapEdited.setSpawnB(this.customMapSpawnB); this.customMapEdited.setContributors(Miscellaneous.with(this.customMapEdited.getContributors(), this.allCollaborators)); for (HubPlayer mapCollaborator : this.mapCollaborators) { mapCollaborator.isCreatingCustomMap = false; mapCollaborator.sendInfoMessage("The owner has finished editing their custom map. You have been sent back to spawn."); mapCollaborator.spawn(true); } this.mapCollaborators.clear(); this.allCollaborators.clear(); } this.customMapEdited.setRepresentative(this.customMapRepresentative); this.customMapEdited.setName(this.customMapName); // ignore publishing for now, just overwrite ig int index = this.customMaps.size(); for (int i = 0; i < this.customMaps.size(); i++) { CustomMap customMap = this.customMaps.get(i); if (customMap.getId().equalsIgnoreCase(this.customMapEdited.getId())) { index = i; break; } } this.customMaps.removeIf(customMap -> customMap.getId().equalsIgnoreCase(this.customMapEdited.getId())); this.smartPlayer.getCustomMaps().removeIf(customMap -> customMap.getId().equalsIgnoreCase(this.customMapEdited.getId())); if (this.customMapEdited.isVisible()) { this.customMapEdited.getNewId(); this.customMapEdited.hide(); } this.customMaps.add(index, this.customMapEdited); this.smartPlayer.getCustomMaps().add(this.customMapEdited); this.updateCustomMapList(); CustomMap.insertIntoDatabase(this.customMapEdited); if (customMapEdited.getMap().isEmpty()) { this.sendInfoMessage("Your custom map is empty!"); } this.sendSuccessMessage("Custom map saved."); this.playSuccessSound(); this.isCreatingCustomMap = false; for (Block customMapBlock : this.getCustomMapBlocks(this.customMapSize)) { customMapBlock.setType(Material.AIR); } CUSTOM_MAP_CENTERS.remove(this.customMapCenter); this.customMapBlocks.clear(); if (fromMapEditor) { this.spawn(true); this.openGui(this.lastEditKitGui); } } private Vector getCustomMapSaveCenter() { return this.customMapCenter.toVector().setY(CUSTOM_MAP_Y); } public int getMaxCustomMapSize() { if (this.isAdministrator()) { return 500; } if (this.isInGroupOrHigher(Group.CHAMPION)) { return new int[]{35, 100, 125, 150, 175, 200, 225, 250, 275, 300}[Math.min(this.smartPlayer.getChampionTier(), 9)]; } return 35; } public void setCustomMapSize() { if (this.isInGroupOrHigher(Group.CHAMPION)) { this.getStringInput("Map Size", String.valueOf(this.customMapSize), s -> { try { int oldSize = this.customMapSize; int val = Integer.parseInt(s); val = Math.max(2, Math.min(val, this.getMaxCustomMapSize())); if (oldSize > val) { SmartGUI smartGUI = new SmartGUI("Confirm", 1, true); int finalVal = val; smartGUI.add(3, Material.GREEN_TERRACOTTA, (player, b, b1) -> { this.customMapSize = finalVal; for (HubPlayer mapCollaborator : this.mapCollaborators) { mapCollaborator.customMapSize = this.customMapSize; mapCollaborator.sendInfoMessage("The map size has been updated."); } this.playSuccessSound(); this.updateMap(oldSize); }, RED + "Confirm", GRAY + "Blocks outside of your new size will be deleted."); smartGUI.add(5, Material.RED_TERRACOTTA, YELLOW + "Cancel"); smartGUI.fillEmptySpots(); this.openGui(smartGUI); } else { this.customMapSize = val; this.playSuccessSound(); this.updateMap(oldSize); } } catch (Exception e) { this.onInvalidInput(); } this.closeInventory(); }); } else { this.sendChampionPurchaseMessage(); } } private void updateMap(int oldSize) { List<Block> customMapBlocks = this.getCustomMapBlocks(); for (Block customMapBlock : this.getCustomMapBlocks(oldSize + 2)) { if (!customMapBlocks.contains(customMapBlock)) { customMapBlock.setType(Material.AIR); } } boolean odd = this.customMapSize % 2 == 1; double halfSize = this.customMapSize / 4D; if (!this.customMapSpawnA.toVector().isInAABB(this.getCustomMapMin().toVector().setY(-50), this.getCustomMapMax().toVector().setY(320))) { this.customMapSpawnA = new Location(this.getWorld(), halfSize + (odd ? 0.75 : 0.5), CUSTOM_MAP_Y + 1, 0 + (odd ? 1 : 1)); for (HubPlayer mapCollaborator : this.mapCollaborators) { mapCollaborator.customMapSpawnA = this.customMapSpawnA; } this.customMapSpawnA.setYaw(90); } if (!this.customMapSpawnB.toVector().isInAABB(this.getCustomMapMin().toVector().setY(-50), this.getCustomMapMax().toVector().setY(320))) { this.customMapSpawnB = new Location(this.getWorld(), -halfSize + (odd ? 0.75 : 0.5), CUSTOM_MAP_Y + 1, 0 + (odd ? 1 : 1)); this.customMapSpawnB.setYaw(-90); } this.customMapBlocks.removeIf(block -> block.getType() == Material.AIR); //this.setFloor(this.customMapCenter.getBlock().getType()); this.sendSuccessMessage("Your map size has been updated."); this.sendSetSpawnMessage(); } public boolean inCustomMapBoundingBox(Location to) { if (this.customMapCenter != null) { Vector min = this.customMapCenter.toVector().subtract(new Vector(this.customMapSize / 2 + 20, 0, this.customMapSize / 2 + 20)).setY(CUSTOM_MAP_Y - 20); Vector max = this.customMapCenter.toVector().add(new Vector(this.customMapSize / 2 + 20, 0, this.customMapSize / 2 + 20)).setY(330); return to.toVector().isInAABB(min, max); } return true; } public Location getCustomMapMin(int customMapSize) { if (customMapSize % 2 == 1) { return this.customMapCenter.clone().subtract((double) customMapSize / 2, CUSTOM_MAP_Y, (double) customMapSize / 2); } return this.customMapCenter.clone().subtract((double) customMapSize / 2 + 0.5, CUSTOM_MAP_Y, (double) customMapSize / 2 + 0.5); } public Location getCustomMapMax(int customMapSize) { if (customMapSize % 2 == 1) { return this.customMapCenter.clone().add((double) customMapSize / 2, CUSTOM_MAP_Y, (double) customMapSize / 2); } return this.customMapCenter.clone().add((double) customMapSize / 2 - 0.5, CUSTOM_MAP_Y, (double) customMapSize / 2 - 0.5); } private static final int CUSTOM_MAP_Y = 0; private static final int MAX_CUSTOM_MAP_Y = CUSTOM_MAP_Y + 128; public Location getCustomMapMin() { return this.getCustomMapMin(this.customMapSize); } public Location getCustomMapMax() { return this.getCustomMapMax(this.customMapSize); } public boolean isCreatingCustomMap() { return this.isCreatingCustomMap; } public void onBreakBlock(BlockBreakEvent event) { if (!event.getBlock().getLocation().toVector().isInAABB(this.getCustomMapMin().add(1, 0, 1).toVector().setY(CUSTOM_MAP_Y), this.getCustomMapMax().toVector().setY(MAX_CUSTOM_MAP_Y))) { event.setCancelled(true); this.sendErrorMessage("You cannot break blocks outside of your map dimensions!"); this.playErrorSound(); } else if (this.collidesWithCustomSpawn(event.getBlock())) { event.setCancelled(true); this.sendErrorMessage("You cannot break blocks too close to your spawns!"); this.playErrorSound(); } else { if (this.isCreatingOwnedCustomMap()) { this.customMapBlocks.remove(event.getBlock()); } else { this.getCollaborationOwner().customMapBlocks.remove(event.getBlock()); } } } public boolean collidesWithCustomSpawn(Block block) { for (Location location : Miscellaneous.getList(this.customMapSpawnA, this.customMapSpawnB)) { for (int i = -1; i < 2; i++) { Block block1 = this.customMapCenter.clone().add(location.toVector()).add(0, i, 0).getBlock(); if (block.equals(block1)) { Main.warn("collieded with block"); return true; } } } return false; } public void renderCustomMapBorder() { Location center = this.customMapCenter.clone(); double sizeX = this.customMapSize + 1; double sizeZ = this.customMapSize + 1; double height = MAX_CUSTOM_MAP_Y; int particleCountX = (int) (sizeX / 6); int particleCountZ = (int) (sizeZ / 6); int heightCount = (int) (height / 3); double increase = this.customMapSize % 2 == 1 ? 1 : 0.5; double xMin = center.getX() - sizeX / 2.0 + increase; double zMin = center.getZ() - sizeZ / 2.0 + increase; double xMax = center.getX() + sizeX / 2.0 + increase; double zMax = center.getZ() + sizeZ / 2.0 + increase; double yMin = CUSTOM_MAP_Y; double yStep = height / (double) heightCount; double xStep = sizeX / particleCountX; double zStep = sizeZ / particleCountZ; for (int j = 0; j < heightCount; j++) { double y = yMin + j * yStep; // Spawn particles along the top edge for (int i = 0; i < particleCountX; i++) { double x = xMin + i * xStep; spawnWorldParticle(new Location(center.getWorld(), x, y, zMin)); spawnWorldParticle(new Location(center.getWorld(), x, y, zMax)); } // Spawn particles along the side edges for (int i = 0; i < particleCountZ + 1; i++) { double z = zMin + i * zStep; spawnWorldParticle(new Location(center.getWorld(), xMin, y, z)); spawnWorldParticle(new Location(center.getWorld(), xMax, y, z)); } } // Spawn Particles along the top and bottom side for (int i = 0; i < particleCountX + 1; i++) { double x = xMin + i * xStep; for (int j = 0; j < particleCountZ + 1; j++) { double z = zMin + j * zStep; spawnWorldParticle(new Location(center.getWorld(), x, MAX_CUSTOM_MAP_Y, z)); spawnWorldParticle(new Location(center.getWorld(), x, yMin, z)); } } } private void spawnWorldParticle(Location location) { float speed = 1000 / 0.25F; long dif = (long) (location.getX() / 10 - location.getY() / 10); long l = System.currentTimeMillis() - dif; boolean chroma = (this.isStaff() && this.isSprinting()); java.awt.Color chromaColor = java.awt.Color.getHSBColor((l % (int) speed) / speed, 0.8F, 0.8F); location.getWorld().spawnParticle(Particle.REDSTONE, location, 1, 0, 0, 0, 0, new Particle.DustOptions(Color.RED, 1)); } public static boolean blacklistedNBT(ItemStack itemStack) { net.minecraft.world.item.ItemStack nms = CraftItemStack.asNMSCopy(itemStack); if (Text.comparablyEquals(itemStack.getType(), "chestplate", "leggings", "helmet", "boots")) { return false; } if (nms.t()) { NBTTagCompound nbtTagCompound = new NBTTagCompound(); nms.b(nbtTagCompound); for (String s : nbtTagCompound.e()) { NBTBase nbtBase = nbtTagCompound.c(s); if (Text.comparablyEquals(s, "items")) { return true; } if (Text.comparablyEquals(s, "entitytag")) { if (nbtBase instanceof NBTTagString) { Main.info("itemstack nbt thing (%s): %s", itemStack, nbtBase); NBTTagString nbtTagString = ((NBTTagString) nbtBase).e(); if (Text.comparablyContains(nbtTagString.m_(), "dragon", "wither", "warden", "minecart", "boat", "shulker")) { return true; } } } if (Text.comparablyEquals(itemStack.getType(), "shulker", "book")) { return true; } } } return false; } public void onPlaceBlock(BlockPlaceEvent event) { ItemStack itemStack = event.getItemInHand(); if (blacklistedNBT(itemStack) || Text.comparablyContains(itemStack.getType(), BLACKLISTED_ITEMS.toArray())) { this.sendErrorMessage("You cannot use this block."); this.playErrorSound(); event.setCancelled(true); return; } if (this.isCreatingCustomMap) { if (!event.getBlock().getLocation().toVector().isInAABB(this.getCustomMapMin().add(1, 0, 1).toVector().setY(CUSTOM_MAP_Y), this.getCustomMapMax().toVector().setY(MAX_CUSTOM_MAP_Y - 1))) { event.setCancelled(true); this.sendErrorMessage("You cannot place blocks outside of your map dimensions!"); this.playErrorSound(); } if (this.collidesWithCustomSpawn(event.getBlock())) { event.setCancelled(true); this.sendErrorMessage("You cannot place blocks too close to your spawns!"); this.playErrorSound(); } else { if (this.isCreatingOwnedCustomMap()) { this.customMapBlocks.add(event.getBlock()); } else { this.getCollaborationOwner().customMapBlocks.add(event.getBlock()); } } } } public HubPlayer getCollaborationOwner() { return getHubPlayer(this.customMapEdited.getOwner()); } public void setCustomMapSpawn(Location location, boolean spawnB) { Location original = location; location = location.getBlock().getLocation(); this.closeInventory(); Location difference = location.clone().subtract(this.customMapCenter.clone()); difference.setPitch(0); difference.setYaw(original.getYaw()); difference.set(difference.getX(), difference.getBlockY(), difference.getZ()); if (this.getPlayer().isFlying() || !location.add(0, -0.5, 0).getBlock().getType().isCollidable()) { this.playErrorSound(); this.sendErrorMessage("Invalid spawn! You must be on the ground and on a solid surface!"); return; } if (spawnB) { this.customMapSpawnB = difference; } else { this.customMapSpawnA = difference; for (HubPlayer mapCollaborator : this.mapCollaborators) { mapCollaborator.customMapSpawnA = this.customMapSpawnA; } } Location asBlock = this.customMapCenter.clone().add(difference.toVector()); Material type = asBlock.getBlock().getType(); BlockData blockData = asBlock.getBlock().getBlockData(); asBlock.getBlock().setType(Material.RED_STAINED_GLASS); Main.schedule(() -> { if (this.isCreatingCustomMap) { asBlock.getBlock().setType(type); asBlock.getBlock().setBlockData(blockData); } }, 1); this.sendSuccessMessage("Spawn %s set to %s%s %s %s [%s %s]%s.", spawnB ? "B" : "A", YELLOW, difference.getX(), difference.getY(), difference.getZ(), difference.getYaw(), difference.getPitch(), GREEN); this.playSuccessSound(); } public void setCustomMapSpawn(Location location) { this.setCustomMapSpawn(location, this.customMapSpawnA != null); } public void onKilled() { this.setPoints(0); this.arenaStats.put("killstreak", 0); this.arenaStats.put("deaths", this.arenaStats.get("deaths").intValue() + 1); this.arenaStats.put("kdr", this.arenaStats.get("kills").doubleValue() / (Math.max(1, this.arenaStats.get("deaths").doubleValue()))); } public void setCanRequeue() { this.canRequeue = true; } public boolean canRequeue() { return this.canRequeue; } public void togglePlayers() { if (this.canSeePlayers) { this.hidePlayers(); } else { this.showPlayers(); } } public void updateLastMovementTime() { this.lastMovementTime = System.currentTimeMillis(); this.AFKAgain = false; } public void setLimboQueuePosition(String position, String size) { this.limboQueuePosition = position; this.limboQueueSize = size; } public void checkCustomMapCenter() { if (this.customMapSize % 2 == 1) { this.customMapCenter.set(this.customMapCenter.getBlockX(), CUSTOM_MAP_Y, this.customMapCenter.getBlockZ()).add(0.5, 0, 0.5); } } public void editSocialSettings(CustomMap customMap, boolean fromMapList) { this.customMapEdited = customMap; if (!fromMapList) { this.customMapEdited.setMap(Miscellaneous.processList(this.getCustomMapBlocks(), block -> { Vector val = block.getLocation().toVector().subtract(getCustomMapSaveCenter()); return new CustomMap.Block((float) val.getX(), (float) val.getY(), (float) val.getZ(), block.getType(), block.getBlockData()); })); } this.customMapCenter = getAvailableCenter(customMap); this.customMapBlocks = new ArrayList<>(); this.customMapSpawnA = customMap.getSpawnA(); this.customMapSpawnB = customMap.getSpawnB(); this.customMapVisibility = customMap.isVisible(); this.customMapName = customMap.getName(); this.customMapRepresentative = customMap.getRepresentative(); this.customMapSize = customMap.getSize(); SmartGUI smartGUI = new SmartGUI("Map Settings", 1, false); smartGUI.add(0, Material.ARROW, (p, b, b1) -> { if (fromMapList) { this.openDuelsCustomMapsListGui(); } else { this.selectMap(); } }, RED + "Back"); smartGUI.add(3, Material.WRITABLE_BOOK, (player, b, b1) -> this.shareCustomMap(this.customMapEdited), AQUA + "Share Map", GRAY + "Share your custom map."); smartGUI.add(4, Material.NAME_TAG, (player, b, b1) -> this.editCustomMapLabel(true, fromMapList), GREEN + "Map Label", GRAY + "Change the name and icon of this kit."); smartGUI.add(5, Material.TNT, (player, b, b1) -> this.deleteMap(false), RED + "Delete", GRAY + "Delete this map."); this.openGui(smartGUI); } public void openDuelsCustomMapsListGui() { final int start = this.isAdministrator() ? 9 : 11; SmartGUI mapGUI = new SmartGUI("Maps", this.isAdministrator() ? 5 : 4, false); if (this.customMaps.isEmpty()) { mapGUI.add(13, Material.OAK_BUTTON, (player, b, b1) -> this.createCustomMap(), GREEN + ChatColor.BOLD.toString() + "CREATE MAP", GRAY + ITALIC.toString() + "Select to create a custom map!"); } else { for (int i = 0; i < (this.isAdministrator() ? 18 : 5); i++) { List<CustomMap> customMaps = Miscellaneous.filter(this.getCustomMaps(), customMap -> customMap.getOwner().equals(this.getUUID())); if (i < customMaps.size()) { CustomMap customMap = customMaps.get(i); mapGUI.add(start + i, customMap.getRepresentative(), (player, b, b1) -> { if (b1) { this.editSocialSettings(customMap, true); } else { this.editCustomMap(customMap, false); } }, AQUA + customMap.getName(), GRAY + "Left or right-click to edit.", GRAY + "Shift-click to edit settings."); } else { if (i < this.getMaxCustomMaps()) { mapGUI.add(start + i, Material.OAK_BUTTON, (((player, b, b1) -> this.createCustomMap())), GREEN + "Create Custom Map", GRAY + "Make your own map."); } else { mapGUI.add(start + i, Material.STONE_BUTTON, (player, b, b1) -> this.playErrorSound(), ChatColor.RED + ChatColor.BOLD.toString() + "CREATE MAP", GRAY + ITALIC.toString() + "Upgrade to Premium rank to unlock this slot."); } } } } mapGUI.add(this.isAdministrator() ? 39 : 30, Material.EMERALD, (player, b, b1) -> this.showCustomMapHistory(null), GREEN + "History", GRAY + "View your recently played maps."); mapGUI.add(this.isAdministrator() ? 41 : 32, Material.CLOCK, (player, b, b1) -> this.browsePublicMaps(null, false), GOLD + "Public Maps", GRAY + "Browse public custom maps."); mapGUI.fillEmptySpots(); this.openGui(mapGUI); } private void createCustomMap() { CustomMap customMap = new CustomMap(this.smartPlayer); this.editCustomMap(customMap, true); } public void onChat(String message) { if (this.smartPlayer.canSendChatMessage(message)) { for (HubPlayer onlineHubPlayer : HubPlayer.getOnlineHubPlayers()) { onlineHubPlayer.sendChatMessage(this, message); } } } public void onClickQueuedGame(QueueData queuedGame, GameType gameType, int playersNeeded, int ready) { if (queuedGame.getData("owner").equals(this.getUUID().toString())) { this.cancelQueue(); this.playSuccessSoundVariation(); return; } if (ready >= playersNeeded) { this.sendErrorMessage("This queue is full!"); this.playErrorSound(); return; } if (this.getPartySize() > 1) { this.sendErrorMessage("You cannot queue public matches in a party!"); this.playErrorSound(); return; } if (ready + this.getPartySize() > playersNeeded) { this.sendErrorMessage("Your party is too large!"); this.playErrorSound(); return; } this.queuedAgainst = UUID.fromString(queuedGame.getData("owner")); this.queue(gameType, new QueueData().attachData("with", queuedGame.getData("owner")).attachBoolean("another", true).attachData("lobby", RelayUtils.getName())); } public void onClickQueuedGame(QueueData queuedGame, boolean rightClick, CustomDuelsKit customDuelsKit, int playersNeeded, int ready) { SmartPlayer owner = SmartPlayer.getOrCreate(UUID.fromString(queuedGame.getData("owner"))); if (owner == this.smartPlayer) { this.cancelQueue(); return; } this.previewKit = customDuelsKit; if (rightClick) { String map = customDuelsKit.getMaps().get(0); CustomMap customMap = CustomMap.CODE_TO_MAP.get(map); if (customMap != null) { this.previewCenter = getAvailableCenter(customMap); if (customMap.getSize() % 2 == 1) { previewCenter.add(0.5, 0, 0.5); } for (CustomMap.Block block : customMap.getMap()) { Vector position = block.getPosition(); int x = (int) (previewCenter.getX() + position.getX()); int y = (int) (previewCenter.getY() + position.getY()); int z = (int) (previewCenter.getZ() + position.getZ()); Block worldBlock = getWorld().getBlockAt(x, y, z); worldBlock.setType(block.material()); worldBlock.setBlockData(block.blockData()); this.previewMapBlocks.add(worldBlock); } this.previewMap = customMap; this.isPreviewingMap = true; Main.synchronous(() -> { this.smartPlayer.setGameMode(GameMode.CREATIVE); this.teleport(previewCenter.clone().add(customMap.getSpawnA().toVector())); this.teleportedToPreviewMap = true; }); this.smartPlayer.clear(true); this.smartPlayer.setAllowFlight(true); this.smartPlayer.setGameMode(GameMode.ADVENTURE); this.giveSmartItem(SmartGUIUtils.PREVIEW_KIT); this.giveSmartItem(SmartGUIUtils.ACCEPT_KIT); this.giveSmartItem(SmartGUIUtils.CANCEL_KIT); this.giveSmartItem(4, SmartGUIUtils.MAP_INFO); } this.previewQueueOwner = owner.getUUID(); this.openPreviewKitGUI(false, false); return; } if (queuedGame.getData("owner").equals(this.getUUID().toString())) { this.sendErrorMessage("You cannot duel yourself!"); this.playErrorSound(); return; } if (ready >= playersNeeded) { this.sendErrorMessage("This queue is full!"); this.playErrorSound(); return; } if (this.getPartySize() > 1) { this.sendErrorMessage("You cannot queue public matches in a party!"); this.playErrorSound(); return; } if (ready + this.getPartySize() > playersNeeded) { this.sendErrorMessage("Your party is too large!"); this.playErrorSound(); return; } this.onClickQueuedGame(queuedGame, GameType.DUELS_CUSTOM, playersNeeded, ready); } private void openPreviewKitGUI(boolean library, boolean browsing) { this.previewCustomKitGUI = new PreviewCustomKitGUI(this.previewKit, this, library, browsing); this.openGui(this.previewCustomKitGUI); } public static void onCustomQueueRemoved(String ownerUUID) { for (HubPlayer onlineHubPlayer : getOnlineHubPlayers()) { if (ownerUUID.equals(String.valueOf(onlineHubPlayer.previewQueueOwner)) && onlineHubPlayer.isInQueue()) { onlineHubPlayer.kickFromPreview(); } } onDuelsQueueRemoved(ownerUUID); } public static void onDuelsQueueRemoved(String ownerUUID) { for (HubPlayer onlineHubPlayer : getOnlineHubPlayers()) { if (ownerUUID.equals(String.valueOf(onlineHubPlayer.queuedAgainst))) { if (onlineHubPlayer.isInQueue()) { onlineHubPlayer.sendErrorMessage("The player you were queued against is no longer queued."); onlineHubPlayer.cancelQueue(); } onlineHubPlayer.queuedAgainst = null; } } } private static final List<Location> CUSTOM_MAP_CENTERS = new ArrayList<>(); private static Location getAvailableCenter(CustomMap customMap) { int rng = Miscellaneous.getRandomIntBetweenRange(2000, 4000); int rng2 = Miscellaneous.getRandomIntBetweenRange(2000, 4000); Location location = new Location(Main.getWorld(), Miscellaneous.getRandomTrueOrFalse() ? rng : -rng, CUSTOM_MAP_Y, Miscellaneous.getRandomTrueOrFalse() ? rng2 : -rng2, 0, 0); if (Miscellaneous.match(CUSTOM_MAP_CENTERS, o -> o.distance(location) <= 150) == null) { CUSTOM_MAP_CENTERS.add(location); return location; } return getAvailableCenter(customMap); } public boolean inPreviewingMapBoundingBox(Location to) { if (this.previewCenter != null) { Vector min = this.previewCenter.toVector().subtract(new Vector(100 / 2 + 20, 0, 100 / 2 + 20)).setY(CUSTOM_MAP_Y - 20); Vector max = this.previewCenter.toVector().add(new Vector(100 / 2 + 20, 0, 100 / 2 + 20)).setY(330); return to.toVector().isInAABB(min, max); } return true; } public void teleportToPreviewMap() { if (this.previewCenter != null) { Location toTeleport = PlayerUtilities.getNearestTwoBlockSpaceAbove(this.previewCenter.clone().add(this.previewMap.getSpawnA().toVector())); toTeleport.add(0, 3, 0); if (toTeleport.getY() >= 130) { toTeleport.setY(5); } Location location = this.previewCenter.clone().add(this.previewMap.getSpawnA().toVector()); if (!this.inCustomMapBoundingBox(location)) { this.teleport(toTeleport); } else { this.teleport(location); } this.sendSuccessMessage("Teleported you to map."); Main.synchronous(() -> { this.addPotionEffect(PotionEffectType.NIGHT_VISION); this.teleportedToPreviewMap = true; }); Main.scheduleSyncDelayedTask(() -> this.addPotionEffect(PotionEffectType.NIGHT_VISION), 1); } } public void previewKit() { this.openPreviewKitGUI(false, false); } public void acceptKit() { if (this.previewQueueOwner.equals(this.getUUID())) { this.playErrorSound(); this.sendErrorMessage("You cannot queue against yourself!"); return; } if (this.previewQueueOwner != null) { this.cancelKit(false); } this.queuedAgainst = this.previewQueueOwner; this.queue(GameType.DUELS_CUSTOM, new QueueData().attachData("with", this.previewQueueOwner).attachBoolean("another", true)); } public void cancelKit(boolean openGUi) { for (Block previewMapBlock : this.previewMapBlocks) { previewMapBlock.setType(Material.AIR); } this.previewMapBlocks.clear(); this.isPreviewingMap = false; this.teleportedToPreviewMap = false; this.previewKit = null; this.previewCustomKitGUI = null; this.previewMap = null; this.spawn(true); if (openGUi) { this.openGui(CUSTOM_KITS_QUEUE); } } public void kickFromPreview() { this.sendErrorMessage("The kit you were previewing is no longer in the queue!"); this.cancelKit(true); } public void spectate(String s) { ServerCommunicator.sendToProxy(Command.SPECTATE, this.getUUID(), s); } public void onEnterQueue() { this.giveSmartItem(SmartGUIUtils.LEAVE_QUEUE); } public void createCustomQueue(int i) { if (this.customDuelKits.isEmpty()) { this.openDuelsCustomKitsListGui(1); this.sendErrorMessage("You do not have any custom kits created!"); this.playErrorSound(); } else { QueueData queueData1 = new QueueData().attachData("owner", this.getUUID()).attachData("another", false).attachData("index", i).attachData("size", this.getPreferredQueueSize(GameType.DUELS_CUSTOM)); this.queue(GameType.DUELS_CUSTOM, queueData1); } } public void cancelQueue() { ServerCommunicator.sendToProxy(Command.CANCEL, this.getUUID()); } public void createQueue(int i, GameType gameType) { if (gameType == GameType.DUELS_CUSTOM) { this.createCustomQueue(i); } else { if (gameType.getMainGame() == MainGame.MANHUNT) { this.queue(gameType, new QueueData().attachData("owner", this.getUUID()) .attachData("index", i) .attachData("size", this.getPreferredHunterCount() + this.getPreferredRunnerCount()) .attachData("runners", this.getPreferredRunnerCount()) .attachData("hunters", this.getPreferredHunterCount()) .attachData("release", this.getPreferredReleaseTime()) .attachData("dropRate", this.getPreferredDropRate()) .attachData("tradeRate", this.getPreferredTradeRate())); } else { this.queue(gameType, new QueueData().attachData("owner", this.getUUID()) .attachData("index", i) .attachData("size", this.getPreferredQueueSize(gameType)) .attachData("rounds", this.getPreferredRounds(gameType)) .attachData("map", this.queuePreferences.getIntPreference(gameType, "map", 0))); } } } private int getPreferredDropRate() { return this.queuePreferences.getIntPreference(GameType.MANHUNT_1V1, "dropRate", 0); } public int maxQueueSize() { return this.isInGroupOrHigher(Group.CHAMPION) ? 20 : 4; } public void changePreferredSize(SmartGUI smartGUI, GameType gameType) { if (gameType.getMainGame() == MainGame.DUELS) { if (gameType == GameType.DUELS_CUSTOM) { this.getStringInput("Player Count", String.valueOf(this.getPreferredQueueSize(gameType)), s -> { try { int val = Integer.parseInt(s); val = Math.max(2, Math.min(val, this.maxQueueSize())); this.queuePreferences.setIntPreference(gameType, "queueSize", val); this.onUpdatePreferences(); this.playSuccessSound(); this.openGui(smartGUI); } catch (Exception e) { this.onInvalidInput(); } }); } else { SmartGUI settingsGUI = new SmartGUI("Public Settings", 3, false); settingsGUI.add(11, Material.ENDER_EYE, ((player, b, b1) -> this.getStringInput("Player Count", String.valueOf(this.getPreferredQueueSize(gameType)), s -> { try { int val = Integer.parseInt(s); val = Math.max(2, Math.min(val, this.maxQueueSize())); this.queuePreferences.setIntPreference(gameType, "queueSize", val); this.onUpdatePreferences(); this.playSuccessSound(); this.changePreferredSize(smartGUI, gameType); } catch (Exception e) { this.onInvalidInput(); } })), GREEN + "Player Count: " + GRAY + this.getPreferredQueueSize(gameType)); settingsGUI.add(13, Material.MAP, ((player, b, b1) -> { SmartGUI mapGUI = new SmartGUI("Map", 2, false); List<DuelMap> duelMaps = Main.getMaps(gameType); int selected = this.queuePreferences.getIntPreference(gameType, "map", 0); for (int i = 0; i < duelMaps.size(); i++) { DuelMap duelMap = duelMaps.get(i); int finalI = i; mapGUI.add(i, i == selected ? ItemUtilities.enchanted(duelMap.getRepresentative()) : new ItemStack(duelMap.getRepresentative()), (player1, b2, b11) -> { this.queuePreferences.setIntPreference(gameType, "map", finalI); this.onUpdatePreferences(); this.playSuccessSound(); this.changePreferredSize(smartGUI, gameType); }, AQUA + duelMap.getName(), (i == selected ? ChatColor.GREEN + "Selected" : GRAY + "Left-click to select.")); } mapGUI.fillEmptySpots(); this.openGui(mapGUI); }), GOLD + "Map: " + GRAY + this.getPreferredMapName(gameType)); settingsGUI.add(15, Material.CLOCK, ((player, b, b1) -> this.getStringInput("Rounds", String.valueOf(this.getPreferredRounds(gameType)), s -> { try { int val = Integer.parseInt(s); val = Math.max(1, Math.min(val, 10)); this.queuePreferences.setIntPreference(gameType, "rounds", val); this.onUpdatePreferences(); this.playSuccessSound(); this.changePreferredSize(smartGUI, gameType); } catch (Exception e) { this.onInvalidInput(); } })), GREEN + "Rounds: " + GRAY + this.getPreferredRounds(gameType)); settingsGUI.add(0, Material.ARROW, (p, b, b1) -> this.openGui(smartGUI), RED + "Back"); this.openGui(settingsGUI); } } else { SmartGUI settingsGUI = new SmartGUI("Public Settings", 5, false); settingsGUI.add(12, Material.ENDER_EYE, ((player, b, b1) -> { this.getStringInput("Runner Count", String.valueOf(this.getPreferredRunnerCount()), s -> { try { int val = Integer.parseInt(s); val = Math.max(1, Math.min(val, this.getMaxRunnerCount())); this.setPreferredRunnerCount(val); this.playSuccessSound(); this.changePreferredSize(smartGUI, gameType); } catch (Exception e) { this.onInvalidInput(); } }); }), GREEN + "Runner Count: " + GRAY + this.getPreferredRunnerCount()); settingsGUI.add(14, Material.STONE_AXE, ((player, b, b1) -> { this.getStringInput("Hunter Count", String.valueOf(this.getPreferredHunterCount()), s -> { try { int val = Integer.parseInt(s); val = Math.max(1, Math.min(val, this.getMaxHunterCount())); this.setPreferredHunterCount(val); this.playSuccessSound(); this.changePreferredSize(smartGUI, gameType); } catch (Exception e) { this.onInvalidInput(); } }); }), RED + "Hunter Count: " + GRAY + this.getPreferredHunterCount()); settingsGUI.add(29, Material.CLOCK, ((player, b, b1) -> { this.getStringInput("Hunter Release Time", String.valueOf(this.getPreferredReleaseTime()), s -> { try { int val = Integer.parseInt(s); val = Math.max(0, Math.min(val, 60)); this.setPreferredReleaseTime(val); this.playSuccessSound(); this.changePreferredSize(smartGUI, gameType); } catch (Exception e) { this.onInvalidInput(); } }); }), GOLD + "Release Time", GRAY.toString() + this.getPreferredReleaseTime() + " seconds"); settingsGUI.add(31, Material.BLAZE_ROD, (p, b, b1) -> { this.setPreferredDropRate(this.getPreferredDropRate() == 1 ? 0 : 1); this.playSuccessSound(); this.setExtraData("dropRate", this.getPreferredDropRate()); this.changePreferredSize(smartGUI, gameType); settingsGUI.setItem(31, Material.BLAZE_ROD, RED + "Blaze/Enderman Drop Rate", GRAY + (this.getPreferredDropRate() == 1 ? "Boosted" : "Normal")); }, RED + "Blaze/Enderman Drop Rate", GRAY + (this.getPreferredDropRate() == 1 ? "Boosted" : "Normal")); settingsGUI.add(33, Material.GOLD_INGOT, (p, b, b1) -> { this.setPreferredTradeRate(this.getPreferredTradeRate() + 1); if (this.getPreferredTradeRate() > 2) { this.setPreferredTradeRate(0); } this.playSuccessSound(); this.changePreferredSize(smartGUI, gameType); settingsGUI.setItem(33, Material.GOLD_INGOT, YELLOW + "Piglin Trade Rate", GRAY + (this.getPreferredTradeRate() == 0 ? "1.16" : (this.getPreferredTradeRate() == 1 ? "1.19" : "Boosted"))); }, YELLOW + "Piglin Trade Rate", GRAY + (this.getPreferredTradeRate() == 0 ? "1.16" : (this.getPreferredTradeRate() == 1 ? "1.19" : "Boosted"))); settingsGUI.add(0, Material.ARROW, (p, b, b1) -> this.openGui(smartGUI), RED + "Back"); settingsGUI.fillEmptySpots(); this.openGui(settingsGUI); } } private void setPreferredDropRate(int i) { this.queuePreferences.setIntPreference(GameType.MANHUNT_1V1, "dropRate", i); this.onUpdatePreferences(); } private void onUpdatePreferences() { getExtraData().setJsonArray("preferences", this.queuePreferences.getAsJsonObject()); this.smartPlayer.updateProfile(ProfileColumn.EXTRA); } private void setPreferredHunterCount(int val) { this.queuePreferences.setIntPreference(GameType.MANHUNT_1V1, "hunters", val); this.onUpdatePreferences(); } private void setPreferredRunnerCount(int val) { this.queuePreferences.setIntPreference(GameType.MANHUNT_1V1, "runners", val); this.onUpdatePreferences(); } private void setPreferredReleaseTime(int val) { this.queuePreferences.setIntPreference(GameType.MANHUNT_1V1, "releaseTime", val); this.onUpdatePreferences(); } private int getPreferredReleaseTime() { return this.queuePreferences.getIntPreference(GameType.MANHUNT_1V1, "releaseTime", 15); } private void setPreferredTradeRate(int i) { this.queuePreferences.setIntPreference(GameType.MANHUNT_1V1, "tradeRate", i); this.onUpdatePreferences(); } private int getPreferredTradeRate() { return this.queuePreferences.getIntPreference(GameType.MANHUNT_1V1, "tradeRate", 0); } private int getPreferredRounds(GameType gameType) { return this.queuePreferences.getIntPreference(gameType, "rounds", 2); } private String getPreferredMapName(GameType gameType) { int map = this.queuePreferences.getIntPreference(gameType, "map", 0); List<DuelMap> maps = Main.getMaps(gameType); return maps.get(Math.min(map, maps.size() - 1)).getName(); } private int getPreferredQueueSize(GameType gameType) { return this.queuePreferences.getIntPreference(gameType, "queueSize", 2); } private int getMaxHunterCount() { return this.getMaxManhuntSize() - this.getPreferredRunnerCount(); } private int getPreferredRunnerCount() { return this.queuePreferences.getIntPreference(GameType.MANHUNT_1V1, "runners", 1); } private int getMaxRunnerCount() { return this.getMaxManhuntSize() - this.getPreferredHunterCount(); } private int getPreferredHunterCount() { return this.queuePreferences.getIntPreference(GameType.MANHUNT_1V1, "hunters", 1); } private int getMaxManhuntSize() { if (this.isAdministrator()) { return 64; } if (this.isInGroupOrHigher(Group.CHAMPION)) { return new int[]{4, 8, 10, 12, 13, 14, 15, 16}[Math.min(this.smartPlayer.getChampionTier(), 7)]; } return 4; } public boolean isCreative() { return this.getPlayer().getGameMode() == GameMode.CREATIVE; } public void browsePublicMaps(EditCustomKitGUI editCustomKitGUI, boolean recent) { SmartGUI smartGUI = new SmartGUI("Public Maps", 6, false); List<CustomMap> orderedMaps = Main.getCustomMaps(recent, timeFrame); for (int i = 0; i < orderedMaps.size() && i < 45; i++) { CustomMap customMap = orderedMaps.get(i); int plays = customMap.getPlays(recent ? 0 : timeFrame); smartGUI.add(i, customMap.getRepresentative(), (player, b, b1) -> this.selectPublicCustomMap(editCustomKitGUI, customMap, true), WHITE + customMap.getName(), RelayUtils.format("%sSize: %s%dx%d", GRAY, YELLOW, customMap.getSize(), customMap.getSize()), RelayUtils.format("%sBuilder: %s", GRAY, SmartPlayer.getOrCreate(customMap.getOwner()).getRealFormattedName()), RelayUtils.format("%s%d Play%s", AQUA, plays, plays == 1 ? "" : "s"), DARK_GRAY + "Click to preview"); } smartGUI.add(45, Material.ARROW, (player, b, b1) -> { if (editCustomKitGUI != null) { editCustomKitGUI.selectMap(); } else { this.openDuelsCustomMapsListGui(); } }, RED + "Back"); if (!recent) { smartGUI.add(52, Material.CLOCK, (p, b, b1) -> { this.cycleTimeFrame(); this.browsePublicMaps(editCustomKitGUI, recent); this.playClickSoundVariation(); }, AQUA + this.getTimeFrame(), DARK_GRAY + "Click to cycle."); } smartGUI.add(53, Material.ANVIL, (player, b, b1) -> { this.browsePublicMaps(editCustomKitGUI, !recent); this.playClickSoundVariation(); }, GOLD + (recent ? "Recent" : "Popular"), DARK_GRAY + "Click to toggle."); smartGUI.fillEmptySpots(); this.openGui(smartGUI); } public void selectPublicCustomMap(EditCustomKitGUI editCustomKitGUI, CustomMap customMap, boolean rightClick) { if (rightClick) { this.previewCenter = getAvailableCenter(customMap); if (customMap.getSize() % 2 == 1) { previewCenter.add(0.5, 0, 0.5); } for (CustomMap.Block block : customMap.getMap()) { Vector position = block.getPosition(); int x = (int) (previewCenter.getX() + position.getX()); int y = (int) (previewCenter.getY() + position.getY()); int z = (int) (previewCenter.getZ() + position.getZ()); Block worldBlock = getWorld().getBlockAt(x, y, z); worldBlock.setType(block.material()); worldBlock.setBlockData(block.blockData()); this.previewMapBlocks.add(worldBlock); } this.previewMap = customMap; this.isPreviewingMap = true; Main.synchronous(() -> { this.smartPlayer.setGameMode(GameMode.CREATIVE); this.teleport(previewCenter.clone().add(customMap.getSpawnA().toVector())); this.teleportedToPreviewMap = true; }); this.smartPlayer.clear(true); this.smartPlayer.setAllowFlight(true); this.smartPlayer.setGameMode(GameMode.ADVENTURE); this.addPotionEffect(PotionEffectType.NIGHT_VISION); this.giveSmartItem(SmartGUIUtils.ACCEPT_MAP); this.giveSmartItem(SmartGUIUtils.ADD_TO_MAP_LIBRARY); this.giveSmartItem(SmartGUIUtils.CANCEL_MAP); this.giveSmartItem(4, SmartGUIUtils.MAP_INFO); } else { if (editCustomKitGUI == null) { if (this.selectedCustomDuelsKit != null) { editCustomKitGUI = new EditCustomKitGUI(this.selectedCustomDuelsKit, this, this.customDuelKits.size()); this.lastEditKitGui = editCustomKitGUI; } else { this.sendErrorMessage("You must have a selected custom kit first!"); this.playErrorSound(); return; } } editCustomKitGUI.customDuelsKit.getMaps().clear(); editCustomKitGUI.customDuelsKit.getMaps().add(customMap.getId()); editCustomKitGUI.publicCustomMap = customMap.getId(); editCustomKitGUI.selectMap(); this.playSuccessSound(); } } public void showCustomMapHistory(EditCustomKitGUI editCustomKitGUI) { SmartGUI smartGUI = new SmartGUI("History", 3, false); for (int i = 0; i < this.recentMaps.size(); ) { CustomMap customMap = this.recentMaps.get(i); if (customMap != null) { int plays = customMap.getPlays(0); smartGUI.add(i++, customMap.getRepresentative(), (player, b, b1) -> this.selectPublicCustomMap(editCustomKitGUI, customMap, true), WHITE + customMap.getName(), RelayUtils.format("%sSize: %s%dx%d", GRAY, YELLOW, customMap.getSize(), customMap.getSize()), RelayUtils.format("%sBuilder: %s", GRAY, SmartPlayer.getOrCreate(customMap.getOwner()).getRealFormattedName()), RelayUtils.format("%s%d Play%s", AQUA, plays, plays == 1 ? "" : "s"), DARK_GRAY + "Click to preview"); } } smartGUI.add(22, Material.ARROW, (player, b, b1) -> { if (editCustomKitGUI != null) { editCustomKitGUI.selectMap(); } else { this.openDuelsCustomMapsListGui(); } }, RED + "Back"); smartGUI.fillEmptySpots(); this.openGui(smartGUI); } public CustomMap getNonOwnedCustomMap() { CustomMap customMap1 = Miscellaneous.match(this.customMaps, customMap -> !customMap.getOwner().equals(this.getUUID())); if (customMap1 != null) { return customMap1; } if (this.customMaps.size() > this.getMaxCustomMaps()) { return Miscellaneous.getLastEntry(this.customMaps); } return null; } public synchronized void acceptMap() { if (this.customMaps.contains(this.previewMap)) { this.playErrorSound(); this.sendErrorMessage("You already have this map!"); return; } if (this.selectedCustomDuelsKit != null) { if (this.lastEditKitGui == null) { this.lastEditKitGui = new EditCustomKitGUI(this.selectedCustomDuelsKit, this, this.customDuelKits.size()); } } else { this.sendErrorMessage("You must select a custom kit first!"); this.playErrorSound(); return; } this.lastEditKitGui.publicCustomMap = this.previewMap.getId(); this.lastEditKitGui.customMap = this.previewMap.getId(); this.customMaps.remove((this.getNonOwnedCustomMap())); this.customMaps.add(this.previewMap); this.clearPreviewMap(); this.playSuccessSound(); this.spawn(true); this.lastEditKitGui.selectMap(); //this.openDuelsCustomKitsListGui(); } public void cancelMap() { this.playClickSound(); this.clearPreviewMap(); this.spawn(true); this.browsePublicMaps(this.lastEditKitGui, true); } public synchronized void addToMapLibrary() { this.customMaps.remove(this.previewMap); if (this.customMaps.size() < this.getMaxCustomMaps()) { CustomMap clone = new CustomMap(this.smartPlayer); clone.setMap(this.previewMap.getMap()); clone.setCreators(Miscellaneous.with(this.previewMap.getCreators(), this.previewMap.getOwner())); clone.setContributors(this.previewMap.getContributors()); clone.setSize(this.previewMap.getSize()); clone.setSpawnA(this.previewMap.getSpawnA()); clone.setSpawnB(this.previewMap.getSpawnB()); clone.setRepresentative(this.previewMap.getRepresentative()); clone.setName(Text.truncate(this.previewMap.getName() + " - Copy", 32)); this.uploadNewCustomMap(clone); this.customMaps.add(clone); this.smartPlayer.getCustomMaps().add(clone); this.updateCustomMapList(); this.playSuccessSound(); this.spawn(true); this.openDuelsCustomMapsListGui(); this.clearPreviewMap(); } else { if (this.isInGroupOrHigher(Group.CHAMPION)) { this.sendErrorMessage("You do not have any more slots available!"); } else { this.sendErrorMessage("You do not have any more slots available! Upgrade to Premium to bypass this restriction!"); } this.playErrorSound(); } } public void clearPreviewMap() { for (Block previewMapBlock : this.previewMapBlocks) { previewMapBlock.setType(Material.AIR); } this.previewMapBlocks.clear(); this.isPreviewingMap = false; this.teleportedToPreviewMap = false; this.previewKit = null; this.previewCustomKitGUI = null; this.previewMap = null; } private void uploadNewCustomMap(CustomMap clone) { CustomMap.insertIntoDatabase(clone); } public int getMaxCustomMaps() { if (this.isAdministrator()) { return 18; } if (this.isInGroupOrHigher(Group.CHAMPION)) { return new int[]{1, 3, 3, 4, 4, 5}[Math.min(5, this.smartPlayer.getChampionTier())]; } return 1; } public synchronized void addToKitLibrary() { this.customDuelKits.remove(this.previewKit); if (this.customDuelKits.size() < this.getMaxCustomKits()) { String id = CustomDuelsKit.generateNewId(); CustomDuelsKit clone = new CustomDuelsKit(id, this.getUUID(), this.previewKit.getKit(), this.previewKit.getGameSettings(), this.previewKit.getMaps(), this.previewKit.getPublicCustomMap(), false, this.previewKit.getVotes(0), Miscellaneous.with(this.previewKit.getCreators(), this.previewKit.getOwner()), 0); clone.setName(Text.truncate(this.previewKit.getName() + " - Copy", 32)); this.uploadNewCustomKit(clone); this.customDuelKits.add(clone); this.updateCustomKitList(); this.playSuccessSound(); this.openDuelsCustomKitsListGui(); } else { if (this.isInGroupOrHigher(Group.CHAMPION)) { this.sendErrorMessage("You do not have any more slots available!"); } else { this.sendErrorMessage("You do not have any more slots available! Upgrade to Premium to bypass this restriction!"); } this.playErrorSound(); } } private void uploadNewCustomKit(CustomDuelsKit clone) { CustomDuelsKit.insertIntoDatabase(clone); } private int getMaxCustomKits() { if (this.isAdministrator()) { return 18; } if (this.isInGroupOrHigher(Group.CHAMPION)) { return new int[]{3, 5, 5, 6, 6, 6, 7}[Math.min(this.smartPlayer.getChampionTier(), 6)]; } return 3; } public synchronized void acceptPreviewKit() { if (this.customDuelKits.contains(this.previewKit)) { this.playErrorSound(); this.sendErrorMessage("You already have this kit!"); return; } this.customDuelKits.remove(this.getNonOwnedKit()); this.customDuelKits.add(this.previewKit); this.selectedCustomDuelsKit = this.previewKit; this.sendSuccessMessage("Selected custom kit."); this.updateSelectedCustomDuelsKit(); this.playSuccessSound(); this.updateCustomKitList(); this.openDuelsCustomKitsListGui(); } public boolean shareCustomKit(CustomDuelsKit asKit, String originalId) { if (this.enoughSecondsHaveElapsed(Cooldown.SHARE_KIT)) { this.updateCooldown(Cooldown.SHARE_KIT); } else { this.showCooldownWarning(Cooldown.SHARE_KIT); return false; } asKit.setVisible(); this.saveCustomKit(asKit, originalId); ComponentBuilder componentBuilder = new ComponentBuilder(); componentBuilder.color(ComponentBuilder.BLUE).line().newLine(); String code = asKit.getId(); componentBuilder.copy("/setkit " + code, GOLD + UNDERLINE.toString() + "/setkit " + code, "Click to copy.").newLine(); componentBuilder.copy(code, GOLD + UNDERLINE.toString() + code, "Click to copy.").newLine(); componentBuilder.color(ComponentBuilder.GREEN).append("This kit has been shared publicly.").newLine(); componentBuilder.color(ComponentBuilder.BLUE).line(); this.playSuccessSound(); this.sendMessage(componentBuilder); return true; } public void setMap(String arg) { CustomMap customMap = CustomMap.getCustomMap(arg); if (customMap == null || !customMap.isVisible()) { this.sendErrorMessage("No public custom map found by the code %s%s%s.", YELLOW, arg, RED); } else { if (this.selectedCustomDuelsKit == null) { this.sendErrorMessage("You must select a custom kit first!"); this.playErrorSound(); } else { if (this.selectedCustomDuelsKit.getOwner().equals(this.getUUID())) { if (this.selectedCustomDuelsKit.isVisible()) { CustomDuelsKit clone = this.selectedCustomDuelsKit.clone(); this.saveCustomKit(clone, this.selectedCustomDuelsKit.getId()); } else { this.selectedCustomDuelsKit.setPublicCustomMap(customMap.getId()); this.saveCustomKit(this.selectedCustomDuelsKit, this.selectedCustomDuelsKit.getId()); } this.playSuccessSound(); this.sendSuccessMessage("Changed your selected public map for your selected custom kit."); } else { this.sendErrorMessage("You can only change the selected public for a map you own!"); this.playErrorSound(); } } } } public void shareKit() { if (this.customDuelKits.isEmpty()) { this.openDuelsCustomKitsListGui(); return; } SmartGUI kitGUI = new SmartGUI("Share Kit", 1, false); for (int i = 0; i < this.customDuelKits.size(); i++) { CustomDuelsKit kit = this.customDuelKits.get(i); if (kit.getOwner().equals(this.getUUID())) { kitGUI.add(i, kit.getRepresentative(), (p, b, b1) -> this.shareCustomKit(kit, kit.getId()), kit.getName(), GRAY + "Share this custom map."); } } this.openGui(kitGUI); } public void shareMap() { if (this.customMaps.isEmpty()) { this.openDuelsCustomMapsListGui(); return; } SmartGUI mapGUI = new SmartGUI("Share Map", this.isAdministrator() ? 2 : 1, false); for (int i = 0; i < this.customMaps.size(); i++) { CustomMap customMap = this.customMaps.get(i); if (customMap.getOwner().equals(this.getUUID())) { mapGUI.add(i, customMap.getRepresentative(), (p, b, b1) -> this.shareCustomMap(customMap), customMap.getName(), GRAY + "Share this custom map."); } } mapGUI.fillEmptySpots(); this.openGui(mapGUI); } public CustomMap getPublicCustomMap(String publicCustomMap) { return this.publicCustomMaps.get(publicCustomMap); } public void showMapInfo() { if (this.previewMap == null) { return; } SmartGUI smartGUI = new SmartGUI("Map Info", 2, false); SmartPlayer owner = SmartPlayer.getOrCreate(this.previewMap.getOwner()); smartGUI.addImmutable(4, owner.getHead(), owner.getRealFormattedName(), GRAY + "Creator"); List<String> contributors = new ArrayList<>(); if (this.previewMap.getContributors().isEmpty()) { contributors.add(DARK_GRAY + " - None"); } else { for (UUID contributor : this.previewMap.getContributors()) { contributors.add(DARK_GRAY + " - " + SmartPlayer.getOrCreate(contributor).getRealFormattedName()); } } smartGUI.addImmutable(6, Material.PAPER, GOLD + "Contributors", contributors); List<String> creators = new ArrayList<>(); if (this.previewMap.getCreators().isEmpty()) { creators.add(DARK_GRAY + " - None"); } else { for (UUID creator : this.previewMap.getCreators()) { creators.add(DARK_GRAY + " - " + SmartPlayer.getOrCreate(creator).getRealFormattedName()); } } smartGUI.addImmutable(2, Material.PAPER, GOLD + "Previous Creators", creators); smartGUI.addImmutable(13, this.previewMap.getRepresentative(), DARK_AQUA + "Stats", String.format("%sSize: %s%dx%d", YELLOW, WHITE, this.previewMap.getSize(), this.previewMap.getSize()), String.format("%sBlocks: %s%d", YELLOW, WHITE, this.previewMapBlocks.size()), String.format("%sPlays: %s%d", YELLOW, WHITE, this.previewMap.getPlays(0)), String.format("%sVotes: %s%d", YELLOW, WHITE, this.previewMap.getVotes(0))); smartGUI.fillEmptySpots(); this.openGui(smartGUI); } public boolean isCreatingOwnedCustomMap() { return this.isCreatingCustomMap && this.customMapEdited.getOwner().equals(this.getUUID()); } public boolean hasCollaborator(HubPlayer player) { return this.mapCollaborators.contains(player); } List<HubPlayer> mapCollaborators = new ArrayList<>(); List<UUID> allCollaborators = new ArrayList<>(); public void kickCollaborator(HubPlayer player) { player.sendErrorMessage("You have been kicked from map editing!"); player.spawn(true); player.playErrorSound(); this.sendSuccessMessage("Kicked %s%s from editing.", player.getFormattedName(), GREEN); this.mapCollaborators.remove(player); } public void collaborate(HubPlayer toJoin) { this.collaborationInvites.remove(toJoin); toJoin.mapCollaborators.add(this); toJoin.allCollaborators.add(this.getUUID()); this.customMapEdited = toJoin.customMapEdited; this.customMapCenter = toJoin.customMapCenter; this.customMapSpawnA = toJoin.customMapSpawnA; this.customMapSpawnB = toJoin.customMapSpawnB; this.customMapSize = toJoin.customMapSize; this.closeInventory(); this.smartPlayer.clear(); this.teleportToCustomMap(); this.smartPlayer.setGameMode(GameMode.CREATIVE); this.smartPlayer.setAllowFlight(true); this.getPlayer().setFlying(true); this.isCreatingCustomMap = true; this.teleportToCustomMap(); this.playSuccessSound(); this.sendSuccessMessage("You have joined editing on %s%s custom map.", toJoin.getFormattedName(), GREEN); toJoin.sendSuccessMessage("%s%s has joined editing your custom map.", this.getFormattedName(), GREEN); this.giveSmartItem(8, SPAWN); } public void inviteCollaborator(HubPlayer player) { player.inviteToCollaborate(this); this.sendSuccessMessage("Invite sent. They have 60 seconds to accept."); } public void inviteToCollaborate(HubPlayer inviter) { this.collaborationInvites.add(inviter); ComponentBuilder componentBuilder = new ComponentBuilder(); componentBuilder.gradientLine(ComponentBuilder.GREEN, ComponentBuilder.YELLOW_GREEN, ComponentBuilder.GREEN).newLine(); componentBuilder.color(GREEN).append(inviter.getComponentFormattedName()).append("%s has invited you to edit their custom map! ", GREEN); componentBuilder.command(GOLD + "Click here.", "/custommap join " + inviter.getName(), RelayUtils.format("%sClick here to accept %s%s collaboration request.", AQUA, inviter.getFormattedName(), AQUA)); componentBuilder.color(YELLOW).append(" You have 60 seconds to accept.").newLine(); componentBuilder.gradientLine(ComponentBuilder.GREEN, ComponentBuilder.YELLOW_GREEN, ComponentBuilder.GREEN); BaseComponent textComponent = componentBuilder.getResult(); ClickEvent clickEvent = new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/custommap join " + inviter.getName()); textComponent.setClickEvent(clickEvent); String hover = RelayUtils.format("%sClick here to accept %s%s collaboration request.", AQUA, inviter.getFormattedName(), AQUA); List<String> lines = Miscellaneous.getList(hover.split("\n")); HoverEvent hoverEvent = new HoverEvent(net.md_5.bungee.api.chat.HoverEvent.Action.SHOW_TEXT, Miscellaneous.processList(lines, net.md_5.bungee.api.chat.hover.content.Text::new)); textComponent.setHoverEvent(hoverEvent); this.sendMessage(textComponent); Main.scheduleSyncDelayedTask(() -> { if (this.collaborationInvites.contains(this)) { this.collaborationInvites.remove(this); inviter.sendInfoMessage("The collaboration invite to %s%s has expired.", this.getRealFormattedName(), YELLOW); this.sendInfoMessage("The collaboration invite from %s%s has expired.", inviter.getFormattedName(), YELLOW); } }, 60); } public boolean isCollaboratingCustomMap() { return this.isCreatingCustomMap && !this.isCreatingOwnedCustomMap(); } public void deleteKit(String originalId, String id) { getCustomDuelKits().removeIf(kit -> kit.getId().equals(id) || kit.getId().equalsIgnoreCase(originalId)); getSmartPlayer().getCustomDuelsKits().removeIf(kit -> kit.getId().equals(id) || kit.getId().equalsIgnoreCase(originalId)); closeInventory(); hasNoKits = customDuelKits.isEmpty(); playSuccessSound(); updateCustomKitList(); updateSelectedCustomDuelsKit(); } public void onDailyJoin() { Main.synchronous(() -> { ItemStack book = new ItemStack(Material.WRITABLE_BOOK); BookMeta bookMeta = (BookMeta) book.getItemMeta(); Component component = JSONComponentSerializer.json().deserialize("[\"\",{\"text\":\"Welcome to\",\"color\":\"#989898\"},{\"text\":\" Relay \",\"color\":\"#0066FF\"},{\"text\":\"Beta!\",\"color\":\"#FF0003\"},{\"text\":\"\\n\\n\",\"color\":\"reset\"},{\"text\":\"Some features are\",\"color\":\"black\"},{\"text\":\" STILL IN DEVELOPMENT\",\"bold\":true,\"color\":\"dark_green\"},{\"text\":\"\\nso you may experience bugs while playing.\\n\\n\",\"color\":\"reset\"},{\"text\":\"Report them in our discord\",\"underlined\":true,\"color\":\"#0054C5\",\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://discord.gg/zQ2pFMjd9R\"},\"hoverEvent\":{\"action\":\"show_text\",\"contents\":{\"text\":\"Click to join the discord!\",\"color\":\"aqua\"}}},{\"text\":\" \",\"color\":\"reset\",\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://discord.gg/zQ2pFMjd9R\"},\"hoverEvent\":{\"action\":\"show_text\",\"contents\":{\"text\":\"Click to join the discord!\",\"color\":\"aqua\"}}},{\"text\":\"to help us improve the network!\",\"color\":\"dark_gray\",\"clickEvent\":{\"action\":\"open_url\",\"value\":\"https://discord.gg/zQ2pFMjd9R\"},\"hoverEvent\":{\"action\":\"show_text\",\"contents\":{\"text\":\"Click to join the discord!\",\"color\":\"aqua\"}}},{\"text\":\"\\n\\n\",\"color\":\"reset\"},{\"text\":\" Have fun!\",\"italic\":true,\"color\":\"#F7B32B\"}]"); Book book1 = bookMeta.title(Component.text("Daily Message")).pages(component).author(Component.text("Relay")); this.getPlayer().openBook(book1); Main.info("daily join"); }); } }