diff --git a/Plugins/Mineplex.Bungee.Mineplexer/.classpath b/Plugins/Mineplex.Bungee.Mineplexer/.classpath
index 40645fe06..c06b6c559 100644
--- a/Plugins/Mineplex.Bungee.Mineplexer/.classpath
+++ b/Plugins/Mineplex.Bungee.Mineplexer/.classpath
@@ -8,6 +8,6 @@
-
+
diff --git a/Plugins/Mineplex.Bungee.Mineplexer/src/mineplex/bungee/playerStats/PlayerStats.java b/Plugins/Mineplex.Bungee.Mineplexer/src/mineplex/bungee/playerStats/PlayerStats.java
index fcae65a57..cc805cbe2 100644
--- a/Plugins/Mineplex.Bungee.Mineplexer/src/mineplex/bungee/playerStats/PlayerStats.java
+++ b/Plugins/Mineplex.Bungee.Mineplexer/src/mineplex/bungee/playerStats/PlayerStats.java
@@ -5,8 +5,8 @@ import java.util.UUID;
import java.util.concurrent.TimeUnit;
import mineplex.bungee.playerStats.data.IpInfo;
-import mineplex.playerCache.PlayerCache;
-import mineplex.playerCache.PlayerInfo;
+import mineplex.cache.player.PlayerCache;
+import mineplex.cache.player.PlayerInfo;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
diff --git a/Plugins/Mineplex.Bungee.Mineplexer/src/mineplex/bungee/playerStats/PlayerStatsRepository.java b/Plugins/Mineplex.Bungee.Mineplexer/src/mineplex/bungee/playerStats/PlayerStatsRepository.java
index 1e9f765f5..5227ab818 100644
--- a/Plugins/Mineplex.Bungee.Mineplexer/src/mineplex/bungee/playerStats/PlayerStatsRepository.java
+++ b/Plugins/Mineplex.Bungee.Mineplexer/src/mineplex/bungee/playerStats/PlayerStatsRepository.java
@@ -9,7 +9,7 @@ import java.sql.Statement;
import java.util.UUID;
import mineplex.bungee.playerStats.data.IpInfo;
-import mineplex.playerCache.PlayerInfo;
+import mineplex.cache.player.PlayerInfo;
public class PlayerStatsRepository
{
diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilItem.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilItem.java
index c82d37f9f..5a300322c 100644
--- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilItem.java
+++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilItem.java
@@ -12,6 +12,7 @@ import java.util.Map.Entry;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
import mineplex.core.common.structs.ItemContainer;
@@ -1116,4 +1117,12 @@ public class UtilItem
{
return _materials.containsKey(material);
}
+
+ public static ItemStack makeUnbreakable(ItemStack i)
+ {
+ ItemMeta im = i.getItemMeta();
+ im.spigot().setUnbreakable(true);
+ i.setItemMeta(im);
+ return i;
+ }
}
diff --git a/Plugins/Mineplex.Core/.classpath b/Plugins/Mineplex.Core/.classpath
index c43f4d9b1..067e728d7 100644
--- a/Plugins/Mineplex.Core/.classpath
+++ b/Plugins/Mineplex.Core/.classpath
@@ -13,7 +13,7 @@
-
+
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java b/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java
index 3c01d37a3..26859a6b3 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java
@@ -9,6 +9,9 @@ import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.gson.Gson;
+
+import mineplex.cache.player.PlayerCache;
+import mineplex.cache.player.PlayerInfo;
import mineplex.core.MiniPlugin;
import mineplex.core.account.command.TestRank;
import mineplex.core.account.command.UpdateRank;
@@ -24,8 +27,6 @@ import mineplex.core.common.util.UtilPlayer;
import mineplex.core.timing.TimingManager;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
-import mineplex.playerCache.PlayerCache;
-import mineplex.playerCache.PlayerInfo;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/achievement/Achievement.java b/Plugins/Mineplex.Core/src/mineplex/core/achievement/Achievement.java
index 6f36f0dd3..ee32d3854 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/achievement/Achievement.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/achievement/Achievement.java
@@ -770,6 +770,48 @@ public enum Achievement
new String[]{"Get hit by a monster and", "land on the Safe Pad"},
new int[]{1},
AchievementCategory.MONSTER_MAZE),
+
+ GLADIATORS_HARDENED_GLADIATOR("Hardened Gladiator", 1000,
+ new String[]{"Gladiators.Wins"},
+ new String[]{"Win 50 games of Gladiators"},
+ new int[]{50},
+ AchievementCategory.GLADIATORS),
+
+ GLADIATORS_BATTLE_BRED("Battle Bred", 1500,
+ new String[]{"Gladiators.Wins"},
+ new String[]{"Win 100 games of Gladiators"},
+ new int[]{100},
+ AchievementCategory.GLADIATORS),
+
+ GLADIATORS_BRAWLER("Brawler", 1000,
+ new String[]{"Gladiators.Brawler"},
+ new String[]{"Kill 3 Gladiators", "with your bare hands"},
+ new int[]{3},
+ AchievementCategory.GLADIATORS),
+
+// GLADIATORS_UNTOUCHABLE("Untouchable", 1500,
+// new String[]{"Gladiators.Untouchable"},
+// new String[]{"Kill 10 Gladiators", "without taking any damage"},
+// new int[]{10},
+// AchievementCategory.GLADIATORS),
+
+// GLADIATORS_FLAWLESS("Flawless", 1000,
+// new String[]{"Gladiators.Flawless"},
+// new String[]{"Win a game of gladiators", "without taking any damage"},
+// new int[]{1},
+// AchievementCategory.GLADIATORS),
+
+ GLADIATORS_PRECISION("Precision", 800,
+ new String[]{"Gladiators.Precision"},
+ new String[]{"Don't miss a single", "arrow in a game of", "Gladiators (Minimum 3)"},
+ new int[]{1},
+ AchievementCategory.GLADIATORS),
+
+ GLADIATORS_SWIFT_KILL("Swift Kill", 1000,
+ new String[]{"Gladiators.SwiftKill"},
+ new String[]{"Earn 15 first bloods", "in Gladiators"},
+ new int[]{15},
+ AchievementCategory.GLADIATORS)
;
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/achievement/AchievementCategory.java b/Plugins/Mineplex.Core/src/mineplex/core/achievement/AchievementCategory.java
index 2bf9be288..265e031a4 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/achievement/AchievementCategory.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/achievement/AchievementCategory.java
@@ -150,6 +150,10 @@ public enum AchievementCategory
MONSTER_MAZE("Monster Maze", null,
new StatDisplay[] {StatDisplay.WINS, StatDisplay.GAMES_PLAYED, StatDisplay.DEATHS, StatDisplay.GEMS_EARNED},
Material.ROTTEN_FLESH, 0, GameCategory.ARCADE, "SoonTM"),
+
+ GLADIATORS("Gladiators", null,
+ new StatDisplay[] { StatDisplay.WINS, StatDisplay.GAMES_PLAYED, StatDisplay.KILLS, StatDisplay.DEATHS, StatDisplay.GEMS_EARNED },
+ Material.IRON_SWORD, 0, GameCategory.ARCADE, null)
;
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/PetTagPage.java b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/PetTagPage.java
index 84da7d074..2ca6490f6 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/PetTagPage.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/PetTagPage.java
@@ -1,5 +1,6 @@
package mineplex.core.cosmetic.ui.page;
+import mineplex.cache.player.PlayerCache;
import mineplex.core.account.CoreClientManager;
import mineplex.core.common.CurrencyType;
import mineplex.core.common.util.C;
@@ -16,7 +17,6 @@ import mineplex.core.pet.repository.token.PetChangeToken;
import mineplex.core.pet.repository.token.PetToken;
import mineplex.core.shop.page.ConfirmationPage;
import mineplex.core.shop.page.ShopPageBase;
-import mineplex.playerCache.PlayerCache;
import net.minecraft.server.v1_8_R3.ItemStack;
import net.minecraft.server.v1_8_R3.Items;
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/donation/DonationManager.java b/Plugins/Mineplex.Core/src/mineplex/core/donation/DonationManager.java
index 54209e7db..813873d73 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/donation/DonationManager.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/donation/DonationManager.java
@@ -10,6 +10,8 @@ import org.bukkit.event.EventHandler;
import org.bukkit.plugin.java.JavaPlugin;
import com.google.gson.Gson;
+
+import mineplex.cache.player.PlayerCache;
import mineplex.core.MiniDbClientPlugin;
import mineplex.core.account.CoreClientManager;
import mineplex.core.account.event.ClientWebResponseEvent;
@@ -24,7 +26,6 @@ import mineplex.core.donation.repository.token.DonorTokenWrapper;
import mineplex.core.server.util.TransactionResponse;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
-import mineplex.playerCache.PlayerCache;
public class DonationManager extends MiniDbClientPlugin
{
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java b/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java
index 6c43e8729..ebdc89a02 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java
@@ -72,6 +72,8 @@ public enum GameDisplay
BouncyBalls("Bouncy Balls", Material.SLIME_BALL, (byte)0, GameCategory.ARCADE, 57),
+ Gladiators("Gladiators", Material.IRON_SWORD, (byte)0, GameCategory.ARCADE, 58),
+
Event("Mineplex Event", Material.CAKE, (byte)0, GameCategory.EVENT, 999);
String _name;
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/inventory/InventoryManager.java b/Plugins/Mineplex.Core/src/mineplex/core/inventory/InventoryManager.java
index a1d19bd53..a10dd5e73 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/inventory/InventoryManager.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/inventory/InventoryManager.java
@@ -22,6 +22,7 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
+import mineplex.cache.player.PlayerCache;
import mineplex.core.MiniDbClientPlugin;
import mineplex.core.account.CoreClientManager;
import mineplex.core.common.util.Callback;
@@ -31,7 +32,6 @@ import mineplex.core.inventory.data.InventoryRepository;
import mineplex.core.inventory.data.Item;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
-import mineplex.playerCache.PlayerCache;
public class InventoryManager extends MiniDbClientPlugin
{
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesRepository.java
index 957785cb4..eca4dd35f 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesRepository.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesRepository.java
@@ -128,7 +128,6 @@ public class PreferencesRepository extends RepositoryBase
preferences.ClanTips = resultSet.getBoolean(13);
preferences.HubMusic = resultSet.getBoolean(14);
preferences.DisableAds = resultSet.getBoolean(15);
- System.out.println("<< " + resultSet.getBoolean(13));
}
return preferences;
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/profileCache/ProfileCacheLookupCallback.java b/Plugins/Mineplex.Core/src/mineplex/core/profileCache/ProfileCacheLookupCallback.java
new file mode 100644
index 000000000..81d62ada2
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/profileCache/ProfileCacheLookupCallback.java
@@ -0,0 +1,29 @@
+package mineplex.core.profileCache;
+
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.ProfileLookupCallback;
+
+public class ProfileCacheLookupCallback implements ProfileLookupCallback
+{
+ private ProfileCacheManager _profileCacheManager;
+ private ProfileLookupCallback _profileLookupCallback;
+
+ public ProfileCacheLookupCallback(ProfileCacheManager profileCacheManager, ProfileLookupCallback profileLookupCallback)
+ {
+ _profileCacheManager = profileCacheManager;
+ _profileLookupCallback = profileLookupCallback;
+ }
+
+ @Override
+ public void onProfileLookupFailed(GameProfile gameProfile, Exception exception)
+ {
+ _profileLookupCallback.onProfileLookupFailed(gameProfile, exception);
+ }
+
+ @Override
+ public void onProfileLookupSucceeded(GameProfile gameProfile)
+ {
+ _profileCacheManager.cacheProfile(gameProfile);
+ _profileLookupCallback.onProfileLookupSucceeded(gameProfile);
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/profileCache/ProfileCacheManager.java b/Plugins/Mineplex.Core/src/mineplex/core/profileCache/ProfileCacheManager.java
index 3f2af0ea7..102df1712 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/profileCache/ProfileCacheManager.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/profileCache/ProfileCacheManager.java
@@ -1,81 +1,134 @@
-//package mineplex.core.profileCache;
-//
-//import java.util.UUID;
-//
-//import org.bukkit.plugin.java.JavaPlugin;
-//import net.minecraft.util.com.google.gson.Gson;
-//import net.minecraft.util.com.google.gson.GsonBuilder;
-//import net.minecraft.util.com.mojang.authlib.GameProfile;
-//import net.minecraft.util.com.mojang.authlib.properties.PropertyMap;
-//import net.minecraft.util.com.mojang.authlib.yggdrasil.ProfileCache;
-//import net.minecraft.util.com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository;
-//import net.minecraft.util.com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService;
-//import net.minecraft.util.com.mojang.authlib.yggdrasil.response.ProfileSearchResultsResponse;
-//import net.minecraft.util.com.mojang.util.UUIDTypeAdapter;
-//
-//import mineplex.core.MiniPlugin;
-//import mineplex.serverdata.Region;
-//import mineplex.serverdata.redis.RedisDataRepository;
-//import mineplex.serverdata.servers.ServerManager;
-//
-//public class ProfileCacheManager extends MiniPlugin implements ProfileCache
-//{
-// private RedisDataRepository _profileRepository;
-// private Gson _gson;
-//
-// public ProfileCacheManager(JavaPlugin plugin)
-// {
-// super("Profile Cache", plugin);
-//
-// _profileRepository = new RedisDataRepository(ServerManager.getMasterConnection(), ServerManager.getSlaveConnection(),
-// Region.ALL, ProfileData.class, "profileCacheRepo");
-//
-// GsonBuilder builder = new GsonBuilder();
-// builder.registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer());
-// builder.registerTypeAdapter(UUID.class, new UUIDTypeAdapter());
-// builder.registerTypeAdapter(ProfileSearchResultsResponse.class, new net.minecraft.util.com.mojang.authlib.yggdrasil.response.ProfileSearchResultsResponse.Serializer());
-// _gson = builder.create();
-//
-// try
-// {
-// YggdrasilMinecraftSessionService.setProfileCache(this);
-// YggdrasilGameProfileRepository.setProfileCache(this);
-// }
-// catch (Exception e)
-// {
-// System.out.println("================================================");
-// System.out.println("Failed to load Profile Cache (Skins)");
-// System.out.println("Are you using the correct modified Craftbukkit?");
-// System.out.println("================================================");
-// }
-// }
-//
-//
-// @Override
-// public GameProfile attemptToLoadProfile(String playerName)
-// {
-// ProfileData profile = _profileRepository.getElement(playerName.toLowerCase());
-//
-// if (profile != null)
-// {
-// PropertyMap propertyMap = _gson.fromJson(profile.getPropertyMap(), PropertyMap.class);
-// GameProfile gameProfile = new GameProfile(profile.getUuid(), profile.getPlayerName());
-// gameProfile.getProperties().putAll(propertyMap);
-//
-//// System.out.println("Loaded profile " + playerName + " from repository!");
-// return gameProfile;
-// }
-//
-//// System.out.println("Profile Null");
-//
-// return null;
-// }
-//
-// @Override
-// public void cacheProfile(GameProfile profile)
-// {
-//// System.out.println("Cached profile: " + profile.getName());
-// ProfileData data = new ProfileData(profile.getId(), profile.getName(), _gson.toJson(profile.getProperties()));
-// _profileRepository.addElement(data, 60 * 60 * 24); // 1 day
-// }
-//}
+package mineplex.core.profileCache;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_8_R3.CraftServer;
+import org.bukkit.event.EventHandler;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.mojang.authlib.Agent;
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.GameProfileRepository;
+import com.mojang.authlib.ProfileLookupCallback;
+import com.mojang.authlib.properties.PropertyMap;
+import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository;
+import com.mojang.authlib.yggdrasil.response.ProfileSearchResultsResponse;
+import com.mojang.util.UUIDTypeAdapter;
+
+import mineplex.core.MiniPlugin;
+import mineplex.core.updater.UpdateType;
+import mineplex.core.updater.event.UpdateEvent;
+import mineplex.serverdata.Region;
+import mineplex.serverdata.redis.RedisDataRepository;
+import mineplex.serverdata.servers.ServerManager;
+
+public class ProfileCacheManager extends MiniPlugin implements GameProfileRepository
+{
+ private YggdrasilGameProfileRepository _mojangProfileRepository;
+ private RedisDataRepository _profileRepository;
+ private Gson _gson;
+
+ public ProfileCacheManager(JavaPlugin plugin)
+ {
+ super("Profile Cache", plugin);
+
+ _profileRepository = new RedisDataRepository(ServerManager.getMasterConnection(), ServerManager.getSlaveConnection(),
+ Region.ALL, ProfileData.class, "profileCacheRepo");
+
+ GsonBuilder builder = new GsonBuilder();
+ builder.registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer());
+ builder.registerTypeAdapter(UUID.class, new UUIDTypeAdapter());
+ builder.registerTypeAdapter(ProfileSearchResultsResponse.class, new com.mojang.authlib.yggdrasil.response.ProfileSearchResultsResponse.Serializer());
+ _gson = builder.create();
+
+ try
+ {
+ Field mojangProfileRepo = net.minecraft.server.v1_8_R3.MinecraftServer.class.getDeclaredField("Y");
+
+ mojangProfileRepo.setAccessible(true);
+
+ _mojangProfileRepository = (YggdrasilGameProfileRepository) mojangProfileRepo.get(((CraftServer)Bukkit.getServer()).getServer());
+ mojangProfileRepo.set(((CraftServer)Bukkit.getServer()).getServer(), this);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ System.out.println("================================================");
+ System.out.println("Failed to load Profile Cache (Skins)");
+ System.out.println("Are you using the correct modified Craftbukkit?");
+ System.out.println("================================================");
+ }
+ }
+
+
+ public GameProfile attemptToLoadProfile(String playerName)
+ {
+ ProfileData profile = _profileRepository.getElement(playerName.toLowerCase());
+
+ if (profile != null)
+ {
+ PropertyMap propertyMap = _gson.fromJson(profile.getPropertyMap(), PropertyMap.class);
+ GameProfile gameProfile = new GameProfile(profile.getUuid(), profile.getPlayerName());
+ gameProfile.getProperties().putAll(propertyMap);
+ return gameProfile;
+ }
+
+ return null;
+ }
+
+ public void cacheProfile(final GameProfile profile)
+ {
+ if (Bukkit.isPrimaryThread())
+ {
+ runAsync(new Runnable()
+ {
+ public void run()
+ {
+ cacheProfileSafely(profile);
+ }
+ });
+ }
+ else
+ cacheProfileSafely(profile);
+ }
+
+ @Override
+ public void findProfilesByNames(String[] profileNames, Agent agent, ProfileLookupCallback profileLookupCallback)
+ {
+ List uncachedProfileNames = new ArrayList<>();
+
+ for (String profileName : profileNames)
+ {
+ GameProfile profile = attemptToLoadProfile(profileName);
+
+ if (profile == null)
+ uncachedProfileNames.add(profileName);
+ else
+ profileLookupCallback.onProfileLookupSucceeded(profile);
+ }
+
+ _mojangProfileRepository.findProfilesByNames(uncachedProfileNames.toArray(new String[uncachedProfileNames.size()]), agent, new ProfileCacheLookupCallback(this, profileLookupCallback));
+ }
+
+ @EventHandler
+ public void clearRepository(UpdateEvent event)
+ {
+ if (event.getType() != UpdateType.MIN_10)
+ return;
+
+ _profileRepository.clean();
+ }
+
+ private void cacheProfileSafely(GameProfile profile)
+ {
+ ProfileData data = new ProfileData(profile.getId(), profile.getName(), _gson.toJson(profile.getProperties()));
+ _profileRepository.addElement(data, 60 * 60 * 24); // 1 day
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/PetReward.java b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/PetReward.java
index 113f8a6cf..c683c100f 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/PetReward.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/reward/rewards/PetReward.java
@@ -5,6 +5,7 @@ import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
+import mineplex.cache.player.PlayerCache;
import mineplex.core.donation.DonationManager;
import mineplex.core.inventory.InventoryManager;
import mineplex.core.pet.PetManager;
@@ -13,7 +14,6 @@ import mineplex.core.pet.repository.token.PetToken;
import mineplex.core.reward.RewardData;
import mineplex.core.reward.RewardRarity;
import mineplex.core.reward.RewardType;
-import mineplex.playerCache.PlayerCache;
/**
* Created by shaun on 14-09-18.
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java b/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java
index 7ec46f8f9..1aa921c2d 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java
@@ -9,6 +9,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
+import mineplex.cache.player.PlayerCache;
import mineplex.core.MiniDbClientPlugin;
import mineplex.core.account.CoreClientManager;
import mineplex.core.common.util.NautHashMap;
@@ -16,7 +17,6 @@ import mineplex.core.common.util.UtilServer;
import mineplex.core.stats.command.GiveStatCommand;
import mineplex.core.stats.command.TimeCommand;
import mineplex.core.stats.event.StatChangeEvent;
-import mineplex.playerCache.PlayerCache;
public class StatsManager extends MiniDbClientPlugin
{
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/task/TaskManager.java b/Plugins/Mineplex.Core/src/mineplex/core/task/TaskManager.java
index 3a9e8601f..85608613e 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/task/TaskManager.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/task/TaskManager.java
@@ -5,12 +5,12 @@ import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
+import mineplex.cache.player.PlayerCache;
import mineplex.core.MiniDbClientPlugin;
import mineplex.core.account.CoreClientManager;
import mineplex.core.common.util.Callback;
import mineplex.core.common.util.NautHashMap;
import mineplex.core.task.repository.TaskRepository;
-import mineplex.playerCache.PlayerCache;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
diff --git a/Plugins/Mineplex.Game.Clans.Core/.classpath b/Plugins/Mineplex.Game.Clans.Core/.classpath
index fa4ddd8ed..c6a118cbe 100644
--- a/Plugins/Mineplex.Game.Clans.Core/.classpath
+++ b/Plugins/Mineplex.Game.Clans.Core/.classpath
@@ -1,7 +1,7 @@
-
+
diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java
index f52155acb..9940694cc 100644
--- a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java
+++ b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java
@@ -38,6 +38,7 @@ import mineplex.core.pet.PetManager;
import mineplex.core.poll.PollManager;
import mineplex.core.portal.Portal;
import mineplex.core.preferences.PreferencesManager;
+import mineplex.core.profileCache.ProfileCacheManager;
import mineplex.core.projectile.ProjectileManager;
import mineplex.core.punish.Punish;
import mineplex.core.recharge.Recharge;
@@ -182,6 +183,8 @@ public class Hub extends JavaPlugin implements IRelation
new ClassCombatShop(shopManager, clientManager, donationManager, false, "Knight", classManager.GetClass("Knight"), true);
new ClassCombatShop(shopManager, clientManager, donationManager, false, "Assassin", classManager.GetClass("Assassin"), true);
+ new ProfileCacheManager(this);
+
//Updates
getServer().getScheduler().scheduleSyncRepeatingTask(this, new Updater(this), 1, 1);
}
diff --git a/Plugins/Mineplex.PlayerCache/.project b/Plugins/Mineplex.PlayerCache/.project
index 0abebe638..5321c2157 100644
--- a/Plugins/Mineplex.PlayerCache/.project
+++ b/Plugins/Mineplex.PlayerCache/.project
@@ -1,6 +1,6 @@
- Mineplex.PlayerCache
+ Mineplex.Cache
diff --git a/Plugins/Mineplex.PlayerCache/src/mineplex/playerCache/PlayerCache.java b/Plugins/Mineplex.PlayerCache/src/mineplex/cache/player/PlayerCache.java
similarity index 97%
rename from Plugins/Mineplex.PlayerCache/src/mineplex/playerCache/PlayerCache.java
rename to Plugins/Mineplex.PlayerCache/src/mineplex/cache/player/PlayerCache.java
index cf320dbde..e83eabf74 100644
--- a/Plugins/Mineplex.PlayerCache/src/mineplex/playerCache/PlayerCache.java
+++ b/Plugins/Mineplex.PlayerCache/src/mineplex/cache/player/PlayerCache.java
@@ -1,4 +1,4 @@
-package mineplex.playerCache;
+package mineplex.cache.player;
import java.util.UUID;
diff --git a/Plugins/Mineplex.PlayerCache/src/mineplex/playerCache/PlayerInfo.java b/Plugins/Mineplex.PlayerCache/src/mineplex/cache/player/PlayerInfo.java
similarity index 97%
rename from Plugins/Mineplex.PlayerCache/src/mineplex/playerCache/PlayerInfo.java
rename to Plugins/Mineplex.PlayerCache/src/mineplex/cache/player/PlayerInfo.java
index 3ab44b0d5..c7cf6faec 100644
--- a/Plugins/Mineplex.PlayerCache/src/mineplex/playerCache/PlayerInfo.java
+++ b/Plugins/Mineplex.PlayerCache/src/mineplex/cache/player/PlayerInfo.java
@@ -1,4 +1,4 @@
-package mineplex.playerCache;
+package mineplex.cache.player;
import java.util.UUID;
diff --git a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/StaffServer.java b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/StaffServer.java
index c1c98cf3b..cdb02169a 100644
--- a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/StaffServer.java
+++ b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/StaffServer.java
@@ -15,6 +15,7 @@ import mineplex.core.monitor.LagMeter;
import mineplex.core.npc.NpcManager;
import mineplex.core.portal.Portal;
import mineplex.core.preferences.PreferencesManager;
+import mineplex.core.profileCache.ProfileCacheManager;
import mineplex.core.punish.Punish;
import mineplex.core.recharge.Recharge;
import mineplex.core.stats.StatsManager;
@@ -88,6 +89,8 @@ public class StaffServer extends JavaPlugin
((CraftServer)getServer()).getHandle().addOp(new GameProfile(UUID.fromString("377bdea3-badc-448d-81c1-65db43b17ea4"), "Strutt20"));
((CraftServer)getServer()).getHandle().addOp(new GameProfile(UUID.fromString("efaf9a17-2304-4f42-8433-421523c308dc"), "B2_mp"));
- ((CraftServer)getServer()).getHandle().addOp(new GameProfile(UUID.fromString("cf85f470-5248-4978-8208-435736fa136e"), "RustyRoo"));
+ ((CraftServer)getServer()).getHandle().addOp(new GameProfile(UUID.fromString("cf85f470-5248-4978-8208-435736fa136e"), "RustyRoo"));
+
+ new ProfileCacheManager(this);
}
}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java
index 7a710683b..aa1468fdf 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java
@@ -45,6 +45,7 @@ import mineplex.core.pet.PetManager;
import mineplex.core.poll.PollManager;
import mineplex.core.portal.Portal;
import mineplex.core.preferences.PreferencesManager;
+import mineplex.core.profileCache.ProfileCacheManager;
import mineplex.core.projectile.ProjectileManager;
import mineplex.core.punish.Punish;
import mineplex.core.recharge.Recharge;
@@ -160,6 +161,8 @@ public class Arcade extends JavaPlugin
new PacketsInteractionFix(this, packetHandler);
new FoodDupeFix(this);
+ new ProfileCacheManager(this);
+
//Updates
getServer().getScheduler().scheduleSyncRepeatingTask(this, new Updater(this), 1, 1);
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 5eedb306e..5ff9e576c 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java
@@ -26,6 +26,7 @@ import nautilus.game.arcade.game.games.dragons.DragonsTeams;
import nautilus.game.arcade.game.games.draw.Draw;
import nautilus.game.arcade.game.games.event.EventGame;
import nautilus.game.arcade.game.games.evolution.Evolution;
+import nautilus.game.arcade.game.games.gladiators.Gladiators;
import nautilus.game.arcade.game.games.gravity.Gravity;
import nautilus.game.arcade.game.games.halloween.Halloween;
import nautilus.game.arcade.game.games.hideseek.HideSeek;
@@ -128,6 +129,7 @@ public enum GameType
SkywarsTeams(TeamSkywars.class, GameDisplay.SkywarsTeams, new GameType[]{GameType.Skywars}, false),
MonsterMaze(MonsterMaze.class, GameDisplay.MonsterMaze),
MonsterLeague(MonsterLeague.class, GameDisplay.MonsterLeague),
+ Gladiators(Gladiators.class, GameDisplay.Gladiators),
BouncyBalls(BouncyBalls.class, GameDisplay.BouncyBalls),
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/events/FirstBloodEvent.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/events/FirstBloodEvent.java
new file mode 100644
index 000000000..a3a5bcbae
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/events/FirstBloodEvent.java
@@ -0,0 +1,39 @@
+package nautilus.game.arcade.events;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+/**
+ * Created by William (WilliamTiger).
+ * 10/12/15
+ */
+public class FirstBloodEvent extends Event
+{
+
+ private Player player;
+
+ public FirstBloodEvent(Player player)
+ {
+ this.player = player;
+ }
+
+ public Player getPlayer()
+ {
+ return player;
+ }
+
+ private static HandlerList _handlers = new HandlerList();
+
+ public static HandlerList getHandlerList()
+ {
+ return _handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers()
+ {
+ return getHandlerList();
+ }
+
+}
\ No newline at end of file
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 edf144f5e..832053604 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
@@ -36,7 +36,6 @@ import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
-import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
@@ -73,6 +72,7 @@ import nautilus.game.arcade.events.GameStateChangeEvent;
import nautilus.game.arcade.events.PlayerGameRespawnEvent;
import nautilus.game.arcade.events.PlayerStateChangeEvent;
import nautilus.game.arcade.game.GameTeam.PlayerState;
+import nautilus.game.arcade.gametutorial.GameTutorial;
import nautilus.game.arcade.kit.Kit;
import nautilus.game.arcade.kit.KitAvailability;
import nautilus.game.arcade.kit.Perk;
@@ -303,6 +303,8 @@ public abstract class Game implements Listener
public boolean DeadBodiesDeath = true;
public int DeadBodiesExpire = -1;
+ public boolean EnableTutorials = false;
+
public boolean FixSpawnFacing = true;
private IPacketHandler _useEntityPacketHandler;
@@ -1724,21 +1726,6 @@ public abstract class Game implements Listener
}
}
}
-
- @EventHandler
- public void debug(PlayerCommandPreprocessEvent event)
- {
- if (event.getMessage().equals("/debugteams"))
- {
- for (GameTeam team : GetTeamList())
- {
- event.getPlayer().sendMessage(team.GetFormattedName());
-
- for (Player player : team.GetPlayers(false))
- {
- event.getPlayer().sendMessage(player.getName() + ": " + team.IsAlive(player));
- }
- }
- }
- }
+
+ public void addTutorials(){}
}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/GameTeam.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/GameTeam.java
index 7d8264b88..256771fdb 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/GameTeam.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/GameTeam.java
@@ -14,6 +14,7 @@ import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.visibility.VisibilityManager;
import nautilus.game.arcade.game.GameTeam.PlayerState;
+import nautilus.game.arcade.gametutorial.GameTutorial;
import nautilus.game.arcade.kit.Kit;
import nautilus.game.arcade.kit.KitAvailability;
@@ -58,6 +59,8 @@ public class GameTeam
private String _name;
private String _displayName;
private ChatColor _color;
+
+ private GameTutorial _tutorial;
private HashMap _players = new HashMap();
@@ -447,4 +450,15 @@ public class GameTeam
return _places;
}
+
+ public GameTutorial getTutorial()
+ {
+ return _tutorial;
+ }
+
+ public void setTutorial(GameTutorial tutorial)
+ {
+ _tutorial = tutorial;
+ }
+
}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/Arena.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/Arena.java
new file mode 100644
index 000000000..a4dca2dcc
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/Arena.java
@@ -0,0 +1,409 @@
+package nautilus.game.arcade.game.games.gladiators;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.entity.EntityDamageEvent;
+
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.UtilAlg;
+import mineplex.core.common.util.UtilTextBottom;
+import mineplex.core.common.util.UtilTextMiddle;
+import mineplex.core.common.util.UtilTime;
+import mineplex.core.recharge.Recharge;
+import nautilus.game.arcade.game.games.gladiators.events.PlayerChangeArenaEvent;
+
+/**
+ * Created by William (WilliamTiger).
+ * 07/12/15
+ */
+public class Arena
+{
+
+ private Gladiators _host;
+ private ArenaType _colour;
+ private Location _mid;
+ private ArrayList _spawns;
+
+ private Arena _parent;
+ private Arena[] _childs = new Arena[2];
+ private boolean _isUsed;
+
+ private ArrayList _doorBlocks;
+ private boolean _isOpenDoor;
+ private boolean _doBye;
+
+ private ArrayList _pastPlayers;
+
+ private ArenaState _state;
+ private long _stateTime;
+
+ private boolean _alertedAlready;
+ private boolean _alertedAlready2;
+
+ private HashMap> _particles;
+
+ public Arena(Gladiators host, Location mid, ArenaType colour)
+ {
+ _host = host;
+ _mid = mid;
+ _colour = colour;
+ _spawns = new ArrayList<>();
+ _parent = null;
+ _isUsed = false;
+ _doorBlocks = new ArrayList<>();
+ _isOpenDoor = false;
+ _pastPlayers = new ArrayList<>();
+ _state = ArenaState.EMPTY;
+ _stateTime = System.currentTimeMillis();
+ _particles = new HashMap<>();
+ _doBye = false;
+ _alertedAlready = false;
+ _alertedAlready2 = false;
+
+ setupSpawns();
+ }
+
+ public boolean isDoBye()
+ {
+ return _doBye;
+ }
+
+ public void setDoBye(boolean doBye)
+ {
+ _doBye = doBye;
+ }
+
+ public Arena getParent()
+ {
+ return _parent;
+ }
+
+ public long getStateTime()
+ {
+ return _stateTime;
+ }
+
+ public void setStateTime(long stateTime)
+ {
+ _stateTime = stateTime;
+ }
+
+ public void setParent(Arena parent)
+ {
+ _parent = parent;
+ }
+
+ public Arena getChildAt(int index)
+ {
+ return _childs[index];
+ }
+
+ public Arena[] getChilds()
+ {
+ return _childs;
+ }
+
+ public int getCapacity()
+ {
+ int cap = _childs.length;
+
+ for(Arena child : _childs)
+ {
+ if(child != null)
+ if(child.isUsed()) cap--;
+ }
+
+ return cap;
+ }
+
+ public ArenaState getState()
+ {
+ return _state;
+ }
+
+ public void setState(ArenaState state)
+ {
+ _state = state;
+ }
+
+ public ArrayList getDoorBlocks()
+ {
+ return _doorBlocks;
+ }
+
+ public void setChild(int index, Arena child)
+ {
+ _childs[index] = child;
+ child.setParent(this);
+ }
+
+ public void getUsageMap(HashMap used)
+ {
+ if(isUsed()) used.put(this, getCapacity());
+
+ for(Arena child : _childs)
+ {
+ if(child != null) child.getUsageMap(used);
+ }
+ }
+
+ public boolean areChildrenUsed()
+ {
+ for(Arena child : _childs)
+ {
+ if(child != null)
+ if(!child.isUsed()) return false;
+ }
+
+ return true;
+ }
+
+ public Arena getUnusedChild()
+ {
+ for(Arena child : _childs)
+ {
+ if(child != null)
+ if(!child.isUsed()) return child;
+ }
+
+ return null;
+ }
+
+ public boolean isAlertedAlready()
+ {
+ return _alertedAlready;
+ }
+
+ public void setAlertedAlready(boolean alertedAlready)
+ {
+ _alertedAlready = alertedAlready;
+ }
+
+ private void setupSpawns()
+ {
+ ArrayList possible = (ArrayList) _host.WorldData.GetDataLocs("BLACK").clone();
+ _mid.setY(UtilAlg.findClosest(_mid, possible).getY());
+
+ _spawns.add(correctFace(UtilAlg.findClosest(_mid, possible)));
+ possible.remove(_spawns.get(0));
+ _spawns.add(correctFace(UtilAlg.findClosest(_mid, possible)));
+ }
+
+ private Location correctFace(Location l)
+ {
+ l.setPitch(UtilAlg.GetPitch(UtilAlg.getTrajectory(l, _mid)));
+ l.setYaw(UtilAlg.GetYaw(UtilAlg.getTrajectory(l, _mid)));
+ return l;
+ }
+
+ public Gladiators getHost()
+ {
+ return _host;
+ }
+
+ public ArenaType getColour()
+ {
+ return _colour;
+ }
+
+ public Location getMid()
+ {
+ return _mid;
+ }
+
+ public ArrayList getSpawns()
+ {
+ return _spawns;
+ }
+
+ public ArrayList capacitySpawns()
+ {
+ ArrayList ret = new ArrayList<>();
+
+ if (getCapacity() == 0) return ret;
+ if (getCapacity() == 1)
+ {
+ ret.add(_spawns.get(0));
+ return ret;
+ }
+ if (getCapacity() == 2)
+ {
+ ret.add(_spawns.get(0));
+ ret.add(_spawns.get(1));
+ return ret;
+ }
+
+ return ret;
+ }
+
+ public ArrayList getPastPlayers()
+ {
+ return _pastPlayers;
+ }
+
+ public boolean isUsed()
+ {
+ return _isUsed;
+ }
+
+ public void setIsUsed(boolean isUsed)
+ {
+ _isUsed = isUsed;
+ }
+
+ public void closeDoor()
+ {
+ for (Location loc : _doorBlocks)
+ loc.getBlock().setType(Material.OBSIDIAN);
+ }
+
+ public boolean isOpenDoor()
+ {
+ return _isOpenDoor;
+ }
+
+ public void openDoor()
+ {
+ _isOpenDoor = true;
+
+ _host.Manager.getScheduler().scheduleSyncDelayedTask(_host.Manager.getPlugin(), () -> {
+
+ for (Location loc : _doorBlocks)
+ {
+ loc.getBlock().setType(Material.AIR);
+ }
+
+ }, 5L);
+ }
+
+ public void update()
+ {
+ if (getPastPlayers().size() <= 0)
+ {
+ setState(ArenaState.EMPTY);
+ return; // Empty check.
+ }
+
+ if (_state.equals(ArenaState.WAITING))
+ {
+ if (_host.getRoundState() != RoundState.FIGHTING)
+ return;
+
+ if (_alertedAlready)
+ return;
+
+ for (Player p : getPastPlayers())
+ {
+ UtilTextMiddle.display(C.cAqua + "Please Wait", "The next round will start shortly", 0, 20 * 100, 0, p);
+ }
+
+ _alertedAlready = true;
+ }
+ else if (_state.equals(ArenaState.FIGHTING))
+ {
+ if (getPastPlayers().size() == 1)
+ {
+ openDoor();
+
+ setState(ArenaState.RUNNING);
+ setStateTime(System.currentTimeMillis());
+ return;
+ }
+
+ if (!UtilTime.elapsed(_stateTime, 60000))
+ return; // No poison yet.
+
+ for (Player p : getPastPlayers())
+ {
+ UtilTextBottom.display(C.cRed + C.Bold + "YOU ARE POISONED! KEEP FIGHTING!", p);
+ _host.Manager.GetDamage().NewDamageEvent(p, null, null, EntityDamageEvent.DamageCause.CUSTOM, 1D, false, true, true, "Health Loss", "Health Loss");
+ }
+ }
+ else if (_state.equals(ArenaState.RUNNING))
+ {
+ for (Player p : getPastPlayers())
+ {
+ if (_alertedAlready2)
+ continue;
+
+ UtilTextMiddle.display(C.cGreen + "Next Battle", "Follow the particles", 0, 20 * 100, 0, p);
+ }
+
+ _alertedAlready2 = true;
+
+ if (UtilTime.elapsed(_stateTime, 15000))
+ handleSlowMovers();
+ }
+ }
+
+ public void updateTick()
+ {
+ if (_state.equals(ArenaState.RUNNING))
+ {
+ for (Player p : getPastPlayers())
+ showParticles(p);
+ }
+ }
+
+ private void showParticles(Player p)
+ {
+ if (!getPastPlayers().contains(p) || !_state.equals(ArenaState.RUNNING))
+ {
+ _particles.remove(p);
+ return;
+ }
+
+ //New Trails
+ if (Recharge.Instance.use(p, "Particle Trail", 3000, false, false))
+ {
+ if (!_particles.containsKey(p))
+ _particles.put(p, new ArrayList());
+
+ Location end = UtilAlg.findClosest(_mid, _host.WorldData.GetDataLocs("PINK"));
+
+ _particles.get(p).add(new ParticleData(p, end));
+ }
+
+ //Old Trails
+ if (_particles.containsKey(p) && !_particles.get(p).isEmpty())
+ {
+ Iterator trailIter = _particles.get(p).iterator();
+
+ while (trailIter.hasNext())
+ {
+ ParticleData data = trailIter.next();
+
+ //Returns true if its hit the endpoint
+ if (data.update())
+ trailIter.remove();
+ }
+ }
+ }
+
+ private void handleSlowMovers()
+ {
+ setState(ArenaState.ENDED);
+
+ Arena next = _host.getArenaByMid(UtilAlg.findClosest(_mid, _host.getAllArenaMidsOfType(_host.getNextColour(_colour))));
+
+ for (Player p : new ArrayList(_pastPlayers))
+ {
+ // TP after 15 seconds of waiting.
+
+ p.teleport(UtilAlg.getLocationAwayFromPlayers(next.getSpawns(), _host.GetPlayers(true)).clone());
+ //p.sendMessage("HANDLE SLOW MOVERS METHOD!");
+ _host.Manager.getPluginManager().callEvent(new PlayerChangeArenaEvent(p, next, this));
+ closeDoor();
+ _host.setPlayerArena(p, next);
+ UtilTextBottom.display("§c§lTELEPORTED! YOU TOOK TOO LONG!", p);
+ next.setDoBye(true);
+ }
+
+ _pastPlayers.clear(); // Clear out the un-used players.
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/ArenaState.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/ArenaState.java
new file mode 100644
index 000000000..c92405389
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/ArenaState.java
@@ -0,0 +1,14 @@
+package nautilus.game.arcade.game.games.gladiators;
+
+/**
+ * Created by William (WilliamTiger).
+ * 08/12/15
+ */
+public enum ArenaState
+{
+ EMPTY,
+ WAITING,
+ FIGHTING,
+ RUNNING,
+ ENDED;
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/ArenaType.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/ArenaType.java
new file mode 100644
index 000000000..73506445e
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/ArenaType.java
@@ -0,0 +1,243 @@
+package nautilus.game.arcade.game.games.gladiators;
+
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * Created by William (WilliamTiger).
+ * 07/12/15
+ */
+public enum ArenaType
+{
+
+ RED(1, new Loadout()
+ {
+ @Override
+ public ItemStack getSword()
+ {
+ return new ItemStack(Material.DIAMOND_SWORD, 1);
+ }
+
+ @Override
+ public ItemStack getRod()
+ {
+ return new ItemStack(Material.FISHING_ROD, 1);
+ }
+
+ @Override
+ public ItemStack getBow()
+ {
+ return new ItemStack(Material.BOW, 1);
+ }
+
+ @Override
+ public ItemStack getArrows()
+ {
+ return new ItemStack(Material.ARROW, 10);
+ }
+
+ @Override
+ public ItemStack getHelmet()
+ {
+ return new ItemStack(Material.IRON_HELMET, 1);
+ }
+
+ @Override
+ public ItemStack getChestplate()
+ {
+ return new ItemStack(Material.IRON_CHESTPLATE, 1);
+ }
+
+ @Override
+ public ItemStack getLeggings()
+ {
+ return new ItemStack(Material.IRON_LEGGINGS, 1);
+ }
+
+ @Override
+ public ItemStack getBoots()
+ {
+ return new ItemStack(Material.IRON_BOOTS, 1);
+ }
+ }),
+ ORANGE(2, new Loadout()
+ {
+ @Override
+ public ItemStack getSword()
+ {
+ return new ItemStack(Material.IRON_SWORD, 1);
+ }
+
+ @Override
+ public ItemStack getRod()
+ {
+ return new ItemStack(Material.FISHING_ROD, 1);
+ }
+
+ @Override
+ public ItemStack getBow()
+ {
+ return new ItemStack(Material.BOW, 1);
+ }
+
+ @Override
+ public ItemStack getArrows()
+ {
+ return new ItemStack(Material.ARROW, 7);
+ }
+
+ @Override
+ public ItemStack getHelmet()
+ {
+ return new ItemStack(Material.CHAINMAIL_HELMET);
+ }
+
+ @Override
+ public ItemStack getChestplate()
+ {
+ return new ItemStack(Material.CHAINMAIL_CHESTPLATE, 1);
+ }
+
+ @Override
+ public ItemStack getLeggings()
+ {
+ return new ItemStack(Material.CHAINMAIL_LEGGINGS, 1);
+ }
+
+ @Override
+ public ItemStack getBoots()
+ {
+ return new ItemStack(Material.CHAINMAIL_BOOTS, 1);
+ }
+ }),
+ YELLOW(4, new Loadout()
+ {
+ @Override
+ public ItemStack getSword()
+ {
+ return new ItemStack(Material.STONE_SWORD, 1);
+ }
+
+ @Override
+ public ItemStack getRod()
+ {
+ return new ItemStack(Material.FISHING_ROD, 1);
+ }
+
+ @Override
+ public ItemStack getBow()
+ {
+ return new ItemStack(Material.BOW, 1);
+ }
+
+ @Override
+ public ItemStack getArrows()
+ {
+ return new ItemStack(Material.ARROW, 5);
+ }
+
+ @Override
+ public ItemStack getHelmet()
+ {
+ return new ItemStack(Material.GOLD_HELMET, 1);
+ }
+
+ @Override
+ public ItemStack getChestplate()
+ {
+ return new ItemStack(Material.GOLD_CHESTPLATE, 1);
+ }
+
+ @Override
+ public ItemStack getLeggings()
+ {
+ return new ItemStack(Material.GOLD_LEGGINGS, 1);
+ }
+
+ @Override
+ public ItemStack getBoots()
+ {
+ return new ItemStack(Material.GOLD_BOOTS, 1);
+ }
+ }),
+ GREEN(8, new Loadout()
+ {
+ @Override
+ public ItemStack getSword()
+ {
+ return new ItemStack(Material.WOOD_SWORD, 1);
+ }
+
+ @Override
+ public ItemStack getRod()
+ {
+ return new ItemStack(Material.FISHING_ROD, 1);
+ }
+
+ @Override
+ public ItemStack getBow()
+ {
+ return new ItemStack(Material.BOW, 1);
+ }
+
+ @Override
+ public ItemStack getArrows()
+ {
+ return new ItemStack(Material.ARROW, 3);
+ }
+
+ @Override
+ public ItemStack getHelmet()
+ {
+ return new ItemStack(Material.LEATHER_HELMET, 1);
+ }
+
+ @Override
+ public ItemStack getChestplate()
+ {
+ return new ItemStack(Material.LEATHER_CHESTPLATE, 1);
+ }
+
+ @Override
+ public ItemStack getLeggings()
+ {
+ return new ItemStack(Material.LEATHER_LEGGINGS, 1);
+ }
+
+ @Override
+ public ItemStack getBoots()
+ {
+ return new ItemStack(Material.LEATHER_BOOTS, 1);
+ }
+ });
+
+ private int _endsAt;
+ private Loadout _loadout;
+
+ ArenaType(int endsAt, Loadout loadout)
+ {
+ _endsAt = endsAt;
+ _loadout = loadout;
+ }
+
+ public Loadout getLoadout()
+ {
+ return _loadout;
+ }
+
+ public int getEndsAt()
+ {
+ return _endsAt;
+ }
+
+ public String getName()
+ {
+ return toString().toLowerCase();
+ }
+
+ public boolean furtherOut(ArenaType other)
+ {
+ return !(compareTo(other) <= 0);
+ }
+
+}
\ No newline at end of file
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
new file mode 100644
index 000000000..9fa85f642
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/Gladiators.java
@@ -0,0 +1,1022 @@
+package nautilus.game.arcade.game.games.gladiators;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+import java.util.UUID;
+
+import org.bukkit.Color;
+import org.bukkit.FireworkEffect;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.Sound;
+import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Zombie;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.EntityShootBowEvent;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.bukkit.inventory.ItemStack;
+
+import net.minecraft.server.v1_8_R3.PacketPlayOutAnimation;
+
+import com.mojang.authlib.GameProfile;
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.ProfileLoader;
+import mineplex.core.common.util.UUIDFetcher;
+import mineplex.core.common.util.UtilAction;
+import mineplex.core.common.util.UtilAlg;
+import mineplex.core.common.util.UtilEnt;
+import mineplex.core.common.util.UtilFirework;
+import mineplex.core.common.util.UtilItem;
+import mineplex.core.common.util.UtilParticle;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.common.util.UtilServer;
+import mineplex.core.common.util.UtilShapes;
+import mineplex.core.common.util.UtilTextMiddle;
+import mineplex.core.disguise.disguises.DisguisePlayer;
+import mineplex.core.recharge.Recharge;
+import mineplex.core.updater.UpdateType;
+import mineplex.core.updater.event.UpdateEvent;
+import mineplex.minecraft.game.core.combat.event.CombatDeathEvent;
+import nautilus.game.arcade.ArcadeFormat;
+import nautilus.game.arcade.ArcadeManager;
+import nautilus.game.arcade.GameType;
+import nautilus.game.arcade.events.GameStateChangeEvent;
+import nautilus.game.arcade.events.PlayerPrepareTeleportEvent;
+import nautilus.game.arcade.game.GameTeam;
+import nautilus.game.arcade.game.SoloGame;
+import nautilus.game.arcade.game.games.gladiators.events.PlayerChangeArenaEvent;
+import nautilus.game.arcade.game.games.gladiators.events.RoundStartEvent;
+import nautilus.game.arcade.game.games.gladiators.kits.KitGladiator;
+import nautilus.game.arcade.game.games.gladiators.trackers.BrawlerTracker;
+import nautilus.game.arcade.game.games.gladiators.trackers.FlawlessTracker;
+import nautilus.game.arcade.game.games.gladiators.trackers.PrecisionTracker;
+import nautilus.game.arcade.game.games.gladiators.trackers.SwiftKillTracker;
+import nautilus.game.arcade.game.games.gladiators.trackers.UntouchableTracker;
+import nautilus.game.arcade.game.games.gladiators.tutorial.TutorialGladiators;
+import nautilus.game.arcade.gametutorial.events.GameTutorialStartEvent;
+import nautilus.game.arcade.kit.Kit;
+
+/**
+ * Created by William (WilliamTiger).
+ * 07/12/15
+ */
+public class Gladiators extends SoloGame
+{
+
+ private ArrayList _allArenas;
+ private ArrayList _gameArenaSet;
+
+ private HashMap _playerArenas;
+
+ private RoundState _roundState;
+
+ private ArenaType _furthestOutCurrent;
+
+ private boolean _firstRound;
+
+ public Gladiators(ArcadeManager manager)
+ {
+ super(manager, GameType.Gladiators,
+ new Kit[]
+ {
+ new KitGladiator(manager)
+ },
+ new String[]
+ {
+ "This is a 1v1 tournament!",
+ "Kill and then run to the next arena!",
+ "There is only one victor!"
+ });
+
+ Damage = true;
+ DamageFall = false;
+ DamagePvP = true;
+ DamageSelf = true;
+ DamageTeamSelf = true;
+ HungerSet = 20;
+ DontAllowOverfill = true;
+ EnableTutorials = false;
+
+ registerStatTrackers(
+ new BrawlerTracker(this),
+ //new UntouchableTracker(this),
+ //new FlawlessTracker(this),
+ new PrecisionTracker(this),
+ new SwiftKillTracker(this)
+ );
+
+ _playerArenas = new HashMap<>();
+
+ _roundState = RoundState.WAITING;
+ _firstRound = true;
+ }
+
+ @EventHandler
+ public void tutorialStart(GameTutorialStartEvent e)
+ {
+ Location white = WorldData.GetDataLocs("WHITE").get(0);
+ Location orange = UtilAlg.findClosest(white, WorldData.GetDataLocs("ORANGE"));
+ Location pink = UtilAlg.findClosest(orange, WorldData.GetDataLocs("PINK"));
+ ArrayList spawns = new ArrayList<>(WorldData.GetDataLocs("BROWN"));
+ Location spawn1 = spawns.get(0);
+ spawns.remove(spawn1);
+ Location spawn2 = spawns.get(0);
+
+ e.getTutorial().getPhase(1).setLocation(white);
+ e.getTutorial().getPhase(1).setTarget(orange);
+
+ CreatureAllowOverride = true;
+ Zombie zombie1 = (Zombie) WorldData.World.spawnEntity(spawn1, EntityType.ZOMBIE);
+ Zombie zombie2 = (Zombie) WorldData.World.spawnEntity(spawn2, EntityType.ZOMBIE);
+ CreatureAllowOverride = false;
+ for (Zombie zombie : Arrays.asList(zombie1, zombie2))
+ {
+ GameProfile tiger = new ProfileLoader(UUIDFetcher.getUUIDOf("WilliamTiger").toString(), "WilliamTiger").loadProfile();
+ GameProfile random = stealGameProfile();
+ DisguisePlayer player = new DisguisePlayer(zombie, (zombie.equals(zombie1) ? tiger : random));
+ Manager.GetDisguise().disguise(player);
+
+ UtilEnt.Vegetate(zombie);
+ zombie.getEquipment().setHelmet(ArenaType.ORANGE.getLoadout().getHelmet());
+ zombie.getEquipment().setChestplate(ArenaType.ORANGE.getLoadout().getChestplate());
+ zombie.getEquipment().setLeggings(ArenaType.ORANGE.getLoadout().getLeggings());
+ zombie.getEquipment().setBoots(ArenaType.ORANGE.getLoadout().getBoots());
+ zombie.getEquipment().setItemInHand(ArenaType.ORANGE.getLoadout().getSword());
+
+ UtilEnt.CreatureMoveFast(zombie, orange, 1);
+ }
+
+ ((TutorialGladiators)e.getTutorial()).setOrange(orange);
+ ((TutorialGladiators)e.getTutorial()).setPink(pink);
+ ((TutorialGladiators)e.getTutorial()).setZombie1(zombie1);
+ ((TutorialGladiators)e.getTutorial()).setZombie2(zombie2);
+ }
+
+ private GameProfile stealGameProfile()
+ {
+ Player random = UtilServer.getPlayers()[0];
+ GameProfile gp = new GameProfile(UUID.randomUUID(), random.getName());
+ gp.getProperties().putAll(((CraftPlayer)random).getHandle().getProfile().getProperties());
+ return gp;
+ }
+
+ @EventHandler
+ public void tutorialUpdate(UpdateEvent e)
+ {
+ if (e.getType() != UpdateType.FASTEST)
+ return;
+
+ if (GetState() != GameState.Prepare)
+ return;
+
+ if (GetTeamList().get(0).getTutorial() == null)
+ return;
+
+ TutorialGladiators tutorial = (TutorialGladiators) GetTeamList().get(0).getTutorial();
+
+ if (tutorial == null)
+ {
+ System.out.println("tutorial object null");
+
+ if (GetTeamList().get(0).getTutorial() == null)
+ System.out.println("tutorial is null");
+
+ if (!(GetTeamList().get(0).getTutorial() instanceof TutorialGladiators))
+ System.out.println("its not a gladiators one");
+
+ return;
+ }
+
+ if (tutorial.hasEnded())
+ return;
+
+ UtilEnt.CreatureMoveFast(tutorial.getZombie1(), tutorial.getOrange(), 1);
+ UtilEnt.CreatureMoveFast(tutorial.getZombie2(), tutorial.getOrange(), 1);
+
+ if (tutorial.getRunning() >= 2000 && !tutorial.isHasHit1())
+ {
+ tutorial.setHasHit1(true);
+
+ // Zombie hit one
+
+ PacketPlayOutAnimation packet = new PacketPlayOutAnimation();
+ packet.a = Manager.GetDisguise().getDisguise(tutorial.getZombie1()).GetEntityId();
+ packet.b = 0;
+
+ for (Player p : UtilServer.getPlayers())
+ {
+ UtilPlayer.sendPacket(p, packet); // Attack effect
+ }
+
+ tutorial.getZombie2().damage(1); // Hurt effect
+
+ return;
+ }
+
+ if (tutorial.getRunning() >= 4000 && !tutorial.isHasHit2())
+ {
+ tutorial.setHasHit2(true);
+
+ // Zombie hit two
+
+ PacketPlayOutAnimation packet = new PacketPlayOutAnimation();
+ packet.a = Manager.GetDisguise().getDisguise(tutorial.getZombie1()).GetEntityId();
+ packet.b = 0;
+
+ for (Player p : UtilServer.getPlayers())
+ {
+ UtilPlayer.sendPacket(p, packet); // Attack effect
+ }
+
+ tutorial.getZombie2().damage(1); // Hurt effect
+
+ return;
+ }
+
+ if (tutorial.getRunning() >= 5000 && !tutorial.getZombie2().isDead())
+ {
+ // Zombie remove time
+
+ tutorial.getZombie2().damage(1);
+ UtilFirework.playFirework(tutorial.getZombie2().getLocation(), FireworkEffect.Type.BALL, Color.ORANGE, false, false);
+ tutorial.getZombie2().remove();
+
+ Arena gateArena = getArenaByMid(tutorial.getOrange());
+ for (Location loc : gateArena.getDoorBlocks())
+ loc.getBlock().setType(Material.AIR); // Manual door open.
+ }
+
+ if (tutorial.getRunning() > 5000)
+ {
+ // Particles
+
+ if (tutorial.getZombie1() == null || tutorial.getPink() == null)
+ return;
+
+ UtilEnt.CreatureMoveFast(tutorial.getZombie1(), tutorial.getPink(), 1);
+
+ for (Location loc : UtilShapes.getLinesDistancedPoints(tutorial.getZombie1().getLocation(), tutorial.getPink(), 0.2))
+ {
+ UtilParticle.PlayParticle(UtilParticle.ParticleType.HAPPY_VILLAGER, loc, 0.03f, 0.03f, 0.03f, 0, 3,
+ UtilParticle.ViewDist.LONG, UtilServer.getPlayers());
+ }
+ }
+ }
+
+ @Override
+ public void addTutorials()
+ {
+ GetTeamList().get(0).setTutorial(new TutorialGladiators(Manager));
+ }
+
+ @Override
+ public void ParseData()
+ {
+ parseArenas();
+ parseDoors();
+ }
+
+ private void parseDoors()
+ {
+ for (Location loc : WorldData.GetCustomLocs("129"))
+ {
+ ArrayList mids = new ArrayList<>(getAllArenaMids());
+ Arena arena1 = getArenaByMid(UtilAlg.findClosest(loc, mids));
+ mids.remove(UtilAlg.findClosest(loc, mids));
+ Arena arena2 = getArenaByMid(UtilAlg.findClosest(loc, mids));
+
+ if (arena1.getColour().furtherOut(arena2.getColour()))
+ arena1.getDoorBlocks().add(loc);
+ else
+ arena2.getDoorBlocks().add(loc);
+
+ loc.getBlock().setType(Material.FENCE);
+ }
+ }
+
+ private void parseArenas()
+ {
+ _allArenas = new ArrayList<>();
+
+ for (Location mid : WorldData.GetDataLocs("RED"))
+ _allArenas.add(new Arena(this, mid, ArenaType.RED));
+
+ for (Location mid : WorldData.GetDataLocs("ORANGE"))
+ _allArenas.add(new Arena(this, mid, ArenaType.ORANGE));
+
+ for (Location mid : WorldData.GetDataLocs("YELLOW"))
+ _allArenas.add(new Arena(this, mid, ArenaType.YELLOW));
+
+ for (Location mid : WorldData.GetDataLocs("GREEN"))
+ _allArenas.add(new Arena(this, mid, ArenaType.GREEN));
+
+ for (Arena a : _allArenas)
+ {
+ if (a.getColour().equals(ArenaType.GREEN))
+ continue;
+
+ // Set the children of that arena.
+ ArrayList possible = (ArrayList) getAllArenaMidsOfType(getPreviousColour(a.getColour())).clone();
+ a.setChild(0, getArenaByMid(UtilAlg.findClosest(a.getMid(), possible)));
+ possible.remove(a.getChildAt(0).getMid());
+ a.setChild(1, getArenaByMid(UtilAlg.findClosest(a.getMid(), possible)));
+ }
+ }
+
+ private void findGameArenaSet()
+ {
+ _gameArenaSet = new ArrayList<>();
+
+ GetTeamList().get(0).GetSpawns().clear(); // Clear the original game spawns.
+
+ int neededSpawns = Math.min(GetPlayers(true).size(), 16); // Quick fix
+ Arena masterNode = getArenasOfType(ArenaType.RED).get(0);
+
+ HashMap spawnsPerRoom = new HashMap<>();
+
+ Queue queue = new LinkedList<>();
+ Queue nextQueue = new LinkedList<>();
+ queue.add(masterNode);
+
+ int sum;
+ boolean solved = false;
+
+ while (!queue.isEmpty() && !solved)
+ {
+ sum = 0;
+ ArrayList currentNodes = new ArrayList<>();
+ while (!queue.isEmpty())
+ {
+ currentNodes.add(queue.poll());
+ }
+
+ for (Arena node : currentNodes)
+ {
+ sum += node.getCapacity();
+ node.setIsUsed(true);
+ }
+
+ if (sum >= neededSpawns)
+ {
+ solved = true;
+ }
+ else
+ {
+ for (Arena node : currentNodes)
+ {
+ for(int i = 0; i < node.getChilds().length; i++)
+ {
+ //System.out.println("Adding child of node: " + node.getColour() + "number of childs: " + node.getChilds().length);
+ nextQueue.add(node.getChildAt(i));
+ queue.add(node.getChildAt(i));
+ }
+ }
+
+ while (!nextQueue.isEmpty())
+ {
+ Arena node = nextQueue.poll();
+ node.setIsUsed(true);
+
+ //System.out.println("Node: " + node.getColour());
+ sum = sum + node.getCapacity() - 1;
+
+ /*
+ if (node.getParent().areChildrenUsed())
+ {
+ node.getParent().setIsUsed(false);
+ }
+ */
+
+ if (sum >= neededSpawns)
+ {
+ solved = true;
+ break;
+ }
+ }
+ }
+
+ if (solved)
+ {
+ masterNode.getUsageMap(spawnsPerRoom);
+ //System.out.println("Solution: ");
+
+ for (Map.Entry entry : spawnsPerRoom.entrySet())
+ {
+ //System.out.println("Color: " + entry.getKey().getColour() + ", Spawns: " + entry.getValue());
+ _gameArenaSet.add(entry.getKey());
+ }
+ }
+ }
+
+ for (Arena a : _gameArenaSet)
+ {
+ if (a.getCapacity() <= 0)
+ continue;
+
+ for (Location l : a.capacitySpawns())
+ GetTeamList().get(0).GetSpawns().add(l);
+ }
+ }
+
+ public ArrayList getGameArenaSet()
+ {
+ return _gameArenaSet;
+ }
+
+ public ArrayList getArenasOfType(ArenaType type)
+ {
+ ArrayList arenas = new ArrayList<>();
+
+ for (Arena a : _allArenas)
+ if (a.getColour().equals(type))
+ arenas.add(a);
+
+ return arenas;
+ }
+
+ public Arena getArenaByMid(Location mid)
+ {
+ for (Arena a : _allArenas)
+ if (a.getMid().equals(mid))
+ return a;
+
+ return null;
+ }
+
+ public ArrayList getAllArenaMidsOfType(ArenaType type)
+ {
+ ArrayList mids = new ArrayList<>();
+
+ for (Arena a : _allArenas)
+ if (a.getColour().equals(type))
+ mids.add(a.getMid());
+
+ return mids;
+ }
+
+ public ArrayList getAllArenaMids()
+ {
+ ArrayList mids = new ArrayList<>();
+
+ for (Arena a : _allArenas)
+ mids.add(a.getMid());
+
+ return mids;
+ }
+
+ public ArenaType getNextColour(ArenaType old)
+ {
+ switch (old)
+ {
+ case GREEN: return ArenaType.YELLOW;
+ case YELLOW: return ArenaType.ORANGE;
+ case ORANGE: return ArenaType.RED;
+ }
+
+ return null;
+ }
+
+ public ArenaType getPreviousColour(ArenaType old)
+ {
+ switch (old)
+ {
+ case RED: return ArenaType.ORANGE;
+ case ORANGE: return ArenaType.YELLOW;
+ case YELLOW: return ArenaType.GREEN;
+ }
+
+ return null;
+ }
+
+ @EventHandler
+ public void setups(GameStateChangeEvent e)
+ {
+ if (e.GetState().equals(GameState.Live))
+ {
+ for (Player p : GetPlayers(true))
+ {
+ Location closest = UtilAlg.findClosest(p.getLocation(), getAllArenaMids());
+ Arena arena = getArenaByMid(closest);
+ arena.getPastPlayers().add(p);
+ _playerArenas.put(p, arena);
+
+ giveLoadout(p, _playerArenas.get(p).getColour());
+ }
+
+ for (Arena a : _gameArenaSet)
+ {
+ if (a.getPastPlayers().size() != 0)
+ a.setState(ArenaState.WAITING);
+ }
+
+ UtilTextMiddle.display(C.cGreen + "Gladiators!", C.cGreen + "Defeat your opponent to advance", 20, 60, 20);
+
+ return;
+ }
+
+ if (e.GetState() != GameState.Prepare)
+ return;
+
+ findGameArenaSet();
+ //closeUnusedArenas();
+ }
+
+ /**
+ *-------------------
+ * MAIN UPDATE METHOD
+ *-------------------
+ */
+ @EventHandler
+ public void roundUpdateCheck(UpdateEvent e)
+ {
+ if (!IsLive())
+ return;
+
+ if (e.getType() != UpdateType.TICK)
+ return;
+
+ if (_roundState == RoundState.WAITING)
+ {
+ _roundState = RoundState.STARTING_5;
+
+ if (_firstRound)
+ return;
+
+ UtilTextMiddle.display("", C.cGreen + C.Bold + getRoundNotation(), 0, 80 , 0);
+
+ _furthestOutCurrent = getFurthestOut(); // Find furthest out for fight.
+
+ for (Arena a : _gameArenaSet)
+ {
+ if (a.getState() == ArenaState.WAITING && a.getColour() == _furthestOutCurrent)
+ {
+ // This arena is going to fight.
+ a.setState(ArenaState.FIGHTING);
+ a.setStateTime(System.currentTimeMillis());
+ }
+
+ if (a.getState() == ArenaState.WAITING)
+ {
+ // No fight for them, they have a bye.
+ for (Player p : a.getPastPlayers())
+ {
+ p.sendMessage(ArcadeFormat.Line);
+ p.sendMessage(" " + C.cWhite + C.Bold + "You have a bye!");
+ p.sendMessage(" " + C.cGreen + "You automatically go through this round.");
+ p.sendMessage(ArcadeFormat.Line);
+ }
+ }
+ }
+
+ Manager.getPluginManager().callEvent(new RoundStartEvent());
+ }
+ else if (_roundState.equals(RoundState.FIGHTING))
+ {
+ for (Arena a : _gameArenaSet)
+ if (!(a.getState() == ArenaState.WAITING ||
+ a.getState() == ArenaState.ENDED ||
+ a.getState() == ArenaState.EMPTY))
+ return;
+
+ //All of the arenas are waiting for the next fight, so let's make them wait a bit.
+ _roundState = RoundState.WAITING;
+ return;
+ }
+ }
+
+ private ArenaType getFurthestOut()
+ {
+ ArenaType best = null;
+ for (Arena a : _gameArenaSet)
+ {
+ if (a.getState() != ArenaState.WAITING)
+ continue;
+
+ if (best == null || a.getColour().furtherOut(best))
+ best = a.getColour();
+ }
+
+ return best;
+ }
+
+ private void closeUnusedArenas()
+ {
+ for (Arena a : _allArenas)
+ if (!_gameArenaSet.contains(a))
+ a.closeDoor();
+ }
+
+ @EventHandler
+ public void arenaCheckPlayer(UpdateEvent e)
+ {
+ if (!IsLive())
+ return;
+
+ if (e.getType() != UpdateType.TICK)
+ return;
+
+ for (Arena a : _gameArenaSet)
+ {
+ Iterator pls = a.getPastPlayers().iterator();
+ while (pls.hasNext())
+ {
+ Player p = pls.next();
+
+ if (!GetPlayers(true).contains(p))
+ pls.remove();
+ }
+ }
+ }
+
+ @EventHandler
+ public void arenaMoveCheck(PlayerMoveEvent e)
+ {
+ if (!IsLive())
+ return;
+
+ if (!GetPlayers(true).contains(e.getPlayer()))
+ return;
+
+ if (!_playerArenas.containsKey(e.getPlayer()))
+ return;
+
+ Player p = e.getPlayer();
+
+ //if (!_playerArenas.get(p).isOpenDoor())
+ //return; // No need to check since no door to go through.
+
+ Arena closest = getArenaByMid(UtilAlg.findClosest(p.getLocation(), getAllArenaMids()));
+
+ if (closest != _playerArenas.get(p))
+ {
+ if (closest.getColour().furtherOut(_playerArenas.get(p).getColour()))
+ {
+ // No going backwards. Bounce baby bounce.
+ if (Recharge.Instance.use(p, "Arena Bounce", 500, false, false))
+ {
+ //p.sendMessage("bounce. closest = " + closest.toString() + " player arena = " + _playerArenas.get(p).toString());
+ UtilAction.velocity(p, UtilAlg.getTrajectory2d(e.getTo(), p.getLocation()), 1.7, true, 0.2, 0, 3, true);
+ }
+
+ return;
+ }
+
+ //p.sendMessage("ARENA MOVE CHECK METHOD!");
+ Manager.getPluginManager().callEvent(new PlayerChangeArenaEvent(e.getPlayer(), closest, _playerArenas.get(p)));
+ _playerArenas.put(p, closest);
+ }
+ }
+
+ @EventHandler
+ public void arenaChange(PlayerChangeArenaEvent e)
+ {
+ Player p = e.getPlayer();
+ Arena old = e.getFrom();
+ Arena current = e.getTo();
+
+ old.closeDoor();
+ old.getPastPlayers().remove(p);
+ old.setState(ArenaState.ENDED);
+ current.getPastPlayers().add(p);
+ current.setState(ArenaState.WAITING);
+ current.setDoBye(true);
+
+ //Bukkit.broadcastMessage("§7§lDEBUG: §3" + p.getName() + " left §b" + old.getColour().toString() + " §3and entered §b" + current.getColour().toString() + "§3.");
+
+ giveLoadout(p, current.getColour()); //Kit
+ p.setHealth(p.getMaxHealth()); //Heal
+ }
+
+ private void giveLoadout(Player p, ArenaType type)
+ {
+ if (!GetPlayers(true).contains(p))
+ return;
+
+ p.getInventory().clear();
+ p.getInventory().setArmorContents(null);
+
+ p.getInventory().setItem(0, UtilItem.makeUnbreakable(type.getLoadout().getSword()));
+ p.getInventory().setItem(1, UtilItem.makeUnbreakable(type.getLoadout().getRod()));
+ p.getInventory().setItem(2, type.getLoadout().getBow());
+ p.getInventory().setItem(8, type.getLoadout().getArrows());
+
+ p.getInventory().setHelmet(type.getLoadout().getHelmet());
+ p.getInventory().setChestplate(type.getLoadout().getChestplate());
+ p.getInventory().setLeggings(type.getLoadout().getLeggings());
+ p.getInventory().setBoots(type.getLoadout().getBoots());
+
+ p.playSound(p.getLocation(), Sound.LEVEL_UP, 1f, 1f);
+ }
+
+// @EventHandler
+// public void debug(PlayerCommandPreprocessEvent e){
+// if (!e.getMessage().equalsIgnoreCase("/arenas"))
+// return;
+// e.setCancelled(true);
+// Player p = e.getPlayer();
+//
+// p.sendMessage("Round State = " + _roundState.toString());
+// p.sendMessage("Out state = " + _furthestOutCurrent.toString());
+// for (Arena a : _gameArenaSet)
+// {
+// p.sendMessage(a.getColour().toString() + " - " + a.getPastPlayers().size() + " - " + a.getState().toString());
+// }
+// }
+
+ @EventHandler
+ public void arenaUpdateTick(UpdateEvent e)
+ {
+ if (!IsLive())
+ return;
+
+ if (e.getType() != UpdateType.TICK)
+ return;
+
+ for (Arena a : _gameArenaSet)
+ a.updateTick();
+ }
+
+ @EventHandler
+ public void arenaUpdate(UpdateEvent e)
+ {
+ if (!IsLive())
+ return;
+
+ if (e.getType() != UpdateType.SEC)
+ return;
+
+ for (Arena a : _gameArenaSet)
+ a.update();
+ }
+
+ @EventHandler
+ public void damageCancel(EntityDamageEvent e)
+ {
+ if (!IsLive())
+ return;
+
+ if (!(e.getEntity() instanceof Player))
+ return;
+
+ Player p = (Player) e.getEntity();
+
+ if (!_playerArenas.containsKey(p))
+ return;
+
+ if ((_playerArenas.get(p).getState() != ArenaState.FIGHTING) || (_roundState != RoundState.FIGHTING))
+ e.setCancelled(true);
+ }
+
+ @EventHandler
+ public void startCountdown(UpdateEvent e)
+ {
+ if (!IsLive())
+ return;
+
+ if (e.getType() != UpdateType.SEC)
+ return;
+
+ if (_roundState.equals(RoundState.FIGHTING))
+ return;
+
+ if (_roundState.equals(RoundState.STARTING_5))
+ {
+ _roundState = RoundState.STARTING_4;
+ return;
+ }
+ else if (_roundState.equals(RoundState.STARTING_4))
+ {
+ _roundState = RoundState.STARTING_3;
+ return;
+ }
+ else if (_roundState.equals(RoundState.STARTING_3))
+ {
+ _roundState = RoundState.STARTING_2;
+
+ if (_firstRound)
+ return;
+
+ UtilTextMiddle.display(C.cGreen + "3", C.cGreen + C.Bold + getRoundNotation(), 0, 80, 0);
+
+ for (Player p : UtilServer.getPlayers())
+ p.playSound(p.getLocation(), Sound.NOTE_STICKS, 1f, 1f);
+ return;
+ }
+ else if (_roundState.equals(RoundState.STARTING_2))
+ {
+ _roundState = RoundState.STARTING_1;
+
+ if (_firstRound)
+ return;
+
+ UtilTextMiddle.display(C.cYellow + "2", C.cGreen + C.Bold + getRoundNotation(), 0, 80, 0);
+
+ for (Player p : UtilServer.getPlayers())
+ p.playSound(p.getLocation(), Sound.NOTE_STICKS, 1f, 1f);
+ return;
+ }
+ else if (_roundState.equals(RoundState.STARTING_1))
+ {
+ _roundState = RoundState.STARTED;
+
+ if (_firstRound)
+ return;
+
+ UtilTextMiddle.display(C.cGold + "1", C.cGreen + C.Bold + getRoundNotation(), 0, 80, 0);
+
+ for (Player p : UtilServer.getPlayers())
+ p.playSound(p.getLocation(), Sound.NOTE_STICKS, 1f, 1f);
+ return;
+ }
+ else if (_roundState.equals(RoundState.STARTED))
+ {
+ _roundState = RoundState.FIGHTING;
+
+ if (_firstRound)
+ {
+ _firstRound = false;
+ return;
+ }
+
+ UtilTextMiddle.display(C.cRed + "FIGHT", C.cGreen + C.Bold + getRoundNotation(), 0, 40, 0);
+
+ for (Player p : UtilServer.getPlayers())
+ p.playSound(p.getLocation(), Sound.NOTE_PLING, 2f, 2f);
+ return;
+ }
+ }
+
+ private String getRoundNotation()
+ {
+ int size = GetPlayers(true).size();
+
+ if (size == 2)
+ return "FINALS";
+ else if (size == 4)
+ return "SEMI-FINALS";
+ else if (size == 8)
+ return "QUARTER-FINALS";
+ else return "ROUND OF " + size + " PLAYERS";
+ }
+
+ public void setPlayerArena(Player p, Arena a)
+ {
+ _playerArenas.put(p, a);
+ }
+
+ public RoundState getRoundState()
+ {
+ return _roundState;
+ }
+
+ @EventHandler
+ public void onShoot(EntityShootBowEvent e)
+ {
+ if (_roundState == null)
+ return;
+
+ if (_roundState.equals(RoundState.FIGHTING))
+ return;
+
+ e.setCancelled(true);
+
+ if (e.getEntity() instanceof Player)
+ {
+ ((Player)e.getEntity()).getInventory().addItem(new ItemStack(Material.ARROW, 1)); // Arrow fix.
+ ((Player)e.getEntity()).updateInventory();
+ }
+ }
+
+ @Override
+ @EventHandler
+ public void ScoreboardUpdate(UpdateEvent event)
+ {
+ if (GetState() != GameState.Live)
+ return;
+
+ Scoreboard.Reset();
+
+ Scoreboard.WriteBlank();
+ Scoreboard.Write(C.cGreen + C.Bold + "Status");
+ if (_roundState == RoundState.FIGHTING)
+ {
+ double start = -1D;
+ for (Arena a : _gameArenaSet)
+ {
+ if (start != -1D)
+ continue;
+
+ if (a.getState() == ArenaState.FIGHTING)
+ start = a.getStateTime();
+ }
+ double number = ((start + 60000) - System.currentTimeMillis());
+ int time = (int)(number / 1000.0 + 0.5);
+ if (time < 0)
+ Scoreboard.Write("Poison Active");
+ else
+ Scoreboard.Write("Poison in " + time + "s");
+ }
+ else
+ {
+ Scoreboard.Write(_roundState.getScoreboardText());
+ }
+
+ Scoreboard.WriteBlank();
+ Scoreboard.Write(C.cAqua + C.Bold + "Matches Left");
+ Scoreboard.Write(C.cWhite + getMatchesFighting());
+
+ Scoreboard.WriteBlank();
+ Scoreboard.Write(C.cYellow + C.Bold + "Players");
+ if (GetPlayers(true).size() > 7)
+ {
+ Scoreboard.Write(C.cWhite + GetPlayers(true).size() + " Players");
+ }
+ else
+ {
+ for (Player p : GetPlayers(true))
+ {
+ Scoreboard.Write(C.cWhite + p.getName());
+ }
+ }
+
+ Scoreboard.Draw();
+ }
+
+ private int getMatchesFighting()
+ {
+ if (_gameArenaSet == null)
+ return 0;
+
+ int count = 0;
+ for (Arena a : _gameArenaSet)
+ {
+ if (a.getState() == ArenaState.FIGHTING)
+ count++;
+ }
+
+ return count;
+ }
+
+ @EventHandler
+ public void overfillCheck(PlayerPrepareTeleportEvent e)
+ {
+ Player p = e.GetPlayer();
+ if (GetPlayers(true).size() > 16)
+ {
+ SetPlayerState(p, GameTeam.PlayerState.OUT);
+ Manager.addSpectator(p, true);
+ p.sendMessage(F.main("Game", "Too many players are in this server. You are now spectating, sorry."));
+ }
+ }
+
+ @EventHandler
+ public void fireworkDeath(CombatDeathEvent e)
+ {
+ Location loc = e.GetEvent().getEntity().getLocation();
+ Color color = Color.AQUA;
+ switch (_furthestOutCurrent)
+ {
+ case RED:
+ color = Color.RED;
+ break;
+ case ORANGE:
+ color = Color.ORANGE;
+ break;
+ case YELLOW:
+ color = Color.YELLOW;
+ break;
+ case GREEN:
+ color = Color.GREEN;
+ break;
+ }
+ UtilFirework.playFirework(loc, FireworkEffect.Type.BALL, color, false, false);
+ }
+
+ @EventHandler
+ public void quitAlert(PlayerQuitEvent e)
+ {
+ if (_playerArenas.containsKey(e.getPlayer()))
+ {
+ for (Player p : _playerArenas.get(e.getPlayer()).getPastPlayers())
+ {
+ if (p.equals(e.getPlayer()))
+ continue;
+
+ p.sendMessage(ArcadeFormat.Line);
+ p.sendMessage(" " + C.cWhite + C.Bold + "Your opponent has QUIT!");
+ p.sendMessage(" " + C.cGreen + "You automatically win the fight.");
+ p.sendMessage(ArcadeFormat.Line);
+ }
+ }
+ }
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/Loadout.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/Loadout.java
new file mode 100644
index 000000000..4d9f23c61
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/Loadout.java
@@ -0,0 +1,22 @@
+package nautilus.game.arcade.game.games.gladiators;
+
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * Created by William (WilliamTiger).
+ * 07/12/15
+ */
+public interface Loadout
+{
+
+ public ItemStack getSword();
+ public ItemStack getRod();
+ public ItemStack getBow();
+ public ItemStack getArrows();
+
+ public ItemStack getHelmet();
+ public ItemStack getChestplate();
+ public ItemStack getLeggings();
+ public ItemStack getBoots();
+
+}
\ No newline at end of file
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/ParticleData.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/ParticleData.java
new file mode 100644
index 000000000..2ec4129b2
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/ParticleData.java
@@ -0,0 +1,56 @@
+package nautilus.game.arcade.game.games.gladiators;
+
+import org.bukkit.Location;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+import mineplex.core.common.util.UtilAlg;
+import mineplex.core.common.util.UtilMath;
+import mineplex.core.common.util.UtilParticle;
+
+/**
+ * Created by William (WilliamTiger).
+ * 08/12/15
+ */
+public class ParticleData
+{
+ public Player Player;
+ public Location CurrentLocation;
+ public Vector Velocity;
+ public Location Target;
+
+ public ParticleData(Player player, Location target)
+ {
+ Player = player;
+
+ Velocity = player.getLocation().getDirection();
+ if (Velocity.getY() < 0)
+ Velocity.setY(0);
+ Velocity.normalize();
+
+ CurrentLocation = player.getLocation().add(0, 1, 0);
+ Target = target;
+ }
+
+ public boolean update()
+ {
+ //Turn
+ Velocity.add(UtilAlg.getTrajectory(CurrentLocation, Target).multiply(0.15));
+
+ //Normalize Speed
+ UtilAlg.Normalize(Velocity);
+
+ //Move
+ CurrentLocation.add(Velocity.clone().multiply(0.5));
+
+ //Particle
+ UtilParticle.PlayParticle(UtilParticle.ParticleType.HAPPY_VILLAGER, CurrentLocation, 0.03f, 0.03f, 0.03f, 0, 3,
+ UtilParticle.ViewDist.LONG, Player);
+
+ //Sound
+ CurrentLocation.getWorld().playSound(CurrentLocation, Sound.FIZZ, 0.2f, 3f);
+
+ return UtilMath.offset(CurrentLocation, Target) < 4;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/RoundState.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/RoundState.java
new file mode 100644
index 000000000..1807db499
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/RoundState.java
@@ -0,0 +1,29 @@
+package nautilus.game.arcade.game.games.gladiators;
+
+/**
+ * Created by William (WilliamTiger).
+ * 08/12/15
+ */
+public enum RoundState
+{
+ WAITING("Waiting"),
+ STARTING_5("Starting in 5s"),
+ STARTING_4("Starting in 4s"),
+ STARTING_3("Starting in 3s"),
+ STARTING_2("Starting in 2s"),
+ STARTING_1("Starting in 1s"),
+ STARTED("FIGHT!"),
+ FIGHTING("Fighting");
+
+ private String scoreboardText;
+
+ RoundState(String scoreboardText)
+ {
+ this.scoreboardText = scoreboardText;
+ }
+
+ public String getScoreboardText()
+ {
+ return scoreboardText;
+ }
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/events/PlayerChangeArenaEvent.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/events/PlayerChangeArenaEvent.java
new file mode 100644
index 000000000..c948b3d90
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/events/PlayerChangeArenaEvent.java
@@ -0,0 +1,53 @@
+package nautilus.game.arcade.game.games.gladiators.events;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import nautilus.game.arcade.game.games.gladiators.Arena;
+
+/**
+ * Created by William (WilliamTiger).
+ * 08/12/15
+ */
+public class PlayerChangeArenaEvent extends Event
+{
+ private static final HandlerList _handlers = new HandlerList();
+
+ private Player player;
+ private Arena to;
+ private Arena from;
+
+ public PlayerChangeArenaEvent(Player player, Arena to, Arena from)
+ {
+ this.player = player;
+ this.to = to;
+ this.from = from;
+ }
+
+ public Player getPlayer()
+ {
+ return player;
+ }
+
+ public Arena getTo()
+ {
+ return to;
+ }
+
+ public Arena getFrom()
+ {
+ return from;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return _handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers()
+ {
+ return getHandlerList();
+ }
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/events/RoundStartEvent.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/events/RoundStartEvent.java
new file mode 100644
index 000000000..91d654d94
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/events/RoundStartEvent.java
@@ -0,0 +1,24 @@
+package nautilus.game.arcade.game.games.gladiators.events;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+/**
+ * Created by William (WilliamTiger).
+ * 10/12/15
+ */
+public class RoundStartEvent extends Event
+{
+ private static final HandlerList _handlers = new HandlerList();
+
+ public static HandlerList getHandlerList()
+ {
+ return _handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers()
+ {
+ return getHandlerList();
+ }
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/kits/KitGladiator.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/kits/KitGladiator.java
new file mode 100644
index 000000000..1a0df8140
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/kits/KitGladiator.java
@@ -0,0 +1,38 @@
+package nautilus.game.arcade.game.games.gladiators.kits;
+
+import org.bukkit.Material;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+import nautilus.game.arcade.ArcadeManager;
+import nautilus.game.arcade.kit.Kit;
+import nautilus.game.arcade.kit.KitAvailability;
+import nautilus.game.arcade.kit.Perk;
+
+/**
+ * Created by William (WilliamTiger).
+ * 07/12/15
+ */
+public class KitGladiator extends Kit
+{
+ public KitGladiator(ArcadeManager manager)
+ {
+ super(manager, "Gladiator", KitAvailability.Free,
+ new String[]
+ {
+ "At my signal, unleash hell."
+ },
+ new Perk[]
+ {
+
+ },
+ EntityType.ZOMBIE, new ItemStack(Material.IRON_SWORD));
+ }
+
+ @Override
+ public void GiveItems(Player player)
+ {
+ //todo: items based on loadout
+ }
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/BrawlerTracker.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/BrawlerTracker.java
new file mode 100644
index 000000000..6aa1da3d7
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/BrawlerTracker.java
@@ -0,0 +1,39 @@
+package nautilus.game.arcade.game.games.gladiators.trackers;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+
+import mineplex.minecraft.game.core.combat.event.CombatDeathEvent;
+import nautilus.game.arcade.game.games.gladiators.Gladiators;
+import nautilus.game.arcade.stats.StatTracker;
+
+/**
+ * Created by William (WilliamTiger).
+ * 08/12/15
+ */
+public class BrawlerTracker extends StatTracker
+{
+ public BrawlerTracker(Gladiators game)
+ {
+ super(game);
+ }
+
+ @EventHandler
+ public void death(CombatDeathEvent e)
+ {
+ if (e.GetLog().GetKiller() == null)
+ return;
+
+ if (Bukkit.getPlayerExact(e.GetLog().GetKiller().GetName()) != null)
+ {
+ Player p = Bukkit.getPlayerExact(e.GetLog().GetKiller().GetName());
+ if (p.getItemInHand() == null)
+ return;
+
+ if (p.getItemInHand().getType().equals(Material.AIR))
+ addStat(p, "Brawler", 1, false, false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/FlawlessTracker.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/FlawlessTracker.java
new file mode 100644
index 000000000..ebdbad1cf
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/FlawlessTracker.java
@@ -0,0 +1,63 @@
+package nautilus.game.arcade.game.games.gladiators.trackers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.EntityDamageEvent;
+
+import nautilus.game.arcade.events.GameStateChangeEvent;
+import nautilus.game.arcade.game.Game;
+import nautilus.game.arcade.game.games.gladiators.Gladiators;
+import nautilus.game.arcade.stats.StatTracker;
+
+/**
+ * Created by William (WilliamTiger).
+ * 08/12/15
+ */
+public class FlawlessTracker extends StatTracker
+{
+
+ private List _noWin;
+
+ public FlawlessTracker(Gladiators game)
+ {
+ super(game);
+
+ _noWin = new ArrayList<>();
+ }
+
+ @EventHandler
+ public void onDmg(EntityDamageEvent e)
+ {
+ if (e.isCancelled())
+ return;
+
+ System.out.println(e.getEventName() + " took damage by " + e.getCause().toString());
+
+ if (e.getEntity() instanceof Player)
+ {
+ _noWin.add(((Player)e.getEntity()).getName());
+ }
+ }
+
+ @EventHandler
+ public void end(GameStateChangeEvent e)
+ {
+ if (e.GetState() != Game.GameState.End)
+ return;
+
+ if (getGame().getWinners() == null)
+ return;
+
+ for (Player p : getGame().getWinners())
+ {
+ if (_noWin.contains(p.getName()))
+ continue;
+
+ addStat(p, "Flawless", 1, true, false);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/PrecisionTracker.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/PrecisionTracker.java
new file mode 100644
index 000000000..975e040be
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/PrecisionTracker.java
@@ -0,0 +1,79 @@
+package nautilus.game.arcade.game.games.gladiators.trackers;
+
+import java.util.HashMap;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.EntityShootBowEvent;
+import org.bukkit.event.entity.ProjectileHitEvent;
+
+import nautilus.game.arcade.events.GameStateChangeEvent;
+import nautilus.game.arcade.game.Game;
+import nautilus.game.arcade.game.games.gladiators.Gladiators;
+import nautilus.game.arcade.stats.StatTracker;
+
+/**
+ * Created by William (WilliamTiger).
+ * 08/12/15
+ */
+public class PrecisionTracker extends StatTracker
+{
+ private HashMap _shot;
+ private HashMap _hit;
+
+ public PrecisionTracker(Gladiators game)
+ {
+ super(game);
+
+ _shot = new HashMap<>();
+ _hit = new HashMap<>();
+ }
+
+ @EventHandler
+ public void end(GameStateChangeEvent e)
+ {
+ if (e.GetState() != Game.GameState.End)
+ return;
+
+ for (Player p : getGame().getWinners())
+ {
+ if (_shot.containsKey(p.getName()) && _hit.containsKey(p.getName()))
+ {
+ if (_shot.get(p.getName()) == _hit.get(p.getName()))
+ {
+ if (_shot.get(p.getName()) >= 3)
+ addStat(p, "Precision", 1, true, false);
+ }
+ }
+ }
+ }
+
+ @EventHandler
+ public void shoot(EntityShootBowEvent e)
+ {
+ if (!(e.getEntity() instanceof Player))
+ return;
+
+ Player p = (Player) e.getEntity();
+
+ if (_shot.containsKey(p.getName()))
+ _shot.put(p.getName(), _shot.get(p.getName()) + 1);
+ else
+ _shot.put(p.getName(), 1);
+ }
+
+ @EventHandler
+ public void hit(ProjectileHitEvent e)
+ {
+ if (e.getEntity().getShooter() instanceof Player)
+ {
+ Player p = (Player) e.getEntity().getShooter();
+
+ if (_hit.containsKey(p.getName()))
+ _hit.put(p.getName(), _hit.get(p.getName()) + 1);
+ else
+ _hit.put(p.getName(), 1);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/SwiftKillTracker.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/SwiftKillTracker.java
new file mode 100644
index 000000000..52caeec89
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/SwiftKillTracker.java
@@ -0,0 +1,26 @@
+package nautilus.game.arcade.game.games.gladiators.trackers;
+
+import org.bukkit.event.EventHandler;
+
+import nautilus.game.arcade.events.FirstBloodEvent;
+import nautilus.game.arcade.game.games.gladiators.Gladiators;
+import nautilus.game.arcade.stats.StatTracker;
+
+/**
+ * Created by William (WilliamTiger).
+ * 10/12/15
+ */
+public class SwiftKillTracker extends StatTracker
+{
+ public SwiftKillTracker(Gladiators game)
+ {
+ super(game);
+ }
+
+ @EventHandler
+ public void blood(FirstBloodEvent e)
+ {
+ addStat(e.getPlayer(), "SwiftKill", 1, false, false);
+ }
+
+}
\ No newline at end of file
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/UntouchableTracker.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/UntouchableTracker.java
new file mode 100644
index 000000000..44115ca72
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/trackers/UntouchableTracker.java
@@ -0,0 +1,55 @@
+package nautilus.game.arcade.game.games.gladiators.trackers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.entity.EntityDamageEvent;
+
+import nautilus.game.arcade.game.games.gladiators.Gladiators;
+import nautilus.game.arcade.game.games.gladiators.events.RoundStartEvent;
+import nautilus.game.arcade.stats.StatTracker;
+
+/**
+ * Created by William (WilliamTiger).
+ * 10/12/15
+ */
+public class UntouchableTracker extends StatTracker
+{
+ private List _noWin;
+
+ public UntouchableTracker(Gladiators game)
+ {
+ super(game);
+
+ _noWin = new ArrayList<>();
+ }
+
+ @EventHandler
+ public void onDmg(EntityDamageEvent e)
+ {
+ if (e.isCancelled())
+ return;
+
+ if (e.getEntity() instanceof Player)
+ {
+ _noWin.add(((Player)e.getEntity()).getName());
+ }
+ }
+
+ @EventHandler
+ public void onEnd(RoundStartEvent e)
+ {
+ for (Player p : getGame().GetPlayers(true))
+ {
+ if (_noWin.contains(p.getName()))
+ continue;
+
+ addStat(p, "Untouchable", 1, false, false);
+ }
+
+ _noWin.clear();
+ }
+
+}
\ No newline at end of file
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/tutorial/TutorialGladiators.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/tutorial/TutorialGladiators.java
new file mode 100644
index 000000000..48bfebcba
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/tutorial/TutorialGladiators.java
@@ -0,0 +1,140 @@
+package nautilus.game.arcade.game.games.gladiators.tutorial;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Zombie;
+
+import nautilus.game.arcade.ArcadeManager;
+import nautilus.game.arcade.game.games.gladiators.Arena;
+import nautilus.game.arcade.game.games.gladiators.Gladiators;
+import nautilus.game.arcade.gametutorial.GameTutorial;
+import nautilus.game.arcade.gametutorial.TutorialPhase;
+
+/**
+ * Created by William (WilliamTiger).
+ * 10/12/15
+ */
+public class TutorialGladiators extends GameTutorial
+{
+
+ private Gladiators _host;
+
+ private Location _pink, _orange;
+ private Zombie _zombie1, _zombie2;
+
+ private boolean hasHit1, hasHit2;
+
+ public TutorialGladiators(ArcadeManager manager)
+ {
+ super(manager, new TutorialPhase[]{
+ new TutorialPhaseGladiators()
+ });
+
+ TeleportOnEnd = false;
+
+ hasHit1 = false;
+ hasHit2 = false;
+
+ _host = (Gladiators) manager.GetGame();
+ }
+
+ public Location getPink()
+ {
+ return _pink;
+ }
+
+ public void setPink(Location pink)
+ {
+ _pink = pink;
+ }
+
+ public Location getOrange()
+ {
+ return _orange;
+ }
+
+ public void setOrange(Location orange)
+ {
+ _orange = orange;
+ }
+
+ public Zombie getZombie1()
+ {
+ return _zombie1;
+ }
+
+ public void setZombie1(Zombie zombie1)
+ {
+ _zombie1 = zombie1;
+ }
+
+ public Zombie getZombie2()
+ {
+ return _zombie2;
+ }
+
+ public void setZombie2(Zombie zombie2)
+ {
+ _zombie2 = zombie2;
+ }
+
+ public boolean isHasHit1()
+ {
+ return hasHit1;
+ }
+
+ public void setHasHit1(boolean hasHit1)
+ {
+ this.hasHit1 = hasHit1;
+ }
+
+ public boolean isHasHit2()
+ {
+ return hasHit2;
+ }
+
+ public void setHasHit2(boolean hasHit2)
+ {
+ this.hasHit2 = hasHit2;
+ }
+
+ @Override
+ public void onEnd()
+ {
+ Gladiators game = (Gladiators) Manager.GetGame();
+
+ for (Player p : game.GetPlayers(true))
+ {
+ p.teleport(game.GetTeam(p).GetSpawn().clone());
+ }
+
+ if (_zombie1 != null)
+ _zombie1.remove();
+
+ if (_zombie2 != null)
+ _zombie2.remove();
+
+ Arena gateArena = _host.getArenaByMid(getOrange());
+ for (Location loc : gateArena.getDoorBlocks())
+ loc.getBlock().setType(Material.FENCE); // Manual door close.
+
+ // Spawns
+
+ _host.GetTeamList().get(0).GetSpawns().clear();
+
+ for (Arena a : _host.getGameArenaSet())
+ {
+ if (a.getCapacity() <= 0)
+ continue;
+
+ for (Location l : a.capacitySpawns())
+ _host.GetTeamList().get(0).GetSpawns().add(l);
+ }
+
+ for (Player p : _host.GetPlayers(true))
+ {
+ _host.GetTeam(p).SpawnTeleport(p);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/tutorial/TutorialPhaseGladiators.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/tutorial/TutorialPhaseGladiators.java
new file mode 100644
index 000000000..1839b204a
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/gladiators/tutorial/TutorialPhaseGladiators.java
@@ -0,0 +1,26 @@
+package nautilus.game.arcade.game.games.gladiators.tutorial;
+
+import nautilus.game.arcade.gametutorial.TutorialPhase;
+import nautilus.game.arcade.gametutorial.TutorialText;
+
+/**
+ * Created by William (WilliamTiger).
+ * 10/12/15
+ */
+public class TutorialPhaseGladiators extends TutorialPhase
+{
+
+ public TutorialPhaseGladiators()
+ {
+ super(new TutorialText[]{
+ new TutorialText("Defeat your opponent!", 20 * 4, 1),
+ new TutorialText("", 20 * 2, 2),
+ });
+ }
+
+ @Override
+ public int ID()
+ {
+ return 1;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/GameTutorial.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/GameTutorial.java
new file mode 100644
index 000000000..fc4457377
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/GameTutorial.java
@@ -0,0 +1,252 @@
+package nautilus.game.arcade.gametutorial;
+
+import java.util.HashMap;
+
+import mineplex.core.common.util.UtilServer;
+import mineplex.core.visibility.VisibilityManager;
+import nautilus.game.arcade.ArcadeManager;
+import nautilus.game.arcade.game.GameTeam;
+import nautilus.game.arcade.gametutorial.events.GameTutorialEndEvent;
+import nautilus.game.arcade.gametutorial.events.GameTutorialPhaseEvent;
+import nautilus.game.arcade.gametutorial.events.GameTutorialStartEvent;
+
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+
+public abstract class GameTutorial
+{
+
+ public ArcadeManager Manager;
+
+ private TutorialPhase[] _phases;
+ private GameTeam _team;
+ private HashMap _players;
+
+ private TutorialPhase _currentPhase;
+
+ private boolean _hasEnded;
+ private boolean _hasStarted;
+
+ private int _tick;
+
+ private long _started;
+
+ public boolean SetTutorialPositions = true;
+ public boolean TeleportOnEnd = true;
+ public boolean RunTasksSync = true;
+ public boolean PlayTutorialSounds = false;
+ public boolean ShowPrepareTimer = false;
+
+ public long TimeBetweenPhase = 0;
+ public long StartAfterTutorial = 5000;
+
+ public GameTutorial(ArcadeManager manager, TutorialPhase[] phases)
+ {
+ Manager = manager;
+ _phases = phases;
+ _players = new HashMap<>();
+ }
+
+ final public void start()
+ {
+ _hasStarted = true;
+ _tick = 0;
+ for(TutorialPhase phase : _phases)
+ phase.setTutorial(this);
+
+ //Manager.GetGame().PrepareTime = 60000;
+ Manager.GetChat().Silence(60000, false);
+ _started = System.currentTimeMillis();
+ Manager.getPluginManager().callEvent(new GameTutorialStartEvent(this));
+ onStart();
+ preparePlayers();
+ _currentPhase = getNextPhase();
+ Manager.runSyncLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ nextPhase(true);
+ }
+ }, 40);
+ _currentPhase.teleport();
+ }
+
+ protected void nextPhase(boolean phaseOne)
+ {
+ TutorialPhase from = _currentPhase;
+ if(!phaseOne)
+ _currentPhase = getNextPhase();
+
+ if(_currentPhase == null)
+ {
+ onEnd();
+ _hasEnded = true;
+ endTutorial();
+ final GameTutorial tutorial = this;
+ Manager.runSyncLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ Manager.getPluginManager().callEvent(new GameTutorialEndEvent(tutorial));
+ }
+ }, 5);
+ }
+ else
+ {
+ Manager.GetChat().Silence(70000, false);
+ onPhaseChange(_currentPhase);
+ Manager.getPluginManager().callEvent(new GameTutorialPhaseEvent(this, from, _currentPhase));
+ _currentPhase.start(phaseOne);
+ }
+ }
+
+ public void setTeam(GameTeam team)
+ {
+ _team = team;
+ }
+
+ private void endTutorial()
+ {
+ for(final Player player : _players.keySet())
+ {
+ //VisibilityManager.Instance.setVisibility(player, true, UtilServer.getPlayers());
+ Manager.runSyncLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ for(Player player : Manager.GetGame().GetPlayers(true))
+ {
+ for(Player other : Manager.GetGame().GetPlayers(true))
+ {
+ player.showPlayer(other);
+ }
+ }
+ player.setAllowFlight(false);
+ player.setFlying(false);
+ }
+ }, 5);
+ if(TeleportOnEnd)
+ {
+ Manager.runSyncLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ _team.SpawnTeleport();
+ }
+ }, 5);
+ }
+ }
+ Manager.GetChat().Silence(StartAfterTutorial, false);
+ Manager.GetGame().PrepareTime = (System.currentTimeMillis() - Manager.GetGame().GetStateTime()) + StartAfterTutorial;
+ }
+
+ protected TutorialPhase getNextPhase()
+ {
+ for(TutorialPhase phase : _phases)
+ {
+ if(_currentPhase == null && phase.ID() == 1)
+ {
+ return phase;
+ }
+ else if(_currentPhase != null && _currentPhase.ID() + 1 == phase.ID())
+ {
+ return phase;
+ }
+ }
+ return null;
+ }
+
+ private void preparePlayers()
+ {
+ for(Player player : UtilServer.getPlayers())
+ {
+ int i = 0;
+ if(Manager.GetGame().GetTeam(player) == _team)
+ {
+ _players.put(player, Manager.GetGame().GetTeam(player).GetSpawns().get(i));
+ player.setAllowFlight(true);
+ player.setFlying(true);
+ // VisibilityManager.Instance.setVisibility(player, false, UtilServer.getPlayers());
+ i++;
+ }
+ }
+ }
+
+ public TutorialPhase getPhase(int index)
+ {
+ for(TutorialPhase phase : _phases)
+ {
+ if(phase.ID() == index)
+ return phase;
+ }
+ return null;
+ }
+
+ public boolean hasEnded()
+ {
+ return _hasEnded;
+ }
+
+ public boolean hasStarted()
+ {
+ return _hasStarted;
+ }
+
+ public HashMap getPlayers()
+ {
+ return _players;
+ }
+
+ public GameTeam getTeam()
+ {
+ return _team;
+ }
+
+ public void onTick(int tick){}
+
+ public void onStart(){}
+
+ public void onPhaseChange(TutorialPhase phase){}
+
+ public void onEnd(){}
+
+ public int tick()
+ {
+ if(!_hasEnded && hasStarted())
+ {
+ for(Player player : UtilServer.getPlayers())
+ {
+ for(Player other : _players.keySet())
+ {
+ player.hidePlayer(other);
+ }
+ }
+ }
+ _tick++;
+ return _tick;
+ }
+
+ public TutorialPhase[] getPhases()
+ {
+ return _phases;
+ }
+
+ public long getTutorialStart()
+ {
+ return _started;
+ }
+
+ public long getRunning()
+ {
+ return System.currentTimeMillis() - _started;
+ }
+
+ public long getPhaseTime()
+ {
+ return _currentPhase.getPhaseTime();
+ }
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/TutorialPhase.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/TutorialPhase.java
new file mode 100644
index 000000000..b140b79bc
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/TutorialPhase.java
@@ -0,0 +1,237 @@
+package nautilus.game.arcade.gametutorial;
+
+import mineplex.core.common.util.UtilAlg;
+import mineplex.core.common.util.UtilTextMiddle;
+
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+public abstract class TutorialPhase
+{
+
+ public abstract int ID();
+
+ private GameTutorial _tutorial;
+ private TutorialText[] _text;
+ private Location _location;
+ private Location _target;
+ private boolean _hasEnded;
+
+ private long _started;
+
+ private TutorialText _currentText;
+
+ public TutorialPhase(TutorialText[] text)
+ {
+ _text = text;
+ }
+
+ final public void start(boolean phaseOne)
+ {
+ _hasEnded = false;
+ _started = System.currentTimeMillis();
+ onStart();
+ if(!phaseOne)
+ {
+ teleport();
+ }
+ displayText();
+ }
+
+ final public void teleport()
+ {
+ if(!getTutorial().SetTutorialPositions)
+ return;
+
+ if(_location != null && _target != null)
+ {
+ prepareLocations();
+ updatePlayers();
+ }
+ }
+
+ private void prepareLocations()
+ {
+ Vector vector = new Vector(_target.getBlockX() - _location.getBlockX(), _target.getBlockY() - _location.getBlockY(), _target.getBlockZ() - _location.getBlockZ());
+ float pitch = UtilAlg.GetPitch(vector);
+ float yaw = UtilAlg.GetYaw(vector);
+ _location.setPitch(pitch);
+ _location.setYaw(yaw);
+ }
+
+ private void updatePlayers()
+ {
+ new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ while(!_hasEnded && !getTutorial().hasEnded())
+ {
+ _tutorial.Manager.runSync(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ if(!_hasEnded && !getTutorial().hasEnded())
+ {
+ for(Player player : _tutorial.getPlayers().keySet())
+ {
+ player.setAllowFlight(true);
+ player.setFlying(true);
+ player.teleport(_location);
+ }
+ }
+ }
+ });
+ try
+ {
+ Thread.sleep(50);
+ } catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ }).start();
+ }
+
+ public void displayText()
+ {
+ new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ while(true)
+ {
+ TutorialText text = getNextMessage();
+ if(text == null)
+ {
+ _tutorial.Manager.runSyncLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ _hasEnded = true;
+ onEnd();
+ _tutorial.nextPhase(false);
+ }
+ }, getTutorial().TimeBetweenPhase);
+ break;
+ }
+ else
+ {
+ Player[] players = new Player[_tutorial.getPlayers().keySet().size()];
+ int i = 0;
+ for(Player player : _tutorial.getPlayers().keySet())
+ {
+ if(_tutorial.PlayTutorialSounds)
+ {
+ if(text.getSound() != null)
+ player.playSound(player.getLocation(), text.getSound(), 2f, 2f);
+ }
+ players[i] = player;
+ i++;
+ }
+ displayMessage(text);
+ UtilTextMiddle.display("", text.getText(), 0, text.getStayTime(), 0, players);
+ try
+ {
+ Thread.sleep(text.getStayTime() * 50);
+ } catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }
+ }).start();
+ }
+
+ private void displayMessage(final TutorialText text)
+ {
+ if(_tutorial.RunTasksSync)
+ {
+ _tutorial.Manager.runSync(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ onMessageDisplay(text);
+ }
+ });
+ }
+ else
+ {
+ onMessageDisplay(text);
+ }
+ }
+
+ protected TutorialText getNextMessage()
+ {
+ for(TutorialText text : _text)
+ {
+ if(_currentText == null && text.ID() == 1)
+ {
+ _currentText = text;
+ return text;
+ }
+ else if(_currentText != null && _currentText.ID() + 1 == text.ID())
+ {
+ _currentText = text;
+ return text;
+ }
+ }
+ return null;
+ }
+
+ public TutorialText[] getText()
+ {
+ return _text;
+ }
+
+ public Location getLocation()
+ {
+ return _location;
+ }
+
+ public void setTutorial(GameTutorial tutorial)
+ {
+ _tutorial = tutorial;
+ }
+
+ public void setLocation(Location location)
+ {
+ _location = location;
+ }
+
+ public void setTarget(Location target)
+ {
+ _target = target;
+ }
+
+ public GameTutorial getTutorial()
+ {
+ return _tutorial;
+ }
+
+ public Location getTarget()
+ {
+ return _target;
+ }
+
+ public long getPhaseTime()
+ {
+ return _started;
+ }
+
+ public void onStart(){}
+
+ public void onMessageDisplay(TutorialText text){}
+
+ public void onEnd(){}
+
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/TutorialText.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/TutorialText.java
new file mode 100644
index 000000000..dba1d39a6
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/TutorialText.java
@@ -0,0 +1,62 @@
+package nautilus.game.arcade.gametutorial;
+
+import org.bukkit.Sound;
+
+
+public class TutorialText
+{
+
+ private String _text;
+ private int _stayTime;
+ private int _id;
+ private Sound _sound;
+
+ public TutorialText(String text, int stayTime, int id, Sound sound)
+ {
+ _text = text;
+ _id = id;
+ _stayTime = stayTime;
+ _sound = sound;
+ }
+
+ public TutorialText(String text, int id)
+ {
+ this(text, (int) (Math.round(1.5 * text.length()) + 25), id, Sound.NOTE_PLING);
+ }
+
+ public TutorialText(String text, int id, Sound sound)
+ {
+ this(text, (int) (Math.round(1.5 * text.length()) + 25), id, sound);
+ }
+
+ public TutorialText(String text, int stayTime, int id)
+ {
+ this(text, stayTime, id, Sound.NOTE_PLING);
+ }
+
+ public String getText()
+ {
+ return _text;
+ }
+
+ public int ID()
+ {
+ return _id;
+ }
+
+ public Sound getSound()
+ {
+ return _sound;
+ }
+
+ public int getStayTime()
+ {
+ return _stayTime;
+ }
+
+ public void setText(String text)
+ {
+ _text = text;
+ }
+
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/events/GameTutorialEndEvent.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/events/GameTutorialEndEvent.java
new file mode 100644
index 000000000..10a540759
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/events/GameTutorialEndEvent.java
@@ -0,0 +1,32 @@
+package nautilus.game.arcade.gametutorial.events;
+
+import nautilus.game.arcade.gametutorial.GameTutorial;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class GameTutorialEndEvent extends Event
+{
+ private static final HandlerList handlers = new HandlerList();
+ private GameTutorial _tutorial;
+
+ public GameTutorialEndEvent(GameTutorial tutorial)
+ {
+ _tutorial = tutorial;
+ }
+
+ public HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+
+ public GameTutorial getTutorial()
+ {
+ return _tutorial;
+ }
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/events/GameTutorialPhaseEvent.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/events/GameTutorialPhaseEvent.java
new file mode 100644
index 000000000..6d9bbf631
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/events/GameTutorialPhaseEvent.java
@@ -0,0 +1,49 @@
+package nautilus.game.arcade.gametutorial.events;
+
+import nautilus.game.arcade.gametutorial.GameTutorial;
+import nautilus.game.arcade.gametutorial.TutorialPhase;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class GameTutorialPhaseEvent extends Event
+{
+ private static final HandlerList handlers = new HandlerList();
+ private GameTutorial _tutorial;
+
+ private TutorialPhase _from;
+ private TutorialPhase _to;
+
+ public GameTutorialPhaseEvent(GameTutorial tutorial, TutorialPhase from, TutorialPhase to)
+ {
+ _tutorial = tutorial;
+ _from = from;
+ _to = to;
+ }
+
+ public HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+
+ public GameTutorial getTutorial()
+ {
+ return _tutorial;
+ }
+
+ public TutorialPhase getFrom()
+ {
+ return _from;
+ }
+
+ public TutorialPhase getTo()
+ {
+ return _to;
+ }
+
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/events/GameTutorialStartEvent.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/events/GameTutorialStartEvent.java
new file mode 100644
index 000000000..38b93f2ca
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gametutorial/events/GameTutorialStartEvent.java
@@ -0,0 +1,32 @@
+package nautilus.game.arcade.gametutorial.events;
+
+import nautilus.game.arcade.gametutorial.GameTutorial;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class GameTutorialStartEvent extends Event
+{
+ private static final HandlerList handlers = new HandlerList();
+ private GameTutorial _tutorial;
+
+ public GameTutorialStartEvent(GameTutorial tutorial)
+ {
+ _tutorial = tutorial;
+ }
+
+ public HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+
+ public GameTutorial getTutorial()
+ {
+ return _tutorial;
+ }
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameGemManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameGemManager.java
index 83230ab09..b49f5bb06 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameGemManager.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameGemManager.java
@@ -16,6 +16,7 @@ import mineplex.serverdata.Utility;
import nautilus.game.arcade.ArcadeFormat;
import nautilus.game.arcade.ArcadeManager;
import nautilus.game.arcade.GameType;
+import nautilus.game.arcade.events.FirstBloodEvent;
import nautilus.game.arcade.events.GameStateChangeEvent;
import nautilus.game.arcade.events.PlayerStateChangeEvent;
import nautilus.game.arcade.game.Game;
@@ -77,6 +78,8 @@ public class GameGemManager implements Listener
{
game.AddGems(killer, 10, "First Blood", false, false);
+ Manager.getPluginManager().callEvent(new FirstBloodEvent(killer));
+
game.FirstKill = false;
game.Announce(F.main("Game", Manager.GetColor(killer) + killer.getName() + " drew first blood!"));
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameManager.java
index ad39df919..ca7bb2df2 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameManager.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameManager.java
@@ -34,6 +34,9 @@ import nautilus.game.arcade.game.Game;
import nautilus.game.arcade.game.GameTeam;
import nautilus.game.arcade.game.Game.GameState;
import nautilus.game.arcade.game.games.uhc.UHC;
+import nautilus.game.arcade.gametutorial.GameTutorial;
+import nautilus.game.arcade.gametutorial.TutorialPhase;
+import nautilus.game.arcade.gametutorial.TutorialText;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -183,6 +186,75 @@ public class GameManager implements Listener
}
}
+ public boolean isInTutorial(boolean checkForTimer)
+ {
+ if (Manager.GetGame() == null || Manager.GetGame().GetState() != GameState.Prepare)
+ return false;
+
+ Game game = Manager.GetGame();
+
+ boolean tutorialSet = false;
+ for(GameTeam team : game.GetTeamList())
+ {
+ if(team.getTutorial() != null)
+ tutorialSet = true;
+ }
+ if(!tutorialSet)
+ {
+ game.addTutorials();
+ }
+ boolean finished = true;
+ if(game.EnableTutorials)
+ {
+ for(Player player : UtilServer.getPlayers())
+ {
+ if(player.getWorld() == Manager.GetLobby().GetSpawn().getWorld())
+ return true;
+ }
+ long prepTime = 0;
+ for(GameTeam team : game.GetTeamList())
+ {
+ long timeUsage = 0;
+ if(team.getTutorial() != null)
+ {
+ if(!team.getTutorial().hasStarted())
+ {
+ team.getTutorial().setTeam(team);
+ team.getTutorial().start();
+ timeUsage = team.getTutorial().StartAfterTutorial;
+ timeUsage = timeUsage + (team.getTutorial().TimeBetweenPhase * team.getTutorial().getPhases().length);
+ for(TutorialPhase phase : team.getTutorial().getPhases())
+ {
+ for(TutorialText text : phase.getText())
+ {
+ timeUsage = timeUsage + (text.getStayTime() * 50);
+ }
+ }
+ }
+ if(!team.getTutorial().hasEnded())
+ {
+ finished = false;
+ if(checkForTimer)
+ {
+ if(team.getTutorial().ShowPrepareTimer)
+ finished = false;
+ else
+ finished = true;
+ }
+ }
+ }
+ if(prepTime <= timeUsage)
+ prepTime = timeUsage;
+ }
+ if(prepTime > 0)
+ Manager.GetGame().PrepareTime = prepTime;
+
+ if(!finished)
+ return true;
+ }
+ return false;
+ }
+
@EventHandler
public void DisplayPrepareTime(UpdateEvent event)
{
@@ -193,6 +265,9 @@ public class GameManager implements Listener
return;
Game game = Manager.GetGame();
+
+ if(isInTutorial(true))
+ return;
double percentage = (double) (System.currentTimeMillis() - game.GetStateTime()) / game.PrepareTime;
@@ -200,6 +275,35 @@ public class GameManager implements Listener
UtilTextBottom.displayProgress("Game Start", percentage,
UtilTime.MakeStr(Math.max(0, game.PrepareTime - (System.currentTimeMillis() - game.GetStateTime()))), player);
}
+
+ @EventHandler
+ public void updateGameTutorials(UpdateEvent event)
+ {
+ if(event.getType() != UpdateType.TICK)
+ return;
+
+ Game game = Manager.GetGame();
+
+ if(game == null)
+ return;
+
+ if(game.GetState() != GameState.Prepare)
+ return;
+
+ if(game.EnableTutorials)
+ {
+ for(GameTeam team : game.GetTeamList())
+ {
+ if(team.getTutorial() != null)
+ {
+ if(!team.getTutorial().hasEnded() && team.getTutorial().hasStarted())
+ {
+ team.getTutorial().onTick(team.getTutorial().tick());
+ }
+ }
+ }
+ }
+ }
@EventHandler
public void StateUpdate(UpdateEvent event)
@@ -247,6 +351,9 @@ public class GameManager implements Listener
}
else if (game.GetState() == GameState.Prepare)
{
+ if(isInTutorial(false))
+ return;
+
if (game.CanStartPrepareCountdown())
{
if (UtilTime.elapsed(game.GetStateTime(), game.PrepareTime))