Change thresholds, add notifs, move stuff around

This commit is contained in:
samczsun 2016-11-19 23:04:51 -05:00
parent c4c46b6ba2
commit 7f3bb9671a
23 changed files with 580 additions and 494 deletions

View File

@ -1,6 +1,7 @@
package mineplex.core.common.util;
import com.google.common.collect.Lists;
import mineplex.core.common.events.PlayerRecieveBroadcastEvent;
import mineplex.serverdata.Region;
@ -15,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.*;
@ -93,7 +95,7 @@ public class UtilServer
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)
@ -197,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);
}
}

View File

@ -8,12 +8,11 @@ import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import net.minecraft.server.v1_8_R3.ChatClickable;
import net.minecraft.server.v1_8_R3.ChatComponentText;
import net.minecraft.server.v1_8_R3.ChatHoverable;
import net.minecraft.server.v1_8_R3.ChatModifier;
import net.minecraft.server.v1_8_R3.EnumChatFormat;
import net.minecraft.server.v1_8_R3.IChatBaseComponent;
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;
@ -22,6 +21,9 @@ import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
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;
@ -56,10 +58,21 @@ 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;
@ -73,15 +86,13 @@ 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.punish.PunishmentResponse;
import mineplex.serverdata.commands.ServerCommandManager;
@ReflectivelyCreateMiniPlugin
public class AntiHack extends MiniPlugin
{
public static final Map<?, CheckThresholds> CHECKS = ImmutableMap.<Class<? extends Check>, CheckThresholds>builder()
private static final Map<Class<? extends Check>, CheckThresholds> CHECKS = ImmutableMap.<Class<? extends Check>, 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))
@ -89,31 +100,43 @@ public class AntiHack extends MiniPlugin
.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", 50, 100, 200)) // TODO: specific VL levels
.put(Speed.class, new CheckThresholds("Speed", 50, 100, 200)) // TODO: specific VL levels
.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 CheckThresholds UNKNOWN_TYPE = new CheckThresholds("Unknown", 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
private static final CheckThresholds NOOP_THRESHOLD = new CheckThresholds("Unknown", 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
private static final Map<Class<? extends Check>, AntiHackAction> ACTIONS = ImmutableMap.<Class<? extends Check>, 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;
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 int VL_DIFF_BEFORE_RENOTIFY = 999999;
private final Cache<String, Integer> _cooldown = CacheBuilder.newBuilder()
.concurrencyLevel(1)
.expireAfterWrite(30, TimeUnit.SECONDS)
.build();
private final String _thisServer;
private final String _thisServer = UtilServer.getServerName();
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);
private final Set<String> _detailedMessages = new HashSet<>();
private Set<Player> _pendingBan = new HashSet<>();
@ -124,69 +147,43 @@ public class AntiHack extends MiniPlugin
{
super("AntiHack");
DisguiseManager disguiseManager = require(DisguiseManager.class);
_detailedMessages.add("Spoobncoobr");
require(GuardianManager.class);
require(BanWaveManager.class);
this._thisServer = UtilServer.getServerName();
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));
}
else if (_clientManager.Get(player).GetRank().has(Rank.HELPER) && (violation.getOriginatingServer().equals(_thisServer) || Managers.get(PreferencesManager.class).get(player).isActive(Preference.GLOBAL_GWEN_REPORTS)))
{
((CraftPlayer) player).getHandle().sendMessage(component);
}
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);
}
});
}
require(BanWaveManager.class);
@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(this, player, after);
new BanwaveAnimationSpin().run(player, after);
}
public void doBan(Player player, Class<? extends Check> cause)
@ -202,28 +199,30 @@ public class AntiHack extends MiniPlugin
JsonObject custom = new JsonObject();
custom.addProperty("ban-reason", CheckManager.getCheckSimpleName(cause));
String id = generateId(ID_LENGTH);
String finalMessage = "[GWEN] " + id + "";
String id = generateId();
String finalMessage = "[GWEN] " + id;
_logger.saveMetadata(player, id, () ->
{
_logger.resetViolations(player, () ->
{
require(Punish.class).AddPunishment(coreClient.getName(), Category.Hacking, finalMessage, AntiHack.NAME, 3, true, -1, true, after);
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);
});
doPunish.accept(result -> _pendingBan.remove(player));
}
else
{
runBanAnimation(player, () ->
{
doPunish.accept(result ->
{
if (result == PunishmentResponse.Punished)
@ -231,29 +230,35 @@ public class AntiHack extends MiniPlugin
announceBan(player);
}
_pendingBan.remove(player);
});
});
})
);
}
}
});
}
public void doBanWave(Player player, String message)
public void doBanWave(Player player, BanWaveInfo info)
{
runSync(() ->
{
int totalPunishments = getPunishments(player);
int daysBanned = getDaysBanned(player);
CoreClient coreClient = _clientManager.Get(player);
Consumer<Consumer<PunishmentResponse>> doPunish = after ->
{
_punish.AddPunishment(coreClient.getName(), Category.Hacking, info.getMessage(), AntiHack.NAME, 3, true, -1, true, after);
};
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);
doPunish.accept(response ->
{
});
}
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, result ->
doPunish.accept(result ->
{
if (result == PunishmentResponse.Punished)
{
@ -302,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)
@ -321,143 +331,18 @@ 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))
if (_detailedMessages.add(player.getName()))
{
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<AntiHack>(this, Rank.DEVELOPER, "acon")
{
@Override
public void Execute(Player caller, String[] args)
{
if (caller.getUniqueId().toString().equals("b86b54da-93dd-46f9-be33-27bd92aa36d7"))
{
enableAnticheat();
UtilPlayer.message(caller, F.main(getName(), "Enabled new anticheat"));
}
}
});
addCommand(new CommandBase<AntiHack>(this, Rank.DEVELOPER, "acoff")
{
@Override
public void Execute(Player caller, String[] args)
{
if (caller.getUniqueId().toString().equals("b86b54da-93dd-46f9-be33-27bd92aa36d7"))
{
disableAnticheat();
UtilPlayer.message(caller, F.main(getName(), "Disabled new anticheat"));
}
}
});
addCommand(new CommandBase<AntiHack>(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);
});
return true;
}
else
{
UtilPlayer.message(caller, F.main(getName(), "Could not find player"));
_detailedMessages.remove(player.getName());
return false;
}
}
else
{
UtilPlayer.message(caller, F.main(getName(), "No player specified"));
}
}
}
});
}
addCommand(new CommandBase<AntiHack>(this, Rank.DEVELOPER, "getvls")
{
@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)
{
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(getName(), "Could not find player"));
}
}
else
{
UtilPlayer.message(caller, F.main(getName(), "No player specified"));
}
}
}
});
}
@EventHandler
public void onHack(PlayerViolationEvent event)
@ -465,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.getCheckClass());
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)
@ -482,16 +365,7 @@ public class AntiHack extends MiniPlugin
String key = event.getPlayer().getName() + "." + event.getHackType() + "." + severity.toString();
Integer pastVl = this._cooldown.getIfPresent(key);
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(), CheckManager.getCheckSimpleName(event.getCheckClass()), event.getViolations(), event.getMessage());
ServerCommandManager.getInstance().publishCommand(command);
}
}
else
if (pastVl == null)
{
MajorViolationCommand command = new MajorViolationCommand(_thisServer, event.getPlayer().getName(), CheckManager.getCheckSimpleName(event.getCheckClass()), event.getViolations(), event.getMessage());
ServerCommandManager.getInstance().publishCommand(command);
@ -531,151 +405,52 @@ public class AntiHack extends MiniPlugin
UtilServer.CallEvent(new GameEndEvent());
}
private IChatBaseComponent getDetailedMessage(MajorViolationCommand violation)
private BaseComponent[] 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)
)
);
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 IChatBaseComponent getMinimalMessage(MajorViolationCommand violation)
private BaseComponent[] getMinimalMessage(MajorViolationCommand violation)
{
Class<? extends Check> checkType = CheckManager.getCheckBySimpleName(violation.getHackType());
if (!CHECKS.containsKey(checkType)) {
if (!CHECKS.containsKey(checkType))
{
System.out.println("Warning: Unknown check type '" + violation.getHackType() + "' " + checkType);
}
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.getOrDefault(checkType, UNKNOWN_TYPE).format(violation.getViolations()));
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))
{
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())
)
)
)
);
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()));
}
return component.addSibling(
new ChatComponentText(".")
.setChatModifier(
new ChatModifier()
.setColor(EnumChatFormat.YELLOW)
)
);
componentBuilder.append(".").color(ChatColor.YELLOW);
return componentBuilder.create();
}
public static String generateId(int length)
public static String generateId()
{
byte[] holder = new byte[length];
byte[] holder = new byte[ID_LENGTH];
ThreadLocalRandom.current().nextBytes(holder);
return DatatypeConverter.printHexBinary(holder);
}

