diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dcf923a --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# Eclipse stuff +.classpath +.project +.settings/ + +# netbeans +nbproject/ +nbactions.xml + +# we use maven! +build.xml + +# maven +target/ +dependency-reduced-pom.xml + +# vim +.*.sw[a-p] + +# various other potential build files +build/ +bin/ +dist/ +manifest.mf + +# Mac filesystem dust +.DS_Store/ +.DS_Store + +# intellij +*.iml +*.ipr +*.iws +.idea/ + +working-dir/ diff --git a/README.md b/README.md index 19f07bc..1fea526 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # FairFight -d +Fat quick anticheat to skid like agc +Not shitty perm plugin needed no more \ No newline at end of file diff --git a/libs/ragespigot-1.8.8-R0.1-SNAPSHOT.jar b/libs/ragespigot-1.8.8-R0.1-SNAPSHOT.jar new file mode 100644 index 0000000..0bb4072 Binary files /dev/null and b/libs/ragespigot-1.8.8-R0.1-SNAPSHOT.jar differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..4f39d36 --- /dev/null +++ b/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + me.joeleoli.fairfight + FairFight + 1.0-SNAPSHOT + + + 1.8 + 1.8 + + + + + me.joeleoli.ragespigot + ragespigot + 1.8.8-R0.1-SNAPSHOT + system + ${project.basedir}/libs/ragespigot-1.8.8-R0.1-SNAPSHOT.jar + + + com.google.code.gson + gson + 2.3.1 + compile + + + org.projectlombok + lombok + 1.14.8 + provided + + + redis.clients + jedis + 2.8.1 + jar + compile + + + org.mongodb + mongodb-driver + LATEST + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-shade-plugin + 2.1 + + + package + + shade + + + + + + + + \ No newline at end of file diff --git a/src/main/java/me/joeleoli/fairfight/FairFight.java b/src/main/java/me/joeleoli/fairfight/FairFight.java new file mode 100644 index 0000000..6eee81e --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/FairFight.java @@ -0,0 +1,91 @@ +package me.joeleoli.fairfight; + + +import lombok.Getter; + +import me.joeleoli.fairfight.client.ClientManager; +import me.joeleoli.fairfight.command.FairFightCommand; +import me.joeleoli.fairfight.handler.CustomMovementHandler; +import me.joeleoli.fairfight.handler.CustomPacketHandler; +import me.joeleoli.fairfight.listener.BungeeListener; +import me.joeleoli.fairfight.manager.PlayerDataManager; +import me.joeleoli.fairfight.mongo.FairFightMongo; +import me.joeleoli.fairfight.task.InsertLogsTask; + +import me.joeleoli.fairfight.util.nucleus.config.FileConfig; +import me.joeleoli.fairfight.util.nucleus.listener.ListenerHandler; +import me.joeleoli.ragespigot.RageSpigot; + +import net.minecraft.server.v1_8_R3.MinecraftServer; + +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +@Getter +public class FairFight extends JavaPlugin { + + @Getter + private static FairFight instance; + + private FileConfig mainFileConfig; + private FairFightMongo mongo; + private PlayerDataManager playerDataManager; + private ClientManager clientManager; + private Set receivingAlerts; + private Set disabledChecks; + private double rangeVl; + + public FairFight() { + this.rangeVl = 30.0; + } + + public void onEnable() { + instance = this; + + this.receivingAlerts = new HashSet<>(); + this.disabledChecks = new HashSet<>(); + + this.mainFileConfig = new FileConfig(this, "config.yml"); + this.mongo = new FairFightMongo(); + + RageSpigot.INSTANCE.addPacketHandler(new CustomPacketHandler(this)); + RageSpigot.INSTANCE.addMovementHandler(new CustomMovementHandler(this)); + + getCommand("fairfight").setExecutor(new FairFightCommand()); + + ListenerHandler.loadListenersFromPackage(this, "me.joeleoli.fairfight.listener"); + + this.getServer().getMessenger().registerIncomingPluginChannel(this, "BungeeCord", new BungeeListener(this)); + this.getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); + + this.getServer().getScheduler().runTaskTimer(this, new InsertLogsTask(), 20L * 60L * 5L, 20L * 60L * 5L); + + this.playerDataManager = new PlayerDataManager(); + this.clientManager = new ClientManager(); + } + + public boolean isAntiCheatEnabled() { + return MinecraftServer.getServer().tps1.getAverage() > 19.0 && MinecraftServer.LAST_TICK_TIME + 100L > System.currentTimeMillis(); + } + + public boolean canAlert(Player player) { + return this.receivingAlerts.contains(player.getUniqueId()); + } + + public boolean toggleAlerts(Player player) { + boolean current = this.receivingAlerts.remove(player.getUniqueId()); + + if (!current) { + this.receivingAlerts.add(player.getUniqueId()); + } + + return !current; + } + + private String oof = "This is the most bullshit thing I've ever made."; + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/AbstractCheck.java b/src/main/java/me/joeleoli/fairfight/check/AbstractCheck.java new file mode 100644 index 0000000..7597fc5 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/AbstractCheck.java @@ -0,0 +1,74 @@ +package me.joeleoli.fairfight.check; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import me.joeleoli.fairfight.FairFight; +import me.joeleoli.fairfight.event.player.AlertType; + +import org.bukkit.entity.Player; + +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.PlayerAlertEvent; +import me.joeleoli.fairfight.event.player.PlayerBanEvent; + +@AllArgsConstructor +@Getter +public abstract class AbstractCheck implements ICheck { + + protected final PlayerData playerData; + private final Class clazz; + private final String name; + + @Override + public Class getType() { + return this.clazz; + } + + protected FairFight getPlugin() { + return FairFight.getInstance(); + } + + protected double getVl() { + return this.playerData.getCheckVl(this); + } + + protected void setVl(final double vl) { + this.playerData.setCheckVl(vl, this); + } + + protected boolean alert(AlertType alertType, Player player, String extra, boolean violation) { + final PlayerAlertEvent event = new PlayerAlertEvent(alertType, player, this.name, extra); + + this.getPlugin().getServer().getPluginManager().callEvent(event); + + if (!event.isCancelled()) { + if (violation) { + this.playerData.addViolation(this); + } + + return true; + } + + return false; + } + + protected boolean ban(final Player player) { + this.playerData.setBanning(true); + + final PlayerBanEvent event = new PlayerBanEvent(player, this.name); + + this.getPlugin().getServer().getPluginManager().callEvent(event); + + return !event.isCancelled(); + } + + protected void randomBan(Player player, double rate) { + this.playerData.setRandomBanRate(rate); + this.playerData.setRandomBanReason(this.name); + this.playerData.setRandomBan(true); + + this.getPlugin().getServer().getPluginManager().callEvent(new PlayerAlertEvent(AlertType.RELEASE, player, this.name, null)); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/ICheck.java b/src/main/java/me/joeleoli/fairfight/check/ICheck.java new file mode 100644 index 0000000..c61b9ee --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/ICheck.java @@ -0,0 +1,11 @@ +package me.joeleoli.fairfight.check; + +import org.bukkit.entity.Player; + +public interface ICheck { + + void handleCheck(Player player, T type); + + Class getType(); + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/checks/PacketCheck.java b/src/main/java/me/joeleoli/fairfight/check/checks/PacketCheck.java new file mode 100644 index 0000000..3e23928 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/checks/PacketCheck.java @@ -0,0 +1,13 @@ +package me.joeleoli.fairfight.check.checks; + +import net.minecraft.server.v1_8_R3.Packet; +import me.joeleoli.fairfight.check.AbstractCheck; +import me.joeleoli.fairfight.player.PlayerData; + +public abstract class PacketCheck extends AbstractCheck { + + public PacketCheck(PlayerData playerData, final String name) { + super(playerData, Packet.class, name); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/checks/PositionCheck.java b/src/main/java/me/joeleoli/fairfight/check/checks/PositionCheck.java new file mode 100644 index 0000000..6b480c0 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/checks/PositionCheck.java @@ -0,0 +1,13 @@ +package me.joeleoli.fairfight.check.checks; + +import me.joeleoli.fairfight.check.AbstractCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.util.update.PositionUpdate; + +public abstract class PositionCheck extends AbstractCheck { + + public PositionCheck(PlayerData playerData, String name) { + super(playerData, PositionUpdate.class, name); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/checks/RotationCheck.java b/src/main/java/me/joeleoli/fairfight/check/checks/RotationCheck.java new file mode 100644 index 0000000..6fecdcc --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/checks/RotationCheck.java @@ -0,0 +1,13 @@ +package me.joeleoli.fairfight.check.checks; + +import me.joeleoli.fairfight.check.AbstractCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.util.update.RotationUpdate; + +public abstract class RotationCheck extends AbstractCheck { + + public RotationCheck(PlayerData playerData, String name) { + super(playerData, RotationUpdate.class, name); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistA.java b/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistA.java new file mode 100644 index 0000000..188b3d4 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistA.java @@ -0,0 +1,41 @@ +package me.joeleoli.fairfight.check.impl.aimassist; + +import me.joeleoli.fairfight.check.checks.RotationCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.MathUtil; +import me.joeleoli.fairfight.util.update.RotationUpdate; +import org.bukkit.entity.Player; + +public class AimAssistA extends RotationCheck { + + private float suspiciousYaw; + + public AimAssistA(PlayerData playerData) { + super(playerData, "Aim (Check 1)"); + } + + @Override + public void handleCheck(Player player, RotationUpdate update) { + if (System.currentTimeMillis() - this.playerData.getLastAttackPacket() > 10000L) { + return; + } + + final float diffYaw = MathUtil.getDistanceBetweenAngles(update.getTo().getYaw(), update.getFrom().getYaw()); + + if (diffYaw > 1.0f && Math.round(diffYaw) == diffYaw && diffYaw % 1.5f != 0.0f) { + if (diffYaw == this.suspiciousYaw && this.alert(AlertType.RELEASE, player, "Y " + diffYaw + ".", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 20) { + this.ban(player); + } + } + + this.suspiciousYaw = Math.round(diffYaw); + } else { + this.suspiciousYaw = 0.0f; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistB.java b/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistB.java new file mode 100644 index 0000000..07fab36 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistB.java @@ -0,0 +1,41 @@ +package me.joeleoli.fairfight.check.impl.aimassist; + +import me.joeleoli.fairfight.check.checks.RotationCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.MathUtil; +import me.joeleoli.fairfight.util.update.RotationUpdate; +import org.bukkit.entity.Player; + +public class AimAssistB extends RotationCheck { + + private float suspiciousYaw; + + public AimAssistB(PlayerData playerData) { + super(playerData, "Aim (Check 2)"); + } + + @Override + public void handleCheck(Player player, RotationUpdate update) { + if (System.currentTimeMillis() - this.playerData.getLastAttackPacket() > 10000L) { + return; + } + + final float diffYaw = MathUtil.getDistanceBetweenAngles(update.getTo().getYaw(), update.getFrom().getYaw()); + + if (diffYaw > 1.0f && Math.round(diffYaw * 10.0f) * 0.1f == diffYaw && Math.round(diffYaw) != diffYaw && diffYaw % 1.5f != 0.0f) { + if (diffYaw == this.suspiciousYaw && this.alert(AlertType.RELEASE, player, String.format("Y %.1f.", diffYaw), true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 20) { + this.ban(player); + } + } + + this.suspiciousYaw = Math.round(diffYaw * 10.0f) * 0.1f; + } else { + this.suspiciousYaw = 0.0f; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistC.java b/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistC.java new file mode 100644 index 0000000..7c54802 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistC.java @@ -0,0 +1,37 @@ +package me.joeleoli.fairfight.check.impl.aimassist; + +import me.joeleoli.fairfight.check.checks.RotationCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.MathUtil; +import me.joeleoli.fairfight.util.update.RotationUpdate; + +import org.bukkit.entity.Player; + +public class AimAssistC extends RotationCheck { + + public AimAssistC(PlayerData playerData) { + super(playerData, "Aim (Check 3)"); + } + + @Override + public void handleCheck(final Player player, final RotationUpdate update) { + if (System.currentTimeMillis() - this.playerData.getLastAttackPacket() > 10000L) { + return; + } + + final float diffYaw = MathUtil.getDistanceBetweenAngles(update.getTo().getYaw(), update.getFrom().getYaw()); + double vl = this.getVl(); + + if (update.getFrom().getPitch() == update.getTo().getPitch() && diffYaw >= 3.0f && update.getFrom().getPitch() != 90.0f && update.getTo().getPitch() != 90.0f) { + if ((vl += 0.9) >= 6.3) { + this.alert(AlertType.EXPERIMENTAL, player, String.format("Y %.1f. VL %.1f.", diffYaw, vl), false); + } + } else { + vl -= 1.6; + } + + this.setVl(vl); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistD.java b/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistD.java new file mode 100644 index 0000000..a87b9b0 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistD.java @@ -0,0 +1,49 @@ +package me.joeleoli.fairfight.check.impl.aimassist; + +import me.joeleoli.fairfight.check.checks.RotationCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.MathUtil; +import me.joeleoli.fairfight.util.update.RotationUpdate; +import org.bukkit.entity.Player; + +public class AimAssistD extends RotationCheck { + private float lastYawRate; + private float lastPitchRate; + + public AimAssistD(PlayerData playerData) { + super(playerData, "Aim (Check 4)"); + } + + @Override + public void handleCheck(final Player player, final RotationUpdate update) { + if (System.currentTimeMillis() - this.playerData.getLastAttackPacket() > 10000L) { + return; + } + + float diffPitch = MathUtil.getDistanceBetweenAngles(update.getTo().getPitch(), update.getFrom().getPitch()); + float diffYaw = MathUtil.getDistanceBetweenAngles(update.getTo().getYaw(), update.getFrom().getYaw()); + + float diffPitchRate = Math.abs(this.lastPitchRate - diffPitch); + float diffYawRate = Math.abs(this.lastYawRate - diffYaw); + + float diffPitchRatePitch = Math.abs(diffPitchRate - diffPitch); + float diffYawRateYaw = Math.abs(diffYawRate - diffYaw); + + if (diffPitch < 0.009 && diffPitch > 0.001 && diffPitchRate > 1.0 && diffYawRate > 1.0 && diffYaw > 3.0 && + this.lastYawRate > 1.5 && (diffPitchRatePitch > 1.0f || diffYawRateYaw > 1.0f)) { + this.alert(AlertType.EXPERIMENTAL, player, + String.format("DPR %.3f. DYR %.3f. LPR %.3f. LYR %.3f. DP %.3f. DY %.2f. DPRP %.3f. DYRY %.3f.", + diffPitchRate, diffYawRate, this.lastPitchRate, this.lastYawRate, diffPitch, diffYaw, + diffPitchRatePitch, diffYawRateYaw), true); + + if (!this.playerData.isBanning() && this.playerData.getViolations(this, 1000L * 60 * 10) > 5) { + this.ban(player); + } + } + + this.lastPitchRate = diffPitch; + this.lastYawRate = diffYaw; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistE.java b/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistE.java new file mode 100644 index 0000000..4432242 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/aimassist/AimAssistE.java @@ -0,0 +1,49 @@ +package me.joeleoli.fairfight.check.impl.aimassist; + +import me.joeleoli.fairfight.check.checks.RotationCheck; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.MathUtil; +import org.bukkit.entity.Player; +import me.joeleoli.fairfight.FairFight; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.util.update.RotationUpdate; + +public class AimAssistE extends RotationCheck { + + private float lastPitchRate; + private float lastYawRate; + + public AimAssistE(PlayerData playerData) { + super(playerData, "Aim (Check 5)"); + } + + @Override + public void handleCheck(Player player, RotationUpdate update) { + if (System.currentTimeMillis() - this.playerData.getLastAttackPacket() > 10000L) { + return; + } + + float diffPitch = MathUtil.getDistanceBetweenAngles(update.getTo().getPitch(), update.getFrom().getPitch()); + float diffYaw = MathUtil.getDistanceBetweenAngles(update.getTo().getYaw(), update.getFrom().getYaw()); + + float diffYawPitch = Math.abs(diffYaw - diffPitch); + + float diffPitchRate = Math.abs(this.lastPitchRate - diffPitch); + float diffYawRate = Math.abs(this.lastYawRate - diffYaw); + + float diffPitchRatePitch = Math.abs(diffPitchRate - diffPitch); + float diffYawRateYaw = Math.abs(diffYawRate - diffYaw); + + if (diffYaw > 0.05f && diffPitch > 0.05 && (diffPitchRate > 1.0 || diffYawRate > 1.0) && + (diffPitchRatePitch > 1.0f || diffYawRateYaw > 1.0f) && diffYawPitch < 0.009f && diffYawPitch > 0.001f) { + this.alert(AlertType.EXPERIMENTAL, player, + String.format("DYP %.3f. DP %.3f. DY %.3f. DPR %.3f. DYR %.3f. DPRP %.3f. DYRY %.3f.", + diffYawPitch, diffYaw, diffPitch, diffPitchRate, diffYawRate, + diffPitchRatePitch, diffYawRateYaw), false); + } + + this.lastYawRate = diffYaw; + this.lastPitchRate = diffPitch; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerA.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerA.java new file mode 100644 index 0000000..c406c29 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerA.java @@ -0,0 +1,45 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +import me.joeleoli.fairfight.player.PlayerData; + +public class AutoClickerA extends PacketCheck { + + private int swings; + private int movements; + + public AutoClickerA(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 1)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInArmAnimation + && !this.playerData.isDigging() && !this.playerData.isPlacing() && !this.playerData.isFakeDigging() + && (System.currentTimeMillis() - this.playerData.getLastDelayedMovePacket()) > 220L + && (System.currentTimeMillis() - this.playerData.getLastMovePacket().getTimestamp()) < 110L) { + ++this.swings; + } else if (packet instanceof PacketPlayInFlying && ++this.movements == 20) { + if (this.swings > 20 && + this.alert(AlertType.RELEASE, player, "C " + this.swings + ".", true)) { + + int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 3) { + this.ban(player); + } + } + + this.playerData.setLastCps(this.swings); + this.movements = this.swings = 0; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerB.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerB.java new file mode 100644 index 0000000..9980b6c --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerB.java @@ -0,0 +1,72 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +import me.joeleoli.fairfight.player.PlayerData; + +public class AutoClickerB extends PacketCheck { + + private int clicks; + private int outliers; + private int flyingCount; + private boolean release; + + public AutoClickerB(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 2)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInArmAnimation && !this.playerData.isDigging() && + !this.playerData.isPlacing() && + System.currentTimeMillis() - this.playerData.getLastDelayedMovePacket() > 220L && + this.playerData.getLastMovePacket() != null && + System.currentTimeMillis() - this.playerData.getLastMovePacket().getTimestamp() < 110L && + !this.playerData.isFakeDigging()) { + + if (this.flyingCount < 10) { + if (this.release) { + this.release = false; + this.flyingCount = 0; + return; + } + + if (this.flyingCount > 3) { + ++this.outliers; + } else if (this.flyingCount == 0) { + return; + } + + if (++this.clicks == 1000) { + double vl = this.getVl(); + + if (this.outliers <= 7) { + if ((vl += 1.4) >= 4.0) { + this.alert(AlertType.DEVELOPMENT, player, String.format("O %s. VL %.2f.", this.outliers, vl), false); + } + } else { + vl -= 0.8; + } + + this.setVl(vl); + final boolean b = false; + this.outliers = (b ? 1 : 0); + this.clicks = (b ? 1 : 0); + } + } + this.flyingCount = 0; + } else if (packet instanceof PacketPlayInFlying) { + ++this.flyingCount; + } else if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.RELEASE_USE_ITEM) { + this.release = true; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerC.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerC.java new file mode 100644 index 0000000..ca43c67 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerC.java @@ -0,0 +1,46 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; + +import org.bukkit.entity.Player; + +public class AutoClickerC extends PacketCheck { + + private boolean sent; + + public AutoClickerC(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 3)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInBlockDig) { + final PacketPlayInBlockDig.EnumPlayerDigType digType = ((PacketPlayInBlockDig) packet).c(); + + if (digType == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + this.sent = true; + } else if (digType == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + int vl = (int) this.getVl(); + + if (this.sent) { + if (++vl > 10 && this.alert(AlertType.RELEASE, player, "VL " + vl + ".", false) && !this.playerData.isBanning() && !this.playerData.isRandomBan() && vl >= 20) { + this.randomBan(player, 250.0); + } + } else { + vl = 0; + } + + this.setVl(vl); + } + } else if (packet instanceof PacketPlayInArmAnimation) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerD.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerD.java new file mode 100644 index 0000000..f1ceb61 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerD.java @@ -0,0 +1,88 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class AutoClickerD extends PacketCheck { + + private int movements; + private int stage; + + public AutoClickerD(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 4)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + int vl = (int) this.getVl(); + + if (this.stage == 0) { + if (packet instanceof PacketPlayInArmAnimation) { + ++this.stage; + } + } else if (this.stage == 1) { + if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + ++this.stage; + } else { + this.stage = 0; + } + } else if (this.stage == 2) { + if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + if (++vl >= 5) { + try { + if (this.movements > 10 && this.alert(AlertType.RELEASE, player, "M " + this.movements + ".", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && !this.playerData.isRandomBan() && violations > 4) { + this.randomBan(player, 250.0); + } + } + } finally { + final boolean movements = false; + this.movements = (movements ? 1 : 0); + vl = (movements ? 1 : 0); + } + } + + this.stage = 0; + } else if (packet instanceof PacketPlayInArmAnimation) { + ++this.stage; + } else { + final boolean b = false; + this.movements = (b ? 1 : 0); + vl = (b ? 1 : 0); + this.stage = (b ? 1 : 0); + } + } else if (this.stage == 3) { + if (packet instanceof PacketPlayInFlying) { + ++this.stage; + } else { + final boolean b2 = false; + this.movements = (b2 ? 1 : 0); + vl = (b2 ? 1 : 0); + this.stage = (b2 ? 1 : 0); + } + } else if (this.stage == 4) { + if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + ++this.movements; + + this.stage = 0; + } else { + final boolean b3 = false; + this.movements = (b3 ? 1 : 0); + vl = (b3 ? 1 : 0); + this.stage = (b3 ? 1 : 0); + } + } + + this.setVl(vl); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerE.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerE.java new file mode 100644 index 0000000..ad945bc --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerE.java @@ -0,0 +1,54 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class AutoClickerE extends PacketCheck { + + private boolean failed; + private boolean sent; + private int count; + + public AutoClickerE(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 5)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInArmAnimation + && (System.currentTimeMillis() - this.playerData.getLastDelayedMovePacket()) > 220L + && (System.currentTimeMillis() - this.playerData.getLastMovePacket().getTimestamp()) < 110L + && !this.playerData.isDigging() && !this.playerData.isPlacing() && !this.playerData.isFakeDigging()) { + if (this.sent) { + ++this.count; + + if (!this.failed) { + int vl = (int) this.getVl(); + + if (++vl >= 5) { + this.alert(AlertType.EXPERIMENTAL, player, "CO " + this.count + ".", false); + vl = 0; + } + + this.setVl(vl); + this.failed = true; + } + } else { + this.sent = true; + this.count = 0; + } + } else if (packet instanceof PacketPlayInFlying) { + final boolean b = false; + this.failed = b; + this.sent = b; + this.count = 0; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerF.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerF.java new file mode 100644 index 0000000..51678b4 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerF.java @@ -0,0 +1,70 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.BlockPosition; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +import me.joeleoli.fairfight.player.PlayerData; + +import java.util.Deque; +import java.util.LinkedList; + +public class AutoClickerF extends PacketCheck { + + private final Deque recentCounts; + private BlockPosition lastBlock; + private int flyingCount; + + public AutoClickerF(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 6)"); + this.recentCounts = new LinkedList<>(); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInBlockDig) { + final PacketPlayInBlockDig blockDig = (PacketPlayInBlockDig) packet; + if (blockDig.c() == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + if (this.lastBlock != null && this.lastBlock.equals(blockDig.a())) { + double vl = this.getVl(); + this.recentCounts.addLast(this.flyingCount); + if (this.recentCounts.size() == 20) { + double average = 0.0; + for (final int i : this.recentCounts) { + average += i; + } + average /= this.recentCounts.size(); + double stdDev = 0.0; + for (final int j : this.recentCounts) { + stdDev += Math.pow(j - average, 2.0); + } + stdDev /= this.recentCounts.size(); + stdDev = Math.sqrt(stdDev); + if (stdDev < 0.45 && ++vl >= 3.0) { + if (this.alert(AlertType.RELEASE, player, String.format("STD %.2f. VL " + + "%.1f.", stdDev, vl), false) && !this.playerData.isBanning() && !this.playerData + .isRandomBan() && vl >= 6.0) { + this.randomBan(player, 200.0); + } + } else { + vl -= 0.5; + } + this.recentCounts.clear(); + } + this.setVl(vl); + } + this.flyingCount = 0; + } else if (blockDig.c() == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + this.lastBlock = blockDig.a(); + } + } else if (packet instanceof PacketPlayInFlying) { + ++this.flyingCount; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerG.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerG.java new file mode 100644 index 0000000..5f01bc7 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerG.java @@ -0,0 +1,44 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockPlace; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class AutoClickerG extends PacketCheck { + + private boolean failed; + private boolean sent; + + public AutoClickerG(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 7)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInBlockPlace && ((PacketPlayInBlockPlace) packet).getFace() == 255 && System + .currentTimeMillis() - this.playerData.getLastDelayedMovePacket() > 220L && this.playerData + .getLastMovePacket() != null && System.currentTimeMillis() - this.playerData.getLastMovePacket() + .getTimestamp() < 110L && this.playerData.getLastAnimationPacket() + 1000L > System.currentTimeMillis + ()) { + if (this.sent) { + if (!this.failed) { + this.alert(AlertType.EXPERIMENTAL, player, "", false); + this.failed = true; + } + } else { + this.sent = true; + } + } else if (packet instanceof PacketPlayInFlying) { + final boolean b = false; + this.failed = b; + this.sent = b; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerH.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerH.java new file mode 100644 index 0000000..c15ff9d --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerH.java @@ -0,0 +1,73 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import java.util.Deque; +import java.util.LinkedList; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import org.bukkit.entity.Player; + +public class AutoClickerH extends PacketCheck { + private final Deque recentCounts; + private int flyingCount; + private boolean release; + + public AutoClickerH(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 8)"); + this.recentCounts = new LinkedList(); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInArmAnimation && !this.playerData.isDigging() && + !this.playerData.isPlacing() && + System.currentTimeMillis() - this.playerData.getLastDelayedMovePacket() > 220L && + this.playerData.getLastMovePacket() != null && + System.currentTimeMillis() - this.playerData.getLastMovePacket().getTimestamp() < 110L && + !this.playerData.isFakeDigging()) { + if (this.flyingCount < 10) { + if (this.release) { + this.release = false; + this.flyingCount = 0; + return; + } + this.recentCounts.add(this.flyingCount); + if (this.recentCounts.size() == 100) { + double average = 0.0; + for (final int i : this.recentCounts) { + average += i; + } + average /= this.recentCounts.size(); + double stdDev = 0.0; + for (final int j : this.recentCounts) { + stdDev += Math.pow(j - average, 2.0); + } + stdDev /= this.recentCounts.size(); + stdDev = Math.sqrt(stdDev); + double vl = this.getVl(); + if (stdDev < 0.45) { + if ((vl += 1.4) >= 4.0) { + this.alert(AlertType.EXPERIMENTAL, player, + String.format("STD %.2f. VL %.2f.", stdDev, vl), false); + } + } else { + vl -= 0.8; + } + this.setVl(vl); + this.recentCounts.clear(); + } + } + this.flyingCount = 0; + } else if (packet instanceof PacketPlayInFlying) { + ++this.flyingCount; + } else if (packet instanceof PacketPlayInBlockDig && + ((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.RELEASE_USE_ITEM) { + this.release = true; + } + } +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerI.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerI.java new file mode 100644 index 0000000..3acd611 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerI.java @@ -0,0 +1,65 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockPlace; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +import java.util.Deque; +import java.util.LinkedList; + +public class AutoClickerI extends PacketCheck { + + private final Deque recentCounts; + private int flyingCount; + + public AutoClickerI(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 9)"); + this.recentCounts = new LinkedList<>(); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.RELEASE_USE_ITEM) { + if (this.flyingCount < 10 && this.playerData.getLastAnimationPacket() + 2000L > System.currentTimeMillis()) { + this.recentCounts.add(this.flyingCount); + if (this.recentCounts.size() == 100) { + double average = 0.0; + for (final double flyingCount : this.recentCounts) { + average += flyingCount; + } + average /= this.recentCounts.size(); + double stdDev = 0.0; + for (final long l : this.recentCounts) { + stdDev += Math.pow(l - average, 2.0); + } + stdDev /= this.recentCounts.size(); + stdDev = Math.sqrt(stdDev); + double vl = this.getVl(); + if (stdDev < 0.2) { + if ((vl += 1.4) >= 4.0) { + this.alert(AlertType.EXPERIMENTAL, player, String.format("STD %.2f. VL %.2f.", stdDev, + vl), false); + } + } else { + vl -= 0.8; + } + this.setVl(vl); + this.recentCounts.clear(); + } + } + } else if (packet instanceof PacketPlayInBlockPlace && ((PacketPlayInBlockPlace) packet).getItemStack() != + null && ((PacketPlayInBlockPlace) packet).getItemStack().getName().toLowerCase().contains("sword")) { + this.flyingCount = 0; + } else if (packet instanceof PacketPlayInFlying) { + ++this.flyingCount; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerJ.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerJ.java new file mode 100644 index 0000000..ef8639b --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerJ.java @@ -0,0 +1,57 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import org.bukkit.entity.Player; + +public class AutoClickerJ extends PacketCheck { + private int stage; + + public AutoClickerJ(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 10)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (this.stage == 0) { + if (packet instanceof PacketPlayInArmAnimation) { + ++this.stage; + } + } else if (packet instanceof PacketPlayInBlockDig) { + if (this.playerData.getFakeBlocks().contains(((PacketPlayInBlockDig) packet).a())) { + return; + } + + double vl = this.getVl(); + + PacketPlayInBlockDig.EnumPlayerDigType digType = ((PacketPlayInBlockDig) packet).c(); + if (digType == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + if (this.stage == 1) { + ++this.stage; + } else { + this.stage = 0; + } + } else if (digType == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + if (this.stage == 2) { + if ((vl += 1.4) >= 15.0 && + this.alert(AlertType.RELEASE, player, String.format("VL %.2f.", vl), true) && + !this.playerData.isBanning() && !this.playerData.isRandomBan() && vl >= 50.0) { + this.randomBan(player, 250.0); + } + } else { + this.stage = 0; + vl -= 0.25; + } + } else { + this.stage = 0; + } + this.setVl(vl); + } else { + this.stage = 0; + } + } +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerK.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerK.java new file mode 100644 index 0000000..3c95007 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerK.java @@ -0,0 +1,104 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class AutoClickerK extends PacketCheck { + + private int stage; + private boolean other; + + public AutoClickerK(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 11)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (this.stage == 0) { + if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig)packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + ++this.stage; + } + } else if (this.stage == 1) { + if (packet instanceof PacketPlayInArmAnimation) { + ++this.stage; + } else { + this.stage = 0; + } + } else if (this.stage == 2) { + if (packet instanceof PacketPlayInFlying) { + ++this.stage; + } else { + this.stage = 0; + } + } else if (this.stage == 3) { + if (packet instanceof PacketPlayInArmAnimation) { + ++this.stage; + } else { + this.stage = 0; + } + } else if (this.stage == 4) { + if (packet instanceof PacketPlayInFlying) { + ++this.stage; + } else { + this.stage = 0; + } + } else if (this.stage == 5) { + if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig)packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + if (this.alert(AlertType.EXPERIMENTAL, player, "", false)) { + this.checkBan(player); + } + + this.stage = 0; + } else if (packet instanceof PacketPlayInArmAnimation) { + ++this.stage; + } else if (packet instanceof PacketPlayInFlying) { + this.other = true; + ++this.stage; + } else { + this.stage = 0; + } + } else if (this.stage == 6) { + if (!this.other) { + if (packet instanceof PacketPlayInFlying) { + ++this.stage; + } else { + this.stage = 0; + } + } else { + if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig)packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + if (this.alert(AlertType.EXPERIMENTAL, player, "Type B.", false)) { + this.checkBan(player); + } + + this.other = false; + } + + this.stage = 0; + } + } else if (this.stage == 7) { + if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig)packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + if (this.alert(AlertType.EXPERIMENTAL, player, "Type C.", false)) { + this.checkBan(player); + } + } else { + this.stage = 0; + } + } + } + + private void checkBan(final Player player) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerL.java b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerL.java new file mode 100644 index 0000000..680383e --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/autoclicker/AutoClickerL.java @@ -0,0 +1,72 @@ +package me.joeleoli.fairfight.check.impl.autoclicker; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class AutoClickerL extends PacketCheck { + + private int movements; + private int failed; + private int passed; + private int stage; + + public AutoClickerL(PlayerData playerData) { + super(playerData, "Auto-Clicker (Check 12)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (System.currentTimeMillis() - this.playerData.getLastDelayedMovePacket() > 220L && this.playerData.getLastMovePacket() != null && System.currentTimeMillis() - this.playerData.getLastMovePacket().getTimestamp() < 110L) { + if (packet instanceof PacketPlayInArmAnimation) { + if (this.stage == 0 || this.stage == 1) { + ++this.stage; + } else { + this.stage = 1; + } + } else if (packet instanceof PacketPlayInFlying) { + if (this.stage == 2) { + ++this.stage; + } else { + this.stage = 0; + } + ++this.movements; + } else if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { + if (this.stage == 3) { + ++this.failed; + } else { + ++this.passed; + } + if (this.movements >= 200 && this.failed + this.passed > 60) { + final double rat = (this.passed == 0) ? -1.0 : (this.failed / this.passed); + double vl = this.getVl(); + + if (rat > 2.5) { + if ((vl += 1.0 + (rat - 2.0) * 0.75) >= 4.0) { + this.alert(AlertType.EXPERIMENTAL, player, String.format("RAT %.2f. VL %.2f.", rat, vl), false); + } + } else { + vl -= 2.0; + } + + this.setVl(vl); + + final boolean failed = false; + this.movements = (failed ? 1 : 0); + this.passed = (failed ? 1 : 0); + this.failed = (failed ? 1 : 0); + } + } + } else { + this.stage = 0; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsA.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsA.java new file mode 100644 index 0000000..1ff6507 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsA.java @@ -0,0 +1,35 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInSteerVehicle; + +import org.bukkit.entity.Player; + +public class BadPacketsA extends PacketCheck { + + private int streak; + + public BadPacketsA(PlayerData playerData) { + super(playerData, "Packets (Check 1)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInFlying) { + if (((PacketPlayInFlying) packet).g()) { + this.streak = 0; + } else if (++this.streak > 20 && this.alert(AlertType.RELEASE, player, "", false) && !this.playerData + .isBanning()) { + this.ban(player); + } + } else if (packet instanceof PacketPlayInSteerVehicle) { + this.streak = 0; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsB.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsB.java new file mode 100644 index 0000000..52b7560 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsB.java @@ -0,0 +1,27 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class BadPacketsB extends PacketCheck { + + public BadPacketsB(PlayerData playerData) { + super(playerData, "Packets (Check 2)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInFlying && Math.abs(((PacketPlayInFlying) packet).e()) > 90.0f && this.alert + (AlertType.RELEASE, player, "", false) && !this.playerData.isBanning() && !this.playerData + .isRandomBan()) { + this.randomBan(player, 200.0); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsC.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsC.java new file mode 100644 index 0000000..b268491 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsC.java @@ -0,0 +1,44 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInEntityAction; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class BadPacketsC extends PacketCheck { + + private boolean sent; + + public BadPacketsC(PlayerData playerData) { + super(playerData, "Packets (Check 3)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInEntityAction) { + final PacketPlayInEntityAction.EnumPlayerAction playerAction = ((PacketPlayInEntityAction) packet).b(); + + if (playerAction == PacketPlayInEntityAction.EnumPlayerAction.START_SPRINTING || playerAction == PacketPlayInEntityAction.EnumPlayerAction.STOP_SPRINTING) { + if (this.sent) { + if (this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } else { + this.sent = true; + } + } + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsD.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsD.java new file mode 100644 index 0000000..7ff05f3 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsD.java @@ -0,0 +1,43 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInEntityAction; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class BadPacketsD extends PacketCheck { + + private boolean sent; + + public BadPacketsD(PlayerData playerData) { + super(playerData, "Packets (Check 4)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInEntityAction) { + final PacketPlayInEntityAction.EnumPlayerAction playerAction = ((PacketPlayInEntityAction) packet).b(); + if (playerAction == PacketPlayInEntityAction.EnumPlayerAction.START_SNEAKING || playerAction == + PacketPlayInEntityAction.EnumPlayerAction.STOP_SNEAKING) { + if (this.sent) { + if (this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } else { + this.sent = true; + } + } + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsE.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsE.java new file mode 100644 index 0000000..f311dee --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsE.java @@ -0,0 +1,29 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; + +import org.bukkit.entity.Player; + +public class BadPacketsE extends PacketCheck { + + public BadPacketsE(PlayerData playerData) { + super(playerData, "Packets (Check 5)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.RELEASE_USE_ITEM && this.playerData.isPlacing() && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsF.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsF.java new file mode 100644 index 0000000..15cd3be --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsF.java @@ -0,0 +1,39 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockPlace; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInHeldItemSlot; + +import org.bukkit.entity.Player; + +public class BadPacketsF extends PacketCheck { + + private boolean sent; + + public BadPacketsF(PlayerData playerData) { + super(playerData, "Packets (Check 6)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInHeldItemSlot) { + if (this.sent && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } else if (packet instanceof PacketPlayInBlockPlace) { + this.sent = true; + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsG.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsG.java new file mode 100644 index 0000000..0f17a60 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsG.java @@ -0,0 +1,39 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInEntityAction; + +import org.bukkit.entity.Player; + +public class BadPacketsG extends PacketCheck { + + private PacketPlayInEntityAction.EnumPlayerAction lastAction; + + public BadPacketsG(PlayerData playerData) { + super(playerData, "Packets (Check 7)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInEntityAction) { + final PacketPlayInEntityAction.EnumPlayerAction playerAction = ((PacketPlayInEntityAction) packet).b(); + + if (playerAction == PacketPlayInEntityAction.EnumPlayerAction.START_SPRINTING || playerAction == PacketPlayInEntityAction.EnumPlayerAction.STOP_SPRINTING) { + if (this.lastAction == playerAction && this.playerData.getLastAttackPacket() + 10000L > System.currentTimeMillis() && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + + this.lastAction = playerAction; + } + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsH.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsH.java new file mode 100644 index 0000000..bf67238 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsH.java @@ -0,0 +1,39 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInHeldItemSlot; + +import org.bukkit.entity.Player; + +public class BadPacketsH extends PacketCheck { + + private int lastSlot; + + public BadPacketsH(PlayerData playerData) { + super(playerData, "Packets (Check 8)"); + + this.lastSlot = -1; + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInHeldItemSlot) { + final int slot = ((PacketPlayInHeldItemSlot) packet).a(); + + if (this.lastSlot == slot && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + + this.lastSlot = slot; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsI.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsI.java new file mode 100644 index 0000000..83c7a3e --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsI.java @@ -0,0 +1,45 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInSteerVehicle; + +import org.bukkit.entity.Player; + +public class BadPacketsI extends PacketCheck { + + private float lastYaw; + private float lastPitch; + private boolean ignore; + + public BadPacketsI(PlayerData playerData) { + super(playerData, "Packets (Check 9)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInFlying) { + final PacketPlayInFlying flying = (PacketPlayInFlying) packet; + + if (!flying.g() && flying.h()) { + if (this.lastYaw == flying.d() && this.lastPitch == flying.e()) { + if (!this.ignore) { + this.alert(AlertType.EXPERIMENTAL, player, "", false); + } + this.ignore = false; + } + this.lastYaw = flying.d(); + this.lastPitch = flying.e(); + } else { + this.ignore = true; + } + } else if (packet instanceof PacketPlayInSteerVehicle) { + this.ignore = true; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsJ.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsJ.java new file mode 100644 index 0000000..8c30598 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsJ.java @@ -0,0 +1,38 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockPlace; + +import org.bukkit.entity.Player; + +public class BadPacketsJ extends PacketCheck { + + private boolean placing; + + public BadPacketsJ(PlayerData playerData) { + super(playerData, "Packets (Check 10)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInBlockDig) { + if (((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.RELEASE_USE_ITEM) { + if (!this.placing && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + this.placing = false; + } + } else if (packet instanceof PacketPlayInBlockPlace) { + this.placing = true; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsK.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsK.java new file mode 100644 index 0000000..798436c --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsK.java @@ -0,0 +1,38 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.*; + +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class BadPacketsK extends PacketCheck { + + public BadPacketsK(PlayerData playerData) { + super(playerData, "Packets (Check 11)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInUseEntity) { + final PacketPlayInUseEntity useEntity = (PacketPlayInUseEntity) packet; + if (useEntity.a() == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT_AT) { + final Entity targetEntity = useEntity.a(((CraftPlayer) player).getHandle().getWorld()); + if (targetEntity instanceof EntityPlayer) { + final Vec3D vec3D = useEntity.b(); + if ((Math.abs(vec3D.a) > 0.41 || Math.abs(vec3D.b) > 1.91 || Math.abs(vec3D.c) > 0.41) && this + .alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + if (!this.playerData.isBanning() && !this.playerData.isRandomBan() && violations > 2) { + this.randomBan(player, 100.0); + } + } + } + } + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsL.java b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsL.java new file mode 100644 index 0000000..ad7f150 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/badpackets/BadPacketsL.java @@ -0,0 +1,47 @@ +package me.joeleoli.fairfight.check.impl.badpackets; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.*; + +import org.bukkit.entity.Player; + +public class BadPacketsL extends PacketCheck { + + private boolean sent; + private boolean vehicle; + + public BadPacketsL(PlayerData playerData) { + super(playerData, "Packets (Check 12)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInFlying) { + if (this.sent) { + this.alert(AlertType.EXPERIMENTAL, player, "", false); + } + + final boolean b = false; + this.vehicle = b; + this.sent = b; + } else if (packet instanceof PacketPlayInBlockPlace) { + final PacketPlayInBlockPlace blockPlace = (PacketPlayInBlockPlace) packet; + + if (blockPlace.getFace() == 255) { + final ItemStack itemStack = blockPlace.getItemStack(); + + if (itemStack != null && itemStack.getName().toLowerCase().contains("sword") && this.playerData.isSprinting() && !this.vehicle) { + this.sent = true; + } + } + } else if (packet instanceof PacketPlayInEntityAction && ((PacketPlayInEntityAction) packet).b() == PacketPlayInEntityAction.EnumPlayerAction.STOP_SPRINTING) { + this.sent = false; + } else if (packet instanceof PacketPlayInSteerVehicle) { + this.vehicle = true; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyA.java b/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyA.java new file mode 100644 index 0000000..4f40548 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyA.java @@ -0,0 +1,58 @@ +package me.joeleoli.fairfight.check.impl.fly; + +import me.joeleoli.fairfight.check.checks.PositionCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.update.PositionUpdate; + +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +public class FlyA extends PositionCheck { + + public FlyA(PlayerData playerData) { + super(playerData, "Flight (Check 1)"); + } + + @Override + public void handleCheck(final Player player, final PositionUpdate update) { + int vl = (int) this.getVl(); + + if (!this.playerData.isInLiquid() && !this.playerData.isOnGround() && this.playerData.getVelocityV() == 0) { + if (update.getFrom().getY() >= update.getTo().getY()) { + return; + } + + final double distance = update.getTo().getY() - this.playerData.getLastGroundY(); + double limit = 2.0; + + if (player.hasPotionEffect(PotionEffectType.JUMP)) { + for (final PotionEffect effect : player.getActivePotionEffects()) { + if (effect.getType().equals(PotionEffectType.JUMP)) { + final int level = effect.getAmplifier() + 1; + limit += Math.pow(level + 4.2, 2.0) / 16.0; + break; + } + } + } + + if (distance > limit) { + if (++vl >= 10 && this.alert(AlertType.RELEASE, player, "VL " + vl + ".", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 8) { + this.ban(player); + } + } + } else { + vl = 0; + } + } else { + vl = 0; + } + + this.setVl(vl); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyB.java b/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyB.java new file mode 100644 index 0000000..ebaa0a2 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyB.java @@ -0,0 +1,42 @@ +package me.joeleoli.fairfight.check.impl.fly; + +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.update.PositionUpdate; +import org.bukkit.entity.Player; + +import me.joeleoli.fairfight.check.checks.PositionCheck; + +public class FlyB extends PositionCheck { + + public FlyB(PlayerData playerData) { + super(playerData, "Flight (Check 2)"); + } + + @Override + public void handleCheck(final Player player, final PositionUpdate update) { + int vl = (int)this.getVl(); + + if (!this.playerData.isInLiquid() && !this.playerData.isOnGround()) { + final double offsetH = Math.hypot(update.getTo().getX() - update.getFrom().getX(), update.getTo().getZ() - update.getFrom().getZ()); + final double offsetY = update.getTo().getY() - update.getFrom().getY(); + + if (offsetH > 0.0 && offsetY == 0.0) { + if (++vl >= 10 && this.alert(AlertType.RELEASE, player, String.format("H %.2f. VL %s.", offsetH, vl), true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 8) { + this.ban(player); + } + } + } else { + vl = 0; + } + } else { + vl = 0; + } + + this.setVl(vl); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyC.java b/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyC.java new file mode 100644 index 0000000..fb25d8c --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyC.java @@ -0,0 +1,103 @@ +package me.joeleoli.fairfight.check.impl.fly; + +import me.joeleoli.fairfight.check.checks.PositionCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.update.PositionUpdate; + +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +public class FlyC extends PositionCheck { + + private int illegalMovements; + private int legalMovements; + + public FlyC(PlayerData playerData) { + super(playerData, "Flight (Check 3)"); + } + + @Override + public void handleCheck(final Player player, final PositionUpdate update) { + if (this.playerData.getVelocityH() == 0) { + final double offsetH = Math.hypot(update.getTo().getX() - update.getFrom().getX(), update.getTo().getZ() - update.getFrom().getZ()); + + int speed = 0; + + for (final PotionEffect effect : player.getActivePotionEffects()) { + if (effect.getType().equals(PotionEffectType.SPEED)) { + speed = effect.getAmplifier() + 1; + break; + } + } + + double threshold; + + if (this.playerData.isOnGround()) { + threshold = 0.34; + + if (this.playerData.isOnStairs()) { + threshold = 0.45; + } else if (this.playerData.isOnIce() || this.playerData.getMovementsSinceIce() < 40) { + if (this.playerData.isUnderBlock()) { + threshold = 1.3; + } else { + threshold = 0.8; + } + } else if (this.playerData.isUnderBlock() || this.playerData.getMovementsSinceUnderBlock() < 40) { + threshold = 0.7; + } else if (this.playerData.isOnCarpet()) { + threshold = 0.7; + } + + threshold += 0.06 * speed; + } else { + threshold = 0.36; + + if (this.playerData.isOnStairs()) { + threshold = 0.45; + } else if (this.playerData.isOnIce() || this.playerData.getMovementsSinceIce() < 40) { + if (this.playerData.isUnderBlock()) { + threshold = 1.3; + } else { + threshold = 0.8; + } + } else if (this.playerData.isUnderBlock() || this.playerData.getMovementsSinceUnderBlock() < 40) { + threshold = 0.7; + } else if (this.playerData.isOnCarpet()) { + threshold = 0.7; + } + + threshold += 0.02 * speed; + } + + threshold += ((player.getWalkSpeed() > 0.2f) ? (player.getWalkSpeed() * 10.0f * 0.33f) : 0.0f); + + if (offsetH > threshold) { + ++this.illegalMovements; + } else { + ++this.legalMovements; + } + + final int total = this.illegalMovements + this.legalMovements; + + if (total == 20) { + final double percentage = this.illegalMovements / 20.0 * 100.0; + + if (percentage >= 45.0 && this.alert(AlertType.RELEASE, player, String.format("P %.1f.", percentage), true)) { + final int violations = this.playerData.getViolations(this, 30000L); + + if (!this.playerData.isBanning() && violations > 5) { + this.ban(player); + } + } + + final boolean b = false; + this.legalMovements = (b ? 1 : 0); + this.illegalMovements = (b ? 1 : 0); + } + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyD.java b/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyD.java new file mode 100644 index 0000000..fa0f4d0 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/fly/FlyD.java @@ -0,0 +1,27 @@ +package me.joeleoli.fairfight.check.impl.fly; + +import me.joeleoli.fairfight.check.checks.PositionCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.update.PositionUpdate; +import org.bukkit.entity.Player; + +public class FlyD extends PositionCheck { + + public FlyD(PlayerData playerData) { + super(playerData, "Flight (Check 4)"); + } + + @Override + public void handleCheck(final Player player, final PositionUpdate update) { + final double offsetY = update.getTo().getY() - update.getFrom().getY(); + if (this.playerData.getVelocityY() == 0.0 && this.playerData.isWasOnGround() && !this.playerData.isUnderBlock + () && !this.playerData.isWasUnderBlock() && !this.playerData.isInLiquid() && !this.playerData + .isWasInLiquid() && !this.playerData.isInWeb() && !this.playerData.isWasInWeb() && !this.playerData + .isOnStairs() && offsetY > 0.0 && offsetY < 0.41999998688697815 && update.getFrom().getY() % 1.0 == + 0.0) { + this.alert(AlertType.EXPERIMENTAL, player, String.format("O %.2f.", offsetY), false); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryA.java b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryA.java new file mode 100644 index 0000000..80688f3 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryA.java @@ -0,0 +1,31 @@ +package me.joeleoli.fairfight.check.impl.inventory; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInWindowClick; + +import org.bukkit.entity.Player; + +public class InventoryA extends PacketCheck { + public InventoryA(PlayerData playerData) { + super(playerData, "Inventory (Check 1)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInWindowClick && ((PacketPlayInWindowClick) packet).a() == 0 && !this + .playerData.isInventoryOpen()) { + if (this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + if (!this.playerData.isBanning() && violations > 5) { + this.ban(player); + } + } + this.playerData.setInventoryOpen(true); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryB.java b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryB.java new file mode 100644 index 0000000..e6bad95 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryB.java @@ -0,0 +1,34 @@ +package me.joeleoli.fairfight.check.impl.inventory; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInEntityAction; + +import org.bukkit.entity.Player; + +public class InventoryB extends PacketCheck { + + public InventoryB(PlayerData playerData) { + super(playerData, "Inventory (Check 2)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (((packet instanceof PacketPlayInEntityAction && ((PacketPlayInEntityAction) packet).b() == PacketPlayInEntityAction.EnumPlayerAction.START_SPRINTING) || packet instanceof PacketPlayInArmAnimation) && this.playerData.isInventoryOpen()) { + if (this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 5) { + this.ban(player); + } + } + + this.playerData.setInventoryOpen(false); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryC.java b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryC.java new file mode 100644 index 0000000..51b7022 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryC.java @@ -0,0 +1,68 @@ +package me.joeleoli.fairfight.check.impl.inventory; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.CustomLocation; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInWindowClick; +import org.bukkit.entity.Player; + +import java.util.Deque; +import java.util.LinkedList; + +public class InventoryC extends PacketCheck { + + private final Deque delays; + + public InventoryC(PlayerData playerData) { + super(playerData, "Inventory (Check 3)"); + + this.delays = new LinkedList<>(); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInWindowClick && System.currentTimeMillis() - this.playerData.getLastDelayedMovePacket() > 220L && !this.playerData.isAllowTeleport()) { + final CustomLocation lastMovePacket = this.playerData.getLastMovePacket(); + + if (lastMovePacket == null) { + return; + } + + final long delay = System.currentTimeMillis() - lastMovePacket.getTimestamp(); + + this.delays.add(delay); + + if (this.delays.size() == 10) { + double average = 0.0; + + for (final long loopDelay : this.delays) { + average += loopDelay; + } + + average /= this.delays.size(); + + this.delays.clear(); + + double vl = this.getVl(); + + if (average <= 35.0) { + if ((vl += 1.25) >= 4.0) { + if (this.alert(AlertType.RELEASE, player, String.format("AVG %.1f. VL %.2f.", average, vl), true)) { + if (!this.playerData.isBanning() && !this.playerData.isRandomBan() && vl >= 10.0) { + this.randomBan(player, 100.0); + } + } else { + vl = 0.0; + } + } + } else { + vl -= 0.5; + } + this.setVl(vl); + } + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryD.java b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryD.java new file mode 100644 index 0000000..f7d3c42 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryD.java @@ -0,0 +1,43 @@ +package me.joeleoli.fairfight.check.impl.inventory; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInClientCommand; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class InventoryD extends PacketCheck { + + private int stage; + + public InventoryD(PlayerData playerData) { + super(playerData, "Inventory (Check 4)"); + this.stage = 0; + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (this.stage == 0) { + if (packet instanceof PacketPlayInClientCommand && ((PacketPlayInClientCommand)packet).a() == PacketPlayInClientCommand.EnumClientCommand.OPEN_INVENTORY_ACHIEVEMENT) { + ++this.stage; + } + } else if (this.stage == 1) { + if (packet instanceof PacketPlayInFlying.PacketPlayInLook) { + ++this.stage; + } else { + this.stage = 0; + } + } else if (this.stage == 2) { + if (packet instanceof PacketPlayInFlying.PacketPlayInLook) { + this.alert(AlertType.EXPERIMENTAL, player, "", false); + } + + this.stage = 0; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryE.java b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryE.java new file mode 100644 index 0000000..31bd08a --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryE.java @@ -0,0 +1,35 @@ +package me.joeleoli.fairfight.check.impl.inventory; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInClientCommand; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInWindowClick; + +import org.bukkit.entity.Player; + +public class InventoryE extends PacketCheck { + + private boolean sent; + + public InventoryE(PlayerData playerData) { + super(playerData, "Inventory (Check 5)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInWindowClick) { + if (this.sent) { + this.alert(AlertType.EXPERIMENTAL, player, "", true); + } + } else if (packet instanceof PacketPlayInClientCommand && ((PacketPlayInClientCommand) packet).a() == PacketPlayInClientCommand.EnumClientCommand.OPEN_INVENTORY_ACHIEVEMENT) { + this.sent = true; + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryF.java b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryF.java new file mode 100644 index 0000000..9ad342b --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryF.java @@ -0,0 +1,35 @@ +package me.joeleoli.fairfight.check.impl.inventory; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInClientCommand; +import net.minecraft.server.v1_8_R3.PacketPlayInCloseWindow; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class InventoryF extends PacketCheck { + + private boolean sent; + + public InventoryF(PlayerData playerData) { + super(playerData, "Inventory (Check 6)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInCloseWindow) { + if (this.sent) { + this.alert(AlertType.EXPERIMENTAL, player, "", true); + } + } else if (packet instanceof PacketPlayInClientCommand && ((PacketPlayInClientCommand) packet).a() == PacketPlayInClientCommand.EnumClientCommand.OPEN_INVENTORY_ACHIEVEMENT) { + this.sent = true; + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryG.java b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryG.java new file mode 100644 index 0000000..5e0e678 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/inventory/InventoryG.java @@ -0,0 +1,40 @@ +package me.joeleoli.fairfight.check.impl.inventory; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.*; +import org.bukkit.entity.Player; + +public class InventoryG extends PacketCheck { + + private boolean sent; + private boolean vehicle; + + public InventoryG(PlayerData playerData) { + super(playerData, "Inventory (Check 7)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInFlying) { + if (this.sent) { + this.alert(AlertType.EXPERIMENTAL, player, "", true); + } + final boolean b = false; + this.vehicle = b; + this.sent = b; + } else if (packet instanceof PacketPlayInClientCommand && ((PacketPlayInClientCommand) packet).a() == + PacketPlayInClientCommand.EnumClientCommand.OPEN_INVENTORY_ACHIEVEMENT) { + if (this.playerData.isSprinting() && !this.vehicle) { + this.sent = true; + } + } else if (packet instanceof PacketPlayInEntityAction && ((PacketPlayInEntityAction) packet).b() == + PacketPlayInEntityAction.EnumPlayerAction.STOP_SPRINTING) { + this.sent = false; + } else if (packet instanceof PacketPlayInSteerVehicle) { + this.vehicle = true; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraA.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraA.java new file mode 100644 index 0000000..cf65540 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraA.java @@ -0,0 +1,41 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraA extends PacketCheck { + private boolean sent; + + public KillAuraA(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 1)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInUseEntity && ((PacketPlayInUseEntity) packet).a() == PacketPlayInUseEntity + .EnumEntityUseAction.ATTACK) { + if (!this.sent) { + if (this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + if (!this.playerData.isBanning() && violations > 5) { + this.ban(player); + } + } + } else { + this.sent = false; + } + } else if (packet instanceof PacketPlayInArmAnimation) { + this.sent = true; + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraB.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraB.java new file mode 100644 index 0000000..ee6f9db --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraB.java @@ -0,0 +1,52 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import org.bukkit.entity.Player; + +public class KillAuraB extends PacketCheck { + private boolean sent; + private boolean failed; + private int movements; + + public KillAuraB(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 2)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (this.playerData.isDigging() && !this.playerData.isInstantBreakDigging() && + System.currentTimeMillis() - this.playerData.getLastDelayedMovePacket() > 220L && + this.playerData.getLastMovePacket() != null && + System.currentTimeMillis() - this.playerData.getLastMovePacket().getTimestamp() < 110L) { + int vl = (int) this.getVl(); + if (packet instanceof PacketPlayInBlockDig && + ((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + this.movements = 0; + vl = 0; + } else if (packet instanceof PacketPlayInArmAnimation && this.movements >= 2) { + if (this.sent) { + if (!this.failed) { + if (++vl >= 5) { + this.alert(AlertType.EXPERIMENTAL, player, "VL " + vl + ".", false); + } + this.failed = true; + } + } else { + this.sent = true; + } + } else if (packet instanceof PacketPlayInFlying) { + final boolean b = false; + this.failed = b; + this.sent = b; + ++this.movements; + } + this.setVl(vl); + } + } +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraC.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraC.java new file mode 100644 index 0000000..4b306d5 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraC.java @@ -0,0 +1,68 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.CustomLocation; +import me.joeleoli.fairfight.util.MathUtil; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class KillAuraC extends PacketCheck { + + private float lastYaw; + + public KillAuraC(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 3)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (this.playerData.getLastTarget() == null) { + return; + } + + if (packet instanceof PacketPlayInFlying) { + final PacketPlayInFlying flying = (PacketPlayInFlying) packet; + + if (flying.h() && !this.playerData.isAllowTeleport()) { + final CustomLocation targetLocation = this.playerData.getLastPlayerPacket(this.playerData.getLastTarget(), MathUtil.pingFormula(this.playerData.getPing())); + + if (targetLocation == null) { + return; + } + + final CustomLocation playerLocation = this.playerData.getLastMovePacket(); + + if (playerLocation.getX() == targetLocation.getX()) { + return; + } + + if (targetLocation.getZ() == playerLocation.getZ()) { + return; + } + + final float yaw = flying.d(); + + if (yaw != this.lastYaw) { + final float bodyYaw = MathUtil.getDistanceBetweenAngles(yaw, MathUtil.getRotationFromPosition + (playerLocation, targetLocation)[0]); + + if (bodyYaw == 0.0f && this.alert(AlertType.RELEASE, player, null, true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 5) { + this.ban(player); + } + } + } + + this.lastYaw = yaw; + } + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraD.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraD.java new file mode 100644 index 0000000..6276324 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraD.java @@ -0,0 +1,30 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraD extends PacketCheck { + + public KillAuraD(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 4)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInUseEntity && ((PacketPlayInUseEntity) packet).a() == PacketPlayInUseEntity + .EnumEntityUseAction.ATTACK && this.playerData.isPlacing() && this.alert(AlertType.RELEASE, player, + "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraE.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraE.java new file mode 100644 index 0000000..2ef28dd --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraE.java @@ -0,0 +1,59 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.CustomLocation; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraE extends PacketCheck { + + private long lastAttack; + private boolean attack; + + public KillAuraE(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 5)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + double vl = this.getVl(); + + if (packet instanceof PacketPlayInUseEntity && ((PacketPlayInUseEntity)packet).a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK && System.currentTimeMillis() - this.playerData.getLastDelayedMovePacket() > 220L && !this.playerData.isAllowTeleport()) { + final CustomLocation lastMovePacket = this.playerData.getLastMovePacket(); + + if (lastMovePacket == null) { + return; + } + + final long delay = System.currentTimeMillis() - lastMovePacket.getTimestamp(); + + if (delay <= 25.0) { + this.lastAttack = System.currentTimeMillis(); + this.attack = true; + } else { + vl -= 0.25; + } + } else if (packet instanceof PacketPlayInFlying && this.attack) { + final long time = System.currentTimeMillis() - this.lastAttack; + + if (time >= 25L) { + if (++vl >= 10.0 && this.alert(AlertType.RELEASE, player, String.format("T %s. VL %.2f.", time, vl), false) && !this.playerData.isBanning() && vl >= 20.0) { + this.ban(player); + } + } else { + vl -= 0.25; + } + + this.attack = false; + } + + this.setVl(vl); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraF.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraF.java new file mode 100644 index 0000000..03d2c49 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraF.java @@ -0,0 +1,43 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraF extends PacketCheck { + + private boolean sent; + + public KillAuraF(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 6)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInUseEntity) { + if (this.sent && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } else if (packet instanceof PacketPlayInBlockDig) { + final PacketPlayInBlockDig.EnumPlayerDigType digType = ((PacketPlayInBlockDig) packet).c(); + + if (digType == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK || digType == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK || digType == PacketPlayInBlockDig.EnumPlayerDigType.RELEASE_USE_ITEM) { + this.sent = true; + } + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraG.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraG.java new file mode 100644 index 0000000..67e2bb2 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraG.java @@ -0,0 +1,75 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.*; +import org.bukkit.entity.Player; + +public class KillAuraG extends PacketCheck { + + private int stage; + + public KillAuraG(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 7)"); + this.stage = 0; + } + + @Override + public void handleCheck(Player player, Packet packet) { + final int calculusStage = this.stage % 6; + if (calculusStage == 0) { + if (packet instanceof PacketPlayInArmAnimation) { + ++this.stage; + } + else { + this.stage = 0; + } + } + else if (calculusStage == 1) { + if (packet instanceof PacketPlayInUseEntity) { + ++this.stage; + } + else { + this.stage = 0; + } + } + else if (calculusStage == 2) { + if (packet instanceof PacketPlayInEntityAction) { + ++this.stage; + } + else { + this.stage = 0; + } + } + else if (calculusStage == 3) { + if (packet instanceof PacketPlayInFlying) { + ++this.stage; + } + else { + this.stage = 0; + } + } + else if (calculusStage == 4) { + if (packet instanceof PacketPlayInEntityAction) { + ++this.stage; + } + else { + this.stage = 0; + } + } + else if (calculusStage == 5) { + if (packet instanceof PacketPlayInFlying) { + if (++this.stage >= 30 && this.alert(AlertType.RELEASE, player, "S " + this.stage + ".", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + if (!this.playerData.isBanning() && violations > 5) { + this.ban(player); + } + } + } + else { + this.stage = 0; + } + } + } +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraH.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraH.java new file mode 100644 index 0000000..f70a97c --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraH.java @@ -0,0 +1,43 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraH extends PacketCheck { + + private boolean sent; + + public KillAuraH(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 8)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInBlockDig) { + final PacketPlayInBlockDig.EnumPlayerDigType digType = ((PacketPlayInBlockDig) packet).c(); + + if ((digType == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK || digType == + PacketPlayInBlockDig.EnumPlayerDigType.RELEASE_USE_ITEM) && this.sent && this.alert(AlertType + .RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } else if (packet instanceof PacketPlayInUseEntity) { + this.sent = true; + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraI.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraI.java new file mode 100644 index 0000000..3b01d5e --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraI.java @@ -0,0 +1,35 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class KillAuraI extends PacketCheck { + + private boolean sent; + + public KillAuraI(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 9)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.STOP_DESTROY_BLOCK) { + if (this.sent) { + this.alert(AlertType.EXPERIMENTAL, player, "", false); + } + } else if (packet instanceof PacketPlayInArmAnimation) { + this.sent = true; + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraJ.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraJ.java new file mode 100644 index 0000000..9e8498f --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraJ.java @@ -0,0 +1,36 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInHeldItemSlot; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraJ extends PacketCheck { + + private boolean sent; + + public KillAuraJ(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 10)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInHeldItemSlot) { + if (this.sent) { + this.alert(AlertType.EXPERIMENTAL, player, "", false); + } + } else if (packet instanceof PacketPlayInUseEntity && ((PacketPlayInUseEntity) packet).a() == + PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + this.sent = true; + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraK.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraK.java new file mode 100644 index 0000000..25bcc0a --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraK.java @@ -0,0 +1,63 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraK extends PacketCheck { + + private int ticksSinceStage; + private int streak; + private int stage; + + public KillAuraK(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 11)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInArmAnimation) { + if (this.stage == 0) { + this.stage = 1; + } else { + final boolean b = false; + this.stage = (b ? 1 : 0); + this.streak = (b ? 1 : 0); + } + } else if (packet instanceof PacketPlayInUseEntity) { + if (this.stage == 1) { + ++this.stage; + } else { + this.stage = 0; + } + } else if (packet instanceof PacketPlayInFlying.PacketPlayInPositionLook) { + if (this.stage == 2) { + ++this.stage; + } else { + this.stage = 0; + } + } else if (packet instanceof PacketPlayInFlying.PacketPlayInPosition) { + if (this.stage == 3) { + if (++this.streak >= 15) { + this.alert(AlertType.EXPERIMENTAL, player, "STR " + this.streak + ".", false); + } + + this.ticksSinceStage = 0; + } + + this.stage = 0; + } + + if (packet instanceof PacketPlayInFlying && ++this.ticksSinceStage > 40) { + this.streak = 0; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraL.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraL.java new file mode 100644 index 0000000..df65547 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraL.java @@ -0,0 +1,43 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInEntityAction; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraL extends PacketCheck { + + private boolean sent; + + public KillAuraL(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 12)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInUseEntity && ((PacketPlayInUseEntity) packet).a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + if (this.sent && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } else if (packet instanceof PacketPlayInEntityAction) { + final PacketPlayInEntityAction.EnumPlayerAction action = ((PacketPlayInEntityAction) packet).b(); + + if (action == PacketPlayInEntityAction.EnumPlayerAction.START_SPRINTING || action == PacketPlayInEntityAction.EnumPlayerAction.STOP_SPRINTING || action == PacketPlayInEntityAction.EnumPlayerAction.START_SNEAKING || action == PacketPlayInEntityAction.EnumPlayerAction.STOP_SNEAKING) { + this.sent = true; + } + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraM.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraM.java new file mode 100644 index 0000000..45958a6 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraM.java @@ -0,0 +1,47 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraM extends PacketCheck { + + private int swings; + private int attacks; + + public KillAuraM(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 13)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (!this.playerData.isDigging() && !this.playerData.isPlacing()) { + if (packet instanceof PacketPlayInFlying) { + if (this.attacks > 0 && this.swings > this.attacks) { + this.alert(AlertType.EXPERIMENTAL, player, "S " + this.swings + ". A " + this.attacks + ".", false); + } + + final KillAuraN auraN = this.playerData.getCheck(KillAuraN.class); + + if (auraN != null) { + auraN.handleCheck(player, new int[]{this.swings, this.attacks}); + } + + this.swings = 0; + this.attacks = 0; + } else if (packet instanceof PacketPlayInArmAnimation) { + ++this.swings; + } else if (packet instanceof PacketPlayInUseEntity && ((PacketPlayInUseEntity) packet).a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + ++this.attacks; + } + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraN.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraN.java new file mode 100644 index 0000000..fbfc966 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraN.java @@ -0,0 +1,50 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.AbstractCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import org.bukkit.entity.Player; + +public class KillAuraN extends AbstractCheck { + + private int doubleSwings; + private int doubleAttacks; + private int bareSwings; + + public KillAuraN(PlayerData playerData) { + super(playerData, int[].class, "Kill-Aura (Check 14)"); + } + + @Override + public void handleCheck(final Player player, final int[] ints) { + final int swings = ints[0]; + final int attacks = ints[1]; + + if (swings > 1 && attacks == 0) { + ++this.doubleSwings; + } else if (swings == 1 && attacks == 0) { + ++this.bareSwings; + } else if (attacks > 1) { + ++this.doubleAttacks; + } + + if (this.doubleSwings + this.doubleAttacks == 20) { + double vl = this.getVl(); + + if (this.doubleSwings == 0) { + if (this.bareSwings > 10 && ++vl > 3.0) { + this.alert(AlertType.EXPERIMENTAL, player, "BS " + this.bareSwings + ", VL " + vl, false); + } + } else { + --vl; + } + + this.setVl(vl); + this.doubleSwings = 0; + this.doubleAttacks = 0; + this.bareSwings = 0; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraO.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraO.java new file mode 100644 index 0000000..b6d8458 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraO.java @@ -0,0 +1,38 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInCloseWindow; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraO extends PacketCheck { + + private boolean sent; + + public KillAuraO(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 15)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInUseEntity && ((PacketPlayInUseEntity)packet).a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + if (this.sent && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } else if (packet instanceof PacketPlayInCloseWindow) { + this.sent = true; + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraP.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraP.java new file mode 100644 index 0000000..f9df31d --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraP.java @@ -0,0 +1,40 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInClientCommand; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraP extends PacketCheck { + + private boolean sent; + + public KillAuraP(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 16)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInClientCommand && ((PacketPlayInClientCommand) packet).a() == PacketPlayInClientCommand.EnumClientCommand.OPEN_INVENTORY_ACHIEVEMENT) { + if (this.sent && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } else if (packet instanceof PacketPlayInUseEntity && ((PacketPlayInUseEntity) packet).a() == + PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + this.sent = true; + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraQ.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraQ.java new file mode 100644 index 0000000..4d00dc3 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraQ.java @@ -0,0 +1,48 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockPlace; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraQ extends PacketCheck { + + private boolean sentAttack; + private boolean sentInteract; + + public KillAuraQ(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 17)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInBlockPlace) { + if (this.sentAttack && !this.sentInteract && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } else if (packet instanceof PacketPlayInUseEntity) { + final PacketPlayInUseEntity.EnumEntityUseAction action = ((PacketPlayInUseEntity) packet).a(); + + if (action == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + this.sentAttack = true; + } else if (action == PacketPlayInUseEntity.EnumEntityUseAction.INTERACT) { + this.sentInteract = true; + } + } else if (packet instanceof PacketPlayInFlying) { + final boolean b = false; + this.sentInteract = b; + this.sentAttack = b; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraR.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraR.java new file mode 100644 index 0000000..24dc46d --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraR.java @@ -0,0 +1,39 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockPlace; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraR extends PacketCheck { + + private boolean sentUseEntity; + + public KillAuraR(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 18)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInBlockPlace) { + if (((PacketPlayInBlockPlace) packet).getFace() != 255 && this.sentUseEntity && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + } else if (packet instanceof PacketPlayInUseEntity) { + this.sentUseEntity = true; + } else if (packet instanceof PacketPlayInFlying) { + this.sentUseEntity = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraS.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraS.java new file mode 100644 index 0000000..bd3ba28 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraS.java @@ -0,0 +1,51 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.*; + +import org.bukkit.entity.Player; + +public class KillAuraS extends PacketCheck { + + private boolean sentArmAnimation; + private boolean sentAttack; + private boolean sentBlockPlace; + private boolean sentUseEntity; + + public KillAuraS(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 19)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInArmAnimation) { + this.sentArmAnimation = true; + } else if (packet instanceof PacketPlayInUseEntity) { + if (((PacketPlayInUseEntity)packet).a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + this.sentAttack = true; + } else { + this.sentUseEntity = true; + } + } else if (packet instanceof PacketPlayInBlockPlace && ((PacketPlayInBlockPlace)packet).getItemStack() != null && ((PacketPlayInBlockPlace)packet).getItemStack().getName().toLowerCase().contains("sword")) { + this.sentBlockPlace = true; + } else if (packet instanceof PacketPlayInFlying) { + if (this.sentArmAnimation && !this.sentAttack && this.sentBlockPlace && this.sentUseEntity && this.alert(AlertType.RELEASE, player, "", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > 2) { + this.ban(player); + } + } + + final boolean b = false; + this.sentUseEntity = b; + this.sentBlockPlace = b; + this.sentAttack = b; + this.sentArmAnimation = b; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraT.java b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraT.java new file mode 100644 index 0000000..12e5a14 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/killaura/KillAuraT.java @@ -0,0 +1,31 @@ +package me.joeleoli.fairfight.check.impl.killaura; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.entity.Player; + +public class KillAuraT extends PacketCheck { + + private boolean sent; + + public KillAuraT(PlayerData playerData) { + super(playerData, "Kill-Aura (Check 20)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInUseEntity) { + if (!this.sent) { + this.sent = true; + } + } else if (packet instanceof PacketPlayInFlying) { + this.sent = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/range/RangeA.java b/src/main/java/me/joeleoli/fairfight/check/impl/range/RangeA.java new file mode 100644 index 0000000..ebf7b04 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/range/RangeA.java @@ -0,0 +1,103 @@ +package me.joeleoli.fairfight.check.impl.range; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.MathUtil; + +import net.minecraft.server.v1_8_R3.Entity; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity; + +import org.bukkit.GameMode; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import me.joeleoli.fairfight.util.CustomLocation; + +public class RangeA extends PacketCheck { + + private boolean sameTick; + + public RangeA(PlayerData playerData) { + super(playerData, "Range"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInUseEntity && !player.getGameMode().equals(GameMode.CREATIVE) && + System.currentTimeMillis() - this.playerData.getLastDelayedMovePacket() > 220L && + this.playerData.getLastMovePacket() != null && + System.currentTimeMillis() - this.playerData.getLastMovePacket().getTimestamp() < 110L && !this.sameTick) { + + PacketPlayInUseEntity useEntity = (PacketPlayInUseEntity) packet; + + if (useEntity.a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + final Entity targetEntity = useEntity.a(((CraftPlayer) player).getHandle().getWorld()); + + if (targetEntity instanceof EntityPlayer) { + final Player target = (Player) targetEntity.getBukkitEntity(); + final CustomLocation targetLocation = this.playerData.getLastPlayerPacket(target.getUniqueId(), MathUtil.pingFormula(this.playerData.getPing())); + + if (targetLocation == null) { + return; + } + + long diff = System.currentTimeMillis() - targetLocation.getTimestamp(); + long estimate = MathUtil.pingFormula(this.playerData.getPing()) * 50L; + long diffEstimate = diff - estimate; + + if (diffEstimate >= 500L) { + return; + } + + CustomLocation playerLocation = this.playerData.getLastMovePacket(); + PlayerData targetData = this.getPlugin().getPlayerDataManager().getPlayerData(target); + + if (targetData == null) { + return; + } + + double range = Math.hypot(playerLocation.getX() - targetLocation.getX(), playerLocation.getZ() - targetLocation.getZ()); + + if (range > 6.5) { + return; + } + + double threshold = 3.3; + + if (!targetData.isSprinting() || + MathUtil.getDistanceBetweenAngles(playerLocation.getYaw(), targetLocation.getYaw()) <= 90.0) { + threshold = 4.0; + } + + double vl = this.getVl(); + + if (range > threshold) { + if (++vl >= 12.5) { + boolean ex = this.getPlugin().getRangeVl() == 0.0; + + if (this.alert(ex ? AlertType.EXPERIMENTAL : AlertType.RELEASE, player, String.format("P %.1f. R %.3f. T %.2f. D %s. VL %.2f.", range - threshold + 3.0, range, threshold, diffEstimate, vl), false)) { + if (!this.playerData.isBanning() && vl >= this.getPlugin().getRangeVl() && !ex) { + this.ban(player); + } + } else { + vl = 0.0; + } + } + } else if (range >= 2.0) { + vl -= 0.25; + } + + this.setVl(vl); + this.sameTick = true; + } + } + } else if (packet instanceof PacketPlayInFlying) { + this.sameTick = false; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/scaffold/ScaffoldA.java b/src/main/java/me/joeleoli/fairfight/check/impl/scaffold/ScaffoldA.java new file mode 100644 index 0000000..003e99a --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/scaffold/ScaffoldA.java @@ -0,0 +1,63 @@ +package me.joeleoli.fairfight.check.impl.scaffold; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.CustomLocation; + +import net.minecraft.server.v1_8_R3.BlockPosition; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockPlace; + +import org.bukkit.entity.Player; + +public class ScaffoldA extends PacketCheck { + + private BlockPosition lastBlock; + private float lastYaw; + private float lastPitch; + private float lastX; + private float lastY; + private float lastZ; + + public ScaffoldA(PlayerData playerData) { + super(playerData, "Placement (Check 1)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInBlockPlace) { + final PacketPlayInBlockPlace blockPlace = (PacketPlayInBlockPlace) packet; + final BlockPosition blockPosition = blockPlace.a(); + final float x = blockPlace.d(); + final float y = blockPlace.e(); + final float z = blockPlace.f(); + + if (this.lastBlock != null && (blockPosition.getX() != this.lastBlock.getX() || blockPosition.getY() != this.lastBlock.getY() || blockPosition.getZ() != this.lastBlock.getZ())) { + final CustomLocation location = this.playerData.getLastMovePacket(); + double vl = this.getVl(); + + if (this.lastX == x && this.lastY == y && this.lastZ == z) { + final float deltaAngle = Math.abs(this.lastYaw - location.getYaw()) + Math.abs(this.lastPitch - location.getPitch()); + + if (deltaAngle > 4.0f && ++vl >= 4.0) { + this.alert(AlertType.EXPERIMENTAL, player, String.format("X %.1f, Y %.1f, Z %.1f, DA %.1f, VL %.1f", x, y, z, deltaAngle, vl), false); + } + } else { + vl -= 0.5; + } + + this.setVl(vl); + + this.lastX = x; + this.lastY = y; + this.lastZ = z; + this.lastYaw = location.getYaw(); + this.lastPitch = location.getPitch(); + } + + this.lastBlock = blockPosition; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/scaffold/ScaffoldB.java b/src/main/java/me/joeleoli/fairfight/check/impl/scaffold/ScaffoldB.java new file mode 100644 index 0000000..bf0466a --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/scaffold/ScaffoldB.java @@ -0,0 +1,51 @@ +package me.joeleoli.fairfight.check.impl.scaffold; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.CustomLocation; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockPlace; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import org.bukkit.entity.Player; + +public class ScaffoldB extends PacketCheck { + + private long lastPlace; + private boolean place; + + public ScaffoldB(PlayerData playerData) { + super(playerData, "Placement (Check 2)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + double vl = this.getVl(); + if (packet instanceof PacketPlayInBlockPlace && System.currentTimeMillis() - this.playerData + .getLastDelayedMovePacket() > 220L && !this.playerData.isAllowTeleport()) { + final CustomLocation lastMovePacket = this.playerData.getLastMovePacket(); + if (lastMovePacket == null) { + return; + } + final long delay = System.currentTimeMillis() - lastMovePacket.getTimestamp(); + if (delay <= 25.0) { + this.lastPlace = System.currentTimeMillis(); + this.place = true; + } else { + vl -= 0.25; + } + } else if (packet instanceof PacketPlayInFlying && this.place) { + final long time = System.currentTimeMillis() - this.lastPlace; + if (time >= 25L) { + if (++vl >= 10.0) { + this.alert(AlertType.EXPERIMENTAL, player, String.format("T %s. VL %.2f.", time, vl), false); + } + } else { + vl -= 0.25; + } + this.place = false; + } + this.setVl(vl); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/scaffold/ScaffoldC.java b/src/main/java/me/joeleoli/fairfight/check/impl/scaffold/ScaffoldC.java new file mode 100644 index 0000000..d59a8d7 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/scaffold/ScaffoldC.java @@ -0,0 +1,75 @@ +package me.joeleoli.fairfight.check.impl.scaffold; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInArmAnimation; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockPlace; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +public class ScaffoldC extends PacketCheck { + + private int looks; + private int stage; + + public ScaffoldC(PlayerData playerData) { + super(playerData, "Placement (Check 3)"); + } + + @Override + public void handleCheck(Player player, Packet packet) { + double vl = this.getVl(); + + if (packet instanceof PacketPlayInFlying.PacketPlayInLook) { + if (this.stage == 0) { + ++this.stage; + } else if (this.stage == 4) { + if ((vl += 1.75) > 3.5) { + this.alert(AlertType.EXPERIMENTAL, player, String.format("VL %.2f.", vl), false); + } + + this.stage = 0; + } else { + final boolean b = false; + this.looks = (b ? 1 : 0); + this.stage = (b ? 1 : 0); + vl -= 0.2; + } + } else if (packet instanceof PacketPlayInBlockPlace) { + if (this.stage == 1) { + ++this.stage; + } else { + final boolean b2 = false; + this.looks = (b2 ? 1 : 0); + this.stage = (b2 ? 1 : 0); + } + } else if (packet instanceof PacketPlayInArmAnimation) { + if (this.stage == 2) { + ++this.stage; + } else { + final boolean b3 = false; + this.looks = (b3 ? 1 : 0); + this.stage = (b3 ? 1 : 0); + vl -= 0.2; + } + } else if (packet instanceof PacketPlayInFlying.PacketPlayInPositionLook || packet instanceof PacketPlayInFlying.PacketPlayInPosition) { + if (this.stage == 3) { + if (++this.looks == 3) { + this.stage = 4; + this.looks = 0; + } + } else { + final boolean b4 = false; + this.looks = (b4 ? 1 : 0); + this.stage = (b4 ? 1 : 0); + } + } + + this.setVl(vl); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/step/StepA.java b/src/main/java/me/joeleoli/fairfight/check/impl/step/StepA.java new file mode 100644 index 0000000..e45b521 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/step/StepA.java @@ -0,0 +1,25 @@ +package me.joeleoli.fairfight.check.impl.step; + +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.update.PositionUpdate; +import org.bukkit.entity.Player; +import me.joeleoli.fairfight.check.checks.PositionCheck; + +public class StepA extends PositionCheck { + + public StepA(PlayerData playerData) { + super(playerData, "Step (Check 1)"); + } + + @Override + public void handleCheck(final Player player, final PositionUpdate update) { + double height = 0.9; + double difference = update.getTo().getY() - update.getFrom().getY(); + + if (difference > height) { + this.alert(AlertType.EXPERIMENTAL, player, "", true); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/timer/TimerA.java b/src/main/java/me/joeleoli/fairfight/check/impl/timer/TimerA.java new file mode 100644 index 0000000..02fcf5f --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/timer/TimerA.java @@ -0,0 +1,53 @@ +package me.joeleoli.fairfight.check.impl.timer; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +import java.util.Deque; +import java.util.LinkedList; + +public class TimerA extends PacketCheck { + + private final Deque delays; + private long lastPacketTime; + + public TimerA(PlayerData playerData) { + super(playerData, "Timer"); + this.delays = new LinkedList<>(); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInFlying && !this.playerData.isAllowTeleport() && System.currentTimeMillis() + - this.playerData.getLastDelayedMovePacket() > 220L) { + this.delays.add(System.currentTimeMillis() - this.lastPacketTime); + if (this.delays.size() == 40) { + double average = 0.0; + for (final long l : this.delays) { + average += l; + } + average /= this.delays.size(); + double vl = this.getVl(); + if (average <= 49.0) { + if ((vl += 1.25) >= 4.0 && this.alert(AlertType.RELEASE, player, String.format("AVG %.3f. R %.2f." + + " VL %.2f.", average, 50.0 / average, vl), false) && !this.playerData.isBanning() && vl + >= 20.0) { + this.ban(player); + } + } else { + vl -= 0.5; + } + this.setVl(vl); + this.delays.clear(); + } + this.lastPacketTime = System.currentTimeMillis(); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/vclip/VClipA.java b/src/main/java/me/joeleoli/fairfight/check/impl/vclip/VClipA.java new file mode 100644 index 0000000..376a850 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/vclip/VClipA.java @@ -0,0 +1,26 @@ +package me.joeleoli.fairfight.check.impl.vclip; + +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.nucleus.BlockUtil; +import me.joeleoli.fairfight.util.update.PositionUpdate; +import me.joeleoli.fairfight.check.checks.PositionCheck; +import me.joeleoli.fairfight.player.PlayerData; + +import org.bukkit.entity.Player; + +public class VClipA extends PositionCheck { + + public VClipA(PlayerData playerData) { + super(playerData, "V-Clip (Check 1)"); + } + + @Override + public void handleCheck(final Player player, final PositionUpdate update) { + double difference = update.getTo().getY() - update.getFrom().getY(); + if (difference >= 2.0 && !BlockUtil.isBlockFaceAir(player)) { + player.teleport(update.getFrom()); + this.alert(AlertType.RELEASE, player, "", true); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/vclip/VClipB.java b/src/main/java/me/joeleoli/fairfight/check/impl/vclip/VClipB.java new file mode 100644 index 0000000..f83fd2d --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/vclip/VClipB.java @@ -0,0 +1,26 @@ +package me.joeleoli.fairfight.check.impl.vclip; + +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.nucleus.BlockUtil; +import me.joeleoli.fairfight.util.update.PositionUpdate; +import org.bukkit.entity.Player; +import me.joeleoli.fairfight.check.checks.PositionCheck; + +public class VClipB extends PositionCheck { + + public VClipB(PlayerData playerData) { + super(playerData, "V-Clip (Check 2)"); + } + + @Override + public void handleCheck(final Player player, final PositionUpdate update) { + + final double difference = update.getTo().getY() - update.getFrom().getY(); + + if (difference >= 2.0 && BlockUtil.isSlab(player)) { + player.teleport(update.getFrom()); + this.alert(AlertType.RELEASE, player, "", true); + } + } +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/velocity/VelocityA.java b/src/main/java/me/joeleoli/fairfight/check/impl/velocity/VelocityA.java new file mode 100644 index 0000000..a710c8a --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/velocity/VelocityA.java @@ -0,0 +1,48 @@ +package me.joeleoli.fairfight.check.impl.velocity; + +import me.joeleoli.fairfight.check.checks.PositionCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.MathUtil; +import me.joeleoli.fairfight.util.update.PositionUpdate; + +import org.bukkit.entity.Player; + +public class VelocityA extends PositionCheck { + + public VelocityA(PlayerData playerData) { + super(playerData, "Velocity (Check 1)"); + } + + @Override + public void handleCheck(final Player player, final PositionUpdate update) { + int vl = (int) this.getVl(); + + if (this.playerData.getVelocityY() > 0.0 && !this.playerData.isUnderBlock() && !this.playerData + .isWasUnderBlock() && !this.playerData.isInLiquid() && !this.playerData.isWasInLiquid() && !this + .playerData.isInWeb() && !this.playerData.isWasInWeb() && System.currentTimeMillis() - this + .playerData.getLastDelayedMovePacket() > 220L && System.currentTimeMillis() - this.playerData + .getLastMovePacket().getTimestamp() < 110L) { + final int threshold = 10 + MathUtil.pingFormula(this.playerData.getPing()) * 2; + + if (++vl >= threshold) { + if (this.alert(AlertType.RELEASE, player, "VL " + vl + ".", true)) { + final int violations = this.playerData.getViolations(this, 60000L); + + if (!this.playerData.isBanning() && violations > Math.max(this.playerData.getPing() / 10L, 15L)) { + this.ban(player); + } + } + + this.playerData.setVelocityY(0.0); + + vl = 0; + } + } else { + vl = 0; + } + + this.setVl(vl); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/velocity/VelocityB.java b/src/main/java/me/joeleoli/fairfight/check/impl/velocity/VelocityB.java new file mode 100644 index 0000000..c26d402 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/velocity/VelocityB.java @@ -0,0 +1,42 @@ +package me.joeleoli.fairfight.check.impl.velocity; + +import me.joeleoli.fairfight.check.checks.PositionCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.update.PositionUpdate; + +import org.bukkit.entity.Player; + +public class VelocityB extends PositionCheck { + + public VelocityB(PlayerData playerData) { + super(playerData, "Velocity (Check 2)"); + } + + @Override + public void handleCheck(final Player player, final PositionUpdate update) { + final double offsetY = update.getTo().getY() - update.getFrom().getY(); + if (this.playerData.getVelocityY() > 0.0 && this.playerData.isWasOnGround() && !this.playerData.isUnderBlock + () && !this.playerData.isWasUnderBlock() && !this.playerData.isInLiquid() && !this.playerData + .isWasInLiquid() && !this.playerData.isInWeb() && !this.playerData.isWasInWeb() && !this.playerData + .isOnStairs() && offsetY > 0.0 && offsetY < 0.41999998688697815 && update.getFrom().getY() % 1.0 == + 0.0) { + final double ratioY = offsetY / this.playerData.getVelocityY(); + int vl = (int) this.getVl(); + + if (ratioY < 0.99) { + final int percent = (int) Math.round(ratioY * 100.0); + + if (++vl >= 5 && this.alert(AlertType.RELEASE, player, "P " + percent + ". VL " + vl + ".", false) && + !this.playerData.isBanning() && vl >= 15) { + this.ban(player); + } + } else { + --vl; + } + + this.setVl(vl); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/velocity/VelocityC.java b/src/main/java/me/joeleoli/fairfight/check/impl/velocity/VelocityC.java new file mode 100644 index 0000000..1687baf --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/velocity/VelocityC.java @@ -0,0 +1,46 @@ +package me.joeleoli.fairfight.check.impl.velocity; + +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.util.update.PositionUpdate; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; +import me.joeleoli.fairfight.check.checks.PositionCheck; + +public class VelocityC extends PositionCheck { + + public VelocityC(PlayerData playerData) { + super(playerData, "Velocity (Check 3)"); + } + + @Override + public void handleCheck(final Player player, final PositionUpdate update) { + double offsetY = update.getTo().getY() - update.getFrom().getY(); + double offsetH = Math.hypot(update.getTo().getX() - update.getFrom().getX(), + update.getTo().getZ() - update.getFrom().getZ()); + + double velocityH = Math.hypot(this.playerData.getVelocityX(), this.playerData.getVelocityZ()); + + EntityPlayer entityPlayer = ((CraftPlayer) update.getPlayer()).getHandle(); + if (this.playerData.getVelocityY() > 0.0 && this.playerData.isWasOnGround() && + !this.playerData.isUnderBlock() && !this.playerData.isWasUnderBlock() && !this.playerData.isInLiquid() && + !this.playerData.isWasInLiquid() && !this.playerData.isInWeb() && !this.playerData.isWasInWeb() && + update.getFrom().getY() % 1.0 == 0.0 && offsetY > 0.0 && offsetY < 0.41999998688697815 && + velocityH > 0.45 && !entityPlayer.world.c(entityPlayer.getBoundingBox().grow(1.0, 0.0, 1.0))) { + double ratio = offsetH / velocityH; + double vl = this.getVl(); + if (ratio < 0.62) { + if ((vl += 1.1) >= 8.0 && this.alert(AlertType.RELEASE, player, + String.format("P %s. VL %.2f.", Math.round(ratio * 100.0), vl), false) && + !this.playerData.isBanning() && vl >= 20.0) { + this.ban(player); + } + } else { + vl -= 0.4; + } + this.setVl(vl); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/wtap/WTapA.java b/src/main/java/me/joeleoli/fairfight/check/impl/wtap/WTapA.java new file mode 100644 index 0000000..75fd3cd --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/wtap/WTapA.java @@ -0,0 +1,82 @@ +package me.joeleoli.fairfight.check.impl.wtap; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayInBlockDig; +import net.minecraft.server.v1_8_R3.PacketPlayInEntityAction; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.entity.Player; + +import java.util.Deque; +import java.util.LinkedList; + +public class WTapA extends PacketCheck { + + private final Deque recentCounts; + private boolean release; + private int flyingCount; + + public WTapA(PlayerData playerData) { + super(playerData, "Tap (Check 1)"); + + this.recentCounts = new LinkedList<>(); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInEntityAction) { + final PacketPlayInEntityAction.EnumPlayerAction playerAction = ((PacketPlayInEntityAction) packet).b(); + + if (playerAction == PacketPlayInEntityAction.EnumPlayerAction.START_SPRINTING) { + if (this.playerData.getLastAttackPacket() + 1000L > System.currentTimeMillis() && this.flyingCount < 10 && !this.release) { + this.recentCounts.add(this.flyingCount); + + if (this.recentCounts.size() == 20) { + double average = 0.0; + + for (final double flyingCount : this.recentCounts) { + average += flyingCount; + } + + average /= this.recentCounts.size(); + + double stdDev = 0.0; + + for (final long l : this.recentCounts) { + stdDev += Math.pow(l - average, 2.0); + } + + stdDev /= this.recentCounts.size(); + stdDev = Math.sqrt(stdDev); + + double vl = this.getVl(); + + if (stdDev == 0.0) { + if ((vl += 1.2) >= 2.4) { + this.alert(AlertType.EXPERIMENTAL, player, String.format("STD %.2f, VL %.2f", stdDev, vl), false); + } + } else { + vl -= 2.0; + } + + this.setVl(vl); + this.recentCounts.clear(); + } + } + } else if (playerAction == PacketPlayInEntityAction.EnumPlayerAction.STOP_SPRINTING) { + this.flyingCount = 0; + } + } else if (packet instanceof PacketPlayInFlying) { + ++this.flyingCount; + + this.release = false; + } else if (packet instanceof PacketPlayInBlockDig && ((PacketPlayInBlockDig) packet).c() == PacketPlayInBlockDig.EnumPlayerDigType.RELEASE_USE_ITEM) { + this.release = true; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/check/impl/wtap/WTapB.java b/src/main/java/me/joeleoli/fairfight/check/impl/wtap/WTapB.java new file mode 100644 index 0000000..b15cb4c --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/check/impl/wtap/WTapB.java @@ -0,0 +1,78 @@ +package me.joeleoli.fairfight.check.impl.wtap; + +import me.joeleoli.fairfight.check.checks.PacketCheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; + +import net.minecraft.server.v1_8_R3.*; + +import org.bukkit.entity.Player; + +import java.util.Deque; +import java.util.LinkedList; + +public class WTapB extends PacketCheck { + + private Deque recentCounts; + private boolean block; + private int flyingCount; + + public WTapB(PlayerData playerData) { + super(playerData, "Tap (Check 2)"); + + this.recentCounts = new LinkedList<>(); + } + + @Override + public void handleCheck(Player player, Packet packet) { + if (packet instanceof PacketPlayInEntityAction) { + final PacketPlayInEntityAction.EnumPlayerAction playerAction = ((PacketPlayInEntityAction) packet).b(); + + if (playerAction == PacketPlayInEntityAction.EnumPlayerAction.STOP_SPRINTING && this.playerData + .getLastAttackPacket() + 1000L > System.currentTimeMillis() && this.flyingCount < 10 && !this + .block) { + this.recentCounts.add(this.flyingCount); + + if (this.recentCounts.size() == 20) { + double average = 0.0; + + for (final double flyingCount : this.recentCounts) { + average += flyingCount; + } + + average /= this.recentCounts.size(); + + double stdDev = 0.0; + + for (final long l : this.recentCounts) { + stdDev += Math.pow(l - average, 2.0); + } + + stdDev /= this.recentCounts.size(); + stdDev = Math.sqrt(stdDev); + + double vl = this.getVl(); + + if (stdDev < 0.3) { + if ((vl += 1.2) >= 2.4) { + this.alert(AlertType.EXPERIMENTAL, player, String.format("STD %.2f, VL %.2f", stdDev, vl), false); + } + } else { + vl -= 2.0; + } + this.setVl(vl); + this.recentCounts.clear(); + } + } + } else if (packet instanceof PacketPlayInUseEntity && ((PacketPlayInUseEntity) packet).a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + this.flyingCount = 0; + } else if (packet instanceof PacketPlayInFlying) { + ++this.flyingCount; + + this.block = false; + } else if (packet instanceof PacketPlayInBlockPlace) { + this.block = true; + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/client/ClientManager.java b/src/main/java/me/joeleoli/fairfight/client/ClientManager.java new file mode 100644 index 0000000..bf80998 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/client/ClientManager.java @@ -0,0 +1,99 @@ +package me.joeleoli.fairfight.client; + +import com.google.common.collect.ImmutableMap; + +import me.joeleoli.fairfight.FairFight; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.event.player.PlayerAlertEvent; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.StringJoiner; + +public class ClientManager { + + public static final Map BLACKLISTED_MODS; + + static { + BLACKLISTED_MODS = ImmutableMap.of("MouseTweaks", "Mouse Tweaks", "Particle Mod", "Particle Mod", "npcmod", "NPC Mod"); + } + + private Set clientTypes; + + public ClientManager() { + this.clientTypes = new HashSet<>(); + this.clientTypes.add(new ModClientType("Ethylene", "ethylene", null)); + this.clientTypes.add(new ModClientType("Ghost Client (Generic)", "gc", null)); + this.clientTypes.add(new ModClientType("Merge Aimbot", "Aimbot", null)); + this.clientTypes.add(new ModClientType("Cracked Vape v2.49", "mergeclient", null)); + this.clientTypes.add(new ModClientType("Cracked Vape v2.50", "wigger", null)); + this.clientTypes.add(new ModClientType("OpenComputers", "OpenComputers", "1.0")); + this.clientTypes.add(new ModClientType("Schematica Reach", "Schematica", "1.7.6.git")); + this.clientTypes.add(new ModClientType("TimeChanger Misplace", "timechanger", "1.0 ")); + this.clientTypes.add(new ModClientType("TcpNoDelay Clients", "TcpNoDelayMod-2.0", "1.0")); + this.clientTypes.add(new PayloadClientType("Cracked Vape v2.06", "LOLIMAHCKER", true)); + this.clientTypes.add(new PayloadClientType("Cracked Merge", "cock", true)); + this.clientTypes.add(new PayloadClientType("BspkrsCore Client 1", "customGuiOpenBspkrs", true)); + this.clientTypes.add(new PayloadClientType("BspkrsCore Client 2", "0SO1Lk2KASxzsd", true)); + this.clientTypes.add(new PayloadClientType("BspkrsCore Client 3", "mincraftpvphcker", true)); + this.clientTypes.add(new PayloadClientType("Cracked Incognito", "lmaohax", true)); + this.clientTypes.add(new PayloadClientType("Old TimeChanger Misplace", "MCnetHandler", true)); + this.clientTypes.add(new PayloadClientType("OCMC", "OCMC", false)); + this.clientTypes.add(new PayloadClientType("CheatBreaker", "CB-Client", false)); + this.clientTypes.add(new PayloadClientType("Cosmic Client", "CC", false)); + this.clientTypes.add(new PayloadClientType("Labymod", "LABYMOD", false)); + } + + public void onModList(PlayerData playerData, Player player, Map mods) { + ClientType type = null; + + typeCheck: + for (Map.Entry entry : mods.entrySet()) { + for (ClientType clientType : this.clientTypes) { + if (clientType instanceof ModClientType) { + final ModClientType modClientType = (ModClientType) clientType; + + if (modClientType.getModId().equalsIgnoreCase(entry.getKey()) && modClientType.getModVersion().equalsIgnoreCase(entry.getValue())) { + type = modClientType; + break typeCheck; + } + } + } + } + + if (type == null) { + type = EnumClientType.FORGE; + + final StringJoiner blacklisted = new StringJoiner(", "); + boolean kick = false; + + for (String modId : ClientManager.BLACKLISTED_MODS.keySet()) { + if (mods.containsKey(modId)) { + blacklisted.add(ClientManager.BLACKLISTED_MODS.get(modId)); + kick = true; + } + } + + if (kick) { + player.kickPlayer(ChatColor.RED + "[FairFight] Blacklisted modification: " + blacklisted.toString()); + } + } + + playerData.setClient(type); + playerData.setForgeMods(mods); + + if (type.isHacked()) { + playerData.setRandomBanRate(500.0); + playerData.setRandomBanReason(type.getName()); + playerData.setRandomBan(true); + + FairFight.getInstance().getServer().getPluginManager().callEvent(new PlayerAlertEvent(AlertType.RELEASE, player, type.getName(), null)); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/client/ClientType.java b/src/main/java/me/joeleoli/fairfight/client/ClientType.java new file mode 100644 index 0000000..5647737 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/client/ClientType.java @@ -0,0 +1,9 @@ +package me.joeleoli.fairfight.client; + +public interface ClientType { + + String getName(); + + boolean isHacked(); + +} diff --git a/src/main/java/me/joeleoli/fairfight/client/EnumClientType.java b/src/main/java/me/joeleoli/fairfight/client/EnumClientType.java new file mode 100644 index 0000000..bd172a6 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/client/EnumClientType.java @@ -0,0 +1,36 @@ +package me.joeleoli.fairfight.client; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum EnumClientType implements ClientType { + + COSMIC_CLIENT(false, "Cosmic-Client"), + CHEAT_BREAKER(false, "Cheat-Breaker"), + VANILLA(false, "Regular-Client"), + FORGE(false, "Forge-Client"), + OCMC(false, "OCMC-Client"), + HACKED_CLIENT_A(true, "Hacked-Client"), + HACKED_CLIENT_B(true, "Hacked-Client"), + HACKED_CLIENT_C(true, "Hacked-Client"), + HACKED_CLIENT_C2(true, "Hacked-Client"), + HACKED_CLIENT_C3(true, "Hacked-Client"), + HACKED_CLIENT_D(true, "Hacked-Client"), + HACKED_CLIENT_E(true, "Hacked-Client"), + HACKED_CLIENT_E2(true, "Hacked-Client"), + HACKED_CLIENT_F(true, "Hacked-Client"), + HACKED_CLIENT_G(true, "Hacked-Client"), + HACKED_CLIENT_H(true, "Hacked-Client"), + HACKED_CLIENT_I(true, "Hacked-Client"), + HACKED_CLIENT_J(true, "Hacked-Client"), + HACKED_CLIENT_K(true, "Hacked-Client"), + HACKED_CLIENT_L(true, "Hacked-Client"), + HACKED_CLIENT_L2(true, "Hacked-Client"), + HACKED_CLIENT_M(true, "Hacked-Client"); + + private boolean hacked; + private String name; + +} diff --git a/src/main/java/me/joeleoli/fairfight/client/ModClientType.java b/src/main/java/me/joeleoli/fairfight/client/ModClientType.java new file mode 100644 index 0000000..e9261ad --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/client/ModClientType.java @@ -0,0 +1,19 @@ +package me.joeleoli.fairfight.client; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class ModClientType implements ClientType { + + private final String name; + private final String modId; + private final String modVersion; + + @Override + public boolean isHacked() { + return true; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/client/PayloadClientType.java b/src/main/java/me/joeleoli/fairfight/client/PayloadClientType.java new file mode 100644 index 0000000..e8e8669 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/client/PayloadClientType.java @@ -0,0 +1,14 @@ +package me.joeleoli.fairfight.client; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class PayloadClientType implements ClientType { + + private final String name; + private final String payload; + private final boolean hacked; + +} diff --git a/src/main/java/me/joeleoli/fairfight/command/FairFightCommand.java b/src/main/java/me/joeleoli/fairfight/command/FairFightCommand.java new file mode 100644 index 0000000..26820c1 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/command/FairFightCommand.java @@ -0,0 +1,63 @@ +package me.joeleoli.fairfight.command; + +import me.joeleoli.fairfight.FairFight; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.util.zoot.util.CC; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class FairFightCommand implements CommandExecutor { + @Override + public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { + if (sender instanceof Player) { + Player player = (Player) sender; + if (args.length == 0) { + player.sendMessage(CC.translate("&6/fairfight check ")); + player.sendMessage(CC.translate("&6/fairfight client ")); + player.sendMessage(CC.translate("&6/fairfight alerts")); + } else if (args[0].equalsIgnoreCase("check") && args.length >= 2) { + boolean contains = FairFight.getInstance().getDisabledChecks().remove(args[1].toUpperCase()); + + if (contains) { + player.sendMessage(CC.GREEN + "The filter `" + args[1] + "` has been removed."); + } else { + FairFight.getInstance().getDisabledChecks().add(args[1].toUpperCase()); + player.sendMessage(CC.GREEN + "The filter `" + args[1] + "` has been added."); + } + } else if (args[0].equalsIgnoreCase("client") && args.length >= 2) { + Player target = Bukkit.getPlayer(args[1]); + + if (target != null) { + final PlayerData playerData = FairFight.getInstance().getPlayerDataManager().getPlayerData(target); + + if (playerData.getClient() != null) { + player.sendMessage(CC.PINK + target.getName() + CC.YELLOW + " is on " + CC.PINK + playerData.getClient().getName()); + } else { + player.sendMessage(CC.PINK + target.getName() + CC.YELLOW + " is on " + CC.PINK + "Unknown"); + } + } else { + player.sendMessage(CC.translate("&cThat player is not online.")); + } + } else if (args[0].equalsIgnoreCase("alerts")) { + boolean receiving = FairFight.getInstance().toggleAlerts(player); + + if (receiving) { + player.sendMessage(CC.GREEN + "You enabled FairFight alerts."); + } else { + player.sendMessage(CC.RED + "You disabled FairFight alerts."); + } + } else { + player.sendMessage(CC.translate("&6/fairfight check ")); + player.sendMessage(CC.translate("&6/fairfight client ")); + player.sendMessage(CC.translate("&6/fairfight alerts")); + } + } else { + sender.sendMessage(CC.translate("&cThis command is for players only!")); + } + + return true; + } +} diff --git a/src/main/java/me/joeleoli/fairfight/event/BaseEvent.java b/src/main/java/me/joeleoli/fairfight/event/BaseEvent.java new file mode 100644 index 0000000..fb40bbf --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/event/BaseEvent.java @@ -0,0 +1,26 @@ +package me.joeleoli.fairfight.event; + +import org.bukkit.Bukkit; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class BaseEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public boolean call() { + Bukkit.getServer().getPluginManager().callEvent(this); + return this instanceof Cancellable && ((Cancellable) this).isCancelled(); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/event/BungeeReceivedEvent.java b/src/main/java/me/joeleoli/fairfight/event/BungeeReceivedEvent.java new file mode 100644 index 0000000..448f6ad --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/event/BungeeReceivedEvent.java @@ -0,0 +1,22 @@ +package me.joeleoli.fairfight.event; +import lombok.Getter; +import org.bukkit.entity.Player; + +@Getter +public class BungeeReceivedEvent extends PlayerEvent { + + private final String channel; + private final String message; + + private final byte[] messageBytes; + private final boolean isValid; + + public BungeeReceivedEvent(Player player, String channel, String message, byte[] messageBytes, boolean isValid) { + super(player); + this.channel = channel; + this.message = message; + this.messageBytes = messageBytes; + this.isValid = isValid; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/event/ModListRetrieveEvent.java b/src/main/java/me/joeleoli/fairfight/event/ModListRetrieveEvent.java new file mode 100644 index 0000000..290475a --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/event/ModListRetrieveEvent.java @@ -0,0 +1,18 @@ +package me.joeleoli.fairfight.event; + +import java.util.Map; +import lombok.Getter; +import org.bukkit.entity.Player; + +@Getter +public class ModListRetrieveEvent extends PlayerEvent { + + private final Map mods; + + public ModListRetrieveEvent(Player player, Map mods) { + super(player); + + this.mods = mods; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/event/PlayerEvent.java b/src/main/java/me/joeleoli/fairfight/event/PlayerEvent.java new file mode 100644 index 0000000..3548917 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/event/PlayerEvent.java @@ -0,0 +1,22 @@ +package me.joeleoli.fairfight.event; + +import java.util.UUID; +import lombok.Getter; +import org.bukkit.entity.Player; + +@Getter +public class PlayerEvent extends BaseEvent { + private Player player; + + public PlayerEvent(Player player) { + this.player = player; + } + + public Player getPlayer() { + return player; + } + + public UUID getUniqueId() { + return player.getUniqueId(); + } +} diff --git a/src/main/java/me/joeleoli/fairfight/event/player/AlertType.java b/src/main/java/me/joeleoli/fairfight/event/player/AlertType.java new file mode 100644 index 0000000..fe973d6 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/event/player/AlertType.java @@ -0,0 +1,9 @@ +package me.joeleoli.fairfight.event.player; + +public enum AlertType { + + RELEASE, + EXPERIMENTAL, + DEVELOPMENT + +} diff --git a/src/main/java/me/joeleoli/fairfight/event/player/PlayerAlertEvent.java b/src/main/java/me/joeleoli/fairfight/event/player/PlayerAlertEvent.java new file mode 100644 index 0000000..d16e3f7 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/event/player/PlayerAlertEvent.java @@ -0,0 +1,42 @@ +package me.joeleoli.fairfight.event.player; + +import lombok.Getter; +import lombok.Setter; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +@Getter +public class PlayerAlertEvent extends Event implements Cancellable { + + private static final HandlerList HANDLER_LIST; + + static { + HANDLER_LIST = new HandlerList(); + } + + private final AlertType alertType; + private final Player player; + private final String checkName; + private final String extra; + @Setter + private boolean cancelled; + + public PlayerAlertEvent(AlertType alertType, Player player, String checkName, String extra) { + this.alertType = alertType; + this.player = player; + this.checkName = checkName; + this.extra = extra; + } + + public HandlerList getHandlers() { + return PlayerAlertEvent.HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return PlayerAlertEvent.HANDLER_LIST; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/event/player/PlayerBanEvent.java b/src/main/java/me/joeleoli/fairfight/event/player/PlayerBanEvent.java new file mode 100644 index 0000000..6232a93 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/event/player/PlayerBanEvent.java @@ -0,0 +1,35 @@ +package me.joeleoli.fairfight.event.player; + +import lombok.Getter; +import lombok.Setter; +import org.bukkit.event.*; +import org.bukkit.entity.*; + +@Getter +public class PlayerBanEvent extends Event implements Cancellable { + + private static final HandlerList HANDLER_LIST; + + static { + HANDLER_LIST = new HandlerList(); + } + + private Player player; + private String reason; + @Setter + private boolean cancelled; + + public PlayerBanEvent(final Player player, final String reason) { + this.player = player; + this.reason = reason; + } + + public static HandlerList getHandlerList() { + return PlayerBanEvent.HANDLER_LIST; + } + + public HandlerList getHandlers() { + return PlayerBanEvent.HANDLER_LIST; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/handler/CustomMovementHandler.java b/src/main/java/me/joeleoli/fairfight/handler/CustomMovementHandler.java new file mode 100644 index 0000000..98328be --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/handler/CustomMovementHandler.java @@ -0,0 +1,149 @@ +package me.joeleoli.fairfight.handler; + +import lombok.AllArgsConstructor; + +import me.joeleoli.fairfight.check.ICheck; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.util.nucleus.BlockUtil; +import me.joeleoli.fairfight.util.update.PositionUpdate; +import me.joeleoli.fairfight.util.update.RotationUpdate; +import me.joeleoli.ragespigot.handler.MovementHandler; +import me.joeleoli.fairfight.FairFight; + +import net.minecraft.server.v1_8_R3.BlockPosition; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.Location; +import org.bukkit.entity.Player; + +@AllArgsConstructor +public class CustomMovementHandler implements MovementHandler { + + private final FairFight plugin; + + public void handleUpdateLocation(Player player, Location to, Location from, PacketPlayInFlying packet) { + if (player.getAllowFlight()) { + return; + } + + if (player.isInsideVehicle()) { + return; + } + + if (to.getY() < 2.0) { + return; + } + + if (!player.getWorld().isChunkLoaded(to.getBlockX() >> 4, to.getBlockZ() >> 4)) { + return; + } + + final PlayerData playerData = this.plugin.getPlayerDataManager().getPlayerData(player); + + if (playerData == null) { + return; + } + + playerData.setWasOnGround(playerData.isOnGround()); + playerData.setWasInLiquid(playerData.isInLiquid()); + playerData.setWasUnderBlock(playerData.isUnderBlock()); + playerData.setWasInWeb(playerData.isInWeb()); + playerData.setOnGround(BlockUtil.isOnGround(to, 0) || BlockUtil.isOnGround(to, 1)); + + if (!playerData.isOnGround()) { + positions: + for (BlockPosition position : playerData.getFakeBlocks()) { + int x = position.getX(); + int z = position.getZ(); + + int blockX = to.getBlock().getX(); + int blockZ = to.getBlock().getZ(); + + for (int xOffset = -1; xOffset <= 1; xOffset++) { + for (int zOffset = -1; zOffset <= 1; zOffset++) { + if (x == blockX + xOffset && z == blockZ + zOffset) { + int y = position.getY(); + int pY = to.getBlock().getY(); + + if (pY - y <= 1 && pY > y) { + playerData.setOnGround(true); + } + + if (playerData.isOnGround()) { + break positions; + } + } + } + } + } + } + + if (playerData.isOnGround()) { + playerData.setLastGroundY(to.getY()); + } + + playerData.setInLiquid(BlockUtil.isOnLiquid(to, 0) || BlockUtil.isOnLiquid(to, 1) || BlockUtil.isOnLiquid(to, -1)); + playerData.setInWeb(BlockUtil.isOnWeb(to, 0)); + playerData.setOnIce(BlockUtil.isOnIce(to, 1) || BlockUtil.isOnIce(to, 2)); + + if (playerData.isOnIce()) { + playerData.setMovementsSinceIce(0); + } else { + playerData.setMovementsSinceIce(playerData.getMovementsSinceIce() + 1); + } + + playerData.setOnStairs(BlockUtil.isOnStairs(to, 0) || BlockUtil.isOnStairs(to, 1)); + playerData.setOnCarpet(BlockUtil.isOnCarpet(to, 0) || BlockUtil.isOnCarpet(to, 1)); + playerData.setUnderBlock(BlockUtil.isOnGround(to, -2)); + + if (playerData.isUnderBlock()) { + playerData.setMovementsSinceUnderBlock(0); + } else { + playerData.setMovementsSinceUnderBlock(playerData.getMovementsSinceUnderBlock() + 1); + } + + if (to.getY() != from.getY() && playerData.getVelocityV() > 0) { + playerData.setVelocityV(playerData.getVelocityV() - 1); + } + + if (Math.hypot(to.getX() - from.getX(), to.getZ() - from.getZ()) > 0.0 && playerData.getVelocityH() > 0) { + playerData.setVelocityH(playerData.getVelocityH() - 1); + } + + for (final Class checkClass : PlayerData.CHECKS) { + if (!FairFight.getInstance().getDisabledChecks().contains(checkClass.getSimpleName().toUpperCase())) { + final ICheck check = playerData.getCheck(checkClass); + if (check != null && check.getType() == PositionUpdate.class) { + check.handleCheck(player, new PositionUpdate(player, to, from, packet)); + } + } + } + + if (playerData.getVelocityY() > 0.0 && to.getY() > from.getY()) { + playerData.setVelocityY(0.0); + } + } + + public void handleUpdateRotation(final Player player, final Location to, final Location from, final PacketPlayInFlying packet) { + if (player.getAllowFlight()) { + return; + } + + final PlayerData playerData = this.plugin.getPlayerDataManager().getPlayerData(player); + + if (playerData == null) { + return; + } + + for (final Class checkClass : PlayerData.CHECKS) { + if (!FairFight.getInstance().getDisabledChecks().contains(checkClass.getSimpleName().toUpperCase())) { + final ICheck check = playerData.getCheck(checkClass); + + if (check != null && check.getType() == RotationUpdate.class) { + check.handleCheck(player, new RotationUpdate(player, to, from, packet)); + } + } + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/handler/CustomPacketHandler.java b/src/main/java/me/joeleoli/fairfight/handler/CustomPacketHandler.java new file mode 100644 index 0000000..c66eed7 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/handler/CustomPacketHandler.java @@ -0,0 +1,619 @@ +package me.joeleoli.fairfight.handler; + +import lombok.AllArgsConstructor; + +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.ragespigot.handler.PacketHandler; +import me.joeleoli.fairfight.FairFight; +import me.joeleoli.fairfight.check.ICheck; +import me.joeleoli.fairfight.client.EnumClientType; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.player.PlayerAlertEvent; +import me.joeleoli.fairfight.event.player.PlayerBanEvent; +import me.joeleoli.fairfight.util.CustomLocation; + +import net.minecraft.server.v1_8_R3.*; + +import org.apache.commons.io.Charsets; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@AllArgsConstructor +public class CustomPacketHandler implements PacketHandler { + + private static Field positionField; + + private static final List INSTANT_BREAK_BLOCKS = Arrays.asList( + "reeds", "waterlily", "deadbush", "flower", "doubleplant", "tallgrass" + ); + + static { + try { + positionField = PacketPlayOutBlockChange.class.getDeclaredField("a"); + positionField.setAccessible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private final FairFight plugin; + + public void handleReceivedPacket(PlayerConnection playerConnection, Packet packet) { + try { + final Player player = playerConnection.getPlayer(); + final PlayerData playerData = this.plugin.getPlayerDataManager().getPlayerData(player); + + if (playerData == null) { + return; + } + + if (playerData.isSniffing()) { + this.handleSniffedPacket(packet, playerData); + } + + final String simpleName = packet.getClass().getSimpleName(); + + switch (simpleName) { + case "PacketPlayInCustomPayload": { + if (!playerData.getClient().isHacked()) { + this.handleCustomPayload((PacketPlayInCustomPayload) packet, playerData, player); + break; + } + break; + } + case "PacketPlayInPosition": + case "PacketPlayInPositionLook": + case "PacketPlayInLook": + case "PacketPlayInFlying": { + this.handleFlyPacket((PacketPlayInFlying)packet, playerData); + break; + } + case "PacketPlayInKeepAlive": { + this.handleKeepAlive((PacketPlayInKeepAlive)packet, playerData, player); + break; + } + case "PacketPlayInUseEntity": { + this.handleUseEntity((PacketPlayInUseEntity)packet, playerData, player); + break; + } + case "PacketPlayInBlockPlace": { + playerData.setPlacing(true); + break; + } + case "PacketPlayInCloseWindow": { + playerData.setInventoryOpen(false); + break; + } + case "PacketPlayInClientCommand": { + if (((PacketPlayInClientCommand)packet).a() == PacketPlayInClientCommand.EnumClientCommand.OPEN_INVENTORY_ACHIEVEMENT) { + playerData.setInventoryOpen(true); + break; + } + break; + } + case "PacketPlayInEntityAction": { + final PacketPlayInEntityAction.EnumPlayerAction actionType = ((PacketPlayInEntityAction)packet).b(); + if (actionType == PacketPlayInEntityAction.EnumPlayerAction.START_SPRINTING) { + playerData.setSprinting(true); + break; + } + if (actionType == PacketPlayInEntityAction.EnumPlayerAction.STOP_SPRINTING) { + playerData.setSprinting(false); + break; + } + break; + } + case "PacketPlayInBlockDig": { + final PacketPlayInBlockDig.EnumPlayerDigType digType = ((PacketPlayInBlockDig)packet).c(); + + if (playerData.getFakeBlocks().contains(((PacketPlayInBlockDig) packet).a())) { + playerData.setInstantBreakDigging(false); + playerData.setFakeDigging(true); + playerData.setDigging(false); + } else { + playerData.setFakeDigging(false); + + if (digType == PacketPlayInBlockDig.EnumPlayerDigType.START_DESTROY_BLOCK) { + Block block = ((CraftWorld) player.getWorld()).getHandle().c(((PacketPlayInBlockDig) packet).a()); + + String tile = block.a().replace("tile.", ""); + + if (INSTANT_BREAK_BLOCKS.contains(tile)) { + playerData.setInstantBreakDigging(true); + } else { + playerData.setInstantBreakDigging(false); + } + + playerData.setDigging(true); + } else if (digType == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK || + digType == PacketPlayInBlockDig.EnumPlayerDigType.STOP_DESTROY_BLOCK) { + playerData.setInstantBreakDigging(false); + playerData.setDigging(false); + } + } + break; + } + case "PacketPlayInArmAnimation": { + playerData.setLastAnimationPacket(System.currentTimeMillis()); + break; + } + } + + for (final Class checkClass : PlayerData.CHECKS) { + if (!FairFight.getInstance().getDisabledChecks().contains(checkClass.getSimpleName().toUpperCase())) { + final ICheck check = (playerData.getCheck(checkClass)); + + if (check != null && check.getType() == Packet.class) { + check.handleCheck(playerConnection.getPlayer(), packet); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void handleSentPacket(final PlayerConnection playerConnection, final Packet packet) { + try { + final Player player = playerConnection.getPlayer(); + final PlayerData playerData = this.plugin.getPlayerDataManager().getPlayerData(player); + + if (playerData == null) { + return; + } + + final String simpleName = packet.getClass().getSimpleName(); + + switch (simpleName) { + case "PacketPlayOutEntityVelocity": { + this.handleVelocityOut((PacketPlayOutEntityVelocity)packet, playerData, player); + break; + } + case "PacketPlayOutExplosion": { + this.handleExplosionPacket((PacketPlayOutExplosion)packet, playerData); + break; + } + case "PacketPlayOutEntityLook": + case "PacketPlayOutRelEntityMove": + case "PacketPlayOutRelEntityMoveLook": + case "PacketPlayOutEntity": { + this.handleEntityPacket((PacketPlayOutEntity)packet, playerData, player); + break; + } + case "PacketPlayOutEntityTeleport": { + this.handleTeleportPacket((PacketPlayOutEntityTeleport)packet, playerData, player); + break; + } + case "PacketPlayOutPosition": { + this.handlePositionPacket((PacketPlayOutPosition)packet, playerData); + break; + } + case "PacketPlayOutKeepAlive": { + playerData.addKeepAliveTime(((PacketPlayOutKeepAlive)packet).getA()); + break; + } + case "PacketPlayOutCloseWindow": { + if (!playerData.keepAliveExists(-1)) { + ((CraftPlayer)player).getHandle().playerConnection.sendPacket(new PacketPlayOutKeepAlive(-1)); + break; + } + + break; + } + case "PacketPlayOutMultiBlockChange": + for (PacketPlayOutMultiBlockChange.MultiBlockChangeInfo info : ((PacketPlayOutMultiBlockChange) packet).getB()) { + BlockPosition position = info.a(); + + String name = info.c().getBlock().toString().replace("Block{minecraft:", "").replace("}", ""); + + StackTraceElement[] elements = Thread.currentThread().getStackTrace(); + + if (elements.length == 19 && elements[3].getMethodName().equals("sendTo")) { + if (name.equals("air")) { + playerData.getFakeBlocks().remove(position); + } else { + playerData.getFakeBlocks().add(position); + } + } + } + break; + case "PacketPlayOutBlockChange": + BlockPosition position = (BlockPosition) positionField.get(packet); + + String name = ((PacketPlayOutBlockChange) packet).block.getBlock().toString() + .replace("Block{minecraft:", "").replace("}", ""); + + StackTraceElement[] elements = Thread.currentThread().getStackTrace(); + + if (elements.length == 13 && elements[3].getMethodName().equals("sendBlockChange")) { + if (name.equals("air")) { + playerData.getFakeBlocks().remove(position); + } else { + playerData.getFakeBlocks().add(position); + } + } + break; + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private void handleSniffedPacket(Packet packet, PlayerData playerData) { + try { + final StringBuilder builder = new StringBuilder(); + + builder.append(packet.getClass().getSimpleName()); + builder.append(" (timestamp = "); + builder.append(System.currentTimeMillis()); + + final List fieldsList = new ArrayList<>(); + + fieldsList.addAll(Arrays.asList(packet.getClass().getDeclaredFields())); + fieldsList.addAll(Arrays.asList(packet.getClass().getSuperclass().getDeclaredFields())); + + for (final Field field : fieldsList) { + if (field.getName().equalsIgnoreCase("timestamp")) { + continue; + } + + field.setAccessible(true); + builder.append(", "); + builder.append(field.getName()); + builder.append(" = "); + builder.append(field.get(packet)); + } + + builder.append(")"); + + playerData.getSniffedPacketBuilder().append(builder.toString()); + playerData.getSniffedPacketBuilder().append("\n"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void handleCustomPayload(PacketPlayInCustomPayload packet, PlayerData playerData, Player player) { + final String a = packet.a(); + int n = -1; + switch (a.hashCode()) { + case -1772699639: { + if (a.equals("LOLIMAHCKER")) { + n = 0; + break; + } + break; + } + case 3059156: { + if (a.equals("cock")) { + n = 1; + break; + } + break; + } + case 509975521: { + if (a.equals("customGuiOpenBspkrs")) { + n = 2; + break; + } + break; + } + case 1228162850: { + if (a.equals("0SO1Lk2KASxzsd")) { + n = 3; + break; + } + break; + } + case 633656225: { + if (a.equals("mincraftpvphcker")) { + n = 4; + break; + } + break; + } + case 279718608: { + if (a.equals("lmaohax")) { + n = 5; + break; + } + break; + } + case 1566847235: { + if (a.equals("MCnetHandler")) { + n = 6; + break; + } + break; + } + case 24251720: { + if (a.equals("L0LIMAHCKER")) { + n = 7; + break; + } + break; + } + case 2420330: { + if (a.equals("OCMC")) { + n = 8; + break; + } + break; + } + case 92413603: { + if (a.equals("REGISTER")) { + n = 9; + break; + } + break; + } + } + + EnumClientType type; + + clientCheck: { + switch (n) { + case 0: { + type = EnumClientType.HACKED_CLIENT_A; + break clientCheck; + } + case 1: { + type = EnumClientType.HACKED_CLIENT_B; + break clientCheck; + } + case 2: { + type = EnumClientType.HACKED_CLIENT_C; + break clientCheck; + } + case 3: { + type = EnumClientType.HACKED_CLIENT_C2; + break clientCheck; + } + case 4: { + type = EnumClientType.HACKED_CLIENT_C3; + break clientCheck; + } + case 5: { + type = EnumClientType.HACKED_CLIENT_D; + break clientCheck; + } + case 6: { + type = EnumClientType.HACKED_CLIENT_E; + break clientCheck; + } + case 7: { + type = EnumClientType.HACKED_CLIENT_M; + break clientCheck; + } + case 8: { + type = EnumClientType.OCMC; + break clientCheck; + } + case 9: { + try { + final String registerType = packet.b().toString(Charsets.UTF_8); + + if (registerType.contains("CB-Client")) { + type = EnumClientType.CHEAT_BREAKER; + } else { + if (!registerType.equalsIgnoreCase("CC")) { + return; + } + + type = EnumClientType.COSMIC_CLIENT; + } + + break clientCheck; + } + catch (Exception e) { + e.printStackTrace(); + return; + } + } + } + + return; + } + + playerData.setClient(type); + + if (type.isHacked()) { + this.plugin.getServer().getPluginManager().callEvent(new PlayerAlertEvent(AlertType.RELEASE, player, type.getName(), null)); + + playerData.setRandomBanRate(500.0); + playerData.setRandomBanReason(type.getName()); + playerData.setRandomBan(true); + } + } + + private void handleFlyPacket(PacketPlayInFlying packet, PlayerData playerData) { + CustomLocation customLocation = new CustomLocation(packet.a(), packet.b(), packet.c(), packet.d(), packet.e()); + CustomLocation lastLocation = playerData.getLastMovePacket(); + + if (lastLocation != null) { + if (!packet.g()) { + customLocation.setX(lastLocation.getX()); + customLocation.setY(lastLocation.getY()); + customLocation.setZ(lastLocation.getZ()); + } + + if (!packet.h()) { + customLocation.setYaw(lastLocation.getYaw()); + customLocation.setPitch(lastLocation.getPitch()); + } + + if (System.currentTimeMillis() - lastLocation.getTimestamp() > 110L) { + playerData.setLastDelayedMovePacket(System.currentTimeMillis()); + } + } + + if (playerData.isSetInventoryOpen()) { + playerData.setInventoryOpen(false); + playerData.setSetInventoryOpen(false); + } + + playerData.setLastMovePacket(customLocation); + playerData.setPlacing(false); + playerData.setAllowTeleport(false); + + if (packet instanceof PacketPlayInFlying.PacketPlayInPositionLook && playerData.allowTeleport(customLocation)) { + playerData.setAllowTeleport(true); + } + } + + private void handleKeepAlive(final PacketPlayInKeepAlive packet, final PlayerData playerData, final Player player) { + final int id = packet.a(); + + if (playerData.keepAliveExists(id)) { + if (id == -1) { + playerData.setSetInventoryOpen(true); + } else { + playerData.setPing(System.currentTimeMillis() - playerData.getKeepAliveTime(id)); + } + + playerData.removeKeepAliveTime(id); + } else if (id != 0) { + this.plugin.getServer().getPluginManager().callEvent(new PlayerAlertEvent(AlertType.RELEASE, player, "Illegal Packets", null)); + } + } + + private void handleUseEntity(final PacketPlayInUseEntity packet, final PlayerData playerData, final Player player) { + if (packet.a() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { + playerData.setLastAttackPacket(System.currentTimeMillis()); + + if (playerData.isSendingVape()) { + playerData.setSendingVape(false); + } + + if (!playerData.isAttackedSinceVelocity()) { + playerData.setVelocityX(playerData.getVelocityX() * 0.6); + playerData.setVelocityZ(playerData.getVelocityZ() * 0.6); + playerData.setAttackedSinceVelocity(true); + } + + if (!playerData.isBanning() && playerData.isRandomBan() && Math.random() * playerData.getRandomBanRate() < 1.0) { + playerData.setBanning(true); + + this.plugin.getServer().getPluginManager().callEvent(new PlayerBanEvent(player, playerData.getRandomBanReason())); + } + + final Entity targetEntity = packet.a(((CraftPlayer)player).getHandle().getWorld()); + + if (targetEntity instanceof EntityPlayer) { + final Player target = (Player) targetEntity.getBukkitEntity(); + playerData.setLastTarget(target.getUniqueId()); + } + } + } + + private void handleVelocityOut(final PacketPlayOutEntityVelocity packet, final PlayerData playerData, final Player player) { + if (packet.getA() == player.getEntityId()) { + final double x = Math.abs(packet.getB() / 8000.0); + final double y = packet.getC() / 8000.0; + final double z = Math.abs(packet.getD() / 8000.0); + if (x > 0.0 || z > 0.0) { + playerData.setVelocityH((int)(((x + z) / 2.0 + 2.0) * 15.0)); + } + if (y > 0.0) { + playerData.setVelocityV((int)(Math.pow(y + 2.0, 2.0) * 5.0)); + if (playerData.isOnGround() && player.getLocation().getY() % 1.0 == 0.0) { + playerData.setVelocityX(x); + playerData.setVelocityY(y); + playerData.setVelocityZ(z); + playerData.setLastVelocity(System.currentTimeMillis()); + playerData.setAttackedSinceVelocity(false); + } + } + } + } + + private void handleExplosionPacket(PacketPlayOutExplosion packet, PlayerData playerData) { + final float x = Math.abs(packet.getF()); + final float y = packet.getG(); + final float z = Math.abs(packet.getH()); + + if (x > 0.0f || z > 0.0f) { + playerData.setVelocityH((int)(((x + z) / 2.0f + 2.0f) * 15.0f)); + } + if (y > 0.0f) { + playerData.setVelocityV((int)(Math.pow(y + 2.0f, 2.0) * 5.0)); + } + } + + private void handleEntityPacket(PacketPlayOutEntity packet, PlayerData playerData, Player player) { + final Entity targetEntity = ((CraftPlayer)player).getHandle().getWorld().a(packet.getA()); + + if (targetEntity instanceof EntityPlayer) { + final Player target = (Player) targetEntity.getBukkitEntity(); + final CustomLocation customLocation = playerData.getLastPlayerPacket(target.getUniqueId(), 1); + + if (customLocation != null) { + final double x = packet.getB() / 32.0; + final double y = packet.getC() / 32.0; + final double z = packet.getD() / 32.0; + float yaw = packet.getE() * 360.0f / 256.0f; + float pitch = packet.getF() * 360.0f / 256.0f; + + if (!packet.isH()) { + yaw = customLocation.getYaw(); + pitch = customLocation.getPitch(); + } + + playerData.addPlayerPacket(target.getUniqueId(), new CustomLocation(customLocation.getX() + x, customLocation.getY() + y, customLocation.getZ() + z, yaw, pitch)); + } + } + } + + private void handleTeleportPacket(final PacketPlayOutEntityTeleport packet, final PlayerData playerData, final Player player) { + final Entity targetEntity = ((CraftPlayer)player).getHandle().getWorld().a(packet.getA()); + + if (targetEntity instanceof EntityPlayer) { + final Player target = (Player)targetEntity.getBukkitEntity(); + double x = packet.getB() / 32.0; + double z = packet.getD() / 32.0; + final double y = packet.getC() / 32.0; + final float yaw = packet.getE() * 360.0f / 256.0f; + final float pitch = packet.getF() * 360.0f / 256.0f; + + playerData.addPlayerPacket(target.getUniqueId(), new CustomLocation(x, y, z, yaw, pitch)); + } + } + + private void handlePositionPacket(final PacketPlayOutPosition packet, final PlayerData playerData) { + if (packet.getE() > 90.0f) { + packet.setE(90.0f); + } else if (packet.getE() < -90.0f) { + packet.setE(-90.0f); + } else if (packet.getE() == 0.0f) { + packet.setE(0.492832f); + } + + playerData.setVelocityY(0.0); + playerData.setVelocityX(0.0); + playerData.setVelocityZ(0.0); + playerData.setAttackedSinceVelocity(false); + playerData.addTeleportLocation(new CustomLocation(packet.getA(), packet.getB(), packet.getC(), packet.getD(), packet.getE())); + } + + private float getAngle(final double posX, final double posZ, final CustomLocation location) { + final double x = posX - location.getX(); + final double z = posZ - location.getZ(); + float newYaw = (float)Math.toDegrees(-Math.atan(x / z)); + + if (z < 0.0 && x < 0.0) { + newYaw = (float)(90.0 + Math.toDegrees(Math.atan(z / x))); + } else if (z < 0.0 && x > 0.0) { + newYaw = (float)(-90.0 + Math.toDegrees(Math.atan(z / x))); + } + + return newYaw; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/listener/BungeeListener.java b/src/main/java/me/joeleoli/fairfight/listener/BungeeListener.java new file mode 100644 index 0000000..c7b84bf --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/listener/BungeeListener.java @@ -0,0 +1,60 @@ +package me.joeleoli.fairfight.listener; + +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteStreams; + +import java.util.Map; + +import lombok.RequiredArgsConstructor; + +import me.joeleoli.fairfight.FairFight; +import me.joeleoli.fairfight.event.BungeeReceivedEvent; +import me.joeleoli.fairfight.event.ModListRetrieveEvent; + +import org.bukkit.entity.Player; +import org.bukkit.plugin.messaging.PluginMessageListener; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +@RequiredArgsConstructor +public class BungeeListener implements PluginMessageListener { + + private final FairFight plugin; + + @Override + public void onPluginMessageReceived(String channel, Player player, byte[] message) { + if (!channel.equals("BungeeCord")) { + return; + } + + final ByteArrayDataInput in = ByteStreams.newDataInput(message); + final String subChannel = in.readUTF(); + + if (subChannel.equals("ForgeMods")) { + try { + Map mods = (Map) new JSONParser().parse(in.readUTF()); + ModListRetrieveEvent event = new ModListRetrieveEvent(player, mods); + + this.plugin.getServer().getPluginManager().callEvent(event); + } catch (ParseException e) { + e.printStackTrace(); + } + + return; + } + + final short len = in.readShort(); + final byte[] messageBytes = new byte[len]; + + in.readFully(messageBytes); + + ByteArrayDataInput dis = ByteStreams.newDataInput(messageBytes); + String data = dis.readUTF(); + Long systemTime = Long.parseLong(data.split(":")[0]); + + final BungeeReceivedEvent event = new BungeeReceivedEvent(player, subChannel, data.replace(systemTime + ":", ""), message, systemTime > System.currentTimeMillis()); + + this.plugin.getServer().getPluginManager().callEvent(event); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/listener/ModListListener.java b/src/main/java/me/joeleoli/fairfight/listener/ModListListener.java new file mode 100644 index 0000000..52d59dd --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/listener/ModListListener.java @@ -0,0 +1,34 @@ +package me.joeleoli.fairfight.listener; + +import me.joeleoli.fairfight.FairFight; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.event.ModListRetrieveEvent; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +import java.util.Map; + +public class ModListListener implements Listener { + + @EventHandler + public void onModListRetrieve(ModListRetrieveEvent event) { + final Player player = event.getPlayer(); + + if (player == null) { + return; + } + + final PlayerData playerData = FairFight.getInstance().getPlayerDataManager().getPlayerData(player); + + if (playerData == null) { + return; + } + + final Map mods = event.getMods(); + + FairFight.getInstance().getClientManager().onModList(playerData, player, mods); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/listener/PlayerListener.java b/src/main/java/me/joeleoli/fairfight/listener/PlayerListener.java new file mode 100644 index 0000000..1055bb0 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/listener/PlayerListener.java @@ -0,0 +1,151 @@ +package me.joeleoli.fairfight.listener; + +import io.netty.buffer.Unpooled; +import java.text.MessageFormat; +import java.util.List; + +import me.joeleoli.fairfight.FairFight; +import me.joeleoli.fairfight.event.player.AlertType; +import me.joeleoli.fairfight.event.player.PlayerAlertEvent; +import me.joeleoli.fairfight.event.player.PlayerBanEvent; +import me.joeleoli.fairfight.mongo.FairFightLog; +import me.joeleoli.fairfight.player.PlayerData; +import me.joeleoli.fairfight.util.nucleus.util.TaskUtil; +import me.joeleoli.fairfight.util.zoot.util.CC; +import net.minecraft.server.v1_8_R3.MinecraftServer; +import net.minecraft.server.v1_8_R3.PacketDataSerializer; +import net.minecraft.server.v1_8_R3.PacketPlayOutCustomPayload; +import net.minecraft.server.v1_8_R3.PlayerConnection; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerChangedWorldEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerTeleportEvent; + +public class PlayerListener implements Listener { + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + FairFight.getInstance().getPlayerDataManager().addPlayerData(event.getPlayer()); + + if (event.getPlayer().hasPermission("fairfight.alerts")) { + FairFight.getInstance().getReceivingAlerts().add(event.getPlayer().getUniqueId()); + } + + FairFight.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(FairFight.getInstance(), () -> { + final PlayerConnection playerConnection = ((CraftPlayer) event.getPlayer()).getHandle().playerConnection; + final PacketPlayOutCustomPayload packetPlayOutCustomPayload = new PacketPlayOutCustomPayload("REGISTER", + new PacketDataSerializer(Unpooled.wrappedBuffer("CB-Client".getBytes())) + ); + final PacketPlayOutCustomPayload packetPlayOutCustomPayload2 = new PacketPlayOutCustomPayload("REGISTER", + new PacketDataSerializer(Unpooled.wrappedBuffer("CC".getBytes())) + ); + + playerConnection.sendPacket(packetPlayOutCustomPayload); + playerConnection.sendPacket(packetPlayOutCustomPayload2); + }, 10L); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + FairFight.getInstance().getReceivingAlerts().remove(event.getPlayer().getUniqueId()); + } + + @EventHandler + public void onPlayerTeleport(PlayerTeleportEvent event) { + final Player player = event.getPlayer(); + final PlayerData playerData = FairFight.getInstance().getPlayerDataManager().getPlayerData(player); + + if (playerData != null) { + playerData.setSendingVape(true); + } + } + + @EventHandler + public void onPlayerChangedWorld(PlayerChangedWorldEvent event) { + final Player player = event.getPlayer(); + final PlayerData playerData = FairFight.getInstance().getPlayerDataManager().getPlayerData(player); + + if (playerData != null) { + playerData.setInventoryOpen(false); + } + } + + @EventHandler + public void onPlayerAlert(PlayerAlertEvent event) { + if (!FairFight.getInstance().isAntiCheatEnabled()) { + event.setCancelled(true); + return; + } + + final Player player = event.getPlayer(); + + if (player == null) { + return; + } + + final PlayerData playerData = FairFight.getInstance().getPlayerDataManager().getPlayerData(player); + + if (playerData == null) { + return; + } + + final String extra = event.getExtra() == null ? "" : " (" + event.getExtra() + ")"; + final String message = CC.translate(new MessageFormat(FairFight.getInstance().getConfig().getString("name") + " {0} &ehas flagged &b{1} &7(Ping: {2}){3}") + .format(new Object[]{ + player.getName(), event.getCheckName(), player.getPing(), extra + // Profile.getProfiles().get(player.getUniqueId()).getColoredUsername(), event.getCheckName(), player.getPing(), extra + // NucleusAPI.getColoredName(player), event.getCheckName(), player.getPing(), extra + })); + + if (event.getAlertType() == AlertType.RELEASE) { + for (Player onlinePlayer : FairFight.getInstance().getServer().getOnlinePlayers()) { + if (FairFight.getInstance().canAlert(onlinePlayer)) { + onlinePlayer.sendMessage(message); + } + } + } + + FairFightLog.getQueue().add(new FairFightLog( + player.getUniqueId(), + event.getCheckName(), + playerData.getClient().getName(), + player.getPing(), + MinecraftServer.getServer().tps1.getAverage(), + System.currentTimeMillis() + )); + } + + @EventHandler + public void onPlayerBan(PlayerBanEvent event) { + if (!FairFight.getInstance().isAntiCheatEnabled()) { + event.setCancelled(true); + return; + } + + final Player player = event.getPlayer(); + + if (player == null) { + return; + } + + final List messages = FairFight.getInstance().getConfig().getStringList("ban-broadcast"); + + for (String s : messages) { + Bukkit.getServer().broadcastMessage(ChatColor.translateAlternateColorCodes('&', s).replaceAll("%player%", player.getName())); + } + + TaskUtil.run(() -> { + FairFight.getInstance().getServer().dispatchCommand( + FairFight.getInstance().getServer().getConsoleSender(), + FairFight.getInstance().getConfig().getString("ban-command").replaceAll("%player%", player.getName()) + ); + }); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/manager/PlayerDataManager.java b/src/main/java/me/joeleoli/fairfight/manager/PlayerDataManager.java new file mode 100644 index 0000000..5fc231c --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/manager/PlayerDataManager.java @@ -0,0 +1,31 @@ +package me.joeleoli.fairfight.manager; + +import me.joeleoli.fairfight.player.PlayerData; + +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class PlayerDataManager { + + private final Map playerDataMap = new HashMap<>(); + + public void addPlayerData(Player player) { + this.playerDataMap.put(player.getUniqueId(), new PlayerData()); + } + + public void removePlayerData(Player player) { + this.playerDataMap.remove(player.getUniqueId()); + } + + public boolean hasPlayerData(Player player) { + return this.playerDataMap.containsKey(player.getUniqueId()); + } + + public PlayerData getPlayerData(Player player) { + return this.playerDataMap.get(player.getUniqueId()); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/mongo/FairFightLog.java b/src/main/java/me/joeleoli/fairfight/mongo/FairFightLog.java new file mode 100644 index 0000000..1565349 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/mongo/FairFightLog.java @@ -0,0 +1,24 @@ +package me.joeleoli.fairfight.mongo; + +import java.util.ArrayList; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.UUID; + +@AllArgsConstructor +@Getter +public class FairFightLog { + + @Getter + private static List queue = new ArrayList<>(); + + private UUID uuid; + private String flag; + private String client; + private int ping; + private double tps; + private long timestamp; + +} diff --git a/src/main/java/me/joeleoli/fairfight/mongo/FairFightMongo.java b/src/main/java/me/joeleoli/fairfight/mongo/FairFightMongo.java new file mode 100644 index 0000000..27ee849 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/mongo/FairFightMongo.java @@ -0,0 +1,58 @@ +package me.joeleoli.fairfight.mongo; + +import com.mongodb.MongoClient; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import java.util.Collections; +import lombok.Getter; +import me.joeleoli.fairfight.FairFight; + +import me.joeleoli.fairfight.util.nucleus.config.ConfigCursor; +import org.bson.Document; + +@Getter +public class FairFightMongo { + + private MongoClient client; + private MongoDatabase database; + private MongoCollection logs; + + public FairFightMongo() { + ConfigCursor cursor = new ConfigCursor(FairFight.getInstance().getMainFileConfig(), "mongo"); + + if (!cursor.exists("host") + || !cursor.exists("port") + || !cursor.exists("database") + || !cursor.exists("authentication.enabled") + || !cursor.exists("authentication.username") + || !cursor.exists("authentication.password") + || !cursor.exists("authentication.database")) { + throw new RuntimeException("Missing configuration option"); + } + + if (cursor.getBoolean("authentication.enabled")) { + final MongoCredential credential = MongoCredential.createCredential( + cursor.getString("authentication.username"), + cursor.getString("authentication.database"), + cursor.getString("authentication.password").toCharArray() + ); + + this.client = new MongoClient( + new ServerAddress(cursor.getString("host"), cursor.getInt("port")), + Collections.singletonList(credential) + ); + } else { + this.client = new MongoClient(new ServerAddress(cursor.getString("host"), cursor.getInt("port"))); + } + + this.database = this.client.getDatabase("fairfight"); + this.logs = this.database.getCollection("alert_logs"); + } + + public static FairFightMongo getInstance() { + return FairFight.getInstance().getMongo(); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/player/PlayerData.java b/src/main/java/me/joeleoli/fairfight/player/PlayerData.java new file mode 100644 index 0000000..190b6a0 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/player/PlayerData.java @@ -0,0 +1,268 @@ +package me.joeleoli.fairfight.player; + +import lombok.Getter; +import lombok.Setter; + +import me.joeleoli.fairfight.FairFight; +import me.joeleoli.fairfight.check.impl.aimassist.*; +import me.joeleoli.fairfight.check.impl.autoclicker.*; +import me.joeleoli.fairfight.check.impl.badpackets.*; +import me.joeleoli.fairfight.check.impl.inventory.*; +import me.joeleoli.fairfight.check.impl.killaura.*; +import me.joeleoli.fairfight.check.impl.velocity.VelocityA; +import me.joeleoli.fairfight.check.ICheck; +import me.joeleoli.fairfight.check.impl.fly.FlyA; +import me.joeleoli.fairfight.check.impl.fly.FlyB; +import me.joeleoli.fairfight.check.impl.fly.FlyC; +import me.joeleoli.fairfight.check.impl.range.RangeA; +import me.joeleoli.fairfight.check.impl.scaffold.ScaffoldA; +import me.joeleoli.fairfight.check.impl.scaffold.ScaffoldB; +import me.joeleoli.fairfight.check.impl.scaffold.ScaffoldC; +import me.joeleoli.fairfight.check.impl.step.StepA; +import me.joeleoli.fairfight.check.impl.timer.TimerA; +import me.joeleoli.fairfight.check.impl.velocity.VelocityB; +import me.joeleoli.fairfight.check.impl.velocity.VelocityC; +import me.joeleoli.fairfight.check.impl.wtap.WTapA; +import me.joeleoli.fairfight.check.impl.wtap.WTapB; +import me.joeleoli.fairfight.client.ClientType; +import me.joeleoli.fairfight.client.EnumClientType; +import me.joeleoli.fairfight.util.CustomLocation; + +import net.minecraft.server.v1_8_R3.BlockPosition; + +import java.lang.reflect.Constructor; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +@Setter @Getter public final class PlayerData { + + private static final Map, Constructor> CONSTRUCTORS; + public static final Class[] CHECKS; + + private final Map> recentPlayerPackets; + private final Map> checkViolationTimes; + private final Map, ICheck> checkMap; + private final Map keepAliveTimes; + private final Map checkVlMap; + private final Set fakeBlocks = new HashSet<>(); + private final Set teleportLocations; + private Map forgeMods; + private StringBuilder sniffedPacketBuilder; + private CustomLocation lastMovePacket; + private ClientType client; + private UUID lastTarget; + private String randomBanReason; + private double randomBanRate; + private boolean randomBan; + private boolean allowTeleport; + private boolean inventoryOpen; + private boolean setInventoryOpen; + private boolean sendingVape; + private boolean attackedSinceVelocity; + private boolean underBlock; + private boolean sprinting; + private boolean inLiquid; + private boolean instantBreakDigging; + private boolean fakeDigging; + private boolean onGround; + private boolean sniffing; + private boolean onStairs; + private boolean onCarpet; + private boolean placing; + private boolean banning; + private boolean digging; + private boolean inWeb; + private boolean onIce; + private boolean wasUnderBlock; + private boolean wasOnGround; + private boolean wasInLiquid; + private boolean wasInWeb; + private double lastGroundY; + private double velocityX; + private double velocityY; + private double velocityZ; + private long lastDelayedMovePacket; + private long lastAnimationPacket; + private long lastAttackPacket; + private long lastVelocity; + private long ping; + private int velocityH; + private int velocityV; + private int lastCps; + private int movementsSinceIce; + private int movementsSinceUnderBlock; + + public PlayerData() { + this.recentPlayerPackets = new HashMap<>(); + this.checkViolationTimes = new HashMap<>(); + this.checkMap = new HashMap<>(); + this.keepAliveTimes = new HashMap<>(); + this.checkVlMap = new HashMap<>(); + this.teleportLocations = Collections.newSetFromMap(new ConcurrentHashMap()); + this.sniffedPacketBuilder = new StringBuilder(); + this.client = EnumClientType.VANILLA; + + FairFight.getInstance().getServer().getScheduler().runTaskAsynchronously(FairFight.getInstance(), () -> { + PlayerData.CONSTRUCTORS.keySet().stream().map(o -> (Class) o).forEach(check -> { + Constructor constructor = PlayerData.CONSTRUCTORS.get(check); + try { + this.checkMap.put(check, constructor.newInstance(this)); + } catch (Exception ex) { + ex.printStackTrace(); + } + }); + }); + } + + public T getCheck(final Class clazz) { + return (T) this.checkMap.get(clazz); + } + + public CustomLocation getLastPlayerPacket(final UUID playerUUID, final int index) { + final List customLocations = this.recentPlayerPackets.get(playerUUID); + if (customLocations != null && customLocations.size() > index) { + return customLocations.get(customLocations.size() - index); + } + return null; + } + + public void addPlayerPacket(final UUID playerUUID, final CustomLocation customLocation) { + List customLocations = this.recentPlayerPackets.get(playerUUID); + if (customLocations == null) { + customLocations = new ArrayList<>(); + } + if (customLocations.size() == 20) { + customLocations.remove(0); + } + customLocations.add(customLocation); + this.recentPlayerPackets.put(playerUUID, customLocations); + } + + public void addTeleportLocation(final CustomLocation teleportLocation) { + this.teleportLocations.add(teleportLocation); + } + + public boolean allowTeleport(final CustomLocation teleportLocation) { + for (final CustomLocation customLocation : this.teleportLocations) { + final double delta = Math.pow(teleportLocation.getX() - customLocation.getX(), 2.0) + + Math.pow(teleportLocation.getZ() - customLocation.getZ(), 2.0); + if (delta <= 0.005) { + this.teleportLocations.remove(customLocation); + return true; + } + } + return false; + } + + public double getCheckVl(final ICheck check) { + if (!this.checkVlMap.containsKey(check)) { + this.checkVlMap.put(check, 0.0); + } + + return this.checkVlMap.get(check); + } + + public void setCheckVl(double vl, final ICheck check) { + if (vl < 0.0) { + vl = 0.0; + } + + this.checkVlMap.put(check, vl); + } + + public boolean keepAliveExists(final int id) { + return this.keepAliveTimes.containsKey(id); + } + + public long getKeepAliveTime(final int id) { + return this.keepAliveTimes.get(id); + } + + public void removeKeepAliveTime(final int id) { + this.keepAliveTimes.remove(id); + } + + public void addKeepAliveTime(final int id) { + this.keepAliveTimes.put(id, System.currentTimeMillis()); + } + + public int getViolations(final ICheck check, final Long time) { + final Set timestamps = this.checkViolationTimes.get(check); + + if (timestamps != null) { + int violations = 0; + + for (final long timestamp : timestamps) { + if (System.currentTimeMillis() - timestamp <= time) { + ++violations; + } + } + + return violations; + } + + return 0; + } + + public void addViolation(final ICheck check) { + Set timestamps = this.checkViolationTimes.get(check); + + if (timestamps == null) { + timestamps = new HashSet<>(); + } + + timestamps.add(System.currentTimeMillis()); + + this.checkViolationTimes.put(check, timestamps); + } + + static { + CHECKS = new Class[]{ + AimAssistA.class, AimAssistB.class, AimAssistC.class, AimAssistD.class, + AimAssistE.class, + + AutoClickerA.class, AutoClickerB.class, AutoClickerC.class, AutoClickerD.class, + AutoClickerE.class, AutoClickerF.class, AutoClickerG.class, AutoClickerH.class, + AutoClickerI.class, AutoClickerJ.class, AutoClickerK.class, AutoClickerK.class, + AutoClickerL.class, + + BadPacketsA.class, BadPacketsB.class, BadPacketsC.class, BadPacketsD.class, + BadPacketsE.class, BadPacketsF.class, BadPacketsG.class, BadPacketsH.class, + BadPacketsI.class, BadPacketsJ.class, BadPacketsK.class, BadPacketsL.class, + + FlyA.class, FlyB.class, FlyC.class, + + InventoryA.class, InventoryB.class, InventoryC.class, InventoryD.class, + InventoryE.class, InventoryF.class, InventoryG.class, + + KillAuraA.class, KillAuraB.class, KillAuraC.class, KillAuraD.class, + KillAuraE.class, KillAuraF.class, KillAuraG.class, KillAuraH.class, + KillAuraI.class, KillAuraJ.class, KillAuraK.class, KillAuraL.class, + KillAuraM.class, KillAuraN.class, KillAuraO.class, KillAuraP.class, + KillAuraQ.class, KillAuraR.class, KillAuraS.class, + + RangeA.class, + + TimerA.class, + + VelocityA.class, VelocityB.class, VelocityC.class, + + WTapA.class, WTapB.class, + + ScaffoldA.class, ScaffoldB.class, ScaffoldC.class, + + StepA.class, + }; + + CONSTRUCTORS = new ConcurrentHashMap<>(); + + for (final Class check : PlayerData.CHECKS) { + try { + PlayerData.CONSTRUCTORS.put(check, check.getConstructor(PlayerData.class)); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/task/InsertLogsTask.java b/src/main/java/me/joeleoli/fairfight/task/InsertLogsTask.java new file mode 100644 index 0000000..c9594c7 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/task/InsertLogsTask.java @@ -0,0 +1,40 @@ +package me.joeleoli.fairfight.task; + +import me.joeleoli.fairfight.mongo.FairFightLog; +import me.joeleoli.fairfight.mongo.FairFightMongo; + +import org.bson.Document; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class InsertLogsTask implements Runnable { + + @Override + public void run() { + final List documents = new ArrayList<>(); + final Iterator iterator = FairFightLog.getQueue().iterator(); + + while (iterator.hasNext()) { + final FairFightLog log = iterator.next(); + final Document document = new Document(); + + document.put("uuid", log.getUuid().toString()); + document.put("flag", log.getFlag()); + document.put("client", log.getClient()); + document.put("ping", log.getPing()); + document.put("tps", log.getTps()); + document.put("timestamp", log.getTimestamp()); + + documents.add(document); + + iterator.remove(); + } + + if (!documents.isEmpty()) { + FairFightMongo.getInstance().getLogs().insertMany(documents); + } + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/CustomLocation.java b/src/main/java/me/joeleoli/fairfight/util/CustomLocation.java new file mode 100644 index 0000000..6691890 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/CustomLocation.java @@ -0,0 +1,140 @@ +package me.joeleoli.fairfight.util; + +import java.util.StringJoiner; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +@Getter +@Setter +@AllArgsConstructor +public class CustomLocation { + + private final long timestamp = System.currentTimeMillis(); + + private String world; + + private double x; + private double y; + private double z; + + private float yaw; + private float pitch; + + public CustomLocation(double x, double y, double z) { + this(x, y, z, 0.0F, 0.0F); + } + + public CustomLocation(String world, double x, double y, double z) { + this(world, x, y, z, 0.0F, 0.0F); + } + + public CustomLocation(double x, double y, double z, float yaw, float pitch) { + this("world", x, y, z, yaw, pitch); + } + + public static CustomLocation fromBukkitLocation(Location location) { + return new CustomLocation(location.getWorld().getName(), location.getX(), location.getY(), location.getZ(), + location.getYaw(), location.getPitch()); + } + + public static CustomLocation stringToLocation(String string) { + String[] split = string.split(", "); + + double x = Double.parseDouble(split[0]); + double y = Double.parseDouble(split[1]); + double z = Double.parseDouble(split[2]); + + CustomLocation customLocation = new CustomLocation(x, y, z); + + if (split.length == 4) { + customLocation.setWorld(split[3]); + } else if (split.length >= 5) { + customLocation.setYaw(Float.parseFloat(split[3])); + customLocation.setPitch(Float.parseFloat(split[4])); + + if (split.length >= 6) { + customLocation.setWorld(split[5]); + } + } + + return customLocation; + } + + public static String locationToString(CustomLocation loc) { + StringJoiner joiner = new StringJoiner(", "); + joiner.add(Double.toString(loc.getX())); + joiner.add(Double.toString(loc.getY())); + joiner.add(Double.toString(loc.getZ())); + + if (loc.getYaw() == 0.0f && loc.getPitch() == 0.0f) { + if (loc.getWorld().equals("world")) { + return joiner.toString(); + } else { + joiner.add(loc.getWorld()); + return joiner.toString(); + } + } else { + joiner.add(Float.toString(loc.getYaw())); + joiner.add(Float.toString(loc.getPitch())); + + if (loc.getWorld().equals("world")) { + return joiner.toString(); + } else { + joiner.add(loc.getWorld()); + return joiner.toString(); + } + } + } + + public Location toBukkitLocation() { + return new Location(this.toBukkitWorld(), this.x, this.y, this.z, this.yaw, this.pitch); + } + + public double getGroundDistanceTo(CustomLocation location) { + return Math.sqrt(Math.pow(this.x - location.x, 2) + Math.pow(this.z - location.z, 2)); + } + + public double getDistanceTo(CustomLocation location) { + return Math.sqrt(Math.pow(this.x - location.x, 2) + Math.pow(this.y - location.y, 2) + Math.pow(this.z - location.z, 2)); + } + + public World toBukkitWorld() { + if (this.world == null) { + return Bukkit.getServer().getWorlds().get(0); + } else { + return Bukkit.getServer().getWorld(this.world); + } + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof CustomLocation)) { + return false; + } + + CustomLocation location = (CustomLocation) obj; + return location.x == this.x && location.y == this.y && location.z == this.z + && location.pitch == this.pitch && location.yaw == this.yaw; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("x", this.x) + .append("y", this.y) + .append("z", this.z) + .append("yaw", this.yaw) + .append("pitch", this.pitch) + .append("world", this.world) + .append("timestamp", this.timestamp) + .toString(); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/MathUtil.java b/src/main/java/me/joeleoli/fairfight/util/MathUtil.java new file mode 100644 index 0000000..36e97fa --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/MathUtil.java @@ -0,0 +1,31 @@ +package me.joeleoli.fairfight.util; + +import net.minecraft.server.v1_8_R3.*; + +public class MathUtil { + + public static float[] getRotationFromPosition(final CustomLocation playerLocation, final CustomLocation targetLocation) { + final double xDiff = targetLocation.getX() - playerLocation.getX(); + final double zDiff = targetLocation.getZ() - playerLocation.getZ(); + final double yDiff = targetLocation.getY() - (playerLocation.getY() + 0.12); + final double dist = MathHelper.sqrt(xDiff * xDiff + zDiff * zDiff); + final float yaw = (float)(Math.atan2(zDiff, xDiff) * 180.0 / 3.141592653589793) - 90.0f; + final float pitch = (float)(-(Math.atan2(yDiff, dist) * 180.0 / 3.141592653589793)); + return new float[] { yaw, pitch }; + } + + public static int pingFormula(final long ping) { + return (int) Math.ceil(ping / 2L / 50.0) + 2; + } + + public static float getDistanceBetweenAngles(final float angle1, final float angle2) { + float distance = Math.abs(angle1 - angle2) % 360.0f; + + if (distance > 180.0f) { + distance = 360.0f - distance; + } + + return distance; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/nucleus/BlockUtil.java b/src/main/java/me/joeleoli/fairfight/util/nucleus/BlockUtil.java new file mode 100644 index 0000000..2329a7a --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/nucleus/BlockUtil.java @@ -0,0 +1,432 @@ +package me.joeleoli.fairfight.util.nucleus; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; + +public class BlockUtil { + + public static List blocked = new ArrayList<>(); + private static Set blockSolidPassSet; + private static Set blockStairsSet; + private static Set blockLiquidsSet; + private static Set blockWebsSet; + private static Set blockIceSet; + private static Set blockCarpetSet; + + static { + BlockUtil.blockSolidPassSet = new HashSet<>(); + BlockUtil.blockStairsSet = new HashSet<>(); + BlockUtil.blockLiquidsSet = new HashSet<>(); + BlockUtil.blockWebsSet = new HashSet<>(); + BlockUtil.blockIceSet = new HashSet<>(); + BlockUtil.blockCarpetSet = new HashSet<>(); + BlockUtil.blockSolidPassSet.add((byte) 0); + BlockUtil.blockSolidPassSet.add((byte) 6); + BlockUtil.blockSolidPassSet.add((byte) 8); + BlockUtil.blockSolidPassSet.add((byte) 9); + BlockUtil.blockSolidPassSet.add((byte) 10); + BlockUtil.blockSolidPassSet.add((byte) 11); + BlockUtil.blockSolidPassSet.add((byte) 27); + BlockUtil.blockSolidPassSet.add((byte) 28); + BlockUtil.blockSolidPassSet.add((byte) 30); + BlockUtil.blockSolidPassSet.add((byte) 31); + BlockUtil.blockSolidPassSet.add((byte) 32); + BlockUtil.blockSolidPassSet.add((byte) 37); + BlockUtil.blockSolidPassSet.add((byte) 38); + BlockUtil.blockSolidPassSet.add((byte) 39); + BlockUtil.blockSolidPassSet.add((byte) 40); + BlockUtil.blockSolidPassSet.add((byte) 50); + BlockUtil.blockSolidPassSet.add((byte) 51); + BlockUtil.blockSolidPassSet.add((byte) 55); + BlockUtil.blockSolidPassSet.add((byte) 59); + BlockUtil.blockSolidPassSet.add((byte) 63); + BlockUtil.blockSolidPassSet.add((byte) 66); + BlockUtil.blockSolidPassSet.add((byte) 68); + BlockUtil.blockSolidPassSet.add((byte) 69); + BlockUtil.blockSolidPassSet.add((byte) 70); + BlockUtil.blockSolidPassSet.add((byte) 72); + BlockUtil.blockSolidPassSet.add((byte) 75); + BlockUtil.blockSolidPassSet.add((byte) 76); + BlockUtil.blockSolidPassSet.add((byte) 77); + BlockUtil.blockSolidPassSet.add((byte) 78); + BlockUtil.blockSolidPassSet.add((byte) 83); + BlockUtil.blockSolidPassSet.add((byte) 90); + BlockUtil.blockSolidPassSet.add((byte) 104); + BlockUtil.blockSolidPassSet.add((byte) 105); + BlockUtil.blockSolidPassSet.add((byte) 115); + BlockUtil.blockSolidPassSet.add((byte) 119); + BlockUtil.blockSolidPassSet.add((byte) (-124)); + BlockUtil.blockSolidPassSet.add((byte) (-113)); + BlockUtil.blockSolidPassSet.add((byte) (-81)); + BlockUtil.blockStairsSet.add((byte) 53); + BlockUtil.blockStairsSet.add((byte) 67); + BlockUtil.blockStairsSet.add((byte) 108); + BlockUtil.blockStairsSet.add((byte) 109); + BlockUtil.blockStairsSet.add((byte) 114); + BlockUtil.blockStairsSet.add((byte) (-128)); + BlockUtil.blockStairsSet.add((byte) (-122)); + BlockUtil.blockStairsSet.add((byte) (-121)); + BlockUtil.blockStairsSet.add((byte) (-120)); + BlockUtil.blockStairsSet.add((byte) (-100)); + BlockUtil.blockStairsSet.add((byte) (-93)); + BlockUtil.blockStairsSet.add((byte) (-92)); + BlockUtil.blockStairsSet.add((byte) (-76)); + BlockUtil.blockStairsSet.add((byte) 126); + BlockUtil.blockStairsSet.add((byte) (-74)); + BlockUtil.blockStairsSet.add((byte) 44); + BlockUtil.blockStairsSet.add((byte) 78); + BlockUtil.blockStairsSet.add((byte) 99); + BlockUtil.blockStairsSet.add((byte) (-112)); + BlockUtil.blockStairsSet.add((byte) (-115)); + BlockUtil.blockStairsSet.add((byte) (-116)); + BlockUtil.blockStairsSet.add((byte) (-105)); + BlockUtil.blockStairsSet.add((byte) (-108)); + BlockUtil.blockStairsSet.add((byte) 100); + BlockUtil.blockLiquidsSet.add((byte) 8); + BlockUtil.blockLiquidsSet.add((byte) 9); + BlockUtil.blockLiquidsSet.add((byte) 10); + BlockUtil.blockLiquidsSet.add((byte) 11); + BlockUtil.blockWebsSet.add((byte) 30); + BlockUtil.blockIceSet.add((byte) 79); + BlockUtil.blockIceSet.add((byte) (-82)); + BlockUtil.blockCarpetSet.add((byte) (-85)); + + blocked.add(Material.ACTIVATOR_RAIL); + blocked.add(Material.ANVIL); + blocked.add(Material.BED_BLOCK); + blocked.add(Material.POTATO); + blocked.add(Material.POTATO_ITEM); + blocked.add(Material.CARROT); + blocked.add(Material.CARROT_ITEM); + blocked.add(Material.BIRCH_WOOD_STAIRS); + blocked.add(Material.BREWING_STAND); + blocked.add(Material.BOAT); + blocked.add(Material.BRICK_STAIRS); + blocked.add(Material.BROWN_MUSHROOM); + blocked.add(Material.CAKE_BLOCK); + blocked.add(Material.CARPET); + blocked.add(Material.CAULDRON); + blocked.add(Material.COBBLESTONE_STAIRS); + blocked.add(Material.COBBLE_WALL); + blocked.add(Material.DARK_OAK_STAIRS); + blocked.add(Material.DIODE); + blocked.add(Material.DIODE_BLOCK_ON); + blocked.add(Material.DIODE_BLOCK_OFF); + blocked.add(Material.DEAD_BUSH); + blocked.add(Material.DETECTOR_RAIL); + blocked.add(Material.DOUBLE_PLANT); + blocked.add(Material.DOUBLE_STEP); + blocked.add(Material.DRAGON_EGG); + blocked.add(Material.PAINTING); + blocked.add(Material.FLOWER_POT); + blocked.add(Material.GOLD_PLATE); + blocked.add(Material.HOPPER); + blocked.add(Material.STONE_PLATE); + blocked.add(Material.IRON_PLATE); + blocked.add(Material.HUGE_MUSHROOM_1); + blocked.add(Material.HUGE_MUSHROOM_2); + blocked.add(Material.IRON_DOOR_BLOCK); + blocked.add(Material.IRON_DOOR); + blocked.add(Material.FENCE); + blocked.add(Material.IRON_FENCE); + blocked.add(Material.IRON_PLATE); + blocked.add(Material.ITEM_FRAME); + blocked.add(Material.JUKEBOX); + blocked.add(Material.JUNGLE_WOOD_STAIRS); + blocked.add(Material.LADDER); + blocked.add(Material.LEVER); + blocked.add(Material.LONG_GRASS); + blocked.add(Material.NETHER_FENCE); + blocked.add(Material.NETHER_STALK); + blocked.add(Material.NETHER_WARTS); + blocked.add(Material.MELON_STEM); + blocked.add(Material.PUMPKIN_STEM); + blocked.add(Material.QUARTZ_STAIRS); + blocked.add(Material.RAILS); + blocked.add(Material.RED_MUSHROOM); + blocked.add(Material.RED_ROSE); + blocked.add(Material.SAPLING); + blocked.add(Material.SEEDS); + blocked.add(Material.SIGN); + blocked.add(Material.SIGN_POST); + blocked.add(Material.SKULL); + blocked.add(Material.SMOOTH_STAIRS); + blocked.add(Material.NETHER_BRICK_STAIRS); + blocked.add(Material.SPRUCE_WOOD_STAIRS); + blocked.add(Material.STAINED_GLASS_PANE); + blocked.add(Material.REDSTONE_COMPARATOR); + blocked.add(Material.REDSTONE_COMPARATOR_OFF); + blocked.add(Material.REDSTONE_COMPARATOR_ON); + blocked.add(Material.REDSTONE_LAMP_OFF); + blocked.add(Material.REDSTONE_LAMP_ON); + blocked.add(Material.REDSTONE_TORCH_OFF); + blocked.add(Material.REDSTONE_TORCH_ON); + blocked.add(Material.REDSTONE_WIRE); + blocked.add(Material.SANDSTONE_STAIRS); + blocked.add(Material.STEP); + blocked.add(Material.ACACIA_STAIRS); + blocked.add(Material.SUGAR_CANE); + blocked.add(Material.SUGAR_CANE_BLOCK); + blocked.add(Material.ENCHANTMENT_TABLE); + blocked.add(Material.SOUL_SAND); + blocked.add(Material.TORCH); + blocked.add(Material.TRAP_DOOR); + blocked.add(Material.TRIPWIRE); + blocked.add(Material.TRIPWIRE_HOOK); + blocked.add(Material.WALL_SIGN); + blocked.add(Material.VINE); + blocked.add(Material.WATER_LILY); + blocked.add(Material.WEB); + blocked.add(Material.WOOD_DOOR); + blocked.add(Material.WOOD_DOUBLE_STEP); + blocked.add(Material.WOOD_PLATE); + blocked.add(Material.WOOD_STAIRS); + blocked.add(Material.WOOD_STEP); + blocked.add(Material.HOPPER); + blocked.add(Material.WOODEN_DOOR); + blocked.add(Material.YELLOW_FLOWER); + blocked.add(Material.LAVA); + blocked.add(Material.WATER); + blocked.add(Material.STATIONARY_WATER); + blocked.add(Material.STATIONARY_LAVA); + blocked.add(Material.CACTUS); + blocked.add(Material.CHEST); + blocked.add(Material.PISTON_BASE); + blocked.add(Material.PISTON_MOVING_PIECE); + blocked.add(Material.PISTON_EXTENSION); + blocked.add(Material.PISTON_STICKY_BASE); + blocked.add(Material.TRAPPED_CHEST); + blocked.add(Material.SNOW); + blocked.add(Material.ENDER_CHEST); + blocked.add(Material.THIN_GLASS); + blocked.add(Material.ENDER_PORTAL_FRAME); + } + + public static boolean isOnStairs(final Location location, final int down) { + return isUnderBlock(location, BlockUtil.blockStairsSet, down); + } + + public static boolean isOnLiquid(final Location location, final int down) { + return isUnderBlock(location, BlockUtil.blockLiquidsSet, down); + } + + public static boolean isOnWeb(final Location location, final int down) { + return isUnderBlock(location, BlockUtil.blockWebsSet, down); + } + + public static boolean isOnIce(final Location location, final int down) { + return isUnderBlock(location, BlockUtil.blockIceSet, down); + } + + public static boolean isOnCarpet(final Location location, final int down) { + return isUnderBlock(location, BlockUtil.blockCarpetSet, down); + } + + public static boolean isSlab(final Player player) { + return blocked.contains(player.getLocation().getBlock().getRelative(BlockFace.DOWN).getType()); + } + + public static boolean isBlockFaceAir(final Player player) { + final Block block = player.getLocation().getBlock().getRelative(BlockFace.DOWN); + return block.getType().equals(Material.AIR) && block.getRelative(BlockFace.WEST).getType().equals(Material + .AIR) && block.getRelative(BlockFace.NORTH).getType().equals(Material.AIR) && block.getRelative + (BlockFace.EAST).getType().equals(Material.AIR) && block.getRelative(BlockFace.SOUTH).getType() + .equals(Material.AIR); + } + + private static boolean isUnderBlock(final Location location, final Set itemIDs, final int down) { + final double posX = location.getX(); + final double posZ = location.getZ(); + final double fracX = (posX % 1.0 > 0.0) ? Math.abs(posX % 1.0) : (1.0 - Math.abs(posX % 1.0)); + final double fracZ = (posZ % 1.0 > 0.0) ? Math.abs(posZ % 1.0) : (1.0 - Math.abs(posZ % 1.0)); + final int blockX = location.getBlockX(); + final int blockY = location.getBlockY() - down; + final int blockZ = location.getBlockZ(); + final World world = location.getWorld(); + + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ).getTypeId())) { + return true; + } + + if (fracX < 0.3) { + if (itemIDs.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ).getTypeId())) { + return true; + } + + if (fracZ < 0.3) { + if (itemIDs.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1).getTypeId())) { + return true; + } + + if (itemIDs.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + } else if (fracZ > 0.7) { + if (itemIDs.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ + 1).getTypeId())) { + return true; + } + + if (itemIDs.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + } + } else if (fracX > 0.7) { + if (itemIDs.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ).getTypeId())) { + return true; + } + + if (fracZ < 0.3) { + if (itemIDs.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1).getTypeId())) { + return true; + } + + if (itemIDs.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + } else if (fracZ > 0.7) { + if (itemIDs.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ + 1).getTypeId())) { + return true; + } + + if (itemIDs.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + } + } else if (fracZ < 0.3) { + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1).getTypeId())) { + return true; + } + } else if (fracZ > 0.7 && itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ + 1).getTypeId())) { + return true; + } + + return false; + } + + public static boolean isOnGround(final Location location, final int down) { + final double posX = location.getX(); + final double posZ = location.getZ(); + final double fracX = (posX % 1.0 > 0.0) ? Math.abs(posX % 1.0) : (1.0 - Math.abs(posX % 1.0)); + final double fracZ = (posZ % 1.0 > 0.0) ? Math.abs(posZ % 1.0) : (1.0 - Math.abs(posZ % 1.0)); + final int blockX = location.getBlockX(); + final int blockY = location.getBlockY() - down; + final int blockZ = location.getBlockZ(); + final World world = location.getWorld(); + + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ).getTypeId())) { + return true; + } + + if (fracX < 0.3) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ).getTypeId() + )) { + return true; + } + + if (fracZ < 0.3) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ - 1) + .getTypeId())) { + return true; + } + + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1) + .getTypeId())) { + return true; + } + + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ - 1) + .getTypeId())) { + return true; + } + } else if (fracZ > 0.7) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ + 1) + .getTypeId())) { + return true; + } + + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ + 1) + .getTypeId())) { + return true; + } + + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ + 1) + .getTypeId())) { + return true; + } + } + } else if (fracX > 0.7) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ).getTypeId() + )) { + return true; + } + + if (fracZ < 0.3) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ - 1) + .getTypeId())) { + return true; + } + + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1) + .getTypeId())) { + return true; + } + + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ - 1) + .getTypeId())) { + return true; + } + } else if (fracZ > 0.7) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ + 1) + .getTypeId())) { + return true; + } + + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ + 1) + .getTypeId())) { + return true; + } + + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ + 1) + .getTypeId())) { + return true; + } + } + } else if (fracZ < 0.3) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1).getTypeId() + )) { + return true; + } + } else if (fracZ > 0.7 && !BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, + blockZ + 1 + ).getTypeId())) { + return true; + } + + return false; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/nucleus/config/ConfigCursor.java b/src/main/java/me/joeleoli/fairfight/util/nucleus/config/ConfigCursor.java new file mode 100644 index 0000000..c8baea3 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/nucleus/config/ConfigCursor.java @@ -0,0 +1,76 @@ +package me.joeleoli.fairfight.util.nucleus.config; + +import java.util.List; +import java.util.Set; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Bukkit; +import org.bukkit.World; + +@AllArgsConstructor +@Getter +public class ConfigCursor { + + private final FileConfig fileConfig; + @Setter private String path; + + public boolean exists() { + return this.exists(null); + } + + public boolean exists(String path) { + return this.fileConfig.getConfig().contains(this.path + (path == null ? "" : "." + path)); + } + + public Set getKeys() { + return this.getKeys(null); + } + + public Set getKeys(String path) { + return this.fileConfig.getConfig().getConfigurationSection(this.path + (path == null ? "" : "." + path)) + .getKeys(false); + } + + public String getString(String path) { + return this.fileConfig.getConfig().getString((this.path == null ? "" : this.path + ".") + path); + } + + public boolean getBoolean(String path) { + return this.fileConfig.getConfig().getBoolean((this.path == null ? "" : this.path + ".") + "." + path); + } + + public int getInt(String path) { + return this.fileConfig.getConfig().getInt((this.path == null ? "" : this.path + ".") + "." + path); + } + + public long getLong(String path) { + return this.fileConfig.getConfig().getLong((this.path == null ? "" : this.path + ".") + "." + path); + } + + public List getStringList(String path) { + return this.fileConfig.getConfig().getStringList((this.path == null ? "" : this.path + ".") + "." + path); + } + + public UUID getUuid(String path) { + return UUID.fromString(this.fileConfig.getConfig().getString(this.path + "." + path)); + } + + public World getWorld(String path) { + return Bukkit.getWorld(this.fileConfig.getConfig().getString(this.path + "." + path)); + } + + public void set(Object value) { + this.set(null, value); + } + + public void set(String path, Object value) { + this.fileConfig.getConfig().set(this.path + (path == null ? "" : "." + path), value); + } + + public void save() { + this.fileConfig.save(); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/nucleus/config/FileConfig.java b/src/main/java/me/joeleoli/fairfight/util/nucleus/config/FileConfig.java new file mode 100644 index 0000000..d566785 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/nucleus/config/FileConfig.java @@ -0,0 +1,46 @@ +package me.joeleoli.fairfight.util.nucleus.config; + +import java.io.File; +import java.io.IOException; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +@Getter +public class FileConfig { + + private File file; + private FileConfiguration config; + + public FileConfig(JavaPlugin plugin, String fileName) { + this.file = new File(plugin.getDataFolder(), fileName); + + if (!this.file.exists()) { + this.file.getParentFile().mkdirs(); + + if (plugin.getResource(fileName) == null) { + try { + this.file.createNewFile(); + } catch (IOException e) { + plugin.getLogger().severe("Failed to create new file " + fileName); + } + } else { + plugin.saveResource(fileName, false); + } + } + + this.config = YamlConfiguration.loadConfiguration(this.file); + } + + public void save() { + try { + this.config.save(this.file); + } catch (IOException e) { + Bukkit.getLogger().severe("Could not save config file " + this.file.toString()); + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/src/main/java/me/joeleoli/fairfight/util/nucleus/listener/ListenerHandler.java b/src/main/java/me/joeleoli/fairfight/util/nucleus/listener/ListenerHandler.java new file mode 100644 index 0000000..96be835 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/nucleus/listener/ListenerHandler.java @@ -0,0 +1,45 @@ +package me.joeleoli.fairfight.util.nucleus.listener; + +import me.joeleoli.fairfight.util.nucleus.util.ClassUtil; +import org.bukkit.event.Listener; +import org.bukkit.plugin.Plugin; + +public class ListenerHandler { + + /** + * Registers all listeners from the given package with the given plugin. + * + * @param plugin The plugin responsible for these listeners. This is here because the .getClassesInPackage + * method requires it (for no real reason) + * @param packageName The package to load listeners from. Example: "me.joeleoli.nucleus.listeners" + */ + public static void loadListenersFromPackage(Plugin plugin, String packageName) { + for (Class clazz : ClassUtil.getClassesInPackage(plugin, packageName)) { + if (isListener(clazz)) { + try { + plugin.getServer().getPluginManager().registerEvents((Listener) clazz.newInstance(), plugin); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + + /** + * Check if the given class implements the {@link Listener} interface. + * + * @param clazz The class to check + * + * @return If the class implements the {@link Listener} interface + */ + public static boolean isListener(Class clazz) { + for (Class interfaze : clazz.getInterfaces()) { + if (interfaze == Listener.class) { + return true; + } + } + + return false; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/nucleus/util/ClassUtil.java b/src/main/java/me/joeleoli/fairfight/util/nucleus/util/ClassUtil.java new file mode 100644 index 0000000..13533f0 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/nucleus/util/ClassUtil.java @@ -0,0 +1,80 @@ +package me.joeleoli.fairfight.util.nucleus.util; + +import com.google.common.collect.ImmutableSet; +import java.io.IOException; +import java.net.URL; +import java.security.CodeSource; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import org.bukkit.plugin.Plugin; + +public final class ClassUtil { + + private ClassUtil() { + throw new RuntimeException("Cannot instantiate a utility class."); + } + + /** + * Gets all the classes in a the provided package. + * + * @param plugin The plugin who owns the package + * @param packageName The package to scan classes in. + * + * @return The classes in the package packageName. + */ + public static Collection> getClassesInPackage(Plugin plugin, String packageName) { + Collection> classes = new ArrayList<>(); + + CodeSource codeSource = plugin.getClass().getProtectionDomain().getCodeSource(); + URL resource = codeSource.getLocation(); + String relPath = packageName.replace('.', '/'); + String resPath = resource.getPath().replace("%20", " "); + String jarPath = resPath.replaceFirst("[.]jar[!].*", ".jar").replaceFirst("file:", ""); + JarFile jarFile; + + try { + jarFile = new JarFile(jarPath); + } catch (IOException e) { + throw (new RuntimeException("Unexpected IOException reading JAR File '" + jarPath + "'", e)); + } + + Enumeration entries = jarFile.entries(); + + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String entryName = entry.getName(); + String className = null; + + if (entryName.endsWith(".class") && entryName.startsWith(relPath) && + entryName.length() > (relPath.length() + "/".length())) { + className = entryName.replace('/', '.').replace('\\', '.').replace(".class", ""); + } + + if (className != null) { + Class clazz = null; + + try { + clazz = Class.forName(className); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + + if (clazz != null) { + classes.add(clazz); + } + } + } + + try { + jarFile.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + return (ImmutableSet.copyOf(classes)); + } + +} \ No newline at end of file diff --git a/src/main/java/me/joeleoli/fairfight/util/nucleus/util/ItemUtil.java b/src/main/java/me/joeleoli/fairfight/util/nucleus/util/ItemUtil.java new file mode 100644 index 0000000..4d5a9e8 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/nucleus/util/ItemUtil.java @@ -0,0 +1,196 @@ +package me.joeleoli.fairfight.util.nucleus.util; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import me.joeleoli.fairfight.FairFight; +import me.joeleoli.fairfight.util.zoot.util.BukkitReflection; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.WordUtils; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +public class ItemUtil { + + private static final Map NAME_MAP = new HashMap<>(); + + public static ItemData[] repeat(Material material, int times) { + return repeat(material, (byte) 0, times); + } + + public static ItemData[] repeat(Material material, byte data, int times) { + ItemData[] itemData = new ItemData[times]; + + for (int i = 0; i < times; i++) { + itemData[i] = new ItemData(material, data); + } + + return itemData; + + } + + public static ItemData[] armorOf(ArmorPart part) { + List data = new ArrayList<>(); + + for (ArmorType at : ArmorType.values()) { + data.add(new ItemData(Material.valueOf(at.name() + "_" + part.name()), (short) 0)); + } + + return data.toArray(new ItemData[data.size()]); + } + + public static ItemData[] swords() { + List data = new ArrayList<>(); + + for (SwordType at : SwordType.values()) { + data.add(new ItemData(Material.valueOf(at.name() + "_SWORD"), (short) 0)); + } + + return data.toArray(new ItemData[data.size()]); + } + + public static void load() { + NAME_MAP.clear(); + + List lines = readLines(); + + for (String line : lines) { + String[] parts = line.split(","); + + NAME_MAP.put( + parts[0], + new ItemData(Material.getMaterial(Integer.parseInt(parts[1])), Short.parseShort(parts[2])) + ); + } + } + + public static ItemStack get(String input, int amount) { + ItemStack item = get(input); + + if (item != null) { + item.setAmount(amount); + } + + return item; + } + + public static ItemStack get(String input) { + if (NumberUtil.isInteger(input)) { + return new ItemStack(Material.getMaterial(Integer.parseInt(input))); + } + + if (input.contains(":")) { + if (NumberUtil.isShort(input.split(":")[1])) { + if (NumberUtil.isInteger(input.split(":")[0])) { + return new ItemStack( + Material.getMaterial(Integer.parseInt(input.split(":")[0])), 1, + Short.parseShort(input.split(":")[1]) + ); + } else { + if (!NAME_MAP.containsKey(input.split(":")[0].toLowerCase())) { + return null; + } + + ItemData data = NAME_MAP.get(input.split(":")[0].toLowerCase()); + return new ItemStack(data.getMaterial(), 1, Short.parseShort(input.split(":")[1])); + } + } else { + return null; + } + } + + if (!NAME_MAP.containsKey(input)) { + return null; + } + + return NAME_MAP.get(input).toItemStack(); + } + + public static String getName(ItemStack item) { + if (item.getDurability() != 0) { + String reflectedName = BukkitReflection.getItemStackName(item); + + if (reflectedName != null) { + if (reflectedName.contains(".")) { + reflectedName = WordUtils.capitalize(item.getType().toString().toLowerCase().replace("_", " ")); + } + + return reflectedName; + } + } + + String string = item.getType().toString().replace("_", " "); + char[] chars = string.toLowerCase().toCharArray(); + boolean found = false; + + for (int i = 0; i < chars.length; i++) { + if (!found && Character.isLetter(chars[i])) { + chars[i] = Character.toUpperCase(chars[i]); + found = true; + } else if (Character.isWhitespace(chars[i]) || chars[i] == '.' || chars[i] == '\'') { + found = false; + } + } + + return String.valueOf(chars); + } + + private static List readLines() { + try { + return IOUtils.readLines(FairFight.class.getClassLoader().getResourceAsStream("items.csv")); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + + public enum ArmorPart { + HELMET, + CHESTPLATE, + LEGGINGS, + BOOTS + } + + public enum ArmorType { + DIAMOND, + IRON, + GOLD, + LEATHER + } + + public enum SwordType { + DIAMOND, + IRON, + GOLD, + STONE + } + + @Getter + @AllArgsConstructor + public static class ItemData { + + private final Material material; + private final short data; + + public String getName() { + return ItemUtil.getName(toItemStack()); + } + + public boolean matches(ItemStack item) { + return item != null && item.getType() == material && item.getDurability() == data; + } + + public ItemStack toItemStack() { + return new ItemStack(material, 1, data); + } + + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/nucleus/util/NumberUtil.java b/src/main/java/me/joeleoli/fairfight/util/nucleus/util/NumberUtil.java new file mode 100644 index 0000000..7ab4e79 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/nucleus/util/NumberUtil.java @@ -0,0 +1,80 @@ +package me.joeleoli.fairfight.util.nucleus.util; + +import java.text.NumberFormat; +import java.util.Locale; +import java.util.Map; +import java.util.NavigableMap; +import java.util.TreeMap; +import java.util.concurrent.ThreadLocalRandom; + +public class NumberUtil { + + private static final NavigableMap SUFFIXES = new TreeMap<>(); + + static { + SUFFIXES.put(1_000L, "k"); + SUFFIXES.put(1_000_000L, "M"); + SUFFIXES.put(1_000_000_000L, "B"); + SUFFIXES.put(1_000_000_000_000L, "T"); + SUFFIXES.put(1_000_000_000_000L, "Q"); + SUFFIXES.put(1_000_000_000_000_000L, "QT"); + } + + public static int getRandomRange(int min, int max) { + return ThreadLocalRandom.current().nextInt(min, max + 1); + } + + public static float getRandomRange() { + return ThreadLocalRandom.current().nextFloat(); + } + + public static boolean isInteger(String input) { + try { + Integer.parseInt(input); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + public static boolean isShort(String input) { + try { + Short.parseShort(input); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + public static boolean isEven(int number) { + return number % 2 == 0; + } + + public static String convertAbbreviated(long value) { + if (value == Long.MIN_VALUE) { + return convertAbbreviated(Long.MIN_VALUE + 1); + } + + if (value < 0) { + return "-" + convertAbbreviated(-value); + } + + if (value < 1000) { + return Long.toString(value); + } + + Map.Entry e = SUFFIXES.floorEntry(value); + Long divideBy = e.getKey(); + String suffix = e.getValue(); + + long truncated = value / (divideBy / 10); + boolean hasDecimal = truncated < 100 && (truncated / 10d) != (truncated / 10); + + return hasDecimal ? (truncated / 10d) + suffix : (truncated / 10) + suffix; + } + + public static String formatNumber(long value) { + return NumberFormat.getInstance(Locale.US).format(value); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/nucleus/util/TaskUtil.java b/src/main/java/me/joeleoli/fairfight/util/nucleus/util/TaskUtil.java new file mode 100644 index 0000000..39d9ee9 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/nucleus/util/TaskUtil.java @@ -0,0 +1,29 @@ +package me.joeleoli.fairfight.util.nucleus.util; + + +import me.joeleoli.fairfight.FairFight; +import org.bukkit.scheduler.BukkitRunnable; + +public class TaskUtil { + + public static void run(Runnable runnable) { + FairFight.getInstance().getServer().getScheduler().runTask(FairFight.getInstance(), runnable); + } + + public static void runTimer(Runnable runnable, long delay, long timer) { + FairFight.getInstance().getServer().getScheduler().runTaskTimer(FairFight.getInstance(), runnable, delay, timer); + } + + public static void runTimer(BukkitRunnable runnable, long delay, long timer) { + runnable.runTaskTimer(FairFight.getInstance(), delay, timer); + } + + public static void runLater(Runnable runnable, long delay) { + FairFight.getInstance().getServer().getScheduler().runTaskLater(FairFight.getInstance(), runnable, delay); + } + + public static void runAsync(Runnable runnable) { + FairFight.getInstance().getServer().getScheduler().runTaskAsynchronously(FairFight.getInstance(), runnable); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/update/MovementUpdate.java b/src/main/java/me/joeleoli/fairfight/util/update/MovementUpdate.java new file mode 100644 index 0000000..8847d2e --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/update/MovementUpdate.java @@ -0,0 +1,25 @@ +package me.joeleoli.fairfight.util.update; + +import lombok.Getter; + +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.Location; +import org.bukkit.entity.Player; + +@Getter +public class MovementUpdate { + + private Player player; + private Location to; + private Location from; + private PacketPlayInFlying packet; + + public MovementUpdate(final Player player, final Location to, final Location from, final PacketPlayInFlying packet) { + this.player = player; + this.to = to; + this.from = from; + this.packet = packet; + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/update/PositionUpdate.java b/src/main/java/me/joeleoli/fairfight/util/update/PositionUpdate.java new file mode 100644 index 0000000..5f95118 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/update/PositionUpdate.java @@ -0,0 +1,14 @@ +package me.joeleoli.fairfight.util.update; + +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.Location; +import org.bukkit.entity.Player; + +public class PositionUpdate extends MovementUpdate { + + public PositionUpdate(Player player, Location to, Location from, PacketPlayInFlying packet) { + super(player, to, from, packet); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/update/RotationUpdate.java b/src/main/java/me/joeleoli/fairfight/util/update/RotationUpdate.java new file mode 100644 index 0000000..66c8a5c --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/update/RotationUpdate.java @@ -0,0 +1,14 @@ +package me.joeleoli.fairfight.util.update; + +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; + +import org.bukkit.Location; +import org.bukkit.entity.Player; + +public class RotationUpdate extends MovementUpdate { + + public RotationUpdate(Player player, Location to, Location from, PacketPlayInFlying packet) { + super(player, to, from, packet); + } + +} diff --git a/src/main/java/me/joeleoli/fairfight/util/zoot/util/BukkitReflection.java b/src/main/java/me/joeleoli/fairfight/util/zoot/util/BukkitReflection.java new file mode 100644 index 0000000..1f127d8 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/zoot/util/BukkitReflection.java @@ -0,0 +1,94 @@ +package me.joeleoli.fairfight.util.zoot.util; + +import org.bukkit.Bukkit; +import org.bukkit.Server; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public class BukkitReflection +{ + private static String CRAFT_BUKKIT_PACKAGE; + private static String NET_MINECRAFT_SERVER_PACKAGE; + private static Class CRAFT_SERVER_CLASS; + private static Method CRAFT_SERVER_GET_HANDLE_METHOD; + private static Class PLAYER_LIST_CLASS; + private static Field PLAYER_LIST_MAX_PLAYERS_FIELD; + private static Class CRAFT_PLAYER_CLASS; + private static Method CRAFT_PLAYER_GET_HANDLE_METHOD; + private static Class ENTITY_PLAYER_CLASS; + private static Field ENTITY_PLAYER_PING_FIELD; + private static Class CRAFT_ITEM_STACK_CLASS; + private static Method CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD; + private static Class ENTITY_ITEM_STACK_CLASS; + private static Method ENTITY_ITEM_STACK_GET_NAME; + private static Class SPIGOT_CONFIG_CLASS; + private static Field SPIGOT_CONFIG_BUNGEE_FIELD; + + public static int getPing(Player player) { + try { + int ping = BukkitReflection.ENTITY_PLAYER_PING_FIELD.getInt(BukkitReflection.CRAFT_PLAYER_GET_HANDLE_METHOD.invoke(player, new Object[0])); + return (ping > 0) ? ping : 0; + } + catch (Exception e) { + return 1; + } + } + + public static void setMaxPlayers(Server server, int slots) { + try { + BukkitReflection.PLAYER_LIST_MAX_PLAYERS_FIELD.set(BukkitReflection.CRAFT_SERVER_GET_HANDLE_METHOD.invoke(server, new Object[0]), slots); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + public static String getItemStackName(ItemStack itemStack) { + try { + return (String)BukkitReflection.ENTITY_ITEM_STACK_GET_NAME.invoke(BukkitReflection.CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD.invoke(itemStack, itemStack), new Object[0]); + } + catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + public static boolean isBungeeServer() { + try { + return (boolean)BukkitReflection.SPIGOT_CONFIG_BUNGEE_FIELD.get(null); + } + catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + static { + try { + String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + CRAFT_BUKKIT_PACKAGE = "org.bukkit.craftbukkit." + version + "."; + NET_MINECRAFT_SERVER_PACKAGE = "net.minecraft.server." + version + "."; + CRAFT_SERVER_CLASS = Class.forName(BukkitReflection.CRAFT_BUKKIT_PACKAGE + "CraftServer"); + (CRAFT_SERVER_GET_HANDLE_METHOD = BukkitReflection.CRAFT_SERVER_CLASS.getDeclaredMethod("getHandle", (Class[])new Class[0])).setAccessible(true); + PLAYER_LIST_CLASS = Class.forName(BukkitReflection.NET_MINECRAFT_SERVER_PACKAGE + "PlayerList"); + (PLAYER_LIST_MAX_PLAYERS_FIELD = BukkitReflection.PLAYER_LIST_CLASS.getDeclaredField("maxPlayers")).setAccessible(true); + CRAFT_PLAYER_CLASS = Class.forName(BukkitReflection.CRAFT_BUKKIT_PACKAGE + "entity.CraftPlayer"); + (CRAFT_PLAYER_GET_HANDLE_METHOD = BukkitReflection.CRAFT_PLAYER_CLASS.getDeclaredMethod("getHandle", (Class[])new Class[0])).setAccessible(true); + ENTITY_PLAYER_CLASS = Class.forName(BukkitReflection.NET_MINECRAFT_SERVER_PACKAGE + "EntityPlayer"); + (ENTITY_PLAYER_PING_FIELD = BukkitReflection.ENTITY_PLAYER_CLASS.getDeclaredField("ping")).setAccessible(true); + CRAFT_ITEM_STACK_CLASS = Class.forName(BukkitReflection.CRAFT_BUKKIT_PACKAGE + "inventory.CraftItemStack"); + (CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD = BukkitReflection.CRAFT_ITEM_STACK_CLASS.getDeclaredMethod("asNMSCopy", ItemStack.class)).setAccessible(true); + ENTITY_ITEM_STACK_CLASS = Class.forName(BukkitReflection.NET_MINECRAFT_SERVER_PACKAGE + "ItemStack"); + ENTITY_ITEM_STACK_GET_NAME = BukkitReflection.ENTITY_ITEM_STACK_CLASS.getDeclaredMethod("getName", (Class[])new Class[0]); + SPIGOT_CONFIG_CLASS = Class.forName("org.spigotmc.SpigotConfig"); + (SPIGOT_CONFIG_BUNGEE_FIELD = BukkitReflection.SPIGOT_CONFIG_CLASS.getDeclaredField("bungee")).setAccessible(true); + } + catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Failed to initialize Bukkit/NMS Reflection"); + } + } +} \ No newline at end of file diff --git a/src/main/java/me/joeleoli/fairfight/util/zoot/util/CC.java b/src/main/java/me/joeleoli/fairfight/util/zoot/util/CC.java new file mode 100644 index 0000000..9f6a069 --- /dev/null +++ b/src/main/java/me/joeleoli/fairfight/util/zoot/util/CC.java @@ -0,0 +1,85 @@ +package me.joeleoli.fairfight.util.zoot.util; + +import org.bukkit.ChatColor; + +import java.util.ArrayList; +import java.util.List; + +public class CC +{ + public static final String BLUE; + public static final String AQUA; + public static final String YELLOW; + public static final String RED; + public static final String GRAY; + public static final String GOLD; + public static final String GREEN; + public static final String WHITE; + public static final String BLACK; + public static final String BOLD; + public static final String ITALIC; + public static final String UNDER_LINE; + public static final String STRIKE_THROUGH; + public static final String RESET; + public static final String MAGIC; + public static final String DARK_BLUE; + public static final String DARK_AQUA; + public static final String DARK_GRAY; + public static final String DARK_GREEN; + public static final String DARK_PURPLE; + public static final String DARK_RED; + public static final String PINK; + public static final String MENU_BAR; + public static final String CHAT_BAR; + public static final String SB_BAR; + + public static String translate(String in) { + return ChatColor.translateAlternateColorCodes('&', in); + } + + public static List translate(List lines) { + List toReturn = new ArrayList<>(); + for (String line : lines) { + toReturn.add(ChatColor.translateAlternateColorCodes('&', line)); + } + return toReturn; + } + + public static List translate(String[] lines) { + List toReturn = new ArrayList<>(); + for (String line : lines) { + if (line != null) { + toReturn.add(ChatColor.translateAlternateColorCodes('&', line)); + } + } + return toReturn; + } + + static { + BLUE = ChatColor.BLUE.toString(); + AQUA = ChatColor.AQUA.toString(); + YELLOW = ChatColor.YELLOW.toString(); + RED = ChatColor.RED.toString(); + GRAY = ChatColor.GRAY.toString(); + GOLD = ChatColor.GOLD.toString(); + GREEN = ChatColor.GREEN.toString(); + WHITE = ChatColor.WHITE.toString(); + BLACK = ChatColor.BLACK.toString(); + BOLD = ChatColor.BOLD.toString(); + ITALIC = ChatColor.ITALIC.toString(); + UNDER_LINE = ChatColor.UNDERLINE.toString(); + STRIKE_THROUGH = ChatColor.STRIKETHROUGH.toString(); + RESET = ChatColor.RESET.toString(); + MAGIC = ChatColor.MAGIC.toString(); + DARK_BLUE = ChatColor.DARK_BLUE.toString(); + DARK_AQUA = ChatColor.DARK_AQUA.toString(); + DARK_GRAY = ChatColor.DARK_GRAY.toString(); + DARK_GREEN = ChatColor.DARK_GREEN.toString(); + DARK_PURPLE = ChatColor.DARK_PURPLE.toString(); + DARK_RED = ChatColor.DARK_RED.toString(); + PINK = ChatColor.LIGHT_PURPLE.toString(); + MENU_BAR = ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH.toString() + "------------------------"; + CHAT_BAR = ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH.toString() + "------------------------------------------------"; + SB_BAR = ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH.toString() + "----------------------"; + } +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..58dc4ed --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,19 @@ +# Placeholders: %player% +name: "&8[&6FairFight&8]" +ban-broadcast: +- '&8&m-------------------------------------' +- '' +- '&6FairFight &7has removed &e%player%' +- '&7From the &eMineXD Network.' +- '' +- '&8&m-------------------------------------' +ban-command: "ban %player% FairFight - Unfair Advantage" +mongo: + host: "127.0.0.1" + port: 27017 + database: "fairfight" + authentication: + enabled: false + username: "admin" + password: "dev" + database: "admin" diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..ce33b2f --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,8 @@ +name: FairFight +author: joeleoli +version: 1.0 +main: me.joeleoli.fairfight.FairFight +commands: + fairfight: + usage: + aliases: [ff] \ No newline at end of file