mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-09-03 10:50:27 +02:00
commit
7e931c8d2e
|
@ -0,0 +1,19 @@
|
|||
package fr.neatmonster.nocheatplus.time;
|
||||
|
||||
/**
|
||||
* Some kind of clock.
|
||||
*
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public interface Clock {
|
||||
|
||||
/**
|
||||
* Get the clock counter. There is no guarantee that this is monotonic, nor
|
||||
* need it be thread-safe.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public long clock();
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package fr.neatmonster.nocheatplus.time.monotonic;
|
||||
|
||||
|
||||
/**
|
||||
* Static provider for monotonic clocks. Note that some calls can only be made
|
||||
* from the server/application main thread, thread safe methods are prefixed
|
||||
* with "synch", however all call results may have different offsets.
|
||||
*/
|
||||
public class Monotonic {
|
||||
|
||||
private static final MonotonicClock nanos = new MonotonicNanosClock();
|
||||
private static final MonotonicClock millis = new MonotonicMillisClock();
|
||||
private static final MonotonicClock synchMillis = new MonotonicSynchClock(new MonotonicMillisClock());
|
||||
private static final MonotonicClock synchNanos = new MonotonicSynchClock(new MonotonicNanosClock());
|
||||
|
||||
/**
|
||||
* Monotonic nanoseconds time, corresponding to System.nanoTime(). <br>
|
||||
* <b>Not thread-safe, only call from the main server/application
|
||||
* thread.</b>
|
||||
*
|
||||
* @return Monotonic time in nanoseconds.
|
||||
*/
|
||||
public static long nanos() {
|
||||
return nanos.clock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Monotonic milliseconds time, corresponding to System.currentTimeMillis(). <br>
|
||||
* <b>Not thread-safe, only call from the main server/application
|
||||
* thread.</b>
|
||||
*
|
||||
* @return Monotonic time in milliseconds.
|
||||
*/
|
||||
public static long millis() {
|
||||
return millis.clock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Monotonic nanoseconds time, corresponding to System.nanoTime(). <br>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @return Monotonic time in nanoseconds.
|
||||
*/
|
||||
public static long synchNanos() {
|
||||
return synchNanos.clock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Monotonic milliseconds time, corresponding to System.currentTimeMillis(). <br>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @return Monotonic time in milliseconds.
|
||||
*/
|
||||
public static long synchMillis() {
|
||||
return synchMillis.clock();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package fr.neatmonster.nocheatplus.time.monotonic;
|
||||
|
||||
/**
|
||||
* Basic implementation of increasing a counter for a not necessarily monotonic
|
||||
* underlying clock, fetched with fetchClock(). Not thread-safe.
|
||||
*
|
||||
*/
|
||||
public abstract class MonotonicAbstractClock implements MonotonicClock {
|
||||
|
||||
private long clock;
|
||||
|
||||
private long lastFetch;
|
||||
|
||||
public MonotonicAbstractClock() {
|
||||
clock = fetchClock();
|
||||
lastFetch = clock;
|
||||
}
|
||||
|
||||
public MonotonicAbstractClock(long clock) {
|
||||
reset(clock);
|
||||
}
|
||||
|
||||
protected abstract long fetchClock();
|
||||
|
||||
@Override
|
||||
public long clock() {
|
||||
// TODO: Add feature to detect running too fast and correction as well.
|
||||
final long fetch = fetchClock();
|
||||
final long diff = fetch - this.lastFetch;
|
||||
if (diff > 0) {
|
||||
this.clock += diff;
|
||||
}
|
||||
this.lastFetch = fetch;
|
||||
return this.clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(long clock) {
|
||||
this.clock = clock;
|
||||
this.lastFetch = fetchClock();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package fr.neatmonster.nocheatplus.time.monotonic;
|
||||
|
||||
import fr.neatmonster.nocheatplus.time.Clock;
|
||||
|
||||
/**
|
||||
* Monotonic clock. The clock() method will count since creation or call of
|
||||
* reset, unless stated otherwise.
|
||||
*
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public interface MonotonicClock extends Clock {
|
||||
|
||||
/**
|
||||
* Monotonic clock allow resetting for some reason.
|
||||
*/
|
||||
public void reset(long clock);
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package fr.neatmonster.nocheatplus.time.monotonic;
|
||||
|
||||
/**
|
||||
* Monotonic clock based on System.currentTimeMillis(). Not thread-safe.
|
||||
*
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public class MonotonicMillisClock extends MonotonicAbstractClock {
|
||||
|
||||
@Override
|
||||
protected long fetchClock() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package fr.neatmonster.nocheatplus.time.monotonic;
|
||||
|
||||
/**
|
||||
* Monotonic clock based on System.nanoTime(). Not thread-safe.
|
||||
*
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public class MonotonicNanosClock extends MonotonicAbstractClock {
|
||||
|
||||
@Override
|
||||
protected long fetchClock() {
|
||||
return System.nanoTime();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package fr.neatmonster.nocheatplus.time.monotonic;
|
||||
|
||||
/**
|
||||
* Thread safe version of a monotonic clock, wrapping around a given clock.
|
||||
* Since synchronized method bodies wrap around the underlying clock, the clock
|
||||
* must not be used outside of this instance.
|
||||
*
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public class MonotonicSynchClock implements MonotonicClock {
|
||||
|
||||
private final MonotonicClock clock;
|
||||
|
||||
public MonotonicSynchClock(MonotonicClock clock) {
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized long clock() {
|
||||
return clock.clock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void reset(long clock) {
|
||||
this.clock.reset(clock);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* Provides monotonic clocks. [Taken from NC4 Planning/Framework.]
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.time.monotonic;
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Time related functionality. [Taken from NC4 Planning/Framework.]
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.time;
|
|
@ -109,7 +109,7 @@ public class CharPrefixTree<N extends CharNode<N>, L extends CharLookupEntry<N>>
|
|||
/**
|
||||
* Test hasPrefixWords for each given argument.
|
||||
* @param inputs
|
||||
* @return true if hasPrefixWords returns ture for any of the inputs, false otherwise.
|
||||
* @return true if hasPrefixWords(String) returns true for any of the inputs, false otherwise.
|
||||
*/
|
||||
public boolean hasAnyPrefixWords(final String... inputs){
|
||||
for (int i = 0; i < inputs.length; i++){
|
||||
|
@ -120,6 +120,20 @@ public class CharPrefixTree<N extends CharNode<N>, L extends CharLookupEntry<N>>
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test hasPrefixWords for each element of the collection.
|
||||
* @param inputs
|
||||
* @return true if hasPrefixWords(String) returns true for any of the elements, false otherwise.
|
||||
*/
|
||||
public boolean hasAnyPrefixWords(final Collection<String> inputs){
|
||||
for (final String input : inputs){
|
||||
if (hasPrefixWords(input)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPrefix(final char[] chars){
|
||||
return isPrefix(toCharacterList(chars));
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
|
|||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.ViolationData;
|
||||
import fr.neatmonster.nocheatplus.compat.BridgeHealth;
|
||||
import fr.neatmonster.nocheatplus.config.ConfPaths;
|
||||
import fr.neatmonster.nocheatplus.config.ConfigManager;
|
||||
import fr.neatmonster.nocheatplus.logging.LogUtil;
|
||||
|
@ -44,26 +45,35 @@ public class FastConsume extends Check implements Listener{
|
|||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void onItemConsume(final PlayerItemConsumeEvent event){
|
||||
final Player player = event.getPlayer();
|
||||
if (!isEnabled(player)) return;
|
||||
if (player.isDead() && BridgeHealth.getHealth(player) <= 0.0) {
|
||||
// Eat after death.
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (!isEnabled(player)) {
|
||||
return;
|
||||
}
|
||||
final InventoryData data = InventoryData.getData(player);
|
||||
if (check(player, event.getItem(), data)){
|
||||
final long time = System.currentTimeMillis();
|
||||
if (check(player, event.getItem(), time, data)){
|
||||
event.setCancelled(true);
|
||||
DataManager.getPlayerData(player.getName(), true).task.updateInventory();
|
||||
}
|
||||
data.instantEatInteract = 0;
|
||||
data.instantEatInteract = time;
|
||||
data.instantEatFood = null;
|
||||
}
|
||||
|
||||
private boolean check(final Player player, final ItemStack stack, final InventoryData data){
|
||||
private boolean check(final Player player, final ItemStack stack, final long time, final InventoryData data){
|
||||
// Uses the instant-eat data for convenience.
|
||||
// Consistency checks...
|
||||
if (stack == null){ // || stack.getType() != data.instantEatFood){
|
||||
// TODO: Strict version should prevent other material (?).
|
||||
return false;
|
||||
}
|
||||
final long time = System.currentTimeMillis();
|
||||
final long ref = Math.max(data.instantEatInteract, data.lastClickTime);
|
||||
final long ref = data.instantEatInteract == 0 ? 0 : Math.max(data.instantEatInteract, data.lastClickTime);
|
||||
if (time < ref){
|
||||
// Time ran backwards.
|
||||
data.instantEatInteract = data.lastClickTime = time;
|
||||
return false;
|
||||
}
|
||||
// Check exceptions.
|
||||
|
@ -71,11 +81,11 @@ public class FastConsume extends Check implements Listener{
|
|||
final Material mat = stack == null ? null : stack.getType();
|
||||
if (mat != null){
|
||||
if (cc.fastConsumeWhitelist){
|
||||
if (!cc.fastConsumeItems.contains(mat.getId())){
|
||||
if (!cc.fastConsumeItems.contains(mat)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (cc.fastConsumeItems.contains(mat.getId())){
|
||||
else if (cc.fastConsumeItems.contains(mat)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -18,14 +21,19 @@ public class BlockCacheBukkit extends BlockCache{
|
|||
@Override
|
||||
public void setAccess(World world) {
|
||||
this.world = world;
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public int fetchTypeId(final int x, final int y, final int z) {
|
||||
// TODO: consider setting type id and data at once.
|
||||
return world.getBlockTypeIdAt(x, y, z);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public int fetchData(final int x, final int y, final int z) {
|
||||
// TODO: consider setting type id and data at once.
|
||||
|
@ -49,8 +57,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;
|
||||
}
|
||||
|
|
|
@ -28,10 +28,12 @@ import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
|
|||
|
||||
public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{
|
||||
|
||||
// private AlmostBoolean entityPlayerAvailable = AlmostBoolean.MAYBE;
|
||||
|
||||
/**
|
||||
* Constructor to let it fail.
|
||||
*/
|
||||
public MCAccessBukkit(){
|
||||
public MCAccessBukkit() {
|
||||
// TODO: Add more that might fail if not supported ?
|
||||
Material.AIR.isSolid();
|
||||
Material.AIR.isOccluding();
|
||||
|
@ -43,7 +45,7 @@ public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{
|
|||
public String getMCVersion() {
|
||||
// Bukkit API.
|
||||
// TODO: maybe output something else.
|
||||
return "1.4.6|1.4.7|1.5.x|1.6.1|1.6.2|?";
|
||||
return "1.4.6|1.4.7|1.5.x|1.6.x|1.7.x"; // 1.7.x is bold!
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -55,7 +57,7 @@ public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{
|
|||
public CommandMap getCommandMap() {
|
||||
try{
|
||||
return (CommandMap) ReflectionUtil.invokeMethodNoArgs(Bukkit.getServer(), "getCommandMap");
|
||||
} catch (Throwable t){
|
||||
} catch (Throwable t) {
|
||||
// Nasty.
|
||||
return null;
|
||||
}
|
||||
|
@ -76,13 +78,19 @@ public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{
|
|||
|
||||
@Override
|
||||
public AlmostBoolean isBlockSolid(final int id) {
|
||||
@SuppressWarnings("deprecation")
|
||||
final Material mat = Material.getMaterial(id);
|
||||
if (mat == null) return AlmostBoolean.MAYBE;
|
||||
else return AlmostBoolean.match(mat.isSolid());
|
||||
if (mat == null) {
|
||||
return AlmostBoolean.MAYBE;
|
||||
}
|
||||
else {
|
||||
return AlmostBoolean.match(mat.isSolid());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlmostBoolean isBlockLiquid(final int id) {
|
||||
@SuppressWarnings("deprecation")
|
||||
final Material mat = Material.getMaterial(id);
|
||||
if (mat == null) return AlmostBoolean.MAYBE;
|
||||
switch (mat) {
|
||||
|
@ -104,8 +112,10 @@ public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{
|
|||
|
||||
@Override
|
||||
public AlmostBoolean isIllegalBounds(final Player player) {
|
||||
if (player.isDead()) return AlmostBoolean.NO;
|
||||
if (!player.isSleeping()){ // TODO: ignored sleeping ?
|
||||
if (player.isDead()) {
|
||||
return AlmostBoolean.NO;
|
||||
}
|
||||
if (!player.isSleeping()) { // TODO: ignored sleeping ?
|
||||
// TODO: This can test like ... nothing !
|
||||
// (Might not be necessary.)
|
||||
}
|
||||
|
@ -161,40 +171,43 @@ public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{
|
|||
// TODO: Might try stuff like setNoDamageTicks.
|
||||
BridgeHealth.damage(player, 1.0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setupBlockProperties(final WorldConfigProvider<?> worldConfigProvider) {
|
||||
// Note deprecation suppression: These ids should be unique for a server run, that should be ok for setting up generic properties.
|
||||
// TODO: (?) Set some generic properties matching what BlockCache.getShape returns.
|
||||
final Set<Integer> fullBlocks = new HashSet<Integer>();
|
||||
final Set<Material> fullBlocks = new HashSet<Material>();
|
||||
for (final Material mat : new Material[]{
|
||||
// TODO: Ice !? / Packed ice !?
|
||||
Material.GLASS, Material.GLOWSTONE, Material.ICE, Material.LEAVES,
|
||||
Material.COMMAND, Material.BEACON,
|
||||
Material.PISTON_BASE,
|
||||
}){
|
||||
fullBlocks.add(mat.getId());
|
||||
}) {
|
||||
fullBlocks.add(mat);
|
||||
}
|
||||
for (final Material mat : Material.values()){
|
||||
if (!mat.isBlock()) continue;
|
||||
final int id = mat.getId();
|
||||
if (id < 0 || id >= 4096 || fullBlocks.contains(id)) continue;
|
||||
if (!mat.isOccluding() || !mat.isSolid() || mat.isTransparent()){
|
||||
for (final Material mat : Material.values()) {
|
||||
if (!mat.isBlock()) {
|
||||
continue;
|
||||
}
|
||||
if (fullBlocks.contains(mat)) {
|
||||
continue;
|
||||
}
|
||||
if (!mat.isOccluding() || !mat.isSolid() || mat.isTransparent()) {
|
||||
// Uncertain bounding-box, allow passing through.
|
||||
long flags = BlockProperties.F_IGN_PASSABLE;
|
||||
if ((BlockProperties.isSolid(id) || BlockProperties.isGround(id)) && !BlockProperties.isLiquid(id)){
|
||||
if ((BlockProperties.isSolid(mat) || BlockProperties.isGround(mat)) && !BlockProperties.isLiquid(mat)) {
|
||||
// Block can be ground, so allow standing on any height.
|
||||
flags |= BlockProperties.F_GROUND_HEIGHT;
|
||||
}
|
||||
BlockProperties.setBlockFlags(id, BlockProperties.getBlockFlags(id) | flags);
|
||||
BlockProperties.setBlockFlags(mat, BlockProperties.getBlockFlags(mat) | flags);
|
||||
}
|
||||
}
|
||||
// Blocks that are reported to be full and solid, but which are not.
|
||||
for (final Material mat : new Material[]{
|
||||
Material.ENDER_PORTAL_FRAME,
|
||||
}){
|
||||
final int id = mat.getId();
|
||||
}) {
|
||||
final long flags = BlockProperties.F_IGN_PASSABLE | BlockProperties.F_GROUND_HEIGHT;
|
||||
BlockProperties.setBlockFlags(id, BlockProperties.getBlockFlags(id) | flags);
|
||||
BlockProperties.setBlockFlags(mat, BlockProperties.getBlockFlags(mat) | flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,9 +222,9 @@ public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{
|
|||
try{
|
||||
return mat.hasGravity();
|
||||
}
|
||||
catch(Throwable t){
|
||||
catch(Throwable t) {
|
||||
// Backwards compatibility.
|
||||
switch(mat){
|
||||
switch(mat) {
|
||||
case SAND:
|
||||
case GRAVEL:
|
||||
return true;
|
||||
|
@ -220,5 +233,10 @@ public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(Player player) {
|
||||
// // TODO: Consider using reflection (detect CraftPlayer, access EntityPlayer + check if possible (!), use flags for if valid or invalid.)
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
package fr.neatmonster.nocheatplus.compat.cb2511;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.server.AxisAlignedBB;
|
||||
import net.minecraft.server.IBlockAccess;
|
||||
import net.minecraft.server.Material;
|
||||
import net.minecraft.server.TileEntity;
|
||||
import net.minecraft.server.Vec3DPool;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.entity.CraftEntity;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
|
||||
public class BlockCacheCB2511 extends BlockCache implements IBlockAccess{
|
||||
|
||||
/** Box for one time use, no nesting, no extra storing this(!). */
|
||||
protected static final AxisAlignedBB useBox = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
|
||||
|
||||
protected net.minecraft.server.World world;
|
||||
|
||||
public BlockCacheCB2511(World world) {
|
||||
setAccess(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccess(final World world) {
|
||||
this.world = world == null ? null : ((CraftWorld) world).getHandle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fetchTypeId(final int x, final int y, final int z) {
|
||||
return world.getTypeId(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fetchData(final int x, final int y, final int z) {
|
||||
return world.getData(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] fetchBounds(final int x, final int y, final int z){
|
||||
|
||||
// TODO: change api for this / use nodes (!)
|
||||
final int id = getTypeId(x, y, z);
|
||||
final net.minecraft.server.Block block = net.minecraft.server.Block.byId[id];
|
||||
if (block == null) return null;
|
||||
block.updateShape(this, x, y, z); // TODO: use THIS instead of world.
|
||||
|
||||
// minX, minY, minZ, maxX, maxY, maxZ
|
||||
return new double[]{block.v(), block.x(), block.z(), block.w(), block.y(), block.A()};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean standsOnEntity(Entity entity, final double minX, final double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
|
||||
try{
|
||||
// TODO: Probably check other ids too before doing this ?
|
||||
|
||||
final net.minecraft.server.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
|
||||
final AxisAlignedBB box = useBox.b(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
@SuppressWarnings("rawtypes")
|
||||
final List list = world.getEntities(mcEntity, box);
|
||||
@SuppressWarnings("rawtypes")
|
||||
Iterator iterator = list.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final net.minecraft.server.Entity other = (net.minecraft.server.Entity) iterator.next();
|
||||
final EntityType type = other.getBukkitEntity().getType();
|
||||
if (type != EntityType.BOAT && type != EntityType.MINECART) continue;
|
||||
final AxisAlignedBB otherBox = other.boundingBox;
|
||||
if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) continue;
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable t){
|
||||
// Ignore exceptions (Context: DisguiseCraft).
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.utilities.BlockCache#cleanup()
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
super.cleanup();
|
||||
world = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getMaterial(final int x, final int y, final int z) {
|
||||
return world.getMaterial(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity getTileEntity(final int x, final int y, final int z) {
|
||||
return world.getTileEntity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3DPool getVec3DPool() {
|
||||
return world.getVec3DPool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlockFacePowered(final int arg0, final int arg1, final int arg2, final int arg3) {
|
||||
return world.isBlockFacePowered(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean t(final int x, final int y, final int z) {
|
||||
return world.t(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatibility with 1.4.2.
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @return
|
||||
*/
|
||||
public boolean s(final int x, final int y, final int z) {
|
||||
return world.t(x, y, z);
|
||||
}
|
||||
|
||||
}
|
|
@ -30,7 +30,12 @@ public class BlockCacheCB2512 extends BlockCache implements IBlockAccess{
|
|||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
this.world = world == null ? null : ((CraftWorld) world).getHandle();
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -99,7 +99,7 @@ public class MCAccessCB2512 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_4_5.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
|
@ -107,7 +107,7 @@ public class MCAccessCB2512 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_4_5.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
@ -134,13 +134,13 @@ public class MCAccessCB2512 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final net.minecraft.server.v1_4_5.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0 ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final net.minecraft.server.v1_4_5.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
@ -162,4 +162,13 @@ public class MCAccessCB2512 implements MCAccess{
|
|||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,12 @@ public class BlockCacheCB2545 extends BlockCache implements IBlockAccess{
|
|||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
this.world = world == null ? null : ((CraftWorld) world).getHandle();
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -99,7 +99,7 @@ public class MCAccessCB2545 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_4_6.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
|
@ -107,7 +107,7 @@ public class MCAccessCB2545 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_4_6.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
@ -134,13 +134,13 @@ public class MCAccessCB2545 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final net.minecraft.server.v1_4_6.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0 ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final net.minecraft.server.v1_4_6.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
@ -162,4 +162,13 @@ public class MCAccessCB2545 implements MCAccess{
|
|||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,12 @@ public class BlockCacheCB2602 extends BlockCache implements IBlockAccess{
|
|||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
this.world = world == null ? null : ((CraftWorld) world).getHandle();
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -100,7 +100,7 @@ public class MCAccessCB2602 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_4_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
|
@ -108,7 +108,7 @@ public class MCAccessCB2602 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_4_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
@ -135,13 +135,13 @@ public class MCAccessCB2602 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final net.minecraft.server.v1_4_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0 ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final net.minecraft.server.v1_4_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
@ -164,4 +164,13 @@ public class MCAccessCB2602 implements MCAccess{
|
|||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,12 @@ public class BlockCacheCB2645 extends BlockCache implements IBlockAccess{
|
|||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
this.world = world == null ? null : ((CraftWorld) world).getHandle();
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -101,7 +101,7 @@ public class MCAccessCB2645 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_5_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
|
@ -109,7 +109,7 @@ public class MCAccessCB2645 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_5_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
@ -136,13 +136,13 @@ public class MCAccessCB2645 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final net.minecraft.server.v1_5_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0 ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final net.minecraft.server.v1_5_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
@ -164,4 +164,13 @@ public class MCAccessCB2645 implements MCAccess{
|
|||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,12 @@ public class BlockCacheCB2691 extends BlockCache implements IBlockAccess{
|
|||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
this.world = world == null ? null : ((CraftWorld) world).getHandle();
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -62,7 +62,9 @@ public class MCAccessCB2691 implements MCAccess{
|
|||
final double entityHeight = Math.max(mcEntity.length, Math.max(mcEntity.height, mcEntity.boundingBox.e - mcEntity.boundingBox.b));
|
||||
if (entity instanceof LivingEntity) {
|
||||
return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight);
|
||||
} else return entityHeight;
|
||||
} else {
|
||||
return entityHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -101,7 +103,7 @@ public class MCAccessCB2691 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_5_R2.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
|
@ -109,7 +111,7 @@ public class MCAccessCB2691 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_5_R2.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
@ -136,13 +138,13 @@ public class MCAccessCB2691 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final net.minecraft.server.v1_5_R2.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0 ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final net.minecraft.server.v1_5_R2.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
@ -164,4 +166,13 @@ public class MCAccessCB2691 implements MCAccess{
|
|||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,12 @@ public class BlockCacheCB2763 extends BlockCache implements IBlockAccess{
|
|||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
this.world = world == null ? null : ((CraftWorld) world).getHandle();
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -101,7 +101,7 @@ public class MCAccessCB2763 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_5_R3.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
|
@ -109,7 +109,7 @@ public class MCAccessCB2763 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_5_R3.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
@ -136,13 +136,13 @@ public class MCAccessCB2763 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final net.minecraft.server.v1_5_R3.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0 ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final net.minecraft.server.v1_5_R3.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
@ -165,4 +165,13 @@ public class MCAccessCB2763 implements MCAccess{
|
|||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -24,11 +24,6 @@
|
|||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.6.1-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.6.1-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<description>Compatibility for CB 2794 (MC 1.6.1).
|
||||
|
|
|
@ -30,7 +30,12 @@ public class BlockCacheCB2794 extends BlockCache implements IBlockAccess{
|
|||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
this.world = world == null ? null : ((CraftWorld) world).getHandle();
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -101,7 +101,7 @@ public class MCAccessCB2794 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_6_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
|
@ -109,7 +109,7 @@ public class MCAccessCB2794 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_6_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
@ -136,13 +136,13 @@ public class MCAccessCB2794 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final net.minecraft.server.v1_6_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0.0f ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final net.minecraft.server.v1_6_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
@ -159,4 +159,13 @@ public class MCAccessCB2794 implements MCAccess{
|
|||
return mat.hasGravity();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -24,11 +24,6 @@
|
|||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.6.2-R1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.6.2-R1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<description>Compatibility for CB2808 (MC 1.6.2).
|
||||
|
|
|
@ -30,7 +30,12 @@ public class BlockCacheCB2808 extends BlockCache implements IBlockAccess{
|
|||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
this.world = world == null ? null : ((CraftWorld) world).getHandle();
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -102,7 +102,7 @@ public class MCAccessCB2808 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_6_R2.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
|
@ -110,7 +110,7 @@ public class MCAccessCB2808 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_6_R2.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
@ -137,13 +137,13 @@ public class MCAccessCB2808 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final net.minecraft.server.v1_6_R2.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0.0f ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final net.minecraft.server.v1_6_R2.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
@ -160,4 +160,13 @@ public class MCAccessCB2808 implements MCAccess{
|
|||
return mat.hasGravity();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -24,11 +24,6 @@
|
|||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.6.4-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.6.4-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<description>Compatibility for CB2882 (MC 1.6.4).
|
||||
|
|
|
@ -30,7 +30,12 @@ public class BlockCacheCB2882 extends BlockCache implements IBlockAccess{
|
|||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
this.world = world == null ? null : ((CraftWorld) world).getHandle();
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -103,7 +103,7 @@ public class MCAccessCB2882 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_6_R3.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
|
@ -111,7 +111,7 @@ public class MCAccessCB2882 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_6_R3.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
@ -138,13 +138,13 @@ public class MCAccessCB2882 implements MCAccess{
|
|||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final net.minecraft.server.v1_6_R3.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0.0f ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final net.minecraft.server.v1_6_R3.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
@ -161,4 +161,13 @@ public class MCAccessCB2882 implements MCAccess{
|
|||
return mat.hasGravity();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>fr.neatmonster</groupId>
|
||||
<artifactId>ncpcompatcb2511</artifactId>
|
||||
<artifactId>ncpcompatcb2922</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>NCPCompatCB2511</name>
|
||||
<name>NCPCompatCB2922</name>
|
||||
<version>static</version>
|
||||
|
||||
<parent>
|
||||
|
@ -22,11 +22,11 @@
|
|||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.4.5-R0.2</version>
|
||||
<version>1.7.2-R0.4-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<description>Compatibility up to CB2512 (i.e. 1.4.5-R0.2).
|
||||
<description>Compatibility for CB2922 (MC 1.7.2).
|
||||
|
||||
Version updating is done for the NoCheatPlus sub-module.</description>
|
||||
</project>
|
|
@ -0,0 +1,127 @@
|
|||
package fr.neatmonster.nocheatplus.compat.cb2922;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.server.v1_7_R1.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_7_R1.Block;
|
||||
import net.minecraft.server.v1_7_R1.EntityBoat;
|
||||
import net.minecraft.server.v1_7_R1.IBlockAccess;
|
||||
import net.minecraft.server.v1_7_R1.TileEntity;
|
||||
import net.minecraft.server.v1_7_R1.Vec3DPool;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.entity.CraftEntity;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
|
||||
public class BlockCacheCB2922 extends BlockCache implements IBlockAccess{
|
||||
|
||||
/** Box for one time use, no nesting, no extra storing this(!). */
|
||||
protected static final AxisAlignedBB useBox = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
|
||||
|
||||
protected net.minecraft.server.v1_7_R1.WorldServer world;
|
||||
|
||||
public BlockCacheCB2922(World world) {
|
||||
setAccess(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fetchTypeId(final int x, final int y, final int z) {
|
||||
return world.getTypeId(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fetchData(final int x, final int y, final int z) {
|
||||
return world.getData(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] fetchBounds(final int x, final int y, final int z){
|
||||
|
||||
// TODO: change api for this / use nodes (!)
|
||||
final int id = getTypeId(x, y, z);
|
||||
final net.minecraft.server.v1_7_R1.Block block = net.minecraft.server.v1_7_R1.Block.e(id);
|
||||
if (block == null) return null;
|
||||
block.updateShape(this, x, y, z); // TODO: use THIS instead of world.
|
||||
|
||||
// minX, minY, minZ, maxX, maxY, maxZ
|
||||
return new double[]{block.x(), block.z(), block.B(), block.y(), block.A(), block.C()};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean standsOnEntity(final Entity entity, final double minX, final double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
|
||||
try{
|
||||
// TODO: Probably check other ids too before doing this ?
|
||||
|
||||
final net.minecraft.server.v1_7_R1.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
|
||||
final AxisAlignedBB box = useBox.b(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
@SuppressWarnings("rawtypes")
|
||||
final List list = world.getEntities(mcEntity, box);
|
||||
@SuppressWarnings("rawtypes")
|
||||
final Iterator iterator = list.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final net.minecraft.server.v1_7_R1.Entity other = (net.minecraft.server.v1_7_R1.Entity) iterator.next();
|
||||
if (!(other instanceof EntityBoat)){ // && !(other instanceof EntityMinecart)) continue;
|
||||
continue;
|
||||
}
|
||||
if (minY >= other.locY && minY - other.locY <= 0.7){
|
||||
return true;
|
||||
}
|
||||
// Still check this for some reason.
|
||||
final AxisAlignedBB otherBox = other.boundingBox;
|
||||
if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) continue;
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable t){
|
||||
// Ignore exceptions (Context: DisguiseCraft).
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.utilities.BlockCache#cleanup()
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
super.cleanup();
|
||||
world = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity getTileEntity(final int x, final int y, final int z) {
|
||||
return world.getTileEntity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockPower(final int arg0, final int arg1, final int arg2, final int arg3) {
|
||||
return world.getBlockPower(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getType(int x, int y, int z) {
|
||||
return world.getType(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3DPool getVec3DPool() {
|
||||
return world.getVec3DPool();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,19 +1,19 @@
|
|||
package fr.neatmonster.nocheatplus.compat.cb2511;
|
||||
package fr.neatmonster.nocheatplus.compat.cb2922;
|
||||
|
||||
import net.minecraft.server.AxisAlignedBB;
|
||||
import net.minecraft.server.Block;
|
||||
import net.minecraft.server.DamageSource;
|
||||
import net.minecraft.server.EntityComplexPart;
|
||||
import net.minecraft.server.EntityPlayer;
|
||||
import net.minecraft.server.MobEffectList;
|
||||
import net.minecraft.server.v1_7_R1.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_7_R1.Block;
|
||||
import net.minecraft.server.v1_7_R1.DamageSource;
|
||||
import net.minecraft.server.v1_7_R1.EntityComplexPart;
|
||||
import net.minecraft.server.v1_7_R1.EntityPlayer;
|
||||
import net.minecraft.server.v1_7_R1.MobEffectList;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -23,33 +23,29 @@ import fr.neatmonster.nocheatplus.compat.MCAccess;
|
|||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
|
||||
|
||||
|
||||
public class MCAccessCB2511 implements MCAccess {
|
||||
public class MCAccessCB2922 implements MCAccess{
|
||||
|
||||
/**
|
||||
* Constructor to let it fail in time.
|
||||
* Constructor to let it fail.
|
||||
*/
|
||||
public MCAccessCB2511(){
|
||||
public MCAccessCB2922(){
|
||||
getCommandMap();
|
||||
ReflectionUtil.checkMembers("net.minecraft.server.", new String[]{"Entity" , "dead"});
|
||||
ReflectionUtil.checkMembers("net.minecraft.server.", new String[]{"EntityPlayer" , "netServerHandler"});
|
||||
ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.Block.class,
|
||||
new String[]{"v", "w", "x", "y", "z", "A"}, double.class);
|
||||
ReflectionUtil.checkMembers("net.minecraft.server.v1_7_R1.", new String[]{"Entity" , "dead"});
|
||||
// block bounds, original: minX, maxX, minY, maxY, minZ, maxZ
|
||||
ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_7_R1.Block.class,
|
||||
new String[]{"x", "y", "z", "A", "B", "C"}, double.class);
|
||||
// TODO: Nail it down further.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMCVersion() {
|
||||
return "1.4.2|1.4.4|1.4.5";
|
||||
// 1_7_R1
|
||||
return "1.7.2";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersionTag() {
|
||||
return "CB2511";
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockCache getBlockCache(World world) {
|
||||
return new BlockCacheCB2511(world);
|
||||
return "CB2922";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,9 +53,14 @@ public class MCAccessCB2511 implements MCAccess {
|
|||
return ((CraftServer) Bukkit.getServer()).getCommandMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockCache getBlockCache(final World world) {
|
||||
return new BlockCacheCB2922(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getHeight(final Entity entity) {
|
||||
final net.minecraft.server.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
final net.minecraft.server.v1_7_R1.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
final double entityHeight = Math.max(mcEntity.length, Math.max(mcEntity.height, mcEntity.boundingBox.e - mcEntity.boundingBox.b));
|
||||
if (entity instanceof LivingEntity) {
|
||||
return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight);
|
||||
|
@ -68,16 +69,16 @@ public class MCAccessCB2511 implements MCAccess {
|
|||
|
||||
@Override
|
||||
public AlmostBoolean isBlockSolid(final int id) {
|
||||
final Block block = Block.byId[id];
|
||||
if (block == null || block.material == null) return AlmostBoolean.MAYBE;
|
||||
else return AlmostBoolean.match(block.material.isSolid());
|
||||
final Block block = Block.e(id);
|
||||
if (block == null || block.getMaterial() == null) return AlmostBoolean.MAYBE;
|
||||
else return AlmostBoolean.match(block.getMaterial().isSolid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlmostBoolean isBlockLiquid(final int id) {
|
||||
final Block block = Block.byId[id];
|
||||
if (block == null || block.material == null) return AlmostBoolean.MAYBE;
|
||||
else return AlmostBoolean.match(block.material.isLiquid());
|
||||
final Block block = Block.e(id);
|
||||
if (block == null || block.getMaterial() == null) return AlmostBoolean.MAYBE;
|
||||
else return AlmostBoolean.match(block.getMaterial().isLiquid());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,6 +90,7 @@ public class MCAccessCB2511 implements MCAccess {
|
|||
public AlmostBoolean isIllegalBounds(final Player player) {
|
||||
final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (entityPlayer.dead) return AlmostBoolean.NO;
|
||||
// TODO: Does this need a method call for the "real" box? Might be no problem during moving events, though.
|
||||
final AxisAlignedBB box = entityPlayer.boundingBox;
|
||||
if (!entityPlayer.isSleeping()){
|
||||
// This can not really test stance but height of bounding box.
|
||||
|
@ -101,7 +103,7 @@ public class MCAccessCB2511 implements MCAccess {
|
|||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final net.minecraft.server.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
|
@ -109,7 +111,7 @@ public class MCAccessCB2511 implements MCAccess {
|
|||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final net.minecraft.server.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
@ -126,7 +128,7 @@ public class MCAccessCB2511 implements MCAccess {
|
|||
|
||||
@Override
|
||||
public void dealFallDamage(final Player player, final double damage) {
|
||||
((CraftPlayer) player).getHandle().damageEntity(DamageSource.FALL, (int) Math.round(damage));
|
||||
((CraftPlayer) player).getHandle().damageEntity(DamageSource.FALL, (float) damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -136,13 +138,13 @@ public class MCAccessCB2511 implements MCAccess {
|
|||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final net.minecraft.server.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0 ;
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0.0f ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final net.minecraft.server.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
@ -155,13 +157,17 @@ public class MCAccessCB2511 implements MCAccess {
|
|||
|
||||
@Override
|
||||
public boolean hasGravity(final Material mat) {
|
||||
switch(mat){
|
||||
case SAND:
|
||||
case GRAVEL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
// TODO: Test/check.
|
||||
return mat.hasGravity();
|
||||
}
|
||||
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
32
NCPCompatCB3026/pom.xml
Normal file
32
NCPCompatCB3026/pom.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>fr.neatmonster</groupId>
|
||||
<artifactId>ncpcompatcb3026</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>NCPCompatCB3026</name>
|
||||
<version>static</version>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.neatmonster</groupId>
|
||||
<artifactId>nocheatplus-parent</artifactId>
|
||||
<version>static</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.neatmonster</groupId>
|
||||
<artifactId>ncpcore</artifactId>
|
||||
<version>static</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.7.5-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<description>Compatibility for CB3026 (MC 1.7.5).
|
||||
|
||||
Version updating is done for the NoCheatPlus sub-module.</description>
|
||||
</project>
|
|
@ -0,0 +1,121 @@
|
|||
package fr.neatmonster.nocheatplus.compat.cb3026;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.server.v1_7_R2.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_7_R2.Block;
|
||||
import net.minecraft.server.v1_7_R2.EntityBoat;
|
||||
import net.minecraft.server.v1_7_R2.IBlockAccess;
|
||||
import net.minecraft.server.v1_7_R2.TileEntity;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_7_R2.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_7_R2.entity.CraftEntity;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
|
||||
public class BlockCacheCB3026 extends BlockCache implements IBlockAccess{
|
||||
|
||||
/** Box for one time use, no nesting, no extra storing this(!). */
|
||||
protected static final AxisAlignedBB useBox = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
|
||||
|
||||
protected net.minecraft.server.v1_7_R2.WorldServer world;
|
||||
|
||||
public BlockCacheCB3026(World world) {
|
||||
setAccess(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fetchTypeId(final int x, final int y, final int z) {
|
||||
return world.getTypeId(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fetchData(final int x, final int y, final int z) {
|
||||
return world.getData(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] fetchBounds(final int x, final int y, final int z){
|
||||
|
||||
// TODO: change api for this / use nodes (!)
|
||||
final int id = getTypeId(x, y, z);
|
||||
final net.minecraft.server.v1_7_R2.Block block = net.minecraft.server.v1_7_R2.Block.e(id);
|
||||
if (block == null) return null;
|
||||
block.updateShape(this, x, y, z); // TODO: use THIS instead of world.
|
||||
|
||||
// minX, minY, minZ, maxX, maxY, maxZ
|
||||
return new double[]{block.x(), block.z(), block.B(), block.y(), block.A(), block.C()};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean standsOnEntity(final Entity entity, final double minX, final double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
|
||||
try{
|
||||
// TODO: Probably check other ids too before doing this ?
|
||||
|
||||
final net.minecraft.server.v1_7_R2.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
|
||||
final AxisAlignedBB box = useBox.b(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
@SuppressWarnings("rawtypes")
|
||||
final List list = world.getEntities(mcEntity, box);
|
||||
@SuppressWarnings("rawtypes")
|
||||
final Iterator iterator = list.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final net.minecraft.server.v1_7_R2.Entity other = (net.minecraft.server.v1_7_R2.Entity) iterator.next();
|
||||
if (!(other instanceof EntityBoat)){ // && !(other instanceof EntityMinecart)) continue;
|
||||
continue;
|
||||
}
|
||||
if (minY >= other.locY && minY - other.locY <= 0.7){
|
||||
return true;
|
||||
}
|
||||
// Still check this for some reason.
|
||||
final AxisAlignedBB otherBox = other.boundingBox;
|
||||
if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) continue;
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable t){
|
||||
// Ignore exceptions (Context: DisguiseCraft).
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.utilities.BlockCache#cleanup()
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
super.cleanup();
|
||||
world = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity getTileEntity(final int x, final int y, final int z) {
|
||||
return world.getTileEntity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockPower(final int arg0, final int arg1, final int arg2, final int arg3) {
|
||||
return world.getBlockPower(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getType(int x, int y, int z) {
|
||||
return world.getType(x, y, z);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
package fr.neatmonster.nocheatplus.compat.cb3026;
|
||||
|
||||
import net.minecraft.server.v1_7_R2.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_7_R2.Block;
|
||||
import net.minecraft.server.v1_7_R2.DamageSource;
|
||||
import net.minecraft.server.v1_7_R2.EntityComplexPart;
|
||||
import net.minecraft.server.v1_7_R2.EntityPlayer;
|
||||
import net.minecraft.server.v1_7_R2.MobEffectList;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.craftbukkit.v1_7_R2.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_7_R2.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_7_R2.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
|
||||
import fr.neatmonster.nocheatplus.compat.MCAccess;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
|
||||
|
||||
public class MCAccessCB3026 implements MCAccess{
|
||||
|
||||
/**
|
||||
* Constructor to let it fail.
|
||||
*/
|
||||
public MCAccessCB3026(){
|
||||
getCommandMap();
|
||||
ReflectionUtil.checkMembers("net.minecraft.server.v1_7_R2.", new String[]{"Entity" , "dead"});
|
||||
// block bounds, original: minX, maxX, minY, maxY, minZ, maxZ
|
||||
ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_7_R2.Block.class,
|
||||
new String[]{"x", "y", "z", "A", "B", "C"}, double.class);
|
||||
// TODO: Nail it down further.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMCVersion() {
|
||||
// 1_7_R2
|
||||
return "1.7.5";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersionTag() {
|
||||
return "CB3026";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandMap getCommandMap() {
|
||||
return ((CraftServer) Bukkit.getServer()).getCommandMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockCache getBlockCache(final World world) {
|
||||
return new BlockCacheCB3026(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getHeight(final Entity entity) {
|
||||
final net.minecraft.server.v1_7_R2.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
final double entityHeight = Math.max(mcEntity.length, Math.max(mcEntity.height, mcEntity.boundingBox.e - mcEntity.boundingBox.b));
|
||||
if (entity instanceof LivingEntity) {
|
||||
return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight);
|
||||
} else return entityHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlmostBoolean isBlockSolid(final int id) {
|
||||
final Block block = Block.e(id);
|
||||
if (block == null || block.getMaterial() == null) return AlmostBoolean.MAYBE;
|
||||
else return AlmostBoolean.match(block.getMaterial().isSolid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlmostBoolean isBlockLiquid(final int id) {
|
||||
final Block block = Block.e(id);
|
||||
if (block == null || block.getMaterial() == null) return AlmostBoolean.MAYBE;
|
||||
else return AlmostBoolean.match(block.getMaterial().isLiquid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getWidth(final Entity entity) {
|
||||
return ((CraftEntity) entity).getHandle().width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlmostBoolean isIllegalBounds(final Player player) {
|
||||
final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (entityPlayer.dead) return AlmostBoolean.NO;
|
||||
// TODO: Does this need a method call for the "real" box? Might be no problem during moving events, though.
|
||||
final AxisAlignedBB box = entityPlayer.boundingBox;
|
||||
if (!entityPlayer.isSleeping()){
|
||||
// This can not really test stance but height of bounding box.
|
||||
final double dY = Math.abs(box.e - box.b);
|
||||
if (dY > 1.8) return AlmostBoolean.YES; // dY > 1.65D ||
|
||||
if (dY < 0.1D && entityPlayer.length >= 0.1) return AlmostBoolean.YES;
|
||||
}
|
||||
return AlmostBoolean.MAYBE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInvulnerableTicks(final Player player) {
|
||||
return ((CraftPlayer) player).getHandle().invulnerableTicks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInvulnerableTicks(final Player player, final int ticks) {
|
||||
((CraftPlayer) player).getHandle().invulnerableTicks = ticks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dealFallDamage(final Player player, final double damage) {
|
||||
((CraftPlayer) player).getHandle().damageEntity(DamageSource.FALL, (float) damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplexPart(final Entity entity) {
|
||||
return ((CraftEntity) entity).getHandle() instanceof EntityComplexPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0.0f ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getKeepAliveTime(final Player player) {
|
||||
// TODO: Implement if possible.
|
||||
return Long.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGravity(final Material mat) {
|
||||
// TODO: Test/check.
|
||||
return mat.hasGravity();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
32
NCPCompatCB3043/pom.xml
Normal file
32
NCPCompatCB3043/pom.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>fr.neatmonster</groupId>
|
||||
<artifactId>ncpcompatcb3043</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>NCPCompatCB3043</name>
|
||||
<version>static</version>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.neatmonster</groupId>
|
||||
<artifactId>nocheatplus-parent</artifactId>
|
||||
<version>static</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.neatmonster</groupId>
|
||||
<artifactId>ncpcore</artifactId>
|
||||
<version>static</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.7.9-R0.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<description>Compatibility for CB3043 (MC 1.7.10).
|
||||
|
||||
Version updating is done for the NoCheatPlus sub-module.</description>
|
||||
</project>
|
|
@ -0,0 +1,121 @@
|
|||
package fr.neatmonster.nocheatplus.compat.cb3043;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.server.v1_7_R3.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_7_R3.Block;
|
||||
import net.minecraft.server.v1_7_R3.EntityBoat;
|
||||
import net.minecraft.server.v1_7_R3.IBlockAccess;
|
||||
import net.minecraft.server.v1_7_R3.TileEntity;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_7_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_7_R3.entity.CraftEntity;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
|
||||
public class BlockCacheCB3043 extends BlockCache implements IBlockAccess{
|
||||
|
||||
/** Box for one time use, no nesting, no extra storing this(!). */
|
||||
protected static final AxisAlignedBB useBox = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
|
||||
|
||||
protected net.minecraft.server.v1_7_R3.WorldServer world;
|
||||
|
||||
public BlockCacheCB3043(World world) {
|
||||
setAccess(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fetchTypeId(final int x, final int y, final int z) {
|
||||
return world.getTypeId(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fetchData(final int x, final int y, final int z) {
|
||||
return world.getData(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] fetchBounds(final int x, final int y, final int z){
|
||||
|
||||
// TODO: change api for this / use nodes (!)
|
||||
final int id = getTypeId(x, y, z);
|
||||
final net.minecraft.server.v1_7_R3.Block block = net.minecraft.server.v1_7_R3.Block.e(id);
|
||||
if (block == null) return null;
|
||||
block.updateShape(this, x, y, z); // TODO: use THIS instead of world.
|
||||
|
||||
// minX, minY, minZ, maxX, maxY, maxZ
|
||||
return new double[]{block.x(), block.z(), block.B(), block.y(), block.A(), block.C()};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean standsOnEntity(final Entity entity, final double minX, final double minY, final double minZ, final double maxX, final double maxY, final double maxZ){
|
||||
try{
|
||||
// TODO: Probably check other ids too before doing this ?
|
||||
|
||||
final net.minecraft.server.v1_7_R3.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
|
||||
final AxisAlignedBB box = useBox.b(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
@SuppressWarnings("rawtypes")
|
||||
final List list = world.getEntities(mcEntity, box);
|
||||
@SuppressWarnings("rawtypes")
|
||||
final Iterator iterator = list.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final net.minecraft.server.v1_7_R3.Entity other = (net.minecraft.server.v1_7_R3.Entity) iterator.next();
|
||||
if (!(other instanceof EntityBoat)){ // && !(other instanceof EntityMinecart)) continue;
|
||||
continue;
|
||||
}
|
||||
if (minY >= other.locY && minY - other.locY <= 0.7){
|
||||
return true;
|
||||
}
|
||||
// Still check this for some reason.
|
||||
final AxisAlignedBB otherBox = other.boundingBox;
|
||||
if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) continue;
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable t){
|
||||
// Ignore exceptions (Context: DisguiseCraft).
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.utilities.BlockCache#cleanup()
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
super.cleanup();
|
||||
world = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity getTileEntity(final int x, final int y, final int z) {
|
||||
return world.getTileEntity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockPower(final int arg0, final int arg1, final int arg2, final int arg3) {
|
||||
return world.getBlockPower(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getType(int x, int y, int z) {
|
||||
return world.getType(x, y, z);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
package fr.neatmonster.nocheatplus.compat.cb3043;
|
||||
|
||||
import net.minecraft.server.v1_7_R3.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_7_R3.Block;
|
||||
import net.minecraft.server.v1_7_R3.DamageSource;
|
||||
import net.minecraft.server.v1_7_R3.EntityComplexPart;
|
||||
import net.minecraft.server.v1_7_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_7_R3.MobEffectList;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.craftbukkit.v1_7_R3.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_7_R3.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_7_R3.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
|
||||
import fr.neatmonster.nocheatplus.compat.MCAccess;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
|
||||
|
||||
public class MCAccessCB3043 implements MCAccess{
|
||||
|
||||
/**
|
||||
* Constructor to let it fail.
|
||||
*/
|
||||
public MCAccessCB3043() {
|
||||
getCommandMap();
|
||||
ReflectionUtil.checkMembers("net.minecraft.server.v1_7_R3.", new String[] {"Entity" , "dead"});
|
||||
// block bounds, original: minX, maxX, minY, maxY, minZ, maxZ
|
||||
ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_7_R3.Block.class,
|
||||
new String[]{"x", "y", "z", "A", "B", "C"}, double.class);
|
||||
// TODO: Nail it down further.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMCVersion() {
|
||||
// 1_7_R3
|
||||
return "1.7.8|1.7.9";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersionTag() {
|
||||
return "CB3043";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandMap getCommandMap() {
|
||||
return ((CraftServer) Bukkit.getServer()).getCommandMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockCache getBlockCache(final World world) {
|
||||
return new BlockCacheCB3043(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getHeight(final Entity entity) {
|
||||
final net.minecraft.server.v1_7_R3.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
final double entityHeight = Math.max(mcEntity.length, Math.max(mcEntity.height, mcEntity.boundingBox.e - mcEntity.boundingBox.b));
|
||||
if (entity instanceof LivingEntity) {
|
||||
return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight);
|
||||
} else return entityHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlmostBoolean isBlockSolid(final int id) {
|
||||
final Block block = Block.e(id);
|
||||
if (block == null || block.getMaterial() == null) {
|
||||
return AlmostBoolean.MAYBE;
|
||||
}
|
||||
else {
|
||||
return AlmostBoolean.match(block.getMaterial().isSolid());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlmostBoolean isBlockLiquid(final int id) {
|
||||
final Block block = Block.e(id);
|
||||
if (block == null || block.getMaterial() == null) {
|
||||
return AlmostBoolean.MAYBE;
|
||||
}
|
||||
else {
|
||||
return AlmostBoolean.match(block.getMaterial().isLiquid());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getWidth(final Entity entity) {
|
||||
return ((CraftEntity) entity).getHandle().width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlmostBoolean isIllegalBounds(final Player player) {
|
||||
final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (entityPlayer.dead) return AlmostBoolean.NO;
|
||||
// TODO: Does this need a method call for the "real" box? Might be no problem during moving events, though.
|
||||
final AxisAlignedBB box = entityPlayer.boundingBox;
|
||||
if (!entityPlayer.isSleeping()) {
|
||||
// This can not really test stance but height of bounding box.
|
||||
final double dY = Math.abs(box.e - box.b);
|
||||
if (dY > 1.8) {
|
||||
return AlmostBoolean.YES; // dY > 1.65D ||
|
||||
}
|
||||
if (dY < 0.1D && entityPlayer.length >= 0.1) {
|
||||
return AlmostBoolean.YES;
|
||||
}
|
||||
}
|
||||
return AlmostBoolean.MAYBE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) {
|
||||
return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
}
|
||||
else {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) {
|
||||
return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
}
|
||||
else {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInvulnerableTicks(final Player player) {
|
||||
return ((CraftPlayer) player).getHandle().invulnerableTicks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInvulnerableTicks(final Player player, final int ticks) {
|
||||
((CraftPlayer) player).getHandle().invulnerableTicks = ticks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dealFallDamage(final Player player, final double damage) {
|
||||
((CraftPlayer) player).getHandle().damageEntity(DamageSource.FALL, (float) damage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplexPart(final Entity entity) {
|
||||
return ((CraftEntity) entity).getHandle() instanceof EntityComplexPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0.0f ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getKeepAliveTime(final Player player) {
|
||||
// TODO: Implement if possible.
|
||||
return Long.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGravity(final Material mat) {
|
||||
// TODO: Test/check.
|
||||
return mat.hasGravity();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
|
@ -22,16 +22,17 @@
|
|||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>1.7.2-R0.4-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.7.2-R0.4-SNAPSHOT</version>
|
||||
<version>1.7.10-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<description>Compatibility for the development version (latest of the supported Minecraft versions).
|
||||
|
||||
Version updating is done for the NoCheatPlus sub-module.</description>
|
||||
Version updating is done for the NoCheatPlus sub-module.
|
||||
|
||||
To add a new compat module three other pom.xml files have to be modified:
|
||||
- Root pom (parent): Add as module.
|
||||
- NCPPlugin: Add as dependency.
|
||||
- NochCheatPlus: Add as include (source).
|
||||
</description>
|
||||
</project>
|
|
@ -3,16 +3,15 @@ package fr.neatmonster.nocheatplus.compat.cbdev;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.server.v1_7_R1.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_7_R1.Block;
|
||||
import net.minecraft.server.v1_7_R1.EntityBoat;
|
||||
import net.minecraft.server.v1_7_R1.IBlockAccess;
|
||||
import net.minecraft.server.v1_7_R1.TileEntity;
|
||||
import net.minecraft.server.v1_7_R1.Vec3DPool;
|
||||
import net.minecraft.server.v1_7_R4.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_7_R4.Block;
|
||||
import net.minecraft.server.v1_7_R4.EntityBoat;
|
||||
import net.minecraft.server.v1_7_R4.IBlockAccess;
|
||||
import net.minecraft.server.v1_7_R4.TileEntity;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_7_R4.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_7_R4.entity.CraftEntity;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
|
@ -22,7 +21,7 @@ public class BlockCacheCBDev extends BlockCache implements IBlockAccess{
|
|||
/** Box for one time use, no nesting, no extra storing this(!). */
|
||||
protected static final AxisAlignedBB useBox = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
|
||||
|
||||
protected net.minecraft.server.v1_7_R1.WorldServer world;
|
||||
protected net.minecraft.server.v1_7_R4.WorldServer world;
|
||||
|
||||
public BlockCacheCBDev(World world) {
|
||||
setAccess(world);
|
||||
|
@ -30,7 +29,12 @@ public class BlockCacheCBDev extends BlockCache implements IBlockAccess{
|
|||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
this.world = world == null ? null : ((CraftWorld) world).getHandle();
|
||||
if (world != null) {
|
||||
this.maxBlockY = world.getMaxHeight() - 1;
|
||||
this.world = ((CraftWorld) world).getHandle();
|
||||
} else {
|
||||
this.world = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,8 +52,10 @@ public class BlockCacheCBDev extends BlockCache implements IBlockAccess{
|
|||
|
||||
// TODO: change api for this / use nodes (!)
|
||||
final int id = getTypeId(x, y, z);
|
||||
final net.minecraft.server.v1_7_R1.Block block = net.minecraft.server.v1_7_R1.Block.e(id);
|
||||
if (block == null) return null;
|
||||
final net.minecraft.server.v1_7_R4.Block block = net.minecraft.server.v1_7_R4.Block.getById(id);
|
||||
if (block == null) {
|
||||
return null;
|
||||
}
|
||||
block.updateShape(this, x, y, z); // TODO: use THIS instead of world.
|
||||
|
||||
// minX, minY, minZ, maxX, maxY, maxZ
|
||||
|
@ -61,7 +67,7 @@ public class BlockCacheCBDev extends BlockCache implements IBlockAccess{
|
|||
try{
|
||||
// TODO: Probably check other ids too before doing this ?
|
||||
|
||||
final net.minecraft.server.v1_7_R1.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
final net.minecraft.server.v1_7_R4.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
|
||||
final AxisAlignedBB box = useBox.b(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
@ -69,7 +75,7 @@ public class BlockCacheCBDev extends BlockCache implements IBlockAccess{
|
|||
@SuppressWarnings("rawtypes")
|
||||
final Iterator iterator = list.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final net.minecraft.server.v1_7_R1.Entity other = (net.minecraft.server.v1_7_R1.Entity) iterator.next();
|
||||
final net.minecraft.server.v1_7_R4.Entity other = (net.minecraft.server.v1_7_R4.Entity) iterator.next();
|
||||
if (!(other instanceof EntityBoat)){ // && !(other instanceof EntityMinecart)) continue;
|
||||
continue;
|
||||
}
|
||||
|
@ -78,7 +84,9 @@ public class BlockCacheCBDev extends BlockCache implements IBlockAccess{
|
|||
}
|
||||
// Still check this for some reason.
|
||||
final AxisAlignedBB otherBox = other.boundingBox;
|
||||
if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) continue;
|
||||
if (box.a > otherBox.d || box.d < otherBox.a || box.b > otherBox.e || box.e < otherBox.b || box.c > otherBox.f || box.f < otherBox.c) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
|
@ -104,11 +112,6 @@ public class BlockCacheCBDev extends BlockCache implements IBlockAccess{
|
|||
return world.getTileEntity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3DPool getVec3DPool() {
|
||||
return world.getVec3DPool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockPower(final int arg0, final int arg1, final int arg2, final int arg3) {
|
||||
return world.getBlockPower(arg0, arg1, arg2, arg3);
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
package fr.neatmonster.nocheatplus.compat.cbdev;
|
||||
|
||||
import net.minecraft.server.v1_7_R1.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_7_R1.Block;
|
||||
import net.minecraft.server.v1_7_R1.DamageSource;
|
||||
import net.minecraft.server.v1_7_R1.EntityComplexPart;
|
||||
import net.minecraft.server.v1_7_R1.EntityPlayer;
|
||||
import net.minecraft.server.v1_7_R1.MobEffectList;
|
||||
import net.minecraft.server.v1_7_R4.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_7_R4.Block;
|
||||
import net.minecraft.server.v1_7_R4.DamageSource;
|
||||
import net.minecraft.server.v1_7_R4.EntityComplexPart;
|
||||
import net.minecraft.server.v1_7_R4.EntityPlayer;
|
||||
import net.minecraft.server.v1_7_R4.MobEffectList;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_7_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_7_R4.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_7_R4.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -28,24 +28,24 @@ public class MCAccessCBDev implements MCAccess{
|
|||
/**
|
||||
* Constructor to let it fail.
|
||||
*/
|
||||
public MCAccessCBDev(){
|
||||
public MCAccessCBDev() {
|
||||
getCommandMap();
|
||||
ReflectionUtil.checkMembers("net.minecraft.server.v1_7_R1.", new String[]{"Entity" , "dead"});
|
||||
ReflectionUtil.checkMembers("net.minecraft.server.v1_7_R4.", new String[] {"Entity" , "dead"});
|
||||
// block bounds, original: minX, maxX, minY, maxY, minZ, maxZ
|
||||
ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_7_R1.Block.class,
|
||||
ReflectionUtil.checkMethodReturnTypesNoArgs(net.minecraft.server.v1_7_R4.Block.class,
|
||||
new String[]{"x", "y", "z", "A", "B", "C"}, double.class);
|
||||
// TODO: Nail it down further.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMCVersion() {
|
||||
// 1_7_R1
|
||||
return "1.7.2";
|
||||
// 1_7_R4
|
||||
return "1.7.10";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerVersionTag() {
|
||||
return "CB2922-DEV";
|
||||
return "CB3100-DEV";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,7 +60,7 @@ public class MCAccessCBDev implements MCAccess{
|
|||
|
||||
@Override
|
||||
public double getHeight(final Entity entity) {
|
||||
final net.minecraft.server.v1_7_R1.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
final net.minecraft.server.v1_7_R4.Entity mcEntity = ((CraftEntity) entity).getHandle();
|
||||
final double entityHeight = Math.max(mcEntity.length, Math.max(mcEntity.height, mcEntity.boundingBox.e - mcEntity.boundingBox.b));
|
||||
if (entity instanceof LivingEntity) {
|
||||
return Math.max(((LivingEntity) entity).getEyeHeight(), entityHeight);
|
||||
|
@ -69,16 +69,24 @@ public class MCAccessCBDev implements MCAccess{
|
|||
|
||||
@Override
|
||||
public AlmostBoolean isBlockSolid(final int id) {
|
||||
final Block block = Block.e(id);
|
||||
if (block == null || block.getMaterial() == null) return AlmostBoolean.MAYBE;
|
||||
else return AlmostBoolean.match(block.getMaterial().isSolid());
|
||||
final Block block = Block.getById(id);
|
||||
if (block == null || block.getMaterial() == null) {
|
||||
return AlmostBoolean.MAYBE;
|
||||
}
|
||||
else {
|
||||
return AlmostBoolean.match(block.getMaterial().isSolid());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlmostBoolean isBlockLiquid(final int id) {
|
||||
final Block block = Block.e(id);
|
||||
if (block == null || block.getMaterial() == null) return AlmostBoolean.MAYBE;
|
||||
else return AlmostBoolean.match(block.getMaterial().isLiquid());
|
||||
final Block block = Block.getById(id);
|
||||
if (block == null || block.getMaterial() == null) {
|
||||
return AlmostBoolean.MAYBE;
|
||||
}
|
||||
else {
|
||||
return AlmostBoolean.match(block.getMaterial().isLiquid());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,31 +97,44 @@ public class MCAccessCBDev implements MCAccess{
|
|||
@Override
|
||||
public AlmostBoolean isIllegalBounds(final Player player) {
|
||||
final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (entityPlayer.dead) return AlmostBoolean.NO;
|
||||
if (entityPlayer.dead) {
|
||||
return AlmostBoolean.NO;
|
||||
}
|
||||
// TODO: Does this need a method call for the "real" box? Might be no problem during moving events, though.
|
||||
final AxisAlignedBB box = entityPlayer.boundingBox;
|
||||
if (!entityPlayer.isSleeping()){
|
||||
if (!entityPlayer.isSleeping()) {
|
||||
// This can not really test stance but height of bounding box.
|
||||
final double dY = Math.abs(box.e - box.b);
|
||||
if (dY > 1.8) return AlmostBoolean.YES; // dY > 1.65D ||
|
||||
if (dY < 0.1D && entityPlayer.length >= 0.1) return AlmostBoolean.YES;
|
||||
if (dY > 1.8) {
|
||||
return AlmostBoolean.YES; // dY > 1.65D ||
|
||||
}
|
||||
if (dY < 0.1D && entityPlayer.length >= 0.1) {
|
||||
return AlmostBoolean.YES;
|
||||
}
|
||||
}
|
||||
return AlmostBoolean.MAYBE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getJumpAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_7_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.JUMP)) {
|
||||
return mcPlayer.getEffect(MobEffectList.JUMP).getAmplifier();
|
||||
}
|
||||
else {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFasterMovementAmplifier(final Player player) {
|
||||
final net.minecraft.server.v1_7_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
else return Double.NEGATIVE_INFINITY;
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (mcPlayer.hasEffect(MobEffectList.FASTER_MOVEMENT)) {
|
||||
return mcPlayer.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier();
|
||||
}
|
||||
else {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -138,13 +159,13 @@ public class MCAccessCBDev implements MCAccess{
|
|||
|
||||
@Override
|
||||
public boolean shouldBeZombie(final Player player) {
|
||||
final net.minecraft.server.v1_7_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
return !mcPlayer.dead && mcPlayer.getHealth() <= 0.0f ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead(final Player player, final int deathTicks) {
|
||||
final net.minecraft.server.v1_7_R1.EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
mcPlayer.deathTicks = deathTicks;
|
||||
mcPlayer.dead = true;
|
||||
}
|
||||
|
@ -161,4 +182,13 @@ public class MCAccessCBDev implements MCAccess{
|
|||
return mat.hasGravity();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void correctDirection(final Player player) {
|
||||
// final EntityPlayer mcPlayer = ((CraftPlayer) player).getHandle();
|
||||
// // Main direction.
|
||||
// mcPlayer.yaw = LocUtil.correctYaw(mcPlayer.yaw);
|
||||
// mcPlayer.pitch = LocUtil.correctPitch(mcPlayer.pitch);
|
||||
// // Consider setting the lastYaw here too.
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
39
NCPCompatProtocolLib/pom.xml
Normal file
39
NCPCompatProtocolLib/pom.xml
Normal file
|
@ -0,0 +1,39 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>fr.neatmonster</groupId>
|
||||
<artifactId>ncpcompatprotocollib</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>NCPCompatProtocolLib</name>
|
||||
<version>static</version>
|
||||
|
||||
<parent>
|
||||
<groupId>fr.neatmonster</groupId>
|
||||
<artifactId>nocheatplus-parent</artifactId>
|
||||
<version>static</version>
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>comphenix-rep</id>
|
||||
<name>Comphenix Repository</name>
|
||||
<url>http://repo.comphenix.net/content/groups/public</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.neatmonster</groupId>
|
||||
<artifactId>ncpcore</artifactId>
|
||||
<version>static</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>LATEST</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<description>Features using the plugin ProtocolLib:
|
||||
http://dev.bukkit.org/bukkit-plugins/protocollib/</description>
|
||||
</project>
|
|
@ -0,0 +1,91 @@
|
|||
package fr.neatmonster.nocheatplus.net.protocollib;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.PacketType.Protocol;
|
||||
import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
|
||||
import fr.neatmonster.nocheatplus.components.JoinLeaveListener;
|
||||
import fr.neatmonster.nocheatplus.utilities.ActionFrequency;
|
||||
|
||||
/**
|
||||
* Prevent extremely fast ticking by just sending packets that don't do anything
|
||||
* new and also don't trigger moving events in CraftBukkit.
|
||||
*
|
||||
* @author dev1mc
|
||||
*
|
||||
*/
|
||||
public class MoveFrequency extends PacketAdapter implements Listener, JoinLeaveListener {
|
||||
|
||||
// TODO: Optimized options (receive only, other?).
|
||||
// TODO: Async version ?
|
||||
|
||||
// private static Collection<PacketType> getPacketTypes() {
|
||||
// final Collection<PacketType> packetTypes = PacketType.fromName("C03PacketPlayer");
|
||||
// if (packetTypes.isEmpty()) {
|
||||
// throw new RuntimeException("Packet types not available.");
|
||||
// }
|
||||
// return packetTypes;
|
||||
// }
|
||||
|
||||
private Map<String, ActionFrequency> freqMap = new LinkedHashMap<String, ActionFrequency>();
|
||||
|
||||
public MoveFrequency(Plugin plugin) {
|
||||
// PacketPlayInFlying[3, legacy: 10]
|
||||
super(plugin, PacketType.findCurrent(Protocol.PLAY, Sender.CLIENT, 3)); //getPacketTypes());
|
||||
// TODO: Try to get packet by name first + legacy first.
|
||||
}
|
||||
|
||||
private ActionFrequency addName(String name) {
|
||||
Map<String, ActionFrequency> freqMap = new HashMap<String, ActionFrequency>(this.freqMap);
|
||||
ActionFrequency freq = new ActionFrequency(5, 1000);
|
||||
freqMap.put(name, freq);
|
||||
this.freqMap = freqMap;
|
||||
return freq;
|
||||
}
|
||||
|
||||
private void removeName(String name) {
|
||||
Map<String, ActionFrequency> freq = new HashMap<String, ActionFrequency>(this.freqMap);
|
||||
freq.remove(name);
|
||||
this.freqMap = freq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerJoins(Player player) {
|
||||
addName(player.getName()); // Could spare that one.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerLeaves(Player player) {
|
||||
removeName(player.getName());
|
||||
}
|
||||
|
||||
private ActionFrequency getFreq(String name) {
|
||||
ActionFrequency freq = this.freqMap.get(name);
|
||||
if (freq == null) {
|
||||
return addName(name);
|
||||
} else {
|
||||
return freq;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceiving(PacketEvent event) {
|
||||
// TODO: Add several (at least has look + has pos individually, maybe none/onground)
|
||||
ActionFrequency freq = getFreq(event.getPlayer().getName());
|
||||
freq.add(System.currentTimeMillis(), 1f);
|
||||
if (freq.score(1f) > 300) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package fr.neatmonster.nocheatplus.net.protocollib;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
|
||||
import fr.neatmonster.nocheatplus.components.DisableListener;
|
||||
import fr.neatmonster.nocheatplus.logging.LogUtil;
|
||||
|
||||
/**
|
||||
* Quick and dirty ProtocolLib setup.
|
||||
* @author dev1mc
|
||||
*
|
||||
*/
|
||||
public class ProtocolLibComponent implements DisableListener{
|
||||
|
||||
private final List<PacketAdapter> registeredPacketAdapters = new LinkedList<PacketAdapter>();
|
||||
|
||||
public ProtocolLibComponent(Plugin plugin) {
|
||||
// Register with ProtocolLib
|
||||
final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
|
||||
LogUtil.logInfo("[NoCheatPlus] ProtocolLib seems to be available.");
|
||||
try {
|
||||
PacketAdapter adapter = new MoveFrequency(plugin);
|
||||
protocolManager.addPacketListener(adapter);
|
||||
registeredPacketAdapters.add(adapter);
|
||||
} catch (Throwable t) {
|
||||
LogUtil.logWarning("[NoCheatPlus] Could not register some packet-level hook.");
|
||||
LogUtil.logWarning(t); // TODO: Maybe temporary.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
|
||||
for (PacketAdapter adapter : registeredPacketAdapters) {
|
||||
try {
|
||||
protocolManager.removePacketListener(adapter);
|
||||
} catch (Throwable t) {
|
||||
LogUtil.logWarning("[NoCheatPlus] Failed to unregister protocol listener: " + adapter.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.7.2-R0.4-SNAPSHOT</version>
|
||||
<version>1.7.9-R0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>fr.neatmonster</groupId>
|
||||
|
|
|
@ -4,19 +4,22 @@ package fr.neatmonster.nocheatplus.actions;
|
|||
* Some wildcards that are used in commands and log messages.
|
||||
*/
|
||||
public enum ParameterName {
|
||||
// TODO: Cleanup for some kind of policies: useful names, alternative names, prefer generic names.
|
||||
BLOCK_ID("blockid"),
|
||||
BLOCK_TYPE("blocktype"),
|
||||
CHECK("check"),
|
||||
TAGS("tags"),
|
||||
DISTANCE("distance"),
|
||||
FALL_DISTANCE("falldistance"),
|
||||
FALL_DISTANCE("falldistance"), // TODO: rather not deprecate ?
|
||||
FOOD("food"),
|
||||
IP("ip"),
|
||||
LIMIT("limit"),
|
||||
LOCATION_FROM("locationfrom"),
|
||||
LOCATION_TO("locationto"),
|
||||
PACKETS("packets"),
|
||||
PLAYER("player"),
|
||||
REACH_DISTANCE("reachdistance"),
|
||||
PLAYER("player"), // TODO: playername rather ? + displayname ?
|
||||
REACH_DISTANCE("reachdistance"), // TODO: deprecate ?
|
||||
UUID("uuid"),
|
||||
VIOLATIONS("violations"),
|
||||
WORLD("world");
|
||||
|
||||
|
|
|
@ -135,6 +135,8 @@ public class ViolationData implements IViolationInfo, ActionData{
|
|||
return player.getName();
|
||||
case VIOLATIONS:
|
||||
return String.valueOf((long) Math.round(vL));
|
||||
case UUID:
|
||||
return player.getUniqueId().toString();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ public class BlockBreakConfig extends ACheckConfig {
|
|||
public final long fastBreakGrace;
|
||||
public final long fastBreakDelay;
|
||||
public final int fastBreakModSurvival;
|
||||
public final int fastBreakModCreative;
|
||||
public final ActionList fastBreakActions;
|
||||
|
||||
|
||||
|
@ -112,7 +111,6 @@ public class BlockBreakConfig extends ACheckConfig {
|
|||
fastBreakBucketDur = data.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_BUCKETS_DUR, 4000);
|
||||
fastBreakBucketFactor = (float) data.getDouble(ConfPaths.BLOCKBREAK_FASTBREAK_BUCKETS_FACTOR, 0.99);
|
||||
fastBreakBuckets = data.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_BUCKETS_N, 30);
|
||||
fastBreakModCreative = data.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_MOD_CREATIVE, 0);
|
||||
fastBreakModSurvival = data.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_MOD_SURVIVAL);
|
||||
// Fastbreak actions, shared.
|
||||
fastBreakActions = data.getOptimizedActionList(ConfPaths.BLOCKBREAK_FASTBREAK_ACTIONS, Permissions.BLOCKBREAK_FASTBREAK);
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.bukkit.inventory.ItemStack;
|
|||
import fr.neatmonster.nocheatplus.checks.CheckListener;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.inventory.Items;
|
||||
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
|
||||
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
|
||||
import fr.neatmonster.nocheatplus.permissions.Permissions;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
|
@ -48,7 +49,7 @@ public class BlockBreakListener extends CheckListener {
|
|||
/** The wrong block check. */
|
||||
private final WrongBlock wrongBlock = addCheck(new WrongBlock());
|
||||
|
||||
private boolean isInstaBreak = false;
|
||||
private AlmostBoolean isInstaBreak = AlmostBoolean.NO;
|
||||
|
||||
public BlockBreakListener(){
|
||||
super(CheckType.BLOCKBREAK);
|
||||
|
@ -60,18 +61,19 @@ public class BlockBreakListener extends CheckListener {
|
|||
* @param event
|
||||
* the event
|
||||
*/
|
||||
@EventHandler(
|
||||
ignoreCancelled = false, priority = EventPriority.LOWEST)
|
||||
@EventHandler(ignoreCancelled = false, priority = EventPriority.LOWEST)
|
||||
public void onBlockBreak(final BlockBreakEvent event) {
|
||||
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
// Illegal enchantments hotfix check.
|
||||
if (Items.checkIllegalEnchantments(player, player.getItemInHand())) event.setCancelled(true);
|
||||
if (Items.checkIllegalEnchantments(player, player.getItemInHand())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
// Cancelled events only leads to resetting insta break.
|
||||
if (event.isCancelled()){
|
||||
isInstaBreak = false;
|
||||
if (event.isCancelled()) {
|
||||
isInstaBreak = AlmostBoolean.NO;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -92,38 +94,45 @@ public class BlockBreakListener extends CheckListener {
|
|||
final GameMode gameMode = player.getGameMode();
|
||||
|
||||
// Has the player broken a block that was not damaged before?
|
||||
if (wrongBlock.isEnabled(player) && wrongBlock.check(player, block, cc, data, isInstaBreak))
|
||||
if (wrongBlock.isEnabled(player) && wrongBlock.check(player, block, cc, data, isInstaBreak)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
// Has the player broken more blocks per second than allowed?
|
||||
if (!cancelled && frequency.isEnabled(player) && frequency.check(player, cc, data))
|
||||
if (!cancelled && frequency.isEnabled(player) && frequency.check(player, cc, data)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
// Has the player broken blocks faster than possible?
|
||||
if (!cancelled && gameMode != GameMode.CREATIVE && fastBreak.isEnabled(player) && fastBreak.check(player, block, isInstaBreak, cc, data))
|
||||
cancelled = true;
|
||||
if (!cancelled && gameMode != GameMode.CREATIVE && fastBreak.isEnabled(player) && fastBreak.check(player, block, isInstaBreak, cc, data)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
// Did the arm of the player move before breaking this block?
|
||||
if (!cancelled && noSwing.isEnabled(player) && noSwing.check(player, data))
|
||||
cancelled = true;
|
||||
if (!cancelled && noSwing.isEnabled(player) && noSwing.check(player, data)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
// Is the block really in reach distance?
|
||||
if (!cancelled && reach.isEnabled(player) && reach.check(player, block, data))
|
||||
cancelled = true;
|
||||
if (!cancelled && reach.isEnabled(player) && reach.check(player, block, data)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
// Did the player look at the block at all?
|
||||
if (!cancelled && direction.isEnabled(player) && direction.check(player, block, data))
|
||||
cancelled = true;
|
||||
if (!cancelled && direction.isEnabled(player) && direction.check(player, block, data)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
// Destroying liquid blocks.
|
||||
if (!cancelled && BlockProperties.isLiquid(block.getTypeId()) && !player.hasPermission(Permissions.BLOCKBREAK_BREAK_LIQUID) && !NCPExemptionManager.isExempted(player, CheckType.BLOCKBREAK_BREAK)){
|
||||
if (!cancelled && BlockProperties.isLiquid(block.getType()) && !player.hasPermission(Permissions.BLOCKBREAK_BREAK_LIQUID) && !NCPExemptionManager.isExempted(player, CheckType.BLOCKBREAK_BREAK)){
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
// At least one check failed and demanded to cancel the event.
|
||||
if (cancelled){
|
||||
// On cancel...
|
||||
if (cancelled) {
|
||||
event.setCancelled(cancelled);
|
||||
// Reset damage position:
|
||||
// TODO: Review this (!), check if set at all !?
|
||||
data.clickedX = block.getX();
|
||||
data.clickedY = block.getY();
|
||||
data.clickedZ = block.getZ();
|
||||
|
@ -133,16 +142,17 @@ public class BlockBreakListener extends CheckListener {
|
|||
// data.clickedX = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
if (isInstaBreak){
|
||||
if (isInstaBreak.decideOptimistically()) {
|
||||
data.wasInstaBreak = now;
|
||||
}
|
||||
else
|
||||
else {
|
||||
data.wasInstaBreak = 0;
|
||||
}
|
||||
|
||||
// Adjust data.
|
||||
data.fastBreakBreakTime = now;
|
||||
// data.fastBreakfirstDamage = now;
|
||||
isInstaBreak = false;
|
||||
isInstaBreak = AlmostBoolean.NO;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,18 +185,32 @@ public class BlockBreakListener extends CheckListener {
|
|||
|
||||
// Return if it is not left clicking a block.
|
||||
// (Allows right click to be ignored.)
|
||||
isInstaBreak = false;
|
||||
if (event.getAction() != Action.LEFT_CLICK_BLOCK) return;
|
||||
isInstaBreak = AlmostBoolean.NO;
|
||||
if (event.getAction() != Action.LEFT_CLICK_BLOCK) {
|
||||
return;
|
||||
}
|
||||
checkBlockDamage(event.getPlayer(), event.getClickedBlock(), event);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(
|
||||
ignoreCancelled = false, priority = EventPriority.MONITOR)
|
||||
@EventHandler(ignoreCancelled = false, priority = EventPriority.LOWEST)
|
||||
public void onBlockDamageLowest(final BlockDamageEvent event) {
|
||||
if (event.getInstaBreak()) {
|
||||
// Indicate that this might have been set by CB/MC.
|
||||
isInstaBreak = AlmostBoolean.MAYBE;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = false, priority = EventPriority.MONITOR)
|
||||
public void onBlockDamage(final BlockDamageEvent event) {
|
||||
// System.out.println("Damage("+event.isCancelled()+"): " + event.getBlock());
|
||||
if (!event.isCancelled() && event.getInstaBreak()) isInstaBreak = true;
|
||||
else isInstaBreak = false;
|
||||
if (!event.isCancelled() && event.getInstaBreak()) {
|
||||
// Keep MAYBE.
|
||||
if (isInstaBreak != AlmostBoolean.MAYBE) {
|
||||
isInstaBreak = AlmostBoolean.YES;
|
||||
}
|
||||
}
|
||||
else {
|
||||
isInstaBreak = AlmostBoolean.NO;
|
||||
}
|
||||
checkBlockDamage(event.getPlayer(), event.getBlock(), event);
|
||||
}
|
||||
|
||||
|
@ -202,8 +226,9 @@ public class BlockBreakListener extends CheckListener {
|
|||
// }
|
||||
|
||||
// Do not care about null blocks.
|
||||
if (block == null)
|
||||
return;
|
||||
if (block == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int tick = TickTask.getTick();
|
||||
// Skip if already set to the same block without breaking within one tick difference.
|
||||
|
@ -211,10 +236,14 @@ public class BlockBreakListener extends CheckListener {
|
|||
final Material tool = stack == null ? null: stack.getType();
|
||||
if (data.toolChanged(tool)) {
|
||||
// Update.
|
||||
} else if (tick < data.clickedTick) {
|
||||
// Update.
|
||||
} else if (tick < data.clickedTick || now < data.fastBreakfirstDamage || now < data.fastBreakBreakTime) {
|
||||
// Time/tick ran backwards: Update.
|
||||
// Tick running backwards should not happen in the main thread unless for reload. A plugin could reset it (not intended).
|
||||
} else if (data.fastBreakBreakTime < data.fastBreakfirstDamage && data.clickedX == block.getX() && data.clickedZ == block.getZ() && data.clickedY == block.getY()){
|
||||
if (tick - data.clickedTick <= 1 ) return;
|
||||
// Preserve first damage time.
|
||||
if (tick - data.clickedTick <= 1 ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// (Always set, the interact event only fires once: the first time.)
|
||||
// Only record first damage:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package fr.neatmonster.nocheatplus.checks.blockbreak;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
@ -10,6 +10,7 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
|
|||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.ViolationData;
|
||||
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
|
||||
import fr.neatmonster.nocheatplus.permissions.Permissions;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
import fr.neatmonster.nocheatplus.utilities.PotionUtil;
|
||||
|
@ -28,7 +29,7 @@ public class FastBreak extends Check {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks a player.
|
||||
* Checks a player for fastbreak. This is NOT for creative mode.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
|
@ -40,84 +41,83 @@ public class FastBreak extends Check {
|
|||
* @param elaspedTime
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player, final Block block, final boolean isInstaBreak, final BlockBreakConfig cc, final BlockBreakData data) {
|
||||
public boolean check(final Player player, final Block block, final AlmostBoolean isInstaBreak, final BlockBreakConfig cc, final BlockBreakData data) {
|
||||
final long now = System.currentTimeMillis();
|
||||
boolean cancel = false;
|
||||
|
||||
// First, check the game mode of the player and choose the right limit.
|
||||
final long breakingTime;
|
||||
final int id = block.getTypeId();
|
||||
if (player.getGameMode() == GameMode.CREATIVE)
|
||||
// Modifier defaults to 0, the Frequency check is responsible for those.
|
||||
breakingTime = Math.max(0, Math.round((double) cc.fastBreakModCreative / 100D * (double) 100));
|
||||
else
|
||||
breakingTime = Math.max(0, Math.round((double) cc.fastBreakModSurvival / 100D * (double) BlockProperties.getBreakingDuration(id, player)));
|
||||
// fastBreakfirstDamage is the first interact on block (!).
|
||||
// Determine expected breaking time by block type.
|
||||
final Material blockType = block.getType();
|
||||
final long expectedBreakingTime = Math.max(0, Math.round((double) BlockProperties.getBreakingDuration(blockType, player) * (double) cc.fastBreakModSurvival / 100D));
|
||||
|
||||
final long elapsedTime;
|
||||
// TODO: Concept for unbreakable blocks? Context: extreme VL.
|
||||
// TODO: Should it be breakingTime instead of 0 for inconsistencies?
|
||||
if (cc.fastBreakStrict){
|
||||
if (cc.fastBreakStrict) {
|
||||
// Counting interact...break.
|
||||
elapsedTime = (data.fastBreakBreakTime > data.fastBreakfirstDamage) ? 0 : now - data.fastBreakfirstDamage;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
// Counting break...break.
|
||||
elapsedTime = (data.fastBreakBreakTime > now) ? 0 : now - data.fastBreakBreakTime;
|
||||
}
|
||||
|
||||
// Check if the time used time is lower than expected.
|
||||
// if (isInstaBreak){
|
||||
// // Ignore those for now.
|
||||
// }
|
||||
// else
|
||||
if (elapsedTime < 0){
|
||||
if (isInstaBreak.decideOptimistically()) {
|
||||
// Ignore those for now.
|
||||
// TODO: Find out why this was commented out long ago a) did not fix mcMMO b) exploits.
|
||||
// TODO: Maybe adjust time to min(time, SOMETHING) for MAYBE/YES.
|
||||
}
|
||||
else if (elapsedTime < 0) {
|
||||
// Ignore it. TODO: ?
|
||||
}
|
||||
else if (elapsedTime + cc.fastBreakDelay < breakingTime){
|
||||
else if (elapsedTime + cc.fastBreakDelay < expectedBreakingTime) {
|
||||
// lag or cheat or Minecraft.
|
||||
|
||||
// Count in server side lag, if desired.
|
||||
final float lag = cc.lag ? TickTask.getLag(breakingTime, true) : 1f;
|
||||
final float lag = cc.lag ? TickTask.getLag(expectedBreakingTime, true) : 1f;
|
||||
|
||||
final long missingTime = breakingTime - (long) (lag * elapsedTime);
|
||||
final long missingTime = expectedBreakingTime - (long) (lag * elapsedTime);
|
||||
|
||||
if (missingTime > 0){
|
||||
if (missingTime > 0) {
|
||||
// Add as penalty
|
||||
data.fastBreakPenalties.add(now, (float) missingTime);
|
||||
|
||||
|
||||
// Only raise a violation, if the total penalty score exceeds the contention duration (for lag, delay).
|
||||
if (data.fastBreakPenalties.score(cc.fastBreakBucketFactor) > cc.fastBreakGrace){
|
||||
if (data.fastBreakPenalties.score(cc.fastBreakBucketFactor) > cc.fastBreakGrace) {
|
||||
// TODO: maybe add one absolute penalty time for big amounts to stop breaking until then
|
||||
final double vlAdded = (double) missingTime / 1000.0;
|
||||
data.fastBreakVL += vlAdded;
|
||||
final ViolationData vd = new ViolationData(this, player, data.fastBreakVL, vlAdded, cc.fastBreakActions);
|
||||
if (vd.needsParameters()) vd.setParameter(ParameterName.BLOCK_ID, "" + id);
|
||||
if (vd.needsParameters()) {
|
||||
vd.setParameter(ParameterName.BLOCK_TYPE, blockType.toString());
|
||||
vd.setParameter(ParameterName.BLOCK_ID, Integer.toString(BlockProperties.getId(blockType)));
|
||||
}
|
||||
cancel = executeActions(vd);
|
||||
}
|
||||
// else: still within contention limits.
|
||||
}
|
||||
}
|
||||
else if (breakingTime > cc.fastBreakDelay){
|
||||
else if (expectedBreakingTime > cc.fastBreakDelay) {
|
||||
// Fast breaking does not decrease violation level.
|
||||
data.fastBreakVL *= 0.9D;
|
||||
}
|
||||
|
||||
if ((cc.fastBreakDebug || cc.debug) && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)){
|
||||
if ((cc.fastBreakDebug || cc.debug) && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)) {
|
||||
// General stats:
|
||||
if (data.stats != null){
|
||||
data.stats.addStats(data.stats.getId(Integer.toString(block.getTypeId())+"u", true), elapsedTime);
|
||||
data.stats.addStats(data.stats.getId(Integer.toString(block.getTypeId())+ "r", true), breakingTime);
|
||||
if (data.stats != null) {
|
||||
data.stats.addStats(data.stats.getId(blockType+ "/u", true), elapsedTime);
|
||||
data.stats.addStats(data.stats.getId(blockType + "/r", true), expectedBreakingTime);
|
||||
player.sendMessage(data.stats.getStatsStr(true));
|
||||
}
|
||||
// Send info about current break:
|
||||
final int blockId = block.getTypeId();
|
||||
final ItemStack stack = player.getItemInHand();
|
||||
final boolean isValidTool = BlockProperties.isValidTool(blockId, stack);
|
||||
final boolean isValidTool = BlockProperties.isValidTool(blockType, stack);
|
||||
final double haste = PotionUtil.getPotionEffectAmplifier(player, PotionEffectType.FAST_DIGGING);
|
||||
String msg = (isInstaBreak ? "[Insta]" : "[Normal]") + "[" + blockId + "] "+ elapsedTime + "u / " + breakingTime +"r (" + (isValidTool?"tool":"no-tool") + ")" + (haste == Double.NEGATIVE_INFINITY ? "" : " haste=" + ((int) haste + 1));
|
||||
String msg = (isInstaBreak.decideOptimistically() ? ("[Insta=" + isInstaBreak + "]") : "[Normal]") + "[" + blockType + "] "+ elapsedTime + "u / " + expectedBreakingTime +"r (" + (isValidTool?"tool":"no-tool") + ")" + (haste == Double.NEGATIVE_INFINITY ? "" : " haste=" + ((int) haste + 1));
|
||||
player.sendMessage(msg);
|
||||
// net.minecraft.server.Item mcItem = net.minecraft.server.Item.byId[stack.getTypeId()];
|
||||
// if (mcItem != null){
|
||||
// if (mcItem != null) {
|
||||
// double x = mcItem.getDestroySpeed(((CraftItemStack) stack).getHandle(), net.minecraft.server.Block.byId[blockId]);
|
||||
// player.sendMessage("mc speed: " + x);
|
||||
// }
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.bukkit.entity.Player;
|
|||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.combined.Improbable;
|
||||
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
|
||||
import fr.neatmonster.nocheatplus.permissions.Permissions;
|
||||
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
|
||||
|
||||
|
@ -26,45 +27,50 @@ public class WrongBlock extends Check {
|
|||
* @param isInstaBreak
|
||||
* @return
|
||||
*/
|
||||
public boolean check(final Player player, final Block block, final BlockBreakConfig cc, final BlockBreakData data, final boolean isInstaBreak){
|
||||
public boolean check(final Player player, final Block block, final BlockBreakConfig cc, final BlockBreakData data, final AlmostBoolean isInstaBreak) {
|
||||
|
||||
boolean cancel = false;
|
||||
|
||||
final boolean wrongTime = data.fastBreakfirstDamage < data.fastBreakBreakTime;
|
||||
final int dist = TrigUtil.manhattan(data.clickedX, data.clickedY, data.clickedZ, block);
|
||||
final int dist = Math.min(4, data.clickedX == Integer.MAX_VALUE ? 100 : TrigUtil.manhattan(data.clickedX, data.clickedY, data.clickedZ, block));
|
||||
final boolean wrongBlock;
|
||||
final long now = System.currentTimeMillis();
|
||||
if (dist == 0){
|
||||
if (wrongTime){
|
||||
// TODO: Remove isInstaBreak argument or use it.
|
||||
if (dist == 0) {
|
||||
if (wrongTime) {
|
||||
data.fastBreakBreakTime = now;
|
||||
data.fastBreakfirstDamage = now;
|
||||
// Could set to wrong block, but prefer to transform it into a quasi insta break.
|
||||
}
|
||||
wrongBlock = false;
|
||||
}
|
||||
else if (dist == 1){
|
||||
else if (dist == 1) {
|
||||
// One might to a concession in case of instant breaking.
|
||||
if (now - data.wasInstaBreak < 60)
|
||||
if (now - data.wasInstaBreak < 60) {
|
||||
wrongBlock = false;
|
||||
else
|
||||
}
|
||||
else {
|
||||
wrongBlock = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
// Note that the maximally counted distance is set above.
|
||||
wrongBlock = true;
|
||||
}
|
||||
|
||||
if (wrongBlock){
|
||||
// Manhattan distance.
|
||||
|
||||
if ((cc.fastBreakDebug || cc.debug) && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)){
|
||||
if (wrongBlock) {
|
||||
if ((cc.fastBreakDebug || cc.debug) && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)) {
|
||||
player.sendMessage("WrongBlock failure with dist: " + dist);
|
||||
}
|
||||
data.wrongBlockVL.add(now, (float) (dist + 1) / 2f);
|
||||
final float score = data.wrongBlockVL.score(0.9f);
|
||||
if (score > cc.wrongBLockLevel){
|
||||
if (executeActions(player, score, 1D, cc.wrongBlockActions))
|
||||
if (score > cc.wrongBLockLevel) {
|
||||
if (executeActions(player, score, 1D, cc.wrongBlockActions)) {
|
||||
cancel = true;
|
||||
if (Improbable.check(player, 2.0f, now, "blockbreak.wrongblock"))
|
||||
}
|
||||
if (Improbable.check(player, 2.0f, now, "blockbreak.wrongblock")) {
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.bukkit.inventory.ItemStack;
|
|||
import fr.neatmonster.nocheatplus.checks.CheckListener;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.combined.CombinedConfig;
|
||||
import fr.neatmonster.nocheatplus.compat.BridgeHealth;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
|
||||
/**
|
||||
|
@ -36,6 +37,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);
|
||||
}
|
||||
|
@ -49,6 +53,15 @@ public class BlockInteractListener extends CheckListener {
|
|||
@EventHandler(
|
||||
ignoreCancelled = false, priority = EventPriority.LOWEST)
|
||||
protected void onPlayerInteract(final PlayerInteractEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
// Cancel interact events for dead players.
|
||||
if (player.isDead() && BridgeHealth.getHealth(player) <= 0.0) {
|
||||
// Auto-soup after death.
|
||||
event.setUseInteractedBlock(Result.DENY);
|
||||
event.setUseItemInHand(Result.DENY);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Re-arrange for interact spam, possibly move ender pearl stuff to a method.
|
||||
final Action action = event.getAction();
|
||||
|
@ -57,7 +70,7 @@ public class BlockInteractListener extends CheckListener {
|
|||
if (block == null){
|
||||
return;
|
||||
}
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
final BlockInteractData data = BlockInteractData.getData(player);
|
||||
data.setLastBlock(block, action);
|
||||
switch(action){
|
||||
|
@ -65,8 +78,8 @@ public class BlockInteractListener extends CheckListener {
|
|||
break;
|
||||
case RIGHT_CLICK_BLOCK:
|
||||
final ItemStack stack = player.getItemInHand();
|
||||
if (stack != null && stack.getTypeId() == Material.ENDER_PEARL.getId()){
|
||||
if (!BlockProperties.isPassable(block.getTypeId())){
|
||||
if (stack != null && stack.getType() == Material.ENDER_PEARL){
|
||||
if (!BlockProperties.isPassable(block.getType())){
|
||||
final CombinedConfig ccc = CombinedConfig.getConfig(player);
|
||||
if (ccc.enderPearlCheck && ccc.enderPearlPreventClickBlock){
|
||||
event.setUseItemInHand(Result.DENY);
|
||||
|
@ -86,7 +99,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 +127,6 @@ public class BlockInteractListener extends CheckListener {
|
|||
event.setUseItemInHand(Result.DENY);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
useLoc.setWorld(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
|
|||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.ViolationData;
|
||||
import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakData;
|
||||
import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractData;
|
||||
import fr.neatmonster.nocheatplus.permissions.Permissions;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
import fr.neatmonster.nocheatplus.utilities.TickTask;
|
||||
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
|
||||
|
@ -29,8 +29,8 @@ public class Against extends Check {
|
|||
boolean violation = false;
|
||||
// TODO: Make more precise (workarounds like WATER_LILY, general points).
|
||||
// Workaround for signs on cactus and similar.
|
||||
final int againstId = blockAgainst.getTypeId();
|
||||
if (againstId == Material.AIR.getId()) {
|
||||
final Material againstType = blockAgainst.getType();
|
||||
if (againstType == null || againstType == Material.AIR) {
|
||||
// Attempt to workaround blocks like cactus.
|
||||
final BlockInteractData bdata = BlockInteractData.getData(player);
|
||||
if (bdata.lastType != null && bdata.lastX != Integer.MAX_VALUE && TickTask.getTick() == bdata.lastTick && TrigUtil.manhattan(bdata.lastX, bdata.lastY, bdata.lastZ, blockAgainst) == 0) {
|
||||
|
@ -41,19 +41,20 @@ public class Against extends Check {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
if (BlockProperties.isLiquid(againstId)) {
|
||||
if ((placedMat != Material.WATER_LILY || !BlockProperties.isLiquid(block.getRelative(BlockFace.DOWN).getTypeId()))) {
|
||||
if (BlockProperties.isLiquid(againstType)) {
|
||||
if ((placedMat != Material.WATER_LILY || !BlockProperties.isLiquid(block.getRelative(BlockFace.DOWN).getType())) && !player.hasPermission(Permissions.BLOCKPLACE_AGAINST_LIQUIDS)) {
|
||||
violation = true;
|
||||
}
|
||||
}
|
||||
else if (againstId == Material.AIR.getId()) {
|
||||
else if (againstType == Material.AIR && !player.hasPermission(Permissions.BLOCKPLACE_AGAINST_AIR)) {
|
||||
violation = true;
|
||||
}
|
||||
// Handle violation and return.
|
||||
if (violation) {
|
||||
data.againstVL += 1.0;
|
||||
final ViolationData vd = new ViolationData(this, player, data.againstVL, 1, cc.againstActions);
|
||||
vd.setParameter(ParameterName.BLOCK_ID, Integer.toString(placedMat.getId()));
|
||||
vd.setParameter(ParameterName.BLOCK_TYPE, placedMat.toString());
|
||||
vd.setParameter(ParameterName.BLOCK_ID, Integer.toString(BlockProperties.getId(placedMat)));
|
||||
return executeActions(vd);
|
||||
} else {
|
||||
data.againstVL *= 0.99; // Assume one false positive every 100 blocks.
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package fr.neatmonster.nocheatplus.checks.blockplace;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ActionList;
|
||||
|
@ -69,6 +72,7 @@ public class BlockPlaceConfig extends ACheckConfig {
|
|||
public final ActionList fastPlaceActions;
|
||||
|
||||
public final boolean noSwingCheck;
|
||||
public final Set<Material> noSwingExceptions = new HashSet<Material>();
|
||||
public final ActionList noSwingActions;
|
||||
|
||||
public final boolean reachCheck;
|
||||
|
@ -104,6 +108,7 @@ public class BlockPlaceConfig extends ACheckConfig {
|
|||
fastPlaceActions = data.getOptimizedActionList(ConfPaths.BLOCKPLACE_FASTPLACE_ACTIONS, Permissions.BLOCKPLACE_FASTPLACE);
|
||||
|
||||
noSwingCheck = data.getBoolean(ConfPaths.BLOCKPLACE_NOSWING_CHECK);
|
||||
data.readMaterialFromList(ConfPaths.BLOCKPLACE_NOSWING_EXCEPTIONS, noSwingExceptions);
|
||||
noSwingActions = data.getOptimizedActionList(ConfPaths.BLOCKPLACE_NOSWING_ACTIONS, Permissions.BLOCKPLACE_NOSWING);
|
||||
|
||||
reachCheck = data.getBoolean(ConfPaths.BLOCKPLACE_REACH_CHECK);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -122,7 +125,7 @@ public class BlockPlaceListener extends CheckListener {
|
|||
}
|
||||
|
||||
// No swing check (player doesn't swing their arm when placing a lily pad).
|
||||
if (!cancelled && placedMat != Material.WATER_LILY && noSwing.isEnabled(player) && noSwing.check(player, data, cc)) {
|
||||
if (!cancelled && !cc.noSwingExceptions.contains(placedMat) && noSwing.isEnabled(player) && noSwing.check(player, data, cc)) {
|
||||
// Consider skipping all insta placables or using simplified version (true or true within time frame).
|
||||
cancelled = true;
|
||||
}
|
||||
|
@ -146,6 +149,8 @@ public class BlockPlaceListener extends CheckListener {
|
|||
if (cancelled) {
|
||||
event.setCancelled(cancelled);
|
||||
}
|
||||
// Cleanup
|
||||
// Reminder(currently unused): useLoc.setWorld(null);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
|
@ -264,7 +269,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,21 +290,22 @@ 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)){
|
||||
if (mat != null && mat != Material.AIR && (BlockProperties.getBlockFlags(mat) & flags) == 0 && !mcAccess.hasGravity(mat)){
|
||||
// Still fails on piston traps etc.
|
||||
if (!BlockProperties.isPassable(player.getLocation(), projectile.getLocation()) && !BlockProperties.isOnGroundOrResetCond(player, player.getLocation(), MovingConfig.getConfig(player).yOnGround)){
|
||||
cancel = true;
|
||||
|
@ -313,5 +319,7 @@ public class BlockPlaceListener extends CheckListener {
|
|||
if (cancel){
|
||||
event.setCancelled(true);
|
||||
}
|
||||
// Cleanup.
|
||||
useLoc.setWorld(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,14 +38,14 @@ public class FastPlace extends Check {
|
|||
|
||||
// Short term arrivals.
|
||||
final int tick = TickTask.getTick();
|
||||
if (tick < data.fastPlaceShortTermTick ){
|
||||
if (tick < data.fastPlaceShortTermTick ) {
|
||||
// TickTask got reset.
|
||||
data.fastPlaceShortTermTick = tick;
|
||||
data.fastPlaceShortTermCount = 1;
|
||||
}
|
||||
else if (tick - data.fastPlaceShortTermTick < cc.fastPlaceShortTermTicks){
|
||||
// Account for server side lag.
|
||||
if (!cc.lag || TickTask.getLag(50L * (tick - data.fastPlaceShortTermTick), true) < 1.2){
|
||||
if (!cc.lag || TickTask.getLag(50L * (tick - data.fastPlaceShortTermTick), true) < 1.2f){
|
||||
// Within range, add.
|
||||
data.fastPlaceShortTermCount ++;
|
||||
}
|
||||
|
@ -62,9 +62,9 @@ public class FastPlace extends Check {
|
|||
|
||||
// Find if one of both or both are violations:
|
||||
final float fullViolation;
|
||||
if (fullScore > cc.fastPlaceLimit){
|
||||
if (fullScore > cc.fastPlaceLimit) {
|
||||
// Account for server side lag.
|
||||
if (cc.lag){
|
||||
if (cc.lag) {
|
||||
fullViolation = fullScore / TickTask.getLag(data.fastPlaceBuckets.bucketDuration() * data.fastPlaceBuckets.numberOfBuckets(), true) - cc.fastPlaceLimit;
|
||||
}
|
||||
else{
|
||||
|
@ -78,14 +78,16 @@ public class FastPlace extends Check {
|
|||
final float violation = Math.max(fullViolation, shortTermViolation);
|
||||
|
||||
boolean cancel = false;
|
||||
if (violation > 0){
|
||||
final double change = violation / 1000;
|
||||
if (violation > 0f) {
|
||||
final double change = (double) violation;
|
||||
data.fastPlaceVL += change;
|
||||
cancel = executeActions(player, data.fastPlaceVL, change, cc.fastPlaceActions);
|
||||
}
|
||||
else if (data.fastPlaceVL > 0d && fullScore < cc.fastPlaceLimit * .75)
|
||||
else if (data.fastPlaceVL > 0d && fullScore < cc.fastPlaceLimit * .75) {
|
||||
data.fastPlaceVL *= 0.95;
|
||||
}
|
||||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import fr.neatmonster.nocheatplus.config.ConfPaths;
|
|||
import fr.neatmonster.nocheatplus.config.ConfigFile;
|
||||
import fr.neatmonster.nocheatplus.config.ConfigManager;
|
||||
import fr.neatmonster.nocheatplus.permissions.Permissions;
|
||||
import fr.neatmonster.nocheatplus.utilities.ColorUtil;
|
||||
|
||||
/**
|
||||
* Configurations specific for the "chat" checks. Every world gets one of these assigned to it, or if a world doesn't
|
||||
|
@ -104,7 +105,8 @@ public class ChatConfig extends AsyncCheckConfig {
|
|||
public final float textMessageNoLetter;
|
||||
public final float textGlobalWeight;
|
||||
public final float textPlayerWeight;
|
||||
public boolean textEngineMaximum;
|
||||
public final boolean textEngineMaximum;
|
||||
public final boolean textAllowVLReset;
|
||||
public final boolean textDebug;
|
||||
|
||||
public final boolean chatWarningCheck;
|
||||
|
@ -120,6 +122,7 @@ public class ChatConfig extends AsyncCheckConfig {
|
|||
public final long loginsStartupDelay;
|
||||
|
||||
public final boolean consoleOnlyCheck;
|
||||
public final String consoleOnlyMessage;
|
||||
|
||||
|
||||
public final boolean relogCheck;
|
||||
|
@ -192,6 +195,7 @@ public class ChatConfig extends AsyncCheckConfig {
|
|||
textEngineMaximum = config.getBoolean(ConfPaths.CHAT_TEXT_ENGINE_MAXIMUM, true);
|
||||
textDebug = config.getBoolean(ConfPaths.CHAT_TEXT_DEBUG, false);
|
||||
textFreqNormActions = config.getOptimizedActionList(ConfPaths.CHAT_TEXT_FREQ_NORM_ACTIONS, Permissions.CHAT_TEXT);
|
||||
textAllowVLReset = config.getBoolean(ConfPaths.CHAT_TEXT_ALLOWVLRESET);
|
||||
|
||||
chatWarningCheck = config.getBoolean(ConfPaths.CHAT_WARNING_CHECK);
|
||||
chatWarningLevel = (float) config.getDouble(ConfPaths.CHAT_WARNING_LEVEL);
|
||||
|
@ -214,6 +218,7 @@ public class ChatConfig extends AsyncCheckConfig {
|
|||
relogActions = config.getOptimizedActionList(ConfPaths.CHAT_RELOG_ACTIONS, Permissions.CHAT_RELOG);
|
||||
|
||||
consoleOnlyCheck = config.getBoolean(ConfPaths.PROTECT_COMMANDS_CONSOLEONLY_ACTIVE);
|
||||
consoleOnlyMessage = ColorUtil.replaceColors(config.getString(ConfPaths.PROTECT_COMMANDS_CONSOLEONLY_MSG));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package fr.neatmonster.nocheatplus.checks.chat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
@ -159,39 +160,46 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
|
|||
// Trim is necessary because the server accepts leading spaces with commands.
|
||||
final String message = event.getMessage();
|
||||
final String lcMessage = message.trim().toLowerCase();
|
||||
// TODO: Remove bukkit: etc.
|
||||
|
||||
final String[] split = lcMessage.split(" ", 2);
|
||||
final String alias = split[0].substring(1);
|
||||
final Command command = CommandUtil.getCommand(alias);
|
||||
final String lcAltMessage;
|
||||
|
||||
final List<String> messageVars = new ArrayList<String>(); // Could as well use an array and allow null on input of SimpleCharPrefixTree.
|
||||
messageVars.add(lcMessage);
|
||||
String checkMessage = message; // Message to run chat checks on.
|
||||
if (command != null){
|
||||
lcAltMessage = "/" + command.getLabel().toLowerCase() + (split.length > 1 ? (" " + split[1]) : "");
|
||||
messageVars.add("/" + command.getLabel().toLowerCase() + (split.length > 1 ? (" " + split[1]) : ""));
|
||||
}
|
||||
else{
|
||||
lcAltMessage = lcMessage;
|
||||
}
|
||||
|
||||
// Prevent /op and /deop commands from being used by players.
|
||||
if (cc.consoleOnlyCheck && consoleOnlyCommands.hasAnyPrefixWords(lcMessage, lcAltMessage)) {
|
||||
if (alias.indexOf(":") != -1) {
|
||||
final int index = message.indexOf(":") + 1;
|
||||
if (index < message.length()) {
|
||||
checkMessage = message.substring(index);
|
||||
messageVars.add(checkMessage.toLowerCase());
|
||||
}
|
||||
}
|
||||
// Prevent commands from being used by players (e.g. /op /deop /reload).
|
||||
if (cc.consoleOnlyCheck && consoleOnlyCommands.hasAnyPrefixWords(messageVars)) {
|
||||
if (command == null || command.testPermission(player)){
|
||||
player.sendMessage(ChatColor.RED + "I'm sorry, but this command can't be executed in chat. Use the console instead!");
|
||||
player.sendMessage(cc.consoleOnlyMessage);
|
||||
}
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle as chat or command.
|
||||
final boolean handleAsChat = chatCommands.hasAnyPrefixWords(lcMessage, lcAltMessage);
|
||||
if (handleAsChat){
|
||||
if (chatCommands.hasAnyPrefixWords(messageVars)){
|
||||
// Treat as chat.
|
||||
// TODO: Consider requesting permission updates on these, for consistency.
|
||||
// TODO: Cut off the command (?).
|
||||
if (textChecks(player, message, true, false)) {
|
||||
// TODO: Cut off the command ?.
|
||||
if (textChecks(player, checkMessage, true, false)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
else if (!commandExclusions.hasAnyPrefixWords(lcMessage, lcAltMessage)){
|
||||
else if (!commandExclusions.hasAnyPrefixWords(messageVars)){
|
||||
// Treat as command.
|
||||
if (commands.isEnabled(player) && commands.check(player, message, captcha)) {
|
||||
if (commands.isEnabled(player) && commands.check(player, checkMessage, captcha)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ public class Text extends AsyncCheck implements INotifyReload{
|
|||
// Set some things from the global config.
|
||||
final ConfigFile config = ConfigManager.getConfigFile();
|
||||
final NoCheatPlusAPI api = NCPAPIProvider.getNoCheatPlusAPI();
|
||||
if (engine != null){
|
||||
if (engine != null) {
|
||||
engine.clear();
|
||||
api.removeComponent(engine);
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ public class Text extends AsyncCheck implements INotifyReload{
|
|||
|
||||
@Override
|
||||
public void onReload() {
|
||||
synchronized(engine){
|
||||
synchronized(engine) {
|
||||
engine.clear();
|
||||
}
|
||||
init();
|
||||
|
@ -120,7 +120,7 @@ public class Text extends AsyncCheck implements INotifyReload{
|
|||
boolean debug = cc.textDebug || cc.debug;
|
||||
|
||||
final List<String> debugParts;
|
||||
if (debug){
|
||||
if (debug) {
|
||||
debugParts = new LinkedList<String>();
|
||||
debugParts.add("[NoCheatPlus][chat.text] Message ("+player.getName()+"/"+message.length()+"): ");
|
||||
}
|
||||
|
@ -143,13 +143,13 @@ public class Text extends AsyncCheck implements INotifyReload{
|
|||
// Full message processing. ------------
|
||||
|
||||
// Upper case.
|
||||
if (letterCounts.fullCount.upperCase > msgLen / 3){
|
||||
if (letterCounts.fullCount.upperCase > msgLen / 3) {
|
||||
final float wUpperCase = 0.6f * letterCounts.fullCount.getUpperCaseRatio();
|
||||
score += wUpperCase * cc.textMessageUpperCase;
|
||||
}
|
||||
|
||||
// Letters vs. word length.
|
||||
if (msgLen > 4){
|
||||
if (msgLen > 4) {
|
||||
final float fullRep = letterCounts.fullCount.getLetterCountRatio();
|
||||
// Long messages: very small and very big are bad !
|
||||
final float wRepetition = (float) msgLen / 15.0f * Math.abs(0.5f - fullRep);
|
||||
|
@ -157,7 +157,7 @@ public class Text extends AsyncCheck implements INotifyReload{
|
|||
|
||||
// Number of words vs. length of message
|
||||
final float fnWords = (float) letterCounts.words.length / (float) msgLen;
|
||||
if (fnWords > 0.75f){ // TODO: balance or configure or remove ?
|
||||
if (fnWords > 0.75f) { // TODO: balance or configure or remove ?
|
||||
score += fnWords * cc.textMessagePartition;
|
||||
}
|
||||
}
|
||||
|
@ -165,40 +165,40 @@ public class Text extends AsyncCheck implements INotifyReload{
|
|||
final CombinedData cData = CombinedData.getData(player);
|
||||
final long timeout = 8000; // TODO: maybe set dynamically in data.
|
||||
// Repetition of last message.
|
||||
if (cc.textMsgRepeatSelf != 0f && time - data.chatLastTime < timeout){
|
||||
if (StringUtil.isSimilar(lcMessage, data.chatLastMessage, 0.8f)){
|
||||
if (cc.textMsgRepeatSelf != 0f && time - data.chatLastTime < timeout) {
|
||||
if (StringUtil.isSimilar(lcMessage, data.chatLastMessage, 0.8f)) {
|
||||
final float timeWeight = (float) (timeout - (time - data.chatLastTime)) / (float) timeout;
|
||||
score += cc.textMsgRepeatSelf * timeWeight;
|
||||
}
|
||||
}
|
||||
// Repetition of last global message.
|
||||
if (cc.textMsgRepeatGlobal != 0f && time - lastGlobalTime < timeout){
|
||||
if (StringUtil.isSimilar(lcMessage, lastGlobalMessage, 0.8f)){
|
||||
if (cc.textMsgRepeatGlobal != 0f && time - lastGlobalTime < timeout) {
|
||||
if (StringUtil.isSimilar(lcMessage, lastGlobalMessage, 0.8f)) {
|
||||
final float timeWeight = (float) (timeout - (time - lastGlobalTime)) / (float) timeout;
|
||||
score += cc.textMsgRepeatGlobal * timeWeight;
|
||||
}
|
||||
}
|
||||
// Repetition of last cancelled message.
|
||||
if (cc.textMsgRepeatCancel != 0f && time - lastCancelledTime < timeout){
|
||||
if (StringUtil.isSimilar(lcMessage, lastCancelledMessage, 0.8f)){
|
||||
if (cc.textMsgRepeatCancel != 0f && time - lastCancelledTime < timeout) {
|
||||
if (StringUtil.isSimilar(lcMessage, lastCancelledMessage, 0.8f)) {
|
||||
final float timeWeight = (float) (timeout - (time - lastCancelledTime)) / (float) timeout;
|
||||
score += cc.textMsgRepeatCancel * timeWeight;
|
||||
}
|
||||
}
|
||||
// Chat quickly after join.
|
||||
if (cc.textMsgAfterJoin != 0f && time - cData.lastJoinTime < timeout){
|
||||
if (cc.textMsgAfterJoin != 0f && time - cData.lastJoinTime < timeout) {
|
||||
final float timeWeight = (float) (timeout - (time - cData.lastJoinTime)) / (float) timeout;
|
||||
score += cc.textMsgAfterJoin * timeWeight;
|
||||
}
|
||||
// Chat without moving.
|
||||
if (cc.textMsgNoMoving != 0f && time - cData.lastMoveTime > timeout){
|
||||
if (cc.textMsgNoMoving != 0f && time - cData.lastMoveTime > timeout) {
|
||||
score += cc.textMsgNoMoving;
|
||||
}
|
||||
|
||||
// Per word checks. -------------------
|
||||
float wWords = 0.0f;
|
||||
final float avwLen = (float) msgLen / (float) letterCounts.words.length;
|
||||
for (final WordLetterCount word: letterCounts.words){
|
||||
for (final WordLetterCount word: letterCounts.words) {
|
||||
float wWord = 0.0f;
|
||||
final int wLen = word.word.length();
|
||||
// TODO: ? used letters vs. word length.
|
||||
|
@ -232,7 +232,7 @@ public class Text extends AsyncCheck implements INotifyReload{
|
|||
engMap = engine.process(letterCounts, player.getName(), cc, data);
|
||||
// TODO: more fine grained sync !s
|
||||
// TODO: different methods (add or max or add+max or something else).
|
||||
for (final Float res : engMap.values()){
|
||||
for (final Float res : engMap.values()) {
|
||||
if (cc.textEngineMaximum) wEngine = Math.max(wEngine, res.floatValue());
|
||||
else wEngine += res.floatValue();
|
||||
}
|
||||
|
@ -252,40 +252,46 @@ public class Text extends AsyncCheck implements INotifyReload{
|
|||
final float shortTermAccumulated = cc.textFreqShortTermWeight * data.chatShortTermFrequency.score(cc.textFreqShortTermFactor);
|
||||
final boolean shortTermViolation = shortTermAccumulated > cc.textFreqShortTermLevel;
|
||||
|
||||
if (normalViolation || shortTermViolation){
|
||||
if (normalViolation || shortTermViolation) {
|
||||
lastCancelledMessage = lcMessage;
|
||||
lastCancelledTime = time;
|
||||
|
||||
final double added;
|
||||
if (shortTermViolation) added = (shortTermAccumulated - cc.textFreqShortTermLevel)/ 3.0;
|
||||
else added = (accumulated - cc.textFreqNormLevel) / 10.0;
|
||||
data.textVL += added;
|
||||
if (shortTermViolation) {
|
||||
added = (shortTermAccumulated - cc.textFreqShortTermLevel)/ 3.0;
|
||||
} else {
|
||||
added = (accumulated - cc.textFreqNormLevel) / 10.0;
|
||||
}
|
||||
data.textVL += added;
|
||||
|
||||
if (captcha.shouldStartCaptcha(cc, data)){
|
||||
if (captcha.shouldStartCaptcha(cc, data)) {
|
||||
captcha.sendNewCaptcha(player, cc, data);
|
||||
cancel = true;
|
||||
}
|
||||
else{
|
||||
if (shortTermViolation){
|
||||
if (executeActions(player, data.textVL, added, cc.textFreqShortTermActions, isMainThread))
|
||||
cancel = true;
|
||||
if (shortTermViolation) {
|
||||
if (executeActions(player, data.textVL, added, cc.textFreqShortTermActions, isMainThread)) {
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
else if (normalViolation){
|
||||
if (executeActions(player, data.textVL, added, cc.textFreqNormActions, isMainThread))
|
||||
cancel = true;
|
||||
else if (normalViolation) {
|
||||
if (executeActions(player, data.textVL, added, cc.textFreqNormActions, isMainThread)) {
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cc.chatWarningCheck && time - data.chatWarningTime > cc.chatWarningTimeout && (100f * accumulated / cc.textFreqNormLevel > cc.chatWarningLevel || 100f * shortTermAccumulated / cc.textFreqShortTermLevel > cc.chatWarningLevel)){
|
||||
else if (cc.chatWarningCheck && time - data.chatWarningTime > cc.chatWarningTimeout && (100f * accumulated / cc.textFreqNormLevel > cc.chatWarningLevel || 100f * shortTermAccumulated / cc.textFreqShortTermLevel > cc.chatWarningLevel)) {
|
||||
NCPAPIProvider.getNoCheatPlusAPI().sendMessageOnTick(player.getName(), ColorUtil.replaceColors(cc.chatWarningMessage));
|
||||
data.chatWarningTime = time;
|
||||
}
|
||||
else {
|
||||
data.textVL *= 0.95;
|
||||
if (normalScore < 2.0f * cc.textFreqNormWeight && shortTermScore < 2.0f * cc.textFreqShortTermWeight)
|
||||
// Reset the VL.
|
||||
if (cc.textAllowVLReset && normalScore < 2.0f * cc.textFreqNormWeight && shortTermScore < 2.0f * cc.textFreqShortTermWeight) {
|
||||
// Reset the VL.
|
||||
// TODO: maybe elaborate on resetting conditions (after some timeout just divide by two or so?).
|
||||
data.textVL = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
|
|
|
@ -32,9 +32,7 @@ public class Angle extends Check {
|
|||
* @param worldChanged
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player, final boolean worldChanged) {
|
||||
final FightConfig cc = FightConfig.getConfig(player);
|
||||
final FightData data = FightData.getData(player);
|
||||
public boolean check(final Player player, final boolean worldChanged, final FightData data, final FightConfig cc) {
|
||||
|
||||
if (worldChanged){
|
||||
// TODO: clear some data.
|
||||
|
@ -44,12 +42,15 @@ public class Angle extends Check {
|
|||
boolean cancel = false;
|
||||
|
||||
// Remove the old locations from the map.
|
||||
for (final long time : new TreeMap<Long, Location>(data.angleHits).navigableKeySet())
|
||||
if (System.currentTimeMillis() - time > 1000L)
|
||||
data.angleHits.remove(time);
|
||||
for (final long time : new TreeMap<Long, Location>(data.angleHits).navigableKeySet()) {
|
||||
if (System.currentTimeMillis() - time > 1000L) {
|
||||
data.angleHits.remove(time);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new location to the map.
|
||||
data.angleHits.put(System.currentTimeMillis(), player.getLocation());
|
||||
// TODO: Alter method to store something less fat.
|
||||
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)
|
||||
|
|
|
@ -38,14 +38,8 @@ public class Critical extends Check {
|
|||
* the player
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player) {
|
||||
final FightConfig cc = FightConfig.getConfig(player);
|
||||
final FightData data = FightData.getData(player);
|
||||
|
||||
public boolean check(final Player player, final Location loc, final FightData data, final FightConfig cc) {
|
||||
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);
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.bukkit.util.Vector;
|
|||
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.LocationTrace.TraceEntry;
|
||||
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
|
||||
|
||||
/**
|
||||
|
@ -22,7 +23,7 @@ public class Direction extends Check {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks a player.
|
||||
* "Classic" check.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
|
@ -30,16 +31,14 @@ public class Direction extends Check {
|
|||
* the damaged
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player, final Entity damaged) {
|
||||
final FightConfig cc = FightConfig.getConfig(player);
|
||||
final FightData data = FightData.getData(player);
|
||||
|
||||
boolean cancel = false;
|
||||
public boolean check(final Player player, final Location loc, final Entity damaged, final Location dLoc, final FightData data, final FightConfig cc) {
|
||||
boolean cancel = false;
|
||||
|
||||
// Safeguard, if entity is complex, this check will fail due to giant and hard to define hitboxes.
|
||||
// if (damaged instanceof EntityComplex || damaged instanceof EntityComplexPart)
|
||||
if (mcAccess.isComplexPart(damaged))
|
||||
return false;
|
||||
if (mcAccess.isComplexPart(damaged)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find out how wide the entity is.
|
||||
final double width = mcAccess.getWidth(damaged);
|
||||
|
@ -47,14 +46,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){
|
||||
|
@ -81,10 +77,117 @@ public class Direction extends Check {
|
|||
// Deal an attack penalty time.
|
||||
data.attackPenalty.applyPenalty(cc.directionPenalty);
|
||||
}
|
||||
} else
|
||||
// Reward the player by lowering their violation level.
|
||||
} else {
|
||||
// Reward the player by lowering their violation level.
|
||||
data.directionVL *= 0.8D;
|
||||
|
||||
}
|
||||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data context for iterating over TraceEntry instances.
|
||||
* @param player
|
||||
* @param loc
|
||||
* @param damaged
|
||||
* @param damagedLoc
|
||||
* @param data
|
||||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
public DirectionContext getContext(final Player player, final Location loc, final Entity damaged, final Location damagedLoc, final FightData data, final FightConfig cc) {
|
||||
final DirectionContext context = new DirectionContext();
|
||||
context.damagedComplex = mcAccess.isComplexPart(damaged);
|
||||
// Find out how wide the entity is.
|
||||
context.damagedWidth = mcAccess.getWidth(damaged);
|
||||
// entity.height is broken and will always be 0, therefore. Calculate height instead based on boundingBox.
|
||||
context.damagedHeight = mcAccess.getHeight(damaged);
|
||||
context.direction = loc.getDirection();
|
||||
context.lengthDirection = context.direction.length();
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the player fails the direction check, no change of FightData.
|
||||
* @param player
|
||||
* @param loc
|
||||
* @param damaged
|
||||
* @param dLoc
|
||||
* @param context
|
||||
* @param data
|
||||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
public boolean loopCheck(final Player player, final Location loc, final Entity damaged, final TraceEntry dLoc, final DirectionContext context, final FightData data, final FightConfig cc) {
|
||||
|
||||
// Ignore complex entities for the moment.
|
||||
if (context.damagedComplex) {
|
||||
// TODO: Revise :p
|
||||
return false;
|
||||
}
|
||||
boolean cancel = false;
|
||||
|
||||
// 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 double off;
|
||||
if (cc.directionStrict){
|
||||
off = TrigUtil.combinedDirectionCheck(loc, player.getEyeHeight(), context.direction, dLoc.x, dLoc.y + context.damagedHeight / 2D, dLoc.z, context.damagedWidth, context.damagedHeight, TrigUtil.DIRECTION_PRECISION, 80.0);
|
||||
}
|
||||
else{
|
||||
// Also take into account the angle.
|
||||
off = TrigUtil.directionCheck(loc, player.getEyeHeight(), context.direction, dLoc.x, dLoc.y + context.damagedHeight / 2D, dLoc.z, context.damagedWidth, context.damagedHeight, TrigUtil.DIRECTION_PRECISION);
|
||||
}
|
||||
|
||||
if (off > 0.1) {
|
||||
// Player failed the check. Let's try to guess how far they were from looking directly to the entity...
|
||||
final Vector blockEyes = new Vector(dLoc.x - loc.getX(), dLoc.y + context.damagedHeight / 2D - loc.getY() - player.getEyeHeight(), dLoc.z - loc.getZ());
|
||||
final double distance = blockEyes.crossProduct(context.direction).length() / context.lengthDirection;
|
||||
context.minViolation = Math.min(context.minViolation, distance);
|
||||
}
|
||||
context.minResult = Math.min(context.minResult, off);
|
||||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply changes to FightData according to check results (context), trigger violations.
|
||||
* @param player
|
||||
* @param loc
|
||||
* @param damaged
|
||||
* @param context
|
||||
* @param forceViolation
|
||||
* @param data
|
||||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
public boolean loopFinish(final Player player, final Location loc, final Entity damaged, final DirectionContext context, final boolean forceViolation, final FightData data, final FightConfig cc) {
|
||||
boolean cancel = false;
|
||||
final double off = forceViolation && context.minViolation != Double.MAX_VALUE ? context.minViolation : context.minResult;
|
||||
if (off == Double.MAX_VALUE) {
|
||||
return false;
|
||||
}
|
||||
else if (off > 0.1) {
|
||||
// Add the overall violation level of the check.
|
||||
data.directionVL += context.minViolation;
|
||||
|
||||
// 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, context.minViolation, cc.directionActions);
|
||||
|
||||
if (cancel) {
|
||||
// Deal an attack penalty time.
|
||||
data.attackPenalty.applyPenalty(cc.directionPenalty);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Reward the player by lowering their violation level.
|
||||
data.directionVL *= 0.8D;
|
||||
}
|
||||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package fr.neatmonster.nocheatplus.checks.fight;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* Context data for the direction check, for repeated use within a loop.
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public class DirectionContext {
|
||||
|
||||
public boolean damagedComplex;
|
||||
public double damagedWidth;
|
||||
public double damagedHeight;
|
||||
public Vector direction = null;
|
||||
public double lengthDirection;
|
||||
|
||||
/** Minimum value for the distance that was a violation. */
|
||||
public double minViolation = Double.MAX_VALUE;
|
||||
/** Minimum value for off. */
|
||||
public double minResult = Double.MAX_VALUE;
|
||||
|
||||
}
|
|
@ -32,7 +32,8 @@ public class FastHeal extends Check {
|
|||
else{
|
||||
// Violation.
|
||||
final double correctedDiff = ((double) time - data.fastHealRefTime) * TickTask.getLag(cc.fastHealInterval);
|
||||
// TODO: Consider using a simple buffer as well (to get closer to the correct interva).
|
||||
// TODO: Consider using a simple buffer as well (to get closer to the correct interval).
|
||||
// TODO: Check if we added a buffer.
|
||||
if (correctedDiff < cc.fastHealInterval){
|
||||
data.fastHealBuffer -= (cc.fastHealInterval - correctedDiff);
|
||||
if (data.fastHealBuffer <= 0){
|
||||
|
|
|
@ -131,7 +131,7 @@ public class FightData extends ACheckData {
|
|||
// Shared
|
||||
public String lastWorld = "";
|
||||
public int lastAttackTick = 0;
|
||||
public double lastAttackedX = Integer.MAX_VALUE;
|
||||
public double lastAttackedX = Double.MAX_VALUE;
|
||||
public double lastAttackedY;
|
||||
public double lastAttackedZ;
|
||||
|
||||
|
@ -197,4 +197,12 @@ public class FightData extends ACheckData {
|
|||
// Start with full fast-heal buffer.
|
||||
fastHealBuffer = cc.fastHealBuffer;
|
||||
}
|
||||
|
||||
public void onWorldChange() {
|
||||
angleHits.clear();
|
||||
lastAttackedX = Double.MAX_VALUE;
|
||||
lastAttackTick = 0;
|
||||
lastWorld = "";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.neatmonster.nocheatplus.checks.fight;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
@ -25,6 +27,8 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
|
|||
import fr.neatmonster.nocheatplus.checks.combined.Combined;
|
||||
import fr.neatmonster.nocheatplus.checks.combined.Improbable;
|
||||
import fr.neatmonster.nocheatplus.checks.inventory.Items;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.LocationTrace;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.LocationTrace.TraceEntry;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.MediumLiftOff;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
|
||||
|
@ -74,6 +78,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,15 +110,21 @@ 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);
|
||||
// // Bad pitch/yaw, just in case.
|
||||
// if (LocUtil.needsDirectionCorrection(useLoc1.getYaw(), useLoc1.getPitch())) {
|
||||
// mcAccess.correctDirection(player);
|
||||
// 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;
|
||||
final long msAge; // Milliseconds the ticks actually took.
|
||||
final double normalizedMove; // Blocks per second.
|
||||
// TODO: relative distance (player - target)!
|
||||
if (data.lastAttackedX == Integer.MAX_VALUE || tick < data.lastAttackTick || worldChanged || tick - data.lastAttackTick > 20){
|
||||
// TODO: Use trace for this ?
|
||||
if (data.lastAttackedX == Double.MAX_VALUE || tick < data.lastAttackTick || worldChanged || tick - data.lastAttackTick > 20){
|
||||
// TODO: 20 ?
|
||||
tickAge = 0;
|
||||
targetMove = 0.0;
|
||||
|
@ -118,7 +134,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);
|
||||
}
|
||||
|
@ -126,15 +142,34 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
|||
|
||||
// TODO: dist < width => skip some checks (direction, ..)
|
||||
|
||||
// Check for self hit exploits (mind that projectiles should be excluded)
|
||||
final LocationTrace damagedTrace;
|
||||
final Player damagedPlayer;
|
||||
if (damaged instanceof Player){
|
||||
final Player damagedPlayer = (Player) damaged;
|
||||
damagedPlayer = (Player) damaged;
|
||||
// // Bad pitch/yaw, just in case.
|
||||
// if (LocUtil.needsDirectionCorrection(useLoc2.getYaw(), useLoc2.getPitch())) {
|
||||
// mcAccess.correctDirection(damagedPlayer);
|
||||
// damagedPlayer.getLocation(useLoc2);
|
||||
// }
|
||||
// Log.
|
||||
if (cc.debug && damagedPlayer.hasPermission(Permissions.ADMINISTRATION_DEBUG)){
|
||||
damagedPlayer.sendMessage("Attacked by " + player.getName() + ": inv=" + mcAccess.getInvulnerableTicks(damagedPlayer) + " ndt=" + damagedPlayer.getNoDamageTicks());
|
||||
}
|
||||
// Check for self hit exploits (mind that projectiles are excluded from this.)
|
||||
if (selfHit.isEnabled(player) && selfHit.check(player, damagedPlayer, data, cc)) {
|
||||
cancelled = true;
|
||||
}
|
||||
// Get+update the damaged players.
|
||||
// TODO: Problem with NPCs: data stays (not a big problem).
|
||||
// (This is done even if the event has already been cancelled, to keep track, if the player is on a horse.)
|
||||
damagedTrace = MovingData.getData(damagedPlayer).updateTrace(damagedPlayer, damagedLoc, tick);
|
||||
} else {
|
||||
damagedPlayer = null; // TODO: This is a temporary workaround.
|
||||
// Use a fake trace.
|
||||
// TODO: Provide for entities too? E.g. one per player, or a fully fledged bookkeeping thing (EntityData).
|
||||
//final MovingConfig mcc = MovingConfig.getConfig(damagedLoc.getWorld().getName());
|
||||
damagedTrace = null; //new LocationTrace(mcc.traceSize, mcc.traceMergeDist);
|
||||
//damagedTrace.addEntry(tick, damagedLoc.getX(), damagedLoc.getY(), damagedLoc.getZ());
|
||||
}
|
||||
|
||||
if (cc.cancelDead){
|
||||
|
@ -176,51 +211,131 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
|||
}
|
||||
}
|
||||
|
||||
if (angle.isEnabled(player)) {
|
||||
if (!cancelled && critical.isEnabled(player) && critical.check(player, loc, data, cc)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
if (!cancelled && knockback.isEnabled(player) && knockback.check(player, data, cc)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
if (!cancelled && noSwing.isEnabled(player) && noSwing.check(player, data, cc)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
if (!cancelled && player.isBlocking() && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_BLOCKING)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
// TODO: Order of all these checks ...
|
||||
// Checks that use LocationTrace.
|
||||
|
||||
// TODO: Later optimize (...), should reverse check window ?
|
||||
|
||||
// First loop through reach and direction, to determine a window.
|
||||
final boolean reachEnabled = !cancelled && reach.isEnabled(player);
|
||||
final boolean directionEnabled = !cancelled && direction.isEnabled(player);
|
||||
|
||||
if (reachEnabled || directionEnabled) {
|
||||
if (damagedPlayer != null) {
|
||||
// TODO: Move to a method (trigonometric checks).
|
||||
final ReachContext reachContext = reachEnabled ? reach.getContext(player, loc, damaged, damagedLoc, data, cc) : null;
|
||||
final DirectionContext directionContext = directionEnabled ? direction.getContext(player, loc, damaged, damagedLoc, data, cc) : null;
|
||||
|
||||
final long traceOldest = tick; // - damagedTrace.getMaxSize(); // TODO: Set by window.
|
||||
// TODO: Iterating direction: could also start from latest, be it on occasion.
|
||||
Iterator<TraceEntry> traceIt = damagedTrace.maxAgeIterator(traceOldest);
|
||||
|
||||
boolean violation = true; // No tick with all checks passed.
|
||||
boolean reachPassed = !reachEnabled; // Passed individually for some tick.
|
||||
boolean directionPassed = !directionEnabled; // Passed individually for some tick.
|
||||
// TODO: Maintain a latency estimate + max diff and invalidate completely (i.e. iterate from latest NEXT time)], or just max latency.
|
||||
while (traceIt.hasNext()) {
|
||||
final TraceEntry entry = traceIt.next();
|
||||
// Simplistic just check both until end or hit.
|
||||
// TODO: Other default distances/tolerances.
|
||||
boolean thisPassed = true;
|
||||
if (reachEnabled) {
|
||||
if (reach.loopCheck(player, loc, damagedPlayer, entry, reachContext, data, cc)) {
|
||||
thisPassed = false;
|
||||
} else {
|
||||
reachPassed = true;
|
||||
}
|
||||
}
|
||||
// TODO: For efficiency one could omit checking at all if reach is failed all the time.
|
||||
if (directionEnabled && (reachPassed || !directionPassed)) {
|
||||
if (direction.loopCheck(player, damagedLoc, damagedPlayer, entry, directionContext, data, cc)) {
|
||||
thisPassed = false;
|
||||
} else {
|
||||
directionPassed = true;
|
||||
}
|
||||
}
|
||||
if (thisPassed) {
|
||||
// TODO: Log/set estimated latency.
|
||||
violation = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// TODO: How to treat mixed state: violation && reachPassed && directionPassed [current: use min violation // thinkable: silent cancel, if actions have cancel (!)]
|
||||
// TODO: Adapt according to strictness settings?
|
||||
if (reachEnabled) {
|
||||
// TODO: Might ignore if already cancelled by mixed/silent cancel.
|
||||
if (reach.loopFinish(player, loc, damagedPlayer, reachContext, violation, data, cc)) {
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
if (directionEnabled) {
|
||||
// TODO: Might ignore if already cancelled.
|
||||
if (direction.loopFinish(player, loc, damagedPlayer, directionContext, violation, data, cc)) {
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
// TODO: Log exact state, probably record min/max latency (individually).
|
||||
} else {
|
||||
// Still use the classic methods for non-players. maybe[]
|
||||
if (reachEnabled && reach.check(player, loc, damaged, damagedLoc, data, cc)) {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
if (directionEnabled && direction.check(player, loc, damaged, damagedLoc, data, cc)) {
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check angle with allowed window.
|
||||
if (angle.isEnabled(player)) {
|
||||
// TODO: Revise, use own trace.
|
||||
// The "fast turning" checks are checked in any case because they accumulate data.
|
||||
// Improbable yaw changing.
|
||||
// Improbable yaw changing: Moving events might be missing up to a ten degrees change.
|
||||
if (Combined.checkYawRate(player, loc.getYaw(), now, worldName, cc.yawRateCheck)) {
|
||||
// (Check or just feed).
|
||||
// TODO: Work into this somehow attacking the same aim and/or similar aim position (not cancel then).
|
||||
cancelled = true;
|
||||
}
|
||||
// Angle check.
|
||||
if (angle.check(player, worldChanged)) cancelled = true;
|
||||
if (angle.check(player, worldChanged, data, cc)) {
|
||||
if (!cancelled && cc.debug) {
|
||||
System.out.println(player.getName() + " fight.angle cancel without yawrate cancel.");
|
||||
}
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cancelled && critical.isEnabled(player) && critical.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 && 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))
|
||||
cancelled = true;
|
||||
|
||||
if (!cancelled && direction.isEnabled(player) && direction.check(player, damaged))
|
||||
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){
|
||||
// TODO: Evaluate if moving traces can help here.
|
||||
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 +348,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 +363,11 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
|||
System.out.println(player.getName() + " ~ attack penalty.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Cleanup.
|
||||
useLoc1.setWorld(null);
|
||||
useLoc2.setWorld(null);
|
||||
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
|
@ -374,7 +493,9 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
|||
final Entity entity = event.getEntity();
|
||||
if (entity instanceof Player){
|
||||
final Player player = (Player) entity;
|
||||
if (godMode.isEnabled(player)) godMode.death(player);
|
||||
if (godMode.isEnabled(player)) {
|
||||
godMode.death(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,6 +529,11 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
|||
final Entity entity = event.getEntity();
|
||||
if (!(entity instanceof Player)) return;
|
||||
final Player player = (Player) entity;
|
||||
if (player.isDead() && BridgeHealth.getHealth(player) <= 0.0) {
|
||||
// Heal after death.
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (event.getRegainReason() != RegainReason.SATIATED) {
|
||||
return;
|
||||
}
|
||||
|
@ -444,8 +570,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
|||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerChangedWorld(final PlayerChangedWorldEvent event){
|
||||
final FightData data = FightData.getData(event.getPlayer());
|
||||
data.angleHits.clear();
|
||||
FightData.getData(event.getPlayer()).onWorldChange();
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = false, priority = EventPriority.MONITOR)
|
||||
|
|
|
@ -173,7 +173,7 @@ public class GodMode extends Check {
|
|||
public void death(final Player player) {
|
||||
// TODO: Is this still relevant ?
|
||||
// First check if the player is really dead (e.g. another plugin could have just fired an artificial event).
|
||||
if (BridgeHealth.getHealth(player) <= 0.0 && player.isDead()){
|
||||
if (BridgeHealth.getHealth(player) <= 0.0 && player.isDead()) {
|
||||
try {
|
||||
// Schedule a task to be executed in roughly 1.5 seconds.
|
||||
// TODO: Get plugin otherwise !?
|
||||
|
|
|
@ -26,10 +26,7 @@ public class Knockback extends Check {
|
|||
* the player
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player) {
|
||||
final FightConfig cc = FightConfig.getConfig(player);
|
||||
final FightData data = FightData.getData(player);
|
||||
|
||||
public boolean check(final Player player, final FightData data, final FightConfig cc) {
|
||||
boolean cancel = false;
|
||||
|
||||
final long time = System.currentTimeMillis();
|
||||
|
|
|
@ -24,9 +24,7 @@ public class NoSwing extends Check {
|
|||
* the player
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player) {
|
||||
final FightData data = FightData.getData(player);
|
||||
|
||||
public boolean check(final Player player, final FightData data, final FightConfig cc) {
|
||||
boolean cancel = false;
|
||||
|
||||
// Did they swing his arm before?
|
||||
|
@ -40,9 +38,10 @@ public class NoSwing 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.noSwingVL, 1D, FightConfig.getConfig(player).noSwingActions);
|
||||
cancel = executeActions(player, data.noSwingVL, 1D, cc.noSwingActions);
|
||||
}
|
||||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,9 +12,11 @@ import org.bukkit.util.Vector;
|
|||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.combined.Improbable;
|
||||
import fr.neatmonster.nocheatplus.checks.moving.LocationTrace.TraceEntry;
|
||||
import fr.neatmonster.nocheatplus.permissions.Permissions;
|
||||
import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.TickTask;
|
||||
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
|
||||
|
||||
/**
|
||||
* The Reach check will find out if a player interacts with something that's too far away.
|
||||
|
@ -43,7 +45,7 @@ public class Reach extends Check {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks a player.
|
||||
* "Classic" check.
|
||||
*
|
||||
* @param player
|
||||
* the player
|
||||
|
@ -51,10 +53,7 @@ public class Reach extends Check {
|
|||
* the damaged
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean check(final Player player, final Entity damaged) {
|
||||
final FightConfig cc = FightConfig.getConfig(player);
|
||||
final FightData data = FightData.getData(player);
|
||||
|
||||
public boolean check(final Player player, final Location pLoc, final Entity damaged, final Location dRef, final FightData data, final FightConfig cc) {
|
||||
boolean cancel = false;
|
||||
|
||||
// The maximum distance allowed to interact with an entity in survival mode.
|
||||
|
@ -67,20 +66,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".
|
||||
|
@ -138,4 +134,139 @@ public class Reach extends Check {
|
|||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data context for iterating over TraceEntry instances.
|
||||
* @param player
|
||||
* @param pLoc
|
||||
* @param damaged
|
||||
* @param damagedLoc
|
||||
* @param data
|
||||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
public ReachContext getContext(final Player player, final Location pLoc, final Entity damaged, final Location damagedLoc, final FightData data, final FightConfig cc) {
|
||||
final ReachContext context = new ReachContext();
|
||||
context.distanceLimit = player.getGameMode() == GameMode.CREATIVE ? CREATIVE_DISTANCE : cc.reachSurvivalDistance + getDistMod(damaged);
|
||||
context.distanceMin = (context.distanceLimit - cc.reachReduceDistance) / context.distanceLimit;
|
||||
context.damagedHeight = mcAccess.getHeight(damaged);
|
||||
//context.eyeHeight = player.getEyeHeight();
|
||||
context.pY = pLoc.getY() + player.getEyeHeight();
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the player fails the reach check, no change of FightData.
|
||||
* @param player
|
||||
* @param pLoc
|
||||
* @param damaged
|
||||
* @param dRef
|
||||
* @param context
|
||||
* @param data
|
||||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
public boolean loopCheck(final Player player, final Location pLoc, final Entity damaged, final TraceEntry dRef, final ReachContext context, final FightData data, final FightConfig cc) {
|
||||
boolean cancel = false;
|
||||
|
||||
// Refine y position.
|
||||
final double dY = dRef.y;
|
||||
double y = dRef.y;
|
||||
|
||||
if (context.pY <= dY) {
|
||||
// Keep the foot level y.
|
||||
}
|
||||
else if (context.pY >= dY + context.damagedHeight) {
|
||||
y = dY + context.damagedHeight; // Highest ref y.
|
||||
}
|
||||
else {
|
||||
y = context.pY; // Level with damaged.
|
||||
}
|
||||
|
||||
// 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".
|
||||
// TODO: Run check on squared distances (quite easy to change to stored boundary-sq values).
|
||||
final double lenpRel = TrigUtil.distance(dRef.x, y, dRef.z, pLoc.getX(), context.pY, pLoc.getZ());
|
||||
|
||||
double violation = lenpRel - context.distanceLimit;
|
||||
|
||||
if (violation > 0 || lenpRel - context.distanceLimit * data.reachMod > 0){
|
||||
// TODO: The silent cancel parts should be sen as "no violation" ?
|
||||
// Set minimum violation in context
|
||||
context.minViolation = Math.min(context.minViolation, lenpRel);
|
||||
cancel = true;
|
||||
}
|
||||
context.minResult = Math.min(context.minResult, lenpRel);
|
||||
|
||||
return cancel;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply changes to FightData according to check results (context), trigger violations.
|
||||
* @param player
|
||||
* @param pLoc
|
||||
* @param damaged
|
||||
* @param context
|
||||
* @param forceViolation
|
||||
* @param data
|
||||
* @param cc
|
||||
* @return
|
||||
*/
|
||||
public boolean loopFinish(final Player player, final Location pLoc, final Entity damaged, final ReachContext context, final boolean forceViolation, final FightData data, final FightConfig cc) {
|
||||
final double lenpRel = forceViolation && context.minViolation != Double.MAX_VALUE ? context.minViolation : context.minResult;
|
||||
if (lenpRel == Double.MAX_VALUE) {
|
||||
return false;
|
||||
}
|
||||
double violation = lenpRel - context.distanceLimit;
|
||||
boolean cancel = false;
|
||||
if (violation > 0) {
|
||||
// They failed, increment violation level. This is influenced by lag, so don't do it if there was lag.
|
||||
if (TickTask.getLag(1000) < 1.5f){
|
||||
// TODO: 1.5 is a fantasy value.
|
||||
data.reachVL += violation;
|
||||
}
|
||||
|
||||
// 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.reachVL, violation, cc.reachActions);
|
||||
if (Improbable.check(player, (float) violation / 2f, System.currentTimeMillis(), "fight.reach")){
|
||||
cancel = true;
|
||||
}
|
||||
if (cancel && cc.reachPenalty > 0){
|
||||
// Apply an attack penalty time.
|
||||
data.attackPenalty.applyPenalty(cc.reachPenalty);
|
||||
}
|
||||
}
|
||||
else if (lenpRel - context.distanceLimit * data.reachMod > 0){
|
||||
// Silent cancel.
|
||||
if (cc.reachPenalty > 0) {
|
||||
data.attackPenalty.applyPenalty(cc.reachPenalty / 2);
|
||||
}
|
||||
cancel = true;
|
||||
Improbable.feed(player, (float) (lenpRel - context.distanceLimit * data.reachMod) / 4f, System.currentTimeMillis());
|
||||
}
|
||||
else{
|
||||
// Player passed the check, reward them.
|
||||
data.reachVL *= 0.8D;
|
||||
|
||||
}
|
||||
// Adaption amount for dynamic range.
|
||||
final double DYNAMIC_STEP = cc.reachReduceStep / cc.reachSurvivalDistance;
|
||||
if (!cc.reachReduce){
|
||||
data.reachMod = 1d;
|
||||
}
|
||||
else if (lenpRel > context.distanceLimit - cc.reachReduceDistance){
|
||||
data.reachMod = Math.max(context.distanceMin, data.reachMod - DYNAMIC_STEP);
|
||||
}
|
||||
else{
|
||||
data.reachMod = Math.min(1.0, data.reachMod + DYNAMIC_STEP);
|
||||
}
|
||||
|
||||
if (cc.debug && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)){
|
||||
player.sendMessage("NC+: Attack/reach " + damaged.getType()+ " height="+ StringUtil.fdec3.format(context.damagedHeight) + " dist=" + StringUtil.fdec3.format(lenpRel) +" @" + StringUtil.fdec3.format(data.reachMod));
|
||||
}
|
||||
|
||||
return cancel;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package fr.neatmonster.nocheatplus.checks.fight;
|
||||
|
||||
/**
|
||||
* Context data for the reach check, for repeated use within a loop.
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public class ReachContext {
|
||||
|
||||
public double distanceLimit;
|
||||
public double distanceMin;
|
||||
public double damagedHeight;
|
||||
/** Attacking player. */
|
||||
public double eyeHeight;
|
||||
/** Eye location y of the attacking player. */
|
||||
public double pY;
|
||||
/** Minimum value of lenpRel that was a violation. */
|
||||
public double minViolation = Double.MAX_VALUE;
|
||||
/** Minimum value of lenpRel. */
|
||||
public double minResult = Double.MAX_VALUE;
|
||||
|
||||
}
|
|
@ -42,20 +42,30 @@ public class InstantBow extends Check {
|
|||
final long expectedPullDuration = (long) (maxTime - maxTime * (1f - force) * (1f - force)) - cc.instantBowDelay;
|
||||
|
||||
// Time taken to pull the string.
|
||||
final long pullDuration = now - (cc.instantBowStrict ? data.instantBowInteract : data.instantBowShoot);
|
||||
final long pullDuration;
|
||||
final boolean valid;
|
||||
if (cc.instantBowStrict) {
|
||||
// The interact time is invalid, if set to 0.
|
||||
valid = data.instantBowInteract != 0;
|
||||
pullDuration = valid ? (now - data.instantBowInteract) : 0L;
|
||||
} else {
|
||||
valid = true;
|
||||
pullDuration = now - data.instantBowShoot;
|
||||
}
|
||||
|
||||
if ((!cc.instantBowStrict || data.instantBowInteract > 0) && pullDuration >= expectedPullDuration){
|
||||
if (valid && (!cc.instantBowStrict || data.instantBowInteract > 0L) && pullDuration >= expectedPullDuration) {
|
||||
// The player was slow enough, reward them by lowering their violation level.
|
||||
data.instantBowVL *= 0.9D;
|
||||
}
|
||||
else if (data.instantBowInteract > now){
|
||||
else if (valid && data.instantBowInteract > now) {
|
||||
// Security check if time ran backwards.
|
||||
// TODO: Maybe this can be removed, though TickTask does not reset at the exact moment.
|
||||
}
|
||||
else {
|
||||
// Account for server side lag.
|
||||
final long correctedPullduration = cc.lag ? (long) (TickTask.getLag(expectedPullDuration, true) * pullDuration) : pullDuration;
|
||||
if (correctedPullduration < expectedPullDuration){
|
||||
// (Do not apply correction to invalid pulling.)
|
||||
final long correctedPullduration = valid ? (cc.lag ? (long) (TickTask.getLag(expectedPullDuration, true) * pullDuration) : pullDuration) : 0;
|
||||
if (correctedPullduration < expectedPullDuration) {
|
||||
// TODO: Consider: Allow one time but set yawrate penalty time ?
|
||||
final double difference = (expectedPullDuration - pullDuration) / 100D;
|
||||
|
||||
|
@ -68,7 +78,7 @@ public class InstantBow extends Check {
|
|||
}
|
||||
}
|
||||
|
||||
if (cc.debug && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)){
|
||||
if (cc.debug && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)) {
|
||||
player.sendMessage(ChatColor.YELLOW + "NCP: " + ChatColor.GRAY + "Bow shot - force: " + force +", " + (cc.instantBowStrict || pullDuration < 2 * expectedPullDuration ? ("pull time: " + pullDuration) : "") + "(" + expectedPullDuration +")");
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.HashSet;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ActionList;
|
||||
|
@ -71,7 +72,7 @@ public class InventoryConfig extends ACheckConfig {
|
|||
public final boolean fastConsumeCheck;
|
||||
public final long fastConsumeDuration;
|
||||
public final boolean fastConsumeWhitelist;
|
||||
public final Set<Integer> fastConsumeItems = new HashSet<Integer>();
|
||||
public final Set<Material> fastConsumeItems = new HashSet<Material>();
|
||||
public final ActionList fastConsumeActions;
|
||||
|
||||
public final boolean instantBowCheck;
|
||||
|
|
|
@ -79,7 +79,8 @@ public class InventoryData extends ACheckData {
|
|||
public int fastClickLastCursorAmount = 0;
|
||||
|
||||
// Data of the instant bow check.
|
||||
public long instantBowInteract;
|
||||
/** Last time right click interact on bow. A value of 0 means 'invalid'.*/
|
||||
public long instantBowInteract = 0;
|
||||
public long instantBowShoot;
|
||||
|
||||
// Data of the instant eat check.
|
||||
|
|
|
@ -29,6 +29,7 @@ import fr.neatmonster.nocheatplus.checks.CheckListener;
|
|||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.combined.Combined;
|
||||
import fr.neatmonster.nocheatplus.checks.combined.Improbable;
|
||||
import fr.neatmonster.nocheatplus.compat.BridgeHealth;
|
||||
import fr.neatmonster.nocheatplus.components.JoinLeaveListener;
|
||||
import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
|
||||
|
||||
|
@ -55,6 +56,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 +77,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 +91,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +112,10 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
|
|||
if (instantEat.isEnabled(player) && instantEat.check(player, event.getFoodLevel())){
|
||||
event.setCancelled(true);
|
||||
}
|
||||
else if (player.isDead() && BridgeHealth.getHealth(player) <= 0.0) {
|
||||
// Eat after death.
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,6 +228,7 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
|
|||
if (event.hasItem()){
|
||||
final ItemStack item = event.getItem();
|
||||
final Material type = item.getType();
|
||||
// TODO: Get Magic values (800) from the config.
|
||||
if (type == Material.BOW){
|
||||
final long now = System.currentTimeMillis();
|
||||
// It was a bow, the player starts to pull the string, remember this time.
|
||||
|
@ -233,9 +243,13 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
|
|||
} else resetAll = true;
|
||||
|
||||
// Illegal enchantments hotfix check.
|
||||
if (Items.checkIllegalEnchantments(player, item)) event.setCancelled(true);
|
||||
if (Items.checkIllegalEnchantments(player, item)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
resetAll = true;
|
||||
}
|
||||
else resetAll = true;
|
||||
|
||||
if (resetAll){
|
||||
// Nothing that we are interested in, reset data.
|
||||
|
@ -248,9 +262,16 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
|
|||
@EventHandler(ignoreCancelled = false, priority = EventPriority.LOWEST)
|
||||
public final void onPlayerInteractEntity(final PlayerInteractEntityEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
if (player.getGameMode() == GameMode.CREATIVE) return;
|
||||
if (player.getGameMode() == GameMode.CREATIVE) {
|
||||
return;
|
||||
}
|
||||
if (player.isDead() && BridgeHealth.getHealth(player) <= 0.0) {
|
||||
// No zombies.
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
final ItemStack stack = player.getItemInHand();
|
||||
if (stack != null && stack.getTypeId() == Material.MONSTER_EGG.getId() && items.isEnabled(player)){
|
||||
if (stack != null && stack.getType() == Material.MONSTER_EGG && items.isEnabled(player)){
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,36 +1,45 @@
|
|||
package fr.neatmonster.nocheatplus.checks.moving;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
|
||||
|
||||
/**
|
||||
* Auxiliary methods for Location handling, mainly intended for use with set-back locations.
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public class LocUtil {
|
||||
|
||||
/**
|
||||
* Simple get a copy (not actually using cloning).
|
||||
* Get a copy of a location (not actually using cloning).
|
||||
* @param loc
|
||||
* @return
|
||||
* @return A new Location instance.
|
||||
* @throws NullPointerException if World is null.
|
||||
*/
|
||||
public static final Location clone(final Location loc){
|
||||
return new Location(loc.getWorld(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
|
||||
return new Location(testWorld(loc.getWorld()), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone with given yaw and pitch.
|
||||
* Get a copy of a location (not actually using cloning), override yaw and pitch with given values.
|
||||
* @param loc
|
||||
* @param yaw
|
||||
* @param pitch
|
||||
* @return
|
||||
* @return A new Location instance.
|
||||
* @throws NullPointerException if the resulting world is null.
|
||||
*/
|
||||
public static final Location clone(final Location loc, final float yaw, final float pitch){
|
||||
return new Location(loc.getWorld(), loc.getX(), loc.getY(), loc.getZ(), yaw, pitch);
|
||||
return new Location(testWorld(loc.getWorld()), loc.getX(), loc.getY(), loc.getZ(), yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone with yaw and pitch of ref, use ref if setBack is null.
|
||||
* @param setBack
|
||||
* @param ref
|
||||
* @return
|
||||
* Clone setBack, with yaw and pitch taken from ref, if setBack is null, ref is cloned fully.
|
||||
* @param setBack Can be null.
|
||||
* @param ref Must not be null.
|
||||
* @return A new Location instance.
|
||||
* @throws NullPointerException if the resulting world is null.
|
||||
*/
|
||||
public static final Location clone(final Location setBack, final Location ref) {
|
||||
if (setBack == null){
|
||||
|
@ -49,26 +58,121 @@ public class LocUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* SA
|
||||
* Update setBack by loc.
|
||||
* @param setBack
|
||||
* @param loc
|
||||
* @throws NullPointerException if loc.getWorld() is null.
|
||||
*/
|
||||
public static final void set(final Location setBack, final Location loc) {
|
||||
setBack.setWorld(loc.getWorld());
|
||||
setBack.setWorld(testWorld(loc.getWorld()));
|
||||
setBack.setX(loc.getX());
|
||||
setBack.setY(loc.getY());
|
||||
setBack.setZ(loc.getZ());
|
||||
setBack.setYaw(loc.getYaw());
|
||||
setBack.setPitch(loc.getPitch());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update setBack by loc.
|
||||
* @param setBack
|
||||
* @param loc
|
||||
* @throws NullPointerException if loc.getWorld() is null.
|
||||
*/
|
||||
public static final void set(final Location setBack, final PlayerLocation loc) {
|
||||
setBack.setWorld(loc.getWorld());
|
||||
setBack.setWorld(testWorld(loc.getWorld()));
|
||||
setBack.setX(loc.getX());
|
||||
setBack.setY(loc.getY());
|
||||
setBack.setZ(loc.getZ());
|
||||
setBack.setYaw(loc.getYaw());
|
||||
setBack.setPitch(loc.getPitch());
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a NullPointerException if world is null.
|
||||
* @param world
|
||||
* @return
|
||||
*/
|
||||
private static World testWorld(final World world) {
|
||||
if (world == null) {
|
||||
throw new NullPointerException("World must not be null.");
|
||||
} else {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick out of bounds check for yaw.
|
||||
* @param yaw
|
||||
* @return
|
||||
*/
|
||||
public static final boolean needsYawCorrection(final float yaw) {
|
||||
return yaw == Float.NaN || yaw < 0f || yaw >= 360f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick out of bounds check for pitch.
|
||||
* @param pitch
|
||||
* @return
|
||||
*/
|
||||
public static final boolean needsPitchCorrection(final float pitch) {
|
||||
return pitch == Float.NaN || pitch < -90f || pitch > 90f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick out of bounds check for yaw and pitch.
|
||||
* @param yaw
|
||||
* @param pitch
|
||||
* @return
|
||||
*/
|
||||
public static final boolean needsDirectionCorrection(final float yaw, final float pitch) {
|
||||
return needsYawCorrection(yaw) || needsPitchCorrection(pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure 0 <= yaw < 360.
|
||||
* @param yaw
|
||||
* @return
|
||||
*/
|
||||
public static final float correctYaw(float yaw) {
|
||||
if (yaw == Float.NaN) {
|
||||
return 0f;
|
||||
}
|
||||
if (yaw >= 360f) {
|
||||
if (yaw > 10000f) {
|
||||
yaw = 0f;
|
||||
} else {
|
||||
while (yaw > 360f) {
|
||||
yaw -= 360f;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (yaw < 0f) {
|
||||
if (yaw < -10000f) {
|
||||
yaw = 0f;
|
||||
} else {
|
||||
while (yaw < 0f) {
|
||||
yaw += 360f;
|
||||
}
|
||||
}
|
||||
}
|
||||
return yaw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure -90 <= pitch <= 90.
|
||||
* @param pitch
|
||||
* @return
|
||||
*/
|
||||
public static final float correctPitch(float pitch) {
|
||||
if (pitch == Float.NaN) {
|
||||
return 0f;
|
||||
} else if (pitch < -90f) {
|
||||
return -90f;
|
||||
} else if (pitch > 90f) {
|
||||
return 90f;
|
||||
} else {
|
||||
return pitch;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
package fr.neatmonster.nocheatplus.checks.moving;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
|
||||
|
||||
/**
|
||||
* This class is meant to record locations for players moving, in order to allow to be more
|
||||
* lenient for the case of latency for player-player interaction such as with fighting.
|
||||
* <br>
|
||||
* NOTES on intended use:<br>
|
||||
* <li>Is meant to always carry some location.</li>
|
||||
* <li>Records only the end-positions of a move.</li>
|
||||
* <li>Prefer calling add(...) with the current location, before iterating. Alternative: guard with isEmpty().</li>
|
||||
* <li>Updating on teleport events is not intended - if the distance is too big, Minecraft should prevent interaction anyway.</li>
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public class LocationTrace {
|
||||
|
||||
public static final class TraceEntry {
|
||||
|
||||
/** We keep it open, if ticks or ms are used. */
|
||||
public long time;
|
||||
/** Coordinates. */
|
||||
public double x, y, z;
|
||||
public double lastDistSq;
|
||||
|
||||
public void set(long time, double x, double y, double z, double lastDistSq) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.time = time;
|
||||
this.lastDistSq = lastDistSq;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate from oldest to latest. Not a fully featured Iterator.
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public static final class TraceIterator implements Iterator<TraceEntry>{
|
||||
private final TraceEntry[] entries;
|
||||
/** Index as in LocationTrace */
|
||||
private final int index;
|
||||
private final int size;
|
||||
private int currentIndex;
|
||||
private final boolean ascend;
|
||||
|
||||
protected TraceIterator(TraceEntry[] entries, int index, int size, int currentIndex, boolean ascend) {
|
||||
if (currentIndex >= entries.length || currentIndex < 0 ||
|
||||
currentIndex <= index - size || currentIndex > index && currentIndex <= index - size + entries.length) {
|
||||
// This should also prevent iterators for size == 0, for the moment (!).
|
||||
throw new IllegalArgumentException("startIndex out of bounds.");
|
||||
}
|
||||
this.entries = entries;
|
||||
this.index = index;
|
||||
this.size = size;
|
||||
this.currentIndex = currentIndex;
|
||||
this.ascend = ascend;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TraceEntry next() {
|
||||
if (!hasNext()) {
|
||||
throw new IndexOutOfBoundsException("No more entries to iterate.");
|
||||
}
|
||||
final TraceEntry entry = entries[currentIndex];
|
||||
if (ascend) {
|
||||
currentIndex ++;
|
||||
if (currentIndex >= entries.length) {
|
||||
currentIndex = 0;
|
||||
}
|
||||
int ref = index - size + 1;
|
||||
if (ref < 0) {
|
||||
ref += entries.length;
|
||||
}
|
||||
if (currentIndex == ref) {
|
||||
// Invalidate the iterator.
|
||||
currentIndex = -1;
|
||||
}
|
||||
} else {
|
||||
currentIndex --;
|
||||
if (currentIndex < 0) {
|
||||
currentIndex = entries.length - 1;
|
||||
}
|
||||
if (currentIndex == index) {
|
||||
// Invalidate the iterator.
|
||||
currentIndex = - 1;
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasNext() {
|
||||
// Just check if currentIndex is within range.
|
||||
return currentIndex >= 0 && currentIndex <= index && currentIndex > index - size || currentIndex > index && currentIndex >= index - size + entries.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A Ring. */
|
||||
private final TraceEntry[] entries;
|
||||
/** Last element index. */
|
||||
private int index = -1;
|
||||
/** Number of valid entries. */
|
||||
private int size = 0;
|
||||
private final double mergeDist;
|
||||
private final double mergeDistSq;
|
||||
|
||||
// (No world name stored: Should be reset on world changes.)
|
||||
|
||||
public LocationTrace(int bufferSize, double mergeDist) {
|
||||
// TODO: Might consider a cut-off distance/age (performance saving for iteration).
|
||||
if (bufferSize < 1) {
|
||||
throw new IllegalArgumentException("Expect bufferSize > 0, got instead: " + bufferSize);
|
||||
}
|
||||
entries = new TraceEntry[bufferSize];
|
||||
for (int i = 0; i < bufferSize; i++) {
|
||||
entries[i] = new TraceEntry();
|
||||
}
|
||||
this.mergeDist = mergeDist;
|
||||
this.mergeDistSq = mergeDist * mergeDist;
|
||||
}
|
||||
|
||||
public final void addEntry(final long time, final double x, final double y, final double z) {
|
||||
double lastDistSq = 0.0;
|
||||
if (size > 0) {
|
||||
final TraceEntry latestEntry = entries[index];
|
||||
// TODO: Consider duration of staying there ?
|
||||
if (x == latestEntry.x && y == latestEntry.y && z == latestEntry.z) {
|
||||
latestEntry.time = time;
|
||||
return;
|
||||
}
|
||||
lastDistSq = TrigUtil.distanceSquared(x, y, z, latestEntry.x, latestEntry.y, latestEntry.z);
|
||||
// TODO: Think about minMergeSize (1 = never merge the first two, size = first fill the ring).
|
||||
if (size > 1 && lastDistSq <= mergeDistSq) {
|
||||
// TODO: Could use Manhattan, after all.
|
||||
// Only merge if last distance was not greater than mergeDist, to prevent too-far-off entries.
|
||||
if (latestEntry.lastDistSq <= mergeDistSq) {
|
||||
// Update lastDistSq, due to shifting the elements position.
|
||||
final TraceEntry secondLatest = index - 1 < 0 ? entries[index - 1 + entries.length] : entries[index - 1];
|
||||
lastDistSq = TrigUtil.distanceSquared(x, y, z, secondLatest.x, secondLatest.y, secondLatest.z);
|
||||
latestEntry.set(time, x, y, z, lastDistSq);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Advance index.
|
||||
index++;
|
||||
if (index == entries.length) {
|
||||
index = 0;
|
||||
}
|
||||
if (size < entries.length) {
|
||||
size ++;
|
||||
}
|
||||
final TraceEntry newEntry = entries[index];
|
||||
newEntry.set(time, x, y, z, lastDistSq);
|
||||
}
|
||||
|
||||
/** Reset content pointers - call with world changes. */
|
||||
public void reset() {
|
||||
index = 0;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actual number of valid elements. After some time of moving this should be entries.length.
|
||||
* @return
|
||||
*/
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
public boolean isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size of ring buffer (maximal possible number of elements).
|
||||
* @return
|
||||
*/
|
||||
public int getMaxSize() {
|
||||
return entries.length;
|
||||
}
|
||||
|
||||
public double getMergeDist() {
|
||||
return mergeDist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate from latest to oldest.
|
||||
* @return
|
||||
*/
|
||||
public TraceIterator latestIterator() {
|
||||
return new TraceIterator(entries, index, size, index, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate from oldest to latest.
|
||||
* @return
|
||||
*/
|
||||
public TraceIterator oldestIterator() {
|
||||
final int currentIndex = index - size + 1;
|
||||
return new TraceIterator(entries, index, size, currentIndex < 0 ? currentIndex + entries.length : currentIndex, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterate from entry with max. age to latest, always includes latest.
|
||||
* @param tick Absolute tick value for oldest accepted tick.
|
||||
* @param ms Absolute ms value for oldest accepted ms;
|
||||
* @return
|
||||
*/
|
||||
public TraceIterator maxAgeIterator(long time) {
|
||||
int currentIndex = index;
|
||||
int tempIndex = currentIndex;
|
||||
int steps = 1;
|
||||
while (steps < size) {
|
||||
tempIndex --;
|
||||
if (tempIndex < 0) {
|
||||
tempIndex += size;
|
||||
}
|
||||
final TraceEntry entry = entries[tempIndex];
|
||||
if (entry.time >= time) {
|
||||
// Continue.
|
||||
currentIndex = tempIndex;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
steps ++;
|
||||
}
|
||||
return new TraceIterator(entries, index, size, currentIndex, true);
|
||||
}
|
||||
|
||||
}
|
|
@ -60,8 +60,12 @@ public class MorePackets extends Check {
|
|||
|
||||
if (!data.hasMorePacketsSetBack()){
|
||||
// TODO: Check if other set-back is appropriate or if to set on other events.
|
||||
if (data.hasSetBack()) data.setMorePacketsSetBack(data.getSetBack(to));
|
||||
else data.setMorePacketsSetBack(from);
|
||||
if (data.hasSetBack()) {
|
||||
data.setMorePacketsSetBack(data.getSetBack(to));
|
||||
}
|
||||
else {
|
||||
data.setMorePacketsSetBack(from);
|
||||
}
|
||||
}
|
||||
|
||||
// Take a packet from the buffer.
|
||||
|
@ -76,10 +80,8 @@ public class MorePackets extends Check {
|
|||
|
||||
// Execute whatever actions are associated with this check and the violation level and find out if we should
|
||||
// cancel the event.
|
||||
if (executeActions(player, data.morePacketsVL, -data.morePacketsBuffer,
|
||||
MovingConfig.getConfig(player).morePacketsActions)){
|
||||
if (executeActions(player, data.morePacketsVL, -data.morePacketsBuffer, MovingConfig.getConfig(player).morePacketsActions)){
|
||||
newTo = data.getMorePacketsSetBack();
|
||||
data.setTeleported(newTo);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -93,23 +95,28 @@ public class MorePackets extends Check {
|
|||
|
||||
// If there was a long pause (maybe server lag?), allow buffer to grow up to 100.
|
||||
if (seconds > 2) {
|
||||
if (data.morePacketsBuffer > 100)
|
||||
data.morePacketsBuffer = 100;
|
||||
} else if (data.morePacketsBuffer > 50)
|
||||
if (data.morePacketsBuffer > 100) {
|
||||
data.morePacketsBuffer = 100;
|
||||
}
|
||||
} else if (data.morePacketsBuffer > 50) {
|
||||
// Only allow growth up to 50.
|
||||
data.morePacketsBuffer = 50;
|
||||
|
||||
}
|
||||
// Set the new "last" time.
|
||||
data.morePacketsLastTime = time;
|
||||
|
||||
// Set the new "setback" location.
|
||||
if (newTo == null) data.setMorePacketsSetBack(from);
|
||||
} else if (data.morePacketsLastTime > time)
|
||||
if (newTo == null) {
|
||||
data.setMorePacketsSetBack(from);
|
||||
}
|
||||
} else if (data.morePacketsLastTime > time) {
|
||||
// Security check, maybe system time changed.
|
||||
data.morePacketsLastTime = time;
|
||||
data.morePacketsLastTime = time;
|
||||
}
|
||||
|
||||
if (newTo == null)
|
||||
return null;
|
||||
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.
|
||||
|
|
|
@ -13,6 +13,9 @@ import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
|
|||
*
|
||||
*/
|
||||
public class MoveInfo {
|
||||
|
||||
/** For temporary use. Might need cloning for passing to external API. Only use after calling MoveInfo.set! */
|
||||
public final Location useLoc = new Location(null, 0, 0, 0);
|
||||
public final BlockCache cache;
|
||||
public final PlayerLocation from;
|
||||
public final PlayerLocation to;
|
||||
|
@ -24,24 +27,31 @@ public class MoveInfo {
|
|||
}
|
||||
|
||||
/**
|
||||
* Demands at least setting from.
|
||||
* Initialize from, and if given to. Note that useLoc is left untouched (!).
|
||||
* @param player
|
||||
* @param from
|
||||
* @param to
|
||||
* @param from Must not be null.
|
||||
* @param to Can be null.
|
||||
* @param yOnGround
|
||||
*/
|
||||
public final void set(final Player player, final Location from, final Location to, final double yOnGround){
|
||||
this.cache.setAccess(from.getWorld());
|
||||
this.from.set(from, player, yOnGround);
|
||||
this.cache.setAccess(from.getWorld());
|
||||
this.from.setBlockCache(cache);
|
||||
if (to != null){
|
||||
this.to.set(to, player, yOnGround);
|
||||
this.to.setBlockCache(cache);
|
||||
}
|
||||
// Note: using set to reset to by passing null won't work.
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear caches and remove World references and such. Also resets the world of useLoc.
|
||||
*/
|
||||
public final void cleanup(){
|
||||
useLoc.setWorld(null);
|
||||
from.cleanup();
|
||||
to.cleanup();
|
||||
cache.cleanup();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -137,8 +137,16 @@ public class MovingConfig extends ACheckConfig {
|
|||
public final long sprintingGrace;
|
||||
public final boolean assumeSprint;
|
||||
public final int speedGrace;
|
||||
public final boolean enforceLocation;
|
||||
|
||||
// Vehicles
|
||||
public final boolean vehicleEnforceLocation;
|
||||
public final boolean vehiclePreventDestroyOwn;
|
||||
|
||||
// Trace
|
||||
public final int traceSize;
|
||||
public final double traceMergeDist;
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates a new moving configuration.
|
||||
|
@ -214,9 +222,14 @@ public class MovingConfig extends ACheckConfig {
|
|||
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
|
||||
enforceLocation = config.getBoolean(ConfPaths.MOVING_ENFORCELOCATION);
|
||||
|
||||
vehicleEnforceLocation = config.getBoolean(ConfPaths.MOVING_VEHICLES_ENFORCELOCATION);
|
||||
vehiclePreventDestroyOwn = config.getBoolean(ConfPaths.MOVING_VEHICLES_PREVENTDESTROYOWN);
|
||||
|
||||
traceSize = config.getInt(ConfPaths.MOVING_TRACE_SIZE);
|
||||
traceMergeDist = config.getDouble(ConfPaths.MOVING_TRACE_MERGEDIST);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -57,9 +57,13 @@ public class MovingData extends ACheckData {
|
|||
* @return the data
|
||||
*/
|
||||
public static MovingData getData(final Player player) {
|
||||
if (!playersMap.containsKey(player.getName()))
|
||||
playersMap.put(player.getName(), new MovingData());
|
||||
return playersMap.get(player.getName());
|
||||
// Note that the trace might be null after just calling this.
|
||||
MovingData data = playersMap.get(player.getName());
|
||||
if (data == null) {
|
||||
data = new MovingData();
|
||||
playersMap.put(player.getName(), data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public static ICheckData removeData(final String playerName) {
|
||||
|
@ -81,6 +85,12 @@ public class MovingData extends ACheckData {
|
|||
}
|
||||
}
|
||||
|
||||
public static void onReload() {
|
||||
for (final MovingData data : playersMap.values()) {
|
||||
data.deleteTrace(); // Safe side.
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Not static.
|
||||
/////////////////
|
||||
|
@ -119,6 +129,8 @@ public class MovingData extends ACheckData {
|
|||
public double fromX = Double.MAX_VALUE, fromY, fromZ;
|
||||
/** Last to coordinates. */
|
||||
public double toX = Double.MAX_VALUE, toY, toZ;
|
||||
/** Moving trace (to positions). This is initialized on "playerJoins, i.e. MONITOR, and set to null on playerLeaves."*/
|
||||
private LocationTrace trace = null;
|
||||
|
||||
// sf rather
|
||||
/** To/from was ground or web or assumed to be etc. */
|
||||
|
@ -269,8 +281,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 +294,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 +395,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 +442,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 +468,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() {
|
||||
|
@ -617,6 +657,7 @@ public class MovingData extends ACheckData {
|
|||
*/
|
||||
public void onPlayerLeave() {
|
||||
removeAllVelocity();
|
||||
deleteTrace();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -665,4 +706,67 @@ public class MovingData extends ACheckData {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests for a LocationTrace instance being set at all, not for locations having been added.
|
||||
* @return
|
||||
*/
|
||||
public boolean hasTrace() {
|
||||
return trace != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience: Access method to simplify coding, being aware of some plugins using Player implementations as NPCs, leading to traces not being present.
|
||||
* @return
|
||||
*/
|
||||
public LocationTrace getTrace(final Player player) {
|
||||
if (trace == null) {
|
||||
final MovingConfig cc = MovingConfig.getConfig(player);
|
||||
trace = new LocationTrace(cc.traceSize, cc.traceMergeDist);
|
||||
}
|
||||
return trace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience
|
||||
* @param player
|
||||
* @param loc
|
||||
*/
|
||||
public void resetTrace(final Player player, final Location loc, final long time) {
|
||||
final MovingConfig cc = MovingConfig.getConfig(player);
|
||||
resetTrace(loc, time, cc.traceSize, cc.traceMergeDist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to add a location to the trace, creates the trace if necessary.
|
||||
* @param player
|
||||
* @param loc
|
||||
* @param time
|
||||
* @return Updated LocationTrace instance, for convenient use, without sticking too much to MovingData.
|
||||
*/
|
||||
public LocationTrace updateTrace(final Player player, final Location loc, final long time) {
|
||||
final LocationTrace trace = getTrace(player);
|
||||
trace.addEntry(time, loc.getX(), loc.getY(), loc.getZ());
|
||||
return trace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience: Create or just reset the trace, add the current location.
|
||||
* @param loc
|
||||
* @param size
|
||||
* @param mergeDist
|
||||
* @param traceMergeDist
|
||||
*/
|
||||
public void resetTrace(final Location loc, final long time, final int size, double mergeDist) {
|
||||
if (trace == null || trace.getMaxSize() != size || trace.getMergeDist() != mergeDist) {
|
||||
trace = new LocationTrace(size, mergeDist);
|
||||
} else {
|
||||
trace.reset();
|
||||
}
|
||||
trace.addEntry(time, loc.getX(), loc.getY(), loc.getZ());
|
||||
}
|
||||
|
||||
public void deleteTrace() {
|
||||
trace = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -114,7 +114,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
event.setTo(setBack);
|
||||
restored = true;
|
||||
}
|
||||
else data.resetSetBack();
|
||||
else {
|
||||
data.resetSetBack();
|
||||
}
|
||||
}
|
||||
if (!restored) {
|
||||
pLoc.set(loc, player);
|
||||
|
@ -125,13 +127,16 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
}
|
||||
}
|
||||
pLoc.cleanup();
|
||||
if (!restored && MovingConfig.getConfig(player).tempKickIllegal) {
|
||||
// TODO: correct the location ?
|
||||
NCPAPIProvider.getNoCheatPlusAPI().denyLogin(player.getName(), 24L * 60L * 60L * 1000L);
|
||||
LogUtil.logSevere("[NCP] could not restore location for " + player.getName() + " deny login for 24 hours");
|
||||
if (!restored) {
|
||||
// TODO: reset the bounding box of the player ?
|
||||
if (MovingConfig.getConfig(player).tempKickIllegal) {
|
||||
NCPAPIProvider.getNoCheatPlusAPI().denyLogin(player.getName(), 24L * 60L * 60L * 1000L);
|
||||
LogUtil.logSevere("[NCP] could not restore location for " + player.getName() + ", kicking them and deny login for 24 hours");
|
||||
} else {
|
||||
LogUtil.logSevere("[NCP] could not restore location for " + player.getName() + ", kicking them.");
|
||||
}
|
||||
CheckUtils.kickIllegalMove(player);
|
||||
}
|
||||
// TODO: reset the bounding box of the player ?
|
||||
CheckUtils.kickIllegalMove(player);
|
||||
}
|
||||
|
||||
|
||||
|
@ -170,12 +175,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,17 +224,18 @@ 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
|
||||
&& (canJumpOffTop(mat.getId()) || BlockProperties.isLiquid(mat.getId()))) {
|
||||
&& (canJumpOffTop(mat) || BlockProperties.isLiquid(mat))) {
|
||||
// The creative fly and/or survival fly check is enabled, the
|
||||
// block was placed below the player and is
|
||||
// solid, so do what we have to do.
|
||||
data.setSetBackY(blockY + 1D);
|
||||
data.sfJumpPhase = 0;
|
||||
}
|
||||
useLoc.setWorld(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -230,9 +243,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
* @param id
|
||||
* @return
|
||||
*/
|
||||
private static boolean canJumpOffTop(final int id) {
|
||||
private static boolean canJumpOffTop(final Material blockType) {
|
||||
// TODO: Test if this can be removed!
|
||||
return BlockProperties.isGround(id) || BlockProperties.isSolid(id);
|
||||
return BlockProperties.isGround(blockType) || BlockProperties.isSolid(blockType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -261,28 +274,29 @@ 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);
|
||||
}
|
||||
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)) {
|
||||
// Check if to deal damage.
|
||||
double y = loc.getY();
|
||||
if (data.hasSetBack()) y = Math.min(y, data.getSetBackY());
|
||||
noFall.checkDamage(player, data, y);
|
||||
}
|
||||
// Teleport.
|
||||
data.setTeleported(target); // Should be enough. | new Location(target.getWorld(), target.getX(), target.getY(), target.getZ(), target.getYaw(), target.getPitch());
|
||||
player.teleport(target, TeleportCause.PLUGIN);// TODO: schedule / other measures ?
|
||||
if (sfCheck && cc.sfFallDamage && noFall.isEnabled(player)) {
|
||||
// Check if to deal damage.
|
||||
double y = loc.getY();
|
||||
if (data.hasSetBack()) y = Math.min(y, data.getSetBackY());
|
||||
noFall.checkDamage(player, data, y);
|
||||
}
|
||||
// Cleanup
|
||||
useLoc.setWorld(null);
|
||||
// Teleport.
|
||||
data.prepareSetBack(target); // Should be enough. | new Location(target.getWorld(), target.getX(), target.getY(), target.getZ(), target.getYaw(), target.getPitch());
|
||||
player.teleport(target, TeleportCause.PLUGIN);// TODO: schedule / other measures ?
|
||||
}
|
||||
else{
|
||||
// Reset bed ...
|
||||
|
@ -303,10 +317,19 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
// Maybe this helps with people teleporting through Multiverse portals having problems?
|
||||
final Player player = event.getPlayer();
|
||||
final MovingData data = MovingData.getData(player);
|
||||
final MovingConfig cc = MovingConfig.getConfig(player);
|
||||
data.clearFlyData();
|
||||
data.clearMorePacketsData();
|
||||
// TODO: Might omit this if neither check is activated.
|
||||
data.setSetBack(player.getLocation());
|
||||
final Location loc = player.getLocation(useLoc);
|
||||
data.setSetBack(loc);
|
||||
data.resetPositions(loc);
|
||||
data.resetTrace(loc, TickTask.getTick(), cc.traceSize, cc.traceMergeDist);
|
||||
if (cc.enforceLocation) {
|
||||
// Just in case.
|
||||
playersEnforce.add(player.getName());
|
||||
}
|
||||
useLoc.setWorld(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -348,6 +371,12 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
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).
|
||||
|
||||
|
@ -371,23 +400,38 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
// Ignore changing worlds.
|
||||
earlyReturn = true;
|
||||
} else {
|
||||
// COntinue with full processing.
|
||||
earlyReturn = false;
|
||||
}
|
||||
|
||||
// TODO: Might log base parts here (+extras).
|
||||
if (earlyReturn) {
|
||||
// TODO: Remove player from enforceLocation ?
|
||||
// TODO: Log "early return: " + tags.
|
||||
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.
|
||||
// TODO: Reset positions? enforceLocation?
|
||||
event.setTo(newTo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// newTo should be null here.
|
||||
|
||||
// TODO: Order this to above "early return"?
|
||||
// Set up data / caching.
|
||||
final MoveInfo moveInfo;
|
||||
if (parkedInfo.isEmpty()) moveInfo = new MoveInfo(mcAccess);
|
||||
else moveInfo = parkedInfo.remove(parkedInfo.size() - 1);
|
||||
if (parkedInfo.isEmpty()) {
|
||||
moveInfo = new MoveInfo(mcAccess);
|
||||
}
|
||||
else {
|
||||
moveInfo = parkedInfo.remove(parkedInfo.size() - 1);
|
||||
}
|
||||
final MovingConfig cc = MovingConfig.getConfig(player);
|
||||
moveInfo.set(player, from, to, cc.yOnGround);
|
||||
// TODO: Data resetting above ?
|
||||
|
@ -405,6 +449,19 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
return;
|
||||
}
|
||||
|
||||
// The players location.
|
||||
final Location loc = (cc.noFallCheck || cc.passableCheck) ? player.getLocation(moveInfo.useLoc) : null;
|
||||
|
||||
|
||||
// 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) {
|
||||
// Hard to confine assumesprint further (some logics change with hdist or sprinting).
|
||||
|
@ -444,10 +501,6 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
final int tick = TickTask.getTick();
|
||||
data.removeInvalidVelocity(tick - cc.velocityActivationTicks);
|
||||
data.velocityTick();
|
||||
|
||||
// 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;
|
||||
|
||||
// Check passable first to prevent set-back override.
|
||||
// TODO: Redesign to set set-backs later (queue + invalidate).
|
||||
|
@ -564,30 +617,21 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
}
|
||||
}
|
||||
|
||||
// Did one of the checks decide we need a new "to"-location?
|
||||
if (newTo != null) {
|
||||
// Reset some data.
|
||||
data.prepareSetBack(newTo);
|
||||
|
||||
// Set new to-location.
|
||||
// TODO: Clone here for the case of using loc with loc = player.getLocation(moveInfo.loc).
|
||||
// TODO: Actually should be a newly created location already (data.getSetBack).
|
||||
event.setTo(newTo);
|
||||
|
||||
// Debug.
|
||||
if (cc.debug) {
|
||||
System.out.println(player.getName() + " set back to: " + newTo.getWorld() + StringUtil.fdec3.format(newTo.getX()) + ", " + StringUtil.fdec3.format(newTo.getY()) + ", " + StringUtil.fdec3.format(newTo.getZ()));
|
||||
}
|
||||
}
|
||||
|
||||
// Set positions.
|
||||
// TODO: Consider setting in Monitor (concept missing for changing coordinates, could double-check).
|
||||
data.fromX = from.getX();
|
||||
data.fromY = from.getY();
|
||||
data.fromZ = from.getZ();
|
||||
data.toX = to.getX();
|
||||
data.toY = to.getY();
|
||||
data.toZ = to.getZ();
|
||||
if (newTo == null) {
|
||||
// Set positions.
|
||||
// TODO: Consider setting in Monitor (concept missing for changing coordinates, could double-check).
|
||||
data.fromX = from.getX();
|
||||
data.fromY = from.getY();
|
||||
data.fromZ = from.getZ();
|
||||
data.toX = to.getX();
|
||||
data.toY = to.getY();
|
||||
data.toZ = to.getZ();
|
||||
}
|
||||
else {
|
||||
// Set-back handling.
|
||||
onSetBack(player, event, newTo, data, cc);
|
||||
}
|
||||
|
||||
// Cleanup.
|
||||
moveInfo.cleanup();
|
||||
|
@ -595,6 +639,36 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param player
|
||||
* @param event
|
||||
* @param newTo Must be a cloned or new Location instance, free for whatever other plugins do with it.
|
||||
* @param data
|
||||
* @param cc
|
||||
*/
|
||||
private void onSetBack(final Player player, final PlayerMoveEvent event, final Location newTo, final MovingData data, final MovingConfig cc) {
|
||||
// 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()));
|
||||
}
|
||||
|
||||
// Reset some data.
|
||||
data.prepareSetBack(newTo);
|
||||
data.resetPositions(newTo); // TODO: Might move into prepareSetBack, experimental here.
|
||||
|
||||
// Set new to-location.
|
||||
event.setTo(newTo);
|
||||
|
||||
// Debug.
|
||||
if (cc.debug) {
|
||||
System.out.println(player.getName() + " set back to: " + newTo.getWorld() + StringUtil.fdec3.format(newTo.getX()) + ", " + StringUtil.fdec3.format(newTo.getY()) + ", " + StringUtil.fdec3.format(newTo.getZ()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from player-move checking, if the player is inside of a vehicle.
|
||||
* @param player
|
||||
* @param from
|
||||
|
@ -612,7 +686,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);
|
||||
|
@ -675,12 +749,14 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
|
||||
// Feed combined check.
|
||||
final CombinedData data = CombinedData.getData(player);
|
||||
data.lastMoveTime = now;
|
||||
data.lastMoveTime = now; // TODO: Evaluate moving this to MovingData !?
|
||||
|
||||
final Location from = event.getFrom();
|
||||
final String fromWorldName = from.getWorld().getName();
|
||||
|
||||
// Feed yawrate and reset moving data positions if necessary.
|
||||
final MovingData mData = MovingData.getData(player);
|
||||
final long time = TickTask.getTick();
|
||||
if (!event.isCancelled()) {
|
||||
final Location to = event.getTo();
|
||||
final String toWorldName = to.getWorld().getName();
|
||||
|
@ -688,20 +764,26 @@ 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());
|
||||
final Location ref = player.getVehicle().getLocation(useLoc);
|
||||
mData.resetPositions(ref);
|
||||
useLoc.setWorld(null);
|
||||
mData.resetTrace(player, ref, time);
|
||||
}
|
||||
else if (!fromWorldName.equals(toWorldName)) {
|
||||
MovingData.getData(player).resetPositions(to);
|
||||
mData.resetPositions(to);
|
||||
mData.resetTrace(player, to, time);
|
||||
}
|
||||
else{
|
||||
// Slightly redundant at present.
|
||||
MovingData.getData(player).setTo(to);
|
||||
mData.setTo(to);
|
||||
mData.resetTrace(player, to, time);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO: teleported + other resetting ?
|
||||
Combined.feedYawRate(player, from.getYaw(), now, fromWorldName, data);
|
||||
MovingData.getData(player).resetPositions(from);
|
||||
mData.resetPositions(from);
|
||||
mData.resetTrace(player, from, time); // TODO: Should probably leave this to the teleport event!
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -719,31 +801,6 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
data.clearMorePacketsData();
|
||||
// TODO: This event might be redundant (!).
|
||||
}
|
||||
|
||||
/**
|
||||
* When a player respawns, all information related to the moving checks
|
||||
* becomes invalid.
|
||||
*
|
||||
* @param event
|
||||
* the event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerRespawn(final PlayerRespawnEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final MovingData data = MovingData.getData(player);
|
||||
data.clearFlyData();
|
||||
data.clearMorePacketsData();
|
||||
data.setSetBack(event.getRespawnLocation());
|
||||
// TODO: consider data.resetPositions(data.setBack);
|
||||
// (Not putting hover in at respawn due to chunk sending.)
|
||||
// TODO: Might use grace ticks for this too (and bigger teleports).
|
||||
// final MovingConfig cc = MovingConfig.getConfig(player);
|
||||
// if (cc.sfHoverCheck) {
|
||||
// // Assume the player might be hovering.
|
||||
// data.sfHoverTicks = 0;
|
||||
// hoverTicks.add(player.getName());
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear fly data on death.
|
||||
|
@ -755,7 +812,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 +901,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
event.setTo(ref);
|
||||
}
|
||||
else{
|
||||
ref = from;
|
||||
ref = from; // Player.getLocation ?
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
@ -857,7 +915,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
// public void run() {
|
||||
// if (!data.hasSetBackWorldChanged(setBack)) { // && data.isSetBack(setBack)) {
|
||||
// player.sendMessage("SETBACK FROM MC DERP.");
|
||||
// player.teleport(setBack);
|
||||
// player.teleport(setBack, TeleportCause.PLUGIN);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
@ -1016,11 +1074,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,26 +1120,40 @@ 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)
|
||||
public void onEntityDamage(final EntityDamageEvent event) {
|
||||
if (event.getCause() != DamageCause.FALL) return;
|
||||
if (event.getCause() != DamageCause.FALL) {
|
||||
return;
|
||||
}
|
||||
final Entity entity = event.getEntity();
|
||||
if (!(entity instanceof Player)) return;
|
||||
if (!(entity instanceof Player)) {
|
||||
return;
|
||||
}
|
||||
final Player player = (Player) entity;
|
||||
final MovingData data = MovingData.getData(player);
|
||||
if (player.isInsideVehicle()) {
|
||||
// Ignore vehicles (noFallFallDistance will be inaccurate anyway).
|
||||
data.clearNoFallData();
|
||||
return;
|
||||
}
|
||||
final MovingConfig cc = MovingConfig.getConfig(player);
|
||||
if (event.isCancelled() || !shouldCheckSurvivalFly(player, data, cc) || !noFall.isEnabled(player)) {
|
||||
data.clearNoFallData();
|
||||
return;
|
||||
}
|
||||
final Location loc = player.getLocation();
|
||||
final Location loc = player.getLocation(useLoc);
|
||||
boolean allowReset = true;
|
||||
if (!data.noFallSkipAirCheck) {
|
||||
final MoveInfo moveInfo;
|
||||
if (parkedInfo.isEmpty()) moveInfo = new MoveInfo(mcAccess);
|
||||
else moveInfo = parkedInfo.remove(parkedInfo.size() - 1);
|
||||
if (parkedInfo.isEmpty()) {
|
||||
moveInfo = new MoveInfo(mcAccess);
|
||||
}
|
||||
else {
|
||||
moveInfo = parkedInfo.remove(parkedInfo.size() - 1);
|
||||
}
|
||||
moveInfo.set(player, loc, null, cc.noFallyOnGround);
|
||||
// NOTE: No isIllegal check here.
|
||||
final PlayerLocation pLoc = moveInfo.from;
|
||||
|
@ -1139,43 +1211,113 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
}
|
||||
}
|
||||
// Entity fall-distance should be reset elsewhere.
|
||||
// Cleanup.
|
||||
useLoc.setWorld(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* When a player respawns, all information related to the moving checks
|
||||
* becomes invalid.
|
||||
*
|
||||
* @param event
|
||||
* the event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerRespawn(final PlayerRespawnEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final MovingData data = MovingData.getData(player);
|
||||
final MovingConfig cc = MovingConfig.getConfig(player);
|
||||
|
||||
final Location loc = event.getRespawnLocation();
|
||||
data.clearFlyData();
|
||||
data.setSetBack(loc);
|
||||
|
||||
// Handle respawn like join.
|
||||
dataOnJoin(player, loc, data, cc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerJoins(final Player player) {
|
||||
final MovingData data = MovingData.getData(player);
|
||||
// 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 MovingConfig cc = MovingConfig.getConfig(player);
|
||||
|
||||
final Location loc = player.getLocation(useLoc);
|
||||
|
||||
// Correct set-back on world changes.
|
||||
if (loc == null) {
|
||||
// Bug on server side ?
|
||||
// Correct set-back on join.
|
||||
if (data.hasSetBackWorldChanged(loc)) {
|
||||
data.clearFlyData();
|
||||
data.setSetBack(loc);
|
||||
}
|
||||
else if (!data.hasSetBack()) {
|
||||
// TODO: Might consider something else like with respawn. Check if it is passable ?
|
||||
data.setSetBack(loc);
|
||||
}
|
||||
else if (data.hasSetBackWorldChanged(loc)) {
|
||||
data.clearFlyData();
|
||||
data.setSetBack(loc);
|
||||
}
|
||||
if (data.fromX == Double.MAX_VALUE && data.toX == Double.MAX_VALUE) {
|
||||
// TODO: re-think: more fine grained reset?
|
||||
data.resetPositions(loc);
|
||||
|
||||
dataOnJoin(player, loc, data, cc);
|
||||
|
||||
// Cleanup.
|
||||
useLoc.setWorld(null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Alter data for players joining (join, respawn).<br>
|
||||
* Do before, if necessary:<br>
|
||||
* <li>data.clearFlyData()</li>
|
||||
* <li>data.setSetBack(...)</li>
|
||||
* @param player
|
||||
* @param loc Can be useLoc (!).
|
||||
* @param data
|
||||
* @param cc
|
||||
*/
|
||||
private void dataOnJoin(Player player, Location loc, MovingData data, MovingConfig cc) {
|
||||
final int tick = TickTask.getTick();
|
||||
// Check loaded chunks.
|
||||
if (cc.loadChunksOnJoin) {
|
||||
final int loaded = BlockCache.ensureChunksLoaded(loc.getWorld(), loc.getX(), loc.getZ(), 3.0);
|
||||
if (loaded > 0 && cc.debug && BuildParameters.debugLevel > 0) {
|
||||
// DEBUG
|
||||
LogUtil.logInfo("[NoCheatPlus] Player join: Loaded " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + loc.getWorld().getName() + " for player: " + player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// Always reset position to this one.
|
||||
// TODO: more fine grained reset?
|
||||
data.resetPositions(loc);
|
||||
data.clearMorePacketsData();
|
||||
data.removeAllVelocity();
|
||||
data.resetTrace(loc, tick, cc.traceSize, cc.traceMergeDist);
|
||||
|
||||
// More resetting.
|
||||
data.vDistAcc.clear();
|
||||
data.toWasReset = false;
|
||||
data.fromWasReset = false;
|
||||
data.toWasReset = BlockProperties.isOnGroundOrResetCond(player, loc, cc.yOnGround);
|
||||
data.fromWasReset = data.toWasReset;
|
||||
|
||||
// Enforcing the location.
|
||||
if (cc.enforceLocation) {
|
||||
playersEnforce.add(player.getName());
|
||||
}
|
||||
|
||||
// Hover.
|
||||
final MovingConfig cc = MovingConfig.getConfig(player);
|
||||
initHover(player, data, cc, data.toWasReset); // isOnGroundOrResetCond
|
||||
|
||||
// // Bad pitch/yaw, just in case.
|
||||
// if (LocUtil.needsDirectionCorrection(useLoc.getYaw(), useLoc.getPitch())) {
|
||||
// DataManager.getPlayerData(player).task.correctDirection();
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the hover check for a player (login, respawn).
|
||||
* @param player
|
||||
* @param data
|
||||
* @param cc
|
||||
* @param isOnGroundOrResetCond
|
||||
*/
|
||||
private void initHover(final Player player, final MovingData data, final MovingConfig cc, final boolean isOnGroundOrResetCond) {
|
||||
// Reset hover ticks until a better method is used.
|
||||
if (cc.sfHoverCheck) {
|
||||
if (!isOnGroundOrResetCond && cc.sfHoverCheck) {
|
||||
// Start as if hovering already.
|
||||
// Could check shouldCheckSurvivalFly(player, data, cc), but this should be more sharp (gets checked on violation).
|
||||
data.sfHoverTicks = 0;
|
||||
|
@ -1186,16 +1328,6 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
data.sfHoverLoginTicks = 0;
|
||||
data.sfHoverTicks = -1;
|
||||
}
|
||||
|
||||
// Check loaded chunks.
|
||||
if (cc.loadChunksOnJoin) {
|
||||
final int loaded = BlockCache.ensureChunksLoaded(loc.getWorld(), loc.getX(), loc.getZ(), 3.0);
|
||||
if (loaded > 0 && cc.debug && BuildParameters.debugLevel > 0) {
|
||||
// DEBUG
|
||||
LogUtil.logInfo("[NoCheatPlus] Player join: Loaded " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + loc.getWorld().getName() + " for player: " + player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1252,7 +1384,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 ?
|
||||
}
|
||||
|
||||
|
@ -1272,7 +1405,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();
|
||||
|
@ -1290,7 +1423,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
loc = vLoc; //
|
||||
if (data.vehicleConsistency != MoveConsistency.INCONSISTENT) {
|
||||
final Location oldLoc = new Location(pLoc.getWorld(), data.toX, data.toY, data.toZ);
|
||||
if (MoveConsistency.getConsistency(oldLoc, null, pLoc) != MoveConsistency.INCONSISTENT) {
|
||||
if (data.toX != Double.MAX_VALUE && MoveConsistency.getConsistency(oldLoc, null, pLoc) != MoveConsistency.INCONSISTENT) {
|
||||
loc = oldLoc;
|
||||
}
|
||||
}
|
||||
|
@ -1302,7 +1435,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
}
|
||||
|
||||
// Adjust loc if in liquid (meant for boats !?).
|
||||
if (BlockProperties.isLiquid(loc.getBlock().getTypeId())) {
|
||||
if (BlockProperties.isLiquid(loc.getBlock().getType())) {
|
||||
loc.setY(Location.locToBlock(loc.getY()) + 1.25);
|
||||
}
|
||||
|
||||
|
@ -1318,6 +1451,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)
|
||||
|
@ -1334,15 +1468,42 @@ 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.
|
||||
// TODO: Change to per world checking (as long as configs are per world).
|
||||
|
||||
// Enforcing location check.
|
||||
for (final String playerName : playersEnforce) {
|
||||
final Player player = DataManager.getPlayerExact(playerName);
|
||||
if (player == null || !player.isOnline()) {
|
||||
rem.add(playerName);
|
||||
continue;
|
||||
} else if (player.isDead() || player.isSleeping() || player.isInsideVehicle()) {
|
||||
// Don't remove but also don't check [subject to change].
|
||||
continue;
|
||||
}
|
||||
final MovingData data = MovingData.getData(player);
|
||||
final Location newTo = enforceLocation(player, player.getLocation(useLoc), data);
|
||||
if (newTo != null) {
|
||||
data.prepareSetBack(newTo);
|
||||
player.teleport(newTo, TeleportCause.PLUGIN);
|
||||
}
|
||||
}
|
||||
if (!rem.isEmpty()) {
|
||||
playersEnforce.removeAll(rem);
|
||||
}
|
||||
// Hover check (survivalfly).
|
||||
rem.clear();
|
||||
if (tick % hoverTicksStep != 0) {
|
||||
// Only check every so and so ticks.
|
||||
return;
|
||||
}
|
||||
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.
|
||||
if (parkedInfo.isEmpty()) {
|
||||
info = new MoveInfo(mcAccess);
|
||||
}
|
||||
else {
|
||||
info = parkedInfo.remove(parkedInfo.size() - 1);
|
||||
}
|
||||
for (final String playerName : hoverTicks) {
|
||||
// TODO: put players into the set (+- one tick would not matter ?)
|
||||
// TODO: might add an online flag to data !
|
||||
|
@ -1383,10 +1544,28 @@ 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);
|
||||
}
|
||||
|
||||
private Location enforceLocation(final Player player, final Location loc, final MovingData data) {
|
||||
if (data.toX != Double.MAX_VALUE && TrigUtil.distanceSquared(data.toX, data.toY, data.toZ, loc.getX(), loc.getY(), loc.getZ()) > 1.0 / 256.0) {
|
||||
// Teleport back.
|
||||
// TODO: Add history / alert?
|
||||
//player.sendMessage(ChatColor.RED + "NCP: enforce location !"); // TODO: DEBUG - REMOVE.
|
||||
if (data.hasSetBack()) {
|
||||
// Might have to re-check all context with playerJoins and keeping old set-backs...
|
||||
// Could use a flexible set-back policy (switch to in-air on login).
|
||||
return data.getSetBack(loc);
|
||||
} else {
|
||||
return new Location(player.getWorld(), data.toX, data.toY, data.toZ, loc.getYaw(), loc.getPitch());
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1399,8 +1578,9 @@ 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);
|
||||
// (Could use useLoc of MoveInfo here. Note orderm though.)
|
||||
final boolean res;
|
||||
// TODO: Collect flags, more margin ?
|
||||
final int loaded = info.from.ensureChunksLoaded();
|
||||
|
@ -1452,12 +1632,14 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
@Override
|
||||
public IData removeData(String playerName) {
|
||||
hoverTicks.remove(playerName);
|
||||
playersEnforce.remove(playerName);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllData() {
|
||||
hoverTicks.clear();
|
||||
playersEnforce.clear();
|
||||
parkedInfo.clear();
|
||||
}
|
||||
|
||||
|
@ -1469,6 +1651,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
|
|||
}
|
||||
parkedInfo.clear();
|
||||
hoverTicksStep = Math.max(1, ConfigManager.getConfigFile().getInt(ConfPaths.MOVING_SURVIVALFLY_HOVER_STEP));
|
||||
MovingData.onReload();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package fr.neatmonster.nocheatplus.checks.moving;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
|
@ -16,6 +17,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.
|
||||
|
@ -206,12 +210,21 @@ public class NoFall extends Check {
|
|||
public void onLeave(final Player player) {
|
||||
final MovingData data = MovingData.getData(player);
|
||||
final float fallDistance = player.getFallDistance();
|
||||
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 maxDist = Math.max(yDiff, Math.max(data.noFallFallDistance, fallDistance));
|
||||
player.setFallDistance(maxDist);
|
||||
if (data.noFallFallDistance - fallDistance > 0.0) {
|
||||
final double playerY = player.getLocation(useLoc).getY();
|
||||
useLoc.setWorld(null);
|
||||
if (player.getAllowFlight() || player.isFlying() || player.getGameMode() == GameMode.CREATIVE) {
|
||||
// Forestall potential issues with flying plugins.
|
||||
player.setFallDistance(0f);
|
||||
data.noFallFallDistance = 0f;
|
||||
data.noFallMaxY = playerY;
|
||||
} else {
|
||||
// Might use tolerance, might log, might use method (compare: MovingListener.onEntityDamage).
|
||||
// Might consider triggering violations here as well.
|
||||
final float yDiff = (float) (data.noFallMaxY - playerY);
|
||||
final float maxDist = Math.max(yDiff, Math.max(data.noFallFallDistance, fallDistance));
|
||||
player.setFallDistance(maxDist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ public class Passable extends Check {
|
|||
System.out.println(player.getName() + " Using set-back location for passable.");
|
||||
}
|
||||
} else if (cc.debug) {
|
||||
System.out.println(player.getName() + " Ignorng set-back for passable.");
|
||||
System.out.println(player.getName() + " Ignoring set-back for passable.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,7 +155,8 @@ public class Passable extends Check {
|
|||
// TODO: Consider another set back position for this, also keeping track of players moving around in blocks.
|
||||
final Location newTo;
|
||||
if (loc != null) {
|
||||
newTo = loc;
|
||||
// Ensure the given location is cloned.
|
||||
newTo = LocUtil.clone(loc);
|
||||
} else {
|
||||
newTo = from.getLocation();
|
||||
if (cc.debug) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.Set;
|
|||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
|
@ -65,6 +66,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.
|
||||
*/
|
||||
|
@ -148,8 +152,6 @@ public class SurvivalFly extends Check {
|
|||
// Mixed checks (lost ground).
|
||||
/////////////////////////////////
|
||||
|
||||
// data.stats.addStats(data.stats.getId("sfCheck", true), 1);
|
||||
|
||||
|
||||
// "Lost ground" workaround.
|
||||
if (fromOnGround || from.isResetCond()) {
|
||||
|
@ -161,7 +163,6 @@ public class SurvivalFly extends Check {
|
|||
// TODO: Consider if (!resetTo) ?
|
||||
// Check lost-ground workarounds.
|
||||
resetFrom = lostGround(player, from, to, hDistance, yDistance, sprinting, data, cc);
|
||||
// data.stats.addStats(data.stats.getId("sfLostGround", true), resetFrom ? 1 : 0);
|
||||
// Note: if not setting resetFrom, other places have to check assumeGround...
|
||||
}
|
||||
|
||||
|
@ -428,7 +429,7 @@ public class SurvivalFly extends Check {
|
|||
}
|
||||
|
||||
// Invalidation of vertical velocity.
|
||||
if (data.verticalVelocityUsed > cc.velocityGraceTicks && yDistance <= 0 && data.sfLastYDist > 0) {
|
||||
if (data.verticalVelocityUsed > cc.velocityGraceTicks && yDistance <= 0 && data.sfLastYDist > 0 && data.sfLastYDist != Double.MAX_VALUE) {
|
||||
// data.verticalFreedom = 0; // TODO: <- why?
|
||||
data.verticalVelocityCounter = 0;
|
||||
data.verticalVelocity = 0;
|
||||
|
@ -637,7 +638,7 @@ public class SurvivalFly extends Check {
|
|||
if (cc.survivalFlyAccountingV) {
|
||||
// Currently only for "air" phases.
|
||||
// Vertical.
|
||||
if (yDirChange && data.sfLastYDist > 0) {
|
||||
if (yDirChange && data.sfLastYDist > 0) { // (Double.MAX_VALUE is checked above.)
|
||||
// Change to descending phase.
|
||||
data.vDistAcc.clear();
|
||||
// Allow adding 0.
|
||||
|
@ -719,6 +720,7 @@ public class SurvivalFly extends Check {
|
|||
|
||||
/**
|
||||
* Check on change of y direction.
|
||||
* <br>Note: data.sfLastYDist must not be Double.MAX_VALUE when calling this.
|
||||
* @param yDistance
|
||||
* @param vDistanceAboveLimit
|
||||
* @return vDistanceAboveLimit
|
||||
|
@ -737,7 +739,9 @@ public class SurvivalFly extends Check {
|
|||
vDistanceAboveLimit = Math.max(vDistanceAboveLimit, Math.abs(yDistance));
|
||||
tags.add("ychincfly");
|
||||
}
|
||||
else tags.add("ychincair");
|
||||
else {
|
||||
tags.add("ychincair");
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
@ -869,7 +873,7 @@ public class SurvivalFly extends Check {
|
|||
allowHop = false; // Magic!
|
||||
|
||||
// 2x horizontal speed increase detection.
|
||||
if (hDistance - data.sfLastHDist >= walkSpeed * 0.5 && data.bunnyhopDelay == bunnyHopMax - 1) {
|
||||
if (data.sfLastHDist != Double.MAX_VALUE && hDistance - data.sfLastHDist >= walkSpeed * 0.5 && data.bunnyhopDelay == bunnyHopMax - 1) {
|
||||
if (data.sfLastYDist == 0.0 && (data.fromWasReset || data.toWasReset) && yDistance >= 0.4) {
|
||||
// TODO: Confine to last was hop (according to so far input on this topic).
|
||||
tags.add(DOUBLE_BUNNY);
|
||||
|
@ -960,7 +964,7 @@ public class SurvivalFly extends Check {
|
|||
// Check workarounds.
|
||||
if (yDistance <= 0.5) {
|
||||
// TODO: mediumLiftOff: refine conditions (general) , to should be near water level.
|
||||
if (data.mediumLiftOff == MediumLiftOff.GROUND && !BlockProperties.isLiquid(from.getTypeIdAbove()) || !to.isInLiquid() || (toOnGround || data.sfLastYDist - yDistance >= 0.010 || to.isAboveStairs())) {
|
||||
if (data.mediumLiftOff == MediumLiftOff.GROUND && !BlockProperties.isLiquid(from.getTypeIdAbove()) || !to.isInLiquid() || (toOnGround || data.sfLastYDist != Double.MAX_VALUE && data.sfLastYDist - yDistance >= 0.010 || to.isAboveStairs())) {
|
||||
vAllowedDistance = walkSpeed * modSwim + 0.5;
|
||||
vDistanceAboveLimit = yDistance - vAllowedDistance;
|
||||
}
|
||||
|
@ -1084,10 +1088,9 @@ public class SurvivalFly extends Check {
|
|||
|
||||
// Half block step up.
|
||||
if (yDistance <= 0.5 && hDistance < 0.5 && setBackYDistance <= 1.3 + 0.2 * data.jumpAmplifier && to.isOnGround()) {
|
||||
if (data.sfLastYDist < 0 || from.isOnGround(0.5 - Math.abs(yDistance))) {
|
||||
if (data.sfLastYDist < 0.0 || from.isOnGround(0.5 - Math.abs(yDistance))) {
|
||||
return applyLostGround(player, from, true, data, "step");
|
||||
}
|
||||
// else data.stats.addStats(data.stats.getId("sfLostGround_" + "step", true), 0);
|
||||
}
|
||||
|
||||
// Interpolation check.
|
||||
|
@ -1096,9 +1099,9 @@ public class SurvivalFly extends Check {
|
|||
// TODO: Check use of jump-amplifier.
|
||||
// TODO: Might check fall distance.
|
||||
// && data.sfJumpPhase > 3 <- Seems to be a problem with cake on a block + jump over both mini edges (...).
|
||||
if (data.fromX != Double.MAX_VALUE && yDistance > 0 && data.sfLastYDist < 0 && !to.isOnGround()) {
|
||||
if (data.fromX != Double.MAX_VALUE && yDistance > 0 && data.sfLastYDist < 0.0 && !to.isOnGround()) {
|
||||
// TODO: Check if last-y-dist or sprinting should be considered.
|
||||
if (setBackYDistance > 0D && setBackYDistance <= 1.5D + 0.2 * data.jumpAmplifier || setBackYDistance < 0 && Math.abs(setBackYDistance) < 3.0) {
|
||||
if (setBackYDistance > 0.0 && setBackYDistance <= 1.5D + 0.2 * data.jumpAmplifier || setBackYDistance < 0.0 && Math.abs(setBackYDistance) < 3.0) {
|
||||
// Interpolate from last to-coordinates to the from
|
||||
// coordinates (with some safe-guard).
|
||||
final double dX = from.getX() - data.fromX;
|
||||
|
@ -1116,7 +1119,6 @@ public class SurvivalFly extends Check {
|
|||
if (BlockProperties.isOnGround(from.getBlockCache(), Math.min(data.fromX, from.getX()) - r, iY - yMargin, Math.min(data.fromZ, from.getZ()) - r, Math.max(data.fromX, from.getX()) + r, iY + 0.25, Math.max(data.fromZ, from.getZ()) + r, 0L)) {
|
||||
return applyLostGround(player, from, true, data, "interpolate");
|
||||
}
|
||||
// else data.stats.addStats(data.stats.getId("sfLostGround_" + "interpolate", true), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1151,26 +1153,24 @@ public class SurvivalFly extends Check {
|
|||
// TODO: <= 7 might work with speed II, not sure with above.
|
||||
// TODO: account for speed/sprint
|
||||
// TODO: account for half steps !?
|
||||
if (from.isOnGround(0.6, 0.4, 0, 0L) ) {
|
||||
if (from.isOnGround(0.6, 0.4, 0.0, 0L) ) {
|
||||
// TODO: further narrow down bounds ?
|
||||
// Temporary "fix".
|
||||
return applyLostGround(player, from, true, data, "pyramid");
|
||||
}
|
||||
// else data.stats.addStats(data.stats.getId("sfLostGround_" + "pyramid", true), 0);
|
||||
}
|
||||
|
||||
// Check for jumping up strange blocks like flower pots on top of other blocks.
|
||||
if (yDistance == 0 && data.sfLastYDist > 0 && data.sfLastYDist < 0.25 && data.sfJumpPhase <= 6 + data.jumpAmplifier * 3 && setBackYDistance > 1.0 && setBackYDistance < 1.5 + 0.2 * data.jumpAmplifier && !to.isOnGround()) {
|
||||
if (yDistance == 0.0 && data.sfLastYDist > 0.0 && data.sfLastYDist < 0.25 && data.sfJumpPhase <= 6 + data.jumpAmplifier * 3.0 && setBackYDistance > 1.0 && setBackYDistance < 1.5 + 0.2 * data.jumpAmplifier && !to.isOnGround()) {
|
||||
// TODO: confine by block types ?
|
||||
if (from.isOnGround(0.25, 0.4, 0, 0L) ) {
|
||||
// Temporary "fix".
|
||||
return applyLostGround(player, from, true, data, "ministep");
|
||||
}
|
||||
// else data.stats.addStats(data.stats.getId("sfLostGround_" + "ministep", true), 0);
|
||||
}
|
||||
}
|
||||
// Lost ground while falling onto/over edges of blocks.
|
||||
if (yDistance < 0 && hDistance <= 0.5 && data.sfLastYDist < 0 && yDistance > data.sfLastYDist && !to.isOnGround()) {
|
||||
if (yDistance < 0 && hDistance <= 0.5 && data.sfLastYDist < 0.0 && yDistance > data.sfLastYDist && !to.isOnGround()) {
|
||||
// TODO: Should this be an extra lost-ground(to) check, setting toOnGround [for no-fall no difference]?
|
||||
// TODO: yDistance <= 0 might be better.
|
||||
// Also clear accounting data.
|
||||
|
@ -1178,7 +1178,6 @@ public class SurvivalFly extends Check {
|
|||
if (from.isOnGround(0.5, 0.2, 0) || to.isOnGround(0.5, Math.min(0.2, 0.01 + hDistance), Math.min(0.1, 0.01 + -yDistance))) {
|
||||
return applyLostGround(player, from, true, data, "edge");
|
||||
}
|
||||
// else data.stats.addStats(data.stats.getId("sfLostGround_" + "edge", true), 0);
|
||||
}
|
||||
|
||||
// Nothing found.
|
||||
|
@ -1213,7 +1212,6 @@ public class SurvivalFly extends Check {
|
|||
// (Usually yDistance should be -0.078)
|
||||
return applyLostGround(player, from, true, data, "fastedge");
|
||||
}
|
||||
// else data.stats.addStats(data.stats.getId("sfLostGround_" + "fastedge", true), 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1246,7 +1244,6 @@ public class SurvivalFly extends Check {
|
|||
// Tell NoFall that we assume the player to have been on ground somehow.
|
||||
data.noFallAssumeGround = true;
|
||||
tags.add("lostground_" + tag);
|
||||
// data.stats.addStats(data.stats.getId("sfLostGround_" + tag, true), 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1310,7 +1307,7 @@ public class SurvivalFly extends Check {
|
|||
if (data.hasSetBack()) {
|
||||
final Location newTo = data.getSetBack(loc);
|
||||
data.prepareSetBack(newTo);
|
||||
player.teleport(newTo);
|
||||
player.teleport(newTo, TeleportCause.PLUGIN);
|
||||
}
|
||||
else{
|
||||
// Solve by extra actions ? Special case (probably never happens)?
|
||||
|
@ -1344,7 +1341,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;
|
||||
|
|
|
@ -30,7 +30,7 @@ public class VehicleSetBack implements Runnable{
|
|||
final MovingData data = MovingData.getData(player);
|
||||
data.morePacketsVehicleTaskId = -1;
|
||||
try{
|
||||
data.setTeleported(location);
|
||||
data.prepareSetBack(location);
|
||||
TeleportUtil.teleport(vehicle, player, location, debug);
|
||||
}
|
||||
catch(Throwable t){
|
||||
|
|
|
@ -24,57 +24,63 @@ public class CommandUtil {
|
|||
* Return plugin + server commands [Subject to change].
|
||||
* @return Returns null if not CraftBukkit or CommandMap not available.
|
||||
*/
|
||||
public static CommandMap getCommandMap(){
|
||||
// TODO: compat / null
|
||||
try{
|
||||
public static CommandMap getCommandMap() {
|
||||
try {
|
||||
return NCPAPIProvider.getNoCheatPlusAPI().getMCAccess().getCommandMap();
|
||||
}
|
||||
catch(Throwable t){
|
||||
catch (Throwable t) {
|
||||
LogUtil.logSevere(t);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fails with an exception if SimpleCommandMap is not found, currently.
|
||||
* Get all Command instances, that NCP can get hold of. Attempt to get a SimpleCommandMap instance from the server to get the actually registered commands, but also get commands from JavaPlugin instances.
|
||||
* @return
|
||||
*/
|
||||
public static Collection<Command> getCommands(){
|
||||
CommandMap commandMap = getCommandMap();
|
||||
if (commandMap != null && commandMap instanceof SimpleCommandMap){
|
||||
return ((SimpleCommandMap) commandMap).getCommands();
|
||||
public static Collection<Command> getCommands() {
|
||||
final Collection<Command> commands = new LinkedHashSet<Command>(500);
|
||||
|
||||
// All (?) commands from the SimpleCommandMap of the server, if available.
|
||||
final CommandMap commandMap = getCommandMap();
|
||||
if (commandMap != null && commandMap instanceof SimpleCommandMap) {
|
||||
commands.addAll(((SimpleCommandMap) commandMap).getCommands());
|
||||
}
|
||||
else{
|
||||
final Collection<Command> commands = new LinkedHashSet<Command>(100);
|
||||
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()){
|
||||
if (plugin instanceof JavaPlugin){
|
||||
final JavaPlugin javaPlugin = (JavaPlugin) plugin;
|
||||
final Map<String, Map<String, Object>> map = javaPlugin.getDescription().getCommands();
|
||||
if (map != null){
|
||||
for (String label : map.keySet()){
|
||||
Command command = javaPlugin.getCommand(label);
|
||||
if (command != null) commands.add(command);
|
||||
// TODO: Fall-back for Vanilla / CB commands? [Fall-back should be altering permission defaults, though negating permissions is the right way.]
|
||||
|
||||
// Fall-back: plugin commands.
|
||||
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
|
||||
if (plugin instanceof JavaPlugin) {
|
||||
final JavaPlugin javaPlugin = (JavaPlugin) plugin;
|
||||
final Map<String, Map<String, Object>> map = javaPlugin.getDescription().getCommands();
|
||||
if (map != null) {
|
||||
for (String label : map.keySet()) {
|
||||
Command command = javaPlugin.getCommand(label);
|
||||
if (command != null) {
|
||||
commands.add(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Vanilla / CB commands !?
|
||||
return commands;
|
||||
}
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the command label (trim + lower case), include server commands [subject to change].
|
||||
* @param alias
|
||||
* @param strict If to return null if no command is found.
|
||||
* @return
|
||||
* @return The command label, if possible to find, or the alias itself (+ trim + lower-case).
|
||||
*/
|
||||
public static String getCommandLabel(final String alias, final boolean strict){
|
||||
public static String getCommandLabel(final String alias, final boolean strict) {
|
||||
final Command command = getCommand(alias);
|
||||
if (command == null){
|
||||
if (command == null) {
|
||||
return strict ? null : alias.trim().toLowerCase();
|
||||
}
|
||||
else return command.getLabel().trim().toLowerCase();
|
||||
else {
|
||||
return command.getLabel().trim().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,7 +91,7 @@ public class CommandUtil {
|
|||
public static Command getCommand(final String alias) {
|
||||
final String lcAlias = alias.trim().toLowerCase();
|
||||
final CommandMap map = getCommandMap();
|
||||
if (map != null){
|
||||
if (map != null) {
|
||||
return map.getCommand(lcAlias);
|
||||
} else {
|
||||
// TODO: maybe match versus plugin commands.
|
||||
|
@ -101,18 +107,22 @@ public class CommandUtil {
|
|||
public static List<String> getCheckTypeTabMatches(final String input) {
|
||||
final String ref = input.toUpperCase().replace('-', '_').replace('.', '_');
|
||||
final List<String> res = new ArrayList<String>();
|
||||
for (final CheckType checkType : CheckType.values()){
|
||||
for (final CheckType checkType : CheckType.values()) {
|
||||
final String name = checkType.name();
|
||||
if (name.startsWith(ref)) res.add(name);
|
||||
}
|
||||
if (ref.indexOf('_') == -1){
|
||||
for (final CheckType checkType : CheckType.values()){
|
||||
final String name = checkType.name();
|
||||
final String[] split = name.split("_", 2);
|
||||
if (split.length > 1 && split[1].startsWith(ref)) res.add(name);
|
||||
if (name.startsWith(ref)) {
|
||||
res.add(name);
|
||||
}
|
||||
}
|
||||
if (!res.isEmpty()){
|
||||
if (ref.indexOf('_') == -1) {
|
||||
for (final CheckType checkType : CheckType.values()) {
|
||||
final String name = checkType.name();
|
||||
final String[] split = name.split("_", 2);
|
||||
if (split.length > 1 && split[1].startsWith(ref)) {
|
||||
res.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!res.isEmpty()) {
|
||||
Collections.sort(res);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import fr.neatmonster.nocheatplus.command.admin.CommandsCommand;
|
|||
import fr.neatmonster.nocheatplus.command.admin.InfoCommand;
|
||||
import fr.neatmonster.nocheatplus.command.admin.InspectCommand;
|
||||
import fr.neatmonster.nocheatplus.command.admin.LagCommand;
|
||||
import fr.neatmonster.nocheatplus.command.admin.NCPVersionCommand;
|
||||
import fr.neatmonster.nocheatplus.command.admin.VersionCommand;
|
||||
import fr.neatmonster.nocheatplus.command.admin.ReloadCommand;
|
||||
import fr.neatmonster.nocheatplus.command.admin.RemovePlayerCommand;
|
||||
import fr.neatmonster.nocheatplus.command.admin.exemption.ExemptCommand;
|
||||
|
@ -89,7 +89,7 @@ public class NoCheatPlusCommand extends BaseCommand{
|
|||
new KickCommand(plugin),
|
||||
new KickListCommand(plugin),
|
||||
new LagCommand(plugin),
|
||||
new NCPVersionCommand(plugin),
|
||||
new VersionCommand(plugin),
|
||||
new NotifyCommand(plugin),
|
||||
new ReloadCommand(plugin, notifyReload),
|
||||
new RemovePlayerCommand(plugin),
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package fr.neatmonster.nocheatplus.command.actions;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -14,6 +15,7 @@ import fr.neatmonster.nocheatplus.command.BaseCommand;
|
|||
import fr.neatmonster.nocheatplus.logging.LogUtil;
|
||||
import fr.neatmonster.nocheatplus.permissions.Permissions;
|
||||
import fr.neatmonster.nocheatplus.players.DataManager;
|
||||
import fr.neatmonster.nocheatplus.utilities.IdUtil;
|
||||
|
||||
public class BanCommand extends BaseCommand {
|
||||
|
||||
|
@ -23,32 +25,62 @@ public class BanCommand extends BaseCommand {
|
|||
|
||||
@Override
|
||||
public boolean onCommand(final CommandSender sender, Command command, String label, String[] args) {
|
||||
|
||||
// TODO: Consider supporting vanilla syntax or removing this command :p.
|
||||
|
||||
// Args contains "ban" as first arg.
|
||||
if (args.length < 2) return false;
|
||||
final String name = args[1];
|
||||
if (args.length < 2) {
|
||||
return false;
|
||||
}
|
||||
final String name = args[1].trim();
|
||||
final String reason;
|
||||
if (args.length > 2) reason = AbstractCommand.join(args, 2);
|
||||
else reason = "";
|
||||
if (args.length > 2) {
|
||||
reason = AbstractCommand.join(args, 2);
|
||||
}
|
||||
else {
|
||||
reason = "";
|
||||
}
|
||||
ban(sender, name, reason);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sender
|
||||
* @param name Trimmed name.
|
||||
* @param reason
|
||||
*/
|
||||
void ban(CommandSender sender, String name, String reason) {
|
||||
final Server server = Bukkit.getServer();
|
||||
Player player = DataManager.getPlayer(name);
|
||||
// Pro logic below.
|
||||
if (player == null && !IdUtil.isValidMinecraftUserName(name)) {
|
||||
UUID id = IdUtil.UUIDFromStringSafe(name);
|
||||
if (id != null) {
|
||||
LogUtil.logWarning("Banning by UUID might not work (" + id.toString()+"), relay to the vanilla command.");
|
||||
} else {
|
||||
LogUtil.logWarning("Might not be a valid user name: " + name);
|
||||
}
|
||||
}
|
||||
if (player != null){
|
||||
player.kickPlayer(reason);
|
||||
}
|
||||
OfflinePlayer offlinePlayer = Bukkit.getServer().getOfflinePlayer(name);
|
||||
offlinePlayer.setBanned(true);
|
||||
LogUtil.logInfo("[NoCheatPlus] (" + sender.getName() + ") Banned " + offlinePlayer.getName() + " : " + reason);
|
||||
// Relay to the server command for compatibility reasons.
|
||||
server.dispatchCommand(server.getConsoleSender(), "ban " + name);
|
||||
logBan(sender, player, name, reason);
|
||||
|
||||
}
|
||||
|
||||
private void logBan(CommandSender sender, Player player, String name, String reason) {
|
||||
LogUtil.logInfo("[NoCheatPlus] (" + sender.getName() + ") Banned " + name + (player != null ? ("/" + player.getName()) : "") + " : " + reason);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see fr.neatmonster.nocheatplus.command.AbstractCommand#onTabComplete(org.bukkit.command.CommandSender, org.bukkit.command.Command, java.lang.String, java.lang.String[])
|
||||
*/
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command,
|
||||
String alias, String[] args) {
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
// TODO: Consider adding player names and other.
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.bukkit.plugin.java.JavaPlugin;
|
|||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import fr.neatmonster.nocheatplus.command.BaseCommand;
|
||||
import fr.neatmonster.nocheatplus.compat.BridgeHealth;
|
||||
import fr.neatmonster.nocheatplus.permissions.Permissions;
|
||||
import fr.neatmonster.nocheatplus.players.DataManager;
|
||||
|
||||
|
@ -53,7 +54,7 @@ public class InspectCommand extends BaseCommand {
|
|||
builder.append(" (" + (player.isOnline() ? "online" : "offline") + (player.isDead() ? ",dead" : "") + (player.isValid() ? "" : ",invalid") + (player.isInsideVehicle() ? (",vehicle=" + player.getVehicle().getType() + "@" + locString(player.getVehicle().getLocation())) : "")+ "):");
|
||||
// TODO: isValid, isDead, isInsideVehicle ...
|
||||
// Health.
|
||||
builder.append(" health=" + f1.format(player.getHealth()) + "/" + f1.format(player.getMaxHealth()));
|
||||
builder.append(" health=" + f1.format(BridgeHealth.getHealth(player)) + "/" + f1.format(BridgeHealth.getMaxHealth(player)));
|
||||
// Food.
|
||||
builder.append(" food=" + player.getFoodLevel());
|
||||
// Exp.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user