mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-06-28 23:34:43 +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);
|
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) {
|
public void addVerticalVelocity(final SimpleEntry entry) {
|
||||||
verVel.add(entry);
|
verVel.add(entry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Location;
|
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.BridgeMisc;
|
||||||
import fr.neatmonster.nocheatplus.compat.MCAccess;
|
import fr.neatmonster.nocheatplus.compat.MCAccess;
|
||||||
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker;
|
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.data.IData;
|
||||||
import fr.neatmonster.nocheatplus.components.location.SimplePositionWithLook;
|
import fr.neatmonster.nocheatplus.components.location.SimplePositionWithLook;
|
||||||
import fr.neatmonster.nocheatplus.components.modifier.IAttributeAccess;
|
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{
|
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. **/
|
/** The no fall check. **/
|
||||||
public final NoFall noFall = addCheck(new NoFall());
|
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.
|
// Pre-check checks (hum), either for cf or for sf.
|
||||||
boolean checkNf = true;
|
boolean checkNf = true;
|
||||||
boolean verticalBounce = false;
|
BounceType verticalBounce = BounceType.NO_BOUNCE;
|
||||||
|
|
||||||
// TODO: More adaptive margin / method (bounding boxes).
|
// TODO: More adaptive margin / method (bounding boxes).
|
||||||
final boolean useBlockChangeTracker = cc.trackBlockMove && (cc.passableCheck || checkSf || checkCf)
|
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.
|
// Check jumping on things like slime blocks.
|
||||||
// Detect potential bounce.
|
// Detect bounce type / use prepared bounce.
|
||||||
if (newTo == null) {
|
if (newTo == null) {
|
||||||
|
// TODO: With past states: What does jump effects do here?
|
||||||
if (to.getY() < from.getY()) {
|
if (to.getY() < from.getY()) {
|
||||||
if ((BlockProperties.getBlockFlags(pTo.getTypeIdBelow()) & BlockProperties.F_BOUNCE25) != 0L
|
// Prepare bounce: The center of the player must be above the block.
|
||||||
&& !survivalFly.isReallySneaking(player) && checkBounceEnvelope(player, pFrom, pTo, data, cc)
|
// Common pre-conditions.
|
||||||
) {
|
// TODO: Check if really leads to calling the method for pistons (checkBounceEnvelope vs. push).
|
||||||
// Prepare bounce: The center of the player must be above the block.
|
if (!survivalFly.isReallySneaking(player)
|
||||||
|
&& checkBounceEnvelope(player, pFrom, pTo, data, cc)) {
|
||||||
// TODO: Check other side conditions (fluids, web, max. distance to the block top (!))
|
// TODO: Check other side conditions (fluids, web, max. distance to the block top (!))
|
||||||
verticalBounce = true;
|
// Classic static bounce.
|
||||||
// Skip NoFall.
|
if ((BlockProperties.getBlockFlags(pTo.getTypeIdBelow())
|
||||||
checkNf = false;
|
& 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) {
|
else {
|
||||||
// Prepared bounce support.
|
if (
|
||||||
if (onPreparedBounceSupport(player, from, to, lastMove, tick, data)) {
|
// 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;
|
checkNf = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -681,7 +730,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||||
// Check passable first to prevent set-back override.
|
// Check passable first to prevent set-back override.
|
||||||
// TODO: Redesign to set set-backs later (queue + invalidate).
|
// TODO: Redesign to set set-backs later (queue + invalidate).
|
||||||
boolean mightSkipNoFall = false; // If to skip nofall check (mainly on violation of other checks).
|
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.
|
// 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);
|
newTo = passable.check(player, pFrom, pTo, data, cc, tick, useBlockChangeTracker);
|
||||||
if (newTo != null) {
|
if (newTo != null) {
|
||||||
|
@ -802,8 +853,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||||
if (newTo == null) {
|
if (newTo == null) {
|
||||||
// Allowed move.
|
// Allowed move.
|
||||||
// Bounce effects.
|
// Bounce effects.
|
||||||
if (verticalBounce) {
|
if (verticalBounce != BounceType.NO_BOUNCE) {
|
||||||
processBounce(player, pFrom.getY(), pTo.getY(), data, cc);
|
processBounce(player, pFrom.getY(), pTo.getY(), verticalBounce, data, cc);
|
||||||
}
|
}
|
||||||
// Finished move processing.
|
// Finished move processing.
|
||||||
if (processingEvents.containsKey(playerName)) {
|
if (processingEvents.containsKey(playerName)) {
|
||||||
|
@ -820,6 +871,14 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
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.
|
// Set-back handling.
|
||||||
onSetBack(player, event, newTo, data, cc);
|
onSetBack(player, event, newTo, data, cc);
|
||||||
return true;
|
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 player
|
||||||
* @param from
|
* @param from
|
||||||
|
@ -836,13 +1004,20 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||||
* @param cc
|
* @param cc
|
||||||
* @return
|
* @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
|
return
|
||||||
// 0: Normal envelope (forestall NoFall).
|
// 0: Normal envelope (forestall NoFall).
|
||||||
(
|
(
|
||||||
// 1: Ordinary.
|
// 1: Ordinary.
|
||||||
to.getY() - to.getBlockY() <= Math.max(cc.yOnGround, cc.noFallyOnGround)
|
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
|
|| to.getTypeId() == 171 && to.getY() - to.getBlockY() <= 0.9
|
||||||
)
|
)
|
||||||
&& MovingUtil.getRealisticFallDistance(player, from.getY(), to.getY(), data) > 1.0
|
&& 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 from
|
||||||
* @param to
|
* @param to
|
||||||
* @param lastMove
|
* @param lastMove
|
||||||
|
* @param lastMove2
|
||||||
* @param tick
|
* @param tick
|
||||||
* @param data
|
* @param data
|
||||||
* @return True, if bounce has been used, i.e. to do without fall damage.
|
* @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) {
|
if (to.getY() > from.getY() || to.getY() == from.getY() && data.verticalBounce.value < 0.13) {
|
||||||
// Apply bounce.
|
// Apply bounce.
|
||||||
if (to.getY() == from.getY()) {
|
if (to.getY() == from.getY()) {
|
||||||
|
@ -900,7 +1077,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@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 thisMove = data.playerMoves.getCurrentMove();
|
||||||
final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
|
final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
|
||||||
// TODO: Latency effects.
|
// 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.
|
// Default margin: Allow slightly less than the previous speed.
|
||||||
final double defaultAmount = lastMove.hDistance * (1.0 + Magic.FRICTION_MEDIUM_AIR) / 2.0;
|
final double defaultAmount = lastMove.hDistance * (1.0 + Magic.FRICTION_MEDIUM_AIR) / 2.0;
|
||||||
// Test for exceptions.
|
// 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.
|
* on ground. This might be a micro-move onto ground.
|
||||||
*
|
*
|
||||||
* @param player
|
* @param player
|
||||||
|
* @param verticalBounce
|
||||||
* @param from
|
* @param from
|
||||||
* @param to
|
* @param to
|
||||||
* @param data
|
* @param data
|
||||||
* @param cc
|
* @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.
|
// Prepare velocity.
|
||||||
final double fallDistance = MovingUtil.getRealisticFallDistance(player, fromY, toY, data);
|
final double fallDistance = MovingUtil.getRealisticFallDistance(player, fromY, toY, data);
|
||||||
final double base = Math.sqrt(fallDistance) / 3.3;
|
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();
|
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).
|
// 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;
|
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) {
|
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?
|
// (Actually observed max. is near 3.5.) TODO: Why 3.14 then?
|
||||||
if (data.debug) {
|
if (data.debug) {
|
||||||
debug(player, "Bounce effect (dY=" + fallDistance + "): " + effect);
|
debug(player, "Set bounce effect (dY=" + fallDistance + " / " + bounceType + "): " + effect);
|
||||||
}
|
}
|
||||||
data.noFallSkipAirCheck = true;
|
data.noFallSkipAirCheck = true;
|
||||||
data.verticalBounce = new SimpleEntry(effect, 1);
|
data.verticalBounce = new SimpleEntry(effect, 1);
|
||||||
|
@ -1998,7 +2187,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||||
* @param to
|
* @param to
|
||||||
* @param mcAccess
|
* @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 StringBuilder builder = new StringBuilder(250);
|
||||||
final Location loc = player.getLocation();
|
final Location loc = player.getLocation();
|
||||||
builder.append(CheckUtils.getLogMessagePrefix(player, checkType));
|
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.016; // Jump upwards, while placing blocks.
|
||||||
// public static final double Y_ON_GROUND_DEFAULT = 0.029; // Bounce off slime 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.
|
// Other constants.
|
||||||
public static final double PAPER_DIST = 0.01;
|
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.Bridge1_9;
|
||||||
import fr.neatmonster.nocheatplus.compat.BridgeEnchant;
|
import fr.neatmonster.nocheatplus.compat.BridgeEnchant;
|
||||||
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker;
|
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.compat.blocks.changetracker.BlockChangeTracker.Direction;
|
||||||
import fr.neatmonster.nocheatplus.components.modifier.IAttributeAccess;
|
import fr.neatmonster.nocheatplus.components.modifier.IAttributeAccess;
|
||||||
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle;
|
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).
|
// TODO: Could run a completely different check here (roughly none :p).
|
||||||
xDistance = yDistance = zDistance = hDistance = 0.0;
|
xDistance = yDistance = zDistance = hDistance = 0.0;
|
||||||
hasHdist = false;
|
hasHdist = false;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
xDistance = to.getX() - from.getX();
|
xDistance = to.getX() - from.getX();
|
||||||
yDistance = thisMove.yDistance;
|
yDistance = thisMove.yDistance;
|
||||||
zDistance = to.getZ() - from.getZ();
|
zDistance = to.getZ() - from.getZ();
|
||||||
if (xDistance == 0.0 && zDistance == 0.0) {
|
if (xDistance == 0.0 && zDistance == 0.0) {
|
||||||
hDistance = 0.0;
|
hDistance = 0.0;
|
||||||
hasHdist = false;
|
hasHdist = false;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
hasHdist = true;
|
hasHdist = true;
|
||||||
hDistance = thisMove.hDistance;
|
hDistance = thisMove.hDistance;
|
||||||
}
|
}
|
||||||
|
@ -168,7 +171,8 @@ public class SurvivalFly extends Check {
|
||||||
tags.add("invalidate_lostsprint");
|
tags.add("invalidate_lostsprint");
|
||||||
if (now <= data.timeSprinting + cc.sprintingGrace) {
|
if (now <= data.timeSprinting + cc.sprintingGrace) {
|
||||||
sprinting = true;
|
sprinting = true;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
sprinting = false;
|
sprinting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,7 +226,8 @@ public class SurvivalFly extends Check {
|
||||||
else if (lastMove.toIsValid && lastMove.hDistance > 0.0 && lastMove.yDistance < -0.3) {
|
else if (lastMove.toIsValid && lastMove.hDistance > 0.0 && lastMove.yDistance < -0.3) {
|
||||||
// Note that to is not on ground either.
|
// Note that to is not on ground either.
|
||||||
resetFrom = LostGround.lostGroundStill(player, from, to, hDistance, yDistance, sprinting, lastMove, data, cc, tags);
|
resetFrom = LostGround.lostGroundStill(player, from, to, hDistance, yDistance, sprinting, lastMove, data, cc, tags);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
resetFrom = false;
|
resetFrom = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -372,7 +377,8 @@ public class SurvivalFly extends Check {
|
||||||
tags.add("sprintback"); // Might add it anyway.
|
tags.add("sprintback"); // Might add it anyway.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
/*
|
/*
|
||||||
* TODO: Consider to log and/or remember when this was last time
|
* TODO: Consider to log and/or remember when this was last time
|
||||||
* cleared [add time distance to tags/log on violations].
|
* 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);
|
outputDebug(player, to, data, cc, hDistance, hAllowedDistance, hFreedom, yDistance, vAllowedDistance, fromOnGround, resetFrom, toOnGround, resetTo);
|
||||||
tagsLength = tags.size();
|
tagsLength = tags.size();
|
||||||
data.ws.setJustUsedIds(null);
|
data.ws.setJustUsedIds(null);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
tagsLength = 0; // JIT vs. IDE.
|
tagsLength = 0; // JIT vs. IDE.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,7 +554,8 @@ public class SurvivalFly extends Check {
|
||||||
}
|
}
|
||||||
else if (!resetFrom || !resetTo) {
|
else if (!resetFrom || !resetTo) {
|
||||||
data.insideMediumCount = 0;
|
data.insideMediumCount = 0;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
data.insideMediumCount ++;
|
data.insideMediumCount ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,7 +607,8 @@ public class SurvivalFly extends Check {
|
||||||
// Adjust in-air counters.
|
// Adjust in-air counters.
|
||||||
if (yDistance == 0.0) {
|
if (yDistance == 0.0) {
|
||||||
data.sfZeroVdistRepeat ++;
|
data.sfZeroVdistRepeat ++;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
data.sfZeroVdistRepeat = 0;
|
data.sfZeroVdistRepeat = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,29 +684,39 @@ public class SurvivalFly extends Check {
|
||||||
|| yDistance <= 1.015 && to.getY() - to.getBlockY() < 0.015)) {
|
|| yDistance <= 1.015 && to.getY() - to.getBlockY() < 0.015)) {
|
||||||
if (from.matchBlockChange(blockChangeTracker, data.blockChangeRef, Direction.Y_POS,
|
if (from.matchBlockChange(blockChangeTracker, data.blockChangeRef, Direction.Y_POS,
|
||||||
Math.min(yDistance, 1.0))) {
|
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");
|
tags.add("blkmv_y_pos");
|
||||||
final double maxDistYPos = yDistance; //1.0 - (from.getY() - from.getBlockY()); // TODO: Margin ?
|
final double maxDistYPos = yDistance; //1.0 - (from.getY() - from.getBlockY()); // TODO: Margin ?
|
||||||
return new double[]{maxDistYPos, 0.0};
|
return new double[]{maxDistYPos, 0.0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// (No else.)
|
// (No else.)
|
||||||
if (yDistance <= 1.55) {
|
// if (yDistance <= 1.55) {
|
||||||
// TODO: Edges ca. 0.5 (or 2x 0.5).
|
// // TODO: Edges ca. 0.5 (or 2x 0.5).
|
||||||
// TODO: Center ca. 1.5. With falling height, values increase slightly.
|
// // TODO: Center ca. 1.5. With falling height, values increase slightly.
|
||||||
// Simplified: Always allow 1.5 or less with being pushed up by slime.
|
// // Simplified: Always allow 1.5 or less with being pushed up by slime.
|
||||||
// TODO:
|
// // TODO:
|
||||||
if (from.matchBlockChangeMatchResultingFlags(
|
// if (from.matchBlockChangeMatchResultingFlags(
|
||||||
blockChangeTracker, data.blockChangeRef, Direction.Y_POS,
|
// blockChangeTracker, data.blockChangeRef, Direction.Y_POS,
|
||||||
Math.min(yDistance, 0.42), // Special limit.
|
// Math.min(yDistance, 0.415), // Special limit.
|
||||||
BlockProperties.F_BOUNCE25)) {
|
// BlockProperties.F_BOUNCE25)) {
|
||||||
tags.add("blkmv_y_pos_bounce");
|
// tags.add("blkmv_y_pos_bounce");
|
||||||
final double maxDistYPos = yDistance; //1.0 - (from.getY() - from.getBlockY()); // TODO: Margin ?
|
// final double maxDistYPos = yDistance; //1.0 - (from.getY() - from.getBlockY()); // TODO: Margin ?
|
||||||
// TODO: Set bounce effect or something !?
|
// // TODO: Set bounce effect or something !?
|
||||||
// TODO: Bounce effect instead ?
|
// // TODO: Bounce effect instead ?
|
||||||
data.addVerticalVelocity(new SimpleEntry(tick, Math.max(0.515, yDistance - 0.5), 2));
|
// data.addVerticalVelocity(new SimpleEntry(tick, Math.max(0.515, yDistance - 0.5), 2));
|
||||||
return new double[]{maxDistYPos, 0.0};
|
// return new double[]{maxDistYPos, 0.0};
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
// Push (/pull) down.
|
// Push (/pull) down.
|
||||||
else if (yDistance < 0.0 && yDistance >= -1.0) {
|
else if (yDistance < 0.0 && yDistance >= -1.0) {
|
||||||
|
@ -969,7 +988,8 @@ public class SurvivalFly extends Check {
|
||||||
// Hack for boats (coarse: allows minecarts too).
|
// Hack for boats (coarse: allows minecarts too).
|
||||||
if (yDistance > cc.sfStepHeight && yDistance - cc.sfStepHeight < 0.00000003 && to.isOnGroundDueToStandingOnAnEntity()) {
|
if (yDistance > cc.sfStepHeight && yDistance - cc.sfStepHeight < 0.00000003 && to.isOnGroundDueToStandingOnAnEntity()) {
|
||||||
vAllowedDistance = yDistance;
|
vAllowedDistance = yDistance;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
vAllowedDistance = Math.max(cc.sfStepHeight, maxJumpGain + jumpGainMargin);
|
vAllowedDistance = Math.max(cc.sfStepHeight, maxJumpGain + jumpGainMargin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1088,7 +1108,8 @@ public class SurvivalFly extends Check {
|
||||||
vDistRelVL = true;
|
vDistRelVL = true;
|
||||||
}
|
}
|
||||||
// else: Allow moving up less. Note: possibility of low jump.
|
// 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) {
|
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%).
|
// 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;
|
final float sc0;
|
||||||
if (count0 == cap) {
|
if (count0 == cap) {
|
||||||
sc0 = acc.bucketScore(0);
|
sc0 = acc.bucketScore(0);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// Catch extreme changes quick.
|
// Catch extreme changes quick.
|
||||||
sc0 = acc.bucketScore(0) * (float) cap / (float) count0 - Magic.GRAVITY_VACC * (float) (cap - count0);
|
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));
|
final double vl2 = Math.abs(yDistAbs - frictDist - (yDistance < 0.0 ? Magic.GRAVITY_MAX + Magic.GRAVITY_SPAN : Magic.GRAVITY_MIN));
|
||||||
if (vl1 <= vl2) {
|
if (vl1 <= vl2) {
|
||||||
return new double[]{yDistance < 0.0 ? -baseSpeed : baseSpeed, vl1};
|
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};
|
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");
|
tags.add("climbstep");
|
||||||
vDistanceAboveLimit = Math.max(vDistanceAboveLimit, Math.abs(yDistance) - maxSpeed);
|
vDistanceAboveLimit = Math.max(vDistanceAboveLimit, Math.abs(yDistance) - maxSpeed);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
tags.add("climbspeed");
|
tags.add("climbspeed");
|
||||||
vDistanceAboveLimit = Math.max(vDistanceAboveLimit, Math.abs(yDistance) - maxSpeed);
|
vDistanceAboveLimit = Math.max(vDistanceAboveLimit, Math.abs(yDistance) - maxSpeed);
|
||||||
}
|
}
|
||||||
|
@ -1942,7 +1966,8 @@ public class SurvivalFly extends Check {
|
||||||
if (now - data.sfCobwebTime > 3000) {
|
if (now - data.sfCobwebTime > 3000) {
|
||||||
data.sfCobwebTime = now;
|
data.sfCobwebTime = now;
|
||||||
data.sfCobwebVL = vDistanceAboveLimit * 100D;
|
data.sfCobwebVL = vDistanceAboveLimit * 100D;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
data.sfCobwebVL += vDistanceAboveLimit * 100D;
|
data.sfCobwebVL += vDistanceAboveLimit * 100D;
|
||||||
}
|
}
|
||||||
if (data.sfCobwebVL < 550) { // Totally random !
|
if (data.sfCobwebVL < 550) { // Totally random !
|
||||||
|
@ -1953,7 +1978,8 @@ public class SurvivalFly extends Check {
|
||||||
}
|
}
|
||||||
data.sfJumpPhase = 0;
|
data.sfJumpPhase = 0;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,27 @@ public class SimpleAxisVelocity {
|
||||||
return null;
|
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
|
* 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
|
* 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
|
* Remove all entries that have been added before the given tick, or for
|
||||||
* which the activation count has reached 0.
|
* 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.
|
// Note: clear invalidated here, append unused to invalidated.
|
||||||
final Iterator<SimpleEntry> it = queued.iterator();
|
final Iterator<SimpleEntry> it = queued.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
final SimpleEntry entry = it.next();
|
final SimpleEntry entry = it.next();
|
||||||
entry.actCount --; // Let others optimize this.
|
entry.actCount --; // Let others optimize this.
|
||||||
if (entry.actCount <= 0 || entry.tick < tick) {
|
if (entry.actCount <= 0 || entry.tick < invalidateBeforeTick) {
|
||||||
it.remove();
|
it.remove();
|
||||||
// Track unused velocity.
|
// Track unused velocity.
|
||||||
if (unusedActive) {
|
if (unusedActive) {
|
||||||
|
|
|
@ -1078,7 +1078,7 @@ public class RichBoundsLocation implements IGetBukkitLocation, IGetBlockPosition
|
||||||
* @param ref
|
* @param ref
|
||||||
* the ref
|
* the ref
|
||||||
* @param direction
|
* @param direction
|
||||||
* the direction
|
* Pass null to ignore the direction.
|
||||||
* @param coverDistance
|
* @param coverDistance
|
||||||
* The (always positive) distance to cover.
|
* The (always positive) distance to cover.
|
||||||
* @return Returns true, iff an entry was found.
|
* @return Returns true, iff an entry was found.
|
||||||
|
@ -1133,7 +1133,7 @@ public class RichBoundsLocation implements IGetBukkitLocation, IGetBlockPosition
|
||||||
* @param ref
|
* @param ref
|
||||||
* the ref
|
* the ref
|
||||||
* @param direction
|
* @param direction
|
||||||
* the direction
|
* Pass null to ignore the direction.
|
||||||
* @param coverDistance
|
* @param coverDistance
|
||||||
* The (always positive) distance to cover.
|
* The (always positive) distance to cover.
|
||||||
* @param matchFlags
|
* @param matchFlags
|
||||||
|
@ -1144,7 +1144,6 @@ public class RichBoundsLocation implements IGetBukkitLocation, IGetBlockPosition
|
||||||
public boolean matchBlockChangeMatchResultingFlags(final BlockChangeTracker blockChangeTracker,
|
public boolean matchBlockChangeMatchResultingFlags(final BlockChangeTracker blockChangeTracker,
|
||||||
final BlockChangeReference ref, final Direction direction, final double coverDistance,
|
final BlockChangeReference ref, final Direction direction, final double coverDistance,
|
||||||
final long matchFlags) {
|
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
|
* TODO: Not sure with code duplication. Is it better to run
|
||||||
* BlockChangeTracker.getBlockChangeMatchFlags for the other method too?
|
* BlockChangeTracker.getBlockChangeMatchFlags for the other method too?
|
||||||
|
|
Loading…
Reference in New Issue
Block a user