Skip to content

Instantly share code, notes, and snippets.

@hansihe
Last active August 29, 2015 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hansihe/737c83d68c3fb632759c to your computer and use it in GitHub Desktop.
Save hansihe/737c83d68c3fb632759c to your computer and use it in GitHub Desktop.
Minecraft portal finding algorithm
private final LongHashMap<Long, ChunkCoordinatesPortal> portalCache = new LongHashMap(); // ChunkCoord -> PortalCoord Originally named 'c', used for caching.
private final List<Long> portalChunks = new ArrayList(); // Originally named 'd', list of portal chunk coordinates (??)
public ChunkCoordinates findPortal(double xPos, double yPos, double zPos, int searchRadius) {
//Inserted
final int worldHeight = this.a.S()
// If world env is END, use spesific algorithm for that
if (this.a.getWorld().getEnvironment() == org.bukkit.World.Environment.THE_END) { // this.a instanceof WorldServer
return this.findEndPortal(this.a.worldProvider.h());
}
// CraftBukkit end
double currentClosestPortal = -1.0D; // d3
int finalX = 0; // i
int finalY = 0; // j
int finalZ = 0; // k
// CraftBukkit start
int xPosI = MathHelper.floor(xPos);
int zPosI = MathHelper.floor(zPos);
// CraftBukkit end
long chunkCoord = ChunkCoordIntPair.a(xPosI, zPosI);
boolean shouldUpdateCache = true;
double zPortalOffset;
int xSearch;
if (this.portalCache.contains(chunkCoord)) {
ChunkCoordinatesPortal cachedPortal = (ChunkCoordinatesPortal) this.portalCache.getEntry(chunkCoord);
currentClosestPortal = 0.0D;
finalX = cachedPortal.x;
finalY = cachedPortal.y;
finalZ = cachedPortal.z;
cachedPortal.d = this.a.getTime(); // this.a instanceof WorldServer (portals use the current time?)
shouldUpdateCache = false;
} else {
for (xSearch = xPosI - searchRadius; xSearch <= xPosI + searchRadius; ++xSearch) {
double xPortalOffset = (double) xSearch + 0.5D - xPos; // CraftBukkit
for (int zSearch = zPosI - searchRadius; zSearch <= zPosI + searchRadius; ++zSearch) {
double yPortalOffset = (double) zSearch + 0.5D - zPos; // CraftBukkit
for (int ySearch = worldHeight - 1; ySearch >= 0; --ySearch) {
if (this.a.getType(xSearch, ySearch, zSearch) == Blocks.PORTAL) {
while (this.a.getType(xSearch, ySearch - 1, zSearch) == Blocks.PORTAL) {
--ySearch;
}
zPortalOffset = (double) ySearch + 0.5D - yPos; // CraftBukkit
double portalDistance = xPortalOffset * xPortalOffset + zPortalOffset * zPortalOffset + yPortalOffset * yPortalOffset;
if (currentClosestPortal < 0.0D || portalDistance < currentClosestPortal) {
currentClosestPortal = portalDistance;
finalX = xSearch;
finalY = ySearch;
finalZ = zSearch;
}
}
}
}
}
}
if (currentClosestPortal >= 0.0D) {
if (shouldUpdateCache) {
this.portalCache.put(chunkCoord, new ChunkCoordinatesPortal(this, finalX, finalY, finalZ, this.a.getTime())); // this.a instanceof WorldServer
this.portalChunks.add(Long.valueOf(chunkCoord));
}
// CraftBukkit start - Moved entity teleportation logic into exit
return new ChunkCoordinates(finalX, finalY, finalZ);
} else {
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment