From fd5b90921efcc1fcbdf8390c356af04e3bda7190 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/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java index 89f3d17f2..6c4c19244 100644 --- a/src/main/java/net/minecraft/server/EntityHuman.java +++ b/src/main/java/net/minecraft/server/EntityHuman.java @@ -75,6 +75,15 @@ public abstract class EntityHuman extends EntityLiving { // Paper start public boolean affectsSpawning = true; // Paper end + // 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 boolean fauxSleeping; diff --git a/src/main/java/net/minecraft/server/EntityTracker.java b/src/main/java/net/minecraft/server/EntityTracker.java index 70c9b1f50..0ea639228 100644 --- a/src/main/java/net/minecraft/server/EntityTracker.java +++ b/src/main/java/net/minecraft/server/EntityTracker.java @@ -200,6 +200,7 @@ public class EntityTracker { } + public void updatePlayer(EntityPlayer entityplayer) { a(entityplayer); } // Paper - OBFHELPER public void a(EntityPlayer entityplayer) { Iterator iterator = this.c.iterator(); diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java index 8478a81f5..5dbd493f4 100644 --- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java +++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java @@ -435,7 +435,7 @@ public class EntityTrackerEntry { public boolean c(EntityPlayer entityplayer) { double d0 = entityplayer.locX - (double) this.xLoc / 4096.0D; double d1 = entityplayer.locZ - (double) this.zLoc / 4096.0D; - int i = Math.min(this.e, this.f); + int i = Math.min(this.e, (entityplayer.getViewDistance() - 1) * 16); // Paper - Use player view distance API return d0 >= (double) (-i) && d0 <= (double) i && d1 >= (double) (-i) && d1 <= (double) i && this.tracker.a(entityplayer); } diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java index d975c2ccf..fb593529e 100644 --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java @@ -35,7 +35,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; @@ -265,8 +265,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)); } } @@ -285,8 +288,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) { @@ -316,7 +322,8 @@ public class PlayerChunkMap { if (d2 >= 64.0D) { int k = (int) entityplayer.d >> 4; int l = (int) entityplayer.e >> 4; - int i1 = this.j; + int i1 = entityplayer.getViewDistance(); // Paper - Player view distance API + int j1 = i - k; int k1 = j - l; @@ -360,6 +367,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) { @@ -369,36 +378,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; @@ -477,4 +505,32 @@ 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); + + //Force update entity trackers + this.getWorld().getTracker().updatePlayer(player); + } + } + // Paper end } diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java index 9e24b77ad..50b1175cc 100644 --- a/src/main/java/net/minecraft/server/SpawnerCreature.java +++ b/src/main/java/net/minecraft/server/SpawnerCreature.java @@ -44,7 +44,7 @@ public final class SpawnerCreature { boolean flag3 = true; // Spigot Start byte b0 = worldserver.spigotConfig.mobSpawnRange; - b0 = ( b0 > worldserver.spigotConfig.viewDistance ) ? (byte) worldserver.spigotConfig.viewDistance : b0; + b0 = ( b0 > entityhuman.getViewDistance() ) ? (byte) entityhuman.getViewDistance() : b0; // Paper - Use player view distance API b0 = ( b0 > 8 ) ? 8 : b0; for (int i1 = -b0; i1 <= b0; ++i1) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 8ecef3ff9..3cc16b692 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1641,6 +1641,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public boolean getAffectsSpawning() { return this.getHandle().affectsSpawning; } + + @Override + public int getViewDistance() { + return getHandle().getViewDistance(); + } + + @Override + public void setViewDistance(int viewDistance) { + ((WorldServer) getHandle().world).getPlayerChunkMap().updateViewDistance(getHandle(), viewDistance); + } // Paper end @Override diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java index 1aade75f3..f52de1023 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java @@ -108,13 +108,13 @@ public class ActivationRange int maxRange = Math.max( monsterActivationRange, animalActivationRange ); maxRange = Math.max( maxRange, miscActivationRange ); - maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); + //maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); Paper - Use player view distance API below instead for ( EntityHuman player : world.players ) { - + int playerMaxRange = maxRange = Math.min( ( player.getViewDistance() << 4 ) - 8, maxRange ); // Paper - Use player view distance API player.activatedTick = MinecraftServer.currentTick; - maxBB = player.getBoundingBox().grow( maxRange, 256, maxRange ); + maxBB = player.getBoundingBox().grow( playerMaxRange, 256, playerMaxRange ); // Paper - Use player view distance API miscBB = player.getBoundingBox().grow( miscActivationRange, 256, miscActivationRange ); animalBB = player.getBoundingBox().grow( animalActivationRange, 256, animalActivationRange ); monsterBB = player.getBoundingBox().grow( monsterActivationRange, 256, monsterActivationRange ); -- 2.18.0.windows.1