use of fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker.BlockChangeEntry in project NoCheatPlus by NoCheatPlus.
the class RichBoundsLocation method matchBlockChange.
/**
* Check for tracked block changes, having moved a block into a certain
* direction, using the full bounding box (pistons).
* BlockChangeReference.updateSpan is called with the earliest entry found
* (updateFinal has to be called extra). This is an opportunistic version
* without any consistency checking done, just updating the span by the
* earliest entry found.
*
* @param blockChangeTracker
* the block change tracker
* @param ref
* the ref
* @param direction
* Pass null to ignore the direction.
* @param coverDistance
* The (always positive) distance to cover.
* @return Returns true, iff an entry was found.
*/
public boolean matchBlockChange(final BlockChangeTracker blockChangeTracker, final BlockChangeReference ref, final Direction direction, final double coverDistance) {
final int tick = TickTask.getTick();
final UUID worldId = world.getUID();
final int iMinX = Location.locToBlock(minX);
final int iMaxX = Location.locToBlock(maxX);
final int iMinY = Location.locToBlock(minY);
final int iMaxY = Location.locToBlock(maxY);
final int iMinZ = Location.locToBlock(minZ);
final int iMaxZ = Location.locToBlock(maxZ);
BlockChangeEntry minEntry = null;
for (int x = iMinX; x <= iMaxX; x++) {
for (int z = iMinZ; z <= iMaxZ; z++) {
for (int y = iMinY; y <= iMaxY; y++) {
final BlockChangeEntry entry = blockChangeTracker.getBlockChangeEntry(ref, tick, worldId, x, y, z, direction);
if (entry != null && (minEntry == null || entry.id < minEntry.id)) {
// Check vs. coverDistance, exclude cases where the piston can't push that far.
if (coverDistance > 0.0 && coversDistance(x, y, z, direction, coverDistance)) {
minEntry = entry;
}
}
}
}
}
if (minEntry == null) {
return false;
} else {
ref.updateSpan(minEntry);
return true;
}
}
use of fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker.BlockChangeEntry in project NoCheatPlus by NoCheatPlus.
the class MovingListener method checkPastStateBounceAscend.
private BounceType checkPastStateBounceAscend(final Player player, final PlayerLocation from, final PlayerLocation to, final PlayerMoveData thisMove, final PlayerMoveData lastMove, final int tick, final boolean debug, final MovingData data, final MovingConfig cc) {
// TODO: More preconditions.
// TODO: Nail down to more precise side conditions for larger jumps, if possible.
final UUID worldId = from.getWorld().getUID();
// Possibly a "lost use of slime".
// TODO: Might need to cover push up, after ordinary slime bounce.
// TODO: Work around 0-dist?
// TODO: Adjust amount based on side conditions (center push or off center, distance to block top).
double amount = -1.0;
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.
thisMove.yDistance < 1.515 && from.matchBlockChangeMatchResultingFlags(blockChangeTracker, data.blockChangeRef, Direction.Y_POS, Math.min(.415, thisMove.yDistance), BlockProperties.F_BOUNCE25)) {
if (debug) {
debug(player, "Direct block push with bounce (" + (entryBelowY_POS == null ? "off_center)." : "center)."));
}
amount = Math.min(Math.max(0.505, 1.0 + (double) from.getBlockY() - from.getY() + 1.515), 2.525);
/*
* TODO: EXACT MAGIC.
*/
if (entryBelowY_POS != null) {
data.blockChangeRef.updateSpan(entryBelowY_POS);
}
}
// Center push while being on the top height of the pushed block already (or 0.5 above (!)).
if (amount < 0.0 && // TODO: MAGIC EVERYWHERE
lastMove.toIsValid && lastMove.yDistance >= 0.0 && lastMove.yDistance <= 0.505 && // TODO: Margin?
from.getY() - (double) from.getBlockY() == lastMove.yDistance) {
final BlockChangeEntry entry2BelowY_POS = blockChangeTracker.getBlockChangeEntryMatchFlags(data.blockChangeRef, tick, worldId, from.getBlockX(), from.getBlockY() - 2, from.getBlockZ(), Direction.Y_POS, BlockProperties.F_BOUNCE25);
if (entry2BelowY_POS != null) // TODO: Does off center push exist with this very case?
{
if (debug) {
debug(player, "Foot position block push with bounce (" + (entry2BelowY_POS == null ? "off_center)." : "center)."));
}
amount = Math.min(Math.max(0.505, 1.0 + (double) from.getBlockY() - from.getY() + 1.515), // TODO: EXACT MAGIC.
2.015 - lastMove.yDistance);
if (entryBelowY_POS != null) {
data.blockChangeRef.updateSpan(entry2BelowY_POS);
}
}
}
// Finally add velocity if set.
if (amount >= 0.0) {
/*
* TODO: USE EXISTING velocity with bounce flag set first, then peek
* / add. (might while peek -> has bounce flag: remove velocity)
*/
data.removeLeadingQueuedVerticalVelocityByFlag(VelocityFlags.ORIGIN_BLOCK_BOUNCE);
/*
* TODO: Concepts for limiting... max amount based on side
* conditions such as block height+1.5, max coordinate, max
* amount per use, ALLOW_ZERO flag/boolean and set in
* constructor, demand max. 1 zero dist during validity. Bind
* use to initial xz coordinates... Too precise = better with
* past move tracking, or a sub-class of SimpleEntry with better
* access signatures including thisMove.
*/
/*
* TODO: Also account for current yDistance here? E.g. Add two
* entries, split based on current yDistance?
*/
final SimpleEntry vel = new SimpleEntry(tick, amount, FLAGS_VELOCITY_BOUNCE_BLOCK_MOVE_ASCEND, 4);
data.verticalBounce = vel;
data.useVerticalBounce(player);
data.useVerticalVelocity(thisMove.yDistance);
// }
if (debug) {
debug(player, "checkPastStateBounceAscend: set velocity: " + vel);
}
// TODO: Exact type to return.
return BounceType.STATIC_PAST_AND_PUSH;
}
// TODO: There is a special case with 1.0 up on pistons pushing horizontal only (!).
return BounceType.NO_BOUNCE;
}
use of fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker.BlockChangeEntry in project NoCheatPlus by NoCheatPlus.
the class MovingListener method checkPastStateBounceDescend.
/**
* 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.
// TODO: Might later need to override/adapt just the bounce effect set by the ordinary method.
final UUID worldId = from.getWorld().getUID();
// Prepare (normal/extra) bounce.
// 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.
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: 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;
}
}
// Nothing found, return no bounce.
return BounceType.NO_BOUNCE;
}
use of fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker.BlockChangeEntry in project NoCheatPlus by NoCheatPlus.
the class RichBoundsLocation method matchBlockChangeMatchResultingFlags.
/**
* Check for tracked block changes, having moved a block into a certain
* direction, confined to certain blocks hitting the player, using the full
* bounding box (pistons), only regarding blocks having flags in common with
* matchFlags. Thus not the replaced state at a position is regarded, but
* the state that should result from a block having been pushed there.
* BlockChangeReference.updateSpan is called with the earliest entry found
* (updateFinal has to be called extra). This is an opportunistic version
* without any consistency checking done, just updating the span by the
* earliest entry found.
*
* @param blockChangeTracker
* the block change tracker
* @param ref
* the ref
* @param direction
* Pass null to ignore the direction.
* @param coverDistance
* The (always positive) distance to cover.
* @param matchFlags
* Only blocks with past states having any flags in common with
* matchFlags. If matchFlags is zero, the parameter is ignored.
* @return Returns true, iff an entry was found.
*/
public boolean matchBlockChangeMatchResultingFlags(final BlockChangeTracker blockChangeTracker, final BlockChangeReference ref, final Direction direction, final double coverDistance, final long matchFlags) {
/*
* TODO: Not sure with code duplication. Is it better to run
* BlockChangeTracker.getBlockChangeMatchFlags for the other method too?
*/
// TODO: Intended use is bouncing off slime, thus need confine to foot level ?
final int tick = TickTask.getTick();
final UUID worldId = world.getUID();
// Shift the entire search box to the opposite direction (if direction is given).
final BlockFace blockFace = direction == null ? BlockFace.SELF : direction.blockFace;
final int iMinX = Location.locToBlock(minX) - blockFace.getModX();
final int iMaxX = Location.locToBlock(maxX) - blockFace.getModX();
final int iMinY = Location.locToBlock(minY) - blockFace.getModY();
final int iMaxY = Location.locToBlock(maxY) - blockFace.getModY();
final int iMinZ = Location.locToBlock(minZ) - blockFace.getModZ();
final int iMaxZ = Location.locToBlock(maxZ) - blockFace.getModZ();
BlockChangeEntry minEntry = null;
for (int x = iMinX; x <= iMaxX; x++) {
for (int z = iMinZ; z <= iMaxZ; z++) {
for (int y = iMinY; y <= iMaxY; y++) {
final BlockChangeEntry entry = blockChangeTracker.getBlockChangeEntryMatchFlags(ref, tick, worldId, x, y, z, direction, matchFlags);
if (entry != null && (minEntry == null || entry.id < minEntry.id)) {
// Check vs. coverDistance, exclude cases where the piston can't push that far.
if (coverDistance > 0.0 && coversDistance(x + blockFace.getModX(), y + blockFace.getModY(), z + blockFace.getModZ(), direction, coverDistance)) {
minEntry = entry;
}
}
}
}
}
if (minEntry == null) {
return false;
} else {
ref.updateSpan(minEntry);
return true;
}
}
Aggregations