From 00654b9f9b82c0f83e4a3fe1a9f66e476702db02 Mon Sep 17 00:00:00 2001 From: "kangobot[bot]" <2869176+kangobot[bot]@users.noreply.github.com> Date: Fri, 1 May 2026 15:10:21 +0000 Subject: [PATCH] Proposed fix for #1506 --- .../org/mineacademy/boss/spawn/SpawnRule.java | 29 +++++++++++++++++-- .../boss/spawn/SpawnRuleRespawn.java | 10 ------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/mineacademy/boss/spawn/SpawnRule.java b/src/main/java/org/mineacademy/boss/spawn/SpawnRule.java index ed97a57..df24961 100644 --- a/src/main/java/org/mineacademy/boss/spawn/SpawnRule.java +++ b/src/main/java/org/mineacademy/boss/spawn/SpawnRule.java @@ -218,12 +218,20 @@ protected boolean checkLastExecuted() { protected boolean canRun() { // Respawn rules are ticked in a runnable task - if (this.checkLastExecuted()) - if (this.lastExecuted != -1 && System.currentTimeMillis() - this.lastExecuted + 1 < this.delay.getTimeSeconds() * 1000) { - Debugger.debug("spawning", "[SpawnRule=" + this.getName() + "] Not running due to last executed " + (System.currentTimeMillis() - this.lastExecuted) / 1000 + "s ago and delay is " + this.delay.getTimeSeconds() + "s"); + if (this.checkLastExecuted()) { + final long now = System.currentTimeMillis(); + final long lastDeathTime = this.getLastDeathTime(); + + // Use whichever happened later: the last successful spawn or the last death of a boss spawned by this rule. + // This way "Delay" also acts as a cooldown after death, not just between spawn attempts. + final long effectiveLast = Math.max(this.lastExecuted, lastDeathTime); + + if (effectiveLast > 0 && now - effectiveLast + 1 < this.delay.getTimeSeconds() * 1000) { + Debugger.debug("spawning", "[SpawnRule=" + this.getName() + "] Not running due to last spawn/death " + (now - effectiveLast) / 1000 + "s ago and delay is " + this.delay.getTimeSeconds() + "s"); return false; } + } if (!RandomUtil.chanceD(this.getChance())) { Debugger.debug("spawning", "[SpawnRule=" + this.getName() + "] Not running due to chance did not pass: " + this.getChance() * 100 + "%"); @@ -341,6 +349,21 @@ public final void spawn(Location location, SpawnData data) { this.lastExecuted = System.currentTimeMillis(); } + /** + * Returns the latest death timestamp of any boss that was spawned by this rule, or 0 if none. + * + * @return + */ + public long getLastDeathTime() { + long lastDeathTime = 0; + + for (final Boss boss : Boss.getBosses()) + if (this.getBosses().contains(boss.getName())) + lastDeathTime = Math.max(lastDeathTime, boss.getLastDeathFromSpawnRule(this)); + + return lastDeathTime; + } + /* ------------------------------------------------------------------------------- */ /* Menu system */ /* ------------------------------------------------------------------------------- */ diff --git a/src/main/java/org/mineacademy/boss/spawn/SpawnRuleRespawn.java b/src/main/java/org/mineacademy/boss/spawn/SpawnRuleRespawn.java index 1b7cc84..4cae5eb 100644 --- a/src/main/java/org/mineacademy/boss/spawn/SpawnRuleRespawn.java +++ b/src/main/java/org/mineacademy/boss/spawn/SpawnRuleRespawn.java @@ -54,14 +54,4 @@ protected boolean canRun(Boss boss, SpawnData data) { return true; } - - public long getLastDeathTime() { - long lastDeathTime = 0; - - for (final Boss boss : Boss.getBosses()) - if (this.getBosses().contains(boss.getName())) - lastDeathTime = Math.max(lastDeathTime, boss.getLastDeathFromSpawnRule(this)); - - return lastDeathTime; - } }