diff --git a/Spigot-API-Patches/0140-Allow-Blocks-to-be-accessed-via-a-long-key.patch b/Spigot-API-Patches/0140-Allow-Blocks-to-be-accessed-via-a-long-key.patch new file mode 100644 index 000000000..fbaf72c96 --- /dev/null +++ b/Spigot-API-Patches/0140-Allow-Blocks-to-be-accessed-via-a-long-key.patch @@ -0,0 +1,116 @@ +From d9e2a8161436e5e69cab70d36e48a2c4900bf1fd Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Tue, 14 Aug 2018 21:42:10 -0700 +Subject: [PATCH] Allow Blocks to be accessed via a long key + +The key can be retrieved via methods Location#toBlockKey() and +Block#getBlockKey() + +World provides lookup for blocks by long key via method World#getBlockAtKey(long) + +The formatting for the key is as follows: + +10 bit y|27 bit z|27 bit x + +The y value is considered unsigned while z and x are considered two's complement + +Y range: [0, 1023] +X, Z range: [-67 108 864, 67 108 863] + +diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java +index 8dcb15fb..7e1ee875 100644 +--- a/src/main/java/org/bukkit/Location.java ++++ b/src/main/java/org/bukkit/Location.java +@@ -10,7 +10,6 @@ import org.bukkit.util.Vector; + + // Paper start + import java.util.Collection; +-import java.util.Collections; + import java.util.function.Predicate; + import org.bukkit.entity.Entity; + import org.bukkit.entity.LivingEntity; +@@ -558,6 +557,18 @@ public class Location implements Cloneable, ConfigurationSerializable { + blockLoc.setZ(getBlockZ()); + return blockLoc; + } ++ ++ // Paper Start ++ ++ /** ++ * @return The block key for this location's block location. ++ * @see Block#getBlockKey() ++ */ ++ public long toBlockKey() { ++ return ((long)getBlockX() & 0x7FFFFFF) | (((long)getBlockZ() & 0x7FFFFFF) << 27) | ((long)getBlockY() << 54); ++ } ++ // Paper End ++ + /** + * @return A new location where X/Y/Z are the center of the block + */ +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index f84f151a..3d8b4925 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -73,6 +73,23 @@ public interface World extends PluginMessageRecipient, Metadatable { + */ + public Block getBlockAt(Location location); + ++ // Paper Start ++ /** ++ * Gets the {@link Block} at the given block key ++ * ++ * @param key The block key. See {@link Block#getBlockKey()} ++ * @return Block at the key ++ * @see Location#toBlockKey() ++ * @see Block#getBlockKey() ++ */ ++ public default Block getBlockAtKey(long key) { ++ int x = (int) ((key << 37) >> 37); ++ int y = (int) (key >>> 54); ++ int z = (int) ((key << 10) >> 37); ++ return getBlockAt(x, y, z); ++ } ++ // Paper End ++ + /** + * Gets the y coordinate of the lowest block at this position such that the + * block and all blocks above it are transparent for lighting purposes. +diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukkit/block/Block.java +index 238de6f0..d700df53 100644 +--- a/src/main/java/org/bukkit/block/Block.java ++++ b/src/main/java/org/bukkit/block/Block.java +@@ -139,6 +139,30 @@ public interface Block extends Metadatable { + */ + int getZ(); + ++ // Paper Start ++ ++ /** ++ * Returns this block's coordinates packed into a long value ++ *

++ * The return value can be computed as follows: ++ *

++ * {@code long value = ((long)getX() & 0x7FFFFFF) | (((long)getZ() & 0x7FFFFFF) << 27) | ((long)getY() << 54);} ++ *

++ * And may be unpacked as follows: ++ *

++ * {@code int x = (int) ((packed << 37) >> 37);} ++ *

++ * {@code int y = (int) (packed >>> 54);} ++ *

