diff --git a/src/main/java/de/fanta/challenges/challenges/ChallengeEvents/BridgeRaceChallengeEvent.java b/src/main/java/de/fanta/challenges/challenges/ChallengeEvents/BridgeRaceChallengeEvent.java new file mode 100644 index 0000000..5c3345c --- /dev/null +++ b/src/main/java/de/fanta/challenges/challenges/ChallengeEvents/BridgeRaceChallengeEvent.java @@ -0,0 +1,316 @@ +package de.fanta.challenges.challenges.ChallengeEvents; + +import de.fanta.challenges.Challenges; +import de.fanta.challenges.events.TimerChangedEvent; +import de.fanta.challenges.scoreboard.ChallengePlayer; +import de.fanta.challenges.scoreboard.Scorable; +import de.fanta.challenges.scoreboard.ScoreManager; +import de.fanta.challenges.utils.ChatSkullAPI.ChatSkull; +import de.fanta.challenges.utils.ChatUtil; +import de.fanta.challenges.utils.Config; +import de.iani.cubesideutils.bukkit.world.EmptyChunkGenerator; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.bukkit.WorldType; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerAttemptPickupItemEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerPortalEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Random; +import java.util.UUID; + +public class BridgeRaceChallengeEvent implements Listener { + + private static final Challenges plugin = Challenges.getPlugin(); + private static boolean running; + private static final HashMap playerSpawnLocations = new HashMap<>(); + private static final Map bossBarMap = new HashMap<>(); + private int updateTaskID = -1; + private int spawnItemTaskID = -1; + private static final ArrayList materials = new ArrayList<>(); + private static Location lastSpawnLocation = null; + private static boolean load = false; + private static World voidWorld; + private final Map> currentBarrier = new HashMap<>(); + private static final Material barrierBlock = Material.GLASS; + + @EventHandler + public void onActivation(TimerChangedEvent event) { + if (Objects.equals(Config.getString("event.type"), "bridgerace")) { + if (event.isRunning()) { + for (Material material : Material.values()) { + if (material.isItem() && !material.isAir() && !plugin.getNotAvailableMaterials().contains(material)) { + materials.add(material); + } + } + materials.remove(Material.ELYTRA); + + for (Player pp : plugin.getVanish().getPlayerListWithoutVanishPlayers()) { + plugin.getScoreManager().join(new ChallengePlayer(pp.getUniqueId())); + } + + startUpdateTask(); + startItemSpawnTask(); + + setRunning(true); + } else { + stopUpdateTask(); + stopItemSpawnTask(); + for (Player pp : plugin.getVanish().getPlayerListWithoutVanishPlayers()) { + pp.setGameMode(GameMode.SPECTATOR); + } + + for (Scorable scorable : plugin.getScoreManager().getByPositon(1)) { + OfflinePlayer p = (Bukkit.getServer().getOfflinePlayer(scorable.getName())); + if (p.isOnline()) { + String[] lines = {"", "", "", " " + ChatUtil.BLUE + p.getName() + "'s", ChatUtil.GREEN + " Brücke ist " + plugin.getScoreManager().getScore(scorable) + " Blöcke lang", ChatUtil.GREEN + " und hat damit gewonnen!", "", ""}; + ChatSkull.sendAll((Player) p, lines); + } else { + ChatUtil.sendBrodcastMessage(ChatUtil.BLUE + scorable.getName() + "'s" + ChatUtil.GREEN + " Brücke ist " + plugin.getScoreManager().getScore(scorable) + " Blöcke lang und hat damit gewonnen!", ChatUtil.BLUE); + } + } + + setRunning(false); + } + } + } + + @EventHandler + public void onPlayerRespawn(PlayerRespawnEvent e) { + if (isRunning()) { + Location respawnLocation = getPlayerLocation(e.getPlayer()).clone().add(0.5, 2, 0.5); + respawnLocation.setYaw(-90); + e.setRespawnLocation(respawnLocation); + } + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent e) { + if (isRunning()) { + if (plugin.getVanish().isVanish(e.getPlayer())) { + return; + } + plugin.getScoreManager().join(new ChallengePlayer(e.getPlayer().getUniqueId())); + } + + if (isLoaded()) { + createPlayerLocation(e.getPlayer()); + teleportPlayer(e.getPlayer()); + } + } + + @EventHandler + public void onMove(PlayerMoveEvent e) { + Player p = e.getPlayer(); + World world = p.getWorld(); + if (isRunning() && plugin.getTimer().isRunning() && !plugin.getVanish().isVanish(p) && p.getGameMode() == GameMode.SURVIVAL) { + Location playerLoc = p.getLocation(); + Location spawnLocation = getPlayerLocation(p).clone(); + double posRelatedToCenter = playerLoc.getZ() - spawnLocation.getZ(); + double distanceToCenter = Math.abs(posRelatedToCenter); + + List barrierLocations = currentBarrier.computeIfAbsent(p.getUniqueId(), uuid -> new ArrayList<>()); + + int BARRIER_POS = 20; + int BARRIER_SIZE = 6; + if (distanceToCenter >= BARRIER_POS) { //Outside border + p.teleport(getPlayerLocation(p).clone().add(0.5,2,0.5)); + } else if (distanceToCenter >= BARRIER_POS - 6) { //Inside border + //Send barrier + double barrierZ = spawnLocation.getZ() + BARRIER_POS * (posRelatedToCenter > 0 ? 1 : -1); + Location loc = new Location(p.getWorld(), playerLoc.getX() - BARRIER_SIZE / 2d, playerLoc.getY() - BARRIER_SIZE / 2d, barrierZ); + + resetBarrier(p, world, barrierLocations); + for (int y = 0; y < BARRIER_SIZE; y++) { + for (int x = 0; x < BARRIER_SIZE; x++) { + Location blockLoc = loc.clone().add(x, y, 0); + if (!world.getBlockAt(blockLoc).isSolid()) { + barrierLocations.add(blockLoc); + p.sendBlockChange(blockLoc, Bukkit.createBlockData(barrierBlock)); + } + } + } + } else if (!barrierLocations.isEmpty()) { //Away from border + resetBarrier(p, world, barrierLocations); + } + } + } + + @EventHandler + public void onPortal(PlayerPortalEvent e) { + if (isRunning()) { + e.setCancelled(true); + } + } + + @EventHandler + public void onPickupItem(PlayerAttemptPickupItemEvent e) { + if (isRunning()) { + Player p = e.getPlayer(); + double posRelatedToCenter = p.getLocation().getZ() - getPlayerLocation(p).clone().getZ(); + double distanceToCenter = Math.abs(posRelatedToCenter); + if (distanceToCenter >= 20) { + e.setCancelled(true); + } + } + } + + public static boolean load(Player player) { + if (!load) { + voidWorld = Bukkit.getWorld("VOID"); + if (voidWorld == null) { + WorldCreator wc = new WorldCreator("VOID"); + wc.environment(World.Environment.NORMAL); + wc.type(WorldType.FLAT); + wc.generateStructures(false); + wc.generator(new EmptyChunkGenerator()); + voidWorld = Bukkit.getServer().createWorld(wc); + } + + for (Player pp : plugin.getVanish().getPlayerListWithoutVanishPlayers()) { + createPlayerLocation(pp); + teleportPlayer(pp); + } + load = true; + return true; + } else { + ChatUtil.sendErrorMessage(player, "Die Void Challenge läuft bereits!"); + return false; + } + } + + private static void createPlayerLocation(Player player) { + if (!playerSpawnLocations.containsKey(player.getUniqueId())) { + if (lastSpawnLocation != null) { + Location tempLocation = lastSpawnLocation.clone(); + lastSpawnLocation = tempLocation.add(0, 0, 50); + } else { + lastSpawnLocation = new Location(voidWorld, 0, 60, 0); + } + playerSpawnLocations.put(player.getUniqueId(), lastSpawnLocation.clone()); + } + } + + private static void teleportPlayer(Player player) { + setBedrock(getPlayerLocation(player).clone()); + Location teleportLocation = getPlayerLocation(player).clone().add(0.5, 2, 0.5); + teleportLocation.setYaw(-90); + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> player.teleport(teleportLocation), 1L); + } + + private static Location getPlayerLocation(Player player) { + if (!playerSpawnLocations.containsKey(player.getUniqueId())) { + createPlayerLocation(player); + } + return playerSpawnLocations.get(player.getUniqueId()); + } + + private static void setBedrock(Location location) { + location.getWorld().getBlockAt(location).setType(Material.BEDROCK); + Block block = location.getWorld().getBlockAt(location.add(1, 0, 0)); + if (block.getType() == Material.AIR) { + block.setType(Material.MAGENTA_GLAZED_TERRACOTTA); + BlockData blockData = block.getBlockData(); + if (blockData instanceof Directional directional) { + directional.setFacing(BlockFace.WEST); + block.setBlockData(blockData); + } + } + } + + public void startUpdateTask() { + updateTaskID = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, this::tick, 1L, 1L); + } + + public void stopUpdateTask() { + plugin.getServer().getScheduler().cancelTask(updateTaskID); + } + + public void startItemSpawnTask() { + spawnItemTaskID = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, this::itemSpawn, 6 * 20, 6 * 20); + } + + public void stopItemSpawnTask() { + plugin.getServer().getScheduler().cancelTask(spawnItemTaskID); + } + + public void itemSpawn() { + Random random = new Random(); + for (Player player : plugin.getVanish().getPlayerListWithoutVanishPlayers()) { + ItemStack randomItem = new ItemStack(materials.get(random.nextInt(materials.size()))); + Location loc = getPlayerLocation(player).clone().add(0.5, 1, 0.5); + loc.getWorld().dropItem(loc, randomItem); + } + } + + private void tick() { + if (Objects.equals(Config.getString("event.type"), "bridgerace") && plugin.getTimer().isRunning()) { + ScoreManager scoreManager = plugin.getScoreManager(); + for (Player p : plugin.getVanish().getPlayerListWithoutVanishPlayers()) { + if (!plugin.getVanish().isVanish(p)) { + if (p.getGameMode() != GameMode.SPECTATOR && p.getLocation().getY() >= 60 && p.getLocation().getX() >= 0 && p.getWorld() == voidWorld) { + double posRelatedToCenter = p.getLocation().getZ() - getPlayerLocation(p).clone().getZ(); + double distanceToCenter = Math.abs(posRelatedToCenter); + if (distanceToCenter >= 20) { + return; + } + + int distance = (int) p.getLocation().toVector().subtract(getPlayerLocation(p).clone().toVector()).length(); + if (distance > scoreManager.getScore(new ChallengePlayer(p.getUniqueId()))) { + scoreManager.setScore(new ChallengePlayer(p.getUniqueId()), distance); + } + } + BossBar bossBar = bossBarMap.computeIfAbsent(p, player -> { + BossBar newBossBar = Bukkit.createBossBar(ChatUtil.GREEN + "Position: " + ChatUtil.BLUE + scoreManager.getPosition(new ChallengePlayer(p.getUniqueId())) + ChatUtil.RED + " | " + ChatUtil.GREEN + "Länge deiner Brücke: " + ChatUtil.BLUE + scoreManager.getScore(new ChallengePlayer(p.getUniqueId())) + " Blöcke", BarColor.GREEN, BarStyle.SOLID); + newBossBar.setVisible(true); + newBossBar.addPlayer(p); + return newBossBar; + }); + bossBar.setTitle(ChatUtil.GREEN + "Position: " + ChatUtil.BLUE + scoreManager.getPosition(new ChallengePlayer(p.getUniqueId())) + ChatUtil.RED + " | " + ChatUtil.GREEN + "Länge deiner Brücke: " + ChatUtil.BLUE + scoreManager.getScore(new ChallengePlayer(p.getUniqueId())) + " Blöcke"); + } + } + } + } + + private void resetBarrier(Player p, World world, List locations) { + for (Location location : locations) { + p.sendBlockChange(location, world.getBlockAt(location).getBlockData()); + } + locations.clear(); + } + + private static boolean isRunning() { + return running; + } + + private static void setRunning(boolean run) { + running = run; + } + + public static boolean isLoaded() { + return load; + } +} diff --git a/src/main/java/de/fanta/challenges/challenges/ChallengeEvents/DeathrunChallengeEvent.java b/src/main/java/de/fanta/challenges/challenges/ChallengeEvents/DeathrunChallengeEvent.java index ccb6210..4147385 100644 --- a/src/main/java/de/fanta/challenges/challenges/ChallengeEvents/DeathrunChallengeEvent.java +++ b/src/main/java/de/fanta/challenges/challenges/ChallengeEvents/DeathrunChallengeEvent.java @@ -260,7 +260,6 @@ } mexico(15, world); mexico(-15, world); - } private void resetBarrier(Player p, World world, List locations) { diff --git a/src/main/java/de/fanta/challenges/guis/eventgui/EventGui.java b/src/main/java/de/fanta/challenges/guis/eventgui/EventGui.java index f1d0806..1e235ef 100644 --- a/src/main/java/de/fanta/challenges/guis/eventgui/EventGui.java +++ b/src/main/java/de/fanta/challenges/guis/eventgui/EventGui.java @@ -1,6 +1,7 @@ package de.fanta.challenges.guis.eventgui; import de.fanta.challenges.Challenges; +import de.fanta.challenges.challenges.ChallengeEvents.BridgeRaceChallengeEvent; import de.fanta.challenges.challenges.ChallengeEvents.DeathrunChallengeEvent; import de.fanta.challenges.utils.ChatUtil; import de.fanta.challenges.utils.Config; @@ -23,6 +24,7 @@ private static final int NULL_EVENT_INDEX = 0; private static final int TEAM_INDEX = 8; + private static final int BRIDGE_RACE_INDEX = 9; private static final int BINGO_EVENT_INDEX = 10; private static final int XP_EVENT_INDEX = 11; private static final int BUILD_EVENT_INDEX = 12; @@ -32,7 +34,7 @@ private static final int ORE_BATTLE_INDEX = 16; private static final int FORCE_ITEM_INDEX = 17; //TODO muss noch schön gemacht werden. - private static final int EVENT_SETTINGS_INDEX = 18; + private static final int EVENT_SETTINGS_INDEX = 18; private static final int BINGO_ITEMS_INDEX = 19; private static final int SAMMEL_FIEBER_SETTINGS_INDEX = 24; private static final int CLOSE_IDEX = 26; @@ -84,6 +86,11 @@ } else { EVENT_GUI.setItem(FORCE_ITEM_INDEX, GUIUtils.createGuiItem(Material.DIAMOND_BLOCK, ChatUtil.RED + "Force Item Event", ChatUtil.GREEN + "Farm so viele Blöcke wie möglich.")); } + if (Objects.equals(Config.getString("event.type"), "bridgerace")) { + EVENT_GUI.setItem(BRIDGE_RACE_INDEX, GUIUtils.createGuiItem(Material.SCAFFOLDING, ChatUtil.GREEN + "Bridge Race Event", true, ChatUtil.GREEN + "Komme so weit wie möglich.")); + } else { + EVENT_GUI.setItem(BRIDGE_RACE_INDEX, GUIUtils.createGuiItem(Material.SCAFFOLDING, ChatUtil.RED + "Bridge Race Event", ChatUtil.GREEN + "Komme so weit wie möglich.")); + } if (Objects.equals(Config.getString("event.type"), "sammelfieber")) { EVENT_GUI.setItem(SAMMEL_FIEBER_INDEX, GUIUtils.createGuiItem(Material.HOPPER, ChatUtil.GREEN + "Sammel Fieber Event", true, ChatUtil.GREEN + "Sammle so viel Items wie möglich!")); EVENT_GUI.setItem(SAMMEL_FIEBER_SETTINGS_INDEX, GUIUtils.createGuiItem(Material.NETHER_STAR, ChatUtil.GREEN + "Sammel Fieber Event Settings")); @@ -148,6 +155,12 @@ Config.setValue("event.type", "forceitem"); ChatUtil.sendTitleToAll("Event", "Force Item", ChatUtil.GREEN); } + case BRIDGE_RACE_INDEX -> { + if (BridgeRaceChallengeEvent.load(p)) { + Config.setValue("event.type", "bridgerace"); + ChatUtil.sendTitleToAll("Event", "Bridge Race", ChatUtil.GREEN); + } + } } createEventGUI(p); diff --git a/src/main/java/de/fanta/challenges/listeners/EventRegistration.java b/src/main/java/de/fanta/challenges/listeners/EventRegistration.java index bc95488..33ed4b8 100644 --- a/src/main/java/de/fanta/challenges/listeners/EventRegistration.java +++ b/src/main/java/de/fanta/challenges/listeners/EventRegistration.java @@ -5,6 +5,7 @@ import de.fanta.challenges.challenges.AllAdvancementsChallenge; import de.fanta.challenges.challenges.BedrockWallChallenge; import de.fanta.challenges.challenges.ChallengeEvents.BingoChallengeEvent; +import de.fanta.challenges.challenges.ChallengeEvents.BridgeRaceChallengeEvent; import de.fanta.challenges.challenges.ChallengeEvents.DeathrunChallengeEvent; import de.fanta.challenges.challenges.ChallengeEvents.ForceItemChallengeEvent; import de.fanta.challenges.challenges.ChallengeEvents.OreBattleChallengeEvent; @@ -98,6 +99,7 @@ pM.registerEvents(new ForceItemChallengeEvent(), plugin); pM.registerEvents(new AllAdvancementsChallenge(), plugin); pM.registerEvents(new MobRemoveWorldChallenge(), plugin); + pM.registerEvents(new BridgeRaceChallengeEvent(), plugin); if (plugin.getProtocolVersion() >= 759) { pM.registerEvents(new WorldBorderLevelChallenge(), plugin); diff --git a/src/main/java/de/fanta/challenges/listeners/PlayerListener.java b/src/main/java/de/fanta/challenges/listeners/PlayerListener.java index ff5e5ab..1d2957a 100644 --- a/src/main/java/de/fanta/challenges/listeners/PlayerListener.java +++ b/src/main/java/de/fanta/challenges/listeners/PlayerListener.java @@ -2,6 +2,7 @@ import de.fanta.challenges.Challenges; import de.fanta.challenges.ServerType; +import de.fanta.challenges.challenges.ChallengeEvents.BridgeRaceChallengeEvent; import de.fanta.challenges.events.PlayerCountChangedEvent; import de.fanta.challenges.scoreboard.ChallengePlayer; import de.fanta.challenges.utils.ChatUtil; @@ -88,6 +89,10 @@ @EventHandler public void onPayerMove(PlayerMoveEvent e) { + if (BridgeRaceChallengeEvent.isLoaded()) { + return; + } + Player player = e.getPlayer(); Location playerloc = player.getLocation(); if (!Config.getBoolean("firsttimerstart") && plugin.getServerType() != ServerType.ADVENTURE) {