summaryrefslogtreecommitdiffstats
path: root/src/main/java/net/minecraft/server/PlayerManager.java
diff options
context:
space:
mode:
authorAndrew Ardill <andrew.ardill@gmail.com>2011-08-12 00:37:22 +1000
committerunknown <user@w.ardill@gmail.com>2011-08-15 14:57:25 +1000
commit12e377501ed7df16ce7e8de2bb99eed41d43fe4e (patch)
treefee981ec5c1d4d52c53480ebd6f392e1e3c91f31 /src/main/java/net/minecraft/server/PlayerManager.java
parenta6c03ded28b65a936003c6f4391923da75c4f7cb (diff)
downloadcraftbukkit-12e377501ed7df16ce7e8de2bb99eed41d43fe4e.tar
craftbukkit-12e377501ed7df16ce7e8de2bb99eed41d43fe4e.tar.gz
craftbukkit-12e377501ed7df16ce7e8de2bb99eed41d43fe4e.tar.lz
craftbukkit-12e377501ed7df16ce7e8de2bb99eed41d43fe4e.tar.xz
craftbukkit-12e377501ed7df16ce7e8de2bb99eed41d43fe4e.zip
Implements interface for changing the view distance.
Uses default view distance if player's view distance is not set Throws an illegal argument exception if view distance is set too high or too low. Pushes notifications of server and world view distance changes to the player. Move view distance functions from PlayerManger to WorldServer. Set player minimum view distance to 1 for now. Reset player's 'last known' position when recalculating visible chunks. Use per-player view distance in chunk distance checks
Diffstat (limited to 'src/main/java/net/minecraft/server/PlayerManager.java')
-rw-r--r--src/main/java/net/minecraft/server/PlayerManager.java122
1 files changed, 104 insertions, 18 deletions
diff --git a/src/main/java/net/minecraft/server/PlayerManager.java b/src/main/java/net/minecraft/server/PlayerManager.java
index 3dbb30d3..ab606fbb 100644
--- a/src/main/java/net/minecraft/server/PlayerManager.java
+++ b/src/main/java/net/minecraft/server/PlayerManager.java
@@ -14,15 +14,10 @@ public class PlayerManager {
private final int[][] g = new int[][] { { 1, 0}, { 0, 1}, { -1, 0}, { 0, -1}};
public PlayerManager(MinecraftServer minecraftserver, int i, int j) {
- if (j > 15) {
- throw new IllegalArgumentException("Too big view radius!");
- } else if (j < 3) {
- throw new IllegalArgumentException("Too small view radius!");
- } else {
- this.f = j;
- this.server = minecraftserver;
- this.e = i;
- }
+ // CraftBukkit start - no longer need to track view distance here, defers to the player.
+ this.server = minecraftserver;
+ this.e = i;
+ // CraftBukkit end
}
public WorldServer a() {
@@ -66,7 +61,7 @@ public class PlayerManager {
entityplayer.d = entityplayer.locX;
entityplayer.e = entityplayer.locZ;
int k = 0;
- int l = this.f;
+ int l = entityplayer.getViewDistance(); // CraftBukkit - use per-player view distance rather than this.f;
int i1 = 0;
int j1 = 0;
@@ -101,8 +96,11 @@ public class PlayerManager {
int i = (int) entityplayer.d >> 4;
int j = (int) entityplayer.e >> 4;
- for (int k = i - this.f; k <= i + this.f; ++k) {
- for (int l = j - this.f; l <= j + this.f; ++l) {
+ // CraftBukkit start - use per-player view distance instead of this.f
+ int viewDistance = entityplayer.getViewDistance();
+ for (int k = i - viewDistance; k <= i + viewDistance; ++k) {
+ for (int l = j - viewDistance; l <= j + viewDistance; ++l) {
+ // CraftBukkit end
PlayerInstance playerinstance = this.a(k, l, false);
if (playerinstance != null) {
@@ -114,12 +112,14 @@ public class PlayerManager {
this.managedPlayers.remove(entityplayer);
}
- private boolean a(int i, int j, int k, int l) {
+ // CraftBukkit start - changed signature to take a reference to a player. Allows for per-player view distance checks
+ private boolean a(int viewDistance, int i, int j, int k, int l) {
int i1 = i - k;
int j1 = j - l;
- return i1 >= -this.f && i1 <= this.f ? j1 >= -this.f && j1 <= this.f : false;
+ return i1 >= -viewDistance && i1 <= viewDistance ? j1 >= -viewDistance && j1 <= viewDistance : false; // CraftBukkit - use per-player view distance
}
+ // CraftBukkit end
public void movePlayer(EntityPlayer entityplayer) {
int i = (int) entityplayer.locX >> 4;
@@ -135,13 +135,16 @@ public class PlayerManager {
int j1 = j - l;
if (i1 != 0 || j1 != 0) {
- for (int k1 = i - this.f; k1 <= i + this.f; ++k1) {
- for (int l1 = j - this.f; l1 <= j + this.f; ++l1) {
- if (!this.a(k1, l1, k, l)) {
+ // CraftBukkit start - use per-player view distance instead of this.f
+ int viewDistance = entityplayer.getViewDistance();
+ for (int k1 = i - viewDistance; k1 <= i + viewDistance; ++k1) {
+ for (int l1 = j - viewDistance; l1 <= j + viewDistance; ++l1) {
+ if (!this.a(viewDistance, k1, l1, k, l)) { // CraftBukkit - use per-player view distance
this.a(k1, l1, true).a(entityplayer);
}
- if (!this.a(k1 - i1, l1 - j1, i, j)) {
+ if (!this.a(viewDistance, k1 - i1, l1 - j1, i, j)) { // CraftBukkit - use per-player view distance
+ // CraftBukkit end
PlayerInstance playerinstance = this.a(k1 - i1, l1 - j1, false);
if (playerinstance != null) {
@@ -182,4 +185,87 @@ public class PlayerManager {
static List b(PlayerManager playermanager) {
return playermanager.c;
}
+
+ // CraftBukkit start
+ /**
+ * This method will update references of the EntityPlayer to ensure they are being sent all and only those chunks they can see.
+ * Note that no attempt is made in this method to track the distance viewable. As such, care should be taken to ensure the
+ * EntityPlayer could indeed see as far previously as you have specified.
+ *
+ * If the chunks which the EntityPlayer can see changes, chunks will be added or removed in a spiral fashion.
+ * @param entityPlayer the EntityPlayer to update
+ * @param oldViewDistance the previous distance they could see
+ * @param newViewDistance the new distance they can see
+ */
+ public void updatePlayerViewDistance(EntityPlayer entityPlayer, int oldViewDistance, int newViewDistance) {
+ if (oldViewDistance == newViewDistance) {
+ return;
+ }
+ int chunkX = (int) entityPlayer.locX >> 4;
+ int chunkZ = (int) entityPlayer.locZ >> 4;
+
+ entityPlayer.d = entityPlayer.locX; // set the 'last known' position
+ entityPlayer.e = entityPlayer.locZ;
+
+ // Going to add/remove players from player-chunk maps in a spiral fashion
+ // This will send players new chunks they don't have, as well as stop sending chunks they shouldn't have
+ // We move in an anticlockwise fashion, and can start at any of the four corners
+ // 0 is [-1,-1]; 1 is [1,-1]; 2 is [1,1]; 3 is [-1,1];
+ int corner = 2; // TODO use the direction the player is facing to determine best start corner
+ int xStartOffset = this.g[(corner+3)%4][(corner+1)%2]; // calculate which offset to use based on corner we start in
+ int zStartOffset = this.g[(corner+2)%4][corner%2];
+ int deltaX;
+ int deltaZ;
+ int loop;
+ int loopStart;
+
+ if (newViewDistance < oldViewDistance) {
+ // Remove player from outer chunk loops in player-chunk map
+ loopStart = oldViewDistance;
+
+ for (loop = loopStart, deltaX = xStartOffset*loopStart, deltaZ = zStartOffset*loopStart;
+ loop > newViewDistance;
+ --loop, deltaX-=xStartOffset, deltaZ-=zStartOffset) {
+ for (int edge = 0; edge < 4; ++edge) {
+ int[] direction = this.g[corner++ % 4];
+
+ for (int i2 = 0; i2 < loop*2; ++i2) {
+ deltaX += direction[0];
+ deltaZ += direction[1];
+ this.removePlayerFromChunk(entityPlayer, chunkX + deltaX, chunkZ + deltaZ);
+ }
+ }
+ }
+ } else if (newViewDistance > oldViewDistance) {
+ // Add player to outer chunk loops in player-chunk map
+ loopStart = oldViewDistance + 1; // start adding outside the current outer loop
+
+ for (loop = loopStart, deltaX = xStartOffset*loopStart, deltaZ = zStartOffset*loopStart;
+ loop <= newViewDistance;
+ ++loop, deltaX+=xStartOffset, deltaZ+=zStartOffset) {
+ for (int edge = 0; edge < 4; ++edge) {
+ int[] direction = this.g[corner++ % 4];
+
+ for (int i2 = 0; i2 < loop*2; ++i2) {
+ deltaX += direction[0];
+ deltaZ += direction[1];
+ this.addPlayerToChunk(entityPlayer, chunkX + deltaX, chunkZ + deltaZ);
+ }
+ }
+ }
+ }
+ }
+
+ private void removePlayerFromChunk(EntityPlayer entityPlayer, int chunkX, int chunkZ) {
+ PlayerInstance chunkPlayerMap = this.a(chunkX, chunkZ, false); // get the chunk-player map for this chunk, don't create it if it doesn't exist yet
+ if (chunkPlayerMap != null) {
+ chunkPlayerMap.b(entityPlayer); // if the chunk-player map exists, remove the player from it.
+ }
+ }
+
+ private void addPlayerToChunk(EntityPlayer entityPlayer, int chunkX, int chunkZ) {
+ PlayerInstance chunkPlayerMap = this.a(chunkX, chunkZ, true); // get the chunk-player map for this chunk, create it if it doesn't exist yet
+ chunkPlayerMap.a(entityPlayer); // add the player to the chunk-player map
+ }
+ // CraftBukkit end
}