Newer
Older
ChallengeSystem / src / main / java / de / fanta / challenges / challenges / DeathrunChallengeEvent.java
@fanta fanta on 20 Mar 2022 9 KB Fix Deathrunevent
package de.fanta.challenges.challenges;

import de.fanta.challenges.Challenges;
import de.fanta.challenges.events.TimerChangedEvent;
import de.fanta.challenges.scoreboard.ScoreManager;
import de.fanta.challenges.utils.ChatSkullAPI.ChatSkull;
import de.fanta.challenges.utils.ChatUtil;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.GameRule;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.block.Block;
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.block.BlockBreakEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerPortalEvent;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

public class DeathrunChallengeEvent implements Listener {

    private final Challenges plugin = Challenges.getPlugin();

    private static final List<String> deadPlayer = new ArrayList<>();
    private final Map<Player, BossBar> bossBarMap = new HashMap<>();

    public static Location spawnLocation;
    private final Map<UUID, List<Location>> currentBarrier = new HashMap<>();
    private static final Material barrierBlock = Material.GLASS;

    @EventHandler
    public void onMove(PlayerMoveEvent e) {
        Player p = e.getPlayer();
        World world = p.getWorld();
        if (Objects.equals(plugin.getConfig().getString("event.type"), "deathrun") && plugin.getTimer().isRunning() && !plugin.getVanish().isVanish(p) && p.getGameMode() != GameMode.SPECTATOR) {
            if (!deadPlayer.contains(p.getUniqueId().toString())) {
                if (!e.getTo().equals(e.getFrom())) {
                    int distance = (int) p.getLocation().toVector().subtract(p.getWorld().getSpawnLocation().toVector()).length();
                    ScoreManager scoreManager = plugin.getScoreManager();
                    scoreManager.setScore(p, distance);

                    BossBar bossBar = bossBarMap.computeIfAbsent(p, player -> {
                        BossBar newBossBar = Bukkit.createBossBar(ChatUtil.GREEN + "Position: " + ChatUtil.BLUE + (scoreManager.getPlayerPosition(p) + 1) + ChatUtil.RED + " | " + ChatUtil.GREEN + " Distanz zum Spawn: " + ChatUtil.BLUE + distance + " Blöcke", BarColor.GREEN, BarStyle.SOLID);
                        newBossBar.setVisible(true);
                        newBossBar.addPlayer(p);
                        return newBossBar;
                    });

                    bossBar.setTitle(ChatUtil.GREEN + "Position: " + ChatUtil.BLUE + (scoreManager.getPlayerPosition(p) + 1) + ChatUtil.RED + " | " + ChatUtil.GREEN + " Distanz zum Spawn: " + ChatUtil.BLUE + distance + " Blöcke");

                }

                Location playerLoc = p.getLocation();
                double posRelatedToCenter = playerLoc.getZ() - spawnLocation.getZ();
                double distanceToCenter = Math.abs(posRelatedToCenter);

                List<Location> barrierLocations = currentBarrier.computeIfAbsent(p.getUniqueId(), uuid -> new ArrayList<>());

                int BARRIER_POS = 15;
                int BARRIER_SIZE = 6;
                if (distanceToCenter >= BARRIER_POS) { //Outside border
                    p.damage(0.5);
                } else if (distanceToCenter >= BARRIER_POS - 4) { //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);
                }

                if (playerLoc.getY() > world.getMaxHeight() - 1) {
                    p.damage(1);
                }
            }
        }
    }

