Search in sources :

Example 1 with PlayerMoveData

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

the class MovingData method resetPlayerPositions.

/**
 * Invalidate all past player moves data and set last position if not null.
 *
 * @param loc
 */
public void resetPlayerPositions(final PlayerLocation loc) {
    resetPlayerPositions();
    if (loc != null) {
        final PlayerMoveData lastMove = playerMoves.getFirstPastMove();
        // Always set with extra properties.
        lastMove.setWithExtraProperties(loc);
    }
}
Also used : PlayerMoveData(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData)

Example 2 with PlayerMoveData

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

the class MovingListener method checkPlayerMove.

/**
 * @param player
 * @param from
 * @param to
 * @param multiMoveCount
 *            0: An ordinary move, not split. 1/2: first/second of a split
 *            move.
 * @param moveInfo
 * @param data
 * @param cc
 * @param event
 * @return If cancelled/done, i.e. not to process further split moves.
 */
private boolean checkPlayerMove(final Player player, final Location from, final Location to, final int multiMoveCount, final PlayerMoveInfo moveInfo, final boolean debug, final MovingData data, final MovingConfig cc, final IPlayerData pData, final PlayerMoveEvent event) {
    Location newTo = null;
    // TODO: Order this to above "early return"?
    // Set up data / caching.
    // TODO: Data resetting above ?
    data.resetTeleported();
    // Debug.
    if (debug) {
        outputMoveDebug(player, moveInfo.from, moveInfo.to, Math.max(cc.noFallyOnGround, cc.yOnGround), mcAccess.getHandle());
    }
    // Check for illegal move and bounding box etc.
    if ((moveInfo.from.hasIllegalCoords() || moveInfo.to.hasIllegalCoords()) || !cc.ignoreStance && (moveInfo.from.hasIllegalStance() || moveInfo.to.hasIllegalStance())) {
        MovingUtil.handleIllegalMove(event, player, data, cc);
        return true;
    }
    // TODO: Could switch to UUID here (needs more changes).
    final String playerName = player.getName();
    // Check for location consistency.
    if (cc.enforceLocation && playersEnforce.contains(playerName)) {
        // NOTE: The setback should not be set before this, even if not yet set.
        // Last to vs. from.
        newTo = enforceLocation(player, from, data);
        // TODO: Remove anyway ?
        playersEnforce.remove(playerName);
    }
    final long time = System.currentTimeMillis();
    if (player.isSprinting() || cc.assumeSprint) {
        // TODO: Collect all these properties within a context object (abstraction + avoid re-fetching).
        if (player.getFoodLevel() > 5 || player.getAllowFlight() || player.isFlying()) {
            data.timeSprinting = time;
            data.multSprinting = attributeAccess.getHandle().getSprintAttributeMultiplier(player);
            if (data.multSprinting == Double.MAX_VALUE) {
                data.multSprinting = 1.30000002;
            } else if (cc.assumeSprint && data.multSprinting == 1.0) {
                // Server side can be inconsistent, so the multiplier might be plain wrong (1.0).
                // TODO: Could be more/less than actual, but "infinite" latency would not work either.
                data.multSprinting = 1.30000002;
            }
        } else if (time < data.timeSprinting) {
            data.timeSprinting = 0;
        } else {
        // keep sprinting time.
        }
    } else if (time < data.timeSprinting) {
        data.timeSprinting = 0;
    }
    // Prepare locations for use.
    // TODO: Block flags might not be needed if neither sf nor passable get checked.
    final PlayerLocation pFrom, pTo;
    pFrom = moveInfo.from;
    pTo = moveInfo.to;
    // HOT FIX - for VehicleLeaveEvent missing.
    if (data.wasInVehicle) {
        vehicleChecks.onVehicleLeaveMiss(player, data, cc, pData);
    }
    // Set some data for this move.
    final PlayerMoveData thisMove = data.playerMoves.getCurrentMove();
    thisMove.set(pFrom, pTo);
    if (multiMoveCount > 0) {
        thisMove.multiMoveCount = multiMoveCount;
    }
    final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
    // Potion effect "Jump".
    /*
         * TODO: Jump amplifier should be set in PlayerMoveData, and/or only get
         * updated for lift off (?).
         */
    final double jumpAmplifier = aux.getJumpAmplifier(player);
    if (jumpAmplifier > data.jumpAmplifier) {
        data.jumpAmplifier = jumpAmplifier;
    }
    // TODO: same for speed (once medium is introduced).
    // Velocity tick (decrease + invalidation).
    // TODO: Rework to generic (?) queued velocity entries: activation + invalidation
    final int tick = TickTask.getTick();
    data.velocityTick(tick - cc.velocityActivationTicks);
    // Check which fly check to use.
    final boolean checkCf;
    final boolean checkSf;
    if (MovingUtil.shouldCheckSurvivalFly(player, pFrom, data, cc, pData)) {
        checkCf = false;
        checkSf = true;
        data.adjustWalkSpeed(player.getWalkSpeed(), tick, cc.speedGrace);
    } else if (pData.isDebugActive(CheckType.MOVING_CREATIVEFLY)) {
        checkCf = true;
        checkSf = false;
        prepareCreativeFlyCheck(player, from, to, moveInfo, thisMove, multiMoveCount, tick, data, cc);
    } else {
        checkCf = checkSf = false;
    // (thisMove.flyCheck stays null.)
    }
    // Pre-check checks (hum), either for cf or for sf.
    boolean checkNf = true;
    BounceType verticalBounce = BounceType.NO_BOUNCE;
    // TODO: More adaptive margin / method (bounding boxes).
    final boolean useBlockChangeTracker;
    final double previousSetBackY;
    final boolean checkPassable = pData.isCheckActive(CheckType.MOVING_PASSABLE, player);
    if (checkSf || checkCf) {
        previousSetBackY = data.hasSetBack() ? data.getSetBackY() : Double.NEGATIVE_INFINITY;
        // Ensure we have a set back set.
        MovingUtil.checkSetBack(player, pFrom, data, pData, this);
        // Check for special cross world teleportation issues with the end.
        if (data.crossWorldFrom != null) {
            if (// Safety check.
            !TrigUtil.isSamePosAndLook(pFrom, pTo) && TrigUtil.isSamePosAndLook(pTo, data.crossWorldFrom)) {
                // Assume to (and possibly the player location) to be set to the location the player teleported from within the other world.
                // (OK, cross-world)
                newTo = data.getSetBack(from);
                checkNf = false;
                NCPAPIProvider.getNoCheatPlusAPI().getLogManager().warning(Streams.STATUS, CheckUtils.getLogMessagePrefix(player, CheckType.MOVING) + " Player move end point seems to be set wrongly.");
            }
            // Always reset.
            data.crossWorldFrom = null;
        }
        // Extreme move check (sf or cf is precondition, should have their own config/actions later).
        if (newTo == null && ((Math.abs(thisMove.yDistance) > Magic.EXTREME_MOVE_DIST_VERTICAL) || thisMove.hDistance > Magic.EXTREME_MOVE_DIST_HORIZONTAL)) {
            // Test for friction and velocity.
            newTo = checkExtremeMove(player, pFrom, pTo, data, cc);
            if (newTo != null) {
                thisMove.flyCheck = checkSf ? CheckType.MOVING_SURVIVALFLY : CheckType.MOVING_CREATIVEFLY;
            }
        }
        useBlockChangeTracker = newTo == null && cc.trackBlockMove && (checkPassable || checkSf || checkCf) && blockChangeTracker.hasActivityShuffled(from.getWorld().getUID(), pFrom, pTo, 1.5625);
        // Detect bounce type / use prepared bounce.
        if (newTo == null) {
            // TODO: With past states: What does jump effects do here?
            if (thisMove.yDistance < 0.0) {
                // TODO: Check if really leads to calling the method for pistons (checkBounceEnvelope vs. push).
                if (!survivalFly.isReallySneaking(player) && checkBounceEnvelope(player, pFrom, pTo, data, cc, pData)) {
                    // 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;
                        // Skip NoFall.
                        checkNf = false;
                    }
                    if (verticalBounce == BounceType.NO_BOUNCE && useBlockChangeTracker) {
                        if (checkPastStateBounceDescend(player, pFrom, pTo, thisMove, lastMove, tick, data, cc) != BounceType.NO_BOUNCE) {
                            // Not set verticalBounce, as this is ascending and it's already force used.
                            // Skip NoFall.
                            checkNf = false;
                        }
                    }
                }
            } 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 && // 0-dist moves count in: && thisMove.yDistance >= 0.415
                thisMove.yDistance <= // TODO: MAGIC
                1.515) {
                    verticalBounce = checkPastStateBounceAscend(player, pFrom, pTo, thisMove, lastMove, tick, debug, data, cc);
                    if (verticalBounce != BounceType.NO_BOUNCE) {
                        checkNf = false;
                    }
                }
            }
        }
    } else {
        // TODO: Might still allow block change tracker with only passable enabled.
        useBlockChangeTracker = false;
        previousSetBackY = Double.NEGATIVE_INFINITY;
    }
    // Check passable first to prevent set back override.
    // TODO: Redesign to set set backs later (queue + invalidate).
    // If to skip nofall check (mainly on violation of other checks).
    boolean mightSkipNoFall = false;
    if (newTo == null && checkPassable && player.getGameMode() != BridgeMisc.GAME_MODE_SPECTATOR) {
        // 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, pData, tick, useBlockChangeTracker);
        if (newTo != null) {
            // Check if to skip the nofall check.
            mightSkipNoFall = true;
        }
    }
    // Flying checks.
    if (checkSf) {
        // SurvivalFly
        // Prepare from, to, thisMove for full checking.
        // TODO: Could further differentiate if really needed to (newTo / NoFall).
        MovingUtil.prepareFullCheck(pFrom, pTo, thisMove, Math.max(cc.noFallyOnGround, cc.yOnGround));
        // Hack: Add velocity for transitions between creativefly and survivalfly.
        if (lastMove.toIsValid && lastMove.flyCheck == CheckType.MOVING_CREATIVEFLY) {
            workaroundFlyNoFlyTransition(player, tick, debug, data);
        }
        // Actual check.
        if (newTo == null) {
            // Only check if passable has not already set back.
            thisMove.flyCheck = CheckType.MOVING_SURVIVALFLY;
            newTo = survivalFly.check(player, pFrom, pTo, multiMoveCount, data, cc, pData, tick, time, useBlockChangeTracker);
        }
        // Only check NoFall, if not already vetoed.
        if (checkNf) {
            checkNf = noFall.isEnabled(player, pData);
        }
        if (newTo == null) {
            // TODO: Could reset for from-on-ground as well, for not too big moves.
            if (cc.sfHoverCheck && !(lastMove.toIsValid && lastMove.to.extraPropertiesValid && lastMove.to.onGroundOrResetCond) && !pTo.isOnGround()) {
                // Start counting ticks.
                hoverTicks.add(playerName);
                data.sfHoverTicks = 0;
            } else {
                data.sfHoverTicks = -1;
            }
            // NoFall.
            if (checkNf) {
                noFall.check(player, pFrom, pTo, previousSetBackY, data, cc, pData);
            }
        } else {
            if (checkNf && cc.sfSetBackPolicyFallDamage) {
                if (!noFall.willDealFallDamage(player, from.getY(), previousSetBackY, data)) {
                    // TODO: Consider making this / damage amount configurable.
                    mightSkipNoFall = true;
                } else if (mightSkipNoFall) {
                    // Check if to really skip.
                    if (!pFrom.isOnGround() && !pFrom.isResetCond()) {
                        mightSkipNoFall = false;
                    }
                }
                if (!mightSkipNoFall && (!pTo.isResetCond() || !pFrom.isResetCond())) {
                    // (Don't deal damage where no fall damage is possible.)
                    noFall.checkDamage(player, Math.min(from.getY(), to.getY()), data, pData);
                }
            }
        }
    } else if (checkCf) {
        // CreativeFly
        if (newTo == null) {
            thisMove.flyCheck = CheckType.MOVING_CREATIVEFLY;
            newTo = creativeFly.check(player, pFrom, pTo, data, cc, pData, time, tick, useBlockChangeTracker);
        }
        data.sfHoverTicks = -1;
        data.sfLowJump = false;
    } else {
        // No fly checking :(.
        data.clearFlyData();
    }
    // Morepackets.
    if (pData.isCheckActive(CheckType.MOVING_MOREPACKETS, player) && (newTo == null || data.isMorePacketsSetBackOldest())) {
        /* (Always check morepackets, if there is a chance that setting/overriding newTo is appropriate,
            to avoid packet speeding using micro-violations.) */
        final Location mpNewTo = morePackets.check(player, pFrom, pTo, newTo == null, data, cc, pData);
        if (mpNewTo != null) {
            // Only override set back, if the morepackets set back location is older/-est.
            if (newTo != null && debug) {
                debug(player, "Override set back by the older morepackets set back.");
            }
            newTo = mpNewTo;
        }
    } else {
        // Otherwise we need to clear their data.
        data.clearPlayerMorePacketsData();
    }
    // Reset jump amplifier if needed.
    if ((checkSf || checkCf) && jumpAmplifier != data.jumpAmplifier) {
        // TODO: General cool-down for latency?
        if (thisMove.touchedGround || !checkSf && (pFrom.isOnGround() || pTo.isOnGround())) {
            // (No need to check from/to for onGround, if SurvivalFly is to be checked.)
            data.jumpAmplifier = jumpAmplifier;
        }
    }
    // Update BlockChangeTracker
    if (useBlockChangeTracker && data.blockChangeRef.firstSpanEntry != null) {
        if (debug) {
            debug(player, "BlockChangeReference: " + data.blockChangeRef.firstSpanEntry.tick + " .. " + data.blockChangeRef.lastSpanEntry.tick + " / " + tick);
        }
        data.blockChangeRef.updateFinal(pTo);
    }
    if (newTo == null) {
        // Allowed move.
        if (data.hasTeleported()) {
            data.resetTeleported();
            if (debug) {
                debug(player, "Ignore hook-induced set-back: actions not set to cancel.");
            }
        }
        // Bounce effects.
        if (verticalBounce != BounceType.NO_BOUNCE) {
            processBounce(player, pFrom.getY(), pTo.getY(), verticalBounce, tick, debug, data, cc, pData);
        }
        // Finished move processing.
        if (processingEvents.containsKey(playerName)) {
            // Normal processing.
            // TODO: More simple: UUID keys or a data flag instead?
            data.playerMoves.finishCurrentMove();
        } else {
            // Teleport during violation processing, just invalidate thisMove.
            thisMove.invalidate();
        }
        // Increase time since set back.
        data.timeSinceSetBack++;
        return false;
    } else {
        if (data.hasTeleported()) {
            if (debug) {
                debug(player, "The set back has been overridden from (" + newTo + ") to: " + data.getTeleported());
            }
            newTo = data.getTeleported();
        }
        if (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.
        prepareSetBack(player, event, newTo, data, cc, pData);
        // Prevent freezing (e.g. ascending with gliding set in water, but moving normally).
        if ((thisMove.flyCheck == CheckType.MOVING_SURVIVALFLY || thisMove.flyCheck == CheckType.MOVING_CREATIVEFLY && pFrom.isInLiquid()) && Bridge1_9.isGlidingWithElytra(player)) {
            stopGliding(player);
        }
        return true;
    }
}
Also used : PlayerMoveData(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData) PlayerLocation(fr.neatmonster.nocheatplus.utilities.location.PlayerLocation) PlayerLocation(fr.neatmonster.nocheatplus.utilities.location.PlayerLocation) Location(org.bukkit.Location)

