3
0
Mirror von https://github.com/PaperMC/Paper.git synchronisiert 2024-12-20 21:40:06 +01:00
Paper/src/main/java/net/minecraft/server/EntityTrackerEntry.java
Travis Watkins f4558f5d7d [Bleeding] Hacky entity clipping fix; Fixes BUKKIT-50
Special thanks to 'trunkz' on Minecraft Forums for initial
implementation.
2012-04-02 14:17:20 -05:00

487 Zeilen
21 KiB
Java

package net.minecraft.server;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class EntityTrackerEntry {
public Entity tracker;
public int b;
public int c;
public int xLoc;
public int yLoc;
public int zLoc;
public int yRot;
public int xRot;
public int i;
public double j;
public double k;
public double l;
public int m = 0;
private double p;
private double q;
private double r;
private boolean s = false;
private boolean isMoving;
private int u = 0;
public boolean n = false;
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) {
this.tracker = entity;
this.b = i;
this.c = j;
this.isMoving = flag;
this.xLoc = MathHelper.floor(entity.locX * 32.0D);
this.yLoc = MathHelper.floor(entity.locY * 32.0D);
this.zLoc = MathHelper.floor(entity.locZ * 32.0D);
this.yRot = MathHelper.d(entity.yaw * 256.0F / 360.0F);
this.xRot = MathHelper.d(entity.pitch * 256.0F / 360.0F);
this.i = MathHelper.d(entity.ar() * 256.0F / 360.0F);
}
public boolean equals(Object object) {
return object instanceof EntityTrackerEntry ? ((EntityTrackerEntry) object).tracker.id == this.tracker.id : false;
}
public int hashCode() {
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) {
this.n = false;
if (!this.s || this.tracker.e(this.p, this.q, this.r) > 16.0D) {
this.p = this.tracker.locX;
this.q = this.tracker.locY;
this.r = this.tracker.locZ;
this.s = true;
this.n = true;
this.scanPlayers(list);
}
++this.u;
if (this.m++ % this.c == 0 || this.tracker.ce) {
int i = MathHelper.floor(this.tracker.locX * 32.0D);
int j = MathHelper.floor(this.tracker.locY * 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 i1 = MathHelper.d(this.tracker.pitch * 256.0F / 360.0F);
int j1 = i - this.xLoc;
int k1 = j - this.yLoc;
int l1 = k - this.zLoc;
Object object = null;
boolean flag = Math.abs(j1) >= 4 || Math.abs(k1) >= 4 || Math.abs(l1) >= 4;
boolean flag1 = Math.abs(l - this.yRot) >= 4 || Math.abs(i1 - this.xRot) >= 4;
// CraftBukkit start - code moved from below
if (flag) {
this.xLoc = i;
this.yLoc = j;
this.zLoc = k;
}
if (flag1) {
this.yRot = l;
this.xRot = i1;
}
// CraftBukkit end
if (j1 >= -128 && j1 < 128 && k1 >= -128 && k1 < 128 && l1 >= -128 && l1 < 128 && this.u <= 400) {
if (flag && flag1) {
object = new Packet33RelEntityMoveLook(this.tracker.id, (byte) j1, (byte) k1, (byte) l1, (byte) l, (byte) i1);
} else if (flag) {
object = new Packet31RelEntityMove(this.tracker.id, (byte) j1, (byte) k1, (byte) l1);
} else if (flag1) {
object = new Packet32EntityLook(this.tracker.id, (byte) l, (byte) i1);
}
} else {
this.u = 0;
// 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) {
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
}
if (this.isMoving) {
double d0 = this.tracker.motX - this.j;
double d1 = this.tracker.motY - this.k;
double d2 = this.tracker.motZ - this.l;
double d3 = 0.02D;
double d4 = d0 * d0 + d1 * d1 + d2 * d2;
if (d4 > d3 * d3 || d4 > 0.0D && this.tracker.motX == 0.0D && this.tracker.motY == 0.0D && this.tracker.motZ == 0.0D) {
this.j = this.tracker.motX;
this.k = this.tracker.motY;
this.l = this.tracker.motZ;
this.broadcast(new Packet28EntityVelocity(this.tracker.id, this.j, this.k, this.l));
}
}
if (object != null) {
this.broadcast((Packet) object);
}
DataWatcher datawatcher = this.tracker.getDataWatcher();
if (datawatcher.a()) {
this.broadcastIncludingSelf(new Packet40EntityMetadata(this.tracker.id, datawatcher));
}
int i2 = MathHelper.d(this.tracker.ar() * 256.0F / 360.0F);
if (Math.abs(i2 - this.i) >= 4) {
this.broadcast(new Packet35EntityHeadRotation(this.tracker.id, (byte) i2));
this.i = i2;
}
/* CraftBukkit start - code moved up
if (flag) {
this.xLoc = i;
this.yLoc = j;
this.zLoc = k;
}
if (flag1) {
this.yRot = l;
this.xRot = i1;
}
// CraftBukkit end */
}
this.tracker.ce = false;
if (this.tracker.velocityChanged) {
// CraftBukkit start - create PlayerVelocity event
boolean cancelled = false;
if (this.tracker instanceof EntityPlayer) {
org.bukkit.entity.Player player = (org.bukkit.entity.Player) this.tracker.getBukkitEntity();
org.bukkit.util.Vector velocity = player.getVelocity();
org.bukkit.event.player.PlayerVelocityEvent event = new org.bukkit.event.player.PlayerVelocityEvent(player, velocity);
this.tracker.world.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
cancelled = true;
} else if (!velocity.equals(event.getVelocity())) {
player.setVelocity(velocity);
}
}
if (!cancelled) {
this.broadcastIncludingSelf((Packet) (new Packet28EntityVelocity(this.tracker)));
}
// CraftBukkit end
this.tracker.velocityChanged = false;
}
}
public void broadcast(Packet packet) {
Iterator iterator = this.trackedPlayers.iterator();
while (iterator.hasNext()) {
EntityPlayer entityplayer = (EntityPlayer) iterator.next();
entityplayer.netServerHandler.sendPacket(packet);
}
}
public void broadcastIncludingSelf(Packet packet) {
this.broadcast(packet);
if (this.tracker instanceof EntityPlayer) {
((EntityPlayer) this.tracker).netServerHandler.sendPacket(packet);
}
}
public void a() {
this.broadcast(new Packet29DestroyEntity(this.tracker.id));
}
public void a(EntityPlayer entityplayer) {
if (this.trackedPlayers.contains(entityplayer)) {
this.trackedPlayers.remove(entityplayer);
}
}
public void updatePlayer(EntityPlayer entityplayer) {
if (entityplayer != this.tracker) {
double d0 = entityplayer.locX - (double) (this.xLoc / 32);
double d1 = entityplayer.locZ - (double) (this.zLoc / 32);
if (d0 >= (double) (-this.b) && d0 <= (double) this.b && d1 >= (double) (-this.b) && d1 <= (double) this.b) {
if (!this.trackedPlayers.contains(entityplayer)) {
// CraftBukkit start
if (tracker instanceof EntityPlayer) {
org.bukkit.entity.Player player = ((EntityPlayer) tracker).getBukkitEntity();
if (!entityplayer.getBukkitEntity().canSee(player)) {
return;
}
}
// CraftBukkit end
this.trackedPlayers.add(entityplayer);
entityplayer.netServerHandler.sendPacket(this.b());
if (this.isMoving) {
entityplayer.netServerHandler.sendPacket(new Packet28EntityVelocity(this.tracker.id, this.tracker.motX, this.tracker.motY, this.tracker.motZ));
}
ItemStack[] aitemstack = this.tracker.getEquipment();
if (aitemstack != null) {
for (int i = 0; i < aitemstack.length; ++i) {
entityplayer.netServerHandler.sendPacket(new Packet5EntityEquipment(this.tracker.id, i, aitemstack[i]));
}
}
if (this.tracker instanceof EntityHuman) {
EntityHuman entityhuman = (EntityHuman) this.tracker;
if (entityhuman.isSleeping()) {
entityplayer.netServerHandler.sendPacket(new Packet17EntityLocationAction(this.tracker, 0, MathHelper.floor(this.tracker.locX), MathHelper.floor(this.tracker.locY), MathHelper.floor(this.tracker.locZ)));
}
}
if (this.tracker instanceof EntityLiving) {
EntityLiving entityliving = (EntityLiving) this.tracker;
Iterator iterator = entityliving.getEffects().iterator();
while (iterator.hasNext()) {
MobEffect mobeffect = (MobEffect) iterator.next();
entityplayer.netServerHandler.sendPacket(new Packet41MobEffect(this.tracker.id, mobeffect));
}
}
}
} else if (this.trackedPlayers.contains(entityplayer)) {
this.trackedPlayers.remove(entityplayer);
entityplayer.netServerHandler.sendPacket(new Packet29DestroyEntity(this.tracker.id));
}
}
}
public void scanPlayers(List list) {
for (int i = 0; i < list.size(); ++i) {
this.updatePlayer((EntityPlayer) list.get(i));
}
}
private Packet b() {
if (this.tracker.dead) {
// CraftBukkit - add some information
System.out.println("Fetching addPacket for removed entity: " + this.tracker.getBukkitEntity().toString());
}
if (this.tracker instanceof EntityItem) {
EntityItem entityitem = (EntityItem) this.tracker;
Packet21PickupSpawn packet21pickupspawn = new Packet21PickupSpawn(entityitem);
entityitem.locX = (double) packet21pickupspawn.b / 32.0D;
entityitem.locY = (double) packet21pickupspawn.c / 32.0D;
entityitem.locZ = (double) packet21pickupspawn.d / 32.0D;
return packet21pickupspawn;
} else if (this.tracker instanceof EntityPlayer) {
return new Packet20NamedEntitySpawn((EntityHuman) this.tracker);
} else {
if (this.tracker instanceof EntityMinecart) {
EntityMinecart entityminecart = (EntityMinecart) this.tracker;
if (entityminecart.type == 0) {
return new Packet23VehicleSpawn(this.tracker, 10);
}
if (entityminecart.type == 1) {
return new Packet23VehicleSpawn(this.tracker, 11);
}
if (entityminecart.type == 2) {
return new Packet23VehicleSpawn(this.tracker, 12);
}
}
if (this.tracker instanceof EntityBoat) {
return new Packet23VehicleSpawn(this.tracker, 1);
} else if (this.tracker instanceof IAnimal) {
return new Packet24MobSpawn((EntityLiving) this.tracker);
} else if (this.tracker instanceof EntityEnderDragon) {
return new Packet24MobSpawn((EntityLiving) this.tracker);
} else if (this.tracker instanceof EntityFishingHook) {
return new Packet23VehicleSpawn(this.tracker, 90);
} else if (this.tracker instanceof EntityArrow) {
Entity entity = ((EntityArrow) this.tracker).shooter;
return new Packet23VehicleSpawn(this.tracker, 60, entity != null ? entity.id : this.tracker.id);
} else if (this.tracker instanceof EntitySnowball) {
return new Packet23VehicleSpawn(this.tracker, 61);
} else if (this.tracker instanceof EntityPotion) {
return new Packet23VehicleSpawn(this.tracker, 73, ((EntityPotion) this.tracker).getPotionValue());
} else if (this.tracker instanceof EntityThrownExpBottle) {
return new Packet23VehicleSpawn(this.tracker, 75);
} else if (this.tracker instanceof EntityEnderPearl) {
return new Packet23VehicleSpawn(this.tracker, 65);
} else if (this.tracker instanceof EntityEnderSignal) {
return new Packet23VehicleSpawn(this.tracker, 72);
} else {
Packet23VehicleSpawn packet23vehiclespawn;
if (this.tracker instanceof EntitySmallFireball) {
EntitySmallFireball entitysmallfireball = (EntitySmallFireball) this.tracker;
packet23vehiclespawn = null;
if (entitysmallfireball.shooter != null) {
packet23vehiclespawn = new Packet23VehicleSpawn(this.tracker, 64, entitysmallfireball.shooter.id);
} else {
packet23vehiclespawn = new Packet23VehicleSpawn(this.tracker, 64, 0);
}
packet23vehiclespawn.e = (int) (entitysmallfireball.dirX * 8000.0D);
packet23vehiclespawn.f = (int) (entitysmallfireball.dirY * 8000.0D);
packet23vehiclespawn.g = (int) (entitysmallfireball.dirZ * 8000.0D);
return packet23vehiclespawn;
} else if (this.tracker instanceof EntityFireball) {
EntityFireball entityfireball = (EntityFireball) this.tracker;
packet23vehiclespawn = null;
if (entityfireball.shooter != null) {
packet23vehiclespawn = new Packet23VehicleSpawn(this.tracker, 63, ((EntityFireball) this.tracker).shooter.id);
} else {
packet23vehiclespawn = new Packet23VehicleSpawn(this.tracker, 63, 0);
}
packet23vehiclespawn.e = (int) (entityfireball.dirX * 8000.0D);
packet23vehiclespawn.f = (int) (entityfireball.dirY * 8000.0D);
packet23vehiclespawn.g = (int) (entityfireball.dirZ * 8000.0D);
return packet23vehiclespawn;
} else if (this.tracker instanceof EntityEgg) {
return new Packet23VehicleSpawn(this.tracker, 62);
} else if (this.tracker instanceof EntityTNTPrimed) {
return new Packet23VehicleSpawn(this.tracker, 50);
} else if (this.tracker instanceof EntityEnderCrystal) {
return new Packet23VehicleSpawn(this.tracker, 51);
} else {
if (this.tracker instanceof EntityFallingBlock) {
EntityFallingBlock entityfallingblock = (EntityFallingBlock) this.tracker;
if (entityfallingblock.id == Block.SAND.id) {
return new Packet23VehicleSpawn(this.tracker, 70);
}
if (entityfallingblock.id == Block.GRAVEL.id) {
return new Packet23VehicleSpawn(this.tracker, 71);
}
if (entityfallingblock.id == Block.DRAGON_EGG.id) {
return new Packet23VehicleSpawn(this.tracker, 74);
}
}
if (this.tracker instanceof EntityPainting) {
return new Packet25EntityPainting((EntityPainting) this.tracker);
} else if (this.tracker instanceof EntityExperienceOrb) {
return new Packet26AddExpOrb((EntityExperienceOrb) this.tracker);
} else {
throw new IllegalArgumentException("Don\'t know how to add " + this.tracker.getClass() + "!");
}
}
}
}
}
public void clear(EntityPlayer entityplayer) {
if (this.trackedPlayers.contains(entityplayer)) {
this.trackedPlayers.remove(entityplayer);
entityplayer.netServerHandler.sendPacket(new Packet29DestroyEntity(this.tracker.id));
}
}
}