mirror of
https://github.com/Updated-NoCheatPlus/NoCheatPlus.git
synced 2026-11-08 09:35:18 -05:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
009c8d00c6 | ||
|
|
aee5ed158e |
No files matched your search
@@ -76,10 +76,12 @@ public enum CheckType {
|
||||
FIGHT_DIRECTION(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_DIRECTION),
|
||||
FIGHT_FASTHEAL(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_FASTHEAL),
|
||||
FIGHT_GODMODE(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_GODMODE),
|
||||
FIGHT_HITBOX(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_DIRECTION),
|
||||
FIGHT_NOSWING(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_NOSWING),
|
||||
FIGHT_REACH(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_REACH),
|
||||
FIGHT_SELFHIT(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_SELFHIT),
|
||||
FIGHT_SPEED(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_SPEED),
|
||||
FIGHT_VISIBLE(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_VISIBLE),
|
||||
FIGHT_WRONGTURN(CheckTypeType.CHECK, FIGHT, null),
|
||||
|
||||
INVENTORY(CheckTypeType.GROUP, CheckType.ALL, Permissions.INVENTORY),
|
||||
|
||||
@@ -86,12 +86,17 @@ public class FightConfig extends ACheckConfig {
|
||||
public final float speedImprobableWeight;
|
||||
public final ActionList speedActions;
|
||||
|
||||
public final ActionList visibleActions;
|
||||
|
||||
public final double hitBoxHorizontalExpansion;
|
||||
public final double hitBoxVerticalExpansion;
|
||||
|
||||
// Special flags:
|
||||
public final boolean cancelDead;
|
||||
public final boolean knockBackVelocityPvP;
|
||||
|
||||
/** Maximum latency counted in ticks for the loop checks (reach, direction). */
|
||||
public final long loopMaxLatencyTicks; // TODO: Configurable, sections for players and entities.
|
||||
/** Maximum latency counted in ms for the loop checks (reach, direction). */
|
||||
public final int loopMaxLatencyMs; // TODO: Configurable, sections for players and entities.
|
||||
|
||||
/**
|
||||
* Instantiates a new fight configuration.
|
||||
@@ -147,7 +152,10 @@ public class FightConfig extends ACheckConfig {
|
||||
|
||||
noSwingActions = config.getOptimizedActionList(ConfPaths.FIGHT_NOSWING_ACTIONS, Permissions.FIGHT_NOSWING);
|
||||
|
||||
reachSurvivalDistance = config.getDouble(ConfPaths.FIGHT_REACH_SURVIVALDISTANCE, 3.5, 6.0, 4.4);
|
||||
hitBoxHorizontalExpansion = config.getDouble(ConfPaths.FIGHT_HITBOX_HORIZONTAL_EXPAND, 0.125);
|
||||
hitBoxVerticalExpansion = config.getDouble(ConfPaths.FIGHT_HITBOX_VERTICAL_EXPAND, 0.125);
|
||||
|
||||
reachSurvivalDistance = config.getDouble(ConfPaths.FIGHT_REACH_SURVIVALDISTANCE, 3.0, 6.0, 4.4);
|
||||
reachPenalty = config.getLong(ConfPaths.FIGHT_REACH_PENALTY);
|
||||
reachPrecision = config.getBoolean(ConfPaths.FIGHT_REACH_PRECISION);
|
||||
reachReduce = config.getBoolean(ConfPaths.FIGHT_REACH_REDUCE);
|
||||
@@ -169,8 +177,10 @@ public class FightConfig extends ACheckConfig {
|
||||
speedImprobableWeight = (float) config.getDouble(ConfPaths.FIGHT_SPEED_IMPROBABLE_WEIGHT);
|
||||
speedActions = config.getOptimizedActionList(ConfPaths.FIGHT_SPEED_ACTIONS, Permissions.FIGHT_SPEED);
|
||||
|
||||
visibleActions = config.getOptimizedActionList(ConfPaths.FIGHT_VISIBLE_ACTIONS, Permissions.FIGHT_VISIBLE);
|
||||
|
||||
cancelDead = config.getBoolean(ConfPaths.FIGHT_CANCELDEAD);
|
||||
loopMaxLatencyTicks = config.getInt(ConfPaths.FIGHT_MAXLOOPLETENCYTICKS, 1, 15, 8);
|
||||
loopMaxLatencyMs = config.getInt(ConfPaths.FIGHT_MAXLOOPLETENCYMS, 500);
|
||||
AlmostBoolean ref = config.getAlmostBoolean(ConfPaths.FIGHT_PVP_KNOCKBACKVELOCITY, AlmostBoolean.MAYBE);
|
||||
knockBackVelocityPvP = ref == AlmostBoolean.MAYBE ? Bugs.shouldPvpKnockBackVelocity() : ref.decide();
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ public class FightData extends ACheckData implements IDataOnRemoveSubCheckData,
|
||||
public double noSwingVL;
|
||||
public double reachVL;
|
||||
public double speedVL;
|
||||
public double visibleVL;
|
||||
|
||||
// Shared
|
||||
public String lastWorld = "";
|
||||
@@ -127,6 +128,14 @@ public class FightData extends ACheckData implements IDataOnRemoveSubCheckData,
|
||||
for (final CheckType checkType : checkTypes) {
|
||||
switch(checkType) {
|
||||
// TODO: case FIGHT: ...
|
||||
case FIGHT_HITBOX:
|
||||
directionVL = 0;
|
||||
visibleVL = 0;
|
||||
reachVL = 0;
|
||||
break;
|
||||
case FIGHT_VISIBLE:
|
||||
visibleVL = 0;
|
||||
break;
|
||||
case FIGHT_DIRECTION:
|
||||
directionVL = 0;
|
||||
break;
|
||||
|
||||
@@ -51,8 +51,6 @@ import fr.neatmonster.nocheatplus.checks.moving.player.UnusedVelocity;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.util.AuxMoving;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.velocity.VelocityFlags;
|
||||
import fr.neatmonster.nocheatplus.checks.net.NetConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.net.NetData;
|
||||
import fr.neatmonster.nocheatplus.compat.Bridge1_9;
|
||||
import fr.neatmonster.nocheatplus.compat.BridgeEnchant;
|
||||
import fr.neatmonster.nocheatplus.compat.BridgeHealth;
|
||||
@@ -100,6 +98,9 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
/** The god mode check. */
|
||||
private final GodMode godMode = addCheck(new GodMode());
|
||||
|
||||
/** THe hit box check. */
|
||||
private final HitBox hitBox = addCheck(new HitBox());
|
||||
|
||||
/** The no swing check. */
|
||||
private final NoSwing noSwing = addCheck(new NoSwing());
|
||||
|
||||
@@ -112,6 +113,9 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
/** The speed check. */
|
||||
private final Speed speed = addCheck(new Speed());
|
||||
|
||||
/** The visible check. */
|
||||
private final Visible visible = addCheck(new Visible());
|
||||
|
||||
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
|
||||
private final Location useLoc1 = new Location(null, 0, 0, 0);
|
||||
|
||||
@@ -249,7 +253,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
// TODO: Problem with NPCs: data stays (not a big problem).
|
||||
// (This is done even if the event has already been cancelled, to keep track, if the player is on a horse.)
|
||||
damagedTrace = DataManager.getPlayerData(damagedPlayer).getGenericInstance(MovingData.class)
|
||||
.updateTrace(damagedPlayer, damagedLoc, tick, damagedIsFake ? null : mcAccess.getHandle()); //.getTrace(damagedPlayer);
|
||||
.updateTrace(damagedPlayer, damagedLoc, now, damagedIsFake ? null : mcAccess.getHandle()); //.getTrace(damagedPlayer);
|
||||
}
|
||||
else {
|
||||
damagedPlayer = null; // TODO: This is a temporary workaround.
|
||||
@@ -364,22 +368,31 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
if (!cancelled) {
|
||||
final boolean reachEnabled = reach.isEnabled(player, pData);
|
||||
final boolean directionEnabled = direction.isEnabled(player, pData) && mData.timeRiptiding + 3000 < now;
|
||||
if (reachEnabled || directionEnabled) {
|
||||
final boolean visibleEnabled = visible.isEnabled(player, pData);
|
||||
final boolean hitboxEnabled = hitBox.isEnabled(player, pData);
|
||||
if (reachEnabled || directionEnabled || visibleEnabled) {
|
||||
if (damagedTrace != null) {
|
||||
// Checks that use the LocationTrace instance of the attacked entity/player.
|
||||
cancelled = locationTraceChecks(player, loc, data, cc, pData,
|
||||
damaged, damagedIsFake, damagedLoc, damagedTrace, tick, now, debug,
|
||||
reachEnabled, directionEnabled);
|
||||
reachEnabled, directionEnabled, visibleEnabled, hitboxEnabled);
|
||||
}
|
||||
else {
|
||||
// Still use the classic methods for non-players. maybe[]
|
||||
if (reachEnabled && reach.check(player, loc, damaged, damagedIsFake, damagedLoc,
|
||||
data, cc, pData)) {
|
||||
cancelled = true;
|
||||
}
|
||||
if (directionEnabled && hitboxEnabled) {
|
||||
if (hitBox.check(player, loc, damaged, damagedIsFake, damagedLoc, data, cc, pData,
|
||||
reachEnabled, visibleEnabled)) {
|
||||
cancelled = true;
|
||||
}
|
||||
} else {
|
||||
if (reachEnabled && reach.check(player, loc, damaged, damagedIsFake, damagedLoc,
|
||||
data, cc, pData)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
if (directionEnabled && direction.check(player, loc, damaged, damagedIsFake, damagedLoc, data, cc)) {
|
||||
cancelled = true;
|
||||
if (directionEnabled && direction.check(player, loc, damaged, damagedIsFake, damagedLoc, data, cc)) {
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -473,6 +486,8 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
* @param tick
|
||||
* @param reachEnabled
|
||||
* @param directionEnabled
|
||||
* @param hitboxEnabled
|
||||
* @param visibleEnabled
|
||||
* @return If to cancel (true) or not (false).
|
||||
*/
|
||||
private boolean locationTraceChecks(final Player player, final Location loc,
|
||||
@@ -480,7 +495,8 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
final Entity damaged, final boolean damagedIsFake,
|
||||
final Location damagedLoc, LocationTrace damagedTrace,
|
||||
final long tick, final long now, final boolean debug,
|
||||
final boolean reachEnabled, final boolean directionEnabled) {
|
||||
final boolean reachEnabled, final boolean directionEnabled,
|
||||
final boolean visibleEnabled, final boolean hitboxEnabled) {
|
||||
// TODO: Order / splitting off generic stuff.
|
||||
/*
|
||||
* TODO: Abstract: interface with common setup/loop/post routine, only
|
||||
@@ -493,8 +509,9 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
// (Might pass generic context to factories, for shared + heavy properties.)
|
||||
final ReachContext reachContext = reachEnabled ? reach.getContext(player, loc, damaged, damagedLoc, data, cc) : null;
|
||||
final DirectionContext directionContext = directionEnabled ? direction.getContext(player, loc, damaged, damagedIsFake, damagedLoc, data, cc) : null;
|
||||
final VisibleContext visibleContext = visibleEnabled ? visible.getContext(player, loc, damaged, damagedLoc, data, cc) : null;
|
||||
|
||||
final long traceOldest = tick - cc.loopMaxLatencyTicks; // TODO: Set by latency-window.
|
||||
final long traceOldest = now - cc.loopMaxLatencyMs; // TODO: Set by latency-window.
|
||||
// TODO: Iterating direction, which, static/dynamic choice.
|
||||
final Iterator<ITraceEntry> traceIt = damagedTrace.maxAgeIterator(traceOldest);
|
||||
|
||||
@@ -510,23 +527,32 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
// Simplistic just check both until end or hit.
|
||||
// TODO: Other default distances/tolerances.
|
||||
boolean thisPassed = true;
|
||||
if (reachEnabled) {
|
||||
if (reach.loopCheck(player, loc, damaged, entry, reachContext, data, cc)) {
|
||||
if (directionEnabled && hitboxEnabled) {
|
||||
if (hitBox.loopCheck(player, loc, entry,
|
||||
directionContext, reachContext, visibleContext, data, cc,
|
||||
directionEnabled, reachEnabled, visibleEnabled)) {
|
||||
thisPassed = false;
|
||||
}
|
||||
else {
|
||||
reachPassed = true;
|
||||
}
|
||||
}
|
||||
// TODO: Efficiency: don't check at all, if strict and !thisPassed.
|
||||
if (directionEnabled && (reachPassed || !directionPassed)) {
|
||||
if (direction.loopCheck(player, loc, damaged, entry, directionContext, data, cc)) {
|
||||
thisPassed = false;
|
||||
}
|
||||
else {
|
||||
directionPassed = true;
|
||||
} else {
|
||||
if (reachEnabled) {
|
||||
if (reach.loopCheck(player, loc, damaged, entry, reachContext, data, cc)) {
|
||||
thisPassed = false;
|
||||
}
|
||||
else {
|
||||
reachPassed = true;
|
||||
}
|
||||
}
|
||||
// TODO: Efficiency: don't check at all, if strict and !thisPassed.
|
||||
if (directionEnabled && (reachPassed || !directionPassed)) {
|
||||
if (direction.loopCheck(player, loc, damaged, entry, directionContext, data, cc)) {
|
||||
thisPassed = false;
|
||||
}
|
||||
else {
|
||||
directionPassed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thisPassed) {
|
||||
// TODO: Log/set estimated latency.
|
||||
violation = false;
|
||||
@@ -535,20 +561,29 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// TODO: How to treat mixed state: violation && reachPassed && directionPassed [current: use min violation // thinkable: silent cancel, if actions have cancel (!)]
|
||||
// TODO: Adapt according to strictness settings?
|
||||
// TODO: violation vs. reachPassed + directionPassed (current: fail one = fail all).
|
||||
if (reachEnabled) {
|
||||
// TODO: Might ignore if already cancelled by mixed/silent cancel.
|
||||
if (reach.loopFinish(player, loc, damaged, reachContext, successEntry, violation,
|
||||
data, cc, pData)) {
|
||||
if (directionEnabled && hitboxEnabled) {
|
||||
if (hitBox.loopFinish(player, loc, damaged,
|
||||
reachContext, directionContext, visibleContext,
|
||||
successEntry, violation, data, cc,
|
||||
reachEnabled, visibleEnabled, pData)) {
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
if (directionEnabled) {
|
||||
// TODO: Might ignore if already cancelled.
|
||||
if (direction.loopFinish(player, loc, damaged, directionContext, violation, data, cc)) {
|
||||
cancelled = true;
|
||||
} else {
|
||||
// TODO: How to treat mixed state: violation && reachPassed && directionPassed [current: use min violation // thinkable: silent cancel, if actions have cancel (!)]
|
||||
// TODO: Adapt according to strictness settings?
|
||||
// TODO: violation vs. reachPassed + directionPassed (current: fail one = fail all).
|
||||
if (reachEnabled) {
|
||||
// TODO: Might ignore if already cancelled by mixed/silent cancel.
|
||||
if (reach.loopFinish(player, loc, damaged, reachContext, successEntry, violation,
|
||||
data, cc, pData)) {
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
if (directionEnabled) {
|
||||
// TODO: Might ignore if already cancelled.
|
||||
if (direction.loopFinish(player, loc, damaged, directionContext, violation, data, cc)) {
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Log exact state, probably record min/max latency (individually).
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.checks.fight;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.ViolationData;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.location.tracking.LocationTrace.ITraceEntry;
|
||||
import fr.neatmonster.nocheatplus.players.IPlayerData;
|
||||
import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.CollideRayVsAABB;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.ICollideRayVsAABB;
|
||||
import fr.neatmonster.nocheatplus.utilities.collision.PassableRayTracing;
|
||||
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.WrapBlockCache;
|
||||
|
||||
public class HitBox extends Check {
|
||||
private final ICollideRayVsAABB boulder = new CollideRayVsAABB();
|
||||
private final PassableRayTracing rayTracing = new PassableRayTracing();
|
||||
private final WrapBlockCache wrapBlockCache;
|
||||
|
||||
public HitBox() {
|
||||
super(CheckType.FIGHT_HITBOX);
|
||||
wrapBlockCache = new WrapBlockCache();
|
||||
rayTracing.setMaxSteps(30);
|
||||
}
|
||||
|
||||
public boolean check(final Player player, final Location pLoc,
|
||||
final Entity damaged, final boolean damagedIsFake, final Location dRef,
|
||||
final FightData data, final FightConfig cc, final IPlayerData pData,
|
||||
final boolean reachEnabled, final boolean visibleEnabled) {
|
||||
boolean cancel = false;
|
||||
final double eyeYLocation = pLoc.getY() + player.getEyeHeight() - (player.isSneaking() ? 0.08 : 0.0);
|
||||
final double distanceLimit = cc.reachSurvivalDistance + (player.getGameMode() == GameMode.CREATIVE ? 2.0 : 0.0);
|
||||
final double height = damagedIsFake ? (damaged instanceof LivingEntity ? ((LivingEntity) damaged).getEyeHeight() : 1.75) : mcAccess.getHandle().getHeight(damaged);
|
||||
final double width = damagedIsFake ? 0.6 : mcAccess.getHandle().getWidth(damaged) / 2;
|
||||
final Vector direction = pLoc.getDirection();
|
||||
final BlockCache blockCache = wrapBlockCache.getBlockCache();
|
||||
blockCache.setAccess(pLoc.getWorld());
|
||||
|
||||
boulder.setFindNearestPointIfNotCollide(false)
|
||||
.setRay(pLoc.getX(), eyeYLocation, pLoc.getZ(), direction.getX(), direction.getY(), direction.getZ())
|
||||
.setAABB(dRef.getX(), dRef.getY(), dRef.getZ(), width + cc.hitBoxHorizontalExpansion, height + cc.hitBoxVerticalExpansion)
|
||||
.loop();
|
||||
|
||||
if (boulder.collides()) {
|
||||
// Direction passed
|
||||
data.directionVL *= 0.8D;
|
||||
// Checking distance
|
||||
final double distance = TrigUtil.distance(boulder.getX(), boulder.getY(), boulder.getZ(),
|
||||
pLoc.getX(), eyeYLocation, pLoc.getZ());
|
||||
if (reachEnabled) {
|
||||
if (distance > distanceLimit) {
|
||||
final ViolationData vd = new ViolationData(this, player, data.reachVL, distance - distanceLimit, cc.reachActions);
|
||||
vd.setParameter(ParameterName.REACH_DISTANCE, StringUtil.fdec3.format(distance));
|
||||
cancel = executeActions(vd).willCancel();
|
||||
} else {
|
||||
data.reachVL *= 0.8D;
|
||||
}
|
||||
}
|
||||
|
||||
// Checking visible
|
||||
if (visibleEnabled && !cancel) {
|
||||
rayTracing.setBlockCache(blockCache);
|
||||
rayTracing.setIgnoreInitiallyColliding(true);
|
||||
rayTracing.set(pLoc.getX(), eyeYLocation, pLoc.getZ(), boulder.getX(), boulder.getY(), boulder.getZ());
|
||||
rayTracing.loop();
|
||||
|
||||
if (rayTracing.collides()) {
|
||||
data.visibleVL++;
|
||||
cancel = executeActions(player, data.visibleVL, 1.0, cc.visibleActions).willCancel();
|
||||
} else {
|
||||
data.visibleVL *= 0.8D;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Direction failed. Skipping distance, visible check
|
||||
final Vector blockEyes = new Vector(dRef.getX() - pLoc.getX(), dRef.getY() + height / 2D - eyeYLocation, dRef.getZ() - pLoc.getZ());
|
||||
final double distance = blockEyes.crossProduct(direction).length() / direction.length();
|
||||
data.directionVL += distance;
|
||||
cancel = executeActions(player, data.directionVL, distance, cc.directionActions).willCancel();
|
||||
if (cancel) {
|
||||
// Deal an attack penalty time.
|
||||
data.attackPenalty.applyPenalty(cc.directionPenalty);
|
||||
}
|
||||
}
|
||||
rayTracing.cleanup();
|
||||
blockCache.cleanup();
|
||||
return cancel;
|
||||
}
|
||||
|
||||
public boolean loopCheck(final Player player, final Location loc, final ITraceEntry dLoc,
|
||||
final DirectionContext dirContext, final ReachContext reachContext, final VisibleContext visibleContext,
|
||||
final FightData data, final FightConfig cc,
|
||||
final boolean directionEnabled, final boolean reachEnabled, final boolean visibleEnabled) {
|
||||
boolean cancel = false;
|
||||
final double eyeYLocation = loc.getY() + player.getEyeHeight() - (player.isSneaking() ? 0.08 : 0.0);
|
||||
final double distanceLimit = cc.reachSurvivalDistance + (player.getGameMode() == GameMode.CREATIVE ? 2.0 : 0.0);
|
||||
if (reachEnabled) reachContext.distanceLimit = distanceLimit;
|
||||
|
||||
boulder.setFindNearestPointIfNotCollide(false)
|
||||
.setRay(loc.getX(), eyeYLocation, loc.getZ(),
|
||||
dirContext.direction.getX(), dirContext.direction.getY(), dirContext.direction.getZ())
|
||||
.setAABB(dLoc.getX(), dLoc.getY(), dLoc.getZ(),
|
||||
dLoc.getBoxMarginHorizontal() + cc.hitBoxHorizontalExpansion, dLoc.getBoxMarginVertical() + cc.hitBoxVerticalExpansion)
|
||||
.loop();
|
||||
|
||||
if (boulder.collides()) {
|
||||
// Direction passed
|
||||
// Checking distance
|
||||
final double distance = TrigUtil.distance(boulder.getX(), boulder.getY(), boulder.getZ(),
|
||||
loc.getX(), eyeYLocation, loc.getZ());
|
||||
if (reachEnabled) {
|
||||
if (distance > distanceLimit) {
|
||||
reachContext.minViolation = Math.min(reachContext.minViolation, distance);
|
||||
cancel = true;
|
||||
}
|
||||
reachContext.minResult = Math.min(reachContext.minResult, distance);
|
||||
}
|
||||
|
||||
// Checking visible
|
||||
if (visibleEnabled && !cancel) {
|
||||
rayTracing.setBlockCache(visibleContext.cache);
|
||||
rayTracing.setIgnoreInitiallyColliding(true);
|
||||
rayTracing.set(loc.getX(), eyeYLocation, loc.getZ(), boulder.getX(), boulder.getY(), boulder.getZ());
|
||||
rayTracing.loop();
|
||||
|
||||
if (rayTracing.collides()) {
|
||||
visibleContext.collided = true;
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Direction failed. Skipping distance, visible check
|
||||
final Vector blockEyes = new Vector(dLoc.getX() - loc.getX(), dLoc.getY() + dLoc.getBoxMarginVertical() / 2D - eyeYLocation, dLoc.getZ() - loc.getZ());
|
||||
final double distance = blockEyes.crossProduct(dirContext.direction).length() / dirContext.lengthDirection;
|
||||
dirContext.minViolation = Math.min(dirContext.minViolation, distance);
|
||||
cancel = true;
|
||||
}
|
||||
rayTracing.cleanup();
|
||||
return cancel;
|
||||
}
|
||||
|
||||
public boolean loopFinish(final Player player, final Location pLoc, final Entity damaged,
|
||||
final ReachContext reachContext, final DirectionContext dirContext, final VisibleContext visibleContext,
|
||||
final ITraceEntry traceEntry, final boolean forceViolation,
|
||||
final FightData data, final FightConfig cc, final boolean reachEnabled, final boolean visibleEnabled, final IPlayerData pData) {
|
||||
boolean cancel = false;
|
||||
final double distance = reachEnabled ? forceViolation && reachContext.minViolation != Double.MAX_VALUE ? reachContext.minViolation : reachContext.minResult : Double.MAX_VALUE;
|
||||
final double off = forceViolation && dirContext.minViolation != Double.MAX_VALUE ? dirContext.minViolation : dirContext.minResult;
|
||||
final boolean collided = visibleEnabled ? forceViolation && visibleContext.collided : false;
|
||||
if (visibleEnabled) visibleContext.cache.cleanup();
|
||||
|
||||
// Direction violation
|
||||
if (off != Double.MAX_VALUE && off > 0) {
|
||||
data.directionVL += off;
|
||||
cancel = executeActions(player, data.directionVL, off, cc.directionActions).willCancel();
|
||||
if (cancel) {
|
||||
// Deal an attack penalty time.
|
||||
data.attackPenalty.applyPenalty(cc.directionPenalty);
|
||||
return cancel;
|
||||
}
|
||||
} else {
|
||||
// Reward the player by lowering their violation level.
|
||||
data.directionVL *= 0.8D;
|
||||
}
|
||||
|
||||
// Reach violation
|
||||
if (distance != Double.MAX_VALUE && distance > reachContext.distanceLimit) {
|
||||
data.reachVL += distance - reachContext.distanceLimit;
|
||||
final ViolationData vd = new ViolationData(this, player, data.reachVL, distance - reachContext.distanceLimit, cc.reachActions);
|
||||
vd.setParameter(ParameterName.REACH_DISTANCE, StringUtil.fdec3.format(distance));
|
||||
cancel = executeActions(vd).willCancel();
|
||||
if (cancel) {
|
||||
// Apply an attack penalty time.
|
||||
data.attackPenalty.applyPenalty(cc.reachPenalty);
|
||||
return cancel;
|
||||
}
|
||||
} else {
|
||||
// Player passed the check, reward them.
|
||||
data.reachVL *= 0.8D;
|
||||
}
|
||||
|
||||
// Visible violation
|
||||
if (collided) {
|
||||
data.visibleVL++;
|
||||
cancel = executeActions(player, data.visibleVL, 1.0, cc.visibleActions).willCancel();
|
||||
} else {
|
||||
data.visibleVL *= 0.8D;
|
||||
}
|
||||
return cancel;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.checks.fight;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.utilities.map.WrapBlockCache;
|
||||
|
||||
public class Visible extends Check {
|
||||
|
||||
private final WrapBlockCache wrapBlockCache;
|
||||
|
||||
public Visible() {
|
||||
super(CheckType.FIGHT_VISIBLE);
|
||||
wrapBlockCache = new WrapBlockCache();
|
||||
}
|
||||
|
||||
public boolean check() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean loopCheck() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean loopFinish() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data context for iterating over ITraceEntry instances.
|
||||
* @param player
|
||||
* @param pLoc
|
||||
* @param damaged
|
||||
* @param damagedLoc
|
||||
* @param data
|
||||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
public VisibleContext getContext(final Player player, final Location pLoc,
|
||||
final Entity damaged, final Location damagedLoc,
|
||||
final FightData data, final FightConfig cc) {
|
||||
final VisibleContext context = new VisibleContext();
|
||||
context.pY = pLoc.getY() + player.getEyeHeight();
|
||||
context.cache = wrapBlockCache.getBlockCache().setAccess(pLoc.getWorld());
|
||||
return context;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.checks.fight;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
|
||||
|
||||
public class VisibleContext {
|
||||
/** Eye location y of the attacking player. */
|
||||
public double pY;
|
||||
public boolean collided = false;
|
||||
public BlockCache cache;
|
||||
}
|
||||
@@ -1774,12 +1774,12 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
final Location ref = player.getVehicle().getLocation(useLoc);
|
||||
aux.resetPositionsAndMediumProperties(player, ref, mData, mCc); // TODO: Consider using to and intercept cheat attempts in another way.
|
||||
useLoc.setWorld(null);
|
||||
mData.updateTrace(player, to, tick, mcAccess.getHandle()); // TODO: Can you become invincible by sending special moves?
|
||||
mData.updateTrace(player, to, now, mcAccess.getHandle()); // TODO: Can you become invincible by sending special moves?
|
||||
}
|
||||
else if (!from.getWorld().getName().equals(toWorldName)) {
|
||||
// A teleport event should follow.
|
||||
aux.resetPositionsAndMediumProperties(player, to, mData, mCc);
|
||||
mData.resetTrace(player, to, tick, mcAccess.getHandle(), mCc);
|
||||
mData.resetTrace(player, to, now, mcAccess.getHandle(), mCc);
|
||||
}
|
||||
else {
|
||||
// TODO: Detect differing location (a teleport event would follow).
|
||||
@@ -1791,7 +1791,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
else {
|
||||
// Normal move, nothing to do.
|
||||
}
|
||||
mData.updateTrace(player, to, tick, mcAccess.getHandle());
|
||||
mData.updateTrace(player, to, now, mcAccess.getHandle());
|
||||
if (mData.hasTeleported()) onPlayerMoveMonitorNotCancelledHasTeleported(player, to, mData, pData, pData.isDebugActive(checkType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,7 +483,7 @@ public abstract class ConfPaths {
|
||||
public static final String FIGHT_CANCELDEAD = FIGHT + "canceldead";
|
||||
public static final String FIGHT_TOOLCHANGEPENALTY = FIGHT + "toolchangepenalty";
|
||||
private static final String FIGHT_PVP = FIGHT + "pvp.";
|
||||
public static final String FIGHT_MAXLOOPLETENCYTICKS = FIGHT + "maxloopletencyticks";
|
||||
public static final String FIGHT_MAXLOOPLETENCYMS = FIGHT + "maxloopletencyms";
|
||||
public static final String FIGHT_PVP_KNOCKBACKVELOCITY = FIGHT_PVP + "knockbackvelocity";
|
||||
|
||||
private static final String FIGHT_ANGLE = FIGHT + "angle.";
|
||||
@@ -523,6 +523,11 @@ public abstract class ConfPaths {
|
||||
public static final String FIGHT_GODMODE_LAGMAXAGE = FIGHT_GODMODE + "maxage";
|
||||
public static final String FIGHT_GODMODE_ACTIONS = FIGHT_GODMODE + "actions";
|
||||
|
||||
private static final String FIGHT_HITBOX = FIGHT + "hitbox.";
|
||||
public static final String FIGHT_HITBOX_CHECK = FIGHT_HITBOX + SUB_ACTIVE;
|
||||
public static final String FIGHT_HITBOX_HORIZONTAL_EXPAND = FIGHT_HITBOX + "marginhorizontal";
|
||||
public static final String FIGHT_HITBOX_VERTICAL_EXPAND = FIGHT_HITBOX + "marginvertical";
|
||||
|
||||
private static final String FIGHT_NOSWING = FIGHT + "noswing.";
|
||||
public static final String FIGHT_NOSWING_CHECK = FIGHT_NOSWING + SUB_ACTIVE;
|
||||
public static final String FIGHT_NOSWING_ACTIONS = FIGHT_NOSWING + "actions";
|
||||
@@ -563,7 +568,11 @@ public abstract class ConfPaths {
|
||||
public static final String FIGHT_SPEED_IMPROBABLE_FEEDONLY = FIGHT_SPEED_IMPROBABLE + "feedonly";
|
||||
public static final String FIGHT_SPEED_IMPROBABLE_WEIGHT = FIGHT_SPEED_IMPROBABLE + "weight";
|
||||
public static final String FIGHT_SPEED_ACTIONS = FIGHT_SPEED + "actions";
|
||||
|
||||
|
||||
private static final String FIGHT_VISIBLE = FIGHT + "visible.";
|
||||
public static final String FIGHT_VISIBLE_CHECK = FIGHT_VISIBLE + SUB_ACTIVE;
|
||||
public static final String FIGHT_VISIBLE_ACTIONS = FIGHT_VISIBLE + "actions";
|
||||
|
||||
private static final String FIGHT_YAWRATE = FIGHT + "yawrate.";
|
||||
public static final String FIGHT_YAWRATE_CHECK = FIGHT_YAWRATE + SUB_ACTIVE;
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.BLOCKINTERACT_SPEED_ACTIONS, "cancel vl>10 cancel log:bspeed:5:4:i cancel vl>500 cancel log:bspeed:0:5:icf cmdc:kickbspeed:2:5", 1154);
|
||||
// Visible
|
||||
set(ConfPaths.BLOCKINTERACT_VISIBLE_CHECK, "default", 785);
|
||||
set(ConfPaths.BLOCKINTERACT_VISIBLE_ACTIONS, "cancel vl>30 log:bvisible:8:5:if cancel", 1154);
|
||||
set(ConfPaths.BLOCKINTERACT_VISIBLE_ACTIONS, "cancel vl>30 log:bvisible:8:5:if cancel", 1154);
|
||||
|
||||
|
||||
/* BlockPlace */
|
||||
@@ -333,8 +333,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.FIGHT_ACTIVE, "default", 1144);
|
||||
// General
|
||||
set(ConfPaths.FIGHT_CANCELDEAD, true, 785);
|
||||
// TODO: Using System.currentTimeMillis() for timestamp not server tick?
|
||||
set(ConfPaths.FIGHT_MAXLOOPLETENCYTICKS, 8, 1154);
|
||||
set(ConfPaths.FIGHT_MAXLOOPLETENCYMS, 2000, 1154);
|
||||
set(ConfPaths.FIGHT_TOOLCHANGEPENALTY, 0L, 1154); // Disabled for now, it interferes too much with pvp. 500L
|
||||
set(ConfPaths.FIGHT_PVP_KNOCKBACKVELOCITY, "default", 785);
|
||||
// YawRate activation flag
|
||||
@@ -367,6 +366,10 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.FIGHT_GODMODE_LAGMINAGE, 1100, 785); // TODO: ndt/2 => 500-600.
|
||||
set(ConfPaths.FIGHT_GODMODE_LAGMAXAGE, 5000, 785);
|
||||
set(ConfPaths.FIGHT_GODMODE_ACTIONS, "cancel log:godmode:0:5:icf cmdc:kickgod:0:5", 1154);
|
||||
// HitBox
|
||||
set(ConfPaths.FIGHT_HITBOX_CHECK, "default", 1154);
|
||||
set(ConfPaths.FIGHT_HITBOX_HORIZONTAL_EXPAND, 0.125, 1154);
|
||||
set(ConfPaths.FIGHT_HITBOX_VERTICAL_EXPAND, 0.125, 1154);
|
||||
// NoSwing
|
||||
set(ConfPaths.FIGHT_NOSWING_CHECK, "default", 785);
|
||||
set(ConfPaths.FIGHT_NOSWING_ACTIONS, "vl>2 cancel vl>10 log:noswing:2:5:i cancel", 1154);
|
||||
@@ -401,6 +404,9 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.FIGHT_SPEED_SHORTTERM_LIMIT, 5, 1154);
|
||||
set(ConfPaths.FIGHT_SPEED_IMPROBABLE_FEEDONLY, false, 1154);
|
||||
set(ConfPaths.FIGHT_SPEED_IMPROBABLE_WEIGHT, 2.0, 1154);
|
||||
// Visible
|
||||
set(ConfPaths.FIGHT_VISIBLE_CHECK, "default", 1154);
|
||||
set(ConfPaths.FIGHT_VISIBLE_ACTIONS, "cancel vl>30 log:fvisible:8:5:if cancel", 1154);
|
||||
|
||||
|
||||
/* Inventory */
|
||||
@@ -701,6 +707,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.STRINGS + ".freach", start + "tried to hit an entity from a suspicious distance (Reach: &6[reachdistance]&7)" + end, 1154);
|
||||
set(ConfPaths.STRINGS + ".fselfhit", start + "tried to hit themselves" + end, 1154);
|
||||
set(ConfPaths.STRINGS + ".fspeed", start + "clicked [violations] times over the established [limit] CPS limit" + end, 1154);
|
||||
set(ConfPaths.STRINGS + ".fvisible", start + "tried to attack through a solid obstacle" + end, 1154);
|
||||
set(ConfPaths.STRINGS + ".godmode", start + "tried to ignore inflicted damage (Health: &7[health]&7)" + end, 1154);
|
||||
set(ConfPaths.STRINGS + ".gutenberg", start + "created a book with too many pages" + end, 785);
|
||||
set(ConfPaths.STRINGS + ".improbable", start + "is exhibiting an erratic behaviour (Check: &6[tags]&7)" + end, 1154);
|
||||
|
||||
@@ -144,6 +144,7 @@ public class Permissions {
|
||||
public static final RegisteredPermission FIGHT_REACH = add(FIGHT + ".reach");
|
||||
public static final RegisteredPermission FIGHT_SELFHIT = add(FIGHT + ".selfhit");
|
||||
public static final RegisteredPermission FIGHT_SPEED = add(FIGHT + ".speed");
|
||||
public static final RegisteredPermission FIGHT_VISIBLE = add(FIGHT + ".visible");
|
||||
|
||||
public static final RegisteredPermission INVENTORY = add(CHECKS + ".inventory");
|
||||
public static final RegisteredPermission INVENTORY_DROP = add(INVENTORY + ".drop");
|
||||
|
||||
Reference in new issue
Block a user