3 Commits

Author SHA1 Message Date
53dbeff829 merged automatic start with hordes per player 2025-11-01 17:43:35 +01:00
b5da06fd49 Merge remote-tracking branch 'origin/develop-bloodmoon' into develop-bloodmoon
# Conflicts:
#	craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/bloodmoon/Bloodmoon.java
2025-11-01 17:32:36 +01:00
b55035f1f0 added timings and announcements for automatic bloodmoon start 2025-11-01 17:29:39 +01:00
3 changed files with 89 additions and 10 deletions

View File

@@ -8,10 +8,13 @@ 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.BloodmoonEntityDamageListener;
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonMonsterDeathListener; 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.BloodmoonPlayerJoinListener;
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonTimeListener;
import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.bossbar.BossBar;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@@ -85,9 +88,11 @@ public class Bloodmoon extends Appliance {
EntityType.SPIDER EntityType.SPIDER
); );
private final Map<Player, @Nullable BukkitTask> hordeSpawnTasks = new HashMap<>(); private final Map<Player, @Nullable BukkitTask> hordeSpawnTasks = new HashMap<>();
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 bloodmoonStartTime = 12000;
private final int daysBetweenBloodmoons = 1; private final int bloodmoonDayInterval = 2;
private final int minBonusDrops = 1; private final int minBonusDrops = 1;
private final int maxBonusDrops = 4; private final int maxBonusDrops = 4;
private final Map<ItemStack, Integer> bonusDropWeightMap = Map.of( private final Map<ItemStack, Integer> bonusDropWeightMap = Map.of(
@@ -111,6 +116,20 @@ public class Bloodmoon extends Appliance {
this.isActive = true; this.isActive = true;
Bukkit.getOnlinePlayers().forEach(this::addPlayerToBossBar); Bukkit.getOnlinePlayers().forEach(this::addPlayerToBossBar);
this.startHordeSpawning(this.getRandomHordeSpawnDelay()); 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() { private int getRandomHordeSpawnDelay() {
@@ -129,18 +148,13 @@ public class Bloodmoon extends Appliance {
() -> { () -> {
if(!this.bloodmoonIsActive()) return; if(!this.bloodmoonIsActive()) return;
this.spawnRandomHorde(); this.spawnRandomHorde();
this.startHordeSpawning(this.getRandomHordeSpawnDelay()); this.startHordeSpawning(this.getRandomHordeSpawnDelay(), player);
}, },
delay delay
); );
this.hordeSpawnTasks.put(player, task); this.hordeSpawnTasks.put(player, task);
} }
public void stopBloodmoon() {
this.isActive = false;
Bukkit.getOnlinePlayers().forEach(player -> player.hideBossBar(this.bossBar));
}
public void addPlayerToBossBar(Player player) { public void addPlayerToBossBar(Player player) {
if(!this.getBloodmoonSetting(player)) return; if(!this.getBloodmoonSetting(player)) return;
player.showBossBar(this.bossBar); player.showBossBar(this.bossBar);
@@ -163,7 +177,7 @@ public class Bloodmoon extends Appliance {
if(!this.hordesEnabled) return; if(!this.hordesEnabled) return;
List<? extends Player> onlinePlayerList = Bukkit.getOnlinePlayers().stream() List<? extends Player> onlinePlayerList = Bukkit.getOnlinePlayers().stream()
.filter(this::getBloodmoonSetting) .filter(this::getBloodmoonSetting)
// .filter(player -> player.getGameMode().equals(GameMode.SURVIVAL)) .filter(player -> player.getGameMode().equals(GameMode.SURVIVAL))
.toList(); .toList();
ThreadLocalRandom random = ThreadLocalRandom.current(); ThreadLocalRandom random = ThreadLocalRandom.current();
Player player = onlinePlayerList.get(random.nextInt(onlinePlayerList.size())); Player player = onlinePlayerList.get(random.nextInt(onlinePlayerList.size()));
@@ -172,6 +186,18 @@ public class Bloodmoon extends Appliance {
this.spawnHorde(player, hordeSize, hordeEntityType); 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) { private void spawnHorde(Player player, int size, EntityType type) {
for(int i = 0; i < size; i++) { for(int i = 0; i < size; i++) {
double spawnRadiant = ThreadLocalRandom.current().nextDouble(0, 2*Math.PI); double spawnRadiant = ThreadLocalRandom.current().nextDouble(0, 2*Math.PI);
@@ -206,12 +232,36 @@ public class Bloodmoon extends Appliance {
return null; return null;
} }
private void sendMessage(Component message) {
if(Bukkit.getOnlinePlayers().isEmpty()) return;
List<? extends Player> 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 @Override
protected @NotNull List<Listener> listeners() { protected @NotNull List<Listener> listeners() {
return List.of( return List.of(
new BloodmoonMonsterDeathListener(), new BloodmoonMonsterDeathListener(),
new BloodmoonPlayerJoinListener(), new BloodmoonPlayerJoinListener(),
new BloodmoonEntityDamageListener() new BloodmoonEntityDamageListener(),
new BloodmoonTimeListener()
); );
} }

View File

@@ -10,5 +10,6 @@ public class BloodmoonPlayerJoinListener extends ApplianceListener<Bloodmoon> {
public void onPlayerJoin(PlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event) {
if(!this.getAppliance().bloodmoonIsActive()) return; if(!this.getAppliance().bloodmoonIsActive()) return;
this.getAppliance().addPlayerToBossBar(event.getPlayer()); this.getAppliance().addPlayerToBossBar(event.getPlayer());
this.getAppliance().sendWarningMessage(event.getPlayer());
} }
} }

View File

@@ -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<Bloodmoon> {
@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();
}
}
}