Newer
Older
ChallengeSystem / Challenge / src / main / java / de / fanta / challenge / challenges / MLGChallenge.java
@fanta fanta on 7 Jun 2024 10 KB ja
package de.fanta.challenge.challenges;

import de.fanta.challenge.Challenge;
import de.fanta.challenge.events.TimerChangedEvent;
import de.fanta.challenge.gravestones.GravestoneUtils;
import de.fanta.challenge.schedular.CancellableTask;
import de.fanta.challenge.utils.ChatUtil;
import de.fanta.challenge.utils.Config;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.GameRule;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.WorldType;
import org.bukkit.entity.Player;
import org.bukkit.entity.SpawnCategory;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityMountEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.ItemStack;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.UUID;

public class MLGChallenge implements Listener {

    private static final Challenge plugin = Challenge.getPlugin();

    private static final Random random = new Random();
    private static boolean MLGinProgress;
    private static boolean running;
    private static CancellableTask task;
    private static final HashMap<UUID, MLGInfo> mlgPlayerMap = new HashMap<>();
    private static int timeSinceMLG; // seconds+
    private static Location mlgLocation;
    private static final ArrayList<Material> mlgBlocks = new ArrayList<>();

    @EventHandler
    public void onTimerChange(TimerChangedEvent e) {
        if (Config.getBoolean("mlg.enabled")) {
            if (e.isRunning()) {
                setRunning(true);
                startTask();
            } else {
                setRunning(false);
                stopTask();
            }
        }
    }

    @EventHandler
    public void onPlayerDeath(PlayerDeathEvent e) {
        if (isMLGinProgress() && e.getPlayer().getWorld().getName().equals("mlg_challenge")) {
            if (mlgPlayerMap.containsKey(e.getPlayer().getUniqueId())) {
                mlgResult(e.getPlayer(), true);
                plugin.getScheduler().runDelayedOnEntity(e.getPlayer(), () -> e.getPlayer().spigot().respawn(), 1L);
            }
        }
    }

    @EventHandler
    public void onTeleport(PlayerTeleportEvent e) {
        if (isMLGinProgress() && e.getFrom().getWorld().getName().equals("mlg_challenge")) {
            if (mlgPlayerMap.containsKey(e.getPlayer().getUniqueId())) {
                mlgResult(e.getPlayer(), true);
            }
        }
    }

    @EventHandler
    public void onGameModeChange(PlayerGameModeChangeEvent e) {
        if (isMLGinProgress() && e.getPlayer().getWorld().getName().equals("mlg_challenge")) {
            if (mlgPlayerMap.containsKey(e.getPlayer().getUniqueId())) {
                mlgResult(e.getPlayer(), true);
            }
        }
    }

    @EventHandler
    public void onDisconnect(PlayerQuitEvent e) {
        if (isMLGinProgress() && e.getPlayer().getWorld().getName().equals("mlg_challenge")) {
            if (mlgPlayerMap.containsKey(e.getPlayer().getUniqueId())) {
                mlgResult(e.getPlayer(), true);
            }
        }
    }

    @EventHandler
    public void onBucketEmpty(PlayerBucketEmptyEvent e) {
        if (isMLGinProgress() && e.getPlayer().getWorld().getName().equals("mlg_challenge")) {
            plugin.getScheduler().runLocalDelayed(e.getBlock().getLocation(), () -> {
                if (mlgPlayerMap.containsKey(e.getPlayer().getUniqueId()) && !e.getPlayer().isDead()) {
                    mlgResult(e.getPlayer(), false);
                }
            }, 40L);
        }
    }

    @EventHandler
    public void onBlockPlace(BlockPlaceEvent e) {
        if (isMLGinProgress() && e.getPlayer().getWorld().getName().equals("mlg_challenge")) {
            plugin.getScheduler().runLocalDelayed(e.getBlock().getLocation(), () -> {
                if (mlgPlayerMap.containsKey(e.getPlayer().getUniqueId()) && !e.getPlayer().isDead()) {
                    mlgResult(e.getPlayer(), false);
                }
            }, 40L);
        }
    }

    @EventHandler
    public void onEntityMount(EntityMountEvent e) {
        if (isMLGinProgress() && e.getMount().getWorld().getName().equals("mlg_challenge")) {
            if (e.getEntity() instanceof Player player) {
                plugin.getScheduler().runDelayedOnEntity(e.getMount(), () -> {
                    if (mlgPlayerMap.containsKey(player.getUniqueId()) && !player.isDead()) {
                        mlgResult(player, false);
                    }
                }, 40L);
            }
        }
    }

