Search in sources :

Example 16 with PlayerMoveData

use of fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData in project NoCheatPlus by NoCheatPlus.

the class MovingUtil method checkUntrackedLocation.

/**
 * Detect if the given location is an untracked spot. This is spots for
 * which a player is at the location, but the moving data has another
 * "last to" position set for that player. Note that one matching player
 * with "last to" being consistent is enough to let this return null, world spawn is exempted.
 * <hr>
 * Pre-conditions:<br>
 * <li>Context-specific (e.g. activation flags for command, teleport).</li>
 * <li>See MovingUtils.shouldCheckUntrackedLocation.</li>
 *
 * @param loc
 * @return Corrected location, if loc is an "untracked location".
 */
public static Location checkUntrackedLocation(final Location loc) {
    // TODO: More efficient method to get entities at the same position (might use MCAccess).
    final Chunk toChunk = loc.getChunk();
    final Entity[] entities = toChunk.getEntities();
    MovingData untrackedData = null;
    for (int i = 0; i < entities.length; i++) {
        final Entity entity = entities[i];
        if (entity.getType() != EntityType.PLAYER) {
            continue;
        }
        final Location refLoc = entity.getLocation(useLoc);
        // TODO: Exempt other warps -> HASH based exemption (expire by time, keep high count)?
        if (TrigUtil.isSamePos(loc, refLoc) && (entity instanceof Player)) {
            final Player other = (Player) entity;
            final IPlayerData otherPData = DataManager.getPlayerData(other);
            final MovingData otherData = otherPData.getGenericInstance(MovingData.class);
            final PlayerMoveData otherLastMove = otherData.playerMoves.getFirstPastMove();
            if (!otherLastMove.toIsValid) {
                // TODO: Consider counting as tracked?
                continue;
            } else if (TrigUtil.isSamePos(refLoc, otherLastMove.to.getX(), otherLastMove.to.getY(), otherLastMove.to.getZ())) {
                // Tracked.
                return null;
            } else {
                // More leniency: allow moving inside of the same block.
                if (TrigUtil.isSameBlock(loc, otherLastMove.to.getX(), otherLastMove.to.getY(), otherLastMove.to.getZ()) && !BlockProperties.isPassable(refLoc.getWorld(), otherLastMove.to.getX(), otherLastMove.to.getY(), otherLastMove.to.getZ())) {
                    continue;
                }
                untrackedData = otherData;
            }
        }
    }
    // Cleanup.
    useLoc.setWorld(null);
    if (untrackedData == null) {
        return null;
    } else {
        // TODO: Count and log to TRACE_FILE, if multiple locations would match (!).
        final PlayerMoveData lastMove = untrackedData.playerMoves.getFirstPastMove();
        return new Location(loc.getWorld(), lastMove.to.getX(), lastMove.to.getY(), lastMove.to.getZ(), loc.getYaw(), loc.getPitch());
    }
}
Also used : Entity(org.bukkit.entity.Entity) Player(org.bukkit.entity.Player) IDebugPlayer(fr.neatmonster.nocheatplus.components.debug.IDebugPlayer) MovingData(fr.neatmonster.nocheatplus.checks.moving.MovingData) PlayerMoveData(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData) IPlayerData(fr.neatmonster.nocheatplus.players.IPlayerData) Chunk(org.bukkit.Chunk) CountableLocation(fr.neatmonster.nocheatplus.checks.net.model.CountableLocation) PlayerLocation(fr.neatmonster.nocheatplus.utilities.location.PlayerLocation) RichBoundsLocation(fr.neatmonster.nocheatplus.utilities.location.RichBoundsLocation) Location(org.bukkit.Location)

Example 17 with PlayerMoveData

use of fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData in project NoCheatPlus by NoCheatPlus.

the class MovingListener method workaroundFlyNoFlyTransition.

/**
 * Add velocity, in order to work around issues with turning off flying,
 * triggering SurvivalFly. Asserts last distances are set.
 *
 * @param tick
 * @param data
 */
