mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-06-26 06:14:42 +02:00
[BLEEDING][BREAKING] Shift entry points for past state bounce.
Lots of issues remain, but vertical push/bounce with pistons is much improved. Still there are show stoppers (false positives remain, as well as occasional fall damage). Use same/similar entry points, like static/classic bounce checking in MovingListener. SurvivalFly still keeps one exception with the after-failure Y_POS block move check. Also check: https://github.com/NoCheatPlus/Issues/issues/5
This commit is contained in:
parent
9dca93e650
commit
6de231ac54
|
@ -822,6 +822,15 @@ public class MovingData extends ACheckData {
|
|||
verVel.addToFront(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first element without using it.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public SimpleEntry peekVerticalVelocity(final double amount, final int maxActCount) {
|
||||
return verVel.peek(amount, maxActCount, TOL_VVEL);
|
||||
}
|
||||
|
||||
public void addVerticalVelocity(final SimpleEntry entry) {
|
||||
verVel.add(entry);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
|
@ -83,6 +84,8 @@ import fr.neatmonster.nocheatplus.compat.BridgeHealth;
|
|||
import fr.neatmonster.nocheatplus.compat.BridgeMisc;
|
||||
import fr.neatmonster.nocheatplus.compat.MCAccess;
|
||||
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker;
|
||||
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker.BlockChangeEntry;
|
||||
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker.Direction;
|
||||
import fr.neatmonster.nocheatplus.components.data.IData;
|
||||
import fr.neatmonster.nocheatplus.components.location.SimplePositionWithLook;
|
||||
import fr.neatmonster.nocheatplus.components.modifier.IAttributeAccess;
|
||||
|
@ -119,6 +122,28 @@ import fr.neatmonster.nocheatplus.utilities.map.MapUtil;
|
|||
*/
|
||||
public class MovingListener extends CheckListener implements TickListener, IRemoveData, IHaveCheckType, INotifyReload, INeedConfig, JoinLeaveListener{
|
||||
|
||||
/**
|
||||
* Bounce preparation state.
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public static enum BounceType {
|
||||
/** No bounce happened. */
|
||||
NO_BOUNCE,
|
||||
/** Ordinary bounce off a static block underneath. */
|
||||
STATIC,
|
||||
/**
|
||||
* Ordinary bounce, due to a slime block having been underneath in the
|
||||
* past. Rather for logging.
|
||||
*/
|
||||
STATIC_PAST,
|
||||
/**
|
||||
* A slime block has been underneath, pushing up into the player.
|
||||
*/
|
||||
STATIC_PAST_AND_PUSH,
|
||||
// WEAK_PUSH <- TBD: with edge on slime, or with falling inside of the new slime block position?
|
||||
}
|
||||
|
||||
/** The no fall check. **/
|
||||
public final NoFall noFall = addCheck(new NoFall());
|
||||
|
||||
|
@ -624,7 +649,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
|
||||
// Pre-check checks (hum), either for cf or for sf.
|
||||
boolean checkNf = true;
|
||||
boolean verticalBounce = false;
|
||||
BounceType verticalBounce = BounceType.NO_BOUNCE;
|
||||
|
||||
// TODO: More adaptive margin / method (bounding boxes).
|
||||
final boolean useBlockChangeTracker = cc.trackBlockMove && (cc.passableCheck || checkSf || checkCf)
|
||||
|
@ -656,22 +681,46 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
}
|
||||
|
||||
// Check jumping on things like slime blocks.
|
||||
// Detect potential bounce.
|
||||
// Detect bounce type / use prepared bounce.
|
||||
if (newTo == null) {
|
||||
// TODO: With past states: What does jump effects do here?
|
||||
if (to.getY() < from.getY()) {
|
||||
if ((BlockProperties.getBlockFlags(pTo.getTypeIdBelow()) & BlockProperties.F_BOUNCE25) != 0L
|
||||
&& !survivalFly.isReallySneaking(player) && checkBounceEnvelope(player, pFrom, pTo, data, cc)
|
||||
) {
|
||||
// Prepare bounce: The center of the player must be above the block.
|
||||
// Prepare bounce: The center of the player must be above the block.
|
||||
// Common pre-conditions.
|
||||
// TODO: Check if really leads to calling the method for pistons (checkBounceEnvelope vs. push).
|
||||
if (!survivalFly.isReallySneaking(player)
|
||||
&& checkBounceEnvelope(player, pFrom, pTo, data, cc)) {
|
||||
// TODO: Check other side conditions (fluids, web, max. distance to the block top (!))
|
||||
verticalBounce = true;
|
||||
// Skip NoFall.
|
||||
checkNf = false;
|
||||
// Classic static bounce.
|
||||
if ((BlockProperties.getBlockFlags(pTo.getTypeIdBelow())
|
||||
& BlockProperties.F_BOUNCE25) != 0L) {
|
||||
/*
|
||||
* TODO: May need to adapt within this method, if
|
||||
* "push up" happened and the trigger had been
|
||||
* ordinary.
|
||||
*/
|
||||
verticalBounce = BounceType.STATIC;
|
||||
checkNf = false; // Skip NoFall.
|
||||
}
|
||||
if (verticalBounce == BounceType.NO_BOUNCE && useBlockChangeTracker) {
|
||||
verticalBounce = checkPastStateBounceDescend(player, pFrom, pTo, thisMove, lastMove,
|
||||
tick, data, cc);
|
||||
if (verticalBounce != BounceType.NO_BOUNCE) {
|
||||
checkNf = false; // Skip NoFall.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (data.verticalBounce != null) {
|
||||
// Prepared bounce support.
|
||||
if (onPreparedBounceSupport(player, from, to, lastMove, tick, data)) {
|
||||
else {
|
||||
if (
|
||||
// Prepared bounce support.
|
||||
data.verticalBounce != null
|
||||
&& onPreparedBounceSupport(player, from, to, thisMove, lastMove, tick, data)
|
||||
// Past state bounce (includes prepending velocity / special calls).
|
||||
|| useBlockChangeTracker
|
||||
&& thisMove.yDistance >= 0.415 && thisMove.yDistance <= 1.515 // TODO: MAGIC
|
||||
&& checkPastStateBounceAscend(player, pFrom, pTo, thisMove, lastMove, tick, data, cc)
|
||||
) {
|
||||
checkNf = false;
|
||||
}
|
||||
}
|
||||
|
@ -681,7 +730,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
// Check passable first to prevent set-back override.
|
||||
// TODO: Redesign to set set-backs later (queue + invalidate).
|
||||
boolean mightSkipNoFall = false; // If to skip nofall check (mainly on violation of other checks).
|
||||
if (newTo == null && cc.passableCheck && player.getGameMode() != BridgeMisc.GAME_MODE_SPECTATOR && !NCPExemptionManager.isExempted(player, CheckType.MOVING_PASSABLE) && !player.hasPermission(Permissions.MOVING_PASSABLE)) {
|
||||
if (newTo == null && cc.passableCheck && player.getGameMode() != BridgeMisc.GAME_MODE_SPECTATOR
|
||||
&& !NCPExemptionManager.isExempted(player, CheckType.MOVING_PASSABLE)
|
||||
&& !player.hasPermission(Permissions.MOVING_PASSABLE)) {
|
||||
// Passable is checked first to get the original set-back locations from the other checks, if needed.
|
||||
newTo = passable.check(player, pFrom, pTo, data, cc, tick, useBlockChangeTracker);
|
||||
if (newTo != null) {
|
||||
|
@ -802,8 +853,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
if (newTo == null) {
|
||||
// Allowed move.
|
||||
// Bounce effects.
|
||||
if (verticalBounce) {
|
||||
processBounce(player, pFrom.getY(), pTo.getY(), data, cc);
|
||||
if (verticalBounce != BounceType.NO_BOUNCE) {
|
||||
processBounce(player, pFrom.getY(), pTo.getY(), verticalBounce, data, cc);
|
||||
}
|
||||
// Finished move processing.
|
||||
if (processingEvents.containsKey(playerName)) {
|
||||
|
@ -820,6 +871,14 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
return false;
|
||||
}
|
||||
else {
|
||||
if (data.debug) { // TODO: Remove, if not relevant (doesn't look like it was :p).
|
||||
if (verticalBounce != BounceType.NO_BOUNCE) {
|
||||
debug(player, "Bounce effect not processed: " + verticalBounce);
|
||||
}
|
||||
if (data.verticalBounce != null) {
|
||||
debug(player, "Bounce effect not used: " + data.verticalBounce);
|
||||
}
|
||||
}
|
||||
// Set-back handling.
|
||||
onSetBack(player, event, newTo, data, cc);
|
||||
return true;
|
||||
|
@ -827,7 +886,116 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
}
|
||||
|
||||
/**
|
||||
* A slime block is underneath, the player isn't really sneaking.
|
||||
* Only for yDistance < 0 + some bounce envelope checked.
|
||||
* @param player
|
||||
* @param from
|
||||
* @param to
|
||||
* @param lastMove
|
||||
* @param lastMove2
|
||||
* @param tick
|
||||
* @param data
|
||||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
private BounceType checkPastStateBounceDescend(
|
||||
final Player player, final PlayerLocation from, final PlayerLocation to,
|
||||
final PlayerMoveData thisMove, final PlayerMoveData lastMove, final int tick,
|
||||
final MovingData data, final MovingConfig cc) {
|
||||
// TODO: Find more preconditions.
|
||||
final UUID worldId = from.getWorld().getUID();
|
||||
// Prepare (normal/extra) bounce.
|
||||
// TODO: Might later need to override/adapt just the bounce effect set by the ordinary method.
|
||||
// Typical: a slime block has been there.
|
||||
final BlockChangeEntry entryBelowAny = blockChangeTracker.getBlockChangeEntryMatchFlags(
|
||||
data.blockChangeRef, tick, worldId, to.getBlockX(), to.getBlockY() - 1, to.getBlockZ(),
|
||||
null, BlockProperties.F_BOUNCE25);
|
||||
if (entryBelowAny != null) {
|
||||
// TODO: Check preconditions for bouncing here at all (!).
|
||||
|
||||
// Check if the/a block below the feet of the player got pushed into the feet of the player.
|
||||
// TODO: Not sure if this can/should be done on ascending.
|
||||
final BlockChangeEntry entryBelowY_POS = entryBelowAny.direction == Direction.Y_POS ? entryBelowAny
|
||||
: blockChangeTracker.getBlockChangeEntryMatchFlags(data.blockChangeRef, tick, worldId,
|
||||
to.getBlockX(), to.getBlockY() - 1, to.getBlockZ(), Direction.Y_POS,
|
||||
BlockProperties.F_BOUNCE25);
|
||||
if (entryBelowY_POS != null) {
|
||||
// TODO: Can't know if used... data.blockChangeRef.updateSpan(entryBelowY_POS);
|
||||
// TODO: So far, doesn't seem to be followed by violations.
|
||||
return BounceType.STATIC_PAST_AND_PUSH;
|
||||
}
|
||||
else {
|
||||
// TODO: Can't know if used... data.blockChangeRef.updateSpan(entryBelowAny);
|
||||
return BounceType.STATIC_PAST;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: ADDITIONAL: A slime block has been pushed up [a) block below counts ? b) into the feet of the player].
|
||||
/*
|
||||
* TODO: Can't update span here. If at all, it can be added as side
|
||||
* condition for using the bounce effect. Probably not worth it.
|
||||
*/
|
||||
return BounceType.NO_BOUNCE; // Nothing found, return no bounce.
|
||||
}
|
||||
|
||||
private boolean checkPastStateBounceAscend(
|
||||
final Player player, final PlayerLocation from, final PlayerLocation to,
|
||||
final PlayerMoveData thisMove, final PlayerMoveData lastMove, final int tick,
|
||||
final MovingData data, final MovingConfig cc) {
|
||||
// TODO: find more preconditions.
|
||||
final UUID worldId = from.getWorld().getUID();
|
||||
// Possibly a "lost use of slime".
|
||||
// TODO: Might need to cover push up, after ordinary slime bounce.
|
||||
// TODO: Cover push by slime block (center/feet on block).
|
||||
// TODO: Might need to cover push by slime block (center/feet off block).
|
||||
// TODO: Low fall distance cases and where no slime block was underneath at descend have to be included here.
|
||||
// TODO: Note that onPreparedBounceSupport etc. has to be called in here, if needed.
|
||||
final BlockChangeEntry entryBelowY_POS = blockChangeTracker.getBlockChangeEntryMatchFlags(
|
||||
data.blockChangeRef, tick, worldId, from.getBlockX(), from.getBlockY() - 1, from.getBlockZ(),
|
||||
Direction.Y_POS, BlockProperties.F_BOUNCE25);
|
||||
if (
|
||||
// Center push.
|
||||
entryBelowY_POS != null
|
||||
// Off center push (2x 0.5(015) only, (sum below 1.015 ?)).
|
||||
|| thisMove.yDistance < 0.5015 && from.matchBlockChangeMatchResultingFlags(blockChangeTracker,
|
||||
data.blockChangeRef, Direction.Y_POS, Math.min(.415, thisMove.yDistance),
|
||||
BlockProperties.F_BOUNCE25)
|
||||
) {
|
||||
// Always allow the double 0.505 move.
|
||||
/*
|
||||
* TODO: May detect the first 0.505 move to match preconditions
|
||||
* better (roughly 2x 0.5, 0.0 -> 1.5, -0.few -> 1.389). One might
|
||||
* also nail down to past y-position further. Also consider
|
||||
* confining to horizontal speed envelope (is that even possible)?
|
||||
*/
|
||||
if (data.debug) {
|
||||
debug(player, "checkPastStateBounceAscend: " + (entryBelowY_POS == null ? "off_center" : "center"));
|
||||
}
|
||||
final double amount = Math.max(0.505, thisMove.yDistance);
|
||||
if (data.peekVerticalVelocity(amount, 2) == null) {
|
||||
// (Could skip peek for low distances around 0.5.)
|
||||
if (amount > 1.38) {
|
||||
// TODO: HACK - More decrease than expected.
|
||||
// TODO: Consider to detect used velocity with vdistrel exceptions using past move tracking.
|
||||
data.prependVerticalVelocity(new SimpleEntry(tick, 0.925, 3));
|
||||
}
|
||||
data.prependVerticalVelocity(new SimpleEntry(tick, amount, 2));
|
||||
/*
|
||||
* TODO: Update span or not ... [could use a class that extends
|
||||
* SimpleEntry but which also contains a block change id to update
|
||||
* span with, upon using that entry?]
|
||||
*/
|
||||
if (entryBelowY_POS != null) {
|
||||
data.blockChangeRef.updateSpan(entryBelowY_POS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre conditions: A slime block is underneath and the player isn't really
|
||||
* sneaking.<br>
|
||||
*
|
||||
* @param player
|
||||
* @param from
|
||||
|
@ -836,13 +1004,20 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
private boolean checkBounceEnvelope(Player player, PlayerLocation from, PlayerLocation to, MovingData data, MovingConfig cc) {
|
||||
private boolean checkBounceEnvelope(final Player player, final PlayerLocation from, final PlayerLocation to,
|
||||
final MovingData data, final MovingConfig cc) {
|
||||
/*
|
||||
* TODO: Likely not conform with getting pushed up, while outside of the
|
||||
* strict envelope. The advantage of detecting that here could be the
|
||||
* invalidation mechanics (also consider passable etc.), otherwise the
|
||||
* move up might miss the already invalidated push up.
|
||||
*/
|
||||
return
|
||||
// 0: Normal envelope (forestall NoFall).
|
||||
(
|
||||
// 1: Ordinary.
|
||||
to.getY() - to.getBlockY() <= Math.max(cc.yOnGround, cc.noFallyOnGround)
|
||||
// 1: With carpet. TODO: Magic block id.
|
||||
// 1: With carpet. TODO: Magic block id. Use isCarpet(id) instead.
|
||||
|| to.getTypeId() == 171 && to.getY() - to.getBlockY() <= 0.9
|
||||
)
|
||||
&& MovingUtil.getRealisticFallDistance(player, from.getY(), to.getY(), data) > 1.0
|
||||
|
@ -860,11 +1035,13 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
* @param from
|
||||
* @param to
|
||||
* @param lastMove
|
||||
* @param lastMove2
|
||||
* @param tick
|
||||
* @param data
|
||||
* @return True, if bounce has been used, i.e. to do without fall damage.
|
||||
*/
|
||||
private boolean onPreparedBounceSupport(Player player, Location from, Location to, PlayerMoveData lastMove, int tick, MovingData data) {
|
||||
private boolean onPreparedBounceSupport(final Player player, final Location from, final Location to,
|
||||
final PlayerMoveData thisMove, final PlayerMoveData lastMove, final int tick, final MovingData data) {
|
||||
if (to.getY() > from.getY() || to.getY() == from.getY() && data.verticalBounce.value < 0.13) {
|
||||
// Apply bounce.
|
||||
if (to.getY() == from.getY()) {
|
||||
|
@ -900,7 +1077,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private Location checkExtremeMove(final Player player, final PlayerLocation from, final PlayerLocation to, final MovingData data, final MovingConfig cc) {
|
||||
private Location checkExtremeMove(final Player player, final PlayerLocation from, final PlayerLocation to,
|
||||
final MovingData data, final MovingConfig cc) {
|
||||
final PlayerMoveData thisMove = data.playerMoves.getCurrentMove();
|
||||
final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
|
||||
// TODO: Latency effects.
|
||||
|
@ -1003,7 +1181,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
}
|
||||
}
|
||||
|
||||
private static double guessFlyNoFlyVelocity(final Player player, final PlayerMoveData thisMove, final PlayerMoveData lastMove, final MovingData data) {
|
||||
private static double guessFlyNoFlyVelocity(final Player player,
|
||||
final PlayerMoveData thisMove, final PlayerMoveData lastMove, final MovingData data) {
|
||||
// Default margin: Allow slightly less than the previous speed.
|
||||
final double defaultAmount = lastMove.hDistance * (1.0 + Magic.FRICTION_MEDIUM_AIR) / 2.0;
|
||||
// Test for exceptions.
|
||||
|
@ -1024,18 +1203,20 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
* on ground. This might be a micro-move onto ground.
|
||||
*
|
||||
* @param player
|
||||
* @param verticalBounce
|
||||
* @param from
|
||||
* @param to
|
||||
* @param data
|
||||
* @param cc
|
||||
*/
|
||||
private void processBounce(final Player player,final double fromY, final double toY, final MovingData data, final MovingConfig cc) {
|
||||
private void processBounce(final Player player,final double fromY, final double toY,
|
||||
final BounceType bounceType, final MovingData data, final MovingConfig cc) {
|
||||
// Prepare velocity.
|
||||
final double fallDistance = MovingUtil.getRealisticFallDistance(player, fromY, toY, data);
|
||||
final double base = Math.sqrt(fallDistance) / 3.3;
|
||||
double effect = Math.min(3.5, base + Math.min(base / 10.0, Magic.GRAVITY_MAX)); // Ancient Greek technology with gravity added.
|
||||
double effect = Math.min(Magic.BOUNCE_VERTICAL_MAX_DIST, base + Math.min(base / 10.0, Magic.GRAVITY_MAX)); // Ancient Greek technology with gravity added.
|
||||
final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
|
||||
if (effect > 0.42 && lastMove.toIsValid) {
|
||||
if (effect > 0.415 && lastMove.toIsValid) {
|
||||
// Extra cap by last y distance(s).
|
||||
final double max_gain = Math.abs(lastMove.yDistance < 0.0 ? Math.min(lastMove.yDistance, toY - fromY) : (toY - fromY)) - Magic.GRAVITY_SPAN;
|
||||
if (max_gain < effect) {
|
||||
|
@ -1045,9 +1226,17 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
}
|
||||
}
|
||||
}
|
||||
if (bounceType == BounceType.STATIC_PAST_AND_PUSH) {
|
||||
/*
|
||||
* TODO: Find out if relevant and handle here (still use maximum
|
||||
* cap, but not by y-distance.). Could be the push part is only
|
||||
* necessary if the player is pushed upwards without prepared
|
||||
* bounce.
|
||||
*/
|
||||
}
|
||||
// (Actually observed max. is near 3.5.) TODO: Why 3.14 then?
|
||||
if (data.debug) {
|
||||
debug(player, "Bounce effect (dY=" + fallDistance + "): " + effect);
|
||||
debug(player, "Set bounce effect (dY=" + fallDistance + " / " + bounceType + "): " + effect);
|
||||
}
|
||||
data.noFallSkipAirCheck = true;
|
||||
data.verticalBounce = new SimpleEntry(effect, 1);
|
||||
|
@ -1998,7 +2187,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
* @param to
|
||||
* @param mcAccess
|
||||
*/
|
||||
private void outputMoveDebug(final Player player, final PlayerLocation from, final PlayerLocation to, final double maxYOnGround, final MCAccess mcAccess) {
|
||||
private void outputMoveDebug(final Player player, final PlayerLocation from, final PlayerLocation to,
|
||||
final double maxYOnGround, final MCAccess mcAccess) {
|
||||
final StringBuilder builder = new StringBuilder(250);
|
||||
final Location loc = player.getLocation();
|
||||
builder.append(CheckUtils.getLogMessagePrefix(player, checkType));
|
||||
|
|
|
@ -90,6 +90,12 @@ public class Magic {
|
|||
public static final double Y_ON_GROUND_DEFAULT = 0.016; // Jump upwards, while placing blocks.
|
||||
// public static final double Y_ON_GROUND_DEFAULT = 0.029; // Bounce off slime blocks.
|
||||
|
||||
/**
|
||||
* The maximum distance that can be achieved with bouncing back from slime
|
||||
* blocks.
|
||||
*/
|
||||
public static final double BOUNCE_VERTICAL_MAX_DIST = 3.5;
|
||||
|
||||
// Other constants.
|
||||
public static final double PAPER_DIST = 0.01;
|
||||
/**
|
||||
|
|
|
@ -44,6 +44,7 @@ import fr.neatmonster.nocheatplus.checks.workaround.WRPT;
|
|||
import fr.neatmonster.nocheatplus.compat.Bridge1_9;
|
||||
import fr.neatmonster.nocheatplus.compat.BridgeEnchant;
|
||||
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker;
|
||||
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker.BlockChangeEntry;
|
||||
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker.Direction;
|
||||
import fr.neatmonster.nocheatplus.components.modifier.IAttributeAccess;
|
||||
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle;
|
||||
|
@ -133,14 +134,16 @@ public class SurvivalFly extends Check {
|
|||
// TODO: Could run a completely different check here (roughly none :p).
|
||||
xDistance = yDistance = zDistance = hDistance = 0.0;
|
||||
hasHdist = false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
xDistance = to.getX() - from.getX();
|
||||
yDistance = thisMove.yDistance;
|
||||
zDistance = to.getZ() - from.getZ();
|
||||
if (xDistance == 0.0 && zDistance == 0.0) {
|
||||
hDistance = 0.0;
|
||||
hasHdist = false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
hasHdist = true;
|
||||
hDistance = thisMove.hDistance;
|
||||
}
|
||||
|
@ -168,7 +171,8 @@ public class SurvivalFly extends Check {
|
|||
tags.add("invalidate_lostsprint");
|
||||
if (now <= data.timeSprinting + cc.sprintingGrace) {
|
||||
sprinting = true;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
sprinting = false;
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +226,8 @@ public class SurvivalFly extends Check {
|
|||
else if (lastMove.toIsValid && lastMove.hDistance > 0.0 && lastMove.yDistance < -0.3) {
|
||||
// Note that to is not on ground either.
|
||||
resetFrom = LostGround.lostGroundStill(player, from, to, hDistance, yDistance, sprinting, lastMove, data, cc, tags);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
resetFrom = false;
|
||||
}
|
||||
}
|
||||
|
@ -372,7 +377,8 @@ public class SurvivalFly extends Check {
|
|||
tags.add("sprintback"); // Might add it anyway.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* TODO: Consider to log and/or remember when this was last time
|
||||
* cleared [add time distance to tags/log on violations].
|
||||
|
@ -454,7 +460,8 @@ public class SurvivalFly extends Check {
|
|||
outputDebug(player, to, data, cc, hDistance, hAllowedDistance, hFreedom, yDistance, vAllowedDistance, fromOnGround, resetFrom, toOnGround, resetTo);
|
||||
tagsLength = tags.size();
|
||||
data.ws.setJustUsedIds(null);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
tagsLength = 0; // JIT vs. IDE.
|
||||
}
|
||||
|
||||
|
@ -547,7 +554,8 @@ public class SurvivalFly extends Check {
|
|||
}
|
||||
else if (!resetFrom || !resetTo) {
|
||||
data.insideMediumCount = 0;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
data.insideMediumCount ++;
|
||||
}
|
||||
|
||||
|
@ -599,7 +607,8 @@ public class SurvivalFly extends Check {
|
|||
// Adjust in-air counters.
|
||||
if (yDistance == 0.0) {
|
||||
data.sfZeroVdistRepeat ++;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
data.sfZeroVdistRepeat = 0;
|
||||
}
|
||||
}
|
||||
|
@ -675,29 +684,39 @@ public class SurvivalFly extends Check {
|
|||
|| yDistance <= 1.015 && to.getY() - to.getBlockY() < 0.015)) {
|
||||
if (from.matchBlockChange(blockChangeTracker, data.blockChangeRef, Direction.Y_POS,
|
||||
Math.min(yDistance, 1.0))) {
|
||||
if (yDistance > 1.0) {
|
||||
final BlockChangeEntry entry = blockChangeTracker.getBlockChangeEntryMatchFlags(data.blockChangeRef,
|
||||
tick, from.getWorld().getUID(), from.getBlockX(), from.getBlockY() - 1, from.getBlockZ(),
|
||||
Direction.Y_POS, BlockProperties.F_BOUNCE25);
|
||||
if (entry != null) {
|
||||
data.blockChangeRef.updateSpan(entry);
|
||||
data.prependVerticalVelocity(new SimpleEntry(tick, 0.5015, 3)); // TODO: HACK
|
||||
tags.add("past_bounce");
|
||||
}
|
||||
}
|
||||
tags.add("blkmv_y_pos");
|
||||
final double maxDistYPos = yDistance; //1.0 - (from.getY() - from.getBlockY()); // TODO: Margin ?
|
||||
return new double[]{maxDistYPos, 0.0};
|
||||
}
|
||||
}
|
||||
// (No else.)
|
||||
if (yDistance <= 1.55) {
|
||||
// TODO: Edges ca. 0.5 (or 2x 0.5).
|
||||
// TODO: Center ca. 1.5. With falling height, values increase slightly.
|
||||
// Simplified: Always allow 1.5 or less with being pushed up by slime.
|
||||
// TODO:
|
||||
if (from.matchBlockChangeMatchResultingFlags(
|
||||
blockChangeTracker, data.blockChangeRef, Direction.Y_POS,
|
||||
Math.min(yDistance, 0.42), // Special limit.
|
||||
BlockProperties.F_BOUNCE25)) {
|
||||
tags.add("blkmv_y_pos_bounce");
|
||||
final double maxDistYPos = yDistance; //1.0 - (from.getY() - from.getBlockY()); // TODO: Margin ?
|
||||
// TODO: Set bounce effect or something !?
|
||||
// TODO: Bounce effect instead ?
|
||||
data.addVerticalVelocity(new SimpleEntry(tick, Math.max(0.515, yDistance - 0.5), 2));
|
||||
return new double[]{maxDistYPos, 0.0};
|
||||
}
|
||||
}
|
||||
// if (yDistance <= 1.55) {
|
||||
// // TODO: Edges ca. 0.5 (or 2x 0.5).
|
||||
// // TODO: Center ca. 1.5. With falling height, values increase slightly.
|
||||
// // Simplified: Always allow 1.5 or less with being pushed up by slime.
|
||||
// // TODO:
|
||||
// if (from.matchBlockChangeMatchResultingFlags(
|
||||
// blockChangeTracker, data.blockChangeRef, Direction.Y_POS,
|
||||
// Math.min(yDistance, 0.415), // Special limit.
|
||||
// BlockProperties.F_BOUNCE25)) {
|
||||
// tags.add("blkmv_y_pos_bounce");
|
||||
// final double maxDistYPos = yDistance; //1.0 - (from.getY() - from.getBlockY()); // TODO: Margin ?
|
||||
// // TODO: Set bounce effect or something !?
|
||||
// // TODO: Bounce effect instead ?
|
||||
// data.addVerticalVelocity(new SimpleEntry(tick, Math.max(0.515, yDistance - 0.5), 2));
|
||||
// return new double[]{maxDistYPos, 0.0};
|
||||
// }
|
||||
// }
|
||||
}
|
||||
// Push (/pull) down.
|
||||
else if (yDistance < 0.0 && yDistance >= -1.0) {
|
||||
|
@ -969,7 +988,8 @@ public class SurvivalFly extends Check {
|
|||
// Hack for boats (coarse: allows minecarts too).
|
||||
if (yDistance > cc.sfStepHeight && yDistance - cc.sfStepHeight < 0.00000003 && to.isOnGroundDueToStandingOnAnEntity()) {
|
||||
vAllowedDistance = yDistance;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
vAllowedDistance = Math.max(cc.sfStepHeight, maxJumpGain + jumpGainMargin);
|
||||
}
|
||||
}
|
||||
|
@ -1088,7 +1108,8 @@ public class SurvivalFly extends Check {
|
|||
vDistRelVL = true;
|
||||
}
|
||||
// else: Allow moving up less. Note: possibility of low jump.
|
||||
} else { // if (yDistance < 0.0) // Rather too fast falling.
|
||||
}
|
||||
else { // if (yDistance < 0.0) // Rather too fast falling.
|
||||
if (yDistance < -3.0 && lastMove.yDistance < -3.0 && Math.abs(yDistDiffEx) < 5.0 * Magic.GRAVITY_MAX) {
|
||||
// Disregard not falling faster at some point (our constants don't match 100%).
|
||||
}
|
||||
|
@ -1333,7 +1354,8 @@ public class SurvivalFly extends Check {
|
|||
final float sc0;
|
||||
if (count0 == cap) {
|
||||
sc0 = acc.bucketScore(0);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// Catch extreme changes quick.
|
||||
sc0 = acc.bucketScore(0) * (float) cap / (float) count0 - Magic.GRAVITY_VACC * (float) (cap - count0);
|
||||
}
|
||||
|
@ -1729,7 +1751,8 @@ public class SurvivalFly extends Check {
|
|||
final double vl2 = Math.abs(yDistAbs - frictDist - (yDistance < 0.0 ? Magic.GRAVITY_MAX + Magic.GRAVITY_SPAN : Magic.GRAVITY_MIN));
|
||||
if (vl1 <= vl2) {
|
||||
return new double[]{yDistance < 0.0 ? -baseSpeed : baseSpeed, vl1};
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return new double[]{yDistance < 0.0 ? -frictDist - Magic.GRAVITY_MAX - Magic.GRAVITY_SPAN : frictDist - Magic.GRAVITY_MIN, vl2};
|
||||
}
|
||||
}
|
||||
|
@ -1772,7 +1795,8 @@ public class SurvivalFly extends Check {
|
|||
tags.add("climbstep");
|
||||
vDistanceAboveLimit = Math.max(vDistanceAboveLimit, Math.abs(yDistance) - maxSpeed);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
tags.add("climbspeed");
|
||||
vDistanceAboveLimit = Math.max(vDistanceAboveLimit, Math.abs(yDistance) - maxSpeed);
|
||||
}
|
||||
|
@ -1942,7 +1966,8 @@ public class SurvivalFly extends Check {
|
|||
if (now - data.sfCobwebTime > 3000) {
|
||||
data.sfCobwebTime = now;
|
||||
data.sfCobwebVL = vDistanceAboveLimit * 100D;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
data.sfCobwebVL += vDistanceAboveLimit * 100D;
|
||||
}
|
||||
if (data.sfCobwebVL < 550) { // Totally random !
|
||||
|
@ -1953,7 +1978,8 @@ public class SurvivalFly extends Check {
|
|||
}
|
||||
data.sfJumpPhase = 0;
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,6 +105,27 @@ public class SimpleAxisVelocity {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Without checking for invalidation, test if there is a matching entry with
|
||||
* same or less the activation count.
|
||||
*
|
||||
* @param amount
|
||||
* @param maxActCount
|
||||
* @param tolerance
|
||||
* @return
|
||||
*/
|
||||
public SimpleEntry peek(final double amount, final int maxActCount, final double tolerance) {
|
||||
final Iterator<SimpleEntry> it = queued.iterator();
|
||||
while (it.hasNext()) {
|
||||
final SimpleEntry entry = it.next();
|
||||
if (entry.actCount < maxActCount && matchesEntry(entry, amount, tolerance)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
// None found.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the demanded amount can be covered by this velocity entry. Might
|
||||
* return an entry with a small value with a different sign, if amount is
|
||||
|
@ -128,15 +149,16 @@ public class SimpleAxisVelocity {
|
|||
* Remove all entries that have been added before the given tick, or for
|
||||
* which the activation count has reached 0.
|
||||
*
|
||||
* @param tick
|
||||
* @param invalidateBeforeTick
|
||||
* Entries with a smaller tick value get removed.
|
||||
*/
|
||||
public void removeInvalid(final int tick) {
|
||||
public void removeInvalid(final int invalidateBeforeTick) {
|
||||
// Note: clear invalidated here, append unused to invalidated.
|
||||
final Iterator<SimpleEntry> it = queued.iterator();
|
||||
while (it.hasNext()) {
|
||||
final SimpleEntry entry = it.next();
|
||||
entry.actCount --; // Let others optimize this.
|
||||
if (entry.actCount <= 0 || entry.tick < tick) {
|
||||
if (entry.actCount <= 0 || entry.tick < invalidateBeforeTick) {
|
||||
it.remove();
|
||||
// Track unused velocity.
|
||||
if (unusedActive) {
|
||||
|
|
|
@ -1078,7 +1078,7 @@ public class RichBoundsLocation implements IGetBukkitLocation, IGetBlockPosition
|
|||
* @param ref
|
||||
* the ref
|
||||
* @param direction
|
||||
* the direction
|
||||
* Pass null to ignore the direction.
|
||||
* @param coverDistance
|
||||
* The (always positive) distance to cover.
|
||||
* @return Returns true, iff an entry was found.
|
||||
|
@ -1133,7 +1133,7 @@ public class RichBoundsLocation implements IGetBukkitLocation, IGetBlockPosition
|
|||
* @param ref
|
||||
* the ref
|
||||
* @param direction
|
||||
* the direction
|
||||
* Pass null to ignore the direction.
|
||||
* @param coverDistance
|
||||
* The (always positive) distance to cover.
|
||||
* @param matchFlags
|
||||
|
@ -1144,7 +1144,6 @@ public class RichBoundsLocation implements IGetBukkitLocation, IGetBlockPosition
|
|||
public boolean matchBlockChangeMatchResultingFlags(final BlockChangeTracker blockChangeTracker,
|
||||
final BlockChangeReference ref, final Direction direction, final double coverDistance,
|
||||
final long matchFlags) {
|
||||
// TODO: Remove this method (!). Use a specialized method (here or external) just for bounce.
|
||||
/*
|
||||
* TODO: Not sure with code duplication. Is it better to run
|
||||
* BlockChangeTracker.getBlockChangeMatchFlags for the other method too?
|
||||
|
|
Loading…
Reference in New Issue
Block a user