From f0c55528733e5e1ed76171f7328f5595a56ae3e2 Mon Sep 17 00:00:00 2001 From: asofold Date: Sun, 4 Jan 2015 20:04:20 +0100 Subject: [PATCH] [SAFETY COMMIT] Redo with proper assignment (details see below). Contained changes: - Melon and pumpkin block break timings: 1.8-specific, keep workaround. - Don't run all horizontal move checking if no move. - Utility method for checking for air. - Some formatting. --- .../compat/bukkit/MCAccessBukkit.java | 172 +++++++------- .../checks/blockbreak/BlockBreakData.java | 5 +- .../checks/blockplace/Against.java | 68 +++--- .../checks/blockplace/BlockPlaceListener.java | 2 +- .../checks/fight/FightListener.java | 21 +- .../checks/inventory/FastClick.java | 188 ++++++++-------- .../checks/moving/MovingListener.java | 23 +- .../checks/moving/SurvivalFly.java | 109 +++++---- .../nocheatplus/compat/BridgeEnchant.java | 7 +- .../blocks/init/vanilla/BlocksMC1_8.java | 210 ++++++++++-------- .../utilities/BlockProperties.java | 68 ++++-- .../nocheatplus/utilities/FakeBlockCache.java | 16 +- .../nocheatplus/utilities/InventoryUtil.java | 29 +-- 13 files changed, 484 insertions(+), 434 deletions(-) diff --git a/NCPCompatBukkit/src/main/java/fr/neatmonster/nocheatplus/compat/bukkit/MCAccessBukkit.java b/NCPCompatBukkit/src/main/java/fr/neatmonster/nocheatplus/compat/bukkit/MCAccessBukkit.java index dbee9555..0ed5ac86 100644 --- a/NCPCompatBukkit/src/main/java/fr/neatmonster/nocheatplus/compat/bukkit/MCAccessBukkit.java +++ b/NCPCompatBukkit/src/main/java/fr/neatmonster/nocheatplus/compat/bukkit/MCAccessBukkit.java @@ -101,74 +101,74 @@ public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{ // Values taken from 1.7.10. final EntityType type = entity.getType(); switch(type){ - // TODO: case COMPLEX_PART: - case ENDER_SIGNAL: // this.a(0.25F, 0.25F); - case FIREWORK: // this.a(0.25F, 0.25F); - case FISHING_HOOK: // this.a(0.25F, 0.25F); - case DROPPED_ITEM: // this.a(0.25F, 0.25F); - case SNOWBALL: // (projectile) this.a(0.25F, 0.25F); - return 0.25; - case CHICKEN: // this.a(0.3F, 0.7F); - case SILVERFISH: // this.a(0.3F, 0.7F); - return 0.3f; - case SMALL_FIREBALL: // this.a(0.3125F, 0.3125F); - case WITHER_SKULL: // this.a(0.3125F, 0.3125F); - return 0.3125f; - case GHAST: // this.a(4.0F, 4.0F); - case SNOWMAN: // this.a(0.4F, 1.8F); - return 0.4f; - case ARROW: // this.a(0.5F, 0.5F); - case BAT: // this.a(0.5F, 0.9F); - case EXPERIENCE_ORB: // this.a(0.5F, 0.5F); - case ITEM_FRAME: // hanging: this.a(0.5F, 0.5F); - case PAINTING: // hanging: this.a(0.5F, 0.5F); - return 0.5f; - case PLAYER: // FAST RETURN - case ZOMBIE: - case PIG_ZOMBIE: - case SKELETON: - case CREEPER: - case ENDERMAN: - case OCELOT: - case BLAZE: - case VILLAGER: - case WITCH: - case WOLF: - return 0.6f; // (Default entity width.) - case CAVE_SPIDER: // this.a(0.7F, 0.5F); - return 0.7f; - case COW: // this.a(0.9F, 1.3F); - case MUSHROOM_COW: // this.a(0.9F, 1.3F); - case PIG: // this.a(0.9F, 0.9F); - case SHEEP: // this.a(0.9F, 1.3F); - case WITHER: // this.a(0.9F, 4.0F); - return 0.9f; - case SQUID: // this.a(0.95F, 0.95F); - return 0.95f; - case PRIMED_TNT: // this.a(0.98F, 0.98F); - return 0.98f; - case FIREBALL: // (EntityFireball) this.a(1.0F, 1.0F); - return 1.0f; - case IRON_GOLEM: // this.a(1.4F, 2.9F); - case SPIDER: // this.a(1.4F, 0.9F); - return 1.4f; - case BOAT: // this.a(1.5F, 0.6F); - return 1.5f; - case ENDER_CRYSTAL: // this.a(2.0F, 2.0F); - return 2.0f; - case GIANT: // this.height *= 6.0F; this.a(this.width * 6.0F, this.length * 6.0F); - return 3.6f; // (Better than nothing.) - case ENDER_DRAGON: // this.a(16.0F, 8.0F); - return 16.0f; - // Variable size: - case SLIME: - case MAGMA_CUBE: - if (entity instanceof Slime) { - // setSize(i): this.a(0.6F * (float) i, 0.6F * (float) i); - return 0.6f * ((Slime) entity).getSize(); - } - default: - break; + // TODO: case COMPLEX_PART: + case ENDER_SIGNAL: // this.a(0.25F, 0.25F); + case FIREWORK: // this.a(0.25F, 0.25F); + case FISHING_HOOK: // this.a(0.25F, 0.25F); + case DROPPED_ITEM: // this.a(0.25F, 0.25F); + case SNOWBALL: // (projectile) this.a(0.25F, 0.25F); + return 0.25; + case CHICKEN: // this.a(0.3F, 0.7F); + case SILVERFISH: // this.a(0.3F, 0.7F); + return 0.3f; + case SMALL_FIREBALL: // this.a(0.3125F, 0.3125F); + case WITHER_SKULL: // this.a(0.3125F, 0.3125F); + return 0.3125f; + case GHAST: // this.a(4.0F, 4.0F); + case SNOWMAN: // this.a(0.4F, 1.8F); + return 0.4f; + case ARROW: // this.a(0.5F, 0.5F); + case BAT: // this.a(0.5F, 0.9F); + case EXPERIENCE_ORB: // this.a(0.5F, 0.5F); + case ITEM_FRAME: // hanging: this.a(0.5F, 0.5F); + case PAINTING: // hanging: this.a(0.5F, 0.5F); + return 0.5f; + case PLAYER: // FAST RETURN + case ZOMBIE: + case PIG_ZOMBIE: + case SKELETON: + case CREEPER: + case ENDERMAN: + case OCELOT: + case BLAZE: + case VILLAGER: + case WITCH: + case WOLF: + return 0.6f; // (Default entity width.) + case CAVE_SPIDER: // this.a(0.7F, 0.5F); + return 0.7f; + case COW: // this.a(0.9F, 1.3F); + case MUSHROOM_COW: // this.a(0.9F, 1.3F); + case PIG: // this.a(0.9F, 0.9F); + case SHEEP: // this.a(0.9F, 1.3F); + case WITHER: // this.a(0.9F, 4.0F); + return 0.9f; + case SQUID: // this.a(0.95F, 0.95F); + return 0.95f; + case PRIMED_TNT: // this.a(0.98F, 0.98F); + return 0.98f; + case FIREBALL: // (EntityFireball) this.a(1.0F, 1.0F); + return 1.0f; + case IRON_GOLEM: // this.a(1.4F, 2.9F); + case SPIDER: // this.a(1.4F, 0.9F); + return 1.4f; + case BOAT: // this.a(1.5F, 0.6F); + return 1.5f; + case ENDER_CRYSTAL: // this.a(2.0F, 2.0F); + return 2.0f; + case GIANT: // this.height *= 6.0F; this.a(this.width * 6.0F, this.length * 6.0F); + return 3.6f; // (Better than nothing.) + case ENDER_DRAGON: // this.a(16.0F, 8.0F); + return 16.0f; + // Variable size: + case SLIME: + case MAGMA_CUBE: + if (entity instanceof Slime) { + // setSize(i): this.a(0.6F * (float) i, 0.6F * (float) i); + return 0.6f * ((Slime) entity).getSize(); + } + default: + break; } // Check by instance for minecarts (too many). if (entity instanceof Minecart) { @@ -177,12 +177,12 @@ public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{ // Latest Bukkit API. try { switch (type) { - case LEASH_HITCH: // hanging: this.a(0.5F, 0.5F); - return 0.5; - case HORSE: // this.a(1.4F, 1.6F); - return 1.4f; - default: - break; + case LEASH_HITCH: // hanging: this.a(0.5F, 0.5F); + return 0.5; + case HORSE: // this.a(1.4F, 1.6F); + return 1.4f; + default: + break; } } catch (Throwable t) {} // Default entity width. @@ -196,13 +196,13 @@ public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{ final Material mat = Material.getMaterial(id); if (mat == null) return AlmostBoolean.MAYBE; switch (mat) { - case STATIONARY_LAVA: - case STATIONARY_WATER: - case WATER: - case LAVA: - return AlmostBoolean.YES; - default: - return AlmostBoolean.NO; + case STATIONARY_LAVA: + case STATIONARY_WATER: + case WATER: + case LAVA: + return AlmostBoolean.YES; + default: + return AlmostBoolean.NO; } } @@ -315,11 +315,11 @@ public class MCAccessBukkit implements MCAccess, BlockPropertiesSetup{ catch(Throwable t) { // Backwards compatibility. switch(mat) { - case SAND: - case GRAVEL: - return true; - default: - return false; + case SAND: + case GRAVEL: + return true; + default: + return false; } } } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakData.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakData.java index 2a292a58..da93d4ae 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakData.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakData.java @@ -13,6 +13,7 @@ import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory; import fr.neatmonster.nocheatplus.checks.access.ICheckData; import fr.neatmonster.nocheatplus.stats.Timings; import fr.neatmonster.nocheatplus.utilities.ActionFrequency; +import fr.neatmonster.nocheatplus.utilities.BlockProperties; /** * Player specific data for the block break checks. @@ -156,8 +157,8 @@ public class BlockBreakData extends ACheckData { } public boolean toolChanged(Material mat) { - if (mat == Material.AIR) { - return clickedTool != null; + if (BlockProperties.isAir(mat)) { + return !BlockProperties.isAir(clickedTool); } else { return clickedTool != mat; } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockplace/Against.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockplace/Against.java index a227f28d..60b5fb7d 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockplace/Against.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockplace/Against.java @@ -20,46 +20,46 @@ import fr.neatmonster.nocheatplus.utilities.TrigUtil; * */ public class Against extends Check { - - public Against() { - super(CheckType.BLOCKPLACE_AGAINST); - } - - public boolean check(final Player player, final Block block, final Material placedMat, final Block blockAgainst, final BlockPlaceData data, final BlockPlaceConfig cc) { - boolean violation = false; - // TODO: Make more precise (workarounds like WATER_LILY, general points). - // Workaround for signs on cactus and similar. + + public Against() { + super(CheckType.BLOCKPLACE_AGAINST); + } + + public boolean check(final Player player, final Block block, final Material placedMat, final Block blockAgainst, final BlockPlaceData data, final BlockPlaceConfig cc) { + boolean violation = false; + // TODO: Make more precise (workarounds like WATER_LILY, general points). + // Workaround for signs on cactus and similar. 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) { - // (Wide screen.) - // Block was placed against something (e.g. cactus), allow it. - // TODO: Later reset can conflict, though it makes sense to reset with placing blocks in general. - bdata.resetLastBlock(); - return false; - } + if (BlockProperties.isAir(againstType)) { + // 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) { + // (Wide screen.) + // Block was placed against something (e.g. cactus), allow it. + // TODO: Later reset can conflict, though it makes sense to reset with placing blocks in general. + bdata.resetLastBlock(); + return false; + } } if (BlockProperties.isLiquid(againstType)) { if ((placedMat != Material.WATER_LILY || !BlockProperties.isLiquid(block.getRelative(BlockFace.DOWN).getType())) && !player.hasPermission(Permissions.BLOCKPLACE_AGAINST_LIQUIDS)) { - violation = true; + violation = true; } } - else if (againstType == Material.AIR && !player.hasPermission(Permissions.BLOCKPLACE_AGAINST_AIR)) { - violation = true; + else if (BlockProperties.isAir(againstType) && !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_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. - return false; - } - } - + if (violation) { + data.againstVL += 1.0; + final ViolationData vd = new ViolationData(this, player, data.againstVL, 1, cc.againstActions); + 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. + return false; + } + } + } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceListener.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceListener.java index d5372864..227fed4b 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceListener.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceListener.java @@ -313,7 +313,7 @@ public class BlockPlaceListener extends CheckListener { else{ final Material mat = player.getLocation(useLoc).getBlock().getType(); final long flags = BlockProperties.F_CLIMBABLE | BlockProperties.F_LIQUID | BlockProperties.F_IGN_PASSABLE; - if (mat != null && mat != Material.AIR && (BlockProperties.getBlockFlags(mat) & flags) == 0 && !mcAccess.hasGravity(mat)){ + if (!BlockProperties.isAir(mat) && (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; diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/fight/FightListener.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/fight/FightListener.java index 87023303..b84ad838 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/fight/FightListener.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/fight/FightListener.java @@ -3,7 +3,6 @@ package fr.neatmonster.nocheatplus.checks.fight; import java.util.Iterator; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; @@ -522,15 +521,15 @@ public class FightListener extends CheckListener implements JoinLeaveListener{ } // Knockback calculation. switch (event.getCause()) { - case ENTITY_ATTACK: - if (event instanceof EntityDamageByEntityEvent) { - final Entity entity = ((EntityDamageByEntityEvent) event).getDamager(); - if ((entity instanceof Player) && !entity.isInsideVehicle() && FightConfig.getConfig(damagedPlayer).knockBackVelocityPvP) { - applyKnockBack((Player) entity, damagedPlayer, damagedData); + case ENTITY_ATTACK: + if (event instanceof EntityDamageByEntityEvent) { + final Entity entity = ((EntityDamageByEntityEvent) event).getDamager(); + if ((entity instanceof Player) && !entity.isInsideVehicle() && FightConfig.getConfig(damagedPlayer).knockBackVelocityPvP) { + applyKnockBack((Player) entity, damagedPlayer, damagedData); + } } - } - default: - break; + default: + break; } } } @@ -547,7 +546,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{ level += 1.0; } final ItemStack stack = attacker.getItemInHand(); - if (stack != null && stack.getType() != Material.AIR) { + if (!BlockProperties.isAir(stack)) { level += (double) stack.getEnchantmentLevel(Enchantment.KNOCKBACK); } final MovingData mdata = MovingData.getData(damagedPlayer); @@ -560,6 +559,8 @@ public class FightListener extends CheckListener implements JoinLeaveListener{ double vy = dir.getY(); if (BlockProperties.isOnGround(damagedPlayer, damagedPlayer.getLocation(useLoc1), mcc.yOnGround)) { // (Re-used useLoc1 without need for cleanup.) + // TODO: What here ? + // vy = Math.max(vy, 0.365); vy = 0.365; } useLoc1.setWorld(null); // Cleanup. diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/FastClick.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/FastClick.java index 87e5e3c8..6b1ea1e6 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/FastClick.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/inventory/FastClick.java @@ -24,117 +24,117 @@ public class FastClick extends Check { super(CheckType.INVENTORY_FASTCLICK); } -// /** -// * Checks a player. -// * -// * @param player -// * the player -// * @param cc -// * @return true, if successful -// */ -// public boolean check(final Player player) { -// // Take time once. -// final long time = System.currentTimeMillis(); -// -// final InventoryData data = InventoryData.getData(player); -// -// boolean cancel = false; -// -// // If the last inventory click has been made within 45 milliseconds. -// if (time - data.fastClickLastTime < 45L) { -// if (data.fastClickLastCancelled) { -// -// // Calculate the difference between the limit and the time elapsed. -// final double difference = 45L - time + data.fastClickLastTime; -// final InventoryConfig cc = InventoryConfig.getConfig(player); -// final ViolationData vd = new ViolationData(this, player, data.fastClickVL + difference, difference, cc.fastClickActions); -// if (TickTask.getLag(150, true) > 1.7f){ -// // Don't increase vl here. -// cancel = vd.hasCancel(); -// } -// else{ -// // Increment the violation level. -// data.fastClickVL += difference; -// -// // Find out if we need to cancel the event. -// cancel = executeActions(vd); -// } -// } else -// data.fastClickLastCancelled = true; -// } else { -// data.fastClickLastCancelled = false; -// -// // Reduce the violation level. -// data.fastClickVL *= 0.98D; -// } -// -// // Remember the current time.s -// data.fastClickLastTime = time; -// -// return cancel; -// } - + // /** + // * Checks a player. + // * + // * @param player + // * the player + // * @param cc + // * @return true, if successful + // */ + // public boolean check(final Player player) { + // // Take time once. + // final long time = System.currentTimeMillis(); + // + // final InventoryData data = InventoryData.getData(player); + // + // boolean cancel = false; + // + // // If the last inventory click has been made within 45 milliseconds. + // if (time - data.fastClickLastTime < 45L) { + // if (data.fastClickLastCancelled) { + // + // // Calculate the difference between the limit and the time elapsed. + // final double difference = 45L - time + data.fastClickLastTime; + // final InventoryConfig cc = InventoryConfig.getConfig(player); + // final ViolationData vd = new ViolationData(this, player, data.fastClickVL + difference, difference, cc.fastClickActions); + // if (TickTask.getLag(150, true) > 1.7f){ + // // Don't increase vl here. + // cancel = vd.hasCancel(); + // } + // else{ + // // Increment the violation level. + // data.fastClickVL += difference; + // + // // Find out if we need to cancel the event. + // cancel = executeActions(vd); + // } + // } else + // data.fastClickLastCancelled = true; + // } else { + // data.fastClickLastCancelled = false; + // + // // Reduce the violation level. + // data.fastClickVL *= 0.98D; + // } + // + // // Remember the current time.s + // data.fastClickLastTime = time; + // + // return cancel; + // } + public boolean check(final Player player, final long now, final InventoryView view, final int slot, final ItemStack cursor, final ItemStack clicked, final boolean isShiftClick, final InventoryData data, final InventoryConfig cc) { - // Take time once. - - final float amount; - - if (cursor != null && cc.fastClickTweaks1_5){ - final Material cursorMat = cursor.getType(); - final int cursorAmount = Math.max(1, cursor.getAmount()); - final Material clickedMat = clicked == null ? Material.AIR : clicked.getType(); - if (cursorMat != data.fastClickLastCursor && (!isShiftClick || clicked == null || clicked.getType() != data.fastClickLastClicked) || cursorMat == Material.AIR || cursorAmount != data.fastClickLastCursorAmount){ - amount = 1f; - } - else{ - if (clickedMat == Material.AIR || clickedMat == cursorMat || isShiftClick && clickedMat == data.fastClickLastClicked ){ - amount = Math.min(cc.fastClickNormalLimit , cc.fastClickShortTermLimit) / (float) (isShiftClick && clickedMat != Material.AIR ? (1.0 + Math.max(cursorAmount, InventoryUtil.getStackCount(view, clicked))) : cursorAmount) * 0.75f; - } - else{ - amount = 1f; - } - } - data.fastClickLastCursor = cursorMat; - data.fastClickLastClicked = clickedMat; - data.fastClickLastCursorAmount = cursorAmount; - } - else{ - data.fastClickLastCursor = null; - data.fastClickLastClicked = null; - data.fastClickLastCursorAmount = 0; - amount = 1f; - } - + // Take time once. + + final float amount; + + if (cursor != null && cc.fastClickTweaks1_5){ + final Material cursorMat = cursor.getType(); + final int cursorAmount = Math.max(1, cursor.getAmount()); + final Material clickedMat = clicked == null ? Material.AIR : clicked.getType(); + if (cursorMat != data.fastClickLastCursor && (!isShiftClick || clicked == null || clicked.getType() != data.fastClickLastClicked) || cursorMat == Material.AIR || cursorAmount != data.fastClickLastCursorAmount){ + amount = 1f; + } + else{ + if (clickedMat == Material.AIR || clickedMat == cursorMat || isShiftClick && clickedMat == data.fastClickLastClicked ){ + amount = Math.min(cc.fastClickNormalLimit , cc.fastClickShortTermLimit) / (float) (isShiftClick && clickedMat != Material.AIR ? (1.0 + Math.max(cursorAmount, InventoryUtil.getStackCount(view, clicked))) : cursorAmount) * 0.75f; + } + else{ + amount = 1f; + } + } + data.fastClickLastCursor = cursorMat; + data.fastClickLastClicked = clickedMat; + data.fastClickLastCursorAmount = cursorAmount; + } + else{ + data.fastClickLastCursor = null; + data.fastClickLastClicked = null; + data.fastClickLastCursorAmount = 0; + amount = 1f; + } + data.fastClickFreq.add(now, amount); - + float shortTerm = data.fastClickFreq.bucketScore(0); if (shortTerm > cc.fastClickShortTermLimit){ - // Check for lag. - shortTerm /= (float) TickTask.getLag(data.fastClickFreq.bucketDuration(), true); + // Check for lag. + shortTerm /= (float) TickTask.getLag(data.fastClickFreq.bucketDuration(), true); } shortTerm -= cc.fastClickShortTermLimit; - + float normal = data.fastClickFreq.score(1f); if (normal > cc.fastClickNormalLimit){ - // Check for lag. - normal /= (float) TickTask.getLag(data.fastClickFreq.bucketDuration() * data.fastClickFreq.numberOfBuckets(), true); + // Check for lag. + normal /= (float) TickTask.getLag(data.fastClickFreq.bucketDuration() * data.fastClickFreq.numberOfBuckets(), true); } normal -= cc.fastClickNormalLimit; final double violation = Math.max(shortTerm, normal); - + boolean cancel = false; - + if (violation > 0){ - data.fastClickVL += violation; - final ViolationData vd = new ViolationData(this, player, data.fastClickVL + violation, violation, cc.fastClickActions); - cancel = executeActions(vd); + data.fastClickVL += violation; + final ViolationData vd = new ViolationData(this, player, data.fastClickVL + violation, violation, cc.fastClickActions); + cancel = executeActions(vd); } - + if (data.debug && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)){ - player.sendMessage("FastClick: " + data.fastClickFreq.bucketScore(0) + " | " + data.fastClickFreq.score(1f) + " | cursor=" + cursor + " | clicked=" + clicked); + player.sendMessage("FastClick: " + data.fastClickFreq.bucketScore(0) + " | " + data.fastClickFreq.score(1f) + " | cursor=" + cursor + " | clicked=" + clicked); } - + return cancel; } } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java index be53e166..c0d9ec2e 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java @@ -518,7 +518,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo // TODO: Could further differentiate if really needed to (newTo / NoFall). final double maxYNoFall = Math.max(cc.noFallyOnGround, cc.yOnGround); pFrom.collectBlockFlags(maxYNoFall); - if (pFrom.isSamePos(pTo)) { + final boolean isSamePos = pFrom.isSamePos(pTo); + if (isSamePos) { // TODO: Could consider pTo = pFrom, set pitch / yaw elsewhere. // Sets all properties, but only once. pTo.prepare(pFrom); @@ -531,7 +532,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo // Actual check. if (newTo == null) { // Only check if passable has not already set back. - newTo = survivalFly.check(player, pFrom, pTo, data, cc, time); + newTo = survivalFly.check(player, pFrom, pTo, isSamePos, data, cc, time); } // Only check NoFall, if not already vetoed. if (checkNf) { @@ -1054,7 +1055,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, "[NoCheatPlus] VehicleMoveEvent fired for: " + entityType); } } - // TODO: Might account for the case of a player letting the vehicle move but not themself (do mind latency). + // TODO: Might account for the case of a player letting the vehicle move but not themselves (do mind latency). // Mind that players could be riding horses inside of minecarts etc. if (vehicle.getVehicle() != null) { // Do ignore events for vehicles inside of other vehicles. @@ -1079,14 +1080,14 @@ public class MovingListener extends CheckListener implements TickListener, IRemo final MovingData data = MovingData.getData(player); data.vehicleConsistency = MoveConsistency.getConsistency(from, to, player.getLocation(useLoc)); switch (data.vehicleConsistency) { - case FROM: - case TO: - data.resetPositions(player.getLocation(useLoc)); // TODO: Drop MC 1.4! - break; - case INCONSISTENT: - // TODO: Any exploits exist? -> TeleportUtil.forceMount(player, vehicle) - // TODO: Test with latency. - break; + case FROM: + case TO: + data.resetPositions(player.getLocation(useLoc)); // TODO: Drop MC 1.4! + break; + case INCONSISTENT: + // TODO: Any exploits exist? -> TeleportUtil.forceMount(player, vehicle) + // TODO: Test with latency. + break; } Location newTo = null; diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java index 0961f000..e70dd21e 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java @@ -93,18 +93,24 @@ public class SurvivalFly extends Check { * the from * @param to * the to + * @param isSamePos * @return the location */ - public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, final MovingData data, final MovingConfig cc, final long now) { + public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, final boolean isSamePos, final MovingData data, final MovingConfig cc, final long now) { tags.clear(); // Calculate some distances. - final double xDistance = to.getX() - from.getX(); - final double yDistance = to.getY() - from.getY(); - final double zDistance = to.getZ() - from.getZ(); - - // TODO: Later switch to squared distances. - final double hDistance = Math.sqrt(xDistance * xDistance + zDistance * zDistance); + final double xDistance, yDistance, zDistance, hDistance; + if (isSamePos) { + // TODO: Could run a completely different check here (roughly none :p). + xDistance = yDistance = zDistance = hDistance = 0.0; + } else { + // TODO: Could still do without this, if horizontal distance is 0 (!). + xDistance = to.getX() - from.getX(); + yDistance = to.getY() - from.getY(); + zDistance = to.getZ() - from.getZ(); + hDistance = Math.sqrt(xDistance * xDistance + zDistance * zDistance); + } // Ensure we have a set-back location set. if (!data.hasSetBack()) { @@ -165,7 +171,10 @@ public class SurvivalFly extends Check { if (fromOnGround || from.isResetCond()) { resetFrom = true; } - // TODO: Extra workarounds for toOnGround ? + // TODO: Extra workarounds for toOnGround (step-up is a case with to on ground)? + else if (isSamePos) { + resetFrom = false; + } else{ // TODO: More refined conditions possible ? // TODO: Consider if (!resetTo) ? @@ -197,52 +206,56 @@ public class SurvivalFly extends Check { data.sfOnIce--; } - // Get the allowed distance. - double hAllowedDistance = getAllowedhDist(player, from, to, sprinting, downStream, hDistance, walkSpeed, data, cc, false); + double hAllowedDistance = 0.0, hDistanceAboveLimit = 0.0, hFreedom = 0.0; + if (!isSamePos) { + // Check allowed vs. taken horizontal distance. + // Get the allowed distance. + hAllowedDistance = getAllowedhDist(player, from, to, sprinting, downStream, hDistance, walkSpeed, data, cc, false); - // Judge if horizontal speed is above limit. - double hDistanceAboveLimit = hDistance - hAllowedDistance; + // Judge if horizontal speed is above limit. + hDistanceAboveLimit = hDistance - hAllowedDistance; - // Velocity, buffers and after failure checks. - final double hFreedom; - if (hDistanceAboveLimit > 0) { - // TODO: Move more of the workarounds (buffer, bunny, ...) into this method. - final double[] res = hDistAfterFailure(player, from, to, walkSpeed, hAllowedDistance, hDistance, hDistanceAboveLimit, yDistance, sprinting, downStream, data, cc, false); - hAllowedDistance = res[0]; - hDistanceAboveLimit = res[1]; - hFreedom = res[2]; - } - else{ - data.clearActiveHorVel(); - hFreedom = 0.0; - if (resetFrom && data.bunnyhopDelay <= 6) { - data.bunnyhopDelay = 0; + // Velocity, buffers and after failure checks. + if (hDistanceAboveLimit > 0) { + // TODO: Move more of the workarounds (buffer, bunny, ...) into this method. + final double[] res = hDistAfterFailure(player, from, to, walkSpeed, hAllowedDistance, hDistance, hDistanceAboveLimit, yDistance, sprinting, downStream, data, cc, false); + hAllowedDistance = res[0]; + hDistanceAboveLimit = res[1]; + hFreedom = res[2]; + } + else{ + data.clearActiveHorVel(); + hFreedom = 0.0; + if (resetFrom && data.bunnyhopDelay <= 6) { + data.bunnyhopDelay = 0; + } } - } - // Prevent players from walking on a liquid in a too simple way. - // TODO: Find something more effective against more smart methods (limitjump helps already). - // TODO: yDistance == 0D <- should there not be a tolerance +- or 0...x ? - // TODO: Complete re-modeling. - if (hDistanceAboveLimit <= 0D && hDistance > 0.1D && yDistance == 0D && data.sfLastYDist == 0D && !toOnGround && !fromOnGround && BlockProperties.isLiquid(to.getTypeId())) { - // TODO: Relative hdistance. - // TODO: Might check actual bounds (collidesBlock). Might implement + use BlockProperties.getCorrectedBounds or getSomeHeight. - hDistanceAboveLimit = Math.max(hDistanceAboveLimit, hDistance); - tags.add("waterwalk"); - } - - // Prevent players from sprinting if they're moving backwards (allow buffers to cover up !?). - if (sprinting && data.lostSprintCount == 0 && !cc.assumeSprint && hDistance > walkSpeed && !data.hasActiveHorVel()) { - // (Ignore some cases, in order to prevent false positives.) - // TODO: speed effects ? - if (TrigUtil.isMovingBackwards(xDistance, zDistance, from.getYaw()) && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_SPRINTING)) { - // (Might have to account for speeding permissions.) - // TODO: hDistance is too harsh? + // Prevent players from walking on a liquid in a too simple way. + // TODO: Find something more effective against more smart methods (limitjump helps already). + // TODO: yDistance == 0D <- should there not be a tolerance +- or 0...x ? + // TODO: Complete re-modeling. + if (hDistanceAboveLimit <= 0D && hDistance > 0.1D && yDistance == 0D && data.sfLastYDist == 0D && !toOnGround && !fromOnGround && BlockProperties.isLiquid(to.getTypeId())) { + // TODO: Relative hdistance. + // TODO: Might check actual bounds (collidesBlock). Might implement + use BlockProperties.getCorrectedBounds or getSomeHeight. hDistanceAboveLimit = Math.max(hDistanceAboveLimit, hDistance); - tags.add("sprintback"); // Might add it anyway. + tags.add("waterwalk"); + } + + // Prevent players from sprinting if they're moving backwards (allow buffers to cover up !?). + if (sprinting && data.lostSprintCount == 0 && !cc.assumeSprint && hDistance > walkSpeed && !data.hasActiveHorVel()) { + // (Ignore some cases, in order to prevent false positives.) + // TODO: speed effects ? + if (TrigUtil.isMovingBackwards(xDistance, zDistance, from.getYaw()) && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_SPRINTING)) { + // (Might have to account for speeding permissions.) + // TODO: hDistance is too harsh? + hDistanceAboveLimit = Math.max(hDistanceAboveLimit, hDistance); + tags.add("sprintback"); // Might add it anyway. + } } } + ////////////////////////// // Vertical move. ////////////////////////// @@ -381,7 +394,7 @@ public class SurvivalFly extends Check { } // Finally check horizontal buffer regain. - if (hDistanceAboveLimit < 0.0 && result <= 0.0 && hDistance > 0.0 && data.sfHorizontalBuffer < hBufMax) { + if (hDistanceAboveLimit < 0.0 && result <= 0.0 && !isSamePos && data.sfHorizontalBuffer < hBufMax) { // TODO: max min other conditions ? hBufRegain(hDistance, Math.min(0.2, Math.abs(hDistanceAboveLimit)), data); } @@ -437,10 +450,12 @@ public class SurvivalFly extends Check { } // Invalidation of vertical velocity. + // TODO: This invalidation is wrong in case of already jumped higher (can not be repaired?). 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; + tags.add("invalidate_vvel"); // TODO: Test / validate by logs. } // Apply reset conditions. diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/BridgeEnchant.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/BridgeEnchant.java index 2675aff2..63ce5016 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/BridgeEnchant.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/BridgeEnchant.java @@ -1,12 +1,13 @@ package fr.neatmonster.nocheatplus.compat; -import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import fr.neatmonster.nocheatplus.utilities.BlockProperties; + public final class BridgeEnchant { - + private static final Enchantment parseEnchantment(final String name) { try { return Enchantment.getByName(name); @@ -25,7 +26,7 @@ public final class BridgeEnchant { public static int getDepthStriderLevel(Player player) { if (DEPTH_STRIDER != null) { final ItemStack boots = player.getInventory().getBoots(); - if (boots != null && boots.getType() != Material.AIR) { + if (!BlockProperties.isAir(boots)) { return Math.min(3, boots.getEnchantmentLevel(BridgeEnchant.DEPTH_STRIDER)); } } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/vanilla/BlocksMC1_8.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/vanilla/BlocksMC1_8.java index 2fc6b13d..20edf710 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/vanilla/BlocksMC1_8.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/vanilla/BlocksMC1_8.java @@ -8,104 +8,120 @@ import fr.neatmonster.nocheatplus.config.WorldConfigProvider; import fr.neatmonster.nocheatplus.logging.StaticLog; import fr.neatmonster.nocheatplus.utilities.BlockFlags; import fr.neatmonster.nocheatplus.utilities.BlockProperties; +import fr.neatmonster.nocheatplus.utilities.BlockProperties.BlockProps; +@SuppressWarnings("deprecation") public class BlocksMC1_8 implements BlockPropertiesSetup { - - public BlocksMC1_8() { - BlockInit.assertMaterialNameMatch(166, "barrier"); - BlockInit.assertMaterialNameMatch(165, "slime"); - BlockInit.assertMaterialNameMatch(187, "fence", "gate"); - BlockInit.assertMaterialNameMatch(176, "banner"); - BlockInit.assertMaterialNameMatch(169, "sea", "lantern"); - } - - @Override - public void setupBlockProperties(WorldConfigProvider worldConfigProvider) { - // 165(SLIME_BLOCK - BlockInit.setAs(165, Material.TNT); // Full block, instant break. - // Add the bouncing flag. - BlockProperties.setBlockFlags(165, BlockProperties.getBlockFlags(165) | BlockProperties.F_BOUNCE25); - - // 166(BARRIER - BlockInit.setAs(166, Material.BEDROCK); // Full block, unbreakable. - - // 167(IRON_TRAP_DOOR - BlockFlags.setFlagsAs(167, Material.TRAP_DOOR); - BlockInit.setPropsAs(167, Material.IRON_DOOR_BLOCK); - - // 168(PRISMARINE - BlockInit.setAs(168, Material.STONE); - - // 169(SEA_LANTERN - BlockInit.setAs(169, Material.REDSTONE_LAMP_OFF); - - // 176(STANDING_BANNER - BlockInit.setInstantAir(176); - - // 177(WALL_BANNER - BlockInit.setInstantAir(177); - - // 178(DAYLIGHT_DETECTOR_INVERTED - BlockInit.setAs(178, Material.DAYLIGHT_DETECTOR); - - // 179(RED_SANDSTONE - BlockInit.setAs(179, Material.SANDSTONE); - - // 180(RED_SANDSTONE_STAIRS - BlockInit.setAs(180, Material.SANDSTONE_STAIRS); - - // 181(DOUBLE_STEP_2 - BlockInit.setAs(181, Material.DOUBLE_STEP); // TODO: red sandstone / prismarine ? - - // 182(STEP_2 - BlockInit.setAs(182, Material.STEP); // TODO: red sandstone / prismarine ? - - // 183(SPRUCE_FENCE_GATE - BlockInit.setAs(183, Material.FENCE_GATE); - - // 184(BIRCH_FENCE_GATE - BlockInit.setAs(184, Material.FENCE_GATE); - - // 185(JUNGLE_FENCE_GATE - BlockInit.setAs(185, Material.FENCE_GATE); - - // 186(DARK_OAK_FENCE_GATE - BlockInit.setAs(186, Material.FENCE_GATE); - - // 187(ACACIA_FENCE_GATE - BlockInit.setAs(187, Material.FENCE_GATE); - - // 188(SPRUCE_FENCE - BlockInit.setAs(188, Material.FENCE); - - // 189(BIRCH_FENCE - BlockInit.setAs(189, Material.FENCE); - - // 190(JUNGLE_FENCE - BlockInit.setAs(190, Material.FENCE); - - // 191(DARK_OAK_FENCE - BlockInit.setAs(191, Material.FENCE); - - // 192(ACACIA_FENCE - BlockInit.setAs(192, Material.FENCE); - - // 193(SPRUCE_DOOR - BlockInit.setAs(193, Material.WOODEN_DOOR); - - // 194(BIRCH_DOOR - BlockInit.setAs(194, Material.WOODEN_DOOR); - - // 195(JUNGLE_DOOR - BlockInit.setAs(195, Material.WOODEN_DOOR); - - // 196(ACACIA_DOOR - BlockInit.setAs(196, Material.WOODEN_DOOR); - - // 197(DARK_OAK_DOOR - BlockInit.setAs(197, Material.WOODEN_DOOR); - - StaticLog.logInfo("[NoCheatPlus] Added block-info for Minecraft 1.8 blocks."); - } + + public BlocksMC1_8() { + BlockInit.assertMaterialNameMatch(166, "barrier"); + BlockInit.assertMaterialNameMatch(165, "slime"); + BlockInit.assertMaterialNameMatch(187, "fence", "gate"); + BlockInit.assertMaterialNameMatch(176, "banner"); + BlockInit.assertMaterialNameMatch(169, "sea", "lantern"); + } + + @Override + public void setupBlockProperties(WorldConfigProvider worldConfigProvider) { + + // Melon/pumpkin block breaking times. + BlockProps props = new BlockProps(BlockProperties.woodAxe, 1f, BlockProperties.secToMs(1.45, 0.70, 0.325, 0.2, 0.13, 0.075), 3f); + for (Material mat : new Material[] { + Material.MELON_BLOCK, + Material.PUMPKIN, + Material.JACK_O_LANTERN, + // Same core breaking times, but behave different on efficiency + other tool (?): + Material.WALL_SIGN, + Material.SIGN_POST, + }) { + BlockProperties.setBlockProps(BlockProperties.getId(mat), props); + } + + // 165(SLIME_BLOCK + BlockInit.setAs(165, Material.TNT); // Full block, instant break. + // Add the bouncing flag. + BlockProperties.setBlockFlags(165, BlockProperties.getBlockFlags(165) | BlockProperties.F_BOUNCE25); + + // 166(BARRIER + BlockInit.setAs(166, Material.BEDROCK); // Full block, unbreakable. + + // 167(IRON_TRAP_DOOR + BlockFlags.setFlagsAs(167, Material.TRAP_DOOR); + BlockInit.setPropsAs(167, Material.IRON_DOOR_BLOCK); + + // 168(PRISMARINE + BlockInit.setAs(168, Material.STONE); + + // 169(SEA_LANTERN + BlockInit.setAs(169, Material.REDSTONE_LAMP_OFF); + + // 176(STANDING_BANNER + BlockInit.setInstantAir(176); + + // 177(WALL_BANNER + BlockInit.setInstantAir(177); + + // 178(DAYLIGHT_DETECTOR_INVERTED + BlockInit.setAs(178, Material.DAYLIGHT_DETECTOR); + + // 179(RED_SANDSTONE + BlockInit.setAs(179, Material.SANDSTONE); + + // 180(RED_SANDSTONE_STAIRS + BlockInit.setAs(180, Material.SANDSTONE_STAIRS); + + // 181(DOUBLE_STEP_2 + BlockInit.setAs(181, Material.DOUBLE_STEP); // TODO: red sandstone / prismarine ? + + // 182(STEP_2 + BlockInit.setAs(182, Material.STEP); // TODO: red sandstone / prismarine ? + + // 183(SPRUCE_FENCE_GATE + BlockInit.setAs(183, Material.FENCE_GATE); + + // 184(BIRCH_FENCE_GATE + BlockInit.setAs(184, Material.FENCE_GATE); + + // 185(JUNGLE_FENCE_GATE + BlockInit.setAs(185, Material.FENCE_GATE); + + // 186(DARK_OAK_FENCE_GATE + BlockInit.setAs(186, Material.FENCE_GATE); + + // 187(ACACIA_FENCE_GATE + BlockInit.setAs(187, Material.FENCE_GATE); + + // 188(SPRUCE_FENCE + BlockInit.setAs(188, Material.FENCE); + + // 189(BIRCH_FENCE + BlockInit.setAs(189, Material.FENCE); + + // 190(JUNGLE_FENCE + BlockInit.setAs(190, Material.FENCE); + + // 191(DARK_OAK_FENCE + BlockInit.setAs(191, Material.FENCE); + + // 192(ACACIA_FENCE + BlockInit.setAs(192, Material.FENCE); + + // 193(SPRUCE_DOOR + BlockInit.setAs(193, Material.WOODEN_DOOR); + + // 194(BIRCH_DOOR + BlockInit.setAs(194, Material.WOODEN_DOOR); + + // 195(JUNGLE_DOOR + BlockInit.setAs(195, Material.WOODEN_DOOR); + + // 196(ACACIA_DOOR + BlockInit.setAs(196, Material.WOODEN_DOOR); + + // 197(DARK_OAK_DOOR + BlockInit.setAs(197, Material.WOODEN_DOOR); + + StaticLog.logInfo("[NoCheatPlus] Added block-info for Minecraft 1.8 blocks."); + } } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockProperties.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockProperties.java index b6e28a7d..5da41750 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockProperties.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockProperties.java @@ -251,8 +251,6 @@ public class BlockProperties { public static final BlockProps sandStoneType = new BlockProps(woodPickaxe, 0.8f); - public static final BlockProps pumpkinType = new BlockProps(woodAxe, 1, secToMs(1.5, 0.75, 0.4, 0.25, 0.2, 0.15)); - public static final BlockProps chestType = new BlockProps(woodAxe, 2.5f, secToMs(3.75, 1.9, 0.95, 0.65, 0.5, 0.35)); public static final BlockProps woodDoorType = new BlockProps(woodAxe, 3.0f, secToMs(4.5, 2.25, 1.15, 0.75, 0.6, 0.4)); @@ -705,11 +703,12 @@ public class BlockProperties { blocks[mat.getId()] = stoneType; } blocks[Material.NOTE_BLOCK.getId()] = new BlockProps(woodAxe, 0.8f, secToMs(1.2, 0.6, 0.3, 0.2, 0.15, 0.1)); + final BlockProps pumpkinType = new BlockProps(woodAxe, 1, secToMs(1.5, 0.75, 0.4, 0.25, 0.2, 0.15)); blocks[Material.WALL_SIGN.getId()] = pumpkinType; blocks[Material.SIGN_POST.getId()] = pumpkinType; blocks[Material.PUMPKIN.getId()] = pumpkinType; blocks[Material.JACK_O_LANTERN.getId()] = pumpkinType; - blocks[Material.MELON_BLOCK.getId()] = new BlockProps(woodAxe, 1f, secToMs(1.5, 0.75, 0.375, 0.25, 0.1875, 0.125), 3f); + blocks[Material.MELON_BLOCK.getId()] = new BlockProps(noTool, 1, secToMs(1.45), 3); blocks[Material.BOOKSHELF.getId()] = new BlockProps(woodAxe, 1.5f, secToMs(2.25, 1.15, 0.6, 0.4, 0.3, 0.2)); for (Material mat : new Material[]{ Material.WOOD_STAIRS, Material.WOOD, Material.WOOD_STEP, Material.LOG, @@ -1021,7 +1020,6 @@ public class BlockProperties { return getBreakingDuration(blockId, itemInHand, onGround, inWater, helmet != null && helmet.containsEnchantment(Enchantment.WATER_WORKER), haste == Double.NEGATIVE_INFINITY ? 0 : 1 + (int) haste); } - /** * Get the normal breaking duration, including enchantments, and tool properties. * @param blockId @@ -1030,12 +1028,14 @@ public class BlockProperties { */ public static long getBreakingDuration(final int blockId, final ItemStack itemInHand, final boolean onGround, final boolean inWater, final boolean aquaAffinity, final int haste) { // TODO: more configurability / load from file for blocks (i.e. set for shears etc. - if (itemInHand == null) { + if (isAir(itemInHand)) { return getBreakingDuration(blockId, getBlockProps(blockId), noTool, onGround, inWater, aquaAffinity, 0); } else { int efficiency = 0; - if (itemInHand.containsEnchantment(Enchantment.DIG_SPEED)) efficiency = itemInHand.getEnchantmentLevel(Enchantment.DIG_SPEED); + if (itemInHand.containsEnchantment(Enchantment.DIG_SPEED)) { + efficiency = itemInHand.getEnchantmentLevel(Enchantment.DIG_SPEED); + } return getBreakingDuration(blockId, getBlockProps(blockId), getToolProps(itemInHand.getTypeId()), onGround, inWater, aquaAffinity, efficiency, haste); } } @@ -1054,21 +1054,15 @@ public class BlockProperties { */ public static long getBreakingDuration(final int blockId, final BlockProps blockProps, final ToolProps toolProps, final boolean onGround, final boolean inWater, boolean aquaAffinity, int efficiency, int haste) { final long dur = getBreakingDuration(blockId, blockProps, toolProps, onGround, inWater, aquaAffinity, efficiency); - // TODO: haste ... - return haste > 0 ? (long) (Math.pow(0.8, haste) * dur): dur; + return haste > 0 ? (long) (Math.pow(0.8, haste) * dur) : dur; } public static long getBreakingDuration(final int blockId, final BlockProps blockProps, final ToolProps toolProps, final boolean onGround, final boolean inWater, boolean aquaAffinity, int efficiency) { boolean isValidTool = isValidTool(blockId, blockProps, toolProps, efficiency); if (efficiency > 0) { // Workaround until something better is found.. - // TODO: Re-evaluate.ww + // TODO: Re-evaluate. if (isLeaves(blockId) || blockProps == glassType) { - /* - * TODO: Some might be dealt with by insta break, by now, - * still getting exact durations would be nice to have, for expected breaking times and - * general API use (spin off, analysis?). - */ if (efficiency == 1) { return 100; } @@ -1148,16 +1142,16 @@ public class BlockProperties { if (blockId == Material.WOODEN_DOOR.getId() && toolProps.toolType != ToolType.AXE) { // Heck [Cleanup pending]... switch (efficiency) { - case 1: - return (long) (mult * 1500); - case 2: - return (long) (mult * 750); - case 3: - return (long) (mult * 450); - case 4: - return (long) (mult * 250); - case 5: - return (long) (mult * 150); + case 1: + return (long) (mult * 1500); + case 2: + return (long) (mult * 750); + case 3: + return (long) (mult * 450); + case 4: + return (long) (mult * 250); + case 5: + return (long) (mult * 150); } } // This seems roughly correct. @@ -1199,6 +1193,14 @@ public class BlockProperties { } } } + // Post/legacy workarounds for efficiency tools ("improper"). + if (efficiency > 0 && !isValidTool) { + if (!isValidTool && blockId == Material.MELON_BLOCK.getId()) { + // Fall back to pre-1.8 behavior. + // 450, 200 , 100 , 50 , 0 + duration = Math.min(duration, 450 / (long) Math.pow(2, efficiency - 1)); + } + } return Math.max(0, duration); } @@ -1504,6 +1506,24 @@ public class BlockProperties { return (blockFlags[id] & F_GROUND) != 0; } + /** + * Convenience method including null checks. + * @param type + * @return + */ + public static final boolean isAir(Material type) { + return type == null || type == Material.AIR; + } + + /** + * Convenience method including null checks. + * @param stack + * @return + */ + public static final boolean isAir(ItemStack stack) { + return stack == null || isAir(stack.getType()); + } + /** * Just check if a position is not inside of a block that has a bounding box.
* This is an inaccurate check, it also returns false for doors etc. diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/FakeBlockCache.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/FakeBlockCache.java index afaf027d..0079d0f2 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/FakeBlockCache.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/FakeBlockCache.java @@ -12,16 +12,16 @@ import fr.neatmonster.nocheatplus.utilities.ds.CoordMap; * */ public class FakeBlockCache extends BlockCache { - + /** Cached type-ids. */ private final CoordMap idMapStored = new CoordMap(23); - + /** Cached data values. */ private final CoordMap dataMapStored = new CoordMap(23); - + /** Cached shape values. */ private final CoordMap boundsMapStored = new CoordMap(23); - + /** * Set with data=0 and bounds=full. * @param x @@ -32,7 +32,7 @@ public class FakeBlockCache extends BlockCache { public void set(int x, int y, int z, Material type) { set(x, y, z, BlockProperties.getId(type)); } - + /** * Set with data=0- * @param x @@ -44,7 +44,7 @@ public class FakeBlockCache extends BlockCache { public void set(int x, int y, int z, Material type, double[] bounds) { set(x, y, z, BlockProperties.getId(type), 0, bounds); } - + /** * Set with data=0 and bounds=full. * @param x @@ -55,7 +55,7 @@ public class FakeBlockCache extends BlockCache { public void set(int x, int y, int z, int typeId) { set(x, y, z, typeId, 0); } - + /** * Set with bounds=full. * @param x @@ -67,7 +67,7 @@ public class FakeBlockCache extends BlockCache { public void set(int x, int y, int z, int typeId, int data) { set(x, y, z, typeId, data, new double[]{0.0, 0.0, 0.0, 1.0, 1.0, 1.0}); } - + /** * Set custom properties. * @param x diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/InventoryUtil.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/InventoryUtil.java index 1df3188a..b1b85d75 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/InventoryUtil.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/InventoryUtil.java @@ -15,21 +15,16 @@ import org.bukkit.inventory.ItemStack; */ public class InventoryUtil { - private static boolean isEmpty(Material mat) { - return mat == null || mat == Material.AIR; - } - /** * Does not account for special slots like armor. * @param inventory * @return */ - public static int getFreeSlots(final Inventory inventory){ + public static int getFreeSlots(final Inventory inventory) { final ItemStack[] contents = inventory.getContents(); int count = 0; - for (int i = 0; i < contents.length; i++){ - final ItemStack stack = contents[i]; - if (stack == null || isEmpty(stack.getType())){ + for (int i = 0; i < contents.length; i++) { + if (BlockProperties.isAir(contents[i])) { count ++; } } @@ -49,12 +44,12 @@ public class InventoryUtil { final int durability = reference.getDurability(); final ItemStack[] contents = inventory.getContents(); int count = 0; - for (int i = 0; i < contents.length; i++){ + for (int i = 0; i < contents.length; i++) { final ItemStack stack = contents[i]; - if (stack == null){ + if (stack == null) { continue; } - else if (stack.getType() == mat && stack.getDurability() == durability){ + else if (stack.getType() == mat && stack.getDurability() == durability) { count ++; } } @@ -75,7 +70,7 @@ public class InventoryUtil { * Search for players / passengers (broken by name: closes the inventory of first player found including entity and passengers recursively). * @param entity */ - public static boolean closePlayerInventoryRecursively(Entity entity){ + public static boolean closePlayerInventoryRecursively(Entity entity) { // Find a player. final Player player = getPlayerPassengerRecursively(entity); if (player != null && closeOpenInventory((Player) entity)) { @@ -91,17 +86,17 @@ public class InventoryUtil { * @return */ public static Player getPlayerPassengerRecursively(Entity entity) { - while (entity != null){ - if (entity instanceof Player){ + while (entity != null) { + if (entity instanceof Player) { // Scrap the case of players riding players for the moment. return (Player) entity; } final Entity passenger = entity.getPassenger(); - if (entity.equals(passenger)){ + if (entity.equals(passenger)) { // Just in case :9. break; } - else{ + else { entity = passenger; } } @@ -113,7 +108,7 @@ public class InventoryUtil { * @param player * @return If closed. */ - public static boolean closeOpenInventory(final Player player){ + public static boolean closeOpenInventory(final Player player) { if (hasInventoryOpen(player)) { player.closeInventory(); return true;