++ * {@code int z = (int) ((packed << 10) >> 37);} ++ * ++ * @return This block's x, y, and z coordinates packed into a long value ++ */ ++ public default long getBlockKey() { ++ return ((long)getX() & 0x7FFFFFF) | (((long)getZ() & 0x7FFFFFF) << 27) | ((long)getY() << 54); ++ } ++ // Paper End ++ + /** + * Gets the Location of the block + * +-- +2.18.0 + diff --git a/Spigot-Server-Patches/0343-Optimize-BlockPosition-helper-methods.patch b/Spigot-Server-Patches/0343-Optimize-BlockPosition-helper-methods.patch new file mode 100644 index 000000000..38392cea5 --- /dev/null +++ b/Spigot-Server-Patches/0343-Optimize-BlockPosition-helper-methods.patch @@ -0,0 +1,125 @@ +From 50228d68672ea49b571450b44a52b9603bf68242 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Wed, 15 Aug 2018 12:05:12 -0700 +Subject: [PATCH] Optimize BlockPosition helper methods + +Resolves #1338 + +diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java +index f769b178c..bff8fcd47 100644 +--- a/src/main/java/net/minecraft/server/BlockPosition.java ++++ b/src/main/java/net/minecraft/server/BlockPosition.java +@@ -58,59 +58,96 @@ public class BlockPosition extends BaseBlockPosition { + } + + public BlockPosition up() { +- return this.up(1); ++ return new BlockPosition(this.getX(), this.getY() + 1, this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition up(int i) { +- return this.shift(EnumDirection.UP, i); ++ return i == 0 ? this : new BlockPosition(this.getX(), this.getY() + i, this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition down() { +- return this.down(1); ++ return new BlockPosition(this.getX(), this.getY() - 1, this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition down(int i) { +- return this.shift(EnumDirection.DOWN, i); ++ return i == 0 ? this : new BlockPosition(this.getX(), this.getY() - i, this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition north() { +- return this.north(1); ++ return new BlockPosition(this.getX(), this.getY(), this.getZ() - 1); // Paper - Optimize BlockPosition + } + + public BlockPosition north(int i) { +- return this.shift(EnumDirection.NORTH, i); ++ return i == 0 ? this : new BlockPosition(this.getX(), this.getY(), this.getZ() - i); // Paper - Optimize BlockPosition + } + + public BlockPosition south() { +- return this.south(1); ++ return new BlockPosition(this.getX(), this.getY(), this.getZ() + 1); // Paper - Optimize BlockPosition + } + + public BlockPosition south(int i) { +- return this.shift(EnumDirection.SOUTH, i); ++ return i == 0 ? this : new BlockPosition(this.getX(), this.getY(), this.getZ() + i); // Paper - Optimize BlockPosition + } + + public BlockPosition west() { +- return this.west(1); ++ return new BlockPosition(this.getX() - 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition west(int i) { +- return this.shift(EnumDirection.WEST, i); ++ return i == 0 ? this : new BlockPosition(this.getX() - i, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition east() { +- return this.east(1); ++ return new BlockPosition(this.getX() + 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition east(int i) { +- return this.shift(EnumDirection.EAST, i); ++ return i == 0 ? this : new BlockPosition(this.getX() + i, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + public BlockPosition shift(EnumDirection enumdirection) { +- return this.shift(enumdirection, 1); ++ // Paper Start - Optimize BlockPosition ++ switch(enumdirection) { ++ case UP: ++ return new BlockPosition(this.getX(), this.getY() + 1, this.getZ()); ++ case DOWN: ++ return new BlockPosition(this.getX(), this.getY() - 1, this.getZ()); ++ case NORTH: ++ return new BlockPosition(this.getX(), this.getY(), this.getZ() - 1); ++ case SOUTH: ++ return new BlockPosition(this.getX(), this.getY(), this.getZ() + 1); ++ case WEST: ++ return new BlockPosition(this.getX() - 1, this.getY(), this.getZ()); ++ case EAST: ++ return new BlockPosition(this.getX() + 1, this.getY(), this.getZ()); ++ default: ++ return new BlockPosition(this.getX() + enumdirection.getAdjacentX(), this.getY() + enumdirection.getAdjacentY(), this.getZ() + enumdirection.getAdjacentZ()); ++ } ++ // Paper End + } + + public BlockPosition shift(EnumDirection enumdirection, int i) { +- return i == 0 ? this : new BlockPosition(this.getX() + enumdirection.getAdjacentX() * i, this.getY() + enumdirection.getAdjacentY() * i, this.getZ() + enumdirection.getAdjacentZ() * i); ++ // Paper Start - Optimize BlockPosition ++ if (i == 0) { ++ return this; ++ } ++ switch(enumdirection) { ++ case UP: ++ return new BlockPosition(this.getX(), this.getY() + i, this.getZ()); ++ case DOWN: ++ return new BlockPosition(this.getX(), this.getY() - i, this.getZ()); ++ case NORTH: ++ return new BlockPosition(this.getX(), this.getY(), this.getZ() - i); ++ case SOUTH: ++ return new BlockPosition(this.getX(), this.getY(), this.getZ() + i); ++ case WEST: ++ return new BlockPosition(this.getX() - i, this.getY(), this.getZ()); ++ case EAST: ++ return new BlockPosition(this.getX() + i, this.getY(), this.getZ()); ++ default: ++ return new BlockPosition(this.getX() + enumdirection.getAdjacentX() * i, this.getY() + enumdirection.getAdjacentY() * i, this.getZ() + enumdirection.getAdjacentZ() * i); ++ } ++ // Paper End + } + + public BlockPosition a(EnumBlockRotation enumblockrotation) { +-- +2.18.0 + diff --git a/Spigot-Server-Patches/0344-Send-nearby-packets-from-world-player-list-not-serve.patch b/Spigot-Server-Patches/0344-Send-nearby-packets-from-world-player-list-not-serve.patch new file mode 100644 index 000000000..af6cc230f --- /dev/null +++ b/Spigot-Server-Patches/0344-Send-nearby-packets-from-world-player-list-not-serve.patch @@ -0,0 +1,136 @@ +From 1fd3e10ebd10b9df74b467451f1c81098e6f0e91 Mon Sep 17 00:00:00 2001 +From: Mystiflow +Date: Fri, 6 Jul 2018 13:21:30 +0100 +Subject: [PATCH] Send nearby packets from world player list not server list + + +diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java +index 7a2b219c6..41c187084 100644 +--- a/src/main/java/net/minecraft/server/PlayerList.java ++++ b/src/main/java/net/minecraft/server/PlayerList.java +@@ -1207,8 +1207,25 @@ public abstract class PlayerList { + } + + public void sendPacketNearby(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, double d3, int i, Packet packet) { +- for (int j = 0; j < this.players.size(); ++j) { +- EntityPlayer entityplayer = (EntityPlayer) this.players.get(j); ++ // Paper start - Use world list instead of server list where preferable ++ sendPacketNearby(entityhuman, d0, d1, d2, d3, i, null, packet); // Retained for compatibility ++ } ++ ++ public void sendPacketNearby(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, double d3, WorldServer world, Packet packet) { ++ sendPacketNearby(entityhuman, d0, d1, d2, d3, world.dimension, world, packet); ++ } ++ ++ public void sendPacketNearby(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, double d3, int i, @Nullable WorldServer world, Packet packet) { ++ if (world == null && entityhuman != null && entityhuman.world instanceof WorldServer) { ++ world = (WorldServer) entityhuman.world; ++ } ++ ++ List players1 = world == null ? players : world.players; ++ for (int j = 0; j < players1.size(); ++j) { ++ EntityHuman entity = players1.get(j); ++ if (!(entity instanceof EntityPlayer)) continue; ++ EntityPlayer entityplayer = (EntityPlayer) players1.get(j); ++ // Paper end + + // CraftBukkit start - Test if player receiving packet can see the source of the packet + if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { +@@ -1216,7 +1233,7 @@ public abstract class PlayerList { + } + // CraftBukkit end + +- if (entityplayer != entityhuman && entityplayer.dimension == i) { ++ if (entityplayer != entityhuman && (world != null || entityplayer.dimension == i)) { // Paper + double d4 = d0 - entityplayer.locX; + double d5 = d1 - entityplayer.locY; + double d6 = d2 - entityplayer.locZ; +diff --git a/src/main/java/net/minecraft/server/WorldManager.java b/src/main/java/net/minecraft/server/WorldManager.java +index e26405d34..23f390c22 100644 +--- a/src/main/java/net/minecraft/server/WorldManager.java ++++ b/src/main/java/net/minecraft/server/WorldManager.java +@@ -35,8 +35,8 @@ public class WorldManager implements IWorldAccess { + } + + public void a(@Nullable EntityHuman entityhuman, SoundEffect soundeffect, SoundCategory soundcategory, double d0, double d1, double d2, float f, float f1) { +- // CraftBukkit - this.world.dimension +- this.a.getPlayerList().sendPacketNearby(entityhuman, d0, d1, d2, f > 1.0F ? (double) (16.0F * f) : 16.0D, this.world.dimension, new PacketPlayOutNamedSoundEffect(soundeffect, soundcategory, d0, d1, d2, f, f1)); ++ // CraftBukkit - this.world.dimension, // Paper - this.world.dimension -> this.world ++ this.a.getPlayerList().sendPacketNearby(entityhuman, d0, d1, d2, f > 1.0F ? (double) (16.0F * f) : 16.0D, this.world, new PacketPlayOutNamedSoundEffect(soundeffect, soundcategory, d0, d1, d2, f, f1)); + } + + public void a(int i, int j, int k, int l, int i1, int j1) {} +@@ -51,7 +51,7 @@ public class WorldManager implements IWorldAccess { + + public void a(EntityHuman entityhuman, int i, BlockPosition blockposition, int j) { + // CraftBukkit - this.world.dimension +- this.a.getPlayerList().sendPacketNearby(entityhuman, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 64.0D, this.world.dimension, new PacketPlayOutWorldEvent(i, blockposition, j, false)); ++ this.a.getPlayerList().sendPacketNearby(entityhuman, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 64.0D, this.world, new PacketPlayOutWorldEvent(i, blockposition, j, false)); + } + + public void a(int i, BlockPosition blockposition, int j) { +@@ -59,7 +59,7 @@ public class WorldManager implements IWorldAccess { + } + + public void b(int i, BlockPosition blockposition, int j) { +- Iterator iterator = this.a.getPlayerList().v().iterator(); ++ // Iterator iterator = this.a.getPlayerList().v().iterator(); // Paper + + // CraftBukkit start + EntityHuman entityhuman = null; +@@ -67,8 +67,14 @@ public class WorldManager implements IWorldAccess { + if (entity instanceof EntityHuman) entityhuman = (EntityHuman) entity; + // CraftBukkit end + ++ // Paper start ++ java.util.List list = entity != null ? entity.world.players : this.a.getPlayerList().v(); ++ Iterator iterator = list.iterator(); + while (iterator.hasNext()) { +- EntityPlayer entityplayer = (EntityPlayer) iterator.next(); ++ EntityHuman human = iterator.next(); ++ if (!(human instanceof EntityPlayer)) continue; ++ EntityPlayer entityplayer = (EntityPlayer) human; ++ // Paper end + + if (entityplayer != null && entityplayer.world == this.world && entityplayer.getId() != i) { + double d0 = (double) blockposition.getX() - entityplayer.locX; +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index f5911fbf0..377831cdf 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -1087,7 +1087,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { + } + // CraftBukkit end + if (super.strikeLightning(entity)) { +- this.server.getPlayerList().sendPacketNearby((EntityHuman) null, entity.locX, entity.locY, entity.locZ, 512.0D, dimension, new PacketPlayOutSpawnEntityWeather(entity)); // CraftBukkit - Use dimension ++ this.server.getPlayerList().sendPacketNearby((EntityHuman) null, entity.locX, entity.locY, entity.locZ, 512.0D, this, new PacketPlayOutSpawnEntityWeather(entity)); // CraftBukkit - Use dimension, // Paper - use world instead of dimension + return true; + } else { + return false; +@@ -1147,8 +1147,8 @@ public class WorldServer extends World implements IAsyncTaskHandler { + BlockActionData blockactiondata = (BlockActionData) this.d.removeFirst(); + + if (this.a(blockactiondata)) { +- // CraftBukkit - this.worldProvider.dimension -> this.dimension +- this.server.getPlayerList().sendPacketNearby((EntityHuman) null, (double) blockactiondata.a().getX(), (double) blockactiondata.a().getY(), (double) blockactiondata.a().getZ(), 64.0D, dimension, new PacketPlayOutBlockAction(blockactiondata.a(), blockactiondata.b(), blockactiondata.c(), blockactiondata.d())); ++ // CraftBukkit - this.worldProvider.dimension -> this.dimension, // Paper - dimension -> world ++ this.server.getPlayerList().sendPacketNearby((EntityHuman) null, (double) blockactiondata.a().getX(), (double) blockactiondata.a().getY(), (double) blockactiondata.a().getZ(), 64.0D, this, new PacketPlayOutBlockAction(blockactiondata.a(), blockactiondata.b(), blockactiondata.c(), blockactiondata.d())); + } + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index b09f0353a..aa0b1f5fa 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -1519,7 +1519,7 @@ public class CraftWorld implements World { + double z = loc.getZ(); + + PacketPlayOutCustomSoundEffect packet = new PacketPlayOutCustomSoundEffect(new MinecraftKey(sound), SoundCategory.valueOf(category.name()), new Vec3D(x, y, z), volume, pitch); +- world.getMinecraftServer().getPlayerList().sendPacketNearby(null, x, y, z, volume > 1.0F ? 16.0F * volume : 16.0D, this.world.dimension, packet); ++ world.getMinecraftServer().getPlayerList().sendPacketNearby(null, x, y, z, volume > 1.0F ? 16.0F * volume : 16.0D, this.world, packet); // Paper - this.world.dimension -> this.world + } + + public String getGameRuleValue(String rule) { +-- +2.18.0 +