Less object creation with short-use Locations + other preparation.

* Make use of Entity.getLocation(Location) in most places, for starters.
* Prepare a check for moving location consistency.
This commit is contained in:
asofold 2014-02-23 01:28:42 +01:00
parent 16db04f397
commit abdeb12377
23 changed files with 243 additions and 95 deletions

View File

@ -11,6 +11,9 @@ public class BlockCacheBukkit extends BlockCache{
protected World world;
/** Temporary use. Use LocUtil.clone before passing on. Call setWorld(null) after use. */
protected final Location useLoc = new Location(null, 0, 0, 0);
public BlockCacheBukkit(World world) {
setAccess(world);
}
@ -49,8 +52,9 @@ public class BlockCacheBukkit extends BlockCache{
if (type != EntityType.BOAT){ // && !(other instanceof Minecart))
continue;
}
final Location loc = entity.getLocation();
if (Math.abs(loc.getY() - minY) < 0.7){
final double locY = entity.getLocation(useLoc).getY();
useLoc.setWorld(null);
if (Math.abs(locY - minY) < 0.7){
// TODO: A "better" estimate is possible, though some more tolerance would be good.
return true;
}

View File

@ -13,6 +13,9 @@ import fr.neatmonster.nocheatplus.utilities.TrigUtil;
* The Direction check will find out if a player tried to interact with something that's not in their field of view.
*/
public class Direction extends Check {
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
private final Location useLoc = new Location(null, 0, 0, 0);
/**
* Instantiates a new direction check.
@ -36,7 +39,7 @@ public class Direction extends Check {
// How far "off" is the player with their aim. We calculate from the players eye location and view direction to
// the center of the target block. If the line of sight is more too far off, "off" will be bigger than 0.
final Location loc = player.getLocation();
final Location loc = player.getLocation(useLoc);
final Vector direction = loc.getDirection();
final double off = TrigUtil.directionCheck(loc, player.getEyeHeight(), direction, block, TrigUtil.DIRECTION_PRECISION);
@ -52,10 +55,11 @@ public class Direction extends Check {
// cancel the event.
cancel = executeActions(player, data.directionVL, distance,
BlockBreakConfig.getConfig(player).directionActions);
} else
} else {
// Player did likely nothing wrong, reduce violation counter to reward them.
data.directionVL *= 0.9D;
}
useLoc.setWorld(null);
return cancel;
}
}

View File

@ -3,6 +3,7 @@ package fr.neatmonster.nocheatplus.checks.blockbreak;
import java.util.Map;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
@ -16,6 +17,9 @@ import fr.neatmonster.nocheatplus.utilities.TrigUtil;
* The Reach check will find out if a player interacts with something that's too far away.
*/
public class Reach extends Check {
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
private final Location useLoc = new Location(null, 0, 0, 0);
/** The maximum distance allowed to interact with a block in creative mode. */
public static final double CREATIVE_DISTANCE = 5.6D;
@ -47,7 +51,10 @@ public class Reach extends Check {
// Distance is calculated from eye location to center of targeted block. If the player is further away from their
// target than allowed, the difference will be assigned to "distance".
final double distance = TrigUtil.distance(player.getEyeLocation(), block) - distanceLimit;
final Location loc = player.getLocation(useLoc);
loc.setY(loc.getY() + player.getEyeHeight());
final double distance = TrigUtil.distance(loc, block) - distanceLimit;
useLoc.setWorld(null);
if (distance > 0) {
// They failed, increment violation level.

View File

@ -36,6 +36,9 @@ public class BlockInteractListener extends CheckListener {
/** Speed of interaction. */
private final Speed speed = addCheck(new Speed());
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
private final Location useLoc = new Location(null, 0, 0, 0);
public BlockInteractListener(){
super(CheckType.BLOCKINTERACT);
}
@ -86,7 +89,7 @@ public class BlockInteractListener extends CheckListener {
boolean cancelled = false;
final BlockFace face = event.getBlockFace();
final Location loc = player.getLocation();
final Location loc = player.getLocation(useLoc);
// Interaction speed.
if (!cancelled && speed.isEnabled(player) && speed.check(player, data, cc)){
@ -114,5 +117,6 @@ public class BlockInteractListener extends CheckListener {
event.setUseItemInHand(Result.DENY);
event.setCancelled(true);
}
useLoc.setWorld(null);
}
}

View File

@ -75,6 +75,9 @@ public class BlockPlaceListener extends CheckListener {
/** The speed check. */
private final Speed speed = addCheck(new Speed());
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
private final Location useLoc = new Location(null, 0, 0, 0);
public BlockPlaceListener(){
super(CheckType.BLOCKPLACE);
}
@ -131,6 +134,7 @@ public class BlockPlaceListener extends CheckListener {
if (!cancelled && reach.isEnabled(player) && reach.check(player, block, data, cc)) {
cancelled = true;
}
useLoc.setWorld(null);
// Direction check.
if (!cancelled && direction.isEnabled(player) && direction.check(player, block, blockAgainst, data, cc)) {
@ -264,7 +268,7 @@ public class BlockPlaceListener extends CheckListener {
boolean cancel = false;
if (speed.isEnabled(player)){
final long now = System.currentTimeMillis();
final Location loc = player.getLocation();
final Location loc = player.getLocation(useLoc);
if (Combined.checkYawRate(player, loc.getYaw(), now, loc.getWorld().getName())){
// Yawrate (checked extra).
cancel = true;
@ -285,19 +289,20 @@ public class BlockPlaceListener extends CheckListener {
// Do nothing !
// TODO: Might have further flags?
}
else if (!BlockProperties.isPassable(projectile.getLocation())){
else if (!BlockProperties.isPassable(projectile.getLocation(useLoc))){
// Launch into a block.
// TODO: This might be a general check later.
cancel = true;
}
else{
if (!BlockProperties.isPassable(player.getEyeLocation(), projectile.getLocation())){
if (!BlockProperties.isPassable(player.getEyeLocation(), projectile.getLocation(useLoc))){
// (Spare a useLoc2, for this is seldom rather.)
// Something between player
// TODO: This might be a general check later.
cancel = true;
}
else{
final Material mat = player.getLocation().getBlock().getType();
final Material mat = player.getLocation(useLoc).getBlock().getType();
final long flags = BlockProperties.F_CLIMBABLE | BlockProperties.F_LIQUID | BlockProperties.F_IGN_PASSABLE;
if (mat != Material.AIR && (BlockProperties.getBlockFlags(mat.getId()) & flags) == 0 && !mcAccess.hasGravity(mat)){
// Still fails on piston traps etc.
@ -313,5 +318,7 @@ public class BlockPlaceListener extends CheckListener {
if (cancel){
event.setCancelled(true);
}
// Cleanup.
useLoc.setWorld(null);
}
}

View File

@ -13,6 +13,9 @@ import fr.neatmonster.nocheatplus.utilities.TrigUtil;
* The Direction check will find out if a player tried to interact with something that's not in their field of view.
*/
public class Direction extends Check {
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
private final Location useLoc = new Location(null, 0, 0, 0);
/**
* Instantiates a new direction check.
@ -38,7 +41,7 @@ public class Direction extends Check {
// How far "off" is the player with their aim. We calculate from the players eye location and view direction to
// the center of the target block. If the line of sight is more too far off, "off" will be bigger than 0.
final Location loc = player.getLocation();
final Location loc = player.getLocation(useLoc);
final Vector direction = loc.getDirection();
double off = TrigUtil.directionCheck(loc, player.getEyeHeight(), direction, against, TrigUtil.DIRECTION_PRECISION);
@ -75,10 +78,11 @@ public class Direction extends Check {
// Execute whatever actions are associated with this check and the violation level and find out if we should
// cancel the event.
cancel = executeActions(player, data.directionVL, distance, cc.directionActions);
} else
} else {
// Player did likely nothing wrong, reduce violation counter to reward them.
data.directionVL *= 0.9D;
}
useLoc.setWorld(null);
return cancel;
}
}

View File

@ -3,6 +3,7 @@ package fr.neatmonster.nocheatplus.checks.blockplace;
import java.util.Map;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
@ -22,6 +23,9 @@ public class Reach extends Check {
/** The maximum distance allowed to interact with a block in survival mode. */
public static final double SURVIVAL_DISTANCE = 5.2D;
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
private final Location useLoc = new Location(null, 0, 0, 0);
/**
* Instantiates a new reach check.
@ -35,6 +39,7 @@ public class Reach extends Check {
*
* @param player
* the player
* @param loc
* @param cc
* @param data2
* @param location
@ -49,7 +54,9 @@ public class Reach extends Check {
// Distance is calculated from eye location to center of targeted block. If the player is further away from their
// target than allowed, the difference will be assigned to "distance".
final double distance = TrigUtil.distance(player.getEyeLocation(), block) - distanceLimit;
final Location eyeLoc = player.getLocation(useLoc);
eyeLoc.setY(eyeLoc.getY() + player.getEyeHeight());
final double distance = TrigUtil.distance(eyeLoc, block) - distanceLimit;
if (distance > 0) {
// They failed, increment violation level.
@ -66,7 +73,9 @@ public class Reach extends Check {
data.reachVL *= 0.9D;
}
// Cleanup.
useLoc.setWorld(null);
return cancel;
}

View File

@ -49,7 +49,7 @@ public class Angle extends Check {
data.angleHits.remove(time);
// Add the new location to the map.
data.angleHits.put(System.currentTimeMillis(), player.getLocation());
data.angleHits.put(System.currentTimeMillis(), player.getLocation()); // This needs to be a copy at present.
// Not enough data to calculate deltas.
if (data.angleHits.size() < 2)

View File

@ -38,14 +38,11 @@ public class Critical extends Check {
* the player
* @return true, if successful
*/
public boolean check(final Player player) {
public boolean check(final Player player, final Location loc) {
final FightConfig cc = FightConfig.getConfig(player);
final FightData data = FightData.getData(player);
boolean cancel = false;
// We'll need the PlayerLocation to know some important stuff.
final Location loc = player.getLocation();
final float mcFallDistance = player.getFallDistance();
final MovingConfig mCc = MovingConfig.getConfig(player);

View File

@ -30,7 +30,7 @@ public class Direction extends Check {
* the damaged
* @return true, if successful
*/
public boolean check(final Player player, final Entity damaged) {
public boolean check(final Player player, final Location loc, final Entity damaged, final Location dLoc) {
final FightConfig cc = FightConfig.getConfig(player);
final FightData data = FightData.getData(player);
@ -47,14 +47,11 @@ public class Direction extends Check {
// entity.height is broken and will always be 0, therefore. Calculate height instead based on boundingBox.
final double height = mcAccess.getHeight(damaged);
final Location dLoc = damaged.getLocation();
// TODO: allow any hit on the y axis (might just adapt interface to use foot position + height)!
// How far "off" is the player with their aim. We calculate from the players eye location and view direction to
// the center of the target entity. If the line of sight is more too far off, "off" will be bigger than 0.
final Location loc = player.getLocation();
final Vector direction = player.getEyeLocation().getDirection();
final Vector direction = loc.getDirection();
final double off;
if (cc.directionStrict){

View File

@ -74,6 +74,12 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
/** The speed check. */
private final Speed speed = addCheck(new Speed());
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
private final Location useLoc1 = new Location(null, 0, 0, 0);
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
private final Location useLoc2 = new Location(null, 0, 0, 0);
public FightListener(){
super(CheckType.FIGHT);
}
@ -100,8 +106,8 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
final long now = System.currentTimeMillis();
final boolean worldChanged = !worldName.equals(data.lastWorld);
final Location loc = player.getLocation();
final Location targetLoc = damaged.getLocation();
final Location loc = player.getLocation(useLoc1);
final Location damagedLoc = damaged.getLocation(useLoc2);
// final double targetDist = CheckUtils.distance(loc, targetLoc); // TODO: Calculate distance as is done in fight.reach !
final double targetMove;
final int tickAge;
@ -118,7 +124,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
else{
tickAge = tick - data.lastAttackTick;
// TODO: Maybe use 3d distance if dy(normalized) is too big.
targetMove = TrigUtil.distance(data.lastAttackedX, data.lastAttackedZ, targetLoc.getX(), targetLoc.getZ());
targetMove = TrigUtil.distance(data.lastAttackedX, data.lastAttackedZ, damagedLoc.getX(), damagedLoc.getZ());
msAge = (long) (50f * TickTask.getLag(50L * tickAge) * (float) tickAge);
normalizedMove = msAge == 0 ? targetMove : targetMove * Math.min(20.0, 1000.0 / (double) msAge);
}
@ -188,39 +194,45 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
if (angle.check(player, worldChanged)) cancelled = true;
}
if (!cancelled && critical.isEnabled(player) && critical.check(player))
cancelled = true;
if (!cancelled && critical.isEnabled(player) && critical.check(player, loc)) {
cancelled = true;
}
if (!cancelled && knockback.isEnabled(player) && knockback.check(player))
cancelled = true;
if (!cancelled && knockback.isEnabled(player) && knockback.check(player)) {
cancelled = true;
}
if (!cancelled && noSwing.isEnabled(player) && noSwing.check(player))
cancelled = true;
if (!cancelled && noSwing.isEnabled(player) && noSwing.check(player)) {
cancelled = true;
}
if (!cancelled && player.isBlocking() && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_BLOCKING))
cancelled = true;
if (!cancelled && player.isBlocking() && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_BLOCKING)) {
cancelled = true;
}
// TODO: Order of the last two [might put first] ?
if (!cancelled && reach.isEnabled(player) && reach.check(player, damaged))
if (!cancelled && reach.isEnabled(player) && reach.check(player, loc, damaged, damagedLoc)) {
cancelled = true;
}
if (!cancelled && direction.isEnabled(player) && direction.check(player, damaged))
cancelled = true;
if (!cancelled && direction.isEnabled(player) && direction.check(player, loc, damaged, damagedLoc)) {
cancelled = true;
}
// Set values.
data.lastWorld = worldName;
data.lastAttackTick = tick;
data.lastAttackedX = targetLoc.getX();
data.lastAttackedY = targetLoc.getY();
data.lastAttackedZ = targetLoc.getZ();
data.lastAttackedX = damagedLoc.getX();
data.lastAttackedY = damagedLoc.getY();
data.lastAttackedZ = damagedLoc.getZ();
// data.lastAttackedDist = targetDist;
// Care for the "lost sprint problem": sprint resets, client moves as if still...
// TODO: Use stored distance calculation same as reach check?
// TODO: For pvp: make use of "player was there" heuristic later on.
// TODO: Confine further with simple pre-conditions.
if (!cancelled && TrigUtil.distance(loc.getX(), loc.getZ(), targetLoc.getX(), targetLoc.getZ()) < 4.5){
if (!cancelled && TrigUtil.distance(loc.getX(), loc.getZ(), damagedLoc.getX(), damagedLoc.getZ()) < 4.5){
final MovingData mData = MovingData.getData(player);
// Check if fly checks is an issue at all, re-check "real sprinting".
if (mData.fromX != Double.MAX_VALUE && mData.mediumLiftOff != MediumLiftOff.LIMIT_JUMP){
@ -233,7 +245,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
// TODO: What would mData.lostSprintCount > 0 mean here?
mData.lostSprintCount = 7;
if ((cc.debug || mc.debug) && BuildParameters.debugLevel > 0){
System.out.println(player.getName() + " (lostsprint) hDist to last from: " + hDist + " | targetdist=" + TrigUtil.distance(loc.getX(), loc.getZ(), targetLoc.getX(), targetLoc.getZ()) + " | sprinting=" + player.isSprinting() + " | food=" + player.getFoodLevel() +" | hbuf=" + mData.sfHorizontalBuffer);
System.out.println(player.getName() + " (lostsprint) hDist to last from: " + hDist + " | targetdist=" + TrigUtil.distance(loc.getX(), loc.getZ(), damagedLoc.getX(), damagedLoc.getZ()) + " | sprinting=" + player.isSprinting() + " | food=" + player.getFoodLevel() +" | hbuf=" + mData.sfHorizontalBuffer);
}
}
}
@ -248,7 +260,11 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
System.out.println(player.getName() + " ~ attack penalty.");
}
}
// Cleanup.
useLoc1.setWorld(null);
useLoc2.setWorld(null);
return cancelled;
}

View File

@ -51,7 +51,7 @@ public class Reach extends Check {
* the damaged
* @return true, if successful
*/
public boolean check(final Player player, final Entity damaged) {
public boolean check(final Player player, final Location pLoc, final Entity damaged, final Location dRef) {
final FightConfig cc = FightConfig.getConfig(player);
final FightData data = FightData.getData(player);
@ -67,20 +67,17 @@ public class Reach extends Check {
final double distanceLimit = player.getGameMode() == GameMode.CREATIVE ? CREATIVE_DISTANCE : SURVIVAL_DISTANCE + getDistMod(damaged);
final double distanceMin = (distanceLimit - DYNAMIC_RANGE) / distanceLimit;
// Reference locations to check distance for.
final Location dRef = damaged.getLocation();
final double height = mcAccess.getHeight(damaged);
final Location pRef = player.getEyeLocation();
// Refine y position.
// TODO: Make a little more accurate by counting in the actual bounding box.
final double pY = pRef.getY();
final double pY = pLoc.getY() + player.getEyeHeight();
final double dY = dRef.getY();
if (pY <= dY); // Keep the foot level y.
else if (pY >= dY + height) dRef.setY(dY + height); // Highest ref y.
else dRef.setY(pY); // Level with damaged.
final Vector pRel = dRef.toVector().subtract(pRef.toVector());
final Vector pRel = dRef.toVector().subtract(pLoc.toVector().setY(pY)); // TODO: Run calculations on numbers only :p.
// Distance is calculated from eye location to center of targeted. If the player is further away from their target
// than allowed, the difference will be assigned to "distance".

View File

@ -55,6 +55,9 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
private final Open open = addCheck(new Open());
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
private final Location useLoc = new Location(null, 0, 0, 0);
public InventoryListener(){
super(CheckType.INVENTORY);
}
@ -73,7 +76,7 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
final Player player = (Player) event.getEntity();
if (instantBow.isEnabled(player)){
final long now = System.currentTimeMillis();
final Location loc = player.getLocation();
final Location loc = player.getLocation(useLoc);
if (Combined.checkYawRate(player, loc.getYaw(), now, loc.getWorld().getName())){
// No else if with this, could be cancelled due to other checks feeding, does not have actions.
event.setCancelled(true);
@ -87,6 +90,7 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
// Combined fighting speed (Else if: Matter of taste, preventing extreme cascading and actions spam).
event.setCancelled(true);
}
useLoc.setWorld(null);
}
}
}

View File

@ -16,6 +16,8 @@ public class MoveInfo {
public final BlockCache cache;
public final PlayerLocation from;
public final PlayerLocation to;
/** For temporary use. Might need cloning for passing to external API. */
public final Location useLoc = new Location(null, 0, 0, 0);
public MoveInfo(final MCAccess mcAccess){
cache = mcAccess.getBlockCache(null);
@ -38,10 +40,12 @@ public class MoveInfo {
this.to.set(to, player, yOnGround);
this.to.setBlockCache(cache);
}
useLoc.setWorld(null); // Just in case of repeated setting.
}
public final void cleanup(){
from.cleanup();
to.cleanup();
cache.cleanup();
useLoc.setWorld(null);
}
}

View File

@ -139,6 +139,8 @@ public class MovingConfig extends ACheckConfig {
public final int speedGrace;
public final boolean vehicleEnforceLocation;
public final boolean vehiclePreventDestroyOwn;
public final boolean enforceLocation = true; // TODO: Configurable + name.
/**
* Instantiates a new moving configuration.

View File

@ -269,8 +269,12 @@ public class MovingData extends ACheckData {
* @param loc
*/
public void resetPositions(final Location loc) {
if (loc == null) resetPositions(Double.MAX_VALUE, 0, 0);
else resetPositions(loc.getX(), loc.getY(), loc.getZ());
if (loc == null) {
resetPositions(Double.MAX_VALUE, 0, 0);
}
else {
resetPositions(loc.getX(), loc.getY(), loc.getZ());
}
}
/**
@ -278,8 +282,12 @@ public class MovingData extends ACheckData {
* @param loc
*/
public void resetPositions(PlayerLocation loc) {
if (loc == null) resetPositions(Double.MAX_VALUE, 0, 0);
else resetPositions(loc.getX(), loc.getY(), loc.getZ());
if (loc == null) {
resetPositions(Double.MAX_VALUE, 0, 0);
}
else {
resetPositions(loc.getX(), loc.getY(), loc.getZ());
}
}
/**
@ -375,8 +383,12 @@ public class MovingData extends ACheckData {
}
public boolean hasSetBackWorldChanged(final Location loc) {
if (setBack == null) return true;
else return setBack.getWorld().equals(loc.getWorld());
if (setBack == null) {
return true;
}
else {
return setBack.getWorld().equals(loc.getWorld());
}
}
@ -418,13 +430,21 @@ public class MovingData extends ACheckData {
}
public final void setMorePacketsSetBack(final PlayerLocation loc) {
if (morePacketsSetback == null) morePacketsSetback = loc.getLocation();
else LocUtil.set(morePacketsSetback, loc);
if (morePacketsSetback == null) {
morePacketsSetback = loc.getLocation();
}
else {
LocUtil.set(morePacketsSetback, loc);
}
}
public final void setMorePacketsSetBack(final Location loc) {
if (morePacketsSetback == null) morePacketsSetback = LocUtil.clone(loc);
else LocUtil.set(morePacketsSetback, loc);
if (morePacketsSetback == null) {
morePacketsSetback = LocUtil.clone(loc);
}
else {
LocUtil.set(morePacketsSetback, loc);
}
}
public Location getMorePacketsSetBack() {
@ -436,13 +456,21 @@ public class MovingData extends ACheckData {
}
public final void setMorePacketsVehicleSetBack(final PlayerLocation loc) {
if (morePacketsVehicleSetback == null) morePacketsVehicleSetback = loc.getLocation();
else LocUtil.set(morePacketsVehicleSetback, loc);
if (morePacketsVehicleSetback == null) {
morePacketsVehicleSetback = loc.getLocation();
}
else {
LocUtil.set(morePacketsVehicleSetback, loc);
}
}
public final void setMorePacketsVehicleSetBack(final Location loc) {
if (morePacketsVehicleSetback == null) morePacketsVehicleSetback = LocUtil.clone(loc);
else LocUtil.set(morePacketsVehicleSetback, loc);
if (morePacketsVehicleSetback == null) {
morePacketsVehicleSetback = LocUtil.clone(loc);
}
else {
LocUtil.set(morePacketsVehicleSetback, loc);
}
}
public final Location getMorePacketsVehicleSetBack() {

View File

@ -170,12 +170,19 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
*/
private final Map<String, PlayerMoveEvent> processingEvents = new HashMap<String, PlayerMoveEvent>();
private final Set<String> hoverTicks = new LinkedHashSet<String>(30);
/** Player names to check hover for, case insensitive. */
private final Set<String> hoverTicks = new LinkedHashSet<String>(30); // TODO: Rename
/** Player names to check enforcing the location for in onTick, case insensitive. */
private final Set<String> playersEnforce = new LinkedHashSet<String>(30);
private int hoverTicksStep = 5;
private final Set<EntityType> normalVehicles = new HashSet<EntityType>();
/** Location for temporary use with getLocation(useLoc). Always call setWorld(null) after use. Use LocUtil.clone before passing to other API. */
private final Location useLoc = new Location(null, 0, 0, 0); // TODO: Put to use...
public MovingListener() {
super(CheckType.MOVING);
}
@ -212,7 +219,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (!data.hasSetBack() || blockY + 1D < data.getSetBackY()) return;
final Location loc = player.getLocation();
final Location loc = player.getLocation(useLoc);
if (Math.abs(loc.getX() - 0.5 - block.getX()) <= 1D
&& Math.abs(loc.getZ() - 0.5 - block.getZ()) <= 1D
&& loc.getY() - blockY > 0D && loc.getY() - blockY < 2D
@ -223,6 +230,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
data.setSetBackY(blockY + 1D);
data.sfJumpPhase = 0;
}
useLoc.setWorld(null);
}
/**
@ -261,16 +269,19 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (bedLeave.isEnabled(player) && bedLeave.checkBed(player)) {
// Check if the player has to be reset.
// To "cancel" the event, we teleport the player.
final Location loc = player.getLocation();
final Location loc = player.getLocation(useLoc);
final MovingData data = MovingData.getData(player);
final MovingConfig cc = MovingConfig.getConfig(player);
Location target = null;
final boolean sfCheck = shouldCheckSurvivalFly(player, data, cc);
if (sfCheck) target = data.getSetBack(loc);
if (sfCheck) {
target = data.getSetBack(loc);
}
if (target == null) {
// TODO: Add something to guess the best set back location (possibly data.guessSetBack(Location)).
target = loc;
target = LocUtil.clone(loc);
}
useLoc.setWorld(null);
if (target != null) {
// Actually this should not possibly be null, this is a block for "future" purpose, feel free to criticize it.
if (sfCheck && cc.sfFallDamage && noFall.isEnabled(player)) {
@ -306,7 +317,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
data.clearFlyData();
data.clearMorePacketsData();
// TODO: Might omit this if neither check is activated.
data.setSetBack(player.getLocation());
data.setSetBack(player.getLocation(useLoc));
useLoc.setWorld(null);
}
/**
@ -382,6 +394,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
return;
}
// newTo should be null here.
// TODO: Order this to above "early return"?
// Set up data / caching.
@ -404,6 +417,10 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
parkedInfo.add(moveInfo);
return;
}
// Check for location consistency.
if (cc.enforceLocation) {
// TODO: Check if lastTo matches from.
}
final long time = System.currentTimeMillis();
if (player.isSprinting() || cc.assumeSprint) {
@ -447,7 +464,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// The players location.
// TODO: Change to getLocation(moveInfo.loc) once 1.4.5 support is dropped.
final Location loc = (cc.noFallCheck || cc.passableCheck) ? player.getLocation() : null;
final Location loc = (cc.noFallCheck || cc.passableCheck) ? player.getLocation(moveInfo.useLoc) : null;
// Check passable first to prevent set-back override.
// TODO: Redesign to set set-backs later (queue + invalidate).
@ -612,7 +629,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
data.sfLowJump = false;
// TODO: What with processingEvents.remove(player.getName());
if (vehicle != null) {
final Location vLoc = vehicle.getLocation();
final Location vLoc = vehicle.getLocation(); // TODO: Use a location as argument.
// (Auto detection of missing events, might fire one time too many per plugin run.)
if (!normalVehicles.contains(vehicle.getType())) {
onVehicleMove(vehicle, vLoc, vLoc, true);
@ -688,7 +705,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// TODO: maybe even not count vehicles at all ?
if (player.isInsideVehicle()) {
// TODO: refine (!).
MovingData.getData(player).resetPositions(player.getVehicle().getLocation());
MovingData.getData(player).resetPositions(player.getVehicle().getLocation(useLoc));
useLoc.setWorld(null);
}
else if (!fromWorldName.equals(toWorldName)) {
MovingData.getData(player).resetPositions(to);
@ -755,7 +773,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final MovingData data = MovingData.getData(player);
data.clearFlyData();
data.clearMorePacketsData();
data.setSetBack(player.getLocation()); // TODO: Monitor this change (!).
data.setSetBack(player.getLocation(useLoc)); // TODO: Monitor this change (!).
useLoc.setWorld(null);
}
/**
@ -843,7 +862,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
event.setTo(ref);
}
else{
ref = from;
ref = from; // Player.getLocation ?
event.setCancelled(true);
}
}
@ -1016,11 +1035,11 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (!from.getWorld().equals(to.getWorld())) return;
final MovingData data = MovingData.getData(player);
data.vehicleConsistency = MoveConsistency.getConsistency(from, to, player.getLocation());
data.vehicleConsistency = MoveConsistency.getConsistency(from, to, player.getLocation(useLoc));
switch (data.vehicleConsistency) {
case FROM:
case TO:
data.resetPositions(player.getLocation()); // TODO: Drop MC 1.4!
data.resetPositions(player.getLocation(useLoc)); // TODO: Drop MC 1.4!
break;
case INCONSISTENT:
// TODO: Any exploits exist? -> TeleportUtil.forceMount(player, vehicle)
@ -1062,6 +1081,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// TODO: Reset on world changes or not?
data.morePacketsVehicleTaskId = Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new VehicleSetBack(vehicle, player, newTo, cc.debug));
}
useLoc.setWorld(null);
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false)
@ -1076,7 +1096,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
data.clearNoFallData();
return;
}
final Location loc = player.getLocation();
final Location loc = player.getLocation(useLoc);
boolean allowReset = true;
if (!data.noFallSkipAirCheck) {
final MoveInfo moveInfo;
@ -1107,6 +1127,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
moveInfo.cleanup();
parkedInfo.add(moveInfo);
}
useLoc.setWorld(null);
final float fallDistance = player.getFallDistance();
final double damage = BridgeHealth.getDamage(event);
final float yDiff = (float) (data.noFallMaxY - loc.getY());
@ -1148,7 +1169,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// TODO: on existing set back: detect world changes and loss of world on join (+ set up some paradigm).
data.clearMorePacketsData();
data.removeAllVelocity();
final Location loc = player.getLocation();
final Location loc = player.getLocation(useLoc);
// Correct set-back on join.
if (data.hasSetBackWorldChanged(loc)) {
@ -1169,6 +1190,11 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
data.toWasReset = BlockProperties.isOnGroundOrResetCond(player, loc, cc.yOnGround);
data.fromWasReset = data.toWasReset;
// Enforcing the location.
if (cc.enforceLocation) {
playersEnforce.add(player.getName());
}
// Hover.
// Reset hover ticks until a better method is used.
if (cc.sfHoverCheck) {
@ -1192,6 +1218,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
}
// Cleanup.
useLoc.setWorld(null);
}
@Override
@ -1248,7 +1277,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final MovingData data = MovingData.getData(player);
data.removeAllVelocity();
// Event should have a vehicle, in case check this last.
data.vehicleConsistency = MoveConsistency.getConsistency(event.getVehicle().getLocation(), null, player.getLocation());
data.vehicleConsistency = MoveConsistency.getConsistency(event.getVehicle().getLocation(), null, player.getLocation(useLoc));
useLoc.setWorld(null); // TODO: A pool ?
// TODO: more resetting, visible check ?
}
@ -1268,7 +1298,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final MovingConfig cc = MovingConfig.getConfig(player);
// TODO: Loc can be inconsistent, determine which to use !
final Location pLoc = player.getLocation();
final Location pLoc = player.getLocation(useLoc);
Location loc = pLoc; // The location to use as set-back.
// TODO: Which vehicle to use ?
// final Entity vehicle = player.getVehicle();
@ -1314,6 +1344,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
data.verticalFreedom = 1.2;
data.verticalVelocity = 0.15;
data.verticalVelocityUsed = 0;
useLoc.setWorld(null);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
@ -1330,7 +1361,16 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
@Override
public void onTick(final int tick, final long timeLast) {
// Hover checks !
final List<String> rem = new ArrayList<String>(hoverTicks.size()); // Pessimistic.
// Enforcing location check.
for (final String playerName : playersEnforce) {
// TODO: Check location consistency (depending on cc).
}
if (!rem.isEmpty()) {
playersEnforce.removeAll(rem);
}
// Hover check (survivalfly).
rem.clear();
if (tick % hoverTicksStep != 0) {
// Only check every so and so ticks.
return;
@ -1338,7 +1378,6 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final MoveInfo info;
if (parkedInfo.isEmpty()) info = new MoveInfo(mcAccess);
else info = parkedInfo.remove(parkedInfo.size() - 1);
final List<String> rem = new ArrayList<String>(hoverTicks.size()); // Pessimistic.
for (final String playerName : hoverTicks) {
// TODO: put players into the set (+- one tick would not matter ?)
// TODO: might add an online flag to data !
@ -1379,10 +1418,11 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
rem.add(playerName);
}
}
info.cleanup(); // Just in case.
parkedInfo.add(info);
hoverTicks.removeAll(rem);
rem.clear();
info.cleanup();
parkedInfo.add(info);
useLoc.setWorld(null);
}
/**
@ -1395,7 +1435,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
*/
private boolean checkHover(final Player player, final MovingData data, final MovingConfig cc, final MoveInfo info) {
// Check if player is on ground.
final Location loc = player.getLocation();
final Location loc = player.getLocation(useLoc); // useLoc.setWorld(null) is done in onTick.
info.set(player, loc, null, cc.yOnGround);
final boolean res;
// TODO: Collect flags, more margin ?

View File

@ -16,6 +16,9 @@ import fr.neatmonster.nocheatplus.utilities.StringUtil;
* A check to see if people cheat by tricking the server to not deal them fall damage.
*/
public class NoFall extends Check {
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
private final Location useLoc = new Location(null, 0, 0, 0);
/**
* Instantiates a new no fall check.
@ -209,7 +212,8 @@ public class NoFall extends Check {
if (data.noFallFallDistance - fallDistance > 0){
// Might use tolerance, might log, might use method (compare: MovingListener.onEntityDamage).
// Might consider triggering violations here as well.
final float yDiff = (float) (data.noFallMaxY - player.getLocation().getY());
final float yDiff = (float) (data.noFallMaxY - player.getLocation(useLoc).getY());
useLoc.setWorld(null);
final float maxDist = Math.max(yDiff, Math.max(data.noFallFallDistance, fallDistance));
player.setFallDistance(maxDist);
}

View File

@ -65,6 +65,9 @@ public class SurvivalFly extends Check {
private final Set<String> reallySneaking = new HashSet<String>(30);
/** For temporary use: LocUtil.clone before passing deeply, call setWorld(null) after use. */
private final Location useLoc = new Location(null, 0, 0, 0);
/**
* Instantiates a new survival fly check.
*/
@ -1344,7 +1347,10 @@ public class SurvivalFly extends Check {
}
if (data.sfCobwebVL < 550) { // Totally random !
// Silently set back.
if (!data.hasSetBack()) data.setSetBack(player.getLocation()); // ? check moment of call.
if (!data.hasSetBack()) {
data.setSetBack(player.getLocation(useLoc)); // ? check moment of call.
useLoc.setWorld(null);
}
data.sfJumpPhase = 0;
data.sfLastYDist = data.sfLastHDist = Double.MAX_VALUE;
return true;

View File

@ -19,6 +19,8 @@ import fr.neatmonster.nocheatplus.utilities.build.BuildParameters;
*/
public class DebugUtil {
// TODO: Add useLoc1 and useLoc2.
public static boolean isSamePos(final double x1, final double y1, final double z1, final double x2, final double y2, final double z2){
return x1 == x2 && y1 == y2 && z1 == z2;
}

View File

@ -355,6 +355,8 @@ public class BlockProperties {
*/
private static final Map<String, Long> nameFlagMap = new LinkedHashMap<String, Long>();
private static final Location useLoc = new Location(null, 0, 0, 0);
static{
// Use reflection to get a flag -> name mapping and vice versa.
for (Field field : BlockProperties.class.getDeclaredFields()){
@ -880,7 +882,9 @@ public class BlockProperties {
* @return
*/
public static long getBreakingDuration(final int blockId, final Player player){
return getBreakingDuration(blockId, player.getItemInHand(), player.getInventory().getHelmet(), player, player.getLocation());
final long res = getBreakingDuration(blockId, player.getItemInHand(), player.getInventory().getHelmet(), player, player.getLocation(useLoc));
useLoc.setWorld(null);
return res;
}
/**

View File

@ -6,6 +6,9 @@ import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
public class TeleportUtil {
/** Temp use. LocUtil.clone on passing. setWorld(null) after use. */
private static final Location useLoc = new Location(null, 0, 0, 0);
/**
* Teleport the player with vehicle, temporarily eject the passenger and set teleported in MovingData.
@ -29,13 +32,14 @@ public class TeleportUtil {
}
else vehicleTeleported = false;
final boolean playerTeleported = player.teleport(location);
if (playerIsPassenger && playerTeleported && vehicleTeleported && player.getLocation().distance(vehicle.getLocation()) < 1.0){
if (playerIsPassenger && playerTeleported && vehicleTeleported && player.getLocation().distance(vehicle.getLocation(useLoc)) < 1.0){
// Somewhat check against tp showing something wrong (< 1.0).
vehicle.setPassenger(player);
}
if (debug){
System.out.println(player.getName() + " vehicle set back: " + location);
}
useLoc.setWorld(null);
}
/**

View File

@ -20,6 +20,8 @@ public class TrigUtil {
public static final double fRadToGrad = 360.0 / (2.0 * Math.PI);
/** Some default precision value for the directionCheck method. */
public static final double DIRECTION_PRECISION = 2.6;
private static final Location useLoc = new Location(null, 0, 0, 0);
/**
* Check if a player looks at a target of a specific size, with a specific
@ -43,9 +45,11 @@ public class TrigUtil {
*/
public static double directionCheck(final Player player, final double targetX, final double targetY, final double targetZ, final double targetWidth, final double targetHeight, final double precision)
{
final Location loc = player.getLocation();
final Location loc = player.getLocation(useLoc);
final Vector dir = loc.getDirection();
return directionCheck(loc.getX(), loc.getY() + player.getEyeHeight(), loc.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision);
final double res = directionCheck(loc.getX(), loc.getY() + player.getEyeHeight(), loc.getZ(), dir.getX(), dir.getY(), dir.getZ(), targetX, targetY, targetZ, targetWidth, targetHeight, precision);
useLoc.setWorld(null);
return res;
}
/**