diff --git a/Lobby/pom.xml b/Lobby/pom.xml index 6480654..f074606 100644 --- a/Lobby/pom.xml +++ b/Lobby/pom.xml @@ -11,6 +11,17 @@ 0.0.1-SNAPSHOT ../pom.xml + + + codemc-repo + https://repo.codemc.org/repository/maven-public/ + default + + + viaversion-repo + https://repo.viaversion.com + + de.iani.cubeside @@ -18,6 +29,24 @@ 1.0.0-SNAPSHOT provided + + de.tr7zw + item-nbt-api-plugin + 2.10.0-SNAPSHOT + provided + + + com.viaversion + viaversion-api + 4.7.1-SNAPSHOT + provided + + + de.fanta + Challenge + 0.0.1-SNAPSHOT + provided + diff --git a/Lobby/src/main/java/de/fanta/lobby/ChallengesGlobalDataHelper.java b/Lobby/src/main/java/de/fanta/lobby/ChallengesGlobalDataHelper.java new file mode 100644 index 0000000..10ebc48 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/ChallengesGlobalDataHelper.java @@ -0,0 +1,164 @@ +package de.fanta.lobby; + +import de.cubeside.connection.GlobalServer; +import de.cubeside.connection.event.GlobalServerConnectedEvent; +import de.cubeside.connection.event.GlobalServerDisconnectedEvent; +import de.fanta.challenge.Challenge; +import de.fanta.lobby.ChallengesGlobalDataHelper.ChallengeMessageType; +import de.iani.cubesideutils.bukkit.plugin.api.GlobalDataHelperBukkit; +import de.speedy64.globalport.GlobalApi; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +import java.io.DataInputStream; +import java.io.IOException; +import java.util.UUID; + +public class ChallengesGlobalDataHelper extends GlobalDataHelperBukkit implements Listener { + + public static final String CHANNEL = "ChallengesJoinEntities"; + + private final Lobby plugin; + + public ChallengesGlobalDataHelper(Lobby plugin) { + super(ChallengeMessageType.class, CHANNEL, plugin); + this.plugin = plugin; + } + + @Override + protected void handleMessage(ChallengeMessageType challengeMessageType, GlobalServer globalServer, DataInputStream data) throws IOException { + String serverName = data.readUTF(); + switch (challengeMessageType) { + case TIMER -> { + boolean running = data.readBoolean(); + plugin.updateTimerStatus(serverName, running); + } + case EVENT -> { + boolean event = data.readBoolean(); + plugin.updateEventStatus(serverName, event); + } + case SERVER_STATUS -> { + boolean online = data.readBoolean(); + plugin.updateServerStatus(serverName, online); + } + case PLAYER_COUNT -> { + int count = data.readInt(); + int maxPlayers = data.readInt(); + plugin.updatePlayerCount(serverName, count, maxPlayers); + } + case INITIAL_DATA_REQUEST -> { + if (Bukkit.getPluginManager().getPlugin("Challenges") != null) { + Challenge challenges = (Challenge) Bukkit.getPluginManager().getPlugin("Challenge"); + boolean timerRunning = challenges.getTimer().isRunning(); + int playerCount = Bukkit.getOnlinePlayers().size(); + int maxPlayers = Bukkit.getMaxPlayers(); + + sendInitialData(serverName, timerRunning, playerCount, maxPlayers); + } + } + case INITIAL_DATA -> { + boolean timerRunning = data.readBoolean(); + int playerCount = data.readInt(); + int maxPlayers = data.readInt(); + plugin.updateTimerStatus(serverName, timerRunning); + plugin.updatePlayerCount(serverName, playerCount, maxPlayers); + } + default -> throw new UnsupportedOperationException(); + } + } + + public void sendTimerUpdate(boolean running) { + sendData(ChallengeMessageType.TIMER, getThisServerName(), running); + } + + public void sendEventUpdate(boolean event) { + sendData(ChallengeMessageType.EVENT, getThisServerName(), event); + } + + public void sendServerStatusUpdate(boolean online) { + sendData(ChallengeMessageType.SERVER_STATUS, getThisServerName(), online); + } + + public void sendPlayerCountUpdate(int count) { + sendData(ChallengeMessageType.PLAYER_COUNT, getThisServerName(), count, Bukkit.getMaxPlayers()); + } + + public void requestInitialData(String fromServer) { + sendData(getServer(fromServer), ChallengeMessageType.INITIAL_DATA_REQUEST, getThisServerName()); + } + + public void sendInitialData(String toServer, boolean timerRunning, int playerCount, int maxPlayers) { + sendData(getServer(toServer), ChallengeMessageType.INITIAL_DATA, getThisServerName(), timerRunning, playerCount, maxPlayers); + } + + @EventHandler + public void onGlobalServerConnected(GlobalServerConnectedEvent event) { + plugin.getScheduler().runGlobalDelayed(() -> { + if (plugin.getEntityData(event.getServer().getName()) != null) { + plugin.updateServerStatus(event.getServer().getName(), true); + this.requestInitialData(event.getServer().getName()); + } + + for (Server server : plugin.getPluginConfig().getChallengeServers()) { + if (server.getName().equals(event.getServer().getName())) { + UUID uuid = Server.serverPlayers.get(server); + if (uuid != null) { + Player p = Bukkit.getPlayer(uuid); + if (p != null) { + server.spawnPiglin(p); + GlobalApi.portOnlinePlayerToLocation(p.getName(), server.getGPLocation()); + } + } + break; + } + } + + for (Server server : plugin.getPluginConfig().getAdventureServers()) { + if (server.getName().equals(event.getServer().getName())) { + UUID uuid = Server.serverPlayers.get(server); + Player p = Bukkit.getPlayer(uuid); + if (p != null) { + server.spawnPiglin(p); + //server.spawnNPC(p); + GlobalApi.portOnlinePlayerToLocation(p.getName(), server.getGPLocation()); + } + break; + } + } + }, 200L); + } + + @EventHandler + public void onGlobalServerDisconnected(GlobalServerDisconnectedEvent event) { + if (plugin.getEntityData(event.getServer().getName()) != null) { + plugin.updateServerStatus(event.getServer().getName(), false); + } + + for (Server server : plugin.getPluginConfig().getChallengeServers()) { + if (server.getName().equals(event.getServer().getName())) { + server.setOnline(false); + Server.serverPlayers.remove(server); + server.despawnPiglin(); + break; + } + } + + for (Server server : plugin.getPluginConfig().getAdventureServers()) { + if (server.getName().equals(event.getServer().getName())) { + server.setOnline(false); + Server.serverPlayers.remove(server); + //server.despawnNPC(); + server.despawnPiglin(); + break; + } + } + + plugin.getAvailableServers().remove(event.getServer().getName()); + } + + public enum ChallengeMessageType { + TIMER, SERVER_STATUS, PLAYER_COUNT, INITIAL_DATA_REQUEST, INITIAL_DATA, EVENT + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/ChatUtil.java b/Lobby/src/main/java/de/fanta/lobby/ChatUtil.java new file mode 100644 index 0000000..ef08e35 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/ChatUtil.java @@ -0,0 +1,51 @@ +package de.fanta.lobby; + +import de.iani.cubesideutils.bukkit.ChatUtilBukkit; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class ChatUtil { + + public static final ChatColor GREEN = ChatColor.of("#52ff9d"); + public static final ChatColor ORANGE = ChatColor.of("#ffac4d"); + public static final ChatColor RED = ChatColor.of("#ff6b6b"); + public static final ChatColor BLUE = ChatColor.of("#87f7ea"); + public static final ChatColor PINK = ChatColor.of("#FF04F7"); + + private ChatUtil() { + // prevent instances + } + + public static void sendMessage(CommandSender sender, String colors, Object... messageParts) { + ChatUtilBukkit.sendMessage(sender, Lobby.PREFIX, colors, messageParts); + } + + public static void sendNormalMessage(CommandSender sender, Object... messageParts) { + sendMessage(sender, GREEN.toString(), messageParts); + } + + public static void sendWarningMessage(CommandSender sender, Object... messageParts) { + sendMessage(sender, ORANGE.toString(), messageParts); + } + + public static void sendErrorMessage(CommandSender sender, Object... messageParts) { + sendMessage(sender, RED.toString(), messageParts); + } + + public static void sendDebugMessage(CommandSender sender, Object... messageParts) { + if (sender.hasPermission("fanta.debug")) { + if (sender != null) { + sendMessage(sender, PINK.toString(), messageParts); + } + } + } + + public static void sendBrodcastMessage(Object... messageParts) { + for (Player player : Bukkit.getOnlinePlayers()) { + sendMessage(player, GREEN.toString(), messageParts); + } + } +} + diff --git a/Lobby/src/main/java/de/fanta/lobby/Config.java b/Lobby/src/main/java/de/fanta/lobby/Config.java new file mode 100644 index 0000000..6950239 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/Config.java @@ -0,0 +1,132 @@ +package de.fanta.lobby; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; + +import java.io.File; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +public class Config { + + private static Lobby plugin; + private static Set challengeServers; + private static Set adventureServers; + + public Config(Lobby plugin) { + Config.plugin = plugin; + challengeServers = new HashSet<>(); + adventureServers = new HashSet<>(); + + if (Bukkit.getPluginManager().getPlugin("Challenges") == null) { + plugin.saveDefaultConfig(); + reloadConfig(); + } + } + + public static void reloadConfig() { + plugin.reloadConfig(); + FileConfiguration config = plugin.getConfig(); + + ConfigurationSection piglinsSection = config.getConfigurationSection("piglins"); + if (piglinsSection != null) { + for (String serverName : piglinsSection.getKeys(false)) { + ConfigurationSection piglin = piglinsSection.getConfigurationSection(serverName); + plugin.addPiglin(UUID.fromString(piglin.getString("uuid")), serverName, piglin.getString("gpLocation"), piglin.getString("displayName"), false); + plugin.getGlobalDataHelper().requestInitialData(serverName); + } + } + + ConfigurationSection filaPathSection = config.getConfigurationSection("fileLocations"); + if (filaPathSection != null) { + plugin.setChallengeSavePath(new File(filaPathSection.getString("challengeSaves")).toPath()); + plugin.setAdventureSavePath(new File(filaPathSection.getString("adventureSaves")).toPath()); + plugin.setAventureMapsPath(new File(filaPathSection.getString("adventureMaps")).toPath()); + plugin.setServerJarsPath(new File(filaPathSection.getString("serverJars")).toPath()); + plugin.setServerFolderPath(new File(filaPathSection.getString("serverFolder")).toPath()); + } + + ConfigurationSection challengeServerSection = config.getConfigurationSection("challenge"); + if (challengeServerSection != null) { + for (String serverName : challengeServerSection.getKeys(false)) { + ConfigurationSection server = challengeServerSection.getConfigurationSection(serverName); + + ConfigurationSection locSection = server.getConfigurationSection("location"); + World world = Bukkit.getWorld(locSection.getString("world")); + double x = locSection.getDouble("x"); + double y = locSection.getDouble("y"); + double z = locSection.getDouble("z"); + float yaw = (float) locSection.getDouble("yaw"); + Location location = new Location(world, x, y, z, yaw, 0.0F); + + challengeServers.add(new Server(serverName, null, server.getString("gpLocation"), server.getString("dir"), ServerType.CHALLENGES, plugin, location)); + } + } + + ConfigurationSection adventureServerSection = config.getConfigurationSection("adventure"); + if (adventureServerSection != null) { + for (String serverName : adventureServerSection.getKeys(false)) { + ConfigurationSection server = adventureServerSection.getConfigurationSection(serverName); + + ConfigurationSection locSection = server.getConfigurationSection("location"); + World world = Bukkit.getWorld(locSection.getString("world")); + double x = locSection.getDouble("x"); + double y = locSection.getDouble("y"); + double z = locSection.getDouble("z"); + float yaw = (float) locSection.getDouble("yaw"); + Location location = new Location(world, x, y, z, yaw, 0.0F); + + adventureServers.add(new Server(serverName, null, server.getString("gpLocation"), server.getString("dir"), ServerType.ADVENTURE, plugin, location)); + } + } + + } + + public void savePiglin(JoinEntityData data) { + FileConfiguration config = plugin.getConfig(); + ConfigurationSection piglinsSection = config.getConfigurationSection("piglins"); + + if (piglinsSection == null) { + config.createSection("piglins"); + piglinsSection = config.getConfigurationSection("piglins"); + } + + ConfigurationSection piglin = piglinsSection.createSection(data.getServerName()); + piglin.set("uuid", data.getEntityUUID().toString()); + piglin.set("gpLocation", data.getGlobalPortLocationName()); + piglin.set("displayName", data.getServerDisplayName()); + + plugin.saveConfig(); + } + + public void removePiglin(String serverName) { + FileConfiguration config = plugin.getConfig(); + ConfigurationSection piglinsSection = config.getConfigurationSection("piglins"); + + piglinsSection.set(serverName, null); + + plugin.saveConfig(); + } + + public Set getChallengeServers() { + return challengeServers; + } + + public Set getAdventureServers() { + return adventureServers; + } + + public Optional getOnlineChanllengeServer() { + return challengeServers.stream().filter(server -> !server.isOnline()).findFirst(); + } + + public Optional getOnlineAdventureServer() { + return adventureServers.stream().filter(server -> !server.isOnline()).findFirst(); + } +} + diff --git a/Lobby/src/main/java/de/fanta/lobby/JoinEntityData.java b/Lobby/src/main/java/de/fanta/lobby/JoinEntityData.java new file mode 100644 index 0000000..6fbfca2 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/JoinEntityData.java @@ -0,0 +1,101 @@ +package de.fanta.lobby; + +import net.md_5.bungee.api.ChatColor; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public class JoinEntityData { + + private final String serverName; + private final UUID entityUUID; + private final String globalPortLocationName; + private final String serverDisplayName; + private ServerStatus serverStatus; + private EventStatus eventStatus; + private int playerCount; + private int maxPlayers; + + private final int mapVersion; + + public JoinEntityData(String serverName, @Nullable Integer mapVersion, UUID entityUUID, String globalPortLocationName, String serverDisplayName, ServerStatus serverStatus, EventStatus eventStatus, int playerCount, int maxPlayers) { + this.serverName = serverName; + this.mapVersion = mapVersion == null ? 0 : mapVersion; + this.entityUUID = entityUUID; + this.globalPortLocationName = globalPortLocationName; + this.serverDisplayName = serverDisplayName; + this.serverStatus = serverStatus; + this.eventStatus = eventStatus; + this.playerCount = playerCount; + this.maxPlayers = maxPlayers; + } + + public String getServerName() { + return serverName; + } + + public UUID getEntityUUID() { + return entityUUID; + } + + public String getGlobalPortLocationName() { + return globalPortLocationName; + } + + public String getServerDisplayName() { + return serverDisplayName; + } + + public ServerStatus getServerStatus() { + return serverStatus; + } + + public void setServerStatus(ServerStatus serverStatus) { + this.serverStatus = serverStatus; + } + + public void setEventStatus(EventStatus eventStatus) { + this.eventStatus = eventStatus; + } + + public EventStatus getEventStatus() { + return eventStatus; + } + + public int getPlayerCount() { + return playerCount; + } + + public void setPlayerCount(int playerCount) { + this.playerCount = playerCount; + } + + public int getMaxPlayers() { + return maxPlayers; + } + + public void setMaxPlayers(int maxPlayers) { + this.maxPlayers = maxPlayers; + } + + public int getMapVersion() { + return mapVersion; + } + + public String createCustomEntityName() { + String statusString = serverStatus == ServerStatus.ONLINE ? ChatUtil.GREEN + "ONLINE" : serverStatus == ServerStatus.OFFLINE ? ChatUtil.RED + "OFFLINE" : serverStatus == ServerStatus.RUNNING ? ChatUtil.ORANGE + "RUNNING" : ""; + String playerCountString = ChatUtil.BLUE + "(" + playerCount + "/" + maxPlayers + ")"; + if (eventStatus == EventStatus.EVENT) { + return ChatUtil.RED + "" + ChatColor.BOLD + "Event" + " " + statusString + (serverStatus != ServerStatus.OFFLINE ? (" " + playerCountString) : " "); + } + return ChatUtil.BLUE + serverDisplayName + " " + statusString + (serverStatus != ServerStatus.OFFLINE ? (" " + playerCountString) : ""); + } + + public enum ServerStatus { + ONLINE, RUNNING, OFFLINE + } + + public enum EventStatus { + EVENT, NORMAL + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/Lobby.java b/Lobby/src/main/java/de/fanta/lobby/Lobby.java index c767c10..4816649 100644 --- a/Lobby/src/main/java/de/fanta/lobby/Lobby.java +++ b/Lobby/src/main/java/de/fanta/lobby/Lobby.java @@ -1,36 +1,490 @@ -package de.fanta.adventure; +package de.fanta.lobby; +import de.cubeside.nmsutils.NMSUtils; +import de.fanta.lobby.adventure.AdventureMapsConfig; +import de.fanta.lobby.adventure.CategoriesConfig; +import de.fanta.lobby.commands.AdventureCommand.AdventureAddCategoryCommand; +import de.fanta.lobby.commands.AdventureCommand.AdventureAddMapCommand; +import de.fanta.lobby.commands.AdventureCommand.AdventureClearSavesCommand; +import de.fanta.lobby.commands.AdventureCommand.AdventureConvertMapCommand; +import de.fanta.lobby.commands.AdventureCommand.AdventureLoadCommand; +import de.fanta.lobby.commands.AdventureCommand.AdventureLoadMapIconsCommand; +import de.fanta.lobby.commands.AdventureCommand.AdventureMapsCommand; +import de.fanta.lobby.commands.AdventureCommand.AdventureStartEventServerCommand; +import de.fanta.lobby.commands.AdventureCommand.AdventureTempCommand; +import de.fanta.lobby.commands.AdventureCommand.AdventureTestMapCommand; +import de.fanta.lobby.commands.AdventureCommand.ChallengesRemovePlayerServer; +import de.fanta.lobby.commands.ChallengesCommand.ChallengeClearSavesCommand; +import de.fanta.lobby.commands.ChallengesCommand.ChallengeListUserStatsCommand; +import de.fanta.lobby.commands.ChallengesCommand.ChallengeLoadCommand; +import de.fanta.lobby.commands.ChallengesCommand.ChallengeSetStatsCommand; +import de.fanta.lobby.commands.ChallengesCommand.ChallengesStatsCommand; +import de.fanta.lobby.commands.PiglinCommand.AddEntityCommand; +import de.fanta.lobby.commands.PiglinCommand.Entitytphere; +import de.fanta.lobby.commands.PiglinCommand.ListPiglinCommand; +import de.fanta.lobby.commands.PiglinCommand.RemoveEntityCommand; +import de.fanta.lobby.commands.PiglinCommand.SetEntitySpawnLocationCommand; +import de.fanta.lobby.commands.PiglinCommand.ToggleArenaCommand; +import de.fanta.lobby.listeners.ChallengesEventListener; +import de.fanta.lobby.listeners.EntityListener; +import de.fanta.lobby.listeners.PlayerListener; +import de.fanta.lobby.schedular.BukkitScheduler; +import de.fanta.lobby.schedular.Scheduler; +import de.fanta.lobby.utils.Statistics; +import de.iani.cubesidestats.api.CubesideStatisticsAPI; +import de.iani.cubesideutils.bukkit.commands.CommandRouter; +import de.iani.playerUUIDCache.PlayerUUIDCache; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.format.TextColor; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Piglin; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.Nullable; -import java.io.File; -import java.util.logging.Logger; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.logging.Level; -public final class Lobby extends JavaPlugin { +public class Lobby extends JavaPlugin { - private Lobby plugin; - private Logger LOGGER; + public static final String PREFIX = ChatUtil.BLUE + "[" + ChatUtil.GREEN + "Lobby" + ChatUtil.BLUE + "]"; + public static final String ADVENTUREGUIPREFIX = ChatColor.of("#2d8745") + "Adventure"; + public static final String CHALLENGEGUIPREFIX = ChatColor.of("#2d8745") + "Challenge"; - @Override - public void onLoad() { - plugin = this; - LOGGER = getLogger(); - File oldPluginFolder = new File("plugins/Challenges"); - if (oldPluginFolder.isDirectory()) { - if (!oldPluginFolder.renameTo(new File("plugins/Adventure"))) { - LOGGER.severe("Challenges Ordner konnte nicht in Adventure umgenannt werden!"); - plugin.getServer().shutdown(); - } - } + private static final TextColor BRACKETS = TextColor.fromHexString("#87f7ea"); + + public static final TextComponent PREFIX_COMPONENT = Component.text("[", BRACKETS).append(Component.text("Lobby", TextColor.fromHexString("#52ff9d"))).append(Component.text("] ", BRACKETS)); + + private static Lobby plugin; + private final Map entityData; + private final Map entityServerMapping; + private final Set availableServers; + public NMSUtils nmsUtils; + private Config config; + private ChallengesGlobalDataHelper globalDataHelper; + private CategoriesConfig categoriesConfig; + private AdventureMapsConfig adventureMapsConfig; + private PlayerUUIDCache playerUUIDCache; + + private CubesideStatisticsAPI cubesideStatistics; + private Statistics statistics; + //private static SignManager signManager; + private final List eventServerPlayerList; + + private Scheduler scheduler; + + private Path challengeSavePath; + private Path adventureSavePath; + private Path aventureMapsPath; + private Path serverJarsPath; + private Path serverFolderPath; + + + public Lobby() { + this.entityData = new HashMap<>(); + this.entityServerMapping = new HashMap<>(); + this.availableServers = new HashSet<>(); + this.eventServerPlayerList = new ArrayList<>(); + } + + public static Lobby getPlugin() { + return plugin; } @Override public void onEnable() { - // Plugin startup logic + plugin = this; + playerUUIDCache = (PlayerUUIDCache) getServer().getPluginManager().getPlugin("PlayerUUIDCache"); + nmsUtils = getServer().getServicesManager().load(NMSUtils.class); + if (getServer().getPluginManager().isPluginEnabled("CubesideStatistics")) { + cubesideStatistics = getServer().getServicesManager().load(CubesideStatisticsAPI.class); + statistics = new Statistics(this); + } + + /*if (getServer().getPluginManager().isPluginEnabled("SignGUI")) { + signManager = new SignManager(this); + signManager.init(); + }*/ + + /*try { + Class.forName("io.papermc.paper.threadedregions.scheduler.ScheduledTask"); + getLogger().log(Level.INFO, "Folia found. Use Folia Scheduler"); + scheduler = new FoliaScheduler(this); + } catch (Throwable ignored) { + getLogger().log(Level.INFO, "Bukkit found. Use Bukkit Scheduler"); + scheduler = new BukkitScheduler(this); + }*/ + getLogger().log(Level.INFO, "Bukkit found. Use Bukkit Scheduler"); + scheduler = new BukkitScheduler(this); + + + this.globalDataHelper = new ChallengesGlobalDataHelper(this); + this.config = new Config(this); + loadCategoriesAndMaps(); + + if (Bukkit.getPluginManager().getPlugin("Challenges") != null) { // Challenge server -> listen on Challenge events + Bukkit.getPluginManager().registerEvents(new ChallengesEventListener(this), this); + } else { // Lobby server -> register commands + CommandRouter router = new CommandRouter(getCommand("piglins")); + router.addCommandMapping(new AddEntityCommand(this), "spawn"); + router.addCommandMapping(new RemoveEntityCommand(this), "remove"); + router.addCommandMapping(new Entitytphere(this), "tphere"); + router.addCommandMapping(new ListPiglinCommand(this), "list"); + router.addCommandMapping(new SetEntitySpawnLocationCommand(this), "setlocation"); + router.addCommandMapping(new ToggleArenaCommand(this, true), "enable"); + router.addCommandMapping(new ToggleArenaCommand(this, false), "disable"); + + CommandRouter challengesrouter = new CommandRouter(getCommand("challenges")); + challengesrouter.addCommandMapping(new ChallengeLoadCommand(this), "load"); + challengesrouter.addCommandMapping(new ChallengesStatsCommand(plugin.getStatistics()), "stats"); + challengesrouter.addCommandMapping(new ChallengeSetStatsCommand(plugin), "setstats"); + challengesrouter.addCommandMapping(new ChallengeClearSavesCommand(plugin), "clearoldsaves"); + challengesrouter.addCommandMapping(new ChallengeListUserStatsCommand(plugin), "listuserstats"); + + CommandRouter adventurerouter = new CommandRouter(getCommand("adventure")); + adventurerouter.addCommandMapping(new AdventureLoadCommand(this), "load"); + adventurerouter.addCommandMapping(new AdventureAddCategoryCommand(this), "addcategory"); + adventurerouter.addCommandMapping(new AdventureAddMapCommand(this), "addmap"); + adventurerouter.addCommandMapping(new AdventureMapsCommand(this), "maps"); + adventurerouter.addCommandMapping(new AdventureTestMapCommand(this), "testmap"); + adventurerouter.addCommandMapping(new ChallengesRemovePlayerServer(this), "removeplayerfromserver"); + adventurerouter.addCommandMapping(new AdventureConvertMapCommand(this), "convertmap"); + adventurerouter.addCommandMapping(new AdventureLoadMapIconsCommand(this), "loadmapicons"); + adventurerouter.addCommandMapping(new AdventureClearSavesCommand(plugin), "clearoldsaves"); + adventurerouter.addCommandMapping(new AdventureTempCommand(this), "temp"); + adventurerouter.addCommandMapping(new AdventureStartEventServerCommand(this), "starteventserver"); + + Bukkit.getPluginManager().registerEvents(new EntityListener(this), this); + Bukkit.getPluginManager().registerEvents(new PlayerListener(this), this); + } + + Bukkit.getPluginManager().registerEvents(globalDataHelper, this); } @Override public void onDisable() { - // Plugin shutdown logic + saveCategoriesAndMaps(); + getPluginConfig().getChallengeServers().forEach(Server::despawnPiglin); + getPluginConfig().getAdventureServers().forEach(Server::despawnPiglin); + } + + public void spawnPiglin(Location location, String serverName, @Nullable Integer serverVersion, String gpLocationName, String serverDisplayName) { + spawnPiglin(location, serverName, serverVersion, gpLocationName, serverDisplayName, true); + } + + public void spawnPiglin(Location location, String serverName, @Nullable Integer serverVersion, String gpLocationName, String serverDisplayName, boolean saveToConfig) { + if (entityData.containsKey(serverName)) { + despawnPiglin(entityData.get(serverName).getEntityUUID(), serverName); + } + Piglin piglin = (Piglin) location.getWorld().spawnEntity(location, EntityType.PIGLIN, CreatureSpawnEvent.SpawnReason.CUSTOM, t -> ((Piglin) t).getEquipment().clear()); + piglin.setAI(false); + piglin.setSilent(true); + piglin.setRemoveWhenFarAway(false); + piglin.setPersistent(true); + piglin.setCustomNameVisible(true); + addPiglin(piglin.getUniqueId(), serverName, serverVersion, gpLocationName, serverDisplayName, saveToConfig); + + globalDataHelper.requestInitialData(serverName); + } + + public void despawnPiglin(UUID piglinUUID, String serverName) { + Entity piglin = Bukkit.getEntity(piglinUUID); + if (piglin != null) { + piglin.remove(); + removePiglin(serverName); + } + } + + public void despawnPiglin(String serverName) { + if (entityData.get(serverName) != null) { + despawnPiglin(entityData.get(serverName).getEntityUUID(), serverName); + } + } + + public void spawnNPC(Location location, String serverName, String gpLocationName, String serverDisplayName, boolean saveToConfig) { + if (entityData.containsKey(serverName)) { + despawnNPC(entityData.get(serverName).getEntityUUID(), serverDisplayName); + } + if (plugin.getServer().getPluginManager().getPlugin("CubesideNPCs") == null) { + return; + } + //addPiglin(CubesideNPCs.getPlugin().spawnNPC(serverDisplayName, location), serverName, gpLocationName, serverDisplayName, saveToConfig); + + globalDataHelper.requestInitialData(serverName); + } + + public void despawnNPC(String serverName) { + if (entityData.get(serverName) != null) { + despawnNPC(entityData.get(serverName).getEntityUUID(), serverName); + } + } + + public void despawnNPC(UUID piglinUUID, String serverName) { + if (plugin.getServer().getPluginManager().getPlugin("CubesideNPCs") == null) { + return; + } + //CubesideNPCs.getPlugin().removeNPC(piglinUUID); + removePiglin(serverName); + } + + public void addPiglin(UUID piglinUUID, String serverName, String gpLocationName, String serverDisplayName, boolean saveToConfig) { + addPiglin(piglinUUID, serverName, null, gpLocationName, serverDisplayName, saveToConfig); + } + + public void addPiglin(UUID piglinUUID, String serverName, @Nullable Integer mapVersion, String gpLocationName, String serverDisplayName, boolean saveToConfig) { + JoinEntityData entityData = new JoinEntityData(serverName, mapVersion, piglinUUID, gpLocationName, serverDisplayName, JoinEntityData.ServerStatus.OFFLINE, JoinEntityData.EventStatus.NORMAL, 0, 0); + this.entityData.put(serverName, entityData); + this.entityServerMapping.put(piglinUUID, serverName); + + if (saveToConfig) { + this.config.savePiglin(entityData); + } + } + + public void removePiglin(String serverName) { + JoinEntityData data = this.entityData.remove(serverName); + if (data != null) { + this.entityServerMapping.remove(data.getEntityUUID()); + } + + this.config.removePiglin(serverName); + } + + public void updateTimerStatus(String serverName, boolean running) { + JoinEntityData data = entityData.get(serverName); + if (data != null) { + data.setServerStatus(running ? JoinEntityData.ServerStatus.RUNNING : JoinEntityData.ServerStatus.ONLINE); + updatePiglinCustomName(serverName); + updatePiglinBehaviour(serverName); + } + } + + public void updateEventStatus(String serverName, boolean event) { + JoinEntityData data = entityData.get(serverName); + if (data != null) { + data.setEventStatus(event ? JoinEntityData.EventStatus.EVENT : JoinEntityData.EventStatus.NORMAL); + updatePiglinCustomName(serverName); + updatePiglinBehaviour(serverName); + } + } + + public void updateServerStatus(String serverName, boolean online) { + JoinEntityData data = entityData.get(serverName); + + if (data != null) { + data.setServerStatus(online ? JoinEntityData.ServerStatus.ONLINE : JoinEntityData.ServerStatus.OFFLINE); + + updatePiglinCustomName(serverName); + updatePiglinBehaviour(serverName); + } + } + + public void updatePlayerCount(String serverName, int count, int maxPlayers) { + JoinEntityData data = entityData.get(serverName); + + if (data != null) { + data.setPlayerCount(count); + data.setMaxPlayers(maxPlayers); + + updatePiglinCustomName(serverName); + updatePiglinBehaviour(serverName); + } + } + + public Piglin getPiglinForServerName(String serverName) { + JoinEntityData data = entityData.get(serverName); + if (data != null) { + Entity piglin = Bukkit.getEntity(data.getEntityUUID()); + + if (piglin instanceof Piglin) { + return (Piglin) piglin; + } + } + return null; + } + + public void updatePiglinCustomName(String serverName) { + Entity entity = getPiglinForServerName(serverName); + JoinEntityData data = entityData.get(serverName); + + if (entity == null) { + return; + } + + if (data == null) { + return; + } + String customName = data.createCustomEntityName(); + entity.setCustomName(customName); + } + + public void updatePiglinBehaviour(String serverName) { + Piglin piglin = getPiglinForServerName(serverName); + JoinEntityData data = entityData.get(serverName); + + if (piglin != null && data != null) { + if (data.getPlayerCount() < data.getMaxPlayers()) { + switch (data.getServerStatus()) { + case ONLINE -> { + piglin.getEquipment().clear(); + if (nmsUtils != null) { + nmsUtils.getEntityUtils().setPiglinDancing(piglin, true); + } + } + case OFFLINE -> { + if (nmsUtils != null) { + nmsUtils.getEntityUtils().setPiglinDancing(piglin, false); + } + + piglin.getEquipment().setItemInOffHand(new ItemStack(Material.GOLD_INGOT)); + } + case RUNNING -> { + piglin.getEquipment().clear(); + if (nmsUtils != null) { + nmsUtils.getEntityUtils().setPiglinDancing(piglin, false); + } + } + } + } else { // server is full + piglin.getEquipment().clear(); + if (nmsUtils != null) { + nmsUtils.getEntityUtils().setPiglinDancing(piglin, false); + } + } + } + } + + public void saveCategoriesAndMaps() { + this.adventureMapsConfig.save(); + this.categoriesConfig.save(); + } + + public void loadCategoriesAndMaps() { + this.categoriesConfig = new CategoriesConfig(this); + this.adventureMapsConfig = new AdventureMapsConfig(this); + this.adventureMapsConfig.load(); + this.categoriesConfig.load(); + } + + public void reloadCategoriesAndMaps() { + getLogger().log(Level.INFO, "Maps werden gespeichert und neu geladen."); + saveCategoriesAndMaps(); + loadCategoriesAndMaps(); + getLogger().log(Level.INFO, "Maps wurden neu geladen."); + } + + public PlayerUUIDCache getPlayerUUIDCache() { + return playerUUIDCache; + } + + public AdventureMapsConfig getAdventureMapsConfig() { + return this.adventureMapsConfig; + } + + public CategoriesConfig getCategoriesConfig() { + return this.categoriesConfig; + } + + public Config getPluginConfig() { + return config; + } + + public ChallengesGlobalDataHelper getGlobalDataHelper() { + return globalDataHelper; + } + + public boolean isJoinEntity(Entity entity) { + return entityServerMapping.containsKey(entity.getUniqueId()); + } + + public JoinEntityData getEntityData(String serverName) { + return entityData.get(serverName); + } + + public String getServerNameForEntity(UUID entityUUID) { + return entityServerMapping.get(entityUUID); + } + + public Map getEntityData() { + return entityData; + } + + public Set getAvailableServers() { + return availableServers; + } + + public CubesideStatisticsAPI getCubesideStatistics() { + return cubesideStatistics; + } + + public Statistics getStatistics() { + return statistics; + } + + /*public SignManager getSignManager() { + return signManager; + }*/ + + public List getEventServerPlayerList() { + return eventServerPlayerList; + } + + public Scheduler getScheduler() { + return scheduler; + } + + public Path getChallengeSavePath() { + return challengeSavePath; + } + + public void setChallengeSavePath(Path challengeSavePath) { + this.challengeSavePath = challengeSavePath; + } + + public Path getAdventureSavePath() { + return adventureSavePath; + } + + public void setAdventureSavePath(Path adventureSavePath) { + this.adventureSavePath = adventureSavePath; + } + + public Path getAdventureMapsPath() { + return aventureMapsPath; + } + + public void setAventureMapsPath(Path aventureMapsPath) { + this.aventureMapsPath = aventureMapsPath; + } + + public Path getServerJarsPath() { + return serverJarsPath; + } + + public void setServerJarsPath(Path serverJarsPath) { + this.serverJarsPath = serverJarsPath; + } + + public Path getServerFolderPath() { + return serverFolderPath; + } + + public void setServerFolderPath(Path serverFolderPath) { + this.serverFolderPath = serverFolderPath; } } diff --git a/Lobby/src/main/java/de/fanta/lobby/SaveSlot.java b/Lobby/src/main/java/de/fanta/lobby/SaveSlot.java new file mode 100644 index 0000000..863cb67 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/SaveSlot.java @@ -0,0 +1,25 @@ +package de.fanta.lobby; + +public enum SaveSlot { + + SLOT_1("1", "challenge.save.slot1"), + SLOT_2("2", "challenge.save.slot2"), + SLOT_3("3", "challenge.save.slot3"), + SLOT_AUTO("autosave", "challenge.save.slotauto"); + + private final String slot; + private final String permission; + + SaveSlot(String prefix, String permission) { + this.slot = prefix; + this.permission = permission; + } + + public String getSlot() { + return slot; + } + + public String getPermission() { + return permission; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/Server.java b/Lobby/src/main/java/de/fanta/lobby/Server.java new file mode 100644 index 0000000..7f83c81 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/Server.java @@ -0,0 +1,318 @@ +package de.fanta.lobby; + +import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; +import org.apache.commons.io.FileUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; + +public class Server { + public static HashMap serverPlayers = new HashMap<>(); + + private final Lobby plugin; + + private final String name; + + private int serverVersion; + + private final String gPLocation; + + private final String dir; + + private final ServerType serverType; + + private final Location piglinLocation; + + private boolean online; + + public Server(String name, @Nullable Integer serverVersion, String gPLocation, String dir, ServerType serverType, Lobby plugin, Location piglinLocation) { + this.name = name; + this.serverVersion = serverVersion == null ? 0 : serverVersion; + this.gPLocation = gPLocation; + this.dir = dir; + this.serverType = serverType; + this.plugin = plugin; + this.online = (plugin.getGlobalDataHelper().getServer(name) != null); + this.piglinLocation = piglinLocation; + } + + public static Server getServerfromPlayer(Player p) { + Server server = null; + if (serverPlayers.containsValue(p.getUniqueId())) + for (Map.Entry entry : serverPlayers.entrySet()) { + if (entry.getValue().equals(p.getUniqueId())) + server = entry.getKey(); + } + return server; + } + + public boolean isOnline() { + return this.online; + } + + public void setOnline(boolean online) { + this.online = online; + } + + public String getName() { + return this.name; + } + + public String getGPLocation() { + return this.gPLocation; + } + + public void setServerVersion(int serverVersion) { + this.serverVersion = serverVersion; + } + + public void loadSaved(Player p, UUID playerID, String slot) { + this.online = true; + serverPlayers.put(this, p.getUniqueId()); + File dir; + //dir = new File("/home/minecraft/" + this.serverType.getDir() + "/" + playerID + "/" + slot); + if (serverType == ServerType.CHALLENGES) { + dir = new File(plugin.getChallengeSavePath().toFile(), "/" + playerID + "/" + slot); + } else { + dir = new File(plugin.getAdventureSavePath().toFile(), "/" + playerID + "/" + slot); + } + + String path = playerID + "/" + slot; + + + if (!dir.isDirectory()) { + ChatUtil.sendErrorMessage(p, "Map " + path + " nicht gefunden!"); + this.online = false; + serverPlayers.remove(this); + return; + } + load(p, this.serverType.getDir(), path, getMapVersion(new File(dir + "/Challenges/serverconfig.yml"))); + } + + public void loadNewAdventure(Player player, String category, String map, String mapVersion) { + int playerVersion = Via.getAPI().getPlayerVersion(player.getUniqueId()); + int mapProtocolVersion = ProtocolVersion.getClosest(mapVersion).getVersion(); + if (playerVersion >= mapProtocolVersion) { + this.online = true; + serverPlayers.put(this, player.getUniqueId()); + //File dir = new File("/home/storagebox/Adventure-Maps", category + "/" + map); + File dir = new File(plugin.getAdventureMapsPath().toFile(), category + "/" + map); + if (!dir.isDirectory()) { + ChatUtil.sendErrorMessage(player, "Map " + map + " nicht gefunden!"); + this.online = false; + serverPlayers.remove(this); + return; + } + + load(player, "Adventure-Maps", category + "/" + map, getMapVersion(new File(dir + "/Challenges/serverconfig.yml"))); + } else { + ChatUtil.sendErrorMessage(player, "Du brauchst mindestens die Version " + ChatUtil.BLUE + mapVersion + ChatUtil.RED + " um die Map zu starten!"); + } + } + + public void load(Player p, String serverTypeDir, String targetDir, String ServerVersion) { + plugin.getScheduler().runAsync(() -> { + File serverFolder = new File(plugin.getServerFolderPath().toFile(), this.dir); + File configs = new File(serverFolder, "/plugins/Challenges"); + File end = new File(serverFolder, "/world_the_end"); + File nether = new File(serverFolder, "/world_nether"); + File world = new File(serverFolder, "/world"); + File mlgworld = new File(serverFolder, "/mlg_challenge"); + File serverJar = new File(serverFolder, "/paper.jar"); + File saveServerJar = new File(plugin.getServerJarsPath().toFile(), ServerVersion + "/paper.jar"); + File saveend; + File savenether; + File saveworld; + File saveconfigs; + + + if (!serverTypeDir.equals("Adventure-Maps")) { + saveend = new File(plugin.getChallengeSavePath().toFile(), targetDir + "/world_the_end"); + savenether = new File(plugin.getChallengeSavePath().toFile(), targetDir + "/world_nether"); + saveworld = new File(plugin.getChallengeSavePath().toFile(), targetDir + "/world"); + saveconfigs = new File(plugin.getChallengeSavePath().toFile(), targetDir + "/Challenges"); + } else { + saveend = new File(plugin.getAdventureMapsPath().toFile(), targetDir + "/world_the_end"); + savenether = new File(plugin.getAdventureMapsPath().toFile(), targetDir + "/world_nether"); + saveworld = new File(plugin.getAdventureMapsPath().toFile(), targetDir + "/world"); + saveconfigs = new File(plugin.getAdventureMapsPath().toFile(), targetDir + "/Challenges"); + } + + ChatUtil.sendNormalMessage(p, "Versuche Map zu laden!"); + try { + if (world.isDirectory()) { + FileUtils.deleteDirectory(world); + FileUtils.deleteDirectory(end); + FileUtils.deleteDirectory(nether); + } + if (mlgworld.isDirectory()) { + FileUtils.deleteDirectory(mlgworld); + } + if (serverJar.exists()) { + FileUtils.delete(serverJar); + } + if (configs.isDirectory()) { + FileUtils.deleteDirectory(configs); + } + + HashMap copyMap = new HashMap<>(); + copyMap.put(saveServerJar, serverJar); + copyMap.put(saveconfigs, configs); + copyMap.put(saveworld, world); + copyMap.put(savenether, nether); + copyMap.put(saveend, end); + moveFolderWithProgress(copyMap, p); + + + File serverConfigFile = new File(plugin.getServerFolderPath().toFile(), this.dir + "/plugins/Challenges/serverconfig.yml"); + YamlConfiguration serverConfig = new YamlConfiguration(); + serverConfig.load(serverConfigFile); + + String tempServerType = serverConfig.getString("servertype"); + if (tempServerType == null || tempServerType.equals("CHALLENGE")) { + serverConfig.set("servertype", "CHALLENGE_LOAD"); + serverConfig.save(serverConfigFile); + Bukkit.getLogger().info(serverConfigFile.getAbsolutePath()); + } + + if (tempServerType != null && serverConfig.getString("servertype").equals("ADVENTURE")) { + setServerVersion(ProtocolVersion.getClosest(serverConfig.getString("serverversion")).getVersion()); + } + + } catch (IOException | InvalidConfigurationException e) { + e.printStackTrace(); + ChatUtil.sendErrorMessage(p, "Map konnte nicht geladen werden!"); + this.online = false; + serverPlayers.remove(this); + return; + } + ChatUtil.sendNormalMessage(p, "Map wurde geladen! Server wird nun gestartet!"); + start(p); + }); + } + + public static void moveFolderWithProgress(HashMap copyMap, Player player) throws IOException { + final long[] totalBytes = {0}; + final long[] copiedBytes = {0}; + AtomicReference progress = new AtomicReference<>(0.0); + + for (File sourceFolder : copyMap.keySet()) { + Files.walk(sourceFolder.toPath()).forEach(source -> { + if (!Files.isDirectory(source)) { + totalBytes[0] += source.toFile().length(); + } + }); + } + + for (File sourceFolder : copyMap.keySet()) { + Files.walk(sourceFolder.toPath()).forEach(source -> { + try { + File target = new File(copyMap.get(sourceFolder).toPath().resolve(sourceFolder.toPath().relativize(source)).toString()); + if (Files.isDirectory(source)) { + target.mkdir(); + } else { + Files.copy(source, target.toPath(), StandardCopyOption.REPLACE_EXISTING); + copiedBytes[0] += source.toFile().length(); + progress.set((double) copiedBytes[0] / totalBytes[0] * 100); + player.sendActionBar(ChatUtil.GREEN + "Kopiere Welt: " + getProgressBar(progress.get())); + } + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + } + + public static String getProgressBar(double value) { + int progress = (int) (value / 100 * 40); + + StringBuilder progressBar = new StringBuilder(); + progressBar.append(ChatUtil.RED + "["); + for (int i = 0; i < 40; i++) { + if (i < progress) { + progressBar.append(ChatUtil.PINK + "|"); + } else { + progressBar.append(ChatUtil.GREEN + "|"); + } + } + progressBar.append(ChatUtil.RED + "] " + ChatUtil.PINK + String.format("%.2f", value) + "%"); + + return progressBar.toString(); + } + + public void start(Player player) { + ProcessBuilder processBuilder = new ProcessBuilder(); + boolean eventServer = false; + if (this.serverType == ServerType.ADVENTURE && plugin.getEventServerPlayerList().contains(player.getUniqueId())) { + //processBuilder.command("screen", "-AmdS", player.getName(), "./event.sh").directory(new File("/home/minecraft/Server/" + this.dir)); + processBuilder.command("screen", "-AmdS", player.getName(), "./event.sh").directory(new File(plugin.getServerFolderPath().toFile(), this.dir)); + plugin.getEventServerPlayerList().remove(player.getUniqueId()); + eventServer = true; + } else { + //processBuilder.command("screen", "-AmdS", player.getName(), "./start.sh").directory(new File("/home/minecraft/Server/" + this.dir)); + processBuilder.command("screen", "-AmdS", player.getName(), "./start.sh").directory(new File(plugin.getServerFolderPath().toFile(), this.dir)); + } + + try { + processBuilder.start(); + Bukkit.getLogger().info(this.serverType.toString().toLowerCase() + (eventServer ? " Event Server: " : " Server: ") + getServerfromPlayer(player).gPLocation + " wurde von " + player.getName() + " gestartet!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void spawnPiglin(Player player) { + this.plugin.spawnPiglin(this.piglinLocation, this.name, this.serverVersion, this.gPLocation, player.getName(), false); + } + + public void despawnPiglin() { + this.plugin.despawnPiglin(this.name); + } + + public void spawnNPC(Player player) { + this.plugin.spawnNPC(this.piglinLocation, this.name, this.gPLocation, player.getName(), false); + } + + public void despawnNPC() { + this.plugin.despawnNPC(this.name); + } + + public String getMapVersion(File config) { + String serverVersion; + YamlConfiguration serverConfiguration = new YamlConfiguration(); + if (!config.exists()) { + serverVersion = "latest"; + return serverVersion; + } + try { + serverConfiguration.load(config); + } catch (IOException | InvalidConfigurationException e) { + e.printStackTrace(); + } + String configServerVersion = serverConfiguration.getString("serverversion"); + if (configServerVersion != null) { + File serverversionfolder = new File(plugin.getServerJarsPath().toFile(), configServerVersion); + if (serverversionfolder.isDirectory()) { + serverVersion = configServerVersion; + } else { + serverVersion = "latest"; + } + } else { + serverVersion = "latest"; + } + return serverVersion; + } +} \ No newline at end of file diff --git a/Lobby/src/main/java/de/fanta/lobby/ServerType.java b/Lobby/src/main/java/de/fanta/lobby/ServerType.java new file mode 100644 index 0000000..a3241c9 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/ServerType.java @@ -0,0 +1,17 @@ +package de.fanta.lobby; + +public enum ServerType { + + ADVENTURE("Adventure-saves"), + CHALLENGES("saves"); + + private final String dir; + + ServerType(String dir) { + this.dir = dir; + } + + public String getDir() { + return dir; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/adventure/AdventureMap.java b/Lobby/src/main/java/de/fanta/lobby/adventure/AdventureMap.java new file mode 100644 index 0000000..7cdf56a --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/adventure/AdventureMap.java @@ -0,0 +1,76 @@ +package de.fanta.lobby.adventure; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class AdventureMap { + private final Lobby plugin; + + private final String name; + private final String version; + + private final ItemStack item; + + private final String creator; + + private final String webLink; + + public AdventureMap(Lobby plugin, String name, String version, Material material, String creator, String webLink) { + this.name = name; + this.version = version; + this.creator = creator; + this.webLink = webLink; + this.plugin = plugin; + this.item = new ItemStack((material != null) ? material : Material.STONE); + ItemMeta meta = this.item.getItemMeta(); + meta.setDisplayName("" + ChatUtil.ORANGE + ChatColor.BOLD + getName().replace("_", " ")); + List lore = new ArrayList<>(); + lore.add(""); + lore.add(ChatUtil.GREEN + "Erbauer: " + ChatUtil.BLUE + creator); + lore.add(ChatUtil.GREEN + "Version: " + ChatUtil.BLUE + version); + lore.add(ChatUtil.GREEN + "MapLink: " + ChatUtil.BLUE + "Rechts Klick"); + lore.add(ChatUtil.GREEN + "Map laden: " + ChatUtil.BLUE + "Links Klick"); + meta.setLore(lore); + this.item.setItemMeta(meta); + } + + public AdventureMap(Lobby plugin, String name, ConfigurationSection section) { + this(plugin, name, section.getString("version"), Material.matchMaterial(Objects.requireNonNull(section.getString("item"))), section.getString("creator"), section.getString("web_link")); + } + + public String getName() { + return this.name; + } + + public String getVersion() { + return version; + } + + public ItemStack getItem() { + return this.item; + } + + public String getCreator() { + return this.creator; + } + + public String getWebLink() { + return this.webLink; + } + + public void save(ConfigurationSection section) { + section.set("item", this.item.getType().getKey().toString()); + section.set("creator", this.creator); + section.set("web_link", this.webLink); + section.set("version", this.version); + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/adventure/AdventureMapsConfig.java b/Lobby/src/main/java/de/fanta/lobby/adventure/AdventureMapsConfig.java new file mode 100644 index 0000000..e284273 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/adventure/AdventureMapsConfig.java @@ -0,0 +1,87 @@ +package de.fanta.lobby.adventure; + +import com.google.common.collect.ImmutableMap; +import de.fanta.lobby.Lobby; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class AdventureMapsConfig { + private final Lobby plugin; + + private final Map maps = new HashMap<>(); + + private static File file; + + private static YamlConfiguration config; + + public AdventureMapsConfig(Lobby plugin) { + this.plugin = plugin; + file = new File(plugin.getDataFolder(), "adventure_maps.yml"); + config = new YamlConfiguration(); + } + + private boolean fileExists() throws IOException { + if (!file.exists()) + return file.createNewFile(); + return true; + } + + public void load() { + try { + if (fileExists()) { + config.load(file); + config.getKeys(false).forEach(key -> { + ConfigurationSection section = config.getConfigurationSection(key); + if (section != null) { + AdventureMap map = new AdventureMap(this.plugin, key, section); + if (!this.maps.containsKey(key)) { + this.maps.put(key, map); + } + } + }); + } + } catch (IOException | org.bukkit.configuration.InvalidConfigurationException e) { + e.printStackTrace(); + } + } + + public void save() { + this.maps.forEach((key, map) -> map.save(config.createSection(key))); + try { + config.save(file); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public boolean addMap(AdventureMap map) { + if (!this.maps.containsKey(map.getName())) { + this.maps.put(map.getName(), map); + return true; + } + return false; + } + + public Map getMaps() { + return ImmutableMap.copyOf(this.maps); + } + + @Nullable + public AdventureMap getMap(String name) { + return this.maps.get(name); + } + + public static YamlConfiguration getConfig() { + return config; + } + + public static File getFile() { + return file; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/adventure/CategoriesConfig.java b/Lobby/src/main/java/de/fanta/lobby/adventure/CategoriesConfig.java new file mode 100644 index 0000000..886daea --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/adventure/CategoriesConfig.java @@ -0,0 +1,98 @@ +package de.fanta.lobby.adventure; + +import com.google.common.collect.ImmutableMap; +import de.fanta.lobby.Lobby; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class CategoriesConfig { + private final Lobby plugin; + + private final Map categories = new HashMap<>(); + + private static File file; + + private static YamlConfiguration config; + + public CategoriesConfig(Lobby plugin) { + this.plugin = plugin; + file = new File(plugin.getDataFolder(), "categories.yml"); + config = new YamlConfiguration(); + } + + private boolean fileExists() throws IOException { + if (!file.exists()) + return file.createNewFile(); + return true; + } + + public void load() { + try { + if (fileExists()) { + config.load(file); + config.getKeys(false).forEach(key -> { + ConfigurationSection section = config.getConfigurationSection(key); + if (section != null) { + Category category = new Category(this.plugin, key, section); + if (!this.categories.containsKey(key)) + this.categories.put(key, category); + } + }); + } + } catch (IOException | org.bukkit.configuration.InvalidConfigurationException e) { + e.printStackTrace(); + } + } + + public void save() { + this.categories.forEach((key, category) -> category.save(config.createSection(key))); + try { + config.save(file); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public boolean addCategory(Category category) { + if (!this.categories.containsKey(category.getName())) { + this.categories.put(category.getName(), category); + return true; + } + return false; + } + + public Map getCategories() { + return ImmutableMap.copyOf(this.categories); + } + + @Nullable + public Category getCategory(String name) { + return this.categories.get(name); + } + + public Category getCategorybyMap(AdventureMap adventureMap) { + for (Category category : plugin.getCategoriesConfig().getCategories().values()) { + for (AdventureMap adventureMapTemp : category.getMaps()) { + if (Objects.equals(adventureMap.getName(), adventureMapTemp.getName())) { + return category; + } + } + } + return null; + } + + public static File getFile() { + return file; + } + + public static YamlConfiguration getConfig() { + return config; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/adventure/Category.java b/Lobby/src/main/java/de/fanta/lobby/adventure/Category.java new file mode 100644 index 0000000..19733cd --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/adventure/Category.java @@ -0,0 +1,74 @@ +package de.fanta.lobby.adventure; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public class Category { + private final String name; + + private final ItemStack item; + + private final Set maps; + + private final Lobby plugin = Lobby.getPlugin(); + + public Category(String name, Material material) { + this(name, material, new HashSet<>()); + } + + public Category(Lobby plugin, String name, ConfigurationSection section) { + this(name, Material.matchMaterial(Objects.requireNonNull(section.getString("item"))), section.getStringList("maps").stream().map(mapName -> { + AdventureMap map = plugin.getAdventureMapsConfig().getMap(mapName); + if (map == null) + plugin.getLogger().warning("Die map \"" + mapName + "\" existiert nicht!"); + return map; + }).filter(Objects::nonNull).collect(Collectors.toSet())); + } + + public Category(String name, Material material, Set maps) { + this.name = name; + this.maps = maps; + this.item = new ItemStack((material != null) ? material : Material.STONE); + ItemMeta meta = this.item.getItemMeta(); + meta.setDisplayName("" + ChatUtil.ORANGE + ChatColor.BOLD + getName().replace("_", " ")); + List lore = new ArrayList<>(); + lore.add(""); + lore.add(ChatUtil.GREEN + "Maps: " + ChatUtil.BLUE + maps.size()); + meta.setLore(lore); + this.item.setItemMeta(meta); + } + + public String getName() { + return this.name; + } + + public ItemStack getItem() { + return this.item; + } + + public Set getMaps() { + return this.maps; + } + + public void addMap(AdventureMap map) { + this.maps.add(map); + plugin.reloadCategoriesAndMaps(); + } + + public void save(ConfigurationSection section) { + section.set("item", this.item.getType().getKey().toString()); + section.set("maps", this.maps.stream().map(AdventureMap::getName).collect(Collectors.toList())); + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/adventure/ui/AdventureMapsUI.java b/Lobby/src/main/java/de/fanta/lobby/adventure/ui/AdventureMapsUI.java new file mode 100644 index 0000000..dade396 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/adventure/ui/AdventureMapsUI.java @@ -0,0 +1,156 @@ +package de.fanta.lobby.adventure.ui; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.Server; +import de.fanta.lobby.adventure.AdventureMap; +import de.fanta.lobby.adventure.Category; +import de.iani.cubesideutils.bukkit.inventory.AbstractWindow; +import de.iani.cubesideutils.bukkit.items.CustomHeads; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.TextColor; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class AdventureMapsUI extends AbstractWindow { + private final Lobby plugin; + private final Category category; + private static final int NUM_OF_COLUMNS = 9; + private static final int NUM_OF_ITEM_COLUMNS = NUM_OF_COLUMNS - 1; + private static final int NUM_OF_ROWS = 6; + private static final int WINDOW_SIZE = NUM_OF_COLUMNS * NUM_OF_ROWS; + private static final int END_OF_FIRST_ROW_INDEX = NUM_OF_COLUMNS - 1; + private static final int END_OF_LAST_ROW_INDEX = WINDOW_SIZE - 1; + + private final List maps; + private final int numOfItemRows; + private int scrollAmount; + + public AdventureMapsUI(Lobby plugin, Category category, Player player) { + super(player, Bukkit.createInventory(player, WINDOW_SIZE, ChatUtil.RED + category.getName().replace("_", " ") + " Map's")); + this.category = category; + this.plugin = plugin; + + List maps = this.category.getMaps().stream().sorted(Comparator.comparing(AdventureMap::getName)).toList(); + this.maps = new ArrayList<>(maps.size()); + this.maps.addAll(maps); + + this.numOfItemRows = (int) (Math.ceil(this.maps.size() / (double) NUM_OF_ITEM_COLUMNS)); + this.scrollAmount = 0; + } + + protected void rebuildInventory() { + ItemStack[] content = new ItemStack[WINDOW_SIZE]; + + // build scroll buttons + ItemStack scrollUpHead = this.scrollAmount <= 0 ? CustomHeads.RAINBOW_BLANK.getHead() : CustomHeads.RAINBOW_ARROW_UP.getHead(); + ItemMeta scrollUpMeta = scrollUpHead.getItemMeta(); + scrollUpMeta.setDisplayName((this.scrollAmount <= 0 ? ChatColor.GRAY : ChatColor.WHITE) + "Nach oben scrollen"); + scrollUpHead.setItemMeta(scrollUpMeta); + content[NUM_OF_COLUMNS - 1] = scrollUpHead; + + ItemStack scrollDownHead = this.scrollAmount >= this.numOfItemRows - NUM_OF_ROWS ? CustomHeads.RAINBOW_BLANK.getHead() : CustomHeads.RAINBOW_ARROW_DOWN.getHead(); + ItemMeta scrollDownMeta = scrollDownHead.getItemMeta(); + scrollDownMeta.setDisplayName((this.scrollAmount >= this.numOfItemRows - NUM_OF_ROWS ? ChatColor.GRAY : ChatColor.WHITE) + "Nach unten scrollen"); + scrollDownHead.setItemMeta(scrollDownMeta); + content[WINDOW_SIZE - 1] = scrollDownHead; + + // build scrollbar + for (int i = 1; i < NUM_OF_ROWS - 1; i++) { + content[(i + 1) * NUM_OF_COLUMNS - 1] = new ItemStack(Material.GRAY_STAINED_GLASS_PANE); + } + int numOfScrollbarRows = NUM_OF_ROWS - 2; + int currentScrollbarRow = + (int) Math.round(this.scrollAmount * numOfScrollbarRows / (double) this.numOfItemRows); + content[(currentScrollbarRow + 2) * NUM_OF_COLUMNS - 1] = new ItemStack(Material.BLACK_STAINED_GLASS_PANE); + + // fill in items + int index = this.scrollAmount * NUM_OF_ITEM_COLUMNS; + for (int row = 0; row < NUM_OF_ROWS && index < this.maps.size(); row++) { + for (int column = 0; column < NUM_OF_ITEM_COLUMNS && index < this.maps.size(); column++) { + AdventureMap adventureMap = this.maps.get(index++); + content[row * NUM_OF_COLUMNS + column] = adventureMap == null ? null : adventureMap.getItem(); + } + } + + getInventory().setContents(content); + } + + public void onItemClicked(InventoryClickEvent event) { + if (!mayAffectThisInventory(event)) { + return; + } + + event.setCancelled(true); + + if (!getInventory().equals(event.getClickedInventory())) { + return; + } + + int slot = event.getSlot(); + if (slot == END_OF_FIRST_ROW_INDEX) { + attempScrollUp(); + return; + } else if (slot == END_OF_LAST_ROW_INDEX) { + attempScrollDown(); + return; + } + + if ((slot + 1) % NUM_OF_COLUMNS == 0) { + int numOfScrollbarRows = NUM_OF_ROWS - 2; + int selectedScrollBarRow = (slot + 1) / NUM_OF_COLUMNS - 2; + int targetScrollAmount = Math.round(selectedScrollBarRow * this.numOfItemRows / numOfScrollbarRows); + this.scrollAmount = Math.min(targetScrollAmount, this.numOfItemRows - NUM_OF_ROWS); + this.scrollAmount = Math.max(this.scrollAmount, 0); + rebuildInventory(); + return; + } + + int shopItemIndex = (slot - (slot / NUM_OF_COLUMNS)) + this.scrollAmount * NUM_OF_ITEM_COLUMNS; + if (shopItemIndex >= this.maps.size()) { + return; + } + + AdventureMap map = this.maps.get(shopItemIndex); + Player p = getPlayer(); + + if (map != null) { + if (event.isRightClick()) { + getPlayer().sendMessage(Lobby.PREFIX_COMPONENT.append(Component.text("MapLink: klick mich :)", TextColor.color(Color.YELLOW.asRGB())).clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, map.getWebLink())))); + } else if (!Server.serverPlayers.containsValue(p.getUniqueId())) { + getPlayer().closeInventory(); + this.plugin.getPluginConfig().getOnlineAdventureServer().ifPresentOrElse(server -> server.loadNewAdventure(p, category.getName(), map.getName(), map.getVersion()), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!")); + } else { + ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!"); + } + getPlayer().closeInventory(); + } + } + + private void attempScrollUp() { + if (this.scrollAmount <= 0) { + return; + } + this.scrollAmount--; + rebuildInventory(); + } + + private void attempScrollDown() { + if (this.scrollAmount >= this.numOfItemRows - NUM_OF_ROWS) { + return; + } + this.scrollAmount++; + rebuildInventory(); + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/adventure/ui/AdventureSearchGUI.java b/Lobby/src/main/java/de/fanta/lobby/adventure/ui/AdventureSearchGUI.java new file mode 100644 index 0000000..7a19dcf --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/adventure/ui/AdventureSearchGUI.java @@ -0,0 +1,172 @@ +package de.fanta.lobby.adventure.ui; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.Server; +import de.fanta.lobby.adventure.AdventureMap; +import de.fanta.lobby.adventure.Category; +import de.iani.cubesideutils.bukkit.inventory.AbstractWindow; +import de.iani.cubesideutils.bukkit.items.CustomHeads; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.TextColor; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.TreeMap; +import java.util.UUID; + +public class AdventureSearchGUI extends AbstractWindow { + private final Lobby plugin; + private static final int NUM_OF_COLUMNS = 9; + private static final int NUM_OF_ITEM_COLUMNS = NUM_OF_COLUMNS - 1; + private static final int NUM_OF_ROWS = 6; + private static final int WINDOW_SIZE = NUM_OF_COLUMNS * NUM_OF_ROWS; + private static final int END_OF_FIRST_ROW_INDEX = NUM_OF_COLUMNS - 1; + private static final int END_OF_LAST_ROW_INDEX = WINDOW_SIZE - 1; + + private static final int BACK_INDEX = 0; + + private static final HashMap> mapsByPlayer = new HashMap<>(); + private final int numOfItemRows; + private int scrollAmount; + + public AdventureSearchGUI(Lobby plugin, TreeMap mapList, String seachEntry, Player player) { + super(player, Bukkit.createInventory(player, WINDOW_SIZE, ChatUtil.GREEN + "Suche: " + ChatUtil.BLUE + seachEntry)); + this.plugin = plugin; + + HashMap maps = new HashMap<>(mapList); + mapsByPlayer.put(player.getUniqueId(), maps); + this.numOfItemRows = (int) (Math.ceil(maps.size() / (double) NUM_OF_ITEM_COLUMNS)); + this.scrollAmount = 0; + } + + protected void rebuildInventory() { + ItemStack[] content = new ItemStack[WINDOW_SIZE]; + + // build scroll buttons + ItemStack scrollUpHead = this.scrollAmount <= 0 ? CustomHeads.RAINBOW_BLANK.getHead() : CustomHeads.RAINBOW_ARROW_UP.getHead(); + ItemMeta scrollUpMeta = scrollUpHead.getItemMeta(); + scrollUpMeta.setDisplayName((this.scrollAmount <= 0 ? ChatColor.GRAY : ChatColor.WHITE) + "Nach oben scrollen"); + scrollUpHead.setItemMeta(scrollUpMeta); + content[NUM_OF_COLUMNS - 1] = scrollUpHead; + + ItemStack scrollDownHead = this.scrollAmount >= this.numOfItemRows - NUM_OF_ROWS ? CustomHeads.RAINBOW_BLANK.getHead() : CustomHeads.RAINBOW_ARROW_DOWN.getHead(); + ItemMeta scrollDownMeta = scrollDownHead.getItemMeta(); + scrollDownMeta.setDisplayName((this.scrollAmount >= this.numOfItemRows - NUM_OF_ROWS ? ChatColor.GRAY : ChatColor.WHITE) + "Nach unten scrollen"); + scrollDownHead.setItemMeta(scrollDownMeta); + content[WINDOW_SIZE - 1] = scrollDownHead; + + // build scrollbar + for (int i = 1; i < NUM_OF_ROWS - 1; i++) { + content[(i + 1) * NUM_OF_COLUMNS - 1] = new ItemStack(Material.GRAY_STAINED_GLASS_PANE); + } + int numOfScrollbarRows = NUM_OF_ROWS - 2; + int currentScrollbarRow = + (int) Math.round(this.scrollAmount * numOfScrollbarRows / (double) this.numOfItemRows); + content[(currentScrollbarRow + 2) * NUM_OF_COLUMNS - 1] = new ItemStack(Material.BLACK_STAINED_GLASS_PANE); + + // fill in items + int index = this.scrollAmount * NUM_OF_ITEM_COLUMNS; + HashMap maps = mapsByPlayer.get(getPlayer().getUniqueId()); + for (int row = 1; row < NUM_OF_ROWS && index < maps.size(); row++) { + for (int column = 0; column < NUM_OF_ITEM_COLUMNS && index < maps.size(); column++) { + AdventureMap adventureMap = new ArrayList<>(maps.values()).get(index++); + ItemStack stack = adventureMap.getItem().clone(); + ItemMeta meta = stack.getItemMeta(); + List lore = meta.getLore(); + lore.add(ChatUtil.GREEN + "Kategorie: " + ChatUtil.BLUE + plugin.getCategoriesConfig().getCategorybyMap(adventureMap).getName()); + meta.setLore(lore); + stack.setItemMeta(meta); + content[row * NUM_OF_COLUMNS + column] = adventureMap == null ? null : stack; + } + } + + content[BACK_INDEX] = CustomHeads.RAINBOW_ARROW_BACKWARD_II.getHead(ChatUtil.GREEN + "Zurück"); + getInventory().setContents(content); + } + + public void onItemClicked(InventoryClickEvent event) { + if (!mayAffectThisInventory(event)) { + return; + } + + event.setCancelled(true); + + if (!getInventory().equals(event.getClickedInventory())) { + return; + } + + int slot = event.getSlot(); + + if (slot == BACK_INDEX) { + new CategoryUI(this.plugin, this.plugin.getCategoriesConfig(), getPlayer()).open(); + return; + } + + if (slot == END_OF_FIRST_ROW_INDEX) { + attempScrollUp(); + return; + } else if (slot == END_OF_LAST_ROW_INDEX) { + attempScrollDown(); + return; + } + + if ((slot + 1) % NUM_OF_COLUMNS == 0) { + int numOfScrollbarRows = NUM_OF_ROWS - 2; + int selectedScrollBarRow = (slot + 1) / NUM_OF_COLUMNS - 2; + int targetScrollAmount = Math.round(selectedScrollBarRow * this.numOfItemRows / numOfScrollbarRows); + this.scrollAmount = Math.min(targetScrollAmount, this.numOfItemRows - NUM_OF_ROWS); + this.scrollAmount = Math.max(this.scrollAmount, 0); + rebuildInventory(); + return; + } + + int adventureMapIndex = ((slot - (slot / NUM_OF_COLUMNS)) + this.scrollAmount * NUM_OF_ITEM_COLUMNS) - NUM_OF_COLUMNS + 1; + HashMap maps = mapsByPlayer.get(getPlayer().getUniqueId()); + if (adventureMapIndex >= maps.size()) { + return; + } + + AdventureMap map = new ArrayList<>(maps.values()).get(adventureMapIndex); + Player p = getPlayer(); + + if (map != null) { + Category category = plugin.getCategoriesConfig().getCategorybyMap(map); + if (event.isRightClick()) { + getPlayer().sendMessage(Lobby.PREFIX_COMPONENT.append(Component.text("MapLink: klick mich :)", TextColor.color(Color.YELLOW.asRGB())).clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, map.getWebLink())))); + } else if (!Server.serverPlayers.containsValue(p.getUniqueId())) { + getPlayer().closeInventory(); + this.plugin.getPluginConfig().getOnlineAdventureServer().ifPresentOrElse(server -> server.loadNewAdventure(p, category.getName(), map.getName(), map.getVersion()), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!")); + } else { + ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!"); + } + getPlayer().closeInventory(); + } + } + + private void attempScrollUp() { + if (this.scrollAmount <= 0) { + return; + } + this.scrollAmount--; + rebuildInventory(); + } + + private void attempScrollDown() { + if (this.scrollAmount >= this.numOfItemRows - NUM_OF_ROWS) { + return; + } + this.scrollAmount++; + rebuildInventory(); + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/adventure/ui/CategoryUI.java b/Lobby/src/main/java/de/fanta/lobby/adventure/ui/CategoryUI.java new file mode 100644 index 0000000..4ad3529 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/adventure/ui/CategoryUI.java @@ -0,0 +1,113 @@ +package de.fanta.lobby.adventure.ui; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.adventure.CategoriesConfig; +import de.fanta.lobby.adventure.Category; +import de.fanta.lobby.utils.ItemUtil; +import de.iani.cubesideutils.bukkit.inventory.AbstractWindow; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CategoryUI extends AbstractWindow { + private final Lobby plugin; + + private final CategoriesConfig config; + + private final Map categoryPerSlot = new HashMap<>(); + + private final int SEARCH_INDEX = 0; + + public CategoryUI(Lobby plugin, CategoriesConfig config, Player player) { + super(player, Bukkit.createInventory(player, 9 * (config.getCategories().size() / 7 + ((config.getCategories().size() % 7 > 0) ? 1 : 0)) + 18, ChatUtil.BLUE + "Adventure Map Kategorien")); + this.config = config; + this.plugin = plugin; + } + + protected void rebuildInventory() { + Map categories = this.config.getCategories(); + List sortedValues = categories.values().stream().sorted(Comparator.comparing(Category::getName)).toList(); + int row = 0; + int cat = 0; + for (Category category : sortedValues) { + int slot = row * 9 + cat + 10; + getInventory().setItem(slot, category.getItem()); + this.categoryPerSlot.put(slot, category); + if (cat < 6) { + cat++; + continue; + } + row++; + cat = 0; + } + + ItemStack searchItem = new ItemStack(Material.DARK_OAK_SIGN); + ItemMeta itemMeta = searchItem.getItemMeta(); + itemMeta.setDisplayName(ChatUtil.GREEN + "Suche"); + String[] lore = {ChatUtil.GREEN + "Suche nach Adventure Maps"}; + itemMeta.setLore(Arrays.stream(lore).toList()); + searchItem.setItemMeta(itemMeta); + + getInventory().setItem(SEARCH_INDEX, searchItem); + + for (int i1 = 0; i1 < getInventory().getSize(); i1++) { + ItemStack item = getInventory().getItem(i1); + if (item == null) { + getInventory().setItem(i1, ItemUtil.EMPTY_ICON); + } + } + } + + public void onItemClicked(InventoryClickEvent event) { + super.onItemClicked(event); + int slot = event.getSlot(); + + if (slot == SEARCH_INDEX) { + /*SignGUI gui = new SignGUI(plugin.getSignManager(), signEvent -> new BukkitRunnable() { + @Override + public void run() { + String line1 = signEvent.getLines()[0]; + if (line1 != null && !line1.equals("")) { + HashMap maps = new HashMap<>(); + for (Category category : plugin.getCategoriesConfig().getCategories().values()) { + for (AdventureMap adventureMap : category.getMaps()) { + if (adventureMap.getName().toLowerCase().replace("_" , " ").contains(line1.toLowerCase())) { + maps.put(adventureMap.getName(), adventureMap); + } + } + } + + if (maps.isEmpty()) { + ChatUtil.sendErrorMessage(signEvent.getPlayer(), "Kein Ergebnis mit deinem Suchbegriff."); + } else { + TreeMap sortedMaps = new TreeMap<>(maps); + new AdventureSearchGUI(plugin, sortedMaps, line1, getPlayer()).open(); + } + + } else { + ChatUtil.sendErrorMessage(signEvent.getPlayer(), "Kein Ergebnis mit deinem Suchbegriff."); + } + } + }.runTaskLater(plugin, 1)); + String[] lines = {"", "^^^^^^^^^^^^^^^", "Suche nach", "Adventure Maps"}; + gui.withLines(lines); + gui.open(getPlayer());*/ + return; + } + + Category category = this.categoryPerSlot.get(slot); + if (category != null) { + new AdventureMapsUI(this.plugin, category, getPlayer()).open(); + } + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureAddCategoryCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureAddCategoryCommand.java new file mode 100644 index 0000000..1b2b235 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureAddCategoryCommand.java @@ -0,0 +1,48 @@ +package de.fanta.lobby.commands.AdventureCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.adventure.CategoriesConfig; +import de.fanta.lobby.adventure.Category; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class AdventureAddCategoryCommand extends SubCommand { + private final CategoriesConfig config; + + public AdventureAddCategoryCommand(Lobby plugin) { + this.config = plugin.getCategoriesConfig(); + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + if (!p.hasPermission("challenges.createcategorie")) { + ChatUtil.sendErrorMessage(sender, "Keine Rechte!"); + return true; + } + Material item = p.getInventory().getItemInMainHand().getType(); + if (item == Material.AIR) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Item in der Hand haben!"); + return true; + } + if (args.hasNext()) { + String name = args.getNext(); + Category category = new Category(name, item); + if (!this.config.addCategory(category)) { + ChatUtil.sendErrorMessage(sender, "Die category " + name + " existiert bereits!"); + return true; + } + ChatUtil.sendNormalMessage(sender, "Die category " + name + " wurde erfolgreich hinzugefügt!"); + this.config.save(); + return true; + } + return false; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureAddMapCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureAddMapCommand.java new file mode 100644 index 0000000..4c8c7e6 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureAddMapCommand.java @@ -0,0 +1,74 @@ +package de.fanta.lobby.commands.AdventureCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.adventure.AdventureMap; +import de.fanta.lobby.adventure.AdventureMapsConfig; +import de.fanta.lobby.adventure.Category; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class AdventureAddMapCommand extends SubCommand { + private final Lobby plugin; + + private final AdventureMapsConfig config; + + public AdventureAddMapCommand(Lobby plugin) { + this.plugin = plugin; + this.config = plugin.getAdventureMapsConfig(); + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + if (!p.hasPermission("challenges.createadventuremap")) { + ChatUtil.sendErrorMessage(sender, "Keine Rechte!"); + return true; + } + Material item = p.getInventory().getItemInMainHand().getType(); + if (item == Material.AIR) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Item in der Hand haben!"); + return true; + } + if (args.hasNext()) { + String name = args.getNext(); + if (args.hasNext()) { + String categoryName = args.getNext(); + Category category = this.plugin.getCategoriesConfig().getCategory(categoryName); + if (category == null) { + ChatUtil.sendErrorMessage(sender, "Die Kategorie " + categoryName + " existiert nicht!"); + return true; + } + if (args.hasNext()) { + String webLink = args.getNext(); + webLink = webLink.equalsIgnoreCase("null") ? "" : webLink; + if (args.hasNext()) { + String version = args.getNext(); + if (args.hasNext()) { + String creator = args.getAll(null); + if (creator != null) { + AdventureMap map = new AdventureMap(this.plugin, name, version, item, creator, webLink); + if (!this.config.addMap(map)) { + ChatUtil.sendErrorMessage(sender, "Die map " + name + " existiert bereits!"); + return true; + } + category.addMap(map); + ChatUtil.sendNormalMessage(sender, "Die map " + name + " wurde erfolgreich hinzugefügt!"); + return true; + } + } + } + + } + } + } + ChatUtil.sendWarningMessage(p, "/adventure addmap "); + return true; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureClearSavesCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureClearSavesCommand.java new file mode 100644 index 0000000..359263f --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureClearSavesCommand.java @@ -0,0 +1,78 @@ +package de.fanta.lobby.commands.AdventureCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.iani.cubesideutils.StringUtil; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.apache.commons.io.FileUtils; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; +import java.util.Objects; +import java.util.logging.Level; + +public class AdventureClearSavesCommand extends SubCommand { + + private final Lobby plugin; + + public AdventureClearSavesCommand(Lobby plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + + ChatUtil.sendNormalMessage(p, "Gespeicherte Adventure-Maps die älter als 120 Tage sind werden gelöscht. Dies kann einige Minuten dauern."); + plugin.getScheduler().runAsync(() -> { + File adventureSaveFolder = plugin.getAdventureSavePath().toFile(); //DELETE OLD AdventureMaps + if (adventureSaveFolder.isDirectory()) { + File[] playerFolders; + playerFolders = adventureSaveFolder.listFiles(); + if (playerFolders != null) { + int deletecounter = 0; + long starttime = System.currentTimeMillis(); + for (File playerFolder : playerFolders) { + File[] saveFolders; + saveFolders = playerFolder.listFiles(); + if (saveFolders != null) { + try { + for (File map : saveFolders) { + BasicFileAttributes attr = Files.readAttributes(map.toPath(), BasicFileAttributes.class); + FileTime fileTime = attr.creationTime(); + if (10368000000L + fileTime.toMillis() <= System.currentTimeMillis()) { //120 Tage + FileUtils.deleteDirectory(map); + deletecounter++; + ChatUtil.sendNormalMessage(p, "Welt " + playerFolder.getName() + "/" + map.getName() + " gelöscht. (" + deletecounter + ")"); + } + } + if (Objects.requireNonNull(playerFolder.listFiles()).length == 0) { + FileUtils.deleteDirectory(playerFolder); + } + } catch (IOException ex) { + Bukkit.getLogger().log(Level.SEVERE, "Fehler beim löschen einer Map", ex); + } + } + } + ChatUtil.sendNormalMessage(p, "Es wurden: " + deletecounter + " maps in " + StringUtil.formatTimespan(System.currentTimeMillis() - starttime) + " gelöscht"); + } + } + }); + return true; + } + + @Override + public String getRequiredPermission() { + return "challenges.clearsaves"; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureConvertMapCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureConvertMapCommand.java new file mode 100644 index 0000000..5fabbc8 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureConvertMapCommand.java @@ -0,0 +1,266 @@ +package de.fanta.lobby.commands.AdventureCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.apache.commons.io.FileUtils; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.UUID; +import java.util.logging.Level; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class AdventureConvertMapCommand extends SubCommand { + private static FileConfiguration ServerConfig; + private static File ServerConfigFile; + private static Lobby plugin; + + public AdventureConvertMapCommand(Lobby plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String s1, ArgsParser args) { + String urlString; + String versioString; + + if (!(sender instanceof Player player)) { + ChatUtil.sendErrorMessage(sender, "You are not a Player"); + return true; + } + + if (!player.hasPermission("adventure.convertmap")) { + ChatUtil.sendErrorMessage(player, "Keine Rechte!"); + return true; + } + + if (args.hasNext()) { + urlString = args.getNext(); + if (args.hasNext()) { + versioString = args.getNext(); + } else { + ChatUtil.sendErrorMessage(player, "/convertmap "); + return true; + } + + File folder = new File(Bukkit.getPluginsFolder().getPath() + "/Challenges/MapConverter"); + + if (!folder.exists()) { + folder.mkdir(); + } + + String finalUrlString = urlString; + String finalVersioString = versioString; + plugin.getScheduler().runAsync(() -> downloadMap(finalUrlString, finalVersioString, folder, player)); + } else { + ChatUtil.sendErrorMessage(sender, "/convertmap "); + return true; + } + return true; + } + + private static void downloadMap(String finalUrlString, String versioString, File folder, Player player) { + Path zipPath = Path.of(folder + "/world.zip"); + try { + InputStream in = new URL(finalUrlString).openStream(); + Files.copy(in, zipPath, StandardCopyOption.REPLACE_EXISTING); + ChatUtil.sendNormalMessage(player, "Map heruntergeladen."); + } catch (IOException e) { + throw new RuntimeException(e); + } + + unZip(folder, zipPath, versioString, player); + } + + + private static void unZip(File folder, Path zipPath, String versioString, Player player) { + File worldFolder = new File(folder.getPath() + "/" + UUID.randomUUID()); + try { + unzipFolder(zipPath, worldFolder.toPath()); + ChatUtil.sendNormalMessage(player, "UnZip Done " + worldFolder.getName()); + } catch (IOException e) { + throw new RuntimeException(e); + } + + searchRegionFile(worldFolder, versioString, player); + } + + private static void searchRegionFile(File file, String versioString, Player player) { + File[] files; + files = file.listFiles(); + if (files != null) { + for (File filefile : files) { + if (filefile.getName().equals("region")) { + ChatUtil.sendNormalMessage(player, "region folder found"); + convertToSpigotMap(filefile.getAbsoluteFile(), versioString, player); + return; + } + + if (filefile.isDirectory()) { + searchRegionFile(filefile, versioString, player); + } + } + } + } + + private static void convertToSpigotMap(File file, String versioString, Player player) { + if (file != null) { + File mapFolder = new File(file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - 7)); + File worldFolder = new File(mapFolder.getAbsoluteFile() + "/world"); + File netherFolder = new File(mapFolder.getAbsoluteFile() + "/world_nether"); + File endFolder = new File(mapFolder.getAbsoluteFile() + "/world_the_end"); + + try { + FileUtils.forceMkdir(worldFolder); + FileUtils.forceMkdir(netherFolder); + FileUtils.forceMkdir(endFolder); + } catch (IOException e) { + throw new RuntimeException(e); + } + + File[] files; + files = mapFolder.listFiles(); + if (files != null) { + for (File tempFiles : files) { + try { + if (!tempFiles.getName().equals("DIM1") && !tempFiles.getName().equals("DIM-1") && !tempFiles.getName().equals("world") && !tempFiles.getName().equals("world_nether") && !tempFiles.getName().equals("world_the_end")) { + if (tempFiles.isDirectory()) { + FileUtils.moveDirectory(tempFiles, new File(worldFolder + "/" + tempFiles.getName())); + } else { + FileUtils.moveFile(tempFiles, new File(worldFolder + "/" + tempFiles.getName())); + } + } + + if (tempFiles.getName().equals("DIM1")) { + FileUtils.moveDirectory(tempFiles, new File(endFolder + "/" + tempFiles.getName())); + } + + if (tempFiles.getName().equals("DIM-1")) { + FileUtils.moveDirectory(tempFiles, new File(netherFolder + "/" + tempFiles.getName())); + } + } catch (IOException e) { + plugin.getLogger().log(Level.SEVERE, "Can't Copy File", e); + } + } + + File challengesFolder = new File(mapFolder.getAbsoluteFile() + "/Challenges"); + + try { + FileUtils.forceMkdir(challengesFolder); + } catch (IOException e) { + throw new RuntimeException(e); + } + + createServerConfig(challengesFolder); + + + try { + getServerConfig().set("servertype", "ADVENTURE"); + ServerConfig.save(ServerConfigFile); + getServerConfig().set("serverversion", versioString); + ServerConfig.save(ServerConfigFile); + } catch (IOException e) { + Bukkit.getLogger().log(Level.SEVERE, "Can't Save Config", e); + } + + String oldFolderName = mapFolder.getName(); + String newFolderName = mapFolder.getName().replace(" ", "_"); + File newFolderFile = new File(mapFolder.getPath().replace(oldFolderName, newFolderName)); + + mapFolder.renameTo(newFolderFile); + + ChatUtil.sendNormalMessage(player, "Konvertierung fertig."); + + File destFolder = new File(plugin.getAdventureMapsPath().toFile(), "test/" + newFolderName); + + try { + FileUtils.moveDirectory(newFolderFile, destFolder); + } catch (IOException e) { + throw new RuntimeException(e); + } + + ChatUtil.sendNormalMessage(player, "Map wurde zum testen in das test Verzeichnis verschoben."); + + TextComponent component = new TextComponent(TextComponent.fromLegacyText(Lobby.PREFIX + ChatUtil.GREEN + " Klicke hier um die Map zu testen.")); + component.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/a testmap test " + newFolderName)); + player.sendMessage(component); + + } else { + ChatUtil.sendErrorMessage(player, "Keine datei gefunden."); + } + + } else { + ChatUtil.sendErrorMessage(player, "Keine datei gefunden."); + } + } + + public static FileConfiguration getServerConfig() { + return ServerConfig; + } + + private static void createServerConfig(File folder) { + ServerConfigFile = new File(folder.getPath() + "/serverconfig.yml"); + if (!ServerConfigFile.exists()) { + try { + FileUtils.forceMkdirParent(ServerConfigFile); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + ServerConfig = new YamlConfiguration(); + } + + public static void unzipFolder(Path source, Path target) throws IOException { + try (ZipInputStream zis = new ZipInputStream(new FileInputStream(source.toFile()))) { + ZipEntry zipEntry = zis.getNextEntry(); + + while (zipEntry != null) { + + boolean isDirectory = zipEntry.getName().endsWith(File.separator); + + Path newPath = zipSlipProtect(zipEntry, target); + + if (isDirectory) { + Files.createDirectories(newPath); + } else { + if (newPath.getParent() != null) { + if (Files.notExists(newPath.getParent())) { + Files.createDirectories(newPath.getParent()); + } + } + Files.copy(zis, newPath, StandardCopyOption.REPLACE_EXISTING); + } + zipEntry = zis.getNextEntry(); + } + zis.closeEntry(); + } + } + + public static Path zipSlipProtect(ZipEntry zipEntry, Path targetDir) throws IOException { + Path targetDirResolved = targetDir.resolve(zipEntry.getName()); + Path normalizePath = targetDirResolved.normalize(); + + if (!normalizePath.startsWith(targetDir)) { + throw new IOException("Bad zip entry: " + zipEntry.getName()); + } + + return normalizePath; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureLoadCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureLoadCommand.java new file mode 100644 index 0000000..b9bd278 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureLoadCommand.java @@ -0,0 +1,45 @@ +package de.fanta.lobby.commands.AdventureCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.loadgui.AdventureLoadGUI; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import de.iani.playerUUIDCache.CachedPlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class AdventureLoadCommand extends SubCommand { + private final Lobby plugin; + + public AdventureLoadCommand(Lobby plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + + CachedPlayer savePlayer; + if (args.hasNext()) { + if (!p.hasPermission("challenges.load.admin")) { + ChatUtil.sendErrorMessage(p, "Keine Rechte! (Du kannst nur eigene maps Laden)"); + return true; + } + String savePlayerName = args.getNext(); + savePlayer = plugin.getPlayerUUIDCache().getPlayer(savePlayerName); + } else { + savePlayer = plugin.getPlayerUUIDCache().getPlayer(p.getUniqueId()); + } + + if (savePlayer != null) { + new AdventureLoadGUI(p, savePlayer).open(); + } else { + ChatUtil.sendErrorMessage(p, "Spieler nicht gefunden!"); + } + return true; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureLoadMapIconsCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureLoadMapIconsCommand.java new file mode 100644 index 0000000..5be0cc8 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureLoadMapIconsCommand.java @@ -0,0 +1,65 @@ +package de.fanta.lobby.commands.AdventureCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.adventure.AdventureMap; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.inventory.ItemStack; + +import java.io.File; +import java.io.IOException; +import java.util.logging.Level; + +public class AdventureLoadMapIconsCommand extends SubCommand { + private final Lobby plugin; + + public AdventureLoadMapIconsCommand(Lobby plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + //File adventureCategories = new File("/home/storagebox/Adventure-Maps/"); + File adventureCategories = plugin.getAdventureMapsPath().toFile(); + File[] categories = adventureCategories.listFiles(); + if (categories != null) { + for (File mapFolder : categories) { + ChatUtil.sendNormalMessage(sender, "- " + mapFolder.getName()); + File[] maps = mapFolder.listFiles(); + if (maps != null) { + for (File map : maps) { + ChatUtil.sendDebugMessage(sender, " - " + map.getName()); + AdventureMap adventureMap = plugin.getAdventureMapsConfig().getMap(map.getName()); + if (adventureMap != null) { + File mapConfig = new File(map, "/Challenges/serverconfig.yml"); + ItemStack stack = adventureMap.getItem(); + ChatUtil.sendWarningMessage(sender, " " + adventureMap.getItem().getType()); + try { + YamlConfiguration serverConfig = new YamlConfiguration(); + serverConfig.load(mapConfig); + serverConfig.set("displayItem.item", stack.getType().toString()); + serverConfig.set("displayItem.name", stack.getItemMeta().getDisplayName()); + serverConfig.save(mapConfig); + } catch (IOException | InvalidConfigurationException ex) { + plugin.getLogger().log(Level.SEVERE, "Fehler beim ändern der Config", ex); + ChatUtil.sendErrorMessage(sender, " --- Map " + map.getName() + ": Fehler beim ändern der Config! ---"); + } + } else { + ChatUtil.sendErrorMessage(sender, "Map " + map.getName() + " nicht gefunden!"); + } + } + } + } + } + return true; + } + + @Override + public String getRequiredPermission() { + return "challenge.command.loadmapicons"; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureMapsCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureMapsCommand.java new file mode 100644 index 0000000..adf0650 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureMapsCommand.java @@ -0,0 +1,27 @@ +package de.fanta.lobby.commands.AdventureCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.adventure.ui.CategoryUI; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class AdventureMapsCommand extends SubCommand { + private final Lobby plugin; + + public AdventureMapsCommand(Lobby plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + (new CategoryUI(this.plugin, this.plugin.getCategoriesConfig(), p)).open(); + return true; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureStartEventServerCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureStartEventServerCommand.java new file mode 100644 index 0000000..8424301 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureStartEventServerCommand.java @@ -0,0 +1,33 @@ +package de.fanta.lobby.commands.AdventureCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class AdventureStartEventServerCommand extends SubCommand { + private final Lobby plugin; + + public AdventureStartEventServerCommand(Lobby plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + + plugin.getEventServerPlayerList().add(p.getUniqueId()); + ChatUtil.sendNormalMessage(p, "Der nächste Adventure Server, denn du startest, wird als Event Server gestartet und hat somit mehr Leistung."); + return true; + } + + @Override + public String getRequiredPermission() { + return "challenges.event"; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureTempCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureTempCommand.java new file mode 100644 index 0000000..c97bd0d --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureTempCommand.java @@ -0,0 +1,111 @@ +package de.fanta.lobby.commands.AdventureCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import de.tr7zw.nbtapi.NBTCompound; +import de.tr7zw.nbtapi.NBTFile; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +import java.io.File; +import java.io.IOException; + +public class AdventureTempCommand extends SubCommand { + private final Lobby plugin; + + public AdventureTempCommand(Lobby plugin) { + this.plugin = plugin; + } + + /*public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + FileConfiguration config = AdventureMapsConfig.getConfig(); + FileConfiguration catConfig = CategoriesConfig.getConfig(); + + //File adventureCategories = new File("/home/storagebox/Adventure-Maps/"); + File adventureCategories = plugin.getAdventureMapsPath().toFile(); + File[] categories = adventureCategories.listFiles(); + if (categories != null) { + for (File mapFolder : categories) { + ChatUtil.sendNormalMessage(sender, "- " + mapFolder.getName()); + File[] maps = mapFolder.listFiles(); + if (maps != null) { + for (File map : maps) { + if (config.getKeys(false).contains(map.getName())) { + try { + File mapConfig = new File(map, "/Challenges/serverconfig.yml"); + YamlConfiguration serverConfig = new YamlConfiguration(); + serverConfig.load(mapConfig); + config.set(map.getName() + "." + "version", serverConfig.get("serverversion")); + config.save(AdventureMapsConfig.getFile()); + + List catList = catConfig.getStringList(mapFolder.getName() + "." + "maps"); + if (!catList.contains(map.getName())) { + catList.add(map.getName()); + catConfig.set(mapFolder.getName() + "." + "maps", catList); + catConfig.save(CategoriesConfig.getFile()); + } + + } catch (IOException | InvalidConfigurationException e) { + throw new RuntimeException(e); + } + + } + } + } + } + } + + return true; + }*/ + + + + + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + + File adventureSaves = plugin.getChallengeSavePath().toFile(); + Bukkit.getLogger().info(adventureSaves.getAbsolutePath()); + File[] players = adventureSaves.listFiles(); + if (players != null) { + Bukkit.getLogger().info("Players"); + for (File player : players) { + ChatUtil.sendNormalMessage(sender, "- " + player.getName()); + + File[] maps = player.listFiles(); + if (maps != null) { + for (File map : maps) { + ChatUtil.sendDebugMessage(sender, " - " + map.getName()); + try { + NBTFile file = new NBTFile(new File(map, "/world/level.dat")); + NBTCompound data = file.getCompound("Data"); + NBTCompound dataPacks = data.getCompound("DataPacks"); + + dataPacks.getStringList("Enabled").add("update_1_21"); + dataPacks.getStringList("Disabled").add("bundle"); + dataPacks.getStringList("Disabled").add("trade_rebalance"); + + data.getStringList("enabled_features").add("minecraft:update_1_21"); + data.getStringList("enabled_features").add("minecraft:vanilla"); + + + file.save(); + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + } + } + return true; + } + + @Override + public String getRequiredPermission() { + return "challenge.command.temp"; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureTestMapCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureTestMapCommand.java new file mode 100644 index 0000000..9cb8114 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/AdventureTestMapCommand.java @@ -0,0 +1,112 @@ +package de.fanta.lobby.commands.AdventureCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.Server; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +public class AdventureTestMapCommand extends SubCommand { + private final Lobby plugin; + + public AdventureTestMapCommand(Lobby plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + if (sender.hasPermission("challenges.starttestmap")) { + if (args.hasNext()) { + String category = args.getNext(); + if (args.hasNext()) { + String map = args.getNext(); + if (args.hasNext()) { + String version = args.getNext(); + if (!Server.serverPlayers.containsValue(p.getUniqueId())) { + this.plugin.getPluginConfig().getOnlineAdventureServer().ifPresentOrElse(server -> server.loadNewAdventure(p, category, map, version), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!")); + } else { + ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!"); + } + } else { + ChatUtil.sendWarningMessage(p, "/adventure testmap "); + } + } else { + ChatUtil.sendWarningMessage(p, "/adventure testmap "); + } + } else { + ChatUtil.sendWarningMessage(p, "/adventure testmap "); + } + } else { + ChatUtil.sendErrorMessage(p, "Keine Rechte!"); + } + return true; + } + + @Override + public Collection onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) { + int i = args.remaining(); + Collection completions = new ArrayList<>(); + if (i == 1) { + //File adventureCategories = new File("/home/storagebox/Adventure-Maps/"); + File adventureCategories = plugin.getAdventureMapsPath().toFile(); + File[] files = adventureCategories.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + completions.add(file.getName()); + } + } + return completions; + } + } + + String category = args.hasNext() ? args.getNext() : null; + + if (category != null && i == 2) { + //File adventureMaps = new File("/home/storagebox/Adventure-Maps/" + category + "/"); + File adventureMaps = new File(plugin.getAdventureMapsPath().toFile(), category + "/"); + File[] files = adventureMaps.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + completions.add(file.getName()); + } + } + return completions; + } + } + + if (category != null && i == 3) { + //File serverJars = new File("/home/minecraft/ServerJars"); + File serverJars = plugin.getServerJarsPath().toFile(); + File[] files = serverJars.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + completions.add(file.getName()); + } + } + return completions; + } + } + + + return Collections.emptyList(); + } + + @Override + public String getRequiredPermission() { + return "challenges.starttestmap"; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/ChallengesRemovePlayerServer.java b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/ChallengesRemovePlayerServer.java new file mode 100644 index 0000000..d220023 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/AdventureCommand/ChallengesRemovePlayerServer.java @@ -0,0 +1,55 @@ +package de.fanta.lobby.commands.AdventureCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.Server; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class ChallengesRemovePlayerServer extends SubCommand { + private final Lobby plugin; + public ChallengesRemovePlayerServer(Lobby plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + if (!p.hasPermission("challenges.overrite")) { + ChatUtil.sendErrorMessage(p, "Keine Rechte!"); + return true; + } + if (args.hasNext()) { + String next = args.getNext(); + if (next.equalsIgnoreCase("all")) { + Server.serverPlayers.clear(); + plugin.getPluginConfig().getAdventureServers().removeIf(Server::isOnline); + plugin.getPluginConfig().getChallengeServers().removeIf(Server::isOnline); + ChatUtil.sendNormalMessage(p, "Server liste geleert!"); + } else { + Player serverplayer = Bukkit.getPlayer(next); + if (serverplayer != null) { + if (Server.serverPlayers.containsValue(serverplayer.getUniqueId())) { + Server.serverPlayers.remove(Server.getServerfromPlayer(serverplayer)); + plugin.getPluginConfig().getAdventureServers().removeIf(server -> server.getName().equals(next)); + plugin.getPluginConfig().getChallengeServers().removeIf(server -> server.getName().equals(next)); + ChatUtil.sendNormalMessage(p, "Spieler " + next + " wurde aus der liste entfernt!"); + } else { + ChatUtil.sendNormalMessage(p, "Es ist kein Server von " + next + " Online!"); + } + } else { + ChatUtil.sendErrorMessage(p, "Spieler " + next + " ist nicht Online"); + } + } + return true; + } + ChatUtil.sendWarningMessage(p, "/challenges removeplayerserver {Playername | all}"); + return true; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeClearSavesCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeClearSavesCommand.java new file mode 100644 index 0000000..c66ca98 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeClearSavesCommand.java @@ -0,0 +1,78 @@ +package de.fanta.lobby.commands.ChallengesCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.iani.cubesideutils.StringUtil; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.apache.commons.io.FileUtils; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; +import java.util.Objects; +import java.util.logging.Level; + +public class ChallengeClearSavesCommand extends SubCommand { + + private final Lobby plugin; + + public ChallengeClearSavesCommand(Lobby plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + + ChatUtil.sendNormalMessage(p, "Gespeicherte Challenges die älter als 120 Tage sind werden gelöscht. Dies kann einige Minuten dauern."); + plugin.getScheduler().runAsync(() -> { + File challengeSaveFolder = plugin.getChallengeSavePath().toFile(); //DELETE OLD ChallengeMaps + if (challengeSaveFolder.isDirectory()) { + File[] playerFolders; + playerFolders = challengeSaveFolder.listFiles(); + if (playerFolders != null) { + int deletecounter = 0; + long starttime = System.currentTimeMillis(); + for (File playerFolder : playerFolders) { + File[] saveFolders; + saveFolders = playerFolder.listFiles(); + if (saveFolders != null) { + try { + for (File map : saveFolders) { + BasicFileAttributes attr = Files.readAttributes(map.toPath(), BasicFileAttributes.class); + FileTime fileTime = attr.creationTime(); + if (10368000000L + fileTime.toMillis() <= System.currentTimeMillis()) { //120 Tage + FileUtils.deleteDirectory(map); + deletecounter++; + ChatUtil.sendNormalMessage(p, "Welt " + playerFolder.getName() + "/" + map.getName() + " gelöscht. (" + deletecounter + ")"); + } + } + if (Objects.requireNonNull(playerFolder.listFiles()).length == 0) { + FileUtils.deleteDirectory(playerFolder); + } + } catch (IOException ex) { + Bukkit.getLogger().log(Level.SEVERE, "Fehler beim löschen einer Map", ex); + } + } + } + ChatUtil.sendNormalMessage(p, "Es wurden: " + deletecounter + " maps in " + StringUtil.formatTimespan(System.currentTimeMillis() - starttime) + " gelöscht"); + } + } + }); + return true; + } + + @Override + public String getRequiredPermission() { + return "challenges.clearsaves"; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeListUserStatsCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeListUserStatsCommand.java new file mode 100644 index 0000000..ffbb6e9 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeListUserStatsCommand.java @@ -0,0 +1,116 @@ +package de.fanta.lobby.commands.ChallengesCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.utils.DurationCommandUtil; +import de.iani.cubesidestats.api.Ordering; +import de.iani.cubesidestats.api.PositionAlgorithm; +import de.iani.cubesidestats.api.StatisticKey; +import de.iani.cubesidestats.api.TimeFrame; +import de.iani.cubesideutils.StringUtil; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import de.iani.playerUUIDCache.CachedPlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; + +public class ChallengeListUserStatsCommand extends SubCommand { + private final Lobby plugin; + + public ChallengeListUserStatsCommand(Lobby plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + + if (!args.hasNext()) { + return false; + } + + String statisticKeyString = args.getNext().toLowerCase(); + if (!plugin.getCubesideStatistics().hasStatisticKey(statisticKeyString)) { + ChatUtil.sendErrorMessage(p, "StatsKey " + statisticKeyString + " nicht gefunden"); + return true; + } + + StatisticKey statisticKey; + try { + statisticKey = plugin.getCubesideStatistics().getStatisticKey(statisticKeyString, false); + } catch (IllegalArgumentException ex) { + ChatUtil.sendErrorMessage(p, "StatsKey " + statisticKeyString + " konnte nicht geladen werden!"); + return true; + } + + if (!args.hasNext()) { + return false; + } + + String timeFrameString = args.getNext(); + TimeFrame timeFrame; + try { + timeFrame = TimeFrame.valueOf(timeFrameString); + } catch (IllegalArgumentException ex) { + ChatUtil.sendErrorMessage(p, "Diesen TimeFrame gibt es nicht! (DAY, MONTH, ALL_TIME)"); + return true; + } + + + long duration = DurationCommandUtil.parseDuration(sender, args, false); + if (duration == 0) { + return true; + } + + statisticKey.getTop(0, 50, Ordering.ASCENDING, timeFrame, PositionAlgorithm.DO_NOT_SKIP_POSITIONS_AFTER_DUPLICATES, playerWithScores -> playerWithScores.forEach(playerWithScore -> { + if (playerWithScore.getScore() <= duration) { + CachedPlayer cachedPlayer = plugin.getPlayerUUIDCache().getPlayer(playerWithScore.getPlayer().getOwner()); + if (cachedPlayer != null) { + ChatUtil.sendNormalMessage(p, ChatUtil.ORANGE + "Position: " + playerWithScore.getPosition() + ChatUtil.BLUE + " Zeit: " + StringUtil.formatTimespan((playerWithScore.getScore() / 1000) * 1000, " Tag, ", ":", "", "", "", ":", false, true) + ChatUtil.GREEN + " " +cachedPlayer.getName()); + } + + } + })); + + + return true; + } + + @Override + public String getRequiredPermission() { + return "challenges.stats.listusers"; + } + + @Override + public String getUsage() { + return " "; + } + + @Override + public ArrayList onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) { + int i = args.remaining(); + if (i == 1) { + ArrayList li = new ArrayList<>(); + plugin.getCubesideStatistics().getAllStatisticKeys().forEach(statisticKey -> { + if (statisticKey.getName().startsWith("challenge.speedruns")) { + li.add(statisticKey.getName()); + } + }); + return li; + } + + if (i == 2) { + ArrayList li = new ArrayList<>(); + for (TimeFrame timeFrame : TimeFrame.values()) { + li.add(timeFrame.name()); + } + return li; + } + return new ArrayList<>(); + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeLoadCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeLoadCommand.java new file mode 100644 index 0000000..570a587 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeLoadCommand.java @@ -0,0 +1,45 @@ +package de.fanta.lobby.commands.ChallengesCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.loadgui.ChallengeLoadGUI; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import de.iani.playerUUIDCache.CachedPlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class ChallengeLoadCommand extends SubCommand { + private final Lobby plugin; + + public ChallengeLoadCommand(Lobby plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + + CachedPlayer savePlayer; + if (args.hasNext()) { + if (!p.hasPermission("challenges.load.admin")) { + ChatUtil.sendErrorMessage(p, "Keine Rechte! (Du kannst nur eigene maps Laden)"); + return true; + } + String savePlayerName = args.getNext(); + savePlayer = plugin.getPlayerUUIDCache().getPlayer(savePlayerName); + } else { + savePlayer = plugin.getPlayerUUIDCache().getPlayer(p.getUniqueId()); + } + + if (savePlayer != null) { + new ChallengeLoadGUI(p, savePlayer).open(); + } else { + ChatUtil.sendErrorMessage(p, "Spieler nicht gefunden!"); + } + return true; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeSetStatsCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeSetStatsCommand.java new file mode 100644 index 0000000..3fc9165 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengeSetStatsCommand.java @@ -0,0 +1,96 @@ +package de.fanta.lobby.commands.ChallengesCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.iani.cubesidestats.api.StatisticKey; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import de.iani.playerUUIDCache.CachedPlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +public class ChallengeSetStatsCommand extends SubCommand { + private final Lobby plugin; + + public ChallengeSetStatsCommand(Lobby plugin) { + this.plugin = plugin; + } + + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player player)) { + ChatUtil.sendErrorMessage(sender, "You are not a Player :>"); + return true; + } + + if (args.hasNext()) { + String playerString = args.getNext(); + CachedPlayer statsPlayer = plugin.getPlayerUUIDCache().getPlayer(playerString); + if (statsPlayer != null) { + if (args.hasNext()) { + String statsKeyString = args.getNext(); + StatisticKey statisticKey = plugin.getCubesideStatistics().getStatisticKey(statsKeyString, false); + if (statisticKey != null) { + if (args.hasNext()) { + int score; + try { + score = Integer.parseInt(args.getNext()); + } catch (NumberFormatException ex) { + ChatUtil.sendErrorMessage(player, "/challenge setstats "); + return true; + } + if (score > 0) { + plugin.getStatistics().setScore(statsPlayer.getUUID(), statisticKey, score); + ChatUtil.sendNormalMessage(player, "Statistik " + ChatUtil.BLUE + statisticKey.getName() + ChatUtil.GREEN + " von " + ChatUtil.BLUE + statsPlayer.getName() + ChatUtil.GREEN + " wurde auf " + ChatUtil.BLUE + score + ChatUtil.GREEN + " gesetzt!"); + } else { + plugin.getStatistics().deleteScore(statsPlayer.getUUID(), statisticKey); + ChatUtil.sendNormalMessage(player, "Statistik " + ChatUtil.BLUE + statisticKey.getName() + ChatUtil.GREEN + " von " + ChatUtil.BLUE + statsPlayer.getName() + ChatUtil.GREEN + " wurde gelöscht!"); + } + } else { + ChatUtil.sendErrorMessage(player, "/challenge setstats "); + return true; + } + } else { + ChatUtil.sendErrorMessage(player, "StatisticKey nicht gefunden!"); + return true; + } + } else { + ChatUtil.sendErrorMessage(player, "/challenge setstats "); + return true; + } + } else { + ChatUtil.sendErrorMessage(player, ChatUtil.BLUE + playerString + ChatUtil.RED + " nicht gefunden!"); + return true; + } + } else { + ChatUtil.sendErrorMessage(player, "/challenge setstats "); + return true; + } + + + return true; + } + + @Override + public Collection onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) { + if (args.remaining() == 2) { + Collection keyList = new ArrayList<>(); + for (StatisticKey statisticKey : plugin.getCubesideStatistics().getAllStatisticKeys()) { + if (statisticKey.getName().startsWith("challenge")) { + keyList.add(statisticKey.getName()); + } + } + return keyList; + } + return Collections.emptyList(); + } + + @Override + public String getRequiredPermission() { + return "challenges.stats.edit"; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengesStatsCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengesStatsCommand.java new file mode 100644 index 0000000..1cc9dfd --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/ChallengesCommand/ChallengesStatsCommand.java @@ -0,0 +1,116 @@ +package de.fanta.lobby.commands.ChallengesCommand; + +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.utils.PlayerStatisticsData; +import de.fanta.lobby.utils.Statistics; +import de.iani.cubesideutils.StringUtil; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.function.Consumer; + +public class ChallengesStatsCommand extends SubCommand { + + private final Statistics statistics; + + public ChallengesStatsCommand(Statistics statistics) { + this.statistics = statistics; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + String statTypeString = args.getNext("SOLO").toUpperCase(); + Statistics.StatType statType; + + try { + statType = Statistics.StatType.valueOf(statTypeString); + } catch (IllegalArgumentException ex) { + statType = Statistics.StatType.SOLO; + } + + String playerName = args.getNext(null); + + Statistics.StatType finalStatType = statType; + Consumer callback = data -> { + if (data == null) { + ChatUtil.sendErrorMessage(sender, "Für Spieler '" + playerName + "' existieren keine Daten."); + return; + } + if (playerName == null) { + ChatUtil.sendNormalMessage(sender, "Deine Speedrun-Statistik " + "(" + finalStatType.getPrefix() + ")"); + } else { + ChatUtil.sendNormalMessage(sender, "Speedrun-Statistik von " + data.getPlayerName() + " (" + finalStatType.getPrefix() + ")"); + } + + + int bestTimeThisMonth = data.getBestTimeMonth(); + if (bestTimeThisMonth < 0) { + ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Beste Zeit: " + ChatUtil.GREEN + formatTime(data.getBestTime())); + } else { + ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Beste Zeit: " + ChatUtil.GREEN + (data.getBestTime() == 0 ? "--:--" : formatTime(data.getBestTime())) + " (Dieser Monat: " + (bestTimeThisMonth == 0 ? "--:--" : formatTime(bestTimeThisMonth)) + ")"); + } + + int runsPlayerThisMonth = data.getRunsPlayedMonth(); + if (bestTimeThisMonth < 0) { + ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Speedruns gespielt: " + ChatUtil.GREEN + data.getRunsPlayed()); + } else { + ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Speedruns gespielt: " + ChatUtil.GREEN + data.getRunsPlayed() + " (Dieser Monat: " + runsPlayerThisMonth + ")"); + } + + int runsWonThisMonth = data.getRunsWonMonth(); + if (bestTimeThisMonth < 0) { + ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Speedruns gewonnen: " + ChatUtil.GREEN + data.getRunsWon()); + } else { + ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Speedruns gewonnen: " + ChatUtil.GREEN + data.getRunsWon() + " (Dieser Monat: " + runsWonThisMonth + ")"); + } + + int positionThisMonth = data.getPositionMonth(); + if (bestTimeThisMonth < 0) { + ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Position: " + ChatUtil.GREEN + data.getPosition()); + } else { + ChatUtil.sendNormalMessage(sender, ChatUtil.ORANGE + " Position: " + ChatUtil.GREEN + data.getPosition() + " (Dieser Monat: " + positionThisMonth + ")"); + } + }; + if (playerName == null) { + if (sender instanceof Player player) { + statistics.getDataForPlayer(player, statType, callback); + } else { + sender.sendMessage(ChatColor.GREEN + "Für die Konsole existieren keine Daten."); + } + } else { + try { + int pos = Integer.parseInt(playerName); + statistics.getDataForPositionIfExists(pos, statType, callback); + } catch (NumberFormatException e) { + statistics.getDataForPlayerIfExists(playerName, statType, callback); + } + } + return true; + } + + @Override + public ArrayList onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) { + int i = args.remaining(); + if (i == 1) { + ArrayList li = new ArrayList<>(); + for (Statistics.StatType statType : Statistics.StatType.values()) { + li.add(statType.getPrefix()); + } + return li; + } + return new ArrayList<>(); + } + + public String formatTime(long time) { + String formattime = StringUtil.formatTimespan((time / 1000) * 1000, "1 Tage, ", ":", "", "", "", ":", false, true); + if (formattime.startsWith("1 Tage")) { + return StringUtil.formatTimespan((time / 1000) * 1000, " Tag, ", ":", "", "", "", ":", false, true); + } + return formattime; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/AddEntityCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/AddEntityCommand.java new file mode 100644 index 0000000..22ad8b2 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/AddEntityCommand.java @@ -0,0 +1,77 @@ +package de.fanta.lobby.commands.PiglinCommand; + +import de.cubeside.connection.GlobalServer; +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.iani.cubesideutils.StringUtil; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collection; +import java.util.Collections; +import java.util.stream.Collectors; + +public class AddEntityCommand extends SubCommand { + + private final Lobby plugin; + + public AddEntityCommand(Lobby plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + + if (!sender.hasPermission("challenges.spawn.teleporter")) { + ChatUtil.sendErrorMessage(sender, "Keine Berechtigung!"); + return true; + } + + if (!args.hasNext()) { + return false; + } + String serverName = args.getNext(); + + if (!args.hasNext()) { + return false; + } + String locationName = args.getNext(); + + if (plugin.getGlobalDataHelper().getServer(serverName) != null) { + String serverDisplayName = StringUtil.convertColors(args.getAll(serverName)); + + plugin.spawnPiglin(((Player) sender).getLocation(), serverName, null, locationName, serverDisplayName); + ChatUtil.sendNormalMessage(sender, "Piglin hinzugefügt! *grunz*"); + } else { + ChatUtil.sendErrorMessage(sender, "Server nicht gefunden!"); + } + return true; + } + + @Override + public Collection onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) { + args.next(); + if (!args.hasNext()) { + return plugin.getGlobalDataHelper().getServers().stream().map(GlobalServer::getName).collect(Collectors.toList()); + } + + return Collections.emptyList(); + } + + @Override + public String getUsage() { + return " [Anzeigename]"; + } + + @Override + public String getRequiredPermission() { + return "challenges.spawn.teleporter"; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/Entitytphere.java b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/Entitytphere.java new file mode 100644 index 0000000..bd7936f --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/Entitytphere.java @@ -0,0 +1,68 @@ +package de.fanta.lobby.commands.PiglinCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Piglin; +import org.bukkit.entity.Player; + +import java.util.Collection; +import java.util.Collections; + +public class Entitytphere extends SubCommand { + + private final Lobby plugin; + + public Entitytphere(Lobby plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + + if (!sender.hasPermission("challenges.spawn.teleporter")) { + ChatUtil.sendErrorMessage(sender, "Keine Berechtigung!"); + return true; + } + + if (args.hasNext()) { + String serverName = args.getNext(); + Piglin piglin = plugin.getPiglinForServerName(serverName); + if (piglin != null) { + piglin.teleport(p.getLocation()); + ChatUtil.sendNormalMessage(sender, "Piglin wurde zu dir Teleportiert."); + } else { + ChatUtil.sendErrorMessage(sender, "Kein Piglin für diesen Server gefunden!"); + } + return true; + } + return false; + } + + @Override + public Collection onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) { + args.next(); + if (!args.hasNext()) { + return plugin.getEntityData().keySet(); + } + + return Collections.emptyList(); + } + + @Override + public String getUsage() { + return ""; + } + + @Override + public String getRequiredPermission() { + return "challenges.spawn.teleporter"; + } +} \ No newline at end of file diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/ListPiglinCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/ListPiglinCommand.java new file mode 100644 index 0000000..01140a9 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/ListPiglinCommand.java @@ -0,0 +1,35 @@ +package de.fanta.lobby.commands.PiglinCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class ListPiglinCommand extends SubCommand { + + private final Lobby plugin; + + public ListPiglinCommand(Lobby plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player p)) { + ChatUtil.sendErrorMessage(sender, "Du musst ein Spieler sein!"); + return true; + } + + if (!sender.hasPermission("challenges.spawn.teleporter")) { + ChatUtil.sendErrorMessage(sender, "Keine Berechtigung!"); + return true; + } + ChatUtil.sendNormalMessage(p, "-------------------------------"); + plugin.getEntityData().keySet().forEach(server -> ChatUtil.sendNormalMessage(p, plugin.getPiglinForServerName(server).getName() + ": " + server)); + ChatUtil.sendNormalMessage(p, "-------------------------------"); + return true; + } +} \ No newline at end of file diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/RemoveEntityCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/RemoveEntityCommand.java new file mode 100644 index 0000000..d5b316b --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/RemoveEntityCommand.java @@ -0,0 +1,62 @@ +package de.fanta.lobby.commands.PiglinCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Piglin; + +import java.util.Collection; +import java.util.Collections; + +public class RemoveEntityCommand extends SubCommand { + + private final Lobby plugin; + + public RemoveEntityCommand(Lobby plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!sender.hasPermission("challenges.spawn.teleporter")) { + ChatUtil.sendErrorMessage(sender, "Keine Berechtigung!"); + return true; + } + + if (args.hasNext()) { + String serverName = args.getNext(); + Piglin piglin = plugin.getPiglinForServerName(serverName); + if (piglin != null) { + plugin.despawnPiglin(piglin.getUniqueId(), serverName); + ChatUtil.sendNormalMessage(sender, "Piglin entfernt."); + } else { + ChatUtil.sendErrorMessage(sender, "Kein Piglin für diesen Server gefunden!"); + } + return true; + } + return false; + } + + @Override + public Collection onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) { + args.next(); + if (!args.hasNext()) { + return plugin.getEntityData().keySet(); + } + + return Collections.emptyList(); + } + + @Override + public String getUsage() { + return ""; + } + + @Override + public String getRequiredPermission() { + return "challenges.spawn.teleporter"; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/SetEntitySpawnLocationCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/SetEntitySpawnLocationCommand.java new file mode 100644 index 0000000..845f148 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/SetEntitySpawnLocationCommand.java @@ -0,0 +1,118 @@ +package de.fanta.lobby.commands.PiglinCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.Config; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class SetEntitySpawnLocationCommand extends SubCommand { + + private final Lobby plugin; + + public SetEntitySpawnLocationCommand(Lobby plugin) { + this.plugin = plugin; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!(sender instanceof Player player)) { + ChatUtil.sendErrorMessage(sender, "You are not a Player :>"); + return true; + } + + if (!sender.hasPermission("challenges.spawn.teleporter")) { + ChatUtil.sendErrorMessage(sender, "Keine Berechtigung!"); + return true; + } + + if (args.hasNext()) { + String serverType = args.getNext(); + if (args.hasNext()) { + String serverName = args.getNext(); + if (serverType.equalsIgnoreCase("challenge")) { + if (setServerLocation(serverType, serverName, player.getLocation())) { + ChatUtil.sendNormalMessage(sender, "Neue location für " + serverName + " gesetzt!"); + } else { + ChatUtil.sendErrorMessage(sender, "Der server steht nicht in der Config."); + return true; + } + } else if (serverType.equalsIgnoreCase("adventure")) { + if (setServerLocation(serverType, serverName, player.getLocation())) { + ChatUtil.sendNormalMessage(sender, "Neue location für " + serverName + " gesetzt!"); + } else { + ChatUtil.sendErrorMessage(sender, "Der server steht nicht in der Config."); + return true; + } + } else { + ChatUtil.sendErrorMessage(sender, "Der Servertyp muss Challenge oder Adventure sein."); + return true; + } + } else { + ChatUtil.sendErrorMessage(sender, "/piglin setentityspawnlocation "); + return true; + } + } else { + ChatUtil.sendErrorMessage(sender, "/piglin setentityspawnlocation "); + return true; + } + return true; + } + + @Override + public Collection onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) { + String ServerType = args.getNext(); + if (!args.hasNext()) { + return List.of("adventure", "challenge"); + } + args.next(); + if (!args.hasNext()) { + if (ServerType.equalsIgnoreCase("adventure")) { + return plugin.getConfig().getConfigurationSection(ServerType.toLowerCase()).getKeys(false); + } else if (ServerType.equalsIgnoreCase("challenge")) { + return plugin.getConfig().getConfigurationSection(ServerType.toLowerCase()).getKeys(false); + } + } + return Collections.emptyList(); + } + + @Override + public String getUsage() { + return " "; + } + + @Override + public String getRequiredPermission() { + return "challenges.spawn.teleporter"; + } + + public boolean setServerLocation(String ServerType, String ServerName, Location location) { + if (plugin.getConfig().getString(ServerType + "." + ServerName) != null) { + World world = location.getWorld(); + double x = location.getX(); + double y = location.getY(); + double z = location.getZ(); + double yaw = location.getYaw(); + plugin.getConfig().set(ServerType.toLowerCase() + "." + ServerName.toLowerCase() + ".location" + ".world", world.getName()); + plugin.getConfig().set(ServerType.toLowerCase() + "." + ServerName.toLowerCase() + ".location" + ".x", x); + plugin.getConfig().set(ServerType.toLowerCase() + "." + ServerName.toLowerCase() + ".location" + ".y", y); + plugin.getConfig().set(ServerType.toLowerCase() + "." + ServerName.toLowerCase() + ".location" + ".z", z); + plugin.getConfig().set(ServerType.toLowerCase() + "." + ServerName.toLowerCase() + ".location" + ".yaw", yaw); + plugin.saveConfig(); + Config.reloadConfig(); + return true; + } else { + return false; + } + + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/ToggleArenaCommand.java b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/ToggleArenaCommand.java new file mode 100644 index 0000000..ec8bb6d --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/commands/PiglinCommand/ToggleArenaCommand.java @@ -0,0 +1,58 @@ +package de.fanta.lobby.commands.PiglinCommand; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.JoinEntityData; +import de.fanta.lobby.JoinEntityData.ServerStatus; +import de.iani.cubesideutils.bukkit.commands.SubCommand; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +import java.util.Collection; +import java.util.Collections; + +public class ToggleArenaCommand extends SubCommand { + + private final Lobby plugin; + private final boolean enable; + + public ToggleArenaCommand(Lobby plugin, boolean enable) { + this.plugin = plugin; + this.enable = enable; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String alias, String commandString, ArgsParser args) { + if (!sender.hasPermission("challenges.event")) { + ChatUtil.sendErrorMessage(sender, "Keine Berechtigung"); + return true; + } + + if (!args.hasNext()) { + return false; + } + String serverName = args.getNext(); + JoinEntityData data = plugin.getEntityData(serverName); + if (data == null) { + ChatUtil.sendErrorMessage(sender, "Server nicht gefunden."); + return true; + } + if (data.getServerStatus() == ServerStatus.RUNNING) { + ChatUtil.sendErrorMessage(sender, "Arena disablen nicht möglich, da gerade eine Runde läuft."); + return true; + } + + plugin.updateServerStatus(serverName, enable); + return true; + } + + @Override + public Collection onTabComplete(CommandSender sender, Command command, String alias, ArgsParser args) { + args.next(); + if (!args.hasNext()) { + return plugin.getEntityData().keySet(); + } + return Collections.emptyList(); + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/listeners/ChallengesEventListener.java b/Lobby/src/main/java/de/fanta/lobby/listeners/ChallengesEventListener.java new file mode 100644 index 0000000..437cfb4 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/listeners/ChallengesEventListener.java @@ -0,0 +1,37 @@ +package de.fanta.lobby.listeners; + +import de.fanta.challenge.events.EventStatusChangedEvent; +import de.fanta.challenge.events.PlayerCountChangedEvent; +import de.fanta.challenge.events.ServerStatusChangedEvent; +import de.fanta.lobby.Lobby; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class ChallengesEventListener implements Listener { + + private final Lobby plugin; + + public ChallengesEventListener(Lobby plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onTimerChanged(de.fanta.challenge.events.TimerChangedEvent event) { + plugin.getGlobalDataHelper().sendTimerUpdate(event.isRunning()); + } + + @EventHandler + public void onEventStatusChanged(EventStatusChangedEvent e) { + plugin.getGlobalDataHelper().sendEventUpdate(e.isEvent()); + } + + @EventHandler + public void onServerStatusChanged(ServerStatusChangedEvent event) { + plugin.getGlobalDataHelper().sendServerStatusUpdate(event.isOnline()); + } + + @EventHandler + public void onPlayerCountChanged(PlayerCountChangedEvent event) { + plugin.getGlobalDataHelper().sendPlayerCountUpdate(event.getCount()); + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/listeners/EntityListener.java b/Lobby/src/main/java/de/fanta/lobby/listeners/EntityListener.java new file mode 100644 index 0000000..c1f3b8f --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/listeners/EntityListener.java @@ -0,0 +1,111 @@ +package de.fanta.lobby.listeners; + +import com.viaversion.viaversion.api.Via; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.JoinEntityData; +import de.speedy64.globalport.GlobalApi; +import io.papermc.paper.event.entity.EntityMoveEvent; +import org.bukkit.GameMode; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.inventory.EquipmentSlot; + +import java.util.UUID; + +public class EntityListener implements Listener { + + private final Lobby plugin; + + public EntityListener(Lobby plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onEntityInteract(PlayerInteractEntityEvent event) { + if (!plugin.isJoinEntity(event.getRightClicked()) || event.getHand() != EquipmentSlot.HAND) { + return; + } + + if (event.getPlayer().getGameMode() != GameMode.CREATIVE || !event.getPlayer().isSneaking()) { + event.setCancelled(true); + onPlayerClickEntity(event.getPlayer(), event.getRightClicked().getUniqueId()); + } + } + + @EventHandler(ignoreCancelled = true) + public void onEntityDamage(EntityDamageEvent event) { + if (plugin.isJoinEntity(event.getEntity())) { + event.setCancelled(true); + } + } + + @EventHandler + public void onEntityDamageByPlayer(EntityDamageByEntityEvent event) { + if (!plugin.isJoinEntity(event.getEntity())) { + return; + } + + event.setCancelled(true); + if (event.getDamager() instanceof Player) { + onPlayerClickEntity((Player) event.getDamager(), event.getEntity().getUniqueId()); + } + } + + @EventHandler + public void onEntityMove(EntityMoveEvent e) { + if (plugin.isJoinEntity(e.getEntity())) { + e.setCancelled(true); + } + } + + public void onPlayerClickEntity(Player player, UUID clicked) { + if (player == null || clicked == null) { + return; + } + String serverName = plugin.getServerNameForEntity(clicked); + if (serverName == null) { + return; + } + JoinEntityData data = plugin.getEntityData(serverName); + if (data == null) { + return; + } + switch (data.getServerStatus()) { + case ONLINE: + if (data.getPlayerCount() < data.getMaxPlayers()) { + if (data.getPlayerCount() == 0 && !player.hasPermission("Challenges.editor")) { + ChatUtil.sendWarningMessage(player, "Der erste Spieler muss VIP haben!"); + ChatUtil.sendWarningMessage(player, "Um VIP zu bekommen musst du im Freebuild (/tt) /voteshop eingeben!"); + } else { + int playerVersion = Via.getAPI().getPlayerVersion(player.getUniqueId()); + int mapProtocolVersion = data.getMapVersion(); + if (playerVersion >= mapProtocolVersion) { + GlobalApi.portOnlinePlayerToLocation(player.getName(), data.getGlobalPortLocationName()); + } else { + ChatUtil.sendErrorMessage(player, "Du brauchst mindestens die Version " + ChatUtil.BLUE + ProtocolVersion.getProtocol(data.getMapVersion()).getName() + ChatUtil.RED + " um die Map zu betreten!"); + } + } + } else { + ChatUtil.sendErrorMessage(player, "Der Server ist bereits voll!"); + } + break; + case OFFLINE: + ChatUtil.sendErrorMessage(player, "Der Server wird gerade resettet."); + break; + case RUNNING: + if (data.getEventStatus() == JoinEntityData.EventStatus.EVENT) { + GlobalApi.portOnlinePlayerToLocation(player.getName(), data.getGlobalPortLocationName()); + } else { + ChatUtil.sendWarningMessage(player, "Der Server ist bereits gestartet!!"); + } + break; + } + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/listeners/PlayerListener.java b/Lobby/src/main/java/de/fanta/lobby/listeners/PlayerListener.java new file mode 100644 index 0000000..fe0458b --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/listeners/PlayerListener.java @@ -0,0 +1,142 @@ +package de.fanta.lobby.listeners; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.iani.cubesideutils.bukkit.plugin.CubesideUtilsBukkit; +import de.iani.cubesideutils.bukkit.plugin.api.UtilsApiBukkit; +import de.iani.cubesideutils.plugin.api.PlayerData; +import de.speedy64.globalport.GlobalApi; +import de.speedy64.globalport.data.GPLocation; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerSwapHandItemsEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; +import org.bukkit.util.Vector; +import org.spigotmc.event.player.PlayerSpawnLocationEvent; + +import java.util.Collection; + +public class PlayerListener implements Listener { + + private final Lobby plugin; + private final NamespacedKey namespacedKey; + + public PlayerListener(Lobby plugin) { + this.plugin = plugin; + this.namespacedKey = new NamespacedKey(plugin, "backitem"); + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + + Collection nearbyEntities = player.getLocation().getNearbyEntities(1.0, 1.0, 1.0); + for (Entity entity : nearbyEntities) { + if (plugin.isJoinEntity(entity)) { + Vector direction = player.getLocation().getDirection(); + player.setVelocity(direction.multiply(-0.75).setY(0.5)); + } + } + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent e) { + ItemStack itemStack = new ItemStack(Material.LIME_BED, 1); + ItemMeta meta = itemStack.getItemMeta(); + meta.setDisplayName(ChatUtil.GREEN + "Zurück zum Spawn"); + meta.getPersistentDataContainer().set(namespacedKey, PersistentDataType.STRING, "backitem"); + itemStack.setItemMeta(meta); + e.getPlayer().getInventory().setItem(8, itemStack); + } + + @EventHandler + public void onPlayerSpawn(PlayerSpawnLocationEvent e) { + plugin.getScheduler().runDelayedOnEntity(e.getPlayer(), () -> { + PlayerData data = UtilsApiBukkit.getInstance().getPlayerData(e.getPlayer()); + if (data.getLastJoin() + (10 * 1000) > System.currentTimeMillis()) { + String hosteName = CubesideUtilsBukkit.getInstance().getPlayerData(e.getPlayer()).getHostName().toLowerCase(); + if (hosteName.startsWith("challenge")) { + Location location = GPLocation.getLocation("challenge").getLocation(); + e.getPlayer().teleportAsync(location); + } else if (hosteName.startsWith("adventure")) { + Location location = GPLocation.getLocation("adventure").getLocation(); + e.getPlayer().teleportAsync(location); + } + } + }, 1L); + } + + @EventHandler + public void onItemClick(InventoryClickEvent e) { + ItemStack stack = e.getCurrentItem(); + if (stack != null) { + ItemMeta meta = stack.getItemMeta(); + if (meta != null && meta.getPersistentDataContainer().has(namespacedKey) && e.getWhoClicked().getGameMode() != GameMode.CREATIVE) { + e.setCancelled(true); + } + } + + if (e.getClick() == ClickType.NUMBER_KEY) { + int slot = e.getHotbarButton(); + if (slot >= 0 && slot < 9) { + if (!e.getWhoClicked().getInventory().equals(e.getInventory())) { + ItemStack swap = e.getWhoClicked().getInventory().getItem(slot); + if (swap != null) { + ItemMeta swapItemMeta = swap.getItemMeta(); + if (swapItemMeta != null && swapItemMeta.getPersistentDataContainer().has(namespacedKey) && e.getWhoClicked().getGameMode() != GameMode.CREATIVE) { + e.setCancelled(true); + } + } + } + } + } + } + + @EventHandler + public void onItemDrop(PlayerDropItemEvent e) { + ItemStack stack = e.getItemDrop().getItemStack(); + ItemMeta meta = stack.getItemMeta(); + if (meta != null && meta.getPersistentDataContainer().has(namespacedKey) && e.getPlayer().getGameMode() != GameMode.CREATIVE) { + e.setCancelled(true); + } + } + + @EventHandler + public void onItemSwitchHand(PlayerSwapHandItemsEvent e) { + ItemStack stack = e.getOffHandItem(); + if (stack != null) { + ItemMeta meta = stack.getItemMeta(); + if (meta != null && meta.getPersistentDataContainer().has(namespacedKey) && e.getPlayer().getGameMode() != GameMode.CREATIVE) { + e.setCancelled(true); + } + } + } + + @EventHandler + public void onInteractItem(PlayerInteractEvent e) { + if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) { + ItemStack stack = e.getItem(); + if (stack != null) { + ItemMeta meta = stack.getItemMeta(); + if (meta != null && meta.getPersistentDataContainer().has(namespacedKey)) { + GlobalApi.portOnlinePlayerToLocation(e.getPlayer().getName(), "spawn"); + } + } + } + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/loadgui/AdventureLoadGUI.java b/Lobby/src/main/java/de/fanta/lobby/loadgui/AdventureLoadGUI.java new file mode 100644 index 0000000..341d6d7 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/loadgui/AdventureLoadGUI.java @@ -0,0 +1,222 @@ +package de.fanta.lobby.loadgui; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.SaveSlot; +import de.fanta.lobby.Server; +import de.fanta.lobby.utils.ItemUtil; +import de.iani.cubesideutils.StringUtil; +import de.iani.cubesideutils.bukkit.inventory.AbstractWindow; +import de.iani.playerUUIDCache.CachedPlayer; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; +import java.util.logging.Level; + +public class AdventureLoadGUI extends AbstractWindow { + + private static final Lobby plugin = Lobby.getPlugin(); + + private static final int SAVE_1_INDEX = 1; + private static final int SAVE_2_INDEX = 3; + private static final int SAVE_3_INDEX = 5; + private static final int SAVE_AUTO_INDEX = 7; + private static final int WINDOW_SIZE = 9; + + private static final HashMap savePlayerList = new HashMap<>(); + + public AdventureLoadGUI(Player player, CachedPlayer savePlayer) { + super(player, Bukkit.createInventory(player, WINDOW_SIZE, Lobby.ADVENTUREGUIPREFIX + " >> Map laden")); + savePlayerList.put(player.getUniqueId(), savePlayer.getUniqueId()); + } + + @Override + protected void rebuildInventory() { + Player player = getPlayer(); + UUID savePlayerID = savePlayerList.get(player.getUniqueId()); + /*File adventureSave1 = new File("/home/minecraft/Adventure-saves/" + savePlayerID + "/1"); + File adventureSave2 = new File("/home/minecraft/Adventure-saves/" + savePlayerID + "/2"); + File adventureSave3 = new File("/home/minecraft/Adventure-saves/" + savePlayerID + "/3"); + File adventureSaveAuto = new File("/home/minecraft/Adventure-saves/" + savePlayerID + "/autosave");*/ + + File adventureSave1 = new File(plugin.getAdventureSavePath().toFile(), savePlayerID + "/1"); + File adventureSave2 = new File(plugin.getAdventureSavePath().toFile(), savePlayerID + "/2"); + File adventureSave3 = new File(plugin.getAdventureSavePath().toFile(), savePlayerID + "/3"); + File adventureSaveAuto = new File(plugin.getAdventureSavePath().toFile(), savePlayerID + "/autosave"); + + for (int i = 0; i < WINDOW_SIZE; i++) { + ItemStack item; + switch (i) { + case SAVE_1_INDEX -> item = getDisplayItem(player, SaveSlot.SLOT_1, adventureSave1); + case SAVE_2_INDEX -> item = getDisplayItem(player, SaveSlot.SLOT_2, adventureSave2); + case SAVE_3_INDEX -> item = getDisplayItem(player, SaveSlot.SLOT_3, adventureSave3); + case SAVE_AUTO_INDEX -> item = getDisplayItem(player, SaveSlot.SLOT_AUTO, adventureSaveAuto); + default -> item = ItemUtil.EMPTY_ICON; + } + this.getInventory().setItem(i, item); + } + } + + @Override + public void onItemClicked(InventoryClickEvent event) { + if (!mayAffectThisInventory(event)) { + return; + } + + event.setCancelled(true); + if (!getInventory().equals(event.getClickedInventory())) { + return; + } + + Player p = getPlayer(); + UUID savePlayerID = savePlayerList.get(p.getUniqueId()); + + /*File adventureSave1 = new File("/home/minecraft/Adventure-saves/" + savePlayerID + "/1"); + File adventureSave2 = new File("/home/minecraft/Adventure-saves/" + savePlayerID + "/2"); + File adventureSave3 = new File("/home/minecraft/Adventure-saves/" + savePlayerID + "/3"); + File adventureSaveAuto = new File("/home/minecraft/Adventure-saves/" + savePlayerID + "/autosave");*/ + + File adventureSave1 = new File(plugin.getAdventureSavePath().toFile(), savePlayerID + "/1"); + File adventureSave2 = new File(plugin.getAdventureSavePath().toFile(), savePlayerID + "/2"); + File adventureSave3 = new File(plugin.getAdventureSavePath().toFile(), savePlayerID + "/3"); + File adventureSaveAuto = new File(plugin.getAdventureSavePath().toFile(), savePlayerID + "/autosave"); + + + int slot = event.getSlot(); + switch (slot) { + case SAVE_1_INDEX -> { + if (!p.hasPermission("challenge.save.slot1")) { + ChatUtil.sendErrorMessage(p, "Für diesen Slot hast du keine Rechte!"); + return; + } + if (!adventureSave1.isDirectory()) { + return; + } + if (!Server.serverPlayers.containsValue(p.getUniqueId())) { + p.closeInventory(); + plugin.getPluginConfig().getOnlineAdventureServer().ifPresentOrElse(server -> server.loadSaved(p, savePlayerID, "1"), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!")); + } else { + p.closeInventory(); + ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!"); + } + } + case SAVE_2_INDEX -> { + if (!p.hasPermission("challenge.save.slot2")) { + ChatUtil.sendErrorMessage(p, "Für diesen Slot brauchst du VIP!"); + return; + } + if (!adventureSave2.isDirectory()) { + return; + } + if (!Server.serverPlayers.containsValue(p.getUniqueId())) { + p.closeInventory(); + plugin.getPluginConfig().getOnlineAdventureServer().ifPresentOrElse(server -> server.loadSaved(p, savePlayerID, "2"), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!")); + } else { + p.closeInventory(); + ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!"); + } + } + case SAVE_3_INDEX -> { + if (!p.hasPermission("challenge.save.slot3")) { + ChatUtil.sendErrorMessage(p, "Für diesen Slot brauchst du VIP!"); + return; + } + if (!adventureSave3.isDirectory()) { + return; + } + if (!Server.serverPlayers.containsValue(p.getUniqueId())) { + p.closeInventory(); + plugin.getPluginConfig().getOnlineAdventureServer().ifPresentOrElse(server -> server.loadSaved(p, savePlayerID, "3"), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!")); + } else { + p.closeInventory(); + ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!"); + } + } + case SAVE_AUTO_INDEX -> { + if (!p.hasPermission("challenge.save.slotauto")) { + ChatUtil.sendErrorMessage(p, "Für diesen Slot hast du keine Rechte!"); + return; + } + if (!adventureSaveAuto.isDirectory()) { + return; + } + if (!Server.serverPlayers.containsValue(p.getUniqueId())) { + p.closeInventory(); + plugin.getPluginConfig().getOnlineAdventureServer().ifPresentOrElse(server -> server.loadSaved(p, savePlayerID, "autosave"), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!")); + } else { + p.closeInventory(); + ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!"); + } + } + default -> { + } + } + } + + private static String getFileDate(File file) { + FileTime fileTime; + try { + BasicFileAttributes attr = Files.readAttributes(file.toPath(), BasicFileAttributes.class); + fileTime = attr.creationTime(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return StringUtil.formatDate(fileTime.toMillis()); + } + + private static ItemStack getDisplayItem(Player player, SaveSlot saveSlot, File save) { + ItemStack item; + if (player.hasPermission(saveSlot.getPermission())) { + if (save.isDirectory()) { + File mapConfig = new File(save, "/Challenges/serverconfig.yml"); + Material displayItem = null; + String displayName = null; + YamlConfiguration serverConfig = new YamlConfiguration(); + try { + serverConfig.load(mapConfig); + String itemType = serverConfig.getString("displayItem.item"); + String itemName = serverConfig.getString("displayItem.name"); + if (itemType != null) { + try { + displayItem = Material.valueOf(itemType); + } catch (IllegalArgumentException ignore) { + } + } + if (itemName != null) { + displayName = itemName; + } + } catch (IOException | InvalidConfigurationException ex) { + plugin.getLogger().log(Level.SEVERE, "Fehler beim laden der config", ex); + } + + ItemStack stack = new ItemStack(displayItem != null ? displayItem : Material.MAP); + ItemMeta meta = stack.getItemMeta(); + meta.setDisplayName(displayName != null ? displayName : ChatUtil.GREEN + "Save " + saveSlot.getSlot()); + meta.setLore(List.of(ChatUtil.GREEN + "Version: " + ChatUtil.BLUE + serverConfig.getString("serverversion"), ChatUtil.GREEN + "Gespeichert am: " + ChatUtil.BLUE + getFileDate(save))); + stack.setItemMeta(meta); + item = stack; + + + } else { + item = ItemUtil.createGuiItem(Material.LIME_STAINED_GLASS_PANE, ChatUtil.GREEN + "Frei"); + } + } else { + item = ItemUtil.createGuiItem(Material.BARRIER, ChatUtil.RED + "Für diesen Slot brauchst du VIP"); + } + return item; + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/loadgui/ChallengeLoadGUI.java b/Lobby/src/main/java/de/fanta/lobby/loadgui/ChallengeLoadGUI.java new file mode 100644 index 0000000..2008505 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/loadgui/ChallengeLoadGUI.java @@ -0,0 +1,219 @@ +package de.fanta.lobby.loadgui; + +import de.fanta.lobby.Lobby; +import de.fanta.lobby.ChatUtil; +import de.fanta.lobby.Server; +import de.fanta.lobby.utils.ItemUtil; +import de.iani.cubesideutils.StringUtil; +import de.iani.cubesideutils.bukkit.inventory.AbstractWindow; +import de.iani.playerUUIDCache.CachedPlayer; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.UUID; + +public class ChallengeLoadGUI extends AbstractWindow { + + private static final Lobby plugin = Lobby.getPlugin(); + + private static final int SAVE_1_INDEX = 1; + private static final int SAVE_2_INDEX = 3; + private static final int SAVE_3_INDEX = 5; + private static final int SAVE_AUTO_INDEX = 7; + private static final int WINDOW_SIZE = 9; + + private static final HashMap savePlayerList = new HashMap<>(); + + public ChallengeLoadGUI(Player player, CachedPlayer savePlayer) { + super(player, Bukkit.createInventory(player, WINDOW_SIZE, Lobby.CHALLENGEGUIPREFIX + " >> Map laden")); + savePlayerList.put(player.getUniqueId(), savePlayer.getUniqueId()); + } + + @Override + protected void rebuildInventory() { + Player p = getPlayer(); + UUID savePlayerID = savePlayerList.get(p.getUniqueId()); + /*File challengeSave1 = new File("/home/minecraft/saves/" + savePlayerID + "/1"); + File challengeSave2 = new File("/home/minecraft/saves/" + savePlayerID + "/2"); + File challengeSave3 = new File("/home/minecraft/saves/" + savePlayerID + "/3"); + File challengeSaveAuto = new File("/home/minecraft/saves/" + savePlayerID + "/autosave");*/ + + File challengeSave1 = new File(plugin.getChallengeSavePath().toFile(), savePlayerID + "/1"); + File challengeSave2 = new File(plugin.getChallengeSavePath().toFile(), savePlayerID + "/2"); + File challengeSave3 = new File(plugin.getChallengeSavePath().toFile(), savePlayerID + "/3"); + File challengeSaveAuto = new File(plugin.getChallengeSavePath().toFile(), savePlayerID + "/autosave"); + + for (int i = 0; i < WINDOW_SIZE; i++) { + ItemStack item; + switch (i) { + case SAVE_1_INDEX -> { + if (p.hasPermission("challenge.save.slot1")) { + if (challengeSave1.isDirectory()) { + item = ItemUtil.createGuiItem(Material.MAP, ChatUtil.GREEN + "Save 1", ChatUtil.GREEN + "Klicken zum laden.", ChatUtil.GREEN + "Gespeichert am " + getFileDate(new File(challengeSave1 + "/Challenges/serverconfig.yml"))); + } else { + item = ItemUtil.createGuiItem(Material.LIME_STAINED_GLASS_PANE, ChatUtil.GREEN + "Frei"); + } + } else { + item = ItemUtil.createGuiItem(Material.BARRIER, ChatUtil.RED + "Für diesen Slot hast du keine Rechte"); + } + } + + case SAVE_2_INDEX -> { + if (p.hasPermission("challenge.save.slot2")) { + if (challengeSave2.isDirectory()) { + item = ItemUtil.createGuiItem(Material.MAP, ChatUtil.GREEN + "Save 2", ChatUtil.GREEN + "Klicken zum laden.", ChatUtil.GREEN + "Gespeichert am " + getFileDate(new File(challengeSave2 + "/Challenges/serverconfig.yml"))); + } else { + item = ItemUtil.createGuiItem(Material.LIME_STAINED_GLASS_PANE, ChatUtil.GREEN + "Frei"); + } + } else { + item = ItemUtil.createGuiItem(Material.BARRIER, ChatUtil.RED + "Für diesen Slot brauchst du VIP"); + } + } + + case SAVE_3_INDEX -> { + if (p.hasPermission("challenge.save.slot3")) { + if (challengeSave3.isDirectory()) { + item = ItemUtil.createGuiItem(Material.MAP, ChatUtil.GREEN + "Save 3", ChatUtil.GREEN + "Klicken zum laden.", ChatUtil.GREEN + "Gespeichert am " + getFileDate(new File(challengeSave3 + "/Challenges/serverconfig.yml"))); + } else { + item = ItemUtil.createGuiItem(Material.LIME_STAINED_GLASS_PANE, ChatUtil.GREEN + "Frei"); + } + } else { + item = ItemUtil.createGuiItem(Material.BARRIER, ChatUtil.RED + "Für diesen Slot brauchst du VIP"); + } + } + + case SAVE_AUTO_INDEX -> { + if (p.hasPermission("challenge.save.slotauto")) { + if (challengeSaveAuto.isDirectory()) { + item = ItemUtil.createGuiItem(Material.CLOCK, ChatUtil.GREEN + "AutoSave", ChatUtil.GREEN + "Klicken zum laden.", ChatUtil.GREEN + "Gespeichert am " + getFileDate(new File(challengeSaveAuto + "/Challenges/serverconfig.yml"))); + } else { + item = ItemUtil.createGuiItem(Material.LIME_STAINED_GLASS_PANE, ChatUtil.GREEN + "AutoSave"); + } + } else { + item = ItemUtil.createGuiItem(Material.BARRIER, ChatUtil.RED + "Für diesen Slot hast du keine Rechte"); + } + } + default -> item = ItemUtil.EMPTY_ICON; + } + this.getInventory().setItem(i, item); + } + } + + @Override + public void onItemClicked(InventoryClickEvent event) { + if (!mayAffectThisInventory(event)) { + return; + } + + event.setCancelled(true); + if (!getInventory().equals(event.getClickedInventory())) { + return; + } + + Player p = getPlayer(); + UUID savePlayerID = savePlayerList.get(p.getUniqueId()); + + /*File challengeSave1 = new File("/home/minecraft/saves/" + savePlayerID + "/1"); + File challengeSave2 = new File("/home/minecraft/saves/" + savePlayerID + "/2"); + File challengeSave3 = new File("/home/minecraft/saves/" + savePlayerID + "/3"); + File challengeSaveAuto = new File("/home/minecraft/saves/" + savePlayerID + "/autosave");*/ + + File challengeSave1 = new File(plugin.getChallengeSavePath().toFile(), savePlayerID + "/1"); + File challengeSave2 = new File(plugin.getChallengeSavePath().toFile(), savePlayerID + "/2"); + File challengeSave3 = new File(plugin.getChallengeSavePath().toFile(), savePlayerID + "/3"); + File challengeSaveAuto = new File(plugin.getChallengeSavePath().toFile(), savePlayerID + "/autosave"); + + + int slot = event.getSlot(); + switch (slot) { + case SAVE_1_INDEX -> { + if (!p.hasPermission("challenge.save.slot1")) { + ChatUtil.sendErrorMessage(p, "Für diesen Slot hast du keine Rechte!"); + return; + } + if (!challengeSave1.isDirectory()) { + return; + } + if (!Server.serverPlayers.containsValue(p.getUniqueId())) { + p.closeInventory(); + plugin.getPluginConfig().getOnlineChanllengeServer().ifPresentOrElse(server -> server.loadSaved(p, savePlayerID, "1"), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!")); + } else { + p.closeInventory(); + ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!"); + } + } + case SAVE_2_INDEX -> { + if (!p.hasPermission("challenge.save.slot2")) { + ChatUtil.sendErrorMessage(p, "Für diesen Slot brauchst du VIP!"); + return; + } + if (!challengeSave2.isDirectory()) { + return; + } + if (!Server.serverPlayers.containsValue(p.getUniqueId())) { + p.closeInventory(); + plugin.getPluginConfig().getOnlineChanllengeServer().ifPresentOrElse(server -> server.loadSaved(p, savePlayerID, "2"), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!")); + } else { + p.closeInventory(); + ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!"); + } + } + case SAVE_3_INDEX -> { + if (!p.hasPermission("challenge.save.slot3")) { + ChatUtil.sendErrorMessage(p, "Für diesen Slot brauchst du VIP!"); + return; + } + if (!challengeSave3.isDirectory()) { + return; + } + if (!Server.serverPlayers.containsValue(p.getUniqueId())) { + p.closeInventory(); + plugin.getPluginConfig().getOnlineChanllengeServer().ifPresentOrElse(server -> server.loadSaved(p, savePlayerID, "3"), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!")); + } else { + p.closeInventory(); + ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!"); + } + } + case SAVE_AUTO_INDEX -> { + if (!p.hasPermission("challenge.save.slotauto")) { + ChatUtil.sendErrorMessage(p, "Für diesen Slot hast du keine Rechte!"); + return; + } + if (!challengeSaveAuto.isDirectory()) { + return; + } + if (!Server.serverPlayers.containsValue(p.getUniqueId())) { + p.closeInventory(); + plugin.getPluginConfig().getOnlineChanllengeServer().ifPresentOrElse(server -> server.loadSaved(p, savePlayerID, "autosave"), () -> ChatUtil.sendErrorMessage(p, "Aktuell ist kein Server Frei!")); + } else { + p.closeInventory(); + ChatUtil.sendErrorMessage(p, "Du kannst nur einen Server starten!"); + } + } + default -> { + } + } + } + + private static String getFileDate(File serverConfigFile) { + long saveTime; + YamlConfiguration serverConfiguration = new YamlConfiguration(); + if (!serverConfigFile.exists()) { + saveTime = 0; + } + try { + serverConfiguration.load(serverConfigFile); + } catch (IOException | org.bukkit.configuration.InvalidConfigurationException e) { + e.printStackTrace(); + } + saveTime = serverConfiguration.getLong("saveTime", 0); + return StringUtil.formatDate(saveTime); + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/schedular/BukkitScheduler.java b/Lobby/src/main/java/de/fanta/lobby/schedular/BukkitScheduler.java new file mode 100644 index 0000000..0344021 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/schedular/BukkitScheduler.java @@ -0,0 +1,72 @@ +package de.fanta.lobby.schedular; + +import de.fanta.lobby.Lobby; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Entity; + +import java.util.function.Consumer; + +public class BukkitScheduler implements Scheduler { + + private final Lobby plugin; + + public BukkitScheduler(Lobby plugin) { + this.plugin = plugin; + } + + @Override + public void runAsync(Runnable task) { + Bukkit.getScheduler().runTaskAsynchronously(this.plugin, task); + } + + @Override + public void run(Runnable task) { + Bukkit.getScheduler().runTask(this.plugin, task); + } + + @Override + public CancellableTask runGlobalDelayed(Runnable task, long delay) { + return Bukkit.getScheduler().runTaskLater(this.plugin, task, delay)::cancel; + } + + @Override + public void runLocalDelayed(Location location, Runnable task, long delay) { + runGlobalDelayed(task, delay); + } + + @Override + public CancellableTask runLocalAtFixedRate(Location location, Runnable task, long delay, long period) { + return runGlobalAtFixedRate(task, delay, period); + } + + @Override + public void runLocalAtFixedRate(Location location, Consumer taskConsumer, long delay, long period) { + runGlobalAtFixedRate(taskConsumer, delay, period); + } + + @Override + public CancellableTask runGlobalAtFixedRate(Runnable task, long delay, long period) { + return Bukkit.getScheduler().runTaskTimer(this.plugin, task, delay, period)::cancel; + } + + @Override + public void runGlobalAtFixedRate(Consumer taskConsumer, long delay, long period) { + Bukkit.getScheduler().runTaskTimer(this.plugin, bukkitTask -> taskConsumer.accept(bukkitTask::cancel), delay, period); + } + + @Override + public CancellableTask runOnEntityAtFixedRate(Entity entity, Runnable task, long delay, long period) { + return runGlobalAtFixedRate(task, delay, period); + } + + @Override + public void runOnEntityAtFixedRate(Entity entity, Consumer taskConsumer, long delay, long period) { + runLocalAtFixedRate(null, taskConsumer, delay, period); + } + + @Override + public void runDelayedOnEntity(Entity entity, Runnable task, long delay) { + Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, task, delay); + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/schedular/CancellableTask.java b/Lobby/src/main/java/de/fanta/lobby/schedular/CancellableTask.java new file mode 100644 index 0000000..95fb4f3 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/schedular/CancellableTask.java @@ -0,0 +1,5 @@ +package de.fanta.lobby.schedular; + +public interface CancellableTask { + void cancel(); +} diff --git a/Lobby/src/main/java/de/fanta/lobby/schedular/FoliaScheduler.java b/Lobby/src/main/java/de/fanta/lobby/schedular/FoliaScheduler.java new file mode 100644 index 0000000..685e394 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/schedular/FoliaScheduler.java @@ -0,0 +1,74 @@ +package de.fanta.lobby.schedular; + +import de.fanta.lobby.Lobby; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Entity; + +import java.util.function.Consumer; + +public class FoliaScheduler implements Scheduler { + + private final Lobby plugin; + + public FoliaScheduler(Lobby plugin) { + this.plugin = plugin; + } + + @Override + public void runAsync(Runnable task) { + Bukkit.getServer().getAsyncScheduler().runNow(this.plugin, scheduledTask -> task.run()); + } + + @Override + public void run(Runnable task) { + Bukkit.getServer().getGlobalRegionScheduler().run(this.plugin, scheduledTask -> task.run()); + } + + @Override + public CancellableTask runGlobalDelayed(Runnable task, long delay) { + return Bukkit.getServer().getGlobalRegionScheduler().runDelayed(this.plugin, scheduledTask -> task.run(), delay)::cancel; + } + + @Override + public void runLocalDelayed(Location location, Runnable task, long delay) { + Bukkit.getServer().getRegionScheduler().runDelayed(this.plugin, location, scheduledTask -> task.run(), delay); + } + + @Override + public CancellableTask runLocalAtFixedRate(Location location, Runnable task, long delay, long period) { + return Bukkit.getServer().getRegionScheduler().runAtFixedRate(this.plugin, location, scheduledTask -> task.run(), delay, period)::cancel; + } + + @Override + public void runLocalAtFixedRate(Location location, Consumer taskConsumer, long delay, long period) { + Bukkit.getServer().getRegionScheduler().runAtFixedRate(this.plugin, location, scheduledTask -> taskConsumer.accept(scheduledTask::cancel), delay, period); + } + + @Override + public CancellableTask runGlobalAtFixedRate(Runnable task, long delay, long period) { + return Bukkit.getServer().getGlobalRegionScheduler().runAtFixedRate(this.plugin, scheduledTask -> task.run(), delay, period)::cancel; + } + + @Override + public void runGlobalAtFixedRate(Consumer taskConsumer, long delay, long period) { + Bukkit.getServer().getGlobalRegionScheduler().runAtFixedRate(this.plugin, scheduledTask -> taskConsumer.accept(scheduledTask::cancel), delay, period); + } + + @Override + public CancellableTask runOnEntityAtFixedRate(Entity entity, Runnable task, long delay, long period) { + ScheduledTask createdTask = entity.getScheduler().runAtFixedRate(this.plugin, scheduledTask -> task.run(), null, delay, period); + return createdTask == null ? null : createdTask::cancel; + } + + @Override + public void runOnEntityAtFixedRate(Entity entity, Consumer taskConsumer, long delay, long period) { + entity.getScheduler().runAtFixedRate(this.plugin, scheduledTask -> taskConsumer.accept(scheduledTask::cancel), null, delay, period); + } + + @Override + public void runDelayedOnEntity(Entity entity, Runnable task, long delay) { + entity.getScheduler().runDelayed(this.plugin, scheduledTask -> task.run(), null, delay); + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/schedular/Scheduler.java b/Lobby/src/main/java/de/fanta/lobby/schedular/Scheduler.java new file mode 100644 index 0000000..fa8d0c4 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/schedular/Scheduler.java @@ -0,0 +1,39 @@ +package de.fanta.lobby.schedular; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; + +import java.util.function.Consumer; + +public interface Scheduler { + + void runAsync(Runnable task); + + void run(Runnable task); + + CancellableTask runGlobalDelayed(Runnable task, long delay); + + default void runGlobalDelayed(Runnable task) { + runGlobalDelayed(task, 1); + } + + void runLocalDelayed(Location location, Runnable task, long delay); + + default void runLocalDelayed(Runnable task) { + runGlobalDelayed(task, 1); + } + + CancellableTask runLocalAtFixedRate(Location location, Runnable task, long delay, long period); + + void runLocalAtFixedRate(Location location, Consumer taskConsumer, long delay, long period); + + CancellableTask runGlobalAtFixedRate(Runnable task, long delay, long period); + + void runGlobalAtFixedRate(Consumer taskConsumer, long delay, long period); + + CancellableTask runOnEntityAtFixedRate(Entity entity, Runnable task, long delay, long period); + + void runOnEntityAtFixedRate(Entity entity, Consumer taskConsumer, long delay, long period); + + void runDelayedOnEntity(Entity entity, Runnable task, long delay); +} diff --git a/Lobby/src/main/java/de/fanta/lobby/utils/DurationCommandUtil.java b/Lobby/src/main/java/de/fanta/lobby/utils/DurationCommandUtil.java new file mode 100644 index 0000000..b97af35 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/utils/DurationCommandUtil.java @@ -0,0 +1,57 @@ +package de.fanta.lobby.utils; + +import de.fanta.lobby.ChatUtil; +import de.iani.cubesideutils.StringUtil; +import de.iani.cubesideutils.commands.ArgsParser; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.Set; +import java.util.TreeSet; + +public class DurationCommandUtil { + + private DurationCommandUtil() { + // prevent instances + } + + public static final Set PERM_STRINGS; + + static { + Set permStrings = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + permStrings.add("-1"); + permStrings.add("perm"); + permStrings.add("permanent"); + permStrings.add("inf"); + permStrings.add("infinite"); + permStrings.add("infinity"); + permStrings.add("forever"); + PERM_STRINGS = Collections.unmodifiableSet(permStrings); + } + + public static long parseDuration(CommandSender sender, ArgsParser args, boolean allowPermanent) { + if (!args.hasNext()) { + ChatUtil.sendWarningMessage(sender, "Bitte gib die Dauer im Format \"7d12h15m30s\" (eine Einheit genügt)", allowPermanent ? " oder als \"perm\"" : "", " an."); + return 0; + } + + String durationString = args.getNext(); + if (PERM_STRINGS.contains(durationString)) { + return -1; + } + + long duration; + try { + duration = StringUtil.parseTimespan(durationString); + if (duration <= 0) { + throw new NumberFormatException(); + } + } catch (IllegalArgumentException e) { + ChatUtil.sendWarningMessage(sender, "Bitte gib die Dauer im Format \"7d12h15m30s\" (eine Einheit genügt)", allowPermanent ? " oder als \"perm\"" : "", " an."); + return 0; + } + + return duration; + } + +} diff --git a/Lobby/src/main/java/de/fanta/lobby/utils/ItemUtil.java b/Lobby/src/main/java/de/fanta/lobby/utils/ItemUtil.java new file mode 100644 index 0000000..cb1c20a --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/utils/ItemUtil.java @@ -0,0 +1,31 @@ +package de.fanta.lobby.utils; + +import de.iani.cubesideutils.bukkit.items.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; + +public class ItemUtil { + public static final ItemStack EMPTY_ICON = createGuiItem(Material.GRAY_STAINED_GLASS_PANE, " ", true, false); + + public static ItemStack createGuiItem(Material material, String name, String... lore) { + return createGuiItem(material, name, false, lore); + } + + public static ItemStack createGuiItem(Material material, String name, boolean glowing, boolean showTooltip, String... lore) { + ItemBuilder builder = ItemBuilder.fromMaterial(material).displayName(name).lore(lore); + if (glowing) { + builder.enchantment(Enchantment.UNBREAKING, 1, true).flag(ItemFlag.HIDE_ENCHANTS); + } + if (!showTooltip) { + builder.flag(ItemFlag.HIDE_ADDITIONAL_TOOLTIP); + } + return builder.build(); + + } + + public static ItemStack createGuiItem(Material material, String name, boolean glowing, String... lore) { + return createGuiItem(material, name, glowing, true, lore); + } +} diff --git a/Lobby/src/main/java/de/fanta/lobby/utils/PlayerStatisticsData.java b/Lobby/src/main/java/de/fanta/lobby/utils/PlayerStatisticsData.java new file mode 100644 index 0000000..ac56a58 --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/utils/PlayerStatisticsData.java @@ -0,0 +1,69 @@ +package de.fanta.lobby.utils; + +import java.util.UUID; + +public class PlayerStatisticsData { + private final UUID playerUUID; + private final String playerName; + private final int runsPlayed; + private final int runsPlayedMonth; + private final int runsWon; + private final int runsWonMonth; + private final int bestTime; + private final int bestTimeMonth; + private final int position; + private final int positionMonth; + + public PlayerStatisticsData(UUID uniqueId, String name, int runsPlayed, int runsPlayedMonth, int runsWon, int runsWonMonth, int bestTime, int bestTimeMonth, int position, int positionMonth) { + this.playerUUID = uniqueId; + this.playerName = name; + this.runsPlayed = runsPlayed; + this.runsPlayedMonth = runsPlayedMonth; + this.runsWon = runsWon; + this.runsWonMonth = runsWonMonth; + this.bestTime = bestTime; + this.bestTimeMonth = bestTimeMonth; + this.position = position; + this.positionMonth = positionMonth; + } + + public UUID getPlayerId() { + return playerUUID; + } + + public String getPlayerName() { + return playerName; + } + + public int getRunsPlayed() { + return runsPlayed; + } + + public int getRunsPlayedMonth() { + return runsPlayedMonth; + } + + public int getRunsWon() { + return runsWon; + } + + public int getRunsWonMonth() { + return runsWonMonth; + } + + public int getBestTime() { + return bestTime; + } + + public int getBestTimeMonth() { + return bestTimeMonth; + } + + public int getPosition() { + return position; + } + + public int getPositionMonth() { + return positionMonth; + } +} \ No newline at end of file diff --git a/Lobby/src/main/java/de/fanta/lobby/utils/Statistics.java b/Lobby/src/main/java/de/fanta/lobby/utils/Statistics.java new file mode 100644 index 0000000..e38a06e --- /dev/null +++ b/Lobby/src/main/java/de/fanta/lobby/utils/Statistics.java @@ -0,0 +1,220 @@ +package de.fanta.lobby.utils; + +import de.fanta.lobby.Lobby; +import de.iani.cubesidestats.api.CubesideStatisticsAPI; +import de.iani.cubesidestats.api.Ordering; +import de.iani.cubesidestats.api.PlayerStatistics; +import de.iani.cubesidestats.api.PlayerStatisticsQueryKey; +import de.iani.cubesidestats.api.StatisticKey; +import de.iani.cubesidestats.api.StatisticsQueryKey; +import de.iani.cubesidestats.api.TimeFrame; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; + +public class Statistics { + private final CubesideStatisticsAPI statistics; + + private final StatisticKey speedRunsPlayedSolo; + private final StatisticKey speedRunsWonSolo; + private final StatisticKey speedRunsTimeSolo; + + private final StatisticKey speedRunsPlayedDuo; + private final StatisticKey speedRunsWonDuo; + private final StatisticKey speedRunsTimeDuo; + + private final StatisticKey speedRunsPlayedTeam; + private final StatisticKey speedRunsWonTeam; + private final StatisticKey speedRunsTimeTeam; + + public Statistics(Lobby plugin) { + statistics = plugin.getCubesideStatistics(); + + speedRunsPlayedSolo = statistics.getStatisticKey("challenge.speedruns.solo.played"); + speedRunsPlayedSolo.setDisplayName("Challenge - SpeedRun's gespielt (Solo)"); + speedRunsPlayedSolo.setIsMonthlyStats(true); + + speedRunsWonSolo = statistics.getStatisticKey("challenge.speedruns.solo.won"); + speedRunsWonSolo.setDisplayName("Challenge - SpeedRun's gewonnen (Solo)"); + speedRunsWonSolo.setIsMonthlyStats(true); + + speedRunsTimeSolo = statistics.getStatisticKey("challenge.speedruns.solo.time"); + speedRunsTimeSolo.setDisplayName("Beste Zeit (Solo)"); + speedRunsTimeSolo.setIsMonthlyStats(true); + + + speedRunsPlayedDuo = statistics.getStatisticKey("challenge.speedruns.duo.played"); + speedRunsPlayedDuo.setDisplayName("Challenge - SpeedRun's gespielt (Duo)"); + speedRunsPlayedDuo.setIsMonthlyStats(true); + + speedRunsWonDuo = statistics.getStatisticKey("challenge.speedruns.duo.won"); + speedRunsWonDuo.setDisplayName("Challenge - SpeedRun's gewonnen (Duo)"); + speedRunsWonDuo.setIsMonthlyStats(true); + + speedRunsTimeDuo = statistics.getStatisticKey("challenge.speedruns.duo.time"); + speedRunsTimeDuo.setDisplayName("Beste Zeit (Duo)"); + speedRunsTimeDuo.setIsMonthlyStats(true); + + + speedRunsPlayedTeam = statistics.getStatisticKey("challenge.speedruns.team.played"); + speedRunsPlayedTeam.setDisplayName("Challenge - SpeedRun's gespielt (Team)"); + speedRunsPlayedTeam.setIsMonthlyStats(true); + + speedRunsWonTeam = statistics.getStatisticKey("challenge.speedruns.team.won"); + speedRunsWonTeam.setDisplayName("Challenge - SpeedRun's gewonnen (Team)"); + speedRunsWonTeam.setIsMonthlyStats(true); + + speedRunsTimeTeam = statistics.getStatisticKey("challenge.speedruns.team.time"); + speedRunsTimeTeam.setDisplayName("Beste Zeit (Team)"); + speedRunsTimeTeam.setIsMonthlyStats(true); + + StatisticKey challengeWeekStats = statistics.getStatisticKey("challenge.challengeweek"); + challengeWeekStats.setDisplayName("Beste Spieler Challenge Woche"); + challengeWeekStats.setIsMonthlyStats(false); + } + + public void getDataForPlayer(OfflinePlayer player, StatType statType, Consumer callback) { + List keys = new ArrayList<>(); + PlayerStatistics ps = statistics.getStatistics(player.getUniqueId()); + + PlayerStatisticsQueryKey kRunsPlayed = null; + PlayerStatisticsQueryKey kRunsPlayedMonth = null; + + PlayerStatisticsQueryKey kRunsWon = null; + PlayerStatisticsQueryKey kRunsWonMonth = null; + + PlayerStatisticsQueryKey kBestTime = null; + PlayerStatisticsQueryKey kBestTimeMonth = null; + + PlayerStatisticsQueryKey kPosition = null; + PlayerStatisticsQueryKey kPositionMonth = null; + + if (statType == StatType.SOLO) { + keys.add(kRunsPlayed = new PlayerStatisticsQueryKey(ps, speedRunsPlayedSolo, PlayerStatisticsQueryKey.QueryType.SCORE)); + keys.add(kRunsPlayedMonth = new PlayerStatisticsQueryKey(ps, speedRunsPlayedSolo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH)); + + keys.add(kRunsWon = new PlayerStatisticsQueryKey(ps, speedRunsWonSolo, PlayerStatisticsQueryKey.QueryType.SCORE)); + keys.add(kRunsWonMonth = new PlayerStatisticsQueryKey(ps, speedRunsWonSolo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH)); + + keys.add(kBestTime = new PlayerStatisticsQueryKey(ps, speedRunsTimeSolo, PlayerStatisticsQueryKey.QueryType.SCORE)); + keys.add(kBestTimeMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeSolo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH)); + + keys.add(kPosition = new PlayerStatisticsQueryKey(ps, speedRunsTimeSolo, PlayerStatisticsQueryKey.QueryType.POSITION_MIN)); + keys.add(kPositionMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeSolo, PlayerStatisticsQueryKey.QueryType.POSITION_MIN, TimeFrame.MONTH)); + } else if (statType == StatType.DUO) { + keys.add(kRunsPlayed = new PlayerStatisticsQueryKey(ps, speedRunsPlayedDuo, PlayerStatisticsQueryKey.QueryType.SCORE)); + keys.add(kRunsPlayedMonth = new PlayerStatisticsQueryKey(ps, speedRunsPlayedDuo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH)); + + keys.add(kRunsWon = new PlayerStatisticsQueryKey(ps, speedRunsWonDuo, PlayerStatisticsQueryKey.QueryType.SCORE)); + keys.add(kRunsWonMonth = new PlayerStatisticsQueryKey(ps, speedRunsWonDuo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH)); + + keys.add(kBestTime = new PlayerStatisticsQueryKey(ps, speedRunsTimeDuo, PlayerStatisticsQueryKey.QueryType.SCORE)); + keys.add(kBestTimeMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeDuo, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH)); + + keys.add(kPosition = new PlayerStatisticsQueryKey(ps, speedRunsTimeDuo, PlayerStatisticsQueryKey.QueryType.POSITION_MIN)); + keys.add(kPositionMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeDuo, PlayerStatisticsQueryKey.QueryType.POSITION_MIN, TimeFrame.MONTH)); + } else if (statType == StatType.TEAM) { + keys.add(kRunsPlayed = new PlayerStatisticsQueryKey(ps, speedRunsPlayedTeam, PlayerStatisticsQueryKey.QueryType.SCORE)); + keys.add(kRunsPlayedMonth = new PlayerStatisticsQueryKey(ps, speedRunsPlayedTeam, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH)); + + keys.add(kRunsWon = new PlayerStatisticsQueryKey(ps, speedRunsWonTeam, PlayerStatisticsQueryKey.QueryType.SCORE)); + keys.add(kRunsWonMonth = new PlayerStatisticsQueryKey(ps, speedRunsWonTeam, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH)); + + keys.add(kBestTime = new PlayerStatisticsQueryKey(ps, speedRunsTimeTeam, PlayerStatisticsQueryKey.QueryType.SCORE)); + keys.add(kBestTimeMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeTeam, PlayerStatisticsQueryKey.QueryType.SCORE, TimeFrame.MONTH)); + + keys.add(kPosition = new PlayerStatisticsQueryKey(ps, speedRunsTimeTeam, PlayerStatisticsQueryKey.QueryType.POSITION_MIN)); + keys.add(kPositionMonth = new PlayerStatisticsQueryKey(ps, speedRunsTimeTeam, PlayerStatisticsQueryKey.QueryType.POSITION_MIN, TimeFrame.MONTH)); + } + + PlayerStatisticsQueryKey finalKRunsPlayed = kRunsPlayed; + PlayerStatisticsQueryKey finalKRunsPlayedMonth = kRunsPlayedMonth; + + PlayerStatisticsQueryKey finalKRunsWon = kRunsWon; + PlayerStatisticsQueryKey finalKRunsWonMonth = kRunsWonMonth; + + PlayerStatisticsQueryKey finalKBestTime = kBestTime; + PlayerStatisticsQueryKey finalKBestTimeMonth = kBestTimeMonth; + + PlayerStatisticsQueryKey finalKPosition = kPosition; + PlayerStatisticsQueryKey finalKPositionMonth = kPositionMonth; + + statistics.queryStats(keys, (c) -> { + Integer runsPlayed = c.getOrDefault(finalKRunsPlayed, 0); + Integer runsPlayedMonth = c.getOrDefault(finalKRunsPlayedMonth, 0); + + Integer runsWon = c.getOrDefault(finalKRunsWon, 0); + Integer runsWonMonth = c.getOrDefault(finalKRunsWonMonth, 0); + + Integer bestTime = c.getOrDefault(finalKBestTime, 0); + Integer bestTimeMonth = c.getOrDefault(finalKBestTimeMonth, 0); + + Integer position = c.getOrDefault(finalKPosition, -1); + Integer positionMonth = c.getOrDefault(finalKPositionMonth, -1); + + callback.accept(new PlayerStatisticsData(player.getUniqueId(), player.getName(), runsPlayed, runsPlayedMonth, runsWon, runsWonMonth, bestTime, bestTimeMonth, position, positionMonth)); + }); + } + + public void setScore(UUID uuid, StatisticKey statisticKey, int score) { + statistics.getStatistics(uuid).setScore(statisticKey, score); + } + + public void deleteScore(UUID uuid, StatisticKey statisticKey) { + statistics.getStatistics(uuid).deleteScore(statisticKey); + } + + public void getDataForPositionIfExists(int pos, StatType statType, Consumer callback) { + if (pos < 1) { + callback.accept(null); + return; + } + + StatisticKey score = null; + + if (statType == StatType.SOLO) { + score = speedRunsTimeSolo; + } else if (statType == StatType.DUO) { + score = speedRunsTimeDuo; + } else if (statType == StatType.TEAM) { + score = speedRunsTimeTeam; + } + + if (score != null) { + score.getTop(pos - 1, 1, Ordering.DESCENDING, TimeFrame.ALL_TIME, (s) -> { + if (s.isEmpty()) { + callback.accept(null); + } else { + OfflinePlayer cplayer = Bukkit.getOfflinePlayer(s.get(0).getPlayer().getOwner()); + getDataForPlayer(cplayer, statType, callback); + } + }); + } + } + + public void getDataForPlayerIfExists(String player, StatType statType, Consumer callback) { + OfflinePlayer cplayer = Bukkit.getOfflinePlayer(player); + getDataForPlayer(cplayer, statType, callback); + } + + public enum StatType { + SOLO("Solo"), + DUO("Duo"), + TEAM("Team"); + + private final String prefix; + + StatType(String prefix) { + this.prefix = prefix; + } + + public String getPrefix() { + return prefix; + } + } +} + diff --git a/Lobby/src/main/resources/config.yml b/Lobby/src/main/resources/config.yml new file mode 100644 index 0000000..a7d7d0e --- /dev/null +++ b/Lobby/src/main/resources/config.yml @@ -0,0 +1,7 @@ +piglins: +fileLocations: + adventureMaps: "/home/storagebox/Adventure-Maps/" + adventureSaves: "/home/storagebox/Adventure-saves/" + challengeSaves: "/home/storagebox/Challenge-saves" + serverJars: "/home/minecraft/ServerJars/" + serverFolder: "/home/minecraft/Server/" diff --git a/Lobby/src/main/resources/plugin.yml b/Lobby/src/main/resources/plugin.yml index 064bf9e..feeabdc 100644 --- a/Lobby/src/main/resources/plugin.yml +++ b/Lobby/src/main/resources/plugin.yml @@ -2,3 +2,17 @@ version: '${project.version}' main: de.fanta.lobby.Lobby api-version: '1.20' + +depend: [GlobalClient, CubesideUtils, GlobalPort, CubesideNMSUtils] +softdepend: [Challenges, CubesideNPCs, SignGUI, ViaVersion, CubesideStatistics] + +commands: + piglins: + aliases: + - piglin + challenges: + aliases: + - c + adventure: + aliases: + - a \ No newline at end of file diff --git a/pom.xml b/pom.xml index d526fd2..085d95b 100644 --- a/pom.xml +++ b/pom.xml @@ -76,6 +76,12 @@ 0.0.1-SNAPSHOT provided + + de.cubeside + globalconnectionbukkit + 0.0.1-SNAPSHOT + provided +