range = it.next();
+ int span = range.getValue() - range.getKey();
+ if (span < selectedPosition)
+ {
+ selectedPosition -= span + 1;
+
+ }
+ else
+ {
+ selected = range.getKey() + selectedPosition;
+ break;
+ }
+ }
+
+ _remaining.remove(selected);
+ --_remainingCount;
+
+ return selected;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return _remainingCount > 0;
+ }
+
+ /**
+ * A set of integers. The set is seeded by a single range, and the only
+ * supported operation is int removal.
+ *
+ * This implementation only exists for performance reasons.
+ */
+ private static class IntSet
+ {
+ /**
+ * A set of ranges representing the remaining integers in this set
+ */
+ private final NavigableMap ranges = new TreeMap<>();
+
+ /**
+ * Create an IntSet containing all numbers from {@code start} to
+ * {@code end}, inclusive
+ *
+ * @param start The range lower bound, inclusive
+ * @param end The range upper bound, inclusive
+ */
+ private IntSet(int start, int end)
+ {
+ ranges.put(start, end);
+ }
+
+ public Set> ranges()
+ {
+ return ranges.entrySet();
+ }
+
+ /**
+ * Remove an integer from this IntSet
+ * @param value The integer to remove
+ */
+ public void remove(int value)
+ {
+ Map.Entry range = ranges.floorEntry(value);
+ if (range == null || range.getValue() < value)
+ {
+ return;
+ }
+
+ int lower = range.getKey();
+ int upper = range.getValue();
+
+ if (upper > value)
+ {
+ reinsert(value + 1, upper);
+ }
+ reinsert(lower, Math.min(upper, value - 1));
+ }
+
+ private void reinsert(int start, int end)
+ {
+ if (end < start)
+ {
+ ranges.remove(start);
+ }
+ else
+ {
+ ranges.put(start, end);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/F.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/F.java
index 08d6147ad..49da7d9cf 100644
--- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/F.java
+++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/F.java
@@ -104,6 +104,11 @@ public class F
return rank.getColor() + cmd + " " + C.mBody + body + " " + rank(rank);
}
+ public static String help(String cmd, String body, Rank rank, ChatColor displayColor)
+ {
+ return displayColor + cmd + " " + C.mBody + body + " " + rank(rank);
+ }
+
public static String rank(Rank rank)
{
if (rank == Rank.ALL)
diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/PlayerMap.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/PlayerMap.java
index 426d2fd20..5cb6e7758 100644
--- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/PlayerMap.java
+++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/PlayerMap.java
@@ -4,6 +4,7 @@ import com.google.common.collect.Sets;
import org.apache.commons.lang3.Validate;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
@@ -218,7 +219,7 @@ public class PlayerMap implements Map
private static class RemovalListener implements Listener
{
- @EventHandler
+ @EventHandler (priority = EventPriority.MONITOR)
public void onQuit(PlayerQuitEvent event)
{
synchronized (LOCK)
diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilServer.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilServer.java
index 80e388daf..c6e1edcdc 100644
--- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilServer.java
+++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilServer.java
@@ -1,7 +1,10 @@
package mineplex.core.common.util;
import com.google.common.collect.Lists;
+
import mineplex.core.common.events.PlayerRecieveBroadcastEvent;
+import mineplex.serverdata.Region;
+
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.Sound;
@@ -13,6 +16,7 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.scheduler.BukkitTask;
import java.lang.reflect.Field;
import java.util.*;
@@ -52,7 +56,7 @@ public class UtilServer
{
return Bukkit.getServer();
}
-
+
public static void broadcast(String message)
{
for (Player cur : getPlayers())
@@ -61,13 +65,13 @@ public class UtilServer
UtilPlayer.message(cur, message);
}
}
-
+
public static void broadcast(LinkedList messages)
{
for (Player cur : getPlayers())
UtilPlayer.message(cur, messages);
}
-
+
public static void broadcastSpecial(String event, String message)
{
for (Player cur : getPlayers())
@@ -78,32 +82,32 @@ public class UtilServer
cur.playSound(cur.getLocation(), Sound.ORB_PICKUP, 2f, 0f);
}
}
-
+
public static void broadcast(String sender, String message)
{
broadcast("§f§l" + sender + " " + "§b" + message);
}
-
+
public static void broadcastMagic(String sender, String message)
{
broadcast("§2§k" + message);
}
-
- public static double getFilledPercent()
+
+ public static double getFilledPercent()
{
- return (double)getPlayers().length / (double)UtilServer.getServer().getMaxPlayers();
+ return (double) getPlayers().length / (double) UtilServer.getServer().getMaxPlayers();
}
-
+
public static void RegisterEvents(Listener listener)
{
getPluginManager().registerEvents(listener, getPlugin());
}
-
+
public static void Unregister(Listener listener)
{
HandlerList.unregisterAll(listener);
}
-
+
public static JavaPlugin getPlugin()
{
return JavaPlugin.getProvidingPlugin(UtilServer.class);
@@ -135,6 +139,16 @@ public class UtilServer
return getPlugin().getConfig().getString("serverstatus.name");
}
+ public static Region getRegion()
+ {
+ return getPlugin().getConfig().getBoolean("serverstatus.us") ? Region.US : Region.EU;
+ }
+
+ public static String getGroup()
+ {
+ return getPlugin().getConfig().getString("serverstatus.group");
+ }
+
public static boolean isTestServer()
{
return getPlugin().getConfig().getString("serverstatus.group").equalsIgnoreCase("Testing");
@@ -185,4 +199,39 @@ public class UtilServer
{
return getPlugin().getConfig().getString("webServer");
}
+
+ public static BukkitTask runAsync(Runnable runnable)
+ {
+ return getPlugin().getServer().getScheduler().runTaskAsynchronously(getPlugin(), runnable);
+ }
+
+ public static BukkitTask runAsync(Runnable runnable, long time)
+ {
+ return getPlugin().getServer().getScheduler().runTaskLaterAsynchronously(getPlugin(), runnable, time);
+ }
+
+ public static BukkitTask runAsyncTimer(Runnable runnable, long time, long period)
+ {
+ return getPlugin().getServer().getScheduler().runTaskTimerAsynchronously(getPlugin(), runnable, time, period);
+ }
+
+ public static BukkitTask runSync(Runnable runnable)
+ {
+ return getPlugin().getServer().getScheduler().runTask(getPlugin(), runnable);
+ }
+
+ public static BukkitTask runSyncLater(Runnable runnable, long delay)
+ {
+ return getPlugin().getServer().getScheduler().runTaskLater(getPlugin(), runnable, delay);
+ }
+
+ public static BukkitTask runSyncTimer(Runnable runnable, long delay, long period)
+ {
+ return getPlugin().getServer().getScheduler().runTaskTimer(getPlugin(), runnable, delay, period);
+ }
+
+ public static BukkitTask runSyncTimer(BukkitRunnable runnable, long delay, long period)
+ {
+ return runnable.runTaskTimer(getPlugin(), delay, period);
+ }
}
diff --git a/Plugins/Mineplex.Core/pom.xml b/Plugins/Mineplex.Core/pom.xml
index c4dbb202a..65a90f2a7 100644
--- a/Plugins/Mineplex.Core/pom.xml
+++ b/Plugins/Mineplex.Core/pom.xml
@@ -45,6 +45,11 @@
anticheat
1.2
+
+ org.tukaani
+ xz
+ 1.5
+
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java b/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java
index 735494949..d6414e463 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java
@@ -14,6 +14,18 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
+import org.bukkit.Bukkit;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
+import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
+import org.bukkit.event.player.PlayerKickEvent;
+import org.bukkit.event.player.PlayerLoginEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.bukkit.plugin.java.JavaPlugin;
+
import com.google.gson.Gson;
import mineplex.cache.player.PlayerCache;
@@ -26,26 +38,14 @@ import mineplex.core.account.event.ClientWebResponseEvent;
import mineplex.core.account.repository.AccountRepository;
import mineplex.core.account.repository.token.ClientToken;
import mineplex.core.common.Rank;
+import mineplex.core.common.timing.TimingManager;
import mineplex.core.common.util.Callback;
import mineplex.core.common.util.UUIDFetcher;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilTasks;
-import mineplex.core.common.timing.TimingManager;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
-
import mineplex.core.utils.UtilGameProfile;
-import org.bukkit.Bukkit;
-import org.bukkit.OfflinePlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
-import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
-import org.bukkit.event.player.PlayerKickEvent;
-import org.bukkit.event.player.PlayerLoginEvent;
-import org.bukkit.event.player.PlayerQuitEvent;
-import org.bukkit.plugin.java.JavaPlugin;
public class CoreClientManager extends MiniPlugin
{
@@ -453,6 +453,12 @@ public class CoreClientManager extends MiniPlugin
return !CLIENT_LOGIN_LOCKS.containsKey(client.getName());
}
+
+ public ClientToken loadOfflineClient(UUID uuid)
+ {
+ String client = _repository.getClientByUUID(uuid);
+ return new Gson().fromJson(client, ClientToken.class);
+ }
@EventHandler(priority = EventPriority.LOWEST)
public void Login(PlayerLoginEvent event)
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHack.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHack.java
index b5f56ca2e..0023bb1e6 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHack.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHack.java
@@ -1,605 +1,270 @@
package mineplex.core.antihack;
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.AtomicDouble;
-import com.mineplex.anticheat.api.GameEndEvent;
-import com.mineplex.anticheat.api.GameStartEvent;
-import com.mineplex.anticheat.api.MineplexLink;
-import com.mineplex.anticheat.api.PlayerViolationEvent;
-import com.mineplex.anticheat.checks.Check;
-import mineplex.core.Managers;
-import mineplex.core.MiniPlugin;
-import mineplex.core.PlayerSelector;
-import mineplex.core.ReflectivelyCreateMiniPlugin;
-import mineplex.core.account.CoreClient;
-import mineplex.core.account.CoreClientManager;
-import mineplex.core.antihack.actions.AntiHackAction;
-import mineplex.core.antihack.banwave.BanWaveManager;
-import mineplex.core.antihack.types.Fly;
-import mineplex.core.antihack.types.Idle;
-import mineplex.core.antihack.types.Reach;
-import mineplex.core.antihack.types.Speed;
-import mineplex.core.command.CommandBase;
-import mineplex.core.common.Rank;
-import mineplex.core.common.util.*;
-import mineplex.core.disguise.DisguiseManager;
-import mineplex.core.disguise.disguises.DisguiseBase;
-import mineplex.core.portal.Portal;
-import mineplex.core.preferences.Preference;
-import mineplex.core.preferences.PreferencesManager;
-import mineplex.core.punish.Category;
-import mineplex.core.punish.Punish;
-import mineplex.core.punish.PunishClient;
-import mineplex.core.punish.Punishment;
-import mineplex.core.updater.UpdateType;
-import mineplex.core.updater.event.UpdateEvent;
-import mineplex.serverdata.commands.ServerCommandManager;
-import net.minecraft.server.v1_8_R3.*;
-import org.bukkit.*;
-import org.bukkit.Material;
+import javax.xml.bind.DatatypeConverter;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.chat.BaseComponent;
+import net.md_5.bungee.api.chat.ClickEvent;
+import net.md_5.bungee.api.chat.ComponentBuilder;
+import net.md_5.bungee.api.chat.HoverEvent;
+import net.minecraft.server.v1_8_R3.MinecraftServer;
+
+import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
-import org.bukkit.event.player.*;
-import org.bukkit.event.server.ServerListPingEvent;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.player.PlayerCommandPreprocessEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.event.player.PlayerToggleFlightEvent;
import org.bukkit.plugin.ServicePriority;
-import org.bukkit.potion.PotionEffect;
-import org.bukkit.potion.PotionEffectType;
-import org.bukkit.scheduler.BukkitTask;
-import java.util.*;
-import java.util.Map.Entry;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Function;
-import java.util.function.Predicate;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.ImmutableMap;
+import com.google.gson.JsonObject;
+import com.mineplex.anticheat.MineplexAnticheat;
+import com.mineplex.anticheat.api.GameEndEvent;
+import com.mineplex.anticheat.api.GameStartEvent;
+import com.mineplex.anticheat.api.MineplexLink;
+import com.mineplex.anticheat.api.PlayerViolationEvent;
+import com.mineplex.anticheat.checks.Check;
+import com.mineplex.anticheat.checks.CheckManager;
+import com.mineplex.anticheat.checks.combat.KillauraTypeA;
+import com.mineplex.anticheat.checks.combat.KillauraTypeB;
+import com.mineplex.anticheat.checks.combat.KillauraTypeC;
+import com.mineplex.anticheat.checks.combat.KillauraTypeD;
+import com.mineplex.anticheat.checks.combat.KillauraTypeE;
+import com.mineplex.anticheat.checks.combat.KillauraTypeF;
+import com.mineplex.anticheat.checks.move.Glide;
+import com.mineplex.anticheat.checks.move.HeadRoll;
+import com.mineplex.anticheat.checks.move.Speed;
+import com.mineplex.anticheat.checks.player.BadPackets;
+
+import mineplex.core.Managers;
+import mineplex.core.MiniPlugin;
+import mineplex.core.ReflectivelyCreateMiniPlugin;
+import mineplex.core.account.CoreClient;
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.antihack.actions.AntiHackAction;
+import mineplex.core.antihack.actions.BanwaveAction;
+import mineplex.core.antihack.actions.ImmediateBanAction;
+import mineplex.core.antihack.actions.NoopAction;
+import mineplex.core.antihack.animations.BanwaveAnimationSpin;
+import mineplex.core.antihack.banwave.BanWaveInfo;
+import mineplex.core.antihack.banwave.BanWaveManager;
+import mineplex.core.antihack.commands.AnticheatOffCommand;
+import mineplex.core.antihack.commands.AnticheatOnCommand;
+import mineplex.core.antihack.commands.DetailedMessagesCommand;
+import mineplex.core.antihack.commands.GetVlsCommand;
+import mineplex.core.antihack.commands.TestBanCommand;
+import mineplex.core.antihack.guardians.GuardianManager;
+import mineplex.core.antihack.logging.AntihackLogger;
+import mineplex.core.antihack.redisnotifications.GwenBanNotification;
+import mineplex.core.antihack.redisnotifications.GwenBanwaveNotification;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilMath;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.common.util.UtilServer;
+import mineplex.core.disguise.DisguiseManager;
+import mineplex.core.disguise.disguises.DisguiseBase;
+import mineplex.core.preferences.Preference;
+import mineplex.core.preferences.PreferencesManager;
+import mineplex.core.punish.Category;
+import mineplex.core.punish.Punish;
+import mineplex.core.punish.PunishmentResponse;
+import mineplex.serverdata.commands.ServerCommandManager;
@ReflectivelyCreateMiniPlugin
public class AntiHack extends MiniPlugin
{
- public static final Map CHECKS = ImmutableMap.builder()
- .put("Killaura (Type A)", new CheckThresholds("Kill Aura", 0, 25, 50))
- .put("Killaura (Type B)", new CheckThresholds("High CPS", 0, 0, Integer.MAX_VALUE))
- .put("Killaura (Type C)", new CheckThresholds("Reach", 0, Integer.MAX_VALUE, Integer.MAX_VALUE))
- .put("Killaura (Type D)", new CheckThresholds("Kill Aura", 500, 1000, 1500))
- .put("Killaura (Type E)", new CheckThresholds("Kill Aura", 300, 700, 2000))
- .put("Killaura (Type F)", new CheckThresholds("Kill Aura", 150, 250, 350))
- .put("BadPackets", new CheckThresholds("Regen", 500, 1000, 2000))
- .put("Glide", new CheckThresholds("Flying", 50, 100, 200)) // TODO: specific VL levels
- .put("Speed", new CheckThresholds("Speed", 50, 100, 200)) // TODO: specific VL levels
- .put("HeadRoll", new CheckThresholds("Illegal Movement", 0, 0, 0))
+ private static final Map, CheckThresholds> CHECKS = ImmutableMap., CheckThresholds>builder()
+ .put(KillauraTypeA.class, new CheckThresholds("Kill Aura", 0, 25, 50))
+ .put(KillauraTypeB.class, new CheckThresholds("High CPS", 0, 0, Integer.MAX_VALUE))
+ .put(KillauraTypeC.class, new CheckThresholds("Reach", 0, Integer.MAX_VALUE, Integer.MAX_VALUE))
+ .put(KillauraTypeD.class, new CheckThresholds("Kill Aura", 500, 1000, 1500))
+ .put(KillauraTypeE.class, new CheckThresholds("Kill Aura", 300, 700, 2000))
+ .put(KillauraTypeF.class, new CheckThresholds("Kill Aura", 150, 250, 350))
+ .put(BadPackets.class, new CheckThresholds("Regen", 500, 1000, 2000))
+ .put(Glide.class, new CheckThresholds("Flying", 150, 250, 500))
+ .put(Speed.class, new CheckThresholds("Speed", 150, 250, 500))
+ .put(HeadRoll.class, new CheckThresholds("Illegal Movement", 0, 0, 0))
.build();
- public static final String NAME = "Chiss";
- public static final String USER_HAS_BEEN_BANNED = F.main("GWEN", "%s has been banned. I am always watching.");
- public static final String USER_HAS_BEEN_BANNED_BANWAVE = USER_HAS_BEEN_BANNED;
+ private static final CheckThresholds NOOP_THRESHOLD = new CheckThresholds("Unknown", 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
- private static final int VL_DIFF_BEFORE_RENOTIFY = 999999;
- private static final int MAX_STALKED_PLAYERS = 3;
- private static final int STALK_COOLDOWN_TIME_SECONDS = 5;
- private static final int MIN_STALK_TIME = 10 * 20;
- private static final int MAX_STALK_TIME = 20 * 20;
- private static final int MAX_MIN_DIFF = MAX_STALK_TIME - MIN_STALK_TIME;
- private static final Function STALK_END_PROBABILITY_EQUATION = x ->
- {
- return 1.0/ MAX_MIN_DIFF * x; // linear equation with points (0, 0) and (diff, 1)
- };
+ private static final Map, AntiHackAction> ACTIONS = ImmutableMap., AntiHackAction>builder()
+ .put(KillauraTypeA.class, new ImmediateBanAction(200))
+ .put(KillauraTypeD.class, new BanwaveAction(1500))
+ .put(Glide.class, new ImmediateBanAction(10000))
+ .put(Speed.class, new ImmediateBanAction(10000))
+// .put(HeadRoll.class, new ImmediateBanAction(200))
+ .build();
+
+ private static final AntiHackAction NOOP_ACTION = new NoopAction();
+
+ private static final String NAME = "Chiss";
+ private static final String USER_HAS_BEEN_BANNED = F.main("GWEN", "%s has been banned. I am always watching.");
+ private static final String USER_HAS_BEEN_BANNED_BANWAVE = USER_HAS_BEEN_BANNED;
+
+ public static final int ID_LENGTH = 5;
private final Cache _cooldown = CacheBuilder.newBuilder()
.concurrencyLevel(1)
.expireAfterWrite(30, TimeUnit.SECONDS)
.build();
- private final Cache _stalkingCooldown = CacheBuilder.newBuilder()
- .concurrencyLevel(1)
- .expireAfterWrite(STALK_COOLDOWN_TIME_SECONDS, TimeUnit.SECONDS)
- .build();
- private final List _stalking = new ArrayList<>();
- private final String _thisServer;
+ private final String _thisServer = UtilServer.getServerName();
- private boolean _enabled = true;
- private boolean _strict = false;
- private boolean _kick = true;
+ private final CoreClientManager _clientManager = require(CoreClientManager.class);
+ private final AntihackLogger _logger = require(AntihackLogger.class);
+ private final PreferencesManager _preferences = require(PreferencesManager.class);
+ private final Punish _punish = require(Punish.class);
- public Portal Portal = require(Portal.class);
- private PreferencesManager _preferences = require(PreferencesManager.class);
- private CoreClientManager _clientManager = require(CoreClientManager.class);
-
- //Record Offenses
- private HashMap>> _offense = new HashMap>>();
-
- //Ignore Player
- private HashMap _ignore = new HashMap();
-
- //Player Info
- private HashSet _velocityEvent = new HashSet();
- private HashMap _lastMoveEvent = new HashMap();
-
- private HashSet _hubAttempted = new HashSet();
-
- //Hack Requirements
- public int FloatHackTicks = 10;
- public int HoverHackTicks = 4;
- public int RiseHackTicks = 6;
- public int SpeedHackTicks = 6;
- public int IdleTime = 20000;
-
- public int KeepOffensesFor = 30000;
-
- //Other Times
- public int FlightTriggerCancel = 2000;
-
- public ArrayList _movementDetectors;
- public ArrayList _combatDetectors;
-
- private AntiHackRepository _repository;
-
- private List _guardians = new ArrayList<>();
+ private final Set _detailedMessages = new HashSet<>();
private Set _pendingBan = new HashSet<>();
// These are the GWEN checks to ignore when handling PlayerViolationEvent
private HashSet> _ignoredChecks = new HashSet<>();
- @SuppressWarnings("Convert2streamapi")
private AntiHack()
{
super("AntiHack");
- DisguiseManager disguiseManager = require(DisguiseManager.class);
+ _detailedMessages.add("Spoobncoobr");
- this._thisServer = UtilServer.getServerName();
+ require(GuardianManager.class);
+ require(BanWaveManager.class);
- _repository = new AntiHackRepository(this._thisServer);
- _repository.initialize();
-
- _movementDetectors = new ArrayList();
- _combatDetectors = new ArrayList();
-
- _movementDetectors.add(new Fly(this));
- _movementDetectors.add(new Idle(this));
- _movementDetectors.add(new Speed(this));
-
- _combatDetectors.add(new Reach(this));
-
- Bukkit.getServicesManager().register(MineplexLink.class, new MineplexLink()
- {
- @Override
- public EntityType getActiveDisguise(Player player)
- {
- DisguiseBase disguise = disguiseManager.getActiveDisguise(player);
- return disguise != null ? disguise.getDisguiseType() : null;
- }
-
- @Override
- public boolean isSpectator(Player player)
- {
- return UtilPlayer.isSpectator(player);
- }
-
- @Override
- public double getTPS()
- {
- return MinecraftServer.getServer().recentTps[0]; // Return the average TPS from the last minute
- }
-
- @Override
- public int getPing(Player player)
- {
- return Math.min(((CraftPlayer)player).getHandle().ping, 1000);
- }
-
- @Override
- public boolean isUsingItem(Player player)
- {
- return ((CraftPlayer)player).getHandle().bS(); // See Anticheat javadoc
- }
- }, this._plugin, ServicePriority.Normal);
+ Bukkit.getServicesManager().register(MineplexLink.class, new MineplexLinkImpl(), this._plugin, ServicePriority.Normal);
ServerCommandManager.getInstance().registerCommandType(MajorViolationCommand.class, violation ->
{
- IChatBaseComponent component = getMinimalMessage(violation);
-
+ BaseComponent[] minimal = getMinimalMessage(violation);
+ BaseComponent[] detailed = getDetailedMessage(violation);
for (Player player : Bukkit.getOnlinePlayers())
{
- if (player.getName().equals("Spoobncoobr"))
- {
- ((CraftPlayer) player).getHandle().sendMessage(getDetailedMessage(violation));
+ if (_detailedMessages.contains(player.getName()))
+ player.spigot().sendMessage(detailed);
+ else if (_clientManager.Get(player).GetRank().has(Rank.HELPER) && (violation.getOriginatingServer().equals(_thisServer) || _preferences.get(player).isActive(Preference.GLOBAL_GWEN_REPORTS)))
+ player.spigot().sendMessage(minimal);
+ }
+ });
+ }
- } else if (_clientManager.Get(player).GetRank().has(Rank.HELPER) && (violation.getOriginatingServer().equals(_thisServer) || Managers.get(PreferencesManager.class).get(player).isActive(Preference.GLOBAL_GWEN_REPORTS)))
+ @Override
+ public void addCommands()
+ {
+ if (UtilServer.isTestServer())
+ {
+ addCommand(new AnticheatOnCommand(this));
+ addCommand(new AnticheatOffCommand(this));
+ addCommand(new TestBanCommand(this));
+ }
+ addCommand(new GetVlsCommand(this));
+ addCommand(new DetailedMessagesCommand(this));
+ }
+
+ private void runBanAnimation(Player player, Runnable after)
+ {
+ new BanwaveAnimationSpin().run(player, after);
+ }
+
+ public void doBan(Player player, Class extends Check> cause)
+ {
+ runSync(() ->
+ {
+ if (_pendingBan.add(player))
+ {
+ CoreClient coreClient = _clientManager.Get(player);
+
+ Consumer> doPunish = after ->
{
- ((CraftPlayer) player).getHandle().sendMessage(component);
+ JsonObject custom = new JsonObject();
+ custom.addProperty("ban-reason", CheckManager.getCheckSimpleName(cause));
+
+ String id = generateId();
+ String finalMessage = "[GWEN] " + id;
+ _logger.saveMetadata(player, id, () ->
+ {
+ _logger.resetViolations(player, () ->
+ {
+ runAsync(() ->
+ {
+ GwenBanNotification notification = new GwenBanNotification(_thisServer, player.getName(), player.getUniqueId().toString(), CheckManager.getCheckSimpleName(cause), id);
+ ServerCommandManager.getInstance().publishCommand(notification);
+ });
+
+ _punish.AddPunishment(coreClient.getName(), Category.Hacking, finalMessage, AntiHack.NAME, 3, true, -1, true, after);
+ });
+ }, custom);
+ };
+
+ if (coreClient.GetRank().has(Rank.TWITCH))
+ {
+ doPunish.accept(result -> _pendingBan.remove(player));
+ }
+ else
+ {
+ runBanAnimation(player, () ->
+ doPunish.accept(result ->
+ {
+ if (result == PunishmentResponse.Punished)
+ {
+ announceBan(player);
+ }
+ _pendingBan.remove(player);
+ })
+ );
}
}
});
+ }
- this._plugin.getServer().getScheduler().runTaskTimer(this._plugin, () ->
+ public void doBanWave(Player player, BanWaveInfo info)
+ {
+ runSync(() ->
{
- for (AntiHackGuardian guardian : this._guardians)
+ CoreClient coreClient = _clientManager.Get(player);
+
+ Consumer> doPunish = after ->
{
- if (guardian.getTarget() != null && !guardian.getTarget().isOnline())
- {
- this._stalking.remove(guardian.getTarget().getUniqueId());
- guardian.stopTargeting();
- }
- else if (guardian.getTargetingTime() > MIN_STALK_TIME)
- {
- double threshold = STALK_END_PROBABILITY_EQUATION.apply(guardian.getTargetingTime() - MIN_STALK_TIME);
- if (Math.random() <= threshold)
- {
- this._stalking.remove(guardian.getTarget().getUniqueId());
- _stalkingCooldown.put(guardian.getTarget().getUniqueId(), true);
- guardian.stopTargeting();
- }
- }
- guardian.tick();
- }
- }, 0L, 1L);
-
- this._plugin.getServer().getScheduler().runTaskTimer(this._plugin, () ->
- {
- if (_stalking.size() >= MAX_STALKED_PLAYERS)
- {
- return;
- }
-
- if (_guardians.size() == 0)
- {
- return;
- }
-
- List targets = PlayerSelector.selectPlayers(
- UtilLambda.and(
- PlayerSelector.NOT_VANISHED,
- PlayerSelector.hasAnyRank(false,
- Rank.ALL,
- Rank.ULTRA,
- Rank.HERO,
- Rank.LEGEND,
- Rank.TITAN,
- Rank.TWITCH,
- Rank.YOUTUBE_SMALL,
- Rank.YOUTUBE,
- Rank.MEDIA,
- Rank.ADMIN,
- Rank.DEVELOPER,
- Rank.OWNER,
- Rank.LT
- ),
- player -> !_stalking.contains(player.getUniqueId()),
- player -> _stalkingCooldown.getIfPresent(player.getUniqueId()) == null
- ));
-
- while (_stalking.size() < MAX_STALKED_PLAYERS && targets.size() > 0)
- {
- Player target = targets.remove(ThreadLocalRandom.current().nextInt(targets.size()));
-
- int start = ThreadLocalRandom.current().nextInt(_guardians.size());
-
- for (int i = start, j = 0; j < _guardians.size(); i++, j++)
- {
- if (i >= _guardians.size())
- {
- i -= _guardians.size();
- }
- AntiHackGuardian guardian = _guardians.get(i);
- if (!guardian.isTargeting())
- {
- guardian.target(target);
- _stalking.add(target.getUniqueId());
- break;
- }
- }
- }
- }, 0L, 20L);
-
- require(BanWaveManager.class);
- }
-
- private IChatBaseComponent getDetailedMessage(MajorViolationCommand violation)
- {
- return new ChatComponentText("")
- .addSibling(
- new ChatComponentText("A")
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.AQUA)
- .setRandom(true)
- )
- )
- .addSibling(
- new ChatComponentText(" GWEN > ")
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.RED)
- .setBold(true)
- )
- )
- .addSibling(
- new ChatComponentText(violation.getPlayerName())
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.GOLD)
- )
- )
- .addSibling(
- new ChatComponentText(" failed " + violation.getHackType() + " VL" + violation.getViolations() + " in server ")
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.YELLOW)
- )
- )
- .addSibling(
- new ChatComponentText(
- violation.getOriginatingServer()
- )
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.YELLOW)
- .setChatClickable(
- new ChatClickable(
- ChatClickable.EnumClickAction.RUN_COMMAND,
- "/server " + violation.getOriginatingServer()
- )
- )
- .setChatHoverable(
- new ChatHoverable(
- ChatHoverable.EnumHoverAction.SHOW_TEXT,
- new ChatComponentText("Teleport to " + violation.getOriginatingServer())
- )
- )
- )
- )
- .addSibling(
- new ChatComponentText(": " + violation.getMessage() + ".")
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.YELLOW)
- )
- );
- }
-
- private IChatBaseComponent getMinimalMessage(MajorViolationCommand violation)
- {
- IChatBaseComponent component = new ChatComponentText("")
- .addSibling(
- new ChatComponentText("A")
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.AQUA)
- .setRandom(true)
- )
- )
- .addSibling(
- new ChatComponentText(" GWEN > ")
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.RED)
- .setBold(true)
- )
- )
- .addSibling(
- new ChatComponentText(violation.getPlayerName())
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.GOLD)
- )
- )
- .addSibling(
- new ChatComponentText(" suspected of ")
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.YELLOW)
- )
- )
- .addSibling(CHECKS.get(violation.getHackType()).format(violation.getViolations()));
-
- if (!violation.getOriginatingServer().equals(this._thisServer))
- {
- component
- .addSibling(
- new ChatComponentText(" in ")
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.YELLOW)
- )
- )
- .addSibling(
- new ChatComponentText(violation.getOriginatingServer())
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.AQUA)
- .setChatClickable(
- new ChatClickable(
- ChatClickable.EnumClickAction.RUN_COMMAND,
- "/server " + violation.getOriginatingServer()
- )
- )
- .setChatHoverable(
- new ChatHoverable(
- ChatHoverable.EnumHoverAction.SHOW_TEXT,
- new ChatComponentText("Teleport to " + violation.getOriginatingServer())
- )
- )
- )
- );
- }
-
- return component.addSibling(
- new ChatComponentText(".")
- .setChatModifier(
- new ChatModifier()
- .setColor(EnumChatFormat.YELLOW)
- )
- );
- }
-
- public void registerGuardian(AntiHackGuardian guardian)
- {
- this._guardians.add(guardian);
- }
-
- public void clearGuardians()
- {
- this._guardians.forEach(AntiHackGuardian::remove);
- this._guardians.clear();
- this._stalking.clear();
- this._stalkingCooldown.cleanUp();
- }
-
- public void runBanAnimation(Player player, Runnable after)
- {
- if (_pendingBan.add(player))
- {
- float oldWalkSpeed = player.getWalkSpeed();
- player.setWalkSpeed(0);
- player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, 999999, -10));
-
- double radius = 4;
- double heightAdj = 8;
-
- double baseDeg = 18;
-
- Location center = player.getLocation().add(0, heightAdj, 0);
- AntiHackGuardian north = new AntiHackGuardian(center.clone().add(0, 0, -radius), 0, 0, 0, 0, 0, 0, false);
- AntiHackGuardian east = new AntiHackGuardian(center.clone().add(radius, 0, 0), 0, 0, 0, 0, 0, 0, false);
- AntiHackGuardian south = new AntiHackGuardian(center.clone().add(0, 0, radius), 0, 0, 0, 0, 0, 0, false);
- AntiHackGuardian west = new AntiHackGuardian(center.clone().add(-radius, 0, 0), 0, 0, 0, 0, 0, 0, false);
-
- UtilEnt.CreatureLook(east.getEntity(), player);
- UtilEnt.CreatureLook(west.getEntity(), player);
- UtilEnt.CreatureLook(south.getEntity(), player);
- UtilEnt.CreatureLook(north.getEntity(), player);
-
- Function magic = seconds ->
- {
- return Math.pow(2, seconds - 5);
+ _punish.AddPunishment(coreClient.getName(), Category.Hacking, info.getMessage(), AntiHack.NAME, 3, true, -1, true, after);
};
- runSyncLater(() ->
- {
- north.shoot(player);
- east.shoot(player);
- south.shoot(player);
- west.shoot(player);
-
- // We get 5 seconds, or 100 ticks
- AtomicInteger timer = new AtomicInteger(5);
- AtomicReference task = new AtomicReference<>();
-
- AtomicDouble cNorth = new AtomicDouble(270);
- AtomicDouble cEast = new AtomicDouble(0);
- AtomicDouble cSouth = new AtomicDouble(90);
- AtomicDouble cWest = new AtomicDouble(180);
-
- task.set(runSyncTimer(() ->
- {
- timer.getAndIncrement();
- if (timer.get() > 100)
- {
- task.get().cancel();
-
- player.removePotionEffect(PotionEffectType.JUMP);
- player.setWalkSpeed(oldWalkSpeed);
- Location location = player.getLocation();
-
- UtilParticle.PlayParticle(UtilParticle.ParticleType.HUGE_EXPLOSION, player.getLocation(), 3f, 3f, 3f, 0, 32, UtilParticle.ViewDist.MAX, UtilServer.getPlayers());
-
- after.run();
-
- _pendingBan.remove(player);
-
- north.shoot(null);
- south.shoot(null);
- east.shoot(null);
- west.shoot(null);
- UtilEnt.CreatureLook(north.getEntity(), location);
- UtilEnt.CreatureLook(south.getEntity(), location);
- UtilEnt.CreatureLook(east.getEntity(), location);
- UtilEnt.CreatureLook(west.getEntity(), location);
- runSyncLater(() ->
- {
- north.remove();
- south.remove();
- east.remove();
- west.remove();
- }, 40L);
- return;
- }
-
- double seconds = timer.get() / 20.0;
-
- double rate = magic.apply(seconds) * 3 * baseDeg;
-
- player.getLocation(center);
- center.add(0, heightAdj, 0);
-
- {
- cNorth.addAndGet(rate);
- north.move(center.getX() + radius * MathHelper.cos((float) Math.toRadians(cNorth.get())), center.getY(), center.getZ() + radius * MathHelper.sin((float) Math.toRadians(cNorth.get())));
- }
- {
- cSouth.addAndGet(rate);
- south.move(center.getX() + radius * MathHelper.cos((float) Math.toRadians(cSouth.get())), center.getY(), center.getZ() + radius * MathHelper.sin((float) Math.toRadians(cSouth.get())));
- }
- {
- cEast.addAndGet(rate);
- east.move(center.getX() + radius * MathHelper.cos((float) Math.toRadians(cEast.get())), center.getY(), center.getZ() + radius * MathHelper.sin((float) Math.toRadians(cEast.get())));
- }
- {
- cWest.addAndGet(rate);
- west.move(center.getX() + radius * MathHelper.cos((float) Math.toRadians(cWest.get())), center.getY(), center.getZ() + radius * MathHelper.sin((float) Math.toRadians(cWest.get())));
- }
- }, 5, 1));
- }, 20);
- }
- }
-
- public void doBan(Player player, String message)
- {
- runSync(() ->
- {
- CoreClient coreClient = _clientManager.Get(player);
-
if (coreClient.GetRank().has(Rank.TWITCH))
{
- require(Punish.class).AddPunishment(coreClient.getName(), Category.Hacking, message, AntiHack.NAME, 3, true, -1, true);
- }
- else
- {
- runBanAnimation(player, () ->
+ doPunish.accept(response ->
{
- require(Punish.class).AddPunishment(coreClient.getName(), Category.Hacking, message, AntiHack.NAME, 3, true, -1, true);
- announceBan(player);
});
}
- });
- }
-
- public void doBanWave(Player player, String message)
- {
- runSync(() ->
- {
- int totalPunishments = getPunishments(player);
- int daysBanned = getDaysBanned(player);
- CoreClient coreClient = _clientManager.Get(player);
- if (coreClient.GetRank().has(Rank.TWITCH))
- {
- require(Punish.class).AddPunishment(coreClient.getName(), Category.Hacking, message, AntiHack.NAME, totalPunishments + 1, true, daysBanned == -1 ? -1 : TimeUnit.DAYS.toHours(daysBanned), true);
- }
else
{
runBanAnimation(player, () ->
{
- require(Punish.class).AddPunishment(coreClient.getName(), Category.Hacking, message, AntiHack.NAME, totalPunishments + 1, true, daysBanned == -1 ? -1 : TimeUnit.DAYS.toHours(daysBanned), true);
- announceBanwave(player);
+ doPunish.accept(result ->
+ {
+ if (result == PunishmentResponse.Punished)
+ {
+ announceBanwave(player);
+ }
+ });
});
}
});
@@ -642,13 +307,18 @@ public class AntiHack extends MiniPlugin
}
}
- @EventHandler
- public void on(PlayerViolationEvent event)
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void on(EntityDamageEvent event)
{
- if (_ignoredChecks.contains(event.getCheckClass()))
- return;
+ if (_pendingBan.contains(event.getEntity()))
+ event.setCancelled(true);
+ }
- AntiHackAction.getAction(event.getCheckClass()).handle(event);
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void on(EntityDamageByEntityEvent event)
+ {
+ if (_pendingBan.contains(event.getDamager()))
+ event.setCancelled(true);
}
public void announceBan(Player player)
@@ -661,326 +331,16 @@ public class AntiHack extends MiniPlugin
Bukkit.getServer().broadcastMessage(String.format(USER_HAS_BEEN_BANNED_BANWAVE, player.getName()));
}
- public int getPunishments(Player player)
+ public boolean toggleDetailedMessage(Player player)
{
- PunishClient punishClient = require(Punish.class).GetClient(player.getName());
-
- int totalPunishments = 0;
-
- if (punishClient.GetPunishments().containsKey(Category.Hacking))
- {
- for (Punishment punishment : punishClient.GetPunishments().get(Category.Hacking))
- {
- if (punishment.GetAdmin().equalsIgnoreCase(NAME))
- {
- totalPunishments++;
- }
- }
- }
-
- return totalPunishments;
- }
-
- public int getDaysBanned(Player player)
- {
- int totalPunishments = getPunishments(player);
-
- int daysBanned = 0;
-
- switch (totalPunishments)
- {
- case 0:
- daysBanned = 7;
- break;
- case 1:
- daysBanned = 30;
- break;
- case 2:
- default:
- daysBanned = -1;
- }
-
- return daysBanned;
- }
-
- @Override
- public void addCommands()
- {
- if (UtilServer.isTestServer())
- {
- addCommand(new CommandBase(this, Rank.DEVELOPER, "acon")
- {
- @Override
- public void Execute(Player caller, String[] args)
- {
- if (caller.getUniqueId().toString().equals("b86b54da-93dd-46f9-be33-27bd92aa36d7"))
- {
- enableNewAnticheat();
- UtilPlayer.message(caller, F.main(getName(), "Enabled new anticheat"));
- }
- }
- });
- addCommand(new CommandBase(this, Rank.DEVELOPER, "acoff")
- {
- @Override
- public void Execute(Player caller, String[] args)
- {
- if (caller.getUniqueId().toString().equals("b86b54da-93dd-46f9-be33-27bd92aa36d7"))
- {
- disableNewAnticheat();
- UtilPlayer.message(caller, F.main(getName(), "Disabled new anticheat"));
- }
- }
- });
- addCommand(new CommandBase(this, Rank.DEVELOPER, "testban")
- {
- @Override
- public void Execute(Player caller, String[] args)
- {
- if (caller.getUniqueId().toString().equals("b86b54da-93dd-46f9-be33-27bd92aa36d7"))
- {
- if (args.length > 0)
- {
- Player p = Bukkit.getPlayerExact(args[0]);
- if (p != null)
- {
- runBanAnimation(p, () ->
- {
- String reason = C.cRed + C.Bold + "You are banned for permanent by " + NAME +
- "\n" + C.cWhite + "Seems to be speeding up time. (" + ThreadLocalRandom.current().nextInt(200, 400) + " packets/150 ms)" +
- "\n" + C.cDGreen + "Unfairly banned? Appeal at " + C.cGreen + "www.mineplex.com/appeals";
- p.kickPlayer(reason);
-
- announceBan(p);
- });
- }
- else
- {
- UtilPlayer.message(caller, F.main(getName(), "Could not find player"));
- }
- }
- else
- {
- UtilPlayer.message(caller, F.main(getName(), "No player specified"));
- }
- }
- }
- });
- }
- }
-
- @EventHandler
- public void playerMove(PlayerMoveEvent event)
- {
- if (!_enabled)
- return;
-
- _lastMoveEvent.put(event.getPlayer(), System.currentTimeMillis());
- }
-
- @EventHandler
- public void playerTeleport(PlayerTeleportEvent event)
- {
- if (!_enabled)
- return;
-
- setIgnore(event.getPlayer(), 2000);
- }
-
- @EventHandler
- public void playerVelocity(PlayerVelocityEvent event)
- {
- if (!_enabled)
- return;
-
- _velocityEvent.add(event.getPlayer());
- }
-
- @EventHandler
- public void playerQuit(PlayerQuitEvent event)
- {
- if (!_enabled)
- return;
-
- resetAll(event.getPlayer());
- }
-
- @EventHandler
- public void startIgnore(PlayerMoveEvent event)
- {
- if (!_enabled)
- return;
-
- Player player = event.getPlayer();
-
- if (_velocityEvent.remove(player))
- {
- setIgnore(player, 2000);
- }
-
- //Initial Move (or Lag) Ignore
- if (_lastMoveEvent.containsKey(player))
- {
- long timeBetweenPackets = System.currentTimeMillis() - _lastMoveEvent.get(player);
-
- if (timeBetweenPackets > 500)
- {
- setIgnore(player, Math.min(4000, timeBetweenPackets));
- }
- }
- }
-
- public void setIgnore(Player player, long time)
- {
- //Wipe Detection
- for (Detector detector : _movementDetectors)
- detector.Reset(player);
-
- //Already ignoring for a longer period
- if (_ignore.containsKey(player) && _ignore.get(player) > System.currentTimeMillis() + time)
- return;
-
- //Add Ignore
- _ignore.put(player, System.currentTimeMillis() + time);
- }
-
- public boolean isValid(Player player, boolean groundValid)
- {
- //Near Other Player
- for (Player other : UtilServer.getPlayers())
- {
- if (player.equals(other))
- continue;
-
- if (other.getGameMode() != GameMode.SURVIVAL || UtilPlayer.isSpectator(player))
- continue;
-
- if (other.getVehicle() != null)
- continue;
-
- if (UtilMath.offset(player, other) < 2)
- return true;
- }
-
- if (player.isFlying() || ((CraftPlayer) player).getHandle().isGliding() || player.isInsideVehicle() || player.getGameMode() != GameMode.SURVIVAL || UtilPlayer.isSpectator(player))
+ if (_detailedMessages.add(player.getName()))
{
return true;
}
-
- if (UtilInv.IsItem(player.getInventory().getArmorContents()[2], Material.ELYTRA, (byte) 0))
+ else
{
- return true;
- }
-
- //On Ground
- if (groundValid)
- {
- if (UtilEnt.onBlock(player) || player.getLocation().getBlock().getType() != Material.AIR)
- {
- return true;
- }
- }
-
- if ((_ignore.containsKey(player) && System.currentTimeMillis() < _ignore.get(player)))
- {
- return true;
- }
-
- return false;
- }
-
- public void addSuspicion(Player player, String type)
- {
- if (!_enabled)
- return;
-
- System.out.println(C.cRed + C.Bold + player.getName() + " suspected for " + type + ".");
-
- //Add Offense
- if (!_offense.containsKey(player))
- _offense.put(player, new HashMap>());
-
- if (!_offense.get(player).containsKey(type))
- _offense.get(player).put(type, new ArrayList());
-
- _offense.get(player).get(type).add(System.currentTimeMillis());
-
- //Cull & Count
- int total = 0;
- for (String curType : _offense.get(player).keySet())
- {
- //Remove Old Offenses
- Iterator offenseIterator = _offense.get(player).get(curType).iterator();
- while (offenseIterator.hasNext())
- {
- if (UtilTime.elapsed(offenseIterator.next(), KeepOffensesFor))
- offenseIterator.remove();
- }
-
- //Count
- total += _offense.get(player).get(curType).size();
- }
-
- // Print (Debug)
- System.out.println("[Offense] #" + total + ": " + player.getName() + " received suspicion for " + type + ".");
- }
-
- @EventHandler
- public void generateReports(UpdateEvent event)
- {
- if (!_enabled)
- return;
-
- if (event.getType() != UpdateType.SEC)
- return;
-
- for (Iterator>>> playerIterator = _offense.entrySet().iterator(); playerIterator.hasNext(); )
- {
- Entry>> entry = playerIterator.next();
- Player player = entry.getKey();
-
- String out = "";
- int total = 0;
-
- for (String type : entry.getValue().keySet())
- {
- //Remove Old Offenses
- Iterator offenseIterator = entry.getValue().get(type).iterator();
- while (offenseIterator.hasNext())
- {
- long time = offenseIterator.next();
-
- if (UtilTime.elapsed(time, KeepOffensesFor))
- offenseIterator.remove();
- }
-
- //Count
- int count = entry.getValue().get(type).size();
- total += count;
-
- out += count + " " + type + ", ";
- }
-
- if (out.length() > 0)
- out = out.substring(0, out.length() - 2);
-
- String severity = "Low";
-
- if (total > (_strict ? 6 : 18))
- severity = "Extreme";
- else if (total > (_strict ? 4 : 12))
- severity = "High";
- else if (total > (_strict ? 2 : 6))
- severity = "Medium";
-
- //Send Report
- sendReport(player, out, severity);
-
- if (severity.equalsIgnoreCase("Extreme"))
- {
- playerIterator.remove();
- resetAll(player, false);
- }
+ _detailedMessages.remove(player.getName());
+ return false;
}
}
@@ -990,13 +350,11 @@ public class AntiHack extends MiniPlugin
if (_ignoredChecks.contains(event.getCheckClass()))
return;
+ ACTIONS.getOrDefault(event.getCheckClass(), NOOP_ACTION).handle(event);
+
if (event.shouldTellStaff())
{
- CheckThresholds thresholds = CHECKS.get(event.getHackType());
- if (thresholds == null)
- {
- thresholds = new CheckThresholds(event.getHackType(), 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
- }
+ CheckThresholds thresholds = CHECKS.getOrDefault(event.getCheckClass(), NOOP_THRESHOLD);
CheckThresholds.Severity severity = thresholds.getSeverity(event.getViolations());
if (severity == CheckThresholds.Severity.NONE)
@@ -1007,18 +365,9 @@ public class AntiHack extends MiniPlugin
String key = event.getPlayer().getName() + "." + event.getHackType() + "." + severity.toString();
Integer pastVl = this._cooldown.getIfPresent(key);
- if (pastVl != null)
+ if (pastVl == null)
{
- if (event.getViolations() - pastVl > VL_DIFF_BEFORE_RENOTIFY)
- {
- this._cooldown.put(key, event.getViolations());
- MajorViolationCommand command = new MajorViolationCommand(_thisServer, event.getPlayer().getName(), event.getHackType(), event.getViolations(), event.getMessage());
- ServerCommandManager.getInstance().publishCommand(command);
- }
- }
- else
- {
- MajorViolationCommand command = new MajorViolationCommand(_thisServer, event.getPlayer().getName(), event.getHackType(), event.getViolations(), event.getMessage());
+ MajorViolationCommand command = new MajorViolationCommand(_thisServer, event.getPlayer().getName(), CheckManager.getCheckSimpleName(event.getCheckClass()), event.getViolations(), event.getMessage());
ServerCommandManager.getInstance().publishCommand(command);
this._cooldown.put(key, event.getViolations());
@@ -1026,138 +375,10 @@ public class AntiHack extends MiniPlugin
}
}
- public void sendReport(Player player, String report, String severity)
- {
- if (severity.equals("Extreme"))
- {
- //Staff
- boolean handled = false;
- for (Player staff : UtilServer.getPlayers())
- {
- if (_clientManager.Get(staff).GetRank().has(Rank.MODERATOR))
- {
- UtilPlayer.message(staff, C.cAqua + C.Scramble + "A" + ChatColor.RESET + C.cRed + C.Bold + " MAC > " + ChatColor.RESET + C.cYellow + report);
- UtilPlayer.message(staff, C.cAqua + C.Scramble + "A" + ChatColor.RESET + C.cRed + C.Bold + " MAC > " + ChatColor.RESET + C.cGold + player.getName() + C.cYellow + " has extreme violation.");
-
- handled = true;
- }
- }
-
- //Record
- ServerListPingEvent event = new ServerListPingEvent(null, Bukkit.getServer().getMotd(), Bukkit.getServer().getOnlinePlayers().size(), Bukkit.getServer().getMaxPlayers());
- getPluginManager().callEvent(event);
-
- String motd = event.getMotd();
- String game = "N/A";
- String map = "N/A";
-
- String[] args = motd.split("\\|");
-
- if (args.length > 0)
- motd = args[0];
-
- if (args.length > 2)
- game = args[2];
-
- if (args.length > 3)
- map = args[3];
-
- _repository.saveOffense(player, motd, game, map, report);
- }
- }
-
- private void reset()
- {
- for (Player player : UtilServer.getPlayers())
- resetAll(player);
- }
-
- private void resetAll(Player player)
- {
- resetAll(player, true);
- }
-
- private void resetAll(Player player, boolean removeOffenses)
- {
- _ignore.remove(player);
- _velocityEvent.remove(player);
- _lastMoveEvent.remove(player);
-
- if (removeOffenses)
- _offense.remove(player);
-
- for (Detector detector : _movementDetectors)
- detector.Reset(player);
-
- for (Detector detector : _combatDetectors)
- detector.Reset(player);
- }
-
- @EventHandler
- public void cleanupPlayers(UpdateEvent event)
- {
- if (!_enabled)
- return;
-
- if (event.getType() != UpdateType.SLOW)
- return;
-
- for (Iterator> playerIterator = _ignore.entrySet().iterator(); playerIterator.hasNext(); )
- {
- Player player = playerIterator.next().getKey();
-
- if (!player.isOnline() || player.isDead() || !player.isValid())
- {
- playerIterator.remove();
-
- _velocityEvent.remove(player);
- _lastMoveEvent.remove(player);
-
- _offense.remove(player);
-
- for (Detector detector : _movementDetectors)
- detector.Reset(player);
-
- for (Detector detector : _combatDetectors)
- detector.Reset(player);
- }
- }
-
-
- for (Iterator playerIterator = _hubAttempted.iterator(); playerIterator.hasNext(); )
- {
- Player player = playerIterator.next();
-
- if (!player.isOnline() || !player.isValid())
- {
- playerIterator.remove();
- }
- }
- }
-
- public void setEnabled(boolean b)
- {
- _enabled = b;
- System.out.println("MAC Enabled: " + b);
- }
-
- public boolean isEnabled()
- {
- return _enabled;
- }
-
- public void setStrict(boolean strict)
- {
- _strict = strict;
-
- reset();
-
- System.out.println("MAC Strict: " + strict);
- }
-
/**
* Add a GWEN Anticheat class to the ignored checks.
* All violation events for these checks will be ignored
+ *
* @param check The class of the check to ignore
*/
public void addIgnoredCheck(Class extends Check> check)
@@ -1174,27 +395,63 @@ public class AntiHack extends MiniPlugin
_ignoredChecks.clear();
}
- public boolean isStrict()
- {
- return _strict;
- }
-
- public void setKick(boolean kick)
- {
- _kick = kick;
-
- System.out.println("MAC Kick: " + kick);
- }
-
- public void enableNewAnticheat()
+ public void enableAnticheat()
{
UtilServer.CallEvent(new GameStartEvent());
- System.out.println("Enabled new anticheat");
}
- public void disableNewAnticheat()
+ public void disableAnticheat()
{
UtilServer.CallEvent(new GameEndEvent());
- System.out.println("Disabled new anticheat");
+ }
+
+ private BaseComponent[] getDetailedMessage(MajorViolationCommand violation)
+ {
+ return new ComponentBuilder("")
+ .append("A").color(ChatColor.AQUA).obfuscated(true)
+ .append(" GWEN > ", ComponentBuilder.FormatRetention.NONE).color(ChatColor.RED).bold(true)
+ .append(violation.getPlayerName(), ComponentBuilder.FormatRetention.NONE).color(ChatColor.GOLD)
+ .append(" failed " + violation.getHackType() + " VL" + violation.getViolations() + " in server", ComponentBuilder.FormatRetention.NONE).color(ChatColor.YELLOW)
+ .append(violation.getOriginatingServer(), ComponentBuilder.FormatRetention.NONE).color(ChatColor.YELLOW)
+ .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/server " + violation.getOriginatingServer()))
+ .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
+ new ComponentBuilder("Teleport to " + violation.getOriginatingServer()).create()))
+ .append(": " + violation.getMessage() + ".", ComponentBuilder.FormatRetention.NONE).color(ChatColor.YELLOW)
+ .create();
+ }
+
+ private BaseComponent[] getMinimalMessage(MajorViolationCommand violation)
+ {
+ Class extends Check> checkType = CheckManager.getCheckBySimpleName(violation.getHackType());
+ if (!CHECKS.containsKey(checkType))
+ {
+ System.out.println("Warning: Unknown check type '" + violation.getHackType() + "' " + checkType);
+ }
+ ComponentBuilder componentBuilder = new ComponentBuilder("")
+ .append("A").color(ChatColor.AQUA).obfuscated(true)
+ .append(" GWEN > ", ComponentBuilder.FormatRetention.NONE).color(ChatColor.RED).bold(true)
+ .append(violation.getPlayerName(), ComponentBuilder.FormatRetention.NONE).color(ChatColor.GOLD)
+ .append(" suspected of ", ComponentBuilder.FormatRetention.NONE).color(ChatColor.YELLOW);
+ CHECKS.getOrDefault(checkType, NOOP_THRESHOLD).format(componentBuilder, violation.getViolations());
+
+ if (!violation.getOriginatingServer().equals(this._thisServer))
+ {
+ componentBuilder.append(" in ", ComponentBuilder.FormatRetention.NONE).color(ChatColor.YELLOW)
+ .append(violation.getOriginatingServer()).color(ChatColor.AQUA)
+ .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/server " + violation.getOriginatingServer()))
+ .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
+ new ComponentBuilder("Teleport to " + violation.getOriginatingServer()).create()));
+ }
+
+ componentBuilder.append(".").color(ChatColor.YELLOW);
+
+ return componentBuilder.create();
+ }
+
+ public static String generateId()
+ {
+ byte[] holder = new byte[ID_LENGTH];
+ ThreadLocalRandom.current().nextBytes(holder);
+ return DatatypeConverter.printHexBinary(holder);
}
}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHackRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHackRepository.java
deleted file mode 100644
index eb3b3cd0c..000000000
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHackRepository.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package mineplex.core.antihack;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-
-import mineplex.serverdata.database.DBPool;
-
-import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-
-public class AntiHackRepository
-{
- private String _serverName;
-
- //private static String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS AntiHack_Kick_Log (id INT NOT NULL AUTO_INCREMENT, updated LONG, playerName VARCHAR(256), motd VARCHAR(56), gameType VARCHAR(56), map VARCHAR(256), serverName VARCHAR(256), report VARCHAR(256), ping VARCHAR(25), PRIMARY KEY (id));";
- private static String UPDATE_PLAYER_OFFENSES = "INSERT INTO AntiHack_Kick_Log (updated, playerName, motd, gameType, map, serverName, report, ping) VALUES (now(), ?, ?, ?, ?, ?, ?, ?);";
-
- public AntiHackRepository(String serverName)
- {
- _serverName = serverName;
- }
-
- public void initialize()
- {
- }
-
- public void saveOffense(final Player player, final String motd, final String game, final String map, final String report)
- {
- new Thread(new Runnable()
- {
- public void run()
- {
- PreparedStatement preparedStatement = null;
-
- try (Connection connection = DBPool.getMineplexStats().getConnection())
- {
- preparedStatement = connection.prepareStatement(UPDATE_PLAYER_OFFENSES);
-
- preparedStatement.setString(1, player.getName());
- preparedStatement.setString(2, motd);
- preparedStatement.setString(3, game);
- preparedStatement.setString(4, map);
- preparedStatement.setString(5, _serverName);
- preparedStatement.setString(6, report);
- preparedStatement.setString(7, ((CraftPlayer)player).getHandle().ping + "ms");
-
- preparedStatement.execute();
- }
- catch (Exception exception)
- {
- exception.printStackTrace();
- }
- finally
- {
- if (preparedStatement != null)
- {
- try
- {
- preparedStatement.close();
- }
- catch (SQLException e)
- {
- e.printStackTrace();
- }
- }
- }
- }
- }).start();
- }
-}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/CheckThresholds.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/CheckThresholds.java
index f64783e55..590739775 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/CheckThresholds.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/CheckThresholds.java
@@ -1,5 +1,7 @@
package mineplex.core.antihack;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.chat.ComponentBuilder;
import net.minecraft.server.v1_8_R3.ChatComponentText;
import net.minecraft.server.v1_8_R3.ChatModifier;
import net.minecraft.server.v1_8_R3.EnumChatFormat;
@@ -25,10 +27,9 @@ public class CheckThresholds
return _friendlyName;
}
- public IChatBaseComponent format(int violationLevel)
+ public void format(ComponentBuilder builder, int violationLevel)
{
- EnumChatFormat color = getSeverity(violationLevel)._color;
- return new ChatComponentText(_friendlyName).setChatModifier(new ChatModifier().setColor(color));
+ builder.append(_friendlyName, ComponentBuilder.FormatRetention.NONE).color(getSeverity(violationLevel)._color);
}
public Severity getSeverity(int violationLevel)
@@ -51,14 +52,14 @@ public class CheckThresholds
public enum Severity
{
- NONE(EnumChatFormat.GREEN),
- LOW(EnumChatFormat.GREEN),
- MEDIUM(EnumChatFormat.GOLD),
- HIGH(EnumChatFormat.RED),
+ NONE(ChatColor.GREEN),
+ LOW(ChatColor.GREEN),
+ MEDIUM(ChatColor.GOLD),
+ HIGH(ChatColor.RED),
;
- private final EnumChatFormat _color;
+ private final ChatColor _color;
- Severity(EnumChatFormat color)
+ Severity(ChatColor color)
{
_color = color;
}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/Detector.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/Detector.java
deleted file mode 100644
index 5cfec165e..000000000
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/Detector.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package mineplex.core.antihack;
-
-import org.bukkit.entity.Player;
-
-public interface Detector
-{
- public void Reset(Player player);
-}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/MineplexLinkImpl.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/MineplexLinkImpl.java
new file mode 100644
index 000000000..6195a3fd2
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/MineplexLinkImpl.java
@@ -0,0 +1,50 @@
+package mineplex.core.antihack;
+
+import net.minecraft.server.v1_8_R3.MinecraftServer;
+
+import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+
+import com.mineplex.anticheat.api.MineplexLink;
+
+import mineplex.core.Managers;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.disguise.DisguiseManager;
+import mineplex.core.disguise.disguises.DisguiseBase;
+
+public class MineplexLinkImpl implements MineplexLink
+{
+ private final DisguiseManager _disguiseManager = Managers.require(DisguiseManager.class);
+
+ @Override
+ public EntityType getActiveDisguise(Player player)
+ {
+ DisguiseBase disguise = _disguiseManager.getActiveDisguise(player);
+ return disguise != null ? disguise.getDisguiseType() : null;
+ }
+
+ @Override
+ public boolean isSpectator(Player player)
+ {
+ return UtilPlayer.isSpectator(player);
+ }
+
+ @Override
+ public double getTPS()
+ {
+ return MinecraftServer.getServer().recentTps[0]; // Return the average TPS from the last minute
+ }
+
+ @Override
+ public int getPing(Player player)
+ {
+ return Math.min(((CraftPlayer) player).getHandle().ping, 1000);
+ }
+
+ @Override
+ public boolean isUsingItem(Player player)
+ {
+ return ((CraftPlayer) player).getHandle().bS(); // See Anticheat javadoc
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/ViolationLevels.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/ViolationLevels.java
new file mode 100644
index 000000000..00a800bce
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/ViolationLevels.java
@@ -0,0 +1,87 @@
+package mineplex.core.antihack;
+
+import com.mineplex.anticheat.checks.Check;
+import com.mineplex.anticheat.checks.CheckManager;
+
+import gnu.trove.map.TObjectIntMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+
+/**
+ * Locally cached information about a user's max violations and total number of alerts for each
+ * check type.
+ *
+ * Instances of this have no concept of identity i.e. account id is not tracked by this.
+ */
+public class ViolationLevels
+{
+ private final TObjectIntMap> _maxViolations;
+
+ private final TObjectIntMap> _totalAlerts;
+
+ private final TObjectIntMap> _lastBan;
+
+ public ViolationLevels()
+ {
+ _maxViolations = new TObjectIntHashMap<>(CheckManager.AVAILABLE_CHECKS.size());
+ _totalAlerts = new TObjectIntHashMap<>(CheckManager.AVAILABLE_CHECKS.size());
+ _lastBan = new TObjectIntHashMap<>(CheckManager.AVAILABLE_CHECKS.size());
+ }
+
+ public void updateMaxViolations(Class extends Check> check, int violationLevel)
+ {
+ if (violationLevel > _maxViolations.get(check))
+ {
+ _maxViolations.put(check, violationLevel);
+ }
+ }
+
+ public void updateMaxViolationsSinceLastBan(Class extends Check> check, int violationLevel)
+ {
+ if (violationLevel > _lastBan.get(check))
+ {
+ _lastBan.put(check, violationLevel);
+ }
+ }
+
+ public void incrementAlerts(Class extends Check> check)
+ {
+ int cur = _totalAlerts.get(check);
+
+ setTotalAlerts(check, cur + 1);
+ }
+
+ public void setTotalAlerts(Class extends Check> check, int totalAlerts)
+ {
+ _totalAlerts.put(check, totalAlerts);
+ }
+
+ public int getTotalAlertsForCheck(Class extends Check> check)
+ {
+ if (_totalAlerts.containsKey(check))
+ {
+ return _totalAlerts.get(check);
+ }
+
+ return -1;
+ }
+
+ public int getMaxViolationsForCheck(Class extends Check> check)
+ {
+ if (_maxViolations.containsKey(check))
+ {
+ return _maxViolations.get(check);
+ }
+
+ return -1;
+ }
+
+ public int getLastBanViolationsForCheck(Class extends Check> check)
+ {
+ if (_lastBan.containsKey(check))
+ {
+ return _lastBan.get(check);
+ }
+
+ return -1;
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/AntiHackAction.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/AntiHackAction.java
index ddcc5e909..c919bba58 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/AntiHackAction.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/AntiHackAction.java
@@ -4,6 +4,7 @@ import com.mineplex.anticheat.api.PlayerViolationEvent;
import com.mineplex.anticheat.checks.combat.KillauraTypeA;
import com.mineplex.anticheat.checks.combat.KillauraTypeD;
import com.mineplex.anticheat.checks.move.Glide;
+import com.mineplex.anticheat.checks.move.HeadRoll;
import com.mineplex.anticheat.checks.move.Speed;
import mineplex.core.common.util.UtilServer;
import org.bukkit.event.Listener;
@@ -13,40 +14,19 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
-public abstract class AntiHackAction implements Listener
+public abstract class AntiHackAction
{
- private static final Map, AntiHackAction> ACTIONS = new HashMap<>();
- private static final AntiHackAction NOOP_ACTION = new NoopAction();
-
- private static final Date NEXT_BAN_WAVE = new Date(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5));
-
- static
- {
- ACTIONS.put(KillauraTypeA.class, new ImmediateBanAction(200));
- ACTIONS.put(KillauraTypeD.class, new BanwaveAction(2000));
- ACTIONS.put(Glide.class, new ImmediateBanAction(10000));
- ACTIONS.put(Speed.class, new ImmediateBanAction(10000));
- }
-
- private int _vl;
+ private final int _vl;
AntiHackAction(int vl)
{
this._vl = vl;
-
- UtilServer.RegisterEvents(this);
}
- public abstract void handle(PlayerViolationEvent event);
-
- public int getMinVl()
+ public final int getMinVl()
{
return this._vl;
}
- public static AntiHackAction getAction(Class> checkClass)
- {
- AntiHackAction action = ACTIONS.getOrDefault(checkClass, NOOP_ACTION);
- return action;
- }
+ public abstract void handle(PlayerViolationEvent event);
}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/BanwaveAction.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/BanwaveAction.java
index 876671029..24408afe9 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/BanwaveAction.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/BanwaveAction.java
@@ -1,17 +1,18 @@
package mineplex.core.antihack.actions;
import com.mineplex.anticheat.api.PlayerViolationEvent;
+
import mineplex.core.Managers;
import mineplex.core.antihack.banwave.BanWaveManager;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilServer;
-class BanwaveAction extends AntiHackAction
+public class BanwaveAction extends AntiHackAction
{
private static final int BAN_DELAY_AVERAGE = 6 * 60 * 60 * 1000; // 6 hours
private static final int BAN_DELAY_VARIANCE_SPAN = 4 * 60 * 60 * 1000; // 4 hours total; 2 on either side
- BanwaveAction(int vl)
+ public BanwaveAction(int vl)
{
super(vl);
}
@@ -27,7 +28,6 @@ class BanwaveAction extends AntiHackAction
event.getPlayer(),
banTime,
event.getCheckClass(),
- "[GWEN] Hacking [BanWave]",
event.getViolations(),
UtilServer.getServerName()
);
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/ImmediateBanAction.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/ImmediateBanAction.java
index ce6eeaf08..a06b38daf 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/ImmediateBanAction.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/ImmediateBanAction.java
@@ -5,9 +5,9 @@ import mineplex.core.Managers;
import mineplex.core.antihack.AntiHack;
import mineplex.core.common.util.UtilServer;
-class ImmediateBanAction extends AntiHackAction
+public class ImmediateBanAction extends AntiHackAction
{
- ImmediateBanAction(int vl)
+ public ImmediateBanAction(int vl)
{
super(vl);
}
@@ -17,12 +17,7 @@ class ImmediateBanAction extends AntiHackAction
{
if (event.getViolations() >= this.getMinVl())
{
- String server = UtilServer.getServerName();
- if (server.contains("-"))
- {
- server = server.substring(0, server.indexOf('-'));
- }
- Managers.get(AntiHack.class).doBan(event.getPlayer(), "[GWEN] Hacking [" + server + "]");
+ Managers.get(AntiHack.class).doBan(event.getPlayer(), event.getCheckClass());
}
}
}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/MixedAction.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/MixedAction.java
deleted file mode 100644
index 14066a4d7..000000000
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/MixedAction.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package mineplex.core.antihack.actions;
-
-import com.mineplex.anticheat.api.PlayerViolationEvent;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-public class MixedAction extends AntiHackAction
-{
- private List _actions = new ArrayList<>();
- private Map> _punished = new HashMap<>();
-
- public MixedAction(AntiHackAction firstAction, AntiHackAction... actions)
- {
- super(firstAction.getMinVl());
- this._actions.add(firstAction);
- this._actions.addAll(Arrays.asList(actions));
- }
-
-
- @Override
- public void handle(PlayerViolationEvent event)
- {
- for (int i = this._actions.size() - 1; i >= 0; i--)
- {
- AntiHackAction action = this._actions.get(i);
- if (action.getMinVl() <= event.getViolations())
- {
- if (_punished.computeIfAbsent(event.getPlayer().getUniqueId(), key -> new HashSet<>()).add(action))
- {
- action.handle(event);
- }
- break;
- }
- }
- }
-
- public int getMinVl()
- {
- return this._actions.get(0).getMinVl();
- }
-}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/NoopAction.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/NoopAction.java
index 38794c630..848322ac3 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/NoopAction.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/actions/NoopAction.java
@@ -4,7 +4,7 @@ import com.mineplex.anticheat.api.PlayerViolationEvent;
public class NoopAction extends AntiHackAction
{
- NoopAction()
+ public NoopAction()
{
super(Integer.MAX_VALUE);
}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/animations/BanwaveAnimation.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/animations/BanwaveAnimation.java
new file mode 100644
index 000000000..e3af1b117
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/animations/BanwaveAnimation.java
@@ -0,0 +1,9 @@
+package mineplex.core.antihack.animations;
+
+import mineplex.core.antihack.AntiHack;
+import org.bukkit.entity.Player;
+
+public interface BanwaveAnimation
+{
+ void run(Player player, Runnable after);
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/animations/BanwaveAnimationSpin.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/animations/BanwaveAnimationSpin.java
new file mode 100644
index 000000000..3370f28f2
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/animations/BanwaveAnimationSpin.java
@@ -0,0 +1,123 @@
+package mineplex.core.antihack.animations;
+
+import com.google.common.util.concurrent.AtomicDouble;
+import mineplex.core.antihack.AntiHack;
+import mineplex.core.antihack.guardians.AntiHackGuardian;
+import mineplex.core.common.util.UtilEnt;
+import mineplex.core.common.util.UtilParticle;
+import mineplex.core.common.util.UtilServer;
+import net.minecraft.server.v1_8_R3.MathHelper;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+
+public class BanwaveAnimationSpin implements BanwaveAnimation
+{
+ @Override
+ public void run(Player player, Runnable after)
+ {
+ float oldWalkSpeed = player.getWalkSpeed();
+ player.setWalkSpeed(0);
+ player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, 999999, -10));
+
+ double radius = 4;
+ double heightAdj = 8;
+
+ double baseDeg = 18;
+
+ Location center = player.getLocation().add(0, heightAdj, 0);
+ AntiHackGuardian north = new AntiHackGuardian(center.clone().add(0, 0, -radius), 0, 0, 0, 0, 0, 0, false);
+ AntiHackGuardian east = new AntiHackGuardian(center.clone().add(radius, 0, 0), 0, 0, 0, 0, 0, 0, false);
+ AntiHackGuardian south = new AntiHackGuardian(center.clone().add(0, 0, radius), 0, 0, 0, 0, 0, 0, false);
+ AntiHackGuardian west = new AntiHackGuardian(center.clone().add(-radius, 0, 0), 0, 0, 0, 0, 0, 0, false);
+
+ UtilEnt.CreatureLook(east.getEntity(), player);
+ UtilEnt.CreatureLook(west.getEntity(), player);
+ UtilEnt.CreatureLook(south.getEntity(), player);
+ UtilEnt.CreatureLook(north.getEntity(), player);
+
+ Function magic = seconds -> Math.pow(2, seconds - 5);
+
+ UtilServer.runSyncLater(() ->
+ {
+ north.shoot(player);
+ east.shoot(player);
+ south.shoot(player);
+ west.shoot(player);
+
+ // We get 5 seconds, or 100 ticks
+ AtomicInteger timer = new AtomicInteger(5);
+
+ AtomicDouble cNorth = new AtomicDouble(270);
+ AtomicDouble cEast = new AtomicDouble(0);
+ AtomicDouble cSouth = new AtomicDouble(90);
+ AtomicDouble cWest = new AtomicDouble(180);
+
+ UtilServer.runSyncTimer(new BukkitRunnable()
+ {
+ public void run()
+ {
+ timer.getAndIncrement();
+ if (timer.get() > 100)
+ {
+ cancel();
+
+ player.removePotionEffect(PotionEffectType.JUMP);
+ player.setWalkSpeed(oldWalkSpeed);
+ Location location = player.getLocation();
+
+ UtilParticle.PlayParticle(UtilParticle.ParticleType.HUGE_EXPLOSION, player.getLocation(), 3f, 3f, 3f, 0, 32, UtilParticle.ViewDist.MAX, UtilServer.getPlayers());
+
+ after.run();
+
+ north.shoot(null);
+ south.shoot(null);
+ east.shoot(null);
+ west.shoot(null);
+ UtilEnt.CreatureLook(north.getEntity(), location);
+ UtilEnt.CreatureLook(south.getEntity(), location);
+ UtilEnt.CreatureLook(east.getEntity(), location);
+ UtilEnt.CreatureLook(west.getEntity(), location);
+ UtilServer.runSyncLater(() ->
+ {
+ north.remove();
+ south.remove();
+ east.remove();
+ west.remove();
+ }, 40L);
+ return;
+ }
+
+ double seconds = timer.get() / 20.0;
+
+ double rate = magic.apply(seconds) * 3 * baseDeg;
+
+ player.getLocation(center);
+ center.add(0, heightAdj, 0);
+
+ {
+ cNorth.addAndGet(rate);
+ north.move(center.getX() + radius * MathHelper.cos((float) Math.toRadians(cNorth.get())), center.getY(), center.getZ() + radius * MathHelper.sin((float) Math.toRadians(cNorth.get())));
+ }
+ {
+ cSouth.addAndGet(rate);
+ south.move(center.getX() + radius * MathHelper.cos((float) Math.toRadians(cSouth.get())), center.getY(), center.getZ() + radius * MathHelper.sin((float) Math.toRadians(cSouth.get())));
+ }
+ {
+ cEast.addAndGet(rate);
+ east.move(center.getX() + radius * MathHelper.cos((float) Math.toRadians(cEast.get())), center.getY(), center.getZ() + radius * MathHelper.sin((float) Math.toRadians(cEast.get())));
+ }
+ {
+ cWest.addAndGet(rate);
+ west.move(center.getX() + radius * MathHelper.cos((float) Math.toRadians(cWest.get())), center.getY(), center.getZ() + radius * MathHelper.sin((float) Math.toRadians(cWest.get())));
+ }
+ }
+ }, 5L, 1L);
+ }, 20);
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/banwave/BanWaveManager.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/banwave/BanWaveManager.java
index dd2bebe96..7349cde03 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/banwave/BanWaveManager.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/banwave/BanWaveManager.java
@@ -5,14 +5,25 @@ import mineplex.core.ReflectivelyCreateMiniPlugin;
import mineplex.core.account.CoreClient;
import mineplex.core.account.CoreClientManager;
import mineplex.core.antihack.AntiHack;
+import mineplex.core.antihack.logging.AntihackLogger;
+import mineplex.core.antihack.redisnotifications.GwenBanwaveNotification;
+import mineplex.core.common.util.UtilServer;
+import mineplex.serverdata.commands.ServerCommandManager;
+
+import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
+import com.google.gson.JsonObject;
+import com.mineplex.anticheat.checks.Check;
+import com.mineplex.anticheat.checks.CheckManager;
+
@ReflectivelyCreateMiniPlugin
public class BanWaveManager extends MiniPlugin
{
private final BanWaveRepository _repository = new BanWaveRepository();
+ private final CoreClientManager _clientManager = require(CoreClientManager.class);
private BanWaveManager()
{
@@ -32,29 +43,39 @@ public class BanWaveManager extends MiniPlugin
if (info.getTimeToBan() < now)
{
- require(AntiHack.class).doBanWave(event.getPlayer(), info.getMessage());
+ require(AntiHack.class).doBanWave(event.getPlayer(), info);
_repository.flagDone(info);
}
});
});
}
- public void insertBanWaveInfo(Player player, long timeToBan, Class> checkClass, String message, int vl, String server)
+ public void insertBanWaveInfo(Player player, long timeToBan, Class extends Check> checkClass, int vl, String server)
{
- insertBanWaveInfo(player, timeToBan, checkClass, message, vl, server, null);
+ insertBanWaveInfo(player, timeToBan, checkClass, vl, server, null);
}
- public void insertBanWaveInfo(Player player, long timeToBan, Class> checkClass, String message, int vl, String server, Runnable after)
+ public void insertBanWaveInfo(Player player, long timeToBan, Class extends Check> checkClass, int vl, String server, Runnable after)
{
runAsync(() ->
{
- CoreClient client = require(CoreClientManager.class).Get(player);
+ String id = AntiHack.generateId();
+ String newMessage = "[GWEN] [BanWave] " + id;
- this._repository.insertBanWaveInfo(client.getAccountId(), timeToBan, checkClass.getName(), message, vl, server);
+ CoreClient client = _clientManager.Get(player);
- if (after != null)
+ if (this._repository.insertBanWaveInfo(client.getAccountId(), timeToBan, CheckManager.getCheckSimpleName(checkClass), newMessage, vl, server))
{
- after.run();
+ runAsync(() ->
+ {
+ GwenBanwaveNotification notification = new GwenBanwaveNotification(UtilServer.getServerName(), player.getName(), player.getUniqueId().toString(), CheckManager.getCheckSimpleName(checkClass), id, timeToBan);
+ ServerCommandManager.getInstance().publishCommand(notification);
+ });
+
+ JsonObject custom = new JsonObject();
+ custom.addProperty("is-banwave", true);
+
+ require(AntihackLogger.class).saveMetadata(player, id, after, custom);
}
});
}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/banwave/BanWaveRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/banwave/BanWaveRepository.java
index 1ddab86f0..baf39fe4e 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/banwave/BanWaveRepository.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/banwave/BanWaveRepository.java
@@ -59,9 +59,9 @@ public class BanWaveRepository extends MinecraftRepository
}, new ColumnInt("accountId", accountId));
}
- void insertBanWaveInfo(int accountId, long timeToBan, String hackType, String message, int vl, String server)
+ boolean insertBanWaveInfo(int accountId, long timeToBan, String hackType, String message, int vl, String server)
{
- executeInsert(INSERT_PENDING, null,
+ int affectedRows = executeInsert(INSERT_PENDING, null,
new ColumnInt("accountId", accountId),
new ColumnLong("timeToBan", timeToBan),
new ColumnVarChar("hacktype", 64, hackType),
@@ -69,6 +69,7 @@ public class BanWaveRepository extends MinecraftRepository
new ColumnInt("vl", vl),
new ColumnVarChar("server", 32, server)
);
+ return affectedRows > 0;
}
void flagDone(BanWaveInfo info)
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/AnticheatOffCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/AnticheatOffCommand.java
new file mode 100644
index 000000000..a3d1f4267
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/AnticheatOffCommand.java
@@ -0,0 +1,24 @@
+package mineplex.core.antihack.commands;
+
+import org.bukkit.entity.Player;
+
+import mineplex.core.antihack.AntiHack;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+
+public class AnticheatOffCommand extends CommandBase
+{
+ public AnticheatOffCommand(AntiHack plugin)
+ {
+ super(plugin, Rank.DEVELOPER, "acoff");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ Plugin.disableAnticheat();
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "Disabled anticheat"));
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/AnticheatOnCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/AnticheatOnCommand.java
new file mode 100644
index 000000000..7c1f3a767
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/AnticheatOnCommand.java
@@ -0,0 +1,24 @@
+package mineplex.core.antihack.commands;
+
+import org.bukkit.entity.Player;
+
+import mineplex.core.antihack.AntiHack;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+
+public class AnticheatOnCommand extends CommandBase
+{
+ public AnticheatOnCommand(AntiHack plugin)
+ {
+ super(plugin, Rank.DEVELOPER, "acon");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ Plugin.enableAnticheat();
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "Enabled anticheat"));
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/DetailedMessagesCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/DetailedMessagesCommand.java
new file mode 100644
index 000000000..e873d22e8
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/DetailedMessagesCommand.java
@@ -0,0 +1,30 @@
+package mineplex.core.antihack.commands;
+
+import org.bukkit.entity.Player;
+
+import mineplex.core.antihack.AntiHack;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+
+public class DetailedMessagesCommand extends CommandBase
+{
+ public DetailedMessagesCommand(AntiHack plugin)
+ {
+ super(plugin, Rank.DEVELOPER, "detailedmessages");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (Plugin.toggleDetailedMessage(caller))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "Detailed messages enabled"));
+ }
+ else
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "Detailed messages disabled"));
+ }
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/GetVlsCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/GetVlsCommand.java
new file mode 100644
index 000000000..84f32311b
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/GetVlsCommand.java
@@ -0,0 +1,47 @@
+package mineplex.core.antihack.commands;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
+import com.mineplex.anticheat.MineplexAnticheat;
+import com.mineplex.anticheat.checks.Check;
+import com.mineplex.anticheat.checks.CheckManager;
+
+import mineplex.core.antihack.AntiHack;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+
+public class GetVlsCommand extends CommandBase
+{
+ public GetVlsCommand(AntiHack plugin)
+ {
+ super(plugin, Rank.DEVELOPER, "getvls");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length > 0)
+ {
+ Player p = Bukkit.getPlayerExact(args[0]);
+ if (p != null)
+ {
+ CheckManager manager = MineplexAnticheat.getPlugin(MineplexAnticheat.class).getCheckManager();
+ for (Check check : manager.getActiveChecks())
+ {
+ UtilPlayer.message(caller, F.desc(check.getName(), String.valueOf(check.getViolationLevel(p))));
+ }
+ }
+ else
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "Could not find player"));
+ }
+ }
+ else
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "No player specified"));
+ }
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/TestBanCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/TestBanCommand.java
new file mode 100644
index 000000000..40ac6c1aa
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/commands/TestBanCommand.java
@@ -0,0 +1,51 @@
+package mineplex.core.antihack.commands;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
+import mineplex.core.antihack.AntiHack;
+import mineplex.core.antihack.animations.BanwaveAnimationSpin;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+
+public class TestBanCommand extends CommandBase
+{
+ public TestBanCommand(AntiHack plugin)
+ {
+ super(plugin, Rank.DEVELOPER, "testban");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length > 0)
+ {
+ Player p = Bukkit.getPlayerExact(args[0]);
+ if (p != null)
+ {
+ new BanwaveAnimationSpin().run(p, () ->
+ {
+ String reason = C.cRed + C.Bold + "You are banned for permanent by Test" +
+ "\n" + C.cWhite + "Seems to be speeding up time. (" + ThreadLocalRandom.current().nextInt(200, 400) + " packets/150 ms)" +
+ "\n" + C.cDGreen + "Unfairly banned? Appeal at " + C.cGreen + "www.mineplex.com/appeals";
+ p.kickPlayer(reason);
+
+ Plugin.announceBan(p);
+ });
+ }
+ else
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "Could not find player"));
+ }
+ }
+ else
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "No player specified"));
+ }
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHackGuardian.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/guardians/AntiHackGuardian.java
similarity index 99%
rename from Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHackGuardian.java
rename to Plugins/Mineplex.Core/src/mineplex/core/antihack/guardians/AntiHackGuardian.java
index 9cff0ce43..cb9ef2898 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/AntiHackGuardian.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/guardians/AntiHackGuardian.java
@@ -1,4 +1,4 @@
-package mineplex.core.antihack;
+package mineplex.core.antihack.guardians;
import com.mineplex.spigot.ChunkAddEntityEvent;
import mineplex.core.Managers;
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/guardians/GuardianManager.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/guardians/GuardianManager.java
new file mode 100644
index 000000000..a5806e753
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/guardians/GuardianManager.java
@@ -0,0 +1,129 @@
+package mineplex.core.antihack.guardians;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import mineplex.core.MiniPlugin;
+import mineplex.core.PlayerSelector;
+import mineplex.core.ReflectivelyCreateMiniPlugin;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.UtilLambda;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+
+@ReflectivelyCreateMiniPlugin
+public class GuardianManager extends MiniPlugin
+{
+ private static final int MAX_STALKED_PLAYERS = 3;
+ private static final int STALK_COOLDOWN_TIME_SECONDS = 5;
+
+ private static final int MIN_STALK_TIME = 10 * 20;
+ private static final int MAX_STALK_TIME = 20 * 20;
+ private static final int MAX_MIN_DIFF = MAX_STALK_TIME - MIN_STALK_TIME;
+ private static final Function STALK_END_PROBABILITY_EQUATION = x ->
+ {
+ return 1.0/ MAX_MIN_DIFF * x; // linear equation with points (0, 0) and (diff, 1)
+ };
+
+ private final Cache _stalkingCooldown = CacheBuilder.newBuilder()
+ .concurrencyLevel(1)
+ .expireAfterWrite(STALK_COOLDOWN_TIME_SECONDS, TimeUnit.SECONDS)
+ .build();
+ private final List _stalking = new ArrayList<>();
+ private List _guardians = new ArrayList<>();
+
+ private GuardianManager()
+ {
+ super("GuardianManager");
+
+ this._plugin.getServer().getScheduler().runTaskTimer(this._plugin, () ->
+ {
+ for (AntiHackGuardian guardian : this._guardians)
+ {
+ if (guardian.getTarget() != null && !guardian.getTarget().isOnline())
+ {
+ this._stalking.remove(guardian.getTarget().getUniqueId());
+ guardian.stopTargeting();
+ }
+ else if (guardian.getTargetingTime() > MIN_STALK_TIME)
+ {
+ double threshold = STALK_END_PROBABILITY_EQUATION.apply(guardian.getTargetingTime() - MIN_STALK_TIME);
+ if (Math.random() <= threshold)
+ {
+ this._stalking.remove(guardian.getTarget().getUniqueId());
+ _stalkingCooldown.put(guardian.getTarget().getUniqueId(), true);
+ guardian.stopTargeting();
+ }
+ }
+ guardian.tick();
+ }
+ }, 0L, 1L);
+
+ this._plugin.getServer().getScheduler().runTaskTimer(this._plugin, () ->
+ {
+ if (_stalking.size() >= MAX_STALKED_PLAYERS)
+ {
+ return;
+ }
+
+ if (_guardians.size() == 0)
+ {
+ return;
+ }
+
+ List targets = PlayerSelector.selectPlayers(
+ UtilLambda.and(
+ PlayerSelector.NOT_VANISHED,
+ PlayerSelector.hasAnyRank(false,
+ Rank.ALL,
+ Rank.ULTRA,
+ Rank.HERO,
+ Rank.LEGEND,
+ Rank.TITAN,
+ Rank.TWITCH,
+ Rank.YOUTUBE_SMALL,
+ Rank.YOUTUBE,
+ Rank.MEDIA,
+ Rank.ADMIN,
+ Rank.DEVELOPER,
+ Rank.OWNER,
+ Rank.LT
+ ),
+ player -> !_stalking.contains(player.getUniqueId()),
+ player -> _stalkingCooldown.getIfPresent(player.getUniqueId()) == null
+ ));
+
+ while (_stalking.size() < MAX_STALKED_PLAYERS && targets.size() > 0)
+ {
+ Player target = targets.remove(ThreadLocalRandom.current().nextInt(targets.size()));
+
+ int start = ThreadLocalRandom.current().nextInt(_guardians.size());
+
+ for (int i = start, j = 0; j < _guardians.size(); i++, j++)
+ {
+ if (i >= _guardians.size())
+ {
+ i -= _guardians.size();
+ }
+ AntiHackGuardian guardian = _guardians.get(i);
+ if (!guardian.isTargeting())
+ {
+ guardian.target(target);
+ _stalking.add(target.getUniqueId());
+ break;
+ }
+ }
+ }
+ }, 0L, 20L);
+ }
+
+ public void registerGuardian(AntiHackGuardian guardian)
+ {
+ this._guardians.add(guardian);
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/AnticheatDatabase.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/AnticheatDatabase.java
new file mode 100644
index 000000000..8d2f78421
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/AnticheatDatabase.java
@@ -0,0 +1,196 @@
+package mineplex.core.antihack.logging;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.Optional;
+
+import org.bukkit.plugin.java.JavaPlugin;
+
+import com.mineplex.anticheat.checks.Check;
+import com.mineplex.anticheat.checks.CheckManager;
+
+import mineplex.core.antihack.ViolationLevels;
+import mineplex.core.database.MinecraftRepository;
+import mineplex.serverdata.database.DBPool;
+
+import gnu.trove.map.TIntObjectMap;
+
+public class AnticheatDatabase extends MinecraftRepository
+{
+ /*
+ CREATE TABLE IF NOT EXISTS anticheat_vl_logs (accountId INT, checkId INT, maxViolations INT, totalAlerts INT, sinceLastBan INT, PRIMARY KEY(accountId, checkId));
+ CREATE TABLE IF NOT EXISTS anticheat_ban_metadata (id INT NOT NULL AUTO_INCREMENT, accountId INT, banId CHAR(10) NOT NULL, data MEDIUMTEXT NOT NULL, PRIMARY KEY(id));
+ */
+
+ private static final String INSERT_INTO_METADATA = "INSERT INTO anticheat_ban_metadata (accountId, banId, data) VALUES (?, ?, ?);";
+
+ private static final String UPDATE_VIOLATIONS = "INSERT INTO anticheat_vl_logs (accountId, checkId, "
+ + "maxViolations, sinceLastBan, totalAlerts) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY"
+ + " UPDATE maxViolations = VALUES(maxViolations), totalAlerts = VALUES(totalAlerts), sinceLastBan = VALUES(sinceLastBan);";
+
+ private static final String CLEAR_LAST_BAN_VIOLATIONS = "UPDATE anticheat_vl_logs SET sinceLastBan = 0 WHERE accountId = ?;";
+
+ private static final String GET_VLS = "SELECT checkId, maxViolations, sinceLastBan, totalAlerts FROM anticheat_vl_logs";
+
+ private static final String GET_VLS_BY_ACCOUNT_ID = GET_VLS + " WHERE accountId = ?";
+
+ private static final String GET_VLS_FOR_CHECK = GET_VLS + " WHERE checkId = ? AND accountId = ?";
+
+
+ public AnticheatDatabase(JavaPlugin plugin)
+ {
+ super(DBPool.getAccount());
+ }
+
+ /**
+ * Submit a set of user violation changes batch style.
+ *
+ * @param uploadQueue the {@link TIntObjectMap} describing the changes.
+ */
+ public void saveViolationLevels(Map uploadQueue)
+ {
+ try (Connection connection = getConnection())
+ {
+ PreparedStatement preparedStatement = connection.prepareStatement(UPDATE_VIOLATIONS);
+
+ uploadQueue.forEach((accountId, vls) ->
+ {
+ CheckManager.AVAILABLE_CHECKS.values().forEach(check ->
+ {
+ int checkId = CheckManager.getCheckId(check),
+ maxVls = vls.getMaxViolationsForCheck(check),
+ maxVlsSinceLastBan = vls.getLastBanViolationsForCheck(check),
+ totalAlerts = vls.getTotalAlertsForCheck(check);
+
+ // if neither value has been set don't store anything
+ if (maxVls < 0 && totalAlerts < 0 && maxVlsSinceLastBan < 0)
+ {
+ return;
+ }
+
+ maxVls = Math.max(maxVls, 0);
+ maxVlsSinceLastBan = Math.max(maxVlsSinceLastBan, 0);
+ totalAlerts = Math.max(totalAlerts, 0);
+
+ try
+ {
+ preparedStatement.setInt(1, accountId);
+ preparedStatement.setInt(2, checkId);
+ preparedStatement.setInt(3, maxVls);
+ preparedStatement.setInt(4, maxVlsSinceLastBan);
+ preparedStatement.setInt(5, totalAlerts);
+ preparedStatement.addBatch();
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ });
+ });
+
+ preparedStatement.executeBatch();
+ }
+ catch (SQLException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * Attempts to retrieve violation levels for the given account id.
+ *
+ * @param accountId The account id;
+ * @return an {@link Optional} describing the user's violation levels, or an empty one if none
+ * are found.
+ * @throws SQLException On failing to connect to the database.
+ */
+ public Optional getViolationLevels(int accountId)
+ {
+ ViolationLevels levels = new ViolationLevels();
+
+ try (Connection connection = getConnection())
+ {
+ PreparedStatement statement = connection.prepareStatement(GET_VLS_BY_ACCOUNT_ID);
+ statement.setInt(1, accountId);
+
+ ResultSet result = statement.executeQuery();
+
+ while (result.next())
+ {
+ int checkId = result.getInt("checkId");
+ Class extends Check> checkType = CheckManager.getCheckById(checkId);
+ if (checkType == null)
+ {
+ System.err.println("Whoops. Unintended refactor?");
+ continue;
+ }
+ levels.updateMaxViolations(checkType, result.getInt("maxViolations"));
+ levels.updateMaxViolationsSinceLastBan(checkType, result.getInt("sinceLastBan"));
+ levels.setTotalAlerts(checkType, result.getInt("totalAlerts"));
+ }
+ }
+ catch (SQLException ex)
+ {
+ ex.printStackTrace();
+ }
+
+ return Optional.of(levels);
+ }
+
+ public void clearLastBan(int accountId, Runnable after)
+ {
+ try (Connection connection = getConnection())
+ {
+ PreparedStatement statement = connection.prepareStatement(CLEAR_LAST_BAN_VIOLATIONS);
+ statement.setInt(1, accountId);
+
+ statement.executeUpdate();
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ if (after != null)
+ after.run();
+ }
+ }
+
+ public void saveMetadata(int accountId, String id, String base64, Runnable after)
+ {
+ try (Connection connection = getConnection())
+ {
+ PreparedStatement statement = connection.prepareStatement(INSERT_INTO_METADATA);
+ statement.setInt(1, accountId);
+ statement.setString(2, id);
+ statement.setString(3, base64);
+
+ statement.executeUpdate();
+ }
+ catch (SQLException ex)
+ {
+ ex.printStackTrace();
+ }
+ finally
+ {
+ if (after != null)
+ after.run();
+ }
+ }
+
+ @Override
+ protected void initialize()
+ {
+
+ }
+
+ @Override
+ protected void update()
+ {
+
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/AnticheatMetadata.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/AnticheatMetadata.java
new file mode 100644
index 000000000..dc015a66a
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/AnticheatMetadata.java
@@ -0,0 +1,23 @@
+package mineplex.core.antihack.logging;
+
+import java.util.UUID;
+
+import org.bukkit.event.Listener;
+
+import com.google.gson.JsonElement;
+
+import mineplex.core.common.util.UtilServer;
+
+public abstract class AnticheatMetadata implements Listener
+{
+ public AnticheatMetadata()
+ {
+ UtilServer.RegisterEvents(this);
+ }
+
+ public abstract String getId();
+
+ public abstract JsonElement build(UUID player);
+
+ public abstract void remove(UUID player);
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/AntihackLogger.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/AntihackLogger.java
new file mode 100644
index 000000000..2a9a628c8
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/AntihackLogger.java
@@ -0,0 +1,214 @@
+package mineplex.core.antihack.logging;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.player.PlayerLoginEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.tukaani.xz.LZMA2Options;
+import org.tukaani.xz.XZ;
+import org.tukaani.xz.XZOutputStream;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.mineplex.anticheat.api.PlayerViolationEvent;
+import com.mineplex.anticheat.checks.Check;
+
+import mineplex.core.MiniPlugin;
+import mineplex.core.ReflectivelyCreateMiniPlugin;
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.antihack.AntiHack;
+import mineplex.core.antihack.ViolationLevels;
+import mineplex.core.antihack.logging.builtin.PartyInfoMetadata;
+import mineplex.core.antihack.logging.builtin.PlayerInfoMetadata;
+import mineplex.core.antihack.logging.builtin.ServerInfoMetadata;
+import mineplex.core.antihack.logging.builtin.ViolationInfoMetadata;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.common.util.UtilServer;
+
+@ReflectivelyCreateMiniPlugin
+public class AntihackLogger extends MiniPlugin
+{
+ public static final Gson GSON = new Gson();
+
+ private static final int PUSH_QUEUE_TIME_IN_SECONDS = 60;
+
+ private final CoreClientManager _clientManager = require(CoreClientManager.class);
+
+ private final Map _violationLevels = new ConcurrentHashMap<>();
+
+ private final Map _metadata = new HashMap<>();
+
+ private final AnticheatDatabase _db;
+
+ private AntihackLogger()
+ {
+ super("AnticheatPlugin");
+
+ _db = new AnticheatDatabase(getPlugin());
+
+ runSyncTimer(this::pushQueuedViolationChanges, 20, 20 * PUSH_QUEUE_TIME_IN_SECONDS);
+
+ registerMetadata(new ServerInfoMetadata());
+ registerMetadata(new ViolationInfoMetadata());
+ registerMetadata(new PartyInfoMetadata());
+ registerMetadata(new PlayerInfoMetadata());
+ }
+
+ @Override
+ public void disable()
+ {
+ pushQueuedViolationChanges();
+ }
+
+ @EventHandler
+ public void addCommands()
+ {
+ if (UtilServer.isTestServer())
+ {
+ addCommand(new CommandBase(this, Rank.SNR_MODERATOR, "savemetadata")
+ {
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length == 1)
+ {
+ Player player = Bukkit.getPlayer(args[0]);
+ if (player != null)
+ {
+ JsonObject custom = new JsonObject();
+ custom.addProperty("is-test-metadata", true);
+ String id = AntiHack.generateId();
+ saveMetadata(player, id, () ->
+ {
+ UtilPlayer.message(caller, F.main(getName(), "Saved metadata for " + player.getName() + " with id " + id));
+ }, custom);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ private void pushQueuedViolationChanges()
+ {
+ Map clone = new HashMap<>(_violationLevels);
+ runAsync(() -> _db.saveViolationLevels(clone));
+ }
+
+ @EventHandler
+ public void onCheckFail(PlayerViolationEvent event)
+ {
+ ViolationLevels playerVls = _violationLevels.get(_clientManager.getAccountId(event.getPlayer()));
+ Class extends Check> check = event.getCheckClass();
+ playerVls.updateMaxViolations(check, event.getViolations());
+ playerVls.updateMaxViolationsSinceLastBan(check, event.getViolations());
+ playerVls.incrementAlerts(check);
+ }
+
+ @EventHandler
+ public void onLoad(PlayerLoginEvent event)
+ {
+ runAsync(() ->
+ {
+ int accountId = _clientManager.getAccountId(event.getPlayer());
+
+ _db.getViolationLevels(accountId)
+ .ifPresent(vls ->
+ {
+ _violationLevels.put(accountId, vls);
+ });
+ });
+ }
+
+ @EventHandler
+ public void onQuit(PlayerQuitEvent event)
+ {
+ Player player = event.getPlayer();
+ int accountId =_clientManager.getAccountId(event.getPlayer());
+
+ ViolationLevels levels = _violationLevels.get(accountId);
+
+ if (levels != null)
+ {
+ Map clone = new HashMap<>();
+ clone.put(accountId, levels);
+
+ runAsync(() -> _db.saveViolationLevels(clone));
+ }
+
+ _metadata.values().forEach(metadata -> metadata.remove(event.getPlayer().getUniqueId()));
+ }
+
+ public void saveMetadata(Player player, String id, Runnable after, JsonObject custom)
+ {
+ runAsync(() ->
+ {
+ JsonObject info = new JsonObject();
+
+ for (AnticheatMetadata anticheatMetadata : _metadata.values())
+ {
+ try
+ {
+ info.add(anticheatMetadata.getId(), anticheatMetadata.build(player.getUniqueId()));
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace();
+ }
+ }
+
+ info.add("custom", custom == null ? JsonNull.INSTANCE: custom);
+
+ String str = GSON.toJson(info);
+ byte[] b = str.getBytes(StandardCharsets.UTF_8);
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+
+ try
+ {
+ XZOutputStream o2 = new XZOutputStream(bout, new LZMA2Options(LZMA2Options.PRESET_MIN), XZ.CHECK_NONE);
+ o2.write(b);
+ o2.close();
+ }
+ catch (IOException ex)
+ {
+ // Should never happen
+ ex.printStackTrace();
+ }
+
+ String base64 = Base64.getEncoder().encodeToString(bout.toByteArray());
+
+ _db.saveMetadata(_clientManager.getAccountId(player), id, base64, after);
+ });
+ }
+
+ public void registerMetadata(AnticheatMetadata metadata)
+ {
+ if (!this._metadata.containsKey(metadata.getId()))
+ {
+ this._metadata.put(metadata.getId(), metadata);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Attempting to register: " + metadata.getId());
+ }
+ }
+
+ public void resetViolations(Player player, Runnable after)
+ {
+ _db.clearLastBan(_clientManager.getAccountId(player), after);
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/PartyInfoMetadata.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/PartyInfoMetadata.java
new file mode 100644
index 000000000..9ffba8361
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/PartyInfoMetadata.java
@@ -0,0 +1,55 @@
+package mineplex.core.antihack.logging.builtin;
+
+import java.util.UUID;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+
+import mineplex.core.antihack.logging.AnticheatMetadata;
+import mineplex.core.party.Party;
+import mineplex.core.party.PartyManager;
+
+import static mineplex.core.Managers.require;
+
+public class PartyInfoMetadata extends AnticheatMetadata
+{
+ private static final String KEY_OWNER = "owner";
+ private static final String KEY_MEMBERS = "members";
+
+ @Override
+ public String getId()
+ {
+ return "party-info";
+ }
+
+ @Override
+ public JsonElement build(UUID player)
+ {
+ Party party = require(PartyManager.class).getPlayerParties().get(player);
+ if (party != null)
+ {
+ JsonObject partyData = new JsonObject();
+ partyData.addProperty(KEY_OWNER, party.getOwner());
+
+ JsonArray members = new JsonArray();
+ party.getMembers().forEach(m -> members.add(new JsonPrimitive(m)));
+
+ partyData.add(KEY_MEMBERS, members);
+
+ return partyData;
+ }
+ else
+ {
+ return JsonNull.INSTANCE;
+ }
+ }
+
+ @Override
+ public void remove(UUID player)
+ {
+
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/PlayerInfoMetadata.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/PlayerInfoMetadata.java
new file mode 100644
index 000000000..479db70d2
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/PlayerInfoMetadata.java
@@ -0,0 +1,51 @@
+package mineplex.core.antihack.logging.builtin;
+
+import java.util.UUID;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.antihack.logging.AnticheatMetadata;
+
+import static mineplex.core.Managers.require;
+
+public class PlayerInfoMetadata extends AnticheatMetadata
+{
+ private static final String KEY_UUID = "uuid";
+ private static final String KEY_ACCOUNT_ID = "accountid";
+ private static final String KEY_NAME = "name";
+
+ private final CoreClientManager _clientManager = require(CoreClientManager.class);
+
+ @Override
+ public String getId()
+ {
+ return "player-info";
+ }
+
+ @Override
+ public JsonElement build(UUID player)
+ {
+ JsonObject object = new JsonObject();
+ object.addProperty(KEY_UUID, player.toString());
+
+ Player bPlayer = Bukkit.getPlayer(player);
+ if (bPlayer != null)
+ {
+ object.addProperty(KEY_NAME, bPlayer.getName());
+ object.addProperty(KEY_ACCOUNT_ID, _clientManager.getAccountId(bPlayer));
+ }
+
+ return object;
+ }
+
+ @Override
+ public void remove(UUID player)
+ {
+
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/ServerInfoMetadata.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/ServerInfoMetadata.java
new file mode 100644
index 000000000..7376a6d3e
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/ServerInfoMetadata.java
@@ -0,0 +1,38 @@
+package mineplex.core.antihack.logging.builtin;
+
+import java.util.UUID;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import mineplex.core.antihack.logging.AnticheatMetadata;
+import mineplex.core.common.util.UtilServer;
+
+public class ServerInfoMetadata extends AnticheatMetadata
+{
+ private static final String KEY_SERVER_NAME = "server-name";
+ private static final String KEY_SERVER_REGION = "server-region";
+ private static final String KEY_SERVER_GROUP = "server-group";
+
+ @Override
+ public String getId()
+ {
+ return "server-info";
+ }
+
+ @Override
+ public JsonElement build(UUID player)
+ {
+ JsonObject info = new JsonObject();
+ info.addProperty(KEY_SERVER_NAME, UtilServer.getServerName());
+ info.addProperty(KEY_SERVER_REGION, UtilServer.getRegion().name());
+ info.addProperty(KEY_SERVER_GROUP, UtilServer.getGroup());
+ return info;
+ }
+
+ @Override
+ public void remove(UUID player)
+ {
+
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/ViolationInfoMetadata.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/ViolationInfoMetadata.java
new file mode 100644
index 000000000..da2ee4278
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/logging/builtin/ViolationInfoMetadata.java
@@ -0,0 +1,154 @@
+package mineplex.core.antihack.logging.builtin;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import net.minecraft.server.v1_8_R3.MinecraftServer;
+
+import org.bukkit.Location;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.player.PlayerJoinEvent;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.mineplex.anticheat.api.CheckDisabledEvent;
+import com.mineplex.anticheat.api.PlayerViolationEvent;
+import com.mineplex.anticheat.checks.Check;
+
+import mineplex.core.antihack.logging.AnticheatMetadata;
+
+import gnu.trove.map.TObjectIntMap;
+import gnu.trove.map.TObjectLongMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.map.hash.TObjectLongHashMap;
+
+public class ViolationInfoMetadata extends AnticheatMetadata
+{
+ private static final Location MUTABLE_LOCATION = new Location(null, 0, 0, 0);
+
+ private static final String KEY_JOIN_TIME_MS = "join-time-ms";
+ private static final String KEY_JOIN_TIME_TICK = "join-time-tick";
+
+ private static final String KEY_CURRENT_TIME = "current-time";
+ private static final String KEY_MS = "ms";
+ private static final String KEY_TICK = "tick";
+
+ private static final String KEY_VIOLATION_INFO = "violation-info";
+ private static final String KEY_VL = "current-vl";
+ private static final String KEY_MESSAGE = "msg";
+
+ private static final String KEY_PLAYER_INFO = "player-info";
+ private static final String KEY_LOCATION = "loc";
+ private static final String KEY_WORLD = "world";
+ private static final String KEY_X = "x";
+ private static final String KEY_Y = "y";
+ private static final String KEY_Z = "z";
+ private static final String KEY_YAW = "yaw";
+ private static final String KEY_PITCH = "pitch";
+
+ private static final JsonObject VAL_CHECK_DISABLED;
+
+ static
+ {
+ VAL_CHECK_DISABLED = new JsonObject();
+ VAL_CHECK_DISABLED.addProperty(KEY_MESSAGE, "disabled");
+ }
+
+ private TObjectLongMap _joinTime = new TObjectLongHashMap<>();
+ private TObjectIntMap _joinTimeTick = new TObjectIntHashMap<>();
+ private Map, List>> _violations = new HashMap<>();
+
+ @Override
+ public String getId()
+ {
+ return "violation-info";
+ }
+
+ @Override
+ public JsonElement build(UUID player)
+ {
+ JsonObject object = new JsonObject();
+ object.addProperty(KEY_JOIN_TIME_MS, _joinTime.get(player));
+ object.addProperty(KEY_JOIN_TIME_TICK, _joinTimeTick.get(player));
+ _violations.get(player).forEach((check, list) ->
+ {
+ JsonArray checkElem = new JsonArray();
+ list.forEach(checkElem::add);
+ object.add(check.getName(), checkElem);
+ });
+
+ return object;
+ }
+
+ @Override
+ public void remove(UUID player)
+ {
+ _joinTime.remove(player);
+ _joinTimeTick.remove(player);
+ _violations.remove(player);
+ }
+
+ @EventHandler
+ public void onJoin(PlayerJoinEvent event)
+ {
+ long thisMs = System.currentTimeMillis();
+ int thisTick = MinecraftServer.getServer().at();
+ _joinTime.put(event.getPlayer().getUniqueId(), thisMs);
+ _joinTimeTick.put(event.getPlayer().getUniqueId(), thisTick);
+ _violations.put(event.getPlayer().getUniqueId(), new HashMap<>());
+ }
+
+ @EventHandler
+ public void onDisabledCheck(CheckDisabledEvent event)
+ {
+ _violations.values().forEach(map ->
+ {
+ List data = map.get(event.getCheck());
+ if (data != null)
+ {
+ data.add(VAL_CHECK_DISABLED);
+ }
+ });
+ }
+
+ @EventHandler
+ public void onViolation(PlayerViolationEvent event)
+ {
+ long thisMs = System.currentTimeMillis();
+ int thisTick = MinecraftServer.getServer().at();
+
+ List violations = _violations.get(event.getPlayer().getUniqueId()).computeIfAbsent(event.getCheckClass(), key -> new ArrayList<>());
+
+ JsonObject currentTime = new JsonObject();
+ currentTime.addProperty(KEY_MS, thisMs);
+ currentTime.addProperty(KEY_TICK, thisTick);
+
+ JsonObject violationInfo = new JsonObject();
+ violationInfo.addProperty(KEY_VL, event.getViolations());
+ violationInfo.addProperty(KEY_MESSAGE, event.getMessage());
+
+ event.getPlayer().getLocation(MUTABLE_LOCATION);
+
+ JsonObject playerInfo = new JsonObject();
+ JsonObject location = new JsonObject();
+ location.addProperty(KEY_WORLD, MUTABLE_LOCATION.getWorld().getName());
+ location.addProperty(KEY_X, MUTABLE_LOCATION.getX());
+ location.addProperty(KEY_Y, MUTABLE_LOCATION.getY());
+ location.addProperty(KEY_Z, MUTABLE_LOCATION.getZ());
+ location.addProperty(KEY_YAW, MUTABLE_LOCATION.getYaw());
+ location.addProperty(KEY_PITCH, MUTABLE_LOCATION.getPitch());
+
+ playerInfo.add(KEY_LOCATION, location);
+
+ JsonObject data = new JsonObject();
+ data.add(KEY_CURRENT_TIME, currentTime);
+ data.add(KEY_VIOLATION_INFO, violationInfo);
+ data.add(KEY_PLAYER_INFO, playerInfo);
+
+ violations.add(data);
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/redisnotifications/GwenBanNotification.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/redisnotifications/GwenBanNotification.java
new file mode 100644
index 000000000..5be1a474c
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/redisnotifications/GwenBanNotification.java
@@ -0,0 +1,46 @@
+package mineplex.core.antihack.redisnotifications;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class GwenBanNotification extends ServerCommand
+{
+ private final String _serverName;
+ private final String _playerName;
+ private final String _playerUUID;
+ private final String _hackType;
+ private final String _metadataId;
+
+ public GwenBanNotification(String serverName, String playerName, String playerUUID, String hackType, String metadataId)
+ {
+ _serverName = serverName;
+ _playerName = playerName;
+ _playerUUID = playerUUID;
+ _hackType = hackType;
+ _metadataId = metadataId;
+ }
+
+ public String getServerName()
+ {
+ return _serverName;
+ }
+
+ public String getPlayerName()
+ {
+ return _playerName;
+ }
+
+ public String getPlayerUUID()
+ {
+ return _playerUUID;
+ }
+
+ public String getHackType()
+ {
+ return _hackType;
+ }
+
+ public String getMetadataId()
+ {
+ return _metadataId;
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/redisnotifications/GwenBanwaveNotification.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/redisnotifications/GwenBanwaveNotification.java
new file mode 100644
index 000000000..0ca1cf628
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/antihack/redisnotifications/GwenBanwaveNotification.java
@@ -0,0 +1,53 @@
+package mineplex.core.antihack.redisnotifications;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class GwenBanwaveNotification extends ServerCommand
+{
+ private final String _serverName;
+ private final String _playerName;
+ private final String _playerUUID;
+ private final String _hackType;
+ private final String _metadataId;
+ private final long _timeToBan;
+
+ public GwenBanwaveNotification(String serverName, String playerName, String playerUUID, String hackType, String metadataId, long timeToBan)
+ {
+ _serverName = serverName;
+ _playerName = playerName;
+ _playerUUID = playerUUID;
+ _hackType = hackType;
+ _metadataId = metadataId;
+ _timeToBan = timeToBan;
+ }
+
+ public String getServerName()
+ {
+ return _serverName;
+ }
+
+ public String getPlayerName()
+ {
+ return _playerName;
+ }
+
+ public String getPlayerUUID()
+ {
+ return _playerUUID;
+ }
+
+ public String getHackType()
+ {
+ return _hackType;
+ }
+
+ public String getMetadataId()
+ {
+ return _metadataId;
+ }
+
+ public long getTimeToBan()
+ {
+ return _timeToBan;
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Fly.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Fly.java
deleted file mode 100644
index 0941d4a2a..000000000
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Fly.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package mineplex.core.antihack.types;
-
-import java.util.AbstractMap;
-import java.util.HashMap;
-import java.util.Map.Entry;
-
-import mineplex.core.MiniPlugin;
-import mineplex.core.antihack.AntiHack;
-import mineplex.core.antihack.Detector;
-import mineplex.core.common.util.UtilBlock;
-import mineplex.core.common.util.UtilMath;
-
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.player.PlayerMoveEvent;
-import org.bukkit.potion.PotionEffect;
-import org.bukkit.potion.PotionEffectType;
-
-public class Fly extends MiniPlugin implements Detector
-{
- private AntiHack Host;
-
- private HashMap> _floatTicks = new HashMap>(); //Ticks, PrevY
- private HashMap> _hoverTicks = new HashMap>(); //Ticks, PrevY
- private HashMap> _riseTicks = new HashMap>(); //Ticks, PrevY
-
- public Fly (AntiHack host)
- {
- super("Fly Detector", host.getPlugin());
- Host = host;
- }
-
- @EventHandler(priority = EventPriority.MONITOR)
- public void updateFlyhack(PlayerMoveEvent event)
- {
- if (!Host.isEnabled())
- return;
-
- Player player = event.getPlayer();
-
- //100% Valid
- if (Host.isValid(player, true))
- Reset(player);
-
- //Hasn't moved, just looking around
- if (UtilMath.offset(event.getFrom(), event.getTo()) <= 0)
- {
- updateFloat(player);
- return;
- }
- else
- {
- _floatTicks.remove(player);
- }
-
- updateHover(player);
- updateRise(player);
- }
-
- private void updateFloat(Player player)
- {
- int count = 0;
-
- if (_floatTicks.containsKey(player))
- {
- if (player.getLocation().getY() == _floatTicks.get(player).getValue())
- {
- count = _floatTicks.get(player).getKey() + 1;
- }
- else
- {
- count = 0;
- }
- }
-
- if (count > Host.FloatHackTicks)
- {
- Host.addSuspicion(player, "Fly (Float)");
- count -= 2;
- }
-
- _floatTicks.put(player, new AbstractMap.SimpleEntry(count, player.getLocation().getY()));
- }
-
- private void updateHover(Player player)
- {
- int count = 0;
-
- if (_hoverTicks.containsKey(player))
- {
- if (player.getLocation().getY() == _hoverTicks.get(player).getValue())
- {
- count = _hoverTicks.get(player).getKey() + 1;
- }
- else
- {
- count = 0;
- }
-
- //player.sendMessage(count + " - " + player.getLocation().getY() + " vs " + _hoverTicks.get(player).getValue());
- }
-
- if (count > Host.HoverHackTicks)
- {
- Host.addSuspicion(player, "Fly (Hover)");
- count -= 2;
- }
-
- _hoverTicks.put(player, new AbstractMap.SimpleEntry(count, player.getLocation().getY()));
- }
-
- private void updateRise(Player player)
- {
- int count = 0;
-
- if (_riseTicks.containsKey(player))
- {
- if (player.getLocation().getY() >= _riseTicks.get(player).getValue())
- {
- boolean nearBlocks = false;
- for (Block block : UtilBlock.getSurrounding(player.getLocation().getBlock(), true))
- {
- if (block.getType() != Material.AIR)
- {
- nearBlocks = true;
- break;
- }
- }
-
- for (PotionEffect effect : player.getActivePotionEffects())
- if (effect.getType() == PotionEffectType.JUMP || effect.getType().equals(PotionEffectType.JUMP))
- nearBlocks = true;
-
- if (nearBlocks)
- {
- count = 0;
- }
- else
- {
- count = _riseTicks.get(player).getKey() + 1;
- }
-
- }
- else
- {
- count = 0;
- }
- }
-
- if (count > Host.RiseHackTicks)
- {
- //Only give Offense if actually rising - initial ticks can be trigged via Hover.
- if (player.getLocation().getY() > _riseTicks.get(player).getValue())
- Host.addSuspicion(player, "Fly (Rise)");
-
- count -= 2;
- }
-
- _riseTicks.put(player, new AbstractMap.SimpleEntry(count, player.getLocation().getY()));
- }
-
- @Override
- public void Reset(Player player)
- {
- _floatTicks.remove(player);
- _hoverTicks.remove(player);
- _riseTicks.remove(player);
- }
-}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Idle.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Idle.java
deleted file mode 100644
index 18889a4c6..000000000
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Idle.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package mineplex.core.antihack.types;
-
-import java.util.HashMap;
-
-import mineplex.core.MiniPlugin;
-import mineplex.core.antihack.AntiHack;
-import mineplex.core.antihack.Detector;
-import mineplex.core.common.util.C;
-import mineplex.core.common.util.UtilPlayer;
-import mineplex.core.common.util.UtilServer;
-import mineplex.core.common.util.UtilTime;
-import mineplex.core.updater.UpdateType;
-import mineplex.core.updater.event.UpdateEvent;
-
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.player.PlayerMoveEvent;
-
-public class Idle extends MiniPlugin implements Detector
-{
- private AntiHack Host;
-
- private HashMap _idleTime = new HashMap();
-
- public Idle (AntiHack host)
- {
- super("Idle Detector", host.getPlugin());
- Host = host;
- }
-
- @EventHandler(priority = EventPriority.MONITOR)
- public void updateFlyhack(PlayerMoveEvent event)
- {
- if (!Host.isEnabled())
- return;
-
- Player player = event.getPlayer();
-
- _idleTime.put(player, System.currentTimeMillis());
- }
-
- @EventHandler(priority = EventPriority.MONITOR)
- public void updateFreeCam(UpdateEvent event)
- {
- if (!Host.isEnabled())
- return;
-
- if (event.getType() != UpdateType.FAST)
- return;
-
- for (Player player : UtilServer.getPlayers())
- {
- //100% Valid
- if (Host.isValid(player, true))
- continue;
-
- if (!_idleTime.containsKey(player))
- continue;
-
- if (!UtilTime.elapsed(_idleTime.get(player), Host.IdleTime))
- continue;
-
- //Host.addSuspicion(player, "Lag / Fly (Idle)");
- //player.kickPlayer(C.cGold + "Mineplex " + C.cRed + "Anti-Cheat " + C.cWhite + "Kicked for Lag / Fly (Idle)");
-
- UtilPlayer.message(player, C.cRed + C.Bold + "Mineplex Anti-Cheat detected Lagging / Fly (Idle)");
- UtilPlayer.message(player, C.cRed + C.Bold + "You have been returned to Lobby.");
- Host.Portal.sendPlayerToServer(player, "Lobby");
- }
- }
-
- @Override
- public void Reset(Player player)
- {
- _idleTime.remove(player);
- }
-}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Reach.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Reach.java
deleted file mode 100644
index 9bf8b4a00..000000000
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Reach.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package mineplex.core.antihack.types;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import mineplex.core.MiniPlugin;
-import mineplex.core.antihack.AntiHack;
-import mineplex.core.antihack.Detector;
-import mineplex.core.common.util.UtilEvent;
-import mineplex.core.common.util.UtilMath;
-import mineplex.core.common.util.UtilPlayer;
-import mineplex.core.common.util.UtilServer;
-import mineplex.core.updater.UpdateType;
-import mineplex.core.updater.event.UpdateEvent;
-
-import org.bukkit.GameMode;
-import org.bukkit.Location;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.entity.EntityDamageEvent;
-import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
-
-public class Reach extends MiniPlugin implements Detector
-{
- private AntiHack Host;
-
- private HashMap> _history = new HashMap>();
-
- public Reach (AntiHack host)
- {
- super("Reach Detector", host.getPlugin());
- Host = host;
- }
-
- @EventHandler(priority = EventPriority.LOWEST)
- public void recordMove(UpdateEvent event)
- {
- if (!Host.isEnabled())
- return;
-
- if (event.getType() != UpdateType.TICK)
- return;
-
- for (Player player : UtilServer.getPlayers())
- {
- if (player.getGameMode() != GameMode.SURVIVAL || UtilPlayer.isSpectator(player))
- continue;
-
- if (!_history.containsKey(player))
- _history.put(player, new ArrayList());
-
- _history.get(player).add(0, player.getLocation());
-
- while (_history.get(player).size() > 40)
- {
- _history.get(player).remove(_history.get(player).size()-1);
- }
- }
- }
-
- @EventHandler(priority = EventPriority.LOWEST)
- public void reachDetect(EntityDamageEvent event)
- {
- if (event.getCause() != DamageCause.ENTITY_ATTACK)
- return;
-
- if (!(event.getEntity() instanceof Player))
- return;
-
- LivingEntity damagerEntity = UtilEvent.GetDamagerEntity(event, false);
-
- if (!(damagerEntity instanceof Player))
- return;
-
- Player damager = (Player)damagerEntity;
- Player damagee = (Player)event.getEntity();
-
- if (!isInRange(damager.getLocation(), damagee.getLocation()))
- {
- ArrayList damageeHistory = _history.get(damagee);
-
- if (damageeHistory != null)
- {
- for (Location historyLoc : damageeHistory)
- {
- if (isInRange(damager.getLocation(), historyLoc))
- {
- return;
- }
- }
- }
-
- //Host.addSuspicion(damager, "Reach");
- }
- }
-
- private boolean isInRange(Location a, Location b)
- {
- //2d Range
- double distFlat = UtilMath.offset2d(a, b); //Limit is 3.40
- if (distFlat > 3.4)
- {
- return true;
- }
-
- //3d Range
- double dist = UtilMath.offset(a, b); //Limit is 6 (highest i saw was 5.67)
- if (dist > 6.0)
- {
- return true;
- }
-
- return false;
- }
-
- @Override
- public void Reset(Player player)
- {
- _history.remove(player);
- }
-}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Speed.java b/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Speed.java
deleted file mode 100644
index 9e57c33df..000000000
--- a/Plugins/Mineplex.Core/src/mineplex/core/antihack/types/Speed.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package mineplex.core.antihack.types;
-
-import java.util.AbstractMap;
-import java.util.HashMap;
-import java.util.Map.Entry;
-
-import mineplex.core.MiniPlugin;
-import mineplex.core.antihack.AntiHack;
-import mineplex.core.antihack.Detector;
-import mineplex.core.common.util.UtilEnt;
-import mineplex.core.common.util.UtilMath;
-import mineplex.core.common.util.UtilTime;
-
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.player.PlayerMoveEvent;
-import org.bukkit.potion.PotionEffect;
-import org.bukkit.potion.PotionEffectType;
-
-public class Speed extends MiniPlugin implements Detector
-{
- private AntiHack Host;
-
- private HashMap> _speedTicks = new HashMap>(); //Ticks, PrevY
-
- public Speed (AntiHack host)
- {
- super("Speed Detector", host.getPlugin());
- Host = host;
- }
-
- @EventHandler(priority = EventPriority.MONITOR)
- public void updateSpeedhack(PlayerMoveEvent event)
- {
- if (!Host.isEnabled())
- return;
-
- Player player = event.getPlayer();
-
- //100% Valid
- if (Host.isValid(player, false))
- return;
-
- UpdateSpeed(player, event);
- }
-
- private void UpdateSpeed(Player player, PlayerMoveEvent event)
- {
- int count = 0;
-
- if (_speedTicks.containsKey(player))
- {
- double offset;
- if (event.getFrom().getY() > event.getTo().getY())
- {
- offset = UtilMath.offset2d(event.getFrom(), event.getTo());
- }
- else
- {
- offset = UtilMath.offset(event.getFrom(), event.getTo());
- }
-
- //Limit
- double limit = 0.74;
- if (UtilEnt.isGrounded(player))
- limit = 0.32;
-
- for (PotionEffect effect : player.getActivePotionEffects())
- {
- if (effect.getType().equals(PotionEffectType.SPEED))
- {
- if (UtilEnt.isGrounded(player))
- limit += 0.08 * (effect.getAmplifier() + 1);
- else
- limit += 0.04 * (effect.getAmplifier() + 1);
- }
- }
-
- //Check
- if (offset > limit && !UtilTime.elapsed(_speedTicks.get(player).getValue(), 100))//Counters Lag
- {
- count = _speedTicks.get(player).getKey() + 1;
- }
- else
- {
- count = 0;
- }
- }
-
- if (count > Host.SpeedHackTicks)
- {
- Host.addSuspicion(player, "Speed (Fly/Move)");
- count -= 2;
- }
-
- _speedTicks.put(player, new AbstractMap.SimpleEntry(count, System.currentTimeMillis()));
- }
-
- @Override
- public void Reset(Player player)
- {
- _speedTicks.remove(player);
- }
-}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/Community.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/Community.java
new file mode 100644
index 000000000..41c4391d3
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/Community.java
@@ -0,0 +1,159 @@
+package mineplex.core.communities;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.game.GameDisplay;
+
+public class Community
+{
+ private final int _id;
+ private String _name;
+ private String _description;
+ private Map _members = new HashMap<>();
+ private Map _joinRequests = new HashMap<>();
+ private ChatColor[] _chatFormat;
+ private long _chatDelay;
+ private GameDisplay _favoriteGame;
+ private PrivacySetting _privacy;
+
+ public Community(int id, String name)
+ {
+ _id = id;
+ _name = name;
+ _description = "No Description Set";
+ _chatFormat = new ChatColor[] {ChatColor.BLUE, ChatColor.RED, ChatColor.GREEN};
+ _chatDelay = 1000;
+ _favoriteGame = GameDisplay.ChampionsCTF;
+ _privacy = PrivacySetting.RECRUITING;
+ }
+
+ public Integer getId()
+ {
+ return _id;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public void setName(String name)
+ {
+ _name = name;
+ }
+
+ public String getDescription()
+ {
+ return _description;
+ }
+
+ public void setDescription(String description)
+ {
+ _description = description;
+ }
+
+ public Map getMembers()
+ {
+ return _members;
+ }
+
+ public Map getJoinRequests()
+ {
+ return _joinRequests;
+ }
+
+ public ChatColor[] getChatFormatting()
+ {
+ return _chatFormat;
+ }
+
+ public void setChatFormatting(ChatColor[] colors)
+ {
+ _chatFormat = colors;
+ }
+
+ public Long getChatDelay()
+ {
+ return _chatDelay;
+ }
+
+ public void setChatDelay(Long delay)
+ {
+ _chatDelay = delay;
+ }
+
+ public GameDisplay getFavoriteGame()
+ {
+ return _favoriteGame;
+ }
+
+ public void setFavoriteGame(GameDisplay game)
+ {
+ _favoriteGame = game;
+ }
+
+ public PrivacySetting getPrivacySetting()
+ {
+ return _privacy;
+ }
+
+ public void setPrivacySetting(PrivacySetting privacy)
+ {
+ _privacy = privacy;
+ }
+
+ public void sendChat(String chat)
+ {
+ getMembers().values().stream().filter(info -> info.ReadingChat).forEach(member -> UtilPlayer.message(Bukkit.getPlayer(member.UUID), chat));
+ }
+
+ public void message(String message)
+ {
+ getMembers().values().forEach(member -> UtilPlayer.message(Bukkit.getPlayer(member.UUID), message));
+ }
+
+ public void message(String message, CommunityRole minimumRole)
+ {
+ getMembers().values().stream().filter(member -> member.Role.ordinal() <= minimumRole.ordinal()).forEach(member -> UtilPlayer.message(Bukkit.getPlayer(member.UUID), message));
+ }
+
+ public static enum PrivacySetting
+ {
+ OPEN("Open to Join"),
+ RECRUITING("Accepting Join Requests"),
+ PRIVATE("Closed")
+ ;
+
+ private String _display;
+
+ private PrivacySetting(String display)
+ {
+ _display = display;
+ }
+
+ public String getDisplayText()
+ {
+ return _display;
+ }
+
+ public static PrivacySetting parsePrivacy(String privacy)
+ {
+ for (PrivacySetting setting : PrivacySetting.values())
+ {
+ if (setting.toString().equalsIgnoreCase(privacy))
+ {
+ return setting;
+ }
+ }
+
+ return PrivacySetting.RECRUITING;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityBrowserUpdateEvent.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityBrowserUpdateEvent.java
new file mode 100644
index 000000000..d9dff9fe7
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityBrowserUpdateEvent.java
@@ -0,0 +1,21 @@
+package mineplex.core.communities;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class CommunityBrowserUpdateEvent extends Event
+{
+ private static final HandlerList handlers = new HandlerList();
+
+ public CommunityBrowserUpdateEvent() {}
+
+ public HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityDisbandEvent.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityDisbandEvent.java
new file mode 100644
index 000000000..ce97ed20e
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityDisbandEvent.java
@@ -0,0 +1,31 @@
+package mineplex.core.communities;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class CommunityDisbandEvent extends Event
+{
+ private static final HandlerList handlers = new HandlerList();
+
+ private Community _community;
+
+ public CommunityDisbandEvent(Community community)
+ {
+ _community = community;
+ }
+
+ public Community getCommunity()
+ {
+ return _community;
+ }
+
+ public HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityJoinRequestInfo.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityJoinRequestInfo.java
new file mode 100644
index 000000000..1eb973551
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityJoinRequestInfo.java
@@ -0,0 +1,47 @@
+package mineplex.core.communities;
+
+import java.util.UUID;
+
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+
+import mineplex.core.common.util.C;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunityJoinRequestInfo
+{
+ public String Name;
+ public final UUID UUID;
+ public final int AccountId;
+ private ItemStack _icon;
+
+ public CommunityJoinRequestInfo(String name, UUID uuid, int accountId)
+ {
+ Name = name;
+ UUID = uuid;
+ AccountId = accountId;
+
+ buildIcon();
+ }
+
+ private void buildIcon()
+ {
+ ItemBuilder builder = new ItemBuilder(Material.SKULL_ITEM);
+ builder.setTitle(C.cGreenB + Name);
+ builder.setLore(C.cRed, C.cYellow + "Left Click " + C.cWhite + "Accept", C.cYellow + "Shift-Right Click " + C.cWhite + "Deny");
+ builder.setData((short)3);
+ builder.setPlayerHead(Name);
+ _icon = builder.build();
+ }
+
+ public void update(String name)
+ {
+ Name = name;
+ buildIcon();
+ }
+
+ public ItemStack getRepresentation()
+ {
+ return _icon;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityJoinRequestsUpdateEvent.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityJoinRequestsUpdateEvent.java
new file mode 100644
index 000000000..899ee7f5e
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityJoinRequestsUpdateEvent.java
@@ -0,0 +1,31 @@
+package mineplex.core.communities;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class CommunityJoinRequestsUpdateEvent extends Event
+{
+ private static final HandlerList handlers = new HandlerList();
+
+ private Community _community;
+
+ public CommunityJoinRequestsUpdateEvent(Community community)
+ {
+ _community = community;
+ }
+
+ public Community getCommunity()
+ {
+ return _community;
+ }
+
+ public HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityManager.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityManager.java
new file mode 100644
index 000000000..b4c5e5555
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityManager.java
@@ -0,0 +1,709 @@
+package mineplex.core.communities;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Pattern;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import com.google.common.collect.Lists;
+
+import mineplex.core.Managers;
+import mineplex.core.MiniDbClientPlugin;
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.common.jsonchat.ClickEvent;
+import mineplex.core.common.jsonchat.JsonMessage;
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.common.util.UtilServer;
+import mineplex.core.communities.Community.PrivacySetting;
+import mineplex.core.communities.commands.CommunityCommand;
+import mineplex.core.communities.redis.CommunityChat;
+import mineplex.core.communities.redis.CommunityChatHandler;
+import mineplex.core.communities.redis.CommunityCloseJoinRequest;
+import mineplex.core.communities.redis.CommunityCloseJoinRequestHandler;
+import mineplex.core.communities.redis.CommunityCreate;
+import mineplex.core.communities.redis.CommunityCreateHandler;
+import mineplex.core.communities.redis.CommunityDisband;
+import mineplex.core.communities.redis.CommunityDisbandHandler;
+import mineplex.core.communities.redis.CommunityInvite;
+import mineplex.core.communities.redis.CommunityInviteHandler;
+import mineplex.core.communities.redis.CommunityJoinRequest;
+import mineplex.core.communities.redis.CommunityJoinRequestHandler;
+import mineplex.core.communities.redis.CommunityUnInvite;
+import mineplex.core.communities.redis.CommunityUnInviteHandler;
+import mineplex.core.communities.redis.CommunityUpdateMemberChatReading;
+import mineplex.core.communities.redis.CommunityUpdateMemberChatReadingHandler;
+import mineplex.core.communities.redis.CommunityUpdateMemberRole;
+import mineplex.core.communities.redis.CommunityUpdateMemberRoleHandler;
+import mineplex.core.communities.redis.CommunityUpdateMembership;
+import mineplex.core.communities.redis.CommunityUpdateMembershipHandler;
+import mineplex.core.communities.redis.CommunityUpdateName;
+import mineplex.core.communities.redis.CommunityUpdateNameHandler;
+import mineplex.core.communities.redis.CommunityUpdateSetting;
+import mineplex.core.communities.redis.CommunityUpdateSettingHandler;
+import mineplex.core.communities.storage.CommunityRepository;
+import mineplex.core.preferences.Preference;
+import mineplex.core.preferences.PreferencesManager;
+import mineplex.core.recharge.Recharge;
+import mineplex.serverdata.Region;
+import mineplex.serverdata.commands.ServerCommandManager;
+import mineplex.serverdata.data.DataRepository;
+import mineplex.serverdata.data.PlayerStatus;
+import mineplex.serverdata.redis.RedisDataRepository;
+import mineplex.serverdata.servers.ServerManager;
+import mineplex.serverdata.servers.ServerRepository;
+
+public class CommunityManager extends MiniDbClientPlugin
+{
+ public final Pattern ALPHA_NUMERIC_PATTERN = Pattern.compile("[^A-Za-z0-9]");
+ public final String[] BLOCKED_NAMES = new String[] {"help", "chat", "create", "description", "disband", "invite", "join", "mcs", "rename", "uninvite", "trainee", "mod", "moderator", "srmod", "seniormod", "seniormoderator", "builder", "maplead", "twitch", "youtube", "support", "admin", "administrator", "leader", "dev", "developer", "owner", "party", "mineplex", "mineplexOfficial", "staff", "mineplexstaff", "qualityassurance", "traineemanagement", "modcoordination", "forumninja", "communitymanagement", "event", "socialmedia"};
+ private final CommunityRepository _repo;
+ private final Map _loadedCommunities;
+
+ public final List BrowserIds = new LinkedList<>();
+
+ public final DataRepository StatusRepository;
+
+ private ServerRepository _serverRepo;
+ private boolean _us;
+
+ private boolean _cycling = false;
+
+ @SuppressWarnings("deprecation")
+ public CommunityManager(JavaPlugin plugin, CoreClientManager clientManager)
+ {
+ super("Communities", plugin, clientManager);
+
+ StatusRepository = new RedisDataRepository(ServerManager.getMasterConnection(), ServerManager.getSlaveConnection(),
+ Region.currentRegion(), PlayerStatus.class, "playerStatus");
+
+ _us = plugin.getConfig().getBoolean("serverstatus.us");
+
+ Region region = _us ? Region.US : Region.EU;
+ _serverRepo = ServerManager.getServerRepository(region);
+
+ _repo = new CommunityRepository(plugin, StatusRepository, _us);
+
+ _loadedCommunities = new ConcurrentHashMap<>();
+
+ Bukkit.getScheduler().scheduleAsyncRepeatingTask(plugin, () ->
+ {
+ if (_cycling)
+ {
+ return;
+ }
+
+ LinkedList communities = new LinkedList<>();
+ _loadedCommunities.values().forEach(community -> communities.add(community));
+ _repo.updateMembersAndJoinRequests(communities);
+ }, 0L, 20 * 5);
+
+ Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, () ->
+ {
+ cycleBrowser();
+ }, 0L, 20 * 30);
+
+ _repo.loadCommunities(_loadedCommunities);
+
+ addCommand(new CommunityCommand(this));
+
+ ServerCommandManager.getInstance().registerCommandType(CommunityChat.class, new CommunityChatHandler(this));
+ ServerCommandManager.getInstance().registerCommandType(CommunityCloseJoinRequest.class, new CommunityCloseJoinRequestHandler(this));
+ ServerCommandManager.getInstance().registerCommandType(CommunityCreate.class, new CommunityCreateHandler(this));
+ ServerCommandManager.getInstance().registerCommandType(CommunityDisband.class, new CommunityDisbandHandler(this));
+ ServerCommandManager.getInstance().registerCommandType(CommunityInvite.class, new CommunityInviteHandler(this));
+ ServerCommandManager.getInstance().registerCommandType(CommunityJoinRequest.class, new CommunityJoinRequestHandler(this));
+ ServerCommandManager.getInstance().registerCommandType(CommunityUnInvite.class, new CommunityUnInviteHandler(this));
+ ServerCommandManager.getInstance().registerCommandType(CommunityUpdateMemberChatReading.class, new CommunityUpdateMemberChatReadingHandler(this));
+ ServerCommandManager.getInstance().registerCommandType(CommunityUpdateMemberRole.class, new CommunityUpdateMemberRoleHandler(this));
+ ServerCommandManager.getInstance().registerCommandType(CommunityUpdateMembership.class, new CommunityUpdateMembershipHandler(this));
+ ServerCommandManager.getInstance().registerCommandType(CommunityUpdateName.class, new CommunityUpdateNameHandler(this));
+ ServerCommandManager.getInstance().registerCommandType(CommunityUpdateSetting.class, new CommunityUpdateSettingHandler(this));
+ }
+
+ private void cycleBrowser()
+ {
+ if (_cycling)
+ {
+ return;
+ }
+ _cycling = true;
+ runAsync(() ->
+ {
+ final List resultant = Lists.newArrayList();
+ final List ids = new LinkedList<>();
+ _loadedCommunities.values().stream().filter(c -> c.getMembers().size() >= 5 && c.getPrivacySetting() != PrivacySetting.PRIVATE).forEach(c -> resultant.add(c.getId()));
+
+ Random random = new Random();
+ while (!resultant.isEmpty())
+ {
+ ids.add(resultant.remove(random.nextInt(resultant.size())));
+ }
+
+ runSync(() ->
+ {
+ BrowserIds.clear();
+ BrowserIds.addAll(ids);
+ _cycling = false;
+ UtilServer.CallEvent(new CommunityBrowserUpdateEvent());
+ });
+ });
+ }
+
+ public Community getLoadedCommunity(Integer id)
+ {
+ return _loadedCommunities.get(id);
+ }
+
+ public Community getLoadedCommunity(String name)
+ {
+ for (Entry entry : _loadedCommunities.entrySet())
+ {
+ if (entry.getValue().getName().equalsIgnoreCase(name))
+ {
+ return entry.getValue();
+ }
+ }
+
+ return null;
+ }
+
+ public void handleCommunitySettingUpdate(Integer id, String sender, CommunitySetting setting, String newValue)
+ {
+ Community community = _loadedCommunities.get(id);
+ if (community == null)
+ {
+ return;
+ }
+ setting.parseValueInto(newValue, community);
+ //community.message(F.main(getName(), F.name(sender) + " has changed settings in " + F.name(community.getName()) + "!"));
+ UtilServer.CallEvent(new CommunitySettingUpdateEvent(community));
+ }
+
+ public void handleCommunityNameUpdate(Integer id, String sender, String name)
+ {
+ Community community = _loadedCommunities.get(id);
+ if (community == null)
+ {
+ return;
+ }
+ String oldName = community.getName();
+ community.setName(name);
+ community.message(F.main(getName(), F.name(sender) + " has changed the name of " + F.name(oldName) + " to " + F.name(community.getName()) + "!"));
+ UtilServer.CallEvent(new CommunityNameUpdateEvent(community));
+ }
+
+ public void handleCommunityMembershipRoleUpdate(Integer id, String sender, UUID uuid, CommunityRole role)
+ {
+ Community community = _loadedCommunities.get(id);
+ if (community == null)
+ {
+ return;
+ }
+ CommunityMemberInfo member = community.getMembers().get(uuid);
+ member.Role = role;
+ if (Bukkit.getPlayer(uuid) != null)
+ {
+ if (role.ordinal() > CommunityRole.COLEADER.ordinal())
+ {
+ UtilPlayer.message(Bukkit.getPlayer(uuid), F.main(getName(), F.name(sender) + " has changed your role to " + F.elem(role.getDisplay()) + " in " + F.name(community.getName()) + "!"));
+ }
+ Get(Bukkit.getPlayer(uuid)).setRoleIn(community, role);
+ }
+ String name = member.Name;
+ community.message(F.main(getName(), F.name(sender) + " has changed " + F.name(name + "'s") + " role to " + F.elem(role.getDisplay()) + " in " + F.name(community.getName()) + "!"), CommunityRole.COLEADER);
+ UtilServer.CallEvent(new CommunityMembershipUpdateEvent(community));
+ }
+
+ public void handleCommunityMembershipUpdate(Integer id, String sender, String playerName, UUID playerUUID, Integer accountId, boolean kick, boolean leave)
+ {
+ Community community = _loadedCommunities.get(id);
+ if (community == null)
+ {
+ return;
+ }
+
+ if (kick)
+ {
+ community.message(F.main(getName(), F.name(sender) + " has kicked " + F.name(playerName) + " from " + F.name(community.getName()) + "!"));
+ community.getMembers().remove(playerUUID);
+ if (Bukkit.getPlayer(playerUUID) != null)
+ {
+ Get(Bukkit.getPlayer(playerUUID)).leaveCommunity(community);
+ }
+ }
+ else if (leave)
+ {
+ community.message(F.main(getName(), F.name(playerName) + " has left " + F.name(community.getName()) + "!"));
+ community.getMembers().remove(playerUUID);
+ if (Bukkit.getPlayer(playerUUID) != null)
+ {
+ Get(Bukkit.getPlayer(playerUUID)).leaveCommunity(community);
+ }
+ }
+ else
+ {
+ community.getMembers().put(playerUUID, new CommunityMemberInfo(playerName, playerUUID, accountId, CommunityRole.MEMBER, System.currentTimeMillis()));
+ if (Bukkit.getPlayer(playerUUID) != null)
+ {
+ Get(Bukkit.getPlayer(playerUUID)).joinCommunity(community);
+ Get(Bukkit.getPlayer(playerUUID)).Invites.remove(community.getId());
+ }
+
+ community.message(F.main(getName(), F.name(playerName) + " has joined " + F.name(community.getName()) + "!"));
+ }
+
+ UtilServer.CallEvent(new CommunityMembershipUpdateEvent(community));
+ if (Bukkit.getPlayer(playerUUID) != null)
+ {
+ UtilServer.CallEvent(new CommunityMemberDataUpdateEvent(Bukkit.getPlayer(playerUUID)));
+ }
+ }
+
+ public void handleCommunityInvite(Integer id, String sender, String targetName, UUID targetUUID)
+ {
+ Community community = _loadedCommunities.get(id);
+ if (community == null)
+ {
+ return;
+ }
+ if (Bukkit.getPlayer(targetUUID) != null)
+ {
+ if (!Get(Bukkit.getPlayer(targetUUID)).Invites.contains(community.getId()))
+ {
+ Get(Bukkit.getPlayer(targetUUID)).Invites.add(community.getId());
+ if (Managers.get(PreferencesManager.class).get(Bukkit.getPlayer(targetUUID)).isActive(Preference.COMMUNITY_INVITES))
+ {
+ new JsonMessage(F.main(getName(), "You have been invited to join " + F.elem(community.getName()) + " by " + F.name(sender) + "! Click to join!")).click(ClickEvent.RUN_COMMAND, "/community join " + community.getName()).sendToPlayer(Bukkit.getPlayer(targetUUID));
+ }
+
+ UtilServer.CallEvent(new CommunityMemberDataUpdateEvent(Bukkit.getPlayer(targetUUID)));
+ }
+ }
+ community.message(F.main(getName(), F.name(sender) + " has invited " + F.name(targetName) + " to " + F.name(community.getName()) + "!"), CommunityRole.COLEADER);
+ }
+
+ public void handleCommunityUninvite(Integer id, String sender, String targetName, UUID targetUUID, boolean announce)
+ {
+ Community community = _loadedCommunities.get(id);
+ if (community == null)
+ {
+ return;
+ }
+ if (Bukkit.getPlayer(targetUUID) != null)
+ {
+ Get(Bukkit.getPlayer(targetUUID)).Invites.remove(community.getId());
+ if (Managers.get(PreferencesManager.class).get(Bukkit.getPlayer(targetUUID)).isActive(Preference.COMMUNITY_INVITES) && announce)
+ {
+ UtilPlayer.message(Bukkit.getPlayer(targetUUID), F.main(getName(), "Your invitation to join " + F.elem(community.getName()) + " has been revoked by " + F.name(sender) + "!"));
+ }
+ UtilServer.CallEvent(new CommunityMemberDataUpdateEvent(Bukkit.getPlayer(targetUUID)));
+ }
+ if (announce)
+ {
+ community.message(F.main(getName(), F.name(targetName) + "'s invitation to join " + F.name(community.getName()) + " has been revoked by " + F.name(sender) + "!"), CommunityRole.COLEADER);
+ }
+ }
+
+ public void handleCommunityJoinRequest(Integer id, String playerName, UUID playerUUID, Integer accountId)
+ {
+ Community community = _loadedCommunities.get(id);
+ if (community == null)
+ {
+ return;
+ }
+ if (Bukkit.getPlayer(playerUUID) != null)
+ {
+ UtilPlayer.message(Bukkit.getPlayer(playerUUID), F.main(getName(), "You have requested to join " + F.elem(community.getName()) + "!"));
+ }
+ community.getJoinRequests().put(playerUUID, new CommunityJoinRequestInfo(playerName, playerUUID, accountId));
+ community.message(F.main(getName(), F.name(playerName) + " has requested to join " + F.name(community.getName()) + "!"), CommunityRole.COLEADER);
+
+ UtilServer.CallEvent(new CommunityJoinRequestsUpdateEvent(community));
+ }
+
+ public void handleCommunityCloseJoinRequest(Integer id, String sender, String playerName, UUID playerUUID, Integer accountId, boolean announce)
+ {
+ Community community = _loadedCommunities.get(id);
+ if (community == null)
+ {
+ return;
+ }
+ community.getJoinRequests().remove(playerUUID);
+ if (announce)
+ {
+ if (Bukkit.getPlayer(playerUUID) != null)
+ {
+ UtilPlayer.message(Bukkit.getPlayer(playerUUID), F.main(getName(), "Your request to join " + F.name(community.getName()) + " has been denied by " + F.name(sender) + "!"));
+ }
+ community.message(F.main(getName(), F.name(playerName) + "'s request to join " + F.name(community.getName()) + " has been denied by " + F.name(sender) + "!"), CommunityRole.COLEADER);
+ }
+
+ UtilServer.CallEvent(new CommunityJoinRequestsUpdateEvent(community));
+ }
+
+ public void handleCommunityCreation(Integer id, UUID leaderUUID)
+ {
+ runAsync(() ->
+ {
+ _repo.loadCommunity(id, _loadedCommunities);
+ runSync(() ->
+ {
+ Community community = _loadedCommunities.get(id);
+ if (Bukkit.getPlayer(leaderUUID) != null)
+ {
+ Player leader = Bukkit.getPlayer(leaderUUID);
+ UtilPlayer.message(leader, F.main(getName(), "You have created a community named " + F.name(community.getName()) + "!"));
+ Get(leader).joinCommunity(id, CommunityRole.LEADER);
+ }
+ });
+ });
+ }
+
+ public void handleCommunityDisband(Integer id, String senderName)
+ {
+ Community community = _loadedCommunities.get(id);
+ if (community == null)
+ {
+ return;
+ }
+ community.message(F.main(getName(), F.name(senderName) + " has disbanded community " + F.name(community.getName()) + "!"));
+ UtilServer.CallEvent(new CommunityDisbandEvent(community));
+ UtilServer.GetPlayers().stream().filter(player -> Get(player).Invites.contains(community.getId())).forEach(player -> Get(player).Invites.remove(community.getId()));
+ community.getMembers().keySet().stream().filter(uuid -> Bukkit.getPlayer(uuid) != null).forEach(uuid -> Get(Bukkit.getPlayer(uuid)).leaveCommunity(community));
+ _loadedCommunities.remove(community.getId());
+ runSync(() ->
+ {
+ if (BrowserIds.remove(community.getId()))
+ {
+ UtilServer.CallEvent(new CommunityBrowserUpdateEvent());
+ }
+ });
+ }
+
+ public void handleToggleReadingCommunityChat(Integer id, UUID uuid, boolean reading)
+ {
+ Community community = _loadedCommunities.get(id);
+ if (community == null)
+ {
+ return;
+ }
+
+ if (community.getMembers().containsKey(uuid))
+ {
+ community.getMembers().get(uuid).ReadingChat = reading;
+ if (reading)
+ {
+ UtilPlayer.message(Bukkit.getPlayer(uuid), F.main(getName(), "You are now reading chat from " + F.name(community.getName()) + "!"));
+ }
+ else
+ {
+ UtilPlayer.message(Bukkit.getPlayer(uuid), F.main(getName(), "You are no longer reading chat from " + F.name(community.getName()) + "!"));
+ }
+ }
+ }
+
+ public void handleCommunityChat(Integer id, String senderName, String message)
+ {
+ Community community = _loadedCommunities.get(id);
+ if (community == null)
+ {
+ return;
+ }
+ community.sendChat(community.getChatFormatting()[0] + C.Bold + community.getName() + " " + community.getChatFormatting()[1] + C.Bold + senderName + " " + community.getChatFormatting()[2] + message);
+ }
+
+ public void handleInvite(Player sender, Community community, String target)
+ {
+ CommunityJoinRequestInfo[] jr = community.getJoinRequests().values().stream().filter(data -> data.Name.equalsIgnoreCase(target)).toArray(size -> new CommunityJoinRequestInfo[size]);
+ if (jr.length == 1)
+ {
+ UtilPlayer.message(sender, F.main(getName(), "You have accepted " + F.name(target) + "'s join request to " + F.name(community.getName()) + "!"));
+ runAsync(() ->
+ {
+ _repo.addToCommunity(jr[0].AccountId, community.getId());
+ _repo.removeJoinRequest(community.getId(), jr[0].AccountId);
+ });
+ new CommunityCloseJoinRequest(community.getId(), sender.getName(), jr[0].Name, jr[0].UUID.toString(), jr[0].AccountId, false).publish();
+ new CommunityUpdateMembership(community.getId(), sender.getName(), jr[0].Name, jr[0].UUID.toString(), jr[0].AccountId, false, false).publish();
+ return;
+ }
+ runAsync(() ->
+ {
+ if (_repo.inviteToCommunity(community.getId(), target))
+ {
+ if (!community.getMembers().containsKey(sender.getUniqueId()))
+ {
+ UtilPlayer.message(sender, F.main(getName(), "You have invited " + F.name(target) + " to join " + F.name(community.getName()) + "!"));
+ }
+ new CommunityInvite(community.getId(), sender.getName(), target, Managers.get(CoreClientManager.class).loadUUIDFromDB(target).toString()).publish();
+ }
+ else
+ {
+ UtilPlayer.message(sender, F.main(getName(), "Either " + F.name(target) + " does not exist or you have already invited them to " + F.name(community.getName()) + "!"));
+ }
+ });
+ }
+
+ public void handleUninvite(Player sender, Community community, String target)
+ {
+ runAsync(() ->
+ {
+ if (_repo.deleteInviteToCommunity(community.getId(), target))
+ {
+ if (!community.getMembers().containsKey(sender.getUniqueId()))
+ {
+ UtilPlayer.message(sender, F.main(getName(), "You have revoked " + F.name(target) + "'s invitation to join " + F.name(community.getName()) + "!"));
+ }
+ new CommunityUnInvite(community.getId(), sender.getName(), target, Managers.get(CoreClientManager.class).loadUUIDFromDB(target).toString(), true).publish();
+ }
+ else
+ {
+ UtilPlayer.message(sender, F.main(getName(), "Either " + F.name(target) + " does not exist or you have not invited them to " + F.name(community.getName()) + "!"));
+ }
+ });
+ }
+
+ public void handleRejectInvite(Player sender, Community community)
+ {
+ final String playerName = Managers.get(CoreClientManager.class).Get(sender).getName();
+ runAsync(() ->
+ {
+ _repo.deleteInviteToCommunity(community.getId(), playerName);
+ });
+
+ new CommunityUnInvite(community.getId(), sender.getName(), sender.getName(), sender.getUniqueId().toString(), false).publish();
+ }
+
+ public void handleJoinRequest(Player sender, Community community)
+ {
+ final int accountId = Managers.get(CoreClientManager.class).getAccountId(sender);
+
+ if (Get(sender).Invites.contains(community.getId()))
+ {
+ String playerName = Managers.get(CoreClientManager.class).Get(sender).getName(); //Guarantee real name (important in this instance)
+ runAsync(() ->
+ {
+ _repo.addToCommunity(accountId, community.getId());
+ _repo.deleteInviteToCommunity(community.getId(), playerName);
+ });
+ new CommunityUnInvite(community.getId(), sender.getName(), sender.getName(), sender.getUniqueId().toString(), false).publish();
+ new CommunityUpdateMembership(community.getId(), sender.getName(), sender.getName(), sender.getUniqueId().toString(), accountId, false, false).publish();
+ return;
+ }
+ runAsync(() ->
+ {
+ _repo.addJoinRequest(community.getId(), accountId);
+ });
+ new CommunityJoinRequest(community.getId(), sender.getName(), sender.getUniqueId().toString(), accountId).publish();
+ }
+
+ public void handleCloseJoinRequest(Player sender, Community community, CommunityJoinRequestInfo info, boolean announce)
+ {
+ runAsync(() ->
+ {
+ _repo.removeJoinRequest(community.getId(), info.AccountId);
+ });
+ new CommunityCloseJoinRequest(community.getId(), sender.getName(), info.Name, info.UUID.toString(), info.AccountId, announce).publish();
+ }
+
+ public void handleJoin(Player sender, Community community, boolean fromInvite)
+ {
+ final int accountId = Managers.get(CoreClientManager.class).getAccountId(sender);
+ final String playerName = Managers.get(CoreClientManager.class).Get(sender).getName();
+ runAsync(() ->
+ {
+ _repo.addToCommunity(accountId, community.getId());
+ if (fromInvite)
+ {
+ _repo.deleteInviteToCommunity(community.getId(), playerName);
+ }
+ });
+ new CommunityUpdateMembership(community.getId(), sender.getName(), sender.getName(), sender.getUniqueId().toString(), accountId, false, false).publish();
+ if (fromInvite)
+ {
+ new CommunityUnInvite(community.getId(), sender.getName(), sender.getName(), sender.getUniqueId().toString(), false).publish();
+ }
+ }
+
+ public void handleKick(Player sender, Community community, CommunityMemberInfo info)
+ {
+ runAsync(() ->
+ {
+ _repo.removeFromCommunity(info.AccountId, community.getId());
+ });
+ new CommunityUpdateMembership(community.getId(), sender.getName(), info.Name, info.UUID.toString(), info.AccountId, true, false).publish();
+ }
+
+ public void handleLeave(Player sender, Community community, CommunityMemberInfo info)
+ {
+ runAsync(() ->
+ {
+ _repo.removeFromCommunity(info.AccountId, community.getId());
+ });
+ new CommunityUpdateMembership(community.getId(), sender.getName(), info.Name, info.UUID.toString(), info.AccountId, false, true).publish();
+ }
+
+ public void handleSettingUpdate(Player sender, Community community, CommunitySetting setting, String newValue)
+ {
+ runAsync(() ->
+ {
+ _repo.updateCommunitySetting(setting, community.getId(), newValue);
+ });
+ new CommunityUpdateSetting(community.getId(), sender.getName(), setting.toString(), newValue).publish();
+ }
+
+ public void handleNameUpdate(Player sender, Community community, String newName)
+ {
+ runAsync(() ->
+ {
+ _repo.updateCommunityName(community.getId(), newName);
+ });
+ new CommunityUpdateName(community.getId(), sender.getName(), newName).publish();
+ }
+
+ public void handleRoleUpdate(Player sender, Community community, CommunityMemberInfo info, CommunityRole role)
+ {
+ runAsync(() ->
+ {
+ _repo.updateCommunityRole(info.AccountId, community.getId(), role);
+ });
+ new CommunityUpdateMemberRole(community.getId(), sender.getName(), info.UUID.toString(), role.toString()).publish();
+ }
+
+ public void handleCreate(Player sender, String name)
+ {
+ int accountId = Managers.get(CoreClientManager.class).getAccountId(sender);
+ runAsync(() ->
+ {
+ _repo.createCommunity(name, accountId, id ->
+ {
+ if (id == -1)
+ {
+ sender.sendMessage(F.main(getName(), "Failed to create community " + F.elem(name)));
+ }
+ else
+ {
+ new CommunityCreate(sender.getUniqueId().toString(), id).publish();
+ }
+ });
+ });
+ }
+
+ public void handleDisband(Player sender, Community community)
+ {
+ runAsync(() ->
+ {
+ _repo.deleteCommunity(community.getId());
+ });
+ new CommunityDisband(sender.getName(), community.getId()).publish();
+ }
+
+ public void handleToggleReadingChat(Player sender, Community community)
+ {
+ final int accountId = Managers.get(CoreClientManager.class).getAccountId(sender);
+ final boolean reading = !community.getMembers().get(sender.getUniqueId()).ReadingChat;
+
+ runAsync(() ->
+ {
+ _repo.setReadingChat(accountId, community.getId(), reading);
+ });
+ new CommunityUpdateMemberChatReading(community.getId(), sender.getUniqueId().toString(), reading).publish();
+ }
+
+ @Override
+ public String getQuery(int accountId, String uuid, String name)
+ {
+ return "SELECT cm.communityId, cm.communityRole, c.region FROM communityMembers AS cm INNER JOIN communities AS c ON c.id=cm.communityId WHERE accountId=" + accountId + ";";
+ }
+
+ @Override
+ public void processLoginResultSet(String playerName, UUID uuid, int accountId, ResultSet resultSet) throws SQLException
+ {
+ CommunityMemberData data = new CommunityMemberData();
+ while (resultSet.next())
+ {
+ Integer communityId = resultSet.getInt("communityId");
+ CommunityRole role = CommunityRole.parseRole(resultSet.getString("communityRole"));
+ String region = resultSet.getString("region");
+ if ((_us && region.equalsIgnoreCase("US")) || (!_us && region.equalsIgnoreCase("EU")))
+ {
+ data.joinCommunity(communityId, role);
+ }
+ }
+ Set(uuid, data);
+ }
+
+ @EventHandler
+ public void loadInvites(PlayerJoinEvent event)
+ {
+ final int accountId = Managers.get(CoreClientManager.class).getAccountId(event.getPlayer());
+ final CommunityMemberData data = Get(event.getPlayer());
+ runAsync(() ->
+ {
+ _repo.loadInvites(accountId, data.Invites);
+ runSync(() ->
+ {
+ if (data.Invites.size() > 0 && Managers.get(PreferencesManager.class).get(event.getPlayer()).isActive(Preference.COMMUNITY_INVITES))
+ {
+ UtilPlayer.message(event.getPlayer(), F.main(getName(), "You have been invited to join " + F.elem(data.Invites.size()) + " communities!"));
+ }
+ });
+ });
+ }
+
+ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
+ public void onChat(AsyncPlayerChatEvent event)
+ {
+ if (!event.getMessage().startsWith("!"))
+ {
+ return;
+ }
+ event.setCancelled(true);
+ Player sender = event.getPlayer();
+ if (Get(sender).getCommunityChattingTo() != -1)
+ {
+ Community target = _loadedCommunities.get(Get(sender).getCommunityChattingTo());
+ if (target == null || !target.getMembers().containsKey(event.getPlayer().getUniqueId()))
+ {
+ UtilPlayer.message(sender, F.main(getName(), "You are not in that community! Use " + F.elem("/com chat ") + " to select a new community to chat to!"));
+ }
+ else
+ {
+ if (Recharge.Instance.use(sender, "Community Chat to " + target.getId(), target.getChatDelay(), false, false))
+ {
+ new CommunityChat(sender.getName(), target.getId(), event.getMessage().substring(1)).publish();
+ }
+ else
+ {
+ UtilPlayer.message(sender, F.main(getName(), "You cannot chat to " + F.name(target.getName()) + " that quickly!"));
+ }
+ }
+ }
+ else
+ {
+ UtilPlayer.message(sender, F.main(getName(), "You are not chatting to a specific community! Use " + F.elem("/com chat ") + " to select a community to chat to."));
+ }
+ }
+
+ @Override
+ protected CommunityMemberData addPlayer(UUID uuid)
+ {
+ return new CommunityMemberData();
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMemberData.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMemberData.java
new file mode 100644
index 000000000..d7138721a
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMemberData.java
@@ -0,0 +1,84 @@
+package mineplex.core.communities;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import mineplex.core.Managers;
+
+public class CommunityMemberData
+{
+ private final Map _communities = new HashMap<>();
+
+ public final List Invites = new ArrayList<>();
+
+ private int _chattingTo = -1;
+
+ public CommunityMemberData()
+ {
+
+ }
+
+ public int getTotalCommunities()
+ {
+ return _communities.size();
+ }
+
+ public boolean ownsCommunity()
+ {
+ return _communities.containsValue(CommunityRole.LEADER);
+ }
+
+ public int getCommunityChattingTo()
+ {
+ return _chattingTo;
+ }
+
+ public void setCommunityChattingTo(Community community)
+ {
+ _chattingTo = community.getId();
+ }
+
+ public Community[] getCommunities()
+ {
+ Community[] communities = new Community[_communities.size()];
+ int index = 0;
+ for (Integer comId : _communities.keySet())
+ {
+ communities[index] = Managers.get(CommunityManager.class).getLoadedCommunity(comId);
+ index++;
+ }
+ return communities;
+ }
+
+ public boolean isMemberOf(Community community)
+ {
+ return _communities.containsKey(community.getId());
+ }
+
+ public CommunityRole getRoleIn(Community community)
+ {
+ return _communities.get(community.getId());
+ }
+
+ public void joinCommunity(Integer communityId, CommunityRole role)
+ {
+ _communities.put(communityId, role);
+ }
+
+ public void joinCommunity(Community community)
+ {
+ joinCommunity(community.getId(), CommunityRole.MEMBER);
+ }
+
+ public void setRoleIn(Community community, CommunityRole role)
+ {
+ _communities.replace(community.getId(), role);
+ }
+
+ public void leaveCommunity(Community community)
+ {
+ _communities.remove(community.getId());
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMemberDataUpdateEvent.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMemberDataUpdateEvent.java
new file mode 100644
index 000000000..1fd22e0e1
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMemberDataUpdateEvent.java
@@ -0,0 +1,32 @@
+package mineplex.core.communities;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class CommunityMemberDataUpdateEvent extends Event
+{
+ private static final HandlerList handlers = new HandlerList();
+
+ private Player _player;
+
+ public CommunityMemberDataUpdateEvent(Player player)
+ {
+ _player = player;
+ }
+
+ public Player getPlayer()
+ {
+ return _player;
+ }
+
+ public HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMemberInfo.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMemberInfo.java
new file mode 100644
index 000000000..fe62d8376
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMemberInfo.java
@@ -0,0 +1,99 @@
+package mineplex.core.communities;
+
+import java.util.UUID;
+
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.UtilTime;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunityMemberInfo
+{
+ public String Name;
+ public final UUID UUID;
+ public final int AccountId;
+ public CommunityRole Role;
+ public boolean OwnsCommunity = false;
+ public boolean ReadingChat = true;
+ private ItemStack _memberIcon, _outsiderIcon;
+ private long _sinceLastLogin;
+ private boolean _online = false;
+ private String _currentServer = "";
+
+ public CommunityMemberInfo(String name, UUID uuid, int accountId, CommunityRole role, long timeSinceLastLogin)
+ {
+ Name = name;
+ UUID = uuid;
+ AccountId = accountId;
+ Role = role;
+ _sinceLastLogin = timeSinceLastLogin;
+
+ buildIcons();
+ }
+
+ private void buildIcons()
+ {
+ ItemBuilder builder = new ItemBuilder(Material.SKULL_ITEM).setTitle(C.cGreenB + Name).setLore(C.cRed, C.cYellow + "Role " + C.cWhite + Role.getDisplay());
+ _outsiderIcon = builder.build();
+ builder.setTitle(!_online ? C.cRedB + Name : C.cGreenB + Name);
+ if (_online)
+ {
+ builder.addLore(C.cYellow + "Server " + C.cWhite + _currentServer);
+ }
+ else
+ {
+ builder.addLore(C.cYellow + "Last Seen " + C.cWhite + UtilTime.MakeStr(_sinceLastLogin) + " Ago");
+ }
+ if (_online)
+ {
+ builder.setData((short)3);
+ builder.setPlayerHead(Name);
+ }
+ _memberIcon = builder.build();
+ }
+
+ public void update(String name, CommunityRole role, long timeSinceLastLogin, boolean online, String currentServer)
+ {
+ Name = name;
+ Role = role;
+ _sinceLastLogin = timeSinceLastLogin;
+ _online = online;
+ _currentServer = currentServer;
+
+ buildIcons();
+ }
+
+ public boolean isOnline()
+ {
+ return _online;
+ }
+
+ public ItemStack getRepresentation(CommunityRole viewerRole)
+ {
+ if (viewerRole == null)
+ {
+ return _outsiderIcon;
+ }
+
+ ItemBuilder builder = new ItemBuilder(_memberIcon);
+ if ((viewerRole == CommunityRole.LEADER && Role != CommunityRole.LEADER) || (viewerRole.ordinal() < Role.ordinal()))
+ {
+ builder.addLore(C.cGold);
+ }
+ if (viewerRole == CommunityRole.LEADER && Role != CommunityRole.LEADER)
+ {
+ builder.addLore(C.cYellow + (Role == CommunityRole.COLEADER ? "Shift-" : "" ) + "Left Click " + C.cWhite + "Promote");
+ if (Role != CommunityRole.MEMBER)
+ {
+ builder.addLore(C.cYellow + "Right Click " + C.cWhite + "Demote");
+ }
+ }
+ if (viewerRole.ordinal() < Role.ordinal())
+ {
+ builder.addLore(C.cYellow + "Shift-Right Click " + C.cWhite + "Kick");
+ }
+ return builder.build();
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMembershipUpdateEvent.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMembershipUpdateEvent.java
new file mode 100644
index 000000000..959044ea3
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityMembershipUpdateEvent.java
@@ -0,0 +1,31 @@
+package mineplex.core.communities;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class CommunityMembershipUpdateEvent extends Event
+{
+ private static final HandlerList handlers = new HandlerList();
+
+ private Community _community;
+
+ public CommunityMembershipUpdateEvent(Community community)
+ {
+ _community = community;
+ }
+
+ public Community getCommunity()
+ {
+ return _community;
+ }
+
+ public HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityNameUpdateEvent.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityNameUpdateEvent.java
new file mode 100644
index 000000000..a583c6ee9
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityNameUpdateEvent.java
@@ -0,0 +1,31 @@
+package mineplex.core.communities;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class CommunityNameUpdateEvent extends Event
+{
+ private static final HandlerList handlers = new HandlerList();
+
+ private Community _community;
+
+ public CommunityNameUpdateEvent(Community community)
+ {
+ _community = community;
+ }
+
+ public Community getCommunity()
+ {
+ return _community;
+ }
+
+ public HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityRole.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityRole.java
new file mode 100644
index 000000000..c98d7f0b9
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunityRole.java
@@ -0,0 +1,34 @@
+package mineplex.core.communities;
+
+public enum CommunityRole
+{
+ LEADER("Leader"),
+ COLEADER("Co-Leader"),
+ MEMBER("Member")
+ ;
+
+ private String _displayName;
+
+ private CommunityRole(String displayName)
+ {
+ _displayName = displayName;
+ }
+
+ public String getDisplay()
+ {
+ return _displayName;
+ }
+
+ public static CommunityRole parseRole(String role)
+ {
+ for (CommunityRole test : CommunityRole.values())
+ {
+ if (test.toString().equalsIgnoreCase(role))
+ {
+ return test;
+ }
+ }
+
+ return CommunityRole.MEMBER;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunitySetting.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunitySetting.java
new file mode 100644
index 000000000..fc049ac5e
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunitySetting.java
@@ -0,0 +1,124 @@
+package mineplex.core.communities;
+
+import org.bukkit.ChatColor;
+
+import mineplex.core.common.Pair;
+import mineplex.core.common.util.Callback;
+import mineplex.core.communities.Community.PrivacySetting;
+import mineplex.core.game.GameDisplay;
+
+public enum CommunitySetting
+{
+ CHAT_NAME_COLOR(1, pair ->
+ {
+ String value = pair.getLeft();
+ Community community = pair.getRight();
+
+ ChatColor color = ChatColor.valueOf(value);
+ if (color == null || !color.isColor())
+ {
+ return;
+ }
+ community.setChatFormatting(new ChatColor[] {color, community.getChatFormatting()[1], community.getChatFormatting()[2]});
+ }
+ ),
+ CHAT_PLAYER_COLOR(2, pair ->
+ {
+ String value = pair.getLeft();
+ Community community = pair.getRight();
+
+ ChatColor color = ChatColor.valueOf(value);
+ if (color == null || !color.isColor())
+ {
+ return;
+ }
+ community.setChatFormatting(new ChatColor[] {community.getChatFormatting()[0], color, community.getChatFormatting()[2]});
+ }
+ ),
+ CHAT_MESSAGE_COLOR(3, pair ->
+ {
+ String value = pair.getLeft();
+ Community community = pair.getRight();
+
+ ChatColor color = ChatColor.valueOf(value);
+ if (color == null || !color.isColor())
+ {
+ return;
+ }
+ community.setChatFormatting(new ChatColor[] {community.getChatFormatting()[0], community.getChatFormatting()[1], color});
+ }
+ ),
+ CHAT_DELAY(4, pair ->
+ {
+ String value = pair.getLeft();
+ Community community = pair.getRight();
+
+ try
+ {
+ Long delay = Long.parseLong(value);
+ community.setChatDelay(delay);
+ }
+ catch (Exception e)
+ {
+ return;
+ }
+ }
+ ),
+ FAVORITE_GAME(5, pair ->
+ {
+ String value = pair.getLeft();
+ Community community = pair.getRight();
+
+ GameDisplay display = GameDisplay.matchName(value);
+ community.setFavoriteGame(display);
+ }
+ ),
+ PRIVACY(6, pair ->
+ {
+ String value = pair.getLeft();
+ Community community = pair.getRight();
+
+ PrivacySetting setting = PrivacySetting.parsePrivacy(value);
+ community.setPrivacySetting(setting);
+ }
+ ),
+ DESCRIPTION(7, pair ->
+ {
+ String value = pair.getLeft();
+ Community community = pair.getRight();
+
+ community.setDescription(value);
+ });
+
+ private int _id;
+ private Callback> _parser;
+
+ private CommunitySetting(int id, Callback> parseValue)
+ {
+ _id = id;
+ _parser = parseValue;
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public void parseValueInto(String value, Community community)
+ {
+ _parser.run(Pair.create(value, community));
+ }
+
+ public static CommunitySetting getSetting(Integer id)
+ {
+ for (CommunitySetting setting : CommunitySetting.values())
+ {
+ if (setting.getId() == id)
+ {
+ return setting;
+ }
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunitySettingUpdateEvent.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunitySettingUpdateEvent.java
new file mode 100644
index 000000000..5f7185fdc
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/CommunitySettingUpdateEvent.java
@@ -0,0 +1,31 @@
+package mineplex.core.communities;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class CommunitySettingUpdateEvent extends Event
+{
+ private static final HandlerList handlers = new HandlerList();
+
+ private Community _community;
+
+ public CommunitySettingUpdateEvent(Community community)
+ {
+ _community = community;
+ }
+
+ public Community getCommunity()
+ {
+ return _community;
+ }
+
+ public HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityChatCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityChatCommand.java
new file mode 100644
index 000000000..a1edba960
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityChatCommand.java
@@ -0,0 +1,42 @@
+package mineplex.core.communities.commands;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityManager;
+
+public class CommunityChatCommand extends CommandBase
+{
+ public CommunityChatCommand(CommunityManager plugin)
+ {
+ super(plugin, Rank.ALL, "chat");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length < 1)
+ {
+ UtilPlayer.message(caller, F.help("/com chat ", "Selects which community you chat to", Rank.ALL, ChatColor.AQUA));
+ return;
+ }
+ Community c = Plugin.getLoadedCommunity(args[0]);
+ if (c == null)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That community was not found!"));
+ return;
+ }
+ if (!c.getMembers().containsKey(caller.getUniqueId()))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You are not in " + F.name(c.getName()) + "!"));
+ return;
+ }
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You are now chatting to " + F.name(c.getName()) + "! Use " + F.elem("!") + " before your message to use community chat!"));
+ Plugin.Get(caller).setCommunityChattingTo(c);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityCommand.java
new file mode 100644
index 000000000..90af36ac7
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityCommand.java
@@ -0,0 +1,68 @@
+package mineplex.core.communities.commands;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+import mineplex.core.command.MultiCommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.communities.gui.community.CommunityMembersPage;
+import mineplex.core.communities.gui.overview.CommunityOverviewPage;
+
+public class CommunityCommand extends MultiCommandBase
+{
+ public CommunityCommand(CommunityManager plugin)
+ {
+ super(plugin, Rank.ALL, "community", "communities", "com");
+
+ AddCommand(new CommunityChatCommand(plugin));
+ AddCommand(new CommunityCreateCommand(plugin));
+ AddCommand(new CommunityDescriptionCommand(plugin));
+ AddCommand(new CommunityDisbandCommand(plugin));
+ AddCommand(new CommunityInviteCommand(plugin));
+ AddCommand(new CommunityJoinCommand(plugin));
+ AddCommand(new CommunityMCSCommand(plugin));
+ //AddCommand(new CommunityMenuCommand(plugin));
+ AddCommand(new CommunityRenameCommand(plugin));
+ AddCommand(new CommunityUnInviteCommand(plugin));
+ }
+
+ @Override
+ protected void Help(Player caller, String[] args)
+ {
+ if (args.length > 0)
+ {
+ if (args[0].equalsIgnoreCase("help"))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "Community Commands:"));
+ UtilPlayer.message(caller, F.help("/com ", "Opens a community's menu", Rank.ALL, ChatColor.DARK_AQUA));
+ //UtilPlayer.message(caller, F.help("/com menu", "Opens your community menu", Rank.ALL));
+ UtilPlayer.message(caller, F.help("/com invite ", "Invites a player to a community you manage", Rank.ALL, ChatColor.DARK_AQUA));
+ UtilPlayer.message(caller, F.help("/com uninvite ", "Revokes a player's invitation to a community you manage", Rank.ALL, ChatColor.DARK_AQUA));
+ UtilPlayer.message(caller, F.help("/com join ", "Joins a community that is open or you have been invited to", Rank.ALL, ChatColor.DARK_AQUA));
+ UtilPlayer.message(caller, F.help("/com chat ", "Selects which community you chat to", Rank.ALL, ChatColor.DARK_AQUA));
+ UtilPlayer.message(caller, F.help("/com create ", "Creates a new community", Rank.ETERNAL, ChatColor.DARK_AQUA));
+ UtilPlayer.message(caller, F.help("/com rename ", "Changes the name of a community you own", Rank.ETERNAL, ChatColor.DARK_AQUA));
+ UtilPlayer.message(caller, F.help("/com mcs ", "Opens the Mineplex Community Server of a community you manage", Rank.ALL, ChatColor.DARK_AQUA));
+ UtilPlayer.message(caller, F.help("/com description ", "Sets the description of a community you manage", Rank.ALL, ChatColor.DARK_AQUA));
+ UtilPlayer.message(caller, F.help("/com disband ", "Disbands a community you own", Rank.ETERNAL, ChatColor.DARK_AQUA));
+ return;
+ }
+ Community community = Plugin.getLoadedCommunity(args[0]);
+ if (community == null)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "Could not find community " + F.name(args[0]) + "!"));
+ }
+ else
+ {
+ new CommunityMembersPage(caller, community);
+ }
+ return;
+ }
+
+ new CommunityOverviewPage(caller);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityCreateCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityCreateCommand.java
new file mode 100644
index 000000000..35c545edc
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityCreateCommand.java
@@ -0,0 +1,65 @@
+package mineplex.core.communities.commands;
+
+import java.util.Arrays;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+import mineplex.core.Managers;
+import mineplex.core.chat.Chat;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityManager;
+
+public class CommunityCreateCommand extends CommandBase
+{
+ public CommunityCreateCommand(CommunityManager plugin)
+ {
+ super(plugin, Rank.ETERNAL, "create");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length < 1)
+ {
+ UtilPlayer.message(caller, F.help("/com create ", "Creates a new community", Rank.ETERNAL, ChatColor.AQUA));
+ return;
+ }
+ Community c = Plugin.getLoadedCommunity(args[0]);
+ if (c != null)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "A community already exists with that name!"));
+ return;
+ }
+ if (Plugin.Get(caller).ownsCommunity())
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You already own a community!"));
+ return;
+ }
+ if (args[0].length() > 15 || Plugin.ALPHA_NUMERIC_PATTERN.matcher(args[0]).find())
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "A community name cannot be longer than 15 characters and must be alphanumeric!"));
+ return;
+ }
+ if (Arrays.asList(Plugin.BLOCKED_NAMES).contains(args[0].toLowerCase()))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That name is not allowed!"));
+ return;
+ }
+ Plugin.runAsync(() ->
+ {
+ if (Managers.get(Chat.class).getFilteredMessage(caller, args[0]).contains("*"))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That name is not allowed!"));
+ }
+ else
+ {
+ Plugin.handleCreate(caller, args[0]);
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityDescriptionCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityDescriptionCommand.java
new file mode 100644
index 000000000..efaae74b2
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityDescriptionCommand.java
@@ -0,0 +1,77 @@
+package mineplex.core.communities.commands;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+import mineplex.core.Managers;
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.chat.Chat;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.communities.CommunityMemberInfo;
+import mineplex.core.communities.CommunityRole;
+import mineplex.core.communities.CommunitySetting;
+
+public class CommunityDescriptionCommand extends CommandBase
+{
+ public CommunityDescriptionCommand(CommunityManager plugin)
+ {
+ super(plugin, Rank.ALL, "description");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length < 2)
+ {
+ UtilPlayer.message(caller, F.help("/com description ", "Sets the description of a community you manage", Rank.ALL, ChatColor.AQUA));
+ return;
+ }
+ Community c = Plugin.getLoadedCommunity(args[0]);
+ String desc = args[1];
+ for (int i = 2; i < args.length; i++)
+ {
+ desc += (" " + args[i]);
+ }
+ if (c == null)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That community was not found!"));
+ return;
+ }
+ if (c.getMembers().getOrDefault(caller.getUniqueId(), new CommunityMemberInfo(caller.getName(), caller.getUniqueId(), -1, CommunityRole.MEMBER, -1L)).Role.ordinal() > CommunityRole.COLEADER.ordinal())
+ {
+ if (!Managers.get(CoreClientManager.class).Get(caller).GetRank().has(Rank.ADMIN))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You are not a co-leader of " + F.name(c.getName()) + "!"));
+ return;
+ }
+ }
+ if (desc.length() > 30)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "A community description cannot be longer than 30 characters!"));
+ return;
+ }
+ if (Plugin.ALPHA_NUMERIC_PATTERN.matcher(desc.replace(" ", "").replace("!", "").replace("?", "").replace(".", "").replace("'", "").replace("\"", "")).find())
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "A community description must be alphanumeric!"));
+ return;
+ }
+ final String description = desc;
+ Plugin.runAsync(() ->
+ {
+ if (Managers.get(Chat.class).getFilteredMessage(caller, description).contains("*"))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That description is not allowed!"));
+ }
+ else
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You have changed the description of " + F.name(c.getName()) + " to " + F.elem(description) + "!"));
+ Plugin.handleSettingUpdate(caller, c, CommunitySetting.DESCRIPTION, description);
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityDisbandCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityDisbandCommand.java
new file mode 100644
index 000000000..a70b77542
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityDisbandCommand.java
@@ -0,0 +1,52 @@
+package mineplex.core.communities.commands;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+import mineplex.core.Managers;
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.communities.CommunityMemberInfo;
+import mineplex.core.communities.CommunityRole;
+
+public class CommunityDisbandCommand extends CommandBase
+{
+ public CommunityDisbandCommand(CommunityManager plugin)
+ {
+ super(plugin, Rank.ETERNAL, "disband");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length < 1)
+ {
+ UtilPlayer.message(caller, F.help("/com disband ", "Disbands a community you own", Rank.ETERNAL, ChatColor.AQUA));
+ return;
+ }
+ Community c = Plugin.getLoadedCommunity(args[0]);
+ if (c == null)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That community was not found!"));
+ return;
+ }
+ if (c.getMembers().getOrDefault(caller.getUniqueId(), new CommunityMemberInfo(caller.getName(), caller.getUniqueId(), -1, CommunityRole.MEMBER, -1L)).Role != CommunityRole.LEADER)
+ {
+ if (!Managers.get(CoreClientManager.class).Get(caller).GetRank().has(Rank.ADMIN))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You are not the leader of " + F.name(c.getName()) + "!"));
+ return;
+ }
+ }
+ if (!c.getMembers().containsKey(caller.getUniqueId()))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You have disbanded community " + F.name(c.getName()) + "!"));
+ }
+ Plugin.handleDisband(caller, c);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityInviteCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityInviteCommand.java
new file mode 100644
index 000000000..f3b6e6b65
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityInviteCommand.java
@@ -0,0 +1,57 @@
+package mineplex.core.communities.commands;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+import mineplex.core.Managers;
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.communities.CommunityMemberInfo;
+import mineplex.core.communities.CommunityRole;
+
+public class CommunityInviteCommand extends CommandBase
+{
+ public CommunityInviteCommand(CommunityManager plugin)
+ {
+ super(plugin, Rank.ALL, "invite");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length < 2)
+ {
+ UtilPlayer.message(caller, F.help("/com invite ", "Invites a player to a community you manage", Rank.ALL, ChatColor.AQUA));
+ return;
+ }
+ String player = args[0];
+ Community c = Plugin.getLoadedCommunity(args[1]);
+ if (c == null)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That community was not found!"));
+ return;
+ }
+ if (c.getMembers().getOrDefault(caller.getUniqueId(), new CommunityMemberInfo(caller.getName(), caller.getUniqueId(), -1, CommunityRole.MEMBER, -1L)).Role.ordinal() > CommunityRole.COLEADER.ordinal())
+ {
+ if (!Managers.get(CoreClientManager.class).Get(caller).GetRank().has(Rank.ADMIN))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You are not a co-leader of " + F.name(c.getName()) + "!"));
+ return;
+ }
+ }
+ for (CommunityMemberInfo info : c.getMembers().values())
+ {
+ if (info.Name.equalsIgnoreCase(player))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), F.name(player) + " is already a member of " + F.name(c.getName()) + "!"));
+ return;
+ }
+ }
+ Plugin.handleInvite(caller, c, player);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityJoinCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityJoinCommand.java
new file mode 100644
index 000000000..202d73fc3
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityJoinCommand.java
@@ -0,0 +1,47 @@
+package mineplex.core.communities.commands;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.Community.PrivacySetting;
+import mineplex.core.communities.CommunityManager;
+
+public class CommunityJoinCommand extends CommandBase
+{
+ public CommunityJoinCommand(CommunityManager plugin)
+ {
+ super(plugin, Rank.ALL, "join");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length < 1)
+ {
+ UtilPlayer.message(caller, F.help("/com join ", "Joins a community that is open or you have been invited to", Rank.ALL, ChatColor.AQUA));
+ return;
+ }
+ Community c = Plugin.getLoadedCommunity(args[0]);
+ if (c == null)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That community was not found!"));
+ return;
+ }
+ if (c.getMembers().containsKey(caller.getUniqueId()))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You are already in " + F.name(c.getName()) + "!"));
+ return;
+ }
+ if (c.getPrivacySetting() != PrivacySetting.OPEN && !Plugin.Get(caller).Invites.contains(c.getId()))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You are have not been invited to " + F.name(c.getName()) + "!"));
+ return;
+ }
+ Plugin.handleJoin(caller, c, Plugin.Get(caller).Invites.contains(c.getId()));
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityMCSCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityMCSCommand.java
new file mode 100644
index 000000000..1e499c57f
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityMCSCommand.java
@@ -0,0 +1,50 @@
+package mineplex.core.communities.commands;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+import mineplex.core.Managers;
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.communities.CommunityMemberInfo;
+import mineplex.core.communities.CommunityRole;
+import mineplex.core.personalServer.PersonalServerManager;
+
+public class CommunityMCSCommand extends CommandBase
+{
+ public CommunityMCSCommand(CommunityManager plugin)
+ {
+ super(plugin, Rank.ALL, "mcs");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length < 1)
+ {
+ UtilPlayer.message(caller, F.help("/com mcs ", "Opens the Mineplex Community Server of a community you manage", Rank.ALL, ChatColor.AQUA));
+ return;
+ }
+ Community c = Plugin.getLoadedCommunity(args[0]);
+ if (c == null)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That community was not found!"));
+ return;
+ }
+ if (c.getMembers().getOrDefault(caller.getUniqueId(), new CommunityMemberInfo(caller.getName(), caller.getUniqueId(), -1, CommunityRole.MEMBER, -1L)).Role.ordinal() > CommunityRole.COLEADER.ordinal())
+ {
+ if (!Managers.get(CoreClientManager.class).Get(caller).GetRank().has(Rank.ADMIN))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You are not a co-leader of " + F.name(c.getName()) + "!"));
+ return;
+ }
+ }
+
+ Managers.get(PersonalServerManager.class).hostCommunityServer(caller, c);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityMenuCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityMenuCommand.java
new file mode 100644
index 000000000..1e93f267e
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityMenuCommand.java
@@ -0,0 +1,22 @@
+package mineplex.core.communities.commands;
+
+import org.bukkit.entity.Player;
+
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.communities.gui.overview.CommunityOverviewPage;
+
+public class CommunityMenuCommand extends CommandBase
+{
+ public CommunityMenuCommand(CommunityManager plugin)
+ {
+ super(plugin, Rank.ALL, "menu");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ new CommunityOverviewPage(caller);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityRenameCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityRenameCommand.java
new file mode 100644
index 000000000..bfa1863bf
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityRenameCommand.java
@@ -0,0 +1,81 @@
+package mineplex.core.communities.commands;
+
+import java.util.Arrays;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+import mineplex.core.Managers;
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.chat.Chat;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.communities.CommunityMemberInfo;
+import mineplex.core.communities.CommunityRole;
+
+public class CommunityRenameCommand extends CommandBase
+{
+ public CommunityRenameCommand(CommunityManager plugin)
+ {
+ super(plugin, Rank.ETERNAL, "rename");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length < 2)
+ {
+ UtilPlayer.message(caller, F.help("/com rename ", "Changes the name of a community you own", Rank.ETERNAL, ChatColor.AQUA));
+ return;
+ }
+ Community c = Plugin.getLoadedCommunity(args[0]);
+ String newName = args[1];
+ if (c == null)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That community was not found!"));
+ return;
+ }
+ if (c.getMembers().getOrDefault(caller.getUniqueId(), new CommunityMemberInfo(caller.getName(), caller.getUniqueId(), -1, CommunityRole.MEMBER, -1L)).Role != CommunityRole.LEADER)
+ {
+ if (!Managers.get(CoreClientManager.class).Get(caller).GetRank().has(Rank.ADMIN))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You are not the leader of " + F.name(c.getName()) + "!"));
+ return;
+ }
+ }
+ if (Plugin.getLoadedCommunity(newName) != null)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "A community already exists with that name!"));
+ return;
+ }
+ if (newName.length() > 15 || Plugin.ALPHA_NUMERIC_PATTERN.matcher(newName).find())
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "A community name cannot be longer than 15 characters and must be alphanumeric!"));
+ return;
+ }
+ if (Arrays.asList(Plugin.BLOCKED_NAMES).contains(newName.toLowerCase()))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That name is not allowed!"));
+ return;
+ }
+ Plugin.runAsync(() ->
+ {
+ if (Managers.get(Chat.class).getFilteredMessage(caller, newName).contains("*"))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That name is not allowed!"));
+ }
+ else
+ {
+ if (!c.getMembers().containsKey(caller.getUniqueId()))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You have changed the name of " + F.name(c.getName()) + " to " + F.name(newName) + "!"));
+ }
+ Plugin.handleNameUpdate(caller, c, newName);
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityUnInviteCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityUnInviteCommand.java
new file mode 100644
index 000000000..99b5e9636
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/commands/CommunityUnInviteCommand.java
@@ -0,0 +1,49 @@
+package mineplex.core.communities.commands;
+
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+import mineplex.core.Managers;
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.communities.CommunityMemberInfo;
+import mineplex.core.communities.CommunityRole;
+
+public class CommunityUnInviteCommand extends CommandBase
+{
+ public CommunityUnInviteCommand(CommunityManager plugin)
+ {
+ super(plugin, Rank.ALL, "uninvite");
+ }
+
+ @Override
+ public void Execute(Player caller, String[] args)
+ {
+ if (args.length < 2)
+ {
+ UtilPlayer.message(caller, F.help("/com uninvite ", "Revokes a player's invitation to a community you manage", Rank.ALL, ChatColor.AQUA));
+ return;
+ }
+ String player = args[0];
+ Community c = Plugin.getLoadedCommunity(args[1]);
+ if (c == null)
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "That community was not found!"));
+ return;
+ }
+ if (c.getMembers().getOrDefault(caller.getUniqueId(), new CommunityMemberInfo(caller.getName(), caller.getUniqueId(), -1, CommunityRole.MEMBER, -1L)).Role.ordinal() > CommunityRole.COLEADER.ordinal())
+ {
+ if (!Managers.get(CoreClientManager.class).Get(caller).GetRank().has(Rank.ADMIN))
+ {
+ UtilPlayer.message(caller, F.main(Plugin.getName(), "You are not a co-leader of " + F.name(c.getName()) + "!"));
+ return;
+ }
+ }
+ Plugin.handleUninvite(caller, c, player);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/ActionButton.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/ActionButton.java
new file mode 100644
index 000000000..b7e1a94bc
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/ActionButton.java
@@ -0,0 +1,27 @@
+package mineplex.core.communities.gui;
+
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.inventory.ItemStack;
+
+import mineplex.core.common.util.Callback;
+
+public class ActionButton extends CommunitiesGUIButton
+{
+ private Callback _onClick;
+
+ public ActionButton(ItemStack icon, Callback onClick)
+ {
+ super(icon);
+
+ _onClick = onClick;
+ }
+
+ @Override
+ public void update() {}
+
+ @Override
+ public void handleClick(ClickType type)
+ {
+ _onClick.run(type);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/CommunitiesGUIButton.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/CommunitiesGUIButton.java
new file mode 100644
index 000000000..a18b7e1f2
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/CommunitiesGUIButton.java
@@ -0,0 +1,26 @@
+package mineplex.core.communities.gui;
+
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.inventory.ItemStack;
+
+import mineplex.core.Managers;
+import mineplex.core.communities.CommunityManager;
+
+public abstract class CommunitiesGUIButton
+{
+ public ItemStack Button = null;
+
+ public CommunitiesGUIButton(ItemStack button)
+ {
+ Button = button;
+ }
+
+ public static CommunityManager getCommunityManager()
+ {
+ return Managers.get(CommunityManager.class);
+ }
+
+ public abstract void update();
+
+ public abstract void handleClick(ClickType type);
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/CommunitiesGUIPage.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/CommunitiesGUIPage.java
new file mode 100644
index 000000000..15bdbaf82
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/CommunitiesGUIPage.java
@@ -0,0 +1,107 @@
+package mineplex.core.communities.gui;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.inventory.Inventory;
+
+import mineplex.core.Managers;
+import mineplex.core.common.util.UtilServer;
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.recharge.Recharge;
+import mineplex.core.updater.UpdateType;
+import mineplex.core.updater.event.UpdateEvent;
+
+public abstract class CommunitiesGUIPage implements Listener
+{
+ protected Player Viewer;
+ protected Inventory Inv;
+ protected Map Buttons = new HashMap<>();
+
+ public CommunitiesGUIPage(String name, int rows, Player viewer)
+ {
+ Viewer = viewer;
+ Inv = Bukkit.createInventory(viewer, 9 * rows, name);
+ }
+
+ private void disable()
+ {
+ HandlerList.unregisterAll(this);
+ }
+
+ public static CommunityManager getCommunityManager()
+ {
+ return Managers.get(CommunityManager.class);
+ }
+
+ public void open()
+ {
+ Viewer.openInventory(Inv);
+ UtilServer.RegisterEvents(this);
+ }
+
+ public void updateButtons(boolean callUpdate)
+ {
+ Inv.clear();
+ Buttons.entrySet().stream().forEach(entry ->
+ {
+ if (callUpdate)
+ {
+ entry.getValue().update();
+ }
+ Inv.setItem(entry.getKey(), entry.getValue().Button);
+ });
+ Viewer.updateInventory();
+ }
+
+ @EventHandler
+ public void onUpdate(UpdateEvent event)
+ {
+ if (event.getType() == UpdateType.TICK)
+ {
+ if (Viewer.getOpenInventory() == null || Viewer.getOpenInventory().getTopInventory() == null || !Viewer.getOpenInventory().getTopInventory().getTitle().equals(Inv.getTitle()))
+ {
+ disable();
+ return;
+ }
+ }
+ if (event.getType() == UpdateType.SEC_05)
+ {
+ Buttons.entrySet().forEach(entry ->
+ {
+ entry.getValue().update();
+ Inv.setItem(entry.getKey(), entry.getValue().Button);
+ });
+ }
+ }
+
+ @EventHandler
+ public void handleClick(InventoryClickEvent event)
+ {
+ if (event.getClickedInventory() == null || !event.getClickedInventory().getTitle().equals(Inv.getTitle()))
+ {
+ return;
+ }
+ if (!Viewer.getName().equals(event.getWhoClicked().getName()))
+ {
+ return;
+ }
+ event.setCancelled(true);
+ if (!Recharge.Instance.use(Viewer, "Communities Button Click", 500, false, false))
+ {
+ return;
+ }
+ Integer slot = event.getSlot();
+ if (!Buttons.containsKey(slot))
+ {
+ return;
+ }
+ Buttons.get(slot).handleClick(event.getClick());
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/browser/CommunityBrowserButton.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/browser/CommunityBrowserButton.java
new file mode 100644
index 000000000..e999b2a8f
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/browser/CommunityBrowserButton.java
@@ -0,0 +1,41 @@
+package mineplex.core.communities.gui.browser;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.inventory.ItemStack;
+
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.LineFormat;
+import mineplex.core.common.util.UtilText;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.gui.CommunitiesGUIButton;
+import mineplex.core.communities.gui.community.CommunityMembersPage;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunityBrowserButton extends CommunitiesGUIButton
+{
+ private Player _viewer;
+ private Community _community;
+
+ @SuppressWarnings("deprecation")
+ public CommunityBrowserButton(Player viewer, Community community)
+ {
+ super(new ItemBuilder(new ItemStack(community.getFavoriteGame().getMaterial(), 1, community.getFavoriteGame().getMaterialData(), null)).setTitle(C.cGreenB + community.getName()).addLore(UtilText.splitLinesToArray(new String[] {C.cRed, C.cYellow + "Members " + C.cWhite + community.getMembers().size(), C.cYellow + "Favorite Game " + C.cWhite + community.getFavoriteGame().getName(), C.cYellow + "Privacy " + C.cWhite + community.getPrivacySetting().getDisplayText(), C.cYellow + "Description " + C.cWhite + community.getDescription(), C.cBlue, C.cGreen + "Click to view community"}, LineFormat.LORE)).build());
+
+ _viewer = viewer;
+ _community = community;
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void update()
+ {
+ Button = new ItemBuilder(new ItemStack(_community.getFavoriteGame().getMaterial(), 1, _community.getFavoriteGame().getMaterialData(), null)).setTitle(C.cGreenB + _community.getName()).addLore(UtilText.splitLinesToArray(new String[] {C.cRed, C.cYellow + "Members " + C.cWhite + _community.getMembers().size(), C.cYellow + "Favorite Game " + C.cWhite + _community.getFavoriteGame().getName(), C.cYellow + "Privacy " + C.cWhite + _community.getPrivacySetting().getDisplayText(), C.cYellow + "Description " + C.cWhite + _community.getDescription(), C.cBlue, C.cGreen + "Click to view community"}, LineFormat.LORE)).build();
+ }
+
+ @Override
+ public void handleClick(ClickType type)
+ {
+ new CommunityMembersPage(_viewer, _community).open();
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/browser/CommunityBrowserPage.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/browser/CommunityBrowserPage.java
new file mode 100644
index 000000000..482a40142
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/browser/CommunityBrowserPage.java
@@ -0,0 +1,124 @@
+package mineplex.core.communities.gui.browser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+
+import mineplex.core.common.util.C;
+import mineplex.core.communities.CommunityBrowserUpdateEvent;
+import mineplex.core.communities.CommunityDisbandEvent;
+import mineplex.core.communities.gui.ActionButton;
+import mineplex.core.communities.gui.CommunitiesGUIPage;
+import mineplex.core.communities.gui.overview.CommunityInvitesPage;
+import mineplex.core.communities.gui.overview.CommunityOverviewPage;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunityBrowserPage extends CommunitiesGUIPage
+{
+ private static final int COMMUNITIES_PER_PAGE = 27;
+
+ private int _page = 1;
+
+ private List _displaying = new ArrayList<>();
+
+ //protected PrivacySetting PrivacyFilter = null;
+ //protected GameDisplay GameFilter = null;
+
+ public CommunityBrowserPage(Player viewer)
+ {
+ super("Community Browser", 6, viewer);
+
+ setup(1, true);
+ open();
+ }
+
+ private void setup(int page, boolean initial)
+ {
+ if (initial)
+ {
+ Buttons.clear();
+ Inv.clear();
+ }
+ {
+ //1
+ ActionButton communitiesButton = new ActionButton(new ItemBuilder(Material.EMERALD).setTitle(C.cGreenB + "Your Communities").build(), clickType ->
+ {
+ new CommunityOverviewPage(Viewer).open();
+ });
+ Buttons.put(1, communitiesButton);
+ Inv.setItem(1, communitiesButton.Button);
+ //4
+ ActionButton browserButton = new ActionButton(new ItemBuilder(Material.COMPASS).setTitle(C.cGreenB + "Browse Communities").build(), clickType -> {});
+ Buttons.put(4, browserButton);
+ Inv.setItem(4, browserButton.Button);
+ //7
+ ActionButton invitesButton = new ActionButton(new ItemBuilder(Material.PAPER).setTitle(C.cGreenB + "Community Invites").build(), clickType ->
+ {
+ new CommunityInvitesPage(Viewer);
+ });
+ Buttons.put(7, invitesButton);
+ Inv.setItem(7, invitesButton.Button);
+ }
+ {
+ ActionButton back = new ActionButton(new ItemBuilder(Material.ARROW).setTitle(C.cGreen + "Previous Page").build(), clickType ->
+ {
+ if (_page == 1)
+ {
+ return;
+ }
+ setup(_page - 1, false);
+ });
+ ActionButton next = new ActionButton(new ItemBuilder(Material.ARROW).setTitle(C.cGreen + "Next Page").build(), clickType ->
+ {
+ setup(_page + 1, false);
+ });
+ Buttons.put(45, back);
+ Inv.setItem(45, back.Button);
+ Buttons.put(53, next);
+ Inv.setItem(53, next.Button);
+ }
+
+ int slot = 18;
+ boolean cleared = false;
+ _displaying.clear();
+ for (int i = (page - 1) * COMMUNITIES_PER_PAGE; i < (page - 1) * COMMUNITIES_PER_PAGE + COMMUNITIES_PER_PAGE && i < getCommunityManager().BrowserIds.size(); i++)
+ {
+ if (!cleared && !initial)
+ {
+ cleared = true;
+ _page = page;
+ for (int clear = 18; clear < 45; clear++)
+ {
+ Buttons.remove(clear);
+ Inv.setItem(clear, null);
+ }
+ }
+ CommunityBrowserButton button = new CommunityBrowserButton(Viewer, getCommunityManager().getLoadedCommunity(getCommunityManager().BrowserIds.get(i)));
+ _displaying.add(getCommunityManager().BrowserIds.get(i));
+ Buttons.put(slot, button);
+ Inv.setItem(slot, button.Button);
+
+ slot++;
+ }
+
+ Viewer.updateInventory();
+ }
+
+ @EventHandler
+ public void onBrowserUpdate(CommunityBrowserUpdateEvent event)
+ {
+ setup(1, true);
+ }
+
+ @EventHandler
+ public void onCommunityDisband(CommunityDisbandEvent event)
+ {
+ if (_displaying.contains(event.getCommunity().getId()))
+ {
+ setup(1, true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityButton.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityButton.java
new file mode 100644
index 000000000..ee5696f5a
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityButton.java
@@ -0,0 +1,99 @@
+package mineplex.core.communities.gui.community;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.inventory.ItemStack;
+
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.LineFormat;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.common.util.UtilText;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.Community.PrivacySetting;
+import mineplex.core.communities.CommunityRole;
+import mineplex.core.communities.gui.CommunitiesGUIButton;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunityButton extends CommunitiesGUIButton
+{
+ private Player _viewer;
+ private Community _community;
+
+ public CommunityButton(Player viewer, Community community)
+ {
+ super(getDisplay(community, viewer));
+
+ _viewer = viewer;
+ _community = community;
+ }
+
+ private static ItemStack getDisplay(Community community, Player viewer)
+ {
+ ItemStack item = new ItemBuilder(Material.REDSTONE_BLOCK).setTitle(C.cGreenB + community.getName()).addLore(UtilText.splitLinesToArray(new String[] {C.cGreen, C.cYellow + "Members " + C.cWhite + community.getMembers().size(), C.cYellow + "Description " + C.cWhite + community.getDescription(), C.cRed, C.cYellow + "Shift-Left Click " + C.cWhite + "Request To Join"}, LineFormat.LORE)).build();
+
+ if (community.getMembers().containsKey(viewer.getUniqueId()))
+ {
+ ItemBuilder builder = new ItemBuilder(Material.EMERALD_BLOCK).setTitle(C.cGreenB + community.getName()).addLore(UtilText.splitLinesToArray(new String[] {C.cGreen, C.cYellow + "Members " + C.cWhite + community.getMembers().size(), C.cYellow + "Description " + C.cWhite + community.getDescription(), C.cRed, C.cYellow + "Shift-Left Click " + C.cWhite + "Leave Community"}, LineFormat.LORE));
+ if (community.getMembers().get(viewer.getUniqueId()).Role == CommunityRole.LEADER)
+ {
+ builder.addLore(C.cBlue);
+ builder.addLore(UtilText.splitLineToArray(C.cGray + "Use " + C.cYellow + "/com disband " + community.getName() + C.cGray + " to disband!", LineFormat.LORE));
+ }
+ item = builder.build();
+ }
+ else if (community.getJoinRequests().containsKey(viewer.getUniqueId()))
+ {
+ item = new ItemBuilder(Material.REDSTONE_BLOCK).setTitle(C.cGold + community.getName()).addLore(UtilText.splitLinesToArray(new String[] {C.cGreen, C.cYellow + "Members " + C.cWhite + community.getMembers().size(), C.cYellow + "Description " + C.cWhite + community.getDescription(), C.cRed, C.cYellow + "Shift-Left Click " + C.cWhite + "Cancel Join Request"}, LineFormat.LORE)).build();
+ }
+ else if (getCommunityManager().Get(viewer).Invites.contains(community.getId()) || community.getPrivacySetting() == PrivacySetting.OPEN)
+ {
+ item = new ItemBuilder(Material.REDSTONE_BLOCK).setTitle(C.cGold + community.getName()).addLore(UtilText.splitLinesToArray(new String[] {C.cGreen, C.cYellow + "Members " + C.cWhite + community.getMembers().size(), C.cYellow + "Description " + C.cWhite + community.getDescription(), C.cRed, C.cYellow + "Shift-Left Click " + C.cWhite + "Join Community"}, LineFormat.LORE)).build();
+ }
+ else if (community.getPrivacySetting() == PrivacySetting.PRIVATE)
+ {
+ item = new ItemBuilder(Material.REDSTONE_BLOCK).setTitle(C.cGreenB + community.getName()).addLore(UtilText.splitLinesToArray(new String[] {C.cGreen, C.cYellow + "Members " + C.cWhite + community.getMembers().size(), C.cYellow + "Description " + C.cWhite + community.getDescription(), C.cRed, C.cRed + "Closed"}, LineFormat.LORE)).build();
+ }
+
+ return item;
+ }
+
+ @Override
+ public void update()
+ {
+ Button = getDisplay(_community, _viewer);
+ }
+
+ @Override
+ public void handleClick(ClickType type)
+ {
+ if (type == ClickType.SHIFT_LEFT)
+ {
+ if (_community.getMembers().containsKey(_viewer.getUniqueId()))
+ {
+ if (_community.getMembers().get(_viewer.getUniqueId()).Role == CommunityRole.LEADER)
+ {
+ UtilPlayer.message(_viewer, F.main(getCommunityManager().getName(), "You cannot leave " + F.name(_community.getName()) + " without passing on leadership first! If you want to disband your community, type " + F.elem("/com disband " + _community.getName()) + "!"));
+ return;
+ }
+ getCommunityManager().handleLeave(_viewer, _community, _community.getMembers().get(_viewer.getUniqueId()));
+ }
+ else if (_community.getJoinRequests().containsKey(_viewer.getUniqueId()))
+ {
+ getCommunityManager().handleCloseJoinRequest(_viewer, _community, _community.getJoinRequests().get(_viewer.getUniqueId()), false);
+ }
+ else if (getCommunityManager().Get(_viewer).Invites.contains(_community.getId()) || _community.getPrivacySetting() == PrivacySetting.OPEN)
+ {
+ getCommunityManager().handleJoin(_viewer, _community, getCommunityManager().Get(_viewer).Invites.contains(_community.getId()));
+ }
+ else
+ {
+ if (_community.getPrivacySetting() != PrivacySetting.PRIVATE)
+ {
+ getCommunityManager().handleJoinRequest(_viewer, _community);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityChatReadingButton.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityChatReadingButton.java
new file mode 100644
index 000000000..38382123a
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityChatReadingButton.java
@@ -0,0 +1,47 @@
+package mineplex.core.communities.gui.community;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.inventory.ItemStack;
+
+import mineplex.core.common.util.C;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.gui.CommunitiesGUIButton;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunityChatReadingButton extends CommunitiesGUIButton
+{
+ private Player _viewer;
+ private Community _community;
+
+ public CommunityChatReadingButton(Player viewer, Community community)
+ {
+ super(getDisplay(community, viewer));
+
+ _viewer = viewer;
+ _community = community;
+ }
+
+ private static ItemStack getDisplay(Community community, Player viewer)
+ {
+ ItemStack item = new ItemBuilder(Material.BOOK_AND_QUILL).setTitle(C.cGreenB + "Toggle Chat Visibility").build();
+
+ return item;
+ }
+
+ @Override
+ public void update()
+ {
+ Button = getDisplay(_community, _viewer);
+ }
+
+ @Override
+ public void handleClick(ClickType type)
+ {
+ if (_community.getMembers().containsKey(_viewer.getUniqueId()))
+ {
+ getCommunityManager().handleToggleReadingChat(_viewer, _community);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityJoinRequestButton.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityJoinRequestButton.java
new file mode 100644
index 000000000..ad9af1d6e
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityJoinRequestButton.java
@@ -0,0 +1,50 @@
+package mineplex.core.communities.gui.community;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityJoinRequestInfo;
+import mineplex.core.communities.CommunityRole;
+import mineplex.core.communities.gui.CommunitiesGUIButton;
+
+public class CommunityJoinRequestButton extends CommunitiesGUIButton
+{
+ private Player _viewer;
+ private Community _community;
+ private CommunityJoinRequestInfo _info;
+
+ public CommunityJoinRequestButton(Player viewer, Community community, CommunityJoinRequestInfo info)
+ {
+ super(info.getRepresentation());
+
+ _viewer = viewer;
+ _community = community;
+ _info = info;
+ }
+
+ @Override
+ public void update()
+ {
+ Button = _info.getRepresentation();
+ }
+
+ @Override
+ public void handleClick(ClickType type)
+ {
+ if (type == ClickType.LEFT)
+ {
+ if (getCommunityManager().Get(_viewer).getRoleIn(_community) != null && getCommunityManager().Get(_viewer).getRoleIn(_community).ordinal() <= CommunityRole.COLEADER.ordinal())
+ {
+ getCommunityManager().handleInvite(_viewer, _community, _info.Name);
+ }
+ }
+ if (type == ClickType.SHIFT_RIGHT)
+ {
+ if (getCommunityManager().Get(_viewer).getRoleIn(_community) != null && getCommunityManager().Get(_viewer).getRoleIn(_community).ordinal() <= CommunityRole.COLEADER.ordinal())
+ {
+ getCommunityManager().handleCloseJoinRequest(_viewer, _community, _info, true);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityJoinRequestsPage.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityJoinRequestsPage.java
new file mode 100644
index 000000000..1c5c69c92
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityJoinRequestsPage.java
@@ -0,0 +1,184 @@
+package mineplex.core.communities.gui.community;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+
+import mineplex.core.common.util.C;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityDisbandEvent;
+import mineplex.core.communities.CommunityJoinRequestInfo;
+import mineplex.core.communities.CommunityJoinRequestsUpdateEvent;
+import mineplex.core.communities.CommunityMemberDataUpdateEvent;
+import mineplex.core.communities.CommunityMembershipUpdateEvent;
+import mineplex.core.communities.CommunityRole;
+import mineplex.core.communities.gui.ActionButton;
+import mineplex.core.communities.gui.CommunitiesGUIPage;
+import mineplex.core.communities.gui.overview.CommunityOverviewPage;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunityJoinRequestsPage extends CommunitiesGUIPage
+{
+ private static final int REQUESTS_PER_PAGE = 27;
+
+ private Community _community;
+ private int _page = 1;
+
+ public CommunityJoinRequestsPage(Player viewer, Community community)
+ {
+ super(community.getName() + C.cBlack, 6, viewer);
+ _community = community;
+
+ setup(1, true);
+ open();
+ }
+
+ private void setup(int page, boolean initial)
+ {
+ if (initial)
+ {
+ Buttons.clear();
+ Inv.clear();
+ }
+ {
+ //0
+ ActionButton membersButton = new ActionButton(new ItemBuilder(Material.SKULL_ITEM).setData((short)3).setTitle(C.cGreenB + "Members").build(), clickType ->
+ {
+ new CommunityMembersPage(Viewer, _community).open();
+ });
+ Buttons.put(0, membersButton);
+ Inv.setItem(0, membersButton.Button);
+ //4
+ CommunityButton communityButton = new CommunityButton(Viewer, _community);
+ Buttons.put(4, communityButton);
+ Inv.setItem(4, communityButton.Button);
+ //8
+ ActionButton returnButton = new ActionButton(new ItemBuilder(Material.BED).setTitle(C.cGray + "\u21FD Go Back").build(), clickType ->
+ {
+ new CommunityOverviewPage(Viewer).open();
+ });
+ Buttons.put(8, returnButton);
+ Inv.setItem(8, returnButton.Button);
+ //CoLeader+
+ if (_community.getMembers().containsKey(Viewer.getUniqueId()) && _community.getMembers().get(Viewer.getUniqueId()).Role.ordinal() <= CommunityRole.COLEADER.ordinal())
+ {
+ ActionButton requestsButton = new ActionButton(new ItemBuilder(Material.PAPER).setTitle(C.cGreenB + "Join Requests").build(), clickType -> {});
+ Buttons.put(2, requestsButton);
+ Inv.setItem(2, requestsButton.Button);
+ ActionButton settingsButton = new ActionButton(new ItemBuilder(Material.REDSTONE_COMPARATOR).setTitle(C.cGreenB + "Community Settings").build(), clickType ->
+ {
+ new CommunitySettingsPage(Viewer, _community);
+ });
+ Buttons.put(6, settingsButton);
+ Inv.setItem(6, settingsButton.Button);
+ }
+ else if (_community.getMembers().containsKey(Viewer.getUniqueId()))
+ {
+ CommunityChatReadingButton chatButton = new CommunityChatReadingButton(Viewer, _community);
+ Buttons.put(6, chatButton);
+ Inv.setItem(6, chatButton.Button);
+ }
+ }
+ {
+ ActionButton back = new ActionButton(new ItemBuilder(Material.ARROW).setTitle(C.cGreen + "Previous Page").build(), clickType ->
+ {
+ if (_page == 1)
+ {
+ return;
+ }
+ setup(_page - 1, false);
+ });
+ ActionButton next = new ActionButton(new ItemBuilder(Material.ARROW).setTitle(C.cGreen + "Next Page").build(), clickType ->
+ {
+ setup(_page + 1, false);
+ });
+ Buttons.put(45, back);
+ Inv.setItem(45, back.Button);
+ Buttons.put(53, next);
+ Inv.setItem(53, next.Button);
+ }
+ List requests = new LinkedList<>();
+ for (CommunityJoinRequestInfo info : _community.getJoinRequests().values())
+ {
+ requests.add(info);
+ }
+ requests.sort((info1, info2) ->
+ {
+ return info1.Name.compareToIgnoreCase(info2.Name);
+ });
+
+ int slot = 18;
+ boolean cleared = false;
+ for (int i = (page - 1) * REQUESTS_PER_PAGE; i < (page - 1) * REQUESTS_PER_PAGE + REQUESTS_PER_PAGE && i < requests.size(); i++)
+ {
+ if (!cleared && !initial)
+ {
+ cleared = true;
+ _page = page;
+ for (int clear = 18; clear < 45; clear++)
+ {
+ Buttons.remove(clear);
+ Inv.setItem(clear, null);
+ }
+ }
+ CommunityJoinRequestButton button = new CommunityJoinRequestButton(Viewer, _community, requests.get(i));
+ Buttons.put(slot, button);
+ Inv.setItem(slot, button.Button);
+
+ slot++;
+ }
+
+ Viewer.updateInventory();
+ }
+
+ @EventHandler
+ public void onMembershipUpdate(CommunityMembershipUpdateEvent event)
+ {
+ if (event.getCommunity().getId().intValue() != _community.getId().intValue())
+ {
+ return;
+ }
+
+ if (_community.getMembers().containsKey(Viewer.getUniqueId()) && _community.getMembers().get(Viewer.getUniqueId()).Role.ordinal() <= CommunityRole.COLEADER.ordinal())
+ {
+ setup(1, true);
+ }
+ else
+ {
+ new CommunityMembersPage(Viewer, _community).open();
+ }
+ }
+
+ @EventHandler
+ public void onRequestsUpdate(CommunityJoinRequestsUpdateEvent event)
+ {
+ if (event.getCommunity().getId().intValue() != _community.getId().intValue())
+ {
+ return;
+ }
+ setup(1, true);
+ }
+
+ @EventHandler
+ public void onCommunityDisband(CommunityDisbandEvent event)
+ {
+ if (_community.getId().intValue() == event.getCommunity().getId().intValue())
+ {
+ Viewer.closeInventory();
+ }
+ }
+
+ @EventHandler
+ public void onMembershipUpdate(CommunityMemberDataUpdateEvent event)
+ {
+ if (!event.getPlayer().getUniqueId().toString().equalsIgnoreCase(Viewer.getUniqueId().toString()))
+ {
+ return;
+ }
+
+ setup(1, true);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityMemberButton.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityMemberButton.java
new file mode 100644
index 000000000..79f2fd375
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityMemberButton.java
@@ -0,0 +1,80 @@
+package mineplex.core.communities.gui.community;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import mineplex.core.Managers;
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityMemberInfo;
+import mineplex.core.communities.CommunityRole;
+import mineplex.core.communities.gui.CommunitiesGUIButton;
+
+public class CommunityMemberButton extends CommunitiesGUIButton
+{
+ private Player _viewer;
+ private Community _community;
+ private CommunityMemberInfo _info;
+
+ public CommunityMemberButton(Player viewer, Community community, CommunityMemberInfo info)
+ {
+ super(info.getRepresentation(getCommunityManager().Get(viewer).getRoleIn(community)));
+
+ _viewer = viewer;
+ _community = community;
+ _info = info;
+ }
+
+ @Override
+ public void update()
+ {
+ Button = _info.getRepresentation(getCommunityManager().Get(_viewer).getRoleIn(_community));
+ }
+
+ @Override
+ public void handleClick(ClickType type)
+ {
+ if (type == ClickType.SHIFT_RIGHT)
+ {
+ if (getCommunityManager().Get(_viewer).getRoleIn(_community) != null && getCommunityManager().Get(_viewer).getRoleIn(_community).ordinal() < _info.Role.ordinal())
+ {
+ getCommunityManager().handleKick(_viewer, _community, _info);
+ }
+ }
+ if (type == ClickType.LEFT || type == ClickType.SHIFT_LEFT)
+ {
+ if (getCommunityManager().Get(_viewer).getRoleIn(_community) != null && getCommunityManager().Get(_viewer).getRoleIn(_community) == CommunityRole.LEADER && _info.Role != CommunityRole.LEADER)
+ {
+ if (_info.Role == CommunityRole.MEMBER)
+ {
+ getCommunityManager().handleRoleUpdate(_viewer, _community, _info, CommunityRole.COLEADER);
+ }
+ if (_info.Role == CommunityRole.COLEADER && type == ClickType.SHIFT_LEFT)
+ {
+ if (_info.OwnsCommunity)
+ {
+ UtilPlayer.message(_viewer, F.main(getCommunityManager().getName(), F.name(_info.Name) + " can only own one community at a time!"));
+ return;
+ }
+ if (!Rank.valueOf(Managers.get(CoreClientManager.class).loadOfflineClient(_info.UUID).Rank).has(Rank.ETERNAL))
+ {
+ UtilPlayer.message(_viewer, F.main(getCommunityManager().getName(), "Only Eternal rank and above can own a community!"));
+ return;
+ }
+ getCommunityManager().handleRoleUpdate(_viewer, _community, _info, CommunityRole.LEADER);
+ getCommunityManager().handleRoleUpdate(_viewer, _community, _community.getMembers().get(_viewer.getUniqueId()), CommunityRole.COLEADER);
+ }
+ }
+ }
+ if (type == ClickType.RIGHT)
+ {
+ if (getCommunityManager().Get(_viewer).getRoleIn(_community) != null && getCommunityManager().Get(_viewer).getRoleIn(_community) == CommunityRole.LEADER && _info.Role == CommunityRole.COLEADER)
+ {
+ getCommunityManager().handleRoleUpdate(_viewer, _community, _info, CommunityRole.MEMBER);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityMembersPage.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityMembersPage.java
new file mode 100644
index 000000000..347312750
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunityMembersPage.java
@@ -0,0 +1,175 @@
+package mineplex.core.communities.gui.community;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+
+import mineplex.core.common.util.C;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityDisbandEvent;
+import mineplex.core.communities.CommunityMemberDataUpdateEvent;
+import mineplex.core.communities.CommunityMemberInfo;
+import mineplex.core.communities.CommunityMembershipUpdateEvent;
+import mineplex.core.communities.CommunityRole;
+import mineplex.core.communities.gui.ActionButton;
+import mineplex.core.communities.gui.CommunitiesGUIPage;
+import mineplex.core.communities.gui.overview.CommunityOverviewPage;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunityMembersPage extends CommunitiesGUIPage
+{
+ private static final int MEMBERS_PER_PAGE = 27;
+
+ private Community _community;
+ private int _page = 1;
+
+ public CommunityMembersPage(Player viewer, Community community)
+ {
+ super(community.getName() + C.cAqua, 6, viewer);
+ _community = community;
+
+ setup(1, true);
+ open();
+ }
+
+ private void setup(int page, boolean initial)
+ {
+ if (initial)
+ {
+ Buttons.clear();
+ Inv.clear();
+ }
+ {
+ //0
+ ActionButton membersButton = new ActionButton(new ItemBuilder(Material.SKULL_ITEM).setData((short)3).setTitle(C.cGreenB + "Members").build(), clickType -> {});
+ Buttons.put(0, membersButton);
+ Inv.setItem(0, membersButton.Button);
+ //4
+ CommunityButton communityButton = new CommunityButton(Viewer, _community);
+ Buttons.put(4, communityButton);
+ Inv.setItem(4, communityButton.Button);
+ //8
+ ActionButton returnButton = new ActionButton(new ItemBuilder(Material.BED).setTitle(C.cGray + "\u21FD Go Back").build(), clickType ->
+ {
+ new CommunityOverviewPage(Viewer).open();
+ });
+ Buttons.put(8, returnButton);
+ Inv.setItem(8, returnButton.Button);
+ //CoLeader+
+ if (_community.getMembers().containsKey(Viewer.getUniqueId()) && _community.getMembers().get(Viewer.getUniqueId()).Role.ordinal() <= CommunityRole.COLEADER.ordinal())
+ {
+ ActionButton requestsButton = new ActionButton(new ItemBuilder(Material.PAPER).setTitle(C.cGreenB + "Join Requests").build(), clickType ->
+ {
+ new CommunityJoinRequestsPage(Viewer, _community).open();
+ });
+ Buttons.put(2, requestsButton);
+ Inv.setItem(2, requestsButton.Button);
+ ActionButton settingsButton = new ActionButton(new ItemBuilder(Material.REDSTONE_COMPARATOR).setTitle(C.cGreenB + "Community Settings").build(), clickType ->
+ {
+ new CommunitySettingsPage(Viewer, _community);
+ });
+ Buttons.put(6, settingsButton);
+ Inv.setItem(6, settingsButton.Button);
+ }
+ else if (_community.getMembers().containsKey(Viewer.getUniqueId()))
+ {
+ CommunityChatReadingButton chatButton = new CommunityChatReadingButton(Viewer, _community);
+ Buttons.put(6, chatButton);
+ Inv.setItem(6, chatButton.Button);
+ }
+ }
+ {
+ ActionButton back = new ActionButton(new ItemBuilder(Material.ARROW).setTitle(C.cGreen + "Previous Page").build(), clickType ->
+ {
+ if (_page == 1)
+ {
+ return;
+ }
+ setup(_page - 1, false);
+ });
+ ActionButton next = new ActionButton(new ItemBuilder(Material.ARROW).setTitle(C.cGreen + "Next Page").build(), clickType ->
+ {
+ setup(_page + 1, false);
+ });
+ Buttons.put(45, back);
+ Inv.setItem(45, back.Button);
+ Buttons.put(53, next);
+ Inv.setItem(53, next.Button);
+ }
+ List members = new LinkedList<>();
+ for (CommunityMemberInfo info : _community.getMembers().values())
+ {
+ members.add(info);
+ }
+ members.sort((info1, info2) ->
+ {
+ if (info1.isOnline() == info2.isOnline())
+ {
+ return info1.Name.compareToIgnoreCase(info2.Name);
+ }
+
+ if (info1.isOnline())
+ {
+ return -1;
+ }
+ return 1;
+ });
+
+ int slot = 18;
+ boolean cleared = false;
+ for (int i = (page - 1) * MEMBERS_PER_PAGE; i < (page - 1) * MEMBERS_PER_PAGE + MEMBERS_PER_PAGE && i < members.size(); i++)
+ {
+ if (!cleared && !initial)
+ {
+ cleared = true;
+ _page = page;
+ for (int clear = 18; clear < 45; clear++)
+ {
+ Buttons.remove(clear);
+ Inv.setItem(clear, null);
+ }
+ }
+ CommunityMemberButton button = new CommunityMemberButton(Viewer, _community, members.get(i));
+ Buttons.put(slot, button);
+ Inv.setItem(slot, button.Button);
+
+ slot++;
+ }
+
+ Viewer.updateInventory();
+ }
+
+ @EventHandler
+ public void onMembershipUpdate(CommunityMembershipUpdateEvent event)
+ {
+ if (event.getCommunity().getId().intValue() != _community.getId().intValue())
+ {
+ return;
+ }
+
+ setup(1, true);
+ }
+
+ @EventHandler
+ public void onCommunityDisband(CommunityDisbandEvent event)
+ {
+ if (_community.getId().intValue() == event.getCommunity().getId().intValue())
+ {
+ Viewer.closeInventory();
+ }
+ }
+
+ @EventHandler
+ public void onMembershipUpdate(CommunityMemberDataUpdateEvent event)
+ {
+ if (!event.getPlayer().getUniqueId().toString().equalsIgnoreCase(Viewer.getUniqueId().toString()))
+ {
+ return;
+ }
+
+ setup(1, true);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunitySettingButton.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunitySettingButton.java
new file mode 100644
index 000000000..27a9bee13
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunitySettingButton.java
@@ -0,0 +1,258 @@
+package mineplex.core.communities.gui.community;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.bukkit.ChatColor;
+import org.bukkit.DyeColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.material.MaterialData;
+
+import mineplex.core.common.util.C;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.Community.PrivacySetting;
+import mineplex.core.communities.CommunityRole;
+import mineplex.core.communities.CommunitySetting;
+import mineplex.core.communities.gui.CommunitiesGUIButton;
+import mineplex.core.game.GameDisplay;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunitySettingButton extends CommunitiesGUIButton
+{
+ @SuppressWarnings("serial")
+ private static final Map COLOR_MAP = new HashMap()
+ {
+ {
+ put(ChatColor.AQUA, DyeColor.CYAN);
+ put(ChatColor.BLACK, DyeColor.BLACK);
+ put(ChatColor.BLUE, DyeColor.LIGHT_BLUE);
+ put(ChatColor.DARK_AQUA, DyeColor.CYAN);
+ put(ChatColor.DARK_BLUE, DyeColor.BLUE);
+ put(ChatColor.DARK_GRAY, DyeColor.GRAY);
+ put(ChatColor.DARK_GREEN, DyeColor.GREEN);
+ put(ChatColor.DARK_PURPLE, DyeColor.PURPLE);
+ put(ChatColor.DARK_RED, DyeColor.RED);
+ put(ChatColor.GOLD, DyeColor.YELLOW);
+ put(ChatColor.GRAY, DyeColor.SILVER);
+ put(ChatColor.GREEN, DyeColor.LIME);
+ put(ChatColor.LIGHT_PURPLE, DyeColor.PINK);
+ put(ChatColor.RED, DyeColor.RED);
+ put(ChatColor.WHITE, DyeColor.WHITE);
+ put(ChatColor.YELLOW, DyeColor.YELLOW);
+ }
+ };
+ @SuppressWarnings("serial")
+ private static final Map COLOR_NAME_MAP = new HashMap()
+ {
+ {
+ put(ChatColor.AQUA, "Aqua");
+ put(ChatColor.BLACK, "Black");
+ put(ChatColor.BLUE, "Blue");
+ put(ChatColor.DARK_AQUA, "Cyan");
+ put(ChatColor.DARK_BLUE, "Dark Blue");
+ put(ChatColor.DARK_GRAY, "Dark Gray");
+ put(ChatColor.DARK_GREEN, "Dark Green");
+ put(ChatColor.DARK_PURPLE, "Purple");
+ put(ChatColor.DARK_RED, "Dark Red");
+ put(ChatColor.GOLD, "Gold");
+ put(ChatColor.GRAY, "Gray");
+ put(ChatColor.GREEN, "Green");
+ put(ChatColor.LIGHT_PURPLE, "Pink");
+ put(ChatColor.RED, "Red");
+ put(ChatColor.WHITE, "White");
+ put(ChatColor.YELLOW, "Yellow");
+ }
+ };
+
+ private Player _viewer;
+ private Community _community;
+ private CommunitySetting _setting;
+
+ public CommunitySettingButton(Player viewer, Community community, CommunitySetting setting)
+ {
+ super(new ItemBuilder(Material.BARRIER).build());
+
+ _viewer = viewer;
+ _community = community;
+ _setting = setting;
+ update();
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void update()
+ {
+ if (_setting == CommunitySetting.FAVORITE_GAME)
+ {
+ Button = new ItemBuilder(new ItemStack(_community.getFavoriteGame().getMaterial(), 1, _community.getFavoriteGame().getMaterialData(), null)).setTitle(C.cGreenB + "Favorite Game").addLore(C.cWhite + _community.getFavoriteGame().getName(), C.cRed, C.cYellow + "Left Click " + C.cWhite + "Next Game", C.cYellow + "Right Click " + C.cWhite + "Previous Game").build();
+ }
+ else if (_setting == CommunitySetting.PRIVACY)
+ {
+ Button = new ItemBuilder(Material.DARK_OAK_DOOR_ITEM).setTitle(C.cGreenB + "Privacy").addLore(C.cWhite + _community.getPrivacySetting().getDisplayText(), C.cRed, C.cYellow + "Left Click " + C.cWhite + "Next Privacy Setting", C.cYellow + "Right Click " + C.cWhite + "Previous Privacy Setting").build();
+ }
+ else if (_setting == CommunitySetting.CHAT_DELAY)
+ {
+ Button = new ItemBuilder(Material.PAPER).setTitle(C.cGreenB + "Chat Delay").addLore(C.cWhite + (_community.getChatDelay() == 0 ? "No Delay" : _community.getChatDelay() / 1000 + " Second(s)"), C.cRed, C.cYellow + "Left Click " + C.cWhite + "Next Delay Setting", C.cYellow + "Right Click " + C.cWhite + "Previous Delay Setting").build();
+ }
+ else if (_setting == CommunitySetting.CHAT_NAME_COLOR)
+ {
+ ItemStack base = new MaterialData(Material.WOOL, COLOR_MAP.get(_community.getChatFormatting()[0]).getWoolData()).toItemStack(1);
+ Button = new ItemBuilder(base).setTitle(C.cGreenB + "Chat Community Color").addLore(C.cWhite + COLOR_NAME_MAP.get(_community.getChatFormatting()[0]), C.cRed, C.cYellow + "Left Click " + C.cWhite + "Next Color", C.cYellow + "Right Click " + C.cWhite + "Previous Color").build();
+ }
+ else if (_setting == CommunitySetting.CHAT_PLAYER_COLOR)
+ {
+ ItemStack base = new MaterialData(Material.WOOL, COLOR_MAP.get(_community.getChatFormatting()[1]).getWoolData()).toItemStack(1);
+ Button = new ItemBuilder(base).setTitle(C.cGreenB + "Chat Player Color").addLore(C.cWhite + COLOR_NAME_MAP.get(_community.getChatFormatting()[1]), C.cRed, C.cYellow + "Left Click " + C.cWhite + "Next Color", C.cYellow + "Right Click " + C.cWhite + "Previous Color").build();
+ }
+ else if (_setting == CommunitySetting.CHAT_MESSAGE_COLOR)
+ {
+ ItemStack base = new MaterialData(Material.WOOL, COLOR_MAP.get(_community.getChatFormatting()[2]).getWoolData()).toItemStack(1);
+ Button = new ItemBuilder(base).setTitle(C.cGreenB + "Chat Message Color").addLore(C.cWhite + COLOR_NAME_MAP.get(_community.getChatFormatting()[2]), C.cRed, C.cYellow + "Left Click " + C.cWhite + "Next Color", C.cYellow + "Right Click " + C.cWhite + "Previous Color").build();
+ }
+ }
+
+ @Override
+ public void handleClick(ClickType type)
+ {
+ if (type == ClickType.LEFT)
+ {
+ if (getCommunityManager().Get(_viewer).getRoleIn(_community) != null && getCommunityManager().Get(_viewer).getRoleIn(_community).ordinal() <= CommunityRole.COLEADER.ordinal())
+ {
+ String[] valueArray = new String[] {};
+ int index = 0;
+
+ if (_setting == CommunitySetting.FAVORITE_GAME)
+ {
+ GameDisplay[] games = Arrays.asList(GameDisplay.values()).stream().filter(display -> display.isCommunityFavoriteOption()).toArray(size -> new GameDisplay[size]);
+ valueArray = new String[games.length];
+ for (int i = 0; i < games.length; i++)
+ {
+ valueArray[i] = games[i].getName();
+ }
+
+ index = Arrays.asList(valueArray).indexOf(_community.getFavoriteGame().getName());
+ }
+ else if (_setting == CommunitySetting.PRIVACY)
+ {
+ valueArray = new String[] {PrivacySetting.OPEN.toString(), PrivacySetting.RECRUITING.toString(), PrivacySetting.PRIVATE.toString()};
+
+ index = Arrays.asList(valueArray).indexOf(_community.getPrivacySetting().toString());
+ }
+ else if (_setting == CommunitySetting.CHAT_DELAY)
+ {
+ valueArray = new String[] {1000L + "", 3000L + "", 5000L + ""};
+
+ index = Arrays.asList(valueArray).indexOf(_community.getChatDelay().toString());
+ }
+ else if (_setting == CommunitySetting.CHAT_NAME_COLOR)
+ {
+ ChatColor[] colors = COLOR_MAP.keySet().toArray(new ChatColor[COLOR_MAP.size()]);
+ valueArray = new String[colors.length];
+ for (int i = 0; i < colors.length; i++)
+ {
+ valueArray[i] = colors[i].name();
+ }
+
+ index = Arrays.asList(valueArray).indexOf(_community.getChatFormatting()[0].name());
+ }
+ else if (_setting == CommunitySetting.CHAT_PLAYER_COLOR)
+ {
+ ChatColor[] colors = COLOR_MAP.keySet().toArray(new ChatColor[COLOR_MAP.size()]);
+ valueArray = new String[colors.length];
+ for (int i = 0; i < colors.length; i++)
+ {
+ valueArray[i] = colors[i].name();
+ }
+
+ index = Arrays.asList(valueArray).indexOf(_community.getChatFormatting()[1].name());
+ }
+ else if (_setting == CommunitySetting.CHAT_MESSAGE_COLOR)
+ {
+ ChatColor[] colors = COLOR_MAP.keySet().toArray(new ChatColor[COLOR_MAP.size()]);
+ valueArray = new String[colors.length];
+ for (int i = 0; i < colors.length; i++)
+ {
+ valueArray[i] = colors[i].name();
+ }
+
+ index = Arrays.asList(valueArray).indexOf(_community.getChatFormatting()[2].name());
+ }
+
+ int newIndex = (index + 1 >= valueArray.length) ? 0 : (index + 1);
+ getCommunityManager().handleSettingUpdate(_viewer, _community, _setting, valueArray[newIndex]);
+ }
+ }
+ if (type == ClickType.RIGHT)
+ {
+ if (getCommunityManager().Get(_viewer).getRoleIn(_community) != null && getCommunityManager().Get(_viewer).getRoleIn(_community).ordinal() <= CommunityRole.COLEADER.ordinal())
+ {
+ String[] valueArray = new String[] {};
+ int index = 0;
+
+ if (_setting == CommunitySetting.FAVORITE_GAME)
+ {
+ GameDisplay[] games = Arrays.asList(GameDisplay.values()).stream().filter(display -> display.isCommunityFavoriteOption()).toArray(size -> new GameDisplay[size]);
+ valueArray = new String[games.length];
+ for (int i = 0; i < games.length; i++)
+ {
+ valueArray[i] = games[i].getName();
+ }
+
+ index = Arrays.asList(valueArray).indexOf(_community.getFavoriteGame().getName());
+ }
+ else if (_setting == CommunitySetting.PRIVACY)
+ {
+ valueArray = new String[] {PrivacySetting.OPEN.toString(), PrivacySetting.RECRUITING.toString(), PrivacySetting.PRIVATE.toString()};
+
+ index = Arrays.asList(valueArray).indexOf(_community.getPrivacySetting().toString());
+ }
+ else if (_setting == CommunitySetting.CHAT_DELAY)
+ {
+ valueArray = new String[] {1000L + "", 3000L + "", 5000L + ""};
+
+ index = Arrays.asList(valueArray).indexOf(_community.getChatDelay().toString());
+ }
+ else if (_setting == CommunitySetting.CHAT_NAME_COLOR)
+ {
+ ChatColor[] colors = COLOR_MAP.keySet().toArray(new ChatColor[COLOR_MAP.size()]);
+ valueArray = new String[colors.length];
+ for (int i = 0; i < colors.length; i++)
+ {
+ valueArray[i] = colors[i].name();
+ }
+
+ index = Arrays.asList(valueArray).indexOf(_community.getChatFormatting()[0].name());
+ }
+ else if (_setting == CommunitySetting.CHAT_PLAYER_COLOR)
+ {
+ ChatColor[] colors = COLOR_MAP.keySet().toArray(new ChatColor[COLOR_MAP.size()]);
+ valueArray = new String[colors.length];
+ for (int i = 0; i < colors.length; i++)
+ {
+ valueArray[i] = colors[i].name();
+ }
+
+ index = Arrays.asList(valueArray).indexOf(_community.getChatFormatting()[1].name());
+ }
+ else if (_setting == CommunitySetting.CHAT_MESSAGE_COLOR)
+ {
+ ChatColor[] colors = COLOR_MAP.keySet().toArray(new ChatColor[COLOR_MAP.size()]);
+ valueArray = new String[colors.length];
+ for (int i = 0; i < colors.length; i++)
+ {
+ valueArray[i] = colors[i].name();
+ }
+
+ index = Arrays.asList(valueArray).indexOf(_community.getChatFormatting()[2].name());
+ }
+
+ int newIndex = (index - 1 < 0) ? (valueArray.length - 1) : (index - 1);
+ getCommunityManager().handleSettingUpdate(_viewer, _community, _setting, valueArray[newIndex]);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunitySettingsPage.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunitySettingsPage.java
new file mode 100644
index 000000000..4ed663137
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/community/CommunitySettingsPage.java
@@ -0,0 +1,149 @@
+package mineplex.core.communities.gui.community;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+
+import mineplex.core.common.util.C;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityDisbandEvent;
+import mineplex.core.communities.CommunityMemberDataUpdateEvent;
+import mineplex.core.communities.CommunityMembershipUpdateEvent;
+import mineplex.core.communities.CommunityRole;
+import mineplex.core.communities.CommunitySetting;
+import mineplex.core.communities.CommunitySettingUpdateEvent;
+import mineplex.core.communities.gui.ActionButton;
+import mineplex.core.communities.gui.CommunitiesGUIPage;
+import mineplex.core.communities.gui.overview.CommunityOverviewPage;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunitySettingsPage extends CommunitiesGUIPage
+{
+ private Community _community;
+
+ public CommunitySettingsPage(Player viewer, Community community)
+ {
+ super(community.getName() + C.cBlue, 6, viewer);
+ _community = community;
+
+ setup();
+ open();
+ }
+
+ private void setup()
+ {
+ {
+ //0
+ ActionButton membersButton = new ActionButton(new ItemBuilder(Material.SKULL_ITEM).setData((short)3).setTitle(C.cGreenB + "Members").build(), clickType ->
+ {
+ new CommunityMembersPage(Viewer, _community).open();
+ });
+ Buttons.put(0, membersButton);
+ Inv.setItem(0, membersButton.Button);
+ //4
+ CommunityButton communityButton = new CommunityButton(Viewer, _community);
+ Buttons.put(4, communityButton);
+ Inv.setItem(4, communityButton.Button);
+ //8
+ ActionButton returnButton = new ActionButton(new ItemBuilder(Material.BED).setTitle(C.cGray + "\u21FD Go Back").build(), clickType ->
+ {
+ new CommunityOverviewPage(Viewer).open();
+ });
+ Buttons.put(8, returnButton);
+ Inv.setItem(8, returnButton.Button);
+ //CoLeader+
+ if (_community.getMembers().containsKey(Viewer.getUniqueId()) && _community.getMembers().get(Viewer.getUniqueId()).Role.ordinal() <= CommunityRole.COLEADER.ordinal())
+ {
+ ActionButton requestsButton = new ActionButton(new ItemBuilder(Material.PAPER).setTitle(C.cGreenB + "Join Requests").build(), clickType ->
+ {
+ new CommunityJoinRequestsPage(Viewer, _community).open();
+ });
+ Buttons.put(2, requestsButton);
+ Inv.setItem(2, requestsButton.Button);
+ ActionButton settingsButton = new ActionButton(new ItemBuilder(Material.REDSTONE_COMPARATOR).setTitle(C.cGreenB + "Community Settings").build(), clickType -> {});
+ Buttons.put(6, settingsButton);
+ Inv.setItem(6, settingsButton.Button);
+ }
+ else if (_community.getMembers().containsKey(Viewer.getUniqueId()))
+ {
+ CommunityChatReadingButton chatButton = new CommunityChatReadingButton(Viewer, _community);
+ Buttons.put(6, chatButton);
+ Inv.setItem(6, chatButton.Button);
+ }
+ }
+ {
+ CommunitySettingButton gameButton = new CommunitySettingButton(Viewer, _community, CommunitySetting.FAVORITE_GAME);
+ Buttons.put(20, gameButton);
+ Inv.setItem(20, gameButton.Button);
+
+ CommunitySettingButton privacyButton = new CommunitySettingButton(Viewer, _community, CommunitySetting.PRIVACY);
+ Buttons.put(22, privacyButton);
+ Inv.setItem(22, privacyButton.Button);
+
+ CommunityChatReadingButton chatButton = new CommunityChatReadingButton(Viewer, _community);
+ Buttons.put(24, chatButton);
+ Inv.setItem(24, chatButton.Button);
+
+ CommunitySettingButton delayButton = new CommunitySettingButton(Viewer, _community, CommunitySetting.CHAT_DELAY);
+ Buttons.put(38, delayButton);
+ Inv.setItem(38, delayButton.Button);
+
+ CommunitySettingButton communityColorButton = new CommunitySettingButton(Viewer, _community, CommunitySetting.CHAT_NAME_COLOR);
+ Buttons.put(40, communityColorButton);
+ Inv.setItem(40, communityColorButton.Button);
+
+ CommunitySettingButton playerColorButton = new CommunitySettingButton(Viewer, _community, CommunitySetting.CHAT_PLAYER_COLOR);
+ Buttons.put(41, playerColorButton);
+ Inv.setItem(41, playerColorButton.Button);
+
+ CommunitySettingButton messageColorButton = new CommunitySettingButton(Viewer, _community, CommunitySetting.CHAT_MESSAGE_COLOR);
+ Buttons.put(42, messageColorButton);
+ Inv.setItem(42, messageColorButton.Button);
+ }
+
+ Viewer.updateInventory();
+ }
+
+ @EventHandler
+ public void onMembershipUpdate(CommunityMembershipUpdateEvent event)
+ {
+ if (event.getCommunity().getId().intValue() != _community.getId().intValue())
+ {
+ return;
+ }
+
+ if (!_community.getMembers().containsKey(Viewer.getUniqueId()) || _community.getMembers().get(Viewer.getUniqueId()).Role.ordinal() > CommunityRole.COLEADER.ordinal())
+ {
+ new CommunityMembersPage(Viewer, _community).open();
+ }
+ }
+
+ @EventHandler
+ public void onSettingsUpdate(CommunitySettingUpdateEvent event)
+ {
+ if (event.getCommunity().getId() != _community.getId())
+ {
+ return;
+ }
+ setup();
+ }
+
+ @EventHandler
+ public void onCommunityDisband(CommunityDisbandEvent event)
+ {
+ if (_community.getId().intValue() == event.getCommunity().getId().intValue())
+ {
+ Viewer.closeInventory();
+ }
+ }
+
+ @EventHandler
+ public void onMembershipUpdate(CommunityMemberDataUpdateEvent event)
+ {
+ if (!event.getPlayer().getUniqueId().toString().equalsIgnoreCase(Viewer.getUniqueId().toString()))
+ {
+ return;
+ }
+ setup();
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/overview/CommunityInvitesPage.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/overview/CommunityInvitesPage.java
new file mode 100644
index 000000000..93796bede
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/overview/CommunityInvitesPage.java
@@ -0,0 +1,118 @@
+package mineplex.core.communities.gui.overview;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+
+import mineplex.core.common.util.C;
+import mineplex.core.communities.CommunityDisbandEvent;
+import mineplex.core.communities.CommunityMemberDataUpdateEvent;
+import mineplex.core.communities.gui.ActionButton;
+import mineplex.core.communities.gui.CommunitiesGUIPage;
+import mineplex.core.communities.gui.browser.CommunityBrowserPage;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunityInvitesPage extends CommunitiesGUIPage
+{
+ private static final int COMMUNITIES_PER_PAGE = 27;
+
+ private int _page = 1;
+
+ public CommunityInvitesPage(Player viewer)
+ {
+ super("Community Invites", 6, viewer);
+
+ setup(1, true);
+ open();
+ }
+
+ private void setup(int page, boolean initial)
+ {
+ if (initial)
+ {
+ Buttons.clear();
+ Inv.clear();
+ }
+ {
+ //1
+ ActionButton communitiesButton = new ActionButton(new ItemBuilder(Material.EMERALD).setTitle(C.cGreenB + "Your Communities").build(), clickType ->
+ {
+ new CommunityOverviewPage(Viewer).open();
+ });
+ Buttons.put(1, communitiesButton);
+ Inv.setItem(1, communitiesButton.Button);
+ //4
+ ActionButton browserButton = new ActionButton(new ItemBuilder(Material.COMPASS).setTitle(C.cGreenB + "Browse Communities").build(), clickType ->
+ {
+ new CommunityBrowserPage(Viewer).open();
+ });
+ Buttons.put(4, browserButton);
+ Inv.setItem(4, browserButton.Button);
+ //7
+ ActionButton invitesButton = new ActionButton(new ItemBuilder(Material.PAPER).setTitle(C.cGreenB + "Community Invites").build(), clickType -> {});
+ Buttons.put(7, invitesButton);
+ Inv.setItem(7, invitesButton.Button);
+ }
+ {
+ ActionButton back = new ActionButton(new ItemBuilder(Material.ARROW).setTitle(C.cGreen + "Previous Page").build(), clickType ->
+ {
+ if (_page == 1)
+ {
+ return;
+ }
+ setup(_page - 1, false);
+ });
+ ActionButton next = new ActionButton(new ItemBuilder(Material.ARROW).setTitle(C.cGreen + "Next Page").build(), clickType ->
+ {
+ setup(_page + 1, false);
+ });
+ Buttons.put(45, back);
+ Inv.setItem(45, back.Button);
+ Buttons.put(53, next);
+ Inv.setItem(53, next.Button);
+ }
+
+ int slot = 18;
+ boolean cleared = false;
+ for (int i = (page - 1) * COMMUNITIES_PER_PAGE; i < (page - 1) * COMMUNITIES_PER_PAGE + COMMUNITIES_PER_PAGE && i < getCommunityManager().Get(Viewer).Invites.size(); i++)
+ {
+ if (!cleared && !initial)
+ {
+ cleared = true;
+ _page = page;
+ for (int clear = 18; clear < 45; clear++)
+ {
+ Buttons.remove(clear);
+ Inv.setItem(clear, null);
+ }
+ }
+ CommunityVisualizationButton button = new CommunityVisualizationButton(Viewer, getCommunityManager().getLoadedCommunity(getCommunityManager().Get(Viewer).Invites.get(i)), true);
+ Buttons.put(slot, button);
+ Inv.setItem(slot, button.Button);
+
+ slot++;
+ }
+
+ Viewer.updateInventory();
+ }
+
+ @EventHandler
+ public void onMembershipUpdate(CommunityMemberDataUpdateEvent event)
+ {
+ if (!event.getPlayer().getUniqueId().toString().equalsIgnoreCase(Viewer.getUniqueId().toString()))
+ {
+ return;
+ }
+
+ setup(1, true);
+ }
+
+ @EventHandler
+ public void onCommunityDisband(CommunityDisbandEvent event)
+ {
+ if (getCommunityManager().Get(Viewer).Invites.contains(event.getCommunity().getId()))
+ {
+ setup(1, true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/overview/CommunityOverviewPage.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/overview/CommunityOverviewPage.java
new file mode 100644
index 000000000..342afa5bd
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/overview/CommunityOverviewPage.java
@@ -0,0 +1,136 @@
+package mineplex.core.communities.gui.overview;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+
+import mineplex.core.common.util.C;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityDisbandEvent;
+import mineplex.core.communities.CommunityMemberDataUpdateEvent;
+import mineplex.core.communities.gui.ActionButton;
+import mineplex.core.communities.gui.CommunitiesGUIPage;
+import mineplex.core.communities.gui.browser.CommunityBrowserPage;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunityOverviewPage extends CommunitiesGUIPage
+{
+ private static final int COMMUNITIES_PER_PAGE = 27;
+
+ private int _page = 1;
+
+ public CommunityOverviewPage(Player viewer)
+ {
+ super("Your Communities", 6, viewer);
+
+ setup(1, true);
+ open();
+ }
+
+ private void setup(int page, boolean initial)
+ {
+ if (initial)
+ {
+ Buttons.clear();
+ Inv.clear();
+ }
+ {
+ //1
+ ActionButton communitiesButton = new ActionButton(new ItemBuilder(Material.EMERALD).setTitle(C.cGreenB + "Your Communities").build(), clickType -> {});
+ Buttons.put(1, communitiesButton);
+ Inv.setItem(1, communitiesButton.Button);
+ //4
+ ActionButton browserButton = new ActionButton(new ItemBuilder(Material.COMPASS).setTitle(C.cGreenB + "Browse Communities").build(), clickType ->
+ {
+ new CommunityBrowserPage(Viewer).open();
+ });
+ Buttons.put(4, browserButton);
+ Inv.setItem(4, browserButton.Button);
+ //7
+ ActionButton invitesButton = new ActionButton(new ItemBuilder(Material.PAPER).setTitle(C.cGreenB + "Community Invites").build(), clickType ->
+ {
+ new CommunityInvitesPage(Viewer);
+ });
+ Buttons.put(7, invitesButton);
+ Inv.setItem(7, invitesButton.Button);
+ }
+ {
+ ActionButton back = new ActionButton(new ItemBuilder(Material.ARROW).setTitle(C.cGreen + "Previous Page").build(), clickType ->
+ {
+ if (_page == 1)
+ {
+ return;
+ }
+ setup(_page - 1, false);
+ });
+ ActionButton next = new ActionButton(new ItemBuilder(Material.ARROW).setTitle(C.cGreen + "Next Page").build(), clickType ->
+ {
+ setup(_page + 1, false);
+ });
+ Buttons.put(45, back);
+ Inv.setItem(45, back.Button);
+ Buttons.put(53, next);
+ Inv.setItem(53, next.Button);
+ }
+
+ int slot = 18;
+ boolean cleared = false;
+ for (int i = (page - 1) * COMMUNITIES_PER_PAGE; i < (page - 1) * COMMUNITIES_PER_PAGE + COMMUNITIES_PER_PAGE && i < getCommunityManager().Get(Viewer).getTotalCommunities(); i++)
+ {
+ if (!cleared && !initial)
+ {
+ cleared = true;
+ _page = page;
+ for (int clear = 18; clear < 45; clear++)
+ {
+ Buttons.remove(clear);
+ Inv.setItem(clear, null);
+ }
+ }
+ List coms = Arrays.asList(getCommunityManager().Get(Viewer).getCommunities());
+ coms.sort((c1, c2) ->
+ {
+ if (c1.getMembers().get(Viewer.getUniqueId()).Role == c2.getMembers().get(Viewer.getUniqueId()).Role)
+ {
+ return c1.getName().compareTo(c2.getName());
+ }
+
+ if (c1.getMembers().get(Viewer.getUniqueId()).Role.ordinal() < c2.getMembers().get(Viewer.getUniqueId()).Role.ordinal())
+ {
+ return -1;
+ }
+ return 1;
+ });
+ CommunityVisualizationButton button = new CommunityVisualizationButton(Viewer, coms.get(i), false);
+ Buttons.put(slot, button);
+ Inv.setItem(slot, button.Button);
+
+ slot++;
+ }
+
+ Viewer.updateInventory();
+ }
+
+ @EventHandler
+ public void onMembershipUpdate(CommunityMemberDataUpdateEvent event)
+ {
+ if (!event.getPlayer().getUniqueId().toString().equalsIgnoreCase(Viewer.getUniqueId().toString()))
+ {
+ return;
+ }
+
+ setup(1, true);
+ }
+
+ @EventHandler
+ public void onCommunityDisband(CommunityDisbandEvent event)
+ {
+ if (getCommunityManager().Get(Viewer).Invites.contains(event.getCommunity().getId()))
+ {
+ setup(1, true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/overview/CommunityVisualizationButton.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/overview/CommunityVisualizationButton.java
new file mode 100644
index 000000000..64ca6a19d
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/gui/overview/CommunityVisualizationButton.java
@@ -0,0 +1,61 @@
+package mineplex.core.communities.gui.overview;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.inventory.ItemStack;
+
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.LineFormat;
+import mineplex.core.common.util.UtilText;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.gui.CommunitiesGUIButton;
+import mineplex.core.communities.gui.community.CommunityMembersPage;
+import mineplex.core.itemstack.ItemBuilder;
+
+public class CommunityVisualizationButton extends CommunitiesGUIButton
+{
+ private Player _viewer;
+ private Community _community;
+ private boolean _invite;
+
+ public CommunityVisualizationButton(Player viewer, Community community, boolean invite)
+ {
+ super(new ItemBuilder(Material.BARRIER).build());
+
+ _viewer = viewer;
+ _community = community;
+ _invite = invite;
+ update();
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void update()
+ {
+ ItemBuilder builder = new ItemBuilder(new ItemStack(_community.getFavoriteGame().getMaterial(), 1, _community.getFavoriteGame().getMaterialData(), null)).setTitle(C.cGreenB + _community.getName()).addLore(UtilText.splitLinesToArray(new String[] {C.cRed, C.cYellow + "Members " + C.cWhite + _community.getMembers().size(), C.cYellow + "Favorite Game " + C.cWhite + _community.getFavoriteGame().getName(), C.cYellow + "Description " + C.cWhite + _community.getDescription()}, LineFormat.LORE));
+ if (_invite)
+ {
+ builder.addLore(UtilText.splitLinesToArray(new String[] {C.cGold, C.cYellow + "Shift-Left Click " + C.cWhite + "Join", C.cYellow + "Shift-Right Click " + C.cWhite + "Decline"}, LineFormat.LORE));
+ }
+ builder.addLore(C.cBlue, C.cGreen + "Click to view community");
+ Button = builder.build();
+ }
+
+ @Override
+ public void handleClick(ClickType type)
+ {
+ if (_invite && type == ClickType.SHIFT_RIGHT)
+ {
+ getCommunityManager().handleRejectInvite(_viewer, _community);
+ }
+ else if (_invite && type == ClickType.SHIFT_LEFT)
+ {
+ getCommunityManager().handleJoin(_viewer, _community, true);
+ }
+ else
+ {
+ new CommunityMembersPage(_viewer, _community).open();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/mcs/MCSTheme.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/mcs/MCSTheme.java
new file mode 100644
index 000000000..a7ed05b78
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/mcs/MCSTheme.java
@@ -0,0 +1,50 @@
+package mineplex.core.communities.mcs;
+
+import org.bukkit.Material;
+
+import mineplex.core.common.util.C;
+
+public enum MCSTheme
+{
+ CANDYLAND(1, C.cPurple + "Candyland", Material.COOKIE, 1000, "Lobby_MPS_Candyland.zip")
+ ;
+
+ private final int _id;
+ private final String _displayName, _file;
+ private final Material _displayType;
+ private final int _cost;
+
+ private MCSTheme(int id, String displayName, Material displayType, int cost, String file)
+ {
+ _id = id;
+ _displayName = displayName;
+ _displayType = displayType;
+ _cost = cost;
+ _file = file;
+ }
+
+ public int getId()
+ {
+ return _id;
+ }
+
+ public String getDisplayName()
+ {
+ return _displayName;
+ }
+
+ public Material getDisplayType()
+ {
+ return _displayType;
+ }
+
+ public int getCost()
+ {
+ return _cost;
+ }
+
+ public String getFile()
+ {
+ return _file;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityChat.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityChat.java
new file mode 100644
index 000000000..15028f160
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityChat.java
@@ -0,0 +1,32 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityChat extends ServerCommand
+{
+ private String _senderName;
+ private Integer _communityId;
+ private String _message;
+
+ public CommunityChat(String senderName, Integer communityId, String message)
+ {
+ _senderName = senderName;
+ _communityId = communityId;
+ _message = message;
+ }
+
+ public String getSenderName()
+ {
+ return _senderName;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+
+ public String getMessage()
+ {
+ return _message;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityChatHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityChatHandler.java
new file mode 100644
index 000000000..de82598e9
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityChatHandler.java
@@ -0,0 +1,25 @@
+package mineplex.core.communities.redis;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityChatHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityChatHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityChat)
+ {
+ CommunityChat chat = ((CommunityChat) command);
+ _manager.handleCommunityChat(chat.getCommunityId(), chat.getSenderName(), chat.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCloseJoinRequest.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCloseJoinRequest.java
new file mode 100644
index 000000000..569a02958
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCloseJoinRequest.java
@@ -0,0 +1,53 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityCloseJoinRequest extends ServerCommand
+{
+ private Integer _communityId;
+ private String _sender;
+ private String _playerName;
+ private String _playerUUID;
+ private Integer _accountId;
+ private boolean _announce;
+
+ public CommunityCloseJoinRequest(Integer communityId, String sender, String playerName, String playerUUID, Integer accountId, boolean announce)
+ {
+ _communityId = communityId;
+ _sender = sender;
+ _playerName = playerName;
+ _playerUUID = playerUUID;
+ _accountId = accountId;
+ _announce = announce;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+
+ public String getSender()
+ {
+ return _sender;
+ }
+
+ public String getPlayerName()
+ {
+ return _playerName;
+ }
+
+ public String getPlayerUUID()
+ {
+ return _playerUUID;
+ }
+
+ public Integer getAccountId()
+ {
+ return _accountId;
+ }
+
+ public boolean shouldAnnounce()
+ {
+ return _announce;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCloseJoinRequestHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCloseJoinRequestHandler.java
new file mode 100644
index 000000000..15f2e2164
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCloseJoinRequestHandler.java
@@ -0,0 +1,34 @@
+package mineplex.core.communities.redis;
+
+import java.util.UUID;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityCloseJoinRequestHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityCloseJoinRequestHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityCloseJoinRequest)
+ {
+ CommunityCloseJoinRequest update = ((CommunityCloseJoinRequest) command);
+ Integer id = update.getCommunityId();
+ String sender = update.getSender();
+ UUID uuid = UUID.fromString(update.getPlayerUUID());
+ String name = update.getPlayerName();
+ Integer accountId = update.getAccountId();
+ boolean announce = update.shouldAnnounce();
+
+ _manager.handleCommunityCloseJoinRequest(id, sender, name, uuid, accountId, announce);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCreate.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCreate.java
new file mode 100644
index 000000000..0637057e5
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCreate.java
@@ -0,0 +1,25 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityCreate extends ServerCommand
+{
+ private String _leaderUUID;
+ private Integer _communityId;
+
+ public CommunityCreate(String leaderUUID, Integer communityId)
+ {
+ _leaderUUID = leaderUUID;
+ _communityId = communityId;
+ }
+
+ public String getLeaderUUID()
+ {
+ return _leaderUUID;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCreateHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCreateHandler.java
new file mode 100644
index 000000000..87803feeb
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityCreateHandler.java
@@ -0,0 +1,30 @@
+package mineplex.core.communities.redis;
+
+import java.util.UUID;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityCreateHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityCreateHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityCreate)
+ {
+ CommunityCreate update = ((CommunityCreate) command);
+ UUID leaderUUID = UUID.fromString(update.getLeaderUUID());
+ Integer communityId = update.getCommunityId();
+
+ _manager.handleCommunityCreation(communityId, leaderUUID);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityDisband.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityDisband.java
new file mode 100644
index 000000000..fe69e4404
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityDisband.java
@@ -0,0 +1,25 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityDisband extends ServerCommand
+{
+ private String _senderName;
+ private Integer _communityId;
+
+ public CommunityDisband(String senderName, Integer communityId)
+ {
+ _senderName = senderName;
+ _communityId = communityId;
+ }
+
+ public String getSenderName()
+ {
+ return _senderName;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityDisbandHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityDisbandHandler.java
new file mode 100644
index 000000000..8b4c31e20
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityDisbandHandler.java
@@ -0,0 +1,30 @@
+package mineplex.core.communities.redis;
+
+import java.util.UUID;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityDisbandHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityDisbandHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityDisband)
+ {
+ CommunityDisband update = ((CommunityDisband) command);
+ String senderName = update.getSenderName();
+ Integer communityId = update.getCommunityId();
+
+ _manager.handleCommunityDisband(communityId, senderName);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityInvite.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityInvite.java
new file mode 100644
index 000000000..374d3b5e1
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityInvite.java
@@ -0,0 +1,39 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityInvite extends ServerCommand
+{
+ private Integer _communityId;
+ private String _sender;
+ private String _playerName;
+ private String _playerUUID;
+
+ public CommunityInvite(Integer communityId, String sender, String playerName, String playerUUID)
+ {
+ _communityId = communityId;
+ _sender = sender;
+ _playerName = playerName;
+ _playerUUID = playerUUID;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+
+ public String getSender()
+ {
+ return _sender;
+ }
+
+ public String getPlayerName()
+ {
+ return _playerName;
+ }
+
+ public String getPlayerUUID()
+ {
+ return _playerUUID;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityInviteHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityInviteHandler.java
new file mode 100644
index 000000000..065ac86a7
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityInviteHandler.java
@@ -0,0 +1,32 @@
+package mineplex.core.communities.redis;
+
+import java.util.UUID;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityInviteHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityInviteHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityInvite)
+ {
+ CommunityInvite update = ((CommunityInvite) command);
+ Integer id = update.getCommunityId();
+ String sender = update.getSender();
+ String name = update.getPlayerName();
+ UUID uuid = UUID.fromString(update.getPlayerUUID());
+
+ _manager.handleCommunityInvite(id, sender, name, uuid);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityJoinRequest.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityJoinRequest.java
new file mode 100644
index 000000000..ccfdaf6bd
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityJoinRequest.java
@@ -0,0 +1,39 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityJoinRequest extends ServerCommand
+{
+ private Integer _communityId;
+ private String _playerName;
+ private String _playerUUID;
+ private Integer _accountId;
+
+ public CommunityJoinRequest(Integer communityId, String playerName, String playerUUID, Integer accountId)
+ {
+ _communityId = communityId;
+ _playerName = playerName;
+ _playerUUID = playerUUID;
+ _accountId = accountId;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+
+ public String getPlayerName()
+ {
+ return _playerName;
+ }
+
+ public String getPlayerUUID()
+ {
+ return _playerUUID;
+ }
+
+ public Integer getAccountId()
+ {
+ return _accountId;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityJoinRequestHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityJoinRequestHandler.java
new file mode 100644
index 000000000..f68ba99d0
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityJoinRequestHandler.java
@@ -0,0 +1,32 @@
+package mineplex.core.communities.redis;
+
+import java.util.UUID;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityJoinRequestHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityJoinRequestHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityJoinRequest)
+ {
+ CommunityJoinRequest update = ((CommunityJoinRequest) command);
+ Integer id = update.getCommunityId();
+ UUID uuid = UUID.fromString(update.getPlayerUUID());
+ String name = update.getPlayerName();
+ Integer accountId = update.getAccountId();
+
+ _manager.handleCommunityJoinRequest(id, name, uuid, accountId);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUnInvite.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUnInvite.java
new file mode 100644
index 000000000..13537e115
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUnInvite.java
@@ -0,0 +1,46 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUnInvite extends ServerCommand
+{
+ private Integer _communityId;
+ private String _sender;
+ private String _playerName;
+ private String _playerUUID;
+ private boolean _announce;
+
+ public CommunityUnInvite(Integer communityId, String sender, String playerName, String playerUUID, boolean announce)
+ {
+ _communityId = communityId;
+ _sender = sender;
+ _playerName = playerName;
+ _playerUUID = playerUUID;
+ _announce = announce;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+
+ public String getSender()
+ {
+ return _sender;
+ }
+
+ public String getPlayerName()
+ {
+ return _playerName;
+ }
+
+ public String getPlayerUUID()
+ {
+ return _playerUUID;
+ }
+
+ public boolean shouldAnnounce()
+ {
+ return _announce;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUnInviteHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUnInviteHandler.java
new file mode 100644
index 000000000..d38f9779f
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUnInviteHandler.java
@@ -0,0 +1,33 @@
+package mineplex.core.communities.redis;
+
+import java.util.UUID;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUnInviteHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityUnInviteHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityUnInvite)
+ {
+ CommunityUnInvite update = ((CommunityUnInvite) command);
+ Integer id = update.getCommunityId();
+ String sender = update.getSender();
+ String name = update.getPlayerName();
+ UUID uuid = UUID.fromString(update.getPlayerUUID());
+ boolean announce = update.shouldAnnounce();
+
+ _manager.handleCommunityUninvite(id, sender, name, uuid, announce);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberChatReading.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberChatReading.java
new file mode 100644
index 000000000..de74302de
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberChatReading.java
@@ -0,0 +1,32 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUpdateMemberChatReading extends ServerCommand
+{
+ private Integer _communityId;
+ private String _playerUUID;
+ private boolean _reading;
+
+ public CommunityUpdateMemberChatReading(Integer communityId, String playerUUID, boolean reading)
+ {
+ _communityId = communityId;
+ _playerUUID = playerUUID;
+ _reading = reading;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+
+ public String getPlayerUUID()
+ {
+ return _playerUUID;
+ }
+
+ public boolean reading()
+ {
+ return _reading;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberChatReadingHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberChatReadingHandler.java
new file mode 100644
index 000000000..a536ee7f8
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberChatReadingHandler.java
@@ -0,0 +1,31 @@
+package mineplex.core.communities.redis;
+
+import java.util.UUID;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUpdateMemberChatReadingHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityUpdateMemberChatReadingHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityUpdateMemberChatReading)
+ {
+ CommunityUpdateMemberChatReading update = ((CommunityUpdateMemberChatReading) command);
+ Integer id = update.getCommunityId();
+ UUID uuid = UUID.fromString(update.getPlayerUUID());
+ boolean reading = update.reading();
+
+ _manager.handleToggleReadingCommunityChat(id, uuid, reading);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberRole.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberRole.java
new file mode 100644
index 000000000..9f42ad0c4
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberRole.java
@@ -0,0 +1,39 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUpdateMemberRole extends ServerCommand
+{
+ private Integer _communityId;
+ private String _sender;
+ private String _playerUUID;
+ private String _memberRole;
+
+ public CommunityUpdateMemberRole(Integer communityId, String sender, String playerUUID, String memberRole)
+ {
+ _communityId = communityId;
+ _sender = sender;
+ _playerUUID = playerUUID;
+ _memberRole = memberRole;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+
+ public String getSender()
+ {
+ return _sender;
+ }
+
+ public String getPlayerUUID()
+ {
+ return _playerUUID;
+ }
+
+ public String getMemberRole()
+ {
+ return _memberRole;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberRoleHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberRoleHandler.java
new file mode 100644
index 000000000..bced0dc12
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMemberRoleHandler.java
@@ -0,0 +1,32 @@
+package mineplex.core.communities.redis;
+
+import java.util.UUID;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.communities.CommunityRole;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUpdateMemberRoleHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityUpdateMemberRoleHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityUpdateMemberRole)
+ {
+ CommunityUpdateMemberRole update = ((CommunityUpdateMemberRole) command);
+ Integer id = update.getCommunityId();
+ UUID uuid = UUID.fromString(update.getPlayerUUID());
+ CommunityRole role = CommunityRole.parseRole(update.getMemberRole());
+
+ _manager.handleCommunityMembershipRoleUpdate(id, update.getSender(), uuid, role);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMembership.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMembership.java
new file mode 100644
index 000000000..cb870d786
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMembership.java
@@ -0,0 +1,60 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUpdateMembership extends ServerCommand
+{
+ private Integer _communityId;
+ private String _sender;
+ private String _playerName;
+ private String _playerUUID;
+ private Integer _accountId;
+ private boolean _kick;
+ private boolean _leave;
+
+ public CommunityUpdateMembership(Integer communityId, String sender, String playerName, String playerUUID, Integer accountId, boolean kick, boolean leave)
+ {
+ _communityId = communityId;
+ _sender = sender;
+ _playerName = playerName;
+ _playerUUID = playerUUID;
+ _accountId = accountId;
+ _kick = kick;
+ _leave = leave;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+
+ public String getSender()
+ {
+ return _sender;
+ }
+
+ public String getPlayerName()
+ {
+ return _playerName;
+ }
+
+ public String getPlayerUUID()
+ {
+ return _playerUUID;
+ }
+
+ public Integer getAccountId()
+ {
+ return _accountId;
+ }
+
+ public boolean isKick()
+ {
+ return _kick;
+ }
+
+ public boolean isLeave()
+ {
+ return _leave;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMembershipHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMembershipHandler.java
new file mode 100644
index 000000000..2ca354304
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateMembershipHandler.java
@@ -0,0 +1,35 @@
+package mineplex.core.communities.redis;
+
+import java.util.UUID;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUpdateMembershipHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityUpdateMembershipHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityUpdateMembership)
+ {
+ CommunityUpdateMembership update = ((CommunityUpdateMembership) command);
+ Integer id = update.getCommunityId();
+ UUID uuid = UUID.fromString(update.getPlayerUUID());
+ String sender = update.getSender();
+ String name = update.getPlayerName();
+ Integer accountId = update.getAccountId();
+ boolean kick = update.isKick();
+ boolean leave = update.isLeave();
+
+ _manager.handleCommunityMembershipUpdate(id, sender, name, uuid, accountId, kick, leave);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateName.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateName.java
new file mode 100644
index 000000000..a58347a2c
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateName.java
@@ -0,0 +1,32 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUpdateName extends ServerCommand
+{
+ private Integer _communityId;
+ private String _sender;
+ private String _name;
+
+ public CommunityUpdateName(Integer communityId, String sender, String name)
+ {
+ _communityId = communityId;
+ _sender = sender;
+ _name = name;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+
+ public String getSender()
+ {
+ return _sender;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateNameHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateNameHandler.java
new file mode 100644
index 000000000..b854b121f
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateNameHandler.java
@@ -0,0 +1,29 @@
+package mineplex.core.communities.redis;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUpdateNameHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityUpdateNameHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityUpdateName)
+ {
+ CommunityUpdateName update = ((CommunityUpdateName) command);
+ Integer id = update.getCommunityId();
+ String sender = update.getSender();
+ String name = update.getName();
+
+ _manager.handleCommunityNameUpdate(id, sender, name);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateSetting.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateSetting.java
new file mode 100644
index 000000000..bae592d9c
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateSetting.java
@@ -0,0 +1,39 @@
+package mineplex.core.communities.redis;
+
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUpdateSetting extends ServerCommand
+{
+ private Integer _communityId;
+ private String _sender;
+ private String _setting;
+ private String _newValue;
+
+ public CommunityUpdateSetting(Integer communityId, String sender, String setting, String newValue)
+ {
+ _communityId = communityId;
+ _sender = sender;
+ _setting = setting;
+ _newValue = newValue;
+ }
+
+ public Integer getCommunityId()
+ {
+ return _communityId;
+ }
+
+ public String getSender()
+ {
+ return _sender;
+ }
+
+ public String getSetting()
+ {
+ return _setting;
+ }
+
+ public String getNewValue()
+ {
+ return _newValue;
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateSettingHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateSettingHandler.java
new file mode 100644
index 000000000..198a50694
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/redis/CommunityUpdateSettingHandler.java
@@ -0,0 +1,30 @@
+package mineplex.core.communities.redis;
+
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.communities.CommunitySetting;
+import mineplex.serverdata.commands.CommandCallback;
+import mineplex.serverdata.commands.ServerCommand;
+
+public class CommunityUpdateSettingHandler implements CommandCallback
+{
+ private CommunityManager _manager;
+
+ public CommunityUpdateSettingHandler(CommunityManager manager)
+ {
+ _manager = manager;
+ }
+
+ @Override
+ public void run(ServerCommand command)
+ {
+ if (command instanceof CommunityUpdateSetting)
+ {
+ CommunityUpdateSetting update = ((CommunityUpdateSetting) command);
+ Integer id = update.getCommunityId();
+ CommunitySetting setting = CommunitySetting.valueOf(update.getSetting());
+ String newValue = update.getNewValue();
+
+ _manager.handleCommunitySettingUpdate(id, update.getSender(), setting, newValue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/communities/storage/CommunityRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/communities/storage/CommunityRepository.java
new file mode 100644
index 000000000..3147d104c
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/communities/storage/CommunityRepository.java
@@ -0,0 +1,438 @@
+package mineplex.core.communities.storage;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.bukkit.plugin.java.JavaPlugin;
+
+import mineplex.core.common.util.Callback;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityJoinRequestInfo;
+import mineplex.core.communities.CommunityMemberInfo;
+import mineplex.core.communities.CommunityRole;
+import mineplex.core.communities.CommunitySetting;
+import mineplex.core.database.MinecraftRepository;
+import mineplex.serverdata.data.DataRepository;
+import mineplex.serverdata.data.PlayerStatus;
+import mineplex.serverdata.database.DBPool;
+import mineplex.serverdata.database.column.ColumnBoolean;
+import mineplex.serverdata.database.column.ColumnInt;
+import mineplex.serverdata.database.column.ColumnVarChar;
+
+public class CommunityRepository extends MinecraftRepository
+{
+ private static final String GET_ALL_COMMUNITIES = "SELECT * FROM communities WHERE region=?;";
+ private static final String GET_COMMUNITY_BY_ID = "SELECT * FROM communities WHERE id=?;";
+ private static final String GET_COMMUNITY_BY_NAME = "SELECT * FROM communities WHERE name=? AND region=?;";
+ private static final String GET_COMMUNITY_MEMBERS = "SELECT cm.accountId, cm.communityRole, ac.name, ac.uuid, ac.lastLogin, now(), cm.readingChat, (SELECT COUNT(id) FROM communityMembers WHERE accountId=cm.accountId AND communityRole='LEADER') FROM communityMembers cm INNER JOIN accounts ac ON ac.id=cm.accountId WHERE communityId=?;";
+ private static final String GET_COMMUNITY_JOIN_REQUESTS = "SELECT cjr.accountId, ac.name, ac.uuid FROM communityJoinRequests cjr INNER JOIN accounts ac ON ac.id=cjr.accountId WHERE communityId=?;";
+ private static final String GET_COMMUNITY_SETTINGS = "SELECT settingId, settingValue FROM communitySettings WHERE communityId=?;";
+
+ private static final String REMOVE_FROM_COMMUNITY = "DELETE FROM communityMembers WHERE accountId=? AND communityId=?;";
+ private static final String UPDATE_COMMUNITY_ROLE = "UPDATE communityMembers SET communityRole=? WHERE accountId=? AND communityId=?;";
+ private static final String ADD_TO_COMMUNITY = "INSERT INTO communityMembers (accountId, communityId, communityRole, readingChat) VALUES (?, ?, ?, true);";
+ private static final String UPDATE_COMMUNITY_SETTING = "INSERT INTO communitySettings (settingId, communityId, settingValue) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE settingValue=VALUES(settingValue);";
+ private static final String UPDATE_COMMUNITY_NAME = "UPDATE communities SET name=? WHERE id=?;";
+ private static final String INVITE_TO_COMMUNITY = "INSERT INTO communityInvites (accountId, communityId) SELECT a.id AS accountId, ? FROM accounts as a WHERE a.name = ? ORDER BY a.lastLogin DESC LIMIT 1 ON DUPLICATE KEY UPDATE communityInvites.id=communityInvites.id;";
+ private static final String DELETE_INVITE_TO_COMMUNITY = "DELETE i FROM communityInvites AS i INNER JOIN accounts as a ON i.accountId = a.id WHERE a.name = ? AND i.communityId=?;";
+ private static final String ADD_JOIN_REQUEST = "INSERT INTO communityJoinRequests (accountId, communityId) VALUES (?, ?);";
+ private static final String REMOVE_JOIN_REQUEST = "DELETE FROM communityJoinRequests WHERE accountId=? AND communityId=?;";
+
+ private static final String CREATE_COMMUNITY = "INSERT INTO communities (name, region) VALUES (?, ?);";
+
+ private static final String SET_READING_CHAT_IN = "UPDATE communityMembers SET readingChat=? WHERE accountId=? AND communityId=?;";
+
+ private DataRepository _repo;
+ private boolean _us;
+
+ public CommunityRepository(JavaPlugin plugin, DataRepository statusRepo, boolean us)
+ {
+ super(DBPool.getAccount());
+
+ _repo = statusRepo;
+ _us = us;
+ }
+
+ public void loadCommunity(int communityId, final Map communityMap)
+ {
+ try (Connection connection = getConnection())
+ {
+ executeQuery(connection, GET_COMMUNITY_BY_ID, resultSet ->
+ {
+ if (resultSet.next())
+ {
+ final int id = resultSet.getInt("id");
+ final String cName = resultSet.getString("name");
+ final Community community = new Community(id, cName);
+ executeQuery(connection, GET_COMMUNITY_MEMBERS, memberSet ->
+ {
+ while (memberSet.next())
+ {
+ final int accountId = memberSet.getInt("accountId");
+ final String name = memberSet.getString("name");
+ final UUID uuid = UUID.fromString(memberSet.getString("uuid"));
+ final CommunityRole role = CommunityRole.parseRole(memberSet.getString("communityRole"));
+ final long timeSinceOnline = memberSet.getTimestamp(6).getTime() - memberSet.getTimestamp(5).getTime();
+ boolean readingChat = memberSet.getBoolean("readingChat");
+ final int owns = memberSet.getInt(8);
+
+ CommunityMemberInfo info = new CommunityMemberInfo(name, uuid, accountId, role, timeSinceOnline);
+ PlayerStatus status = _repo.getElement(name);
+ if (status != null)
+ {
+ info.update(name, role, timeSinceOnline, true, status.getServer());
+ }
+ info.ReadingChat = readingChat;
+ info.OwnsCommunity = owns > 0;
+ community.getMembers().put(info.UUID, info);
+ }
+ }, new ColumnInt("communityId", community.getId()));
+
+ executeQuery(connection, GET_COMMUNITY_JOIN_REQUESTS, requestSet ->
+ {
+ while (requestSet.next())
+ {
+ final int accountId = requestSet.getInt("accountId");
+ final UUID uuid = UUID.fromString(requestSet.getString("uuid"));
+ final String name = requestSet.getString("name");
+
+ community.getJoinRequests().put(uuid, new CommunityJoinRequestInfo(name, uuid, accountId));
+ }
+ }, new ColumnInt("communityId", community.getId()));
+
+ executeQuery(connection, GET_COMMUNITY_SETTINGS, settingSet ->
+ {
+ while (settingSet.next())
+ {
+ final int settingId = settingSet.getInt("settingId");
+ final String value = settingSet.getString("settingValue");
+
+ CommunitySetting setting = CommunitySetting.getSetting(settingId);
+ if (setting != null)
+ {
+ setting.parseValueInto(value, community);
+ }
+ }
+ }, new ColumnInt("communityId", community.getId()));
+
+ communityMap.put(community.getId(), community);
+ }
+ }, new ColumnInt("id", communityId));
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public void loadCommunities(final Map communityMap)
+ {
+ try (Connection connection = getConnection())
+ {
+ executeQuery(connection, GET_ALL_COMMUNITIES, resultSet ->
+ {
+ Map resultant = new HashMap<>();
+ while (resultSet.next())
+ {
+ final int id = resultSet.getInt("id");
+ final String cName = resultSet.getString("name");
+ final Community community = new Community(id, cName);
+ executeQuery(connection, GET_COMMUNITY_MEMBERS, memberSet ->
+ {
+ while (memberSet.next())
+ {
+ final int accountId = memberSet.getInt("accountId");
+ final String name = memberSet.getString("name");
+ final UUID uuid = UUID.fromString(memberSet.getString("uuid"));
+ final CommunityRole role = CommunityRole.parseRole(memberSet.getString("communityRole"));
+ final long timeSinceOnline = memberSet.getTimestamp(6).getTime() - memberSet.getTimestamp(5).getTime();
+ boolean readingChat = memberSet.getBoolean("readingChat");
+ final int owns = memberSet.getInt(8);
+
+ CommunityMemberInfo info = new CommunityMemberInfo(name, uuid, accountId, role, timeSinceOnline);
+ PlayerStatus status = _repo.getElement(name);
+ if (status != null)
+ {
+ info.update(name, role, timeSinceOnline, true, status.getServer());
+ }
+ info.ReadingChat = readingChat;
+ info.OwnsCommunity = owns > 0;
+ community.getMembers().put(info.UUID, info);
+ }
+ }, new ColumnInt("communityId", community.getId()));
+
+ executeQuery(connection, GET_COMMUNITY_JOIN_REQUESTS, requestSet ->
+ {
+ while (requestSet.next())
+ {
+ final int accountId = requestSet.getInt("accountId");
+ final UUID uuid = UUID.fromString(requestSet.getString("uuid"));
+ final String name = requestSet.getString("name");
+
+ community.getJoinRequests().put(uuid, new CommunityJoinRequestInfo(name, uuid, accountId));
+ }
+ }, new ColumnInt("communityId", community.getId()));
+
+ executeQuery(connection, GET_COMMUNITY_SETTINGS, settingSet ->
+ {
+ while (settingSet.next())
+ {
+ final int settingId = settingSet.getInt("settingId");
+ final String value = settingSet.getString("settingValue");
+
+ CommunitySetting setting = CommunitySetting.getSetting(settingId);
+ if (setting != null)
+ {
+ setting.parseValueInto(value, community);
+ }
+ }
+ }, new ColumnInt("communityId", community.getId()));
+
+ resultant.put(community.getId(), community);
+ }
+
+ communityMap.clear();
+ communityMap.putAll(resultant);
+ }, new ColumnVarChar("region", 5, _us ? "US" : "EU"));
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public void updateMembersAndJoinRequests(LinkedList communities)
+ {
+ if (communities.isEmpty())
+ {
+ return;
+ }
+ String query = "";
+ for (Community c : communities)
+ {
+ query = query + GET_COMMUNITY_MEMBERS.replace("?", c.getId().toString()) + GET_COMMUNITY_JOIN_REQUESTS.replace("?", c.getId().toString());
+ }
+
+ if (query.isEmpty())
+ {
+ return;
+ }
+
+ try (Connection connection = getConnection(); Statement statement = connection.createStatement())
+ {
+ statement.executeQuery(query);
+
+ for (Community c : communities)
+ {
+ ResultSet memberSet = statement.getResultSet();
+ while (memberSet.next())
+ {
+ final UUID uuid = UUID.fromString(memberSet.getString("uuid"));
+ final String name = memberSet.getString("name");
+ final CommunityRole role = CommunityRole.parseRole(memberSet.getString("communityRole"));
+ final long timeSinceOnline = memberSet.getTimestamp(6).getTime() - memberSet.getTimestamp(5).getTime();
+ //boolean readingChat = memberSet.getBoolean("readingChat");
+ final int owns = memberSet.getInt(8);
+
+ if (c.getMembers().containsKey(uuid))
+ {
+ PlayerStatus status = _repo.getElement(name);
+ boolean online = false;
+ String server = "";
+ if (status != null)
+ {
+ online = true;
+ server = status.getServer();
+ }
+ //c.getMembers().get(uuid).ReadingChat = readingChat;
+ c.getMembers().get(uuid).OwnsCommunity = owns > 0;
+ c.getMembers().get(uuid).update(name, role, timeSinceOnline, online, server);
+ }
+ }
+
+ statement.getMoreResults();
+
+ ResultSet requestSet = statement.getResultSet();
+ while (requestSet.next())
+ {
+ final UUID uuid = UUID.fromString(requestSet.getString("uuid"));
+ final String name = requestSet.getString("name");
+
+ if (c.getJoinRequests().containsKey(uuid))
+ {
+ c.getJoinRequests().get(uuid).update(name);
+ }
+ }
+
+ statement.getMoreResults();
+ }
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public void updateMembers(Map members, int communityId)
+ {
+ executeQuery(GET_COMMUNITY_MEMBERS, memberSet ->
+ {
+ while (memberSet.next())
+ {
+ final UUID uuid = UUID.fromString(memberSet.getString("uuid"));
+ final String name = memberSet.getString("name");
+ final CommunityRole role = CommunityRole.parseRole(memberSet.getString("communityRole"));
+ final long timeSinceOnline = memberSet.getTimestamp(5).getTime() - memberSet.getTimestamp(4).getTime();
+ //boolean readingChat = memberSet.getBoolean("readingChat");
+ final int owns = memberSet.getInt(8);
+
+ if (members.containsKey(uuid))
+ {
+ PlayerStatus status = _repo.getElement(name);
+ boolean online = false;
+ String server = "";
+ if (status != null)
+ {
+ online = true;
+ server = status.getServer();
+ }
+ //members.get(uuid).ReadingChat = readingChat;
+ members.get(uuid).OwnsCommunity = owns > 0;
+ members.get(uuid).update(name, role, timeSinceOnline, online, server);
+ }
+ }
+ }, new ColumnInt("communityId", communityId));
+ }
+
+ public void updateJoinRequests(Map requests, int communityId)
+ {
+ executeQuery(GET_COMMUNITY_JOIN_REQUESTS, requestSet ->
+ {
+ while (requestSet.next())
+ {
+ final UUID uuid = UUID.fromString(requestSet.getString("uuid"));
+ final String name = requestSet.getString("name");
+
+ if (requests.containsKey(uuid))
+ {
+ requests.get(uuid).update(name);
+ }
+ }
+ }, new ColumnInt("communityId", communityId));
+ }
+
+ public void loadInvites(int accountId, List invites)
+ {
+ executeQuery("SELECT ci.communityId, c.region FROM communityInvites AS ci INNER JOIN communities AS c ON c.id=ci.communityId WHERE accountId=?;", resultSet ->
+ {
+ while (resultSet.next())
+ {
+ String region = resultSet.getString("region");
+ if ((_us && region.equalsIgnoreCase("US")) || (!_us && region.equalsIgnoreCase("EU")))
+ {
+ invites.add(resultSet.getInt("communityId"));
+ }
+ }
+ }, new ColumnInt("accountId", accountId));
+ }
+
+ public void removeFromCommunity(int accountId, int communityId)
+ {
+ executeUpdate(REMOVE_FROM_COMMUNITY, new ColumnInt("accountId", accountId), new ColumnInt("communityId", communityId));
+ }
+
+ public void updateCommunityRole(int accountId, int communityId, CommunityRole role)
+ {
+ executeUpdate(UPDATE_COMMUNITY_ROLE, new ColumnVarChar("communityRole", 20, role.toString()), new ColumnInt("accountId", accountId), new ColumnInt("communityId", communityId));
+ }
+
+ public void addToCommunity(int accountId, int communityId)
+ {
+ executeUpdate(ADD_TO_COMMUNITY, new ColumnInt("accountId", accountId), new ColumnInt("communityId", communityId), new ColumnVarChar("communityRole", 20, CommunityRole.MEMBER.toString()));
+ }
+
+ public void updateCommunitySetting(CommunitySetting setting, int communityId, String value)
+ {
+ executeUpdate(UPDATE_COMMUNITY_SETTING, new ColumnInt("settingId", setting.getId()), new ColumnInt("communityId", communityId), new ColumnVarChar("settingValue", 100, value));
+ }
+
+ public void updateCommunityName(int communityId, String name)
+ {
+ executeUpdate(UPDATE_COMMUNITY_NAME, new ColumnVarChar("name", 15, name), new ColumnInt("id", communityId));
+ }
+
+ public boolean inviteToCommunity(int communityId, String name)
+ {
+ return executeUpdate(INVITE_TO_COMMUNITY, new ColumnInt("communityId", communityId), new ColumnVarChar("name", 32, name)) > 0;
+ }
+
+ public boolean deleteInviteToCommunity(int communityId, String name)
+ {
+ return executeUpdate(DELETE_INVITE_TO_COMMUNITY, new ColumnVarChar("name", 32, name), new ColumnInt("communityId", communityId)) > 0;
+ }
+
+ public void addJoinRequest(int communityId, int accountId)
+ {
+ executeUpdate(ADD_JOIN_REQUEST, new ColumnInt("accountId", accountId), new ColumnInt("communityId", communityId));
+ }
+
+ public void removeJoinRequest(int communityId, int accountId)
+ {
+ executeUpdate(REMOVE_JOIN_REQUEST, new ColumnInt("accountId", accountId), new ColumnInt("communityId", communityId));
+ }
+
+ public void createCommunity(String name, int leaderAccount, Callback idCallback)
+ {
+ try (Connection connection = getConnection())
+ {
+ executeInsert(connection, CREATE_COMMUNITY, resultSet ->
+ {
+ if (resultSet.next())
+ {
+ int id = resultSet.getInt(1);
+ executeUpdate(connection, ADD_TO_COMMUNITY, new ColumnInt("accountId", leaderAccount), new ColumnInt("communityId", id), new ColumnVarChar("communityRole", 20, CommunityRole.LEADER.toString()));
+ idCallback.run(id);
+ }
+ else
+ {
+ idCallback.run(-1);
+ }
+ }, new ColumnVarChar("name", 15, name), new ColumnVarChar("region", 5, _us ? "US" : "EU"));
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public void deleteCommunity(int communityId)
+ {
+ try (Connection connection = getConnection())
+ {
+ executeUpdate(connection, "DELETE FROM communities WHERE id=?;", new ColumnInt("id", communityId));
+ executeUpdate(connection, "DELETE FROM communitySettings WHERE communityId=?;", new ColumnInt("communityId", communityId));
+ executeUpdate(connection, "DELETE FROM communityMembers WHERE communityId=?;", new ColumnInt("communityId", communityId));
+ executeUpdate(connection, "DELETE FROM communityInvites WHERE communityId=?;", new ColumnInt("communityId", communityId));
+ executeUpdate(connection, "DELETE FROM communityJoinRequests WHERE communityId=?", new ColumnInt("communityId", communityId));
+ }
+ catch (SQLException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public void setReadingChat(int accountId, int communityId, boolean reading)
+ {
+ executeUpdate(SET_READING_CHAT_IN, new ColumnBoolean("readingChat", reading), new ColumnInt("accountId", accountId), new ColumnInt("communityId", communityId));
+ }
+
+ protected void initialize() {}
+ protected void update() {}
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/button/open/OpenTaunts.java b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/button/open/OpenTaunts.java
new file mode 100644
index 000000000..e87cdcfb1
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/button/open/OpenTaunts.java
@@ -0,0 +1,21 @@
+package mineplex.core.cosmetic.ui.button.open;
+
+import org.bukkit.entity.Player;
+
+import mineplex.core.cosmetic.ui.page.Menu;
+import mineplex.core.cosmetic.ui.page.TauntPage;
+import mineplex.core.gadget.types.Gadget;
+
+public class OpenTaunts extends OpenPageButton
+{
+ public OpenTaunts(Menu menu, Gadget active)
+ {
+ super(menu, active);
+ }
+
+ @Override
+ protected void leftClick(Player player)
+ {
+ getMenu().getShop().openPageForPlayer(player, new TauntPage(getMenu().getPlugin(), getMenu().getShop(), getMenu().getClientManager(), getMenu().getDonationManager(), "Taunts", player));
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/GadgetPage.java b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/GadgetPage.java
index 17e2a0b20..566443c22 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/GadgetPage.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/GadgetPage.java
@@ -201,6 +201,11 @@ public class GadgetPage extends ShopPageBase
itemLore.add(C.cBlack);
itemLore.add(C.cRed + "Unlocked with Titan Rank");
}
+ else if (gadget.getCost(GlobalCurrency.TREASURE_SHARD) == -15)
+ {
+ itemLore.add(C.cBlack);
+ itemLore.add(C.cDAqua + "Unlocked with Eternal Rank");
+ }
}
//Special case for item gadgets!
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/Menu.java b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/Menu.java
index 229448b95..ef27ea645 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/Menu.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/Menu.java
@@ -1,9 +1,17 @@
package mineplex.core.cosmetic.ui.page;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Creature;
+import org.bukkit.entity.Player;
+
import mineplex.core.account.CoreClientManager;
import mineplex.core.common.currency.GlobalCurrency;
import mineplex.core.common.util.C;
-import mineplex.core.common.util.F;
import mineplex.core.common.util.LineFormat;
import mineplex.core.common.util.UtilText;
import mineplex.core.cosmetic.CosmeticManager;
@@ -20,24 +28,15 @@ import mineplex.core.cosmetic.ui.button.open.OpenMounts;
import mineplex.core.cosmetic.ui.button.open.OpenMusic;
import mineplex.core.cosmetic.ui.button.open.OpenParticles;
import mineplex.core.cosmetic.ui.button.open.OpenPets;
+import mineplex.core.cosmetic.ui.button.open.OpenTaunts;
import mineplex.core.cosmetic.ui.button.open.OpenWinEffect;
import mineplex.core.donation.DonationManager;
import mineplex.core.gadget.types.Gadget;
import mineplex.core.gadget.types.GadgetType;
import mineplex.core.mount.Mount;
import mineplex.core.pet.PetType;
-import mineplex.core.shop.item.IButton;
import mineplex.core.shop.item.ShopItem;
import mineplex.core.shop.page.ShopPageBase;
-import org.bukkit.Material;
-import org.bukkit.entity.Creature;
-import org.bukkit.entity.Player;
-import org.bukkit.event.inventory.ClickType;
-
-import java.util.ArrayList;
-import java.util.EnumMap;
-import java.util.List;
-import java.util.Map;
public class Menu extends ShopPageBase
{
@@ -187,14 +186,10 @@ public class Menu extends ShopPageBase
addButton(musicSlot, new ShopItem(Material.GREEN_RECORD, "Music", lore, 1, false), new OpenMusic(this, enabled.get(type)));
if (enabled.containsKey(type)) addGlow(musicSlot);
- addButton(tauntSlot, new ShopItem(Material.NAME_TAG, "Taunts", new String[]{C.Bold + "", C.cDGreen + C.Italics + "Coming soon!"}, 1, false), new IButton()
- {
- @Override
- public void onClick(Player player, ClickType clickType)
- {
- player.sendMessage(F.main("Shop", "Coming soon!"));
- }
- });
+ type = GadgetType.TAUNT;
+ lore = getLore(ownedCount.get(type), maxCount.get(type), "Taunt your enemies or just show off. Use /taunt to have a good time!", "Visible in Games", enabled.get(type));
+ addButton(tauntSlot, new ShopItem(Material.NAME_TAG, "Taunts", lore, 1, false), new OpenTaunts(this, enabled.get(type)));
+ if (enabled.containsKey(type)) addGlow(tauntSlot);
type = GadgetType.WIN_EFFECT;
lore = getLore(ownedCount.get(type), maxCount.get(type), "Winning a game with your friends all good and dandy, but then being able to also show off awesome effects is even more fun!", "Usable in Lobbies", enabled.get(type));
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/TauntPage.java b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/TauntPage.java
index 3db625e5d..a519cfce8 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/TauntPage.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/cosmetic/ui/page/TauntPage.java
@@ -1,57 +1,57 @@
-package mineplex.core.cosmetic.ui.page;
-
-import java.util.List;
-
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.event.inventory.ClickType;
-
-import mineplex.core.account.CoreClientManager;
-import mineplex.core.common.util.C;
-import mineplex.core.cosmetic.CosmeticManager;
-import mineplex.core.cosmetic.ui.CosmeticShop;
-import mineplex.core.donation.DonationManager;
-import mineplex.core.gadget.types.Gadget;
-import mineplex.core.gadget.types.GadgetType;
-import mineplex.core.shop.item.IButton;
-import mineplex.core.shop.item.ShopItem;
-
-public class TauntPage extends GadgetPage
-{
-
-
- public TauntPage(CosmeticManager plugin, CosmeticShop shop, CoreClientManager clientManager, DonationManager donationManager, String name,
- Player player)
- {
- super(plugin, shop, clientManager, donationManager, name, player);
- }
-
- @Override
- protected void buildPage()
- {
- int slot = 10;
-
- List list = getPlugin().getGadgetManager().getGadgets(GadgetType.TAUNT);
- if(list != null)
- for (Gadget gadget : list)
- {
- addGadget(gadget, slot);
-
- if (getPlugin().getGadgetManager().getActive(getPlayer(), GadgetType.MORPH) == gadget)
- addGlow(slot);
-
- slot++;
-
- if (slot == 26)
- slot += 2;
- }
-
- addButton(4, new ShopItem(Material.BED, C.cGray + " \u21FD Go Back", new String[]{}, 1, false), new IButton()
- {
- public void onClick(Player player, ClickType clickType)
- {
- getShop().openPageForPlayer(getPlayer(), new Menu(getPlugin(), getShop(), getClientManager(), getDonationManager(), player));
- }
- });
- }
-}
+package mineplex.core.cosmetic.ui.page;
+
+import java.util.List;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import mineplex.core.account.CoreClientManager;
+import mineplex.core.common.util.C;
+import mineplex.core.cosmetic.CosmeticManager;
+import mineplex.core.cosmetic.ui.CosmeticShop;
+import mineplex.core.donation.DonationManager;
+import mineplex.core.gadget.types.Gadget;
+import mineplex.core.gadget.types.GadgetType;
+import mineplex.core.shop.item.IButton;
+import mineplex.core.shop.item.ShopItem;
+
+public class TauntPage extends GadgetPage
+{
+
+
+ public TauntPage(CosmeticManager plugin, CosmeticShop shop, CoreClientManager clientManager, DonationManager donationManager, String name,
+ Player player)
+ {
+ super(plugin, shop, clientManager, donationManager, name, player);
+ }
+
+ @Override
+ protected void buildPage()
+ {
+ int slot = 10;
+
+ List list = getPlugin().getGadgetManager().getGadgets(GadgetType.TAUNT);
+ if(list != null)
+ for (Gadget gadget : list)
+ {
+ addGadget(gadget, slot);
+
+ if (getPlugin().getGadgetManager().getActive(getPlayer(), GadgetType.TAUNT) == gadget)
+ addGlow(slot);
+
+ slot++;
+
+ if (slot == 26)
+ slot += 2;
+ }
+
+ addButton(4, new ShopItem(Material.BED, C.cGray + " \u21FD Go Back", new String[]{}, 1, false), new IButton()
+ {
+ public void onClick(Player player, ClickType clickType)
+ {
+ getShop().openPageForPlayer(getPlayer(), new Menu(getPlugin(), getShop(), getClientManager(), getDonationManager(), player));
+ }
+ });
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/GadgetManager.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/GadgetManager.java
index f2d007fb3..e0cc2219b 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/gadget/GadgetManager.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/GadgetManager.java
@@ -31,6 +31,7 @@ import mineplex.core.common.util.F;
import mineplex.core.common.util.NautHashMap;
import mineplex.core.common.util.UtilEnt;
import mineplex.core.common.util.UtilMath;
+import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTime;
import mineplex.core.disguise.DisguiseManager;
@@ -42,6 +43,7 @@ import mineplex.core.gadget.event.GadgetChangeEvent;
import mineplex.core.gadget.event.GadgetCollideEntityEvent;
import mineplex.core.gadget.event.GadgetEnableEvent;
import mineplex.core.gadget.event.PlayerToggleSwimEvent;
+import mineplex.core.gadget.event.TauntCommandEvent;
import mineplex.core.gadget.gadgets.arrowtrail.ArrowTrailHalloween;
import mineplex.core.gadget.gadgets.arrowtrail.candycane.ArrowTrailCandyCane;
import mineplex.core.gadget.gadgets.arrowtrail.cupidslove.ArrowTrailCupid;
@@ -168,6 +170,7 @@ import mineplex.core.gadget.gadgets.particle.shadow.ParticleFoot;
import mineplex.core.gadget.gadgets.particle.titan.ParticleTitan;
import mineplex.core.gadget.gadgets.particle.vampire.ParticleBlood;
import mineplex.core.gadget.gadgets.particle.wisdom.ParticleEnchant;
+import mineplex.core.gadget.gadgets.taunts.EternalTaunt;
import mineplex.core.gadget.gadgets.wineffect.WinEffectBabyChicken;
import mineplex.core.gadget.gadgets.wineffect.WinEffectFlames;
import mineplex.core.gadget.gadgets.wineffect.WinEffectHalloween;
@@ -207,6 +210,7 @@ import mineplex.core.gadget.types.MusicGadget;
import mineplex.core.gadget.types.OutfitGadget;
import mineplex.core.gadget.types.OutfitGadget.ArmorSlot;
import mineplex.core.gadget.types.ParticleGadget;
+import mineplex.core.gadget.types.TauntGadget;
import mineplex.core.gadget.types.WinEffectGadget;
import mineplex.core.hologram.HologramManager;
import mineplex.core.incognito.IncognitoManager;
@@ -531,6 +535,9 @@ public class GadgetManager extends MiniPlugin
// Balloons
//addGadget(new BabyCowBalloon(this));
+ // TAUNTS!!!
+ addGadget(new EternalTaunt(this));
+
for (GadgetType gadgetType : GadgetType.values())
{
if (!_gadgets.containsKey(gadgetType))
@@ -765,7 +772,10 @@ public class GadgetManager extends MiniPlugin
if (gadget instanceof WinEffectGadget)
continue;
- if(gadget instanceof GameModifierGadget)
+ if (gadget instanceof GameModifierGadget)
+ continue;
+
+ if (gadget instanceof TauntGadget)
continue;
for (Player player : UtilServer.getPlayers())
@@ -1239,4 +1249,56 @@ public class GadgetManager extends MiniPlugin
{
return _soulManager;
}
+
+ /**
+ * Handles taunt commands
+ * @param event
+ */
+ @EventHandler
+ public void onTauntCommand(TauntCommandEvent event)
+ {
+ Player player = event.getPlayer();
+
+ Gadget gadget = getActive(player, GadgetType.TAUNT);
+
+ if (gadget == null)
+ {
+ event.setState(TauntCommandEvent.TauntState.NO_TAUNT);
+ UtilPlayer.message(player, F.main("Taunt", event.getState().getMessage()));
+ return;
+ }
+
+ if (!(gadget instanceof TauntGadget))
+ {
+ event.setState(TauntCommandEvent.TauntState.NO_TAUNT);
+ UtilPlayer.message(player, F.main("Taunt", event.getState().getMessage()));
+ return;
+ }
+
+ TauntGadget taunt = (TauntGadget) gadget;
+
+ if (!event.isGameInProgress() && event.getState().equals(TauntCommandEvent.TauntState.NONE))
+ event.setState(TauntCommandEvent.TauntState.NOT_IN_GAME);
+
+ if (taunt.isGameDisabled(event.getGameType()) && event.getState().equals(TauntCommandEvent.TauntState.NONE))
+ event.setState(TauntCommandEvent.TauntState.GAME_DISABLED);
+
+ if (!event.isAlive() && event.getState().equals(TauntCommandEvent.TauntState.NONE))
+ event.setState(TauntCommandEvent.TauntState.NOT_ALIVE);
+
+ if (event.isSpectator() && event.getState().equals(TauntCommandEvent.TauntState.NONE))
+ event.setState(TauntCommandEvent.TauntState.SPECTATOR);
+
+ if (event.isInPvp(taunt.getPvpCooldown()) && !taunt.canPlayWithPvp()
+ && event.getState().equals(TauntCommandEvent.TauntState.NONE))
+ event.setState(TauntCommandEvent.TauntState.PVP);
+
+ if (event.getState() != TauntCommandEvent.TauntState.NONE)
+ {
+ UtilPlayer.message(player, F.main("Taunt", event.getState().getMessage()));
+ return;
+ }
+
+ taunt.start(player);
+ }
}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/event/TauntCommandEvent.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/event/TauntCommandEvent.java
new file mode 100644
index 000000000..fc6e643f3
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/event/TauntCommandEvent.java
@@ -0,0 +1,106 @@
+package mineplex.core.gadget.event;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import mineplex.core.common.util.UtilTime;
+import mineplex.core.gadget.gadgets.taunts.GameType;
+
+public class TauntCommandEvent extends Event
+{
+
+ private static final HandlerList handlers = new HandlerList();
+
+ private Player _player;
+ private boolean _gameInProgress;
+ private boolean _alive;
+ private boolean _spectator;
+ private long _lastPvp;
+ private TauntState _state = TauntState.NONE;
+ private GameType _gameType;
+
+ public TauntCommandEvent(Player player, boolean gameInProgress, boolean alive, boolean spectator, long lastPvp, GameType gameType)
+ {
+ _player = player;
+ _gameInProgress = gameInProgress;
+ _alive = alive;
+ _spectator = spectator;
+ _lastPvp = lastPvp;
+ _gameType = gameType;
+ }
+
+ public Player getPlayer()
+ {
+ return _player;
+ }
+
+ public boolean isGameInProgress()
+ {
+ return _gameInProgress;
+ }
+
+ public boolean isAlive()
+ {
+ return _alive;
+ }
+
+ public boolean isSpectator()
+ {
+ return _spectator;
+ }
+
+ public boolean isInPvp(long cooldown)
+ {
+ return !UtilTime.elapsed(_lastPvp, cooldown);
+ }
+
+ public TauntState getState()
+ {
+ return _state;
+ }
+
+ public GameType getGameType()
+ {
+ return _gameType;
+ }
+
+ public void setState(TauntState state)
+ {
+ _state = state;
+ }
+
+ public HandlerList getHandlers()
+ {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList()
+ {
+ return handlers;
+ }
+
+ public enum TauntState
+ {
+ NONE(""),
+ NO_TAUNT("You have no active taunts!"),
+ NOT_IN_GAME("You are not in a game!"),
+ NOT_ALIVE("You are not playing the game!"),
+ SPECTATOR("You can't run this as a spectator!"),
+ PVP("You can't run this while in pvp!"),
+ GAME_DISABLED("Taunts are disabled in this game!");
+
+ private String _message;
+
+ TauntState(String message)
+ {
+ _message = message;
+ }
+
+ public String getMessage()
+ {
+ return _message;
+ }
+ }
+
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/taunts/EternalTaunt.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/taunts/EternalTaunt.java
new file mode 100644
index 000000000..f34726000
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/taunts/EternalTaunt.java
@@ -0,0 +1,153 @@
+package mineplex.core.gadget.gadgets.taunts;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Color;
+import org.bukkit.FireworkEffect;
+import org.bukkit.Material;
+import org.bukkit.Sound;
+import org.bukkit.entity.Item;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerPickupItemEvent;
+import org.bukkit.util.Vector;
+
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.LineFormat;
+import mineplex.core.common.util.UtilAction;
+import mineplex.core.common.util.UtilFirework;
+import mineplex.core.common.util.UtilText;
+import mineplex.core.disguise.disguises.DisguiseSkeleton;
+import mineplex.core.events.EnableArcadeSpawnEvent;
+import mineplex.core.gadget.GadgetManager;
+import mineplex.core.gadget.gadgets.morph.managers.UtilMorph;
+import mineplex.core.gadget.types.TauntGadget;
+import mineplex.core.itemstack.ItemStackFactory;
+import mineplex.core.recharge.Recharge;
+import mineplex.core.updater.UpdateType;
+
+public class EternalTaunt extends TauntGadget
+{
+
+ private static final int COOLDOWN = 30000;
+ private static final int PVP_COOLDOWN = 10000;
+
+ private Map> _clocks = new HashMap<>();
+
+ public EternalTaunt(GadgetManager manager)
+ {
+ super(manager, "Eternal Taunt", UtilText.splitLinesToArray(new String[]{C.cGray + "Although the Eternal has been around forever, he waited to long for a worthy opponent and he turned to bones.",
+ "",
+ C.cWhite + "Use /taunt in game to show how long you've been waiting.",
+ C.cRed + "Cannot be used while in PvP!"}, LineFormat.LORE),
+ -15, Material.WATCH, (byte) 0);
+ setCanPlayWithPvp(false);
+ setPvpCooldown(PVP_COOLDOWN);
+ setShouldPlay(true);
+ setEventType(UpdateType.FAST);
+ addDisabledGames(GameType.SMASH, GameType.SMASHTEAMS, GameType.SMASHDOMINATION);
+ }
+
+ @Override
+ public void disableCustom(Player player, boolean message)
+ {
+ finish(player);
+ }
+
+ @Override
+ public void onStart(Player player)
+ {
+ if (!Recharge.Instance.use(player, getName(), COOLDOWN, true, false, "Cosmetics"))
+ return;
+ UtilFirework.playFirework(player.getLocation(), FireworkEffect.builder().with(FireworkEffect.Type.BALL_LARGE).withColor(Color.fromRGB(255, 175, 175)).withFade(Color.RED).build());
+
+ _clocks.put(player.getUniqueId(), new ArrayList<>());
+
+ Bukkit.broadcastMessage(F.main("Taunt", F.name(player.getName()) + " waited so long they turned to bones."));
+
+ DisguiseSkeleton disguiseSkeleton = new DisguiseSkeleton(player);
+ UtilMorph.disguise(player, disguiseSkeleton, Manager);
+ }
+
+ @Override
+ public void onPlay(Player player)
+ {
+ if (!_clocks.containsKey(player.getUniqueId()))
+ return;
+
+ int i = getPlayerTicks(player);
+
+ EnableArcadeSpawnEvent enableArcadeSpawnEvent = new EnableArcadeSpawnEvent(true);
+ Bukkit.getPluginManager().callEvent(enableArcadeSpawnEvent);
+
+ Item clock = player.getWorld().dropItem(player.getLocation().add(0.5, 1.5, 0.5),
+ ItemStackFactory.Instance.CreateStack(Material.WATCH, (byte) 0, 1, " " + i));
+
+ enableArcadeSpawnEvent = new EnableArcadeSpawnEvent(false);
+ Bukkit.getPluginManager().callEvent(enableArcadeSpawnEvent);
+
+ Vector vel = new Vector(Math.sin(i * 9/5d), 0, Math.cos(i * 9/5d));
+ UtilAction.velocity(clock, vel, Math.abs(Math.sin(i * 12/3000d)), false, 0, 0.2 + Math.abs(Math.cos(i * 12/3000d))*0.6, 1, false);
+
+ _clocks.get(player.getUniqueId()).add(clock);
+
+ if (_clocks.get(player.getUniqueId()).size() >= 5)
+ {
+ _clocks.get(player.getUniqueId()).get(0).remove();
+ _clocks.get(player.getUniqueId()).remove(0);
+ }
+
+ if (i % 2 == 0)
+ player.playSound(player.getLocation(), Sound.CLICK, 1f, 1f);
+ else
+ player.playSound(player.getLocation(), Sound.CLICK, 0.5f, 0.5f);
+
+ if (i >= 15)
+ {
+ finish(player);
+ }
+ }
+
+ @Override
+ public void onFinish(Player player)
+ {
+ UtilMorph.undisguise(player, Manager.getDisguiseManager());
+ if (_clocks.containsKey(player.getUniqueId()))
+ {
+ _clocks.get(player.getUniqueId()).forEach(c -> c.remove());
+ _clocks.get(player.getUniqueId()).clear();
+ _clocks.remove(player.getUniqueId());
+ }
+ }
+
+ @EventHandler
+ public void titanOwner(PlayerJoinEvent event)
+ {
+ if (Manager.getClientManager().Get(event.getPlayer()).GetRank().has(Rank.ETERNAL))
+ {
+ Manager.getDonationManager().Get(event.getPlayer()).addOwnedUnknownSalesPackage(getName());
+ }
+ }
+
+ @EventHandler
+ public void onClockPickup(PlayerPickupItemEvent event)
+ {
+ for (List- clocks : _clocks.values())
+ {
+ for (Item item : clocks)
+ {
+ if (event.getItem().equals(item))
+ event.setCancelled(true);
+ }
+ }
+ }
+
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/taunts/GameType.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/taunts/GameType.java
new file mode 100644
index 000000000..26e0c607c
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/gadgets/taunts/GameType.java
@@ -0,0 +1,84 @@
+package mineplex.core.gadget.gadgets.taunts;
+
+public enum GameType
+{
+
+ BACONBRAWL,
+ BARBARIANS,
+ BASKETBALL,
+ BOSSBATTLES,
+ BRIDGE,
+ CASTLESIEGE,
+ CHAMPIONSCTF,
+ CHAMPIONSDOMINATE,
+ CHAMPIONSTDM,
+ CHRISTMAS,
+ DEATHTAG,
+ DRAGONESCAPE,
+ DRAGONESCAPETEAMS,
+ DRAGONRIDERS,
+ DRAGONS,
+ DRAGONSTEAMS,
+ DRAW,
+ ELYTRARINGS,
+ EVOLUTION,
+ GRAVITY,
+ HALLOWEEN,
+ HALLOWEEN2016,
+ HIDESEEK,
+ HOLEINTHEWALL,
+ HORSE,
+ LOBBERS,
+ MICRO,
+ MILKCOW,
+ MINESTRIKE,
+ BAWKBAWKBATTLES,
+ MINECRAFTLEAGUE,
+ OLDMINEWARE,
+ PAINTBALL,
+ QUIVER,
+ QUIVERPAYLOAD,
+ QUIVERTEAMS,
+ RUNNER,
+ SEARCHANDDESTROY,
+ SHEEP,
+ TYPEWARS,
+ SMASH,
+ SMASHDOMINATION,
+ SMASHTEAMS,
+ SNAKE,
+ SNEAKYASSASSINS,
+ SNOWFIGHT,
+ SPEEDBUILDERS,
+ SPLEEF,
+ SPLEEFTEAMS,
+ SQUIDSHOOTER,
+ STACKER,
+ SURVIVALGAMES,
+ SURVIVALGAMESTEAMS,
+ TUG,
+ TURFWARS,
+ UHC,
+ UHCSOLO,
+ UHCSOLOSPEED,
+ UHCTEAMSSPEED,
+ WITHERASSAULT,
+ WIZARDS,
+ ZOMBIESURVIVAL,
+ BUILD,
+ BUILDMAVERICKS,
+ CARDS,
+ SKYWARS,
+ SKYWARSTEAMS,
+ MONSTERMAZE,
+ MONSTERLEAGUE,
+ GLADIATORS,
+ SKYFALL,
+ SKYFALLTEAMS,
+ BOUNCYBALLS,
+ VALENTINES,
+ EVENT,
+ BRAWL,
+ NONE
+
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/gadget/types/TauntGadget.java b/Plugins/Mineplex.Core/src/mineplex/core/gadget/types/TauntGadget.java
new file mode 100644
index 000000000..f1bce90be
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/gadget/types/TauntGadget.java
@@ -0,0 +1,156 @@
+package mineplex.core.gadget.types;
+
+import java.time.YearMonth;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+
+import mineplex.core.gadget.GadgetManager;
+import mineplex.core.gadget.gadgets.taunts.GameType;
+import mineplex.core.updater.UpdateType;
+import mineplex.core.updater.event.UpdateEvent;
+
+/**
+ * Handles Taunts
+ */
+public abstract class TauntGadget extends Gadget
+{
+
+ /** Sets if this specific taunt can be used while in PvP */
+ private boolean _canPlayWithPvp = false;
+ /** Sets the cooldown for pvp */
+ private long _pvpCooldown = 0;
+ /** Sets if this taunt needs to run on updates */
+ private boolean _shouldPlay = false;
+ /** Sets when the taunt will run, if set above */
+ private UpdateType _updateType = UpdateType.TICK;
+ /** List of games where this item is disabled */
+ private List _disabledGames = new ArrayList<>();
+ /** The ticks that passed since the player started the effect */
+ private Map _ticksPerPlayer = new HashMap<>();
+
+ /**
+ * @param manager The normal GadgetManager
+ * @param name The name of the item
+ * @param desc The lore/description of the item
+ * @param cost The cost of the item
+ * @param mat The display material of the item
+ * @param data The display data of the item
+ * @param alternativeSalesPackageNames Possible alternative names for this package
+ */
+ public TauntGadget(GadgetManager manager, String name, String[] desc, int cost, Material mat, byte data,
+ String... alternativeSalesPackageNames)
+ {
+ super(manager, GadgetType.TAUNT, name, desc, cost, mat, data, 1, alternativeSalesPackageNames);
+ }
+
+ /**
+ * @param manager The normal GadgetManager
+ * @param name The name of the item
+ * @param desc The lore/description of the item
+ * @param cost The cost of the item
+ * @param mat The display material of the item
+ * @param data The display data of the item
+ * @param yearMonth The year and month of this item, if it is a PPC item
+ * @param alternativeSalesPackageNames Possible alternative names for this package
+ */
+ public TauntGadget(GadgetManager manager, String name, String[] desc, int cost, Material mat, byte data,
+ YearMonth yearMonth, String... alternativeSalesPackageNames)
+ {
+ super(manager, GadgetType.TAUNT, name, desc, cost, mat, data, yearMonth, 1, alternativeSalesPackageNames);
+ }
+
+ public void start(Player player)
+ {
+ onStart(player);
+ _ticksPerPlayer.put(player.getUniqueId(), 0);
+ }
+
+ public abstract void onStart(Player player);
+
+ public void play(Player player)
+ {
+ onPlay(player);
+ int ticks = getPlayerTicks(player) + 1;
+ _ticksPerPlayer.put(player.getUniqueId(), ticks);
+ }
+
+ public abstract void onPlay(Player player);
+
+ public void finish(Player player)
+ {
+ onFinish(player);
+ _ticksPerPlayer.remove(player.getUniqueId());
+ }
+
+ public abstract void onFinish(Player player);
+
+ public void setCanPlayWithPvp(boolean canPlayWithPvp)
+ {
+ _canPlayWithPvp = canPlayWithPvp;
+ }
+
+ public void setPvpCooldown(long pvpCooldown)
+ {
+ _pvpCooldown = pvpCooldown;
+ }
+
+ public void setShouldPlay(boolean shouldPlay)
+ {
+ _shouldPlay = shouldPlay;
+ }
+
+ public void setEventType(UpdateType updateType)
+ {
+ _updateType = updateType;
+ }
+
+ public void addDisabledGames(GameType... disabledGames)
+ {
+ _disabledGames.addAll(Arrays.asList(disabledGames));
+ }
+
+ public boolean canPlayWithPvp()
+ {
+ return _canPlayWithPvp;
+ }
+
+ public boolean isGameDisabled(GameType gameType)
+ {
+ return _disabledGames.contains(gameType);
+ }
+
+ public long getPvpCooldown()
+ {
+ return _pvpCooldown;
+ }
+
+ public int getPlayerTicks(Player player)
+ {
+ return (_ticksPerPlayer.containsKey(player.getUniqueId())) ? _ticksPerPlayer.get(player.getUniqueId()) : -1;
+ }
+
+ @EventHandler
+ public void onUpdate(UpdateEvent event)
+ {
+ if (!_shouldPlay)
+ return;
+
+ if (event.getType() != _updateType)
+ return;
+
+ for (Player player : getActive())
+ {
+ if (_ticksPerPlayer.containsKey(player.getUniqueId()))
+ play(player);
+ }
+ }
+
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java b/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java
index 30467d6f7..585e37864 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java
@@ -10,96 +10,96 @@ import org.bukkit.Material;
public enum GameDisplay
{
//Mini
- BaconBrawl("Bacon Brawl", Material.PORK, (byte)0, GameCategory.ARCADE, 1),
- Barbarians("A Barbarians Life", Material.WOOD_AXE, (byte)0, GameCategory.EXTRA, 2),
- BossBattles("Boss Battles", Material.SKULL_ITEM, (byte) 0, GameCategory.EVENT, 55),
- Bridge("The Bridges", Material.IRON_PICKAXE, (byte)0, GameCategory.SURVIVAL, 3),
- CastleSiege("Castle Siege", Material.DIAMOND_CHESTPLATE, (byte)0, GameCategory.CLASSICS, 4),
- ChampionsDominate("Champions Domination", "Champions", Material.BEACON, (byte)0, GameCategory.CHAMPIONS, 6),
- ChampionsTDM("Champions TDM", "Champions", Material.GOLD_SWORD, (byte)0, GameCategory.CHAMPIONS, 5),
- Christmas("Christmas Chaos", Material.SNOW_BALL, (byte)0, GameCategory.CLASSICS, 8),
- DeathTag("Death Tag", Material.SKULL_ITEM, (byte)0, GameCategory.ARCADE, 9),
- DragonEscape("Dragon Escape", Material.DRAGON_EGG, (byte)0, GameCategory.ARCADE, 10),
- DragonEscapeTeams("Dragon Escape Teams", Material.DRAGON_EGG, (byte)0, GameCategory.TEAM_VARIANT, 11),
- DragonRiders("Dragon Riders", Material.DRAGON_EGG, (byte)0, GameCategory.ARCADE, 12),
- Dragons("Dragons", Material.ENDER_STONE, (byte)0, GameCategory.ARCADE, 13),
- DragonsTeams("Dragons Teams", Material.DRAGON_EGG, (byte)0, GameCategory.TEAM_VARIANT, 14),
- Draw("Draw My Thing", Material.BOOK_AND_QUILL, (byte)0, GameCategory.CLASSICS, 15),
- ElytraRings("Elytra Rings", Material.ELYTRA, (byte) 0, GameCategory.CLASSICS, 61),
- Evolution("Evolution", Material.EMERALD, (byte)0, GameCategory.ARCADE, 16),
- Gravity("Gravity", Material.ENDER_PORTAL_FRAME, (byte)0, GameCategory.EXTRA, 18),
- Halloween("Halloween Horror", Material.PUMPKIN, (byte)0, GameCategory.CLASSICS, 19),
- Halloween2016("Pumpkin's Revenge", Material.PUMPKIN, (byte)0, GameCategory.CLASSICS, 63),
- HideSeek("Block Hunt", Material.GRASS, (byte)0, GameCategory.CLASSICS, 20),
- HoleInTheWall("Hole in the Wall", Material.STAINED_GLASS, (byte) 2, GameCategory.ARCADE, 52),
- Horse("Horseback", Material.IRON_BARDING, (byte)0, GameCategory.ARCADE, 21),
+ BaconBrawl("Bacon Brawl", Material.PORK, (byte)0, GameCategory.ARCADE, 1, true),
+ Barbarians("A Barbarians Life", Material.WOOD_AXE, (byte)0, GameCategory.EXTRA, 2, false),
+ BossBattles("Boss Battles", Material.SKULL_ITEM, (byte) 0, GameCategory.EVENT, 55, false),
+ Bridge("The Bridges", Material.IRON_PICKAXE, (byte)0, GameCategory.SURVIVAL, 3, true),
+ CastleSiege("Castle Siege", Material.DIAMOND_CHESTPLATE, (byte)0, GameCategory.CLASSICS, 4, true),
+ ChampionsDominate("Champions Domination", "Champions", Material.BEACON, (byte)0, GameCategory.CHAMPIONS, 6, true),
+ ChampionsTDM("Champions TDM", "Champions", Material.GOLD_SWORD, (byte)0, GameCategory.CHAMPIONS, 5, true),
+ Christmas("Christmas Chaos", Material.SNOW_BALL, (byte)0, GameCategory.CLASSICS, 8, false),
+ DeathTag("Death Tag", Material.SKULL_ITEM, (byte)0, GameCategory.ARCADE, 9, true),
+ DragonEscape("Dragon Escape", Material.DRAGON_EGG, (byte)0, GameCategory.ARCADE, 10, true),
+ DragonEscapeTeams("Dragon Escape Teams", Material.DRAGON_EGG, (byte)0, GameCategory.TEAM_VARIANT, 11, false),
+ DragonRiders("Dragon Riders", Material.DRAGON_EGG, (byte)0, GameCategory.ARCADE, 12, false),
+ Dragons("Dragons", Material.ENDER_STONE, (byte)0, GameCategory.ARCADE, 13, true),
+ DragonsTeams("Dragons Teams", Material.DRAGON_EGG, (byte)0, GameCategory.TEAM_VARIANT, 14, false),
+ Draw("Draw My Thing", Material.BOOK_AND_QUILL, (byte)0, GameCategory.CLASSICS, 15, true),
+ ElytraRings("Elytra Rings", Material.ELYTRA, (byte) 0, GameCategory.CLASSICS, 61, false),
+ Evolution("Evolution", Material.EMERALD, (byte)0, GameCategory.ARCADE, 16, true),
+ Gravity("Gravity", Material.ENDER_PORTAL_FRAME, (byte)0, GameCategory.EXTRA, 18, false),
+ Halloween("Halloween Horror", Material.PUMPKIN, (byte)0, GameCategory.CLASSICS, 19, false),
+ Halloween2016("Pumpkin's Revenge", Material.PUMPKIN, (byte)0, GameCategory.CLASSICS, 63, false),
+ HideSeek("Block Hunt", Material.GRASS, (byte)0, GameCategory.CLASSICS, 20, true),
+ HoleInTheWall("Hole in the Wall", Material.STAINED_GLASS, (byte) 2, GameCategory.ARCADE, 52, false),
+ Horse("Horseback", Material.IRON_BARDING, (byte)0, GameCategory.ARCADE, 21, false),
- Micro("Micro Battle", Material.LAVA_BUCKET, (byte)0, GameCategory.ARCADE, 24),
- MilkCow("Milk the Cow", Material.MILK_BUCKET, (byte)0, GameCategory.ARCADE, 27),
- MineStrike("MineStrike", Material.TNT, (byte)0, GameCategory.CHAMPIONS, 25),// Temp set to CHAMPIONS to fix UI bug
- BawkBawkBattles("Bawk Bawk Battles", Material.EGG, (byte)0, GameCategory.CLASSICS, 26),
- OldMineWare("Old MineWare", Material.PAPER, (byte)0, GameCategory.EXTRA, 26),
- Paintball("Super Paintball", Material.ENDER_PEARL, (byte)0, GameCategory.ARCADE, 28),
- Quiver("One in the Quiver", Material.ARROW, (byte)0, GameCategory.ARCADE, 29),
- QuiverTeams("One in the Quiver Teams", Material.ARROW, (byte)0, GameCategory.TEAM_VARIANT, 30),
- Runner("Runner", Material.LEATHER_BOOTS, (byte)0, GameCategory.ARCADE, 31),
- SearchAndDestroy("Search and Destroy", Material.TNT, (byte)0, GameCategory.SURVIVAL, 32),
- Sheep("Sheep Quest", Material.WOOL, (byte)4, GameCategory.ARCADE, 33),
+ Micro("Micro Battle", Material.LAVA_BUCKET, (byte)0, GameCategory.ARCADE, 24, true),
+ MilkCow("Milk the Cow", Material.MILK_BUCKET, (byte)0, GameCategory.ARCADE, 27, false),
+ MineStrike("MineStrike", Material.TNT, (byte)0, GameCategory.CHAMPIONS, 25, true),// Temp set to CHAMPIONS to fix UI bug
+ BawkBawkBattles("Bawk Bawk Battles", Material.EGG, (byte)0, GameCategory.CLASSICS, 26, true),
+ OldMineWare("Old MineWare", Material.PAPER, (byte)0, GameCategory.EXTRA, 26, false),
+ Paintball("Super Paintball", Material.ENDER_PEARL, (byte)0, GameCategory.ARCADE, 28, true),
+ Quiver("One in the Quiver", Material.ARROW, (byte)0, GameCategory.ARCADE, 29, true),
+ QuiverTeams("One in the Quiver Teams", Material.ARROW, (byte)0, GameCategory.TEAM_VARIANT, 30, false),
+ Runner("Runner", Material.LEATHER_BOOTS, (byte)0, GameCategory.ARCADE, 31, true),
+ SearchAndDestroy("Search and Destroy", Material.TNT, (byte)0, GameCategory.SURVIVAL, 32, false),
+ Sheep("Sheep Quest", Material.WOOL, (byte)4, GameCategory.ARCADE, 33, true),
- Smash("Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.CLASSICS, 34),
- SmashDomination("Super Smash Mobs Domination", "Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.EXTRA, 36),
- SmashTeams("Super Smash Mobs Teams", "Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.TEAM_VARIANT, 35),
- Snake("Snake", Material.WOOL, (byte)0, GameCategory.ARCADE, 37),
- SneakyAssassins("Sneaky Assassins", Material.INK_SACK, (byte)0, GameCategory.ARCADE, 38),
- SnowFight("Snow Fight", Material.SNOW_BALL, (byte)0, GameCategory.EXTRA, 39),
- Spleef("Super Spleef", Material.IRON_SPADE, (byte)0, GameCategory.ARCADE, 40),
- SpleefTeams("Super Spleef Teams", Material.IRON_SPADE, (byte)0, GameCategory.TEAM_VARIANT, 41),
- SquidShooter("Squid Shooter", Material.FIREWORK_CHARGE, (byte)0, GameCategory.ARCADE, 43),
- Stacker("Super Stacker", Material.BOWL, (byte)0, GameCategory.ARCADE, 42),
- SurvivalGames("Survival Games", Material.IRON_SWORD, (byte)0, GameCategory.SURVIVAL, 22),
- SurvivalGamesTeams("Survival Games Teams", "Survival Games", Material.IRON_SWORD, (byte)0, GameCategory.TEAM_VARIANT, 23),
- Tug("Tug of Wool", Material.WHEAT, (byte)0, GameCategory.ARCADE, 44),
- TurfWars("Turf Wars", Material.STAINED_CLAY, (byte)14, GameCategory.ARCADE, 45),
- UHC("Ultra Hardcore", Material.GOLDEN_APPLE, (byte)0, GameCategory.TEAM_VARIANT, 46),
- UHCSolo("Ultra Hardcore Solo", "Ultra Hardcore", Material.GOLDEN_APPLE, (byte)0, GameCategory.SURVIVAL, 46),
- UHCSoloSpeed("Ultra Hardcore Solo Speed", "Ultra Hardcore", Material.GOLDEN_APPLE, (byte)0, GameCategory.SURVIVAL, 67),
- UHCTeamsSpeed("Ultra Hardcore Teams Speed", "Ultra Hardcore", Material.GOLDEN_APPLE, (byte)0, GameCategory.TEAM_VARIANT, 67),
- WitherAssault("Wither Assault", Material.SKULL_ITEM, (byte)1, GameCategory.ARCADE, 47),
- Wizards("Wizards", Material.BLAZE_ROD, (byte)0, GameCategory.SURVIVAL, 48),
- ZombieSurvival("Zombie Survival", Material.SKULL_ITEM, (byte)2, GameCategory.SURVIVAL, 49),
+ Smash("Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.CLASSICS, 34, true),
+ SmashDomination("Super Smash Mobs Domination", "Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.EXTRA, 36, false),
+ SmashTeams("Super Smash Mobs Teams", "Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.TEAM_VARIANT, 35, false),
+ Snake("Snake", Material.WOOL, (byte)0, GameCategory.ARCADE, 37, true),
+ SneakyAssassins("Sneaky Assassins", Material.INK_SACK, (byte)0, GameCategory.ARCADE, 38, true),
+ SnowFight("Snow Fight", Material.SNOW_BALL, (byte)0, GameCategory.EXTRA, 39, false),
+ Spleef("Super Spleef", Material.IRON_SPADE, (byte)0, GameCategory.ARCADE, 40, true),
+ SpleefTeams("Super Spleef Teams", Material.IRON_SPADE, (byte)0, GameCategory.TEAM_VARIANT, 41, false),
+ SquidShooter("Squid Shooter", Material.FIREWORK_CHARGE, (byte)0, GameCategory.ARCADE, 43, false),
+ Stacker("Super Stacker", Material.BOWL, (byte)0, GameCategory.ARCADE, 42, false),
+ SurvivalGames("Survival Games", Material.IRON_SWORD, (byte)0, GameCategory.SURVIVAL, 22, true),
+ SurvivalGamesTeams("Survival Games Teams", "Survival Games", Material.IRON_SWORD, (byte)0, GameCategory.TEAM_VARIANT, 23, false),
+ Tug("Tug of Wool", Material.WHEAT, (byte)0, GameCategory.ARCADE, 44, false),
+ TurfWars("Turf Wars", Material.STAINED_CLAY, (byte)14, GameCategory.ARCADE, 45, true),
+ UHC("Ultra Hardcore", Material.GOLDEN_APPLE, (byte)0, GameCategory.TEAM_VARIANT, 46, true),
+ UHCSolo("Ultra Hardcore Solo", "Ultra Hardcore", Material.GOLDEN_APPLE, (byte)0, GameCategory.SURVIVAL, 46, false),
+ UHCSoloSpeed("Ultra Hardcore Solo Speed", "Ultra Hardcore", Material.GOLDEN_APPLE, (byte)0, GameCategory.SURVIVAL, 67, false),
+ UHCTeamsSpeed("Ultra Hardcore Teams Speed", "Ultra Hardcore", Material.GOLDEN_APPLE, (byte)0, GameCategory.TEAM_VARIANT, 67, false),
+ WitherAssault("Wither Assault", Material.SKULL_ITEM, (byte)1, GameCategory.ARCADE, 47, true),
+ Wizards("Wizards", Material.BLAZE_ROD, (byte)0, GameCategory.SURVIVAL, 48, true),
+ ZombieSurvival("Zombie Survival", Material.SKULL_ITEM, (byte)2, GameCategory.SURVIVAL, 49, false),
- Build("Master Builders", Material.WOOD, (byte)0, GameCategory.CLASSICS, 50),
- BuildMavericks("Mavericks Master Builders", Material.WOOD, (byte)3, GameCategory.CLASSICS, 63),
- Cards("Craft Against Humanity", Material.MAP, (byte)0, GameCategory.CLASSICS, 51),
- Skywars("Skywars", Material.FEATHER, (byte) 0, GameCategory.SURVIVAL, 52),
- SkywarsTeams("Skywars Teams", "Skywars", Material.FEATHER, (byte)0, GameCategory.TEAM_VARIANT, 53),
- MonsterMaze("Monster Maze", Material.ROTTEN_FLESH, (byte)0, GameCategory.ARCADE, 55),
- MonsterLeague("Monster League", Material.MINECART, (byte)0, GameCategory.ARCADE, 56),
+ Build("Master Builders", Material.WOOD, (byte)0, GameCategory.CLASSICS, 50, true),
+ BuildMavericks("Mavericks Master Builders", Material.WOOD, (byte)3, GameCategory.CLASSICS, 63, false),
+ Cards("Craft Against Humanity", Material.MAP, (byte)0, GameCategory.CLASSICS, 51, false),
+ Skywars("Skywars", Material.FEATHER, (byte) 0, GameCategory.SURVIVAL, 52, true),
+ SkywarsTeams("Skywars Teams", "Skywars", Material.FEATHER, (byte)0, GameCategory.TEAM_VARIANT, 53, false),
+ MonsterMaze("Monster Maze", Material.ROTTEN_FLESH, (byte)0, GameCategory.ARCADE, 55, true),
+ MonsterLeague("Monster League", Material.MINECART, (byte)0, GameCategory.ARCADE, 56, false),
- Lobbers("Bomb Lobbers", Material.FIREBALL, (byte) 0, GameCategory.ARCADE, 54),
+ Lobbers("Bomb Lobbers", Material.FIREBALL, (byte) 0, GameCategory.ARCADE, 54, true),
- Minecraft_League("MC League", Material.DIAMOND_SWORD, (byte)0, GameCategory.SURVIVAL, 62),
+ Minecraft_League("MC League", Material.DIAMOND_SWORD, (byte)0, GameCategory.SURVIVAL, 62, false),
- ChampionsCTF("Champions CTF", "Champions", Material.BANNER, DyeColor.RED.getDyeData(), GameCategory.CHAMPIONS, 56),
+ ChampionsCTF("Champions CTF", "Champions", Material.BANNER, DyeColor.RED.getDyeData(), GameCategory.CHAMPIONS, 56, true),
- BouncyBalls("Bouncy Balls", Material.SLIME_BALL, (byte)0, GameCategory.ARCADE, 57),
- Gladiators("Gladiators", Material.IRON_SWORD, (byte)0, GameCategory.ARCADE, 58),
- TypeWars("Type Wars", Material.NAME_TAG, (byte) 0, GameCategory.CLASSICS, 59),
+ BouncyBalls("Bouncy Balls", Material.SLIME_BALL, (byte)0, GameCategory.ARCADE, 57, false),
+ Gladiators("Gladiators", Material.IRON_SWORD, (byte)0, GameCategory.ARCADE, 58, true),
+ TypeWars("Type Wars", Material.NAME_TAG, (byte) 0, GameCategory.CLASSICS, 59, false),
- SpeedBuilders("Speed Builders", Material.QUARTZ_BLOCK, (byte) 0, GameCategory.CLASSICS, 60),
+ SpeedBuilders("Speed Builders", Material.QUARTZ_BLOCK, (byte) 0, GameCategory.CLASSICS, 60, true),
- Valentines("Valentines Vendetta", Material.LEATHER, (byte)0, GameCategory.EXTRA, 61),
+ Valentines("Valentines Vendetta", Material.LEATHER, (byte)0, GameCategory.EXTRA, 61, false),
- Skyfall("Skyfall", Material.DIAMOND_BOOTS, (byte)0, GameCategory.SURVIVAL, 62),
- SkyfallTeams("Skyfall Teams", Material.DIAMOND_BOOTS, (byte)0, GameCategory.SURVIVAL, 65),
+ Skyfall("Skyfall", Material.DIAMOND_BOOTS, (byte)0, GameCategory.SURVIVAL, 62, true),
+ SkyfallTeams("Skyfall Teams", Material.DIAMOND_BOOTS, (byte)0, GameCategory.SURVIVAL, 65, false),
- Basketball("Hoops", Material.SLIME_BALL, (byte)0, GameCategory.EXTRA, 63),
+ Basketball("Hoops", Material.SLIME_BALL, (byte)0, GameCategory.EXTRA, 63, false),
- QuiverPayload("One in the Quiver Payload", Material.ARROW, (byte)0, GameCategory.ARCADE, 64),
+ QuiverPayload("One in the Quiver Payload", Material.ARROW, (byte)0, GameCategory.ARCADE, 64, false),
- Event("Mineplex Event", Material.CAKE, (byte)0, GameCategory.EVENT, 999),
+ Event("Mineplex Event", Material.CAKE, (byte)0, GameCategory.EVENT, 999, false),
- Brawl("Brawl", Material.DIAMOND, (byte) 0, GameCategory.EVENT, 998);
+ Brawl("Brawl", Material.DIAMOND, (byte) 0, GameCategory.EVENT, 998, false);
String _name;
String _lobbyName;
@@ -109,13 +109,16 @@ public enum GameDisplay
private int _gameId; // Unique identifying id for this gamemode (used for statistics)
public int getGameId() { return _gameId; }
+
+ private boolean _communityFavorite;
+ public boolean isCommunityFavoriteOption() { return _communityFavorite; }
- GameDisplay(String name, Material mat, byte data, GameCategory gameCategory, int gameId)
+ GameDisplay(String name, Material mat, byte data, GameCategory gameCategory, int gameId, boolean communityFavorite)
{
- this(name, name, mat, data, gameCategory, gameId);
+ this(name, name, mat, data, gameCategory, gameId, communityFavorite);
}
- GameDisplay(String name, String lobbyName, Material mat, byte data, GameCategory gameCategory, int gameId)
+ GameDisplay(String name, String lobbyName, Material mat, byte data, GameCategory gameCategory, int gameId, boolean communityFavorite)
{
_name = name;
_lobbyName = lobbyName;
@@ -123,6 +126,7 @@ public enum GameDisplay
_data = data;
_gameCategory = gameCategory;
_gameId = gameId;
+ _communityFavorite = communityFavorite;
}
public String getName()
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/particleeffects/Effect.java b/Plugins/Mineplex.Core/src/mineplex/core/particleeffects/Effect.java
index 5ddda6a72..f72a32fbf 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/particleeffects/Effect.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/particleeffects/Effect.java
@@ -4,6 +4,7 @@ import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.common.util.Callback;
+import mineplex.core.particleeffects.events.EffectStopEvent;
public abstract class Effect
{
@@ -50,6 +51,8 @@ public abstract class Effect
{
_running = false;
Bukkit.getScheduler().cancelTask(_task);
+ EffectStopEvent effectStopEvent = new EffectStopEvent(this);
+ Bukkit.getPluginManager().callEvent(effectStopEvent);
if (_callback != null)
_callback.run(this);
onStop();
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/particleeffects/LineEffect.java b/Plugins/Mineplex.Core/src/mineplex/core/particleeffects/LineEffect.java
new file mode 100644
index 000000000..8698761dd
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/particleeffects/LineEffect.java
@@ -0,0 +1,51 @@
+package mineplex.core.particleeffects;
+
+import org.bukkit.Color;
+import org.bukkit.Location;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.util.Vector;
+
+import mineplex.core.common.util.UtilParticle;
+import mineplex.core.common.util.particles.ColoredParticle;
+import mineplex.core.common.util.particles.DustSpellColor;
+
+public class LineEffect extends Effect
+{
+
+ private int _particles = 100;
+ private Color _color;
+ private int _count = 0;
+ private Vector _vector;
+ private Location _fixedLoc;
+
+ public LineEffect(JavaPlugin plugin, Location location, Location target, Color color)
+ {
+ super(-1, new EffectLocation(location), plugin);
+ setTargetLocation(new EffectLocation(target));
+ _color = color;
+ }
+
+ @Override
+ public void runEffect()
+ {
+ Location location = _effectLocation.getFixedLocation().clone().add(0, 1, 0);
+ if (_vector == null)
+ {
+ Location targetLoc = getTargetLocation().getFixedLocation().clone();
+ Vector link = targetLoc.toVector().subtract(location.toVector());
+ float length = (float) link.length();
+ link.normalize();
+ Vector vector = link.multiply(length / _particles);
+ _vector = vector;
+ _fixedLoc = location.clone().subtract(_vector);
+ }
+ ColoredParticle coloredParticle = new ColoredParticle(UtilParticle.ParticleType.RED_DUST,
+ new DustSpellColor(_color), _effectLocation.getLocation().clone());
+ _fixedLoc.add(_vector);
+ if (_count == _particles)
+ {
+ stop();
+ }
+ }
+
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/personalServer/PersonalServerManager.java b/Plugins/Mineplex.Core/src/mineplex/core/personalServer/PersonalServerManager.java
index 24b4eb9e5..976814e4d 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/personalServer/PersonalServerManager.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/personalServer/PersonalServerManager.java
@@ -20,6 +20,7 @@ import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.communities.Community;
import mineplex.core.itemstack.ItemStackFactory;
import mineplex.core.recharge.Recharge;
import mineplex.serverdata.Region;
@@ -36,6 +37,7 @@ public class PersonalServerManager extends MiniPlugin
private int _interfaceSlot = 6;
private ItemStack _interfaceItem;
+ private boolean _useInterfaceItem = true;
private boolean _giveInterfaceItem = true;
public PersonalServerManager(JavaPlugin plugin, CoreClientManager clientManager)
@@ -65,6 +67,10 @@ public class PersonalServerManager extends MiniPlugin
@EventHandler
public void openServer(PlayerInteractEvent event)
{
+ if (!_useInterfaceItem)
+ {
+ return;
+ }
if (_interfaceItem.equals(event.getPlayer().getItemInHand()))
{
if (!Recharge.Instance.use(event.getPlayer(), "Host Server Melon", 30000, false, false))
@@ -124,7 +130,7 @@ public class PersonalServerManager extends MiniPlugin
Rank rank = _clientManager.Get(player).GetRank();
- if (eventServer || rank.has(Rank.SNR_MODERATOR) || rank == Rank.YOUTUBE || rank == Rank.TWITCH)
+ if (rank.has(Rank.SNR_MODERATOR) || rank == Rank.YOUTUBE || rank == Rank.TWITCH)
{
ram = 2048;
cpu = 4;
@@ -140,6 +146,34 @@ public class PersonalServerManager extends MiniPlugin
createGroup(player, serverName, ram, cpu, 40, 80, "Smash", eventServer);
}
+ public void hostCommunityServer(Player host, Community community)
+ {
+ int ram = 2048;
+ int cpu = 4;
+
+ runAsync(() ->
+ {
+ for (ServerGroup existingServerGroup : _repository.getServerGroups(null))
+ {
+ if (existingServerGroup.getPrefix().equalsIgnoreCase("COM-" + community.getName()) || existingServerGroup.getName().equalsIgnoreCase("COM-" + community.getId()))
+ {
+ host.sendMessage(F.main(getName(), "Your server is still being created or already exists. If you have just started it up, wait 20 seconds and type /server COM-" + community.getName() + "-1."));
+ return;
+ }
+ }
+
+ final ServerGroup serverGroup = new ServerGroup("COM-" + community.getId(), "COM-" + community.getName(), "COM-" + community.getId(), ram, cpu, 1, 0, UtilMath.random.nextInt(250) + 19999, "", true, "Lobby_MCS.zip", "Arcade.jar", "plugins/Arcade/", 15, 20,
+ true, false, false, community.getFavoriteGame().name(), "", "", "Community", true, false, false, true, false, false, true, false, false, false, false, true, true, true, false, false, "", _us ? Region.US : Region.EU, "", "", "", "");
+
+ _repository.updateServerGroup(serverGroup);
+ runSync(() ->
+ {
+ host.sendMessage(F.main(getName(), "COM-" + community.getName() + "-1 successfully created. You will be able to join it shortly."));
+ host.sendMessage(F.main(getName(), "In around 10 seconds, type /server COM-" + community.getName() + "-1."));
+ });
+ });
+ }
+
private void createGroup(final Player host, final String serverName, final int ram, final int cpu, final int minPlayers, final int maxPlayers, final String games, final boolean event)
{
getPlugin().getServer().getScheduler().runTaskAsynchronously(getPlugin(), new Runnable()
@@ -185,4 +219,9 @@ public class PersonalServerManager extends MiniPlugin
{
return _clientManager;
}
+
+ public void setUseInterfaceItem(boolean use)
+ {
+ _useInterfaceItem = use;
+ }
}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/preferences/Preference.java b/Plugins/Mineplex.Core/src/mineplex/core/preferences/Preference.java
index 9f420e218..aef708f46 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/preferences/Preference.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/preferences/Preference.java
@@ -32,8 +32,8 @@ public enum Preference
SHOW_USER_REPORTS(false, PreferenceCategory.EXCLUSIVE, Material.BOOK, "User Reports"),
IGNORE_VELOCITY(false, PreferenceCategory.EXCLUSIVE, Material.SADDLE, "Hub Ignore Velocity"),
- PENDING_FRIEND_REQUESTS(true, PreferenceCategory.FRIEND, Material.RED_ROSE, "Show Pending Friend Requests"),
- FRIENDS_DISPLAY_INVENTORY_UI(true, PreferenceCategory.FRIEND, Material.CHEST, "Display Friend GUI"),
+ PENDING_FRIEND_REQUESTS(true, PreferenceCategory.SOCIAL, Material.RED_ROSE, "Show Pending Friend Requests"),
+ FRIENDS_DISPLAY_INVENTORY_UI(true, PreferenceCategory.SOCIAL, Material.CHEST, "Display Friend GUI"),
CLAN_TIPS(true, PreferenceCategory.MISC, Material.IRON_SWORD, "Show Clan Tips"),
HUB_MUSIC(true, PreferenceCategory.MISC, Material.NOTE_BLOCK, "Hub Music"),
@@ -41,6 +41,8 @@ public enum Preference
AUTO_JOIN_NEXT_GAME(true, PreferenceCategory.GAME_PLAY, Material.DIAMOND_SWORD, "Auto Join Next Game", "Feel like playing again?", "Enable this, and when you're out", "a 15 second timer will start", "when it ends, it'll send you", "to another game!"),
DISABLE_WARNING(true, PreferenceCategory.GAME_PLAY, Material.BARRIER, "Disable Automatic Warning", "Know what you're doing?", "Disable this to not receive", "a message warning you about Auto-Join"),
COUNTDOWN_ON_CLICK(false, PreferenceCategory.GAME_PLAY, Material.WATCH, "Countdown to Join", "See that fancy text when you're out?", "If you click it, and this is enabled", "a 15 second time will countdown", "until you are sent to a new game"),
+
+ COMMUNITY_INVITES(true, PreferenceCategory.SOCIAL, Material.BOOK, "Show Community Invites"),
;
private static final Map PREFERENCE_MAP = Maps.newHashMap();
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferenceCategory.java b/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferenceCategory.java
index 7e99cd29e..1f870bd4e 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferenceCategory.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferenceCategory.java
@@ -15,7 +15,7 @@ public enum PreferenceCategory
EXCLUSIVE("Exclusive", Material.DIAMOND),
GAME_PLAY("Game Mechanic", Material.REDSTONE_COMPARATOR),
MISC("Miscellaneous", Material.COMPASS),
- FRIEND("Friend", Material.CHEST),
+ SOCIAL("Social", Material.RED_ROSE),
;
private String _name;
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/preferences/ui/ExclusivePreferencesPage.java b/Plugins/Mineplex.Core/src/mineplex/core/preferences/ui/ExclusivePreferencesPage.java
deleted file mode 100644
index e69de29bb..000000000
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/punish/Punish.java b/Plugins/Mineplex.Core/src/mineplex/core/punish/Punish.java
index 8c5125364..560cd293d 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/punish/Punish.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/punish/Punish.java
@@ -1,7 +1,7 @@
package mineplex.core.punish;
import java.util.HashMap;
-import java.util.UUID;
+import java.util.function.Consumer;
import java.util.logging.Level;
import mineplex.core.account.CoreClient;
@@ -170,6 +170,11 @@ public class Punish extends MiniPlugin
}
public void AddPunishment(String playerName, final Category category, final String reason, String callerName, final int severity, boolean ban, long duration, final boolean silent)
+ {
+ AddPunishment(playerName, category, reason, callerName, severity, ban, duration, silent, null);
+ }
+
+ public void AddPunishment(String playerName, final Category category, final String reason, String callerName, final int severity, boolean ban, long duration, final boolean silent, Consumer callback)
{
Player player = Bukkit.getPlayerExact(playerName);
if (player != null)
@@ -257,8 +262,8 @@ public class Punish extends MiniPlugin
if (player != null)
player.kickPlayer(kickReason);
- else
- new mineplex.serverdata.commands.PunishCommand(finalPlayerName, true, false, kickReason).publish();
+
+ new mineplex.serverdata.commands.PunishCommand(finalPlayerName, true, false, kickReason).publish();
}
});
@@ -284,8 +289,8 @@ public class Punish extends MiniPlugin
UtilPlayer.message(player, F.main("Punish", F.elem(C.cGray + C.Bold + "Reason: ") + reason));
player.playSound(player.getLocation(), Sound.CAT_MEOW, 1f, 1f);
}
- else
- new mineplex.serverdata.commands.PunishCommand(finalPlayerName, false, finalDuration != 0, F.main("Punish", F.elem(C.cGray + C.Bold + "Report Ban Reason: ") + reason)).publish();
+
+ new mineplex.serverdata.commands.PunishCommand(finalPlayerName, false, finalDuration != 0, F.main("Punish", F.elem(C.cGray + C.Bold + "Report Ban Reason: ") + reason)).publish();
_repository.LoadPunishClient(finalPlayerName, new Callback()
{
@@ -323,8 +328,8 @@ public class Punish extends MiniPlugin
UtilPlayer.message(player, F.main("Punish", F.elem(C.cGray + C.Bold + "Reason: ") + reason));
player.playSound(player.getLocation(), Sound.CAT_MEOW, 1f, 1f);
}
- else
- new mineplex.serverdata.commands.PunishCommand(finalPlayerName, false, finalDuration != 0, F.main("Punish", F.elem(C.cGray + C.Bold + (finalDuration != 0 ? "Mute" : "Warning") + " Reason: ") + reason)).publish();
+
+ new mineplex.serverdata.commands.PunishCommand(finalPlayerName, false, finalDuration != 0, F.main("Punish", F.elem(C.cGray + C.Bold + (finalDuration != 0 ? "Mute" : "Warning") + " Reason: ") + reason)).publish();
_repository.LoadPunishClient(finalPlayerName, new Callback()
{
@@ -335,6 +340,10 @@ public class Punish extends MiniPlugin
});
}
}
+ if (callback != null)
+ {
+ callback.accept(banResult);
+ }
}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/punish/UI/PunishPage.java b/Plugins/Mineplex.Core/src/mineplex/core/punish/UI/PunishPage.java
index 32dff3486..afd83db92 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/punish/UI/PunishPage.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/punish/UI/PunishPage.java
@@ -270,15 +270,6 @@ public class PunishPage extends CraftInventoryCustom implements Listener
int flightSeverity = 2;
- try
- {
- if (Managers.get(AntiHack.class).isStrict())
- {
- flightSeverity = 3;
- }
- }
- catch (Exception e) {}
-
AddButton(41, new ShopItem(Material.INK_SACK, (byte)1, "Severity 3",new String[]
{
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardManager.java b/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardManager.java
index 66cae6122..75b658660 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardManager.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardManager.java
@@ -388,8 +388,7 @@ public class RewardManager
addMineStrikeSkin(Type.NORMAL, MineStrikeSkin.Steyr_AUG_Torque, rarity, 30);
addMineStrikeSkin(Type.NORMAL, MineStrikeSkin.XM1014_Tranquility, rarity, 30);
-
-
+
// VALENTINES
//Hats
addHat(Type.VALENTINES_GIFT, HatType.COMPANION_BLOCK, rarity, 100, 0);
@@ -905,9 +904,7 @@ public class RewardManager
public Reward[] getRewards(Player player, RewardPool.Type pool, RewardType type)
{
- int amount = 4;
- if(type == RewardType.ILLUMINATED_CHEST || type == RewardType.FREEDOM_CHEST || type == RewardType.OMEGA_CHEST
- || type == RewardType.HAUNTED_CHEST || type == RewardType.GINGERBREAD_CHEST) amount = 1;
+ int amount = pool.getChestAmount();
int currentReward = 0;
Reward[] rewards = new Reward[amount];
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardPool.java b/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardPool.java
index 904a27659..61306a0b7 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardPool.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardPool.java
@@ -53,29 +53,42 @@ public class RewardPool
NORMAL(true),
WINTER_HOLIDAY(true),
VALENTINES_GIFT(false),
- ILLUMINATED(false),
- FREEDOM(false),
- OMEGA(false),
- HAUNTED(false),
+ ILLUMINATED(false, 1),
+ FREEDOM(false, 1),
+ OMEGA(false, 1),
+ HAUNTED(false, 1),
TRICK_OR_TREAT(false),
INFUSED_CHESTS(false),
INFUSED_GADGETS(true),
MYTHICAL(true),
THANKFUL(false),
- GINGERBREAD(false),
+ GINGERBREAD(false, 1),
+ MINESTRIKE(false, 1),
CARL_SPINNER(true);
private boolean _useDuplicates;
+ private int _chestAmount;
+
+ Type(boolean useDuplicates, int amount)
+ {
+ _useDuplicates = useDuplicates;
+ _chestAmount = amount;
+ }
Type(boolean useDuplicates)
{
- _useDuplicates = useDuplicates;
+ this(useDuplicates, 4);
}
public boolean getUseDuplicates()
{
return _useDuplicates;
}
+
+ public int getChestAmount()
+ {
+ return _chestAmount;
+ }
public boolean canGive(Player player, Reward reward)
{
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardType.java b/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardType.java
index c30336f2b..8c0ed40a0 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardType.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/reward/RewardType.java
@@ -18,6 +18,7 @@ public enum RewardType
TRICK_OR_TREAT_CHEST(0.1, 2, 16, 0),
THANKFUL_CHEST( 0.1, 2, 16, 0),
GINGERBREAD_CHEST( 0, 2, 16, 0),
+ MINESTRIKE_CHEST( 0, 2, 16, 0),
VALENTINES_GIFT( 0, 7, 20, 20),
SPINNER_FILLER( 0.1, 1, 4, 20),
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/treasure/TreasureStyle.java b/Plugins/Mineplex.Core/src/mineplex/core/treasure/TreasureStyle.java
index c32d1e8da..3fd0114c9 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/treasure/TreasureStyle.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/treasure/TreasureStyle.java
@@ -76,6 +76,13 @@ public enum TreasureStyle
ParticleType.SNOW_SHOVEL,
Sound.DIG_SNOW,
Sound.DIG_SNOW
+ ),
+ MINESTRIKE(
+ ParticleType.FIREWORKS_SPARK,
+ ParticleType.FIREWORKS_SPARK,
+ ParticleType.FIREWORKS_SPARK,
+ Sound.EXPLODE,
+ Sound.EXPLODE
);
private ParticleType _secondaryParticle;
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/treasure/TreasureType.java b/Plugins/Mineplex.Core/src/mineplex/core/treasure/TreasureType.java
index aca216b22..ee63ac714 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/treasure/TreasureType.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/treasure/TreasureType.java
@@ -28,7 +28,9 @@ public enum TreasureType
THANKFUL(C.cGold + "Thankful Treasure", "Thankful Chest", "ThankFul", RewardType.THANKFUL_CHEST, Material.CHEST, TreasureStyle.THANKFUL, RewardPool.Type.THANKFUL, true, 20000),
- GINGERBREAD(C.cRed + "Gingerbread " + C.cGreen + "Treasure", "Gingerbread Chest", "Gingerbread", RewardType.GINGERBREAD_CHEST, Material.CHEST, TreasureStyle.GINGERBREAD, RewardPool.Type.GINGERBREAD, true, 20000);
+ GINGERBREAD(C.cRed + "Gingerbread " + C.cGreen + "Treasure", "Gingerbread Chest", "Gingerbread", RewardType.GINGERBREAD_CHEST, Material.CHEST, TreasureStyle.GINGERBREAD, RewardPool.Type.GINGERBREAD, true, 20000),
+
+ MINESTRIKE(C.cGold + "Minestrike Treasure", "Minestrike Chest", "MinestrikeChest", RewardType.MINESTRIKE_CHEST, Material.CHEST, TreasureStyle.MINESTRIKE, RewardPool.Type.MINESTRIKE, true, 20000);
private final String _name;
private final RewardType _rewardType;
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/TreasurePage.java b/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/TreasurePage.java
index 77d190c5a..ea864c012 100644
--- a/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/TreasurePage.java
+++ b/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/TreasurePage.java
@@ -28,23 +28,36 @@ import mineplex.core.gadget.gadgets.particle.freedom.ParticleFreedom;
import mineplex.core.gadget.types.Gadget;
import mineplex.core.gadget.types.GadgetType;
import mineplex.core.inventory.InventoryManager;
+import mineplex.core.itemstack.ItemStackFactory;
import mineplex.core.mount.Mount;
import mineplex.core.shop.item.ShopItem;
import mineplex.core.shop.page.ShopPageBase;
import mineplex.core.treasure.TreasureLocation;
import mineplex.core.treasure.TreasureManager;
import mineplex.core.treasure.TreasureType;
+import mineplex.core.treasure.gui.pages.NextPageButton;
+import mineplex.core.treasure.gui.pages.PreviousPageButton;
public class TreasurePage extends ShopPageBase
{
+
+ private TreasureManager _treasureManager;
+ private TreasureShop _treasureShop;
private TreasureLocation _treasureLocation;
private InventoryManager _inventoryManager;
private GadgetManager _gadgetManager;
+ private int _actualPage = 1;
+
+ private List _specialTreasures = new ArrayList<>();
+ private List _normalTreasures = new ArrayList<>();
+ private List _seasonalTreasures = new ArrayList<>();
public TreasurePage(TreasureManager plugin, TreasureShop shop, TreasureLocation treasureLocation, CoreClientManager clientManager, DonationManager donationManager, InventoryManager inventoryManager, GadgetManager gadgetManager, Player player)
{
- super(plugin, shop, clientManager, donationManager, "Open Treasure", player, 54);
+ super(plugin, shop, clientManager, donationManager, "Open Treasure - Page 1", player, 54);
+ _treasureManager = plugin;
+ _treasureShop = shop;
_treasureLocation = treasureLocation;
_inventoryManager = inventoryManager;
_gadgetManager = gadgetManager;
@@ -52,8 +65,62 @@ public class TreasurePage extends ShopPageBase
buildPage();
}
+ public TreasurePage(TreasureManager plugin, TreasureShop shop, TreasureLocation treasureLocation, CoreClientManager clientManager, DonationManager donationManager, InventoryManager inventoryManager, GadgetManager gadgetManager, Player player, int actualPage)
+ {
+ super(plugin, shop, clientManager, donationManager, "Open Treasure - Page " + actualPage, player, 54);
+
+ _treasureManager = plugin;
+ _treasureShop = shop;
+ _treasureLocation = treasureLocation;
+ _inventoryManager = inventoryManager;
+ _gadgetManager = gadgetManager;
+ _actualPage = actualPage;
+
+ buildPage();
+ }
+
+ public TreasureManager getTreasureManager()
+ {
+ return _treasureManager;
+ }
+
+ public TreasureShop getTreasureShop()
+ {
+ return _treasureShop;
+ }
+
+ public TreasureLocation getTreasureLocation()
+ {
+ return _treasureLocation;
+ }
+
+ public InventoryManager getInventoryManager()
+ {
+ return _inventoryManager;
+ }
+
+ public GadgetManager getGadgetManager()
+ {
+ return _gadgetManager;
+ }
+
+ public int getActualPage()
+ {
+ return _actualPage;
+ }
+
@Override
- protected void buildPage()
+ public void buildPage()
+ {
+ addAllChests();
+
+ if (_actualPage == 1)
+ buildFirstPage();
+ else
+ buildSecondPage();
+ }
+
+ private void addAllChests()
{
int treasureShards = getDonationManager().Get(getPlayer()).getBalance(GlobalCurrency.TREASURE_SHARD);
@@ -68,6 +135,7 @@ public class TreasurePage extends ShopPageBase
int trickCount = _inventoryManager.Get(getPlayer()).getItemCount(TreasureType.TRICK_OR_TREAT.getItemName());
int thankCount = _inventoryManager.Get(getPlayer()).getItemCount(TreasureType.THANKFUL.getItemName());
int gingerbreadCount = _inventoryManager.Get(getPlayer()).getItemCount(TreasureType.GINGERBREAD.getItemName());
+ int minestrikeCount = _inventoryManager.Get(getPlayer()).getItemCount(TreasureType.MINESTRIKE.getItemName());
List shardLore = new ArrayList<>();
shardLore.add(" ");
@@ -86,7 +154,7 @@ public class TreasurePage extends ShopPageBase
basicLore.add(C.cGray + "many kinds of loot.");
basicLore.add(" ");
if (basicCount > 0)
- basicLore.add(ChatColor.RESET + C.cGreen + "Click to Open!");
+ basicLore.add(C.cGreen + "Click to Open!");
else
{
basicLore.add(ChatColor.RESET + "Click to craft for " + C.cAqua + "1000 Treasure Shards");
@@ -103,7 +171,7 @@ public class TreasurePage extends ShopPageBase
heroicLore.add(C.cGray + "temples hidden in Minecrafts worlds.");
heroicLore.add(" ");
if (heroicCount > 0)
- heroicLore.add(ChatColor.RESET + C.cGreen + "Click to Open!");
+ heroicLore.add(C.cGreen + "Click to Open!");
else
{
heroicLore.add(ChatColor.RESET + "Click to craft for " + C.cAqua + "5000 Treasure Shards");
@@ -123,7 +191,7 @@ public class TreasurePage extends ShopPageBase
legendaryLore.add(C.cGray + "location of these chests on their own.");
legendaryLore.add(" ");
if (legendaryCount > 0)
- legendaryLore.add(ChatColor.RESET + C.cGreen + "Click to Open!");
+ legendaryLore.add(C.cGreen + "Click to Open!");
else
{
legendaryLore.add(ChatColor.RESET + "Click to craft for " + C.cAqua + "10000 Treasure Shards");
@@ -142,15 +210,10 @@ public class TreasurePage extends ShopPageBase
christmasLore.add(C.cGray + "accessed in the deepest parts of Winter...");
christmasLore.add(" ");
if (christmasCount > 0)
- christmasLore.add(ChatColor.RESET + C.cGreen + "Click to Open!");
+ christmasLore.add(C.cGreen + "Click to Open!");
else
{
christmasLore.add(C.cRed + "This item is no longer available!");
- /*
- christmasLore.add(ChatColor.RESET + "Click to craft for " + C.cAqua + "15000 Treasure Shards");
- christmasLore.add(" ");
- christmasLore.add(ChatColor.RESET + "or Purchase at: " + C.cYellow + "www.mineplex.com/shop");
- */
}
List illuminatedLore = new ArrayList();
@@ -162,7 +225,7 @@ public class TreasurePage extends ShopPageBase
illuminatedLore.add(C.cGray + "treasure from the darkness.");
illuminatedLore.add(" ");
if (illuminatedCount > 0)
- illuminatedLore.add(ChatColor.RESET + C.cGreen + "Click to Open!");
+ illuminatedLore.add(C.cGreen + "Click to Open!");
else
{
illuminatedLore.add(ChatColor.RESET + "Click to craft for " + C.cAqua + "20000 Treasure Shards");
@@ -179,7 +242,7 @@ public class TreasurePage extends ShopPageBase
freedomLore.add(C.cGray + "of the apple tree he cut down...");
freedomLore.add(" ");
if (freedomCount > 0 && !hasAllFreedomItems(getPlayer()))
- freedomLore.add(ChatColor.RESET + C.cGreen + "Click to Open!");
+ freedomLore.add(C.cGreen + "Click to Open!");
else
{
freedomLore.add(C.cRed + "This item is no longer available!");
@@ -196,7 +259,7 @@ public class TreasurePage extends ShopPageBase
omegaLore.add(C.cGray + "loot that has been lost...");
omegaLore.add(" ");
if (omegaCount > 0)
- omegaLore.add(ChatColor.RESET + C.cGreen + "Click to Open!");
+ omegaLore.add(C.cGreen + "Click to Open!");
else
{
@@ -212,13 +275,13 @@ public class TreasurePage extends ShopPageBase
hauntedLore.add(" ");
if (hauntedCount > 0 && !hasAllHauntedItems(getPlayer()))
{
- hauntedLore.add(ChatColor.RESET + C.cGreen + "Click to Open!");
+ hauntedLore.add(C.cGreen + "Click to Open!");
}
else
{
hauntedLore.add(C.cRed + "This item is no longer available!");
}
-
+
List trickLore = Lists.newArrayList();
trickLore.add(" ");
trickLore.add(F.value("Trick or Treat Chests Owned", "" + trickCount));
@@ -229,7 +292,7 @@ public class TreasurePage extends ShopPageBase
trickLore.add(" ");
if (trickCount > 0)
{
- trickLore.add(ChatColor.RESET + C.cGreen + "Click to Open!");
+ trickLore.add(C.cGreen + "Click to Open!");
}
else
{
@@ -245,7 +308,7 @@ public class TreasurePage extends ShopPageBase
trickLore.add(ChatColor.RESET + "or Purchase at: " + C.cYellow + "www.mineplex.com/shop");
}
}
-
+
List thankLore = Lists.newArrayList();
thankLore.add(" ");
thankLore.add(F.value("Thankful Chests Owned", "" + thankCount));
@@ -256,7 +319,7 @@ public class TreasurePage extends ShopPageBase
thankLore.add(" ");
if (thankCount > 0)
{
- thankLore.add(ChatColor.RESET + C.cGreen + "Click to Open!");
+ thankLore.add(C.cGreen + "Click to Open!");
}
else
{
@@ -278,13 +341,13 @@ public class TreasurePage extends ShopPageBase
gingerbreadLore.add(F.value("Gingerbread Chests Owned", "" + gingerbreadCount));
gingerbreadLore.add(" ");
gingerbreadLore.addAll(UtilText.splitLine(C.cGray + "The legendary burglar, " +
- "the Gingerbread Man, has finally been caught! Now, for the first time his loot is available for auction." +
- " There are 8 pieces available for to collect and no duplicates can be obtained from this chest!",
+ "the Gingerbread Man, has finally been caught! Now, for the first time his loot is available for auction." +
+ " There are 8 pieces available for to collect and no duplicates can be obtained from this chest!",
LineFormat.LORE));
gingerbreadLore.add(" ");
if (gingerbreadCount > 0)
{
- gingerbreadLore.add(ChatColor.RESET + C.cGreen + "Click to Open!");
+ gingerbreadLore.add(C.cGreen + "Click to Open!");
}
else
{
@@ -293,49 +356,202 @@ public class TreasurePage extends ShopPageBase
gingerbreadLore.add(ChatColor.RESET + "or Purchase at: " + C.cYellow + "www.mineplex.com/shop");
}
+ // Minestrike Chests not being released in this update!
+ /*List minestrikeLore = Lists.newArrayList();
+ minestrikeLore.add(" ");
+ minestrikeLore.add(F.value("Minestrike Chests Owned", "" + minestrikeCount));
+ minestrikeLore.add(" ");
+ minestrikeLore.addAll(UtilText.splitLine(C.cGray + "Placeholder", LineFormat.LORE));
+ minestrikeLore.add(" ");
+ if (minestrikeCount > 0)
+ {
+ minestrikeLore.add(C.cGreen + "Click to Open!");
+ }
+ else
+ {
+ minestrikeLore.add(ChatColor.RESET + "Click to craft for " + C.cAqua + "20000 Treasure Shards");
+ minestrikeLore.add(" ");
+ minestrikeLore.add(ChatColor.RESET + "or Purchase at: " + C.cYellow + "www.mineplex.com/shop");
+ }*/
+
ShopItem shards = new ShopItem(Material.PRISMARINE_SHARD, C.cAqua + C.Bold + treasureShards + " Treasure Shards", shardLore.toArray(new String[0]), 0, false);
+
+ // Normal chests
ShopItem basic = new ShopItem(Material.CHEST, C.cGreen + C.Bold + "Old Treasure", basicLore.toArray(new String[0]), 0, false, false);
ShopItem heroic = new ShopItem(Material.TRAPPED_CHEST, C.cGold + C.Bold + "Ancient Treasure", heroicLore.toArray(new String[0]), 0, false, false);
ShopItem legendary = new ShopItem(Material.ENDER_CHEST, C.cRed + C.Bold + "Mythical Treasure", legendaryLore.toArray(new String[0]), 0, false, false);
- ItemStack christmas = SkinData.PRESENT.getSkull(C.cDGreen + C.Bold + "Winter Holiday Treasure", christmasLore);
ItemStack illuminated = new ShopItem(Material.SEA_LANTERN, C.cDAqua + C.Bold + "Illuminated Treasure", illuminatedLore.toArray(new String[0]), 0, false, false);
- ItemStack freedom = SkinData.FREEDOM_CHEST.getSkull(C.cRedB + "Freedom " + C.cBlueB + "Treasure", freedomLore);
ItemStack omega = SkinData.OMEGA_CHEST.getSkull(C.cAquaB + "Omega Treasure", omegaLore);
+ //ItemStack minestrike = new ShopItem(Material.GLASS, C.cGoldB + "Minestrike Treasure", minestrikeLore.toArray(new String[0]), 0, false, false);
+
+ // Seasonal chests
+ ItemStack christmas = SkinData.PRESENT.getSkull(C.cDGreen + C.Bold + "Winter Holiday Treasure", christmasLore);
+ ItemStack freedom = SkinData.FREEDOM_CHEST.getSkull(C.cRedB + "Freedom " + C.cBlueB + "Treasure", freedomLore);
ItemStack haunted = SkinData.HAUNTED_CHEST.getSkull(C.cGoldB + "Haunted Treasure", hauntedLore);
ItemStack trick = new ShopItem(Material.SKULL_ITEM, C.cGoldB + "Trick or Treat Treasure", trickLore.toArray(new String[0]), 0, false, false);
ItemStack thank = new ShopItem(Material.COOKED_CHICKEN, C.cGoldB + "Thankful Treasure", thankLore.toArray(new String[0]), 0, false, false);
ItemStack gingerbread = SkinData.GINGERBREAD.getSkull(C.cRedB + "Gingerbread" + C.cGreenB + " Treasure", gingerbreadLore);
+ // Adds shard item
addItem(49, shards);
- addChest(10, christmas, TreasureType.CHRISTMAS, christmasCount);
- addChest(12, freedom, TreasureType.FREEDOM, freedomCount);
- addChest(14, haunted, TreasureType.HAUNTED, hauntedCount);
- addChest(16, omega, TreasureType.OMEGA, omegaCount);
- addChest(20, trick, TreasureType.TRICK_OR_TREAT, trickCount);
- addChest(22, gingerbread, TreasureType.GINGERBREAD, gingerbreadCount);
- addChest(24, thank, TreasureType.THANKFUL, thankCount);
- addChest(28, basic, TreasureType.OLD, basicCount);
- addChest(30, heroic, TreasureType.ANCIENT, heroicCount);
- addChest(32, legendary, TreasureType.MYTHICAL, legendaryCount);
- addChest(34, illuminated, TreasureType.ILLUMINATED, illuminatedCount);
+ // Adds chests to lists, to handle them later
+
+ // Normal chests
+ TreasurePageItem oldTreasureItem = new TreasurePageItem(basic, basicCount, TreasureType.OLD);
+ TreasurePageItem ancientTreasureItem = new TreasurePageItem(heroic, heroicCount, TreasureType.ANCIENT);
+ TreasurePageItem mythicalTreasureItem = new TreasurePageItem(legendary, legendaryCount, TreasureType.MYTHICAL);
+ TreasurePageItem illuminatedTreasureItem = new TreasurePageItem(illuminated, illuminatedCount, TreasureType.ILLUMINATED);
+ TreasurePageItem omegaTreasureItem = new TreasurePageItem(omega, omegaCount, TreasureType.OMEGA);
+ //TreasurePageItem minestrikeTreasureItem = new TreasurePageItem(minestrike, minestrikeCount, TreasureType.MINESTRIKE);
+
+ // Seasonal chests
+ TreasurePageItem winterTreasureItem = new TreasurePageItem(christmas, christmasCount, TreasureType.CHRISTMAS);
+ TreasurePageItem freedomTreasureItem = new TreasurePageItem(freedom, freedomCount, TreasureType.FREEDOM);
+ TreasurePageItem hauntedTreasureItem = new TreasurePageItem(haunted, hauntedCount, TreasureType.HAUNTED);
+ TreasurePageItem trickTreasureItem = new TreasurePageItem(trick, trickCount, TreasureType.TRICK_OR_TREAT);
+ TreasurePageItem thankTreasureItem = new TreasurePageItem(thank, thankCount, TreasureType.THANKFUL);
+ TreasurePageItem gingerbreadTreasureItem = new TreasurePageItem(gingerbread, gingerbreadCount, TreasureType.GINGERBREAD);
+
+ _normalTreasures.add(oldTreasureItem);
+ _normalTreasures.add(ancientTreasureItem);
+ _normalTreasures.add(mythicalTreasureItem);
+ _normalTreasures.add(illuminatedTreasureItem);
+ _normalTreasures.add(omegaTreasureItem);
+ //_normalTreasures.add(minestrikeTreasureItem);
+
+ _seasonalTreasures.add(winterTreasureItem);
+ _seasonalTreasures.add(freedomTreasureItem);
+ _seasonalTreasures.add(hauntedTreasureItem);
+ _seasonalTreasures.add(trickTreasureItem);
+ _seasonalTreasures.add(thankTreasureItem);
+
+ _specialTreasures.add(gingerbreadTreasureItem);
}
- private void addChest(int slot, ItemStack item, TreasureType treasureType, int owned)
+ private void buildFirstPage()
{
+ int i = 0;
+ if (_specialTreasures.size() >= 0)
+ {
+ int[] specialDisplayPositions = getSpecialDisplayOrder();
+ for (TreasurePageItem treasurePageItem : _specialTreasures)
+ {
+ addChest(treasurePageItem, specialDisplayPositions[i]);
+ i++;
+ }
+ i = 0;
+ }
+
+ int[] normalDisplayPositions = getNormalDisplayOrder();
+ for (TreasurePageItem treasurePageItem : _normalTreasures)
+ {
+ addChest(treasurePageItem, normalDisplayPositions[i]);
+ i++;
+ }
+
+ ItemStack nextPage = ItemStackFactory.Instance.CreateStack(Material.ARROW, (byte) 0, 1, C.cGreen + "Next Page");
+ NextPageButton nextPageButton = new NextPageButton(this, _player);
+ addButton(53, nextPage, nextPageButton);
+ }
+
+ private void buildSecondPage()
+ {
+ int i = 0;
+ int[] seasonalDisplayPositions = getSeasonalDisplayOrder();
+ for (TreasurePageItem treasurePageItem : _seasonalTreasures)
+ {
+ addChest(treasurePageItem, seasonalDisplayPositions[i]);
+ i++;
+ }
+
+ ItemStack previousPage = ItemStackFactory.Instance.CreateStack(Material.ARROW, (byte) 0, 1, C.cGreen + "Previous Page");
+ PreviousPageButton previousPageButton = new PreviousPageButton(this, _player);
+ addButton(45, previousPage, previousPageButton);
+ }
+
+ private void addChest(TreasurePageItem treasurePageItem, int position)
+ {
+ ItemStack item = treasurePageItem.getItem();
+ int owned = treasurePageItem.getCount();
+ TreasureType treasureType = treasurePageItem.getTreasureType();
+
if (owned > 0)
{
- addButton(slot, item, new OpenTreasureButton(getPlayer(), _treasureLocation, treasureType));
+ addButton(position, item, new OpenTreasureButton(getPlayer(), _treasureLocation, treasureType));
}
else if (treasureType.isPurchasable()) {
- addButton(slot, item, new BuyChestButton(_inventoryManager, this, treasureType.getItemName(), Material.CHEST, treasureType.getPurchasePrice(), treasureType));
- }
+ addButton(position, item, new BuyChestButton(_inventoryManager, this, treasureType.getItemName(), Material.CHEST, treasureType.getPurchasePrice(), treasureType));
+ }
else
{
- setItem(slot, item);
+ setItem(position, item);
}
}
+ private int[] getSpecialDisplayOrder()
+ {
+ int specialTreasuresSize = _specialTreasures.size();
+ switch (specialTreasuresSize)
+ {
+ case 1:
+ return new int[]{4};
+ case 2:
+ return new int[]{3, 5};
+ case 3:
+ return new int[]{2, 4, 6};
+ case 4:
+ return new int[]{1, 3, 5, 7};
+ }
+ return new int[]{4};
+ }
+
+ private int[] getNormalDisplayOrder()
+ {
+ int seasonalTreasuresSize = _seasonalTreasures.size();
+ switch (seasonalTreasuresSize)
+ {
+ case 5:
+ return new int[]{20, 22, 24, 39, 41};
+ case 6:
+ return new int[]{19, 21, 23, 25, 38, 42};
+ case 7:
+ return new int[]{19, 21, 23, 25, 38, 40, 42};
+ case 8:
+ return new int[]{19, 21, 23, 25, 37, 39, 41, 43};
+ case 9:
+ return new int[]{19, 21, 23, 25, 31, 37, 39, 41, 43};
+ case 10:
+ return new int[]{19, 21, 23, 25, 29, 33, 37, 39, 41, 43};
+ case 11:
+ return new int[]{19, 21, 23, 25, 29, 31, 33, 37, 39, 32, 43};
+ }
+ return new int[]{20, 22, 24, 39, 41};
+ }
+
+ private int[] getSeasonalDisplayOrder()
+ {
+ int seasonalTreasuresSize = _seasonalTreasures.size();
+ switch (seasonalTreasuresSize)
+ {
+ case 5:
+ return new int[]{11, 13, 15, 30, 32};
+ case 6:
+ return new int[]{10, 12, 14, 16, 29, 33};
+ case 7:
+ return new int[]{10, 12, 14, 16, 29, 31, 33};
+ case 8:
+ return new int[]{10, 12, 14, 16, 28, 30, 32, 34};
+ case 9:
+ return new int[]{10, 12, 14, 16, 22, 28, 30, 32, 34};
+ case 10:
+ return new int[]{10, 12, 14, 16, 20, 24, 28, 30, 32, 34};
+ case 11:
+ return new int[]{10, 12, 14, 16, 20, 22, 24, 28, 30, 32, 34};
+ }
+ return new int[]{11, 13, 15, 30, 32};
+ }
+
public boolean hasAllFreedomItems(Player player)
{
return !getPlugin().hasItemsToGivePlayer(TreasureType.FREEDOM.getRewardPool(), player);
@@ -378,4 +594,5 @@ public class TreasurePage extends ShopPageBase
}
return amount;
}
+
}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/TreasurePageItem.java b/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/TreasurePageItem.java
new file mode 100644
index 000000000..dded3fa99
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/TreasurePageItem.java
@@ -0,0 +1,35 @@
+package mineplex.core.treasure.gui;
+
+import org.bukkit.inventory.ItemStack;
+
+import mineplex.core.treasure.TreasureType;
+
+public class TreasurePageItem
+{
+
+ private final ItemStack _item;
+ private final int _count;
+ private final TreasureType _treasureType;
+
+ public TreasurePageItem(ItemStack item, int count, TreasureType treasureType)
+ {
+ _item = item;
+ _count = count;
+ _treasureType = treasureType;
+ }
+
+ public ItemStack getItem()
+ {
+ return _item;
+ }
+
+ public int getCount()
+ {
+ return _count;
+ }
+
+ public TreasureType getTreasureType()
+ {
+ return _treasureType;
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/pages/NextPageButton.java b/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/pages/NextPageButton.java
new file mode 100644
index 000000000..c98745293
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/pages/NextPageButton.java
@@ -0,0 +1,32 @@
+package mineplex.core.treasure.gui.pages;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import mineplex.core.shop.item.IButton;
+import mineplex.core.treasure.gui.TreasurePage;
+
+public class NextPageButton implements IButton
+{
+
+ private TreasurePage _treasurePage;
+ private Player _player;
+
+ public NextPageButton(TreasurePage treasurePage, Player player)
+ {
+ _treasurePage = treasurePage;
+ _player = player;
+ }
+
+ @Override
+ public void onClick(Player player, ClickType clickType)
+ {
+ if (_player != player)
+ return;
+ player.closeInventory();
+ TreasurePage nextPage = new TreasurePage(_treasurePage.getTreasureManager(), _treasurePage.getTreasureShop(), _treasurePage.getTreasureLocation(),
+ _treasurePage.getClientManager(), _treasurePage.getDonationManager(), _treasurePage.getInventoryManager(),
+ _treasurePage.getGadgetManager(), _player, _treasurePage.getActualPage() + 1);
+ _treasurePage.getTreasureShop().openPageForPlayer(player, nextPage);
+ }
+}
diff --git a/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/pages/PreviousPageButton.java b/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/pages/PreviousPageButton.java
new file mode 100644
index 000000000..a34b59963
--- /dev/null
+++ b/Plugins/Mineplex.Core/src/mineplex/core/treasure/gui/pages/PreviousPageButton.java
@@ -0,0 +1,33 @@
+package mineplex.core.treasure.gui.pages;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+
+import mineplex.core.shop.item.IButton;
+import mineplex.core.treasure.gui.TreasurePage;
+
+public class PreviousPageButton implements IButton
+{
+
+ private TreasurePage _treasurePage;
+ private Player _player;
+
+ public PreviousPageButton(TreasurePage treasurePage, Player player)
+ {
+ _treasurePage = treasurePage;
+ _player = player;
+ }
+
+ @Override
+ public void onClick(Player player, ClickType clickType)
+ {
+ if (_player != player)
+ return;
+ player.closeInventory();
+ TreasurePage previousPage = new TreasurePage(_treasurePage.getTreasureManager(), _treasurePage.getTreasureShop(), _treasurePage.getTreasureLocation(),
+ _treasurePage.getClientManager(), _treasurePage.getDonationManager(), _treasurePage.getInventoryManager(),
+ _treasurePage.getGadgetManager(), _player, _treasurePage.getActualPage() - 1);
+ _treasurePage.getTreasureShop().openPageForPlayer(player, previousPage);
+ }
+
+}
diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java
index 8c5d79ec0..d865e5d6e 100644
--- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java
+++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java
@@ -6,7 +6,8 @@ import mineplex.core.TimingsFix;
import mineplex.core.account.CoreClientManager;
import mineplex.core.achievement.AchievementManager;
import mineplex.core.antihack.AntiHack;
-import mineplex.core.antihack.AntiHackGuardian;
+import mineplex.core.antihack.guardians.AntiHackGuardian;
+import mineplex.core.antihack.guardians.GuardianManager;
import mineplex.core.blockrestore.BlockRestore;
import mineplex.core.chat.Chat;
import mineplex.core.chatsnap.SnapshotManager;
@@ -139,8 +140,9 @@ public class Clans extends JavaPlugin
Creature creature = new Creature(this);
AntiHack antiHack = require(AntiHack.class);
- antiHack.setKick(false);
- Bukkit.getScheduler().runTask(this, antiHack::enableNewAnticheat);
+ GuardianManager guardianManager = require(GuardianManager.class);
+
+ Bukkit.getScheduler().runTask(this, antiHack::enableAnticheat);
new EternalGiveawayManager(this, _clientManager, serverStatusManager);
@@ -155,7 +157,7 @@ public class Clans extends JavaPlugin
Location spawn = new Location(Bukkit.getWorld("world"), -422, 95, 8);
for (int i = 0; i < 10; i++)
{
- antiHack.registerGuardian(new AntiHackGuardian(spawn.clone(), maxX, minX, maxY, minY, maxZ, minZ));
+ guardianManager.registerGuardian(new AntiHackGuardian(spawn.clone(), maxX, minX, maxY, minY, maxZ, minZ));
}
}
@@ -170,7 +172,7 @@ public class Clans extends JavaPlugin
Location spawn = new Location(Bukkit.getWorld("world"), 424, 95, -8);
for (int i = 0; i < 10; i++)
{
- antiHack.registerGuardian(new AntiHackGuardian(spawn.clone(), maxX, minX, maxY, minY, maxZ, minZ));
+ guardianManager.registerGuardian(new AntiHackGuardian(spawn.clone(), maxX, minX, maxY, minY, maxZ, minZ));
}
}
@@ -185,7 +187,7 @@ public class Clans extends JavaPlugin
Location spawn = new Location(Bukkit.getWorld("world"), 9, 210, -393);
for (int i = 0; i < 10; i++)
{
- antiHack.registerGuardian(new AntiHackGuardian(spawn.clone(), maxX, minX, maxY, minY, maxZ, minZ));
+ guardianManager.registerGuardian(new AntiHackGuardian(spawn.clone(), maxX, minX, maxY, minY, maxZ, minZ));
}
}
@@ -200,7 +202,7 @@ public class Clans extends JavaPlugin
Location spawn = new Location(Bukkit.getWorld("world"), 8, 210, 390);
for (int i = 0; i < 10; i++)
{
- antiHack.registerGuardian(new AntiHackGuardian(spawn.clone(), maxX, minX, maxY, minY, maxZ, minZ));
+ guardianManager.registerGuardian(new AntiHackGuardian(spawn.clone(), maxX, minX, maxY, minY, maxZ, minZ));
}
}
@@ -215,7 +217,7 @@ public class Clans extends JavaPlugin
Location spawn = new Location(Bukkit.getWorld("world"), 0, 100, 0);
for (int i = 0; i < 40; i++)
{
- antiHack.registerGuardian(new AntiHackGuardian(spawn.clone(), maxX, minX, maxY, minY, maxZ, minZ));
+ guardianManager.registerGuardian(new AntiHackGuardian(spawn.clone(), maxX, minX, maxY, minY, maxZ, minZ));
}
}
diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java
index 325d63309..3fb75c743 100644
--- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java
+++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java
@@ -54,6 +54,7 @@ import mineplex.core.common.util.UtilBlock;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTextMiddle;
+import mineplex.core.communities.CommunityManager;
import mineplex.core.creature.Creature;
import mineplex.core.creature.event.CreatureSpawnCustomEvent;
import mineplex.core.disguise.DisguiseManager;
@@ -70,6 +71,7 @@ import mineplex.core.menu.MenuManager;
import mineplex.core.movement.Movement;
import mineplex.core.npc.NpcManager;
import mineplex.core.packethandler.PacketHandler;
+import mineplex.core.personalServer.PersonalServerManager;
import mineplex.core.portal.Portal;
import mineplex.core.preferences.PreferencesManager;
import mineplex.core.projectile.ProjectileManager;
@@ -405,6 +407,9 @@ public class ClansManager extends MiniClientPluginimplements IRelati
loadClan(token, false);
}
_bannerManager.loadBanners(this);
+
+ new PersonalServerManager(plugin, _clientManager).setUseInterfaceItem(false);
+ new CommunityManager(plugin, _clientManager);
Bukkit.getMessenger().registerOutgoingPluginChannel(plugin, "Replay|Restrict");
diff --git a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansHub.java b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansHub.java
index df1993e94..04cf7bd71 100644
--- a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansHub.java
+++ b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansHub.java
@@ -5,7 +5,8 @@ import mineplex.core.PacketsInteractionFix;
import mineplex.core.account.CoreClientManager;
import mineplex.core.achievement.AchievementManager;
import mineplex.core.antihack.AntiHack;
-import mineplex.core.antihack.AntiHackGuardian;
+import mineplex.core.antihack.guardians.AntiHackGuardian;
+import mineplex.core.antihack.guardians.GuardianManager;
import mineplex.core.aprilfools.AprilFoolsManager;
import mineplex.core.blockrestore.BlockRestore;
import mineplex.core.boosters.BoosterManager;
@@ -122,10 +123,11 @@ public class ClansHub extends JavaPlugin
Portal portal = new Portal(this, clientManager, serverStatusManager.getCurrentServerName());
AntiHack antiHack = require(AntiHack.class);
+ GuardianManager guardianManager = require(GuardianManager.class);
for (int i = 0; i < 8; i++)
{
- antiHack.registerGuardian(new AntiHackGuardian(new Location(Bukkit.getWorld("world"), 0, 195, 0), 25, -8, 195, 185, 17, -16));
+ guardianManager.registerGuardian(new AntiHackGuardian(new Location(Bukkit.getWorld("world"), 0, 195, 0), 25, -8, 195, 185, 17, -16));
}
IgnoreManager ignoreManager = new IgnoreManager(this, clientManager, preferenceManager, portal);
diff --git a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/HubManager.java b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/HubManager.java
index 252bd6bca..8357a531b 100644
--- a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/HubManager.java
+++ b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/HubManager.java
@@ -67,6 +67,7 @@ import mineplex.core.common.util.UtilTextBottom;
import mineplex.core.common.util.UtilTextTop;
import mineplex.core.common.util.UtilTime;
import mineplex.core.common.util.UtilWorld;
+import mineplex.core.communities.CommunityManager;
import mineplex.core.cosmetic.CosmeticManager;
import mineplex.core.customdata.CustomDataManager;
import mineplex.core.disguise.DisguiseManager;
@@ -93,6 +94,7 @@ import mineplex.core.npc.NpcManager;
import mineplex.core.packethandler.PacketHandler;
import mineplex.core.party.Party;
import mineplex.core.party.PartyManager;
+import mineplex.core.personalServer.PersonalServerManager;
import mineplex.core.pet.PetManager;
import mineplex.core.playerCount.PlayerCountManager;
import mineplex.core.playwire.PlayWireManager;
@@ -259,6 +261,9 @@ public class HubManager extends MiniPlugin implements IChatMessageFormatter
_serverName = _serverName.substring(0, Math.min(16, _serverName.length()));
new SalesAnnouncementManager(plugin);
+
+ new PersonalServerManager(plugin, _clientManager).setUseInterfaceItem(false);
+ new CommunityManager(plugin, _clientManager);
}
@Override
diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java
index b474dbe30..cd87eaf8e 100644
--- a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java
+++ b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java
@@ -10,7 +10,8 @@ import mineplex.core.PacketsInteractionFix;
import mineplex.core.account.CoreClientManager;
import mineplex.core.achievement.AchievementManager;
import mineplex.core.antihack.AntiHack;
-import mineplex.core.antihack.AntiHackGuardian;
+import mineplex.core.antihack.guardians.AntiHackGuardian;
+import mineplex.core.antihack.guardians.GuardianManager;
import mineplex.core.aprilfools.AprilFoolsManager;
import mineplex.core.blockrestore.BlockRestore;
import mineplex.core.boosters.BoosterManager;
@@ -148,10 +149,11 @@ public class Hub extends JavaPlugin implements IRelation
Portal portal = new Portal(this, clientManager, serverStatusManager.getCurrentServerName());
AntiHack antiHack = require(AntiHack.class);
+ GuardianManager guardianManager = require(GuardianManager.class);
for (int i = 0; i < 8; i++)
{
- antiHack.registerGuardian(new AntiHackGuardian(new Location(Bukkit.getWorld("world"), 0, 100, 0), 50, -50, 105, 95, 50, -50));
+ guardianManager.registerGuardian(new AntiHackGuardian(new Location(Bukkit.getWorld("world"), 0, 100, 0), 50, -50, 105, 95, 50, -50));
}
IgnoreManager ignoreManager = new IgnoreManager(this, clientManager, preferenceManager, portal);
diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/HubManager.java b/Plugins/Mineplex.Hub/src/mineplex/hub/HubManager.java
index 38fd80ce8..5b65fd27a 100644
--- a/Plugins/Mineplex.Hub/src/mineplex/hub/HubManager.java
+++ b/Plugins/Mineplex.Hub/src/mineplex/hub/HubManager.java
@@ -58,6 +58,7 @@ import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTime;
+import mineplex.core.communities.CommunityManager;
import mineplex.core.cosmetic.CosmeticManager;
import mineplex.core.customdata.CustomDataManager;
import mineplex.core.disguise.DisguiseManager;
@@ -273,6 +274,8 @@ public class HubManager extends MiniClientPlugin implements IChatMess
_valentinesManager = new ValentinesManager(plugin, clientManager, donationManager);
new SalesAnnouncementManager(plugin);
+
+ new CommunityManager(plugin, _clientManager);
ScoreboardManager scoreboardManager = new ScoreboardManager(plugin)
{
diff --git a/Plugins/Mineplex.Minecraft.Game.Core/src/mineplex/minecraft/game/core/combat/CombatLog.java b/Plugins/Mineplex.Minecraft.Game.Core/src/mineplex/minecraft/game/core/combat/CombatLog.java
index 879fc3c30..c2f6329e5 100644
--- a/Plugins/Mineplex.Minecraft.Game.Core/src/mineplex/minecraft/game/core/combat/CombatLog.java
+++ b/Plugins/Mineplex.Minecraft.Game.Core/src/mineplex/minecraft/game/core/combat/CombatLog.java
@@ -4,14 +4,14 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
-import mineplex.core.common.util.F;
-import mineplex.core.common.util.UtilTime;
-import mineplex.minecraft.game.core.damage.DamageChange;
-
import org.bukkit.ChatColor;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilTime;
+import mineplex.minecraft.game.core.damage.DamageChange;
+
public class CombatLog
{
private LinkedList _damager = new LinkedList();
@@ -34,6 +34,7 @@ public class CombatLog
{
_expireTime = expireTime;
_player = new CombatComponent(player.getName(), player);
+ _lastCombatEngaged = 0; // Just so taunts can be used before pvp
}
public LinkedList GetAttackers()
diff --git a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/data/ServerGroup.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/data/ServerGroup.java
index ba3295037..04c2c5118 100644
--- a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/data/ServerGroup.java
+++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/data/ServerGroup.java
@@ -325,7 +325,8 @@ public class ServerGroup
String serverName = server.getName();
try
{
- int serverNum = Integer.parseInt(serverName.split("-")[1]);
+ String[] nameArgs = serverName.split("-");
+ int serverNum = Integer.parseInt(nameArgs[nameArgs.length - 1]);
if (serverNum == id)
{
diff --git a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/database/RepositoryBase.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/database/RepositoryBase.java
index ec5a2c8de..987904b2c 100644
--- a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/database/RepositoryBase.java
+++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/database/RepositoryBase.java
@@ -75,6 +75,11 @@ public abstract class RepositoryBase
return null;
}
}
+
+ protected int executeUpdate(Connection connection, String query, Column>...columns)
+ {
+ return executeInsert(connection, query, null, columns);
+ }
/**
* Execute a query against the repository.
@@ -87,13 +92,12 @@ public abstract class RepositoryBase
return executeInsert(query, null, columns);
}
- protected int executeInsert(String query, ResultSetCallable callable, Column>...columns)
+ protected int executeInsert(Connection connection, String query, ResultSetCallable callable, Column>...columns)
{
int affectedRows = 0;
// Automatic resource management for handling/closing objects.
try (
- Connection connection = getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)
)
{
@@ -121,6 +125,29 @@ public abstract class RepositoryBase
return affectedRows;
}
+ protected int executeInsert(String query, ResultSetCallable callable, Column>...columns)
+ {
+ int affectedRows = 0;
+
+ // Automatic resource management for handling/closing objects.
+ try (
+ Connection connection = getConnection();
+ )
+ {
+ affectedRows = executeInsert(connection, query, callable, columns);
+ }
+ catch (SQLException exception)
+ {
+ exception.printStackTrace();
+ }
+ catch (Exception exception)
+ {
+ exception.printStackTrace();
+ }
+
+ return affectedRows;
+ }
+
protected void executeQuery(PreparedStatement statement, ResultSetCallable callable, Column>...columns)
{
try
@@ -148,11 +175,10 @@ public abstract class RepositoryBase
}
}
- protected void executeQuery(String query, ResultSetCallable callable, Column>...columns)
- {
+ protected void executeQuery(Connection connection, String query, ResultSetCallable callable, Column>...columns)
+ {
// Automatic resource management for handling/closing objects.
try (
- Connection connection = getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query)
)
{
@@ -167,4 +193,23 @@ public abstract class RepositoryBase
exception.printStackTrace();
}
}
-}
+
+ protected void executeQuery(String query, ResultSetCallable callable, Column>...columns)
+ {
+ // Automatic resource management for handling/closing objects.
+ try (
+ Connection connection = getConnection();
+ )
+ {
+ executeQuery(connection, query, callable, columns);
+ }
+ catch (SQLException exception)
+ {
+ exception.printStackTrace();
+ }
+ catch (Exception exception)
+ {
+ exception.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerMonitor.java b/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerMonitor.java
index 2bb711a58..086e356f2 100644
--- a/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerMonitor.java
+++ b/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerMonitor.java
@@ -211,6 +211,14 @@ public class ServerMonitor
System.out.println("Removed MPS : " + groupStatus.getName());
}
+ if (groupStatus.getServerType().equalsIgnoreCase("Community"))
+ {
+ _repository.removeServerGroup(groupStatus);
+ _serverGroupMap.remove(groupStatus.getName());
+ groupStatusIterator.remove();
+
+ System.out.println("Removed MCS : " + groupStatus.getName());
+ }
}
}
@@ -226,7 +234,8 @@ public class ServerMonitor
try
{
MinecraftServer server = serverIterator.next();
- int serverNum = Integer.parseInt(server.getName().split("-")[1]);
+ String[] nameArgs = server.getName().split("-");
+ int serverNum = Integer.parseInt(nameArgs[nameArgs.length - 1]);
if (serverMap.containsKey(serverNum))
{
diff --git a/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerSorter.java b/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerSorter.java
index 06ea39063..dd97c296d 100644
--- a/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerSorter.java
+++ b/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerSorter.java
@@ -9,9 +9,11 @@ public class ServerSorter implements Comparator
@Override
public int compare(MinecraftServer first, MinecraftServer second)
{
- if (Integer.parseInt(first.getName().split("-")[1]) < Integer.parseInt(second.getName().split("-")[1]))
+ String[] args1 = first.getName().split("-");
+ String[] args2 = second.getName().split("-");
+ if (Integer.parseInt(args1[args1.length - 1]) < Integer.parseInt(args2[args2.length - 1]))
return -1;
- else if (Integer.parseInt(second.getName().split("-")[1]) < Integer.parseInt(first.getName().split("-")[1]))
+ else if (Integer.parseInt(args2[args2.length - 1]) < Integer.parseInt(args1[args1.length - 1]))
return 1;
return 0;
diff --git a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/customerSupport/CustomerSupport.java b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/customerSupport/CustomerSupport.java
index f9cd84940..2e09e5181 100644
--- a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/customerSupport/CustomerSupport.java
+++ b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/customerSupport/CustomerSupport.java
@@ -162,6 +162,7 @@ public class CustomerSupport extends MiniPlugin implements ResultSetCallable
int trickOrTreatChestsReceived = 0;
int thankfulChestsReceived = 0;
int gingerbreadChestsReceived = 0;
+ //int minestrikeChestsReceived = 0;
for (CoinTransactionToken transaction : donor.getCoinTransactions())
{
@@ -295,6 +296,16 @@ public class CustomerSupport extends MiniPlugin implements ResultSetCallable
}
}
+ /*if (transaction.SalesPackageName.startsWith("Minestrike Chest"))
+ {
+ if (transaction.Coins == 0 && transaction.Gems == 0)
+ {
+ if (transaction.SalesPackageName.split(" ").length == 3)
+ minestrikeChestsReceived += Integer.parseInt(transaction.SalesPackageName.split(" ")[2]);
+ else if (transaction.SalesPackageName.split(" ").length == 2)
+ minestrikeChestsReceived += 1;
+ }
+ }*/
if (transaction.SalesPackageName.startsWith("Valentines Gift"))
{
if (transaction.Coins == 0 && transaction.Gems == 0)
@@ -367,6 +378,7 @@ public class CustomerSupport extends MiniPlugin implements ResultSetCallable
caller.sendMessage(C.cBlue + "Trick or Treat Chests Received: " + C.cYellow + trickOrTreatChestsReceived);
caller.sendMessage(C.cBlue + "Thankful Chests Received: " + C.cYellow + thankfulChestsReceived);
caller.sendMessage(C.cBlue + "Gingerbread Chests Received: " + C.cYellow + gingerbreadChestsReceived);
+ //caller.sendMessage(C.cBlue + "Minestrike Chests Received: " + C.cYellow + minestrikeChestsReceived);
caller.sendMessage(C.cBlue + "Game Amplifiers Received: " + C.cYellow + boostersReceived);
caller.sendMessage(C.cBlue + "Rune Amplifiers (20 min) Received: " + C.cYellow + runeAmplifier20);
caller.sendMessage(C.cBlue + "Rune Amplifiers (60 min) Received: " + C.cYellow + runeAmplifier60);
diff --git a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/SalesPackageManager.java b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/SalesPackageManager.java
index 25bb9dffa..1f26eaad6 100644
--- a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/SalesPackageManager.java
+++ b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/SalesPackageManager.java
@@ -96,6 +96,7 @@ public class SalesPackageManager extends MiniPlugin
AddSalesPackage(new PowerPlayClub(this, true));
AddSalesPackage(new OmegaChest(this));
AddSalesPackage(new HauntedChest(this));
+ //AddSalesPackage(new MinestrikeChest(this));
AddSalesPackage(new TrickOrTreatChest(this));
AddSalesPackage(new ThankfulChest(this));
@@ -167,7 +168,7 @@ public class SalesPackageManager extends MiniPlugin
coinBuilder = coinBuilder.extra("[").color("gray").extra(salesPackage.getName()).color("green").click("run_command", "/display " + playerName + " " + salesPackage.getName()).extra("] ").color("gray");
}
else if (salesPackage instanceof MythicalChest || salesPackage instanceof AncientChest || salesPackage instanceof OldChest || salesPackage instanceof IlluminatedChest || salesPackage instanceof FreedomChest || salesPackage instanceof HauntedChest || salesPackage instanceof TrickOrTreatChest
- || salesPackage instanceof GingerbreadChest)
+ || salesPackage instanceof ThankfulChest || salesPackage instanceof GingerbreadChest /*|| salesPackage instanceof MinestrikeChest*/)
{
chestBuilder = chestBuilder.extra("[").color("gray").extra(salesPackage.getName()).color("green").click("run_command", "/display " + playerName + " " + salesPackage.getName()).extra("] ").color("gray");
}
diff --git a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/command/RankCommand.java b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/command/RankCommand.java
index 21fad01ea..d46ae258e 100644
--- a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/command/RankCommand.java
+++ b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/command/RankCommand.java
@@ -34,7 +34,7 @@ public class RankCommand extends CommandBase
final Rank rankEnum = Rank.valueOf(rank);
- if (rankEnum == Rank.HERO || rankEnum == Rank.ULTRA || rankEnum == Rank.LEGEND || rankEnum == Rank.TITAN || rankEnum == Rank.ALL)
+ if (rankEnum == Rank.HERO || rankEnum == Rank.ULTRA || rankEnum == Rank.LEGEND || rankEnum == Rank.TITAN || rankEnum == Rank.ETERNAL || rankEnum == Rank.ALL)
{
Plugin.getClientManager().SaveRank(playerName, uuid, mineplex.core.common.Rank.valueOf(rank), perm);
caller.sendMessage(F.main(Plugin.getName(), playerName + "'s rank has been updated to " + rank + "!"));
diff --git a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/salespackages/MinestrikeChest.java b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/salespackages/MinestrikeChest.java
new file mode 100644
index 000000000..7f984e12d
--- /dev/null
+++ b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/salespackages/MinestrikeChest.java
@@ -0,0 +1,20 @@
+package mineplex.staffServer.salespackage.salespackages;
+
+import org.bukkit.entity.Player;
+
+import mineplex.staffServer.salespackage.SalesPackageManager;
+
+public class MinestrikeChest extends SalesPackageBase
+{
+ public MinestrikeChest(SalesPackageManager manager)
+ {
+ super(manager, "1 Minestrike Chest");
+ }
+
+ public void displayToAgent(Player agent, String playerName)
+ {
+ addButton(agent, "/sales item " + playerName + " 1 Item Minestrike Chest", "Give 1 Minestrike Chest.");
+ agent.sendMessage(" ");
+ addBackButton(agent, playerName);
+ }
+}
\ No newline at end of file
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 c59a47594..5f8828c95 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java
@@ -4,6 +4,7 @@ import mineplex.core.CustomTagFix;
import mineplex.core.FoodDupeFix;
import mineplex.core.PacketsInteractionFix;
import mineplex.core.TimingsFix;
+import mineplex.core.antihack.logging.AntihackLogger;
import mineplex.core.chatsnap.SnapshotRepository;
import mineplex.core.customdata.CustomDataManager;
import mineplex.core.chatsnap.SnapshotManager;
@@ -65,6 +66,8 @@ import mineplex.core.velocity.VelocityFix;
import mineplex.core.visibility.VisibilityManager;
import mineplex.minecraft.game.core.combat.CombatManager;
import mineplex.minecraft.game.core.damage.DamageManager;
+
+import nautilus.game.arcade.anticheatmetadata.GameInfoMetadata;
import nautilus.game.arcade.game.GameServerConfig;
import org.bukkit.Bukkit;
@@ -148,8 +151,7 @@ public class Arcade extends JavaPlugin
Punish punish = new Punish(this, webServerAddress, _clientManager);
- AntiHack antiHack = require(AntiHack.class);
- antiHack.setKick(false);
+ require(AntiHack.class);
IgnoreManager ignoreManager = new IgnoreManager(this, _clientManager, preferenceManager, portal);
StatsManager statsManager = new StatsManager(this, _clientManager);
@@ -185,7 +187,9 @@ public class Arcade extends JavaPlugin
//Arcade Manager
PollManager pollManager = new PollManager(this, _clientManager, _donationManager);
_gameManager = new ArcadeManager(this, serverStatusManager, ReadServerConfig(), _clientManager, _donationManager, _damageManager, statsManager, incognito, achievementManager, disguiseManager, creature, teleport, new Blood(this), chat, portal, preferenceManager, inventoryManager, packetHandler, cosmeticManager, projectileManager, petManager, hologramManager, webServerAddress, pollManager, npcmanager, customDataManager, punish, eloManager, thankManager, boosterManager);
-
+
+ require(AntihackLogger.class).registerMetadata(new GameInfoMetadata());
+
new GlobalPacketManager(this, _clientManager, serverStatusManager, inventoryManager, _donationManager, petManager, statsManager, _gameManager.getBonusManager().getRewardManager());
//new BroadcastManager(this, _gameManager);
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java
index f42ea1e7d..cbc0cd184 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java
@@ -4,8 +4,6 @@ import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
-import net.minecraft.server.v1_8_R3.EntityLiving;
-
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
@@ -54,6 +52,7 @@ import mineplex.core.common.util.UtilGear;
import mineplex.core.common.util.UtilInv;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
+import mineplex.core.communities.CommunityManager;
import mineplex.core.cosmetic.CosmeticManager;
import mineplex.core.creature.Creature;
import mineplex.core.customdata.CustomDataManager;
@@ -83,6 +82,7 @@ import mineplex.core.movement.Movement;
import mineplex.core.npc.NpcManager;
import mineplex.core.packethandler.PacketHandler;
import mineplex.core.party.PartyManager;
+import mineplex.core.personalServer.PersonalServerManager;
import mineplex.core.pet.PetManager;
import mineplex.core.playwire.PlayWireManager;
import mineplex.core.poll.PollManager;
@@ -120,7 +120,6 @@ import mineplex.minecraft.game.core.condition.ConditionManager;
import mineplex.minecraft.game.core.damage.DamageManager;
import mineplex.minecraft.game.core.fire.Fire;
import mineplex.serverdata.Region;
-
import nautilus.game.arcade.addons.SoupAddon;
import nautilus.game.arcade.addons.TeamArmorAddon;
import nautilus.game.arcade.booster.GameBoosterManager;
@@ -131,6 +130,7 @@ import nautilus.game.arcade.command.GoToNextGameCommand;
import nautilus.game.arcade.command.KitUnlockCommand;
import nautilus.game.arcade.command.OpenGameMechPrefsCommand;
import nautilus.game.arcade.command.RequiredRankCommand;
+import nautilus.game.arcade.command.TauntCommand;
import nautilus.game.arcade.command.WriteCommand;
import nautilus.game.arcade.events.GameStateChangeEvent;
import nautilus.game.arcade.game.Game;
@@ -165,7 +165,7 @@ import nautilus.game.arcade.managers.lobby.current.NewGameLobbyManager;
import nautilus.game.arcade.managers.lobby.legacy.LegacyGameLobbyManager;
import nautilus.game.arcade.player.ArcadePlayer;
import nautilus.game.arcade.shop.ArcadeShop;
-import static mineplex.core.Managers.require;
+import net.minecraft.server.v1_8_R3.EntityLiving;
public class ArcadeManager extends MiniPlugin implements IRelation
{
@@ -388,7 +388,7 @@ public class ArcadeManager extends MiniPlugin implements IRelation
_progressionKitManager = new ProgressingKitManager(this);
_serverUptimeManager = new ServerUptimeManager(this);
- if (GetHost() != null && !GetHost().isEmpty())
+ if (GetHost() != null && !GetHost().isEmpty() && !GetHost().startsWith("COM-"))
{
Bukkit.getScheduler().runTaskLater(plugin, () -> Portal.transferPlayer(GetHost(), _serverStatusManager.getCurrentServerName()), 80L);
}
@@ -404,6 +404,10 @@ public class ArcadeManager extends MiniPlugin implements IRelation
addCommand(new GoToNextGameCommand(this));
addCommand(new OpenGameMechPrefsCommand(this));
addCommand(new CancelNextGameCommand(this));
+ addCommand(new TauntCommand(this));
+
+ new PersonalServerManager(plugin, _clientManager).setUseInterfaceItem(false);
+ new CommunityManager(plugin, _clientManager);
_scoreboardManager = new ScoreboardManager(_plugin)
{
@@ -916,7 +920,7 @@ public class ArcadeManager extends MiniPlugin implements IRelation
return;
}
- if (!GetServerConfig().PublicServer || GetServerConfig().PlayerServerWhitelist)
+ if (!GetServerConfig().PublicServer || GetServerConfig().PlayerServerWhitelist || _gameHostManager.isCommunityServer())
{
event.setMotd(ChatColor.GRAY + "Private");
return;
@@ -1751,8 +1755,7 @@ public class ArcadeManager extends MiniPlugin implements IRelation
if (_enabled)
{
- //enableChampionsModules();
- disableChampionsModules();
+ enableChampionsModules();
}
else
{
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/anticheatmetadata/GameInfoMetadata.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/anticheatmetadata/GameInfoMetadata.java
new file mode 100644
index 000000000..8cf07119d
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/anticheatmetadata/GameInfoMetadata.java
@@ -0,0 +1,207 @@
+package nautilus.game.arcade.anticheatmetadata;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.player.PlayerJoinEvent;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import mineplex.core.antihack.logging.AnticheatMetadata;
+import mineplex.core.common.util.UtilServer;
+
+import nautilus.game.arcade.ArcadeManager;
+import nautilus.game.arcade.events.GameStateChangeEvent;
+import nautilus.game.arcade.game.Game;
+import nautilus.game.arcade.kit.Kit;
+import nautilus.game.arcade.kit.ProgressingKit;
+import nautilus.game.arcade.managers.GameHostManager;
+import static mineplex.core.Managers.require;
+
+public class GameInfoMetadata extends AnticheatMetadata
+{
+ private static final String KEY_GAME_INFO = "game-info";
+ private static final String KEY_GAME_MAP = "map";
+ private static final String KEY_GAME_TYPE = "type";
+ private static final String KEY_GAME_MODE = "mode";
+ private static final String KEY_CURRENT_STATE = "current-state";
+ private static final String KEY_STATE_START_TIME = "current-state-start-time";
+ private static final String KEY_JOIN_GAME_TIME = "join-game-time-ms";
+
+ private static final String KEY_STATE_TIMES = "state-times";
+
+ private static final String KEY_KIT_INFO = "kit-info";
+ private static final String KEY_KIT_NAME = "name";
+ private static final String KEY_KIT_LEVEL = "level";
+
+ private static final String KEY_MPS = "mps";
+ private static final String KEY_OWNER = "owner";
+
+ private static final String KEY_STATS = "stats";
+
+ private static final String KEY_WINNER = "winner";
+
+ private final Map _allGames = new HashMap<>();
+ private final Map _currentGame = new HashMap<>();
+
+ private final ArcadeManager _arcadeManager = require(ArcadeManager.class);
+
+ @Override
+ public String getId()
+ {
+ return "game-info";
+ }
+
+ @EventHandler
+ public void onJoin(PlayerJoinEvent event)
+ {
+ _allGames.put(event.getPlayer().getUniqueId(), new JsonArray());
+
+ JsonObject currentGame = buildCurrentGame();
+
+ if (currentGame != null)
+ {
+ _currentGame.put(event.getPlayer().getUniqueId(), currentGame);
+ }
+ }
+
+ private JsonObject buildCurrentGame()
+ {
+ Game game = _arcadeManager.GetGame();
+
+ if (game == null)
+ return null;
+
+ JsonObject currentGame = new JsonObject();
+
+ JsonObject gameInfo = new JsonObject();
+ gameInfo.addProperty(KEY_GAME_MAP, game.WorldData.File);
+ gameInfo.addProperty(KEY_GAME_TYPE, game.GetName());
+ gameInfo.addProperty(KEY_GAME_MODE, game.GetMode());
+ gameInfo.addProperty(KEY_CURRENT_STATE, game.GetState().name());
+ gameInfo.addProperty(KEY_STATE_START_TIME, game.GetStateTime());
+ gameInfo.addProperty(KEY_JOIN_GAME_TIME, System.currentTimeMillis());
+
+ if (_arcadeManager.GetGameHostManager() != null && _arcadeManager.GetGameHostManager().isPrivateServer())
+ {
+ GameHostManager gameHostManager = _arcadeManager.GetGameHostManager();
+
+ JsonObject mpsInfo = new JsonObject();
+ mpsInfo.addProperty(KEY_OWNER, _arcadeManager.GetHost());
+
+ currentGame.add(KEY_MPS, mpsInfo);
+ }
+
+ currentGame.add(KEY_GAME_INFO, gameInfo);
+
+ JsonObject stateStartTimes = new JsonObject();
+ stateStartTimes.addProperty(game.GetState().name(), game.GetStateTime());
+
+ currentGame.add(KEY_STATE_TIMES, stateStartTimes);
+
+ return currentGame;
+ }
+
+ @EventHandler
+ public void onStateChange(GameStateChangeEvent event)
+ {
+ if (event.GetState() == Game.GameState.Recruit)
+ {
+ for (Player player : UtilServer.getPlayersCollection())
+ {
+ if (!_currentGame.containsKey(player.getUniqueId()))
+ {
+ _currentGame.put(player.getUniqueId(), buildCurrentGame());
+ }
+ }
+ }
+
+ if (event.GetState() == Game.GameState.Live)
+ {
+ _currentGame.forEach((id, obj) ->
+ {
+ Player player = Bukkit.getPlayer(id);
+ if (player != null)
+ {
+ Kit kit = event.GetGame().GetKit(player);
+ if (kit != null)
+ {
+ JsonObject kitInfo = new JsonObject();
+ kitInfo.addProperty(KEY_KIT_NAME, kit.GetName());
+
+ if (kit instanceof ProgressingKit)
+ {
+ ProgressingKit pk = (ProgressingKit) kit;
+ kitInfo.addProperty(KEY_KIT_LEVEL, pk.getLevel(player.getUniqueId()));
+ }
+
+ obj.add(KEY_KIT_INFO, kitInfo);
+ }
+ }
+ });
+
+ }
+
+ _currentGame.values().forEach(obj ->
+ {
+ obj.get(KEY_STATE_TIMES).getAsJsonObject().addProperty(event.GetState().name(), System.currentTimeMillis());
+ });
+
+ if (event.GetState() == Game.GameState.Dead)
+ {
+ new ArrayList<>(_currentGame.keySet()).forEach(ent -> archivePlayer(event.GetGame(), ent));
+ }
+ }
+
+ private void archivePlayer(Game game, UUID uuid)
+ {
+ JsonObject gameObj = _currentGame.remove(uuid);
+
+ if (gameObj == null)
+ return;
+
+ _allGames.get(uuid).add(gameObj);
+
+ if (game == null)
+ return;
+
+ Player player = Bukkit.getPlayer(uuid);
+
+ if (player == null)
+ return;
+
+ Map stats = game.GetStats().get(player);
+
+ if (stats != null)
+ {
+ JsonObject statsObject = new JsonObject();
+ stats.forEach(statsObject::addProperty);
+
+ gameObj.add(KEY_STATS, statsObject);
+ }
+
+ gameObj.addProperty(KEY_WINNER, game.Winner);
+ }
+
+ @Override
+ public JsonElement build(UUID player)
+ {
+ archivePlayer(_arcadeManager.GetGame(), player);
+
+ return _allGames.get(player);
+ }
+
+ @Override
+ public void remove(UUID player)
+ {
+ _allGames.remove(player);
+ _currentGame.remove(player);
+ }
+}
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/command/TauntCommand.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/command/TauntCommand.java
new file mode 100644
index 000000000..50a4b4bf6
--- /dev/null
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/command/TauntCommand.java
@@ -0,0 +1,51 @@
+package nautilus.game.arcade.command;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
+import mineplex.core.Managers;
+import mineplex.core.command.CommandBase;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.common.util.UtilTime;
+import mineplex.core.gadget.event.TauntCommandEvent;
+import mineplex.core.gadget.gadgets.taunts.GameType;
+import mineplex.minecraft.game.core.combat.CombatManager;
+
+import nautilus.game.arcade.ArcadeManager;
+import nautilus.game.arcade.game.Game;
+
+public class TauntCommand extends CommandBase
+{
+
+ private ArcadeManager _arcadeManager;
+
+ public TauntCommand(ArcadeManager manager)
+ {
+ super(manager, Rank.ALL, "taunt");
+ _arcadeManager = manager;
+ }
+
+ @Override
+ public void Execute(Player player, String[] args)
+ {
+ boolean pvp = false;
+ CombatManager combatManager = Managers.get(CombatManager.class);
+ if (combatManager != null)
+ {
+ pvp = UtilTime.elapsed(combatManager.Get(player).GetLastCombatEngaged(), 5000 * 60);
+ }
+ Game game = _arcadeManager.GetGame();
+ GameType gameType = GameType.NONE;
+ if (game != null)
+ {
+ gameType = GameType.valueOf(game.GetType().toString().toUpperCase());
+ }
+ TauntCommandEvent event = new TauntCommandEvent(player, _arcadeManager.isGameInProgress(),
+ _arcadeManager.GetGame().IsAlive(player), UtilPlayer.isSpectator(player), combatManager.Get(player).GetLastCombatEngaged(),
+ gameType);
+ Bukkit.getPluginManager().callEvent(event);
+ }
+
+
+}
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 94d745ab4..d2864e5e5 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
@@ -82,6 +82,9 @@ 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.game.games.build.Build;
+import nautilus.game.arcade.game.games.draw.Draw;
+import nautilus.game.arcade.game.games.speedbuilders.SpeedBuilders;
import nautilus.game.arcade.game.modules.Module;
import nautilus.game.arcade.kit.ChampionsKit;
import nautilus.game.arcade.kit.Kit;
@@ -740,11 +743,14 @@ public abstract class Game implements Listener
if (this._gameState == Game.GameState.Prepare)
{
- Managers.get(AntiHack.class).enableNewAnticheat();
+ if (!(this instanceof SpeedBuilders) && !(this instanceof Build) && !(this instanceof Draw))
+ {
+ Managers.get(AntiHack.class).enableAnticheat();
+ }
}
else if (this._gameState == Game.GameState.End)
{
- Managers.get(AntiHack.class).disableNewAnticheat();
+ Managers.get(AntiHack.class).disableAnticheat();
}
@@ -1648,6 +1654,11 @@ public abstract class Game implements Listener
if (!UtilTime.elapsed(_helpTimer, 8000))
return;
+
+ if (Manager.GetGameHostManager().isCommunityServer())
+ {
+ return;
+ }
if (_helpColor == ChatColor.YELLOW)
_helpColor = ChatColor.GOLD;
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/privateServer/page/MenuPage.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/privateServer/page/MenuPage.java
index 94f2730d9..c31d8d7cd 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/privateServer/page/MenuPage.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/privateServer/page/MenuPage.java
@@ -11,6 +11,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import mineplex.core.common.Rank;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilServer;
+import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.shop.item.ShopItem;
import nautilus.game.arcade.ArcadeManager;
import nautilus.game.arcade.gui.privateServer.PrivateServerShop;
@@ -100,9 +101,12 @@ public class MenuPage extends BasePage
GameVotingButton votingButton = new GameVotingButton(getPlugin(), getShop());
addButton(3 + 27, new ShopItem(Material.BOOKSHELF, "Game Voting", new String[]{}, 1, false), votingButton);
-
- WhitelistButton whitelistButton = new WhitelistButton(getPlugin(), getShop());
- addButton(5 + 27, new ShopItem(Material.PAPER, "Whitelisted Players", new String[]{}, 1, false), whitelistButton);
+
+ if (!_manager.isCommunityServer())
+ {
+ WhitelistButton whitelistButton = new WhitelistButton(getPlugin(), getShop());
+ addButton(5 + 27, new ShopItem(Material.PAPER, "Whitelisted Players", new String[]{}, 1, false), whitelistButton);
+ }
}
OptionsButton optionsButton = new OptionsButton(getPlugin(), getShop());
@@ -114,6 +118,24 @@ public class MenuPage extends BasePage
private ShopItem getOwnerHead()
{
+ if (_manager.isCommunityServer())
+ {
+ String title = C.cGreen + C.Bold + _manager.getOwner().getName() + "'s Mineplex Community Server";
+ ItemStack head = new ItemBuilder(new ItemStack(_manager.getOwner().getFavoriteGame().getMaterial(), 1, _manager.getOwner().getFavoriteGame().getMaterialData(), null)).setTitle(ChatColor.RESET + title).build();
+ ArrayList lore = new ArrayList();
+ lore.add(" ");
+ lore.add(ChatColor.RESET + C.cYellow + "Server Name: " + C.cWhite + getPlugin().getPlugin().getConfig().getString("serverstatus.name"));
+ lore.add(ChatColor.RESET + C.cYellow + "Players Online: " + C.cWhite + UtilServer.getPlayers().length);
+ lore.add(ChatColor.RESET + C.cYellow + "Players Max: " + C.cWhite + getPlugin().GetServerConfig().MaxPlayers);
+ lore.add(" ");
+ lore.add(ChatColor.RESET + "Left-Click to increase Max Players");
+ lore.add(ChatColor.RESET + "Right-Click to decrease Max Players");
+ ItemMeta meta = head.getItemMeta();
+ meta.setLore(lore);
+ head.setItemMeta(meta);
+
+ return new ShopItem(head, title, title, 1, false, false);
+ }
String title = C.cGreen + C.Bold + getPlugin().GetHost() + "'s Mineplex Private Server";
ItemStack head = getPlayerHead(getPlugin().GetHost(), ChatColor.RESET + title);
ArrayList lore = new ArrayList();
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/privateServer/page/OptionsPage.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/privateServer/page/OptionsPage.java
index e68206e2f..4ac322c5b 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/privateServer/page/OptionsPage.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/gui/privateServer/page/OptionsPage.java
@@ -33,24 +33,30 @@ public class OptionsPage extends BasePage
//GameAutoStart
//GameTimeout
//PlayerKickIdle
-
- buildPreference(11, Material.EYE_OF_ENDER, "Public Server", _config.PublicServer, new IButton()
- {
- @Override
- public void onClick(Player player, ClickType clickType)
- {
- togglePublic();
- }
- });
- buildPreference(13, Material.PAPER, "Enforce Whitelist", _config.PlayerServerWhitelist, new IButton()
+ if (!_plugin.GetGameHostManager().isCommunityServer())
{
- @Override
- public void onClick(Player player, ClickType clickType)
+ buildPreference(11, Material.EYE_OF_ENDER, "Public Server", _config.PublicServer, new IButton()
{
- toggleWhitelist();
- }
- });
+ @Override
+ public void onClick(Player player, ClickType clickType)
+ {
+ togglePublic();
+ }
+ });
+ }
+
+ if (!_plugin.GetGameHostManager().isCommunityServer())
+ {
+ buildPreference(13, Material.PAPER, "Enforce Whitelist", _config.PlayerServerWhitelist, new IButton()
+ {
+ @Override
+ public void onClick(Player player, ClickType clickType)
+ {
+ toggleWhitelist();
+ }
+ });
+ }
buildPreference(15, Material.RAILS, "Force Team Balancing", _config.TeamForceBalance, new IButton()
{
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameFlagManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameFlagManager.java
index a76cf81ab..b9c61fddb 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameFlagManager.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameFlagManager.java
@@ -1230,17 +1230,7 @@ public class GameFlagManager implements Listener
}
}
}
-
- @EventHandler
- public void AntiHackStrict(GameStateChangeEvent event)
- {
- if (event.GetState() == GameState.Prepare || event.GetState() == GameState.Live)
- Managers.get(AntiHack.class).setStrict(event.GetGame().StrictAntiHack);
-
- else
- Managers.get(AntiHack.class).setStrict(true);
- }
-
+
@EventHandler
public void PlayerKillCommandCancel(PlayerCommandPreprocessEvent event)
{
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameHostManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameHostManager.java
index 77dfa7d8b..2dd77e929 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameHostManager.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameHostManager.java
@@ -4,25 +4,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
-import mineplex.core.common.Rank;
-import mineplex.core.common.util.C;
-import mineplex.core.common.util.F;
-import mineplex.core.common.util.UtilGear;
-import mineplex.core.common.util.UtilPlayer;
-import mineplex.core.common.util.UtilServer;
-import mineplex.core.common.util.UtilTextBottom;
-import mineplex.core.common.util.UtilTime;
-import mineplex.core.game.GameCategory;
-import mineplex.core.itemstack.ItemStackFactory;
-import mineplex.core.punish.PunishClient;
-import mineplex.core.updater.UpdateType;
-import mineplex.core.updater.event.UpdateEvent;
-import nautilus.game.arcade.ArcadeManager;
-import nautilus.game.arcade.GameType;
-import nautilus.game.arcade.game.Game.GameState;
-import nautilus.game.arcade.gui.privateServer.PrivateServerShop;
-import nautilus.game.arcade.gui.privateServer.page.GameVotingPage;
-
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
@@ -30,7 +11,6 @@ import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
-import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
@@ -40,6 +20,29 @@ import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
+import mineplex.core.Managers;
+import mineplex.core.common.Rank;
+import mineplex.core.common.util.C;
+import mineplex.core.common.util.F;
+import mineplex.core.common.util.UtilGear;
+import mineplex.core.common.util.UtilPlayer;
+import mineplex.core.common.util.UtilServer;
+import mineplex.core.common.util.UtilTextBottom;
+import mineplex.core.common.util.UtilTime;
+import mineplex.core.communities.Community;
+import mineplex.core.communities.CommunityDisbandEvent;
+import mineplex.core.communities.CommunityManager;
+import mineplex.core.communities.CommunityRole;
+import mineplex.core.game.GameCategory;
+import mineplex.core.itemstack.ItemStackFactory;
+import mineplex.core.updater.UpdateType;
+import mineplex.core.updater.event.UpdateEvent;
+import nautilus.game.arcade.ArcadeManager;
+import nautilus.game.arcade.GameType;
+import nautilus.game.arcade.game.Game.GameState;
+import nautilus.game.arcade.gui.privateServer.PrivateServerShop;
+import nautilus.game.arcade.gui.privateServer.page.GameVotingPage;
+
public class GameHostManager implements Listener
{
private ArrayList ultraGames = new ArrayList();
@@ -49,7 +52,6 @@ public class GameHostManager implements Listener
ArcadeManager Manager;
private Player _host;
- private String _hostName;
private Rank _hostRank;
private long _serverStartTime = System.currentTimeMillis();
private long _serverExpireTime = 21600000;
@@ -174,13 +176,13 @@ public class GameHostManager implements Listener
// Admins update
for (Player player : UtilServer.getPlayers())
{
- if (player.equals(_host) || _adminList.contains(player.getName()) || Manager.GetClients().Get(player).GetRank().has(Rank.ADMIN))
+ if (isHost(player) || isAdmin(player, true))
{
if (Manager.GetGame() == null || Manager.GetGame().GetState() == GameState.Recruit)
giveAdminItem(player);
}
- if (player.equals(_host) || (isAdmin(player, false) && isEventServer()))
+ if (isHost(player) || (isAdmin(player, false) && (isEventServer() || isCommunityServer())))
_lastOnline = System.currentTimeMillis();
}
}
@@ -212,6 +214,15 @@ public class GameHostManager implements Listener
public void handleLogin(PlayerLoginEvent event)
{
Player p = event.getPlayer();
+ if (isCommunityServer())
+ {
+ if (getOwner().getMembers().containsKey(p.getUniqueId()))
+ {
+ return;
+ }
+ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, "You are not a member of this MCS.");
+ return;
+ }
if (Manager.GetServerConfig().PlayerServerWhitelist){
if (!getWhitelist().contains(p.getName().toLowerCase())){
if ((Manager.GetHost() != null) && (Manager.GetHost().equalsIgnoreCase(p.getName())))
@@ -222,7 +233,16 @@ public class GameHostManager implements Listener
}
}
if (_blacklist.contains(p.getName()))
- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, "You were removed from this Mineplex Private Server.");
+ {
+ if (isCommunityServer())
+ {
+ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, "You were removed from this Mineplex Community Server.");
+ }
+ else
+ {
+ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, "You were removed from this Mineplex Private Server.");
+ }
+ }
}
@EventHandler
@@ -309,7 +329,16 @@ public class GameHostManager implements Listener
return;
if (UtilTime.elapsed(_lastOnline, _expireTime))
- setHostExpired(true, Manager.GetServerConfig().HostName + " has abandoned the server. Thanks for playing!");
+ {
+ if (isCommunityServer())
+ {
+ setHostExpired(true, getOwner().getName() + " has abandoned the server. Thanks for playing!");
+ }
+ else
+ {
+ setHostExpired(true, Manager.GetServerConfig().HostName + " has abandoned the server. Thanks for playing!");
+ }
+ }
else if (UtilTime.elapsed(_serverStartTime, _serverExpireTime))
setHostExpired(true, "This server has expired! Thank you for playing!");
@@ -501,11 +530,23 @@ public class GameHostManager implements Listener
public boolean isAdmin(Player player, boolean includeStaff)
{
+ if (isCommunityServer())
+ {
+ return (getOwner().getMembers().containsKey(player.getUniqueId()) && getOwner().getMembers().get(player.getUniqueId()).Role.ordinal() <= CommunityRole.COLEADER.ordinal()) || (includeStaff && Manager.GetClients().Get(player).GetRank().has(Rank.ADMIN));
+ }
return player.equals(_host) || _adminList.contains(player.getName()) || (includeStaff && Manager.GetClients().Get(player).GetRank().has(Rank.ADMIN));
}
public boolean isHost(Player player)
{
+ if (Manager.GetHost() != null && Manager.GetHost().startsWith("COM-"))
+ {
+ CommunityManager cmanager = Managers.get(CommunityManager.class);
+ int communityId = Integer.parseInt(Manager.GetHost().replace("COM-", ""));
+ Community c = cmanager.getLoadedCommunity(communityId);
+ return c.getMembers().containsKey(player.getUniqueId()) && c.getMembers().get(player.getUniqueId()).Role == CommunityRole.LEADER;
+ }
+
return player.getName().equals(Manager.GetHost());
}
@@ -519,6 +560,8 @@ public class GameHostManager implements Listener
{
if (_host == null || !event.getPlayer().equals(_host))
return;
+ if (isCommunityServer())
+ return;
if (!event.getMessage().toLowerCase().startsWith("/whitelist"))
return;
@@ -540,67 +583,13 @@ public class GameHostManager implements Listener
}
}
}
-
- public void setGame(GameType type)
- {
- if (_host == null)
- return;
-
- Manager.GetGameCreationManager().SetNextGameType(type);
-
- //End Current
- if (Manager.GetGame().GetState() == GameState.Recruit)
- {
- Manager.GetGame().SetState(GameState.Dead);
-
- Bukkit.broadcastMessage(C.cGreen + C.Bold + _host.getName() + " has changed game to " + type.GetName() + ".");
- }
- else
- {
- Bukkit.broadcastMessage(C.cGreen + C.Bold + _host.getName() + " set next game to " + type.GetName() + ".");
- }
- }
-
- public void startGame()
- {
- if (_host == null)
- return;
-
- Manager.GetGameManager().StateCountdown(Manager.GetGame(), 10, true);
-
- Manager.GetGame().Announce(C.cGreen + C.Bold + _host.getName() + " has started the game.");
- }
-
- public void stopGame()
- {
- if (_host == null)
- return;
-
- if (Manager.GetGame() == null)
- return;
-
- HandlerList.unregisterAll(Manager.GetGame());
-
- if (Manager.GetGame().GetState() == GameState.End || Manager.GetGame().GetState() == GameState.End)
- {
- _host.sendMessage("Game is already ending...");
- return;
- }
- else if (Manager.GetGame().GetState() == GameState.Recruit)
- {
- Manager.GetGame().SetState(GameState.Dead);
- }
- else
- {
- Manager.GetGame().SetState(GameState.End);
- }
-
-
- Manager.GetGame().Announce(C.cGreen + C.Bold + _host.getName() + " has stopped the game.");
- }
public boolean hasRank(Rank rank)
{
+ if (isCommunityServer())
+ {
+ return Rank.ETERNAL.has(rank);
+ }
if (_hostRank == null)
return false;
@@ -642,8 +631,15 @@ public class GameHostManager implements Listener
public void ban(Player player)
{
_blacklist.add(player.getName());
-
- Manager.GetPortal().sendToHub(player, "You were removed from this Mineplex Private Server.");
+
+ if (isCommunityServer())
+ {
+ Manager.GetPortal().sendToHub(player, "You were removed from this Mineplex Community Server.");
+ }
+ else
+ {
+ Manager.GetPortal().sendToHub(player, "You were removed from this Mineplex Private Server.");
+ }
}
@EventHandler
@@ -656,7 +652,26 @@ public class GameHostManager implements Listener
{
if (_blacklist.contains(player.getName()))
{
- Manager.GetPortal().sendToHub(player, "You were removed from this Mineplex Private Server.");
+ if (isCommunityServer())
+ {
+ Manager.GetPortal().sendToHub(player, "You were removed from this Mineplex Community Server.");
+ }
+ else
+ {
+ Manager.GetPortal().sendToHub(player, "You were removed from this Mineplex Private Server.");
+ }
+ }
+ }
+ }
+
+ @EventHandler
+ public void onDisband(CommunityDisbandEvent event)
+ {
+ if (isCommunityServer())
+ {
+ if (getOwner().getId().intValue() == event.getCommunity().getId().intValue())
+ {
+ setHostExpired(true, getOwner().getName() + " has disbanded and abandoned the server. Thanks for playing!");
}
}
}
@@ -715,6 +730,10 @@ public class GameHostManager implements Listener
public int getMaxPlayerCap()
{
+ if (isCommunityServer())
+ {
+ return 20;
+ }
if (hasRank(Rank.SNR_MODERATOR) || _hostRank == Rank.YOUTUBE || _hostRank == Rank.TWITCH)
return 100;
else if (_hostRank == Rank.YOUTUBE_SMALL || _hostRank == Rank.ETERNAL)
@@ -809,10 +828,31 @@ public class GameHostManager implements Listener
return;
String serverName = Manager.getPlugin().getConfig().getString("serverstatus.name");
- UtilPlayer.message(event.getPlayer(), ChatColor.BOLD + "Welcome to Mineplex Private Servers!");
+ if (!isCommunityServer())
+ {
+ UtilPlayer.message(event.getPlayer(), ChatColor.BOLD + "Welcome to Mineplex Private Servers!");
+ }
+ else
+ {
+ UtilPlayer.message(event.getPlayer(), ChatColor.BOLD + "Welcome to Mineplex Community Servers!");
+ }
UtilPlayer.message(event.getPlayer(), C.Bold + "Friends can connect with " + C.cGreen + C.Bold + "/server " + serverName);
}
+ public boolean isCommunityServer()
+ {
+ return Manager.GetHost() != null && Manager.GetHost().startsWith("COM-");
+ }
+
+ public Community getOwner()
+ {
+ if (!isCommunityServer())
+ {
+ return null;
+ }
+ return Managers.get(CommunityManager.class).getLoadedCommunity(Integer.parseInt(Manager.GetHost().replace("COM-", "")));
+ }
+
public boolean isEventServer()
{
return _isEventServer;
@@ -856,6 +896,5 @@ public class GameHostManager implements Listener
public void setHost(Player player)
{
_host = player;
- }
-
-}
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/chat/GameChatManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/chat/GameChatManager.java
index f8e887c4e..190e2fca7 100644
--- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/chat/GameChatManager.java
+++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/chat/GameChatManager.java
@@ -96,6 +96,8 @@ public class GameChatManager implements Listener
{
if (_manager.GetGameHostManager().isEventServer())
rankStr = C.cDGreen + C.Bold + "Event Host " + C.Reset;
+ else if (_manager.GetGameHostManager().isCommunityServer())
+ rankStr = C.cDGreen + C.Bold + "MCS Host " + C.Reset;
else
rankStr = C.cDGreen + C.Bold + "MPS Host " + C.Reset;
}
@@ -103,6 +105,8 @@ public class GameChatManager implements Listener
{
if (_manager.GetGameHostManager().isEventServer())
rankStr = C.cDGreen + C.Bold + "Event Co-Host " + C.Reset;
+ else if (_manager.GetGameHostManager().isCommunityServer())
+ rankStr = C.cDGreen + C.Bold + "MCS Co-Host " + C.Reset;
else
rankStr = C.cDGreen + C.Bold + "MPS Co-Host " + C.Reset;
}