mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-09-27 14:13:11 +02:00
[BLEEDING] Add the capability to load chunks on moving and teleporting.
Except with join/respawn, the methods will not load chunks if close by past moves have extra properties set, assuming the chunks are already loaded then.
This commit is contained in:
parent
3bfd3a7aff
commit
245f5389a0
@ -186,6 +186,9 @@ public class MovingConfig extends ACheckConfig {
|
||||
public final boolean ignoreStance;
|
||||
public final boolean tempKickIllegal;
|
||||
public final boolean loadChunksOnJoin;
|
||||
public final boolean loadChunksOnMove;
|
||||
public final boolean loadChunksOnTeleport;
|
||||
public final boolean loadChunksOnWorldChange;
|
||||
public final long sprintingGrace;
|
||||
public final boolean assumeSprint;
|
||||
public final int speedGrace;
|
||||
@ -308,6 +311,9 @@ public class MovingConfig extends ACheckConfig {
|
||||
ignoreStance = refIgnoreStance == AlmostBoolean.MAYBE ? ServerVersion.compareMinecraftVersion("1.8") >= 0 : refIgnoreStance.decide();
|
||||
tempKickIllegal = config.getBoolean(ConfPaths.MOVING_TEMPKICKILLEGAL);
|
||||
loadChunksOnJoin = config.getBoolean(ConfPaths.MOVING_LOADCHUNKS_JOIN);
|
||||
loadChunksOnMove = config.getBoolean(ConfPaths.MOVING_LOADCHUNKS_MOVE);
|
||||
loadChunksOnTeleport = config.getBoolean(ConfPaths.MOVING_LOADCHUNKS_TELEPORT);
|
||||
loadChunksOnWorldChange = config.getBoolean(ConfPaths.MOVING_LOADCHUNKS_WORLDCHANGE);
|
||||
sprintingGrace = Math.max(0L, (long) (config.getDouble(ConfPaths.MOVING_SPRINTINGGRACE) * 1000.0)); // Config: seconds.
|
||||
assumeSprint = config.getBoolean(ConfPaths.MOVING_ASSUMESPRINT);
|
||||
speedGrace = Math.max(0, (int) Math.round(config.getDouble(ConfPaths.MOVING_SPEEDGRACE) * 20.0)); // Config: seconds
|
||||
|
@ -308,6 +308,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
// TODO: Might omit this if neither check is activated.
|
||||
final Location loc = player.getLocation(useLoc);
|
||||
data.setSetBack(loc);
|
||||
if (cc.loadChunksOnWorldChange) {
|
||||
ensureChunksLoaded(player, loc, "world change", data, cc);
|
||||
}
|
||||
aux.resetPositionsAndMediumProperties(player, loc, data, cc);
|
||||
data.resetTrace(loc, TickTask.getTick(), cc);
|
||||
if (cc.enforceLocation) {
|
||||
@ -423,6 +426,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
final PlayerMoveInfo moveInfo = aux.usePlayerMoveInfo();
|
||||
final Location loc = player.getLocation(moveInfo.useLoc);
|
||||
final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
|
||||
if (cc.loadChunksOnMove) {
|
||||
ensureChunksLoaded(player, from, to, lastMove, data, cc);
|
||||
}
|
||||
// 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.
|
||||
@ -463,6 +469,89 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
aux.returnPlayerMoveInfo(moveInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure chunks are loaded so that the move can be processed at all. Assume
|
||||
* too big moves to be cancelled anyway and/or passable accounting for chunk
|
||||
* load.
|
||||
*
|
||||
* @param from
|
||||
* @param to
|
||||
* @param lastMove
|
||||
* @param data
|
||||
* @param cc
|
||||
*/
|
||||
private void ensureChunksLoaded(final Player player, final Location from, final Location to, final PlayerMoveData lastMove,
|
||||
final MovingData data, final MovingConfig cc) {
|
||||
// (Worlds must be equal. Ensured in player move handling.)
|
||||
final double x0 = from.getX();
|
||||
final double z0 = from.getZ();
|
||||
final double x1 = to.getX();
|
||||
final double z1 = to.getZ();
|
||||
if (TrigUtil.distanceSquared(x0, z0, x1, z1) > 2.0 * Magic.CHUNK_LOAD_MARGIN_MIN) {
|
||||
// Assume extreme move to trigger.
|
||||
return;
|
||||
}
|
||||
boolean loadFrom = true;
|
||||
boolean loadTo = true;
|
||||
double margin = Magic.CHUNK_LOAD_MARGIN_MIN;
|
||||
// Heuristic for if loading may be necessary at all.
|
||||
if (lastMove.toIsValid && lastMove.to.extraPropertiesValid) {
|
||||
if (TrigUtil.distanceSquared(lastMove.to, x0, z0) < 1.0) {
|
||||
loadFrom = false;
|
||||
}
|
||||
if (TrigUtil.distanceSquared(lastMove.to, x1, z1) < 1.0) {
|
||||
loadTo = false;
|
||||
}
|
||||
}
|
||||
else if (lastMove.valid && lastMove.from.extraPropertiesValid
|
||||
&& cc.loadChunksOnJoin) {
|
||||
// TODO: Might need to distinguish join/teleport/world-change later.
|
||||
if (TrigUtil.distanceSquared(lastMove.from, x0, z0) < 1.0) {
|
||||
loadFrom = false;
|
||||
}
|
||||
if (TrigUtil.distanceSquared(lastMove.from, x1, z1) < 1.0) {
|
||||
loadTo = false;
|
||||
}
|
||||
}
|
||||
int loaded = 0;
|
||||
if (loadFrom) {
|
||||
loaded += BlockCache.ensureChunksLoaded(from.getWorld(), x0, z0, margin);
|
||||
if (TrigUtil.distanceSquared(x0, z0, x1, z1) < 1.0) {
|
||||
loadTo = false;
|
||||
}
|
||||
}
|
||||
if (loadTo) {
|
||||
loaded += BlockCache.ensureChunksLoaded(to.getWorld(), x1, z1, margin);
|
||||
}
|
||||
if (loaded > 0 && data.debug) {
|
||||
StaticLog.logInfo("Player move: Loaded " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + from.getWorld().getName() + " for player: " + player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureChunksLoaded(final Player player, final Location loc, final String tag,
|
||||
final MovingData data, final MovingConfig cc) {
|
||||
final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
|
||||
final double x0 = loc.getX();
|
||||
final double z0 = loc.getZ();
|
||||
// Heuristic for if loading may be necessary at all.
|
||||
if (lastMove.toIsValid && lastMove.to.extraPropertiesValid) {
|
||||
if (TrigUtil.distanceSquared(lastMove.to, x0, z0) < 1.0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (lastMove.valid && lastMove.from.extraPropertiesValid
|
||||
&& cc.loadChunksOnJoin) {
|
||||
// TODO: Might need to distinguish join/teleport/world-change later.
|
||||
if (TrigUtil.distanceSquared(lastMove.from, x0, z0) < 1.0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
int loaded = BlockCache.ensureChunksLoaded(loc.getWorld(), loc.getX(), loc.getZ(), Magic.CHUNK_LOAD_MARGIN_MIN);
|
||||
if (loaded > 0 && data.debug) {
|
||||
StaticLog.logInfo("Player " + tag + ": Loaded " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + loc.getWorld().getName() + " for player: " + player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param player
|
||||
@ -882,6 +971,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
// 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)?
|
||||
final double amount = thisMove.hDistance - data.getHorizontalFreedom(); // Will change with model change.
|
||||
@ -1237,13 +1327,18 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
// Teleport to untracked locations.
|
||||
else if (cause == TeleportCause.COMMAND) { // TODO: TeleportCause.PLUGIN?
|
||||
// Attempt to prevent teleporting to players inside of blocks at untracked coordinates.
|
||||
if (cc.passableUntrackedTeleportCheck && MovingUtil.shouldCheckUntrackedLocation(player, to)) {
|
||||
final Location newTo = MovingUtil.checkUntrackedLocation(to);
|
||||
if (newTo != null) {
|
||||
// Adjust the teleport to go to the last tracked to-location of the other player.
|
||||
event.setTo(newTo);
|
||||
// TODO: Consider console, consider data.debug.
|
||||
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().warning(Streams.TRACE_FILE, player.getName() + " correct untracked teleport destination (" + to + " corrected to " + newTo + ").");
|
||||
if (cc.passableUntrackedTeleportCheck) {
|
||||
if (cc.loadChunksOnTeleport) {
|
||||
ensureChunksLoaded(player, to, "teleport", data, cc);
|
||||
}
|
||||
if (cc.passableUntrackedTeleportCheck && MovingUtil.shouldCheckUntrackedLocation(player, to)) {
|
||||
final Location newTo = MovingUtil.checkUntrackedLocation(to);
|
||||
if (newTo != null) {
|
||||
// Adjust the teleport to go to the last tracked to-location of the other player.
|
||||
event.setTo(newTo);
|
||||
// TODO: Consider console, consider data.debug.
|
||||
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().warning(Streams.TRACE_FILE, player.getName() + " correct untracked teleport destination (" + to + " corrected to " + newTo + ").");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1339,6 +1434,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
final Location teleported = data.getTeleported();
|
||||
final PlayerMoveInfo moveInfo = aux.usePlayerMoveInfo();
|
||||
moveInfo.set(player, teleported, null, cc.yOnGround);
|
||||
if (cc.loadChunksOnTeleport) {
|
||||
ensureChunksLoaded(player, teleported, "teleport", data, cc);
|
||||
}
|
||||
data.onSetBack(moveInfo.from);
|
||||
aux.returnPlayerMoveInfo(moveInfo);
|
||||
|
||||
@ -1377,6 +1475,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
data.clearPlayerMorePacketsData();
|
||||
data.setSetBack(to);
|
||||
data.sfHoverTicks = -1; // Important against concurrent modification exception.
|
||||
if (cc.loadChunksOnTeleport) {
|
||||
ensureChunksLoaded(player, to, "teleport", data, cc);
|
||||
}
|
||||
aux.resetPositionsAndMediumProperties(player, to, data, cc);
|
||||
// TODO: Decide to remove the LiftOffEnvelope thing completely.
|
||||
// if (TrigUtil.maxDistance(from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ()) <= 12.0) {
|
||||
@ -1565,9 +1666,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
final String tag = isRespawn ? "Respawn" : "Join";
|
||||
// Check loaded chunks.
|
||||
if (cc.loadChunksOnJoin) {
|
||||
final int loaded = BlockCache.ensureChunksLoaded(loc.getWorld(), loc.getX(), loc.getZ(), 3.0);
|
||||
if (loaded > 0 && data.debug && BuildParameters.debugLevel > 0) {
|
||||
// DEBUG
|
||||
// (Don't use past-move heuristic for skipping here.)
|
||||
final int loaded = BlockCache.ensureChunksLoaded(loc.getWorld(), loc.getX(), loc.getZ(), Magic.CHUNK_LOAD_MARGIN_MIN);
|
||||
if (loaded > 0 && data.debug) {
|
||||
StaticLog.logInfo("Player " + tag + ": Loaded " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + loc.getWorld().getName() + " for player: " + player.getName());
|
||||
}
|
||||
}
|
||||
@ -1854,7 +1955,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
||||
final boolean res;
|
||||
// TODO: Collect flags, more margin ?
|
||||
final int loaded = info.from.ensureChunksLoaded();
|
||||
if (loaded > 0 && data.debug && BuildParameters.debugLevel > 0) {
|
||||
if (loaded > 0 && data.debug) {
|
||||
// DEBUG
|
||||
StaticLog.logInfo("Hover check: Needed to load " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + loc.getWorld().getName() + " around " + loc.getBlockX() + "," + loc.getBlockZ() + " in order to check player: " + player.getName());
|
||||
}
|
||||
|
@ -100,6 +100,8 @@ public class Magic {
|
||||
*/
|
||||
public static final double EXTREME_MOVE_DIST_VERTICAL = 4.0;
|
||||
public static final double EXTREME_MOVE_DIST_HORIZONTAL = 22.0;
|
||||
/** Minimal xz-margin for chunk load. */
|
||||
public static final double CHUNK_LOAD_MARGIN_MIN = 3.0;
|
||||
|
||||
/**
|
||||
* The absolute per-tick base speed for swimming vertically.
|
||||
|
@ -644,6 +644,9 @@ public abstract class ConfPaths {
|
||||
// TODO: Might add a section for illegal move.
|
||||
private static final String MOVING_LOADCHUNKS = MOVING + "loadchunks.";
|
||||
public static final String MOVING_LOADCHUNKS_JOIN = MOVING_LOADCHUNKS + "join";
|
||||
public static final String MOVING_LOADCHUNKS_MOVE = MOVING_LOADCHUNKS + "move";
|
||||
public static final String MOVING_LOADCHUNKS_TELEPORT = MOVING_LOADCHUNKS + "teleport";
|
||||
public static final String MOVING_LOADCHUNKS_WORLDCHANGE = MOVING_LOADCHUNKS + "worldchange";
|
||||
public static final String MOVING_SPRINTINGGRACE = MOVING + "sprintinggrace";
|
||||
public static final String MOVING_ASSUMESPRINT = MOVING + "assumesprint";
|
||||
public static final String MOVING_SPEEDGRACE = MOVING + "speedgrace";
|
||||
|
@ -455,6 +455,9 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.MOVING_IGNORESTANCE, "default");
|
||||
set(ConfPaths.MOVING_TEMPKICKILLEGAL, true);
|
||||
set(ConfPaths.MOVING_LOADCHUNKS_JOIN, true);
|
||||
set(ConfPaths.MOVING_LOADCHUNKS_MOVE, true);
|
||||
set(ConfPaths.MOVING_LOADCHUNKS_TELEPORT, true);
|
||||
set(ConfPaths.MOVING_LOADCHUNKS_WORLDCHANGE, true);
|
||||
set(ConfPaths.MOVING_SPRINTINGGRACE, 2.0);
|
||||
set(ConfPaths.MOVING_ASSUMESPRINT, true);
|
||||
set(ConfPaths.MOVING_SPEEDGRACE, 4.0);
|
||||
|
@ -288,6 +288,17 @@ public class TrigUtil {
|
||||
return distanceSquared(location1.getX(), location1.getY(), location1.getZ(), location2.getX(), location2.getY(), location2.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Horizontal: squared distance.
|
||||
* @param location1
|
||||
* @param x1
|
||||
* @return
|
||||
*/
|
||||
public static final double distanceSquared(final IGetPosition location, final double x, final double z)
|
||||
{
|
||||
return distanceSquared(location.getX(), location.getZ(), x, z);
|
||||
}
|
||||
|
||||
public static final double distanceSquared(final IGetPosition location1, final Location location2)
|
||||
{
|
||||
return distanceSquared(location1.getX(), location1.getY(), location1.getZ(), location2.getX(), location2.getY(), location2.getZ());
|
||||
|
Loading…
Reference in New Issue
Block a user