Add ability to use a cache for block id and data for PlayerLocation.

This commit is contained in:
asofold 2012-10-08 04:56:53 +02:00
parent a5c37a884b
commit 5bf347ca88
2 changed files with 181 additions and 13 deletions

View File

@ -86,6 +86,8 @@ public class PlayerLocation {
/** The worldServer. */
private WorldServer worldServer;
private TypeIdCache idCache;
/**
* Gets the location.
@ -215,7 +217,7 @@ public class PlayerLocation {
.floor(boundingBox.e - 0.001D); blockY++)
for (int blockZ = (int) Math.floor(boundingBox.c + 0.001D); blockZ <= (int) Math
.floor(boundingBox.f - 0.001D); blockZ++)
if (worldServer.getTypeId(blockX, blockY, blockZ) == Material.WEB.getId())
if (getTypeId(blockX, blockY, blockZ) == Material.WEB.getId())
inWeb = true;
if (inWeb == null)
inWeb = false;
@ -254,7 +256,7 @@ public class PlayerLocation {
public boolean isOnIce() {
if (onIce == null)
if (entity.getBukkitEntity().isSneaking() || entity.getBukkitEntity().isBlocking())
onIce = worldServer.getTypeId(blockX, (int) Math.floor(boundingBox.b - 0.1D), blockZ) == Material.ICE.getId();
onIce = getTypeId(blockX, (int) Math.floor(boundingBox.b - 0.1D), blockZ) == Material.ICE.getId();
else
onIce = getTypeIdBelow() == Material.ICE.getId();
return onIce;
@ -336,18 +338,18 @@ public class PlayerLocation {
}
public Integer getTypeId() {
if (typeId == null) typeId = worldServer.getTypeId(blockX, blockY, blockZ);
if (typeId == null) typeId = getTypeId(blockX, blockY, blockZ);
return typeId;
}
public Integer getTypeIdBelow() {
if (typeIdBelow == null) typeIdBelow = worldServer.getTypeId(blockX, blockY - 1, blockZ);
if (typeIdBelow == null) typeIdBelow = getTypeId(blockX, blockY - 1, blockZ);
return typeIdBelow;
}
public Integer getData(){
if (data == null) data = worldServer.getData(blockX, blockY, blockZ);
if (data == null) data = getData(blockX, blockY, blockZ);
return data;
}
@ -358,36 +360,36 @@ public class PlayerLocation {
if ((fromData & 0x8) == 0){
// not falling.
if ((xDistance > 0)){
if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX + 1, blockY, blockZ)) && worldServer.getData(blockX + 1, blockY, blockZ) > fromData){
if (fromData < 7 && BlockProperties.isLiquid(getTypeId(blockX + 1, blockY, blockZ)) && getData(blockX + 1, blockY, blockZ) > fromData){
return true;
}
else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX - 1, blockY, blockZ)) && worldServer.getData(blockX - 1, blockY, blockZ) < fromData){
else if (fromData > 0 && BlockProperties.isLiquid(getTypeId(blockX - 1, blockY, blockZ)) && getData(blockX - 1, blockY, blockZ) < fromData){
// reverse direction.
return true;
}
} else if (xDistance < 0){
if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX - 1, blockY, blockZ)) && worldServer.getData(blockX - 1, blockY, blockZ) > fromData){
if (fromData < 7 && BlockProperties.isLiquid(getTypeId(blockX - 1, blockY, blockZ)) && getData(blockX - 1, blockY, blockZ) > fromData){
return true;
}
else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX + 1, blockY, blockZ)) && worldServer.getData(blockX + 1, blockY, blockZ) < fromData){
else if (fromData > 0 && BlockProperties.isLiquid(getTypeId(blockX + 1, blockY, blockZ)) && getData(blockX + 1, blockY, blockZ) < fromData){
// reverse direction.
return true;
}
}
if (zDistance > 0){
if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX, blockY, blockZ + 1)) && worldServer.getData(blockX, blockY, blockZ + 1) > fromData){
if (fromData < 7 && BlockProperties.isLiquid(getTypeId(blockX, blockY, blockZ + 1)) && getData(blockX, blockY, blockZ + 1) > fromData){
return true;
}
else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX , blockY, blockZ - 1)) && worldServer.getData(blockX, blockY, blockZ - 1) < fromData){
else if (fromData > 0 && BlockProperties.isLiquid(getTypeId(blockX , blockY, blockZ - 1)) && getData(blockX, blockY, blockZ - 1) < fromData){
// reverse direction.
return true;
}
}
else if (zDistance < 0 ){
if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX, blockY, blockZ - 1)) && worldServer.getData(blockX, blockY, blockZ - 1) > fromData){
if (fromData < 7 && BlockProperties.isLiquid(getTypeId(blockX, blockY, blockZ - 1)) && getData(blockX, blockY, blockZ - 1) > fromData){
return true;
}
else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX , blockY, blockZ + 1)) && worldServer.getData(blockX, blockY, blockZ + 1) < fromData){
else if (fromData > 0 && BlockProperties.isLiquid(getTypeId(blockX , blockY, blockZ + 1)) && getData(blockX, blockY, blockZ + 1) < fromData){
// reverse direction.
return true;
}
@ -400,7 +402,29 @@ public class PlayerLocation {
// Maybe make block coordinate fields later.
return blockX == other.getBlockX() && blockZ == other.getBlockZ() && blockY == other.getBlockY();
}
/**
* Uses id cache if present.
* @param x
* @param y
* @param z
* @return
*/
public final int getTypeId(final int x, final int y, final int z){
return idCache == null ? worldServer.getTypeId(x, y, z) : idCache.getTypeId(x, y, z);
}
/**
* Uses id cache if present.
* @param x
* @param y
* @param z
* @return
*/
public final int getData(final int x, final int y, final int z){
return idCache == null ? worldServer.getData(x, y, z) : idCache.getData(x, y, z);
}
/**
* TODO: temp maybe
* @return
@ -409,6 +433,14 @@ public class PlayerLocation {
return worldServer;
}
/**
* Set the id cache for faster id getting.
* @param cache
*/
public void setIdCache(final TypeIdCache cache) {
this.idCache = cache;
}
/**
* Set some references to null.
*/

View File

@ -0,0 +1,136 @@
package fr.neatmonster.nocheatplus.utilities;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.server.IBlockAccess;
import org.bukkit.World;
import org.bukkit.craftbukkit.CraftWorld;
/**
* Access to type-ids using caching techniques.
* @author mc_dev
*
*/
public class TypeIdCache {
/**
* TODO: Make a map for faster queries (without object creation).
* TODO: Not sure the prime numbers are too big for normal use.
* @author mc_dev
*
*/
private static class Pos3D{
private static final int p1 = 73856093;
private static final int p2 = 19349663;
private static final int p3 = 83492791;
// Cube coordinates:
public final int x;
public final int y;
public final int z;
public final int hash;
/**
*
* @param x
* @param y
* @param z
* @param size
*/
public Pos3D (final int x, final int y, final int z){
// Cube related coordinates:
this.x = x;
this.y = y;
this.z = z;
// Hash
hash = getHash(this.x, this.y, this.z);
}
@Override
public final boolean equals(final Object obj) {
if (obj instanceof Pos3D){
final Pos3D other = (Pos3D) obj;
return other.x == x && other.y == y && other.z == z;
}
else return false;
}
@Override
public final int hashCode() {
return hash;
}
public static final int getHash(final int x, final int y, final int z) {
return p1 * x ^ p2 * y ^ p3 * z;
}
}
/**
* For getting ids.
*/
private IBlockAccess access = null;
/** Cached type-ids. */
private final Map<Pos3D, Integer> idMap = new HashMap<Pos3D, Integer>();
/** Cahced data values. */
private final Map<Pos3D, Integer> dataMap = new HashMap<Pos3D, Integer>();
// TODO: maybe make very fast access arrays for the ray tracing checks.
// private int[] id = null;
// private int[] data = null;
public TypeIdCache(){
}
public TypeIdCache(final World world){
setAccess(world);
}
public TypeIdCache(final IBlockAccess access){
setAccess(access);
}
/**
* Does not do cleanup.
* @param world
*/
public void setAccess(final World world){
setAccess(((CraftWorld) world).getHandle());
}
/**
* Does not do cleanup.
* @param access
*/
public void setAccess(final IBlockAccess access){
this.access = access;
}
/**
* Remove references.
*/
public void cleanup(){
access = null;
idMap.clear();
dataMap.clear();
}
public Integer 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;
final Integer nId = access.getTypeId(x, y, z);
idMap.put(pos, nId);
return nId;
}
public Integer 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;
final Integer nData = access.getData(x, y, z);
dataMap.put(pos, nData);
return nData;
}
}