mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-11-07 03:02:11 +01:00
Add Methods for bounding box tests. PlayerLocation: Use idCache for
more, return idCache as IBlockAccess if present. [DEBUG, Ongoing]
This commit is contained in:
parent
4025cd3e55
commit
c9427d4ff1
@ -70,7 +70,7 @@ public class MovingListener implements Listener {
|
||||
public final void set(final Player player, final Location from, final Location to, final double yOnGround){
|
||||
this.from.set(from, player, yOnGround);
|
||||
this.to.set(to, player, yOnGround);
|
||||
this.cache.setAccess(this.from.getBlockAccess());
|
||||
this.cache.setAccess(this.from.getWorldServer());
|
||||
this.from.setIdCache(cache);
|
||||
this.to.setIdCache(cache);
|
||||
}
|
||||
|
@ -247,6 +247,8 @@ public class BlockProperties {
|
||||
public static final int F_LIQUID = 0x2;
|
||||
public static final int F_SOLID = 0x4;
|
||||
public static final int F_IGN_PASSABLE = 0x8;
|
||||
public static final int F_WATER = 0x10;
|
||||
public static final int F_LAVA = 0x20;
|
||||
|
||||
static{
|
||||
init();
|
||||
@ -314,13 +316,20 @@ public class BlockProperties {
|
||||
Material.WOOD_STAIRS, Material.SPRUCE_WOOD_STAIRS, Material.BIRCH_WOOD_STAIRS, Material.JUNGLE_WOOD_STAIRS}){
|
||||
blockFlags[mat.getId()] |= F_STAIRS;
|
||||
}
|
||||
// Liquid.
|
||||
// WATER.
|
||||
for (final Material mat : new Material[]{
|
||||
Material.LAVA, Material.STATIONARY_LAVA,
|
||||
Material.STATIONARY_WATER, Material.WATER,
|
||||
}) {
|
||||
blockFlags[mat.getId()] |= F_LIQUID; // TODO: This might already be handled above now.
|
||||
blockFlags[mat.getId()] |= F_LIQUID | F_WATER;
|
||||
}
|
||||
// LAVA.
|
||||
for (final Material mat : new Material[]{
|
||||
Material.LAVA, Material.STATIONARY_LAVA,
|
||||
}) {
|
||||
blockFlags[mat.getId()] |= F_LIQUID | F_LAVA;
|
||||
}
|
||||
// Workarounds.
|
||||
blockFlags[Material.WATER_LILY.getId()] |= F_SOLID;
|
||||
// Ignore for passable.
|
||||
for (final Material mat : new Material[]{
|
||||
Material.WOOD_PLATE, Material.STONE_PLATE,
|
||||
|
@ -175,20 +175,16 @@ public class PlayerLocation {
|
||||
if (inLava == null) {
|
||||
AxisAlignedBB boundingBoxLava = boundingBox.clone();
|
||||
boundingBoxLava = boundingBoxLava.grow(-0.10000000149011612D, -0.40000000596046448D, -0.10000000149011612D);
|
||||
inLava = worldServer.a(boundingBoxLava, net.minecraft.server.Material.LAVA);
|
||||
inLava = idCache.collides(boundingBoxLava, BlockProperties.F_LAVA);
|
||||
// inLava = worldServer.a(boundingBoxLava, net.minecraft.server.Material.LAVA);
|
||||
// if (inLava.booleanValue() != idCache.collides(boundingBoxLava, BlockProperties.F_LAVA)){
|
||||
// System.out.println("INCONSISTENCY IN LAVA (" + inWater + ")."); // TODO: remove
|
||||
// System.out.println("("+ x +"," + y + "," + z + ":"+ getTypeId() + ")");
|
||||
// }
|
||||
}
|
||||
return inLava;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player is in a liquid.
|
||||
*
|
||||
* @return true, if the player is in a liquid
|
||||
*/
|
||||
public boolean isInLiquid() {
|
||||
return isInLava() || isInWater();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the player is in water.
|
||||
*
|
||||
@ -199,25 +195,45 @@ public class PlayerLocation {
|
||||
AxisAlignedBB boundingBoxWater = boundingBox.clone();
|
||||
boundingBoxWater = boundingBoxWater.grow(0.0D, -0.40000000596046448D, 0.0D);
|
||||
boundingBoxWater = boundingBoxWater.shrink(0.001D, 0.001D, 0.001D);
|
||||
inWater = worldServer.a(boundingBoxWater, net.minecraft.server.Material.WATER, entity);
|
||||
inWater = idCache.collides(boundingBoxWater, BlockProperties.F_WATER);
|
||||
// inWater = worldServer.a(boundingBoxWater, net.minecraft.server.Material.WATER, entity);
|
||||
// if (inWater.booleanValue() != idCache.collides(boundingBoxWater, BlockProperties.F_WATER)){
|
||||
// System.out.println("INCONSISTENCY IN WATER (" + inWater + ")."); // TODO: remove
|
||||
// System.out.println("("+ x +"," + y + "," + z + ":"+ getTypeId() + ")");
|
||||
// }
|
||||
}
|
||||
return inWater;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player is in a liquid.
|
||||
*
|
||||
* @return true, if the player is in a liquid
|
||||
*/
|
||||
public boolean isInLiquid() {
|
||||
// TODO: optimize (check liquid first and only if liquid check further)
|
||||
return isInLava() || isInWater();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player is in web.
|
||||
*
|
||||
* @return true, if the player is in web
|
||||
*/
|
||||
public boolean isInWeb() {
|
||||
final int webId = Material.WEB.getId();
|
||||
if (inWeb == null) {
|
||||
for (int blockX = Location.locToBlock(boundingBox.a + 0.001D); blockX <= Location.locToBlock(boundingBox.d - 0.001D); blockX++)
|
||||
for (int blockY = Location.locToBlock(boundingBox.b + 0.001D); blockY <= Location.locToBlock(boundingBox.e - 0.001D); blockY++)
|
||||
for (int blockZ = Location.locToBlock(boundingBox.c + 0.001D); blockZ <= Location.locToBlock(boundingBox.f - 0.001D); blockZ++)
|
||||
if (getTypeId(blockX, blockY, blockZ) == Material.WEB.getId())
|
||||
for (int blockX = Location.locToBlock(boundingBox.a + 0.001D); blockX <= Location.locToBlock(boundingBox.d - 0.001D); blockX++){
|
||||
for (int blockY = Location.locToBlock(boundingBox.b + 0.001D); blockY <= Location.locToBlock(boundingBox.e - 0.001D); blockY++){
|
||||
for (int blockZ = Location.locToBlock(boundingBox.c + 0.001D); blockZ <= Location.locToBlock(boundingBox.f - 0.001D); blockZ++){
|
||||
if (getTypeId(blockX, blockY, blockZ) == webId){
|
||||
inWeb = true;
|
||||
if (inWeb == null)
|
||||
inWeb = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
inWeb = false;
|
||||
}
|
||||
return inWeb;
|
||||
}
|
||||
@ -231,7 +247,13 @@ public class PlayerLocation {
|
||||
if (onGround == null) {
|
||||
AxisAlignedBB boundingBoxGround = boundingBox.clone();
|
||||
boundingBoxGround = boundingBoxGround.d(0D, -getyOnGround(), 0D);
|
||||
onGround = worldServer.getCubes(entity, boundingBoxGround).size() > 0;
|
||||
onGround = idCache.collides(boundingBoxGround, BlockProperties.F_SOLID);
|
||||
// onGround = worldServer.getCubes(entity, boundingBoxGround).size() > 0;
|
||||
// if (onGround.booleanValue() != idCache.collides(boundingBoxGround, BlockProperties.F_SOLID)){
|
||||
// System.out.println("INCONSISTENCY ON GROUND (" + onGround + ")."); // TODO: remove
|
||||
// System.out.println("("+ x +"," + y + "," + z + ":"+ getTypeId() + ")");
|
||||
// }
|
||||
// TODO: Check for entities (boats etc.)
|
||||
}
|
||||
return onGround;
|
||||
}
|
||||
@ -242,11 +264,13 @@ public class PlayerLocation {
|
||||
* @return true, if the player is on ice
|
||||
*/
|
||||
public boolean isOnIce() {
|
||||
if (onIce == null)
|
||||
if (entity.getBukkitEntity().isSneaking() || entity.getBukkitEntity().isBlocking())
|
||||
if (onIce == null){
|
||||
final org.bukkit.entity.Player entity = this.entity.getBukkitEntity();
|
||||
if (entity.isSneaking() || entity.isBlocking())
|
||||
onIce = getTypeId(blockX, Location.locToBlock(boundingBox.b - 0.1D), blockZ) == Material.ICE.getId();
|
||||
else
|
||||
onIce = getTypeIdBelow() == Material.ICE.getId();
|
||||
onIce = getTypeIdBelow().intValue() == Material.ICE.getId();
|
||||
}
|
||||
return onIce;
|
||||
}
|
||||
|
||||
@ -287,7 +311,7 @@ public class PlayerLocation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player location object.
|
||||
* Sets the player location object. Does not set or reset idCache.
|
||||
*
|
||||
* @param location
|
||||
* the location
|
||||
@ -313,6 +337,8 @@ public class PlayerLocation {
|
||||
typeId = typeIdBelow = null;
|
||||
aboveStairs = inLava = inWater = inWeb = onGround = onIce = onLadder = null;
|
||||
|
||||
// TODO: consider idCache.setAccess.
|
||||
|
||||
this.setyOnGround(yFreedom);
|
||||
}
|
||||
|
||||
@ -414,11 +440,11 @@ public class PlayerLocation {
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: temp maybe
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final IBlockAccess getBlockAccess() {
|
||||
return worldServer;
|
||||
return idCache == null ? worldServer : idCache;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -437,6 +463,11 @@ public class PlayerLocation {
|
||||
world = null;
|
||||
worldServer = null;
|
||||
boundingBox = null;
|
||||
idCache = null;
|
||||
}
|
||||
|
||||
public WorldServer getWorldServer() {
|
||||
return worldServer;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,8 +3,13 @@ package fr.neatmonster.nocheatplus.utilities;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.server.AxisAlignedBB;
|
||||
import net.minecraft.server.Block;
|
||||
import net.minecraft.server.IBlockAccess;
|
||||
import net.minecraft.server.Material;
|
||||
import net.minecraft.server.TileEntity;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
|
||||
@ -13,7 +18,7 @@ import org.bukkit.craftbukkit.CraftWorld;
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public class TypeIdCache {
|
||||
public class TypeIdCache implements IBlockAccess{
|
||||
/**
|
||||
* TODO: Make a map for faster queries (without object creation).
|
||||
* TODO: Not sure the prime numbers are too big for normal use.
|
||||
@ -114,7 +119,7 @@ public class TypeIdCache {
|
||||
}
|
||||
|
||||
|
||||
public Integer getTypeId(final int x, final int y, final int z){
|
||||
public int getTypeId(final int x, final int y, final int z){
|
||||
final Pos3D pos = new Pos3D(x, y, z);
|
||||
final Integer pId = idMap.get(pos);
|
||||
if (pId != null) return pId;
|
||||
@ -123,7 +128,7 @@ public class TypeIdCache {
|
||||
return nId;
|
||||
}
|
||||
|
||||
public Integer getData(final int x, final int y, final int z){
|
||||
public int getData(final int x, final int y, final int z){
|
||||
final Pos3D pos = new Pos3D(x, y, z);
|
||||
final Integer pData = dataMap.get(pos);
|
||||
if (pData != null) return pData;
|
||||
@ -132,5 +137,117 @@ public class TypeIdCache {
|
||||
return nData;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param box
|
||||
* @param flags Block flags (@see fr.neatmonster.nocheatplus.utilities.BlockProperties).
|
||||
* @return If any block has the flags.
|
||||
*/
|
||||
public final boolean hasAnyFlags(final AxisAlignedBB box, final long flags){
|
||||
return hasAnyFlags(box.a, box.b, box.c, box.d, box.e, box.f, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param minX
|
||||
* @param minY
|
||||
* @param minZ
|
||||
* @param maxX
|
||||
* @param maxY
|
||||
* @param maxZ
|
||||
* @param flags Block flags (@see fr.neatmonster.nocheatplus.utilities.BlockProperties).
|
||||
* @return If any block has the flags.
|
||||
*/
|
||||
public final boolean hasAnyFlags(final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final long flags){
|
||||
return hasAnyFlags(Location.locToBlock(minX), Location.locToBlock(minY), Location.locToBlock(minZ), Location.locToBlock(maxX), Location.locToBlock(maxY), Location.locToBlock(maxZ), flags);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param minX
|
||||
* @param minY
|
||||
* @param minZ
|
||||
* @param maxX
|
||||
* @param maxY
|
||||
* @param maxZ
|
||||
* @param flags Block flags (@see fr.neatmonster.nocheatplus.utilities.BlockProperties).
|
||||
* @return If any block has the flags.
|
||||
*/
|
||||
public final boolean hasAnyFlags(final int minX, int minY, final int minZ, final int maxX, final int maxY, final int maxZ, final long flags){
|
||||
for (int x = minX; x <= maxX; x++){
|
||||
for (int z = minZ; z <= maxZ; z++){
|
||||
for (int y = minY; y <= maxY; y++){
|
||||
if ((BlockProperties.getBLockFlags(getTypeId(x, y, z)) & flags) != 0) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the box collide with any block that matches the flags somehow.
|
||||
* @param box
|
||||
* @param flags
|
||||
* @return
|
||||
*/
|
||||
public final boolean collides(final AxisAlignedBB box, final long flags){
|
||||
return collides(box.a, box.b, box.c, box.d, box.e, box.f, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the box collide with any block that matches the flags somehow.
|
||||
* @param minX
|
||||
* @param minY
|
||||
* @param minZ
|
||||
* @param maxX
|
||||
* @param maxY
|
||||
* @param maxZ
|
||||
* @param flags
|
||||
* @return
|
||||
*/
|
||||
public final boolean collides(final double minX, double minY, final double minZ, final double maxX, final double maxY, final double maxZ, final long flags){
|
||||
for (int x = Location.locToBlock(minX); x <= Location.locToBlock(maxX); x++){
|
||||
for (int z = Location.locToBlock(minZ); z <= Location.locToBlock(maxZ); z++){
|
||||
for (int y = Location.locToBlock(minY); y <= Location.locToBlock(maxY); y++){
|
||||
final int id = getTypeId(x, y, z);
|
||||
if ((BlockProperties.getBLockFlags(id) & flags) != 0){
|
||||
// Might collide.
|
||||
final Block block = Block.byId[id];
|
||||
block.updateShape(this, x, y, z);
|
||||
if (minX > block.maxX + x || maxX < block.minX + x) continue;
|
||||
else if (minY > block.maxY + y || maxY < block.minY + y) continue;
|
||||
else if (minZ > block.maxZ + z || maxZ < block.minZ + z) continue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not Optimized.
|
||||
*/
|
||||
@Override
|
||||
public Material getMaterial(int arg0, int arg1, int arg2) {
|
||||
return access.getMaterial(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not optimized.
|
||||
*/
|
||||
@Override
|
||||
public TileEntity getTileEntity(int arg0, int arg1, int arg2) {
|
||||
return access.getTileEntity(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not optimized.
|
||||
*/
|
||||
@Override
|
||||
public boolean s(int arg0, int arg1, int arg2) {
|
||||
return access.s(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user