diff --git a/src/ca/gibstick/discosheep/BaaBaaBlockSheepEvents.java b/src/ca/gibstick/discosheep/BaaBaaBlockSheepEvents.java index 3346904..0ae93e0 100644 --- a/src/ca/gibstick/discosheep/BaaBaaBlockSheepEvents.java +++ b/src/ca/gibstick/discosheep/BaaBaaBlockSheepEvents.java @@ -5,6 +5,7 @@ */ package ca.gibstick.discosheep; +import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.Sheep; import org.bukkit.event.EventHandler; @@ -47,7 +48,7 @@ public class BaaBaaBlockSheepEvents implements Listener { for (DiscoParty party : parent.getParties()) { if (party.getSheepList().contains((Sheep) e.getEntity())) { { - party.jumpSheep((Sheep) e.getEntity()); // for kicks + party.jump((LivingEntity) e.getEntity()); // for kicks e.setCancelled(true); } } @@ -56,6 +57,7 @@ public class BaaBaaBlockSheepEvents implements Listener { for (DiscoParty party : parent.getParties()) { if (party.getGuestList().contains(e.getEntity())) { + party.jump((LivingEntity) e.getEntity()); e.setCancelled(true); } } diff --git a/src/ca/gibstick/discosheep/DiscoParty.java b/src/ca/gibstick/discosheep/DiscoParty.java index 4632072..a1e2c5e 100644 --- a/src/ca/gibstick/discosheep/DiscoParty.java +++ b/src/ca/gibstick/discosheep/DiscoParty.java @@ -41,7 +41,8 @@ public class DiscoParty { static int minPeriod = 5; // 0.25 seconds static int maxPeriod = 40; // 2.0 seconds private HashMap guestNumbers = new HashMap(); - static HashMap defaultGuestNumbers = new HashMap(); + private static HashMap defaultGuestNumbers = new HashMap(); + private static HashMap maxGuestNumbers = new HashMap(); private boolean doFireworks = false; private boolean doJump = true; private int duration, period, radius, sheep; @@ -70,8 +71,7 @@ public class DiscoParty { this.period = DiscoParty.defaultPeriod; this.radius = DiscoParty.defaultRadius; this.sheep = DiscoParty.defaultSheep; - - this.guestNumbers = DiscoParty.getDefaultGuestNumbers(); + this.guestNumbers = (HashMap) DiscoParty.getDefaultGuestNumbers().clone(); } public DiscoParty(DiscoSheep parent) { @@ -80,7 +80,7 @@ public class DiscoParty { this.period = DiscoParty.defaultPeriod; this.radius = DiscoParty.defaultRadius; this.sheep = DiscoParty.defaultSheep; - this.guestNumbers = DiscoParty.getDefaultGuestNumbers(); + this.guestNumbers = (HashMap) DiscoParty.getDefaultGuestNumbers().clone(); } // copy but with new player @@ -92,6 +92,7 @@ public class DiscoParty { newParty.period = this.period; newParty.radius = this.radius; newParty.sheep = this.sheep; + newParty.guestNumbers = this.getGuestNumbers(); return newParty; } @@ -107,6 +108,14 @@ public class DiscoParty { return defaultGuestNumbers; } + public HashMap getGuestNumbers() { + return guestNumbers; + } + + public static HashMap getMaxGuestNumbers() { + return maxGuestNumbers; + } + public int getSheep() { return this.sheep; } @@ -174,12 +183,24 @@ public class DiscoParty { 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 = (HashMap) this.getGuestNumbers().clone(); return this; } @@ -241,7 +262,6 @@ public class DiscoParty { void spawnGuest(World world, Location loc, EntityType type) { LivingEntity newGuest = (LivingEntity) world.spawnEntity(loc, type); getGuestList().add(newGuest); - ds.getLogger().log(Level.INFO, "SPAWNING GUEST"); } // Mark all guests for removal, then clear the array @@ -261,11 +281,11 @@ public class DiscoParty { sheep.setColor(discoColours[(int) Math.round(Math.random() * (discoColours.length - 1))]); } - void jumpSheep(Sheep sheep) { - Vector orgVel = sheep.getVelocity(); + void jump(LivingEntity entity) { + Vector orgVel = entity.getVelocity(); Vector newVel = (new Vector()).copy(orgVel); newVel.add(new Vector(0, defaultSheepJump, 0)); - sheep.setVelocity(newVel); + entity.setVelocity(newVel); } // WHY ISN'T THERE A Color.getValue() ?!?!?!?! @@ -326,7 +346,7 @@ public class DiscoParty { return c; } - void updateAllSheep() { + void updateAll() { for (Sheep sheeple : getSheepList()) { randomizeSheepColour(sheeple); @@ -337,10 +357,16 @@ public class DiscoParty { } if (doJump) { - if (state % 2 == 0) { - if (Math.random() < 0.5) { - jumpSheep(sheeple); - } + if (state % 2 == 0 && Math.random() < 0.5) { + jump(sheeple); + } + } + } + + for (LivingEntity guest : getGuestList()) { + if (doJump) { + if (state % 2 == 0 && Math.random() < 0.5) { + jump(guest); } } } @@ -390,7 +416,7 @@ public class DiscoParty { void update() { if (duration > 0) { - updateAllSheep(); + updateAll(); playSounds(); duration -= period; this.scheduleUpdate(); diff --git a/src/ca/gibstick/discosheep/DiscoSheep.java b/src/ca/gibstick/discosheep/DiscoSheep.java index eadb301..b790bbc 100644 --- a/src/ca/gibstick/discosheep/DiscoSheep.java +++ b/src/ca/gibstick/discosheep/DiscoSheep.java @@ -26,41 +26,43 @@ public final class DiscoSheep extends JavaPlugin { static final String PERMISSION_SPAWNGUESTS = "discosheep.spawnguests"; Map parties = new HashMap(); private BaaBaaBlockSheepEvents blockEvents = new BaaBaaBlockSheepEvents(this); - FileConfiguration config; @Override public void onEnable() { getCommand("ds").setExecutor(new DiscoSheepCommandExecutor(this)); getServer().getPluginManager().registerEvents(blockEvents, this); - if (config == null) { - config = this.getConfig(); - } + 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); - config.addDefault("max.sheep", DiscoParty.maxSheep); - config.addDefault("max.radius", DiscoParty.maxRadius); - config.addDefault("max.duration", toSeconds_i(DiscoParty.maxDuration)); - config.addDefault("max.period-ticks", DiscoParty.maxPeriod); - config.addDefault("min.period-ticks", DiscoParty.minPeriod); - config.addDefault("default.sheep", DiscoParty.defaultSheep); - config.addDefault("default.radius", DiscoParty.defaultRadius); - config.addDefault("default.duration", toSeconds_i(DiscoParty.defaultDuration)); - config.addDefault("default.period-ticks", DiscoParty.defaultPeriod); - - Map defaultGuests = new HashMap(); + Map tempMap = new HashMap(); // temporary map to store guest config values // create a default hashmap of for all living entities // this creates a default config entry with all living entites present - // except for bosses (they throw NPE for some reason) + // except for bosses, pigzombie (NPE for some reason) for (EntityType ent : EntityType.values()) { - if (ent.isAlive() && !ent.equals(EntityType.ENDER_DRAGON) && !ent.equals(EntityType.WITHER)) { - defaultGuests.put(ent.toString(), 0); + if (ent.isAlive() && !ent.equals(EntityType.ENDER_DRAGON) && !ent.equals(EntityType.WITHER) + && !ent.equals(EntityType.PIG_ZOMBIE)) { + tempMap.put(ent.toString(), 0); } } - for (Map.Entry entry : defaultGuests.entrySet()) { - config.addDefault("default.guests." + entry.getKey(), entry.getValue()); + for (Map.Entry entry : tempMap.entrySet()) { + getConfig().addDefault("default.guests." + entry.getKey(), entry.getValue()); + } + + // same thing, but for limits (no default limits) + + for (Map.Entry entry : tempMap.entrySet()) { + getConfig().addDefault("max.guests." + entry.getKey(), entry.getValue()); } loadConfigFromDisk(); @@ -84,6 +86,10 @@ public final class DiscoSheep extends JavaPlugin { 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() { @@ -92,25 +98,21 @@ public final class DiscoSheep extends JavaPlugin { } void saveConfigToDisk() { - if (config == null) { - config = getConfig(); - } - - config.set("default.sheep", DiscoParty.defaultSheep); - config.set("default.radius", DiscoParty.defaultRadius); - config.set("default.duration", toSeconds_i(DiscoParty.defaultDuration)); - config.set("default.period-ticks", DiscoParty.defaultPeriod); + 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()) { - config.addDefault("default.guests." + entry.getKey(), entry.getValue()); + getConfig().set("default.guests." + entry.getKey(), entry.getValue()); } + saveConfig(); } @Override public void onDisable() { this.stopAllParties(); // or else the parties will continue FOREVER - this.config = null; } int toTicks(double seconds) { @@ -161,7 +163,20 @@ public final class DiscoSheep extends JavaPlugin { /*-- 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\n" + "You do not need permission to use the \"stop\" command\n" + "other : start a party for the space-delimited list of players\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" + "-fw: enables fireworks"); + sender.sendMessage(ChatColor.YELLOW + + "DiscoSheep Help\n" + + ChatColor.GRAY + + " Subcommands\n" + + ChatColor.WHITE + "me, stop, all, stopall, save, reload\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" + + "-fw: enables fireworks"); return true; } @@ -248,6 +263,7 @@ public final class DiscoSheep extends JavaPlugin { 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); @@ -257,6 +273,7 @@ public final class DiscoSheep extends JavaPlugin { 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); diff --git a/src/ca/gibstick/discosheep/DiscoSheepCommandExecutor.java b/src/ca/gibstick/discosheep/DiscoSheepCommandExecutor.java index 8d4d8ab..e2bd626 100644 --- a/src/ca/gibstick/discosheep/DiscoSheepCommandExecutor.java +++ b/src/ca/gibstick/discosheep/DiscoSheepCommandExecutor.java @@ -22,7 +22,15 @@ public class DiscoSheepCommandExecutor implements CommandExecutor { return false; } - private int parseNextIntArg(String[] args, int i) { + 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]); @@ -33,7 +41,7 @@ public class DiscoSheepCommandExecutor implements CommandExecutor { return -1; // ibid } - private Double parseNextDoubleArg(String[] args, int i) { + private Double getNextDoubleArg(String[] args, int i) { if (i < args.length - 1) { try { return Double.parseDouble(args[i + 1]); @@ -44,8 +52,9 @@ public class DiscoSheepCommandExecutor implements CommandExecutor { return -1.0d; // ibid } - // return portion of the array that contains the list of players - private String[] parsePlayerList(String[] args, int i) { + // 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++; @@ -100,7 +109,7 @@ public class DiscoSheepCommandExecutor implements CommandExecutor { } if (!specialRadius) { try { - mainParty.setRadius(parseNextIntArg(args, i)); + mainParty.setRadius(getNextIntArg(args, i)); } catch (IllegalArgumentException e) { sender.sendMessage("Radius must be an integer within the range [1, " + DiscoParty.maxRadius + "]"); @@ -109,7 +118,7 @@ public class DiscoSheepCommandExecutor implements CommandExecutor { } } else if (args[i].equalsIgnoreCase("-n")) { try { - mainParty.setSheep(parseNextIntArg(args, i)); + mainParty.setSheep(getNextIntArg(args, i)); } catch (IllegalArgumentException e) { sender.sendMessage("The number of sheep must be an integer within the range [1, " + DiscoParty.maxSheep + "]"); @@ -117,7 +126,7 @@ public class DiscoSheepCommandExecutor implements CommandExecutor { } } else if (args[i].equalsIgnoreCase("-t")) { try { - mainParty.setDuration(parent.toTicks(parseNextIntArg(args, i))); + 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) + "]"); @@ -128,7 +137,7 @@ public class DiscoSheepCommandExecutor implements CommandExecutor { return parent.noPermsMessage(sender, DiscoSheep.PERMISSION_CHANGEPERIOD); } try { - mainParty.setPeriod(parseNextIntArg(args, i)); + mainParty.setPeriod(getNextIntArg(args, i)); } catch (IllegalArgumentException e) { sender.sendMessage( "The period in ticks must be within the range [" @@ -136,6 +145,21 @@ public class DiscoSheepCommandExecutor implements CommandExecutor { + DiscoParty.maxPeriod + "]"); return false; } + } else if (args[i].equalsIgnoreCase("-g")) { + if (!sender.hasPermission(DiscoSheep.PERMISSION_SPAWNGUESTS)) { + return parent.noPermsMessage(sender, DiscoSheep.PERMISSION_SPAWNGUESTS); + } + String[] guests = getNextArgs(args, i + 1); + int j = 0; + while (j < guests.length) { + try { + mainParty.setGuestNumber(guests[j], getNextIntArg(guests, j)); + } catch (IllegalArgumentException e) { + sender.sendMessage("Invalid arguments: " + 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 + } } } @@ -149,7 +173,7 @@ public class DiscoSheepCommandExecutor implements CommandExecutor { } else if (args[0].equalsIgnoreCase("me") && isPlayer) { return parent.partyCommand(player, mainParty); } else if (args[0].equalsIgnoreCase("other")) { - return parent.partyOtherCommand(parsePlayerList(args, 1), sender, mainParty); + return parent.partyOtherCommand(getNextArgs(args, 1), sender, mainParty); } else if (args[0].equalsIgnoreCase("defaults")) { return parent.setDefaultsCommand(sender, mainParty); } else { diff --git a/src/plugin.yml b/src/plugin.yml index 80600aa..fd155fb 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -62,4 +62,7 @@ permissions: default: op discosheep.partyonjoin: description: Gives a player a disco party on join - default: false \ No newline at end of file + default: false + discosheep.spawnguests: + description: Allow a player to spawn other mobs + default: op \ No newline at end of file