diff --git a/src/main/java/fr/communaywen/core/AywenCraftPlugin.java b/src/main/java/fr/communaywen/core/AywenCraftPlugin.java index 800c331e..568e91f6 100644 --- a/src/main/java/fr/communaywen/core/AywenCraftPlugin.java +++ b/src/main/java/fr/communaywen/core/AywenCraftPlugin.java @@ -35,6 +35,8 @@ import fr.communaywen.core.contest.listeners.*; import fr.communaywen.core.customitems.listeners.*; +import fr.communaywen.core.event.CubeListener; +import fr.communaywen.core.event.CubeManager; import fr.communaywen.core.listeners.*; import fr.communaywen.core.contest.managers.ContestManager; @@ -375,6 +377,7 @@ public void run() { /* LISTENERS */ registerEvents( + new CubeListener(), new ParticleListener(this), new HeadListener(this), new JumpListener(this, jumpManager), @@ -441,6 +444,7 @@ public void run() { ClaimConfigDataBase.processStoredClaimData(); new BandageRecipe(); + new CubeManager(this); // BETTER SPAWN // - Leaderboard @@ -481,6 +485,9 @@ public void onDisable() { jumpManager.removeDisplayJumpStart(); jumpManager.removeDisplayJumpEnd(); + CubeManager.saveCubeLocation(); + CubeManager.clearCube(); + for (Player player : Bukkit.getOnlinePlayers()) { PlayerQuests pq = QuestsManager.getPlayerQuests(player.getUniqueId()); // Load quest progress QuestsManager.savePlayerQuestProgress(player, pq); // Save quest progress diff --git a/src/main/java/fr/communaywen/core/Managers.java b/src/main/java/fr/communaywen/core/Managers.java index 43f01229..3e85a880 100644 --- a/src/main/java/fr/communaywen/core/Managers.java +++ b/src/main/java/fr/communaywen/core/Managers.java @@ -84,6 +84,7 @@ public class Managers { private FileConfiguration levelsConfig; private FileConfiguration quizzesConfig; private FileConfiguration customItemsConfig; + private FileConfiguration kevinConfig; public void initConfig(AywenCraftPlugin plugin) { plugin.saveDefaultConfig(); @@ -93,6 +94,7 @@ public void initConfig(AywenCraftPlugin plugin) { levelsConfig = ConfigUtils.loadConfig(plugin, "levels.yml"); quizzesConfig = ConfigUtils.loadConfig(plugin, "quizzes.yml"); customItemsConfig = ConfigUtils.loadConfig(plugin, "customitems.yml"); + kevinConfig = ConfigUtils.loadConfig(plugin, "cube.yml"); } public void init(AywenCraftPlugin plugin) { diff --git a/src/main/java/fr/communaywen/core/event/CubeListener.java b/src/main/java/fr/communaywen/core/event/CubeListener.java new file mode 100644 index 00000000..aa05474f --- /dev/null +++ b/src/main/java/fr/communaywen/core/event/CubeListener.java @@ -0,0 +1,77 @@ +package fr.communaywen.core.event; + +import org.bukkit.Location; +import org.bukkit.Sound; +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.EntityDamageByEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.util.Vector; + +import static fr.communaywen.core.event.CubeManager.*; + +public class CubeListener implements Listener { + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + Location clickedBlock = event.getClickedBlock() != null ? event.getClickedBlock().getLocation() : null; + if (clickedBlock != null && isCubeBlock(clickedBlock)) { + repulsePlayer(event.getPlayer()); + } + } + + @EventHandler + public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (event.getDamager() instanceof Player player && isCubeBlock(event.getEntity().getLocation())) { + repulsePlayer(player); + } + } + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + if (isCubeBlock(event.getBlock().getLocation())) { + event.setCancelled(true); + } + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + Location belowPlayer = player.getLocation().clone().subtract(0, 1, 0); + + if (isCubeBlock(belowPlayer)) { + Vector velocity = player.getVelocity(); + velocity.setY(1.0); + player.setVelocity(velocity); + + player.playSound(player.getLocation(), Sound.BLOCK_BEACON_POWER_SELECT, 1.0f, 2.0f); + } + } + + + public static boolean isCubeBlock(Location blockLocation) { + int x = blockLocation.getBlockX(); + int y = blockLocation.getBlockY(); + int z = blockLocation.getBlockZ(); + + int cubeX = currentLocation.getBlockX(); + int cubeY = currentLocation.getBlockY(); + int cubeZ = currentLocation.getBlockZ(); + + return x >= cubeX && x < cubeX + CUBE_SIZE && + y >= cubeY && y < cubeY + CUBE_SIZE && + z >= cubeZ && z < cubeZ + CUBE_SIZE && + blockLocation.getBlock().getType() == CUBE_MATERIAL; + } + + private void repulsePlayer(Player player) { + Vector direction = player.getLocation().toVector().subtract(currentLocation.toVector()).normalize(); + direction.multiply(3); + direction.setY(1); + player.setVelocity(direction); + + player.playSound(player.getLocation(), Sound.BLOCK_BEACON_POWER_SELECT, 1.0f, 2.0f); + } +} diff --git a/src/main/java/fr/communaywen/core/event/CubeManager.java b/src/main/java/fr/communaywen/core/event/CubeManager.java new file mode 100644 index 00000000..83b669f0 --- /dev/null +++ b/src/main/java/fr/communaywen/core/event/CubeManager.java @@ -0,0 +1,252 @@ +package fr.communaywen.core.event; + +import fr.communaywen.core.AywenCraftPlugin; +import net.kyori.adventure.text.Component; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarFlag; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; + +import java.io.File; +import java.io.IOException; +import java.util.Random; + +import static fr.communaywen.core.event.CubeListener.isCubeBlock; + +public class CubeManager { + + private static AywenCraftPlugin plugin; + public static Location currentLocation; + public static int CUBE_SIZE = 5; + public static Material CUBE_MATERIAL = Material.LAPIS_BLOCK; + private final int MOVE_DELAY = 18000; // 15 minutes + private final Material CORRUPTION_MATERIAL = Material.WARPED_NYLIUM; + private final int CORRUPTION_RADIUS = 15; + private final Random random = new Random(); + private BossBar bossBar; + + public CubeManager(AywenCraftPlugin plugin) { + this.plugin = plugin; + World world = Bukkit.getWorld("world"); + if (world == null) return; + + int startX = plugin.getManagers().getKevinConfig().getInt("posX", -126); + int startZ = plugin.getManagers().getKevinConfig().getInt("posZ", -87); + int startY = world.getHighestBlockYAt(startX, startZ); + + currentLocation = new Location(world, startX, startY, startZ); + + bossBar = Bukkit.createBossBar("Cube d'OpenMC", BarColor.BLUE, BarStyle.SOLID, BarFlag.CREATE_FOG, BarFlag.DARKEN_SKY); + bossBar.setVisible(true); + + new BukkitRunnable() { + + @Override + public void run() { + moveCube(); + } + }.runTaskTimer(plugin, 0, MOVE_DELAY); + + startBossBarUpdater(); + + startMobSpawnTask(); + } + + private void startBossBarUpdater() { + new BukkitRunnable() { + @Override + public void run() { + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.getWorld().equals(currentLocation.getWorld())) { + double distance = player.getLocation().distance(currentLocation); + + if (distance <= 100) { + if (!bossBar.getPlayers().contains(player)) { + bossBar.addPlayer(player); + } + } else { + bossBar.removePlayer(player); + } + } + } + } + }.runTaskTimer(plugin, 0, 20); + } + + private void startMobSpawnTask() { + new BukkitRunnable() { + @Override + public void run() { + spawnMobsAroundCube(); + } + }.runTaskTimer(plugin, 0, 6000); // 6000 ticks = 5 minutes + } + + private void spawnMobsAroundCube() { + World world = currentLocation.getWorld(); + int baseX = currentLocation.getBlockX(); + int baseY = currentLocation.getBlockY(); + int baseZ = currentLocation.getBlockZ(); + + int mobsToSpawn = random.nextInt(5) + 15; + + for (int i = 0; i < mobsToSpawn; i++) { + int x = baseX + random.nextInt(CORRUPTION_RADIUS * 2) - CORRUPTION_RADIUS; + int z = baseZ + random.nextInt(CORRUPTION_RADIUS * 2) - CORRUPTION_RADIUS; + int y = world.getHighestBlockYAt(x, z); + + Location spawnLocation = new Location(world, x, y, z); + + if (spawnLocation.distance(currentLocation) <= CORRUPTION_RADIUS) { + EntityType mobType = random.nextBoolean() ? EntityType.ZOMBIE : EntityType.SKELETON; + LivingEntity entity = (LivingEntity) world.spawnEntity(spawnLocation, mobType); + + entity.getEquipment().setHelmet(new ItemStack(Material.LAPIS_BLOCK)); + entity.getEquipment().setHelmetDropChance(0); + + entity.addPotionEffect(new PotionEffect(PotionEffectType.STRENGTH, Integer.MAX_VALUE, 1)); + entity.addPotionEffect(new PotionEffect(PotionEffectType.RESISTANCE, Integer.MAX_VALUE, 1)); + entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 1)); + entity.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, Integer.MAX_VALUE, 0)); + + entity.getEquipment().setChestplate(new ItemStack(Material.IRON_CHESTPLATE)); + entity.getEquipment().setChestplateDropChance(0); + entity.getEquipment().setBoots(new ItemStack(Material.IRON_BOOTS)); + entity.getEquipment().setBootsDropChance(0); + + if (mobType == EntityType.SKELETON) { + Skeleton skeleton = (Skeleton) entity; + skeleton.getEquipment().setItemInMainHand(new ItemStack(Material.BOW)); + skeleton.getEquipment().setItemInMainHandDropChance(0); + } + } + } + } + + private void createCube(Location location) { + for (int x = 0; x < CUBE_SIZE; x++) { + for (int y = 0; y < CUBE_SIZE; y++) { + for (int z = 0; z < CUBE_SIZE; z++) { + location.clone().add(x, y, z).getBlock().setType(CUBE_MATERIAL); + } + } + } + } + + private void clearCube(Location location) { + for (int x = 0; x < CUBE_SIZE; x++) { + for (int y = 0; y < CUBE_SIZE; y++) { + for (int z = 0; z < CUBE_SIZE; z++) { + location.clone().add(x, y, z).getBlock().setType(Material.AIR); + } + } + } + } + + private int lastDirection = -1; + + private void moveCube() { + clearCube(currentLocation); + + int direction; + do { + direction = random.nextInt(4); + } while ((lastDirection == 0 && direction == 1) || (lastDirection == 1 && direction == 0) || + (lastDirection == 2 && direction == 3) || (lastDirection == 3 && direction == 2)); + + lastDirection = direction; + + int newX = currentLocation.getBlockX(); + int newZ = currentLocation.getBlockZ(); + + switch (direction) { + case 0 -> newX += CUBE_SIZE; + case 1 -> newX -= CUBE_SIZE; + case 2 -> newZ += CUBE_SIZE; + case 3 -> newZ -= CUBE_SIZE; + } + + World world = currentLocation.getWorld(); + int newY = world.getHighestBlockYAt(newX, newZ); + + currentLocation.setX(newX); + currentLocation.setY(newY+1); + currentLocation.setZ(newZ); + + world.playSound(currentLocation, Sound.BLOCK_BEACON_ACTIVATE, 100, 1.0f); + + Bukkit.broadcast(Component.text("§9Le Cube §7s'est déplacé en §f" + currentLocation.x() + " " + currentLocation.y() + " " + currentLocation.z())); + createCube(currentLocation); + corruptAreaAroundCube(); + } + + private void corruptAreaAroundCube() { + World world = currentLocation.getWorld(); + int baseX = currentLocation.getBlockX(); + int baseY = currentLocation.getBlockY(); + int baseZ = currentLocation.getBlockZ(); + + int corruptionStartX = baseX - CORRUPTION_RADIUS; + int corruptionEndX = baseX + CUBE_SIZE + CORRUPTION_RADIUS; + int corruptionStartZ = baseZ - CORRUPTION_RADIUS; + int corruptionEndZ = baseZ + CUBE_SIZE + CORRUPTION_RADIUS; + + for (int x = corruptionStartX; x < corruptionEndX; x++) { + for (int z = corruptionStartZ; z < corruptionEndZ; z++) { + for (int yOffset = -1; yOffset <= 5; yOffset++) { + Location targetLocation = new Location(world, x, baseY + yOffset, z); + + if (targetLocation.getBlock().getType().isSolid() && !isCubeBlock(targetLocation) && random.nextDouble() < 0.4) { + targetLocation.getBlock().setType(CORRUPTION_MATERIAL); + + if (targetLocation.getBlock().getType() == CORRUPTION_MATERIAL) { + applyBoneMealEffect(targetLocation); + } + } + } + } + } + } + + private void applyBoneMealEffect(Location location) { + Block block = location.getBlock(); + + + if (block.getType() == Material.WARPED_NYLIUM || block.getType() == Material.CRIMSON_NYLIUM) { + block.applyBoneMeal(BlockFace.UP); + } + } + + public static void clearCube() { + for (int x = 0; x < CUBE_SIZE; x++) { + for (int y = 0; y < CUBE_SIZE; y++) { + for (int z = 0; z < CUBE_SIZE; z++) { + currentLocation.clone().add(x, y, z).getBlock().setType(Material.AIR); + } + } + } + } + + public static void saveCubeLocation() { + plugin.getManagers().getKevinConfig().set("posX", currentLocation.getBlockX()); + plugin.getManagers().getKevinConfig().set("posY", currentLocation.getBlockY()); + plugin.getManagers().getKevinConfig().set("posZ", currentLocation.getBlockZ()); + try { + plugin.getManagers().getKevinConfig().save(new File(plugin.getDataFolder(), "cube.yml")); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/resources/cube.yml b/src/main/resources/cube.yml new file mode 100644 index 00000000..3b16b965 --- /dev/null +++ b/src/main/resources/cube.yml @@ -0,0 +1,3 @@ +posX: -126 +posY: 0 +posZ: -87 \ No newline at end of file