private void workaroundFlyNoFlyTransition(final Player player, final int tick, final boolean debug, final MovingData data) {
    final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
    final double amount = guessFlyNoFlyVelocity(player, data.playerMoves.getCurrentMove(), lastMove, data);
    // Clear active velocity due to adding actual speed here.
    data.clearActiveHorVel();
    data.addHorizontalVelocity(new AccountEntry(tick, amount, 1, MovingData.getHorVelValCount(amount)));
    data.addVerticalVelocity(new SimpleEntry(lastMove.yDistance, 2));
    data.addVerticalVelocity(new SimpleEntry(0.0, 2));
    data.setFrictionJumpPhase();
    // Reset fall height.
    // TODO: Later (e.g. 1.9) check for the ModelFlying, if fall damage is intended.
    data.clearNoFallData();
    // TODO: Might do without this in case of elytra, needs ensure NoFall doesn't kill the player (...).
    player.setFallDistance(0f);
    if (debug) {
        debug(player, "Fly-nofly transition: Add velocity.");
    }
}
Also used : PlayerMoveData(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData) SimpleEntry(fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleEntry) AccountEntry(fr.neatmonster.nocheatplus.checks.moving.velocity.AccountEntry)

Example 18 with PlayerMoveData

use of fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData in project NoCheatPlus by NoCheatPlus.

the class MovingListener method checkFallDamageEvent.

