diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a25a269
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/target/
+*.jar
\ No newline at end of file
diff --git a/README.md b/README.md
index 11ff927..a0c7c53 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,13 @@
DiscoSheep
==========
-A plugin for [Bukkit](http://bukkit.org/), the Minecraft server API. This is a from-scratch remake of the fabulous [DiscoSheep plugin](http://forums.bukkit.org/threads/inactive-fun-discosheep-v0-3-uninvited-guesssts-permissions-and-source-code-522.7106/) which spawns a dance party of sheep at your whim.
+A plugin for [Bukkit](http://bukkit.org/), the Minecraft server plugin API. This is a from-scratch remake of the fabulous [DiscoSheep plugin](http://forums.bukkit.org/threads/inactive-fun-discosheep-v0-3-uninvited-guesssts-permissions-and-source-code-522.7106/) which spawns a dance party of sheep at your whim.
+
+###A note on UUIDs###
+DiscoSheep doesn't store anything after a party, and disco-party-on-join is handled by a permissions plugin. Thus, we don't need to worry about the migration to UUIDs.
###Versions###
-Tested up to CraftBukkit build 2918 (RB for 1.6.4 R2.0); can be built with Java 6.
+Tested up to CraftBukkit build #3092 (MC: 1.7.9); can be built with Java 7.
###[BukkitDev](http://dev.bukkit.org/bukkit-plugins/superdiscosheep/)###
@@ -12,7 +15,7 @@ Tested up to CraftBukkit build 2918 (RB for 1.6.4 R2.0); can be built with Java
See BukkitDev, or https://github.com/Gibstick/DiscoSheep/releases
###License###
-Copyright (c) 2013 "Gibstick", "RangerMauve"
+Copyright (c) 2013-2014 "Gibstick", "RangerMauve"
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/nb-configuration.xml b/nb-configuration.xml
new file mode 100644
index 0000000..8de99a0
--- /dev/null
+++ b/nb-configuration.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+ mit
+ 132
+ none
+ 4
+ 4
+ 4
+ 80
+ true
+ none
+ 4
+ 4
+ 4
+ 80
+ true
+ project
+
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..de20afd
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,105 @@
+
+
+ 4.0.0
+ ca.gibstick
+ DiscoSheep
+ 1.1.2
+ jar
+
+
+ bukkit-repo
+ http://repo.bukkit.org/content/groups/public/
+
+
+ repo.oc.tc
+ http://repo.oc.tc/content/repositories/public/
+
+
+
+
+ org.bukkit
+ bukkit
+ provided
+ 1.7.9-R0.2
+
+
+ com.sk89q
+ command-framework-bukkit
+ 0.5-SNAPSHOT
+
+
+
+ DiscoSheep
+ src/main/java
+
+
+ .
+ true
+ src/main/resources/
+
+ plugin.yml
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+
+ -Xlint:deprecation
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.3
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.9.1
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ 2.8.1
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 2.3
+
+
+ package
+
+ shade
+
+
+ DiscoSheep
+ true
+
+ ${project.basedir}
+
+
+ com.sk89q:command-framework-bukkit
+
+
+ false
+ true
+ shaded
+
+
+
+
+
+
+
+ UTF-8
+ 1.7
+ 1.7
+
+ DiscoSheep
+
\ No newline at end of file
diff --git a/src/ca/gibstick/discosheep/DiscoParty.java b/src/ca/gibstick/discosheep/DiscoParty.java
deleted file mode 100644
index 132e4a7..0000000
--- a/src/ca/gibstick/discosheep/DiscoParty.java
+++ /dev/null
@@ -1,527 +0,0 @@
-package ca.gibstick.discosheep;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Random;
-import org.bukkit.Color;
-import org.bukkit.DyeColor;
-import org.bukkit.Location;
-import org.bukkit.Sound;
-import org.bukkit.World;
-import org.bukkit.entity.EntityType;
-import org.bukkit.entity.Firework;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.Sheep;
-import org.bukkit.FireworkEffect;
-import org.bukkit.FireworkEffect.Builder;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.block.BlockState;
-import org.bukkit.entity.Entity;
-import org.bukkit.event.HandlerList;
-import org.bukkit.inventory.meta.FireworkMeta;
-import org.bukkit.scheduler.BukkitRunnable;
-import org.bukkit.util.Vector;
-
-public class DiscoParty {
-
- // Static properties
- static int defaultDuration = 300; // ticks for entire party
- static int defaultPeriod = 10; // ticks per state change
- static int defaultRadius = 5;
- static int defaultSheep = 10;
- static float defaultSheepJump = 0.35f;
- static int maxDuration = 2400; // 120 seconds
- static int maxSheep = 100;
- static int maxRadius = 100;
- static int minPeriod = 5; // 0.25 seconds
- static int maxPeriod = 40; // 2.0 seconds
- private static HashMap defaultGuestNumbers = new HashMap();
- private static HashMap maxGuestNumbers = new HashMap();
- private static final DyeColor[] discoColours = {
- DyeColor.RED,
- DyeColor.ORANGE,
- DyeColor.YELLOW,
- DyeColor.GREEN,
- DyeColor.BLUE,
- DyeColor.LIGHT_BLUE,
- DyeColor.PINK,
- DyeColor.MAGENTA,
- DyeColor.LIME,
- DyeColor.CYAN,
- DyeColor.PURPLE,
- DyeColor.BLACK,
- DyeColor.WHITE
- };
- private static final float[] pentatonicNotes = {
- 1.0f,
- 1.125f,
- 1.25f,
- 1.5f,
- 1.667f,
- 2.0f
- };
- // Instance properties
- private Random r = new Random();
- private PartyEvents partyEvents;
- private DiscoSheep parent;
- private Player player;
- private ArrayList sheepList = new ArrayList();
- private ArrayList guestList = new ArrayList();
- private ArrayList floorBlockCache = new ArrayList();
- private ArrayList floorBlocks = new ArrayList();
- private HashMap guestNumbers = new HashMap();
- private boolean doFireworks = false;
- private boolean doJump = true;
- private boolean doLightning = false;
- private int duration, period, radius, sheep;
- private int state = 0; // basically our own tick system
- private DiscoUpdater updater;
-
- public DiscoParty(DiscoSheep parent, Player player) {
- this(parent);
- this.player = player;
- }
-
- public DiscoParty(DiscoSheep parent) {
- this.parent = parent;
- this.duration = DiscoParty.defaultDuration;
- this.period = DiscoParty.defaultPeriod;
- this.radius = DiscoParty.defaultRadius;
- this.sheep = DiscoParty.defaultSheep;
- this.guestNumbers = new HashMap(DiscoParty.defaultGuestNumbers);
- r = new Random();
- }
-
- // copy but with new player
- // used for /ds other and /ds all
- public DiscoParty clone(Player player) {
- DiscoParty newParty;
- newParty = new DiscoParty(this.parent, player);
- newParty.doFireworks = this.doFireworks;
- newParty.duration = this.duration;
- newParty.period = this.period;
- newParty.radius = this.radius;
- newParty.sheep = this.sheep;
- newParty.doLightning = this.doLightning;
- newParty.guestNumbers = this.getGuestNumbers();
- return newParty;
- }
-
- ArrayList getSheepList() {
- return sheepList;
- }
-
- ArrayList getGuestList() {
- return guestList;
- }
-
- ArrayList getFloorCache() {
- return this.floorBlockCache;
- }
-
- ArrayList getFloorBlocks() {
- return this.floorBlocks;
- }
-
- public static HashMap getDefaultGuestNumbers() {
- return defaultGuestNumbers;
- }
-
- public HashMap getGuestNumbers() {
- return guestNumbers;
- }
-
- public static HashMap getMaxGuestNumbers() {
- return maxGuestNumbers;
- }
-
- public int getSheep() {
- return this.sheep;
- }
-
- public DiscoParty setPlayer(Player player) {
- if (player != null) {
- this.player = player;
- return this;
- } else {
- throw new NullPointerException();
- }
- }
-
- public DiscoParty setDuration(int duration) throws IllegalArgumentException {
- if (duration <= DiscoParty.maxDuration && duration > 0) {
- this.duration = duration;
- return this;
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- public DiscoParty setPeriod(int period) throws IllegalArgumentException {
- if (period >= DiscoParty.minPeriod && period <= DiscoParty.maxPeriod) {
- this.period = period;
- return this;
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- public DiscoParty setRadius(int radius) throws IllegalArgumentException {
- if (radius <= DiscoParty.maxRadius && radius > 0) {
- this.radius = radius;
- return this;
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- public DiscoParty setDenseRadius(int sheepNo) throws IllegalArgumentException {
- Integer rand = (int) Math.floor(Math.sqrt(sheep / Math.PI));
- if (rand > DiscoParty.maxRadius) {
- rand = DiscoParty.maxRadius;
- }
- if (rand < 1) {
- rand = 1;
- }
-
- this.setRadius(rand);
- return this;
- }
-
- public DiscoParty setSheep(int sheep) throws IllegalArgumentException {
- if (sheep <= DiscoParty.maxSheep && sheep > 0) {
- this.sheep = sheep;
- return this;
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- public DiscoParty setDoFireworks(boolean doFireworks) {
- this.doFireworks = doFireworks;
- return this;
- }
-
- public DiscoParty setDoLightning(boolean doLightning) {
- this.doLightning = doLightning;
- return this;
- }
-
- public DiscoParty setGuestNumber(String key, int n) throws IllegalArgumentException {
- if (getMaxGuestNumbers().containsKey(key.toUpperCase())) {
- if (n <= getMaxGuestNumbers().get(key.toUpperCase()) && n >= 0) { // so that /ds defaults can take 0 as arg
- getGuestNumbers().put(key, n);
-
- return this;
- }
- }
- throw new IllegalArgumentException();
- }
-
- // use current settings as new defaults
- public DiscoParty setDefaultsFromCurrent() {
- DiscoParty.defaultDuration = this.duration;
- DiscoParty.defaultPeriod = this.period;
- DiscoParty.defaultRadius = this.radius;
- DiscoParty.defaultSheep = this.sheep;
- DiscoParty.defaultGuestNumbers = new HashMap(this.getGuestNumbers());
- return this;
- }
-
- Location getRandomSpawnLocation(double x, double z, World world, int spawnRadius) {
- Location loc;
-
- double y;
-
- /* random point on circle with polar coordinates
- * random number must be square rooted to obtain uniform distribution
- * otherwise the sheep are biased toward the centre */
- double rand = Math.sqrt(r.nextDouble()) * spawnRadius;
- double azimuth = r.nextDouble() * 2 * Math.PI; // radians
- x += rand * Math.cos(azimuth);
- z += rand * Math.sin(azimuth);
- y = this.player.getLocation().getY();
-
- loc = new Location(world, x, y, z);
- loc.setPitch(r.nextFloat() * 360 - 180);
- loc.setYaw(0);
-
- return loc;
- }
-
- // Spawn some number of guests next to given player
- void spawnAll(int sheep, int spawnRadius) {
- Location loc;
- World world = player.getWorld();
-
-
- double x = player.getLocation().getX();
- double z = player.getLocation().getZ();
- for (int i = 0; i < sheep; i++) {
- loc = getRandomSpawnLocation(x, z, world, spawnRadius);
- spawnSheep(world, loc);
- }
-
- // loop through hashmap of other guests and spawn accordingly
- for (Map.Entry entry : guestNumbers.entrySet()) {
- EntityType ent = EntityType.valueOf((String) entry.getKey());
- int num = (Integer) entry.getValue();
-
- for (int i = 0; i < num; i++) {
- loc = getRandomSpawnLocation(x, z, world, spawnRadius);
- spawnGuest(world, loc, ent);
- }
- }
-
- loc = player.getLocation();
- this.spawnFloor(world, new Location(world, loc.getBlockX(), loc.getBlockY() - 1, loc.getBlockZ()));
- }
-
- void spawnSheep(World world, Location loc) {
- Sheep newSheep = (Sheep) world.spawnEntity(loc, EntityType.SHEEP);
- newSheep.setColor(discoColours[(r.nextInt(discoColours.length))]);
- newSheep.setBreed(false); // this prevents breeding - no event listener required
- newSheep.teleport(loc); // teleport is needed to set orientation
- getSheepList().add(newSheep);
- if (doLightning) {
- world.strikeLightningEffect(loc);
- }
- }
-
- void spawnGuest(World world, Location loc, EntityType type) {
- Entity newGuest = loc.getWorld().spawnEntity(loc, type);
- getGuestList().add(newGuest);
- if (doLightning) {
- world.strikeLightningEffect(loc);
- }
- }
-
- void spawnFloor(World world, Location loc) {
- // First we'll save the floor state
- for (int x = loc.getBlockX() - this.radius; x < loc.getX() + this.radius; ++x) {
- for (int z = loc.getBlockZ() - this.radius; z < loc.getZ() + this.radius; ++z) {
- Block block = world.getBlockAt(x, loc.getBlockY(), z);
- if (block.getType() != Material.WOOL) {
- this.getFloorCache().add(block.getState());
- block.setType(Material.WOOL);
- this.getFloorBlocks().add(block);
- }
- }
- }
- }
-
- // Mark all guests for removal, then clear the array
- void removeAll() {
- for (Sheep sheeple : getSheepList()) {
- sheeple.remove();
- }
- for (Entity guest : getGuestList()) {
- guest.remove();
- }
- for (BlockState block : this.floorBlockCache) {
- block.update(true);
- }
- getSheepList().clear();
- getGuestList().clear();
- floorBlockCache.clear();
- }
-
- // Set a random colour for all sheep in array
- void randomizeSheepColour(Sheep sheep) {
- sheep.setColor(discoColours[(r.nextInt(discoColours.length))]);
- }
-
- void randomizeFloor(Block block) {
- block.setType(Material.WOOL);
- block.setData(discoColours[(r.nextInt(discoColours.length))].getData());
- }
-
- void jump(Entity entity) {
- Vector orgVel = entity.getVelocity();
- Vector newVel = (new Vector()).copy(orgVel);
- newVel.add(new Vector(0, defaultSheepJump, 0));
- entity.setVelocity(newVel);
- }
-
- // WHY ISN'T THERE A Color.getValue() ?!?!?!?!
- private Color getColor(int i) {
- Color c = null;
- if (i == 1) {
- c = Color.AQUA;
- }
- if (i == 2) {
- c = Color.BLACK;
- }
- if (i == 3) {
- c = Color.BLUE;
- }
- if (i == 4) {
- c = Color.FUCHSIA;
- }
- if (i == 5) {
- c = Color.GRAY;
- }
- if (i == 6) {
- c = Color.GREEN;
- }
- if (i == 7) {
- c = Color.LIME;
- }
- if (i == 8) {
- c = Color.MAROON;
- }
- if (i == 9) {
- c = Color.NAVY;
- }
- if (i == 10) {
- c = Color.OLIVE;
- }
- if (i == 11) {
- c = Color.ORANGE;
- }
- if (i == 12) {
- c = Color.PURPLE;
- }
- if (i == 13) {
- c = Color.RED;
- }
- if (i == 14) {
- c = Color.SILVER;
- }
- if (i == 15) {
- c = Color.TEAL;
- }
- if (i == 16) {
- c = Color.WHITE;
- }
- if (i == 17) {
- c = Color.YELLOW;
- }
-
- return c;
- }
-
- void updateAll() {
- for (Sheep sheeple : getSheepList()) {
- randomizeSheepColour(sheeple);
-
- if (doFireworks && state % 8 == 0) {
- if (r.nextDouble() < 0.50) {
- spawnRandomFireworkAtSheep(sheeple);
- }
- }
-
- if (doJump) {
- if (state % 2 == 0 && r.nextDouble() < 0.5) {
- jump(sheeple);
- }
- }
- }
-
- for (Entity guest : getGuestList()) {
- if (doJump) {
- if (state % 2 == 0 && r.nextDouble() < 0.5) {
- jump(guest);
- }
- }
- }
-
- for (Block block : this.floorBlocks) {
- this.randomizeFloor(block);
- }
-
- }
-
- private float getPentatonicNote() {
- return DiscoParty.pentatonicNotes[r.nextInt(pentatonicNotes.length)];
- }
-
- void playSounds() {
- player.playSound(player.getLocation(), Sound.NOTE_BASS_DRUM, 0.75f, 1.0f);
- if (this.state % 2 == 0) {
- player.playSound(player.getLocation(), Sound.NOTE_SNARE_DRUM, 0.8f, 1.0f);
- }
-
- if ((this.state + 1) % 8 == 0) {
- player.playSound(player.getLocation(), Sound.NOTE_STICKS, 1.0f, 1.0f);
- }
- }
-
- void randomizeFirework(Firework firework) {
- Builder effect = FireworkEffect.builder();
- FireworkMeta meta = firework.getFireworkMeta();
-
- // construct [1, 3] random colours
- int numColours = r.nextInt(3) + 1;
- Color[] colourArray = new Color[numColours];
- for (int i = 0; i < numColours; i++) {
- colourArray[i] = getColor(r.nextInt(17) + 1);
- }
-
- // randomize effects
- effect.withColor(colourArray);
- effect.flicker(r.nextDouble() < 0.5);
- effect.trail(r.nextDouble() < 0.5);
- effect.with(FireworkEffect.Type.values()[r.nextInt(FireworkEffect.Type.values().length)]);
-
- // set random effect and randomize power
- meta.addEffect(effect.build());
- meta.setPower(r.nextInt(2) + 1);
-
- // apply it to the given firework
- firework.setFireworkMeta(meta);
- }
-
- void spawnRandomFireworkAtSheep(Sheep sheep) {
- Firework firework = (Firework) sheep.getWorld().spawnEntity(sheep.getEyeLocation(), EntityType.FIREWORK);
- randomizeFirework(firework);
- }
-
- void update() {
- if (duration > 0) {
- updateAll();
- playSounds();
- duration -= period;
- this.scheduleUpdate();
- this.state = (this.state + 1) % 10000;
- } else {
- this.stopDisco();
- }
- }
-
- void scheduleUpdate() {
- updater = new DiscoUpdater();
- updater.runTaskLater(parent, this.period);
- }
-
- void startDisco() {
- this.spawnAll(sheep, radius);
- this.scheduleUpdate();
- parent.getPartyMap().put(this.player.getName(), this);
- // start listening
- this.partyEvents = new PartyEvents(this.parent, this);
- parent.getServer().getPluginManager().registerEvents(this.partyEvents, this.parent);
- }
-
- void stopDisco() {
- removeAll();
- this.duration = 0;
- if (updater != null) {
- updater.cancel();
- }
- updater = null;
- parent.getPartyMap().remove(this.player.getName());
- // stop listening
- HandlerList.unregisterAll(this.partyEvents);
- }
-
- class DiscoUpdater extends BukkitRunnable {
-
- @Override
- public void run() {
- update();
- }
- }
-}
diff --git a/src/ca/gibstick/discosheep/DiscoSheep.java b/src/ca/gibstick/discosheep/DiscoSheep.java
deleted file mode 100644
index 2cfb22c..0000000
--- a/src/ca/gibstick/discosheep/DiscoSheep.java
+++ /dev/null
@@ -1,311 +0,0 @@
-package ca.gibstick.discosheep;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.EntityType;
-import org.bukkit.entity.Player;
-import org.bukkit.plugin.java.JavaPlugin;
-
-public final class DiscoSheep extends JavaPlugin {
-
- static final String PERMISSION_PARTY = "discosheep.party.me";
- static final String PERMISSION_ALL = "discosheep.party.all";
- static final String PERMISSION_FIREWORKS = "discosheep.party.fireworks";
- static final String PERMISSION_STOPALL = "discosheep.admin.stopall";
- static final String PERMISSION_RELOAD = "discosheep.admin.reload";
- static final String PERMISSION_OTHER = "discosheep.party.other";
- static final String PERMISSION_CHANGEPERIOD = "discosheep.party.changeperiod";
- static final String PERMISSION_CHANGEDEFAULTS = "discosheep.admin.changedefaults";
- static final String PERMISSION_SAVECONFIG = "discosheep.admin.saveconfig";
- static final String PERMISSION_ONJOIN = "discosheep.party.onjoin";
- static final String PERMISSION_SPAWNGUESTS = "discosheep.party.spawnguests";
- static final String PERMISSION_TOGGLEPARTYONJOIN = "discosheep.admin.toggleonjoin";
- static final String PERMISSION_LIGHTNING = "discosheep.party.lightning";
- static boolean partyOnJoin = true;
- Map parties = new HashMap();
-
- @Override
- public void onEnable() {
- getCommand("ds").setExecutor(new DiscoSheepCommandExecutor(this));
- getServer().getPluginManager().registerEvents(new GlobalEvents(this), this);
-
- getConfig().addDefault("on-join.enabled", partyOnJoin);
- getConfig().addDefault("max.sheep", DiscoParty.maxSheep);
- getConfig().addDefault("max.radius", DiscoParty.maxRadius);
- getConfig().addDefault("max.duration", toSeconds_i(DiscoParty.maxDuration));
- getConfig().addDefault("max.period-ticks", DiscoParty.maxPeriod);
- getConfig().addDefault("min.period-ticks", DiscoParty.minPeriod);
- getConfig().addDefault("default.sheep", DiscoParty.defaultSheep);
- getConfig().addDefault("default.radius", DiscoParty.defaultRadius);
- getConfig().addDefault("default.duration", toSeconds_i(DiscoParty.defaultDuration));
- getConfig().addDefault("default.period-ticks", DiscoParty.defaultPeriod);
-
- /*
- * Iterate through all live entities and create default configuration values for them
- * excludes bosses and other mobs that throw NPE
- */
- for (EntityType ent : EntityType.values()) {
- if (ent.isAlive()
- && !ent.equals(EntityType.ENDER_DRAGON)
- && !ent.equals(EntityType.WITHER)
- && !ent.equals(EntityType.PIG_ZOMBIE)
- && !ent.equals(EntityType.OCELOT)
- && !ent.equals(EntityType.CAVE_SPIDER)
- && !ent.equals(EntityType.MAGMA_CUBE)
- && !ent.equals(EntityType.MUSHROOM_COW)
- && !ent.equals(EntityType.IRON_GOLEM)
- && !ent.equals(EntityType.PLAYER)) {
- getConfig().addDefault("default.guests." + ent.toString(), 0);
- getConfig().addDefault("max.guests." + ent.toString(), 0);
- }
- }
-
- loadConfigFromDisk();
- }
-
- void loadConfigFromDisk() {
- getConfig().options().copyDefaults(true);
- saveConfig();
-
- partyOnJoin = getConfig().getBoolean("on-join.enabled");
- DiscoParty.maxSheep = getConfig().getInt("max.sheep");
- DiscoParty.maxRadius = getConfig().getInt("max.radius");
- DiscoParty.maxDuration = toTicks(getConfig().getInt("max.duration"));
- DiscoParty.maxPeriod = getConfig().getInt("max.period-ticks");
- DiscoParty.minPeriod = getConfig().getInt("min.period-ticks");
- DiscoParty.defaultSheep = getConfig().getInt("default.sheep");
- DiscoParty.defaultRadius = getConfig().getInt("default.radius");
- DiscoParty.defaultDuration = toTicks(getConfig().getInt("default.duration"));
- DiscoParty.defaultPeriod = getConfig().getInt("default.period-ticks");
-
- for (String key : getConfig().getConfigurationSection("default.guests").getKeys(false)) {
- DiscoParty.getDefaultGuestNumbers().put(key, getConfig().getInt("default.guests." + key));
- }
-
- for (String key : getConfig().getConfigurationSection("max.guests").getKeys(false)) {
- DiscoParty.getMaxGuestNumbers().put(key, getConfig().getInt("max.guests." + key));
- }
-
- }
-
- void reloadConfigFromDisk() {
- reloadConfig();
- loadConfigFromDisk();
- }
-
- void saveConfigToDisk() {
- getConfig().set("on-join.enabled", partyOnJoin);
- getConfig().set("default.sheep", DiscoParty.defaultSheep);
- getConfig().set("default.radius", DiscoParty.defaultRadius);
- getConfig().set("default.duration", toSeconds_i(DiscoParty.defaultDuration));
- getConfig().set("default.period-ticks", DiscoParty.defaultPeriod);
-
- for (Map.Entry entry : DiscoParty.getDefaultGuestNumbers().entrySet()) {
- getConfig().set("default.guests." + entry.getKey(), entry.getValue());
- }
-
- saveConfig();
- }
-
- @Override
- public void onDisable() {
- this.stopAllParties(); // or else the parties will continue FOREVER
- }
-
- static int toTicks(double seconds) {
- return (int) Math.round(seconds * 20.0);
- }
-
- static double toSeconds(int ticks) {
- return (double) Math.round(ticks / 20.0);
- }
-
- static int toSeconds_i(int ticks) {
- return (int) Math.round(ticks / 20.0);
- }
-
- public synchronized Map getPartyMap() {
- return this.parties;
- }
-
- public synchronized ArrayList getParties() {
- return new ArrayList(this.getPartyMap().values());
- }
-
- public void stopParty(String name) {
- if (this.hasParty(name)) {
- this.getParty(name).stopDisco();
- }
- }
-
- public void stopAllParties() {
- for (DiscoParty party : this.getParties()) {
- party.stopDisco();
- }
- }
-
- public boolean hasParty(String name) {
- return this.getPartyMap().containsKey(name);
- }
-
- public DiscoParty getParty(String name) {
- return this.getPartyMap().get(name);
- }
-
- public void removeParty(String name) {
- if (this.hasParty(name)) {
- this.getPartyMap().remove(name);
- }
- }
-
- /*-- Actual commands begin here --*/
- boolean helpCommand(CommandSender sender) {
- sender.sendMessage(ChatColor.YELLOW
- + "DiscoSheep Help\n"
- + ChatColor.GRAY
- + " Subcommands\n"
- + ChatColor.WHITE + "me, stop, all, stopall, save, reload, togglejoin\n"
- + "other : start a party for the space-delimited list of players\n"
- + "defaults: Change the default settings for parties (takes normal arguments)\n"
- + ChatColor.GRAY + " Arguments\n"
- + ChatColor.WHITE + "-n : set the number of sheep per player that spawn\n"
- + "-t : set the party duration in seconds\n"
- + "-p : set the number of ticks between each disco beat\n"
- + "-r : set radius of the area in which sheep can spawn\n"
- + "-g : set spawns for other mobs"
- + "-l: enables lightning"
- + "-fw: enables fireworks");
- return true;
- }
-
- boolean stopMeCommand(CommandSender sender) {
- stopParty(sender.getName());
- return true;
- }
-
- boolean stopAllCommand(CommandSender sender) {
- if (sender.hasPermission(PERMISSION_STOPALL)) {
- stopAllParties();
- return true;
- } else {
- return noPermsMessage(sender, PERMISSION_STOPALL);
- }
- }
-
- boolean partyCommand(Player player, DiscoParty party) {
- if (player.hasPermission(PERMISSION_PARTY)) {
- if (!hasParty(player.getName())) {
- party.setPlayer(player);
- party.startDisco();
- } else {
- player.sendMessage(ChatColor.RED + "You already have a party. Are you underground?");
- }
- return true;
- } else {
- return noPermsMessage(player, PERMISSION_PARTY);
- }
- }
-
- boolean reloadCommand(CommandSender sender) {
- if (sender.hasPermission(PERMISSION_RELOAD)) {
- reloadConfigFromDisk();
- sender.sendMessage(ChatColor.GREEN + "DiscoSheep config reloaded from disk");
- return true;
- } else {
- return noPermsMessage(sender, PERMISSION_RELOAD);
- }
- }
-
- boolean partyOtherCommand(String[] players, CommandSender sender, DiscoParty party) {
- if (sender.hasPermission(PERMISSION_OTHER)) {
- Player p;
- for (String playerName : players) {
- p = Bukkit.getServer().getPlayer(playerName);
- if (p != null) {
- if (!hasParty(p.getName())) {
- DiscoParty individualParty = party.clone(p);
- individualParty.startDisco();
- }
- } else {
- sender.sendMessage("Invalid player: " + playerName);
- }
- }
- return true;
- } else {
- return noPermsMessage(sender, PERMISSION_OTHER);
- }
- }
-
- boolean partyAllCommand(CommandSender sender, DiscoParty party) {
- if (sender.hasPermission(PERMISSION_ALL)) {
- for (Player p : Bukkit.getServer().getOnlinePlayers()) {
- if (!hasParty(p.getName())) {
- DiscoParty individualParty = party.clone(p);
- individualParty.startDisco();
- p.sendMessage(ChatColor.RED + "LET'S DISCO!!");
- }
- }
- return true;
- } else {
- return noPermsMessage(sender, PERMISSION_ALL);
- }
- }
-
- void partyOnJoin(Player player) {
- if (!partyOnJoin) {
- return;
- }
- if (player.hasPermission(PERMISSION_ONJOIN)) {
- DiscoParty party = new DiscoParty(this, player);
- party.startDisco();
- }
- }
-
- boolean togglePartyOnJoinCommand(CommandSender sender) {
- if (!sender.hasPermission(PERMISSION_TOGGLEPARTYONJOIN)) {
- return noPermsMessage(sender, PERMISSION_TOGGLEPARTYONJOIN);
- }
- partyOnJoin = !partyOnJoin;
- if (partyOnJoin) {
- sender.sendMessage(ChatColor.GREEN + "DiscoSheep party on join functionality enabled.");
- } else {
- sender.sendMessage(ChatColor.GREEN + "DiscoSheep party on join functionality disabled.");
- }
- return true;
- }
-
- boolean setDefaultsCommand(CommandSender sender, DiscoParty party) {
- if (sender.hasPermission(PERMISSION_CHANGEDEFAULTS)) {
- party.setDefaultsFromCurrent();
- sender.sendMessage(ChatColor.GREEN + "DiscoSheep configured with new defaults (not saved to disk yet)");
- return true;
- } else {
- return noPermsMessage(sender, PERMISSION_CHANGEDEFAULTS);
- }
- }
-
- boolean saveConfigCommand(CommandSender sender) {
- if (sender.hasPermission(PERMISSION_SAVECONFIG)) {
- saveConfigToDisk();
- sender.sendMessage(ChatColor.GREEN + "DiscoSheep config saved to disk");
- return true;
- } else {
- return noPermsMessage(sender, PERMISSION_SAVECONFIG);
- }
-
- }
-
- boolean clearGuests(DiscoParty party) {
- party.getGuestNumbers().clear();
- return true;
- }
-
- boolean noPermsMessage(CommandSender sender, String permission) {
- sender.sendMessage(ChatColor.RED + "You do not have the permission node " + ChatColor.GRAY + permission);
- return false;
- }
-}
diff --git a/src/ca/gibstick/discosheep/DiscoSheepCommandExecutor.java b/src/ca/gibstick/discosheep/DiscoSheepCommandExecutor.java
deleted file mode 100644
index 72bdca7..0000000
--- a/src/ca/gibstick/discosheep/DiscoSheepCommandExecutor.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package ca.gibstick.discosheep;
-
-import java.util.Arrays;
-import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-public class DiscoSheepCommandExecutor implements CommandExecutor {
-
- private DiscoSheep parent;
-
- public DiscoSheepCommandExecutor(DiscoSheep parent) {
- this.parent = parent;
- }
-
- private boolean parseNextArg(String[] args, int i, String compare) {
- if (i < args.length - 1) {
- return args[i + 1].equalsIgnoreCase(compare);
- }
- return false;
- }
-
- private String getNextArg(String[] args, int i) {
- if (i < args.length - 1) {
- return args[i + 1];
- } else {
- return null;
- }
- }
-
- private int getNextIntArg(String[] args, int i) {
- if (i < args.length - 1) {
- try {
- return Integer.parseInt(args[i + 1]);
- } catch (NumberFormatException e) {
- return -1; // so that it fails limit checks elsewhere
- }
- }
- return -1; // ibid
- }
-
- private Double getNextDoubleArg(String[] args, int i) {
- if (i < args.length - 1) {
- try {
- return Double.parseDouble(args[i + 1]);
- } catch (NumberFormatException e) {
- return -1.0d; // so that it fais limit checks elsewhere
- }
- }
- return -1.0d; // ibid
- }
-
- // return portion of the array that contains space-separated args,
- // stopping at the end of the array or the next -switch
- private String[] getNextArgs(String[] args, int i) {
- int j = i;
- while (j < args.length && !args[j].startsWith("-")) {
- j++;
- }
- return Arrays.copyOfRange(args, i, j);
- }
-
- @Override
- public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
-
- Player player = null;
- boolean isPlayer = false;
- boolean specialRadius = false;
- // flag to determine if we calculate a radius so that the sheep spawn densely in an area
-
- if (sender instanceof Player) {
- player = (Player) sender;
- isPlayer = true;
- } // check isPlayer before "stop" and "me" commands
-
- // check for commands that don't need a party
- // so that we get them out of the way, and
- // prevent needless construction of parties
- if (args.length == 1) {
- if (args[0].equalsIgnoreCase("stopall")) {
- return parent.stopAllCommand(sender);
- } else if (args[0].equalsIgnoreCase("stop") && isPlayer) {
- return parent.stopMeCommand(sender);
- } else if (args[0].equalsIgnoreCase("help")) {
- return parent.helpCommand(sender);
- } else if (args[0].equalsIgnoreCase("reload")) {
- return parent.reloadCommand(sender);
- } else if (args[0].equalsIgnoreCase("save") || args[0].equalsIgnoreCase("saveconfig")) {
- return parent.saveConfigCommand(sender);
- } else if (args[0].equalsIgnoreCase("togglejoin")) {
- return parent.togglePartyOnJoinCommand(sender);
- }
- }
-
- // construct a main party; all other parties will copy from this
- DiscoParty mainParty = new DiscoParty(parent);
-
- // omg I love argument parsing and I know the best way!
- for (int i = 1; i < args.length; i++) {
- if (args[i].equalsIgnoreCase("-fw")) {
- if (sender.hasPermission(DiscoSheep.PERMISSION_FIREWORKS)) {
- mainParty.setDoFireworks(true);
- } else {
- return parent.noPermsMessage(sender, DiscoSheep.PERMISSION_FIREWORKS);
- }
- } else if (args[i].equalsIgnoreCase("-r")) {
- if (parseNextArg(args, i, "dense")) {
- specialRadius = true;
- }
- if (!specialRadius) {
- try {
- mainParty.setRadius(getNextIntArg(args, i));
- } catch (IllegalArgumentException e) {
- sender.sendMessage("Radius must be an integer within the range [1, "
- + DiscoParty.maxRadius + "]");
- return false;
- }
- }
- } else if (args[i].equalsIgnoreCase("-n")) {
- try {
- mainParty.setSheep(getNextIntArg(args, i));
- } catch (IllegalArgumentException e) {
- sender.sendMessage("The number of sheep must be an integer within the range [1, "
- + DiscoParty.maxSheep + "]");
- return false;
- }
- } else if (args[i].equalsIgnoreCase("-t")) {
- try {
- mainParty.setDuration(parent.toTicks(getNextIntArg(args, i)));
- } catch (IllegalArgumentException e) {
- sender.sendMessage("The duration in seconds must be an integer within the range [1, "
- + parent.toSeconds(DiscoParty.maxDuration) + "]");
- return false;
- }
- } else if (args[i].equalsIgnoreCase("-p")) {
- if (!sender.hasPermission(DiscoSheep.PERMISSION_CHANGEPERIOD)) {
- return parent.noPermsMessage(sender, DiscoSheep.PERMISSION_CHANGEPERIOD);
- }
- try {
- mainParty.setPeriod(getNextIntArg(args, i));
- } catch (IllegalArgumentException e) {
- sender.sendMessage(
- "The period in ticks must be within the range ["
- + DiscoParty.minPeriod + ", "
- + DiscoParty.maxPeriod + "]");
- return false;
- }
- } else if (args[i].equalsIgnoreCase("-g")) {
- if (!sender.hasPermission(DiscoSheep.PERMISSION_SPAWNGUESTS)) {
- return parent.noPermsMessage(sender, DiscoSheep.PERMISSION_SPAWNGUESTS);
- }
-
- if (parseNextArg(args, i, "none")) {
- return parent.clearGuests(mainParty);
- }
-
- String[] guests = getNextArgs(args, i + 1);
- int j = 0;
- while (j < guests.length - 1) {
- try {
- mainParty.setGuestNumber(guests[j], getNextIntArg(guests, j));
- } catch (IllegalArgumentException e) {
- sender.sendMessage(ChatColor.RED + "Invalid arguments: " + ChatColor.WHITE + guests[j] + ", " + guests[j + 1]
- + ".\nEither a name typo or a number that is not within limits.");
- }
- j += 2; // skip over two arguments, since they come in pairs of entity-number
- }
- } else if (args[i].equalsIgnoreCase("-l")) {
- if (!sender.hasPermission(DiscoSheep.PERMISSION_LIGHTNING)) {
- return parent.noPermsMessage(sender, DiscoSheep.PERMISSION_LIGHTNING);
- }
- mainParty.setDoLightning(true);
- }
- }
-
- if (specialRadius) {
- mainParty.setDenseRadius(mainParty.getSheep());
- }
-
- if (args.length > 0) {
- if (args[0].equalsIgnoreCase("all")) {
- return parent.partyAllCommand(sender, mainParty);
- } else if (args[0].equalsIgnoreCase("me") && isPlayer) {
- return parent.partyCommand(player, mainParty);
- } else if (args[0].equalsIgnoreCase("other")) {
- return parent.partyOtherCommand(getNextArgs(args, 1), sender, mainParty);
- } else if (args[0].equalsIgnoreCase("defaults")) {
- return parent.setDefaultsCommand(sender, mainParty);
- } else {
- sender.sendMessage(ChatColor.RED + "Invalid argument (certain commands do not work from console).");
- return false;
- }
- }
-
- return false;
- }
-}
diff --git a/src/ca/gibstick/discosheep/GlobalEvents.java b/src/ca/gibstick/discosheep/GlobalEvents.java
deleted file mode 100644
index 74ee35b..0000000
--- a/src/ca/gibstick/discosheep/GlobalEvents.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * BaaBaaBlockSheep have you any wool?
- * Nope, event got cancelled.
- * Also listens to other events, not just sheep events
- */
-package ca.gibstick.discosheep;
-
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.Listener;
-import org.bukkit.event.player.PlayerJoinEvent;
-import org.bukkit.event.player.PlayerQuitEvent;
-
-public class GlobalEvents implements Listener {
-
- DiscoSheep parent;
-
- public GlobalEvents(DiscoSheep parent) {
- this.parent = parent;
- }
-
- @EventHandler (priority = EventPriority.MONITOR)
- public void onPlayerQuitEvent(PlayerQuitEvent e) {
- String name = e.getPlayer().getName();
- parent.stopParty(name);
- // stop party on player quit or else it will CONTINUE FOR ETERNITY
- }
-
- @EventHandler (priority = EventPriority.MONITOR)
- public void onPlayerJoinEvent(PlayerJoinEvent e) {
- Player player = e.getPlayer();
- parent.partyOnJoin(player);
- }
-}
diff --git a/src/ca/gibstick/discosheep/PartyEvents.java b/src/ca/gibstick/discosheep/PartyEvents.java
deleted file mode 100644
index 1de12b8..0000000
--- a/src/ca/gibstick/discosheep/PartyEvents.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package ca.gibstick.discosheep;
-
-import org.bukkit.entity.Sheep;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.Listener;
-import org.bukkit.event.entity.EntityDamageEvent;
-import org.bukkit.event.entity.EntityTargetEvent;
-import org.bukkit.event.player.PlayerShearEntityEvent;
-
-/**
- *
- * @author Charlie
- */
-public class PartyEvents implements Listener {
-
- DiscoSheep parent;
- DiscoParty party;
- /*
- * There will be multiple instances of PartyEvents,
- * and each instance will only listen for its own party.
- * That way, we don't have multiple instances iterating through
- * the entire parties hashmap redundantly, yet we can still
- * unregister the listeners when no parties are running.
- */
-
- public PartyEvents(DiscoSheep parent, DiscoParty party) {
- this.parent = parent;
- this.party = party;
- }
-
- // prevent sheep shearing
- @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
- public void onPlayerShear(PlayerShearEntityEvent e) {
- if (e.getEntity() instanceof Sheep) {
-
- if (party.getSheepList().contains((Sheep) e.getEntity())) {
- e.setCancelled(true);
- }
-
- }
- }
-
- // actually make sheep and other guests invincible
- @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
- public void onLivingEntityDamageEvent(EntityDamageEvent e) {
- if (e.getEntity() instanceof Sheep) {
- if (party.getSheepList().contains((Sheep) e.getEntity())) {
- {
- party.jump(e.getEntity()); // for kicks
- e.setCancelled(true);
- }
- }
-
- }
- if (party.getGuestList().contains(e.getEntity())) {
- party.jump(e.getEntity());
- e.setCancelled(true);
- }
- }
-
- // prevent uninvited guests from targetting players
- @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
- public void onEntityTargetLivingEntityEvent(EntityTargetEvent e) {
-
- if (party.getGuestList().contains(e.getEntity())) {
- e.setCancelled(true);
- }
-
- }
-}
diff --git a/src/main/java/ca/gibstick/discosheep/DiscoCommands.java b/src/main/java/ca/gibstick/discosheep/DiscoCommands.java
new file mode 100644
index 0000000..faff3df
--- /dev/null
+++ b/src/main/java/ca/gibstick/discosheep/DiscoCommands.java
@@ -0,0 +1,313 @@
+package ca.gibstick.discosheep;
+
+import com.sk89q.minecraft.util.commands.Command;
+import com.sk89q.minecraft.util.commands.CommandContext;
+import com.sk89q.minecraft.util.commands.CommandPermissions;
+import com.sk89q.minecraft.util.commands.NestedCommand;
+import java.util.Arrays;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandException;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+/**
+ *
+ * @author Charlie
+ */
+public class DiscoCommands {
+
+ static final String PERMISSION_PARTY = "discosheep.party.me";
+ static final String PERMISSION_ALL = "discosheep.party.all";
+ static final String PERMISSION_FIREWORKS = "discosheep.party.fireworks";
+ static final String PERMISSION_STOPALL = "discosheep.admin.stopall";
+ static final String PERMISSION_RELOAD = "discosheep.admin.reload";
+ static final String PERMISSION_OTHER = "discosheep.party.other";
+ static final String PERMISSION_CHANGEPERIOD = "discosheep.party.changeperiod";
+ static final String PERMISSION_CHANGEDEFAULTS = "discosheep.admin.changedefaults";
+ static final String PERMISSION_SAVECONFIG = "discosheep.admin.saveconfig";
+ static final String PERMISSION_ONJOIN = "discosheep.party.onjoin";
+ static final String PERMISSION_SPAWNGUESTS = "discosheep.party.spawnguests";
+ static final String PERMISSION_TOGGLEPARTYONJOIN = "discosheep.admin.toggleonjoin";
+ static final String PERMISSION_LIGHTNING = "discosheep.party.lightning";
+
+ static final String FLAGS = "n:t:p:r:lfg";
+
+ private static final DiscoSheep plugin = DiscoSheep.getInstance();
+
+ public static class ParentCommand {
+
+ @Command(aliases = {"ds", "discosheep"}, desc = "Main Discosheep Command (see /ds help)", min = 0, max = -1)
+ @NestedCommand(DiscoCommands.class)
+ public static void DiscoCommand(final CommandContext args, CommandSender sender) throws CommandException {
+ }
+ }
+
+ private static boolean getNextArg(String[] args, int i, String compare) {
+ if (i < args.length - 1) {
+ return args[i + 1].equalsIgnoreCase(compare);
+ }
+ return false;
+ }
+
+ private static String getNextArg(String[] args, int i) {
+ if (i < args.length - 1) {
+ return args[i + 1];
+ } else {
+ return null;
+ }
+ }
+
+ // return portion of the array that contains space-separated args,
+ // stopping at the end of the array or the next -switch
+ private static String[] getNextArgs(String[] args, int i) {
+ int j = i;
+ while (j < args.length && !args[j].startsWith("-")) {
+ j++;
+ }
+ return Arrays.copyOfRange(args, i, j);
+ }
+
+ private static int getNextIntArg(String[] args, int i) {
+ if (i < args.length - 1) {
+ try {
+ return Integer.parseInt(args[i + 1]);
+ } catch (NumberFormatException e) {
+ return -1; // so that it fails limit checks elsewhere
+ }
+ }
+ return -1; // ibid
+ }
+
+ private static void parsePartyFlags(DiscoParty party, final CommandContext args, CommandSender sender) throws IllegalArgumentException {
+ party.setPeriod(args.getFlagInteger('p', DiscoParty.defaultPeriod));
+ party.setSheep(args.getFlagInteger('n', DiscoParty.defaultSheep));
+
+ // handle special case of duration conversion ugh
+ if (args.hasFlag('t')) {
+ int duration = args.getFlagInteger('t');
+ party.setDuration(plugin.toTicks(duration));
+ }
+
+ // handle the special case of radius flag arg "dense"
+ String radiusArg = args.getFlag('r', Integer.toString(DiscoParty.defaultRadius));
+ if ("dense".equals(radiusArg)) {
+ party.setDenseRadius(party.getSheep());
+ } else {
+ party.setRadius(Integer.parseInt(radiusArg));
+ }
+
+ // party will still start if player doesn't have permission for extras
+ if (sender.hasPermission(PERMISSION_FIREWORKS)) {
+ party.setDoFireworks(args.hasFlag('f'));
+ } else {
+ plugin.noPermsMessage(sender, PERMISSION_FIREWORKS);
+ }
+
+ if (sender.hasPermission(PERMISSION_LIGHTNING)) {
+ party.setDoLightning(args.hasFlag('l'));
+ } else {
+ plugin.noPermsMessage(sender, PERMISSION_LIGHTNING);
+ }
+
+ // handle guests
+ if (args.hasFlag('g')) {
+ // stop if no permission for spawning guests
+ if (!sender.hasPermission(PERMISSION_SPAWNGUESTS)) {
+ plugin.noPermsMessage(sender, PERMISSION_SPAWNGUESTS);
+ return;
+ }
+
+ String dirtyArgs[] = args.getParsedSlice(0);
+ //sender.sendMessage(dirtyArgs);
+ for (int i = 0; i < dirtyArgs.length; i++) {
+ if ("none".equals(dirtyArgs[0])) {
+ plugin.clearGuests(party);
+ return;
+ }
+
+ String[] guests = dirtyArgs;
+ int j = 0;
+ while (j < guests.length - 1) {
+ try {
+ party.setGuestNumber(guests[j].toUpperCase(), getNextIntArg(guests, j));
+ } catch (IllegalArgumentException e) {
+ sender.sendMessage(ChatColor.RED + "Invalid arguments: " + ChatColor.WHITE + guests[j] + ", " + guests[j + 1]
+ + ".\nEither a name typo or a number that is not within limits.");
+ }
+ j += 2; // skip over two arguments, since they come in pairs of entity-number
+ }
+ }
+
+ }
+
+ }
+
+ /*-- Actual commands begin here --*/
+ @Command(aliases = "help", desc = "DiscoSheep help", usage = "No arguments", min = 0, max = -1)
+ public static void helpCommand(CommandContext args, CommandSender sender) {
+ sender.sendMessage(ChatColor.YELLOW
+ + "DiscoSheep Help\n"
+ + ChatColor.GRAY
+ + " Subcommands\n"
+ + ChatColor.WHITE + "me, stop, all, stopall, save, reload, togglejoin\n"
+ + "other : start a party for the space-delimited list of players\n"
+ + "defaults: Change the default settings for parties (takes normal arguments)\n"
+ + ChatColor.GRAY + " Arguments\n"
+ + ChatColor.WHITE + "-n : set the number of sheep per player that spawn\n"
+ + "-t : set the party duration in seconds\n"
+ + "-p : set the number of ticks between each disco beat\n"
+ + "-r : set radius of the area in which sheep can spawn\n"
+ + "-g : set spawns for other mobs"
+ + "-l: enables lightning"
+ + "-f: enables fireworks");
+ }
+
+ @Command(aliases = {"stop", "stoppls", "wtf"}, desc = "Stop your own disco party", usage = "No arguments", min = 0, max = 0)
+ public static void stopMeCommand(final CommandContext args, CommandSender sender) throws CommandException {
+ plugin.stopParty(sender.getName());
+ }
+
+ @Command(aliases = {"stopall"}, desc = "Stop all disco parties on the server", usage = "No arguments", min = 0, max = 0)
+ @CommandPermissions(value = PERMISSION_STOPALL)
+ public static void stopAllCommand(final CommandContext args, CommandSender sender) throws CommandException {
+ plugin.stopAllParties();
+ }
+
+ @Command(aliases = {"reload"}, desc = "Reload DiscoSheep configuration from file", usage = "No arguments", min = 0, max = 0)
+ public static void reloadCommand(final CommandContext args, CommandSender sender
+ ) {
+ plugin.reloadConfigFromDisk();
+ sender.sendMessage(ChatColor.GREEN + "DiscoSheep config reloaded from file.");
+ }
+
+ @Command(
+ aliases = {"me", "party", "partay", "turnup"},
+ desc = "Start your own private DiscoParty",
+ usage = "[optional flags]",
+ min = 0,
+ max = -1,
+ flags = FLAGS
+ )
+ @CommandPermissions(value = PERMISSION_PARTY)
+ public static void partyCommand(final CommandContext args, CommandSender sender
+ ) {
+ if (!(sender instanceof Player)) {
+ sender.sendMessage("You must be a player to have a party");
+ return;
+ }
+ Player player = (Player) sender;
+ if (!plugin.hasParty(player.getName())) {
+ DiscoParty party = new DiscoParty(player);
+ parsePartyFlags(party, args, sender);
+ party.startDisco();
+ } else {
+ player.sendMessage(ChatColor.RED + "You already have a party.");
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ // UUIDs not necessary since DiscoSheep only lasts for one session at most
+ // and permissions will handle onJoin DiscoSheep
+ @Command(
+ aliases = {"other", "yall"},
+ desc = "Start a party for other players",
+ usage = "[optional flags]",
+ min = 0,
+ max = -1,
+ flags = FLAGS
+ )
+ @CommandPermissions(value = PERMISSION_OTHER)
+ public static void partyOtherCommand(CommandContext args, CommandSender sender
+ ) {
+ DiscoParty party = new DiscoParty();
+ parsePartyFlags(party, args, sender);
+ String players[] = args.getParsedSlice(0);
+
+ Player p;
+ for (String playerName : players) {
+ p = Bukkit.getServer().getPlayer(playerName);
+ if (p != null) {
+ if (!plugin.hasParty(p.getName())) {
+ DiscoParty individualParty = party.clone(p);
+ individualParty.startDisco();
+ }
+ } else {
+ sender.sendMessage("Invalid player: " + playerName);
+ }
+ }
+ }
+
+ @Command(
+ aliases = {"all", "allturnup"},
+ desc = "Start a party for all players on the server",
+ usage = "[optional flags]",
+ min = 0,
+ max = -1,
+ flags = FLAGS
+ )
+ @CommandPermissions(value = PERMISSION_ALL)
+ public static void partyAllCommand(final CommandContext args, CommandSender sender
+ ) {
+ DiscoParty party = new DiscoParty();
+ parsePartyFlags(party, args, sender);
+ for (Player p : Bukkit.getServer().getOnlinePlayers()) {
+ if (!plugin.hasParty(p.getName())) {
+ DiscoParty individualParty = party.clone(p);
+ individualParty.startDisco();
+ p.sendMessage(ChatColor.RED + "LET'S DISCO!!");
+ }
+ }
+ }
+
+ @Command(
+ aliases = {"togglejoin", "toggleonjoin"},
+ desc = "Start a party for all players on the server",
+ usage = "[optional flags]",
+ min = 0,
+ max = -1,
+ flags = FLAGS
+ )
+ @CommandPermissions(value = PERMISSION_TOGGLEPARTYONJOIN)
+ public static void togglePartyOnJoinCommand(final CommandContext args, CommandSender sender
+ ) {
+ boolean result = plugin.toggleOnJoin();
+ if (result) {
+ sender.sendMessage(ChatColor.GREEN + "DiscoSheep party on join functionality enabled.");
+ } else {
+ sender.sendMessage(ChatColor.GREEN + "DiscoSheep party on join functionality disabled.");
+ }
+ }
+
+ @Command(
+ aliases = {"defaults", "setdefaults"},
+ desc = "Change the default party settings",
+ usage = "[optional flags]",
+ min = 0,
+ max = -1,
+ flags = FLAGS
+ )
+ @CommandPermissions(value = PERMISSION_CHANGEDEFAULTS)
+ public static void setDefaultsCommand(final CommandContext args, CommandSender sender
+ ) {
+ DiscoParty party = new DiscoParty();
+ parsePartyFlags(party, args, sender);
+ party.setDefaultsFromCurrent();
+ sender.sendMessage(ChatColor.GREEN + "DiscoSheep configured with new defaults (not saved to disk yet)");
+ }
+
+ @Command(
+ aliases = {"defaults", "setdefaults"},
+ desc = "Change the default party settings",
+ usage = "[optional flags]",
+ min = 0,
+ max = -1,
+ flags = FLAGS
+ )
+ @CommandPermissions(value = PERMISSION_SAVECONFIG)
+ public static void saveConfigCommand(final CommandContext args, CommandSender sender
+ ) {
+ plugin.saveConfigToDisk();
+ sender.sendMessage(ChatColor.GREEN + "DiscoSheep config saved to disk");
+ }
+}
diff --git a/src/main/java/ca/gibstick/discosheep/DiscoParty.java b/src/main/java/ca/gibstick/discosheep/DiscoParty.java
new file mode 100644
index 0000000..42c4ce2
--- /dev/null
+++ b/src/main/java/ca/gibstick/discosheep/DiscoParty.java
@@ -0,0 +1,524 @@
+package ca.gibstick.discosheep;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import org.bukkit.Color;
+import org.bukkit.DyeColor;
+import org.bukkit.Location;
+import org.bukkit.Sound;
+import org.bukkit.World;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Firework;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Sheep;
+import org.bukkit.FireworkEffect;
+import org.bukkit.FireworkEffect.Builder;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockState;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.HandlerList;
+import org.bukkit.inventory.meta.FireworkMeta;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.util.Vector;
+
+public class DiscoParty {
+
+ // Static properties
+ static int defaultDuration = 300; // ticks for entire party
+ static int defaultPeriod = 10; // ticks per state change
+ static int defaultRadius = 5;
+ static int defaultSheep = 10;
+ static float defaultSheepJump = 0.35f;
+ static int maxDuration = 2400; // 120 seconds
+ static int maxSheep = 100;
+ static int maxRadius = 100;
+ static int minPeriod = 5; // 0.25 seconds
+ static int maxPeriod = 40; // 2.0 seconds
+ private static HashMap defaultGuestNumbers = new HashMap();
+ private static HashMap maxGuestNumbers = new HashMap();
+ private static final DyeColor[] discoColours = {
+ DyeColor.RED,
+ DyeColor.ORANGE,
+ DyeColor.YELLOW,
+ DyeColor.GREEN,
+ DyeColor.BLUE,
+ DyeColor.LIGHT_BLUE,
+ DyeColor.PINK,
+ DyeColor.MAGENTA,
+ DyeColor.LIME,
+ DyeColor.CYAN,
+ DyeColor.PURPLE,
+ DyeColor.BLACK,
+ DyeColor.WHITE
+ };
+ private static final float[] pentatonicNotes = {
+ 1.0f,
+ 1.125f,
+ 1.25f,
+ 1.5f,
+ 1.667f,
+ 2.0f
+ };
+ // Instance properties
+ private Random r = new Random();
+ private PartyEvents partyEvents;
+ private final DiscoSheep parent = DiscoSheep.getInstance();
+ private Player player;
+ private ArrayList sheepList = new ArrayList();
+ private ArrayList guestList = new ArrayList();
+ private ArrayList floorBlockCache = new ArrayList();
+ private ArrayList floorBlocks = new ArrayList();
+ private HashMap guestNumbers = new HashMap();
+ private boolean doFireworks = false;
+ private boolean doJump = true;
+ private boolean doLightning = false;
+ private int duration, period, radius, sheep;
+ private int state = 0; // basically our own tick system
+ private DiscoUpdater updater;
+
+ public DiscoParty(Player player) {
+ this();
+ this.player = player;
+ }
+
+ public DiscoParty() {
+ this.duration = DiscoParty.defaultDuration;
+ this.period = DiscoParty.defaultPeriod;
+ this.radius = DiscoParty.defaultRadius;
+ this.sheep = DiscoParty.defaultSheep;
+ this.guestNumbers = new HashMap(DiscoParty.defaultGuestNumbers);
+ r = new Random();
+ }
+
+ // copy but with new player
+ // used for /ds other and /ds all
+ public DiscoParty clone(Player player) {
+ DiscoParty newParty;
+ newParty = new DiscoParty(player);
+ newParty.doFireworks = this.doFireworks;
+ newParty.duration = this.duration;
+ newParty.period = this.period;
+ newParty.radius = this.radius;
+ newParty.sheep = this.sheep;
+ newParty.doLightning = this.doLightning;
+ newParty.guestNumbers = this.getGuestNumbers();
+ return newParty;
+ }
+
+ ArrayList getSheepList() {
+ return sheepList;
+ }
+
+ ArrayList getGuestList() {
+ return guestList;
+ }
+
+ ArrayList getFloorCache() {
+ return this.floorBlockCache;
+ }
+
+ ArrayList getFloorBlocks() {
+ return this.floorBlocks;
+ }
+
+ public static HashMap getDefaultGuestNumbers() {
+ return defaultGuestNumbers;
+ }
+
+ public HashMap getGuestNumbers() {
+ return guestNumbers;
+ }
+
+ public static HashMap getMaxGuestNumbers() {
+ return maxGuestNumbers;
+ }
+
+ public int getSheep() {
+ return this.sheep;
+ }
+
+ public DiscoParty setPlayer(Player player) {
+ if (player != null) {
+ this.player = player;
+ return this;
+ } else {
+ throw new NullPointerException();
+ }
+ }
+
+ public DiscoParty setDuration(int duration) throws IllegalArgumentException {
+ if (duration <= DiscoParty.maxDuration && duration > 0) {
+ this.duration = duration;
+ return this;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public DiscoParty setPeriod(int period) throws IllegalArgumentException {
+ if (period >= DiscoParty.minPeriod && period <= DiscoParty.maxPeriod) {
+ this.period = period;
+ return this;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public DiscoParty setRadius(int radius) throws IllegalArgumentException {
+ if (radius <= DiscoParty.maxRadius && radius > 0) {
+ this.radius = radius;
+ return this;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public DiscoParty setDenseRadius(int sheepNo) throws IllegalArgumentException {
+ Integer rand = (int) Math.floor(Math.sqrt(sheep / Math.PI));
+ if (rand > DiscoParty.maxRadius) {
+ rand = DiscoParty.maxRadius;
+ }
+ if (rand < 1) {
+ rand = 1;
+ }
+
+ this.setRadius(rand);
+ return this;
+ }
+
+ public DiscoParty setSheep(int sheep) throws IllegalArgumentException {
+ if (sheep <= DiscoParty.maxSheep && sheep > 0) {
+ this.sheep = sheep;
+ return this;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public DiscoParty setDoFireworks(boolean doFireworks) {
+ this.doFireworks = doFireworks;
+ return this;
+ }
+
+ public DiscoParty setDoLightning(boolean doLightning) {
+ this.doLightning = doLightning;
+ return this;
+ }
+
+ public DiscoParty setGuestNumber(String key, int n) throws IllegalArgumentException {
+ if (getMaxGuestNumbers().containsKey(key.toUpperCase())) {
+ if (n <= getMaxGuestNumbers().get(key.toUpperCase()) && n >= 0) { // so that /ds defaults can take 0 as arg
+ getGuestNumbers().put(key, n);
+
+ return this;
+ }
+ }
+ throw new IllegalArgumentException();
+ }
+
+ // use current settings as new defaults
+ public DiscoParty setDefaultsFromCurrent() {
+ DiscoParty.defaultDuration = this.duration;
+ DiscoParty.defaultPeriod = this.period;
+ DiscoParty.defaultRadius = this.radius;
+ DiscoParty.defaultSheep = this.sheep;
+ DiscoParty.defaultGuestNumbers = new HashMap(this.getGuestNumbers());
+ return this;
+ }
+
+ Location getRandomSpawnLocation(double x, double z, World world, int spawnRadius) {
+ Location loc;
+
+ double y;
+
+ /* random point on circle with polar coordinates
+ * random number must be square rooted to obtain uniform distribution
+ * otherwise the sheep are biased toward the centre */
+ double rand = Math.sqrt(r.nextDouble()) * spawnRadius;
+ double azimuth = r.nextDouble() * 2 * Math.PI; // radians
+ x += rand * Math.cos(azimuth);
+ z += rand * Math.sin(azimuth);
+ y = this.player.getLocation().getY();
+
+ loc = new Location(world, x, y, z);
+ loc.setPitch(r.nextFloat() * 360 - 180);
+ loc.setYaw(0);
+
+ return loc;
+ }
+
+ // Spawn some number of guests next to given player
+ void spawnAll(int sheep, int spawnRadius) {
+ Location loc;
+ World world = player.getWorld();
+
+ double x = player.getLocation().getX();
+ double z = player.getLocation().getZ();
+ for (int i = 0; i < sheep; i++) {
+ loc = getRandomSpawnLocation(x, z, world, spawnRadius);
+ spawnSheep(world, loc);
+ }
+
+ // loop through hashmap of other guests and spawn accordingly
+ for (Map.Entry entry : guestNumbers.entrySet()) {
+ EntityType ent = EntityType.valueOf((String) entry.getKey());
+ int num = (Integer) entry.getValue();
+
+ for (int i = 0; i < num; i++) {
+ loc = getRandomSpawnLocation(x, z, world, spawnRadius);
+ spawnGuest(world, loc, ent);
+ }
+ }
+
+ //loc = player.getLocation();
+ //this.spawnFloor(world, new Location(world, loc.getBlockX(), loc.getBlockY() - 1, loc.getBlockZ()));
+ }
+
+ void spawnSheep(World world, Location loc) {
+ Sheep newSheep = (Sheep) world.spawnEntity(loc, EntityType.SHEEP);
+ newSheep.setColor(discoColours[(r.nextInt(discoColours.length))]);
+ newSheep.setBreed(false); // this prevents breeding - no event listener required
+ newSheep.teleport(loc); // teleport is needed to set orientation
+ getSheepList().add(newSheep);
+ if (doLightning) {
+ world.strikeLightningEffect(loc);
+ }
+ }
+
+ void spawnGuest(World world, Location loc, EntityType type) {
+ Entity newGuest = loc.getWorld().spawnEntity(loc, type);
+ getGuestList().add(newGuest);
+ if (doLightning) {
+ world.strikeLightningEffect(loc);
+ }
+ }
+
+ void spawnFloor(World world, Location loc) {
+ // First we'll save the floor state
+ for (int x = loc.getBlockX() - this.radius; x < loc.getX() + this.radius; ++x) {
+ for (int z = loc.getBlockZ() - this.radius; z < loc.getZ() + this.radius; ++z) {
+ Block block = world.getBlockAt(x, loc.getBlockY(), z);
+ if (block.getType() != Material.WOOL) {
+ this.getFloorCache().add(block.getState());
+ block.setType(Material.WOOL);
+ this.getFloorBlocks().add(block);
+ }
+ }
+ }
+ }
+
+ // Mark all guests for removal, then clear the array
+ void removeAll() {
+ for (Sheep sheeple : getSheepList()) {
+ sheeple.remove();
+ }
+ for (Entity guest : getGuestList()) {
+ guest.remove();
+ }
+ for (BlockState block : this.floorBlockCache) {
+ block.update(true);
+ }
+ getSheepList().clear();
+ getGuestList().clear();
+ floorBlockCache.clear();
+ }
+
+ // Set a random colour for all sheep in array
+ void randomizeSheepColour(Sheep sheep) {
+ sheep.setColor(discoColours[(r.nextInt(discoColours.length))]);
+ }
+
+ void randomizeFloor(Block block) {
+ block.setType(Material.WOOL);
+ block.setData(discoColours[(r.nextInt(discoColours.length))].getData());
+ }
+
+ void jump(Entity entity) {
+ Vector orgVel = entity.getVelocity();
+ Vector newVel = (new Vector()).copy(orgVel);
+ newVel.add(new Vector(0, defaultSheepJump, 0));
+ entity.setVelocity(newVel);
+ }
+
+ // WHY ISN'T THERE A Color.getValue() ?!?!?!?!
+ private Color getColor(int i) {
+ Color c = null;
+ if (i == 1) {
+ c = Color.AQUA;
+ }
+ if (i == 2) {
+ c = Color.BLACK;
+ }
+ if (i == 3) {
+ c = Color.BLUE;
+ }
+ if (i == 4) {
+ c = Color.FUCHSIA;
+ }
+ if (i == 5) {
+ c = Color.GRAY;
+ }
+ if (i == 6) {
+ c = Color.GREEN;
+ }
+ if (i == 7) {
+ c = Color.LIME;
+ }
+ if (i == 8) {
+ c = Color.MAROON;
+ }
+ if (i == 9) {
+ c = Color.NAVY;
+ }
+ if (i == 10) {
+ c = Color.OLIVE;
+ }
+ if (i == 11) {
+ c = Color.ORANGE;
+ }
+ if (i == 12) {
+ c = Color.PURPLE;
+ }
+ if (i == 13) {
+ c = Color.RED;
+ }
+ if (i == 14) {
+ c = Color.SILVER;
+ }
+ if (i == 15) {
+ c = Color.TEAL;
+ }
+ if (i == 16) {
+ c = Color.WHITE;
+ }
+ if (i == 17) {
+ c = Color.YELLOW;
+ }
+
+ return c;
+ }
+
+ void updateAll() {
+ for (Sheep sheeple : getSheepList()) {
+ randomizeSheepColour(sheeple);
+
+ if (doFireworks && state % 8 == 0) {
+ if (r.nextDouble() < 0.50) {
+ spawnRandomFireworkAtSheep(sheeple);
+ }
+ }
+
+ if (doJump) {
+ if (state % 2 == 0 && r.nextDouble() < 0.5) {
+ jump(sheeple);
+ }
+ }
+ }
+
+ for (Entity guest : getGuestList()) {
+ if (doJump) {
+ if (state % 2 == 0 && r.nextDouble() < 0.5) {
+ jump(guest);
+ }
+ }
+ }
+
+ /* for (Block block : this.floorBlocks) {
+ this.randomizeFloor(block);
+ }*/
+ }
+
+ private float getPentatonicNote() {
+ return DiscoParty.pentatonicNotes[r.nextInt(pentatonicNotes.length)];
+ }
+
+ void playSounds() {
+ player.playSound(player.getLocation(), Sound.NOTE_BASS_DRUM, 0.75f, 1.0f);
+ if (this.state % 2 == 0) {
+ player.playSound(player.getLocation(), Sound.NOTE_SNARE_DRUM, 0.8f, 1.0f);
+ }
+
+ if ((this.state + 1) % 8 == 0) {
+ player.playSound(player.getLocation(), Sound.NOTE_STICKS, 1.0f, 1.0f);
+ }
+ }
+
+ void randomizeFirework(Firework firework) {
+ Builder effect = FireworkEffect.builder();
+ FireworkMeta meta = firework.getFireworkMeta();
+
+ // construct [1, 3] random colours
+ int numColours = r.nextInt(3) + 1;
+ Color[] colourArray = new Color[numColours];
+ for (int i = 0; i < numColours; i++) {
+ colourArray[i] = getColor(r.nextInt(17) + 1);
+ }
+
+ // randomize effects
+ effect.withColor(colourArray);
+ effect.flicker(r.nextDouble() < 0.5);
+ effect.trail(r.nextDouble() < 0.5);
+ effect.with(FireworkEffect.Type.values()[r.nextInt(FireworkEffect.Type.values().length)]);
+
+ // set random effect and randomize power
+ meta.addEffect(effect.build());
+ meta.setPower(r.nextInt(2) + 1);
+
+ // apply it to the given firework
+ firework.setFireworkMeta(meta);
+ }
+
+ void spawnRandomFireworkAtSheep(Sheep sheep) {
+ Firework firework = (Firework) sheep.getWorld().spawnEntity(sheep.getEyeLocation(), EntityType.FIREWORK);
+ randomizeFirework(firework);
+ }
+
+ void update() {
+ if (duration > 0) {
+ updateAll();
+ playSounds();
+ duration -= period;
+ this.scheduleUpdate();
+ this.state = (this.state + 1) % 10000;
+ } else {
+ this.stopDisco();
+ }
+ }
+
+ void scheduleUpdate() {
+ updater = new DiscoUpdater();
+ updater.runTaskLater(parent, this.period);
+ }
+
+ void startDisco() {
+ this.spawnAll(sheep, radius);
+ this.scheduleUpdate();
+ parent.getPartyMap().put(this.player.getName(), this);
+ // start listening
+ this.partyEvents = new PartyEvents(this);
+ parent.getServer().getPluginManager().registerEvents(this.partyEvents, this.parent);
+ }
+
+ void stopDisco() {
+ removeAll();
+ this.duration = 0;
+ if (updater != null) {
+ updater.cancel();
+ }
+ updater = null;
+ parent.getPartyMap().remove(this.player.getName());
+ // stop listening
+ HandlerList.unregisterAll(this.partyEvents);
+ }
+
+ class DiscoUpdater extends BukkitRunnable {
+
+ @Override
+ public void run() {
+ update();
+ }
+ }
+}
diff --git a/src/main/java/ca/gibstick/discosheep/DiscoSheep.java b/src/main/java/ca/gibstick/discosheep/DiscoSheep.java
new file mode 100644
index 0000000..c3f8b53
--- /dev/null
+++ b/src/main/java/ca/gibstick/discosheep/DiscoSheep.java
@@ -0,0 +1,360 @@
+package ca.gibstick.discosheep;
+
+import com.sk89q.bukkit.util.CommandsManagerRegistration;
+import com.sk89q.minecraft.util.commands.CommandPermissionsException;
+import com.sk89q.minecraft.util.commands.CommandUsageException;
+import com.sk89q.minecraft.util.commands.CommandsManager;
+import com.sk89q.minecraft.util.commands.MissingNestedCommandException;
+import com.sk89q.minecraft.util.commands.WrappedCommandException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandException;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.ConsoleCommandSender;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
+
+public final class DiscoSheep extends JavaPlugin {
+
+ private static DiscoSheep instance;
+
+ static boolean partyOnJoin = false;
+ Map parties = new HashMap();
+ private CommandsManager commands;
+
+ public static DiscoSheep getInstance() {
+ if (instance == null) {
+ instance = new DiscoSheep();
+ return instance;
+ }
+ return instance;
+ }
+
+ private void setupCommands() {
+ this.commands = new CommandsManager() {
+ @Override
+ public boolean hasPermission(CommandSender sender, String perm) {
+ return sender instanceof ConsoleCommandSender || sender.hasPermission(perm);
+ }
+ };
+ CommandsManagerRegistration cmdRegister = new CommandsManagerRegistration(this, this.commands);
+ cmdRegister.register(DiscoCommands.ParentCommand.class);
+ }
+
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
+ try {
+ this.commands.execute(cmd.getName(), args, sender, sender);
+ } catch (CommandPermissionsException e) {
+ sender.sendMessage(ChatColor.RED + "You don't have permission.");
+ } catch (MissingNestedCommandException e) {
+ sender.sendMessage(ChatColor.RED + e.getUsage());
+ } catch (CommandUsageException e) {
+ sender.sendMessage(ChatColor.RED + e.getMessage());
+ sender.sendMessage(ChatColor.RED + e.getUsage());
+ } catch (WrappedCommandException e) {
+ if (e.getCause() instanceof NumberFormatException) {
+ sender.sendMessage(ChatColor.RED + "Number expected, string received instead.");
+ } else if (e.getCause() instanceof IllegalArgumentException) {
+ sender.sendMessage(ChatColor.RED + "Illegal argument (out of bounds or bad format).");
+ } else {
+ sender.sendMessage(ChatColor.RED + "An error has occurred. See console.");
+ e.printStackTrace();
+ }
+ } catch (CommandException e) {
+ sender.sendMessage(ChatColor.RED + e.getMessage());
+ } catch (com.sk89q.minecraft.util.commands.CommandException ex) {
+ Logger.getLogger(DiscoSheep.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ return true;
+ }
+
+ @Override
+ public void onEnable() {
+ instance = this;
+ //getCommand("ds").setExecutor(new DiscoSheepCommandExecutor(this));
+ setupCommands();
+ getServer().getPluginManager().registerEvents(new GlobalEvents(), this);
+
+ getConfig().addDefault("on-join.enabled", partyOnJoin);
+ getConfig().addDefault("max.sheep", DiscoParty.maxSheep);
+ getConfig().addDefault("max.radius", DiscoParty.maxRadius);
+ getConfig().addDefault("max.duration", toSeconds_i(DiscoParty.maxDuration));
+ getConfig().addDefault("max.period-ticks", DiscoParty.maxPeriod);
+ getConfig().addDefault("min.period-ticks", DiscoParty.minPeriod);
+ getConfig().addDefault("default.sheep", DiscoParty.defaultSheep);
+ getConfig().addDefault("default.radius", DiscoParty.defaultRadius);
+ getConfig().addDefault("default.duration", toSeconds_i(DiscoParty.defaultDuration));
+ getConfig().addDefault("default.period-ticks", DiscoParty.defaultPeriod);
+
+ /*
+ * Iterate through all live entities and create default configuration values for them
+ * excludes bosses and other mobs that throw NPE
+ */
+ for (EntityType ent : EntityType.values()) {
+ if (ent.isAlive()
+ && !ent.equals(EntityType.ENDER_DRAGON)
+ && !ent.equals(EntityType.WITHER)
+ && !ent.equals(EntityType.PLAYER)) {
+ getConfig().addDefault("default.guests." + ent.toString(), 0);
+ getConfig().addDefault("max.guests." + ent.toString(), 5);
+ }
+ }
+ loadConfigFromDisk();
+ }
+
+ void loadConfigFromDisk() {
+ getConfig().options().copyDefaults(true);
+ saveConfig();
+
+ partyOnJoin = getConfig().getBoolean("on-join.enabled");
+ DiscoParty.maxSheep = getConfig().getInt("max.sheep");
+ DiscoParty.maxRadius = getConfig().getInt("max.radius");
+ DiscoParty.maxDuration = toTicks(getConfig().getInt("max.duration"));
+ DiscoParty.maxPeriod = getConfig().getInt("max.period-ticks");
+ DiscoParty.minPeriod = getConfig().getInt("min.period-ticks");
+ DiscoParty.defaultSheep = getConfig().getInt("default.sheep");
+ DiscoParty.defaultRadius = getConfig().getInt("default.radius");
+ DiscoParty.defaultDuration = toTicks(getConfig().getInt("default.duration"));
+ DiscoParty.defaultPeriod = getConfig().getInt("default.period-ticks");
+
+ for (String key : getConfig().getConfigurationSection("default.guests").getKeys(false)) {
+ DiscoParty.getDefaultGuestNumbers().put(key, getConfig().getInt("default.guests." + key));
+ }
+
+ for (String key : getConfig().getConfigurationSection("max.guests").getKeys(false)) {
+ DiscoParty.getMaxGuestNumbers().put(key, getConfig().getInt("max.guests." + key));
+ }
+ }
+
+ void reloadConfigFromDisk() {
+ reloadConfig();
+ loadConfigFromDisk();
+ }
+
+ void saveConfigToDisk() {
+ getConfig().set("on-join.enabled", partyOnJoin);
+ getConfig().set("default.sheep", DiscoParty.defaultSheep);
+ getConfig().set("default.radius", DiscoParty.defaultRadius);
+ getConfig().set("default.duration", toSeconds_i(DiscoParty.defaultDuration));
+ getConfig().set("default.period-ticks", DiscoParty.defaultPeriod);
+
+ for (Map.Entry entry : DiscoParty.getDefaultGuestNumbers().entrySet()) {
+ getConfig().set("default.guests." + entry.getKey(), entry.getValue());
+ }
+ saveConfig();
+ }
+
+ @Override
+ public void onDisable() {
+ this.stopAllParties(); // or else the parties will continue FOREVER
+ instance = null;
+ commands = null;
+ }
+
+ int toTicks(double seconds) {
+ return (int) Math.round(seconds * 20.0);
+ }
+
+ double toSeconds(int ticks) {
+ return (double) Math.round(ticks / 20.0);
+ }
+
+ int toSeconds_i(int ticks) {
+ return (int) Math.round(ticks / 20.0);
+ }
+
+ public synchronized Map getPartyMap() {
+ return this.parties;
+ }
+
+ public synchronized ArrayList getParties() {
+ return new ArrayList(this.getPartyMap().values());
+ }
+
+ public void stopParty(String name) {
+ if (this.hasParty(name)) {
+ this.getParty(name).stopDisco();
+ }
+ }
+
+ public void stopAllParties() {
+ for (DiscoParty party : this.getParties()) {
+ party.stopDisco();
+ }
+ }
+
+ public boolean hasParty(String name) {
+ return this.getPartyMap().containsKey(name);
+ }
+
+ public DiscoParty getParty(String name) {
+ return this.getPartyMap().get(name);
+ }
+
+ public boolean toggleOnJoin() {
+ DiscoSheep.partyOnJoin = !DiscoSheep.partyOnJoin;
+ return DiscoSheep.partyOnJoin;
+ }
+
+ public void removeParty(String name) {
+ if (this.hasParty(name)) {
+ this.getPartyMap().remove(name);
+ }
+ }
+
+ /*-- Actual commands begin here --*/
+ /*boolean helpCommand(CommandSender sender) {
+ sender.sendMessage(ChatColor.YELLOW
+ + "DiscoSheep Help\n"
+ + ChatColor.GRAY
+ + " Subcommands\n"
+ + ChatColor.WHITE + "me, stop, all, stopall, save, reload, togglejoin\n"
+ + "other : start a party for the space-delimited list of players\n"
+ + "defaults: Change the default settings for parties (takes normal arguments)\n"
+ + ChatColor.GRAY + " Arguments\n"
+ + ChatColor.WHITE + "-n : set the number of sheep per player that spawn\n"
+ + "-t : set the party duration in seconds\n"
+ + "-p : set the number of ticks between each disco beat\n"
+ + "-r : set radius of the area in which sheep can spawn\n"
+ //+ "-g : set spawns for other mobs\n"
+ + "-l: enables lightning\n"
+ + "-fw: enables fireworks");
+ return true;
+ }
+
+ boolean stopMeCommand(CommandSender sender) {
+ stopParty(sender.getName());
+ return true;
+ }
+
+ boolean stopAllCommand(CommandSender sender) {
+ if (sender.hasPermission(PERMISSION_STOPALL)) {
+ stopAllParties();
+ return true;
+ } else {
+ return noPermsMessage(sender, PERMISSION_STOPALL);
+ }
+ }
+
+ boolean partyCommand(Player player, DiscoParty party) {
+ if (player.hasPermission(PERMISSION_PARTY)) {
+ if (!hasParty(player.getName())) {
+ party.setPlayer(player);
+ party.startDisco();
+ } else {
+ player.sendMessage(ChatColor.RED + "You already have a party. Are you underground?");
+ }
+ return true;
+ } else {
+ return noPermsMessage(player, PERMISSION_PARTY);
+ }
+ }
+
+ boolean reloadCommand(CommandSender sender) {
+ if (sender.hasPermission(PERMISSION_RELOAD)) {
+ reloadConfigFromDisk();
+ sender.sendMessage(ChatColor.GREEN + "DiscoSheep config reloaded from disk");
+ return true;
+ } else {
+ return noPermsMessage(sender, PERMISSION_RELOAD);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ // UUIDs not necessary since DiscoSheep only lasts for one session at most
+ // and permissions will handle onJoin DiscoSheep
+ boolean partyOtherCommand(String[] players, CommandSender sender, DiscoParty party) {
+ if (sender.hasPermission(PERMISSION_OTHER)) {
+ Player p;
+ for (String playerName : players) {
+ p = Bukkit.getServer().getPlayer(playerName);
+ if (p != null) {
+ if (!hasParty(p.getName())) {
+ DiscoParty individualParty = party.clone(p);
+ individualParty.startDisco();
+ }
+ } else {
+ sender.sendMessage("Invalid player: " + playerName);
+ }
+ }
+ return true;
+ } else {
+ return noPermsMessage(sender, PERMISSION_OTHER);
+ }
+ }
+
+ boolean partyAllCommand(CommandSender sender, DiscoParty party) {
+ if (sender.hasPermission(PERMISSION_ALL)) {
+ for (Player p : Bukkit.getServer().getOnlinePlayers()) {
+ if (!hasParty(p.getName())) {
+ DiscoParty individualParty = party.clone(p);
+ individualParty.startDisco();
+ p.sendMessage(ChatColor.RED + "LET'S DISCO!!");
+ }
+ }
+ return true;
+ } else {
+ return noPermsMessage(sender, PERMISSION_ALL);
+ }
+ }
+
+ boolean togglePartyOnJoinCommand(CommandSender sender) {
+ if (!sender.hasPermission(PERMISSION_TOGGLEPARTYONJOIN)) {
+ return noPermsMessage(sender, PERMISSION_TOGGLEPARTYONJOIN);
+ }
+ partyOnJoin = !partyOnJoin;
+ if (partyOnJoin) {
+ sender.sendMessage(ChatColor.GREEN + "DiscoSheep party on join functionality enabled.");
+ } else {
+ sender.sendMessage(ChatColor.GREEN + "DiscoSheep party on join functionality disabled.");
+ }
+ return true;
+ }
+
+ boolean setDefaultsCommand(CommandSender sender, DiscoParty party) {
+ if (sender.hasPermission(PERMISSION_CHANGEDEFAULTS)) {
+ party.setDefaultsFromCurrent();
+ sender.sendMessage(ChatColor.GREEN + "DiscoSheep configured with new defaults (not saved to disk yet)");
+ return true;
+ } else {
+ return noPermsMessage(sender, PERMISSION_CHANGEDEFAULTS);
+ }
+ }
+
+ boolean saveConfigCommand(CommandSender sender) {
+ if (sender.hasPermission(PERMISSION_SAVECONFIG)) {
+ saveConfigToDisk();
+ sender.sendMessage(ChatColor.GREEN + "DiscoSheep config saved to disk");
+ return true;
+ } else {
+ return noPermsMessage(sender, PERMISSION_SAVECONFIG);
+ }
+
+ }*/
+ void partyOnJoin(Player player) {
+ if (!partyOnJoin) {
+ return;
+ }
+ if (player.hasPermission(DiscoCommands.PERMISSION_ONJOIN)) {
+ DiscoParty party = new DiscoParty(player);
+ party.startDisco();
+ }
+ }
+
+ boolean clearGuests(DiscoParty party) {
+ party.getGuestNumbers().clear();
+ return true;
+ }
+
+ boolean noPermsMessage(CommandSender sender, String permission) {
+ sender.sendMessage(ChatColor.RED + "You do not have the permission node " + ChatColor.GRAY + permission);
+ return false;
+ }
+}
diff --git a/src/main/java/ca/gibstick/discosheep/GlobalEvents.java b/src/main/java/ca/gibstick/discosheep/GlobalEvents.java
new file mode 100644
index 0000000..aca1959
--- /dev/null
+++ b/src/main/java/ca/gibstick/discosheep/GlobalEvents.java
@@ -0,0 +1,31 @@
+/*
+ * BaaBaaBlockSheep have you any wool?
+ * Nope, event got cancelled.
+ * Also listens to other events, not just sheep events
+ */
+package ca.gibstick.discosheep;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+
+public class GlobalEvents implements Listener {
+
+ DiscoSheep plugin = DiscoSheep.getInstance();
+
+ @EventHandler(priority = EventPriority.MONITOR)
+ public void onPlayerQuitEvent(PlayerQuitEvent e) {
+ String name = e.getPlayer().getName();
+ plugin.stopParty(name);
+ // stop party on player quit or else it will CONTINUE FOR ETERNITY
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR)
+ public void onPlayerJoinEvent(PlayerJoinEvent e) {
+ Player player = e.getPlayer();
+ plugin.partyOnJoin(player);
+ }
+}
diff --git a/src/main/java/ca/gibstick/discosheep/PartyEvents.java b/src/main/java/ca/gibstick/discosheep/PartyEvents.java
new file mode 100644
index 0000000..5a052e5
--- /dev/null
+++ b/src/main/java/ca/gibstick/discosheep/PartyEvents.java
@@ -0,0 +1,82 @@
+package ca.gibstick.discosheep;
+
+import org.bukkit.entity.Sheep;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.EntityPortalEvent;
+import org.bukkit.event.entity.EntityTargetEvent;
+import org.bukkit.event.player.PlayerInteractEntityEvent;
+import org.bukkit.event.player.PlayerShearEntityEvent;
+
+/**
+ *
+ * @author Charlie
+ */
+public class PartyEvents implements Listener {
+
+ DiscoSheep plugin = DiscoSheep.getInstance();
+ DiscoParty party;
+ /*
+ * There will be multiple instances of PartyEvents,
+ * and each instance will only listen for its own party.
+ * That way, we don't have multiple instances iterating through
+ * the entire parties hashmap redundantly, yet we can still
+ * unregister the listeners when no parties are running.
+ */
+
+ public PartyEvents(DiscoParty party) {
+ this.party = party;
+ }
+
+ // prevent sheep shearing
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onPlayerShear(PlayerShearEntityEvent e) {
+ if (e.getEntity() instanceof Sheep) {
+ if (party.getSheepList().contains((Sheep) e.getEntity())) {
+ e.setCancelled(true);
+ }
+ }
+ }
+
+ // actually make sheep and other guests invincible
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onLivingEntityDamageEvent(EntityDamageEvent e) {
+ if (e.getEntity() instanceof Sheep) {
+ if (party.getSheepList().contains((Sheep) e.getEntity())) {
+ party.jump(e.getEntity()); // for kicks
+ e.setCancelled(true);
+ }
+ }
+ if (party.getGuestList().contains(e.getEntity())) {
+ party.jump(e.getEntity());
+ e.setCancelled(true);
+ }
+ }
+
+ // prevent uninvited guests from targetting players
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onEntityTargetLivingEntityEvent(EntityTargetEvent e) {
+ if (party.getGuestList().contains(e.getEntity())) {
+ e.setCancelled(true);
+ }
+ }
+
+ // prevent egg breeding
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onPlayerInteractEntityEvent(PlayerInteractEntityEvent e) {
+ if (party.getSheepList().contains(e.getRightClicked()) || party.getGuestList().contains(e.getRightClicked())) {
+ e.setCancelled(true);
+ }
+ }
+
+ // prevent portal teleport
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onEntityPortalEvent(EntityPortalEvent e) {
+ if (party.getSheepList().contains(e.getEntity()) || party.getGuestList().contains(e.getEntity())) {
+ e.setCancelled(true);
+ }
+ }
+
+}
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
new file mode 100644
index 0000000..59a2f36
--- /dev/null
+++ b/src/main/resources/plugin.yml
@@ -0,0 +1,93 @@
+name: DiscoSheep
+main: ca.gibstick.discosheep.DiscoSheep
+authors: [Gibstick, RangerMauve]
+version: 1.1.2
+commands:
+ #ds:
+ #description: "Main DiscoSheep command"
+ #usage: |
+ # [arguments]
+ #Use /ds help for more information
+ #To stop your party, use /ds stop.
+permissions:
+ # If default is set to false, console will not have permission!
+ discosheep.*:
+ description: Permission node for all DiscoSheep commands
+ default: op
+ children:
+ discosheep.party: true
+ discosheep.admin: true
+ discosheep.party.*:
+ description: All permissions related to parties
+ defualt: op
+ children:
+ discosheep.party.me: true
+ discosheep.party.all: true
+ discosheep.party.fireworks: true
+ discosheep.party.other: true
+ discosheep.party.changeperiod: true
+ discosheep.party.spawnguests: true
+ discosheep.party.lightning: true
+ discosheep.admin.*:
+ description: Suggested permissions for administrators
+ default: op
+ children:
+ discosheep.admin.stopall: true
+ discosheep.admin.reload: true
+ discosheep.admin.changedefaults: true
+ discosheep.admin.saveconfig: true
+ discosheep.admin.toggleonjoin: true
+ discosheep.party.me:
+ description: Allows a player to have a party of one
+ default: op
+ discosheep.party.all:
+ description: Allows a player to call a server-wide party
+ default: op
+ discosheep.admin.stopall:
+ description: Allows a player to stop all parties on the server
+ default: op
+ discosheep.party.fireworks:
+ description: Allows a player to enable have parties with fireworks
+ default: op
+ discosheep.admin.reload:
+ description: Allows a player to reload settings from config.yml
+ default: op
+ discosheep.party.other:
+ description: Allows a player to call parties for other people, including themselves.
+ default: op
+ children:
+ discosheep.party.me: true
+ discosheep.party.changeperiod:
+ description: Allows a player to use the -p switch
+ default: op
+ discosheep.admin.changedefaults:
+ description: Allows a player to change the default settings
+ default: op
+ discosheep.admin.saveconfig:
+ description: Allows a player to save the config with current values set in memory
+ default: op
+ discosheep.party.onjoin:
+ description: Gives a player a disco party on join
+ default: false
+ discosheep.party.spawnguests:
+ description: Allow a player to spawn other mobs
+ default: op
+ discosheep.admin.toggleonjoin:
+ description: Allow a player to toggle party-on-join functionality (force disable)
+ default: op
+ discosheep.party.lightning:
+ description: Allow a player to use lightning for parties
+ default: op
+ # FOR BACKWARDS COMPAT FROM 1.1 TO 1.1.1
+ discosheep.party:
+ children:
+ discosheep.party.me: true
+ discosheep.partyall:
+ children:
+ discosheep.party.all: true
+ discosheep.reload:
+ children:
+ discoshep.admin.reload: true
+ discosheep.stopall:
+ children:
+ discosheep.admin.stopall: true
\ No newline at end of file