[BLEEDING] Make use of DefaultSetBackStorage for vehicle set-back.

This commit is contained in:
asofold 2016-04-29 18:13:53 +02:00
parent 5b8039c5ae
commit 3f00f73d40
10 changed files with 182 additions and 142 deletions

View File

@ -15,6 +15,7 @@ import fr.neatmonster.nocheatplus.checks.access.ACheckData;
import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckData;
import fr.neatmonster.nocheatplus.checks.moving.location.LocUtil;
import fr.neatmonster.nocheatplus.checks.moving.location.setback.DefaultSetBackStorage;
import fr.neatmonster.nocheatplus.checks.moving.location.tracking.LocationTrace;
import fr.neatmonster.nocheatplus.checks.moving.magic.Magic;
import fr.neatmonster.nocheatplus.checks.moving.model.LiftOffEnvelope;
@ -211,14 +212,6 @@ public class MovingData extends ACheckData {
public final ActionFrequency morePacketsBurstFreq;
private Location morePacketsSetback = null;
// Data of the more packets vehicle check.
public int vehicleMorePacketsBuffer = 50;
public long vehicleMorePacketsLastTime;
private Location vehicleMorePacketsSetback = null;
/** Task id of the vehicle set-back task. */
public int vehicleSetBackTaskId = -1;
// Data of the no fall check.
public float noFallFallDistance = 0;
/** Last y coordinate from when the player was on ground. */
@ -247,20 +240,32 @@ public class MovingData extends ACheckData {
public boolean sfLowJump = false;
public boolean sfNoLowJump = false; // Hacks.
/** Counting while the player is not on ground and not moving. A value <0 means not hovering at all. */
public int sfHoverTicks = -1;
/** First count these down before incrementing sfHoverTicks. Set on join, if configured so. */
public int sfHoverLoginTicks = 0;
public int sfOnIce = 0; // TODO: Replace by allowed speed + friction.
public long sfCobwebTime = 0;
public double sfCobwebVL = 0;
public long sfVLTime = 0;
/**
* Counting while the player is not on ground and not moving. A value <0
* means not hovering at all.
*/
public int sfHoverTicks = -1;
/**
* First count these down before incrementing sfHoverTicks. Set on join, if
* configured so.
*/
public int sfHoverLoginTicks = 0;
public int sfOnIce = 0; // TODO: Replace by allowed speed + friction.
public long sfCobwebTime = 0;
public double sfCobwebVL = 0;
public long sfVLTime = 0;
// Accounting info.
public final ActionAccumulator vDistAcc = new ActionAccumulator(3, 3);
/** Rough friction factor estimate, 0.0 is the reset value (maximum with lift-off/burst speed is used). */
/**
* Rough friction factor estimate, 0.0 is the reset value (maximum with
* lift-off/burst speed is used).
*/
public double lastFrictionHorizontal = 0.0;
/** Rough friction factor estimate, 0.0 is the reset value (maximum with lift-off/burst speed is used). */
/**
* Rough friction factor estimate, 0.0 is the reset value (maximum with
* lift-off/burst speed is used).
*/
public double lastFrictionVertical = 0.0;
/** Used during processing, no resetting necessary.*/
public double nextFrictionHorizontal = 0.0;
@ -269,23 +274,34 @@ public class MovingData extends ACheckData {
/** Workarounds */
public final WorkaroundSet ws;
// HOT FIX
/** Inconsistency-flag. Set on moving inside of vehicles, reset on exiting properly. Workaround for VehicleLeaveEvent missing. */
public boolean wasInVehicle = false;
public MoveConsistency vehicleConsistency = MoveConsistency.INCONSISTENT;
/** Set to true after login/respawn, only if the set-back is reset there. Reset in MovingListener after handling PlayerMoveEvent */
// HOT FIX / WORKAROUND
/**
* Set to true after login/respawn, only if the set-back is reset there.
* Reset in MovingListener after handling PlayerMoveEvent
*/
public boolean joinOrRespawn = false;
/**
* Number of (vehicle) move events since set.back. Update after running
* standard checks on that EventPriority level (not MONITOR).
* Number of (player/vehicle) move events since set.back. Update after
* running standard checks on that EventPriority level (not MONITOR).
*/
public int timeSinceSetBack = 0;
/**
* Location hash value of the last set-back, for checking independently of
* which set-back location had been used.
* Location hash value of the last (player/vehicle) set-back, for checking
* independently of which set-back location had been used.
*/
public int lastSetBackHash = 0;
// Vehicles.
/** Inconsistency-flag. Set on moving inside of vehicles, reset on exiting properly. Workaround for VehicleLeaveEvent missing. */
public boolean wasInVehicle = false; // Workaround
public MoveConsistency vehicleConsistency = MoveConsistency.INCONSISTENT; // Workaround
public final DefaultSetBackStorage vehicleSetBacks = new DefaultSetBackStorage();
// Data of the more packets vehicle check.
public int vehicleMorePacketsBuffer = 50;
public long vehicleMorePacketsLastTime;
/** Task id of the vehicle set-back task. */
public int vehicleSetBackTaskId = -1;
public MovingData(final MovingConfig config) {
super(config);
morePacketsFreq = new ActionFrequency(config.morePacketsEPSBuckets, 500);
@ -384,7 +400,7 @@ public class MovingData extends ACheckData {
resetPositions(setBack);
adjustMediumProperties(setBack);
setSetBack(setBack);
setVehicleMorePacketsSetBack(setBack); // TODO: Switch to the one making most sense, once implemented.
vehicleSetBacks.resetAllLazily(setBack);
}
/**
@ -458,10 +474,7 @@ public class MovingData extends ACheckData {
if (setBack != null && worldName.equalsIgnoreCase(setBack.getWorld().getName())) {
clearFlyData();
}
if (morePacketsSetback != null && worldName.equalsIgnoreCase(morePacketsSetback.getWorld().getName()) || vehicleMorePacketsSetback != null && worldName.equalsIgnoreCase(vehicleMorePacketsSetback.getWorld().getName())) {
clearAllMorePacketsData();
clearNoFallData(); // just in case.
}
vehicleSetBacks.resetByWorldName(worldName);
}
/**
@ -516,7 +529,7 @@ public class MovingData extends ACheckData {
}
public void clearVehicleMorePacketsData() {
vehicleMorePacketsSetback = null;
vehicleSetBacks.getMidTermEntry().setValid(false);
// TODO: Also reset other data ?
}
@ -673,32 +686,6 @@ public class MovingData extends ACheckData {
return LocUtil.clone(morePacketsSetback);
}
public boolean hasVehicleMorePacketsSetBack() {
return vehicleMorePacketsSetback != null;
}
public final void setVehicleMorePacketsSetBack(final PlayerLocation loc) {
if (vehicleMorePacketsSetback == null) {
vehicleMorePacketsSetback = loc.getLocation();
}
else {
LocUtil.set(vehicleMorePacketsSetback, loc);
}
}
public final void setVehicleMorePacketsSetBack(final Location loc) {
if (vehicleMorePacketsSetback == null) {
vehicleMorePacketsSetback = LocUtil.clone(loc);
}
else {
LocUtil.set(vehicleMorePacketsSetback, loc);
}
}
public final Location getVehicleMorePacketsSetBack() {
return LocUtil.clone(vehicleMorePacketsSetback);
}
public final void resetTeleported() {
teleported = null;
}
@ -949,18 +936,6 @@ public class MovingData extends ACheckData {
return loc.getX() == setBack.getX() && loc.getY() == setBack.getY() && loc.getZ() == setBack.getZ();
}
/**
* Standard equals for the more packets set-back location. Implies
* world1.equals(world2).
*
* @param loc
* @return
*/
public boolean equalsVehicleMorePacketsSetBack(final Location loc) {
return vehicleMorePacketsSetback != null && vehicleMorePacketsSetback.equals(loc)
|| loc == null && vehicleMorePacketsSetback == null;
}
public void adjustWalkSpeed(final float walkSpeed, final int tick, final int speedGrace) {
if (walkSpeed > this.walkSpeed) {
this.walkSpeed = walkSpeed;

View File

@ -47,6 +47,7 @@ public class DefaultSetBackStorage extends SetBackStorage {
/**
* Get the 'mid-term' set-back entry, disregarding validity.
*
* @return
*/
public SetBackEntry getMidTermEntry() {
@ -55,6 +56,7 @@ public class DefaultSetBackStorage extends SetBackStorage {
/**
* Get the 'safe-medium' set-back entry, disregarding validity.
*
* @return
*/
public SetBackEntry getSafeMediumEntry() {
@ -62,7 +64,9 @@ public class DefaultSetBackStorage extends SetBackStorage {
}
/**
* Get the 'last-move' set-back entry, disregarding validity of the entry itself.
* Get the 'last-move' set-back entry, disregarding validity of the entry
* itself.
*
* @return
*/
public SetBackEntry getLastMoveEntry() {
@ -129,6 +133,37 @@ public class DefaultSetBackStorage extends SetBackStorage {
getLastMoveEntry().set(loc, ++time, Monotonic.millis());
}
// TODO: Getter methods with fall-back to default entry. Not sure: get a Location instance or just the entry?
/**
* Get a valid 'mid-term' entry. If that entry is not valid, fall back to
* the default entry. If neither entry is valid, return null. returned.
*
* @param world
* @return
*/
public SetBackEntry getValidMidTermEntry() {
return getValidEntry(indexMidTerm, true);
}
/**
* Get a valid 'safe-medium' entry. If that entry is not valid, fall back to
* the default entry. If neither entry is valid, return null.
*
* @param world
* @return
*/
public SetBackEntry getValidSafeMediumEntry() {
return getValidEntry(indexSafeMedium, true);
}
/**
* Get a valid 'last-move' entry. If that entry is not valid, fall back to
* the default entry. If neither entry is valid, return null.
*
* @param world
* @return
*/
public SetBackEntry getValidLastMoveEntry() {
return getValidEntry(indexLastMove, true);
}
}

View File

@ -1,11 +0,0 @@
package fr.neatmonster.nocheatplus.checks.moving.location.setback;
/**
* Public access methods for set-back storage.
*
* @author asofold
*
*/
public interface ISetBackAccess {
// TODO: Consider to hide implementations behind this / specialized interfaces extending this.
}

View File

@ -14,6 +14,8 @@ import fr.neatmonster.nocheatplus.components.location.ILocationWithLook;
*/
public class SetBackEntry implements ILocationWithLook {
// TODO: Support a hash for locations (can't be Location.hashCode()).
private String worldName;
private double x, y, z;
private float pitch, yaw;
@ -23,28 +25,23 @@ public class SetBackEntry implements ILocationWithLook {
private boolean isValid = false;
public SetBackEntry set(final Location loc, final int time, final long msTime) {
worldName = loc.getWorld().getName();
x = loc.getX();
y = loc.getY();
z = loc.getZ();
pitch = loc.getPitch();
yaw = loc.getYaw();
this.time = time;
this.msTime = msTime;
isValid = true;
return this;
return set(loc.getWorld().getName(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), time, msTime);
}
public SetBackEntry set(final ILocationWithLook loc, final int time, final long msTime) {
worldName = loc.getWorldName();
x = loc.getX();
y = loc.getY();
z = loc.getZ();
pitch = loc.getPitch();
yaw = loc.getYaw();
return set(loc.getWorldName(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), time, msTime);
}
public SetBackEntry set(final String worldName, final double x, final double y, final double z, final float yaw, final float pitch, final int time, final long msTime) {
this.worldName = worldName;
this.x = x;
this.y = y;
this.z = z;
this.yaw = yaw;
this.pitch = pitch;
this.time = time;
this.msTime = msTime;
isValid = true;
this.isValid = true;
return this;
}
@ -126,25 +123,38 @@ public class SetBackEntry implements ILocationWithLook {
this.worldName = worldName;
}
/**
* Convenience method to test with this instance is both valid and older
* than the given one. The time field (getTime) is used for time comparison,
* assuming both locations come from the same storage/context. Validity of
* the given instance is not checked.
*
* @param other
* @return
*/
public boolean isValidAndOlderThan(final SetBackEntry other) {
return isValid && time < other.time;
}
/**
* Retrieve a Bukkit Location instance, using the given world.
*
* @param world
* @return A new Location object, containing the given world, ready to be
* used.
* @throws IllegalStateException
* In case the set-back entry is not valid.
* @throws IllegalArgumentException
* In case the name of the given world does not match the stored
* one.
* @throws IllegalStateException
* In case the set-back entry is not valid.
*/
public Location getLocation(final World world) {
if (!world.getName().equals(worldName)) {
throw new IllegalArgumentException("The name of the given world must equal the stored world name.");
}
if (!isValid) {
throw new IllegalStateException("Can't return a Location instance from an invalid state.");
}
if (!world.getName().equals(worldName)) {
throw new IllegalArgumentException("The name of the given world must equal the stored world name.");
}
return new Location(world, x, y, z, yaw, pitch);
}

View File

@ -1,6 +1,7 @@
package fr.neatmonster.nocheatplus.checks.moving.location.setback;
import org.bukkit.Location;
import org.bukkit.World;
import fr.neatmonster.nocheatplus.components.location.ILocationWithLook;
import fr.neatmonster.nocheatplus.time.monotonic.Monotonic;
@ -17,6 +18,9 @@ import fr.neatmonster.nocheatplus.time.monotonic.Monotonic;
*/
public class SetBackStorage {
// TODO: Support a hash for locations (can't be Location.hashCode()).
// TODO: Support for last-used set-back (on retrieving a Location instance)?
final SetBackEntry[] entries;
final int defaultIndex;
/** Count times setting a set-back. */
@ -164,6 +168,15 @@ public class SetBackStorage {
}
}
public void resetByWorldName(final String worldName) {
// TODO: Not needed for memory leaks, possibly tie resetAll to a global world?
for (int i = 0; i < entries.length; i++) {
if (worldName.equals(entries[i].getWorldName())) {
entries[i].setValid(false);
}
}
}
/**
* Test if any of the stored set-back location is valid.
*
@ -222,4 +235,16 @@ public class SetBackStorage {
getDefaultEntry().set(loc, ++time, Monotonic.millis());
}
/**
* Retrieve the default location as a Location instance, if valid. If not
* valid, null is returned.
*
* @param world
* @return
*/
public Location getValidDefaultLocation(final World world) {
final SetBackEntry entry = getDefaultEntry();
return entry.isValid() ? entry.getLocation(world) : null;
}
}

View File

@ -12,11 +12,11 @@ public class MagicVehicle {
// TODO: Configuration, once certain.
/** Extreme value. */
public static final double maxDistanceHorizontal = 4.0;
public static final double maxDistanceHorizontal = 4.0; // TODO: 2.5 / 3.4?
// Entity.
public static final double minecartMaxDistanceHorizontal = maxDistanceHorizontal; // 13.0 / 20.0; // Include turn.
public static final double boatMaxDistanceHorizontal = maxDistanceHorizontal; // 18.0 / 20.0; // Including some downstream, rough testing.
public static final double boatMaxDistanceHorizontal = 0.7; // maxDistanceHorizontal; // 18.0 / 20.0; // Including some downstream, rough testing.
// TODO: Boat on ice: 42 / 20.
public static final double entityMaxDistanceHorizontal = maxDistanceHorizontal; // (No idea, cannon balls?)

View File

@ -25,6 +25,7 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.moving.location.LocUtil;
import fr.neatmonster.nocheatplus.checks.moving.location.setback.SetBackEntry;
import fr.neatmonster.nocheatplus.checks.moving.model.MoveConsistency;
import fr.neatmonster.nocheatplus.checks.moving.model.MoveData;
import fr.neatmonster.nocheatplus.checks.moving.util.AuxMoving;
@ -208,7 +209,7 @@ public class VehicleChecks extends CheckListener {
break;
}
Location newTo = null;
SetBackEntry newTo = null;
data.sfNoLowJump = true;
if (cc.noFallVehicleReset) {
@ -223,11 +224,12 @@ public class VehicleChecks extends CheckListener {
outputDebugVehicleMove(player, vehicle, from, to, fake);
}
// Ensure a common set-back for now.
// TODO: Check activation of any check?
if (!data.hasVehicleMorePacketsSetBack()) {
// Ensure a common set-back for now.
if (!data.vehicleSetBacks.isDefaultEntryValid()) {
// TODO: Check if other set-back is appropriate or if to set on other events.
data.setVehicleMorePacketsSetBack(from);
data.vehicleSetBacks.setDefaultEntry(from);
if (data.debug) {
debug(player, "Ensure vehicle set-back: " + from);
}
@ -238,7 +240,9 @@ public class VehicleChecks extends CheckListener {
}
// Moving envelope check(s).
if (newTo == null && vehicleEnvelope.isEnabled(player, data, cc)) {
// TODO: Use set-back storage for testing if this is appropriate (use SetBackEntry instead, remove Location retrieval then?).
if ((newTo == null || data.vehicleSetBacks.getSafeMediumEntry().isValidAndOlderThan(newTo))
&& vehicleEnvelope.isEnabled(player, data, cc)) {
// Skip if this is the first move after set-back, with to=set-back.
if (data.timeSinceSetBack == 0 || to.hashCode() == data.lastSetBackHash) {
// TODO: This is a hot fix, to prevent a set-back loop. Depends on having only the morepackets set-back for vehicles.
@ -248,23 +252,27 @@ public class VehicleChecks extends CheckListener {
}
}
else {
newTo = vehicleEnvelope.check(player, vehicle, from, to, fake, data, cc);
final SetBackEntry tempNewTo = vehicleEnvelope.check(player, vehicle, from, to, fake, data, cc);
if (tempNewTo != null) {
newTo = tempNewTo;
}
}
}
// More packets: Sort this in last, to avoid setting the set-back early. Always check to adjust set-back, for now.
if (vehicleMorePackets.isEnabled(player, data, cc)) {
// If the player is handled by the vehicle more packets check, execute it.
final Location mpNewTo = vehicleMorePackets.check(player, from, to,
newTo == null && data.vehicleSetBackTaskId == -1, data, cc);
if (mpNewTo != null) {
// Just prefer this for now.
newTo = mpNewTo;
// TODO: Still always update the frequency part?
if ((newTo == null || data.vehicleSetBacks.getMidTermEntry().isValidAndOlderThan(newTo))) {
if (vehicleMorePackets.isEnabled(player, data, cc)) {
final SetBackEntry tempNewTo = vehicleMorePackets.check(player, from, to, newTo == null && data.vehicleSetBackTaskId == -1, data, cc);
if (tempNewTo != null) {
newTo = tempNewTo;
}
}
else {
// Otherwise we need to clear their data.
// TODO: Should only if disabled.
data.clearVehicleMorePacketsData();
}
}
else {
// Otherwise we need to clear their data.
data.clearVehicleMorePacketsData();
}
// Schedule a set-back?
@ -273,7 +281,7 @@ public class VehicleChecks extends CheckListener {
data.timeSinceSetBack ++;
}
else {
setBack(player, vehicle, newTo, data);;
setBack(player, vehicle, newTo.getLocation(from.getWorld()), data);
}
useLoc.setWorld(null);
}

View File

@ -22,6 +22,7 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.moving.location.setback.SetBackEntry;
import fr.neatmonster.nocheatplus.checks.moving.magic.MagicVehicle;
import fr.neatmonster.nocheatplus.checks.moving.model.VehicleMoveData;
import fr.neatmonster.nocheatplus.logging.Streams;
@ -53,7 +54,7 @@ public class VehicleEnvelope extends Check {
super(CheckType.MOVING_VEHICLE_ENVELOPE);
}
public Location check(final Player player, final Entity vehicle, final Location from, final Location to, final boolean isFake, final MovingData data, final MovingConfig cc) {
public SetBackEntry check(final Player player, final Entity vehicle, final Location from, final Location to, final boolean isFake, final MovingData data, final MovingConfig cc) {
// Delegate to a sub-check.
tags.clear();
tags.add("entity." + vehicle.getType());
@ -71,11 +72,12 @@ public class VehicleEnvelope extends Check {
final ViolationData vd = new ViolationData(this, player, data.vehicleEnvelopeVL, 1, cc.vehicleEnvelopeActions);
vd.setParameter(ParameterName.TAGS, StringUtil.join(tags, "+"));
if (executeActions(vd).willCancel()) {
return data.getVehicleMorePacketsSetBack();
return data.vehicleSetBacks.getValidMidTermEntry();
}
}
else {
data.vehicleEnvelopeVL *= 0.99; // Random cooldown for now.
data.vehicleEnvelopeVL *= 0.99; // Random cool down for now.
data.vehicleSetBacks.setSafeMediumEntry(to); // TODO: Set only if it is safe to set. Set on monitor rather.
}
return null;
}

View File

@ -9,6 +9,7 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.moving.location.setback.SetBackEntry;
/**
* This check does the exact same thing as the MorePacket check but this one works for players inside vehicles.
@ -44,19 +45,20 @@ public class VehicleMorePackets extends Check {
* @param data
* @return the location
*/
public Location check(final Player player, final Location from, final Location to,
public SetBackEntry check(final Player player, final Location from, final Location to,
final boolean allowSetSetBack, final MovingData data, final MovingConfig cc) {
// Take time once, first:
final long time = System.currentTimeMillis();
Location newTo = null;
SetBackEntry newTo = null;
// Take a packet from the buffer.
data.vehicleMorePacketsBuffer--;
if (data.vehicleSetBackTaskId != -1){
// Short version !
return data.getVehicleMorePacketsSetBack();
// TODO: This is bad. Needs to check if still scheduled (a BukkitTask thing) and just skip.
return data.vehicleSetBacks.getValidMidTermEntry();
}
// Player used up buffer, they fail the check.
@ -72,7 +74,7 @@ public class VehicleMorePackets extends Check {
vd.setParameter(ParameterName.PACKETS, Integer.toString(-data.vehicleMorePacketsBuffer));
}
if (executeActions(vd).willCancel()){
newTo = data.getVehicleMorePacketsSetBack();
newTo = data.vehicleSetBacks.getValidMidTermEntry();
}
}
@ -98,7 +100,7 @@ public class VehicleMorePackets extends Check {
// Set the new set-back location.
if (allowSetSetBack && newTo == null) {
data.setVehicleMorePacketsSetBack(from);
data.vehicleSetBacks.setMidTermEntry(from);
if (data.debug) {
debug(player, "Update vehicle morepackets set-back: " + from);
}
@ -108,13 +110,7 @@ public class VehicleMorePackets extends Check {
data.vehicleMorePacketsLastTime = time;
}
if (newTo == null) {
return null;
}
// Compose a new location based on coordinates of "newTo" and viewing direction of "event.getTo()" to allow the
// player to look somewhere else despite getting pulled back by NoCheatPlus.
return new Location(player.getWorld(), newTo.getX(), newTo.getY(), newTo.getZ(), to.getYaw(), to.getPitch());
return newTo;
}
}

View File

@ -72,7 +72,7 @@ public class TeleportUtil {
// TODO: VehicleEnter fires.
// TODO: Not enter if vehicle teleport failed?
vehicle.setPassenger(player);
data.setVehicleMorePacketsSetBack(location); // HACK, needed due to teleportation resetting the set-back.
data.vehicleSetBacks.setDefaultEntry(location); // HACK, needed due to teleportation resetting the set-back.
// TODO: What on failure of setPassenger?
}
}