diff --git a/plugin.yml b/plugin.yml index f50365c6..b0645449 100644 --- a/plugin.yml +++ b/plugin.yml @@ -82,6 +82,8 @@ permissions: description: Allow a player to fight over bigger distances than usual nocheat.checks.fight.speed: description: Allow a player to attack faster than usual + nocheat.checks.fight.godmode: + description: Allow a player to not take damage by exploiting a design flaw in Minecraft nocheat.checks.inventory: description: Allow the player to bypass all inventory checks children: diff --git a/pom.xml b/pom.xml index 3392b2a5..9ebe1a46 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 cc.co.evenprime.bukkit NoCheat - 3.2.2 + 3.3.0 jar NoCheat diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/fight/DirectionCheck.java b/src/cc/co/evenprime/bukkit/nocheat/checks/fight/DirectionCheck.java index 91d679f0..16884982 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/fight/DirectionCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/fight/DirectionCheck.java @@ -80,6 +80,7 @@ public class DirectionCheck extends FightCheck { return cc.directionCheck; } + @Override public String getParameter(ParameterName wildcard, NoCheatPlayer player) { if(wildcard == ParameterName.VIOLATIONS) diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightCheckListener.java b/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightCheckListener.java index 9d4e21b8..3e970760 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightCheckListener.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightCheckListener.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -21,6 +22,8 @@ import cc.co.evenprime.bukkit.nocheat.config.Permissions; public class FightCheckListener implements Listener, EventManager { private final List checks; + + private final GodmodeCheck godmodeCheck; private final NoCheat plugin; public FightCheckListener(NoCheat plugin) { @@ -31,15 +34,18 @@ public class FightCheckListener implements Listener, EventManager { this.checks.add(new DirectionCheck(plugin)); this.checks.add(new ReachCheck(plugin)); + this.godmodeCheck = new GodmodeCheck(plugin); + this.plugin = plugin; } @EventHandler(priority = EventPriority.LOWEST) public void entityDamage(final EntityDamageEvent event) { + if(event.isCancelled() || !(event instanceof EntityDamageByEntityEvent)) return; - EntityDamageByEntityEvent e = (EntityDamageByEntityEvent) event; + final EntityDamageByEntityEvent e = (EntityDamageByEntityEvent) event; if(!(e.getDamager() instanceof Player)) { return; } @@ -51,6 +57,32 @@ public class FightCheckListener implements Listener, EventManager { } } + @EventHandler(priority = EventPriority.LOW) + public void entityDamageForGodmodeCheck(final EntityDamageEvent event) { + + if(event.isCancelled()) + return; + + final Entity entity = event.getEntity(); + if(!(entity instanceof Player) || entity.isDead()) { + return; + } + + NoCheatPlayer player = plugin.getPlayer((Player) entity); + FightConfig cc = FightCheck.getConfig(player.getConfigurationStore()); + + if(!godmodeCheck.isEnabled(cc) || player.hasPermission(godmodeCheck.getPermission())) { + return; + } + + FightData data = FightCheck.getData(player.getDataStore()); + boolean cancelled = godmodeCheck.check(plugin.getPlayer((Player) entity), data, cc); + if(cancelled) { + // Remove the invulnerability from the player + player.getPlayer().setNoDamageTicks(0); + } + } + private void normalDamage(final EntityDamageByEntityEvent event) { final Player damager = (Player) event.getDamager(); @@ -120,6 +152,8 @@ public class FightCheckListener implements Listener, EventManager { s.add("fight.reach"); if(f.speedCheck) s.add("fight.speed"); + if(f.godmodeCheck) + s.add("fight.godmode"); return s; } } diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightConfig.java b/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightConfig.java index 11e03860..c5dad2c8 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightConfig.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightConfig.java @@ -20,6 +20,8 @@ public class FightConfig implements ConfigItem { public final int speedAttackLimit; public final ActionList speedActions; public final boolean speedCheck; + public final boolean godmodeCheck; + public final ActionList godmodeActions; public final boolean damageChecks; @@ -39,6 +41,9 @@ public class FightConfig implements ConfigItem { speedActions = data.getActionList(ConfPaths.FIGHT_SPEED_ACTIONS); speedAttackLimit = data.getInt(ConfPaths.FIGHT_SPEED_ATTACKLIMIT); + godmodeCheck = data.getBoolean(ConfPaths.FIGHT_GODMODE_CHECK); + godmodeActions = data.getActionList(ConfPaths.FIGHT_GODMODE_ACTIONS); + damageChecks = directionCheck || noswingCheck || reachCheck || speedCheck; } } diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightData.java b/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightData.java index 99a16c0c..5cf0d38d 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightData.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/fight/FightData.java @@ -9,14 +9,19 @@ public class FightData implements DataItem { public double noswingVL; public double reachVL; public int speedVL; + public double godmodeVL; public long directionLastViolationTime; public long reachLastViolationTime; + public long godmodeLastDamageTime; + public int godmodeLastAge; + public int godmodeBuffer = 40; public Entity damagee; - public boolean armswung = true; - public boolean skipNext = false; + public boolean armswung = true; + public boolean skipNext = false; public long speedTime; public int speedAttackCount; + } diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/fight/GodmodeCheck.java b/src/cc/co/evenprime/bukkit/nocheat/checks/fight/GodmodeCheck.java new file mode 100644 index 00000000..3b584721 --- /dev/null +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/fight/GodmodeCheck.java @@ -0,0 +1,76 @@ +package cc.co.evenprime.bukkit.nocheat.checks.fight; + +import java.util.Locale; +import cc.co.evenprime.bukkit.nocheat.NoCheat; +import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer; +import cc.co.evenprime.bukkit.nocheat.actions.ParameterName; +import cc.co.evenprime.bukkit.nocheat.config.Permissions; +import cc.co.evenprime.bukkit.nocheat.data.Statistics; + +public class GodmodeCheck extends FightCheck { + + public GodmodeCheck(NoCheat plugin) { + super(plugin, "fight.godmode", Permissions.FIGHT_GODMODE); + } + + @Override + public boolean check(NoCheatPlayer player, FightData data, FightConfig cc) { + + boolean cancelled = false; + + long time = System.currentTimeMillis(); + // Check at most once a second + if(data.godmodeLastDamageTime + 1000 < time) { + data.godmodeLastDamageTime = time; + + // How old is the player now? + int age = player.getTicksLived(); + // How much older did he get? + int ageDiff = Math.max(0, age - data.godmodeLastAge); + // Is he invulnerable? + int nodamageTicks = player.getPlayer().getNoDamageTicks(); + + if(nodamageTicks > 0 && ageDiff < 15) { + // He is invulnerable and didn't age fast enough, that costs some points + data.godmodeBuffer -= (15 - ageDiff); + + // Still points left? + if(data.godmodeBuffer <= 0) { + // No + data.godmodeVL -= data.godmodeBuffer; + incrementStatistics(player, Statistics.Id.FI_GODMODE, -data.godmodeBuffer); + cancelled = executeActions(player, cc.godmodeActions.getActions(data.godmodeVL)); + } + } else { + // Give some new points, once a second + data.godmodeBuffer += 15; + data.godmodeVL *= 0.95; + } + + if(data.godmodeBuffer < 0) { + data.godmodeBuffer = 0; + } else if(data.godmodeBuffer > 40) { + data.godmodeBuffer = 40; + } + + // Start age counting from a new time + data.godmodeLastAge = age; + } + + return cancelled; + } + + @Override + public boolean isEnabled(FightConfig cc) { + return cc.godmodeCheck; + } + + @Override + public String getParameter(ParameterName wildcard, NoCheatPlayer player) { + + if(wildcard == ParameterName.VIOLATIONS) + return String.format(Locale.US, "%d", (int) getData(player.getDataStore()).godmodeVL); + else + return super.getParameter(wildcard, player); + } +} diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/moving/MovingCheckListener.java b/src/cc/co/evenprime/bukkit/nocheat/checks/moving/MovingCheckListener.java index e82f2ff6..f4e9e087 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/moving/MovingCheckListener.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/moving/MovingCheckListener.java @@ -102,6 +102,7 @@ public class MovingCheckListener implements Listener, EventManager { @EventHandler(priority = EventPriority.MONITOR) public void worldChange(final PlayerChangedWorldEvent event) { + // Maybe this helps with people teleporting through multiverse portals having problems? final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()).getDataStore()); data.teleportTo.reset(); data.clearRunFlyData(); diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/moving/MovingConfig.java b/src/cc/co/evenprime/bukkit/nocheat/checks/moving/MovingConfig.java index 6396e35e..6cf61144 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/moving/MovingConfig.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/moving/MovingConfig.java @@ -43,14 +43,19 @@ public class MovingConfig implements ConfigItem { identifyCreativeMode = data.getBoolean(ConfPaths.MOVING_RUNFLY_FLYING_ALLOWINCREATIVE); runflyCheck = data.getBoolean(ConfPaths.MOVING_RUNFLY_CHECK); - walkingSpeedLimit = ((double) 22) / 100D; - sprintingSpeedLimit = ((double) 35) / 100D; - jumpheight = ((double) 135) / 100D; - actions = data.getActionList(ConfPaths.MOVING_RUNFLY_ACTIONS); - swimmingSpeedLimit = ((double) 18) / 100D; + int walkspeed = data.getInt(ConfPaths.MOVING_RUNFLY_WALKSPEED, 100); + int sprintspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SPRINTSPEED, 100); + int swimspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SWIMSPEED, 100); + int sneakspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SNEAKSPEED, 100); + walkingSpeedLimit = ((double) 0.22 * walkspeed) / 100D; + sprintingSpeedLimit = ((double) 0.35 * sprintspeed) / 100D; + swimmingSpeedLimit = ((double) 0.18 * swimspeed) / 100D; + sneakingSpeedLimit = ((double) 0.14 * sneakspeed) / 100D; + jumpheight = ((double) 135) / 100D; + sneakingCheck = !data.getBoolean(ConfPaths.MOVING_RUNFLY_ALLOWFASTSNEAKING); - sneakingSpeedLimit = ((double) 14) / 100D; + actions = data.getActionList(ConfPaths.MOVING_RUNFLY_ACTIONS); allowFlying = data.getBoolean(ConfPaths.MOVING_RUNFLY_FLYING_ALLOWALWAYS); flyingSpeedLimitVertical = ((double) data.getInt(ConfPaths.MOVING_RUNFLY_FLYING_SPEEDLIMITVERTICAL)) / 100D; diff --git a/src/cc/co/evenprime/bukkit/nocheat/config/ConfPaths.java b/src/cc/co/evenprime/bukkit/nocheat/config/ConfPaths.java index f0f0c667..046ee84a 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/config/ConfPaths.java +++ b/src/cc/co/evenprime/bukkit/nocheat/config/ConfPaths.java @@ -38,6 +38,13 @@ public abstract class ConfPaths { private final static String MOVING_RUNFLY = MOVING + "runfly."; public final static String MOVING_RUNFLY_CHECK = MOVING_RUNFLY + "active"; + + // These four are not automatically shown in the config + public final static String MOVING_RUNFLY_WALKSPEED = MOVING_RUNFLY + "walkspeed"; + public final static String MOVING_RUNFLY_SNEAKSPEED = MOVING_RUNFLY + "sneakspeed"; + public final static String MOVING_RUNFLY_SWIMSPEED = MOVING_RUNFLY + "swimspeed"; + public final static String MOVING_RUNFLY_SPRINTSPEED = MOVING_RUNFLY + "sprintspeed"; + public final static String MOVING_RUNFLY_ALLOWFASTSNEAKING = MOVING_RUNFLY + "allowfastsneaking"; public final static String MOVING_RUNFLY_ACTIONS = MOVING_RUNFLY + "actions"; @@ -122,6 +129,10 @@ public abstract class ConfPaths { public final static String FIGHT_SPEED_ATTACKLIMIT = FIGHT_SPEED + "attacklimit"; public final static String FIGHT_SPEED_ACTIONS = FIGHT_SPEED + "actions"; + private final static String FIGHT_GODMODE = FIGHT + "godmode."; + public static final String FIGHT_GODMODE_CHECK = FIGHT_GODMODE + "active"; + public final static String FIGHT_GODMODE_ACTIONS = FIGHT_GODMODE + "actions"; + public final static String STRINGS = "strings"; } diff --git a/src/cc/co/evenprime/bukkit/nocheat/config/DefaultConfiguration.java b/src/cc/co/evenprime/bukkit/nocheat/config/DefaultConfiguration.java index fc13a5ae..b639953e 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/config/DefaultConfiguration.java +++ b/src/cc/co/evenprime/bukkit/nocheat/config/DefaultConfiguration.java @@ -107,6 +107,9 @@ public class DefaultConfiguration extends NoCheatConfiguration { set(ConfPaths.FIGHT_SPEED_CHECK, true); set(ConfPaths.FIGHT_SPEED_ATTACKLIMIT, 15); set(ConfPaths.FIGHT_SPEED_ACTIONS, "log:fspeed:0:5:if cancel"); + + set(ConfPaths.FIGHT_GODMODE_CHECK, true); + set(ConfPaths.FIGHT_GODMODE_ACTIONS, "log:fgod:2:5:if cancel"); set(ConfPaths.STRINGS + ".drop", "[player] failed [check]: Tried to drop more items than allowed. VL [violations]"); set(ConfPaths.STRINGS + ".moveshort", "[player] failed [check]. VL [violations]"); @@ -124,6 +127,7 @@ public class DefaultConfiguration extends NoCheatConfiguration { set(ConfPaths.STRINGS + ".freach", "[player] failed [check]: tried to attack entity out of reach. VL [violations]"); set(ConfPaths.STRINGS + ".fspeed", "[player] failed [check]: tried to attack more than [limit] times per second. VL [violations]"); set(ConfPaths.STRINGS + ".fnoswing", "[player] failed [check]: Didn't swing arm. VL [violations]"); + set(ConfPaths.STRINGS + ".fgod", "[player] failed [check]: Avoided taking damage or lagging. VL [violations]"); set(ConfPaths.STRINGS + ".ibow", "[player] failed [check]: Fires bow to fast. VL [violations]"); set(ConfPaths.STRINGS + ".ieat", "[player] failed [check]: Eats food [food] too fast. VL [violations]"); set(ConfPaths.STRINGS + ".kick", "kick [player]"); diff --git a/src/cc/co/evenprime/bukkit/nocheat/config/Permissions.java b/src/cc/co/evenprime/bukkit/nocheat/config/Permissions.java index d7e1b28c..230c8f56 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/config/Permissions.java +++ b/src/cc/co/evenprime/bukkit/nocheat/config/Permissions.java @@ -36,6 +36,7 @@ public class Permissions { public static final String FIGHT_NOSWING = FIGHT + ".noswing"; public static final String FIGHT_REACH = FIGHT + ".reach"; public static final String FIGHT_SPEED = FIGHT + ".speed"; + public static final String FIGHT_GODMODE = FIGHT + ".godmode"; public final static String ADMIN_CHATLOG = ADMIN + ".chatlog"; public static final String ADMIN_COMMANDS = ADMIN + ".commands"; diff --git a/src/cc/co/evenprime/bukkit/nocheat/data/Statistics.java b/src/cc/co/evenprime/bukkit/nocheat/data/Statistics.java index 6933bd73..1f9c987d 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/data/Statistics.java +++ b/src/cc/co/evenprime/bukkit/nocheat/data/Statistics.java @@ -18,7 +18,8 @@ public class Statistics { INV_BOW("inventory.instantbow"), INV_EAT("inventory.instanteat"), MOV_RUNNING("moving.running"), MOV_FLYING("moving.flying"), MOV_MOREPACKETS("moving.morepackets"), MOV_NOFALL("moving.nofall"), - MOV_SNEAKING("moving.sneaking"), MOV_SWIMMING("moving.swimming"); + MOV_SNEAKING("moving.sneaking"), MOV_SWIMMING("moving.swimming"), + FI_GODMODE("fight.godmode"); private final String name;