    public static void checkMLGWorld() {
        World mlgWorld = Bukkit.getWorld("mlg_challenge");
        if (mlgWorld == null) {
            mlgWorld = Bukkit.createWorld((new WorldCreator("mlg_challenge")).type(WorldType.FLAT).generateStructures(false));
            mlgWorld.setSpawnLimit(SpawnCategory.ANIMAL, 0);
            mlgWorld.setGameRule(GameRule.DO_MOB_SPAWNING, false);
            mlgWorld.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false);
            mlgWorld.setGameRule(GameRule.DO_WEATHER_CYCLE, false);
            mlgWorld.setGameRule(GameRule.KEEP_INVENTORY, true);
            mlgWorld.setTime(6000L);
        }
    }

    public static boolean triggerMLG() {
        if (isRunning() && !MLGinProgress && !plugin.getVanish().getPlayerListWithoutVanishPlayers().isEmpty()) {
            timeSinceMLG = 0;
            mlgPlayerMap.clear();
            for (Player p : plugin.getVanish().getPlayerListWithoutVanishPlayers()) {
                if (p.getGameMode() == GameMode.SURVIVAL && !p.isDead()) {
                    MLGInfo mlgInfo = new MLGInfo(p.getInventory().getContents(), p.getLocation());
                    mlgPlayerMap.put(p.getUniqueId(), mlgInfo);
                    ChatUtil.sendNormalMessage(p, "Zeit für einen MLG! Viel Glück!");
                    p.getInventory().clear();
                    tpMLG(p);
                }
            }
            if (!mlgPlayerMap.isEmpty()) {
                setMLGinProgress(true);
            }

            return true;
        }
        return false;
    }

    private static void tpMLG(Player p) {
        p.closeInventory();
        if (Config.getBoolean("mlg.randommlgblock")) {
            if (mlgBlocks.isEmpty()) {
                mlgBlocks.add(Material.WATER_BUCKET);
                mlgBlocks.add(Material.SLIME_BLOCK);
                mlgBlocks.add(Material.OAK_BOAT);
                mlgBlocks.add(Material.SCAFFOLDING);
                mlgBlocks.add(Material.SWEET_BERRIES);
                mlgBlocks.add(Material.POWDER_SNOW_BUCKET);
                mlgBlocks.add(Material.COBWEB);
                mlgBlocks.add(Material.TWISTING_VINES);
            }
            Material mlgItem = mlgBlocks.get(random.nextInt(mlgBlocks.size()));
            plugin.getScheduler().runDelayedOnEntity(p, () -> p.getInventory().setItemInMainHand(new ItemStack(mlgItem)), 1L);
        } else {
            plugin.getScheduler().runDelayedOnEntity(p, () -> p.getInventory().setItemInMainHand(new ItemStack(Material.WATER_BUCKET)), 1L);
        }

        if (mlgLocation == null) {
            mlgLocation = new Location(Bukkit.getWorld("mlg_challenge"), 0, 0, 0);
        }

        mlgLocation.add(100, 0, 0);
        Location newloc = mlgLocation.clone();
        newloc.add(0.5, 0, 0.5);
        newloc.setY(100 + random.nextInt(40));
        p.teleportAsync(newloc);
    }

    private static void mlgResult(Player p, boolean dead) {
        MLGInfo mlgInfo = mlgPlayerMap.get(p.getUniqueId());
        mlgPlayerMap.remove(p.getUniqueId());
        Location loc = mlgInfo.location();
        ItemStack[] content = mlgInfo.content();
        if (!dead) {
            p.setInvulnerable(true);
            mlgBack(p, loc, content);
            ChatUtil.sendNormalMessage(p, "Du hast den MLG erfolgreich absolviert! Weitere folgen...");
        } else {
            p.getInventory().clear();
            if (Bukkit.getWorlds().getFirst().getGameRuleValue(GameRule.KEEP_INVENTORY)) {
                p.getInventory().setContents(content);
            } else if (Config.getBoolean("gravestone")) {
                String inventoryString = GravestoneUtils.createInventoryString(content);
                GravestoneUtils.spawnAtBlock(loc.getBlock(), p, GravestoneUtils.compressString(inventoryString));
            } else {
                for (ItemStack stack : content) {
                    if (stack != null) {
                        loc.getWorld().dropItemNaturally(loc, stack);
                    }
                }
            }
        }

        if (mlgPlayerMap.isEmpty()) {
            plugin.getScheduler().runGlobalDelayed(() -> setMLGinProgress(false), 60L);
        }
    }

    private static void mlgBack(final Player p, Location loc, ItemStack[] content) {
        p.teleportAsync(loc);
        p.getInventory().setContents(content);
        plugin.getScheduler().runDelayedOnEntity(p, () -> p.setInvulnerable(false), 60L);
    }

    private static void tick() {
        if (!mlgPlayerMap.isEmpty()) {
            return;
        }
        int randomInt = random.nextInt(Config.getInt("mlg.maxtime"));
        timeSinceMLG++;
        if (randomInt == 0 || timeSinceMLG >= Config.getInt("mlg.maxtime")) {
            triggerMLG();
        }
    }

    public static boolean isRunning() {
        return running;
    }

    public static void setRunning(boolean running) {
        MLGChallenge.running = running;
    }

    private static boolean isMLGinProgress() {
        return MLGinProgress;
    }

    public static void setMLGinProgress(boolean MLGinProgress) {
        MLGChallenge.MLGinProgress = MLGinProgress;
    }

    public static void startTask() {
        if (task == null && plugin.getTimer().isRunning()) {
            task = plugin.getScheduler().runGlobalAtFixedRate(MLGChallenge::tick, 20L, 20L);
        }
    }

    public static void stopTask() {
        if (task != null) {
            task.cancel();
            task = null;
        }
    }

    record MLGInfo(ItemStack[] content, Location location) {
    }
}