diff --git a/changelog.md b/changelog.md index 314c4eb..58387a4 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,10 @@ These changes will (most likely) be included in the next version. ## [Unreleased] +### Changed +- Recurrent waves can now be randomized. If two or more recurrent waves clash on wave number, frequency, _and_ priority, MobArena will now randomly pick between them. This should make it easier to create more varied and interesting wave setups without having to resort to only massively randomized default waves. +- Single waves can now be randomized. If two or more single waves clash on wave number, MobArena will now randomly pick between them. This means it is now possible to make randomly selected bosses for boss waves, for instance. + ### Fixed - MobArena no longer throws errors when handling block explosions on Minecraft 1.21. diff --git a/src/main/java/com/garbagemule/MobArena/waves/WaveManager.java b/src/main/java/com/garbagemule/MobArena/waves/WaveManager.java index 922795c..b1dc2e4 100644 --- a/src/main/java/com/garbagemule/MobArena/waves/WaveManager.java +++ b/src/main/java/com/garbagemule/MobArena/waves/WaveManager.java @@ -4,7 +4,9 @@ import com.garbagemule.MobArena.framework.Arena; import com.garbagemule.MobArena.waves.enums.WaveBranch; import org.bukkit.configuration.ConfigurationSection; -import java.util.SortedSet; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; import java.util.TreeSet; public class WaveManager @@ -12,10 +14,11 @@ public class WaveManager private Arena arena; private ConfigurationSection section; - private Wave defaultWave, currentWave; - private TreeSet recurrentWaves, singleWaves, singleWavesInstance; + private Wave defaultWave, currentWave, nextWave; + private TreeSet recurrentWaves, singleWaves; private int wave, finalWave; + private Random random = new Random(); public WaveManager(Arena arena, ConfigurationSection section) { this.arena = arena; @@ -26,14 +29,10 @@ public class WaveManager reloadWaves(); } - public TreeSet getRecurrentWaves() { - return recurrentWaves; - } - public void reset() { reloadWaves(); wave = 0; - singleWavesInstance = new TreeSet<>(singleWaves); + determineNextWave(); } public void reloadWaves() { @@ -61,21 +60,77 @@ public class WaveManager } } + private void determineNextWave() { + // Single waves take precedence over recurrent waves + List singles = findSingleWaveCandidates(wave + 1); + if (!singles.isEmpty()) { + nextWave = pickRandomWave(singles); + return; + } + + List recurrents = findRecurrentWaveCandidates(wave + 1); + if (!recurrents.isEmpty()) { + nextWave = pickRandomWave(recurrents); + } else { + nextWave = defaultWave.copy(); + } + } + + private List findSingleWaveCandidates(int wave) { + List candidates = new ArrayList<>(singleWaves.size()); + for (Wave w : singleWaves) { + if (w.matches(wave)) { + candidates.add(w); + } + } + + return candidates; + } + + private List findRecurrentWaveCandidates(int wave) { + List matches = new ArrayList<>(recurrentWaves.size()); + for (Wave w : recurrentWaves) { + if (w.matches(wave)) { + matches.add(w); + } + } + + int priority = 0; + for (Wave w : matches) { + if (w.getPriority() > priority) { + priority = w.getPriority(); + } + } + + List candidates = new ArrayList<>(matches.size()); + for (Wave w : matches) { + if (w.getPriority() == priority) { + candidates.add(w); + } + } + + return candidates; + } + + private Wave pickRandomWave(List candidates) { + if (candidates.size() == 1) { + return candidates.get(0).copy(); + } + + int index = random.nextInt(candidates.size()); + return candidates.get(index).copy(); + } + /** * Increment the wave number and get the next Wave to be spawned. * Note that this method is a mutator. * @return the next Wave */ public Wave next() { - wave++; + currentWave = nextWave; - if (!singleWavesInstance.isEmpty() && singleWavesInstance.first().matches(wave)) { - currentWave = singleWavesInstance.pollFirst().copy(); - } - else { - SortedSet matches = getMatchingRecurrentWaves(wave); - currentWave = (matches.isEmpty() ? defaultWave : matches.last()).copy(); - } + wave++; + determineNextWave(); return currentWave; } @@ -87,14 +142,7 @@ public class WaveManager * @return the next Wave */ public Wave getNext() { - int next = wave + 1; - - if (!singleWavesInstance.isEmpty() && singleWavesInstance.first().matches(next)) { - return singleWavesInstance.first(); - } - - SortedSet matches = getMatchingRecurrentWaves(wave); - return (matches.isEmpty() ? defaultWave : matches.last()); + return nextWave; } /** @@ -121,14 +169,4 @@ public class WaveManager public int getFinalWave() { return finalWave; } - - private SortedSet getMatchingRecurrentWaves(int wave) { - TreeSet result = new TreeSet<>(WaveUtils.getRecurrentComparator()); - for (Wave w : recurrentWaves) { - if (w.matches(wave)) { - result.add(w); - } - } - return result; - } } diff --git a/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java b/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java index 633c79d..0f13460 100644 --- a/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java +++ b/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java @@ -114,7 +114,7 @@ public class WaveUtils return -1; else if (w1.getFirstWave() > w2.getFirstWave()) return 1; - else return 0; + else return w1.getName().compareTo(w2.getName()); } }; }