commit
4841885835
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,5 +1,4 @@
|
||||
/target/
|
||||
*.jar
|
||||
/build/
|
||||
/dist/
|
||||
/server/
|
||||
/out/
|
||||
.idea
|
||||
*.iml
|
||||
|
@ -1,21 +1,17 @@
|
||||
DiscoSheep
|
||||
==========
|
||||
|
||||
A plugin for [Bukkit](http://bukkit.org/)/Spigot, 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 plugin for [Bukkit](http://bukkit.org/)/[Spigot](https://www.spigotmc.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.
|
||||
|
||||
[Demo](https://www.youtube.com/watch?v=Ls4L9Cjp-As)
|
||||
|
||||
###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.
|
||||
|
||||
###A Note on Performance###
|
||||
DiscoSheep can be a fairly resource intensive plugin, but only when it is running. The events are unregistered when there are no parties. To prevent server slowdowns, set sensible limits in your config.yml, though the defaults are already fairly conservative.
|
||||
|
||||
###[Documentation](https://github.com/Gibstick/DiscoSheep/wiki)###
|
||||
|
||||
###Versions###
|
||||
Tested up to CraftBukkit build #3092 (MC: 1.7.9); can be built with Java 7.
|
||||
Also works as-is with Spigot for 1.8.
|
||||
Last tested on CraftBukkit version git-Bukkit-53fac9f (MC: 1.8.8) (Implementing API version 1.8.8-R0.1-SNAPSHOT) AKA Spigot for 1.8.8.
|
||||
|
||||
###[~~BukkitDev~~](http://dev.bukkit.org/bukkit-plugins/superdiscosheep/)###
|
||||
No longer updated.
|
||||
|
@ -1,3 +0,0 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-shared-configuration>
|
||||
<!--
|
||||
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||
The configuration is intended to be shared among all the users of project and
|
||||
therefore it is assumed to be part of version control checkout.
|
||||
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||
-->
|
||||
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||
<!--
|
||||
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||
-->
|
||||
<netbeans.hint.jdkPlatform>JDK_1.7</netbeans.hint.jdkPlatform>
|
||||
<org-netbeans-modules-javascript2-requirejs.enabled>true</org-netbeans-modules-javascript2-requirejs.enabled>
|
||||
</properties>
|
||||
</project-shared-configuration>
|
105
pom.xml
105
pom.xml
@ -1,105 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ca.gibstick</groupId>
|
||||
<artifactId>DiscoSheep</artifactId>
|
||||
<version>1.1.2</version>
|
||||
<packaging>jar</packaging>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>repo.oc.tc</id>
|
||||
<url>http://repo.oc.tc/content/repositories/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.sk89q</groupId>
|
||||
<artifactId>command-framework-bukkit</artifactId>
|
||||
<version>0.5-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.8-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>DiscoSheep</finalName>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<targetPath>.</targetPath>
|
||||
<filtering>true</filtering>
|
||||
<directory>src/main/resources/</directory>
|
||||
<includes>
|
||||
<include>plugin.yml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<compilerArgs>
|
||||
<arg>-Xlint:deprecation</arg>
|
||||
</compilerArgs>
|
||||
<showDeprecation>true</showDeprecation>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<finalName>DiscoSheep</finalName>
|
||||
<useBaseVersion>true</useBaseVersion>
|
||||
<shadedClassifierName/>
|
||||
<outputDirectory>${project.basedir}</outputDirectory>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>com.sk89q:command-framework-bukkit</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<generateUniqueDependencyReducedPom>false</generateUniqueDependencyReducedPom>
|
||||
<shadedArtifactAttached>true</shadedArtifactAttached> <!-- Makes Netbeans shut up -->
|
||||
<shadedClassifierName>shaded</shadedClassifierName>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
</properties>
|
||||
<name>DiscoSheep</name>
|
||||
</project>
|
@ -1,315 +0,0 @@
|
||||
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 PERMISSION_DANCEFLOOR = "discosheep.party.dancefloor";
|
||||
|
||||
static final String FLAGS = "n:t:p:r:lfgd";
|
||||
|
||||
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));
|
||||
|
||||
if (sender.hasPermission(PERMISSION_DANCEFLOOR)) {
|
||||
party.setDoFloor(args.hasFlag('d'));
|
||||
}
|
||||
|
||||
// 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])) { // wtf??
|
||||
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 <players>: 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 <integer>: set the number of sheep per player that spawn\n"
|
||||
+ "-t <seconds>: set the party duration in seconds\n"
|
||||
+ "-p <ticks>: set the number of ticks between each disco beat\n"
|
||||
+ "-r <radius>: set radius of the area in which sheep can spawn\n"
|
||||
+ "-g <mob> <number>: set spawns for other mobs\n"
|
||||
+ "-l: enables lightning\n"
|
||||
+ "-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");
|
||||
}
|
||||
}
|
@ -1,554 +0,0 @@
|
||||
package ca.gibstick.discosheep;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.DyeColor;
|
||||
import static org.bukkit.EntityEffect.*;
|
||||
import org.bukkit.FireworkEffect;
|
||||
import org.bukkit.FireworkEffect.Builder;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Firework;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Sheep;
|
||||
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 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 maxFloorSize = 5;
|
||||
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<String, Integer> defaultGuestNumbers = new HashMap<>();
|
||||
private static HashMap<String, Integer> maxGuestNumbers = new HashMap<>();
|
||||
private static final EnumSet<Material> floorExceptions = EnumSet.of(
|
||||
//Material.STAINED_GLASS,
|
||||
Material.FURNACE,
|
||||
Material.CHEST,
|
||||
Material.ENDER_CHEST,
|
||||
Material.BURNING_FURNACE,
|
||||
Material.ENDER_PORTAL,
|
||||
Material.ENDER_PORTAL_FRAME,
|
||||
Material.OBSIDIAN,
|
||||
Material.BED,
|
||||
Material.BED_BLOCK,
|
||||
Material.SOIL
|
||||
);
|
||||
|
||||
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 plugin = DiscoSheep.getInstance();
|
||||
private Player player;
|
||||
private final ArrayList<Sheep> sheepList = new ArrayList<>();
|
||||
private final HashSet<Sheep> sheepSet = new HashSet<>();
|
||||
private final ArrayList<Entity> guestList = new ArrayList<>();
|
||||
private final HashSet<Entity> guestSet = new HashSet<>();
|
||||
private final ArrayList<BlockState> floorBlockCache = new ArrayList<>();
|
||||
private final ArrayList<Block> floorBlocks = new ArrayList<>();
|
||||
private HashMap<String, Integer> guestNumbers = new HashMap<>();
|
||||
private boolean doFireworks = false;
|
||||
private final boolean doJump = true;
|
||||
private boolean doLightning = false;
|
||||
private boolean doFloor = false;
|
||||
private int duration, period, radius, sheep;
|
||||
private int state = 0; // basically our own tick system
|
||||
private float volumeMultiplier;
|
||||
private Location partyLocation;
|
||||
private DiscoUpdater updater;
|
||||
|
||||
public DiscoParty(Player player) {
|
||||
this();
|
||||
this.player = player;
|
||||
this.partyLocation = player.getLocation();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
HashSet<Sheep> getSheepSet() {
|
||||
return sheepSet;
|
||||
}
|
||||
|
||||
HashSet<Entity> getGuestSet() {
|
||||
return guestSet;
|
||||
}
|
||||
|
||||
ArrayList<Sheep> getSheepList() {
|
||||
return sheepList;
|
||||
}
|
||||
|
||||
ArrayList<Entity> getGuestList() {
|
||||
return guestList;
|
||||
}
|
||||
|
||||
ArrayList<BlockState> getFloorCache() {
|
||||
return this.floorBlockCache;
|
||||
}
|
||||
|
||||
ArrayList<Block> getFloorBlocks() {
|
||||
return this.floorBlocks;
|
||||
}
|
||||
|
||||
public int getRadius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
public static HashMap<String, Integer> getDefaultGuestNumbers() {
|
||||
return defaultGuestNumbers;
|
||||
}
|
||||
|
||||
public HashMap<String, Integer> getGuestNumbers() {
|
||||
return guestNumbers;
|
||||
}
|
||||
|
||||
public static HashMap<String, Integer> getMaxGuestNumbers() {
|
||||
return maxGuestNumbers;
|
||||
}
|
||||
|
||||
public int getSheep() {
|
||||
return this.sheep;
|
||||
}
|
||||
|
||||
public DiscoParty setPlayer(Player player) {
|
||||
this.player = player;
|
||||
this.partyLocation = player.getLocation();
|
||||
return this;
|
||||
}
|
||||
|
||||
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 void setDoFloor(boolean doFloor) {
|
||||
this.doFloor = doFloor;
|
||||
}
|
||||
|
||||
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 = partyLocation.getY();
|
||||
|
||||
loc = new Location(world, x, y, z);
|
||||
loc.setPitch(r.nextFloat() * 360 - 180);
|
||||
loc.setYaw(r.nextFloat() * 360 - 180);
|
||||
|
||||
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 = partyLocation.getX();
|
||||
double z = partyLocation.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);
|
||||
}
|
||||
}
|
||||
|
||||
if (doFloor) {
|
||||
this.spawnFloor(world, new Location(world, partyLocation.getBlockX(), partyLocation.getBlockY() - 1, partyLocation.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);
|
||||
getSheepSet().add(newSheep);
|
||||
if (doLightning) {
|
||||
world.strikeLightningEffect(loc);
|
||||
}
|
||||
//newSheep.setCustomName("jeb_");
|
||||
//newSheep.setCustomNameVisible(false);
|
||||
newSheep.setRemoveWhenFarAway(false);
|
||||
}
|
||||
|
||||
void spawnGuest(World world, Location loc, EntityType type) {
|
||||
LivingEntity newGuest = (LivingEntity) loc.getWorld().spawnEntity(loc, type);
|
||||
newGuest.setRemoveWhenFarAway(false);
|
||||
getGuestList().add(newGuest);
|
||||
getGuestSet().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() - Math.min(this.radius, DiscoParty.maxFloorSize); x < loc.getX() + Math.min(this.radius, DiscoParty.maxFloorSize); ++x) {
|
||||
for (int z = loc.getBlockZ() - Math.min(this.radius, DiscoParty.maxFloorSize); z < loc.getZ() + Math.min(this.radius, DiscoParty.maxFloorSize); ++z) {
|
||||
Block block = world.getBlockAt(x, loc.getBlockY(), z);
|
||||
if (!DiscoParty.floorExceptions.contains(block.getType())
|
||||
&& block.getRelative(BlockFace.UP).getType() == Material.AIR
|
||||
&& (block.getType().isSolid() || block.getType() == Material.AIR)) {
|
||||
this.getFloorCache().add(block.getState());
|
||||
//block.setType(Material.STAINED_GLASS);
|
||||
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();
|
||||
getSheepSet().clear();
|
||||
getGuestSet().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, int index) {
|
||||
int to_color = (index + state) % discoColours.length;
|
||||
block.setData(discoColours[to_color].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);
|
||||
}
|
||||
|
||||
Color[] getColor = {
|
||||
Color.AQUA,
|
||||
Color.BLACK,
|
||||
Color.BLUE,
|
||||
Color.FUCHSIA,
|
||||
Color.GRAY,
|
||||
Color.GREEN,
|
||||
Color.LIME,
|
||||
Color.MAROON,
|
||||
Color.NAVY,
|
||||
Color.OLIVE,
|
||||
Color.ORANGE,
|
||||
Color.PURPLE,
|
||||
Color.RED,
|
||||
Color.SILVER,
|
||||
Color.TEAL,
|
||||
Color.WHITE,
|
||||
Color.YELLOW
|
||||
};
|
||||
|
||||
void updateAll() {
|
||||
for (Sheep sheeple : getSheepList()) {
|
||||
//randomizeSheepColour(sheeple);
|
||||
|
||||
if (state % 8 == 0) {
|
||||
if (r.nextDouble() < 0.50 && doFireworks) {
|
||||
spawnRandomFireworkAtSheep(sheeple);
|
||||
}
|
||||
sheeple.playEffect(SHEEP_EAT);
|
||||
}
|
||||
|
||||
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 (int i = 0; i < this.floorBlocks.size(); i++) {
|
||||
// this.randomizeFloor(floorBlocks.get(i), i);
|
||||
// }
|
||||
}
|
||||
|
||||
float getPentatonicNote() {
|
||||
return DiscoParty.pentatonicNotes[r.nextInt(pentatonicNotes.length)];
|
||||
}
|
||||
|
||||
void playSounds() {
|
||||
|
||||
/*for (Sheep sheep : this.getSheepList()) {
|
||||
sheep.getWorld().playSound(sheep.getLocation(), Sound.NOTE_BASS_DRUM, 0.75f, 1.0f);
|
||||
|
||||
if (this.state % 2 == 0) {
|
||||
sheep.getWorld().playSound(sheep.getLocation(), Sound.NOTE_SNARE_DRUM, 0.8f, 1.0f);
|
||||
}
|
||||
|
||||
if ((this.state + 1) % 8 == 0) {
|
||||
sheep.getWorld().playSound(sheep.getLocation(), Sound.NOTE_STICKS, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
}*/
|
||||
partyLocation.getWorld().playSound(partyLocation, Sound.NOTE_BASS_DRUM, volumeMultiplier * 0.75f, 1.0f);
|
||||
if (this.state % 2 == 0) {
|
||||
partyLocation.getWorld().playSound(partyLocation, Sound.NOTE_SNARE_DRUM, volumeMultiplier * 0.8f, 1.0f);
|
||||
}
|
||||
|
||||
if ((this.state + 1) % 8 == 0) {
|
||||
partyLocation.getWorld().playSound(partyLocation, Sound.NOTE_STICKS, volumeMultiplier * 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)];
|
||||
}
|
||||
|
||||
// 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(plugin, this.period);
|
||||
}
|
||||
|
||||
void startDisco() {
|
||||
this.volumeMultiplier = Math.max(this.radius / 10, 1.0f);
|
||||
this.spawnAll(sheep, radius);
|
||||
this.scheduleUpdate();
|
||||
plugin.getPartyMap().put(this.player.getName(), this);
|
||||
// start listening
|
||||
this.partyEvents = new PartyEvents(this);
|
||||
plugin.getServer().getPluginManager().registerEvents(this.partyEvents, this.plugin);
|
||||
}
|
||||
|
||||
void stopDisco() {
|
||||
removeAll();
|
||||
this.duration = 0;
|
||||
if (updater != null) {
|
||||
updater.cancel();
|
||||
}
|
||||
updater = null;
|
||||
plugin.getPartyMap().remove(this.player.getName());
|
||||
// stop listening
|
||||
HandlerList.unregisterAll(this.partyEvents);
|
||||
}
|
||||
|
||||
class DiscoUpdater extends BukkitRunnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,247 +0,0 @@
|
||||
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.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
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;
|
||||
|
||||
boolean partyOnJoin = true;
|
||||
Map<String, DiscoParty> parties = new HashMap<>();
|
||||
private CommandsManager<CommandSender> commands;
|
||||
|
||||
public static DiscoSheep getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new DiscoSheep();
|
||||
return instance;
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void setupCommands() {
|
||||
this.commands = new CommandsManager<CommandSender>() {
|
||||
@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.");
|
||||
}
|
||||
} 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;
|
||||
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);
|
||||
getConfig().addDefault("max.floor_size", DiscoParty.maxFloorSize);
|
||||
|
||||
/*
|
||||
* 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");
|
||||
DiscoParty.maxFloorSize = getConfig().getInt("max.floor_size");
|
||||
|
||||
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<String, Integer> 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<String, DiscoParty> getPartyMap() {
|
||||
return this.parties;
|
||||
}
|
||||
|
||||
public synchronized ArrayList<DiscoParty> 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() {
|
||||
partyOnJoin = !partyOnJoin;
|
||||
return partyOnJoin;
|
||||
}
|
||||
|
||||
public void removeParty(String name) {
|
||||
if (this.hasParty(name)) {
|
||||
this.getPartyMap().remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// From user "desht" on bukkit forums
|
||||
public List<Player> getPlayersWithin(Player player, int distance) {
|
||||
List<Player> res = new ArrayList<>();
|
||||
int d2 = distance * distance;
|
||||
for (Player p : Bukkit.getServer().getOnlinePlayers()) {
|
||||
if (p.getWorld() == player.getWorld() && p.getLocation().distanceSquared(player.getLocation()) <= d2) {
|
||||
res.add(p);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
@ -1,31 +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 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);
|
||||
}
|
||||
}
|
274
src/me/cwang/discosheep/AbstractParty.java
Normal file
274
src/me/cwang/discosheep/AbstractParty.java
Normal file
@ -0,0 +1,274 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by Charlie on 2015-08-13.
|
||||
*/
|
||||
public abstract class AbstractParty {
|
||||
public 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
|
||||
};
|
||||
|
||||
// Static properties
|
||||
static HashMap<EntityType, Integer> defaultGuestNumbers = new HashMap<>();
|
||||
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
|
||||
static HashMap<EntityType, Integer> maxGuestNumbers = new HashMap<>();
|
||||
protected BukkitRunnable updater;
|
||||
|
||||
public AbstractParty() {
|
||||
}
|
||||
|
||||
static HashMap<EntityType, Integer> getDefaultGuestNumbers() {
|
||||
return defaultGuestNumbers;
|
||||
}
|
||||
|
||||
static HashMap<EntityType, Integer> getMaxGuestNumbers() {
|
||||
return maxGuestNumbers;
|
||||
}
|
||||
|
||||
protected abstract Player getPlayer();
|
||||
|
||||
protected abstract void jump(Entity entity);
|
||||
|
||||
public abstract int getSheep();
|
||||
|
||||
protected abstract List<Sheep> getSheepList();
|
||||
|
||||
protected abstract List<LivingEntity> getGuestList();
|
||||
|
||||
protected abstract HashMap<EntityType, Integer> getGuestMap();
|
||||
|
||||
protected abstract int getPeriod();
|
||||
|
||||
protected abstract int getState();
|
||||
|
||||
protected abstract float getVolumeMultiplier();
|
||||
|
||||
protected abstract Location getLocation();
|
||||
|
||||
protected abstract Sheep spawnSheep();
|
||||
|
||||
protected abstract boolean isExpired();
|
||||
|
||||
protected abstract Entity spawnGuest(EntityType type);
|
||||
|
||||
protected final void spawnAll() {
|
||||
for (int i = 0; i < getSheep(); ++i) spawnSheep();
|
||||
|
||||
for (Map.Entry<EntityType, Integer> entry : getGuestMap().entrySet()) {
|
||||
for (int i = 0; i < entry.getValue(); ++i) spawnGuest(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
protected final void removeAll() {
|
||||
for (Sheep sheep : getSheepList()) {
|
||||
sheep.removeMetadata(DiscoSheep.METADATA_KEY, DiscoSheep.getInstance());
|
||||
sheep.remove();
|
||||
}
|
||||
|
||||
for (LivingEntity g : getGuestList()) {
|
||||
g.removeMetadata(DiscoSheep.METADATA_KEY, DiscoSheep.getInstance());
|
||||
g.remove();
|
||||
}
|
||||
|
||||
getSheepList().clear();
|
||||
getGuestList().clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the static default settings. Takes the values from the current instance
|
||||
* and sets them as the defaults for all parties.
|
||||
*/
|
||||
abstract void setDefaultsFromCurrent();
|
||||
|
||||
|
||||
/**
|
||||
* Map an integer i to a Color enum value
|
||||
*
|
||||
* @param i
|
||||
* @return A Color enum
|
||||
*/
|
||||
public final Color getColor(int i) {
|
||||
Color c = null;
|
||||
switch (i) {
|
||||
case 1:
|
||||
c = Color.AQUA;
|
||||
break;
|
||||
case 2:
|
||||
c = Color.BLACK;
|
||||
break;
|
||||
case 3:
|
||||
c = Color.BLUE;
|
||||
break;
|
||||
case 4:
|
||||
c = Color.FUCHSIA;
|
||||
break;
|
||||
case 5:
|
||||
c = Color.GRAY;
|
||||
break;
|
||||
case 6:
|
||||
c = Color.GREEN;
|
||||
break;
|
||||
case 7:
|
||||
c = Color.LIME;
|
||||
break;
|
||||
case 8:
|
||||
c = Color.MAROON;
|
||||
break;
|
||||
case 9:
|
||||
c = Color.NAVY;
|
||||
break;
|
||||
case 10:
|
||||
c = Color.OLIVE;
|
||||
break;
|
||||
case 11:
|
||||
c = Color.ORANGE;
|
||||
break;
|
||||
case 12:
|
||||
c = Color.PURPLE;
|
||||
break;
|
||||
case 13:
|
||||
c = Color.RED;
|
||||
break;
|
||||
case 14:
|
||||
c = Color.SILVER;
|
||||
break;
|
||||
case 15:
|
||||
c = Color.TEAL;
|
||||
break;
|
||||
case 16:
|
||||
c = Color.WHITE;
|
||||
break;
|
||||
case 17:
|
||||
c = Color.YELLOW;
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance the internal tick state of the party by 1.
|
||||
*/
|
||||
protected abstract void updateState();
|
||||
|
||||
/**
|
||||
* Method called on all sheep to update the sheep. Could involve colour update,
|
||||
* a jump, etc.
|
||||
*
|
||||
* @param sheep the sheep to update
|
||||
*/
|
||||
protected abstract void updateSheep(Sheep sheep);
|
||||
|
||||
/**
|
||||
* Method called on all guests for updates. Could involve jumping, teleporting, etc.
|
||||
*
|
||||
* @param guest The mob to update.
|
||||
*/
|
||||
protected abstract void updateGuest(LivingEntity guest);
|
||||
|
||||
/**
|
||||
* Template method that updates all guests using the above functions.
|
||||
*/
|
||||
protected final void updateAllGuests() {
|
||||
for (Sheep sheeple : getSheepList()) {
|
||||
updateSheep(sheeple);
|
||||
}
|
||||
|
||||
for (LivingEntity guest : getGuestList()) {
|
||||
updateGuest(guest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule an update to run after a constant period. This drives the party.
|
||||
*/
|
||||
protected final void scheduleUpdate() {
|
||||
updater = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateParty();
|
||||
}
|
||||
};
|
||||
updater.runTaskLater(DiscoSheep.getInstance(), getPeriod());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the event handler to start listening for the party's events, such as sheep damage.
|
||||
*/
|
||||
protected abstract void startListening();
|
||||
|
||||
/**
|
||||
* Unregister the event handler
|
||||
*/
|
||||
protected abstract void stopListening();
|
||||
|
||||
/**
|
||||
* Plays the sound for a party.
|
||||
*/
|
||||
protected abstract void playSounds();
|
||||
|
||||
/**
|
||||
* Template method that performs one update on the entire party.
|
||||
*/
|
||||
protected final void updateParty() {
|
||||
if (!isExpired()) {
|
||||
updateAllGuests();
|
||||
playSounds();
|
||||
scheduleUpdate();
|
||||
updateState();
|
||||
} else {
|
||||
stopDisco();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize things and start a BasicDiscoParty.
|
||||
*/
|
||||
public final void startDisco() {
|
||||
spawnAll();
|
||||
updateParty();
|
||||
DiscoSheep.getInstance().addParty(getPlayer().getName(), this);
|
||||
startListening();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a BasicDiscoParty. Can be called more than once.
|
||||
*/
|
||||
public final void stopDisco() {
|
||||
removeAll();
|
||||
if (updater != null) {
|
||||
updater.cancel();
|
||||
}
|
||||
updater = null;
|
||||
DiscoSheep.getInstance().removeParty(getPlayer().getName());
|
||||
stopListening();
|
||||
}
|
||||
}
|
45
src/me/cwang/discosheep/BabyParty.java
Normal file
45
src/me/cwang/discosheep/BabyParty.java
Normal file
@ -0,0 +1,45 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import org.bukkit.entity.Ageable;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Sheep;
|
||||
|
||||
/**
|
||||
* Created by Charlie on 2015-08-17.
|
||||
*/
|
||||
public class BabyParty extends DiscoDecorator {
|
||||
private int guestBabyCount;
|
||||
private int sheepBabyCount;
|
||||
|
||||
public BabyParty(AbstractParty p, int babyness) {
|
||||
super(p);
|
||||
sheepBabyCount = (int) ((babyness / 100.0d) * getSheep());
|
||||
int totalGuests = 0;
|
||||
for (int i : getGuestMap().values()) {
|
||||
totalGuests += i;
|
||||
}
|
||||
guestBabyCount = (int) ((babyness / 100.0d) * totalGuests);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entity spawnGuest(EntityType type) {
|
||||
Entity guest = super.spawnGuest(type);
|
||||
if (guest instanceof Ageable && guestBabyCount > 0) {
|
||||
Ageable baby = (Ageable) guest;
|
||||
baby.setBaby();
|
||||
--guestBabyCount;
|
||||
}
|
||||
return guest;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheep spawnSheep() {
|
||||
Sheep sheep = super.spawnSheep();
|
||||
if (sheepBabyCount > 0) {
|
||||
sheep.setBaby();
|
||||
--sheepBabyCount;
|
||||
}
|
||||
return sheep;
|
||||
}
|
||||
}
|
236
src/me/cwang/discosheep/BasicDiscoParty.java
Normal file
236
src/me/cwang/discosheep/BasicDiscoParty.java
Normal file
@ -0,0 +1,236 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
public class BasicDiscoParty extends AbstractParty {
|
||||
|
||||
protected final DiscoSheep plugin;
|
||||
protected final Player player;
|
||||
// Instance properties
|
||||
private Random r;
|
||||
private ArrayList<Sheep> sheepList;
|
||||
private ArrayList<LivingEntity> guestList;
|
||||
private HashMap<EntityType, Integer> guestNumbers;
|
||||
private int duration;
|
||||
private final int radius;
|
||||
private final int period;
|
||||
private final int sheep;
|
||||
private final Location partyLocation;
|
||||
private PartyEvents partyEvents;
|
||||
private int state = 0; // basically our own tick system
|
||||
private final float volumeMultiplier;
|
||||
|
||||
public BasicDiscoParty(Player player, int duration, int radius, int period, int sheep, HashMap<EntityType, Integer> guestNumbers) {
|
||||
super();
|
||||
this.plugin = DiscoSheep.getInstance();
|
||||
this.player = player;
|
||||
this.duration = duration;
|
||||
this.radius = radius;
|
||||
this.period = period;
|
||||
this.sheep = sheep;
|
||||
this.guestNumbers = guestNumbers;
|
||||
this.sheepList = new ArrayList<Sheep>();
|
||||
this.r = new Random();
|
||||
this.guestList = new ArrayList<LivingEntity>();
|
||||
this.partyLocation = player.getLocation();
|
||||
this.volumeMultiplier = 2.0f * Math.max(this.radius / 10, 1.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an entity jump (add some y velocity)
|
||||
*
|
||||
* @param entity
|
||||
*/
|
||||
@Override
|
||||
protected void jump(Entity entity) {
|
||||
Vector orgVel = entity.getVelocity();
|
||||
Vector newVel = (new Vector()).copy(orgVel);
|
||||
newVel.add(new Vector(0, defaultSheepJump, 0));
|
||||
entity.setVelocity(newVel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSheep() {
|
||||
return sheep;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Sheep> getSheepList() {
|
||||
return sheepList;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<LivingEntity> getGuestList() {
|
||||
return guestList;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HashMap<EntityType, Integer> getGuestMap() {
|
||||
return guestNumbers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateGuest(LivingEntity guest) {
|
||||
if (state % 2 == 0 && r.nextDouble() < 0.5) {
|
||||
jump(guest);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateSheep(Sheep sheep) {
|
||||
randomizeSheepColour(sheep);
|
||||
if (state % 2 == 0 && r.nextDouble() < 0.5) {
|
||||
jump(sheep);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateState() {
|
||||
duration -= period;
|
||||
state = state > 10000 ? 1 : state + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isExpired() {
|
||||
return (duration <= 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPeriod() {
|
||||
return period;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getVolumeMultiplier() {
|
||||
return volumeMultiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Location getLocation() {
|
||||
return partyLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheep spawnSheep() {
|
||||
World world = partyLocation.getWorld();
|
||||
Location loc = getRandomSpawnLocation(partyLocation.getBlockX(), player.getLocation().getBlockY(), partyLocation.getBlockZ(), world, radius);
|
||||
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);
|
||||
newSheep.setRemoveWhenFarAway(false);
|
||||
newSheep.setMetadata(DiscoSheep.METADATA_KEY, new FixedMetadataValue(plugin, true));
|
||||
return newSheep;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entity spawnGuest(EntityType type) {
|
||||
World world = partyLocation.getWorld();
|
||||
Location loc = getRandomSpawnLocation(partyLocation.getBlockX(), player.getLocation().getBlockY(), partyLocation.getBlockZ(), world, radius);
|
||||
LivingEntity newGuest = (LivingEntity) world.spawnEntity(loc, type);
|
||||
getGuestList().add(newGuest);
|
||||
newGuest.setRemoveWhenFarAway(false);
|
||||
newGuest.setMetadata(DiscoSheep.METADATA_KEY, new FixedMetadataValue(plugin, true));
|
||||
newGuest.setCanPickupItems(false);
|
||||
return newGuest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the static default settings. Takes the values from the current instance
|
||||
* and sets them as the defaults for all parties.
|
||||
*/
|
||||
@Override
|
||||
public void setDefaultsFromCurrent() {
|
||||
AbstractParty.defaultDuration = this.duration;
|
||||
AbstractParty.defaultPeriod = this.period;
|
||||
AbstractParty.defaultRadius = this.radius;
|
||||
AbstractParty.defaultSheep = this.sheep;
|
||||
AbstractParty.defaultGuestNumbers = new HashMap<EntityType, Integer>(getGuestMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a random Location within a radius around (x, y, z)
|
||||
* where y is the player's current height.
|
||||
*
|
||||
* @param x party center
|
||||
* @param z party center
|
||||
* @param world
|
||||
* @param radius
|
||||
* @return
|
||||
*/
|
||||
public Location getRandomSpawnLocation(double x, double y, double z, World world, int radius) {
|
||||
Location loc;
|
||||
|
||||
/* 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()) * radius;
|
||||
double azimuth = r.nextDouble() * 2 * Math.PI; // radians
|
||||
x += rand * Math.cos(azimuth);
|
||||
z += rand * Math.sin(azimuth);
|
||||
|
||||
loc = new Location(world, x, y, z);
|
||||
loc.setPitch(r.nextFloat() * 360 - 180);
|
||||
loc.setYaw(0);
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a random colour for a sheep
|
||||
*
|
||||
* @param sheep
|
||||
*/
|
||||
protected void randomizeSheepColour(Sheep sheep) {
|
||||
sheep.setColor(discoColours[(r.nextInt(discoColours.length))]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Play sounds at the party's starting location.
|
||||
* These sounds are global and will play for all players.
|
||||
*/
|
||||
@Override
|
||||
protected void playSounds() {
|
||||
partyLocation.getWorld().playSound(partyLocation, Sound.NOTE_BASS_DRUM, volumeMultiplier * 0.75f, 1.0f);
|
||||
if (this.state % 2 == 0) {
|
||||
partyLocation.getWorld().playSound(partyLocation, Sound.NOTE_SNARE_DRUM, volumeMultiplier * 0.8f, 1.0f);
|
||||
}
|
||||
|
||||
if ((this.state + 1) % 8 == 0) {
|
||||
partyLocation.getWorld().playSound(partyLocation, Sound.NOTE_STICKS, volumeMultiplier * 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startListening() {
|
||||
// start listening
|
||||
partyEvents = new PartyEvents(this);
|
||||
plugin.getServer().getPluginManager().registerEvents(this.partyEvents, this.plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopListening() {
|
||||
HandlerList.unregisterAll(this.partyEvents);
|
||||
}
|
||||
}
|
156
src/me/cwang/discosheep/DiscoCommands.java
Normal file
156
src/me/cwang/discosheep/DiscoCommands.java
Normal file
@ -0,0 +1,156 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import gnu.getopt.Getopt;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class DiscoCommands implements CommandExecutor {
|
||||
|
||||
private DiscoSheep plugin;
|
||||
|
||||
public DiscoCommands() {
|
||||
this.plugin = DiscoSheep.getInstance();
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
if (sender instanceof Player) {
|
||||
player = (Player) sender;
|
||||
isPlayer = true;
|
||||
} // check isPlayer before "stop" and "me" commands
|
||||
|
||||
// no-arg subcommands
|
||||
if (args.length == 1) {
|
||||
if (args[0].equalsIgnoreCase("stopall")) {
|
||||
return plugin.stopAllCommand(sender);
|
||||
} else if (args[0].equalsIgnoreCase("stop") && isPlayer) {
|
||||
return plugin.stopMeCommand(sender);
|
||||
} else if (args[0].equalsIgnoreCase("help")) {
|
||||
return plugin.helpCommand(sender);
|
||||
} else if (args[0].equalsIgnoreCase("reload")) {
|
||||
return plugin.reloadCommand(sender);
|
||||
} else if (args[0].equalsIgnoreCase("save") || args[0].equalsIgnoreCase("saveconfig")) {
|
||||
return plugin.saveConfigCommand(sender);
|
||||
} else if (args[0].equalsIgnoreCase("togglejoin")) {
|
||||
return plugin.togglePartyOnJoinCommand(sender);
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
return plugin.helpCommand(sender);
|
||||
}
|
||||
|
||||
PartyBuilder builder = new PartyBuilder(player);
|
||||
// ctor takes "program name" as first arg so we pass the sub-command as that
|
||||
// args then start at args[1] so we slice args[1:]
|
||||
Getopt g = new Getopt(args[0], Arrays.copyOfRange(args, 1, args.length), "n:t:p:r:g:lfjPb:");
|
||||
g.setOpterr(false); // do own error handling
|
||||
int c;
|
||||
while ((c = g.getopt()) != -1) {
|
||||
try {
|
||||
switch (c) {
|
||||
case 'n':
|
||||
builder.sheep(Integer.parseInt(g.getOptarg()));
|
||||
break;
|
||||
case 't':
|
||||
builder.duration(DiscoSheep.toTicks(Integer.parseInt(g.getOptarg())));
|
||||
break;
|
||||
case 'p':
|
||||
builder.period(Integer.parseInt(g.getOptarg()));
|
||||
break;
|
||||
case 'r':
|
||||
try {
|
||||
int radius = Integer.parseInt(g.getOptarg());
|
||||
builder.radius(radius);
|
||||
} catch (NumberFormatException e) {
|
||||
if (g.getOptarg().equals("dense")) {
|
||||
builder.dense();
|
||||
} else throw e;
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
String monsters = g.getOptarg();
|
||||
if ("none".equals(monsters)) {
|
||||
builder.noGuests();
|
||||
} else if (sender.hasPermission((DiscoSheep.PERMISSION_SPAWNGUESTS))) {
|
||||
StringTokenizer tokens = new StringTokenizer(monsters,",");
|
||||
while(tokens.hasMoreTokens()) {
|
||||
try {
|
||||
String[] pair = tokens.nextToken().split(":");
|
||||
builder.guests(pair[0], Integer.parseInt(pair[1]));
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
throw new IllegalArgumentException("a valid list of guest:number pairs was not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
builder.fireworks();
|
||||
break;
|
||||
case 'l':
|
||||
if (sender.hasPermission(DiscoSheep.PERMISSION_LIGHTNING))
|
||||
builder.lightning();
|
||||
break;
|
||||
case 'j':
|
||||
builder.jeb();
|
||||
break;
|
||||
case 'P':
|
||||
builder.pentatonic();
|
||||
break;
|
||||
case 'b':
|
||||
builder.baby(Integer.parseInt(g.getOptarg()));
|
||||
break;
|
||||
case '?': // handle invalid switch
|
||||
// need to cast getOptopt() to char because it returns a string representation of an integer
|
||||
sender.sendMessage(String.format("Invalid switch '%s' was found", (char)g.getOptopt()));
|
||||
return false;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
String badNumber = e.getMessage().replace("For input string: ", "");
|
||||
sender.sendMessage(String.format("Error: %s is not a valid number", badNumber));
|
||||
return false;
|
||||
} catch (IllegalArgumentException e) { // handle invalid arguments
|
||||
sender.sendMessage("Bad command: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length > 0) {
|
||||
if (args[0].equalsIgnoreCase("all")) {
|
||||
return plugin.partyAllCommand(sender, builder);
|
||||
} else if (args[0].equalsIgnoreCase("me") && isPlayer) {
|
||||
return plugin.partyCommand(player, builder);
|
||||
} else if (args[0].equalsIgnoreCase("other")) {
|
||||
return plugin.partyOtherCommand(getNextArgs(args, 1), sender, builder);
|
||||
} else if (args[0].equalsIgnoreCase("defaults")) {
|
||||
return plugin.setDefaultsCommand(sender, builder);
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.RED + "Invalid argument (certain commands do not work from console).");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
109
src/me/cwang/discosheep/DiscoDecorator.java
Normal file
109
src/me/cwang/discosheep/DiscoDecorator.java
Normal file
@ -0,0 +1,109 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Charlie on 2015-08-13.
|
||||
*/
|
||||
public class DiscoDecorator extends AbstractParty {
|
||||
protected final AbstractParty decoratedParty;
|
||||
|
||||
public DiscoDecorator(AbstractParty p) {
|
||||
decoratedParty = p;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Player getPlayer() {
|
||||
return decoratedParty.getPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void jump(Entity entity) {
|
||||
decoratedParty.jump(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSheep() {
|
||||
return decoratedParty.getSheep();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Sheep> getSheepList() {
|
||||
return decoratedParty.getSheepList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<LivingEntity> getGuestList() {
|
||||
return decoratedParty.getGuestList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HashMap<EntityType, Integer> getGuestMap() {
|
||||
return decoratedParty.getGuestMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPeriod() { return decoratedParty.getPeriod(); }
|
||||
|
||||
@Override
|
||||
protected int getState() { return decoratedParty.getState(); }
|
||||
|
||||
@Override
|
||||
protected float getVolumeMultiplier() { return decoratedParty.getVolumeMultiplier(); }
|
||||
|
||||
@Override
|
||||
protected Location getLocation() {
|
||||
return decoratedParty.getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheep spawnSheep() {
|
||||
return decoratedParty.spawnSheep();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isExpired() {
|
||||
return decoratedParty.isExpired();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entity spawnGuest(EntityType type) {
|
||||
return decoratedParty.spawnGuest(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setDefaultsFromCurrent() {
|
||||
decoratedParty.setDefaultsFromCurrent();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateState() { decoratedParty.updateState(); }
|
||||
|
||||
@Override
|
||||
protected void updateSheep(Sheep sheep) {
|
||||
decoratedParty.updateSheep(sheep);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateGuest(LivingEntity guest) {
|
||||
decoratedParty.updateGuest(guest);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startListening() {
|
||||
decoratedParty.startListening();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopListening() { decoratedParty.stopListening(); }
|
||||
|
||||
@Override
|
||||
protected void playSounds() {
|
||||
decoratedParty.playSounds();
|
||||
}
|
||||
}
|
349
src/me/cwang/discosheep/DiscoSheep.java
Normal file
349
src/me/cwang/discosheep/DiscoSheep.java
Normal file
@ -0,0 +1,349 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
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 final String METADATA_KEY = "discosheep123u1ohads";
|
||||
static final HashSet<EntityType> VALID_GUESTS = new HashSet<>(Arrays.asList( // list of valid guests
|
||||
EntityType.BAT,
|
||||
EntityType.BLAZE,
|
||||
EntityType.CAVE_SPIDER,
|
||||
EntityType.CHICKEN,
|
||||
EntityType.COW,
|
||||
EntityType.CREEPER,
|
||||
EntityType.ENDERMAN,
|
||||
EntityType.ENDERMITE,
|
||||
EntityType.GHAST,
|
||||
EntityType.GIANT,
|
||||
EntityType.IRON_GOLEM,
|
||||
EntityType.HORSE,
|
||||
EntityType.MAGMA_CUBE,
|
||||
EntityType.MUSHROOM_COW,
|
||||
EntityType.OCELOT,
|
||||
EntityType.PIG_ZOMBIE,
|
||||
EntityType.RABBIT,
|
||||
EntityType.SKELETON,
|
||||
EntityType.SLIME,
|
||||
EntityType.SPIDER,
|
||||
EntityType.SQUID,
|
||||
EntityType.VILLAGER,
|
||||
EntityType.WOLF,
|
||||
EntityType.ZOMBIE
|
||||
));
|
||||
static boolean partyOnJoin = true;
|
||||
Map<String, AbstractParty> parties = new HashMap<>();
|
||||
static DiscoSheep instance = null;
|
||||
|
||||
public static DiscoSheep getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new DiscoSheep();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
DiscoSheep.instance = this;
|
||||
getCommand("ds").setExecutor(new DiscoCommands());
|
||||
getServer().getPluginManager().registerEvents(new GlobalEvents(this), this);
|
||||
|
||||
getConfig().addDefault("on-join.enabled", partyOnJoin);
|
||||
getConfig().addDefault("max.sheep", BasicDiscoParty.maxSheep);
|
||||
getConfig().addDefault("max.radius", BasicDiscoParty.maxRadius);
|
||||
getConfig().addDefault("max.duration", toSeconds_i(BasicDiscoParty.maxDuration));
|
||||
getConfig().addDefault("max.period-ticks", BasicDiscoParty.maxPeriod);
|
||||
getConfig().addDefault("min.period-ticks", BasicDiscoParty.minPeriod);
|
||||
getConfig().addDefault("default.sheep", BasicDiscoParty.defaultSheep);
|
||||
getConfig().addDefault("default.radius", BasicDiscoParty.defaultRadius);
|
||||
getConfig().addDefault("default.duration", toSeconds_i(BasicDiscoParty.defaultDuration));
|
||||
getConfig().addDefault("default.period-ticks", BasicDiscoParty.defaultPeriod);
|
||||
|
||||
/*
|
||||
* Iterate through all live entities and create default configuration values for them
|
||||
*/
|
||||
for (EntityType ent : EntityType.values()) {
|
||||
if (VALID_GUESTS.contains(ent)) {
|
||||
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");
|
||||
BasicDiscoParty.maxSheep = getConfig().getInt("max.sheep");
|
||||
BasicDiscoParty.maxRadius = getConfig().getInt("max.radius");
|
||||
BasicDiscoParty.maxDuration = toTicks(getConfig().getInt("max.duration"));
|
||||
BasicDiscoParty.maxPeriod = getConfig().getInt("max.period-ticks");
|
||||
BasicDiscoParty.minPeriod = getConfig().getInt("min.period-ticks");
|
||||
BasicDiscoParty.defaultSheep = getConfig().getInt("default.sheep");
|
||||
BasicDiscoParty.defaultRadius = getConfig().getInt("default.radius");
|
||||
BasicDiscoParty.defaultDuration = toTicks(getConfig().getInt("default.duration"));
|
||||
BasicDiscoParty.defaultPeriod = getConfig().getInt("default.period-ticks");
|
||||
|
||||
|
||||
// TODO: Catch IllegalArgumentException thrown by valueOf
|
||||
for (String key : getConfig().getConfigurationSection("default.guests").getKeys(false)) {
|
||||
AbstractParty.getDefaultGuestNumbers().put(EntityType.valueOf(key), getConfig().getInt("default.guests." + key));
|
||||
}
|
||||
|
||||
for (String key : getConfig().getConfigurationSection("max.guests").getKeys(false)) {
|
||||
AbstractParty.getMaxGuestNumbers().put(EntityType.valueOf(key), getConfig().getInt("max.guests." + key));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void reloadConfigFromDisk() {
|
||||
reloadConfig();
|
||||
loadConfigFromDisk();
|
||||
}
|
||||
|
||||
void saveConfigToDisk() {
|
||||
getConfig().set("on-join.enabled", partyOnJoin);
|
||||
getConfig().set("default.sheep", BasicDiscoParty.defaultSheep);
|
||||
getConfig().set("default.radius", BasicDiscoParty.defaultRadius);
|
||||
getConfig().set("default.duration", toSeconds_i(BasicDiscoParty.defaultDuration));
|
||||
getConfig().set("default.period-ticks", BasicDiscoParty.defaultPeriod);
|
||||
|
||||
for (Map.Entry<EntityType, Integer> entry : BasicDiscoParty.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 void addParty(String player, AbstractParty party) {
|
||||
parties.put(player, party);
|
||||
}
|
||||
|
||||
public synchronized ArrayList<AbstractParty> getParties() {
|
||||
return new ArrayList<>(parties.values());
|
||||
}
|
||||
|
||||
public void stopParty(String name) {
|
||||
if (this.hasParty(name)) {
|
||||
this.getParty(name).stopDisco();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopAllParties() {
|
||||
for (AbstractParty p : getParties()) {
|
||||
p.stopDisco();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasParty(String name) { return parties.containsKey(name); }
|
||||
|
||||
public AbstractParty getParty(String name) { return parties.get(name); }
|
||||
|
||||
public void removeParty(String name) {
|
||||
if (this.hasParty(name)) {
|
||||
parties.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 <players>: 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 <integer>: set the number of sheep per player that spawn\n"
|
||||
+ "-t <integer>: set the party duration in seconds\n"
|
||||
+ "-p <ticks>: set the number of ticks between each disco beat\n"
|
||||
+ "-r <integer>: set radius of the area in which sheep can spawn\n"
|
||||
+ "-g <mob:integer, mob:integer...>: set spawns for other mobs, eg. -g cow:5,pig:2\n"
|
||||
+ "-l: enables lightning\n"
|
||||
+ "-f: enables fireworks\n"
|
||||
+ "-j: enables alternative method for setting sheep colours\n"
|
||||
+ "-b <integer>: spawns a percentage of mobs as babies, if possible\n"
|
||||
+ "-P: enables pentatonic backing track\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean stopMeCommand(CommandSender sender) {
|
||||
stopParty(sender.getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean stopAllCommand(CommandSender sender) {
|
||||
return checkPermissionsAndRun(new PermissibleCommand() {
|
||||
@Override
|
||||
public boolean run(CommandSender sender) {
|
||||
stopAllParties();
|
||||
return true;
|
||||
}
|
||||
}, sender, PERMISSION_STOPALL);
|
||||
}
|
||||
|
||||
boolean partyCommand(Player player, final PartyBuilder builder) {
|
||||
return checkPermissionsAndRun(new PermissibleCommand() {
|
||||
@Override
|
||||
public boolean run(CommandSender s) {
|
||||
if (!hasParty(s.getName())) {
|
||||
builder.build().startDisco();
|
||||
} else {
|
||||
s.sendMessage(ChatColor.RED + "You already have a party.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} , player, PERMISSION_PARTY);
|
||||
}
|
||||
|
||||
boolean reloadCommand(CommandSender sender) {
|
||||
return checkPermissionsAndRun(new PermissibleCommand() {
|
||||
@Override
|
||||
public boolean run(CommandSender s) {
|
||||
reloadConfigFromDisk();
|
||||
s.sendMessage(ChatColor.GREEN + "DiscoSheep config reloaded from disk");
|
||||
return true;
|
||||
}
|
||||
}, sender, PERMISSION_RELOAD);
|
||||
}
|
||||
|
||||
boolean partyOtherCommand(final String[] players, CommandSender sender, final PartyBuilder builder) {
|
||||
return checkPermissionsAndRun(new PermissibleCommand() {
|
||||
@Override
|
||||
public boolean run(CommandSender s) {
|
||||
Player p;
|
||||
for (String playerName : players) {
|
||||
p = Bukkit.getServer().getPlayer(playerName);
|
||||
if (p != null) {
|
||||
if (!hasParty(p.getName())) {
|
||||
builder.buildOther(p).startDisco();
|
||||
}
|
||||
} else {
|
||||
s.sendMessage("Invalid player: " + playerName);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, sender, PERMISSION_OTHER);
|
||||
}
|
||||
|
||||
boolean partyAllCommand(CommandSender sender, final PartyBuilder builder) {
|
||||
return checkPermissionsAndRun(new PermissibleCommand() {
|
||||
@Override
|
||||
public boolean run(CommandSender s) {
|
||||
for (Player p : Bukkit.getServer().getOnlinePlayers()) {
|
||||
if (!hasParty(p.getName())) {
|
||||
builder.buildOther(p).startDisco();
|
||||
p.sendMessage(ChatColor.RED + "LET'S DISCO!!");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} , sender, PERMISSION_ALL);
|
||||
}
|
||||
|
||||
void partyOnJoin(Player player) {
|
||||
if (!partyOnJoin) {
|
||||
return;
|
||||
}
|
||||
if (player.hasPermission(PERMISSION_ONJOIN)) {
|
||||
PartyBuilder builder = new PartyBuilder(player);
|
||||
builder.build().startDisco();
|
||||
}
|
||||
}
|
||||
|
||||
boolean togglePartyOnJoinCommand(CommandSender sender) {
|
||||
return checkPermissionsAndRun(new PermissibleCommand() {
|
||||
@Override
|
||||
public boolean run(CommandSender s) {
|
||||
partyOnJoin = !partyOnJoin;
|
||||
if (partyOnJoin) {
|
||||
s.sendMessage(ChatColor.GREEN + "DiscoSheep party on join functionality enabled.");
|
||||
} else {
|
||||
s.sendMessage(ChatColor.GREEN + "DiscoSheep party on join functionality disabled.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, sender, PERMISSION_TOGGLEPARTYONJOIN);
|
||||
}
|
||||
|
||||
boolean setDefaultsCommand(CommandSender sender, final PartyBuilder builder) {
|
||||
return checkPermissionsAndRun(new PermissibleCommand() {
|
||||
@Override
|
||||
public boolean run(CommandSender s) {
|
||||
builder.build().setDefaultsFromCurrent();
|
||||
s.sendMessage(ChatColor.GREEN + "DiscoSheep configured with new defaults (not yet saved to disk)");
|
||||
return true;
|
||||
}
|
||||
}, sender, PERMISSION_CHANGEDEFAULTS);
|
||||
}
|
||||
|
||||
boolean saveConfigCommand(CommandSender sender) {
|
||||
return checkPermissionsAndRun(new PermissibleCommand() {
|
||||
@Override
|
||||
public boolean run(CommandSender s) {
|
||||
saveConfigToDisk();
|
||||
s.sendMessage(ChatColor.GREEN + "DiscoSheep config saved to disk");
|
||||
return true;
|
||||
}
|
||||
}, sender, PERMISSION_SAVECONFIG);
|
||||
}
|
||||
|
||||
public interface PermissibleCommand {
|
||||
boolean run(CommandSender sender);
|
||||
}
|
||||
|
||||
public boolean checkPermissionsAndRun(PermissibleCommand command, CommandSender sender, String permission) {
|
||||
if (sender.hasPermission(permission)) {
|
||||
return command.run(sender);
|
||||
} else {
|
||||
noPermsMessage(sender, permission);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void noPermsMessage(CommandSender sender, String permission) {
|
||||
sender.sendMessage(ChatColor.RED + "You do not have the permission node " + ChatColor.GRAY + permission);
|
||||
}
|
||||
}
|
61
src/me/cwang/discosheep/FireworkParty.java
Normal file
61
src/me/cwang/discosheep/FireworkParty.java
Normal file
@ -0,0 +1,61 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.FireworkEffect;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Firework;
|
||||
import org.bukkit.entity.Sheep;
|
||||
import org.bukkit.inventory.meta.FireworkMeta;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Charlie on 2015-08-17.
|
||||
*/
|
||||
public class FireworkParty extends DiscoDecorator {
|
||||
Random r;
|
||||
|
||||
public FireworkParty(AbstractParty p) {
|
||||
super(p);
|
||||
r = new Random();
|
||||
}
|
||||
|
||||
|
||||
private void randomizeFirework(Firework firework) {
|
||||
FireworkEffect.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);
|
||||
}
|
||||
|
||||
private void spawnRandomFireworkAtSheep(Sheep sheep) {
|
||||
Firework firework = (Firework) sheep.getWorld().spawnEntity(sheep.getEyeLocation(), EntityType.FIREWORK);
|
||||
randomizeFirework(firework);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateSheep(Sheep sheep) {
|
||||
super.updateSheep(sheep);
|
||||
if (getState() % 8 == 0 && r.nextDouble() < 0.5) {
|
||||
spawnRandomFireworkAtSheep(sheep);
|
||||
}
|
||||
}
|
||||
}
|
35
src/me/cwang/discosheep/GlobalEvents.java
Normal file
35
src/me/cwang/discosheep/GlobalEvents.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* BaaBaaBlockSheep have you any wool?
|
||||
* Nope, event got cancelled.
|
||||
* Also listens to other events, not just sheep events
|
||||
*/
|
||||
package me.cwang.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);
|
||||
}
|
||||
}
|
26
src/me/cwang/discosheep/JebParty.java
Normal file
26
src/me/cwang/discosheep/JebParty.java
Normal file
@ -0,0 +1,26 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import org.bukkit.entity.Sheep;
|
||||
|
||||
/**
|
||||
* Created by Charlie on 2015-08-16.
|
||||
* This DiscoParty toggles sheep colours by setting names to jeb_
|
||||
*/
|
||||
public class JebParty extends DiscoDecorator {
|
||||
public JebParty(AbstractParty p) {
|
||||
super(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a sheep and sets its name to "jeb_", using the easter egg to change colours
|
||||
* This feature has been around for long enough so it should be safe to use.
|
||||
* @return The sheep that was spawned
|
||||
*/
|
||||
@Override
|
||||
protected Sheep spawnSheep() {
|
||||
Sheep sheep = super.spawnSheep();
|
||||
sheep.setCustomName("jeb_");
|
||||
sheep.setCustomNameVisible(false);
|
||||
return sheep;
|
||||
}
|
||||
}
|
61
src/me/cwang/discosheep/LightningParty.java
Normal file
61
src/me/cwang/discosheep/LightningParty.java
Normal file
@ -0,0 +1,61 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Sheep;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Charlie on 2015-08-13.
|
||||
*/
|
||||
public class LightningParty extends DiscoDecorator {
|
||||
private int count; // maximum number of lightning strikes
|
||||
|
||||
public LightningParty(AbstractParty p) {
|
||||
super(p);
|
||||
count = super.getSheep() / 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strike a certain percentage of the spawned sheep with lightning effects.
|
||||
* The lightning effects should be purely visual, ie. not set anything on fire.
|
||||
* @return The sheep that was spawned.
|
||||
*/
|
||||
@Override
|
||||
protected Sheep spawnSheep() {
|
||||
Sheep sheep = super.spawnSheep();
|
||||
if (count > 0) {
|
||||
--count;
|
||||
sheep.getWorld().strikeLightningEffect(sheep.getLocation());
|
||||
}
|
||||
return sheep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strike all the non-sheep guests with lightning effects.
|
||||
* The lightning effects hsould be purely visual ie. not set anything on fire.
|
||||
* @param type The type of entity to spawn.
|
||||
* @return The spawned entity.
|
||||
*/
|
||||
@Override
|
||||
protected Entity spawnGuest(EntityType type) {
|
||||
Entity guest = super.spawnGuest(type);
|
||||
guest.getWorld().strikeLightningEffect(guest.getLocation());
|
||||
return guest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strike sheep with lightning 0.05% of the time.
|
||||
*/
|
||||
@Override
|
||||
protected void updateSheep(Sheep sheep) {
|
||||
super.updateSheep(sheep);
|
||||
Random r = new Random();
|
||||
if (r.nextDouble() < 0.005) {
|
||||
sheep.getWorld().strikeLightningEffect(sheep.getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
143
src/me/cwang/discosheep/PartyBuilder.java
Normal file
143
src/me/cwang/discosheep/PartyBuilder.java
Normal file
@ -0,0 +1,143 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Created by Charlie on 2015-08-15.
|
||||
*/
|
||||
public class PartyBuilder {
|
||||
// required
|
||||
protected Player player;
|
||||
// optional
|
||||
private int duration = AbstractParty.defaultDuration;
|
||||
private int radius = AbstractParty.defaultRadius;
|
||||
private int period = AbstractParty.defaultPeriod;
|
||||
private int sheep = AbstractParty.defaultSheep;
|
||||
private HashMap<EntityType, Integer> guests = AbstractParty.defaultGuestNumbers;
|
||||
private boolean dense = false;
|
||||
private boolean fireworks = false;
|
||||
private boolean lightning = false;
|
||||
private boolean jeb = false;
|
||||
private boolean pentatonic = false;
|
||||
private int babyness = 0;
|
||||
|
||||
public PartyBuilder(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public PartyBuilder duration(int duration) throws IllegalArgumentException {
|
||||
if (duration < 0 || duration > AbstractParty.maxDuration) {
|
||||
throw new IllegalArgumentException("nvalid duration");
|
||||
}
|
||||
this.duration = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartyBuilder radius(int radius) throws IllegalArgumentException {
|
||||
if (radius < 0 || radius > AbstractParty.maxRadius) {
|
||||
throw new IllegalArgumentException("Invalid radius");
|
||||
}
|
||||
this.radius = radius;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartyBuilder dense() {
|
||||
this.dense = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartyBuilder period(int period) throws IllegalArgumentException {
|
||||
if (period < 0 || period > AbstractParty.maxPeriod) {
|
||||
throw new IllegalArgumentException("invalid period");
|
||||
}
|
||||
this.period = period;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartyBuilder sheep(int sheep) throws IllegalArgumentException {
|
||||
if (sheep < 0 || sheep > AbstractParty.maxSheep) {
|
||||
throw new IllegalArgumentException("invalid sheep number");
|
||||
}
|
||||
this.sheep = sheep;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartyBuilder guests(String key, int n) throws IllegalArgumentException {
|
||||
key = key.toUpperCase();
|
||||
EntityType type = EntityType.UNKNOWN;
|
||||
try {
|
||||
type = EntityType.valueOf(key);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(String.format("invalid guest %s", key));
|
||||
}
|
||||
if (guests.containsKey(type)) {
|
||||
if (n <= AbstractParty.getMaxGuestNumbers().get(type) && n >= 0) { // so that /ds defaults can take 0 as arg
|
||||
guests.put(type, n);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(String.format("invalid number for %s", key));
|
||||
}
|
||||
|
||||
public PartyBuilder noGuests() {
|
||||
guests.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartyBuilder fireworks() {
|
||||
fireworks = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartyBuilder jeb() {
|
||||
jeb = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PartyBuilder lightning() {
|
||||
lightning = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AbstractParty build() {
|
||||
if (dense) {
|
||||
int denseRadius = (int) Math.floor(Math.sqrt(sheep / Math.PI));
|
||||
if (denseRadius > AbstractParty.maxRadius) {
|
||||
denseRadius = AbstractParty.maxRadius;
|
||||
}
|
||||
if (denseRadius < 1) {
|
||||
denseRadius = 1;
|
||||
}
|
||||
radius = denseRadius;
|
||||
}
|
||||
AbstractParty party = new BasicDiscoParty(player, duration, radius, period, sheep, guests);
|
||||
if (fireworks) party = new FireworkParty(party);
|
||||
if (lightning) party = new LightningParty(party);
|
||||
if (jeb) party = new JebParty(party);
|
||||
if (pentatonic) party = new PentatonicParty(party);
|
||||
if (babyness > 0) party = new BabyParty(party, babyness);
|
||||
|
||||
return party;
|
||||
}
|
||||
|
||||
public void pentatonic() {
|
||||
pentatonic = true;
|
||||
}
|
||||
|
||||
public void baby(int babyness) {
|
||||
this.babyness = babyness;
|
||||
}
|
||||
|
||||
public AbstractParty buildOther(Player newPlayer) {
|
||||
Player oldPlayer = player;
|
||||
player = newPlayer;
|
||||
AbstractParty otherParty = build();
|
||||
player = oldPlayer;
|
||||
return otherParty;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,12 +1,10 @@
|
||||
package ca.gibstick.discosheep;
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import org.bukkit.Instrument;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Sheep;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityPortalEvent;
|
||||
import org.bukkit.event.entity.EntityTargetEvent;
|
||||
@ -14,13 +12,12 @@ 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;
|
||||
BasicDiscoParty party;
|
||||
/*
|
||||
* There will be multiple instances of PartyEvents,
|
||||
* and each instance will only listen for its own party.
|
||||
@ -29,64 +26,77 @@ public class PartyEvents implements Listener {
|
||||
* unregister the listeners when no parties are running.
|
||||
*/
|
||||
|
||||
public PartyEvents(DiscoParty party) {
|
||||
public PartyEvents(BasicDiscoParty party) {
|
||||
this.party = party;
|
||||
}
|
||||
|
||||
// prevent sheep shearing
|
||||
/**
|
||||
* Predicate that returns true if the Entity e is from the given DiscoParty.
|
||||
*
|
||||
* @param e The entity to check
|
||||
* @return True if the Entity is in any DiscoParty
|
||||
*/
|
||||
private boolean isFromParty(Entity e) {
|
||||
return e.hasMetadata(DiscoSheep.METADATA_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler that prevents sheep shearing
|
||||
*
|
||||
* @param e The event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onPlayerShear(PlayerShearEntityEvent e) {
|
||||
if (e.getEntity() instanceof Sheep) {
|
||||
if (party.getSheepSet().contains((Sheep) e.getEntity())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
if (e.getEntity() instanceof Sheep && isFromParty(e.getEntity())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
// actually make sheep and other guests invincible
|
||||
/**
|
||||
* Make all party mobs invincible by cancelling the damage event.
|
||||
* Mobs will instead jump when taking damage.
|
||||
* @param e The damage event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onLivingEntityDamageEvent(EntityDamageEvent e) {
|
||||
if (e.getEntity() instanceof Sheep) {
|
||||
if (party.getSheepSet().contains((Sheep) e.getEntity())) {
|
||||
party.jump(e.getEntity()); // for kicks
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
if (party.getGuestSet().contains(e.getEntity())) {
|
||||
party.jump(e.getEntity());
|
||||
if (isFromParty(e.getEntity())) {
|
||||
party.jump(e.getEntity()); // for kicks
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
// prevent uninvited guests from targetting players
|
||||
/**
|
||||
* Pacify monsters that are part of parties by preventing them from targeting players.
|
||||
* @param e The target event.
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onEntityTargetLivingEntityEvent(EntityTargetEvent e) {
|
||||
if (party.getGuestSet().contains(e.getEntity())) {
|
||||
if (isFromParty(e.getEntity())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
// prevent egg breeding
|
||||
/**
|
||||
* Prevent egg breeding and other shenanigans from party members by disabling all
|
||||
* right click events.
|
||||
* @param e The right click event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onPlayerInteractEntityEvent(PlayerInteractEntityEvent e) {
|
||||
if (party.getSheepSet().contains(e.getRightClicked()) || party.getGuestSet().contains(e.getRightClicked())) {
|
||||
if (isFromParty(e.getRightClicked())) {
|
||||
e.setCancelled(true);
|
||||
e.getPlayer().playSound(e.getRightClicked().getLocation(), Sound.NOTE_BASS_GUITAR, 1.0f, party.getPentatonicNote());
|
||||
}
|
||||
}
|
||||
|
||||
// prevent portal teleport
|
||||
/**
|
||||
* Prevent party members from going through portals (end, nether).
|
||||
* @param e The portal event.
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onEntityPortalEvent(EntityPortalEvent e) {
|
||||
if (party.getSheepSet().contains(e.getEntity()) || party.getGuestSet().contains(e.getEntity())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
// prevent disco floor breaking
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onBlockBreakEvent(BlockBreakEvent e) {
|
||||
if (party.getFloorBlocks().contains(e.getBlock())) {
|
||||
if (isFromParty(e.getEntity())) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
19
src/me/cwang/discosheep/PartyGuests.java
Normal file
19
src/me/cwang/discosheep/PartyGuests.java
Normal file
@ -0,0 +1,19 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import org.bukkit.entity.Creature;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Sheep;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A container class for storing and updating
|
||||
* occupants of a single party.
|
||||
* One AbstractParty will have one PartyGuests
|
||||
*/
|
||||
public abstract class PartyGuests {
|
||||
|
||||
|
||||
}
|
36
src/me/cwang/discosheep/PentatonicParty.java
Normal file
36
src/me/cwang/discosheep/PentatonicParty.java
Normal file
@ -0,0 +1,36 @@
|
||||
package me.cwang.discosheep;
|
||||
|
||||
import org.bukkit.Sound;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Charlie on 2015-08-17.
|
||||
*/
|
||||
public class PentatonicParty extends DiscoDecorator {
|
||||
|
||||
Random r = new Random();
|
||||
|
||||
private static final float[] pentatonicNotes = {
|
||||
1.0f,
|
||||
1.125f,
|
||||
1.25f,
|
||||
1.5f,
|
||||
1.667f,
|
||||
2.0f
|
||||
};
|
||||
|
||||
public PentatonicParty(AbstractParty p) {
|
||||
super(p);
|
||||
}
|
||||
|
||||
float getPentatonicNote() {
|
||||
return pentatonicNotes[r.nextInt(pentatonicNotes.length)];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void playSounds() {
|
||||
super.playSounds();
|
||||
getLocation().getWorld().playSound(getLocation(), Sound.NOTE_PIANO, getVolumeMultiplier() * 1.0f, getPentatonicNote());
|
||||
}
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
name: DiscoSheep
|
||||
main: ca.gibstick.discosheep.DiscoSheep
|
||||
main: me.cwang.discosheep.DiscoSheep
|
||||
authors: [Gibstick, RangerMauve]
|
||||
version: 1.2
|
||||
version: 2.0
|
||||
commands:
|
||||
#ds:
|
||||
#description: "Main DiscoSheep command"
|
||||
#usage: |
|
||||
#<command> <subcommand> [arguments]
|
||||
#Use /ds help for more information
|
||||
#To stop your party, use /ds stop.
|
||||
ds:
|
||||
description: "Main DiscoSheep command"
|
||||
usage: |
|
||||
<command> <subcommand> [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.*:
|
Loading…
Reference in New Issue
Block a user