geforkt von Mirrors/Paper
132fdbc4ac
Due to the having to generate new logic to avoid using the customized PlayerConnection.moveToWorld, entities returning from The End were not properly calculating their exit target. This commit corrects that logic.
530 Zeilen
18 KiB
Java
530 Zeilen
18 KiB
Java
package net.minecraft.server;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Random;
|
|
|
|
// CraftBukkit start
|
|
import org.bukkit.Location;
|
|
import org.bukkit.event.entity.EntityPortalExitEvent;
|
|
import org.bukkit.util.Vector;
|
|
// CraftBukkit end
|
|
|
|
public class PortalTravelAgent {
|
|
|
|
private final WorldServer a;
|
|
private final Random b;
|
|
private final LongHashMap c = new LongHashMap();
|
|
private final List d = new ArrayList();
|
|
|
|
public PortalTravelAgent(WorldServer worldserver) {
|
|
this.a = worldserver;
|
|
this.b = new Random(worldserver.getSeed());
|
|
}
|
|
|
|
public void a(Entity entity, double d0, double d1, double d2, float f) {
|
|
if (this.a.worldProvider.dimension != 1) {
|
|
if (!this.b(entity, d0, d1, d2, f)) {
|
|
this.a(entity);
|
|
this.b(entity, d0, d1, d2, f);
|
|
}
|
|
} else {
|
|
// CraftBukkit start - modularize end portal creation
|
|
ChunkCoordinates created = this.createEndPortal(d0, d1, d2);
|
|
entity.setPositionRotation((double) created.x, (double) created.y, (double) created.z, entity.yaw, 0.0F);
|
|
entity.motX = entity.motY = entity.motZ = 0.0D;
|
|
}
|
|
}
|
|
|
|
// split out from original a(Entity, double, double, double, float) method in order to enable being called from createPortal
|
|
private ChunkCoordinates createEndPortal(double x, double y, double z) {
|
|
int i = MathHelper.floor(x);
|
|
int j = MathHelper.floor(y) - 1;
|
|
int k = MathHelper.floor(z);
|
|
// CraftBukkit end
|
|
byte b0 = 1;
|
|
byte b1 = 0;
|
|
|
|
for (int l = -2; l <= 2; ++l) {
|
|
for (int i1 = -2; i1 <= 2; ++i1) {
|
|
for (int j1 = -1; j1 < 3; ++j1) {
|
|
int k1 = i + i1 * b0 + l * b1;
|
|
int l1 = j + j1;
|
|
int i2 = k + i1 * b1 - l * b0;
|
|
boolean flag = j1 < 0;
|
|
|
|
this.a.setTypeId(k1, l1, i2, flag ? Block.OBSIDIAN.id : 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// CraftBukkit start
|
|
return new ChunkCoordinates(i, j, k);
|
|
}
|
|
|
|
// use logic based on creation to verify end portal
|
|
private ChunkCoordinates findEndPortal(ChunkCoordinates portal) {
|
|
int i = portal.x;
|
|
int j = portal.y - 1;
|
|
int k = portal.z;
|
|
byte b0 = 1;
|
|
byte b1 = 0;
|
|
|
|
for (int l = -2; l <= 2; ++l) {
|
|
for (int i1 = -2; i1 <= 2; ++i1) {
|
|
for (int j1 = -1; j1 < 3; ++j1) {
|
|
int k1 = i + i1 * b0 + l * b1;
|
|
int l1 = j + j1;
|
|
int i2 = k + i1 * b1 - l * b0;
|
|
boolean flag = j1 < 0;
|
|
|
|
if (this.a.getTypeId(k1, l1, i2) != (flag ? Block.OBSIDIAN.id : 0)) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return new ChunkCoordinates(i, j, k);
|
|
}
|
|
// CraftBukkit end
|
|
|
|
public boolean b(Entity entity, double d0, double d1, double d2, float f) {
|
|
// CraftBukkit start - modularize portal search process and entity teleportation
|
|
ChunkCoordinates found = this.findPortal(entity.locX, entity.locY, entity.locZ, 128);
|
|
if (found == null) {
|
|
return false;
|
|
}
|
|
|
|
Location exit = new Location(this.a.getWorld(), found.x, found.y, found.z, f, entity.pitch);
|
|
Vector velocity = entity.getBukkitEntity().getVelocity();
|
|
this.adjustExit(entity, exit, velocity);
|
|
entity.setPositionRotation(exit.getX(), exit.getY(), exit.getZ(), exit.getYaw(), exit.getPitch());
|
|
if (entity.motX != velocity.getX() || entity.motY != velocity.getY() || entity.motZ != velocity.getZ()) {
|
|
entity.getBukkitEntity().setVelocity(velocity);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public ChunkCoordinates findPortal(double x, double y, double z, int short1) {
|
|
if (this.a.getWorld().getEnvironment() == org.bukkit.World.Environment.THE_END) {
|
|
return this.findEndPortal(this.a.worldProvider.h());
|
|
}
|
|
// CraftBukkit end
|
|
double d3 = -1.0D;
|
|
int i = 0;
|
|
int j = 0;
|
|
int k = 0;
|
|
// CraftBukkit start
|
|
int l = MathHelper.floor(x);
|
|
int i1 = MathHelper.floor(z);
|
|
// CraftBukkit end
|
|
long j1 = ChunkCoordIntPair.a(l, i1);
|
|
boolean flag = true;
|
|
double d4;
|
|
int k1;
|
|
|
|
if (this.c.contains(j1)) {
|
|
ChunkCoordinatesPortal chunkcoordinatesportal = (ChunkCoordinatesPortal) this.c.getEntry(j1);
|
|
|
|
d3 = 0.0D;
|
|
i = chunkcoordinatesportal.x;
|
|
j = chunkcoordinatesportal.y;
|
|
k = chunkcoordinatesportal.z;
|
|
chunkcoordinatesportal.d = this.a.getTime();
|
|
flag = false;
|
|
} else {
|
|
for (k1 = l - short1; k1 <= l + short1; ++k1) {
|
|
double d5 = (double) k1 + 0.5D - x; // CraftBukkit
|
|
|
|
for (int l1 = i1 - short1; l1 <= i1 + short1; ++l1) {
|
|
double d6 = (double) l1 + 0.5D - z; // CraftBukkit
|
|
|
|
for (int i2 = this.a.P() - 1; i2 >= 0; --i2) {
|
|
if (this.a.getTypeId(k1, i2, l1) == Block.PORTAL.id) {
|
|
while (this.a.getTypeId(k1, i2 - 1, l1) == Block.PORTAL.id) {
|
|
--i2;
|
|
}
|
|
|
|
d4 = (double) i2 + 0.5D - y; // CraftBukkit
|
|
double d7 = d5 * d5 + d4 * d4 + d6 * d6;
|
|
|
|
if (d3 < 0.0D || d7 < d3) {
|
|
d3 = d7;
|
|
i = k1;
|
|
j = i2;
|
|
k = l1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (d3 >= 0.0D) {
|
|
if (flag) {
|
|
this.c.put(j1, new ChunkCoordinatesPortal(this, i, j, k, this.a.getTime()));
|
|
this.d.add(Long.valueOf(j1));
|
|
}
|
|
// CraftBukkit start - moved entity teleportation logic into exit
|
|
return new ChunkCoordinates(i, j, k);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
// entity repositioning logic split out from original b method and combined with repositioning logic for The End from original a method
|
|
public void adjustExit(Entity entity, Location position, Vector velocity) {
|
|
Location from = position.clone();
|
|
Vector before = velocity.clone();
|
|
int i = position.getBlockX();
|
|
int j = position.getBlockY();
|
|
int k = position.getBlockZ();
|
|
float f = position.getYaw();
|
|
|
|
if (this.a.getWorld().getEnvironment() == org.bukkit.World.Environment.THE_END) {
|
|
// entity.setPositionRotation((double) i, (double) j, (double) k, entity.yaw, 0.0F);
|
|
// entity.motX = entity.motY = entity.motZ = 0.0D;
|
|
position.setPitch(0.0F);
|
|
velocity.setX(0);
|
|
velocity.setY(0);
|
|
velocity.setZ(0);
|
|
} else {
|
|
double d4;
|
|
int k1;
|
|
// CraftBukkit end
|
|
|
|
double d8 = (double) i + 0.5D;
|
|
double d9 = (double) j + 0.5D;
|
|
|
|
d4 = (double) k + 0.5D;
|
|
int j2 = -1;
|
|
|
|
if (this.a.getTypeId(i - 1, j, k) == Block.PORTAL.id) {
|
|
j2 = 2;
|
|
}
|
|
|
|
if (this.a.getTypeId(i + 1, j, k) == Block.PORTAL.id) {
|
|
j2 = 0;
|
|
}
|
|
|
|
if (this.a.getTypeId(i, j, k - 1) == Block.PORTAL.id) {
|
|
j2 = 3;
|
|
}
|
|
|
|
if (this.a.getTypeId(i, j, k + 1) == Block.PORTAL.id) {
|
|
j2 = 1;
|
|
}
|
|
|
|
int k2 = entity.at();
|
|
|
|
if (j2 > -1) {
|
|
int l2 = Direction.h[j2];
|
|
int i3 = Direction.a[j2];
|
|
int j3 = Direction.b[j2];
|
|
int k3 = Direction.a[l2];
|
|
int l3 = Direction.b[l2];
|
|
boolean flag1 = !this.a.isEmpty(i + i3 + k3, j, k + j3 + l3) || !this.a.isEmpty(i + i3 + k3, j + 1, k + j3 + l3);
|
|
boolean flag2 = !this.a.isEmpty(i + i3, j, k + j3) || !this.a.isEmpty(i + i3, j + 1, k + j3);
|
|
|
|
if (flag1 && flag2) {
|
|
j2 = Direction.f[j2];
|
|
l2 = Direction.f[l2];
|
|
i3 = Direction.a[j2];
|
|
j3 = Direction.b[j2];
|
|
k3 = Direction.a[l2];
|
|
l3 = Direction.b[l2];
|
|
k1 = i - k3;
|
|
d8 -= (double) k3;
|
|
int i4 = k - l3;
|
|
|
|
d4 -= (double) l3;
|
|
flag1 = !this.a.isEmpty(k1 + i3 + k3, j, i4 + j3 + l3) || !this.a.isEmpty(k1 + i3 + k3, j + 1, i4 + j3 + l3);
|
|
flag2 = !this.a.isEmpty(k1 + i3, j, i4 + j3) || !this.a.isEmpty(k1 + i3, j + 1, i4 + j3);
|
|
}
|
|
|
|
float f1 = 0.5F;
|
|
float f2 = 0.5F;
|
|
|
|
if (!flag1 && flag2) {
|
|
f1 = 1.0F;
|
|
} else if (flag1 && !flag2) {
|
|
f1 = 0.0F;
|
|
} else if (flag1 && flag2) {
|
|
f2 = 0.0F;
|
|
}
|
|
|
|
d8 += (double) ((float) k3 * f1 + f2 * (float) i3);
|
|
d4 += (double) ((float) l3 * f1 + f2 * (float) j3);
|
|
float f3 = 0.0F;
|
|
float f4 = 0.0F;
|
|
float f5 = 0.0F;
|
|
float f6 = 0.0F;
|
|
|
|
if (j2 == k2) {
|
|
f3 = 1.0F;
|
|
f4 = 1.0F;
|
|
} else if (j2 == Direction.f[k2]) {
|
|
f3 = -1.0F;
|
|
f4 = -1.0F;
|
|
} else if (j2 == Direction.g[k2]) {
|
|
f5 = 1.0F;
|
|
f6 = -1.0F;
|
|
} else {
|
|
f5 = -1.0F;
|
|
f6 = 1.0F;
|
|
}
|
|
|
|
// CraftBukkit start
|
|
double d10 = velocity.getX();
|
|
double d11 = velocity.getZ();
|
|
// CraftBukkit end
|
|
|
|
// CraftBukkit start - adjust position and velocity instances instead of entity
|
|
velocity.setX(d10 * (double) f3 + d11 * (double) f6);
|
|
velocity.setZ(d10 * (double) f5 + d11 * (double) f4);
|
|
f = f - (float) (k2 * 90) + (float) (j2 * 90);
|
|
} else {
|
|
// entity.motX = entity.motY = entity.motZ = 0.0D;
|
|
velocity.setX(0);
|
|
velocity.setY(0);
|
|
velocity.setZ(0);
|
|
}
|
|
|
|
// entity.setPositionRotation(d8, d9, d4, entity.yaw, entity.pitch);
|
|
position.setX(d8);
|
|
position.setY(d9);
|
|
position.setZ(d4);
|
|
position.setYaw(f);
|
|
}
|
|
|
|
EntityPortalExitEvent event = new EntityPortalExitEvent(entity.getBukkitEntity(), from, position, before, velocity);
|
|
this.a.getServer().getPluginManager().callEvent(event);
|
|
Location to = event.getTo();
|
|
if (event.isCancelled() || to == null || !entity.isAlive()) {
|
|
position = from;
|
|
velocity = before;
|
|
} else {
|
|
position = to;
|
|
velocity = event.getAfter();
|
|
}
|
|
// CraftBukkit end
|
|
}
|
|
|
|
public boolean a(Entity entity) {
|
|
// CraftBukkit start - allow for portal creation to be based on coordinates instead of entity
|
|
return this.createPortal(entity.locX, entity.locY, entity.locZ, 16);
|
|
}
|
|
|
|
public boolean createPortal(double x, double y, double z, int b0) {
|
|
if (this.a.getWorld().getEnvironment() == org.bukkit.World.Environment.THE_END) {
|
|
this.createEndPortal(x, y, z);
|
|
return true;
|
|
}
|
|
// CraftBukkit end
|
|
double d0 = -1.0D;
|
|
// CraftBukkit start
|
|
int i = MathHelper.floor(x);
|
|
int j = MathHelper.floor(y);
|
|
int k = MathHelper.floor(z);
|
|
// CraftBukkit end
|
|
int l = i;
|
|
int i1 = j;
|
|
int j1 = k;
|
|
int k1 = 0;
|
|
int l1 = this.b.nextInt(4);
|
|
|
|
int i2;
|
|
double d1;
|
|
double d2;
|
|
int j2;
|
|
int k2;
|
|
int l2;
|
|
int i3;
|
|
int j3;
|
|
int k3;
|
|
int l3;
|
|
int i4;
|
|
int j4;
|
|
int k4;
|
|
double d3;
|
|
double d4;
|
|
|
|
for (i2 = i - b0; i2 <= i + b0; ++i2) {
|
|
d1 = (double) i2 + 0.5D - x; // CraftBukkit
|
|
|
|
for (j2 = k - b0; j2 <= k + b0; ++j2) {
|
|
d2 = (double) j2 + 0.5D - z; // CraftBukkit
|
|
|
|
label274:
|
|
for (k2 = this.a.P() - 1; k2 >= 0; --k2) {
|
|
if (this.a.isEmpty(i2, k2, j2)) {
|
|
while (k2 > 0 && this.a.isEmpty(i2, k2 - 1, j2)) {
|
|
--k2;
|
|
}
|
|
|
|
for (i3 = l1; i3 < l1 + 4; ++i3) {
|
|
l2 = i3 % 2;
|
|
k3 = 1 - l2;
|
|
if (i3 % 4 >= 2) {
|
|
l2 = -l2;
|
|
k3 = -k3;
|
|
}
|
|
|
|
for (j3 = 0; j3 < 3; ++j3) {
|
|
for (i4 = 0; i4 < 4; ++i4) {
|
|
for (l3 = -1; l3 < 4; ++l3) {
|
|
k4 = i2 + (i4 - 1) * l2 + j3 * k3;
|
|
j4 = k2 + l3;
|
|
int l4 = j2 + (i4 - 1) * k3 - j3 * l2;
|
|
|
|
if (l3 < 0 && !this.a.getMaterial(k4, j4, l4).isBuildable() || l3 >= 0 && !this.a.isEmpty(k4, j4, l4)) {
|
|
continue label274;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
d3 = (double) k2 + 0.5D - y; // CraftBukkit
|
|
d4 = d1 * d1 + d3 * d3 + d2 * d2;
|
|
if (d0 < 0.0D || d4 < d0) {
|
|
d0 = d4;
|
|
l = i2;
|
|
i1 = k2;
|
|
j1 = j2;
|
|
k1 = i3 % 4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (d0 < 0.0D) {
|
|
for (i2 = i - b0; i2 <= i + b0; ++i2) {
|
|
d1 = (double) i2 + 0.5D - x; // CraftBukkit
|
|
|
|
for (j2 = k - b0; j2 <= k + b0; ++j2) {
|
|
d2 = (double) j2 + 0.5D - z; // CraftBukkit
|
|
|
|
label222:
|
|
for (k2 = this.a.P() - 1; k2 >= 0; --k2) {
|
|
if (this.a.isEmpty(i2, k2, j2)) {
|
|
while (k2 > 0 && this.a.isEmpty(i2, k2 - 1, j2)) {
|
|
--k2;
|
|
}
|
|
|
|
for (i3 = l1; i3 < l1 + 2; ++i3) {
|
|
l2 = i3 % 2;
|
|
k3 = 1 - l2;
|
|
|
|
for (j3 = 0; j3 < 4; ++j3) {
|
|
for (i4 = -1; i4 < 4; ++i4) {
|
|
l3 = i2 + (j3 - 1) * l2;
|
|
k4 = k2 + i4;
|
|
j4 = j2 + (j3 - 1) * k3;
|
|
if (i4 < 0 && !this.a.getMaterial(l3, k4, j4).isBuildable() || i4 >= 0 && !this.a.isEmpty(l3, k4, j4)) {
|
|
continue label222;
|
|
}
|
|
}
|
|
}
|
|
|
|
d3 = (double) k2 + 0.5D - y; // CraftBukkit
|
|
d4 = d1 * d1 + d3 * d3 + d2 * d2;
|
|
if (d0 < 0.0D || d4 < d0) {
|
|
d0 = d4;
|
|
l = i2;
|
|
i1 = k2;
|
|
j1 = j2;
|
|
k1 = i3 % 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int i5 = l;
|
|
int j5 = i1;
|
|
|
|
j2 = j1;
|
|
int k5 = k1 % 2;
|
|
int l5 = 1 - k5;
|
|
|
|
if (k1 % 4 >= 2) {
|
|
k5 = -k5;
|
|
l5 = -l5;
|
|
}
|
|
|
|
boolean flag;
|
|
|
|
if (d0 < 0.0D) {
|
|
if (i1 < 70) {
|
|
i1 = 70;
|
|
}
|
|
|
|
if (i1 > this.a.P() - 10) {
|
|
i1 = this.a.P() - 10;
|
|
}
|
|
|
|
j5 = i1;
|
|
|
|
for (k2 = -1; k2 <= 1; ++k2) {
|
|
for (i3 = 1; i3 < 3; ++i3) {
|
|
for (l2 = -1; l2 < 3; ++l2) {
|
|
k3 = i5 + (i3 - 1) * k5 + k2 * l5;
|
|
j3 = j5 + l2;
|
|
i4 = j2 + (i3 - 1) * l5 - k2 * k5;
|
|
flag = l2 < 0;
|
|
this.a.setTypeId(k3, j3, i4, flag ? Block.OBSIDIAN.id : 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (k2 = 0; k2 < 4; ++k2) {
|
|
this.a.suppressPhysics = true;
|
|
|
|
for (i3 = 0; i3 < 4; ++i3) {
|
|
for (l2 = -1; l2 < 4; ++l2) {
|
|
k3 = i5 + (i3 - 1) * k5;
|
|
j3 = j5 + l2;
|
|
i4 = j2 + (i3 - 1) * l5;
|
|
flag = i3 == 0 || i3 == 3 || l2 == -1 || l2 == 3;
|
|
this.a.setTypeId(k3, j3, i4, flag ? Block.OBSIDIAN.id : Block.PORTAL.id);
|
|
}
|
|
}
|
|
|
|
this.a.suppressPhysics = false;
|
|
|
|
for (i3 = 0; i3 < 4; ++i3) {
|
|
for (l2 = -1; l2 < 4; ++l2) {
|
|
k3 = i5 + (i3 - 1) * k5;
|
|
j3 = j5 + l2;
|
|
i4 = j2 + (i3 - 1) * l5;
|
|
this.a.applyPhysics(k3, j3, i4, this.a.getTypeId(k3, j3, i4));
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public void a(long i) {
|
|
if (i % 100L == 0L) {
|
|
Iterator iterator = this.d.iterator();
|
|
long j = i - 600L;
|
|
|
|
while (iterator.hasNext()) {
|
|
Long olong = (Long) iterator.next();
|
|
ChunkCoordinatesPortal chunkcoordinatesportal = (ChunkCoordinatesPortal) this.c.getEntry(olong.longValue());
|
|
|
|
if (chunkcoordinatesportal == null || chunkcoordinatesportal.d < j) {
|
|
iterator.remove();
|
|
this.c.remove(olong.longValue());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|