Add Methods for bounding box tests. PlayerLocation: Use idCache for

more, return idCache as IBlockAccess if present. [DEBUG, Ongoing]
This commit is contained in:
asofold 2012-10-08 17:50:27 +02:00
parent 4025cd3e55
commit c9427d4ff1
4 changed files with 189 additions and 32 deletions

View File

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

View File

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

View File

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

View File

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