private void checkFallDamageEvent(final Player player, final EntityDamageEvent event) {
    final IPlayerData pData = DataManager.getPlayerData(player);
    final MovingData data = pData.getGenericInstance(MovingData.class);
    if (player.isInsideVehicle()) {
        // Ignore vehicles (noFallFallDistance will be inaccurate anyway).
        data.clearNoFallData();
        return;
    }
    final MovingConfig cc = pData.getGenericInstance(MovingConfig.class);
    final PlayerMoveInfo moveInfo = aux.usePlayerMoveInfo();
    final double yOnGround = Math.max(cc.noFallyOnGround, cc.yOnGround);
    final Location loc = player.getLocation(useLoc);
    moveInfo.set(player, loc, null, yOnGround);
    final PlayerLocation pLoc = moveInfo.from;
    pLoc.collectBlockFlags(yOnGround);
    if (event.isCancelled() || !MovingUtil.shouldCheckSurvivalFly(player, pLoc, data, cc, pData) || !noFall.isEnabled(player, pData)) {
        data.clearNoFallData();
        useLoc.setWorld(null);
        aux.returnPlayerMoveInfo(moveInfo);
        return;
    }
    final boolean debug = pData.isDebugActive(CheckType.MOVING_NOFALL);
    boolean allowReset = true;
    float fallDistance = player.getFallDistance();
    final float yDiff = (float) (data.noFallMaxY - loc.getY());
    // Raw damage.
    final double damage = BridgeHealth.getRawDamage(event);
    // TODO: Account for modifiers.
    if (debug) {
        debug(player, "Damage(FALL/PRE): " + damage + " / mc=" + player.getFallDistance() + " nf=" + data.noFallFallDistance + " yDiff=" + yDiff);
    }
    // NoFall bypass checks.
    if (!data.noFallSkipAirCheck) {
        // Cheat: let Minecraft gather and deal fall damage.
        /*
             * TODO: data.noFallSkipAirCheck is used to skip checking in
             * general, thus move into that block or not?
             */
        // TODO: Could consider skipping accumulated fall distance for NoFall in general as well.
        final float dataDist = Math.max(yDiff, data.noFallFallDistance);
        final double dataDamage = NoFall.getDamage(dataDist);
        if (damage > dataDamage + 0.5 || dataDamage <= 0.0) {
            // TODO: Also relate past y-distance(s) to the fall distance (mc).
            // Hot fix: allow fall damage in lava.
            /*
                 * TODO: Correctly model the half fall distance per in-lava move
                 * and taking fall damage in lava. Should have a block flag for
                 * this.
                 */
            final PlayerMoveData firstPastMove = data.playerMoves.getFirstPastMove();
            if (pLoc.isOnGround() && pLoc.isInLava() && firstPastMove.toIsValid && firstPastMove.yDistance < 0.0) {
                /*
                     * 1. Strictly someone could attempt to accumulate fall
                     * damage by help of fast place and pickup lava. 2. There
                     * are other cases not ending up in lava, but having a
                     * reduced fall distance (then bigger than nofall data).
                     */
                if (debug) {
                    debug(player, "NoFall/Damage: allow fall damage in lava (hotfix).");
                }
            } else if (noFallVL(player, "fakefall", data, cc)) {
                // NOTE: Double violations are possible with the in-air check below.
                // TODO: Differing sub checks, once cancel action...
                player.setFallDistance(dataDist);
                if (dataDamage <= 0.0) {
                    // Cancel the event.
                    event.setCancelled(true);
                    useLoc.setWorld(null);
                    aux.returnPlayerMoveInfo(moveInfo);
                    return;
                } else {
                    // Adjust and continue.
                    if (debug) {
                        debug(player, "NoFall/Damage: override player fall distance and damage (" + fallDistance + " -> " + dataDist + ").");
                    }
                    fallDistance = dataDist;
                    BridgeHealth.setRawDamage(event, dataDamage);
                }
            }
        }
        // Cheat: set ground to true in-air.
        // Be sure not to lose that block.
        // TODO: What is this and why is it right here?
        data.noFallFallDistance += 1.0;
        // TODO: Account for liquid too?
        if (!pLoc.isOnGround(1.0, 0.3, 0.1) && !pLoc.isResetCond() && !pLoc.isAboveLadder() && !pLoc.isAboveStairs()) {
            // Likely: force damage in mid-air by setting on-ground to true.
            if (noFallVL(player, "fakeground", data, cc) && data.hasSetBack()) {
                // Cancel the event and restore fall distance.
                // NoFall data will not be reset
                allowReset = false;
            }
        } else {
            // Legitimate damage: clear accounting data.
            data.vDistAcc.clear();
        // TODO: Why only reset in case of !data.noFallSkipAirCheck?
        // TODO: Also reset other properties.
        // TODO: Also reset in other cases (moved too quickly)?
        }
    }
    aux.returnPlayerMoveInfo(moveInfo);
    // Fall-back check (skip with jump amplifier).
    final double maxD = data.jumpAmplifier > 0.0 ? NoFall.getDamage((float) NoFall.getApplicableFallHeight(player, loc.getY(), data)) : NoFall.getDamage(Math.max(yDiff, Math.max(data.noFallFallDistance, fallDistance))) + (allowReset ? 0.0 : Magic.FALL_DAMAGE_DIST);
    if (maxD > damage) {
        // TODO: respect dealDamage ?
        BridgeHealth.setRawDamage(event, maxD);
        if (debug) {
            debug(player, "Adjust fall damage to: " + maxD);
        }
    }
    if (allowReset) {
        // Normal fall damage, reset data.
        data.clearNoFallData();
        if (debug) {
            debug(player, "Reset NoFall data on fall damage.");
        }
    } else {
        // (Do not cancel the event, otherwise: "moved too quickly exploit".)
        if (cc.noFallViolationReset) {
            data.clearNoFallData();
        }
        // Add player to hover checks.
        if (cc.sfHoverCheck && data.sfHoverTicks < 0) {
            data.sfHoverTicks = 0;
            hoverTicks.add(player.getName());
        }
    }
    // Entity fall-distance should be reset elsewhere.
    // Cleanup.
    useLoc.setWorld(null);
}
Also used : PlayerMoveData(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData) IPlayerData(fr.neatmonster.nocheatplus.players.IPlayerData) PlayerLocation(fr.neatmonster.nocheatplus.utilities.location.PlayerLocation) PlayerMoveInfo(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveInfo) PlayerLocation(fr.neatmonster.nocheatplus.utilities.location.PlayerLocation) Location(org.bukkit.Location)

Example 19 with PlayerMoveData

use of fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData in project NoCheatPlus by NoCheatPlus.

the class MovingListener method onMoveMonitorNotCancelled.

/**
 * Uses useLoc if in vehicle.
 * @param player
 * @param from Might use useLoc, but will reset it, if in vehicle.
 * @param to Do not use useLoc for this.
 * @param now
 * @param tick
 * @param data
 * @param mData
 */
