mirror of
https://github.com/garbagemule/MobArena.git
synced 2024-11-22 18:46:45 +01:00
Preparations for customizable waves..
This commit is contained in:
parent
a277bf2b33
commit
4c7d85193e
14
.classpath
Normal file
14
.classpath
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="S:/Java/Minecraft/lib/craftbukkit-0.0.1-SNAPSHOT.jar"/>
|
||||
<classpathentry kind="lib" path="S:/Java/Minecraft/lib/Permissions.jar"/>
|
||||
<classpathentry kind="lib" path="S:/Java/Minecraft/lib/BOSEconomy7.jar"/>
|
||||
<classpathentry kind="lib" path="S:/Java/Minecraft/lib/Essentials.jar"/>
|
||||
<classpathentry kind="lib" path="S:/Java/Minecraft/lib/iCo4.jar"/>
|
||||
<classpathentry kind="lib" path="S:/Java/Minecraft/lib/iCo5.jar"/>
|
||||
<classpathentry kind="lib" path="MobArena.jar"/>
|
||||
<classpathentry kind="lib" path="S:/Java/Minecraft/lib/jdom.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
17
.project
Normal file
17
.project
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>MobArena</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
41
build.xml
Normal file
41
build.xml
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="MobArena" default="dist" basedir=".">
|
||||
<property name="pluginname" value="MobArena"/>
|
||||
<property name="server" location="S:\Minecraft Server\plugins"/>
|
||||
|
||||
<property name="src" location="src"/>
|
||||
<property name="bin" location="bin"/>
|
||||
<property name="lib" location="../lib"/>
|
||||
<property name="res" location="resources"/>
|
||||
<path id="classpath">
|
||||
<fileset dir="${lib}" includes="**/*.jar"/>
|
||||
<fileset dir="${res}" includes="**/*.*"/>
|
||||
</path>
|
||||
|
||||
<target name="init">
|
||||
<mkdir dir="${bin}"/>
|
||||
</target>
|
||||
|
||||
<!-- Compile the source and put in the bin-folder -->
|
||||
<target name="compile" depends="init">
|
||||
<javac srcdir="${src}" destdir="${bin}" includeantruntime="false" classpathref="classpath"/>
|
||||
</target>
|
||||
|
||||
<!-- Build a .jar and copy to server's plugins-folder -->
|
||||
<target name="dist" depends="compile">
|
||||
<delete file="${pluginname}.jar"/>
|
||||
<jar jarfile="${pluginname}.jar">
|
||||
<!-- Include the class-files (bin) and the resources (res) -->
|
||||
<fileset dir="${bin}"/>
|
||||
<fileset dir="${res}"/>
|
||||
<!-- Set up the classpath so MobArena can find JDOM if needed -->
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="com.garbagemule.MobArena.MobArena"/>
|
||||
<attribute name="Class-Path" value="plugins/MobArena/lib/jdom.jar MobArena/lib/jdom.jar"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
<!-- Copy to server and clean up -->
|
||||
<copy file="${pluginname}.jar" tofile="${server}/${pluginname}.jar"/>
|
||||
<delete dir="${bin}"/>
|
||||
</target>
|
||||
</project>
|
26
resources/plugin.yml
Normal file
26
resources/plugin.yml
Normal file
@ -0,0 +1,26 @@
|
||||
name: MobArena
|
||||
main: com.garbagemule.MobArena.MobArena
|
||||
version: 0.93.4
|
||||
softdepend: [MultiVerse,XcraftGate,Towny]
|
||||
commands:
|
||||
ma:
|
||||
description: Base command for MobArena
|
||||
usage: |
|
||||
/ma join - Join the arena.
|
||||
/ma leave - Leave the arena.
|
||||
/ma notready - List of players who aren't ready.
|
||||
/ma spectate - Warp to the spectator area.
|
||||
marena:
|
||||
description: Base command for MobArena
|
||||
usage: |
|
||||
/marena join - Join the arena.
|
||||
/marena leave - Leave the arena.
|
||||
/marena notready - List of players who aren't ready.
|
||||
/marena spectate - Warp to the spectator area.
|
||||
mobarena:
|
||||
description: Base command for MobArena
|
||||
usage: |
|
||||
/mobarena join - Join the arena.
|
||||
/mobarena leave - Leave the arena.
|
||||
/mobarena notready - List of players who aren't ready.
|
||||
/mobarena spectate - Warp to the spectator area.
|
51
resources/res/announcements.properties
Normal file
51
resources/res/announcements.properties
Normal file
@ -0,0 +1,51 @@
|
||||
ARENA_START=Let the slaughter begin!
|
||||
ARENA_END=Arena finished.
|
||||
ARENA_DOES_NOT_EXIST=That arena does not exist. Type /ma arenas for a list.
|
||||
JOIN_PLAYER_JOINED=
|
||||
JOIN_NOT_ENABLED=MobArena is not enabled.
|
||||
JOIN_IN_OTHER_ARENA=You are already in an arena! Leave that one first.
|
||||
JOIN_ARENA_NOT_ENABLED=This arena is not enabled.
|
||||
JOIN_ARENA_NOT_SETUP=This arena has not been set up yet.
|
||||
JOIN_ARENA_PERMISSION=You don't have permission to join this arena.
|
||||
JOIN_FEE_REQUIRED=Insufficient funds. Price: %
|
||||
JOIN_FEE_PAID=Price to join was: %
|
||||
JOIN_ARENA_IS_RUNNING=This arena is in already progress.
|
||||
JOIN_ALREADY_PLAYING=You are already playing!
|
||||
JOIN_ARG_NEEDED=You must specify an arena. Type /ma arenas for a list.
|
||||
JOIN_TOO_FAR=You are too far away from the arena to join/spectate.
|
||||
JOIN_EMPTY_INV=You must empty your inventory to join the arena.
|
||||
JOIN_PLAYER_LIMIT_REACHED=The player limit of this arena has been reached.
|
||||
JOIN_STORE_INV_FAIL=Failed to store inventory. Try again.
|
||||
LEAVE_PLAYER_LEFT=You left the arena. Thanks for playing!
|
||||
LEAVE_NOT_PLAYING=You are not in the arena.
|
||||
PLAYER_DIED=% died!
|
||||
SPEC_PLAYER_SPECTATE=Enjoy the show!
|
||||
SPEC_NOT_RUNNING=This arena isn't running.
|
||||
SPEC_ARG_NEEDED=You must specify an arena. Type /ma arenas for a list.
|
||||
SPEC_EMPTY_INV=Empty your inventory first!
|
||||
SPEC_ALREADY_PLAYING=Can't spectate when in the arena!
|
||||
NOT_READY_PLAYERS=Not ready: %
|
||||
FORCE_START_STARTED=Forced arena start.
|
||||
FORCE_START_RUNNING=Arena has already started.
|
||||
FORCE_START_NOT_READY=Can't force start, no players are ready.
|
||||
FORCE_END_ENDED=Forced arena end.
|
||||
FORCE_END_EMPTY=No one is in the arena.
|
||||
FORCE_END_IDLE=You weren't quick enough!
|
||||
REWARDS_GIVE=Here are all of your rewards!
|
||||
LOBBY_CLASS_PICKED=You have chosen % as your class!
|
||||
LOBBY_CLASS_RANDOM=You will get a random class on arena start.
|
||||
LOBBY_CLASS_PERMISSION=You don't have permission to use this class!
|
||||
LOBBY_PLAYER_READY=You have been flagged as ready!
|
||||
LOBBY_DROP_ITEM=No sharing before the arena starts!
|
||||
LOBBY_PICK_CLASS=You must first pick a class!
|
||||
LOBBY_RIGHT_CLICK=Punch the sign. Don't right-click.
|
||||
WARP_TO_ARENA=Can't warp to the arena during battle!
|
||||
WARP_FROM_ARENA=Warping not allowed in the arena!
|
||||
WAVE_DEFAULT=Get ready for wave #%!
|
||||
WAVE_SPECIAL=Get ready for wave #%! [SPECIAL]
|
||||
WAVE_REWARD=You just earned a reward: %
|
||||
MISC_LIST_ARENAS=Available arenas: %
|
||||
MISC_LIST_PLAYERS=Live players: %
|
||||
MISC_COMMAND_NOT_ALLOWED=You can't use that command in the arena!
|
||||
MISC_NO_ACCESS=You don't have access to this command.
|
||||
MISC_NONE=<none>
|
107
resources/res/config.yml
Normal file
107
resources/res/config.yml
Normal file
@ -0,0 +1,107 @@
|
||||
### MobArena Configuration File
|
||||
### Please visit the MobArena Wiki here: http://goo.gl/F5TTc for more details
|
||||
### on how to set up this file.
|
||||
### Note that you CAN'T use tabs in this file! Always use spaces!
|
||||
|
||||
### GLOBAL SETTINGS
|
||||
# These settings are arena-independent and count in all arenas. Note that if
|
||||
# enabled: false in the global settings, MobArena is disabled globally, and
|
||||
# arena-specific enabled-values do not matter. If true, however, the per-arena
|
||||
# enabled-values count.
|
||||
global-settings:
|
||||
enabled: true
|
||||
allowed-commands: /list, /pl
|
||||
update-notification: true
|
||||
|
||||
### CLASS SETUP
|
||||
# Items can be written as either their data value (numbers) or their Material
|
||||
# type (names); check the Wiki for links to lists of both.
|
||||
# The notation is <item>:<amount>. If no amount is given, 1 is assumed. Sub-
|
||||
# types can be created
|
||||
# Item SUBTYPES (wool/dye colors) are written as <item>:<subtype>:<amount>,
|
||||
# but here, the amount is REQUIRED, even if it is just 1.
|
||||
# Note: If you want to specify only one item, but apostrophes around that one
|
||||
# item, e.g.: items: '278'
|
||||
# Note: For every bone a class has, one PET WOLF will spawn upon arena start,
|
||||
# which will assist the player in the arena session.
|
||||
classes:
|
||||
Knight:
|
||||
items: diamond_sword, grilled_pork:2
|
||||
armor: 306,307,308,309
|
||||
Tank:
|
||||
items: iron_sword, grilled_pork:3, apple
|
||||
armor: 310,311,312,313
|
||||
Archer:
|
||||
items: wood_sword, bow, arrow:64, arrow:64, grilled_pork, bone:2
|
||||
armor: 298,299,300,301
|
||||
Chef:
|
||||
items: stone_sword, bread:6, grilled_pork:4, mushroom_soup, cake:5
|
||||
armor: 314,315,316,317
|
||||
Oddjob:
|
||||
items: stone_sword, flint_and_steel, netherrack:2, tnt:4, pork:3
|
||||
armor: 298,299,300,301
|
||||
|
||||
### ARENA SETUP
|
||||
# The arena setup is split into 4 different sections per arena: settings,
|
||||
# waves, rewards and coords (not shown until coords are set up).
|
||||
# Please refer to the Wiki for descriptions of all these settings.
|
||||
# Note: The REWARDS use the same notation as the items in the CLASS SETUP
|
||||
# section. However, only -one- item from the list is picked (at random) when
|
||||
# the rewards are given.
|
||||
arenas:
|
||||
default:
|
||||
settings:
|
||||
world: ''
|
||||
enabled: true
|
||||
protect: true
|
||||
entry-fee: ''
|
||||
logging: true
|
||||
clear-wave-before-next: false
|
||||
detonate-creepers: false
|
||||
detonate-damage: false
|
||||
lightning: true
|
||||
auto-equip-armor: true
|
||||
force-restore: false
|
||||
soft-restore: false
|
||||
soft-restore-drops: false
|
||||
require-empty-inv-join: false
|
||||
require-empty-inv-spec: false
|
||||
hellhounds: false
|
||||
pvp-enabled: false
|
||||
monster-infight: false
|
||||
allow-teleporting: false
|
||||
spectate-on-death: true
|
||||
share-items-in-arena: true
|
||||
min-players: 0
|
||||
max-players: 0
|
||||
max-join-distance: 0
|
||||
repair-delay: 5
|
||||
first-wave-delay: 5
|
||||
wave-interval: 20
|
||||
special-modulo: 4
|
||||
max-idle-time: 0
|
||||
waves:
|
||||
default:
|
||||
zombies: 10
|
||||
skeletons: 10
|
||||
spiders: 10
|
||||
creepers: 10
|
||||
wolves: 10
|
||||
special:
|
||||
powered-creepers: 10
|
||||
zombie-pigmen: 10
|
||||
angry-wolves: 10
|
||||
slimes: 10
|
||||
humans: 10
|
||||
giants: 0
|
||||
ghasts: 0
|
||||
rewards:
|
||||
waves:
|
||||
every:
|
||||
'3': feather, bone, stick
|
||||
'5': dirt:4, gravel:4, stone:4
|
||||
'10': iron_ingot:10, gold_ingot:8
|
||||
after:
|
||||
'7': minecart, storage_minecart, powered_minecart
|
||||
'13': iron_sword, iron_pickaxe, iron_spade
|
||||
'16': diamond_sword
|
57
resources/res/totals.txt
Normal file
57
resources/res/totals.txt
Normal file
@ -0,0 +1,57 @@
|
||||
### General data
|
||||
### Statistics for overall information about the arena, such as
|
||||
### times played, durations, max players seen, total kills, etc.
|
||||
general-info:
|
||||
total-games-played: 0
|
||||
total-duration: 0:00:00
|
||||
longest-session-duration: 0:00:00
|
||||
most-players: 0
|
||||
highest-wave-reached: 0
|
||||
total-monsters-killed: 0
|
||||
|
||||
### Class specific data
|
||||
### How many times has each class been played, and how many kills, how
|
||||
### much damage, etc. does the class make/do/take.
|
||||
classes:
|
||||
overall-distribution:
|
||||
# Percentages can be calculated with <classname> / total-count * 100.
|
||||
total-count: 0
|
||||
|
||||
#classes:
|
||||
# overall-distribution:
|
||||
# total-count: 0
|
||||
# archer:
|
||||
# kills:
|
||||
# damage-done:
|
||||
# damage-taken:
|
||||
# accuracy:
|
||||
# knight:
|
||||
# kills:
|
||||
# damage-done:
|
||||
# damage-taken:
|
||||
# accuracy:
|
||||
# ...
|
||||
### Reward data
|
||||
### Totals for all rewards given, perhaps good for balancing?
|
||||
rewards:
|
||||
total-given:
|
||||
# This might be useless information, I don't know.
|
||||
# Might have to make it data values instead of Material names?
|
||||
money: 0
|
||||
|
||||
### Player data
|
||||
### Total games played, kills, damage, swings and hits (for accuracy), and how
|
||||
### many times the player has played as each class.
|
||||
players: {}
|
||||
# garbagemule:
|
||||
# games-played: 5
|
||||
# kills: 4
|
||||
# damage-done: 251
|
||||
# damage-taken: 102
|
||||
# swings: 1820
|
||||
# hits: 1214
|
||||
# classes-played:
|
||||
# archer: 2
|
||||
# ...
|
||||
# Agnate:
|
||||
# ...
|
57
resources/res/totals.yml
Normal file
57
resources/res/totals.yml
Normal file
@ -0,0 +1,57 @@
|
||||
### General data
|
||||
### Statistics for overall information about the arena, such as
|
||||
### times played, durations, max players seen, total kills, etc.
|
||||
general-info:
|
||||
total-games-played: 0
|
||||
total-duration: 0:00:00
|
||||
longest-session-duration: 0:00:00
|
||||
most-players: 0
|
||||
highest-wave-reached: 0
|
||||
total-monsters-killed: 0
|
||||
|
||||
### Class specific data
|
||||
### How many times has each class been played, and how many kills, how
|
||||
### much damage, etc. does the class make/do/take.
|
||||
classes:
|
||||
overall-distribution:
|
||||
# Percentages can be calculated with <classname> / total-count * 100.
|
||||
total-count: 0
|
||||
|
||||
#classes:
|
||||
# overall-distribution:
|
||||
# total-count: 0
|
||||
# archer:
|
||||
# kills:
|
||||
# damage-done:
|
||||
# damage-taken:
|
||||
# accuracy:
|
||||
# knight:
|
||||
# kills:
|
||||
# damage-done:
|
||||
# damage-taken:
|
||||
# accuracy:
|
||||
# ...
|
||||
### Reward data
|
||||
### Totals for all rewards given, perhaps good for balancing?
|
||||
rewards:
|
||||
total-given:
|
||||
# This might be useless information, I don't know.
|
||||
# Might have to make it data values instead of Material names?
|
||||
money: 0
|
||||
|
||||
### Player data
|
||||
### Total games played, kills, damage, swings and hits (for accuracy), and how
|
||||
### many times the player has played as each class.
|
||||
players: {}
|
||||
# garbagemule:
|
||||
# games-played: 5
|
||||
# kills: 4
|
||||
# damage-done: 251
|
||||
# damage-taken: 102
|
||||
# swings: 1820
|
||||
# hits: 1214
|
||||
# classes-played:
|
||||
# archer: 2
|
||||
# ...
|
||||
# Agnate:
|
||||
# ...
|
42
src/com/garbagemule/MobArena/ArenaPlayer.java
Normal file
42
src/com/garbagemule/MobArena/ArenaPlayer.java
Normal file
@ -0,0 +1,42 @@
|
||||
package com.garbagemule.MobArena;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class ArenaPlayer
|
||||
{
|
||||
public MobArena plugin;
|
||||
public Player player;
|
||||
public String className;
|
||||
public Arena arena;
|
||||
public List<ItemStack> rewards;
|
||||
|
||||
protected boolean inArena, inLobby, inSpec, isReady;
|
||||
|
||||
// Session fields.
|
||||
public int kills, dmgDone, dmgTaken, swings, hits, deaths, lastWave;
|
||||
public int flagCaps, flagAttempts, flagReturns; // BG: Capture the Pumpkin
|
||||
public int baseCaps; // BG: Domination
|
||||
|
||||
// All-time fields.
|
||||
protected int totalKills, totalDmgDone, totalDmgTaken, totalSwings, totalHits, totalDeaths;
|
||||
protected int totalFlagCaps, totalFlagAttempts, totalFlagReturns; // BG: Capture the Pumpkin
|
||||
protected int totalBaseCaps; // BG: Domination
|
||||
|
||||
public ArenaPlayer(Player player, Arena arena, MobArena plugin)
|
||||
{
|
||||
this.player = player;
|
||||
this.arena = arena;
|
||||
this.plugin = plugin;
|
||||
|
||||
className = arena.classMap.get(player);
|
||||
rewards = new LinkedList<ItemStack>();
|
||||
}
|
||||
|
||||
public Player getPlayer() { return player; }
|
||||
public Arena getArena() { return arena; }
|
||||
public String getClassName() { return className; }
|
||||
}
|
211
src/com/garbagemule/MobArena/util/FileUtils.java
Normal file
211
src/com/garbagemule/MobArena/util/FileUtils.java
Normal file
@ -0,0 +1,211 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.util.config.Configuration;
|
||||
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
|
||||
public class FileUtils
|
||||
{
|
||||
public static enum Libs
|
||||
{
|
||||
xml("jdom.jar", "http://mirrors.ibiblio.org/pub/mirrors/maven2/org/jdom/jdom/1.1/jdom-1.1.jar");
|
||||
|
||||
public String url, filename;
|
||||
private Libs(String filename, String url)
|
||||
{
|
||||
this.filename = filename;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public static Libs getLib(String filename)
|
||||
{
|
||||
for (Libs l : Libs.values())
|
||||
if (l.filename.equals(filename))
|
||||
return l;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create default files from the res/ directory, if they exist.
|
||||
* @param filenames Files to be created.
|
||||
*/
|
||||
public static void extractDefaults(String... filenames)
|
||||
{
|
||||
for (String filename : filenames)
|
||||
extractFile(MobArena.dir, filename);
|
||||
}
|
||||
|
||||
public static void extractFile(File dir, String filename)
|
||||
{
|
||||
// Skip if file exists
|
||||
File file = new File(dir, filename);
|
||||
if (file.exists()) return;
|
||||
|
||||
// Skip if there is no resource with that name
|
||||
InputStream in = MobArena.class.getResourceAsStream("/res/" + filename);
|
||||
if (in == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
// Set up an output stream
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
byte[] buffer = new byte[8192];
|
||||
int length = 0;
|
||||
|
||||
// Write the resource data to the file
|
||||
while ((length = in.read(buffer)) > 0)
|
||||
out.write(buffer, 0, length);
|
||||
|
||||
if (in != null) in.close();
|
||||
if (out != null) out.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
System.out.println("[MobArena] ERROR! Problem creating file '" + filename + "'!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download all necessary libraries.
|
||||
* @param config The MobArena config-file
|
||||
*/
|
||||
public static void fetchLibs(Configuration config)
|
||||
{
|
||||
// Get all arenas
|
||||
List<String> arenas = config.getKeys("arenas");
|
||||
if (arenas == null) return;
|
||||
|
||||
// Add all the logging types
|
||||
Set<String> libs = new HashSet<String>();
|
||||
for (String a : arenas)
|
||||
{
|
||||
String type = config.getString("arenas." + a + ".settings.logging", "").toLowerCase();
|
||||
if (type.equals("xml"))
|
||||
libs.add(type);
|
||||
}
|
||||
|
||||
// Download all libraries
|
||||
for (String lib : libs)
|
||||
{
|
||||
if (download(Libs.valueOf(lib)))
|
||||
continue;
|
||||
|
||||
// If a library couldn't be downloaded, default to false.
|
||||
for (String a : arenas)
|
||||
{
|
||||
if (!config.getString("arenas." + a + ".settings.logging", "").equalsIgnoreCase(lib))
|
||||
continue;
|
||||
|
||||
System.out.println("[MobArena] ERROR! Unrecognized format for arena '" + a + "': " + lib + ". Logging disabled.");
|
||||
config.setProperty("arenas." + a + ".logging", "false");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized boolean download(Libs lib)
|
||||
{
|
||||
if (lib == null) return false;
|
||||
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
|
||||
try
|
||||
{
|
||||
URLConnection con = new URL(lib.url).openConnection();
|
||||
con.setUseCaches(false);
|
||||
|
||||
// Library folder: plugin/MobArena/lib
|
||||
File libdir = new File(MobArena.dir, "lib");
|
||||
libdir.mkdir();
|
||||
|
||||
// Create the file if it doesn't exist, if it does, return
|
||||
File file = new File(libdir, lib.filename);
|
||||
if (file.exists()) return true;
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
System.out.println("[MobArena] Downloading library: " + lib.filename + "...");
|
||||
|
||||
// Set up the streams
|
||||
in = con.getInputStream();
|
||||
out = new FileOutputStream(file);
|
||||
if (in == null || out == null) return false;
|
||||
|
||||
byte[] buffer = new byte[65536];
|
||||
int length = 0;
|
||||
|
||||
// Write the library to disk
|
||||
while ((length = in.read(buffer)) > 0)
|
||||
out.write(buffer, 0, length);
|
||||
|
||||
System.out.println("[MobArena] " + lib.filename + " downloaded in " + ((System.currentTimeMillis()-startTime)/1000.0) + " seconds.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
System.out.println("[MobArena] ERROR! Couldn't download library: " + lib.filename);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (in != null) in.close();
|
||||
if (out != null) out.close();
|
||||
}
|
||||
catch (Exception e) { e.printStackTrace(); }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static File getMostRecent(String folder)
|
||||
{
|
||||
return getMostRecent(new File(folder));
|
||||
}
|
||||
|
||||
public static File getMostRecent(File dir)
|
||||
{
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
if (!dir.isDirectory()) return null;
|
||||
|
||||
long mostRecent = 0;
|
||||
File result = null;
|
||||
|
||||
for (File file : dir.listFiles())
|
||||
{
|
||||
if (file.isDirectory() || file.lastModified() > mostRecent)
|
||||
continue;
|
||||
|
||||
result = file;
|
||||
mostRecent = file.lastModified();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Configuration parseXML(File file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Configuration parseCSV(File file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Configuration parsePlainText(File file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
42
src/com/garbagemule/MobArena/util/TextUtils.java
Normal file
42
src/com/garbagemule/MobArena/util/TextUtils.java
Normal file
@ -0,0 +1,42 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
public class TextUtils
|
||||
{
|
||||
/**
|
||||
* Add character padding on the right side of a String.
|
||||
* @param s String to add padding to
|
||||
* @param length Total amount of characters in the returned String
|
||||
* @param pad The padding character
|
||||
* @return A padded String with the input length
|
||||
*/
|
||||
public static String padRight(String s, int length, char pad)
|
||||
{
|
||||
StringBuffer buffy = new StringBuffer();
|
||||
buffy.append(s);
|
||||
for (int i = s.length(); i < length; i++)
|
||||
buffy.append(pad);
|
||||
return buffy.toString();
|
||||
}
|
||||
public static String padRight(String s, int length) { return padRight(s, length, ' '); }
|
||||
public static String padRight(int s, int length) { return padRight(Integer.toString(s), length, ' '); }
|
||||
public static String padRight(double s, int length) { return padRight(Double.toString(s), length, ' '); }
|
||||
|
||||
/**
|
||||
* Add character padding on the left side of a String.
|
||||
* @param s String to add padding to
|
||||
* @param length Total amount of characters in the returned String
|
||||
* @param pad The padding character
|
||||
* @return A padded String with the input length
|
||||
*/
|
||||
public static String padLeft(String s, int length, char pad)
|
||||
{
|
||||
StringBuffer buffy = new StringBuffer();
|
||||
for (int i = 0; i < length - s.length(); i++)
|
||||
buffy.append(pad);
|
||||
buffy.append(s);
|
||||
return buffy.toString();
|
||||
}
|
||||
public static String padLeft(String s, int length) { return padLeft(s, length, ' '); }
|
||||
public static String padLeft(int s, int length) { return padLeft(Integer.toString(s), length, ' '); }
|
||||
public static String padLeft(double s, int length) { return padLeft(Double.toString(s), length, ' '); }
|
||||
}
|
534
src/com/garbagemule/MobArena/util/WaveUtils.java
Normal file
534
src/com/garbagemule/MobArena/util/WaveUtils.java
Normal file
@ -0,0 +1,534 @@
|
||||
package com.garbagemule.MobArena.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.CreatureType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.config.Configuration;
|
||||
|
||||
import com.garbagemule.MobArena.MAUtils;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.waves.RecurrentWave;
|
||||
import com.garbagemule.MobArena.waves.SingleWave;
|
||||
import com.garbagemule.MobArena.waves.Wave;
|
||||
import com.garbagemule.MobArena.waves.Wave.BossAbility;
|
||||
import com.garbagemule.MobArena.waves.Wave.BossHealth;
|
||||
import com.garbagemule.MobArena.waves.Wave.SwarmAmount;
|
||||
import com.garbagemule.MobArena.waves.Wave.WaveBranch;
|
||||
import com.garbagemule.MobArena.waves.Wave.WaveGrowth;
|
||||
import com.garbagemule.MobArena.waves.Wave.WaveType;
|
||||
|
||||
public class WaveUtils
|
||||
{
|
||||
/**
|
||||
* Get all the spawnpoints that have players nearby.
|
||||
*/
|
||||
public static List<Location> getValidSpawnpoints(Collection<Location> spawnpoints, Collection<Player> players)
|
||||
{
|
||||
List<Location> result = new ArrayList<Location>();
|
||||
|
||||
for (Location s : spawnpoints)
|
||||
{
|
||||
for (Player p : players)
|
||||
{
|
||||
// If the player somehow got out of the arena world, kick him.
|
||||
if (!s.getWorld().getName().equals(p.getWorld().getName()))
|
||||
{
|
||||
System.out.println("[MobArena] Player '" + p.getName() + "' is not in the right world. Kicking...");
|
||||
p.kickPlayer("[MobArena] Cheater! (Warped out of the arena world.)");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s.distanceSquared(p.getLocation()) > MobArena.MIN_PLAYER_DISTANCE)
|
||||
continue;
|
||||
|
||||
result.add(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no players are in range, just use all the spawnpoints.
|
||||
if (result.isEmpty())
|
||||
result.addAll(spawnpoints);
|
||||
|
||||
// Else, return the valid spawnpoints.
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab and process all the waves in the config-file for the arena.
|
||||
*/
|
||||
public static TreeSet<Wave> getWaves(Configuration config, String arena, WaveBranch branch)
|
||||
{
|
||||
// Determine the branch type of the wave, and grab the appropriate comparator
|
||||
String b = branch.toString().toLowerCase();
|
||||
TreeSet<Wave> result = new TreeSet<Wave>(getComparator(branch));
|
||||
|
||||
// Grab the waves from the config-file
|
||||
String path = "arenas." + arena + ".waves." + b;
|
||||
List<String> waves = config.getKeys(path);
|
||||
|
||||
// If there are any waves, process them
|
||||
if (waves != null)
|
||||
{
|
||||
Wave wave;
|
||||
for (String w : waves)
|
||||
{
|
||||
// path argument becomes: "arenas.<arena>.waves.<branch>.<wave>."
|
||||
wave = getWave(config, path + "." + w + ".", w, branch);
|
||||
if (wave != null) result.add(wave);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no waves and the type is 'recurrent', add a default wave.
|
||||
if (branch == WaveBranch.RECURRENT && (result.isEmpty() || waves == null))
|
||||
{
|
||||
RecurrentWave def = new RecurrentWave("DEF_WAVE_AUTO", 1, 1, 1);
|
||||
def.setType(WaveType.DEFAULT);
|
||||
def.setGrowth(WaveGrowth.MEDIUM);
|
||||
def.setDefault(true);
|
||||
|
||||
result.add(def);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single wave based on the config-file, the path, and branch
|
||||
* @return A Wave object if it is well defined, null otherwise.
|
||||
*/
|
||||
private static Wave getWave(Configuration config, String path, String name, WaveBranch branch)
|
||||
{
|
||||
// Grab the wave type, if null, return null
|
||||
WaveType type = WaveType.fromString(config.getString(path + "type"));
|
||||
if (type == null || !isWaveWellDefined(config, path, branch, type))
|
||||
return null;
|
||||
|
||||
// TODO: Generate waves properly. These are place-holders!
|
||||
Wave result;
|
||||
if (branch == WaveBranch.RECURRENT)
|
||||
{
|
||||
int frequency = config.getInt(path + "frequency", 0);
|
||||
int priority = config.getInt(path + "priority", 0);
|
||||
int wave = config.getInt(path + "wave", frequency);
|
||||
result = new RecurrentWave(name, wave, frequency, priority);
|
||||
}
|
||||
else
|
||||
{
|
||||
int wave = config.getInt(path + "wave", 0);
|
||||
result = new SingleWave(name, wave);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
public static RecurrentWave getRecurrentWave(Configuration config, String arena, String w)
|
||||
{
|
||||
// Grab the path
|
||||
String path = "arenas." + arena + ".waves.recurrent." + w + ".";
|
||||
|
||||
// Ensure that frequency and priority exist, otherwise return null
|
||||
int frequency = config.getInt(path + "frequency", 0);
|
||||
int priority = config.getInt(path + "priority", 0);
|
||||
if (frequency == 0 || priority == 0) return null;
|
||||
|
||||
// Grab other variables
|
||||
int wave = config.getInt(path + "wave", frequency);
|
||||
WaveType type = WaveType.fromString(config.getString(path + "type", "default"));
|
||||
WaveGrowth growth = WaveGrowth.fromString(config.getString(path + "growth", "medium"));
|
||||
|
||||
// Grab monster distribution
|
||||
//Map<CreatureType,Integer> monsters = getWaveMonsters(config, arena, path, type);
|
||||
|
||||
// Create the wave
|
||||
RecurrentWave result = new RecurrentWave(w, wave, frequency, priority, type, growth);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static SingleWave getSingleWave(Configuration config, String arena, String w)
|
||||
{
|
||||
// Grab the path
|
||||
String path = "arenas." + arena + ".waves.single." + w + ".";
|
||||
|
||||
// Ensure that the wave number exists, otherwise return null
|
||||
int wave = config.getInt(path + "wave", 0);
|
||||
if (wave == 0) return null;
|
||||
|
||||
// Grab other variables
|
||||
|
||||
SingleWave result = new SingleWave(w, wave);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Map<CreatureType,Integer> getWaveMonsters(Configuration config, String arena, String path, String type)
|
||||
{
|
||||
Map<CreatureType,Integer> result = new HashMap<CreatureType,Integer>();
|
||||
|
||||
List<String> monsters = config.getKeys(path + "monsters");
|
||||
|
||||
// If no monsters specified, make sure to add some
|
||||
if (monsters == null)
|
||||
{
|
||||
if (type.equals("default"))
|
||||
{
|
||||
result.put(CreatureType.ZOMBIE, 10);
|
||||
result.put(CreatureType.SKELETON, 10);
|
||||
result.put(CreatureType.SPIDER, 10);
|
||||
result.put(CreatureType.CREEPER, 10);
|
||||
result.put(CreatureType.WOLF, 10);
|
||||
}
|
||||
else if (type.equals("default"))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Comparators
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/**
|
||||
* Get a comparator based on the WaveBranch parameter.
|
||||
*/
|
||||
public static Comparator<Wave> getComparator(WaveBranch branch)
|
||||
{
|
||||
if (branch == WaveBranch.SINGLE)
|
||||
return getSingleComparator();
|
||||
else if (branch == WaveBranch.RECURRENT)
|
||||
return getRecurrentComparator();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Comparator that compares Wave objects by wave number.
|
||||
* If the wave numbers are equal, the waves are equal. This is to
|
||||
* DISALLOW "duplicates" in the SINGLE WAVES collection.
|
||||
* @return Comparator whose compare()-method compares wave numbers.
|
||||
*/
|
||||
public static Comparator<Wave> getSingleComparator()
|
||||
{
|
||||
return new Comparator<Wave>()
|
||||
{
|
||||
public int compare(Wave w1, Wave w2)
|
||||
{
|
||||
if (w1.getWave() < w2.getWave())
|
||||
return -1;
|
||||
else if (w1.getWave() > w2.getWave())
|
||||
return 1;
|
||||
else return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Comparator that compares Wave objects by priority.
|
||||
* If the priorities are equal, the names are compared. This is to
|
||||
* ALLOW "duplicates" in the RECURRENT WAVES collection.
|
||||
* @return Comparator whose compare()-method compares wave priorities.
|
||||
*/
|
||||
public static Comparator<Wave> getRecurrentComparator()
|
||||
{
|
||||
return new Comparator<Wave>()
|
||||
{
|
||||
public int compare(Wave w1, Wave w2)
|
||||
{
|
||||
if (w1.getPriority() < w2.getPriority())
|
||||
return -1;
|
||||
else if (w1.getPriority() > w2.getPriority())
|
||||
return 1;
|
||||
else return w1.getName().compareTo(w2.getName());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the single waves for the given arena.
|
||||
*/
|
||||
/*public static TreeSet<SingleWave> getSingleWaves(Configuration config, String arena)
|
||||
{
|
||||
TreeSet<SingleWave> result = new TreeSet<SingleWave>();
|
||||
|
||||
List<String> waves = config.getKeys("arenas." + arena + ".waves.single");
|
||||
if (waves != null)
|
||||
{
|
||||
int wave;
|
||||
|
||||
for (String w : waves)
|
||||
{
|
||||
wave = config.getInt("arenas." + arena + ".waves.single." + w + ".wave", 0);
|
||||
if (wave == 0) continue;
|
||||
result.add(new SingleWave(w, wave));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Get all the recurrent waves for the given arena.
|
||||
* If no waves are found, a default wave is added. This ensures that
|
||||
* the arena always has monsters spawning, regardless of how badly the
|
||||
* user messes up the config-file.
|
||||
*/
|
||||
/*public static TreeSet<RecurrentWave> getRecurrentWaves(Configuration config, String arena)
|
||||
{
|
||||
TreeSet<RecurrentWave> result = new TreeSet<RecurrentWave>();
|
||||
|
||||
List<String> waves = config.getKeys("arenas." + arena + ".waves.recurrent");
|
||||
if (waves != null)
|
||||
{
|
||||
int wave, frequency, priority;
|
||||
|
||||
for (String w : waves)
|
||||
{
|
||||
frequency = config.getInt("arenas." + arena + ".waves.recurrent." + w + ".frequency", 0);
|
||||
priority = config.getInt("arenas." + arena + ".waves.recurrent." + w + ".priority", 0);
|
||||
if (frequency == 0 || priority == 0) continue;
|
||||
|
||||
wave = config.getInt("arenas." + arena + ".waves.single." + w + ".wave", frequency);
|
||||
result.add(new RecurrentWave(w, wave, frequency, priority));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RecurrentWave def = new RecurrentWave("DEF_WAVE_AUTO", 1, 1, 1);
|
||||
def.setType(WaveType.DEFAULT);
|
||||
def.setGrowth(WaveGrowth.MEDIUM);
|
||||
|
||||
RecurrentWave spec = new RecurrentWave("SPEC_WAVE_AUTO", 4, 4, 4);
|
||||
spec.setType(WaveType.SPECIAL);
|
||||
|
||||
result.add(def);
|
||||
result.add(spec);
|
||||
}
|
||||
|
||||
return result;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
/*////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Well definedness checks
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/**
|
||||
* Check if a wave in the config-file is well-defined.
|
||||
* The method first checks if the wave is well-defined according to
|
||||
* the branch-specific requirements. Recurrent waves must have the
|
||||
* two nodes 'priority' and 'frequency', and single waves must have
|
||||
* the node 'wave'.
|
||||
* Any other requirements are type-specific, and thus we check if the
|
||||
* type is well-defined.
|
||||
* @param config Config-file Configuration
|
||||
* @param path The absolute path of the wave
|
||||
* @param branch The branch of the wave
|
||||
* @param type The wave type
|
||||
* @return true, if the wave is well-defined, false otherwise
|
||||
*/
|
||||
private static boolean isWaveWellDefined(Configuration config, String path, WaveBranch branch, WaveType type)
|
||||
{
|
||||
if (branch == WaveBranch.RECURRENT)
|
||||
{
|
||||
// REQUIRED: Priority and frequency
|
||||
int priority = config.getInt(path + "priority", 0);
|
||||
int frequency = config.getInt(path + "frequency", 0);
|
||||
if (priority == 0 || frequency == 0)
|
||||
return false;
|
||||
|
||||
// TODO: OPTIONAL: Wave growth, others?
|
||||
}
|
||||
else if (branch == WaveBranch.SINGLE)
|
||||
{
|
||||
// REQUIRED: Wave number
|
||||
int wave = config.getInt(path + "wave", 0);
|
||||
if (wave == 0)
|
||||
return false;
|
||||
}
|
||||
else return false;
|
||||
|
||||
// Passed branch-checks; check type
|
||||
return isTypeWellDefined(config, path, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a wave type in the config-file is well-defined.
|
||||
* The method calls the appropriate sub-method to check if the type
|
||||
* is well-defined.
|
||||
* @param config Config-file Configuration
|
||||
* @param path The absolute path of the wave
|
||||
* @param type The wave type
|
||||
* @return true, if the wave type is well-defined, false otherwise
|
||||
*/
|
||||
private static boolean isTypeWellDefined(Configuration config, String path, WaveType type)
|
||||
{
|
||||
if (type == WaveType.DEFAULT || type == WaveType.SPECIAL)
|
||||
return isNormalWaveWellDefined(config, path);
|
||||
else if (type == WaveType.BOSS)
|
||||
return isBossWaveWellDefined(config, path);
|
||||
else if (type == WaveType.SWARM)
|
||||
return isSwarmWaveWellDefined(config, path);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a default or special wave is well-defined.
|
||||
* There are no REQUIRED nodes for default or special wave types, besides
|
||||
* the ones for the branch they belong to.
|
||||
* The only OPTIONAL node is (currently) 'monsters'
|
||||
* @param config Config-file Configuration
|
||||
* @param path The absolute path of the wave
|
||||
* @return true, if the wave type is well-defined, false otherwise
|
||||
*/
|
||||
private static boolean isNormalWaveWellDefined(Configuration config, String path)
|
||||
{
|
||||
// OPTIONAL: Monsters
|
||||
List<String> monsters = config.getKeys(path + "monsters");
|
||||
if (monsters == null)
|
||||
return true;
|
||||
|
||||
for (String monster : monsters)
|
||||
{
|
||||
if (getEnumFromString(CreatureType.class, monster) != null)
|
||||
continue;
|
||||
|
||||
MAUtils.error("Invalid monster type '" + monster + "' in " + path);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a swarm wave is well defined
|
||||
* @param config Config-file Configuration
|
||||
* @param path The absolute path of the wave
|
||||
* @return true, if the wave type is well-defined, false otherwise
|
||||
*/
|
||||
private static boolean isSwarmWaveWellDefined(Configuration config, String path)
|
||||
{
|
||||
// REQUIRED: Monster type
|
||||
String monster = config.getString(path + "monster");
|
||||
if (monster == null)
|
||||
{
|
||||
MAUtils.error("Missing monster type in '" + path);
|
||||
return false;
|
||||
}
|
||||
else if (getEnumFromString(CreatureType.class, monster) == null)
|
||||
{
|
||||
MAUtils.error("Invalid monster type '" + monster + "' in " + path);
|
||||
return false;
|
||||
}
|
||||
|
||||
// OPTIONAL: Amount
|
||||
String amount = config.getString(path + "amount");
|
||||
if (amount != null && SwarmAmount.fromString(amount) == null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a boss wave is well defined.
|
||||
* @param config Config-file Configuration
|
||||
* @param path The absolute path of the wave
|
||||
* @return true, if the wave type is well-defined, false otherwise
|
||||
*/
|
||||
private static boolean isBossWaveWellDefined(Configuration config, String path)
|
||||
{
|
||||
// REQUIRED: Monster type
|
||||
String monster = config.getString(path + "monster");
|
||||
if (monster == null)
|
||||
{
|
||||
MAUtils.error("Missing monster type in '" + path);
|
||||
return false;
|
||||
}
|
||||
else if (getEnumFromString(CreatureType.class, monster) == null)
|
||||
{
|
||||
MAUtils.error("Invalid monster type '" + monster + "' in " + path);
|
||||
return false;
|
||||
}
|
||||
|
||||
// OPTIONAL: Abilities
|
||||
String abilities = config.getString(path + "abilities");
|
||||
if (abilities != null)
|
||||
{
|
||||
for (String ability : abilities.split(","))
|
||||
{
|
||||
if (BossAbility.fromString(ability.trim().toUpperCase()) != null)
|
||||
continue;
|
||||
|
||||
MAUtils.error("Invalid boss ability '" + ability + "' in " + path);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: OPTIONAL: Adds
|
||||
// Unsure about config-file implementation...
|
||||
|
||||
// OPTIONAL: Health
|
||||
String health = config.getString(path + "health");
|
||||
if (health != null && BossHealth.fromString(health) == null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Misc - Perhaps move into MAUtils?
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/**
|
||||
* Get the num value of a string, def if it doesn't exist.
|
||||
*/
|
||||
public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string, T def)
|
||||
{
|
||||
if (c != null && string != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Enum.valueOf(c, string.trim().toUpperCase());
|
||||
}
|
||||
catch (IllegalArgumentException ex) { }
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the enum value of a string, null if it doesn't exist.
|
||||
*/
|
||||
public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string)
|
||||
{
|
||||
if(c != null && string != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Enum.valueOf(c, string.trim().toUpperCase());
|
||||
}
|
||||
catch(IllegalArgumentException ex) { }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
153
src/com/garbagemule/MobArena/util/data/PlainText.java
Normal file
153
src/com/garbagemule/MobArena/util/data/PlainText.java
Normal file
@ -0,0 +1,153 @@
|
||||
package com.garbagemule.MobArena.util.data;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.garbagemule.MobArena.ArenaLog;
|
||||
import com.garbagemule.MobArena.ArenaPlayer;
|
||||
import com.garbagemule.MobArena.MAUtils;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.util.TextUtils;
|
||||
|
||||
public class PlainText
|
||||
{
|
||||
public static void saveSessionData(ArenaLog log)
|
||||
{
|
||||
File dir = new File(MobArena.arenaDir, log.getArena().configName());
|
||||
if (!dir.exists()) dir.mkdirs();
|
||||
|
||||
// General information
|
||||
List<String> toWrite = new LinkedList<String>();
|
||||
toWrite.add("Start: " + log.getStartTime());
|
||||
toWrite.add("End: " + log.getEndTime());
|
||||
toWrite.add("Duration: " + log.getDuration());
|
||||
toWrite.add("Last wave: " + log.getLastWave());
|
||||
toWrite.add(" ");
|
||||
|
||||
int classLength = longestClassName(log.distribution.keySet());
|
||||
int classCount = log.distribution.keySet().size();
|
||||
int playerCount = log.players.keySet().size();
|
||||
|
||||
// Class distribution
|
||||
toWrite.add("Class Distribution: " + classCount + " classes");
|
||||
toWrite.addAll(getClassDistribution(log.distribution, playerCount, classLength));
|
||||
toWrite.add(" ");
|
||||
|
||||
// Player data
|
||||
toWrite.add("Player Data: " + playerCount + " players");
|
||||
toWrite.addAll(getPlayerData(log.players, classLength));
|
||||
|
||||
// Serialize!
|
||||
try
|
||||
{
|
||||
File file = new File(dir, "lastsession.txt");
|
||||
if (!file.exists()) file.createNewFile();
|
||||
|
||||
FileWriter fw = new FileWriter(file);
|
||||
for (String s : toWrite)
|
||||
{
|
||||
fw.write(s);
|
||||
fw.write(System.getProperty("line.separator"));
|
||||
}
|
||||
fw.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
System.out.println("[MobArena] ERROR! Problem saving session data for arena '" + log.getArena().configName() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateArenaTotals(ArenaLog log)
|
||||
{
|
||||
// Grab the Configuration
|
||||
//Configuration totals = Totals.getArenaTotals(log.arena);
|
||||
|
||||
// Parse shit
|
||||
|
||||
// Serialize
|
||||
}
|
||||
|
||||
/* public static void updateTotals(ArenaLog log, MobArena plugin)
|
||||
{
|
||||
File dir = new File(MobArena.arenaDir, log.getArena().configName());
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
} */
|
||||
|
||||
private static List<String> getClassDistribution(Map<String,Integer> map, int playerCount, int classLength)
|
||||
{
|
||||
List<String> result = new LinkedList<String>();
|
||||
|
||||
// Add each entry - class: # (percentage%)
|
||||
for (Map.Entry<String,Integer> entry : map.entrySet())
|
||||
{
|
||||
StringBuffer buffy = new StringBuffer(classLength + 15);
|
||||
|
||||
buffy.append("- ");
|
||||
buffy.append(TextUtils.padRight(entry.getKey() + ":", classLength + 3)); // <classname>:
|
||||
buffy.append(TextUtils.padLeft(entry.getValue().toString(), 2)); // <count>
|
||||
buffy.append("(" + (entry.getValue()*100/playerCount) + "%)"); // (<count/playerCount>%)
|
||||
|
||||
result.add(buffy.toString());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<String> getPlayerData(Map<Player,ArenaPlayer> map, int classLength)
|
||||
{
|
||||
List<String> result = new LinkedList<String>();
|
||||
String pad = " ";
|
||||
|
||||
// Padding variables; +2 for extra padding
|
||||
int NAME = 12, CLASS = classLength, WAVE = 4, KILLS = 5, DMGDONE = 7, DMGTAKEN = 8, ACCURACY = 8;
|
||||
result.add(" " + TextUtils.padRight("NAME", NAME+2) +
|
||||
TextUtils.padRight("CLASS", CLASS+2) +
|
||||
TextUtils.padRight("WAVE", WAVE+2) +
|
||||
TextUtils.padRight("KILLS", KILLS+2) +
|
||||
TextUtils.padRight("DMGDONE", DMGDONE+2) +
|
||||
TextUtils.padRight("DMGTAKEN", DMGTAKEN+2) +
|
||||
TextUtils.padRight("ACCURACY", ACCURACY+2) +
|
||||
"REWARDS");
|
||||
|
||||
// Add each player - name class wave dmgdone dmgtaken accuracy rewards
|
||||
for (Map.Entry<Player,ArenaPlayer> entry : map.entrySet())
|
||||
{
|
||||
Player p = entry.getKey();
|
||||
ArenaPlayer ap = entry.getValue();
|
||||
StringBuffer buffy = new StringBuffer(80);
|
||||
|
||||
String name = (p.getName().length() <= NAME) ? p.getName() : p.getName().substring(0, NAME+1);
|
||||
buffy.append("- ");
|
||||
buffy.append(TextUtils.padRight(name, NAME)); buffy.append(pad);
|
||||
buffy.append(TextUtils.padRight(ap.getClassName(), CLASS)); buffy.append(pad);
|
||||
buffy.append(TextUtils.padLeft(ap.lastWave, WAVE)); buffy.append(pad);
|
||||
buffy.append(TextUtils.padLeft(ap.kills, KILLS)); buffy.append(pad);
|
||||
buffy.append(TextUtils.padLeft(ap.dmgDone, DMGDONE)); buffy.append(pad);
|
||||
buffy.append(TextUtils.padLeft(ap.dmgTaken, DMGTAKEN)); buffy.append(pad);
|
||||
buffy.append(TextUtils.padLeft(((ap.swings != 0) ? ap.hits*100/ap.swings : 0), ACCURACY-1)); buffy.append("%"); buffy.append(pad);
|
||||
buffy.append(MAUtils.listToString(ap.rewards));
|
||||
|
||||
result.add(buffy.toString());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int longestClassName(Collection<String> names)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
for (String c : names)
|
||||
if (c.length() > result)
|
||||
result = c.length();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
159
src/com/garbagemule/MobArena/util/data/Totals.java
Normal file
159
src/com/garbagemule/MobArena/util/data/Totals.java
Normal file
@ -0,0 +1,159 @@
|
||||
package com.garbagemule.MobArena.util.data;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.bukkit.util.config.Configuration;
|
||||
|
||||
import com.garbagemule.MobArena.Arena;
|
||||
import com.garbagemule.MobArena.ArenaLog;
|
||||
import com.garbagemule.MobArena.ArenaPlayer;
|
||||
import com.garbagemule.MobArena.MAUtils;
|
||||
import com.garbagemule.MobArena.MobArena;
|
||||
import com.garbagemule.MobArena.util.FileUtils;
|
||||
|
||||
public class Totals
|
||||
{
|
||||
private static final String totals_yml = "totals.yml";
|
||||
|
||||
/**
|
||||
* Update the totals-file with the session data from the ArenaLog object
|
||||
* @param log ArenaLog to update with
|
||||
*/
|
||||
public static void updateArenaTotals(ArenaLog log)
|
||||
{
|
||||
// Grab the configuration
|
||||
Configuration totals = getArenaTotals(log.arena);
|
||||
totals.load();
|
||||
|
||||
// General data
|
||||
updateInt(totals, "general-info.total-games-played", 1, true);
|
||||
updateInt(totals, "general-info.most-players", log.players.keySet().size(), false);
|
||||
updateInt(totals, "general-info.highest-wave-reached", log.lastWave, false);
|
||||
updateInt(totals, "general-info.total-monsters-killed", countKills(log), true);
|
||||
updateDuration(totals, "general-info.total-duration", log.getDurationLong(), true);
|
||||
updateDuration(totals, "general-info.longest-session-duration", log.getDurationLong(), false);
|
||||
|
||||
// Classes
|
||||
updateInt(totals, "classes.overall-distribution.total-count", log.players.keySet().size(), true);
|
||||
for (String c : log.arena.getClasses())
|
||||
{
|
||||
// Array {kills, dmgDone, dmgTaken}
|
||||
int[] a = getKillsAndDamageByClass(log, c);
|
||||
updateInt(totals,"classes." + c + ".kills", a[0],true);
|
||||
updateInt(totals,"classes." + c + ".damage-done", a[1],true);
|
||||
updateInt(totals,"classes." + c + ".damage-taken",a[2],true);
|
||||
}
|
||||
|
||||
// Rewards
|
||||
|
||||
// Players
|
||||
for (ArenaPlayer ap : log.players.values())
|
||||
{
|
||||
// Basic values
|
||||
updateInt(totals,"players." + ap.player.getName() + ".games-played", 1, true);
|
||||
updateInt(totals,"players." + ap.player.getName() + ".kills", ap.kills, true);
|
||||
updateInt(totals,"players." + ap.player.getName() + ".damage-done", ap.dmgDone, true);
|
||||
updateInt(totals,"players." + ap.player.getName() + ".damage-taken", ap.dmgTaken, true);
|
||||
updateInt(totals,"players." + ap.player.getName() + ".swings", ap.swings, true);
|
||||
updateInt(totals,"players." + ap.player.getName() + ".hits", ap.hits, true);
|
||||
|
||||
// Class count
|
||||
updateInt(totals,"players." + ap.player.getName() + ".classes." + ap.className,1,true);
|
||||
}
|
||||
|
||||
// Save everything
|
||||
totals.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or create a Configuration from the totals-file
|
||||
* @param arena Arena to get or create a Configuration for
|
||||
* @return Configuration from the arena's totals-file
|
||||
*/
|
||||
public static Configuration getArenaTotals(Arena arena)
|
||||
{
|
||||
// Create the folder if it doesn't exist.
|
||||
File dir = new File(MobArena.arenaDir, arena.configName());
|
||||
if (!dir.exists()) dir.mkdirs();
|
||||
|
||||
File file = new File(dir, totals_yml);
|
||||
if (!file.exists()) FileUtils.extractFile(dir, totals_yml);
|
||||
|
||||
// Grab the totals-file and return the Configuration
|
||||
return new Configuration(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an integer in a config-file
|
||||
* @param totals Configuration to alter
|
||||
* @param node Node to alter
|
||||
* @param b Integer for comparison
|
||||
* @param increment If true, the node will be incremented by b, otherwise overwritten if greater
|
||||
*/
|
||||
private static void updateInt(Configuration totals, String node, int b, boolean increment)
|
||||
{
|
||||
int a = totals.getInt(node, 0);
|
||||
|
||||
if (increment) totals.setProperty(node, a+b);
|
||||
else if (b > a) totals.setProperty(node, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a duration in a config-file
|
||||
* @param totals Configuration to alter
|
||||
* @param node Node to alter
|
||||
* @param b Duration for comparison. This is a java.sql.Timestamp.getTime() long
|
||||
* @param increment If true, the node will be incremented by b, otherwise overwritten if greater
|
||||
*/
|
||||
private static void updateDuration(Configuration totals, String node, long b, boolean increment)
|
||||
{
|
||||
long a = MAUtils.parseDuration(totals.getString(node, "0:00:00"));
|
||||
|
||||
if (increment) totals.setProperty(node, MAUtils.getDuration(a+b));
|
||||
else if (b > a) totals.setProperty(node, MAUtils.getDuration(b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total kills from an arena session
|
||||
* @param log The ArenaLog to count kills in
|
||||
* @return Total kills
|
||||
*/
|
||||
private static int countKills(ArenaLog log)
|
||||
{
|
||||
int kills = 0;
|
||||
for (ArenaPlayer ap : log.players.values())
|
||||
kills += ap.kills;
|
||||
return kills;
|
||||
}
|
||||
|
||||
/*
|
||||
private static int getKillsByClass(ArenaLog log, String className)
|
||||
{
|
||||
int kills = 0;
|
||||
for (ArenaPlayer ap : log.players.values())
|
||||
if (ap.className.equals(className))
|
||||
kills += ap.kills;
|
||||
return kills;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get a (dirty) int-array in the form {kills, damage done, damage taken} for a class
|
||||
* @param log ArenaLog to count kills, damage done/taken from
|
||||
* @param className The class to count for
|
||||
* @return Resulting kills, damage done and damage taken in an int-array
|
||||
*/
|
||||
private static int[] getKillsAndDamageByClass(ArenaLog log, String className)
|
||||
{
|
||||
int kills = 0, dmgDone = 0, dmgTaken = 0;
|
||||
for (ArenaPlayer ap : log.players.values())
|
||||
{
|
||||
if (!ap.className.equals(className))
|
||||
continue;
|
||||
kills += ap.kills;
|
||||
dmgDone += ap.dmgDone;
|
||||
dmgTaken += ap.dmgTaken;
|
||||
}
|
||||
return new int[]{kills, dmgDone, dmgTaken};
|
||||
}
|
||||
}
|
6
src/com/garbagemule/MobArena/util/data/XML.java
Normal file
6
src/com/garbagemule/MobArena/util/data/XML.java
Normal file
@ -0,0 +1,6 @@
|
||||
package com.garbagemule.MobArena.util.data;
|
||||
|
||||
public class XML
|
||||
{
|
||||
|
||||
}
|
90
src/com/garbagemule/MobArena/waves/AbstractWave.java
Normal file
90
src/com/garbagemule/MobArena/waves/AbstractWave.java
Normal file
@ -0,0 +1,90 @@
|
||||
package com.garbagemule.MobArena.waves;
|
||||
|
||||
public abstract class AbstractWave implements Wave
|
||||
{
|
||||
private String name;
|
||||
private int wave, frequency, priority;
|
||||
private WaveType type;
|
||||
private WaveGrowth growth;
|
||||
|
||||
/**
|
||||
* Basic wave constructor.
|
||||
* Constructs a wave with an initial wave number, a wave frequency, and
|
||||
* a wave priority.
|
||||
* @param wave Initial wave number. This is the first wave number this wave can spawn at.
|
||||
* @param frequency How often the wave can spawn.
|
||||
* @param priority The priority of the wave.
|
||||
*/
|
||||
public AbstractWave(String name, int wave, int frequency, int priority)
|
||||
{
|
||||
this.name = name;
|
||||
this.wave = wave;
|
||||
this.frequency = frequency;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default wave constructor.
|
||||
* Constructs a basic wave with additional information in the type of
|
||||
* wave and the wave growth.
|
||||
* @param wave Initial wave number. This is the first wave number this wave can spawn at.
|
||||
* @param frequency How often the wave can spawn.
|
||||
* @param priority The priority of the wave.
|
||||
* @param type The type of wave.
|
||||
* @param growth The growth rate of the wave.
|
||||
*/
|
||||
public AbstractWave(String name, int wave, int frequency, int priority, WaveType type, WaveGrowth growth)
|
||||
{
|
||||
this(name, wave, frequency, priority);
|
||||
this.type = type;
|
||||
this.growth = growth;
|
||||
}
|
||||
|
||||
public WaveType getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(WaveType type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public WaveGrowth getGrowth()
|
||||
{
|
||||
return growth;
|
||||
}
|
||||
|
||||
public void setGrowth(WaveGrowth growth)
|
||||
{
|
||||
this.growth = growth;
|
||||
}
|
||||
|
||||
public int getWave()
|
||||
{
|
||||
return wave;
|
||||
}
|
||||
|
||||
public int getFrequency()
|
||||
{
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public int getPriority()
|
||||
{
|
||||
return priority;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "[name=" + name +
|
||||
", wave=" + wave +
|
||||
", frequency=" + frequency +
|
||||
", priority=" + priority + "]";
|
||||
}
|
||||
}
|
35
src/com/garbagemule/MobArena/waves/BossWave.java
Normal file
35
src/com/garbagemule/MobArena/waves/BossWave.java
Normal file
@ -0,0 +1,35 @@
|
||||
package com.garbagemule.MobArena.waves;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.entity.Creature;
|
||||
|
||||
import com.garbagemule.MobArena.waves.Wave.BossAbility;
|
||||
|
||||
public class BossWave
|
||||
{
|
||||
private Creature boss;
|
||||
private Set<BossAbility> abilities;
|
||||
private Set<Creature> adds;
|
||||
private int health;
|
||||
|
||||
public BossWave(Creature boss)
|
||||
{
|
||||
this.boss = boss;
|
||||
}
|
||||
|
||||
public void addAbility(BossAbility ability)
|
||||
{
|
||||
abilities.add(ability);
|
||||
}
|
||||
|
||||
public void addAdds(Creature creature)
|
||||
{
|
||||
adds.add(creature);
|
||||
}
|
||||
|
||||
public void setHealth(int health)
|
||||
{
|
||||
this.health = health;
|
||||
}
|
||||
}
|
47
src/com/garbagemule/MobArena/waves/RecurrentWave.java
Normal file
47
src/com/garbagemule/MobArena/waves/RecurrentWave.java
Normal file
@ -0,0 +1,47 @@
|
||||
package com.garbagemule.MobArena.waves;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class RecurrentWave extends AbstractWave
|
||||
{
|
||||
public RecurrentWave(String name, int wave, int frequency, int priority)
|
||||
{
|
||||
super(name, wave, frequency, priority);
|
||||
}
|
||||
|
||||
public RecurrentWave(String name, int wave, int frequency, int priority, WaveType type, WaveGrowth growth)
|
||||
{
|
||||
super(name, wave, frequency, priority, type, growth);
|
||||
}
|
||||
|
||||
public void spawn(int wave, Collection<Location> spawnpoints)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void setDefault(boolean def)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public boolean matches(int wave)
|
||||
{
|
||||
return wave % getWave() + getFrequency() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recurrent waves are sorted by their priorities.
|
||||
* If the priorities are equal, the names are compared. This is to
|
||||
* ALLOW "duplicates" in the RECURRENT WAVES collection.
|
||||
*/
|
||||
public int compareTo(Wave w)
|
||||
{
|
||||
if (getPriority() < w.getPriority())
|
||||
return -1;
|
||||
else if (getPriority() > w.getPriority())
|
||||
return 1;
|
||||
else return getName().compareTo(w.getName());
|
||||
}
|
||||
}
|
37
src/com/garbagemule/MobArena/waves/SingleWave.java
Normal file
37
src/com/garbagemule/MobArena/waves/SingleWave.java
Normal file
@ -0,0 +1,37 @@
|
||||
package com.garbagemule.MobArena.waves;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class SingleWave extends AbstractWave
|
||||
{
|
||||
public SingleWave(String name, int wave)
|
||||
{
|
||||
super(name, wave, 0, 0);
|
||||
}
|
||||
|
||||
public void spawn(int wave, Collection<Location> spawnpoints)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public boolean matches(int wave)
|
||||
{
|
||||
return getWave() == wave;
|
||||
}
|
||||
|
||||
/**
|
||||
* Single waves are compared by their wave numbers.
|
||||
* If the wave numbers are equal, the waves are equal. This is to
|
||||
* DISALLOW "duplicates" in the SINGLE WAVES collection.
|
||||
*/
|
||||
public int compareTo(Wave w)
|
||||
{
|
||||
if (this.getWave() < w.getWave())
|
||||
return -1;
|
||||
else if (this.getWave() > w.getWave())
|
||||
return 1;
|
||||
else return 0;
|
||||
}
|
||||
}
|
119
src/com/garbagemule/MobArena/waves/Wave.java
Normal file
119
src/com/garbagemule/MobArena/waves/Wave.java
Normal file
@ -0,0 +1,119 @@
|
||||
package com.garbagemule.MobArena.waves;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import com.garbagemule.MobArena.util.WaveUtils;
|
||||
|
||||
public interface Wave extends Comparable<Wave>
|
||||
{
|
||||
public enum WaveBranch
|
||||
{
|
||||
SINGLE, RECURRENT;
|
||||
}
|
||||
|
||||
public enum WaveType
|
||||
{
|
||||
DEFAULT, SPECIAL, SWARM, BOSS;
|
||||
|
||||
public static WaveType fromString(String string)
|
||||
{
|
||||
return WaveUtils.getEnumFromString(WaveType.class, string, DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
public enum WaveGrowth
|
||||
{
|
||||
SLOW, MEDIUM, FAST;
|
||||
|
||||
public static WaveGrowth fromString(String string)
|
||||
{
|
||||
return WaveUtils.getEnumFromString(WaveGrowth.class, string, MEDIUM);
|
||||
}
|
||||
}
|
||||
|
||||
public enum BossAbility
|
||||
{
|
||||
ARROWS, FIREBALLS, RING_OF_FIRE;
|
||||
|
||||
public static BossAbility fromString(String string)
|
||||
{
|
||||
return WaveUtils.getEnumFromString(BossAbility.class, string);
|
||||
}
|
||||
}
|
||||
|
||||
public enum BossHealth
|
||||
{
|
||||
LOW, MEDIUM, HIGH;
|
||||
|
||||
public static BossHealth fromString(String string)
|
||||
{
|
||||
return WaveUtils.getEnumFromString(BossHealth.class, string);
|
||||
}
|
||||
}
|
||||
|
||||
public enum SwarmAmount
|
||||
{
|
||||
LOW, MEDIUM, HIGH, PSYCHO;
|
||||
|
||||
public static SwarmAmount fromString(String string)
|
||||
{
|
||||
return WaveUtils.getEnumFromString(SwarmAmount.class, string);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The spawn() method must spawn one or more monsters in
|
||||
* the arena. The monster count, damage, health, etc. can
|
||||
* be modified by the wave parameter.
|
||||
* @param wave Wave number
|
||||
*/
|
||||
public void spawn(int wave, Collection<Location> spawnpoints);
|
||||
|
||||
/**
|
||||
* Get the type of wave.
|
||||
* @return The WaveType of this Wave.
|
||||
*/
|
||||
public WaveType getType();
|
||||
|
||||
/**
|
||||
* Get the growth rate of this wave.
|
||||
* @return The growth rate
|
||||
*/
|
||||
public WaveGrowth getGrowth();
|
||||
|
||||
/**
|
||||
* Get the first wave number for this wave
|
||||
* @return The wave number
|
||||
*/
|
||||
public int getWave();
|
||||
|
||||
/**
|
||||
* Get the wave's frequency, i.e. wave number "modulo"
|
||||
* @return The wave's frequency
|
||||
*/
|
||||
public int getFrequency();
|
||||
|
||||
/**
|
||||
* Get the wave's priority value.
|
||||
* @return The priority
|
||||
*/
|
||||
public int getPriority();
|
||||
|
||||
/**
|
||||
* Get the wave's name.
|
||||
* @return The name
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Check if this wave matches the wave number.
|
||||
* The SingleWave class does a simple check if its wave == the parameter.
|
||||
* The RecurrentWave class is more complex in that it needs to do some
|
||||
* calculations based on the initial wave and the frequency.
|
||||
* @param wave The current wave number
|
||||
* @return true, if the wave should spawn, false otherwise
|
||||
*/
|
||||
public boolean matches(int wave);
|
||||
}
|
Loading…
Reference in New Issue
Block a user