Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions src/main/java/com/garbagemule/MobArena/MASpawnThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@
import com.garbagemule.MobArena.things.ExperienceThing;
import com.garbagemule.MobArena.things.Thing;
import com.garbagemule.MobArena.things.ThingPicker;
import com.garbagemule.MobArena.waves.MABoss;
import com.garbagemule.MobArena.waves.MACreature;
import com.garbagemule.MobArena.waves.Wave;
import com.garbagemule.MobArena.waves.WaveManager;
import com.garbagemule.MobArena.waves.*;
import com.garbagemule.MobArena.waves.enums.WaveType;
import com.garbagemule.MobArena.waves.types.BossWave;
import com.garbagemule.MobArena.waves.types.ComboWave;
import com.garbagemule.MobArena.waves.types.SupplyWave;
import com.garbagemule.MobArena.waves.types.UpgradeWave;
import org.bukkit.Bukkit;
Expand Down Expand Up @@ -180,8 +178,32 @@ private void spawnNextWave() {

private void spawnWave(int wave) {
Wave w = waveManager.next();
handleWave(w, wave, true);

w.announce(arena, wave);
Wave sw = waveManager.getCurrentShadow();
if (sw != null && WaveUtils.waveBlocked(sw, w.getShadowBlacklist())) {
handleWave(sw, wave, false);
}
}

private void handleWave(Wave w, int wave, boolean announce) {
if (w.getType() == WaveType.COMBO) {
ComboWave cw = (ComboWave) w;

Wave waveA = cw.getWaveA();
handleWave(cw.getWaveA(), wave, waveA.getType() == WaveType.COMBO);
handleWave(cw.getWaveB(), wave, false);


if (announce && waveA.getType() != WaveType.COMBO) {
cw.getWaveA().announce(arena, wave); // announce only waveA in outermost COMBO wave.
}
return;
}

if (announce) {
w.announce(arena, wave);
}

arena.getScoreboard().updateWave(wave);

Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/garbagemule/MobArena/waves/AbstractWave.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public abstract class AbstractWave implements Wave
private double healthMultiplier, amountMultiplier;

private int firstWave, frequency, priority;
private String shadowBlacklist;

private List<Location> spawnpoints;
private List<PotionEffect> effects;
Expand Down Expand Up @@ -120,6 +121,16 @@ public void setPriority(int priority) {
this.priority = priority;
}

@Override
public String getShadowBlacklist() {
return shadowBlacklist;
}

@Override
public void setShadowBlacklist(String shadowBlacklist) {
this.shadowBlacklist = shadowBlacklist;
}

@Override
public double getHealthMultiplier() {
return healthMultiplier;
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/garbagemule/MobArena/waves/Wave.java
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,18 @@ public interface Wave
*/
void setAmountMultiplier(double amountMultiplier);

/**
* Get the wave's shadow blacklist.
* @return a list of shadow wave names
*/
String getShadowBlacklist();

/**
* Set the wave's shadow blacklist.
* @param blacklist a list of shadow wave names
*/
void setShadowBlacklist(String blacklist);

/**
* Check if this wave matches the wave number.
* The SingleWave class does a simple check if its wave == the parameter.
Expand Down
61 changes: 53 additions & 8 deletions src/main/java/com/garbagemule/MobArena/waves/WaveManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ public class WaveManager
private ConfigurationSection section;

private Wave defaultWave, currentWave, nextWave;
private Wave currentShadowWave, nextShadowWave;
private TreeSet<Wave> recurrentWaves, singleWaves;
private TreeSet<Wave> recurrentShadowWaves, singleShadowWaves;

private int wave, finalWave;
private Random random = new Random();
Expand All @@ -33,6 +35,7 @@ public void reset() {
reloadWaves();
wave = 0;
determineNextWave();
determineNextShadowWave();
}

public void reloadWaves() {
Expand All @@ -42,6 +45,12 @@ public void reloadWaves() {
recurrentWaves = WaveParser.parseWaves(arena, rConfig, WaveBranch.RECURRENT);
singleWaves = WaveParser.parseWaves(arena, sConfig, WaveBranch.SINGLE);

ConfigurationSection shadowRConfig = section.getConfigurationSection("shadow.recurrent");
ConfigurationSection shadowSConfig = section.getConfigurationSection("shadow.single");

recurrentShadowWaves = WaveParser.parseWaves(arena, shadowRConfig, WaveBranch.RECURRENT);
singleShadowWaves = WaveParser.parseWaves(arena, shadowSConfig, WaveBranch.SINGLE);

// getParent() => go back to the arena-node to access settings
finalWave = section.getParent().getInt("settings.final-wave", 0);

Expand All @@ -62,23 +71,37 @@ public void reloadWaves() {

private void determineNextWave() {
// Single waves take precedence over recurrent waves
List<Wave> singles = findSingleWaveCandidates(wave + 1);
List<Wave> singles = findSingleWaveCandidates(wave + 1, singleWaves);
if (!singles.isEmpty()) {
nextWave = pickRandomWave(singles);
return;
}

List<Wave> recurrents = findRecurrentWaveCandidates(wave + 1);
List<Wave> recurrents = findRecurrentWaveCandidates(wave + 1, recurrentWaves);
if (!recurrents.isEmpty()) {
nextWave = pickRandomWave(recurrents);
} else {
nextWave = defaultWave.copy();
}
}

private List<Wave> findSingleWaveCandidates(int wave) {
List<Wave> candidates = new ArrayList<>(singleWaves.size());
for (Wave w : singleWaves) {
private void determineNextShadowWave() {
// Single waves take precedence over recurrent waves
List<Wave> singles = findSingleWaveCandidates(wave + 1, singleShadowWaves);
if (!singles.isEmpty()) {
nextShadowWave = pickRandomWave(singles);
return;
}

List<Wave> recurrents = findRecurrentWaveCandidates(wave + 1, recurrentShadowWaves);
if (!recurrents.isEmpty()) {
nextShadowWave = pickRandomWave(recurrents);
}
}

private List<Wave> findSingleWaveCandidates(int wave, TreeSet<Wave> waves) {
List<Wave> candidates = new ArrayList<>(waves.size());
for (Wave w : waves) {
if (w.matches(wave)) {
candidates.add(w);
}
Expand All @@ -87,9 +110,9 @@ private List<Wave> findSingleWaveCandidates(int wave) {
return candidates;
}

private List<Wave> findRecurrentWaveCandidates(int wave) {
List<Wave> matches = new ArrayList<>(recurrentWaves.size());
for (Wave w : recurrentWaves) {
private List<Wave> findRecurrentWaveCandidates(int wave, TreeSet<Wave> waves) {
List<Wave> matches = new ArrayList<>(waves.size());
for (Wave w : waves) {
if (w.matches(wave)) {
matches.add(w);
}
Expand Down Expand Up @@ -123,14 +146,17 @@ private Wave pickRandomWave(List<Wave> candidates) {

/**
* Increment the wave number and get the next Wave to be spawned.
* Does NOT return the next Shadow Wave.
* Note that this method is a mutator.
* @return the next Wave
*/
public Wave next() {
currentWave = nextWave;
currentShadowWave = nextShadowWave;

wave++;
determineNextWave();
determineNextShadowWave();

return currentWave;
}
Expand All @@ -154,6 +180,25 @@ public Wave getCurrent() {
return currentWave;
}

/**
* Get the next Shadow Wave to be spawned. This is an accessor and does not
* advance the "counter". Note that the Wave objects, however, are
* mutable.
* @return the next Shadow Wave
*/
public Wave getNextShadow() {
return nextShadowWave;
}

/**
* Get the current Shadow wave that's being used.
* Note that the current wave might not have spawned yet.
* @return the current Shadow wave
*/
public Wave getCurrentShadow() {
return currentShadowWave;
}

/**
* Get the current wave number.
* @return the current wave number
Expand Down
39 changes: 22 additions & 17 deletions src/main/java/com/garbagemule/MobArena/waves/WaveParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,14 @@
import com.garbagemule.MobArena.waves.ability.AbilityManager;
import com.garbagemule.MobArena.waves.enums.WaveBranch;
import com.garbagemule.MobArena.waves.enums.WaveType;
import com.garbagemule.MobArena.waves.types.BossWave;
import com.garbagemule.MobArena.waves.types.DefaultWave;
import com.garbagemule.MobArena.waves.types.SpecialWave;
import com.garbagemule.MobArena.waves.types.SupplyWave;
import com.garbagemule.MobArena.waves.types.SwarmWave;
import com.garbagemule.MobArena.waves.types.UpgradeWave;
import com.garbagemule.MobArena.waves.types.*;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.*;
import java.util.stream.Collectors;

public class WaveParser
Expand Down Expand Up @@ -98,6 +84,9 @@ public static Wave parseWave(Arena arena, String name, ConfigurationSection conf
case BOSS:
result = parseBossWave(arena, name, config);
break;
case COMBO:
result = parseComboWave(arena, name, config);
break;
}

// Grab the branch-specific nodes.
Expand All @@ -122,7 +111,7 @@ public static Wave parseWave(Arena arena, String name, ConfigurationSection conf
// Potion effects
List<PotionEffect> effects = getPotionEffects(arena, name, config);

// Recurrent must have priority + frequency, single must have firstWave
// Recurrent must have priority + frequency, single must have firstWave, combo doesn't need this
if (branch == WaveBranch.RECURRENT) {
if (priority <= 0) {
throw new ConfigError("Missing or invalid 'priority' node for recurrent wave " + name + " of arena " + arena.configName());
Expand All @@ -140,6 +129,7 @@ public static Wave parseWave(Arena arena, String name, ConfigurationSection conf
result.setFirstWave(firstWave);
result.setPriority(priority);
result.setFrequency(frequency);
result.setShadowBlacklist(Optional.ofNullable(config.getString("noshadow")).orElse(""));

// And the multipliers.
result.setHealthMultiplier(healthMultiplier);
Expand Down Expand Up @@ -350,6 +340,21 @@ private static Wave parseBossWave(Arena arena, String name, ConfigurationSection
return result;
}

private static Wave parseComboWave(Arena arena, String name, ConfigurationSection config) {
ConfigurationSection waveAConfig = config.getConfigurationSection("waveA");
if (waveAConfig == null) {
throw new ConfigError("No waveA defined in wave " + name + " of arena " + arena.configName() + ".");
}
Wave waveA = parseWave(arena, name, waveAConfig, WaveBranch.COMBO);
ConfigurationSection waveBConfig = config.getConfigurationSection("waveB");
if (waveBConfig == null) {
throw new ConfigError("No waveB defined in wave " + name + " of arena " + arena.configName() + ".");
}
Wave waveB = parseWave(arena, name, waveBConfig, WaveBranch.COMBO);

return new ComboWave(waveA, waveB);
}

/**
* Scan the ConfigSection for a "monster" (singular) node, which
* must be exactly a single monster.
Expand Down
24 changes: 20 additions & 4 deletions src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,29 @@
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.*;

public class WaveUtils
{
/**
* Test if a wave gets blocked by a given blacklist
*/
public static boolean waveBlocked(Wave wave, String blacklist) {
if (blacklist == null) {
return true;
}
if (blacklist.equals("*")) {
return false;
}
String[] blacklistedWaves = blacklist.split(", ?");
for (String waveName : blacklistedWaves) {
if (waveName.equalsIgnoreCase(wave.getName())) {
return false;
}
}
return true;
}

/**
* Get all the spawnpoints that have players nearby.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ public boolean matches(int wave, Wave w) {
}
return ((wave - w.getFirstWave()) % w.getFrequency() == 0);
}
},

COMBO {
@Override
public boolean matches(int wave, Wave w) {
return false; // doesn't get used anyway on COMBO branch
}
};

public abstract boolean matches(int wave, Wave w);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ public void announce(Arena arena, int wave) {
public void announce(Arena arena, int wave) {
arena.announce(Msg.WAVE_UPGRADE, "" + wave);
}
},

COMBO {
@Override
public void announce(Arena arena, int wave) {
// announce waveA in MASpawnThread.handleWave(Wave, int, boolean)
}
};

public abstract void announce(Arena arena, int wave);
Expand Down
Loading