diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilAlg.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilAlg.java index 40f1147c9..d01556e40 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilAlg.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilAlg.java @@ -152,6 +152,21 @@ public class UtilAlg return list.get(UtilMath.r(list.size())); } + public static T Random(List list, List exclude) + { + int attempts = 0; + T element; + + do + { + element = Random(list); + attempts++; + } + while (element != null && exclude.contains(element) && attempts < 15); + + return element; + } + public static boolean inBoundingBox(Location loc, Location cornerA, Location cornerB) { if (loc.getX() <= Math.min(cornerA.getX(), cornerB.getX())) return false; @@ -515,4 +530,5 @@ public class UtilAlg { return new AxisAlignedBB(a.getX(), a.getY(), a.getZ(), b.getX(), b.getY(), b.getZ()); } + } diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilBlock.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilBlock.java index c0a7f5f3b..3acb09f70 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilBlock.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilBlock.java @@ -1405,6 +1405,9 @@ public class UtilBlock itemStack.setType(Material.DARK_OAK_DOOR_ITEM); itemStack.setDurability((short) 0); break; + case ANVIL: + itemStack.setDurability((short) (itemStack.getDurability() / 4)); + break; } return itemStacks; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java b/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java index 2d92b75aa..1f2dc672d 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java @@ -471,6 +471,13 @@ public class CoreClientManager extends MiniPlugin if (event.getReason().contains("You logged in from another location")) { _duplicateLoginGlitchPreventionList.add(event.getPlayer().getName()); + Bukkit.getScheduler().runTask(_plugin, new Runnable() { + public void run() { + if(!_clientList.containsKey(event.getPlayer().getName())) return; + Player p = _clientList.get(event.getPlayer().getName()).GetPlayer(); + p.kickPlayer("You're already logged in."); + } + }); } } @@ -478,7 +485,7 @@ public class CoreClientManager extends MiniPlugin public void Quit(PlayerQuitEvent event) { // When an account is logged in to this server and the same account name logs in - // Then it Fires events in this order (original, new for accounts) + // Then it Fires events in this order (original, new for acco unts) // AsyncPreLogin -> new // PlayerLogin -> new // PlayerKick -> old diff --git a/Plugins/Mineplex.Core/src/mineplex/core/achievement/Achievement.java b/Plugins/Mineplex.Core/src/mineplex/core/achievement/Achievement.java index d7e71c18e..ab07c5147 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/achievement/Achievement.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/achievement/Achievement.java @@ -854,7 +854,37 @@ public enum Achievement new String[]{"Type Wars.Wins"}, new String[]{"Win 30 Games"}, new int[]{30}, - AchievementCategory.TYPE_WARS); + AchievementCategory.TYPE_WARS), + + SPEED_BUILDERS_SPEED_MASTER("Speed Master", 800, + new String[]{"Speed Builders.Wins"}, + new String[]{"Win 10 Games of Speed Builder"}, + new int[]{10}, + AchievementCategory.SPEED_BUILDERS), + + SPEED_BUILDERS_DEPENDABLE("Dependable", 1200, + new String[]{"Speed Builders.PerfectBuild"}, + new String[]{"Complete 50 Perfect Builds"}, + new int[]{50}, + AchievementCategory.SPEED_BUILDERS), + + SPEED_BUILDERS_FIRST_BUILD("First Build!", 1800, + new String[]{"Speed Builders.PerfectFirst"}, + new String[]{"Be the first person to complete a build in the game 10 times"}, + new int[]{10}, + AchievementCategory.SPEED_BUILDERS), + + SPEED_BUILDERS_PERFECTIONIST("Perfectionist", 2200, + new String[]{"Speed Builders.PerfectWins"}, + new String[]{"Win a game of Speed Builder with a perfect build every round"}, + new int[]{1}, + AchievementCategory.SPEED_BUILDERS), + + SPEED_BUILDERS_SPEEDIEST("Speediest Builderizer", 2000, + new String[]{"Speed Builders.SpeediestBuilderizer"}, + new String[]{"Perfect a build in less than 10 seconds"}, + new int[]{1}, + AchievementCategory.SPEED_BUILDERS); private String _name; private String[] _desc; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/achievement/AchievementCategory.java b/Plugins/Mineplex.Core/src/mineplex/core/achievement/AchievementCategory.java index 4a12d45cb..ca55d520f 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/achievement/AchievementCategory.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/achievement/AchievementCategory.java @@ -2,10 +2,6 @@ package mineplex.core.achievement; import java.util.List; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.entity.Player; - import mineplex.core.account.CoreClientManager; import mineplex.core.common.Rank; import mineplex.core.common.util.C; @@ -14,6 +10,10 @@ import mineplex.core.game.GameDisplay; import mineplex.core.stats.PlayerStats; import mineplex.core.stats.StatsManager; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; + public enum AchievementCategory { GLOBAL("Global", null, @@ -157,7 +157,11 @@ public enum AchievementCategory TYPE_WARS("Type Wars", null, new StatDisplay[] {StatDisplay.WINS, StatDisplay.GAMES_PLAYED, new StatDisplay("Minions killed", "MinionKills"), new StatDisplay("Words Per Minute", false, true, "MinionKills", "TimeInGame"), StatDisplay.GEMS_EARNED}, - Material.NAME_TAG, 0, GameCategory.CLASSICS, null); + Material.NAME_TAG, 0, GameCategory.CLASSICS, null), + + SPEED_BUILDERS("Speed Builders", null, + new StatDisplay[] {StatDisplay.WINS, StatDisplay.GAMES_PLAYED, StatDisplay.GEMS_EARNED, null, new StatDisplay("Perfect Builds", "PerfectBuild")}, + Material.QUARTZ_BLOCK, 0, GameCategory.CLASSICS, null); private String _name; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/achievement/ui/page/AchievementMainPage.java b/Plugins/Mineplex.Core/src/mineplex/core/achievement/ui/page/AchievementMainPage.java index 40ec84525..3817df163 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/achievement/ui/page/AchievementMainPage.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/achievement/ui/page/AchievementMainPage.java @@ -49,7 +49,7 @@ public class AchievementMainPage extends ShopPageBase if (enabled.containsKey(type)) addGlow(deathSlot); type = GadgetType.Item; - lore = getLore(ownedCount.get(type), maxCount.get(type), "All sorts of zaney contraptions to use on your friends and foes.", "Usable in Lobbies", enabled.get(type)); + lore = getLore(ownedCount.get(type), maxCount.get(type), "All sorts of zany contraptions to use on your friends and foes.", "Usable in Lobbies", enabled.get(type)); addButton(gadgetSlot, new ShopItem(Material.MELON_BLOCK, "Gadgets", lore, 1, false), new OpenGadgets(this, enabled.get(type))); if (enabled.containsKey(type)) addGlow(gadgetSlot); type = GadgetType.Morph; - lore = getLore(ownedCount.get(type), maxCount.get(type), "Ever want to be a tiger? Well, you can’t be a tiger! That’s silly! But you can be many other things!", "Usable in Lobbies", enabled.get(type)); + lore = getLore(ownedCount.get(type), maxCount.get(type), "Have you ever wanted to be a tiger? Well, you can't be a tiger! That's silly! But you can be many other things!", "Usable in Lobbies", enabled.get(type)); addButton(morphSlot, new ShopItem(Material.LEATHER, "Morphs", lore, 1, false), new OpenMorphs(this, enabled.get(type))); if (enabled.containsKey(type)) addGlow(morphSlot); diff --git a/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/PetPage.java b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/PetPage.java index 4e796c47e..114b700ce 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/PetPage.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/PetPage.java @@ -193,7 +193,7 @@ public class PetPage extends ShopPageBase } else if (getPlugin().getPetManager().getActivePet(getPlayer().getName()).getType() != EntityType.WITHER) { - addButton(slot, new ShopItem(petExtra.GetMaterial(), (byte) 0, "Rename " + getPlugin().getPetManager().getActivePet(getPlayer().getName()).getCustomName() + " for " + C.cYellow + petExtra.GetCost(CurrencyType.Coins) + C.cGreen + " Coins", itemLore.toArray(new String[itemLore.size()]), 1, false, false), new RenamePetButton(this)); + addButton(slot, new ShopItem(petExtra.GetMaterial(), (byte) 0, "Rename " + getPlugin().getPetManager().getActivePet(getPlayer().getName()).getCustomName() + " for " + C.cYellow + petExtra.GetCost(CurrencyType.Coins) + C.cGreen + " Shards", itemLore.toArray(new String[itemLore.size()]), 1, false, false), new RenamePetButton(this)); } slot++; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/arrowtrail/ArrowTrailCandyCane.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/arrowtrail/ArrowTrailCandyCane.java index ec6b33ba6..d528c4a7c 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/arrowtrail/ArrowTrailCandyCane.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/arrowtrail/ArrowTrailCandyCane.java @@ -20,7 +20,7 @@ public class ArrowTrailCandyCane extends ArrowEffectGadget public ArrowTrailCandyCane(GadgetManager manager) { super(manager, "Candy Cane Arrows", - UtilText.splitLineToArray(C.cGray + "The real reason no one visits the North Pole? Santa’s Elves are deadly shots.", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "The real reason no one visits the North Pole? Santa's Elves are deadly shots.", LineFormat.LORE), -3, Material.INK_SACK, (byte)1); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/arrowtrail/ArrowTrailFrostLord.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/arrowtrail/ArrowTrailFrostLord.java index 171860cd5..3a7c910b5 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/arrowtrail/ArrowTrailFrostLord.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/arrowtrail/ArrowTrailFrostLord.java @@ -18,7 +18,7 @@ public class ArrowTrailFrostLord extends ArrowEffectGadget public ArrowTrailFrostLord(GadgetManager manager) { super(manager, "Arrows of the Frost Lord", - UtilText.splitLineToArray(C.cGray + "The Frost Lord’s arrows bring a blast of winter in the wind of their passing.", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "The Frost Lord's arrows bring a blast of winter in the wind of their passing.", LineFormat.LORE), -3, Material.SNOW_BALL, (byte)0, "Frost Lord"); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/death/DeathCandyCane.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/death/DeathCandyCane.java index a6ccbda55..58bb91a1b 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/death/DeathCandyCane.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/death/DeathCandyCane.java @@ -19,7 +19,7 @@ public class DeathCandyCane extends DeathEffectGadget public DeathCandyCane(GadgetManager manager) { super(manager, "Candy Cane Remains", - UtilText.splitLineToArray(C.cGray + "The biggest enemy of the Holidays, is January.", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "The biggest enemy of the Holidays is January.", LineFormat.LORE), -3, Material.INK_SACK, (byte)1); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatCoal.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatCoal.java index 7897272a8..c83e00ed4 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatCoal.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatCoal.java @@ -15,7 +15,7 @@ public class HatCoal extends HatGadget public HatCoal(GadgetManager manager) { super(manager, "Lump of Coal Hat", - UtilText.splitLineToArray(C.cGray + "When life gives you coal, make a wierd cube hat out it!", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "When life gives you coal, make a weird cube hat out it!", LineFormat.LORE), -1, new ItemStack(Material.COAL_BLOCK)); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatGrinch.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatGrinch.java index 9ef68b04a..747d969d0 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatGrinch.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatGrinch.java @@ -13,7 +13,7 @@ public class HatGrinch extends HatGadget public HatGrinch(GadgetManager manager) { super(manager, "The Grinch", - UtilText.splitLineToArray(C.cGray + "Great! Now where’s the Roast Beast?!", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "Great! Now where's the Roast Beast?!", LineFormat.LORE), -3, SkinData.THE_GRINCH.getSkull(), "The Grinch Hat"); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatPresent.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatPresent.java index e92b2b398..12ccc8db2 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatPresent.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatPresent.java @@ -13,7 +13,7 @@ public class HatPresent extends HatGadget public HatPresent(GadgetManager manager) { super(manager, "Present", - UtilText.splitLineToArray(C.cGray + "WHAT IN THE PRESENT? Oh, it's just you...", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "WHAT'S IN THE PRESENT? Oh, it's just you...", LineFormat.LORE), -3, SkinData.PRESENT.getSkull()); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatRudolph.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatRudolph.java index 1dfd9fa5c..574508d1e 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatRudolph.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/hat/HatRudolph.java @@ -13,7 +13,7 @@ public class HatRudolph extends HatGadget public HatRudolph(GadgetManager manager) { super(manager, "Rudolph", - UtilText.splitLineToArray(C.cGray + "WHAT IN THE PRESENT? Oh, it's just you...", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "HEY YOU! Wanna lead Santa's sleigh team?", LineFormat.LORE), -3, SkinData.RUDOLPH.getSkull()); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/item/ItemCoinBomb.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/item/ItemCoinBomb.java index d0039cd87..1f9f69217 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/item/ItemCoinBomb.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/item/ItemCoinBomb.java @@ -38,7 +38,7 @@ public class ItemCoinBomb extends ItemGadget public ItemCoinBomb(GadgetManager manager) { super(manager, "Treasure Party Bomb", - UtilText.splitLineToArray(C.cWhite + "It's party time! You'll be everyones favourite player when you use one of these!", LineFormat.LORE), + UtilText.splitLineToArray(C.cWhite + "It's party time! You'll be everyone's favourite player when you use one of these!", LineFormat.LORE), -1, Material.PRISMARINE, (byte)0, 30000, new Ammo("Treasure Party Bomb", "1 Coin Party Bomb", Material.PRISMARINE, (byte)0, new String[] { C.cWhite + "1 Treasure Party Bomb" }, 2000, 1)); diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/item/ItemPartyPopper.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/item/ItemPartyPopper.java index 92da2218c..c3ea07224 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/item/ItemPartyPopper.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/item/ItemPartyPopper.java @@ -32,7 +32,7 @@ public class ItemPartyPopper extends ItemGadget implements IThrown public ItemPartyPopper(GadgetManager manager) { super(manager, "Party Popper", - UtilText.splitLineToArray(C.cWhite + "Celebrate by blasting confetti into peoples eyes!", LineFormat.LORE), + UtilText.splitLineToArray(C.cWhite + "Celebrate by blasting confetti into peoples' eyes!", LineFormat.LORE), 1, Material.GOLDEN_CARROT, (byte) 0, 1000, new Ammo("Party Popper", "1 Party Popper", Material.GOLDEN_CARROT, (byte) 0, new String[] { diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphBunny.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphBunny.java index 55f67dc0d..50d789985 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphBunny.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphBunny.java @@ -59,7 +59,7 @@ public class MorphBunny extends MorphGadget "#" + C.cWhite + "Charge Crouch to use Super Jump", "#" + C.cWhite + "Left Click to use Hide Easter Egg", C.blankLine, - "#" + C.cRed +C.Bold + "WARNING: " + ChatColor.RESET + "Hide Easter Egg uses 500 Coins" , + "#" + C.cRed +C.Bold + "WARNING: " + ChatColor.RESET + "Hide Easter Egg uses 500 Shards" , }, LineFormat.LORE), -5, Material.MONSTER_EGG, (byte)98); @@ -154,7 +154,7 @@ public class MorphBunny extends MorphGadget if (Manager.getDonationManager().Get(player.getName()).GetBalance(CurrencyType.Coins) < 500) { - UtilPlayer.message(player, F.main("Gadget", "You do not have enough Coins.")); + UtilPlayer.message(player, F.main("Gadget", "You do not have enough Shards.")); return; } @@ -183,7 +183,7 @@ public class MorphBunny extends MorphGadget ChatColor.RESET + C.Bold + " hid an " + C.cYellow + C.Bold + "Easter Egg" + ChatColor.RESET + C.Bold + " worth " + - C.cYellow + C.Bold + "450 Coins"); + C.cYellow + C.Bold + "450 Shards"); for (Player other : UtilServer.getPlayers()) other.playSound(other.getLocation(), Sound.CAT_HIT, 1.5f, 1.5f); diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphSlime.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphSlime.java index 7a8430173..7e539bf90 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphSlime.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphSlime.java @@ -29,7 +29,7 @@ public class MorphSlime extends MorphGadget { super(manager, "Big Larry Morph", UtilText.splitLinesToArray(new String[] { - C.cGray + "Have you ever looked at Big Larry and thought, \'I really want to be that guy!\'? Well, today is your lucky day!", + C.cGray + "Have you ever looked at Big Larry and thought, \'I really want to be that guy\'!? Well, today is your lucky day!", C.blankLine, "#" + C.cWhite + "Left Click to use Bounce", C.blankLine, diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphTitan.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphTitan.java index 13fe0ee14..68091b674 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphTitan.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/morph/MorphTitan.java @@ -46,7 +46,7 @@ public class MorphTitan extends MorphGadget { super(manager, "Elder Guardian Morph", UtilText.splitLinesToArray(new String[] { - C.cGray + "From the depths of the sea, the Elder Guardian posseses powers more amazing than any seen before!", + C.cGray + "From the depths of the sea, the Elder Guardian possesses powers more amazing than any seen before!", C.blankLine, "#" + C.cWhite + "Left-Click to use Guardians Laser", }, LineFormat.LORE), diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleCandyCane.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleCandyCane.java index d36ca5021..2d9c8c8c7 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleCandyCane.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleCandyCane.java @@ -29,7 +29,7 @@ public class ParticleCandyCane extends ParticleGadget public ParticleCandyCane(GadgetManager manager) { super(manager, "Crushed Candy Cane", - UtilText.splitLineToArray(C.cGray + "There’s no such thing as too much Christmas Candy. Don’t listen to your dentist.", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "There's no such thing as too much Christmas Candy. Don't listen to your dentist.", LineFormat.LORE), -3, Material.INK_SACK, (byte)1); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleEnchant.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleEnchant.java index 230705505..43319483c 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleEnchant.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleEnchant.java @@ -22,7 +22,7 @@ public class ParticleEnchant extends ParticleGadget public ParticleEnchant(GadgetManager manager) { super(manager, "Enchanted", - UtilText.splitLineToArray(C.cGray + "The wisdom of the universe suddenly find you extremely attractive, and wants to \'enchant\' you.", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "The wisdom of the universe suddenly finds you extremely attractive, and wants to \'enchant\' you.", LineFormat.LORE), -2, Material.BOOK, (byte)0); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleFrostLord.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleFrostLord.java index 035615c59..aaaa4d79c 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleFrostLord.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleFrostLord.java @@ -28,7 +28,7 @@ public class ParticleFrostLord extends ParticleGadget public ParticleFrostLord(GadgetManager manager) { super(manager, "Wind of the Frost Lord", - UtilText.splitLineToArray(C.cGray + "He’s not passing wind okay? HE HAS A CONDITION!", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "He's not passing wind, okay? HE HAS A CONDITION!", LineFormat.LORE), -3, Material.SNOW_BALL, (byte)0, "Frost Lord"); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleGreen.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleGreen.java index a9bd2739d..68304788a 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleGreen.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleGreen.java @@ -24,7 +24,7 @@ public class ParticleGreen extends ParticleGadget public ParticleGreen(GadgetManager manager) { super(manager, "Green Ring", - UtilText.splitLineToArray(C.cGray + "With these sparkles, you can sparkle while sparkle with CaptainSparklez!", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "With these sparkles, you can sparkle while sparkling with CaptainSparklez!", LineFormat.LORE), -2, Material.EMERALD, (byte)0); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleHelix.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleHelix.java index a9336927b..9e33bdc52 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleHelix.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/particle/ParticleHelix.java @@ -24,7 +24,7 @@ public class ParticleHelix extends ParticleGadget public ParticleHelix(GadgetManager manager) { super(manager, "Blood Helix", - UtilText.splitLineToArray(C.cGray + "Blood magic is very dangerous... but also very cool!", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "Blood magic is very dangerous...but also very cool!", LineFormat.LORE), -2, Material.REDSTONE, (byte)0); } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java b/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java index 8ae12ae88..5d90a1b98 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java @@ -67,6 +67,9 @@ public enum GameDisplay MonsterLeague("Monster League", Material.MINECART, (byte)0, GameCategory.ARCADE, 56), Lobbers("Bomb Lobbers", Material.FIREBALL, (byte) 0, GameCategory.ARCADE, 54), + + SpeedBuilders("Speed Builders", Material.QUARTZ_BLOCK, (byte) 0, GameCategory.CLASSICS, 60), + ChampionsCTF("Champions CTF", "Champions", Material.BANNER, DyeColor.RED.getDyeData(), GameCategory.CHAMPIONS, 56), BouncyBalls("Bouncy Balls", Material.SLIME_BALL, (byte)0, GameCategory.ARCADE, 57), Gladiators("Gladiators", Material.IRON_SWORD, (byte)0, GameCategory.ARCADE, 58), diff --git a/Plugins/Mineplex.Core/src/mineplex/core/mount/types/MountBabyReindeer.java b/Plugins/Mineplex.Core/src/mineplex/core/mount/types/MountBabyReindeer.java index 64e56f971..da0c765bc 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/mount/types/MountBabyReindeer.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/mount/types/MountBabyReindeer.java @@ -32,7 +32,7 @@ public class MountBabyReindeer extends HorseMount public MountBabyReindeer(MountManager manager) { super(manager, "Baby Reindeer", - UtilText.splitLineToArray(C.cGray + "One of Santas baby reindeers. He's still learning how to fly...", LineFormat.LORE), + UtilText.splitLineToArray(C.cGray + "One of Santa's baby reindeers. He's still learning how to fly...", LineFormat.LORE), Material.GOLDEN_CARROT, (byte) 0, -3, Color.CREAMY, Style.WHITEFIELD, Variant.HORSE, 0, null); } diff --git a/Plugins/Mineplex.MapParser/src/mineplex/mapparser/Parse.java b/Plugins/Mineplex.MapParser/src/mineplex/mapparser/Parse.java index a4702cc64..79d74e141 100644 --- a/Plugins/Mineplex.MapParser/src/mineplex/mapparser/Parse.java +++ b/Plugins/Mineplex.MapParser/src/mineplex/mapparser/Parse.java @@ -128,8 +128,19 @@ public class Parse String name = ""; try - { + { name = s.getLine(0); + + if (s.getLine(1) != null && s.getLine(1).length() > 0) + name += " " + s.getLine(1); + + if (s.getLine(2) != null && s.getLine(2).length() > 0) + name += " " + s.getLine(2); + + if (s.getLine(3) != null && s.getLine(3).length() > 0) + name += " " + s.getLine(3); + + System.out.println("Custom Location: " + name); } catch (Exception e) { diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java index 494f5dcd5..bded257c0 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java @@ -31,6 +31,8 @@ import mineplex.core.energy.Energy; import mineplex.core.explosion.Explosion; import mineplex.core.explosion.ExplosionEvent; import mineplex.core.facebook.FacebookManager; +import mineplex.core.gadget.types.Gadget; +import mineplex.core.gadget.types.GadgetType; import mineplex.core.giveaway.GiveawayManager; import mineplex.core.hologram.HologramManager; import mineplex.core.inventory.InventoryManager; @@ -901,6 +903,10 @@ public class ArcadeManager extends MiniPlugin implements IRelation HubClock(player); GetDisguise().undisguise(player); + + Gadget morph = getCosmeticManager().getGadgetManager().getActive(player, GadgetType.Morph); + if (morph.IsActive(player)) + morph.Disable(player); } public ArrayList LoadFiles(String gameName) @@ -1166,6 +1172,7 @@ public class ArcadeManager extends MiniPlugin implements IRelation if (event.GetState() == GameState.Recruit) { getCosmeticManager().setActive(true); + getCosmeticManager().setHideParticles(false); } else if (event.GetState() == GameState.Prepare || event.GetState() == GameState.Loading || event.GetState() == GameState.Dead) { @@ -1177,6 +1184,9 @@ public class ArcadeManager extends MiniPlugin implements IRelation getCosmeticManager().disableItemsForGame(); } } + + if (!event.GetGame().AllowParticles) + getCosmeticManager().setHideParticles(true); } } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java index 5f647dcd9..58fe9a3a5 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java @@ -1,7 +1,5 @@ package nautilus.game.arcade; -import org.bukkit.Material; - import mineplex.core.game.GameCategory; import mineplex.core.game.GameDisplay; import nautilus.game.arcade.game.Game; @@ -54,6 +52,7 @@ import nautilus.game.arcade.game.games.smash.TeamSuperSmash; import nautilus.game.arcade.game.games.snake.Snake; import nautilus.game.arcade.game.games.sneakyassassins.SneakyAssassins; import nautilus.game.arcade.game.games.snowfight.SnowFight; +import nautilus.game.arcade.game.games.speedbuilders.SpeedBuilders; import nautilus.game.arcade.game.games.spleef.Spleef; import nautilus.game.arcade.game.games.spleef.SpleefTeams; import nautilus.game.arcade.game.games.squidshooter.SquidShooter; @@ -68,6 +67,8 @@ import nautilus.game.arcade.game.games.wither.WitherGame; import nautilus.game.arcade.game.games.wizards.Wizards; import nautilus.game.arcade.game.games.zombiesurvival.ZombieSurvival; +import org.bukkit.Material; + public enum GameType { //Mini @@ -113,6 +114,7 @@ public enum GameType Snake(Snake.class, GameDisplay.Snake), SneakyAssassins(SneakyAssassins.class, GameDisplay.SneakyAssassins), SnowFight(SnowFight.class, GameDisplay.SnowFight), + SpeedBuilders(SpeedBuilders.class, GameDisplay.SpeedBuilders), Spleef(Spleef.class, GameDisplay.Spleef), SpleefTeams(SpleefTeams.class, GameDisplay.SpleefTeams), SquidShooter(SquidShooter.class, GameDisplay.SquidShooter), diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java index 6eec52eb7..349c131f8 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java @@ -311,6 +311,8 @@ public abstract class Game implements Listener public boolean EnableTutorials = false; public boolean FixSpawnFacing = true; + + public boolean AllowEntitySpectate = true; private IPacketHandler _useEntityPacketHandler; private int _deadBodyCount; @@ -1751,4 +1753,6 @@ public abstract class Game implements Listener } public void addTutorials(){} + + public void disable(){} } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/christmas/parts/Part.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/christmas/parts/Part.java index ea8e171cc..80c3a276e 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/christmas/parts/Part.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/christmas/parts/Part.java @@ -223,7 +223,7 @@ public abstract class Part implements Listener Host.GetSleigh().AddPresent(present.getBlock().getLocation()); - Host.SantaSay("Well done " + event.getPlayer().getName() + "! You collected a present!", null); + Host.SantaSay("Well done, " + event.getPlayer().getName() + "! You collected a present!", null); } public void SetObjectiveText(String text, double percent) diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/christmas/parts/Part5.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/christmas/parts/Part5.java index 2dceaca60..b91aa0d13 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/christmas/parts/Part5.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/christmas/parts/Part5.java @@ -143,7 +143,7 @@ public class Part5 extends Part _a = true; _dialogueDelay = System.currentTimeMillis(); - Host.SantaSay("WHAT IS THIS?! Who's castle is this?!", ChristmasAudio.BANTER_A); + Host.SantaSay("WHAT IS THIS?! Whose castle is this?!", ChristmasAudio.BANTER_A); } else if (_a && !_b && UtilTime.elapsed(_dialogueDelay, _delayTime)) { diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/Gladiators.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/Gladiators.java index 66701b54a..caff47df6 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/Gladiators.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/Gladiators.java @@ -1095,4 +1095,11 @@ public class Gladiators extends SoloGame Scoreboard.Draw(); } + + @Override + public void disable() + { + _hotbarEditor.deregisterSelf(); // De-register as listener + _hotbarEditor.onDisable(); // Fully disable + } } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/hotbar/HotbarEditor.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/hotbar/HotbarEditor.java index e12ee785e..da6897997 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/hotbar/HotbarEditor.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/hotbar/HotbarEditor.java @@ -9,6 +9,8 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; @@ -37,6 +39,7 @@ public class HotbarEditor extends MiniPlugin { private Gladiators _host; private ItemStack _item; + private Listener _pageListener; public HotbarEditor(JavaPlugin plugin, Gladiators gladiators) { @@ -46,7 +49,14 @@ public class HotbarEditor extends MiniPlugin _item = new ItemBuilder(Material.NAME_TAG).setTitle(C.cGold + "Hotbar Editor") .addLore(C.cGray + "Right click to edit your Gladiators hotbar").build(); - getPluginManager().registerEvents(new HotbarPageListener(this), getPlugin()); + _pageListener = new HotbarPageListener(this); + getPluginManager().registerEvents(_pageListener, getPlugin()); + } + + @Override + public void disable() + { + HandlerList.unregisterAll(_pageListener); } @EventHandler @@ -81,6 +91,9 @@ public class HotbarEditor extends MiniPlugin { if (event.getMessage().equalsIgnoreCase("/spec")) { + if (_host == null) + return; + if (!_host.IsAlive(event.getPlayer()) && !UtilInv.contains(event.getPlayer(), _item.getType(), (byte) 0, 1)) { diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/SpeedBuilders.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/SpeedBuilders.java new file mode 100644 index 000000000..aa7606f8a --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/SpeedBuilders.java @@ -0,0 +1,1738 @@ +package nautilus.game.arcade.game.games.speedbuilders; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map.Entry; + +import mineplex.core.common.Rank; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.MapUtil; +import mineplex.core.common.util.NautHashMap; +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilEvent; +import mineplex.core.common.util.UtilEvent.ActionType; +import mineplex.core.common.util.UtilInv; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTextBottom; +import mineplex.core.common.util.UtilTextMiddle; +import mineplex.core.common.util.UtilTime; +import mineplex.core.disguise.disguises.DisguiseGuardian; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import nautilus.game.arcade.ArcadeManager; +import nautilus.game.arcade.GameType; +import nautilus.game.arcade.events.GameStateChangeEvent; +import nautilus.game.arcade.game.GameTeam; +import nautilus.game.arcade.game.GameTeam.PlayerState; +import nautilus.game.arcade.game.SoloGame; +import nautilus.game.arcade.game.games.speedbuilders.data.BuildData; +import nautilus.game.arcade.game.games.speedbuilders.data.DemolitionData; +import nautilus.game.arcade.game.games.speedbuilders.data.MobData; +import nautilus.game.arcade.game.games.speedbuilders.data.RecreationData; +import nautilus.game.arcade.game.games.speedbuilders.events.PerfectBuildEvent; +import nautilus.game.arcade.game.games.speedbuilders.kits.DefaultKit; +import nautilus.game.arcade.game.games.speedbuilders.stattrackers.DependableTracker; +import nautilus.game.arcade.game.games.speedbuilders.stattrackers.FirstBuildTracker; +import nautilus.game.arcade.game.games.speedbuilders.stattrackers.PerfectionistTracker; +import nautilus.game.arcade.game.games.speedbuilders.stattrackers.SpeediestBuilderizerTracker; +import nautilus.game.arcade.kit.Kit; +import net.minecraft.server.v1_8_R3.PacketPlayOutGameStateChange; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockFadeEvent; +import org.bukkit.event.block.BlockFormEvent; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.block.BlockGrowEvent; +import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockSpreadEvent; +import org.bukkit.event.block.LeavesDecayEvent; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityCombustEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.ItemMergeEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerBucketFillEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.world.StructureGrowEvent; +import org.bukkit.material.Bed; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +public class SpeedBuilders extends SoloGame +{ + private static final String GUARDIAN_NAME = "Gwen the Guardian"; + + //Build Size and some other values used commonly + public int BuildSize = 7; + public int BuildSizeDiv2 = BuildSize / 2; + public int BuildSizeMin1 = BuildSize - 1; + public int BuildSizePow3 = BuildSize * BuildSize * BuildSize; + + public boolean InstaBreak = true; + + private SpeedBuildersState _state = SpeedBuildersState.VIEWING; + private long _stateTime = System.currentTimeMillis(); + + private int _roundsPlayed; + + private int _buildCountStage; + private int _viewCountStage; + + private int _buildTimeTracker = 40; + private int _buildTime = 40; + private int _viewTime = 10; + + private Location _buildMiddle; + + private ArrayList _buildData = new ArrayList(); + private ArrayList _usedBuilds = new ArrayList<>(); + private BuildData _currentBuild; + + private BlockState[][] _defaultMiddleGround = new BlockState[BuildSize][BuildSize]; + private ArrayList _middleMobs = new ArrayList(); + + private NautHashMap _buildRecreations = new NautHashMap(); + + private ArmorStand _judgeEntity; + private DisguiseGuardian _judgeDisguise; + private Location _judgeSpawn; + private ArmorStand _judgeLaserTarget; + + private ArrayList _toEliminate = new ArrayList(); + private long _lastElimination; + private boolean _eliminating; + // Track the time we switch to review so we can give players 8 seconds to look around + private long _reviewStartTime; + + private NautHashMap _perfectBuild = new NautHashMap(); + private boolean _allPerfect; + + private Location _lookTarget; + private ArmorStand _lookStand; + private long _targetReached; + private long _stayTime; + private RecreationData _lastRecreationTarget; + private double _standMoveProgress; + private Location _standStart; + + private BuildData _nextBuild; + + public SpeedBuilders(ArcadeManager manager) + { + super(manager, GameType.SpeedBuilders, + new Kit[] + { + new DefaultKit(manager) + }, + new String[] + { + "Recreate the build shown to you.", + "The least correct build is eliminated.", + "Last person left wins!" + }); + + Damage = false; + + HungerSet = 20; + HealthSet = 20; + + DontAllowOverfill = true; + + DeathMessages = false; + + FixSpawnFacing = false; + + AllowParticles = false; + + InventoryClick = true; + + registerStatTrackers( + new DependableTracker(this), + new FirstBuildTracker(this), + new PerfectionistTracker(this), + new SpeediestBuilderizerTracker(this) + ); + } + + @Override + public void ParseData() + { + _buildMiddle = WorldData.GetDataLocs("RED").get(0).clone().subtract(0.5, 0, 0.5); + + _judgeSpawn = _buildMiddle.clone().add(0.5, BuildSize, 0.5); + + Location groundMin = _buildMiddle.clone().subtract(BuildSizeDiv2, 1, BuildSizeDiv2); + + for (int x = 0; x < BuildSize; x++) + { + for (int z = 0; z < BuildSize; z++) + { + _defaultMiddleGround[x][z] = groundMin.clone().add(x, 0, z).getBlock().getState(); + } + } + + for (Entry> entry : WorldData.GetAllCustomLocs().entrySet()) + { + BuildData buildData = new BuildData(entry.getValue().get(0).clone().subtract(0.5, 0, 0.5), ChatColor.translateAlternateColorCodes('&', entry.getKey()), this); + boolean add = false; + for (int x = 0; x < BuildSize && !add; x++) + { + for (int y = 0; y < BuildSize && !add; y++) + { + for (int z = 0; z < BuildSize && !add; z++) + { + if (buildData.Build[x][y][z] != null && buildData.Build[x][y][z].getType() != Material.AIR) + add = true; + } + } + } + + if (!buildData.Mobs.isEmpty()) + add = true; + + if (add) + _buildData.add(buildData); + } + + for (Location loc : WorldData.GetDataLocs("YELLOW")) + { + loc.subtract(0.5, 0, 0.5); + } + + for (Location loc : GetTeamList().get(0).GetSpawns()) + { + loc.setDirection(UtilAlg.getTrajectory(loc, _buildMiddle.clone().add(0.5, 0, 0.5))); + } + } + + public void setSpeedBuilderState(SpeedBuildersState state) + { + _state = state; + _stateTime = System.currentTimeMillis(); + } + + public SpeedBuildersState getSpeedBuilderState() + { + return _state; + } + + public long getSpeedBuilderStateTime() + { + return _stateTime; + } + + public int getRoundsPlayed() + { + return _roundsPlayed; + } + + public void clearCenterArea(boolean resetGround) + { + Location buildMin = _buildMiddle.clone().subtract(BuildSizeDiv2, 0, BuildSizeDiv2); + Location buildMax = _buildMiddle.clone().add(BuildSizeDiv2, BuildSizeMin1, BuildSizeDiv2); + + for (Block block : UtilBlock.getInBoundingBox(buildMin, buildMax)) + { + MapUtil.QuickChangeBlockAt(block.getLocation(), Material.AIR); + } + + for (Entity entity : _middleMobs) + { + entity.remove(); + } + + _middleMobs.clear(); + + if (resetGround) + { + for (int x = 0; x < BuildSize; x++) + { + for (int z = 0; z < BuildSize; z++) + { + MapUtil.QuickChangeBlockAt(buildMin.clone().add(x, -1, z), _defaultMiddleGround[x][z].getType(), _defaultMiddleGround[x][z].getRawData()); + } + } + } + } + + public void pasteBuildInCenter(BuildData buildData) + { + clearCenterArea(true); + + Location groundMin = _buildMiddle.clone().subtract(BuildSizeDiv2, 1, BuildSizeDiv2); + + for (int x = 0; x < BuildSize; x++) + { + for (int z = 0; z < BuildSize; z++) + { + MapUtil.QuickChangeBlockAt(groundMin.clone().add(x, 0, z), buildData.Ground[x][z].getType(), buildData.Ground[x][z].getRawData()); + } + } + + Location buildMin = _buildMiddle.clone().subtract(BuildSizeDiv2, 0, BuildSizeDiv2); + + for (int x = 0; x < BuildSize; x++) + { + for (int y = 0; y < BuildSize; y++) + { + for (int z = 0; z < BuildSize; z++) + { + MapUtil.QuickChangeBlockAt(buildMin.clone().add(x, y, z), buildData.Build[x][y][z].getType(), buildData.Build[x][y][z].getRawData()); + } + } + } + + CreatureAllowOverride = true; + + for (MobData mobData : buildData.Mobs) + { + Location loc = buildMin.clone().add(mobData.DX + 0.5, mobData.DY, mobData.DZ + 0.5); + + Entity entity = loc.getWorld().spawnEntity(loc, mobData.EntityType); + + UtilEnt.Vegetate(entity, true); + UtilEnt.ghost(entity, true, false); + + _middleMobs.add(entity); + } + + CreatureAllowOverride = false; + } + + public void spawnJudge() + { + CreatureAllowOverride = true; + + _judgeEntity = _judgeSpawn.getWorld().spawn(_judgeSpawn, ArmorStand.class); + + CreatureAllowOverride = false; + + _judgeEntity.setVisible(false); + _judgeEntity.setGravity(false); + _judgeEntity.setSmall(true); + + _judgeDisguise = new DisguiseGuardian(_judgeEntity); + + _judgeDisguise.setElder(true); + _judgeDisguise.setCustomNameVisible(true); + _judgeDisguise.setName(GUARDIAN_NAME); + + Manager.GetDisguise().disguise(_judgeDisguise); + } + + public void despawnJudge() + { + Manager.GetDisguise().undisguise(_judgeEntity); + + _judgeEntity.remove(); + + _judgeDisguise = null; + _judgeEntity = null; + } + + public void judgeTargetLocation(Location loc) + { + if (loc == null) + { + if (_judgeLaserTarget == null) + return; + + _judgeLaserTarget.remove(); + + _judgeLaserTarget = null; + + _judgeDisguise.setTarget(0); + + Manager.GetDisguise().updateDisguise(_judgeDisguise); + } + else + { + if (_judgeLaserTarget != null) + judgeTargetLocation(null); + + CreatureAllowOverride = true; + + _judgeLaserTarget = _judgeEntity.getWorld().spawn(loc, ArmorStand.class); + + CreatureAllowOverride = false; + + _judgeLaserTarget.setVisible(false); + _judgeLaserTarget.setGravity(false); + _judgeLaserTarget.setSmall(true); + + UtilEnt.CreatureLook(_judgeEntity, _judgeLaserTarget.getLocation()); + + _judgeDisguise.setTarget(_judgeLaserTarget.getEntityId()); + + Manager.GetDisguise().updateDisguise(_judgeDisguise); + } + } + + public void moveToGuardians(Player player, boolean elimination) + { + if (elimination) + { + GetTeamList().get(0).SetPlacement(player, PlayerState.OUT); + GetTeamList().get(0).RemovePlayer(player); + } + + GetTeamList().get(1).AddPlayer(player, true); + + DisguiseGuardian disguise = new DisguiseGuardian(player); + disguise.setName(C.cGray + player.getName()); + disguise.setCustomNameVisible(true); + + Manager.GetDisguise().disguise(disguise); + + player.setGameMode(GameMode.SURVIVAL); + + player.setAllowFlight(true); + player.setFlying(true); + + EndCheck(); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void teamGen(GameStateChangeEvent event) + { + if (event.GetState() != GameState.Live) + return; + + //Add 1 spawn so it doesn't freak out + ArrayList spawns = new ArrayList(); + spawns.add(GetSpectatorLocation()); + + GameTeam guardians = new GameTeam(this, "Guardians", ChatColor.GRAY, spawns); + + AddTeam(guardians); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPrepare(GameStateChangeEvent event) + { + if (event.GetState() != GameState.Prepare) + return; + + spawnJudge(); + //GUARDIAN LAZORZ WILL ROXORZ YOUR BOXORZ + + ArrayList players = GetPlayers(true); + + for (int i = 0; i < players.size(); i++) + { + if (i >= WorldData.GetDataLocs("YELLOW").size()) + { + Manager.addSpectator(players.get(i), true); + GetTeamList().get(0).RemovePlayer(players.get(i)); + } + } + } + + @EventHandler + public void onLive(GameStateChangeEvent event) + { + if (!IsLive()) + return; + + if (WorldData.GetDataLocs("YELLOW").size() < GetPlayers(true).size()) + { + Announce(C.Bold + "Too many players..."); + SetState(GameState.End); + return; + } + + if (_nextBuild != null) + _currentBuild = _nextBuild; + else + _currentBuild = UtilAlg.Random(_buildData, _usedBuilds); + + _nextBuild = null; + _usedBuilds.add(_currentBuild); + _buildTime = _currentBuild.getBuildTime(_buildTimeTracker); + + HashSet usedBuildLocs = new HashSet(); + + for (Player player : GetPlayers(true)) + { + Location buildLoc = UtilAlg.findClosest(player.getLocation(), WorldData.GetDataLocs("YELLOW")); + Location spawnLoc = UtilAlg.findClosest(buildLoc, GetTeamList().get(0).GetSpawns()); + + _buildRecreations.put(player, new RecreationData(this, player, buildLoc, spawnLoc)); + + _buildRecreations.get(player).pasteBuildData(_currentBuild); + + usedBuildLocs.add(buildLoc); + } + + for (Location loc : WorldData.GetDataLocs("YELLOW")) + { + if (!usedBuildLocs.contains(loc)) + { + HashSet blocks = UtilBlock.findConnectedBlocks(loc.getBlock(), loc.getBlock(), null, 2000, 8); + + Manager.GetExplosion().BlockExplosion(blocks, loc, false, true); + } + } + + for (Player player : GetTeamList().get(0).GetPlayers(true)) + { + UtilPlayer.message(player, F.main("Build", "Recreate the build shown.")); + } + + UtilTextMiddle.display("", C.cGold + _currentBuild.BuildText, 0, 80, 10); + + _roundsPlayed++; + + setSpeedBuilderState(SpeedBuildersState.VIEWING); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) + { + if (GetTeamList().size() > 1 && GetTeamList().get(1).HasPlayer(event.getPlayer())) + GetTeamList().get(1).RemovePlayer(event.getPlayer()); + + RecreationData recreation = null; + + if (_buildRecreations.containsKey(event.getPlayer())) + recreation = _buildRecreations.remove(event.getPlayer()); + + if (recreation != null) + { + HashSet blocks = UtilBlock.findConnectedBlocks(recreation.OriginalBuildLocation.getBlock(), recreation.OriginalBuildLocation.getBlock(), null, 2000, 8); + + //Sets should remove duplicates + blocks.addAll(recreation.getBlocks()); + + Manager.GetExplosion().BlockExplosion(blocks, recreation.getMidpoint(), false, true); + + recreation.clearBuildArea(false); + + if (_toEliminate.contains(recreation)) + _toEliminate.remove(recreation); + } + } + + @EventHandler + public void onBlockPlace(BlockPlaceEvent event) + { + if (_state != SpeedBuildersState.BUILDING) + return; + + if (!_buildRecreations.containsKey(event.getPlayer())) + return; + + if (_perfectBuild.containsKey(event.getPlayer())) + { + event.setCancelled(true); + return; + } + + if (_buildRecreations.get(event.getPlayer()).isQueuedForDemolition(event.getBlock())) + { + event.setCancelled(true); + return; + } + + if (_buildRecreations.get(event.getPlayer()).inBuildArea(event.getBlock()) && event.getBlock().getType() != Material.BED_BLOCK) + return; + else if (event.getBlock().getType() == Material.BED_BLOCK) + { + Bed bed = (Bed) event.getBlock().getState().getData(); + + if (bed.isHeadOfBed()) + { + Block foot = event.getBlock().getRelative(bed.getFacing().getOppositeFace()); + + if (_buildRecreations.get(event.getPlayer()).inBuildArea(foot)) + return; + } + else + { + Block head = event.getBlock().getRelative(bed.getFacing()); + + if (_buildRecreations.get(event.getPlayer()).inBuildArea(head)) + return; + } + } + + event.setCancelled(true); + UtilPlayer.message(event.getPlayer(), F.main("Build", "Cannot build outside your area!")); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBuildFinish(final BlockPlaceEvent event) + { + checkPerfectBuild(event.getPlayer()); + } + + //This is here because if you open a door then close it you won't be informed of a perfect build + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void interactInformSuccess(PlayerInteractEvent event) + { + checkPerfectBuild(event.getPlayer()); + } + + public void checkPerfectBuild(Player player) + { + if (_perfectBuild.containsKey(player)) + return; + + Manager.runSyncLater(new Runnable() + { + @Override + public void run() + { + if (!IsLive()) + return; + + if (_state != SpeedBuildersState.BUILDING) + return; + + if (!_buildRecreations.containsKey(player)) + return; + + if (_perfectBuild.containsKey(player)) + return; + + if (_buildRecreations.get(player).calculateScoreFromBuild(_currentBuild) == _currentBuild.getPerfectScore()) + { + long timeElapsed = System.currentTimeMillis() - _stateTime; + PerfectBuildEvent perfectBuildEvent = new PerfectBuildEvent(player, timeElapsed, SpeedBuilders.this); + + Bukkit.getServer().getPluginManager().callEvent(perfectBuildEvent); + + player.playSound(player.getEyeLocation(), Sound.LEVEL_UP, 10F, 1F); + + String time = UtilTime.convertString(timeElapsed, 1, UtilTime.TimeUnit.SECONDS); + Announce(F.main("Build", F.name(player.getName()) + " got a perfect build in " + F.time(time) + "!")); + + _perfectBuild.put(player, System.currentTimeMillis()); + + if (_perfectBuild.size() == GetTeamList().get(0).GetPlayers(false).size()) + { + // Everyone has a perfect build + _allPerfect = true; + } + else + { + // Don't display middle text if everyone now has a perfect build + UtilTextMiddle.display("", C.cGreen + "Perfect Match", 0, 30, 10, player); + } + } + } + }, 1L); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerPickupItem(PlayerPickupItemEvent event) + { + if (_state != SpeedBuildersState.BUILDING) + return; + + if (!_buildRecreations.containsKey(event.getPlayer())) + return; + + if (_buildRecreations.get(event.getPlayer()).DroppedItems.containsKey(event.getItem())) + _buildRecreations.get(event.getPlayer()).DroppedItems.remove(event.getItem()); + else + event.setCancelled(true); + } + + @EventHandler + public void stopItemMerge(ItemMergeEvent event) + { + event.setCancelled(true); + } + + @EventHandler + public void stopMoveOffArea(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + return; + + if (!IsLive()) + return; + + for (Player player : GetPlayers(true)) + { + if (!_buildRecreations.containsKey(player)) + continue; + + RecreationData recreation = _buildRecreations.get(player); + double dist = UtilMath.offsetSquared(player.getLocation(), recreation.OriginalBuildLocation.clone().add(0.5, 0, 0.5)); + + for (Location loc : WorldData.GetDataLocs("YELLOW")) + { + if (loc.equals(recreation.OriginalBuildLocation)) + continue; + + double distFromOther = UtilMath.offsetSquared(player.getLocation(), loc.clone().add(0.5, 0, 0.5)); + + if (player.getGameMode() != GameMode.SPECTATOR && (dist > distFromOther || player.getLocation().getY() < recreation.OriginalBuildLocation.getY() - 2)) + { + player.teleport(recreation.PlayerSpawn); + + UtilPlayer.message(player, F.main("Build", "You cannot leave your area!")); + UtilTextMiddle.display("", C.cRed + "You cannot leave your area!", 0, 30, 10, player); + + break; + } + } + } + } + + @EventHandler + public void stopGuardiansBuildEnter(UpdateEvent event) + { + if (event.getType() != UpdateType.FASTER) + return; + + if (!IsLive()) + return; + + for (Player player : GetTeamList().get(1).GetPlayers(false)) + { + for (RecreationData recreation : _buildRecreations.values()) + { + Vector vec = player.getLocation().getDirection().multiply(-1); + + if (UtilMath.offsetSquared(player.getLocation(), recreation.getMidpoint()) < 64) + { + player.playSound(player.getEyeLocation(), Sound.NOTE_PLING, 10F, 0.5F); + UtilAction.velocity(player, vec, 1.6, false, 0, 0.4, vec.length(), false); + } + } + } + } + + @EventHandler + public void border(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + return; + + if (!InProgress()) + return; + + Location specLocation = GetSpectatorLocation(); + + //This can be done like this cause nobody should be outside + for (Player player : UtilServer.getPlayers()) + { + if (!isInsideMap(player)) + player.teleport(specLocation); + } + } + + @EventHandler + public void stateUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + return; + + if (!IsLive()) + return; + + if (_state == SpeedBuildersState.VIEWING) + { + if (UtilTime.elapsed(_stateTime, _viewTime * 1000)) + { + for (RecreationData recreation : _buildRecreations.values()) + { + recreation.breakAndDropItems(); + } + + ItemPickup = true; + BlockPlace = true; + + _buildCountStage = 0; + + //Sometimes it doesn't show in the update method + UtilTextMiddle.display("", C.cRed + "View Time Over!", 0, 30, 10); + + for (Player player : GetTeamList().get(0).GetPlayers(true)) + { + UtilPlayer.message(player, F.main("Build", "Recreate the build shown.")); + } + + setSpeedBuilderState(SpeedBuildersState.BUILDING); + } + } + else if (_state == SpeedBuildersState.BUILDING) + { + if (UtilTime.elapsed(_stateTime, _buildTime * 1000) || _allPerfect) + { + for (RecreationData recreation : _buildRecreations.values()) + { + for (Item item : recreation.DroppedItems.keySet()) + { + item.remove(); + } + + recreation.DroppedItems.clear(); + + UtilInv.Clear(recreation.Player); + } + + //Sometimes it stops on 0.1 and has one bar green + UtilTextBottom.displayProgress("Time Left:", 0, UtilTime.MakeStr(0), UtilServer.getPlayers()); + + if (_allPerfect) + { + UtilTextMiddle.display("", C.cAqua + GUARDIAN_NAME + " is Impressed!", 0, 100, 10); + _allPerfect = false; + } + else + { + //Sometimes doesn't show in the update method + UtilTextMiddle.display("", C.cRed + "TIME'S UP!", 0, 30, 10); + + Manager.runSyncLater(new Runnable() + { + @Override + public void run() + { + UtilTextMiddle.display("", C.cAqua + GUARDIAN_NAME + " is Judging", 0, 40, 10); + } + }, 40L); + } + + for (Player player : UtilServer.getPlayers()) + { +// player.setGameMode(GameMode.SPECTATOR); +// player.setSpectatorTarget(_judgeEntity); + +// Manager.GetCondition().Factory().Cloak("Guardian POV", player, null, 999999999, false, false); + + PacketPlayOutGameStateChange packet = new PacketPlayOutGameStateChange(10, 0.0F); + UtilPlayer.sendPacket(player, packet); + } + + _perfectBuild.clear(); + + ItemPickup = false; + BlockPlace = false; + + RecreationData lowest = null; + int lowestScore = -1; + + boolean allPerfectMatch = !_buildRecreations.isEmpty(); + boolean allPlayersEqual = true; + + for (RecreationData recreation : _buildRecreations.values()) + { + int score = recreation.calculateScoreFromBuild(_currentBuild); + + if (lowest != null && lowestScore != score) + { + allPlayersEqual = false; + } + + if (lowest == null || lowestScore > score) + { + lowest = recreation; + lowestScore = score; + } + + if (score != _currentBuild.getPerfectScore()) + allPerfectMatch = false; + + if (recreation.isEmptyBuild(_currentBuild)) + _toEliminate.add(recreation); + } + + if (!allPerfectMatch && !allPlayersEqual && lowest != null && !_toEliminate.contains(lowest)) + _toEliminate.add(lowest); + + if (!_toEliminate.isEmpty()) + { + Manager.runSyncLater(new Runnable() + { + @Override + public void run() + { + for (Player player : GetTeamList().get(0).GetPlayers(true)) + { + if (!_buildRecreations.containsKey(player)) + return; + + int percent = (int) (((double) _buildRecreations.get(player).calculateScoreFromBuild(_currentBuild) / _currentBuild.getPerfectScore()) * 100d); + + UtilTextMiddle.display("", getPercentPrefix(percent) + "You scored " + percent + " Percent", 0, 40, 10, player); + } + } + }, 130L); + } + + _lastElimination = System.currentTimeMillis(); + _reviewStartTime = System.currentTimeMillis(); + + pasteBuildInCenter(_currentBuild); + + setSpeedBuilderState(SpeedBuildersState.REVIEWING); + + for (Player player : GetTeamList().get(0).GetPlayers(true)) + { + player.setGameMode(GameMode.SPECTATOR); +// player.setAllowFlight(true); +// player.setFlying(true); + } + } + } + else if (_state == SpeedBuildersState.REVIEWING) + { + if (_toEliminate.isEmpty()) + { + if (!UtilTime.elapsed(_lastElimination, 3000)) + return; + + clearCenterArea(true); + + if (_nextBuild != null) + _currentBuild = _nextBuild; + else + _currentBuild = UtilAlg.Random(_buildData, _usedBuilds); + + _nextBuild = null; + _usedBuilds.add(_currentBuild); + _buildTime = _currentBuild.getBuildTime(_buildTimeTracker); + + for (Player player : GetTeamList().get(0).GetPlayers(true)) + { + player.setGameMode(GameMode.SURVIVAL); +// player.setAllowFlight(false); +// player.setFlying(false); + } + + for (RecreationData recreation : _buildRecreations.values()) + { + recreation.Player.teleport(recreation.PlayerSpawn); + + recreation.pasteBuildData(_currentBuild); + } + +// Location specLocation = GetSpectatorLocation(); +// double avgDist = 0; +// +// //Add up all the distances +// for (Location loc : GetTeamList().get(0).GetSpawns()) +// { +// avgDist += UtilMath.offset2d(specLocation, loc); +// } +// +// //Get the average by dividing +// avgDist /= GetTeamList().get(0).GetSpawns().size(); +// +// for (Player player : UtilServer.getPlayers()) +// { +// player.setGameMode(GameMode.SURVIVAL); +// +// Manager.GetCondition().EndCondition(player, ConditionType.CLOAK, "Guardian POV"); +// +// if (_buildRecreations.containsKey(player)) +// player.teleport(_buildRecreations.get(player).PlayerSpawn); +// +// if (!IsAlive(player) || GetTeamList().get(1).HasPlayer(player)) +// { +// player.setAllowFlight(true); +// player.setFlying(true); +// +// Location toTeleport = specLocation.clone(); +// +// //Spread players by getting a random x and z in that radius +// toTeleport.setX(toTeleport.getX() + (Math.random() * avgDist * 2 - avgDist)); +// toTeleport.setZ(toTeleport.getZ() + (Math.random() * avgDist * 2 - avgDist)); +// +// toTeleport.setDirection(UtilAlg.getTrajectory(toTeleport, _buildMiddle.clone().add(0.5, 0, 0.5))); +// +// player.teleport(toTeleport); +// } +// } + + _roundsPlayed++; + + if (_buildTimeTracker > 1) + _buildTimeTracker--; + + _viewCountStage = 0; + + for (Player player : GetTeamList().get(0).GetPlayers(true)) + { + UtilPlayer.message(player, F.main("Build", "You will recreate this build.")); + } + + UtilTextMiddle.display("", C.cGold + _currentBuild.BuildText, 0, 80, 10); + + setSpeedBuilderState(SpeedBuildersState.VIEWING); + } + else + { + if (UtilTime.elapsed(_reviewStartTime, 10000) && UtilTime.elapsed(_lastElimination, 2000) && !_eliminating) + { + //Eliminate in order This also means that the empty builds are eliminated first + final RecreationData eliminating = _toEliminate.get(0); + + judgeTargetLocation(eliminating.OriginalBuildLocation.clone().subtract(0, 1.7, 0)); + + UtilTextMiddle.display("", C.cRed + eliminating.Player.getName() + C.cGreen + " was eliminated!", 0, 30, 10); + + _eliminating = true; + + Manager.runSyncLater(new Runnable() + { + @Override + public void run() + { + _lastElimination = System.currentTimeMillis(); + + _eliminating = false; + + if (!_toEliminate.contains(eliminating)) + return; + + WorldData.World.playEffect(eliminating.getMidpoint(), Effect.EXPLOSION_HUGE, 0); + + for (Player player : UtilServer.getPlayers()) + { + player.playSound(player.getEyeLocation(), Sound.ZOMBIE_REMEDY, 1F, 1F); + } + + HashSet blocks = UtilBlock.findConnectedBlocks(eliminating.OriginalBuildLocation.getBlock(), eliminating.OriginalBuildLocation.getBlock(), null, 2000, 8); + + //Sets should remove duplicates + blocks.addAll(eliminating.getBlocks()); + + Manager.GetExplosion().BlockExplosion(blocks, eliminating.getMidpoint(), false, true); + + eliminating.clearBuildArea(false); + eliminating.removeHologram(); + + judgeTargetLocation(null); + + _toEliminate.remove(eliminating); + + _buildRecreations.remove(eliminating.Player); + + moveToGuardians(eliminating.Player, true); + } + }, 100L); + } + else if (!_eliminating) + { + double speed = 10d; + + double oX = -Math.sin(_judgeEntity.getTicksLived() / speed) * 12; + double oY = 0; + double oZ = Math.cos(_judgeEntity.getTicksLived() / speed) * 12; + + Location toLook = _judgeEntity.getLocation().add(new Vector(oX, oY, oZ)); + + UtilEnt.CreatureLook(_judgeEntity, toLook); + } + } + } + } + + private String getPercentPrefix(int percent) + { + if (percent >= 75) + return C.cAqua; + else if (percent >= 50) + return C.cGreen; + else if (percent >= 25) + return C.cYellow; + else + return C.cRed; + } + + @EventHandler + public void buildTimeProgressBar(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + return; + + if (!IsLive()) + return; + + if (_state != SpeedBuildersState.BUILDING) + return; + + long timeLeft = 1000 * _buildTime - (System.currentTimeMillis() - _stateTime); + + if (timeLeft < 0) + timeLeft = 0; + + UtilTextBottom.displayProgress("Time Left", timeLeft / (_buildTime * 1000.0D), UtilTime.MakeStr(timeLeft), UtilServer.getPlayers()); + } + + @EventHandler + public void buildEndCountdown(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + return; + + if (!IsLive()) + return; + + if (_state != SpeedBuildersState.BUILDING) + return; + + if (UtilTime.elapsed(_stateTime, 1000 * _buildCountStage)) + { + ArrayList players = new ArrayList(UtilServer.getServer().getOnlinePlayers()); + + for (Entry entry : _perfectBuild.entrySet()) + { + if (!UtilTime.elapsed(entry.getValue(), 5000)) + players.remove(entry.getKey()); + } + + if (_buildCountStage == _buildTime) + UtilTextMiddle.display("", C.cRed + "TIME'S UP!", 0, 30, 10); + else if (_buildCountStage >= _buildTime - 5) + UtilTextMiddle.display("", C.cGreen + (_buildTime - _buildCountStage), 0, 30, 10, players.toArray(new Player[players.size()])); + + if (_buildCountStage >= _buildTime - 5) + { + for (Player player : UtilServer.getPlayers()) + { + player.playSound(player.getEyeLocation(), Sound.NOTE_PLING, 1F, 1F - (float) (0.1 * (_buildTime - _buildCountStage))); + } + } + + _buildCountStage++; + } + } + + @EventHandler + public void viewCountdown(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + return; + + if (!IsLive()) + return; + + if (_state != SpeedBuildersState.VIEWING) + return; + + if (UtilTime.elapsed(_stateTime, _viewCountStage * 1000)) + { + if (_viewCountStage == _viewTime) + UtilTextMiddle.display("", C.cRed + "View Time Over!", 0, 30, 10); + else if (_viewCountStage > 3) + UtilTextMiddle.display("", C.cGreen + (_viewTime - _viewCountStage), 0, 30, 10); + + if (_viewCountStage > 3) + { + for (Player player : UtilServer.getPlayers()) + { + player.playSound(player.getEyeLocation(), Sound.NOTE_PLING, 1F, 1F - (float) (0.1 * (_viewTime - _viewCountStage))); + } + } + + _viewCountStage++; + } + } + + @EventHandler + public void markBlockForDemolition(PlayerInteractEvent event) + { + if (_state != SpeedBuildersState.BUILDING) + return; + + if (!_buildRecreations.containsKey(event.getPlayer())) + return; + + if (!UtilEvent.isAction(event, ActionType.L_BLOCK)) + return; + + if (_perfectBuild.containsKey(event.getPlayer())) + return; + + if (!_buildRecreations.get(event.getPlayer()).inBuildArea(event.getClickedBlock())) + return; + + if (event.getClickedBlock().getType() == Material.AIR) + return; + + _buildRecreations.get(event.getPlayer()).addToDemolition(event.getClickedBlock()); + } + + @EventHandler + public void markMobForDemolition(EntityDamageByEntityEvent event) + { + if (!(event.getDamager() instanceof Player)) + return; + + Player player = (Player) event.getDamager(); + + if (_state != SpeedBuildersState.BUILDING) + return; + + if (!_buildRecreations.containsKey(player)) + return; + + if (_perfectBuild.containsKey(player)) + return; + + if (!_buildRecreations.get(player).inBuildArea(event.getEntity().getLocation())) + return; + + _buildRecreations.get(player).addToDemolition(event.getEntity()); + } + + @EventHandler + public void updateDemolitionBlocks(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + return; + + for (RecreationData recreation : _buildRecreations.values()) + { + ArrayList blocksForDemolition = new ArrayList(recreation.BlocksForDemolition); + + for (DemolitionData demolition : blocksForDemolition) + { + if (_state != SpeedBuildersState.BUILDING || _perfectBuild.containsKey(demolition.Parent.Player)) + demolition.cancelBreak(); + else + demolition.update(); + } + } + } + + @EventHandler + public void preventBlockGrowth(BlockGrowEvent event) + { + event.setCancelled(true); + } + + @EventHandler + public void preventStructureGrowth(StructureGrowEvent event) + { + event.setCancelled(true); + } + + @EventHandler + public void judgeLooking(UpdateEvent event) + { + if (event.getType() != UpdateType.FASTEST) + return; + + if (!InProgress()) + return; + + if (_state != SpeedBuildersState.BUILDING && _state != SpeedBuildersState.VIEWING) + return; + + if (_buildRecreations.isEmpty()) + return; + + if (_lookTarget == null || (UtilTime.elapsed(_targetReached, _stayTime) && _standMoveProgress > 1)) + { + + RecreationData target = null; + + do + { + target = _buildRecreations.get(UtilAlg.Random(_buildRecreations.keySet())); + } + while (target.equals(_lastRecreationTarget) && _buildRecreations.size() > 1); + + _lookTarget = target.getMidpoint().subtract(UtilAlg.getTrajectory(_judgeEntity.getEyeLocation(), target.getMidpoint()).multiply(5)); + _stayTime = UtilMath.rRange(4000, 8000); + _lastRecreationTarget = target; + _standMoveProgress = 0; + + if (_lookStand != null) + _standStart = _lookStand.getLocation(); + } + + if (_lookStand == null) + { + _lookStand = WorldData.World.spawn(_judgeEntity.getEyeLocation().add(_judgeEntity.getEyeLocation().getDirection().multiply(10)), ArmorStand.class); + + _lookStand.setGravity(false); + _lookStand.setSmall(true); + _lookStand.setVisible(false); + _lookStand.setGhost(true); + _lookStand.setMarker(false); + + _standStart = _lookStand.getLocation(); + } + + if (_standMoveProgress > 1) + return; + + Location newLoc = _standStart.clone().add(UtilAlg.getTrajectory(_standStart, _lookTarget).multiply(UtilMath.offset(_standStart, _lookTarget) * _standMoveProgress)); + + moveEntity(newLoc, _lookStand); + + UtilEnt.CreatureLook(_judgeEntity, _lookStand); + + _standMoveProgress += 0.2; + + if (_standMoveProgress > 1) + _targetReached = System.currentTimeMillis(); + } + + private void moveEntity(Location loc, Entity entity) + { + double dx = loc.getX() - entity.getLocation().getX(); + double dy = loc.getY() - entity.getLocation().getY(); + double dz = loc.getZ() - entity.getLocation().getZ(); + + ((CraftEntity) entity).getHandle().move(dx, dy, dz); + } + + @EventHandler + public void specNightVision(UpdateEvent event) + { + if (!InProgress()) + return; + + if (event.getType() != UpdateType.SEC) + return; + + for (Player player : UtilServer.getPlayers()) + { + if (UtilPlayer.isSpectator(player) || (GetTeamList().size() > 1 && GetTeamList().get(1).HasPlayer(player))) + { + player.addPotionEffect(new PotionEffect(PotionEffectType.NIGHT_VISION, Integer.MAX_VALUE, 0, true, false), true); + player.addPotionEffect(new PotionEffect(PotionEffectType.WATER_BREATHING, Integer.MAX_VALUE, 0, true, false), true); + } + } + } + +// @EventHandler +// public void stopJudgeUnspec(UpdateEvent event) +// { +// if (event.getType() != UpdateType.TICK) +// return; +// +// if (!IsLive()) +// return; +// +// if (_state != SpeedBuilderState.REVIEWING) +// return; +// +// for (Player player : UtilServer.getPlayers()) +// { +// player.setGameMode(GameMode.SPECTATOR); +// player.setSpectatorTarget(_judgeEntity); +// +// if (!Manager.GetCondition().HasCondition(player, ConditionType.CLOAK, "Guardian POV")) +// Manager.GetCondition().Factory().Cloak("Guardian POV", player, null, 999999999, false, false); +// } +// } + + @EventHandler + public void stopGuardianSpecPickup(PlayerPickupItemEvent event) + { + if (GetState().ordinal() < GameState.Prepare.ordinal()) + return; + + if (Manager.isSpectator(event.getPlayer()) || GetTeamList().get(1).HasPlayer(event.getPlayer())) + event.setCancelled(true); + } + + @EventHandler + public void stopGuardianSpecPlace(BlockPlaceEvent event) + { + if (GetState().ordinal() < GameState.Prepare.ordinal()) + return; + + if (Manager.isSpectator(event.getPlayer()) || GetTeamList().get(1).HasPlayer(event.getPlayer())) + event.setCancelled(true); + } + + @EventHandler + public void stopEntityChangeBlock(EntityChangeBlockEvent event) + { + if (!IsLive()) + return; + + event.setCancelled(true); + } + + @EventHandler + public void stopBlockFade(BlockFadeEvent event) + { + if (!IsLive()) + return; + + event.setCancelled(true); + } + + @EventHandler + public void stopBlockBurn(BlockBurnEvent event) + { + if (!IsLive()) + return; + + event.setCancelled(true); + } + + @EventHandler + public void stopLeavesDecay(LeavesDecayEvent event) + { + if (!IsLive()) + return; + + event.setCancelled(true); + } + + @EventHandler + public void stopBlockForm(BlockFormEvent event) + { + if (!IsLive()) + return; + + event.setCancelled(true); + } + + @EventHandler + public void stopBlockSpread(BlockSpreadEvent event) + { + if (!IsLive()) + return; + + event.setCancelled(true); + } + + @EventHandler + public void stopLiquidLeaks(BlockFromToEvent event) + { + for (RecreationData recreation : _buildRecreations.values()) + { + if ((recreation.inBuildArea(event.getBlock()) && !recreation.inBuildArea(event.getToBlock())) || (!recreation.inBuildArea(event.getBlock()) && recreation.inBuildArea(event.getToBlock()))) + event.setCancelled(true); + } + } + + @EventHandler + public void stopPhysics(BlockPhysicsEvent event) + { + if (!IsLive()) + return; + + event.setCancelled(true); + } + + @EventHandler + public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) + { + if (!IsLive()) + return; + + if (_state != SpeedBuildersState.BUILDING) + return; + + if (!_buildRecreations.containsKey(event.getPlayer())) + return; + + if (_perfectBuild.containsKey(event.getPlayer())) + { + event.setCancelled(true); + return; + } + + Block liquid = event.getBlockClicked().getRelative(event.getBlockFace()); + + if (!_buildRecreations.get(event.getPlayer()).inBuildArea(liquid)) + { + event.setCancelled(true); + + UtilPlayer.message(event.getPlayer(), F.main("Build", "Cannot build outside your area!")); + } + } + + @EventHandler + public void onPlayerBucketFill(PlayerBucketFillEvent event) + { + if (!IsLive()) + return; + + if (_state != SpeedBuildersState.BUILDING) + return; + + if (!_buildRecreations.containsKey(event.getPlayer())) + return; + + if (_perfectBuild.containsKey(event.getPlayer())) + { + event.setCancelled(true); + return; + } + + Block liquid = event.getBlockClicked().getRelative(event.getBlockFace()); + + if (!_buildRecreations.get(event.getPlayer()).inBuildArea(liquid)) + { + event.setCancelled(true); + + UtilPlayer.message(event.getPlayer(), F.main("Build", "Cannot build outside your area!")); + } + } + + @EventHandler + public void addMob(PlayerInteractEvent event) + { + if (!IsLive()) + return; + + if (_state != SpeedBuildersState.BUILDING) + return; + + if (!UtilEvent.isAction(event, ActionType.R_BLOCK)) + return; + + if (event.getItem() == null) + return; + + if (event.getItem().getType() != Material.MONSTER_EGG) + return; + + if (!_buildRecreations.containsKey(event.getPlayer())) + return; + + EntityType type = EntityType.fromId(event.getItem().getDurability()); + + Block block = event.getClickedBlock().getRelative(event.getBlockFace()); + + if (!_buildRecreations.get(event.getPlayer()).inBuildArea(block)) + return; + + CreatureAllowOverride = true; + + Entity entity = block.getWorld().spawnEntity(block.getLocation().add(0.5, 0, 0.5), type); + + UtilEnt.Vegetate(entity, true); + UtilEnt.ghost(entity, true, false); + + CreatureAllowOverride = false; + + _buildRecreations.get(event.getPlayer()).Mobs.add(entity); + + UtilInv.remove(event.getPlayer(), Material.MONSTER_EGG, (byte) event.getItem().getDurability(), 1); + } + + @EventHandler + public void stopCombust(EntityCombustEvent event) + { + if (!IsLive()) + return; + + event.setCancelled(true); + } + + //Add to guardians before arcade manager adds to spectator to trick it into thinking the player is "alive" + @EventHandler(priority = EventPriority.LOW) + public void joinAddGuardian(PlayerJoinEvent event) + { + if (!InProgress()) + return; + + moveToGuardians(event.getPlayer(), false); + event.getPlayer().teleport(GetSpectatorLocation()); + + //We need to disguise a tick after + Manager.runSyncLater(new Runnable() + { + @Override + public void run() + { + DisguiseGuardian disguise = new DisguiseGuardian(event.getPlayer()); + disguise.setName(C.cGray + event.getPlayer().getName()); + disguise.setCustomNameVisible(true); + + Manager.GetDisguise().disguise(disguise); + + event.getPlayer().setAllowFlight(true); + event.getPlayer().setFlying(true); + } + }, 1); + } + + @EventHandler + public void setNextBuild(PlayerCommandPreprocessEvent event) + { + if (!event.getMessage().startsWith("/setnext ")) + return; + + event.setCancelled(true); + + if (!Manager.GetClients().Get(event.getPlayer()).GetRank().has(event.getPlayer(), Rank.MAPDEV, true)) + return; + + if (!Manager.getPlugin().getConfig().getString("serverstatus.group").equalsIgnoreCase("Testing")) + { + UtilPlayer.message(event.getPlayer(), F.main("Build", C.cYellow + "You can only use this on testing servers!")); + + return; + } + + String buildName = event.getMessage().substring(9); + + BuildData build = null; + + for (BuildData buildData : _buildData) + { + if (buildData.BuildText.toUpperCase().startsWith(buildName.toUpperCase())) + { + build = buildData; + + break; + } + } + + if (build == null) + UtilPlayer.message(event.getPlayer(), F.main("Build", "That build does not exist!")); + else + { + _nextBuild = build; + + UtilPlayer.message(event.getPlayer(), F.main("Build", "Set next build to " + F.elem(build.BuildText))); + } + } + + @Override + public void EndCheck() + { + if (!IsLive()) + return; + + GameTeam playersTeam = GetTeamList().get(0); + + if (playersTeam.GetPlayers(true).size() <= 1) + { + ArrayList places = playersTeam.GetPlacements(true); + + //Announce + AnnounceEnd(places); + + //Gems + if (places.size() >= 1) + AddGems(places.get(0), 20, "1st Place", false, false); + + if (places.size() >= 2) + AddGems(places.get(1), 15, "2nd Place", false, false); + + if (places.size() >= 3) + AddGems(places.get(2), 10, "3rd Place", false, false); + + for (Player player : GetPlayers(false)) + if (player.isOnline()) + AddGems(player, 10, "Participation", false, false); + + //End + SetState(GameState.End); + } + } + + @Override + public List getLosers() + { + List winners = getWinners(); + + if (winners == null) + return null; + + if (GetTeamList().size() < 2) + return new ArrayList(); + + List losers = GetTeamList().get(1).GetPlayers(false); + + losers.removeAll(winners); + losers.retainAll(GetTeamList().get(0).GetPlacements(true)); + + return losers; + } + + @Override + @EventHandler + public void ScoreboardUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + return; + + if (GetTeamList().isEmpty()) + return; + + Scoreboard.Reset(); + + Scoreboard.WriteBlank(); + + Scoreboard.Write(C.cYellowB + "Build"); + + if (_currentBuild == null) + Scoreboard.Write("(None)"); + else + Scoreboard.Write(C.cWhite + _currentBuild.BuildText); + + Scoreboard.WriteBlank(); + + Scoreboard.Write(C.cYellowB + "Round"); + Scoreboard.Write("" + _roundsPlayed); + + Scoreboard.WriteBlank(); + + List playersAlive = GetTeamList().get(0).GetPlayers(true); + + List playersDead = new ArrayList(); + + if (GetTeamList().size() > 1) + playersDead.addAll(GetTeamList().get(1).GetPlayers(false)); + + Scoreboard.Write(C.cYellowB + "Players"); + + for (Player player : playersAlive) + { + Scoreboard.Write(player.getName()); + } + + for (Player player : playersDead) + { + Scoreboard.Write(C.cGray + player.getName()); + } + + Scoreboard.Draw(); + } + + public Location getJudgeSpawn() + { + return _judgeSpawn; + } +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/SpeedBuildersState.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/SpeedBuildersState.java new file mode 100644 index 000000000..d79445240 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/SpeedBuildersState.java @@ -0,0 +1,10 @@ +package nautilus.game.arcade.game.games.speedbuilders; + +public enum SpeedBuildersState +{ + + VIEWING, + BUILDING, + REVIEWING; + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/BuildData.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/BuildData.java new file mode 100644 index 000000000..1f56c816d --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/BuildData.java @@ -0,0 +1,198 @@ +package nautilus.game.arcade.game.games.speedbuilders.data; + +import java.util.ArrayList; + +import mineplex.core.common.util.MapUtil; +import nautilus.game.arcade.game.games.speedbuilders.SpeedBuilders; +import net.minecraft.server.v1_8_R3.BlockPosition; +import net.minecraft.server.v1_8_R3.BlockStairs; +import net.minecraft.server.v1_8_R3.BlockStairs.EnumStairShape; +import net.minecraft.server.v1_8_R3.IBlockData; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.Sign; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.util.CraftMagicNumbers; +import org.bukkit.entity.EntityType; +import org.bukkit.material.Stairs; + +public class BuildData +{ + public SpeedBuilders Game; + + public Location BuildMin; + + public BlockState[][][] Build; + public BlockState[][] Ground; + + //Store stair shapes for stair fix + public EnumStairShape[][][] StairShapes; + + public String BuildText; + + public ArrayList Mobs = new ArrayList(); + + private int _timeAdd = 0; + private int _timeSubtract = 0; + private int _timeEqual = -1; + private double _timeMultiplier = 1.0; + + public BuildData(Location loc, String buildText, SpeedBuilders game) + { + Build = new BlockState[game.BuildSize][game.BuildSize][game.BuildSize]; + Ground = new BlockState[game.BuildSize][game.BuildSize]; + + StairShapes = new EnumStairShape[game.BuildSize][game.BuildSize][game.BuildSize]; + + Game = game; + + Location groundMin = loc.clone().subtract(game.BuildSizeDiv2, 11, game.BuildSizeDiv2); + + for (int x = 0; x < game.BuildSize; x++) + { + for (int z = 0; z < game.BuildSize; z++) + { + Ground[x][z] = groundMin.clone().add(x, 0, z).getBlock().getState(); + } + } + + parseText(buildText); + + Location buildMin = loc.clone().subtract(game.BuildSizeDiv2, 10, game.BuildSizeDiv2); + + BuildMin = buildMin; + + for (int x = 0; x < game.BuildSize; x++) + { + for (int y = 0; y < game.BuildSize; y++) + { + for (int z = 0; z < game.BuildSize; z++) + { + Block block = buildMin.clone().add(x, y, z).getBlock(); + + if (block.getType() == Material.SIGN_POST) + { + Sign sign = (Sign) block.getState(); + + EntityType type = null; + + try + { + type = EntityType.valueOf(sign.getLine(0).toUpperCase()); + } + catch (IllegalArgumentException e) + { + // Not a entity sign or someone messed up... + } + + if (type != null) + { + Mobs.add(new MobData(type, x, y, z)); + + MapUtil.QuickChangeBlockAt(block.getLocation(), Material.AIR); + } + } + + Build[x][y][z] = block.getState(); + + if (block.getState().getData() instanceof Stairs) + { + net.minecraft.server.v1_8_R3.Block nmsBlock = CraftMagicNumbers.getBlock(block); + + IBlockData blockData = nmsBlock.getBlockData(); + blockData = nmsBlock.updateState(blockData, ((CraftWorld) block.getWorld()).getHandle(), new BlockPosition(block.getX(), block.getY(), block.getZ())); + + StairShapes[x][y][z] = blockData.get(BlockStairs.SHAPE); + } + } + } + } + } + + private void parseText(String buildText) + { + StringBuilder sb = new StringBuilder(); + for (String part : buildText.split(" ")) + { + if (part.matches("^time[\\Q+-=\\E][0-9]+$")) + { + // + - = add subtract or set seconds + try + { + int num = Integer.parseInt(part.substring(5)); + switch (part.charAt(4)) + { + case '-': + _timeSubtract = num; + break; + case '=': + _timeEqual = num; + break; + default: + _timeAdd = num; + } + } + catch (NumberFormatException e) + { + System.out.println("Failed parsing data for customloc: " + buildText); + e.printStackTrace(); + } + } + else if (part.matches("^time\\*[0-9]*\\.?[0-9]+$")) + { + // * multiply by a number + try + { + double num = Double.parseDouble(part.substring(5)); + _timeMultiplier = num; + } + catch (NumberFormatException e) + { + System.out.println("Failed parsing data for customloc: " + buildText); + e.printStackTrace(); + } + } + else + { + sb.append(part + " "); + } + } + + BuildText = sb.toString().trim(); + } + + public int getBuildTime(int unmodified) + { + int newTime = unmodified; + newTime += _timeAdd; + newTime -= _timeSubtract; + newTime = (int) (_timeMultiplier * newTime); + if (_timeEqual != -1) newTime = _timeEqual; + + // limit to range of 5-60 seconds + return Math.min(Math.max(newTime, 5), 60); + } + + public int getPerfectScore() + { + int nonAirBlocks = 0; + + for (int x = 0; x < Game.BuildSize; x++) + { + for (int y = 0; y < Game.BuildSize; y++) + { + for (int z = 0; z < Game.BuildSize; z++) + { + if (Build[x][y][z].getType() != Material.AIR) + nonAirBlocks++; + } + } + } + + return nonAirBlocks + Mobs.size(); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/DemolitionData.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/DemolitionData.java new file mode 100644 index 000000000..f53f653c0 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/DemolitionData.java @@ -0,0 +1,227 @@ +package nautilus.game.arcade.game.games.speedbuilders.data; + +import java.util.ArrayList; + +import mineplex.core.common.util.MapUtil; +import mineplex.core.common.util.NautHashMap; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilTime; +import mineplex.core.hologram.Hologram; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Item; +import org.bukkit.inventory.ItemStack; +import org.bukkit.material.Bed; +import org.bukkit.material.Door; + +public class DemolitionData +{ + + public RecreationData Parent; + + public NautHashMap Blocks; + public ArrayList Mobs; + + public long Start; + + private Hologram _hologram; + + private boolean _flickerAir = true; + private long _lastFlicker = System.currentTimeMillis(); + + public DemolitionData(RecreationData parent, ArrayList blocks, ArrayList mobs) + { + Parent = parent; + + Blocks = new NautHashMap(); + Mobs = mobs; + + for (Block block : blocks) + { + Blocks.put(block, block.getState()); + } + + Start = System.currentTimeMillis(); + + spawnHologram(); + } + + public void spawnHologram() + { + if (Parent.Game.InstaBreak) + return; + + Location loc = Parent.getMidpoint(); + + if (!Blocks.isEmpty()) + loc = Blocks.keySet().iterator().next().getLocation().add(0.5, 0.5, 0.5); + else if (!Mobs.isEmpty()) + loc = UtilAlg.Random(Mobs).getLocation().add(0, 1, 0); + + _hologram = new Hologram(Parent.Game.Manager.getHologramManager(), loc, "3"); + + _hologram.start(); + } + + public void despawnHologram() + { + if (_hologram == null) + return; + + _hologram.stop(); + + _hologram = null; + } + + public void update() + { + if (Parent.Game.InstaBreak) + { + breakBlocks(); + + return; + } + + if (_hologram == null) + spawnHologram(); + + int secondsLeft = (int) Math.ceil((3000 - (System.currentTimeMillis() - Start)) / 1000.0D); + + if (secondsLeft < 0) + secondsLeft = 0; + + _hologram.setText("" + secondsLeft); + + if (UtilTime.elapsed(_lastFlicker, 500)) + { + _lastFlicker = System.currentTimeMillis(); + + for (Block block : Blocks.keySet()) + { + if (_flickerAir) + MapUtil.QuickChangeBlockAt(block.getLocation(), Material.AIR); + else + Blocks.get(block).update(true, false); + } + + for (Entity entity : Mobs) + { + if (_flickerAir) + UtilEnt.ghost(entity, true, true); + else + UtilEnt.ghost(entity, true, false); + } + + _flickerAir = !_flickerAir; + } + + if (secondsLeft == 0) + breakBlocks(); + } + + public void cancelBreak() + { + despawnHologram(); + + for (Block block : Blocks.keySet()) + { + Blocks.get(block).update(true, false); + } + + for (Entity entity : Mobs) + { + UtilEnt.ghost(entity, true, false); + } + + Parent.BlocksForDemolition.remove(this); + } + + public void breakBlocks() + { + despawnHologram(); + + //Effect will play for all blocks even two-parted ones + for (Block block : Blocks.keySet()) + { + Blocks.get(block).update(true, false); + + block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getTypeId()); + } + + for (Block block : Blocks.keySet()) + { + if (block.getType() == Material.AIR) + continue; + + //Ignore top double plant blocks + if (block.getType() == Material.DOUBLE_PLANT) + { + if (block.getData() > 7) + continue; + } + + for (ItemStack itemStack : UtilBlock.blockToInventoryItemStacks(block)) + { + Item item = block.getWorld().dropItem(block.getLocation().add(0.5, 0.5, 0.5), itemStack); + + Parent.DroppedItems.put(item, System.currentTimeMillis()); + } + + //Destroy the other part + if (block.getType() == Material.BED_BLOCK) + { + Bed bed = (Bed) block.getState().getData(); + + if (bed.isHeadOfBed()) + MapUtil.QuickChangeBlockAt(block.getRelative(bed.getFacing().getOppositeFace()).getLocation(), Material.AIR); + else + MapUtil.QuickChangeBlockAt(block.getRelative(bed.getFacing()).getLocation(), Material.AIR); + } + else if (block.getType() == Material.WOODEN_DOOR || block.getType() == Material.IRON_DOOR_BLOCK || block.getType() == Material.SPRUCE_DOOR || block.getType() == Material.BIRCH_DOOR || block.getType() == Material.JUNGLE_DOOR || block.getType() == Material.ACACIA_DOOR || block.getType() == Material.DARK_OAK_DOOR) + { + Door door = (Door) block.getState().getData(); + + if (door.isTopHalf()) + MapUtil.QuickChangeBlockAt(block.getRelative(BlockFace.DOWN).getLocation(), Material.AIR); + else + MapUtil.QuickChangeBlockAt(block.getRelative(BlockFace.UP).getLocation(), Material.AIR); + } + else if (block.getType() == Material.DOUBLE_PLANT) + { + //The top block does not carry the correct data + if (block.getData() <= 7) + MapUtil.QuickChangeBlockAt(block.getRelative(BlockFace.UP).getLocation(), Material.AIR); + else + MapUtil.QuickChangeBlockAt(block.getLocation(), Material.AIR); + } + + MapUtil.QuickChangeBlockAt(block.getLocation(), Material.AIR); + } + + for (Entity entity : Mobs) + { + ItemStack spawnEgg = new ItemStack(Material.MONSTER_EGG, 1, entity.getType().getTypeId()); + + Item item = entity.getWorld().dropItem(entity.getLocation().add(0, 1, 0), spawnEgg); + + Parent.DroppedItems.put(item, System.currentTimeMillis()); + + entity.remove(); + + Parent.Mobs.remove(entity); + } + + Parent.BlocksForDemolition.remove(this); + + Parent.Game.checkPerfectBuild(Parent.Player); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/MobData.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/MobData.java new file mode 100644 index 000000000..51858381c --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/MobData.java @@ -0,0 +1,23 @@ +package nautilus.game.arcade.game.games.speedbuilders.data; + +import org.bukkit.entity.EntityType; + +public class MobData +{ + + public EntityType EntityType; + + public int DX; + public int DY; + public int DZ; + + public MobData(EntityType entityType, int dx, int dy, int dz) + { + EntityType = entityType; + + DX = dx; + DY = dy; + DZ = dz; + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/RecreationData.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/RecreationData.java new file mode 100644 index 000000000..11aaac85a --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/data/RecreationData.java @@ -0,0 +1,444 @@ +package nautilus.game.arcade.game.games.speedbuilders.data; + +import java.util.ArrayList; +import java.util.List; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.MapUtil; +import mineplex.core.common.util.NautHashMap; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilInv; +import mineplex.core.hologram.Hologram; +import nautilus.game.arcade.game.games.speedbuilders.SpeedBuilders; +import net.minecraft.server.v1_8_R3.BlockPosition; +import net.minecraft.server.v1_8_R3.BlockStairs; +import net.minecraft.server.v1_8_R3.BlockStairs.EnumStairShape; +import net.minecraft.server.v1_8_R3.IBlockData; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.util.CraftMagicNumbers; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.material.Bed; +import org.bukkit.material.Door; +import org.bukkit.material.Stairs; +import org.bukkit.util.Vector; + +public class RecreationData +{ + + public SpeedBuilders Game; + + public Player Player; + + public BlockState[][] DefaultGround; + + public Location OriginalBuildLocation; + + public Location CornerA; + public Location CornerB; + + public Location PlayerSpawn; + + public NautHashMap DroppedItems = new NautHashMap(); + + public ArrayList BlocksForDemolition = new ArrayList(); + + public ArrayList Mobs = new ArrayList(); + + private Hologram _hologram; + + public RecreationData(SpeedBuilders game, Player player, Location loc, Location playerSpawn) + { + Game = game; + + DefaultGround = new BlockState[game.BuildSize][game.BuildSize]; + + Player = player; + + OriginalBuildLocation = loc; + + CornerA = loc.clone().subtract(game.BuildSizeDiv2, 0, game.BuildSizeDiv2); + CornerB = loc.clone().add(game.BuildSizeDiv2, game.BuildSizeMin1, game.BuildSizeDiv2); + + PlayerSpawn = playerSpawn; + + for (int x = 0; x < game.BuildSize; x++) + { + for (int z = 0; z < game.BuildSize; z++) + { + DefaultGround[x][z] = CornerA.clone().add(x, -1, z).getBlock().getState(); + } + } + + Vector mid = game.getJudgeSpawn().toVector().subtract(loc.toVector()).multiply(0.4); + Location hologramLocation = loc.clone().add(mid).add(0, 1, 0); + Location above = loc.clone().add(0.5, game.BuildSize + 0.5, 0.5); + _hologram = new Hologram(game.getArcadeManager().getHologramManager(), hologramLocation, C.cYellow + player.getName()); + _hologram.start(); + } + + public boolean inBuildArea(Block block) + { + if (block.getX() < Math.min(CornerA.getBlockX(), CornerB.getBlockX())) + return false; + + if (block.getY() < Math.min(CornerA.getBlockY(), CornerB.getBlockY())) + return false; + + if (block.getZ() < Math.min(CornerA.getBlockZ(), CornerB.getBlockZ())) + return false; + + if (block.getX() > Math.max(CornerA.getBlockX(), CornerB.getBlockX())) + return false; + + if (block.getY() > Math.max(CornerA.getBlockY(), CornerB.getBlockY())) + return false; + + if (block.getZ() > Math.max(CornerA.getBlockZ(), CornerB.getBlockZ())) + return false; + + return true; + } + + public boolean inBuildArea(Location loc) + { + if (loc.getX() < Math.min(CornerA.getBlockX(), CornerB.getBlockX())) + return false; + + if (loc.getY() < Math.min(CornerA.getBlockY(), CornerB.getBlockY())) + return false; + + if (loc.getZ() < Math.min(CornerA.getBlockZ(), CornerB.getBlockZ())) + return false; + + if (loc.getX() > Math.max(CornerA.getBlockX(), CornerB.getBlockX()) + 1) + return false; + + if (loc.getY() > Math.max(CornerA.getBlockY(), CornerB.getBlockY()) + 1) + return false; + + if (loc.getZ() > Math.max(CornerA.getBlockZ(), CornerB.getBlockZ()) + 1) + return false; + + return true; + } + + public void clearBuildArea(boolean resetGround) + { + for (Block block : getBlocks()) + { + MapUtil.QuickChangeBlockAt(block.getLocation(), Material.AIR); + } + + for (Entity entity : Mobs) + { + entity.remove(); + } + + Mobs.clear(); + + if (resetGround) + { + for (int x = 0; x < Game.BuildSize; x++) + { + for (int z = 0; z < Game.BuildSize; z++) + { + MapUtil.QuickChangeBlockAt(CornerA.clone().add(x, -1, z), DefaultGround[x][z].getType(), DefaultGround[x][z].getRawData()); + } + } + } + } + + public void pasteBuildData(BuildData buildData) + { + clearBuildArea(true); + + for (int x = 0; x < Game.BuildSize; x++) + { + for (int z = 0; z < Game.BuildSize; z++) + { + MapUtil.QuickChangeBlockAt(CornerA.clone().add(x, -1, z), buildData.Ground[x][z].getType(), buildData.Ground[x][z].getRawData()); + } + } + + for (int x = 0; x < Game.BuildSize; x++) + { + for (int y = 0; y < Game.BuildSize; y++) + { + for (int z = 0; z < Game.BuildSize; z++) + { + MapUtil.QuickChangeBlockAt(CornerA.clone().add(x, y, z), buildData.Build[x][y][z].getType(), buildData.Build[x][y][z].getRawData()); + } + } + } + + Game.CreatureAllowOverride = true; + + for (MobData mobData : buildData.Mobs) + { + Location loc = CornerA.clone().add(mobData.DX + 0.5, mobData.DY, mobData.DZ + 0.5); + + Entity entity = loc.getWorld().spawnEntity(loc, mobData.EntityType); + + UtilEnt.Vegetate(entity, true); + UtilEnt.ghost(entity, true, false); + + Mobs.add(entity); + } + + Game.CreatureAllowOverride = false; + } + + public void breakAndDropItems() + { + for (Block block : getBlocks()) + { + if (block.getType() == Material.AIR) + continue; + + //Ignore top double plant blocks + if (block.getType() == Material.DOUBLE_PLANT) + { + if (block.getData() > 7) + continue; + } + + for (ItemStack itemStack : UtilBlock.blockToInventoryItemStacks(block)) + { + UtilInv.insert(Player, itemStack); + } + + //Destroy the other part + if (block.getType() == Material.BED_BLOCK) + { + Bed bed = (Bed) block.getState().getData(); + + if (bed.isHeadOfBed()) + MapUtil.QuickChangeBlockAt(block.getRelative(bed.getFacing().getOppositeFace()).getLocation(), Material.AIR); + else + MapUtil.QuickChangeBlockAt(block.getRelative(bed.getFacing()).getLocation(), Material.AIR); + } + else if (block.getType() == Material.WOODEN_DOOR || block.getType() == Material.IRON_DOOR_BLOCK || block.getType() == Material.SPRUCE_DOOR || block.getType() == Material.BIRCH_DOOR || block.getType() == Material.JUNGLE_DOOR || block.getType() == Material.ACACIA_DOOR || block.getType() == Material.DARK_OAK_DOOR) + { + Door door = (Door) block.getState().getData(); + + if (door.isTopHalf()) + MapUtil.QuickChangeBlockAt(block.getRelative(BlockFace.DOWN).getLocation(), Material.AIR); + else + MapUtil.QuickChangeBlockAt(block.getRelative(BlockFace.UP).getLocation(), Material.AIR); + } + else if (block.getType() == Material.DOUBLE_PLANT) + { + //The top block does not carry the correct data + if (block.getData() <= 7) + MapUtil.QuickChangeBlockAt(block.getRelative(BlockFace.UP).getLocation(), Material.AIR); + else + MapUtil.QuickChangeBlockAt(block.getLocation(), Material.AIR); + } + } + + for (Entity entity : Mobs) + { + ItemStack spawnEgg = new ItemStack(Material.MONSTER_EGG, 1, entity.getType().getTypeId()); + + UtilInv.insert(Player, spawnEgg); + } + + CornerA.getWorld().playEffect(getMidpoint(), Effect.STEP_SOUND, Material.LOG.getId()); + + clearBuildArea(false); + } + + public boolean isEmptyBuild(BuildData buildData) + { + for (Block block : getBlocks()) + { + if (block.getType() != Material.AIR) + return false; + } + + if (!buildData.Mobs.isEmpty()) + return Mobs.isEmpty(); + + return true; + } + + public int calculateScoreFromBuild(BuildData buildData) + { + int score = 0; + + for (int x = 0; x < Game.BuildSize; x++) + { + for (int y = 0; y < Game.BuildSize; y++) + { + for (int z = 0; z < Game.BuildSize; z++) + { + Block currentBlock = CornerA.clone().add(x, y, z).getBlock(); + BlockState expectedState = buildData.Build[x][y][z]; + + if (expectedState.getType() == Material.AIR) + continue; + + if (expectedState.getType() == currentBlock.getType() && expectedState.getRawData() == currentBlock.getData()) + { + score++; + continue; + } + + //Ender portal direction fix & 0x4 is a check to see if the frame has an ender eye in it + if (currentBlock.getType() == Material.ENDER_PORTAL_FRAME && expectedState.getType() == Material.ENDER_PORTAL_FRAME && (currentBlock.getData() & 0x4) == (expectedState.getRawData() & 0x4)) + { + score++; + continue; + } + + //Sapling growth fix + if (expectedState.getType() == Material.SAPLING && currentBlock.getType() == Material.SAPLING) + { + if (currentBlock.getData() % 8 == expectedState.getRawData() % 8) + score++; + } + + //Fix for leaves decay flags + if ((expectedState.getType() == Material.LEAVES && currentBlock.getType() == Material.LEAVES) || ((expectedState.getType() == Material.LEAVES_2 && currentBlock.getType() == Material.LEAVES_2))) + { + if (currentBlock.getData() % 4 == expectedState.getRawData() % 4) + score++; + } + + //Fix for corner stair shape + if (currentBlock.getState().getData() instanceof Stairs && expectedState.getData() instanceof Stairs) + { + net.minecraft.server.v1_8_R3.Block nmsBlock = CraftMagicNumbers.getBlock(currentBlock); + + IBlockData blockData = nmsBlock.getBlockData(); + blockData = nmsBlock.updateState(blockData, ((CraftWorld) currentBlock.getWorld()).getHandle(), new BlockPosition(currentBlock.getX(), currentBlock.getY(), currentBlock.getZ())); + + EnumStairShape expectedShape = buildData.StairShapes[x][y][z]; + EnumStairShape currentShape = blockData.get(BlockStairs.SHAPE); + + if ((expectedShape == EnumStairShape.INNER_LEFT && currentShape == EnumStairShape.INNER_RIGHT) || (expectedShape == EnumStairShape.INNER_RIGHT && currentShape == EnumStairShape.INNER_LEFT) || (expectedShape == EnumStairShape.OUTER_LEFT && currentShape == EnumStairShape.OUTER_RIGHT) || (expectedShape == EnumStairShape.OUTER_RIGHT && currentShape == EnumStairShape.OUTER_LEFT)) + score++; + } + } + } + } + + for (MobData mobData : buildData.Mobs) + { + for (Entity entity : Mobs) + { + int dx = (int) (entity.getLocation().getX() - (CornerA.getX() + 0.5)); + int dy = (int) (entity.getLocation().getY() - CornerA.getY()); + int dz = (int) (entity.getLocation().getZ() - (CornerA.getZ() + 0.5)); + + if (mobData.EntityType == entity.getType() && mobData.DX == dx && mobData.DY == dy && mobData.DZ == dz) + { + score++; + + break; + } + } + } + + return score; + } + + public Location getMidpoint() + { + return UtilAlg.getMidpoint(CornerA, CornerB.clone().add(1, 1, 1)); + } + + public List getBlocks() + { + return UtilBlock.getInBoundingBox(CornerA, CornerB); + } + + public boolean isQueuedForDemolition(Block block) + { + for (DemolitionData demolition : BlocksForDemolition) + { + if (demolition.Blocks.containsKey(block)) + return true; + } + + return false; + } + + public boolean isQueuedForDemolition(Entity entity) + { + for (DemolitionData demolition : BlocksForDemolition) + { + if (demolition.Mobs.contains(entity)) + return true; + } + + return false; + } + + public void addToDemolition(Block block) + { + if (isQueuedForDemolition(block)) + return; + + ArrayList blocks = new ArrayList(); + blocks.add(block); + + //Add the other part of the block + if (block.getType() == Material.BED_BLOCK) + { + Bed bed = (Bed) block.getState().getData(); + + if (bed.isHeadOfBed()) + blocks.add(block.getRelative(bed.getFacing().getOppositeFace())); + else + blocks.add(block.getRelative(bed.getFacing())); + } + else if (block.getType() == Material.WOODEN_DOOR || block.getType() == Material.IRON_DOOR_BLOCK || block.getType() == Material.SPRUCE_DOOR || block.getType() == Material.BIRCH_DOOR || block.getType() == Material.JUNGLE_DOOR || block.getType() == Material.ACACIA_DOOR || block.getType() == Material.DARK_OAK_DOOR) + { + Door door = (Door) block.getState().getData(); + + if (door.isTopHalf()) + blocks.add(block.getRelative(BlockFace.DOWN)); + else + blocks.add(block.getRelative(BlockFace.UP)); + } + else if (block.getType() == Material.DOUBLE_PLANT) + { + if (block.getData() > 7) + blocks.add(block.getRelative(BlockFace.DOWN)); + else + blocks.add(block.getRelative(BlockFace.UP)); + } + + BlocksForDemolition.add(new DemolitionData(this, blocks, new ArrayList())); + } + + public void addToDemolition(Entity entity) + { + if (isQueuedForDemolition(entity)) + return; + + ArrayList mobs = new ArrayList(); + mobs.add(entity); + + BlocksForDemolition.add(new DemolitionData(this, new ArrayList(), mobs)); + } + + public void removeHologram() + { + _hologram.stop(); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/events/PerfectBuildEvent.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/events/PerfectBuildEvent.java new file mode 100644 index 000000000..a2fcc31e9 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/events/PerfectBuildEvent.java @@ -0,0 +1,50 @@ +package nautilus.game.arcade.game.games.speedbuilders.events; + +import nautilus.game.arcade.game.games.speedbuilders.SpeedBuilders; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class PerfectBuildEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + + private Player _player; + private SpeedBuilders _game; + private long _timeElapsed; // Build time elapsed in ms + + public PerfectBuildEvent(Player player, long timeElapsed, SpeedBuilders game) + { + _player = player; + _timeElapsed = timeElapsed; + _game = game; + } + + public Player getPlayer() + { + return _player; + } + + public long getTimeElapsed() + { + return _timeElapsed; + } + + public SpeedBuilders getGame() + { + return _game; + } + + public static HandlerList getHandlerList() + { + return handlers; + } + + @Override + public HandlerList getHandlers() + { + return handlers; + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/kits/DefaultKit.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/kits/DefaultKit.java new file mode 100644 index 000000000..ff79b7fc0 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/kits/DefaultKit.java @@ -0,0 +1,34 @@ +package nautilus.game.arcade.game.games.speedbuilders.kits; + +import nautilus.game.arcade.ArcadeManager; +import nautilus.game.arcade.kit.Kit; +import nautilus.game.arcade.kit.KitAvailability; +import nautilus.game.arcade.kit.Perk; + +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; + +public class DefaultKit extends Kit +{ + + public DefaultKit(ArcadeManager manager) + { + super(manager, "Speed Builder", KitAvailability.Free, + new String[] + { + "Professional build recreator!", + }, + new Perk[] + { + + }, + EntityType.ZOMBIE, null); + } + + @Override + public void GiveItems(Player player) + { + + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/DependableTracker.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/DependableTracker.java new file mode 100644 index 000000000..2996d9db2 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/DependableTracker.java @@ -0,0 +1,23 @@ +package nautilus.game.arcade.game.games.speedbuilders.stattrackers; + +import nautilus.game.arcade.game.games.speedbuilders.SpeedBuilders; +import nautilus.game.arcade.game.games.speedbuilders.events.PerfectBuildEvent; +import nautilus.game.arcade.stats.StatTracker; + +import org.bukkit.event.EventHandler; + +public class DependableTracker extends StatTracker +{ + + public DependableTracker(SpeedBuilders game) + { + super(game); + } + + @EventHandler + public void onPerfectBuild(PerfectBuildEvent event) + { + addStat(event.getPlayer(), "PerfectBuild", 1, false, false); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/FirstBuildTracker.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/FirstBuildTracker.java new file mode 100644 index 000000000..c79c55e41 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/FirstBuildTracker.java @@ -0,0 +1,30 @@ +package nautilus.game.arcade.game.games.speedbuilders.stattrackers; + +import org.bukkit.event.EventHandler; + +import nautilus.game.arcade.game.games.speedbuilders.SpeedBuilders; +import nautilus.game.arcade.game.games.speedbuilders.events.PerfectBuildEvent; +import nautilus.game.arcade.stats.StatTracker; + +public class FirstBuildTracker extends StatTracker +{ + + private boolean _first = true; + + public FirstBuildTracker(SpeedBuilders game) + { + super(game); + } + + @EventHandler + public void onPerfectBuild(PerfectBuildEvent event) + { + if (_first) + { + addStat(event.getPlayer(), "PerfectFirst", 1, false, false); + + _first = false; + } + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/PerfectionistTracker.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/PerfectionistTracker.java new file mode 100644 index 000000000..02de00fc5 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/PerfectionistTracker.java @@ -0,0 +1,50 @@ +package nautilus.game.arcade.game.games.speedbuilders.stattrackers; + +import java.util.Map.Entry; + +import mineplex.core.common.util.NautHashMap; +import nautilus.game.arcade.events.GameStateChangeEvent; +import nautilus.game.arcade.game.Game.GameState; +import nautilus.game.arcade.game.games.speedbuilders.SpeedBuilders; +import nautilus.game.arcade.game.games.speedbuilders.events.PerfectBuildEvent; +import nautilus.game.arcade.stats.StatTracker; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; + +public class PerfectionistTracker extends StatTracker +{ + + private SpeedBuilders _game; + + private NautHashMap _perfectBuilds = new NautHashMap(); + + public PerfectionistTracker(SpeedBuilders game) + { + super(game); + + _game = game; + } + + @EventHandler + public void onPerfectBuild(PerfectBuildEvent event) + { + int previousPerfectBuilds = _perfectBuilds.containsKey(event.getPlayer()) ? _perfectBuilds.get(event.getPlayer()) : 0; + + _perfectBuilds.put(event.getPlayer(), previousPerfectBuilds + 1); + } + + @EventHandler + public void onEnd(GameStateChangeEvent event) + { + if (event.GetState() != GameState.End) + return; + + for (Entry entry : _perfectBuilds.entrySet()) + { + if (entry.getValue().intValue() == _game.getRoundsPlayed()) + addStat(entry.getKey(), "PerfectWins", 1, true, false); + } + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/SpeediestBuilderizerTracker.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/SpeediestBuilderizerTracker.java new file mode 100644 index 000000000..800277a22 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/speedbuilders/stattrackers/SpeediestBuilderizerTracker.java @@ -0,0 +1,23 @@ +package nautilus.game.arcade.game.games.speedbuilders.stattrackers; + +import org.bukkit.event.EventHandler; + +import nautilus.game.arcade.game.games.speedbuilders.SpeedBuilders; +import nautilus.game.arcade.game.games.speedbuilders.events.PerfectBuildEvent; +import nautilus.game.arcade.stats.StatTracker; + +public class SpeediestBuilderizerTracker extends StatTracker +{ + public SpeediestBuilderizerTracker(SpeedBuilders game) + { + super(game); + } + + @EventHandler + public void onPerfectBuild(PerfectBuildEvent event) + { + if (event.getTimeElapsed() < 10000) // 10 Seconds + addStat(event.getPlayer(), "SpeediestBuilderizer", 1, true, false); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/typewars/Minion.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/typewars/Minion.java index b4c4832cf..91d05aef2 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/typewars/Minion.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/typewars/Minion.java @@ -122,7 +122,7 @@ public class Minion "Purpose", "Symptom", "Sticks", "Measure", "Slimes", "Greece", "Spooky", "Coffee", "Aliens", "Cities", "Bikini", "Mortal", "Serena", "Future", "Bottle", "Helmet", "Crunch", "Afraid", "Threat", "Static", "Happy", "Knife", "Scary", "Lapis", "Skirt", "Waves", "Calem", "Clock", "Taste", "Lucas", - "Anger", "Spork", "Maike", "Candy", "Shirt", "Tides", "Ocean", "Crawl", "Smell", "React", + "Anger", "Spork", "Make", "Candy", "Shirt", "Tides", "Ocean", "Crawl", "Smell", "React", "Dolls", "Roses", "Trips", "Flute", "Pants", "Brick", "Three", "Ethan", "Uncle", "Lunch", "Legos", "Tulip", "Beach", "Wipes", "Heels", "Straw", "Seven", "Hands", "Queen", "Books", "Couch", "Grass", "Clans", "Frame", "Nails", "Cream", "Eight", "Belly", "Crown", "Polls", diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/spectatorMenu/button/SpectatorButton.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/spectatorMenu/button/SpectatorButton.java index fa5b7e111..d2f170f5f 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/spectatorMenu/button/SpectatorButton.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/spectatorMenu/button/SpectatorButton.java @@ -1,10 +1,15 @@ package nautilus.game.arcade.gui.spectatorMenu.button; +import org.bukkit.GameMode; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; +import mineplex.core.common.util.C; import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTextBottom; import mineplex.core.shop.item.IButton; import nautilus.game.arcade.ArcadeManager; @@ -33,7 +38,26 @@ public class SpectatorButton implements IButton if (_arcadeManager.IsAlive(_target)) { - _player.teleport(_target.getLocation().add(0, 1, 0)); + if(clickType == ClickType.RIGHT) + { + _player.closeInventory(); + _player.teleport(_target.getLocation().add(0, 1, 0)); + _arcadeManager.runSyncLater(new Runnable() + { + @Override + public void run() + { + _player.setGameMode(GameMode.SPECTATOR); + _player.setSpectatorTarget(_target); + UtilTextBottom.display(C.cYellow + "You are spectating " + F.game(_target.getName()), player); + UtilPlayer.message(_player, F.main("Game", "Sneak to stop spectating")); + } + }, 3); + } + else + { + _player.teleport(_target.getLocation().add(0, 1, 0)); + } } else { diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/spectatorMenu/page/SpectatorPage.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/spectatorMenu/page/SpectatorPage.java index 1b687bb71..5a2a4fe36 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/spectatorMenu/page/SpectatorPage.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/spectatorMenu/page/SpectatorPage.java @@ -228,7 +228,8 @@ public class SpectatorPage extends lore.add(ChatColor.RESET + C.cYellow + "Height Difference: " + C.cWhite + UtilMath.trim(1, heightDifference)); lore.add(" "); - lore.add(ChatColor.RESET + C.Line + "Click to Spectate"); + lore.add(ChatColor.YELLOW + "Left Click" + ChatColor.RESET + " Teleport"); + lore.add(ChatColor.YELLOW + "Right Click" + ChatColor.RESET + " Spectate"); SkullMeta skullMeta = ((SkullMeta) item.getItemMeta()); skullMeta.setOwner(other.getName()); skullMeta.setDisplayName(team.GetColor() + other.getName()); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java index 1e51b1d42..ef31b741b 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java @@ -97,6 +97,7 @@ public class GameCreationManager implements Listener { Game game = gameIterator.next(); + game.disable(); HandlerList.unregisterAll(game); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameFlagManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameFlagManager.java index f0533de91..ff47122fb 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameFlagManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameFlagManager.java @@ -888,7 +888,7 @@ public class GameFlagManager implements Listener for (Player player : UtilServer.getPlayers()) { if (!game.isInsideMap(player) && game.IsAlive(player)) - { + { //Riding a Projectile, edgecase if (player.getVehicle() != null && player.getVehicle() instanceof Projectile) { @@ -897,38 +897,36 @@ public class GameFlagManager implements Listener ((CraftPlayer)player).getHandle().spectating = false; } - if (!Manager.IsAlive(player) || ((CraftPlayer)player).getHandle().spectating) + if (!game.WorldBoundaryKill) { - player.teleport(game.GetSpectatorLocation()); + UtilPlayer.message(player, C.cRed + C.Bold + "WARNING: " + C.cWhite + C.Bold + "RETURN TO PLAYABLE AREA!"); + + if (game.GetType() != GameType.Gravity) + { + if (player.getLocation().getY() > game.WorldData.MaxY) + UtilAction.velocity(player, UtilAlg.getTrajectory2d(player.getLocation(), game.GetSpectatorLocation()), 1, true, 0, 0, 10, true); + else + UtilAction.velocity(player, UtilAlg.getTrajectory2d(player.getLocation(), game.GetSpectatorLocation()), 1, true, 0.4, 0, 10, true); + } + + Manager.GetDamage().NewDamageEvent(player, null, null, + DamageCause.VOID, 4, false, false, false, + "Border", "Border Damage"); + + player.getWorld().playSound(player.getLocation(), Sound.NOTE_BASS, 2f, 1f); + player.getWorld().playSound(player.getLocation(), Sound.NOTE_BASS, 2f, 1f); } else { - if (!game.WorldBoundaryKill) - { - UtilPlayer.message(player, C.cRed + C.Bold + "WARNING: " + C.cWhite + C.Bold + "RETURN TO PLAYABLE AREA!"); - - if (game.GetType() != GameType.Gravity) - { - if (player.getLocation().getY() > game.WorldData.MaxY) - UtilAction.velocity(player, UtilAlg.getTrajectory2d(player.getLocation(), game.GetSpectatorLocation()), 1, true, 0, 0, 10, true); - else - UtilAction.velocity(player, UtilAlg.getTrajectory2d(player.getLocation(), game.GetSpectatorLocation()), 1, true, 0.4, 0, 10, true); - } - - Manager.GetDamage().NewDamageEvent(player, null, null, - DamageCause.VOID, 4, false, false, false, - "Border", "Border Damage"); - - player.getWorld().playSound(player.getLocation(), Sound.NOTE_BASS, 2f, 1f); - player.getWorld().playSound(player.getLocation(), Sound.NOTE_BASS, 2f, 1f); - } - else - { - Manager.GetDamage().NewDamageEvent(player, null, null, - DamageCause.VOID, 9001, false, false, false, - "Border", "Border Damage"); - } - } + Manager.GetDamage().NewDamageEvent(player, null, null, + DamageCause.VOID, 9001, false, false, false, + "Border", "Border Damage"); + } + } + + if (!game.isInsideMap(player) && (!Manager.IsAlive(player) || ((CraftPlayer)player).getHandle().spectating)) + { + player.teleport(game.GetSpectatorLocation()); } } } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameSpectatorManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameSpectatorManager.java index f82d75403..0082fc1ce 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameSpectatorManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameSpectatorManager.java @@ -1,15 +1,34 @@ package nautilus.game.arcade.managers; +import java.util.List; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTextBottom; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; import nautilus.game.arcade.ArcadeManager; import nautilus.game.arcade.game.Game.GameState; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerToggleSneakEvent; import org.bukkit.event.vehicle.VehicleDamageEvent; +import org.bukkit.inventory.ItemStack; public class GameSpectatorManager implements Listener { @@ -22,9 +41,9 @@ public class GameSpectatorManager implements Listener Manager.getPluginManager().registerEvents(this, Manager.getPlugin()); } - @EventHandler(priority = EventPriority.LOW) + @EventHandler(priority = EventPriority.LOW, ignoreCancelled=true) public void interactCancel(PlayerInteractEvent event) - { + { if (Manager.GetGame() == null) return; @@ -32,6 +51,56 @@ public class GameSpectatorManager implements Listener if (!Manager.GetGame().IsAlive(player)) event.setCancelled(true); + + processClick(player, event.getAction()); + } + + public void processClick(Player player, Action action) + { + if (Manager.GetGame() == null) + return; + + if(!Manager.GetGame().AllowEntitySpectate) + return; + + if(!Manager.GetGame().IsLive()) + return; + + if(player.getGameMode() != GameMode.SPECTATOR) + return; + + if(player.getSpectatorTarget() == null) + return; + + if(!(player.getSpectatorTarget() instanceof Player)) + return; + + List players = Manager.GetGame().GetPlayers(true); + int currentPlayer = 0; + for(Player otherPlayer : players) + { + currentPlayer++; + if(((Player) player.getSpectatorTarget()) == otherPlayer) + break; + } + + if(action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK) + currentPlayer = currentPlayer - 2; + else + return; + + if(currentPlayer < 0) + currentPlayer = players.size() - 1; + + if(currentPlayer >= players.size()) + currentPlayer = 0; + + if(players.get(currentPlayer) == null) + return; + + Player specPlayer = players.get(currentPlayer); + + setSpectating(player, specPlayer); } @EventHandler(priority = EventPriority.LOW) @@ -51,7 +120,127 @@ public class GameSpectatorManager implements Listener } if (!Manager.GetGame().IsAlive(player)) + { event.setCancelled(true); + if(Manager.GetGame().IsLive()) + { + if(Manager.GetGame().AllowEntitySpectate) + { + setSpectating(player, event.getRightClicked()); + } + } + } + } + + @EventHandler + public void updateSpecEntitys(UpdateEvent event) + { + if(event.getType() != UpdateType.FASTER) + return; + + if(Manager.GetGame() == null) + return; + + if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End) + { + if(Manager.GetGame().AllowEntitySpectate) + { + for(Player player : UtilServer.getPlayers()) + { + if (!Manager.GetGame().IsAlive(player)) + { + if(player.getGameMode() == GameMode.SPECTATOR) + { + if(player.getSpectatorTarget() == null) + { + player.setGameMode(GameMode.SURVIVAL); + player.setAllowFlight(true); + } + } + } + } + } + } + } + + @EventHandler(priority = EventPriority.LOW) + public void spectatedEntityDeath(PlayerDeathEvent event) + { + if(Manager.GetGame() == null) + return; + + if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End) + { + if(Manager.GetGame().AllowEntitySpectate) + { + for(Player player : UtilServer.getPlayers()) + { + if (!Manager.GetGame().IsAlive(player)) + { + if(player.getGameMode() == GameMode.SPECTATOR) + { + if(player.getSpectatorTarget() == event.getEntity()) + { + if(Manager.GetGame().GetPlayers(true).size() >= 1) + { + setSpectating(player, Manager.GetGame().GetPlayers(true).get(UtilMath.r(Manager.GetGame().GetPlayers(true).size()))); + return; + } + player.setGameMode(GameMode.SURVIVAL); + player.setAllowFlight(true); + } + } + } + } + } + } + } + + @EventHandler(priority = EventPriority.LOW) + public void dismountEntity(PlayerToggleSneakEvent event) + { + if(Manager.GetGame() == null) + return; + + if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End) + { + if(Manager.GetGame().AllowEntitySpectate) + { + if(!Manager.GetGame().IsAlive(event.getPlayer())) + { + if(event.getPlayer().getGameMode() == GameMode.SPECTATOR) + { + event.getPlayer().setGameMode(GameMode.SURVIVAL); + event.getPlayer().setAllowFlight(true); + } + } + } + } + } + + private void setSpectating(Player player, Entity target) + { + player.setGameMode(GameMode.SURVIVAL); + player.teleport(target.getLocation().add(0, 1, 0)); + player.getInventory().setHeldItemSlot(5); + Manager.runSyncLater(new Runnable() + { + @Override + public void run() + { + if(target instanceof Player) + { + if(!Manager.GetGame().IsAlive(target)) + return; + } + player.setGameMode(GameMode.SPECTATOR); + player.setSpectatorTarget(target); + if(target instanceof Player) + UtilTextBottom.display(C.cYellow + "You are spectating " + F.game(((Player) target).getName()), player); + + UtilPlayer.message(player, F.main("Game", "Sneak to stop spectating")); + } + }, 3); } @EventHandler(priority = EventPriority.LOW)