[Bleeding] Hacky entity clipping fix; Fixes BUKKIT-50

Special thanks to 'trunkz' on Minecraft Forums for initial
implementation.
This commit is contained in:
Travis Watkins 2012-04-02 14:17:20 -05:00 committed by Wesley Wolfe
parent a963880bd8
commit f4558f5d7d

View File

@ -29,6 +29,11 @@ public class EntityTrackerEntry {
private int u = 0; private int u = 0;
public boolean n = false; public boolean n = false;
public Set trackedPlayers = new HashSet(); public Set trackedPlayers = new HashSet();
// CraftBukkit start
public static ArrayList<AxisAlignedBB> collisions = new ArrayList<AxisAlignedBB>();
public static ArrayList<AxisAlignedBB> bigCollisions = new ArrayList<AxisAlignedBB>();
public static AxisAlignedBB entityBB = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
// CraftBukkit end
public EntityTrackerEntry(Entity entity, int i, int j, boolean flag) { public EntityTrackerEntry(Entity entity, int i, int j, boolean flag) {
this.tracker = entity; this.tracker = entity;
@ -51,6 +56,75 @@ public class EntityTrackerEntry {
return this.tracker.id; return this.tracker.id;
} }
// CraftBukkit start
private int[] fixCoords(int bigX, int bigY, int bigZ) {
final float halfWidth = this.tracker.width / 2.0F;
this.collisions.clear();
this.getCollisions(this.tracker.boundingBox, this.collisions);
// loop through all combinations of adding 0 or 1 to x, y, and z
outerloop:
for (int i = 0; i < 8; i++) {
int x = bigX + (i & 0x1);
int y = bigY + (i >> 2 & 0x1);
int z = bigZ + (i >> 1 & 0x1);
// create a bounding box for our possible match
double minXd = (x / 32.0D) - halfWidth;
double maxXd = (x / 32.0D) + halfWidth;
double minYd = (y / 32.0D) - this.tracker.height + this.tracker.bO;
double maxYd = (y / 32.0D) - this.tracker.height + this.tracker.bO + this.tracker.length;
double minZd = (z / 32.0D) - halfWidth;
double maxZd = (z / 32.0D) + halfWidth;
this.entityBB = this.entityBB.c(minXd, minYd, minZd, maxXd, maxYd, maxZd);
this.bigCollisions.clear();
this.getCollisions(entityBB, this.bigCollisions);
if (this.collisions.size() == this.bigCollisions.size()) {
for (int j = 0; j < this.collisions.size(); j++) {
AxisAlignedBB collision = this.collisions.get(j);
AxisAlignedBB bigCollision = this.bigCollisions.get(j);
if (!(collision.a == bigCollision.a && collision.b == bigCollision.b && collision.c == bigCollision.c && collision.d == bigCollision.d && collision.e == bigCollision.e && collision.f == bigCollision.f)) {
continue outerloop;
}
}
// if we make it here we got a match
return new int[] { x, y, z };
}
}
return new int[] { bigX, bigY, bigZ };
}
private void getCollisions(AxisAlignedBB bb, ArrayList collisions) {
int minX = MathHelper.floor(bb.a);
int maxX = MathHelper.floor(bb.d) + 1;
int minY = MathHelper.floor(bb.b);
int maxY = MathHelper.floor(bb.e) + 1;
int minZ = MathHelper.floor(bb.c);
int maxZ = MathHelper.floor(bb.f) + 1;
for (int curX = minX; curX <= maxX; curX++) {
for (int curZ = minZ; curZ <= maxZ; curZ++) {
if (!this.tracker.world.isLoaded(curX, 64, curZ)) {
continue;
}
for (int curY = minY; curY <= maxY; curY++) {
Block block = Block.byId[this.tracker.world.getTypeId(curX, curY, curZ)];
if (block == null) {
continue;
}
// get all bounding boxes for this block that intersect the entity
block.a(this.tracker.world, curX, curY, curZ, bb, collisions);
}
}
}
}
// CraftBukkit end
public void track(List list) { public void track(List list) {
this.n = false; this.n = false;
if (!this.s || this.tracker.e(this.p, this.q, this.r) > 16.0D) { if (!this.s || this.tracker.e(this.p, this.q, this.r) > 16.0D) {
@ -67,6 +141,14 @@ public class EntityTrackerEntry {
int i = MathHelper.floor(this.tracker.locX * 32.0D); int i = MathHelper.floor(this.tracker.locX * 32.0D);
int j = MathHelper.floor(this.tracker.locY * 32.0D); int j = MathHelper.floor(this.tracker.locY * 32.0D);
int k = MathHelper.floor(this.tracker.locZ * 32.0D); int k = MathHelper.floor(this.tracker.locZ * 32.0D);
// CraftBukkit start - fix up coordinates to prevent entities clipping through blocks
int[] fixedCoords = this.fixCoords(i, j, k);
i = fixedCoords[0];
j = fixedCoords[1];
k = fixedCoords[2];
// CraftBukkit end
int l = MathHelper.d(this.tracker.yaw * 256.0F / 360.0F); int l = MathHelper.d(this.tracker.yaw * 256.0F / 360.0F);
int i1 = MathHelper.d(this.tracker.pitch * 256.0F / 360.0F); int i1 = MathHelper.d(this.tracker.pitch * 256.0F / 360.0F);
int j1 = i - this.xLoc; int j1 = i - this.xLoc;
@ -99,15 +181,18 @@ public class EntityTrackerEntry {
} }
} else { } else {
this.u = 0; this.u = 0;
this.tracker.locX = (double) i / 32.0D;
this.tracker.locY = (double) j / 32.0D;
this.tracker.locZ = (double) k / 32.0D;
// CraftBukkit start // CraftBukkit start
// remove (redundant?) setting of entity location to avoid clipping through blocks
//this.tracker.locX = (double) i / 32.0D;
//this.tracker.locY = (double) j / 32.0D;
//this.tracker.locZ = (double) k / 32.0D;
// refresh list of who can see a player before sending teleport packet
if (this.tracker instanceof EntityPlayer) { if (this.tracker instanceof EntityPlayer) {
this.scanPlayers(new ArrayList(this.trackedPlayers)); this.scanPlayers(new ArrayList(this.trackedPlayers));
} }
object = new Packet34EntityTeleport(this.tracker.id, i, j - 1, k, (byte) l, (byte) i1); // move entities down 1 client side so they don't clip up out of boxes
// CraftBukkit end // CraftBukkit end
object = new Packet34EntityTeleport(this.tracker.id, i, j, k, (byte) l, (byte) i1);
} }
if (this.isMoving) { if (this.isMoving) {