From b55035f1f021659d59faf9d7faa7daf9be80950f Mon Sep 17 00:00:00 2001 From: lars Date: Sat, 1 Nov 2025 17:29:39 +0100 Subject: [PATCH] added timings and announcements for automatic bloodmoon start --- .../gameplay/bloodmoon/Bloodmoon.java | 65 ++++++++++++++++--- .../listener/BloodmoonPlayerJoinListener.java | 1 + .../listener/BloodmoonTimeListener.java | 28 ++++++++ 3 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/listener/BloodmoonTimeListener.java diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/Bloodmoon.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/Bloodmoon.java index b7de9a3..dc1b1cf 100644 --- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/Bloodmoon.java +++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/Bloodmoon.java @@ -8,9 +8,11 @@ import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.comma import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonEntityDamageListener; import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonMonsterDeathListener; import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonPlayerJoinListener; +import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonTimeListener; import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; @@ -86,9 +88,11 @@ public class Bloodmoon extends Appliance { EntityType.SPIDER ); private @Nullable BukkitTask hordeSpawnTask = null; - private final int bloodmoonLegth = 12000; + public final int bloodmoonLength = 12000; + public final int ticksPerDay = 24000; + private final int bloodmoonFreeDaysAtStart = 3; private final int bloodmoonStartTime = 12000; - private final int daysBetweenBloodmoons = 1; + private final int bloodmoonDayInterval = 2; private final int minBonusDrops = 1; private final int maxBonusDrops = 4; private final Map bonusDropWeightMap = Map.of( @@ -112,6 +116,20 @@ public class Bloodmoon extends Appliance { this.isActive = true; Bukkit.getOnlinePlayers().forEach(this::addPlayerToBossBar); this.startHordeSpawning(this.getRandomHordeSpawnDelay()); + this.sendStartMessages(); + } + + public void stopBloodmoon() { + this.isActive = false; + Bukkit.getOnlinePlayers().forEach(player -> player.hideBossBar(this.bossBar)); + this.sendStopMessages(); + } + + public boolean isStartTick(long tick) { + long day = tick / this.ticksPerDay; + if(day % this.bloodmoonDayInterval != 0 || day - this.bloodmoonFreeDaysAtStart <= 0) return false; + long time = tick - (day * this.ticksPerDay); + return time == this.bloodmoonStartTime; } private int getRandomHordeSpawnDelay() { @@ -131,11 +149,6 @@ public class Bloodmoon extends Appliance { ); } - public void stopBloodmoon() { - this.isActive = false; - Bukkit.getOnlinePlayers().forEach(player -> player.hideBossBar(this.bossBar)); - } - public void addPlayerToBossBar(Player player) { if(!this.getBloodmoonSetting(player)) return; player.showBossBar(this.bossBar); @@ -167,6 +180,18 @@ public class Bloodmoon extends Appliance { this.spawnHorde(player, hordeSize, hordeEntityType); } + public void sendWarningMessage(Player p) { + p.sendMessage(Component.text("Der Blutmond waltet in diesem Augenblick!", NamedTextColor.RED)); + } + + public void sendAnnouncementMessages() { + this.sendMessage(Component.text("Der Blutmond naht; morgen wird er den Himmel beherrschen", NamedTextColor.GOLD)); + } + + public void sendPreStartMessages() { + this.sendMessage(Component.text("Der Himmel ist heute Nacht ungewöhnlich düster", NamedTextColor.DARK_PURPLE)); + } + private void spawnHorde(Player player, int size, EntityType type) { for(int i = 0; i < size; i++) { double spawnRadiant = ThreadLocalRandom.current().nextDouble(0, 2*Math.PI); @@ -201,12 +226,36 @@ public class Bloodmoon extends Appliance { return null; } + private void sendMessage(Component message) { + if(Bukkit.getOnlinePlayers().isEmpty()) return; + List onlinePlayers = Bukkit.getOnlinePlayers().stream() + .filter(this::getBloodmoonSetting) + .toList(); + onlinePlayers.forEach(player -> player.sendMessage(message)); + } + + private void sendStartMessages() { + this.sendMessage( + Component.empty() + .append(Component.text("Der Blutmond ist über uns", NamedTextColor.DARK_RED, TextDecoration.BOLD)) + .appendNewline() + .append(Component.text("Erfahrung vervielfacht sich und Mobs lassen reichere Beute fallen", NamedTextColor.RED)) + .appendNewline() + .append(Component.text("Mobs sind erstarkt und belegen dich mit finsteren Debuffs", NamedTextColor.RED)) + ); + } + + private void sendStopMessages() { + this.sendMessage(Component.text("Der Blutmond weicht...", NamedTextColor.GREEN, TextDecoration.BOLD)); + } + @Override protected @NotNull List listeners() { return List.of( new BloodmoonMonsterDeathListener(), new BloodmoonPlayerJoinListener(), - new BloodmoonEntityDamageListener() + new BloodmoonEntityDamageListener(), + new BloodmoonTimeListener() ); } diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/listener/BloodmoonPlayerJoinListener.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/listener/BloodmoonPlayerJoinListener.java index 61da747..30c575e 100644 --- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/listener/BloodmoonPlayerJoinListener.java +++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/listener/BloodmoonPlayerJoinListener.java @@ -10,5 +10,6 @@ public class BloodmoonPlayerJoinListener extends ApplianceListener { public void onPlayerJoin(PlayerJoinEvent event) { if(!this.getAppliance().bloodmoonIsActive()) return; this.getAppliance().addPlayerToBossBar(event.getPlayer()); + this.getAppliance().sendWarningMessage(event.getPlayer()); } } diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/listener/BloodmoonTimeListener.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/listener/BloodmoonTimeListener.java new file mode 100644 index 0000000..13325e3 --- /dev/null +++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/listener/BloodmoonTimeListener.java @@ -0,0 +1,28 @@ +package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener; + +import com.destroystokyo.paper.event.server.ServerTickStartEvent; +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener; +import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.Bloodmoon; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; + +public class BloodmoonTimeListener extends ApplianceListener { + @EventHandler + public void onServerTick(ServerTickStartEvent event) { + if(this.getAppliance().isStartTick(Bukkit.getWorlds().getFirst().getFullTime())) { + this.getAppliance().startBloodmoon(); + return; + } + if(this.getAppliance().isStartTick(Bukkit.getWorlds().getFirst().getFullTime() - this.getAppliance().bloodmoonLength)) { + this.getAppliance().stopBloodmoon(); + return; + } + if(this.getAppliance().isStartTick(Bukkit.getWorlds().getFirst().getFullTime() + this.getAppliance().ticksPerDay)) { + this.getAppliance().sendAnnouncementMessages(); + return; + } + if(this.getAppliance().isStartTick(Bukkit.getWorlds().getFirst().getFullTime() + 1000)) { + this.getAppliance().sendPreStartMessages(); + } + } +}