private void onMoveMonitorNotCancelled(final Player player, final Location from, final Location to, final long now, final long tick, final CombinedData data, final MovingData mData, final MovingConfig mCc, final IPlayerData pData) {
    final String toWorldName = to.getWorld().getName();
    Combined.feedYawRate(player, to.getYaw(), now, toWorldName, data, pData);
    // TODO: maybe even not count vehicles at all ?
    if (player.isInsideVehicle()) {
        // TODO: refine (!).
        final Location ref = player.getVehicle().getLocation(useLoc);
        // TODO: Consider using to and intercept cheat attempts in another way.
        aux.resetPositionsAndMediumProperties(player, ref, mData, mCc);
        useLoc.setWorld(null);
        // TODO: Can you become invincible by sending special moves?
        mData.updateTrace(player, to, tick, mcAccess.getHandle());
    } 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);
    } else {
        // TODO: Detect differing location (a teleport event would follow).
        final PlayerMoveData lastMove = mData.playerMoves.getFirstPastMove();
        if (!lastMove.toIsValid || !TrigUtil.isSamePos(to, lastMove.to.getX(), lastMove.to.getY(), lastMove.to.getZ())) {
            // Something odd happened, e.g. a set back.
            aux.resetPositionsAndMediumProperties(player, to, mData, mCc);
        } else {
        // Normal move, nothing to do.
        }
        mData.updateTrace(player, to, tick, mcAccess.getHandle());
        if (mData.hasTeleported()) {
            onPlayerMoveMonitorNotCancelledHasTeleported(player, to, mData, pData, pData.isDebugActive(checkType));
        }
    }
}
Also used : PlayerMoveData(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData) PlayerLocation(fr.neatmonster.nocheatplus.utilities.location.PlayerLocation) Location(org.bukkit.Location)

Example 20 with PlayerMoveData

use of fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData in project NoCheatPlus by NoCheatPlus.

the class MovingListener method processBounce.

/**
 * Adjust data to allow bouncing back and/or removing fall damage.<br>
 * yDistance is < 0, the middle of the player is above a slime block (to) +
 * 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 BounceType bounceType, final int tick, final boolean debug, final MovingData data, final MovingConfig cc, final IPlayerData pData) {
    // Prepare velocity.
    final double fallDistance = MovingUtil.getRealisticFallDistance(player, fromY, toY, data, pData);
    final double base = Math.sqrt(fallDistance) / 3.3;
    // Ancient Greek technology with gravity added.
    double effect = Math.min(Magic.BOUNCE_VERTICAL_MAX_DIST, base + Math.min(base / 10.0, Magic.GRAVITY_MAX));
    final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
    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) {
            effect = max_gain;
            if (debug) {
                debug(player, "Cap bounce effect by recent y-distances.");
            }
        }
    }
    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 (debug) {
        debug(player, "Set bounce effect (dY=" + fallDistance + " / " + bounceType + "): " + effect);
    }
    data.noFallSkipAirCheck = true;
    // Just bounce for now.
    data.verticalBounce = new SimpleEntry(tick, effect, FLAGS_VELOCITY_BOUNCE_BLOCK, 1);
}
Also used : PlayerMoveData(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData) SimpleEntry(fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleEntry)

Aggregations

PlayerMoveData (fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData)25 Location (org.bukkit.Location)11 PlayerLocation (fr.neatmonster.nocheatplus.utilities.location.PlayerLocation)9 IPlayerData (fr.neatmonster.nocheatplus.players.IPlayerData)5 MovingData (fr.neatmonster.nocheatplus.checks.moving.MovingData)3 PlayerMoveInfo (fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveInfo)3 SimpleEntry (fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleEntry)3 Player (org.bukkit.entity.Player)3 ViolationData (fr.neatmonster.nocheatplus.checks.ViolationData)2 MovingConfig (fr.neatmonster.nocheatplus.checks.moving.MovingConfig)2 AccountEntry (fr.neatmonster.nocheatplus.checks.moving.velocity.AccountEntry)2 RichBoundsLocation (fr.neatmonster.nocheatplus.utilities.location.RichBoundsLocation)2 ActionList (fr.neatmonster.nocheatplus.actions.ActionList)1 Check (fr.neatmonster.nocheatplus.checks.Check)1 CombinedData (fr.neatmonster.nocheatplus.checks.combined.CombinedData)1 LocationTrace (fr.neatmonster.nocheatplus.checks.moving.location.tracking.LocationTrace)1 LiftOffEnvelope (fr.neatmonster.nocheatplus.checks.moving.model.LiftOffEnvelope)1 LocationData (fr.neatmonster.nocheatplus.checks.moving.model.LocationData)1 ModelFlying (fr.neatmonster.nocheatplus.checks.moving.model.ModelFlying)1 CountableLocation (fr.neatmonster.nocheatplus.checks.net.model.CountableLocation)1