summaryrefslogtreecommitdiffstats
path: root/src/main/java/net/minecraft/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/net/minecraft/server')
-rw-r--r--src/main/java/net/minecraft/server/EntityPlayer.java69
-rw-r--r--src/main/java/net/minecraft/server/PlayerManager.java122
-rw-r--r--src/main/java/net/minecraft/server/ServerConfigurationManager.java20
-rw-r--r--src/main/java/net/minecraft/server/WorldServer.java54
4 files changed, 238 insertions, 27 deletions
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index c7fa3a18..1146605f 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -29,6 +29,16 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
private int bO = 0;
public boolean h;
+ // CraftBukkit start - extra variables
+ private boolean viewDistanceSet;
+ private int viewDistance; // set view distance on a per player basis
+ private int actualViewDistance; // when view distance in the world changes, need to know how far I could previously see
+ public String displayName;
+ public org.bukkit.Location compassTarget;
+ public long timeOffset = 0;
+ public boolean relativeTime = true;
+ // CraftBukkit end
+
public EntityPlayer(MinecraftServer minecraftserver, World world, String s, ItemInWorldManager iteminworldmanager) {
super(world);
iteminworldmanager.player = this;
@@ -51,13 +61,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
this.height = 0.0F;
// CraftBukkit start
+ this.viewDistanceSet = false;
+ this.actualViewDistance = getViewDistance(); // set the 'current' view distance. This value will be updated any time the actual view distance changes
this.displayName = this.name;
+ // CraftBukkit end
}
- public String displayName;
- public org.bukkit.Location compassTarget;
- // CraftBukkit end
-
public void spawnIn(World world) {
super.spawnIn(world);
// CraftBukkit - world fallback code, either respawn location or global spawn
@@ -483,8 +492,6 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
}
// CraftBukkit start
- public long timeOffset = 0;
- public boolean relativeTime = true;
public long getPlayerTime() {
if (this.relativeTime) {
@@ -500,5 +507,55 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
public String toString() {
return super.toString() + "(" + this.name + " at " + this.locX + "," + this.locY + "," + this.locZ + ")";
}
+
+ public void setViewDistance(int viewDistance) {
+ if (viewDistance < 1) { // for now must set view distance to 1 or higher. 0 might be possible, but it breaks the game at the moment
+ viewDistance = 1;
+ }
+ this.viewDistance = viewDistance;
+ this.viewDistanceSet = true;
+ updateViewDistance();
+ }
+
+ public int getViewDistance() {
+ if (viewDistanceSet) {
+ return viewDistance;
+ } else {
+ return defaultViewDistance();
+ }
+ }
+
+ private int defaultViewDistance() {
+ org.bukkit.World world = getBukkitEntity().getWorld();
+ if (world != null) {
+ return world.getViewDistance();
+ } else {
+ return getBukkitEntity().getServer().getViewDistance();
+ }
+ }
+
+ public void resetViewDistance() {
+ this.viewDistanceSet = false;
+ updateViewDistance();
+ }
+
+ public boolean isViewDistanceSet() {
+ return viewDistanceSet;
+ }
+
+ /**
+ * Should be called every time the view distance might have changed.
+ * Ensures we are always aware of the current and previous view distances.
+ *
+ * synchronized so that we are always sure that we have accurately tracked the view distance changes
+ */
+ public synchronized void updateViewDistance() {
+ if (actualViewDistance == getViewDistance()) {
+ return;
+ }
+ // notify the player manager that our view distance may have changed
+ ((CraftWorld) getBukkitEntity().getWorld()).getHandle().manager.updatePlayerViewDistance(this, actualViewDistance, getViewDistance());
+ actualViewDistance = getViewDistance();
+ }
// CraftBukkit end
}
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
}
diff --git a/src/main/java/net/minecraft/server/ServerConfigurationManager.java b/src/main/java/net/minecraft/server/ServerConfigurationManager.java
index c7bb9f07..de35bc20 100644
--- a/src/main/java/net/minecraft/server/ServerConfigurationManager.java
+++ b/src/main/java/net/minecraft/server/ServerConfigurationManager.java
@@ -46,6 +46,7 @@ public class ServerConfigurationManager {
// CraftBukkit start
private CraftServer cserver;
+ private int viewDistance;
public ServerConfigurationManager(MinecraftServer minecraftserver) {
minecraftserver.server = new CraftServer(minecraftserver, this);
@@ -58,7 +59,7 @@ public class ServerConfigurationManager {
this.k = minecraftserver.a("banned-ips.txt");
this.l = minecraftserver.a("ops.txt");
this.m = minecraftserver.a("white-list.txt");
- int i = minecraftserver.propertyManager.getInt("view-distance", 10);
+ this.viewDistance = minecraftserver.propertyManager.getInt("view-distance", 10); // CraftBukkit - add field viewDistance
// CraftBukkit - removed playermanagers
this.maxPlayers = minecraftserver.propertyManager.getInt("max-players", 20);
@@ -95,7 +96,7 @@ public class ServerConfigurationManager {
public int a() {
// CraftBukkit start
if (this.server.worlds.size() == 0) {
- return this.server.propertyManager.getInt("view-distance", 10) * 16 - 16;
+ return this.viewDistance * 16 - 16; // Use field value
}
return this.server.worlds.get(0).manager.getFurthestViewableBlock();
// CraftBukkit end
@@ -637,4 +638,19 @@ public class ServerConfigurationManager {
entityplayer.updateInventory(entityplayer.defaultContainer);
entityplayer.C();
}
+
+ // CraftBukkit start - getters and setters for viewDistance
+ public void setViewDistance(int viewDistance) {
+ this.viewDistance = viewDistance;
+ }
+
+ public int getViewDistance() {
+ return viewDistance;
+ }
+
+ public void saveViewDistance() {
+ this.server.propertyManager.properties.setProperty("view-distance", Integer.toString(this.viewDistance));
+ this.server.propertyManager.savePropertiesFile();
+ }
+ // CraftBukkit end
}
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 2005a9bc..b5f3b8ff 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -21,6 +21,10 @@ public class WorldServer extends World implements BlockChangeDelegate {
public boolean canSave;
public final MinecraftServer server; // CraftBukkit - private -> public final
private EntityList G = new EntityList();
+ // CraftBukkit start - extra variables
+ private int viewDistance; // keep track of changes to view distance
+ private boolean viewDistanceSet; // ...and if any changes have been made
+ // CraftBukkit end
// CraftBukkit start - change signature
public WorldServer(MinecraftServer minecraftserver, IDataManager idatamanager, String s, int i, long j, org.bukkit.World.Environment env, ChunkGenerator gen) {
@@ -29,7 +33,9 @@ public class WorldServer extends World implements BlockChangeDelegate {
this.dimension = i;
this.pvpMode = minecraftserver.pvpMode;
- this.manager = new PlayerManager(minecraftserver, this.dimension, minecraftserver.propertyManager.getInt("view-distance", 10));
+ // use view distance from configuration manager, instead of property manager
+ // TODO allow saving view distance per world
+ this.manager = new PlayerManager(minecraftserver, this.dimension, minecraftserver.serverConfigurationManager.getViewDistance());
}
public final int dimension;
@@ -182,4 +188,50 @@ public class WorldServer extends World implements BlockChangeDelegate {
// CraftBukkit end
}
}
+
+ // CraftBukkit start - add getter and setter for view distance
+ public int getViewDistance() {
+ if (viewDistanceSet) {
+ return viewDistance;
+ } else {
+ return getServer().getViewDistance();
+ }
+ }
+
+ /**
+ * This method enforces notchian view distances. Do not set it below 3 or above 15.
+ * It is possible to set view distance per-player to any positive value.
+ * @param viewDistance the number of chunks players herein managed can see by default.
+ * @throws IllegalArgumentException If view distance is less than 3 or greater than 15
+ */
+ public void setViewDistance(int viewDistance) throws IllegalArgumentException{
+ if (viewDistance > 15) {
+ throw new IllegalArgumentException("Too big view radius!");
+ } else if (viewDistance < 3) {
+ throw new IllegalArgumentException("Too small view radius!");
+ } else {
+ this.viewDistance = viewDistance;
+ this.viewDistanceSet = true;
+ updateViewDistance();
+ }
+ }
+
+ public void resetViewDistance() {
+ viewDistanceSet = false;
+ updateViewDistance();
+ }
+
+ public boolean isViewDistanceSet() {
+ return viewDistanceSet;
+ }
+
+ public void updateViewDistance() {
+ // notify players that they may have to update their view distance
+ for (Object entityPlayerObject : this.manager.managedPlayers) {
+ if (entityPlayerObject instanceof EntityPlayer) {
+ ((EntityPlayer) entityPlayerObject).updateViewDistance();
+ }
+ }
+ }
+ // CraftBukkit end
}