diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/BlockInit.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/BlockInit.java index add4dd29..02d8f270 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/BlockInit.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/blocks/init/BlockInit.java @@ -12,29 +12,29 @@ import fr.neatmonster.nocheatplus.utilities.BlockProperties; */ public class BlockInit { - // TODO: Add "assertMaterialExist" for id and id + name (name: add assertMaterialMatches) also with name with RuntimeException + // TODO: Change to assert names only?, would be better with being able to feed MC names or map them as well, though. /** * Check for Material existence, throw RuntimeException if not. * @param id */ public static void assertMaterialExists(int id) { - if (Material.getMaterial(id) == null){ + if (Material.getMaterial(id) == null) { throw new RuntimeException("Material " + id + " does not exist."); } } /** - * Check for material existence and naming (exact match). + * Check for material existence and naming (exact match). * @param id * @param name */ public static void assertMaterialName(int id, String name) { Material mat = Material.getMaterial(id); - if ( mat == null){ + if ( mat == null) { throw new RuntimeException("Material " + id + " does not exist."); } - if (mat.name().equals(name)){ + if (mat.name().equals(name)) { throw new RuntimeException("Name for Material " + id + " ('" + mat.name() + "') does not match '" + name + "'."); } } @@ -46,12 +46,12 @@ public class BlockInit { */ public static void assertMaterialNameMatch(int id, String... parts) { Material mat = Material.getMaterial(id); - if ( mat == null){ + if ( mat == null) { throw new RuntimeException("Material " + id + " does not exist."); } String name = mat.name().toLowerCase(); - for (String part : parts){ - if (name.indexOf(part.toLowerCase()) < 0){ + for (String part : parts) { + if (name.indexOf(part.toLowerCase()) < 0) { throw new RuntimeException("Name for Material " + id + " ('" + mat.name() + "') should contain '" + part + "'."); } } @@ -62,7 +62,7 @@ public class BlockInit { * @param newId * @param mat */ - public static void setPropsAs(int newId, Material mat){ + public static void setPropsAs(int newId, Material mat) { setPropsAs(newId, mat.getId()); } @@ -71,7 +71,7 @@ public class BlockInit { * @param newId * @param mat */ - public static void setPropsAs(int newId, int otherId){ + public static void setPropsAs(int newId, int otherId) { BlockProperties.setBlockProps(newId, BlockProperties.getBlockProps(otherId)); } @@ -80,7 +80,7 @@ public class BlockInit { * @param newId * @param mat */ - public static void setAs(int newId, Material mat){ + public static void setAs(int newId, Material mat) { BlockFlags.setFlagsAs(newId, mat); setPropsAs(newId, mat); } @@ -90,7 +90,7 @@ public class BlockInit { * @param newId * @param mat */ - public static void setAs(int newId, int otherId){ + public static void setAs(int newId, int otherId) { BlockFlags.setFlagsAs(newId, otherId); setPropsAs(newId, otherId); } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockCache.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockCache.java index e060ecbd..d129bda8 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockCache.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockCache.java @@ -14,6 +14,8 @@ import fr.neatmonster.nocheatplus.utilities.ds.CoordMap; */ public abstract class BlockCache { + // TODO: New concepts (Might switch to material, inspect MC+CB code for reliability and performance of block-ids during runtime). + private static final int ID_AIR = 0; /** @@ -23,7 +25,7 @@ public abstract class BlockCache { */ public static final boolean isFullBounds(final double[] bounds) { if (bounds == null) return false; - for (int i = 0; i < 3; i ++){ + for (int i = 0; i < 3; i ++) { if (bounds[i] > 0.0) return false; if (bounds[i + 3] < 1.0) return false; } @@ -45,9 +47,9 @@ public abstract class BlockCache { final int maxX = Location.locToBlock(x + xzMargin) / 16; final int minZ = Location.locToBlock(z - xzMargin) / 16; final int maxZ = Location.locToBlock(z + xzMargin) / 16; - for (int cx = minX; cx <= maxX; cx ++){ - for (int cz = minZ; cz <= maxZ; cz ++){ - if (!world.isChunkLoaded(cx, cz)){ + for (int cx = minX; cx <= maxX; cx ++) { + for (int cz = minZ; cz <= maxZ; cz ++) { + if (!world.isChunkLoaded(cx, cz)) { world.loadChunk(cx, cz); loaded ++; } @@ -73,10 +75,10 @@ public abstract class BlockCache { // private int[] id = null; // private int[] data = null; - public BlockCache(){ + public BlockCache() { } - public BlockCache(final World world){ + public BlockCache(final World world) { setAccess(world); } @@ -124,7 +126,7 @@ public abstract class BlockCache { * Remove references.
* NOTE: You must delete world references with this one. */ - public void cleanup(){ + public void cleanup() { idMap.clear(); dataMap.clear(); boundsMap.clear(); @@ -191,7 +193,7 @@ public abstract class BlockCache { * @param z * @return Array of floats (minX, minY, minZ, maxX, maxY, maxZ), may be null theoretically. Do not change these in place, because they might get cached. */ - public double[] getBounds(final int x, final int y, final int z){ + public double[] getBounds(final int x, final int y, final int z) { final double[] pBounds = boundsMap.get(x, y, z); if (pBounds != null) { return pBounds; @@ -208,7 +210,7 @@ public abstract class BlockCache { * @param z * @return */ - public boolean isFullBounds(final int x, final int y, final int z){ + public boolean isFullBounds(final int x, final int y, final int z) { return isFullBounds(getBounds(x, y, z)); } @@ -216,7 +218,7 @@ public abstract class BlockCache { * Get the maximal y coordinate a block can be at (non air). * @return */ - public int getMaxBlockY(){ + public int getMaxBlockY() { return maxBlockY; } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockFlags.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockFlags.java index a101274c..da6ea99d 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockFlags.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/BlockFlags.java @@ -15,7 +15,7 @@ public class BlockFlags { * @param id * @param mat */ - public static void setFlagsAs(int id, Material mat){ + public static void setFlagsAs(int id, Material mat) { setFlagsAs(id, mat.getId()); } @@ -24,7 +24,7 @@ public class BlockFlags { * @param id * @param mat */ - public static void setFlagsAs(int id, int otherId){ + public static void setFlagsAs(int id, int otherId) { BlockProperties.setBlockFlags(id, BlockProperties.getBlockFlags(otherId)); } @@ -33,7 +33,7 @@ public class BlockFlags { * @param id * @param flags */ - public static void addFlags(int id, long flags){ + public static void addFlags(int id, long flags) { BlockProperties.setBlockFlags(id, BlockProperties.getBlockFlags(id) | flags); } @@ -42,7 +42,7 @@ public class BlockFlags { * @param id * @param flags */ - public static void removeFlags(int id, long flags){ + public static void removeFlags(int id, long flags) { BlockProperties.setBlockFlags(id, BlockProperties.getBlockFlags(id) & ~flags); } diff --git a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java index f1b6c7a5..d650bcda 100644 --- a/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java +++ b/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java @@ -36,8 +36,17 @@ public class PlayerLocation { /** Bounding box of the player. */ private double minX, maxX, minY, maxY, minZ, maxZ; - // Object members (reset to null) // - + // TODO: Check if onGround can be completely replaced by onGroundMinY and notOnGroundMaxY. + /** Minimal yOnGround for which the player is on ground. No extra xz/y margin.*/ + private double onGroundMinY = Double.MAX_VALUE; + /** Maximal yOnGround for which the player is not on ground. No extra xz/y margin.*/ + private double notOnGroundMaxY = Double.MIN_VALUE; + + // "Light" object members (reset to null) // + + // TODO: The following should be changed to primitive types, add one long for "checked"-flags. Booleans can be compressed into a long. + // TODO: All properties that can be set should have a "checked" flag, thus resetting the flag suffices. + /** Type id of the block at the position. */ private Integer typeId = null; @@ -46,7 +55,19 @@ public class PlayerLocation { /** Data value of the block this position is on. */ private Integer data = null; + + /** All block flags collected for maximum used bounds. */ + private Long blockFlags = null; + + /** Is the player on ice? */ + private Boolean onIce = null; + /** Is the player on ladder? */ + private Boolean onClimbable = null; + + /** Simple test if the exact position is passable. */ + private Boolean passable = null; + /** Is the player above stairs? */ private Boolean aboveStairs = null; @@ -61,38 +82,22 @@ public class PlayerLocation { /** Is the player on the ground? */ private Boolean onGround = null; - - // TODO: Check if onGround can be completely replaced by onGroundMinY and notOnGroundMaxY. - /** Minimal yOnGround for which the player is on ground. No extra xz/y margin.*/ - private double onGroundMinY = Double.MAX_VALUE; - /** Maximal yOnGround for which the player is not on ground. No extra xz/y margin.*/ - private double notOnGroundMaxY = Double.MIN_VALUE; - /** Is the player on ice? */ - private Boolean onIce = null; - - /** Is the player on ladder? */ - private Boolean onClimbable = null; - - /** Simple test if the exact position is passable. */ - private Boolean passable = null; - - /** All block flags collected for maximum used bounds. */ - private Long blockFlags = null; - - // "Heavy" members (should be reset to null or cleaned up at some point) // + // "Heavy" object members (reset to null for cleanup). // /** The player ! */ private Player player = null; /** Bukkit world. */ private World world = null; + + // "Heavy" object members (further cleanup call needed + set to null for cleanup) // /** Optional block property cache. */ private BlockCache blockCache = null; - public PlayerLocation(final MCAccess mcAccess, final BlockCache blockCache){ + public PlayerLocation(final MCAccess mcAccess, final BlockCache blockCache) { this.mcAccess = mcAccess; this.blockCache = blockCache; } @@ -118,7 +123,7 @@ public class PlayerLocation { * Get the world! * @return */ - public World getWorld(){ + public World getWorld() { return world; } @@ -222,7 +227,7 @@ public class PlayerLocation { * @param loc * @return */ - public boolean isBlockAbove(final PlayerLocation loc){ + public boolean isBlockAbove(final PlayerLocation loc) { return blockY == loc.getBlockY() + 1 && blockX == loc.getBlockX() && blockZ == loc.getBlockZ(); } @@ -231,7 +236,7 @@ public class PlayerLocation { * @param loc * @return */ - public boolean isBlockAbove(final Location loc){ + public boolean isBlockAbove(final Location loc) { return blockY == loc.getBlockY() + 1 && blockX == loc.getBlockX() && blockZ == loc.getBlockZ(); } @@ -260,7 +265,7 @@ public class PlayerLocation { * @param other * @return */ - public int manhattan(final PlayerLocation other){ + public int manhattan(final PlayerLocation other) { // TODO: Consider using direct field access from other methods as well. return TrigUtil.manhattan(this.blockX, this.blockY, this.blockZ, other.blockX, other.blockY, other.blockZ); } @@ -270,7 +275,7 @@ public class PlayerLocation { * @param other * @return */ - public int maxBlockDist(final PlayerLocation other){ + public int maxBlockDist(final PlayerLocation other) { // TODO: Consider using direct field access from other methods as well. return TrigUtil.maxDistance(this.blockX, this.blockY, this.blockZ, other.blockX, other.blockY, other.blockZ); } @@ -282,7 +287,7 @@ public class PlayerLocation { */ public boolean isAboveStairs() { if (aboveStairs == null) { - if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_STAIRS) == 0 ){ + if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_STAIRS) == 0 ) { aboveStairs = false; return false; } @@ -301,7 +306,7 @@ public class PlayerLocation { */ public boolean isInLava() { if (inLava == null) { - if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_LAVA) == 0 ){ + if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_LAVA) == 0 ) { inLava = false; return false; } @@ -322,7 +327,7 @@ public class PlayerLocation { */ public boolean isInWater() { if (inWater == null) { - if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_WATER) == 0 ){ + if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_WATER) == 0 ) { inWater = false; return false; } @@ -383,7 +388,7 @@ public class PlayerLocation { public boolean isOnClimbable() { if (onClimbable == null) { // Climbable blocks. - if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_CLIMBABLE) == 0 ){ + if (blockFlags != null && (blockFlags.longValue() & BlockProperties.F_CLIMBABLE) == 0 ) { onClimbable = false; return false; } @@ -401,25 +406,25 @@ public class PlayerLocation { * @param jumpHeigth Height the player is allowed to have jumped. * @return */ - public boolean canClimbUp(double jumpHeigth){ + public boolean canClimbUp(double jumpHeigth) { // TODO: distinguish vines. - if (getTypeId() == Material.VINE.getId()){ + if (getTypeId() == Material.VINE.getId()) { // Check if vine is attached to something solid - if (BlockProperties.canClimbUp(blockCache, blockX, blockY, blockZ)){ + if (BlockProperties.canClimbUp(blockCache, blockX, blockY, blockZ)) { return true; } // Check the block at head height. final int headY = Location.locToBlock(y + player.getEyeHeight()); - if (headY > blockY){ - for (int cy = blockY + 1; cy <= headY; cy ++){ - if (BlockProperties.canClimbUp(blockCache, blockX, cy, blockZ)){ + if (headY > blockY) { + for (int cy = blockY + 1; cy <= headY; cy ++) { + if (BlockProperties.canClimbUp(blockCache, blockX, cy, blockZ)) { return true; } } } // Finally check possible jump height. // TODO: This too is inaccurate. - if (isOnGround(jumpHeigth)){ + if (isOnGround(jumpHeigth)) { // Here ladders are ok. return true; } @@ -460,34 +465,34 @@ public class PlayerLocation { * @return true, if the player is on ground */ public boolean isOnGround() { - if (onGround != null){ + if (onGround != null) { return onGround; } // Check cached values and simplifications. if (notOnGroundMaxY >= yOnGround) onGround = false; else if (onGroundMinY <= yOnGround) onGround = true; - else{ + else { // Shortcut check (currently needed for being stuck + sf). - if (blockFlags == null || (blockFlags.longValue() & BlockProperties.F_GROUND) != 0){ + if (blockFlags == null || (blockFlags.longValue() & BlockProperties.F_GROUND) != 0) { // TODO: Consider dropping this shortcut. final int bY = Location.locToBlock(y - yOnGround); final int id = bY == blockY ? getTypeId() : (bY == blockY -1 ? getTypeIdBelow() : blockCache.getTypeId(blockX, bY, blockZ)); final long flags = BlockProperties.getBlockFlags(id); // TODO: Might remove check for variable ? - if ((flags & BlockProperties.F_GROUND) != 0 && (flags & BlockProperties.F_VARIABLE) == 0){ + if ((flags & BlockProperties.F_GROUND) != 0 && (flags & BlockProperties.F_VARIABLE) == 0) { final double[] bounds = blockCache.getBounds(blockX, bY, blockZ); // Check collision if not inside of the block. [Might be a problem for cauldron or similar + something solid above.] // TODO: Might need more refinement. - if (bounds != null && y - bY >= bounds[4] && BlockProperties.collidesBlock(blockCache, x, minY - yOnGround, z, x, minY, z, blockX, bY, blockZ, id, bounds, flags)){ + if (bounds != null && y - bY >= bounds[4] && BlockProperties.collidesBlock(blockCache, x, minY - yOnGround, z, x, minY, z, blockX, bY, blockZ, id, bounds, flags)) { // TODO: BlockHeight is needed for fences, use right away (above)? if (!BlockProperties.isPassableWorkaround(blockCache, blockX, bY, blockZ, minX - blockX, minY - yOnGround - bY, minZ - blockZ, id, maxX - minX, yOnGround, maxZ - minZ, 1.0) - || (flags & BlockProperties.F_GROUND_HEIGHT) != 0 && BlockProperties.getGroundMinHeight(blockCache, blockX, bY, blockZ, id, bounds, flags) <= y - bY){ + || (flags & BlockProperties.F_GROUND_HEIGHT) != 0 && BlockProperties.getGroundMinHeight(blockCache, blockX, bY, blockZ, id, bounds, flags) <= y - bY) { // System.out.println("*** onground SHORTCUT"); onGround = true; } } } - if (onGround == null){ + if (onGround == null) { // System.out.println("*** fetch onground std"); // Full on-ground check (blocks). // Note: Might check for half-block height too (getTypeId), but that is much more seldom. @@ -497,7 +502,7 @@ public class PlayerLocation { else onGround = false; } if (onGround) onGroundMinY = Math.min(onGroundMinY, yOnGround); - else{ + else { // System.out.println("*** onground check entities"); // TODO: further confine this ? notOnGroundMaxY = Math.max(notOnGroundMaxY, yOnGround); @@ -512,7 +517,7 @@ public class PlayerLocation { * @param yOnGround Margin below the player. * @return */ - public boolean isOnGround(final double yOnGround){ + public boolean isOnGround(final double yOnGround) { if (notOnGroundMaxY >= yOnGround) return false; else if (onGroundMinY <= yOnGround) return true; return isOnGround(yOnGround, 0D, 0D, 0L); @@ -525,7 +530,7 @@ public class PlayerLocation { * @return */ public boolean isOnGround(final double yOnGround, final long ignoreFlags) { - if (ignoreFlags == 0){ + if (ignoreFlags == 0) { if (notOnGroundMaxY >= yOnGround) return false; else if (onGroundMinY <= yOnGround) return true; } @@ -542,7 +547,7 @@ public class PlayerLocation { */ public boolean isOnGround(final double yOnGround, final double xzMargin, final double yMargin) { if (xzMargin >= 0 && onGroundMinY <= yOnGround) return true; - if (xzMargin <= 0 && yMargin == 0){ + if (xzMargin <= 0 && yMargin == 0) { if (notOnGroundMaxY >= yOnGround) return false; } return isOnGround(yOnGround, xzMargin, yMargin, 0); @@ -557,20 +562,24 @@ public class PlayerLocation { * @return */ public boolean isOnGround(final double yOnGround, final double xzMargin, final double yMargin, final long ignoreFlags) { - if (ignoreFlags == 0){ + if (ignoreFlags == 0) { if (xzMargin >= 0 && onGroundMinY <= yOnGround) return true; - if (xzMargin <= 0 && yMargin == 0){ + if (xzMargin <= 0 && yMargin == 0) { if (notOnGroundMaxY >= yOnGround) return false; } } // System.out.println("*** Fetch on-ground: yOnGround=" + yOnGround + " xzM=" + xzMargin + " yM=" + yMargin + " ign=" + ignoreFlags); final boolean onGround = BlockProperties.isOnGround(blockCache, minX - xzMargin, minY - yOnGround - yMargin, minZ - xzMargin, maxX + xzMargin, minY + yMargin, maxZ + xzMargin, ignoreFlags); - if (ignoreFlags == 0){ - if (onGround){ - if (xzMargin <= 0 && yMargin == 0) onGroundMinY = Math.min(onGroundMinY, yOnGround); + if (ignoreFlags == 0) { + if (onGround) { + if (xzMargin <= 0 && yMargin == 0) { + onGroundMinY = Math.min(onGroundMinY, yOnGround); + } } - else{ - if (xzMargin >= 0) notOnGroundMaxY = Math.max(notOnGroundMaxY, yOnGround); + else { + if (xzMargin >= 0) { + notOnGroundMaxY = Math.max(notOnGroundMaxY, yOnGround); + } } } return onGround; @@ -583,7 +592,7 @@ public class PlayerLocation { * @param yMargin Extra margin added below and above. * @return */ - public boolean standsOnEntity(final double yOnGround, final double xzMargin, final double yMargin){ + public boolean standsOnEntity(final double yOnGround, final double xzMargin, final double yMargin) { return blockCache.standsOnEntity(player, minX - xzMargin, minY - yOnGround - yMargin, minZ - xzMargin, maxX + xzMargin, minY + yMargin, maxZ + xzMargin); } @@ -593,7 +602,7 @@ public class PlayerLocation { * @param yMargin * @return */ - public boolean isNextToSolid(final double xzMargin, final double yMargin){ + public boolean isNextToSolid(final double xzMargin, final double yMargin) { // TODO: Adjust to check block flags ? return BlockProperties.collides(blockCache, minX - xzMargin, minY - yMargin, minZ - xzMargin, maxX + xzMargin, maxY + yMargin, maxZ + xzMargin, BlockProperties.F_SOLID); } @@ -604,7 +613,7 @@ public class PlayerLocation { * @param yMargin * @return */ - public boolean isNextToGround(final double xzMargin, final double yMargin){ + public boolean isNextToGround(final double xzMargin, final double yMargin) { // TODO: Adjust to check block flags ? return BlockProperties.collides(blockCache, minX - xzMargin, minY - yMargin, minZ - xzMargin, maxX + xzMargin, maxY + yMargin, maxZ + xzMargin, BlockProperties.F_GROUND); } @@ -613,7 +622,7 @@ public class PlayerLocation { * Reset condition for flying checks (sf + nofall): liquids, web, ladder (not on-ground, though). * @return */ - public boolean isResetCond(){ + public boolean isResetCond() { // NOTE: if optimizing, setYOnGround has to be kept in mind. return isInLiquid() || isOnClimbable() || isInWeb(); } @@ -638,7 +647,7 @@ public class PlayerLocation { * @return */ public boolean isPassable() { - if (passable == null){ + if (passable == null) { passable = BlockProperties.isPassable(blockCache, x, y, z, getTypeId()); // passable = BlockProperties.isPassableExact(blockCache, x, y, z, getTypeId()); } @@ -784,7 +793,7 @@ public class PlayerLocation { * to have flags ready for faster denial. * @param maxYonGround */ - public void collectBlockFlags(double maxYonGround){ + public void collectBlockFlags(double maxYonGround) { maxYonGround = Math.max(yOnGround, maxYonGround); // TODO: Clearly refine this for 1.5 high blocks. // TODO: Check which checks need blocks below. @@ -845,7 +854,7 @@ public class PlayerLocation { * Set the block flags which are usually collected on base of bounding box, yOnGround and other considerations, such as 1.5 high blocks. * @param blockFlags */ - public void setBlockFlags(Long blockFlags){ + public void setBlockFlags(Long blockFlags) { this.blockFlags = blockFlags; }