mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-10-06 10:27:26 +02:00
Attempt to fix issues with pvp and knockback.
Might disable for older versions of MC (checks.fight.pvp.knockbackvelocity).
This commit is contained in:
parent
ec997796b8
commit
3c8b255817
@ -111,6 +111,7 @@ public class FightConfig extends ACheckConfig {
|
||||
// Special flags:
|
||||
public final boolean yawRateCheck;
|
||||
public final boolean cancelDead;
|
||||
public final boolean knockBackVelocityPvP;
|
||||
|
||||
/**
|
||||
* Instantiates a new fight configuration.
|
||||
@ -176,6 +177,7 @@ public class FightConfig extends ACheckConfig {
|
||||
|
||||
yawRateCheck = data.getBoolean(ConfPaths.FIGHT_YAWRATE_CHECK, true);
|
||||
cancelDead = data.getBoolean(ConfPaths.FIGHT_CANCELDEAD);
|
||||
knockBackVelocityPvP = data.getBoolean(ConfPaths.FIGHT_PVP_KNOCKBACKVELOCITY);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
@ -3,6 +3,7 @@ package fr.neatmonster.nocheatplus.checks.fight;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -21,6 +22,7 @@ import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.event.player.PlayerToggleSprintEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import fr.neatmonster.nocheatplus.NCPAPIProvider;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckListener;
|
||||
@ -39,6 +41,7 @@ import fr.neatmonster.nocheatplus.components.JoinLeaveListener;
|
||||
import fr.neatmonster.nocheatplus.logging.Streams;
|
||||
import fr.neatmonster.nocheatplus.permissions.Permissions;
|
||||
import fr.neatmonster.nocheatplus.stats.Counters;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
import fr.neatmonster.nocheatplus.utilities.TickTask;
|
||||
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.build.BuildParameters;
|
||||
@ -233,7 +236,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
// TODO: Permission ?
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
|
||||
if (!cancelled) {
|
||||
final boolean reachEnabled = reach.isEnabled(player);
|
||||
final boolean directionEnabled = direction.isEnabled(player);
|
||||
@ -253,7 +256,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check angle with allowed window.
|
||||
if (angle.isEnabled(player)) {
|
||||
// TODO: Revise, use own trace.
|
||||
@ -321,7 +324,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Quick split-off: Checks using a location trace.
|
||||
* @param player
|
||||
@ -338,18 +341,18 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
* @return If to cancel (true) or not (false).
|
||||
*/
|
||||
private boolean locationTraceChecks(Player player, Location loc, FightData data, FightConfig cc, Entity damaged, Location damagedLoc, LocationTrace damagedTrace, long tick, boolean reachEnabled, boolean directionEnabled) {
|
||||
// TODO: Order / splitting off generic stuff.
|
||||
// TODO: Order / splitting off generic stuff.
|
||||
boolean cancelled = false;
|
||||
|
||||
|
||||
// (Might pass generic context to factories, for shared + heavy properties.)
|
||||
final SharedContext sharedContext = new SharedContext(damaged, mcAccess);
|
||||
final ReachContext reachContext = reachEnabled ? reach.getContext(player, loc, damaged, damagedLoc, data, cc, sharedContext) : null;
|
||||
final DirectionContext directionContext = directionEnabled ? direction.getContext(player, loc, damaged, damagedLoc, data, cc, sharedContext) : null;
|
||||
|
||||
|
||||
final long traceOldest = tick; // - damagedTrace.getMaxSize(); // TODO: Set by window.
|
||||
// TODO: Iterating direction, which, static/dynamic choice.
|
||||
final Iterator<TraceEntry> traceIt = damagedTrace.maxAgeIterator(traceOldest);
|
||||
|
||||
|
||||
boolean violation = true; // No tick with all checks passed.
|
||||
boolean reachPassed = !reachEnabled; // Passed individually for some tick.
|
||||
boolean directionPassed = !directionEnabled; // Passed individually for some tick.
|
||||
@ -399,7 +402,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
// TODO: Log exact state, probably record min/max latency (individually).
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if a player might return some damage due to the "thorns" enchantment.
|
||||
* @param player
|
||||
@ -431,10 +434,12 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
final FightData damagedData = damagedPlayer == null ? null : FightData.getData(damagedPlayer);
|
||||
final boolean damagedIsDead = damaged.isDead();
|
||||
if (damagedPlayer != null && !damagedIsDead) {
|
||||
if (!damagedPlayer.isDead() && godMode.isEnabled(damagedPlayer) && godMode.check(damagedPlayer, BridgeHealth.getDamage(event), damagedData)){
|
||||
// God mode check.
|
||||
if (godMode.isEnabled(damagedPlayer) && godMode.check(damagedPlayer, BridgeHealth.getDamage(event), damagedData)){
|
||||
// It requested to "cancel" the players invulnerability, so set their noDamageTicks to 0.
|
||||
damagedPlayer.setNoDamageTicks(0);
|
||||
}
|
||||
// Adjust buffer for fast heal checks.
|
||||
if (BridgeHealth.getHealth(damagedPlayer) >= BridgeHealth.getMaxHealth(damagedPlayer)){
|
||||
// TODO: Might use the same FightData instance for GodMode.
|
||||
if (damagedData.fastHealBuffer < 0){
|
||||
@ -500,16 +505,65 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
public void onEntityDamageMonitor(final EntityDamageEvent event) {
|
||||
final Entity damaged = event.getEntity();
|
||||
if (damaged instanceof Player){
|
||||
final Player player = (Player) damaged;
|
||||
final FightData data = FightData.getData(player);
|
||||
final int ndt = player.getNoDamageTicks();
|
||||
if (data.lastDamageTick == TickTask.getTick() && data.lastNoDamageTicks != ndt){
|
||||
final Player damagedPlayer = (Player) damaged;
|
||||
final FightData damagedData = FightData.getData(damagedPlayer);
|
||||
final int ndt = damagedPlayer.getNoDamageTicks();
|
||||
if (damagedData.lastDamageTick == TickTask.getTick() && damagedData.lastNoDamageTicks != ndt){
|
||||
// Plugin compatibility thing.
|
||||
data.lastNoDamageTicks = ndt;
|
||||
damagedData.lastNoDamageTicks = ndt;
|
||||
}
|
||||
// Knockback calculation.
|
||||
switch (event.getCause()) {
|
||||
case ENTITY_ATTACK:
|
||||
if (event instanceof EntityDamageByEntityEvent) {
|
||||
final Entity entity = ((EntityDamageByEntityEvent) event).getDamager();
|
||||
if ((entity instanceof Player) && FightConfig.getConfig(damagedPlayer).knockBackVelocityPvP) {
|
||||
checkKnockBack((Player) entity, damagedPlayer, damagedData);
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Knockback accounting: Add velocity.
|
||||
* @param attacker
|
||||
* @param damagedPlayer
|
||||
* @param damagedData
|
||||
*/
|
||||
private void checkKnockBack(final Player attacker, final Player damagedPlayer, final FightData damagedData) {
|
||||
double level = 1.0; // Assume "some knock-back" always.
|
||||
if (attacker.isSprinting()) {
|
||||
level += 1.0;
|
||||
}
|
||||
final ItemStack stack = attacker.getItemInHand();
|
||||
if (stack != null && stack.getType() != Material.AIR) {
|
||||
level += (double) stack.getEnchantmentLevel(Enchantment.KNOCKBACK);
|
||||
}
|
||||
if (level > 0.0) {
|
||||
final MovingData mdata = MovingData.getData(damagedPlayer);
|
||||
final MovingConfig mcc = MovingConfig.getConfig(damagedPlayer);
|
||||
// Cap the level to something reasonable. TODO: Config.
|
||||
level = Math.min(20.0, level);
|
||||
// TODO: How is the direction really calculated?
|
||||
final Vector dir = attacker.getLocation(useLoc1).getDirection().multiply(0.5 * level);
|
||||
|
||||
double vy = dir.getY();
|
||||
if (BlockProperties.isOnGround(damagedPlayer, damagedPlayer.getLocation(useLoc1), mcc.yOnGround)) {
|
||||
// (Re-used useLoc1 without need for cleanup.)
|
||||
vy = 0.365;
|
||||
}
|
||||
useLoc1.setWorld(null); // Cleanup.
|
||||
if (damagedData.debug || mdata.debug) {
|
||||
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, damagedPlayer.getName() + " received knockback level: " + level);
|
||||
}
|
||||
MovingListener.addVelocity(damagedPlayer, mdata, mcc, dir.getX(), vy, dir.getZ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* We listen to death events to prevent a very specific method of doing godmode.
|
||||
*
|
||||
|
@ -1010,57 +1010,64 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
* @param event
|
||||
* the event
|
||||
*/
|
||||
@EventHandler(
|
||||
ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onPlayerVelocity(final PlayerVelocityEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final MovingData data = MovingData.getData(player);
|
||||
// Ignore velocity if inside of vehicles.
|
||||
// Ignore players who are in vehicles.
|
||||
if (player.isInsideVehicle()) {
|
||||
data.removeAllVelocity();
|
||||
return;
|
||||
}
|
||||
// Process velocity.
|
||||
final Vector velocity = event.getVelocity();
|
||||
final MovingConfig cc = MovingConfig.getConfig(player);
|
||||
addVelocity(player, data, cc, velocity.getX(), velocity.getY(), velocity.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add velocity to internal book-keeping.
|
||||
* @param player
|
||||
* @param data
|
||||
* @param cc
|
||||
* @param vx
|
||||
* @param vy
|
||||
* @param vz
|
||||
*/
|
||||
public static void addVelocity(final Player player, final MovingData data, final MovingConfig cc, final double vx, final double vy, final double vz) {
|
||||
|
||||
final int tick = TickTask.getTick();
|
||||
data.removeInvalidVelocity(tick - cc.velocityActivationTicks);
|
||||
|
||||
|
||||
final Vector velocity = event.getVelocity();
|
||||
|
||||
if (data.debug) {
|
||||
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, event.getPlayer().getName() + " new velocity: " + velocity);
|
||||
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, player.getName() + " new velocity: " + vx + ", " + vy + ", " + vz);
|
||||
}
|
||||
|
||||
double newVal = velocity.getY();
|
||||
boolean used = false;
|
||||
if (newVal >= 0D) { // TODO: Just >, not >=.
|
||||
if (vy > 0D) {
|
||||
used = true;
|
||||
if (data.verticalFreedom <= 0.001 && data.verticalVelocityCounter >= 0) {
|
||||
data.verticalVelocity = 0;
|
||||
}
|
||||
data.verticalVelocity += newVal;
|
||||
data.verticalVelocity += vy;
|
||||
data.verticalFreedom += data.verticalVelocity;
|
||||
data.verticalVelocityCounter = Math.min(100, Math.max(data.verticalVelocityCounter, cc.velocityGraceTicks ) + 1 + (int) Math.round(newVal * 10.0)); // 50;
|
||||
data.verticalVelocityCounter = Math.min(100, Math.max(data.verticalVelocityCounter, cc.velocityGraceTicks ) + 1 + (int) Math.round(vy * 10.0)); // 50;
|
||||
data.verticalVelocityUsed = 0;
|
||||
}
|
||||
|
||||
newVal = Math.sqrt(velocity.getX() * velocity.getX() + velocity.getZ() * velocity.getZ());
|
||||
if (newVal > 0D) {
|
||||
|
||||
if (vx != 0.0 && vz != 0.0) {
|
||||
final double newVal = Math.sqrt(vx * vx + vz * vz);
|
||||
used = true;
|
||||
final Velocity vel = new Velocity(tick, newVal, cc.velocityActivationCounter, Math.max(20, 1 + (int) Math.round(newVal * 10.0)));
|
||||
data.addHorizontalVelocity(vel);
|
||||
// data.horizontalFreedom += newVal;
|
||||
// data.horizontalVelocityCounter = Math.min(100, Math.max(data.horizontalVelocityCounter, cc.velocityGraceTicks ) + 1 + (int) Math.round(newVal * 10.0)); // 30;
|
||||
// data.horizontalVelocityUsed = 0;
|
||||
}
|
||||
|
||||
// Set dirty flag here.
|
||||
if (used) {
|
||||
data.sfDirty = true;
|
||||
data.sfDirty = true; // TODO: Only needed for vertical velocity? Get rid anyway :p.
|
||||
data.sfNoLowJump = true;
|
||||
}
|
||||
|
||||
// TODO: clear accounting here ?
|
||||
}
|
||||
|
||||
@ -1281,7 +1288,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
* @param cc
|
||||
*/
|
||||
private void dataOnJoin(Player player, Location loc, MovingData data, MovingConfig cc) {
|
||||
|
||||
|
||||
final int tick = TickTask.getTick();
|
||||
// Check loaded chunks.
|
||||
if (cc.loadChunksOnJoin) {
|
||||
@ -1291,7 +1298,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
StaticLog.logInfo("[NoCheatPlus] Player join: Loaded " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + loc.getWorld().getName() + " for player: " + player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Correct set-back on join.
|
||||
if (!data.hasSetBack() || data.hasSetBackWorldChanged(loc)) {
|
||||
data.clearFlyData();
|
||||
@ -1304,7 +1311,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
// TODO: If to reset positions: relate to previous ones and set-back.
|
||||
data.resetPositions(loc); // TODO: See above.
|
||||
}
|
||||
|
||||
|
||||
// Always reset position to this one.
|
||||
// TODO: more fine grained reset?
|
||||
data.clearMorePacketsData();
|
||||
|
@ -376,7 +376,9 @@ public abstract class ConfPaths {
|
||||
public static final String FIGHT = CHECKS + "fight.";
|
||||
|
||||
public static final String FIGHT_CANCELDEAD = FIGHT + "canceldead";
|
||||
public static final String FIGHT_TOOLCHANGEPENALTY = FIGHT + "toolchangepenalty";
|
||||
public static final String FIGHT_TOOLCHANGEPENALTY = FIGHT + "toolchangepenalty";
|
||||
private static final String FIGHT_PVP = FIGHT + "pvp.";
|
||||
public static final String FIGHT_PVP_KNOCKBACKVELOCITY = FIGHT_PVP + "knockbackvelocity";
|
||||
|
||||
private static final String FIGHT_ANGLE = FIGHT + "angle.";
|
||||
public static final String FIGHT_ANGLE_CHECK = FIGHT_ANGLE + "active";
|
||||
@ -645,5 +647,4 @@ public abstract class ConfPaths {
|
||||
@Deprecated
|
||||
public static final String BLOCKBREAK_FASTBREAK_DEBUG = "checks.blockbreak.fastbreak.debug";
|
||||
|
||||
|
||||
}
|
||||
|
@ -262,6 +262,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
// FIGHT
|
||||
set(ConfPaths.FIGHT_CANCELDEAD, true);
|
||||
set(ConfPaths.FIGHT_TOOLCHANGEPENALTY, 500L);
|
||||
set(ConfPaths.FIGHT_PVP_KNOCKBACKVELOCITY, true);
|
||||
|
||||
set(ConfPaths.FIGHT_YAWRATE_CHECK, true);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user