use of fr.neatmonster.nocheatplus.checks.net.model.CountableLocation in project NoCheatPlus by NoCheatPlus.
the class MovingUtil method processStoredSetBack.
/**
* @param player
* @param debugMessagePrefix
* @return True, if the teleport has been successful.
*/
public static boolean processStoredSetBack(final Player player, final String debugMessagePrefix, final IPlayerData pData) {
final MovingData data = pData.getGenericInstance(MovingData.class);
final boolean debug = pData.isDebugActive(CheckType.MOVING);
if (!data.hasTeleported()) {
if (debug) {
CheckUtils.debug(player, CheckType.MOVING, debugMessagePrefix + "No stored location available.");
}
return false;
}
// (teleported is set.).
final Location loc = player.getLocation(useLoc);
if (data.isTeleportedPosition(loc)) {
// Skip redundant teleport.
if (debug) {
CheckUtils.debug(player, CheckType.MOVING, debugMessagePrefix + "Skip teleport, player is there, already.");
}
// Not necessary to keep.
data.resetTeleported();
useLoc.setWorld(null);
return false;
}
useLoc.setWorld(null);
// (player is somewhere else.)
// Post-1.9 packet level workaround.
final MovingConfig cc = pData.getGenericInstance(MovingConfig.class);
// TODO: Consider to skip checking for packet level, if not available (plus optimize access).
// TODO: Consider a config flag, so this can be turned off (set back method).
final PlayerSetBackMethod method = cc.playerSetBackMethod;
if (!method.shouldNoRisk() && (method.shouldCancel() || method.shouldSetTo()) && method.shouldUpdateFrom()) {
/*
* Another leniency option: Skip, if we have already received an ACK
* for this position on packet level - typically the next move would
* confirm the set-back, but a redundant teleport would freeze the
* player for a slightly longer time. This could happen with the set
* back being at the coordinates the player had just been at, but
* between set back and on-tick there has been a micro move (not
* firing a PlayerMoveEvent) - similarly observed on a local test
* server once, HOWEVER there the micro move had been a look-only
* packet, not explaining why the position of the player wasn't
* reflecting the outgoing position. So here remains the uncertainty
* concerning the question if a (silent) Minecraft entity teleport
* always follows a cancelled PlayerMoveEvent (!), and a thinkable
* potential for abuse.
*/
// (CANCEL + UPDATE_FROM mean a certain teleport to the set back, still could be repeated tp.)
// TODO: Better method, full sync reference?
final CountableLocation cl = pData.getGenericInstance(NetData.class).teleportQueue.getLastAck();
if (data.isTeleportedPosition(cl)) {
if (debug) {
CheckUtils.debug(player, CheckType.MOVING, debugMessagePrefix + "Skip teleport, having received an ACK for the teleport on packet level. Player is at: " + LocUtil.simpleFormat(loc));
}
// Keep teleported in data. Subject to debug logs and/or discussion.
return false;
}
}
// (No ACK received yet.)
// Attempt to teleport.
final Location teleported = data.getTeleported();
// (Data resetting is done during PlayerTeleportEvent handling.)
if (player.teleport(teleported, BridgeMisc.TELEPORT_CAUSE_CORRECTION_OF_POSITION)) {
return true;
} else {
if (debug) {
CheckUtils.debug(player, CheckType.MOVING, "Player set back on tick: Teleport failed.");
}
return false;
}
}
use of fr.neatmonster.nocheatplus.checks.net.model.CountableLocation in project NoCheatPlus by NoCheatPlus.
the class OutgoingPosition method interpretPacket.
private void interpretPacket(final Player player, final PacketContainer packet, final long time, final NetData data, final boolean debug) {
final StructureModifier<Double> doubles = packet.getDoubles();
final StructureModifier<Float> floats = packet.getFloat();
if (doubles.size() != 3 || floats.size() != 2) {
packetMismatch(packet);
return;
}
// TODO: Detect/skip data with relative coordinates.
// TODO: Concept: force KeepAlive vs. set expected coordinates in Bukkit events.
final double x = doubles.read(indexX);
final double y = doubles.read(indexY);
final double z = doubles.read(indexZ);
final float yaw = floats.read(indexYaw);
final float pitch = floats.read(indexPitch);
Integer teleportId = Integer.MIN_VALUE;
if (hasTeleportId) {
try {
final StructureModifier<Integer> integers = packet.getIntegers();
if (integers.size() == 1) {
// Accept as id.
teleportId = integers.read(0);
if (teleportId == null) {
teleportId = Integer.MIN_VALUE;
}
if (teleportId != Integer.MIN_VALUE && debug) {
debug(player, "Outgoing confirm teleport id: " + teleportId);
}
} else {
hasTeleportId = false;
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().info(Streams.STATUS, "PacketPlayOutPosition: Teleport confirm id not available, field mismatch: " + integers.size());
}
} catch (Throwable t) {
hasTeleportId = false;
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().info(Streams.STATUS, "PacketPlayOutPosition: Teleport confirm id not available.");
}
}
final CountableLocation packetData = data.teleportQueue.onOutgoingTeleport(x, y, z, yaw, pitch, teleportId);
if (packetData == null) {
// Add counter for untracked (by Bukkit API) outgoing teleport.
// TODO: There may be other cases which are indicated by Bukkit API events.
counters.add(ID_OUTGOING_POSITION_UNTRACKED, 1);
if (debug) {
debug(player, "Untracked outgoing position: " + x + ", " + y + ", " + z + " (yaw=" + yaw + ", pitch=" + pitch + ").");
}
} else {
if (debug) {
debug(player, "Expect ACK on outgoing position: " + packetData);
}
}
}
Aggregations