From b37938d4ce59d4ae17feb44e60dd1f8124c1a4d8 Mon Sep 17 00:00:00 2001 From: Byteflux Date: Wed, 2 Mar 2016 14:35:27 -0600 Subject: [PATCH] Add player view distance API diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java index dfaab774d..3058dfef0 100644 --- a/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java @@ -66,6 +66,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public boolean f; public int ping; public boolean viewingCredits; + // Paper start - Player view distance API + private int viewDistance = -1; + public int getViewDistance() { + return viewDistance == -1 ? ((WorldServer) world).getPlayerChunkMap().getViewDistance() : viewDistance; + } + public void setViewDistance(int viewDistance) { + this.viewDistance = viewDistance; + } + // Paper end // CraftBukkit start public String displayName; diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java index e4ed2e991..9627a9be0 100644 --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java @@ -47,7 +47,7 @@ public class PlayerChunkMap { private final List g = Lists.newLinkedList(); private final List h = Lists.newLinkedList(); private final List i = Lists.newArrayList(); - private int j; + private int j;public int getViewDistance() { return j; } // Paper OBFHELPER private long k; private boolean l = true; private boolean m = true; @@ -291,8 +291,11 @@ public class PlayerChunkMap { // CraftBukkit start - Load nearby chunks first List chunkList = new LinkedList(); - for (int k = i - this.j; k <= i + this.j; ++k) { - for (int l = j - this.j; l <= j + this.j; ++l) { + // Paper start - Player view distance API + int viewDistance = entityplayer.getViewDistance(); + for (int k = i - viewDistance; k <= i + viewDistance; ++k) { + for (int l = j - viewDistance; l <= j + viewDistance; ++l) { + // Paper end chunkList.add(new ChunkCoordIntPair(k, l)); } } @@ -311,8 +314,11 @@ public class PlayerChunkMap { int i = (int) entityplayer.d >> 4; int j = (int) entityplayer.e >> 4; - for (int k = i - this.j; k <= i + this.j; ++k) { - for (int l = j - this.j; l <= j + this.j; ++l) { + // Paper start - Player view distance API + int viewDistance = entityplayer.getViewDistance(); + for (int k = i - viewDistance; k <= i + viewDistance; ++k) { + for (int l = j - viewDistance; l <= j + viewDistance; ++l) { + // Paper end PlayerChunk playerchunk = this.getChunk(k, l); if (playerchunk != null) { @@ -342,7 +348,9 @@ public class PlayerChunkMap { if (d2 >= 64.0D) { int k = (int) entityplayer.d >> 4; int l = (int) entityplayer.e >> 4; - int i1 = this.j; + final int viewDistance = entityplayer.getViewDistance(); // Paper - Player view distance API + int i1 = Math.max(getViewDistance(), viewDistance); // Paper - Player view distance API + int j1 = i - k; int k1 = j - l; @@ -351,7 +359,7 @@ public class PlayerChunkMap { if (j1 != 0 || k1 != 0) { for (int l1 = i - i1; l1 <= i + i1; ++l1) { for (int i2 = j - i1; i2 <= j + i1; ++i2) { - if (!this.a(l1, i2, k, l, i1)) { + if (!this.a(l1, i2, k, l, viewDistance)) { // Paper - Player view distance API // this.c(l1, i2).a(entityplayer); chunksToLoad.add(new ChunkCoordIntPair(l1, i2)); // CraftBukkit } @@ -386,6 +394,8 @@ public class PlayerChunkMap { return playerchunk != null && playerchunk.d(entityplayer) && playerchunk.e(); } + public final void setViewDistanceForAll(int viewDistance) { this.a(viewDistance); } // Paper - OBFHELPER + // Paper start - Separate into two methods public void a(int i) { i = MathHelper.clamp(i, 3, 32); if (i != this.j) { @@ -395,36 +405,55 @@ public class PlayerChunkMap { while (iterator.hasNext()) { EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - int k = (int) entityplayer.locX >> 4; - int l = (int) entityplayer.locZ >> 4; - int i1; - int j1; - - if (j > 0) { - for (i1 = k - i; i1 <= k + i; ++i1) { - for (j1 = l - i; j1 <= l + i; ++j1) { - PlayerChunk playerchunk = this.c(i1, j1); - - if (!playerchunk.d(entityplayer)) { - playerchunk.a(entityplayer); - } + this.setViewDistance(entityplayer, i, false); // Paper - Split, don't mark sort pending, we'll handle it after + } + + this.j = i; + this.e(); + } + } + + public void setViewDistance(EntityPlayer entityplayer, int i) { + this.setViewDistance(entityplayer, i, true); // Mark sort pending by default so we don't have to remember to do so all the time + } + + // Copied from above with minor changes + public void setViewDistance(EntityPlayer entityplayer, int i, boolean markSort) { + i = MathHelper.clamp(i, 3, 32); + int oldViewDistance = entityplayer.getViewDistance(); + if (i != oldViewDistance) { + int j = i - oldViewDistance; + + int k = (int) entityplayer.locX >> 4; + int l = (int) entityplayer.locZ >> 4; + int i1; + int j1; + + if (j > 0) { + for (i1 = k - i; i1 <= k + i; ++i1) { + for (j1 = l - i; j1 <= l + i; ++j1) { + PlayerChunk playerchunk = this.c(i1, j1); + + if (!playerchunk.d(entityplayer)) { + playerchunk.a(entityplayer); } } - } else { - for (i1 = k - this.j; i1 <= k + this.j; ++i1) { - for (j1 = l - this.j; j1 <= l + this.j; ++j1) { - if (!this.a(i1, j1, k, l, i)) { - this.c(i1, j1).b(entityplayer); - } + } + } else { + for (i1 = k - oldViewDistance; i1 <= k + oldViewDistance; ++i1) { + for (j1 = l - oldViewDistance; j1 <= l + oldViewDistance; ++j1) { + if (!this.a(i1, j1, k, l, i)) { + this.c(i1, j1).b(entityplayer); } } } + if (markSort) { + this.e(); + } } - - this.j = i; - this.e(); } } + // Paper end private void e() { this.l = true; @@ -503,4 +532,29 @@ public class PlayerChunkMap { } } // CraftBukkit end + + // Paper start - Player view distance API + public void updateViewDistance(EntityPlayer player, int distanceIn) { + final int oldViewDistance = player.getViewDistance(); + + // This represents the view distance that we will set on the player + // It can exist as a negative value + int playerViewDistance = MathHelper.clamp(distanceIn, 3, 32); + + // This value is the one we actually use to update the chunk map + // We don't ever want this to be a negative + int toSet = playerViewDistance; + + if (distanceIn < 0) { + playerViewDistance = -1; + toSet = world.getPlayerChunkMap().getViewDistance(); + } + + if (toSet != oldViewDistance) { + // Order matters + this.setViewDistance(player, toSet); + player.setViewDistance(playerViewDistance); + } + } + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 44d0db180..b2b707305 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1549,6 +1549,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this.getHandle().affectsSpawning; } + @Override + public int getViewDistance() { + return getHandle().getViewDistance(); + } + + @Override + public void setViewDistance(int viewDistance) { + ((WorldServer) getHandle().world).getPlayerChunkMap().updateViewDistance(getHandle(), viewDistance); + } + // Spigot start private final Player.Spigot spigot = new Player.Spigot() { -- 2.17.0