[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.
This commit is contained in:
asofold 2015-01-04 20:04:20 +01:00
parent d5632035b4
commit f0c5552873
13 changed files with 484 additions and 434 deletions

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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.

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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.

View File

@ -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));
}
}

View File

@ -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.");
}
}

View File

@ -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.<br>
* This is an inaccurate check, it also returns false for doors etc.

View File

@ -12,16 +12,16 @@ import fr.neatmonster.nocheatplus.utilities.ds.CoordMap;
*
*/
public class FakeBlockCache extends BlockCache {
/** Cached type-ids. */
private final CoordMap<Integer> idMapStored = new CoordMap<Integer>(23);
/** Cached data values. */
private final CoordMap<Integer> dataMapStored = new CoordMap<Integer>(23);
/** Cached shape values. */
private final CoordMap<double[]> boundsMapStored = new CoordMap<double[]>(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

View File

@ -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;