fixed bloodmoon sleep / time skip issue, added endermite hordes for end, fixed server restart during bloodmoon issue
This commit is contained in:
@@ -5,23 +5,18 @@ import eu.mhsl.craftattack.spawn.core.Main;
|
|||||||
import eu.mhsl.craftattack.spawn.core.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.core.appliance.Appliance;
|
||||||
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand;
|
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand;
|
||||||
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.commands.BloodmoonCommand;
|
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.commands.BloodmoonCommand;
|
||||||
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.BloodmoonEntityDamageListener;
|
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener.*;
|
||||||
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.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 net.kyori.adventure.text.format.TextDecoration;
|
||||||
import net.kyori.adventure.util.Ticks;
|
import net.kyori.adventure.util.Ticks;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.*;
|
||||||
import org.bukkit.GameMode;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
@@ -70,7 +65,6 @@ public class Bloodmoon extends Appliance {
|
|||||||
public final double mobHealthMultiplier = 2;
|
public final double mobHealthMultiplier = 2;
|
||||||
|
|
||||||
private final ThreadLocalRandom random = ThreadLocalRandom.current();
|
private final ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||||
private boolean isActive = false;
|
|
||||||
private final BossBar bossBar = BossBar.bossBar(
|
private final BossBar bossBar = BossBar.bossBar(
|
||||||
Component.text("Blutmond", NamedTextColor.DARK_RED),
|
Component.text("Blutmond", NamedTextColor.DARK_RED),
|
||||||
1f,
|
1f,
|
||||||
@@ -79,6 +73,7 @@ public class Bloodmoon extends Appliance {
|
|||||||
Set.of(BossBar.Flag.CREATE_WORLD_FOG, BossBar.Flag.DARKEN_SCREEN)
|
Set.of(BossBar.Flag.CREATE_WORLD_FOG, BossBar.Flag.DARKEN_SCREEN)
|
||||||
);
|
);
|
||||||
private final boolean hordesEnabled = true;
|
private final boolean hordesEnabled = true;
|
||||||
|
public final boolean bloodmoonSkippable = true;
|
||||||
private final int hordeSpawnRateTicks = 40 * Ticks.TICKS_PER_SECOND;
|
private final int hordeSpawnRateTicks = 40 * Ticks.TICKS_PER_SECOND;
|
||||||
private final int hordeSpawnRateVariationTicks = 40 * Ticks.TICKS_PER_SECOND;
|
private final int hordeSpawnRateVariationTicks = 40 * Ticks.TICKS_PER_SECOND;
|
||||||
private final int hordeMinPopulation = 3;
|
private final int hordeMinPopulation = 3;
|
||||||
@@ -90,10 +85,10 @@ public class Bloodmoon extends Appliance {
|
|||||||
EntityType.SPIDER
|
EntityType.SPIDER
|
||||||
);
|
);
|
||||||
private final Map<Player, @Nullable BukkitTask> hordeSpawnTasks = new WeakHashMap<>();
|
private final Map<Player, @Nullable BukkitTask> hordeSpawnTasks = new WeakHashMap<>();
|
||||||
private long lastBloodmoonStartTick = 0;
|
|
||||||
public final int ticksPerDay = 24000;
|
public final int ticksPerDay = 24000;
|
||||||
public final int bloodmoonLength = this.ticksPerDay /2;
|
public final int bloodmoonLength = this.ticksPerDay / 2;
|
||||||
public final int preStartMessageTicks = Ticks.TICKS_PER_SECOND * 50;
|
public final int preStartMessageTicks = Ticks.TICKS_PER_SECOND * 50;
|
||||||
|
private boolean bossbarActive = false;
|
||||||
private final int bloodmoonFreeDaysAtStart = 3;
|
private final int bloodmoonFreeDaysAtStart = 3;
|
||||||
private final int bloodmoonStartTime = this.ticksPerDay /2;
|
private final int bloodmoonStartTime = this.ticksPerDay /2;
|
||||||
private final int bloodmoonDayInterval = 30;
|
private final int bloodmoonDayInterval = 30;
|
||||||
@@ -113,35 +108,71 @@ public class Bloodmoon extends Appliance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean bloodmoonIsActive() {
|
public boolean bloodmoonIsActive() {
|
||||||
return this.isActive;
|
long currentTick = Bukkit.getWorlds().getFirst().getFullTime();
|
||||||
|
long day = currentTick / this.ticksPerDay;
|
||||||
|
if(day % this.bloodmoonDayInterval != 0 || day - this.bloodmoonFreeDaysAtStart <= 0) return false;
|
||||||
|
long time = currentTick % this.ticksPerDay;
|
||||||
|
return time >= this.bloodmoonStartTime && time <= this.bloodmoonStartTime + this.bloodmoonLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startBloodmoon(long startTick) {
|
public void startBloodmoon() {
|
||||||
this.lastBloodmoonStartTick = startTick;
|
this.bossbarActive = true;
|
||||||
this.isActive = true;
|
|
||||||
Bukkit.getOnlinePlayers().forEach(this::addPlayerToBossBar);
|
Bukkit.getOnlinePlayers().forEach(this::addPlayerToBossBar);
|
||||||
this.startHordeSpawning(this.getRandomHordeSpawnDelay());
|
this.startHordeSpawning(this.getRandomHordeSpawnDelay());
|
||||||
this.sendStartMessages();
|
this.sendStartMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopBloodmoon() {
|
public void stopBloodmoonIfInactive() {
|
||||||
this.isActive = false;
|
Bukkit.getScheduler().runTaskLater(
|
||||||
|
Main.instance(),
|
||||||
|
() -> {
|
||||||
|
if(!this.bossbarActive) return;
|
||||||
|
if(this.bloodmoonIsActive()) return;
|
||||||
|
this.bossbarActive = false;
|
||||||
|
Bukkit.getOnlinePlayers().forEach(player -> player.hideBossBar(this.bossBar));
|
||||||
|
this.stopHordeSpawning();
|
||||||
|
this.sendStopMessages();
|
||||||
|
},
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// not working for entity effects and debuffs...
|
||||||
|
public void forceStopBloodmoon() {
|
||||||
|
this.bossbarActive = false;
|
||||||
Bukkit.getOnlinePlayers().forEach(player -> player.hideBossBar(this.bossBar));
|
Bukkit.getOnlinePlayers().forEach(player -> player.hideBossBar(this.bossBar));
|
||||||
|
this.stopHordeSpawning();
|
||||||
this.sendStopMessages();
|
this.sendStopMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateBossBar() {
|
public void updateBossBar() {
|
||||||
long tick = Bukkit.getWorlds().getFirst().getFullTime();
|
long tick = Bukkit.getWorlds().getFirst().getFullTime();
|
||||||
long sinceStart = tick - this.lastBloodmoonStartTick;
|
long sinceStart = tick - this.lastBloodmoonStartTick();
|
||||||
float progress = 1f - ((float) sinceStart / this.bloodmoonLength);
|
float progress = 1f - ((float) sinceStart / this.bloodmoonLength);
|
||||||
if(progress < 0) progress = 1f;
|
if(progress < 0) progress = 1f;
|
||||||
this.bossBar.progress(progress);
|
this.bossBar.progress(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long lastBloodmoonStartTick() {
|
||||||
|
long currentTick = Bukkit.getWorlds().getFirst().getFullTime();
|
||||||
|
long day = currentTick / this.ticksPerDay;
|
||||||
|
long time = currentTick % this.ticksPerDay;
|
||||||
|
|
||||||
|
boolean todayIsBloodmoon = (day % this.bloodmoonDayInterval == 0) && (day > this.bloodmoonFreeDaysAtStart);
|
||||||
|
if (todayIsBloodmoon && time < this.bloodmoonStartTime) {
|
||||||
|
day -= this.bloodmoonDayInterval;
|
||||||
|
} else if (!todayIsBloodmoon) {
|
||||||
|
day -= (day % this.bloodmoonDayInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (day <= this.bloodmoonFreeDaysAtStart) return -1L;
|
||||||
|
return day * this.ticksPerDay + this.bloodmoonStartTime;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isStartTick(long tick) {
|
public boolean isStartTick(long tick) {
|
||||||
long day = tick / this.ticksPerDay;
|
long day = tick / this.ticksPerDay;
|
||||||
if(day % this.bloodmoonDayInterval != 0 || day - this.bloodmoonFreeDaysAtStart <= 0) return false;
|
if(day % this.bloodmoonDayInterval != 0 || day <= this.bloodmoonFreeDaysAtStart) return false;
|
||||||
long time = tick - (day * this.ticksPerDay);
|
long time = tick % this.ticksPerDay;
|
||||||
return time == this.bloodmoonStartTime;
|
return time == this.bloodmoonStartTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +184,14 @@ public class Bloodmoon extends Appliance {
|
|||||||
Bukkit.getOnlinePlayers().forEach(player -> this.startHordeSpawning(delay, player));
|
Bukkit.getOnlinePlayers().forEach(player -> this.startHordeSpawning(delay, player));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startHordeSpawning(int delay, Player player) {
|
private void stopHordeSpawning() {
|
||||||
|
this.hordeSpawnTasks.forEach((player, bukkitTask) -> {
|
||||||
|
@Nullable BukkitTask task = this.hordeSpawnTasks.get(player);
|
||||||
|
if(task != null) task.cancel();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startHordeSpawning(int delay, Player player) {
|
||||||
@Nullable BukkitTask task = this.hordeSpawnTasks.get(player);
|
@Nullable BukkitTask task = this.hordeSpawnTasks.get(player);
|
||||||
if(task != null) task.cancel();
|
if(task != null) task.cancel();
|
||||||
BukkitTask newTask = Bukkit.getScheduler().runTaskLater(
|
BukkitTask newTask = Bukkit.getScheduler().runTaskLater(
|
||||||
@@ -191,6 +229,7 @@ public class Bloodmoon extends Appliance {
|
|||||||
if(!player.getGameMode().equals(GameMode.SURVIVAL)) return;
|
if(!player.getGameMode().equals(GameMode.SURVIVAL)) return;
|
||||||
|
|
||||||
EntityType hordeEntityType = this.hordeMobList.get(this.random.nextInt(this.hordeMobList.size()));
|
EntityType hordeEntityType = this.hordeMobList.get(this.random.nextInt(this.hordeMobList.size()));
|
||||||
|
if(player.getLocation().getWorld().getEnvironment().equals(World.Environment.THE_END)) hordeEntityType = EntityType.ENDERMITE;
|
||||||
int hordeSize = this.random.nextInt(this.hordeMinPopulation, this.hordeMaxPopulation + 1);
|
int hordeSize = this.random.nextInt(this.hordeMinPopulation, this.hordeMaxPopulation + 1);
|
||||||
this.spawnHorde(player, hordeSize, hordeEntityType);
|
this.spawnHorde(player, hordeSize, hordeEntityType);
|
||||||
}
|
}
|
||||||
@@ -217,7 +256,7 @@ public class Bloodmoon extends Appliance {
|
|||||||
Math.cos(spawnRadiant)*this.hordeSpawnDistance
|
Math.cos(spawnRadiant)*this.hordeSpawnDistance
|
||||||
);
|
);
|
||||||
mobSpawnLocation.setY(player.getWorld().getHighestBlockYAt(mobSpawnLocation) + 1);
|
mobSpawnLocation.setY(player.getWorld().getHighestBlockYAt(mobSpawnLocation) + 1);
|
||||||
player.getWorld().spawnEntity(mobSpawnLocation, type);
|
player.getWorld().spawnEntity(mobSpawnLocation, type, CreatureSpawnEvent.SpawnReason.NATURAL);
|
||||||
player.getWorld().strikeLightningEffect(mobSpawnLocation);
|
player.getWorld().strikeLightningEffect(mobSpawnLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,7 +310,8 @@ public class Bloodmoon extends Appliance {
|
|||||||
new BloodmoonMonsterDeathListener(),
|
new BloodmoonMonsterDeathListener(),
|
||||||
new BloodmoonPlayerJoinListener(),
|
new BloodmoonPlayerJoinListener(),
|
||||||
new BloodmoonEntityDamageListener(),
|
new BloodmoonEntityDamageListener(),
|
||||||
new BloodmoonTimeListener()
|
new BloodmoonTimeListener(),
|
||||||
|
new BloodmoonTimeSkipListener()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.comm
|
|||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand;
|
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand;
|
||||||
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.Bloodmoon;
|
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.Bloodmoon;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -23,15 +24,19 @@ public class BloodmoonCommand extends ApplianceCommand<Bloodmoon> {
|
|||||||
|
|
||||||
switch(args[0]) {
|
switch(args[0]) {
|
||||||
case "start": {
|
case "start": {
|
||||||
this.getAppliance().startBloodmoon(0L);
|
this.getAppliance().startBloodmoon();
|
||||||
sender.sendMessage("Started bloodmoon.");
|
sender.sendMessage("Started bloodmoon.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "stop": {
|
case "stop": {
|
||||||
this.getAppliance().stopBloodmoon();
|
this.getAppliance().forceStopBloodmoon();
|
||||||
sender.sendMessage("Stopped bloodmoon.");
|
sender.sendMessage("Stopped bloodmoon.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "time": {
|
||||||
|
sender.sendMessage(String.valueOf(Bukkit.getWorlds().getFirst().getFullTime()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: throw new Error("No such option: '%s' !".formatted(args[0]));
|
default: throw new Error("No such option: '%s' !".formatted(args[0]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.list
|
|||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener;
|
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener;
|
||||||
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.Bloodmoon;
|
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.Bloodmoon;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
@@ -9,7 +10,9 @@ public class BloodmoonPlayerJoinListener extends ApplianceListener<Bloodmoon> {
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
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());
|
Player player = event.getPlayer();
|
||||||
this.getAppliance().sendWarningMessage(event.getPlayer());
|
this.getAppliance().addPlayerToBossBar(player);
|
||||||
|
this.getAppliance().startHordeSpawning(1500, player);
|
||||||
|
this.getAppliance().sendWarningMessage(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ public class BloodmoonTimeListener extends ApplianceListener<Bloodmoon> {
|
|||||||
public void onServerTick(ServerTickStartEvent event) {
|
public void onServerTick(ServerTickStartEvent event) {
|
||||||
long currentTime = Bukkit.getWorlds().getFirst().getFullTime();
|
long currentTime = Bukkit.getWorlds().getFirst().getFullTime();
|
||||||
if(this.getAppliance().isStartTick(currentTime)) {
|
if(this.getAppliance().isStartTick(currentTime)) {
|
||||||
this.getAppliance().startBloodmoon(currentTime);
|
this.getAppliance().startBloodmoon();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(this.getAppliance().isStartTick(currentTime - this.getAppliance().bloodmoonLength)) {
|
if(this.getAppliance().isStartTick(currentTime - this.getAppliance().bloodmoonLength)) {
|
||||||
this.getAppliance().stopBloodmoon();
|
this.getAppliance().stopBloodmoonIfInactive();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(currentTime % Ticks.TICKS_PER_SECOND == 0 && this.getAppliance().bloodmoonIsActive()) this.getAppliance().updateBossBar();
|
if(currentTime % Ticks.TICKS_PER_SECOND == 0 && this.getAppliance().bloodmoonIsActive()) this.getAppliance().updateBossBar();
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.listener;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener;
|
||||||
|
import eu.mhsl.craftattack.spawn.craftattack.appliances.gameplay.bloodmoon.Bloodmoon;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.player.PlayerBedEnterEvent;
|
||||||
|
import org.bukkit.event.world.TimeSkipEvent;
|
||||||
|
|
||||||
|
public class BloodmoonTimeSkipListener extends ApplianceListener<Bloodmoon> {
|
||||||
|
@EventHandler
|
||||||
|
public void onTimeSkip(TimeSkipEvent event) {
|
||||||
|
if(this.getAppliance().bloodmoonSkippable || !event.getSkipReason().equals(TimeSkipEvent.SkipReason.NIGHT_SKIP)) {
|
||||||
|
this.getAppliance().stopBloodmoonIfInactive();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerSleep(PlayerBedEnterEvent event) {
|
||||||
|
if(!this.getAppliance().bloodmoonIsActive()) return;
|
||||||
|
if(this.getAppliance().bloodmoonSkippable) return;
|
||||||
|
if(!event.getBedEnterResult().equals(PlayerBedEnterEvent.BedEnterResult.OK)) return;
|
||||||
|
event.setUseBed(Event.Result.DENY);
|
||||||
|
event.getPlayer().sendActionBar(Component.text("Du kannst während dem Blutmond nicht schlafen"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user