View File

@ -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;
}

View File

@ -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
}
}

View File

@ -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,38 +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<Class<?>, AntiHackAction> ACTIONS = new HashMap<>();
private static final AntiHackAction NOOP_ACTION = new NoopAction();
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);
}

View File

@ -1,19 +1,18 @@
package mineplex.core.antihack.actions;
import org.bukkit.Bukkit;
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);
}

View File

@ -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);
}

View File

@ -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<AntiHackAction> _actions = new ArrayList<>();
private Map<UUID, Set<AntiHackAction>> _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();
}
}

View File

@ -4,7 +4,7 @@ import com.mineplex.anticheat.api.PlayerViolationEvent;
public class NoopAction extends AntiHackAction
{
NoopAction()
public NoopAction()
{
super(Integer.MAX_VALUE);
}

View File

@ -5,5 +5,5 @@ import org.bukkit.entity.Player;
public interface BanwaveAnimation
{
void run(AntiHack antiHack, Player player, Runnable after);
void run(Player player, Runnable after);
}

View File

@ -19,7 +19,7 @@ import java.util.function.Function;
public class BanwaveAnimationSpin implements BanwaveAnimation
{
@Override
public void run(AntiHack antiHack, Player player, Runnable after)
public void run(Player player, Runnable after)
{
float oldWalkSpeed = player.getWalkSpeed();
player.setWalkSpeed(0);
@ -41,12 +41,9 @@ public class BanwaveAnimationSpin implements BanwaveAnimation
UtilEnt.CreatureLook(south.getEntity(), player);
UtilEnt.CreatureLook(north.getEntity(), player);
Function<Double, Double> magic = seconds ->
{
return Math.pow(2, seconds - 5);
};
Function<Double, Double> magic = seconds -> Math.pow(2, seconds - 5);
antiHack.runSyncLater(() ->
UtilServer.runSyncLater(() ->
{
north.shoot(player);
east.shoot(player);
@ -61,7 +58,7 @@ public class BanwaveAnimationSpin implements BanwaveAnimation
AtomicDouble cSouth = new AtomicDouble(90);
AtomicDouble cWest = new AtomicDouble(180);
antiHack.runSyncTimer(new BukkitRunnable()
UtilServer.runSyncTimer(new BukkitRunnable()
{
public void run()
{
@ -86,7 +83,7 @@ public class BanwaveAnimationSpin implements BanwaveAnimation
UtilEnt.CreatureLook(south.getEntity(), location);
UtilEnt.CreatureLook(east.getEntity(), location);
UtilEnt.CreatureLook(west.getEntity(), location);
antiHack.runSyncLater(() ->
UtilServer.runSyncLater(() ->
{
north.remove();
south.remove();

View File

@ -6,6 +6,9 @@ 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;
@ -13,11 +16,14 @@ 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()
{
@ -37,34 +43,40 @@ 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, int vl, String server)
public void insertBanWaveInfo(Player player, long timeToBan, Class<? extends Check> checkClass, int vl, String server)
{
insertBanWaveInfo(player, timeToBan, checkClass, vl, server, null);
}
public void insertBanWaveInfo(Player player, long timeToBan, Class<?> checkClass, int vl, String server, Runnable after)
public void insertBanWaveInfo(Player player, long timeToBan, Class<? extends Check> checkClass, int vl, String server, Runnable after)
{
runAsync(() ->
{
String id = AntiHack.generateId(AntiHack.ID_LENGTH);
Bukkit.broadcastMessage("Banwave scheduled for " + player.getName() + ", id " + id + ", for " + checkClass.getSimpleName());
String newMessage = "[GWEN] [BanWave] " + id + "";
String id = AntiHack.generateId();
String newMessage = "[GWEN] [BanWave] " + id;
CoreClient client = require(CoreClientManager.class).Get(player);
CoreClient client = _clientManager.Get(player);
this._repository.insertBanWaveInfo(client.getAccountId(), timeToBan, checkClass.getName(), newMessage, vl, server);
if (this._repository.insertBanWaveInfo(client.getAccountId(), timeToBan, CheckManager.getCheckSimpleName(checkClass), newMessage, vl, server))
{
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);
}
});
}
}

View File

@ -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)

View File

@ -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<AntiHack>
{
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"));
}
}

View File

@ -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<AntiHack>
{
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"));
}
}

View File

@ -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<AntiHack>
{
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"));
}
}
}

View File

@ -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<AntiHack>
{
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"));
}
}
}

View File

@ -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<AntiHack>
{
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"));
}
}
}

View File

@ -58,7 +58,7 @@ public class AnticheatDatabase extends MinecraftRepository
uploadQueue.forEach((accountId, vls) ->
{
CheckManager.AVAILABLE_CHECKS.forEach(check ->
CheckManager.AVAILABLE_CHECKS.values().forEach(check ->
{
int checkId = CheckManager.getCheckId(check),
maxVls = vls.getMaxViolationsForCheck(check),

View File

@ -90,7 +90,7 @@ public class AntihackLogger extends MiniPlugin
{
JsonObject custom = new JsonObject();
custom.addProperty("is-test-metadata", true);
String id = AntiHack.generateId(AntiHack.ID_LENGTH);
String id = AntiHack.generateId();
saveMetadata(player, id, () ->
{
UtilPlayer.message(caller, F.main(getName(), "Saved metadata for " + player.getName() + " with id " + id));

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
@ -739,9 +742,12 @@ public abstract class Game implements Listener
_gameStateTime = System.currentTimeMillis();
if (this._gameState == Game.GameState.Prepare)
{
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).disableAnticheat();