Example 3 with PlayerMoveData

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

the class MovingListener method onPlayerMove.

/**
 * When a player moves, they will be checked for various suspicious behaviors.<br>
 * (lowest priority)
 *
 * @param event
 *            the event
 */
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerMove(final PlayerMoveEvent event) {
    counters.add(idMoveEvent, 1);
    final Player player = event.getPlayer();
    // Store the event for monitor level checks.
    processingEvents.put(player.getName(), event);
    final IPlayerData pData = DataManager.getPlayerData(player);
    final MovingConfig cc = pData.getGenericInstance(MovingConfig.class);
    final MovingData data = pData.getGenericInstance(MovingData.class);
    data.increasePlayerMoveCount();
    /*
         * TODO: Check if teleportation is set, verify if scheduled (tick task).
         * Early return / adapt, if necessary.
         */
    final Location from = event.getFrom();
    final Location to = event.getTo();
    Location newTo = null;
    // // Check problematic yaw/pitch values.
    // if (LocUtil.needsDirectionCorrection(from.getYaw(), from.getPitch())
    // || LocUtil.needsDirectionCorrection(to.getYaw(), to.getPitch())) {
    // DataManager.getPlayerData(player).task.correctDirection();
    // }
    // TODO: Check illegal moves here anyway (!).
    // TODO: Check if vehicle move logs correctly (fake).
    // Early return checks (no full processing).
    final boolean earlyReturn;
    final String token;
    if (player.isInsideVehicle()) {
        // No full processing for players in vehicles.
        newTo = vehicleChecks.onPlayerMoveVehicle(player, from, to, data, pData);
        earlyReturn = true;
        token = "vehicle";
    } else if (player.isDead()) {
        // Ignore dead players.
        data.sfHoverTicks = -1;
        earlyReturn = true;
        token = "dead";
    } else if (player.isSleeping()) {
        // Ignore sleeping playerrs.
        // TODO: sleeping: (which cb!) debug(player, "isSleepingIgnored=" + player.isSleepingIgnored());
        data.sfHoverTicks = -1;
        earlyReturn = true;
        token = "sleeping";
    } else if (!from.getWorld().equals(to.getWorld())) {
        // Keep hover ticks.
        // Ignore changing worlds.
        earlyReturn = true;
        token = "worldchange";
    } else if (data.hasTeleported()) {
        earlyReturn = handleTeleportedOnMove(player, event, data, cc, pData);
        token = "awaitsetback";
    } else {
        earlyReturn = false;
        token = null;
    }
    final boolean debug = pData.isDebugActive(checkType);
    // TODO: Might log base parts here (+extras).
    if (earlyReturn) {
        // TODO: Log "early return: " + tags.
        if (debug) {
            debug(player, "Early return" + (token == null ? "" : (" (" + token + ")")) + " on PlayerMoveEvent: from: " + from + " , to: " + to);
        }
        if (newTo != null) {
            // Illegal Yaw/Pitch.
            if (LocUtil.needsYawCorrection(newTo.getYaw())) {
                newTo.setYaw(LocUtil.correctYaw(newTo.getYaw()));
            }
            if (LocUtil.needsPitchCorrection(newTo.getPitch())) {
                newTo.setPitch(LocUtil.correctPitch(newTo.getPitch()));
            }
            // Set.
            // Logs set back details.
            prepareSetBack(player, event, newTo, data, cc, pData);
        }
        data.joinOrRespawn = false;
        return;
    }
    // newTo should be null here.
    // Fire one or two moves here.
    final PlayerMoveInfo moveInfo = aux.usePlayerMoveInfo();
    final Location loc = player.getLocation(moveInfo.useLoc);
    final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
    if (cc.loadChunksOnMove) {
        MovingUtil.ensureChunksLoaded(player, from, to, lastMove, "move", cc, pData);
    }
    // TODO: On pistons pulling the player back: -1.15 yDistance for split move 1 (untracked position > 0.5 yDistance!).
    if (// Handling split moves has been disabled.
    !cc.splitMoves || // The usual case: no micro move happened.
    TrigUtil.isSamePos(from, loc) || // Special case / bug? TODO: Which/why, which version of MC/spigot?
    lastMove.valid && TrigUtil.isSamePos(loc, lastMove.from.getX(), lastMove.from.getY(), lastMove.from.getZ())) // Could also be other envelopes (0.9 velocity upwards), too tedious to research.
    // && data.lastYDist < -SurvivalFly.GRAVITY_MIN && data.lastYDist > -SurvivalFly.GRAVITY_MAX - SurvivalFly.GRAVITY_MIN
    {
        // Fire move from -> to
        // (Special case: Location has not been updated last moving event.)
        moveInfo.set(player, from, to, cc.yOnGround);
        checkPlayerMove(player, from, to, 0, moveInfo, debug, data, cc, pData, event);
    } else {
        // 1. Process from -> loc.
        if (debug) {
            debug(player, "Split move 1 (from -> loc):");
        }
        moveInfo.set(player, from, loc, cc.yOnGround);
        if (!checkPlayerMove(player, from, loc, 1, moveInfo, debug, data, cc, pData, event) && processingEvents.containsKey(player.getName())) {
            // Between -> set data accordingly (compare: onPlayerMoveMonitor).
            onMoveMonitorNotCancelled(player, from, loc, System.currentTimeMillis(), TickTask.getTick(), pData.getGenericInstance(CombinedData.class), data, cc, pData);
            data.joinOrRespawn = false;
            // 2. Process loc -> to.
            if (debug) {
                debug(player, "Split move 2 (loc -> to):");
            }
            moveInfo.set(player, loc, to, cc.yOnGround);
            checkPlayerMove(player, loc, to, 2, moveInfo, debug, data, cc, pData, event);
        }
    }
    // Cleanup.
    data.joinOrRespawn = false;
    aux.returnPlayerMoveInfo(moveInfo);
}
Also used : Player(org.bukkit.entity.Player) PlayerMoveData(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData) IPlayerData(fr.neatmonster.nocheatplus.players.IPlayerData) CombinedData(fr.neatmonster.nocheatplus.checks.combined.CombinedData) PlayerMoveInfo(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveInfo) PlayerLocation(fr.neatmonster.nocheatplus.utilities.location.PlayerLocation) Location(org.bukkit.Location) EventHandler(org.bukkit.event.EventHandler)

