Anticheat Logging #299
Remove MAC Add AntiHack Logging Change thresholds, add notifs, move stuff around Add warning if check does not exist Handle multiple bans when ranked TWITCH+ Prevent punishment abuse
This commit is contained in:
parent
df741fd394
commit
cae9d2f67e
@ -20,6 +20,11 @@
|
|||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
<artifactId>httpclient</artifactId>
|
<artifactId>httpclient</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.mineplex</groupId>
|
||||||
|
<artifactId>mineplex-serverdata</artifactId>
|
||||||
|
<version>dev-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -4,6 +4,7 @@ import com.google.common.collect.Sets;
|
|||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
@ -218,7 +219,7 @@ public class PlayerMap<V> implements Map<UUID, V>
|
|||||||
|
|
||||||
private static class RemovalListener implements Listener
|
private static class RemovalListener implements Listener
|
||||||
{
|
{
|
||||||
@EventHandler
|
@EventHandler (priority = EventPriority.MONITOR)
|
||||||
public void onQuit(PlayerQuitEvent event)
|
public void onQuit(PlayerQuitEvent event)
|
||||||
{
|
{
|
||||||
synchronized (LOCK)
|
synchronized (LOCK)
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package mineplex.core.common.util;
|
package mineplex.core.common.util;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import mineplex.core.common.events.PlayerRecieveBroadcastEvent;
|
import mineplex.core.common.events.PlayerRecieveBroadcastEvent;
|
||||||
|
import mineplex.serverdata.Region;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
@ -13,6 +16,7 @@ import org.bukkit.plugin.Plugin;
|
|||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -91,7 +95,7 @@ public class UtilServer
|
|||||||
|
|
||||||
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)
|
public static void RegisterEvents(Listener listener)
|
||||||
@ -135,6 +139,16 @@ public class UtilServer
|
|||||||
return getPlugin().getConfig().getString("serverstatus.name");
|
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()
|
public static boolean isTestServer()
|
||||||
{
|
{
|
||||||
return getPlugin().getConfig().getString("serverstatus.group").equalsIgnoreCase("Testing");
|
return getPlugin().getConfig().getString("serverstatus.group").equalsIgnoreCase("Testing");
|
||||||
@ -180,4 +194,39 @@ public class UtilServer
|
|||||||
throwable.printStackTrace(System.out);
|
throwable.printStackTrace(System.out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,11 @@
|
|||||||
<artifactId>anticheat</artifactId>
|
<artifactId>anticheat</artifactId>
|
||||||
<version>1.2</version>
|
<version>1.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.tukaani</groupId>
|
||||||
|
<artifactId>xz</artifactId>
|
||||||
|
<version>1.5</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,7 @@
|
|||||||
package mineplex.core.antihack;
|
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.ChatComponentText;
|
||||||
import net.minecraft.server.v1_8_R3.ChatModifier;
|
import net.minecraft.server.v1_8_R3.ChatModifier;
|
||||||
import net.minecraft.server.v1_8_R3.EnumChatFormat;
|
import net.minecraft.server.v1_8_R3.EnumChatFormat;
|
||||||
@ -25,10 +27,9 @@ public class CheckThresholds
|
|||||||
return _friendlyName;
|
return _friendlyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IChatBaseComponent format(int violationLevel)
|
public void format(ComponentBuilder builder, int violationLevel)
|
||||||
{
|
{
|
||||||
EnumChatFormat color = getSeverity(violationLevel)._color;
|
builder.append(_friendlyName, ComponentBuilder.FormatRetention.NONE).color(getSeverity(violationLevel)._color);
|
||||||
return new ChatComponentText(_friendlyName).setChatModifier(new ChatModifier().setColor(color));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Severity getSeverity(int violationLevel)
|
public Severity getSeverity(int violationLevel)
|
||||||
@ -51,14 +52,14 @@ public class CheckThresholds
|
|||||||
|
|
||||||
public enum Severity
|
public enum Severity
|
||||||
{
|
{
|
||||||
NONE(EnumChatFormat.GREEN),
|
NONE(ChatColor.GREEN),
|
||||||
LOW(EnumChatFormat.GREEN),
|
LOW(ChatColor.GREEN),
|
||||||
MEDIUM(EnumChatFormat.GOLD),
|
MEDIUM(ChatColor.GOLD),
|
||||||
HIGH(EnumChatFormat.RED),
|
HIGH(ChatColor.RED),
|
||||||
;
|
;
|
||||||
private final EnumChatFormat _color;
|
private final ChatColor _color;
|
||||||
|
|
||||||
Severity(EnumChatFormat color)
|
Severity(ChatColor color)
|
||||||
{
|
{
|
||||||
_color = color;
|
_color = color;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
package mineplex.core.antihack;
|
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public interface Detector
|
|
||||||
{
|
|
||||||
public void Reset(Player player);
|
|
||||||
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
||||||
|
* <p>
|
||||||
|
* Instances of this have no concept of identity i.e. account id is not tracked by this.
|
||||||
|
*/
|
||||||
|
public class ViolationLevels
|
||||||
|
{
|
||||||
|
private final TObjectIntMap<Class<? extends Check>> _maxViolations;
|
||||||
|
|
||||||
|
private final TObjectIntMap<Class<? extends Check>> _totalAlerts;
|
||||||
|
|
||||||
|
private final TObjectIntMap<Class<? extends Check>> _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;
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import com.mineplex.anticheat.api.PlayerViolationEvent;
|
|||||||
import com.mineplex.anticheat.checks.combat.KillauraTypeA;
|
import com.mineplex.anticheat.checks.combat.KillauraTypeA;
|
||||||
import com.mineplex.anticheat.checks.combat.KillauraTypeD;
|
import com.mineplex.anticheat.checks.combat.KillauraTypeD;
|
||||||
import com.mineplex.anticheat.checks.move.Glide;
|
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.move.Speed;
|
||||||
import mineplex.core.common.util.UtilServer;
|
import mineplex.core.common.util.UtilServer;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
@ -13,40 +14,19 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
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 final int _vl;
|
||||||
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;
|
|
||||||
|
|
||||||
AntiHackAction(int vl)
|
AntiHackAction(int vl)
|
||||||
{
|
{
|
||||||
this._vl = vl;
|
this._vl = vl;
|
||||||
|
|
||||||
UtilServer.RegisterEvents(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void handle(PlayerViolationEvent event);
|
public final int getMinVl()
|
||||||
|
|
||||||
public int getMinVl()
|
|
||||||
{
|
{
|
||||||
return this._vl;
|
return this._vl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AntiHackAction getAction(Class<?> checkClass)
|
public abstract void handle(PlayerViolationEvent event);
|
||||||
{
|
|
||||||
AntiHackAction action = ACTIONS.getOrDefault(checkClass, NOOP_ACTION);
|
|
||||||
return action;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
package mineplex.core.antihack.actions;
|
package mineplex.core.antihack.actions;
|
||||||
|
|
||||||
import com.mineplex.anticheat.api.PlayerViolationEvent;
|
import com.mineplex.anticheat.api.PlayerViolationEvent;
|
||||||
|
|
||||||
import mineplex.core.Managers;
|
import mineplex.core.Managers;
|
||||||
import mineplex.core.antihack.banwave.BanWaveManager;
|
import mineplex.core.antihack.banwave.BanWaveManager;
|
||||||
import mineplex.core.common.util.UtilMath;
|
import mineplex.core.common.util.UtilMath;
|
||||||
import mineplex.core.common.util.UtilServer;
|
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_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
|
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);
|
super(vl);
|
||||||
}
|
}
|
||||||
@ -27,7 +28,6 @@ class BanwaveAction extends AntiHackAction
|
|||||||
event.getPlayer(),
|
event.getPlayer(),
|
||||||
banTime,
|
banTime,
|
||||||
event.getCheckClass(),
|
event.getCheckClass(),
|
||||||
"[GWEN] Hacking [BanWave]",
|
|
||||||
event.getViolations(),
|
event.getViolations(),
|
||||||
UtilServer.getServerName()
|
UtilServer.getServerName()
|
||||||
);
|
);
|
||||||
|
@ -5,9 +5,9 @@ import mineplex.core.Managers;
|
|||||||
import mineplex.core.antihack.AntiHack;
|
import mineplex.core.antihack.AntiHack;
|
||||||
import mineplex.core.common.util.UtilServer;
|
import mineplex.core.common.util.UtilServer;
|
||||||
|
|
||||||
class ImmediateBanAction extends AntiHackAction
|
public class ImmediateBanAction extends AntiHackAction
|
||||||
{
|
{
|
||||||
ImmediateBanAction(int vl)
|
public ImmediateBanAction(int vl)
|
||||||
{
|
{
|
||||||
super(vl);
|
super(vl);
|
||||||
}
|
}
|
||||||
@ -17,12 +17,7 @@ class ImmediateBanAction extends AntiHackAction
|
|||||||
{
|
{
|
||||||
if (event.getViolations() >= this.getMinVl())
|
if (event.getViolations() >= this.getMinVl())
|
||||||
{
|
{
|
||||||
String server = UtilServer.getServerName();
|
Managers.get(AntiHack.class).doBan(event.getPlayer(), event.getCheckClass());
|
||||||
if (server.contains("-"))
|
|
||||||
{
|
|
||||||
server = server.substring(0, server.indexOf('-'));
|
|
||||||
}
|
|
||||||
Managers.get(AntiHack.class).doBan(event.getPlayer(), "[GWEN] Hacking [" + server + "]");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,7 @@ import com.mineplex.anticheat.api.PlayerViolationEvent;
|
|||||||
|
|
||||||
public class NoopAction extends AntiHackAction
|
public class NoopAction extends AntiHackAction
|
||||||
{
|
{
|
||||||
NoopAction()
|
public NoopAction()
|
||||||
{
|
{
|
||||||
super(Integer.MAX_VALUE);
|
super(Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
@ -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<Double, Double> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -34,6 +34,11 @@ public class BanWaveInfo
|
|||||||
*/
|
*/
|
||||||
private String _server;
|
private String _server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The metadata id
|
||||||
|
*/
|
||||||
|
private String _metadata;
|
||||||
|
|
||||||
public int getAccountId()
|
public int getAccountId()
|
||||||
{
|
{
|
||||||
return _accountId;
|
return _accountId;
|
||||||
@ -94,6 +99,16 @@ public class BanWaveInfo
|
|||||||
_server = server;
|
_server = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMetadataId()
|
||||||
|
{
|
||||||
|
return this._metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetadataId(String id)
|
||||||
|
{
|
||||||
|
this._metadata = id;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
|
@ -5,14 +5,25 @@ import mineplex.core.ReflectivelyCreateMiniPlugin;
|
|||||||
import mineplex.core.account.CoreClient;
|
import mineplex.core.account.CoreClient;
|
||||||
import mineplex.core.account.CoreClientManager;
|
import mineplex.core.account.CoreClientManager;
|
||||||
import mineplex.core.antihack.AntiHack;
|
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.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.mineplex.anticheat.checks.Check;
|
||||||
|
import com.mineplex.anticheat.checks.CheckManager;
|
||||||
|
|
||||||
@ReflectivelyCreateMiniPlugin
|
@ReflectivelyCreateMiniPlugin
|
||||||
public class BanWaveManager extends MiniPlugin
|
public class BanWaveManager extends MiniPlugin
|
||||||
{
|
{
|
||||||
private final BanWaveRepository _repository = new BanWaveRepository();
|
private final BanWaveRepository _repository = new BanWaveRepository();
|
||||||
|
private final CoreClientManager _clientManager = require(CoreClientManager.class);
|
||||||
|
|
||||||
private BanWaveManager()
|
private BanWaveManager()
|
||||||
{
|
{
|
||||||
@ -32,29 +43,39 @@ public class BanWaveManager extends MiniPlugin
|
|||||||
|
|
||||||
if (info.getTimeToBan() < now)
|
if (info.getTimeToBan() < now)
|
||||||
{
|
{
|
||||||
require(AntiHack.class).doBanWave(event.getPlayer(), info.getMessage());
|
require(AntiHack.class).doBanWave(event.getPlayer(), info);
|
||||||
_repository.flagDone(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(() ->
|
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, id))
|
||||||
{
|
{
|
||||||
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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ public class BanWaveRepository extends MinecraftRepository
|
|||||||
"message VARCHAR(255), " +
|
"message VARCHAR(255), " +
|
||||||
"vl INT, " +
|
"vl INT, " +
|
||||||
"server VARCHAR(32), " +
|
"server VARCHAR(32), " +
|
||||||
|
"metadata VARCHAR(10), " +
|
||||||
"PRIMARY KEY (accountId)," +
|
"PRIMARY KEY (accountId)," +
|
||||||
"FOREIGN KEY (accountId) REFERENCES accounts(id))";
|
"FOREIGN KEY (accountId) REFERENCES accounts(id))";
|
||||||
|
|
||||||
@ -28,12 +29,14 @@ public class BanWaveRepository extends MinecraftRepository
|
|||||||
"message VARCHAR(255), " +
|
"message VARCHAR(255), " +
|
||||||
"vl INT, " +
|
"vl INT, " +
|
||||||
"server VARCHAR(32), " +
|
"server VARCHAR(32), " +
|
||||||
|
"metadata VARCHAR(10), " +
|
||||||
"PRIMARY KEY (id)," +
|
"PRIMARY KEY (id)," +
|
||||||
"FOREIGN KEY (accountId) REFERENCES accounts(id))";
|
"FOREIGN KEY (accountId) REFERENCES accounts(id))";
|
||||||
private static final String QUERY_PENDING = "SELECT * FROM banwavePending WHERE accountId = ?";
|
|
||||||
private static final String INSERT_PENDING = "INSERT IGNORE INTO banwavePending (accountId, timeToBan, hacktype, message, vl, server) VALUES (?, ?, ?, ?, ?, ?)";
|
|
||||||
|
|
||||||
private static final String PROCESS_WAVE_FOR_ACCOUNT = "INSERT INTO banwaveProcessed SELECT 0, accountId, timeToBan, hacktype, message, vl, server FROM banwavePending WHERE accountId = ?";
|
private static final String QUERY_PENDING = "SELECT * FROM banwavePending WHERE accountId = ?";
|
||||||
|
private static final String INSERT_PENDING = "INSERT IGNORE INTO banwavePending (accountId, timeToBan, hacktype, message, vl, server, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)";
|
||||||
|
|
||||||
|
private static final String PROCESS_WAVE_FOR_ACCOUNT = "INSERT INTO banwaveProcessed SELECT 0, accountId, timeToBan, hacktype, message, vl, server, metadata FROM banwavePending WHERE accountId = ?";
|
||||||
private static final String DELETE_PENDING = "DELETE FROM banwavePending WHERE accountId = ?";
|
private static final String DELETE_PENDING = "DELETE FROM banwavePending WHERE accountId = ?";
|
||||||
|
|
||||||
BanWaveRepository()
|
BanWaveRepository()
|
||||||
@ -66,22 +69,25 @@ public class BanWaveRepository extends MinecraftRepository
|
|||||||
info.setMessage(resultSet.getString(4));
|
info.setMessage(resultSet.getString(4));
|
||||||
info.setVl(resultSet.getInt(5));
|
info.setVl(resultSet.getInt(5));
|
||||||
info.setServer(resultSet.getString(6));
|
info.setServer(resultSet.getString(6));
|
||||||
|
info.setMessage(resultSet.getString(7));
|
||||||
|
|
||||||
callback.run(info);
|
callback.run(info);
|
||||||
}
|
}
|
||||||
}, new ColumnInt("accountId", accountId));
|
}, 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, String metadata)
|
||||||
{
|
{
|
||||||
executeInsert(INSERT_PENDING, null,
|
int affectedRows = executeInsert(INSERT_PENDING, null,
|
||||||
new ColumnInt("accountId", accountId),
|
new ColumnInt("accountId", accountId),
|
||||||
new ColumnLong("timeToBan", timeToBan),
|
new ColumnLong("timeToBan", timeToBan),
|
||||||
new ColumnVarChar("hacktype", 64, hackType),
|
new ColumnVarChar("hacktype", 64, hackType),
|
||||||
new ColumnVarChar("message", 255, message),
|
new ColumnVarChar("message", 255, message),
|
||||||
new ColumnInt("vl", vl),
|
new ColumnInt("vl", vl),
|
||||||
new ColumnVarChar("server", 32, server)
|
new ColumnVarChar("server", 32, server),
|
||||||
|
new ColumnVarChar("metadata", 10, metadata)
|
||||||
);
|
);
|
||||||
|
return affectedRows > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void flagDone(BanWaveInfo info)
|
void flagDone(BanWaveInfo info)
|
||||||
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package mineplex.core.antihack;
|
package mineplex.core.antihack.guardians;
|
||||||
|
|
||||||
import com.mineplex.spigot.ChunkAddEntityEvent;
|
import com.mineplex.spigot.ChunkAddEntityEvent;
|
||||||
import mineplex.core.Managers;
|
import mineplex.core.Managers;
|
@ -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<Integer, Double> STALK_END_PROBABILITY_EQUATION = x ->
|
||||||
|
{
|
||||||
|
return 1.0/ MAX_MIN_DIFF * x; // linear equation with points (0, 0) and (diff, 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Cache<UUID, Boolean> _stalkingCooldown = CacheBuilder.newBuilder()
|
||||||
|
.concurrencyLevel(1)
|
||||||
|
.expireAfterWrite(STALK_COOLDOWN_TIME_SECONDS, TimeUnit.SECONDS)
|
||||||
|
.build();
|
||||||
|
private final List<UUID> _stalking = new ArrayList<>();
|
||||||
|
private List<AntiHackGuardian> _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<Player> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,196 @@
|
|||||||
|
package mineplex.core.antihack.logging;
|
||||||
|
|
||||||
|
import com.mineplex.anticheat.checks.Check;
|
||||||
|
import com.mineplex.anticheat.checks.CheckManager;
|
||||||
|
|
||||||
|
import gnu.trove.map.TIntObjectMap;
|
||||||
|
|
||||||
|
import mineplex.core.antihack.ViolationLevels;
|
||||||
|
import mineplex.core.database.MinecraftRepository;
|
||||||
|
import mineplex.serverdata.database.DBPool;
|
||||||
|
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
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(plugin, DBPool.getAccount());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit a set of user violation changes batch style.
|
||||||
|
*
|
||||||
|
* @param uploadQueue the {@link TIntObjectMap} describing the changes.
|
||||||
|
*/
|
||||||
|
public void saveViolationLevels(Map<Integer, ViolationLevels> 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<ViolationLevels> 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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
@ -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<Integer, ViolationLevels> _violationLevels = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private final Map<String, AnticheatMetadata> _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<AntihackLogger>(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<Integer, ViolationLevels> 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<Integer, ViolationLevels> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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<UUID> _joinTime = new TObjectLongHashMap<>();
|
||||||
|
private TObjectIntMap<UUID> _joinTimeTick = new TObjectIntHashMap<>();
|
||||||
|
private Map<UUID, Map<Class<? extends Check>, List<JsonObject>>> _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<JsonObject> 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<JsonObject> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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<Player, Entry<Integer, Double>> _floatTicks = new HashMap<Player, Entry<Integer, Double>>(); //Ticks, PrevY
|
|
||||||
private HashMap<Player, Entry<Integer, Double>> _hoverTicks = new HashMap<Player, Entry<Integer, Double>>(); //Ticks, PrevY
|
|
||||||
private HashMap<Player, Entry<Integer, Double>> _riseTicks = new HashMap<Player, Entry<Integer, Double>>(); //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<Integer, Double>(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<Integer, Double>(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<Integer, Double>(count, player.getLocation().getY()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void Reset(Player player)
|
|
||||||
{
|
|
||||||
_floatTicks.remove(player);
|
|
||||||
_hoverTicks.remove(player);
|
|
||||||
_riseTicks.remove(player);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<Player, Long> _idleTime = new HashMap<Player, Long>();
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<Player, ArrayList<Location>> _history = new HashMap<Player, ArrayList<Location>>();
|
|
||||||
|
|
||||||
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<Location>());
|
|
||||||
|
|
||||||
_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<Location> 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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<Player, Entry<Integer, Long>> _speedTicks = new HashMap<Player, Entry<Integer, Long>>(); //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<Integer, Long>(count, System.currentTimeMillis()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void Reset(Player player)
|
|
||||||
{
|
|
||||||
_speedTicks.remove(player);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
package mineplex.core.punish;
|
package mineplex.core.punish;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import mineplex.core.account.CoreClient;
|
import mineplex.core.account.CoreClient;
|
||||||
@ -167,6 +168,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)
|
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<PunishmentResponse> callback)
|
||||||
{
|
{
|
||||||
Player player = Bukkit.getPlayerExact(playerName);
|
Player player = Bukkit.getPlayerExact(playerName);
|
||||||
if (player != null)
|
if (player != null)
|
||||||
@ -250,7 +256,7 @@ public class Punish extends MiniPlugin
|
|||||||
|
|
||||||
if (player != null)
|
if (player != null)
|
||||||
player.kickPlayer(kickReason);
|
player.kickPlayer(kickReason);
|
||||||
else
|
|
||||||
new mineplex.serverdata.commands.PunishCommand(finalPlayerName, true, false, kickReason).publish();
|
new mineplex.serverdata.commands.PunishCommand(finalPlayerName, true, false, kickReason).publish();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -277,7 +283,7 @@ public class Punish extends MiniPlugin
|
|||||||
UtilPlayer.message(player, F.main("Punish", F.elem(C.cGray + C.Bold + "Reason: ") + reason));
|
UtilPlayer.message(player, F.main("Punish", F.elem(C.cGray + C.Bold + "Reason: ") + reason));
|
||||||
player.playSound(player.getLocation(), Sound.CAT_MEOW, 1f, 1f);
|
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<PunishClientToken>()
|
_repository.LoadPunishClient(finalPlayerName, new Callback<PunishClientToken>()
|
||||||
@ -316,7 +322,7 @@ public class Punish extends MiniPlugin
|
|||||||
UtilPlayer.message(player, F.main("Punish", F.elem(C.cGray + C.Bold + "Reason: ") + reason));
|
UtilPlayer.message(player, F.main("Punish", F.elem(C.cGray + C.Bold + "Reason: ") + reason));
|
||||||
player.playSound(player.getLocation(), Sound.CAT_MEOW, 1f, 1f);
|
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<PunishClientToken>()
|
_repository.LoadPunishClient(finalPlayerName, new Callback<PunishClientToken>()
|
||||||
@ -328,6 +334,10 @@ public class Punish extends MiniPlugin
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (callback != null)
|
||||||
|
{
|
||||||
|
callback.accept(banResult);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -259,15 +259,6 @@ public class PunishPage extends CraftInventoryCustom implements Listener
|
|||||||
|
|
||||||
|
|
||||||
int flightSeverity = 2;
|
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[]
|
AddButton(41, new ShopItem(Material.INK_SACK, (byte)1, "Severity 3",new String[]
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,8 @@ import mineplex.core.TimingsFix;
|
|||||||
import mineplex.core.account.CoreClientManager;
|
import mineplex.core.account.CoreClientManager;
|
||||||
import mineplex.core.achievement.AchievementManager;
|
import mineplex.core.achievement.AchievementManager;
|
||||||
import mineplex.core.antihack.AntiHack;
|
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.blockrestore.BlockRestore;
|
||||||
import mineplex.core.chat.Chat;
|
import mineplex.core.chat.Chat;
|
||||||
import mineplex.core.chatsnap.SnapshotManager;
|
import mineplex.core.chatsnap.SnapshotManager;
|
||||||
@ -139,8 +140,9 @@ public class Clans extends JavaPlugin
|
|||||||
Creature creature = new Creature(this);
|
Creature creature = new Creature(this);
|
||||||
|
|
||||||
AntiHack antiHack = require(AntiHack.class);
|
AntiHack antiHack = require(AntiHack.class);
|
||||||
antiHack.setKick(false);
|
GuardianManager guardianManager = require(GuardianManager.class);
|
||||||
Bukkit.getScheduler().runTask(this, antiHack::enableNewAnticheat);
|
|
||||||
|
Bukkit.getScheduler().runTask(this, antiHack::enableAnticheat);
|
||||||
|
|
||||||
new EternalGiveawayManager(this, _clientManager, serverStatusManager);
|
new EternalGiveawayManager(this, _clientManager, serverStatusManager);
|
||||||
|
|
||||||
@ -155,7 +157,7 @@ public class Clans extends JavaPlugin
|
|||||||
Location spawn = new Location(Bukkit.getWorld("world"), -422, 95, 8);
|
Location spawn = new Location(Bukkit.getWorld("world"), -422, 95, 8);
|
||||||
for (int i = 0; i < 10; i++)
|
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);
|
Location spawn = new Location(Bukkit.getWorld("world"), 424, 95, -8);
|
||||||
for (int i = 0; i < 10; i++)
|
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);
|
Location spawn = new Location(Bukkit.getWorld("world"), 9, 210, -393);
|
||||||
for (int i = 0; i < 10; i++)
|
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);
|
Location spawn = new Location(Bukkit.getWorld("world"), 8, 210, 390);
|
||||||
for (int i = 0; i < 10; i++)
|
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);
|
Location spawn = new Location(Bukkit.getWorld("world"), 0, 100, 0);
|
||||||
for (int i = 0; i < 40; i++)
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ import mineplex.core.PacketsInteractionFix;
|
|||||||
import mineplex.core.account.CoreClientManager;
|
import mineplex.core.account.CoreClientManager;
|
||||||
import mineplex.core.achievement.AchievementManager;
|
import mineplex.core.achievement.AchievementManager;
|
||||||
import mineplex.core.antihack.AntiHack;
|
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.aprilfools.AprilFoolsManager;
|
||||||
import mineplex.core.blockrestore.BlockRestore;
|
import mineplex.core.blockrestore.BlockRestore;
|
||||||
import mineplex.core.boosters.BoosterManager;
|
import mineplex.core.boosters.BoosterManager;
|
||||||
@ -120,10 +121,11 @@ public class ClansHub extends JavaPlugin
|
|||||||
Portal portal = new Portal(this, clientManager, serverStatusManager.getCurrentServerName());
|
Portal portal = new Portal(this, clientManager, serverStatusManager.getCurrentServerName());
|
||||||
|
|
||||||
AntiHack antiHack = require(AntiHack.class);
|
AntiHack antiHack = require(AntiHack.class);
|
||||||
|
GuardianManager guardianManager = require(GuardianManager.class);
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
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);
|
IgnoreManager ignoreManager = new IgnoreManager(this, clientManager, preferenceManager, portal);
|
||||||
|
@ -10,7 +10,8 @@ import mineplex.core.PacketsInteractionFix;
|
|||||||
import mineplex.core.account.CoreClientManager;
|
import mineplex.core.account.CoreClientManager;
|
||||||
import mineplex.core.achievement.AchievementManager;
|
import mineplex.core.achievement.AchievementManager;
|
||||||
import mineplex.core.antihack.AntiHack;
|
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.aprilfools.AprilFoolsManager;
|
||||||
import mineplex.core.blockrestore.BlockRestore;
|
import mineplex.core.blockrestore.BlockRestore;
|
||||||
import mineplex.core.boosters.BoosterManager;
|
import mineplex.core.boosters.BoosterManager;
|
||||||
@ -147,10 +148,11 @@ public class Hub extends JavaPlugin implements IRelation
|
|||||||
Portal portal = new Portal(this, clientManager, serverStatusManager.getCurrentServerName());
|
Portal portal = new Portal(this, clientManager, serverStatusManager.getCurrentServerName());
|
||||||
|
|
||||||
AntiHack antiHack = require(AntiHack.class);
|
AntiHack antiHack = require(AntiHack.class);
|
||||||
|
GuardianManager guardianManager = require(GuardianManager.class);
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
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);
|
IgnoreManager ignoreManager = new IgnoreManager(this, clientManager, preferenceManager, portal);
|
||||||
|
@ -4,6 +4,7 @@ import mineplex.core.CustomTagFix;
|
|||||||
import mineplex.core.FoodDupeFix;
|
import mineplex.core.FoodDupeFix;
|
||||||
import mineplex.core.PacketsInteractionFix;
|
import mineplex.core.PacketsInteractionFix;
|
||||||
import mineplex.core.TimingsFix;
|
import mineplex.core.TimingsFix;
|
||||||
|
import mineplex.core.antihack.logging.AntihackLogger;
|
||||||
import mineplex.core.chatsnap.SnapshotRepository;
|
import mineplex.core.chatsnap.SnapshotRepository;
|
||||||
import mineplex.core.customdata.CustomDataManager;
|
import mineplex.core.customdata.CustomDataManager;
|
||||||
import mineplex.core.chatsnap.SnapshotManager;
|
import mineplex.core.chatsnap.SnapshotManager;
|
||||||
@ -65,6 +66,8 @@ import mineplex.core.velocity.VelocityFix;
|
|||||||
import mineplex.core.visibility.VisibilityManager;
|
import mineplex.core.visibility.VisibilityManager;
|
||||||
import mineplex.minecraft.game.core.combat.CombatManager;
|
import mineplex.minecraft.game.core.combat.CombatManager;
|
||||||
import mineplex.minecraft.game.core.damage.DamageManager;
|
import mineplex.minecraft.game.core.damage.DamageManager;
|
||||||
|
|
||||||
|
import nautilus.game.arcade.anticheatmetadata.GameInfoMetadata;
|
||||||
import nautilus.game.arcade.game.GameServerConfig;
|
import nautilus.game.arcade.game.GameServerConfig;
|
||||||
import net.minecraft.server.v1_8_R3.BiomeBase;
|
import net.minecraft.server.v1_8_R3.BiomeBase;
|
||||||
import net.minecraft.server.v1_8_R3.MinecraftServer;
|
import net.minecraft.server.v1_8_R3.MinecraftServer;
|
||||||
@ -149,8 +152,7 @@ public class Arcade extends JavaPlugin
|
|||||||
|
|
||||||
Punish punish = new Punish(this, webServerAddress, _clientManager);
|
Punish punish = new Punish(this, webServerAddress, _clientManager);
|
||||||
|
|
||||||
AntiHack antiHack = require(AntiHack.class);
|
require(AntiHack.class);
|
||||||
antiHack.setKick(false);
|
|
||||||
|
|
||||||
IgnoreManager ignoreManager = new IgnoreManager(this, _clientManager, preferenceManager, portal);
|
IgnoreManager ignoreManager = new IgnoreManager(this, _clientManager, preferenceManager, portal);
|
||||||
StatsManager statsManager = new StatsManager(this, _clientManager);
|
StatsManager statsManager = new StatsManager(this, _clientManager);
|
||||||
@ -187,6 +189,8 @@ public class Arcade extends JavaPlugin
|
|||||||
PollManager pollManager = new PollManager(this, _clientManager, _donationManager);
|
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);
|
_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 GlobalPacketManager(this, _clientManager, serverStatusManager, inventoryManager, _donationManager, petManager, statsManager, _gameManager.getBonusManager().getRewardManager());
|
||||||
|
|
||||||
//new BroadcastManager(this, _gameManager);
|
//new BroadcastManager(this, _gameManager);
|
||||||
|
@ -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<UUID, JsonArray> _allGames = new HashMap<>();
|
||||||
|
private final Map<UUID, JsonObject> _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<String, Integer> 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);
|
||||||
|
}
|
||||||
|
}
|
@ -82,6 +82,9 @@ import nautilus.game.arcade.events.GameStateChangeEvent;
|
|||||||
import nautilus.game.arcade.events.PlayerGameRespawnEvent;
|
import nautilus.game.arcade.events.PlayerGameRespawnEvent;
|
||||||
import nautilus.game.arcade.events.PlayerStateChangeEvent;
|
import nautilus.game.arcade.events.PlayerStateChangeEvent;
|
||||||
import nautilus.game.arcade.game.GameTeam.PlayerState;
|
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.game.modules.Module;
|
||||||
import nautilus.game.arcade.kit.ChampionsKit;
|
import nautilus.game.arcade.kit.ChampionsKit;
|
||||||
import nautilus.game.arcade.kit.Kit;
|
import nautilus.game.arcade.kit.Kit;
|
||||||
@ -740,11 +743,14 @@ public abstract class Game implements Listener
|
|||||||
|
|
||||||
if (this._gameState == Game.GameState.Prepare)
|
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)
|
else if (this._gameState == Game.GameState.End)
|
||||||
{
|
{
|
||||||
Managers.get(AntiHack.class).disableNewAnticheat();
|
Managers.get(AntiHack.class).disableAnticheat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1231,16 +1231,6 @@ 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
|
@EventHandler
|
||||||
public void PlayerKillCommandCancel(PlayerCommandPreprocessEvent event)
|
public void PlayerKillCommandCancel(PlayerCommandPreprocessEvent event)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user