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) {
}
}