Example 4 with PlayerMoveData

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

the class MovingListener method playerLeaves.

@Override
public void playerLeaves(final Player player) {
    final IPlayerData pData = DataManager.getPlayerData(player);
    final MovingData data = pData.getGenericInstance(MovingData.class);
    final Location loc = player.getLocation(useLoc);
    // Debug logout.
    if (pData.isDebugActive(checkType)) {
        StaticLog.logInfo("Player " + player.getName() + " leaves at location: " + loc.toString());
    }
    if (!player.isSleeping() && !player.isDead()) {
        // TODO: Consider to catch all, at least (debug-) logging-wise.
        if (!BlockProperties.isPassable(loc)) {
            final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
            if (lastMove.toIsValid) {
                final Location refLoc = new Location(loc.getWorld(), lastMove.to.getX(), lastMove.to.getY(), lastMove.to.getZ());
                final double d = refLoc.distanceSquared(loc);
                if (d > 0.0) {
                    // TODO: Consider to always set back here. Might skip on big distances.
                    if (TrigUtil.manhattan(loc, refLoc) > 0 || BlockProperties.isPassable(refLoc)) {
                        if (passable.isEnabled(player, pData)) {
                            StaticLog.logWarning("Potential exploit: Player " + player.getName() + " leaves, having moved into a block (not tracked by moving checks): " + player.getWorld().getName() + " / " + DebugUtil.formatMove(refLoc, loc));
                            // TODO: Actually trigger a passable violation (+tag).
                            if (d > 1.25) {
                                StaticLog.logWarning("SKIP set back for " + player.getName() + ", because distance is too high (risk of false positives): " + d);
                            } else {
                                StaticLog.logInfo("Set back player " + player.getName() + ": " + LocUtil.simpleFormat(refLoc));
                                data.prepareSetBack(refLoc);
                                if (!player.teleport(refLoc, BridgeMisc.TELEPORT_CAUSE_CORRECTION_OF_POSITION)) {
                                    StaticLog.logWarning("FAILED to set back player " + player.getName());
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    useLoc.setWorld(null);
    // Adjust data.
    survivalFly.setReallySneaking(player, false);
    noFall.onLeave(player, data, pData);
    // TODO: Add a method for ordinary presence-change resetting (use in join + leave).
    data.onPlayerLeave();
    if (data.vehicleSetBackTaskId != -1) {
        // Reset the id, assume the task will still teleport the vehicle.
        // TODO: Should rather force teleport (needs storing the task + data).
        data.vehicleSetBackTaskId = -1;
    }
}
Also used : PlayerMoveData(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData) IPlayerData(fr.neatmonster.nocheatplus.players.IPlayerData) PlayerLocation(fr.neatmonster.nocheatplus.utilities.location.PlayerLocation) Location(org.bukkit.Location)

Example 5 with PlayerMoveData

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

the class MovingListener method checkExtremeMove.

/**
 * Check for extremely large moves. Initial intention is to prevent cheaters
 * from creating extreme load. SurvivalFly or CreativeFly is needed.
 *
 * @param player
 * @param from
 * @param to
 * @param data
 * @param cc
 * @return
 */
@SuppressWarnings("unused")
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.
    // h + v violation (full move).
    double violation = 0.0;
    // Vertical move.
    // TODO: Configurable
    final boolean allowVerticalVelocity = false;
    if (Math.abs(thisMove.yDistance) > Magic.EXTREME_MOVE_DIST_VERTICAL) {
        // About -1.85 seems to be the negative maximum for velocity use in survival mode. Falling can result in slightly less than -3.
        if (lastMove.toIsValid && Math.abs(thisMove.yDistance) < Math.abs(lastMove.yDistance) && (thisMove.yDistance > 0.0 && lastMove.yDistance > 0.0 || thisMove.yDistance < 0.0 && lastMove.yDistance < 0.0) || allowVerticalVelocity && data.getOrUseVerticalVelocity(thisMove.yDistance) != null) {
        // Speed decreased or velocity is present.
        } else {
            // Violation.
            // Could subtract lastMove.yDistance.
            violation += thisMove.yDistance;
        }
    }
    // Horizontal move.
    if (thisMove.hDistance > Magic.EXTREME_MOVE_DIST_HORIZONTAL) {
        // Exclude valid moves first.
        // TODO: Attributes might allow unhealthy moves as well.
        // Observed maximum use so far: 5.515
        // TODO: Velocity flag too (if combined with configurable distances)?
        // Will change with model change.
        final double amount = thisMove.hDistance - data.getHorizontalFreedom();
        if (amount < 0.0 || lastMove.toIsValid && thisMove.hDistance - lastMove.hDistance <= 0.0 || data.useHorizontalVelocity(amount) >= amount) {
        // Speed decreased or velocity is present.
        } else {
            // Violation.
            // Could subtract lastMove.yDistance.
            violation += thisMove.hDistance;
        }
    }
    if (violation > 0.0) {
        // Ensure a set back location is present.
        if (!data.hasSetBack()) {
            data.setSetBack(from);
        }
        // Process violation as sub check of the appropriate fly check.
        violation *= 100.0;
        final Check check;
        final ActionList actions;
        final double vL;
        if (thisMove.flyCheck == CheckType.MOVING_SURVIVALFLY) {
            check = survivalFly;
            actions = cc.survivalFlyActions;
            data.survivalFlyVL += violation;
            vL = data.survivalFlyVL;
        } else {
            check = creativeFly;
            actions = cc.creativeFlyActions;
            data.creativeFlyVL += violation;
            vL = data.creativeFlyVL;
        }
        final ViolationData vd = new ViolationData(check, player, vL, violation, actions);
        // TODO: Reduce copy and paste (method to fill in locations, once using exact coords and latering default actions).
        if (vd.needsParameters()) {
            vd.setParameter(ParameterName.LOCATION_FROM, String.format(Locale.US, "%.2f, %.2f, %.2f", from.getX(), from.getY(), from.getZ()));
            vd.setParameter(ParameterName.LOCATION_TO, String.format(Locale.US, "%.2f, %.2f, %.2f", to.getX(), to.getY(), to.getZ()));
            vd.setParameter(ParameterName.DISTANCE, String.format(Locale.US, "%.2f", TrigUtil.distance(from, to)));
            vd.setParameter(ParameterName.TAGS, "EXTREME_MOVE");
        }
        // Some resetting is done in MovingListener.
        if (check.executeActions(vd).willCancel()) {
            // Set back + view direction of to (more smooth).
            return MovingUtil.getApplicableSetBackLocation(player, to.getYaw(), to.getPitch(), from, data, cc);
        }
    }
    // No cancel intended.
    return null;
}
Also used : PlayerMoveData(fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData) Check(fr.neatmonster.nocheatplus.checks.Check) ActionList(fr.neatmonster.nocheatplus.actions.ActionList) ViolationData(fr.neatmonster.nocheatplus.checks.ViolationData)

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