    @EventHandler
    public void onDamage(EntityDamageEvent e) {
        if (e.getEntity() instanceof Player p) {
            if (Objects.equals(plugin.getConfig().getString("event.type"), "deathrun") && plugin.getTimer().isRunning()) {
                Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> {
                    p.setWalkSpeed((float) (p.getHealth() / 100f));
                }, 1L);
            }
        }
    }

    @EventHandler
    public void onDeath(PlayerDeathEvent e) {
        Player p = e.getEntity();
        if (Objects.equals(plugin.getConfig().getString("event.type"), "deathrun") && plugin.getTimer().isRunning()) {
            deadPlayer.add(p.getUniqueId().toString());
            plugin.getSBManager().removeScoreboard(p);
            if (plugin.getSBManager().countScoreboardPlayers() == 0) {
                plugin.getTimer().stopTimer();
                ChatUtil.sendBrodcastMessage("Das Event wurde beendet, da alle Spieler gestorben sind!");
            }
        }
    }

    @EventHandler
    public void onPortalUse(PlayerPortalEvent e) {
        if (Objects.equals(plugin.getConfig().getString("event.type"), "deathrun")) {
            e.setCancelled(true);
        }
    }

    @EventHandler
    public void onTimerChange(TimerChangedEvent e) {
        if (Objects.equals(plugin.getConfig().getString("event.type"), "deathrun")) {
            if (!e.isRunning()) {
                Map.Entry<String, Integer> maxEntry = plugin.getScoreManager().getScores().entrySet().stream().max(Map.Entry.comparingByValue()).get();
                OfflinePlayer p = (Bukkit.getServer().getOfflinePlayer(maxEntry.getKey()));
                if (p.isOnline()) {
                    String[] lines = {"", "", "", "    " + ChatUtil.BLUE + p.getName(), ChatUtil.GREEN + "    ist " + maxEntry.getValue() + " Blöcke gelaufen und", ChatUtil.GREEN + "    hat damit gewonnen!", "", ""};
                    ChatSkull.sendAll((Player) p, lines);
                } else {
                    ChatUtil.sendBrodcastMessage(ChatUtil.BLUE + maxEntry.getKey() + ChatUtil.GREEN + " ist " + maxEntry.getValue() + " Blöcke gelaufen und hat damit gewonnen!", ChatUtil.BLUE);
                }
            } else {
                World world = Bukkit.getWorld("world");
                world.setGameRule(GameRule.MAX_ENTITY_CRAMMING, Bukkit.getServer().getMaxPlayers());
                for (Player pp : Bukkit.getOnlinePlayers()) {
                    Location spawn = world.getSpawnLocation();
                    spawn.setYaw(-90f);
                    pp.teleport(spawn);
                }
            }
        }
    }

    @EventHandler
    public void onBarrierBreak(BlockBreakEvent e) {
        if (Objects.equals(plugin.getConfig().getString("event.type"), "deathrun")) {
            Block block = e.getBlock();
            Location loc = block.getLocation();
            int x = loc.getBlockX();
            int z = loc.getBlockZ();
            int spawnX = spawnLocation.getBlockX();
            int spawnZ = spawnLocation.getBlockZ();

            int distanceX = spawnX - x;

            if (distanceX > -15 && (Math.abs(distanceX) >= 15 || Math.abs(spawnZ - z) >= 15)) {
                ChatUtil.sendWarningMessage(e.getPlayer(), "Niemand hat die Absicht, eine Mauer zu errichten!");
                e.setCancelled(true);
            }
        }
    }


    public static void load() {
        World world = Bukkit.getWorld("world");
        spawnLocation = world.getSpawnLocation();

        int height = world.getMaxHeight() - world.getMinHeight();
        int width = 30;

        Location loc = spawnLocation.clone().subtract(15, 0, 15);
        loc.setY(world.getMinHeight());
        for (int y = 0; y < height; y++) {
            for (int z = 0; z < width; z++) {
                Block block = loc.clone().add(0, y, z).getBlock();
                if (!block.isSolid()) {
                    block.setType(barrierBlock);
                }
            }
        }
        mexico(15, world);
        mexico(-15, world);

    }

    private void resetBarrier(Player p, World world, List<Location> locations) {
        for (Location location : locations) {
            p.sendBlockChange(location, world.getBlockAt(location).getBlockData());
        }
        locations.clear();
    }

    private static void mexico(int startPos, World world) {
        int height = world.getMaxHeight() - world.getMinHeight();
        int width = 30;
        Location loc = spawnLocation.clone().add(-15, 0, startPos);
        loc.setY(world.getMinHeight());
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                Block block = loc.clone().add(x, y, 0).getBlock();
                if (!block.isSolid()) {
                    block.setType(barrierBlock);
                }
            }
        }
    }

    public static List<String> getDeadPlayer() {
        return deadPlayer;
    }
}