diff --git a/nmshandler/src/main/java/net/aufdemrand/denizen/nms/interfaces/ChunkHelper.java b/nmshandler/src/main/java/net/aufdemrand/denizen/nms/interfaces/ChunkHelper.java index c2e7c53f32..33d2c5bfde 100644 --- a/nmshandler/src/main/java/net/aufdemrand/denizen/nms/interfaces/ChunkHelper.java +++ b/nmshandler/src/main/java/net/aufdemrand/denizen/nms/interfaces/ChunkHelper.java @@ -4,7 +4,7 @@ public interface ChunkHelper { - void refreshChunk(Chunk chunk); + void refreshChunkSections(Chunk chunk); int[] getHeightMap(Chunk chunk); } diff --git a/plugin/src/main/java/net/aufdemrand/denizen/objects/dChunk.java b/plugin/src/main/java/net/aufdemrand/denizen/objects/dChunk.java index 48b610482a..5650cfe98c 100644 --- a/plugin/src/main/java/net/aufdemrand/denizen/objects/dChunk.java +++ b/plugin/src/main/java/net/aufdemrand/denizen/objects/dChunk.java @@ -608,6 +608,19 @@ public void run() { }.runTaskLater(DenizenAPI.getCurrentInstance(), 2); } + // <--[mechanism] + // @object dChunk + // @name refresh_chunk_sections + // @input None + // @description + // Refreshes all 16x16x16 chunk sections within the chunk. + // @tags + // None + // --> + if (mechanism.matches("refresh_chunk_sections")) { + NMSHandler.getInstance().getChunkHelper().refreshChunkSections(chunk); + } + if (!mechanism.fulfilled()) { mechanism.reportInvalid(); } diff --git a/plugin/src/main/java/net/aufdemrand/denizen/objects/dLocation.java b/plugin/src/main/java/net/aufdemrand/denizen/objects/dLocation.java index 63b4a666ab..5dbb719460 100644 --- a/plugin/src/main/java/net/aufdemrand/denizen/objects/dLocation.java +++ b/plugin/src/main/java/net/aufdemrand/denizen/objects/dLocation.java @@ -749,7 +749,6 @@ else if (type == Material.TRAP_DOOR MaterialData contents = NMSHandler.getInstance().getBlockHelper().getFlowerpotContents(getBlock()); return dMaterial.getMaterialFrom(contents.getItemType(), contents.getData()) .getAttribute(attribute.fulfill(1)); - } @@ -2206,6 +2205,8 @@ && getBlock().getState() instanceof CreatureSpawner) { // @input dMaterial // @description // Sets the contents of a flower pot. + // NOTE: Flowerpot contents will not update client-side until players refresh the chunk. + // Refresh a chunk manually with mechanism: refresh_chunk_sections for dChunk objects // @tags // // --> @@ -2213,7 +2214,6 @@ && getBlock().getState() instanceof CreatureSpawner) { if (getBlock().getType() == Material.FLOWER_POT) { MaterialData data = value.asType(dMaterial.class).getMaterialData(); NMSHandler.getInstance().getBlockHelper().setFlowerpotContents(getBlock(), data); - NMSHandler.getInstance().getChunkHelper().refreshChunk(getChunk()); } } diff --git a/v1_10_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_10_R1.java b/v1_10_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_10_R1.java index 5751e9cd61..61cd37c398 100644 --- a/v1_10_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_10_R1.java +++ b/v1_10_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_10_R1.java @@ -1,23 +1,26 @@ package net.aufdemrand.denizen.nms.helpers; import net.aufdemrand.denizen.nms.interfaces.ChunkHelper; +import net.minecraft.server.v1_10_R1.EntityPlayer; import net.minecraft.server.v1_10_R1.PacketPlayOutMapChunk; +import net.minecraft.server.v1_10_R1.PlayerChunk; import org.bukkit.Chunk; import org.bukkit.craftbukkit.v1_10_R1.CraftChunk; -import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer; -import org.bukkit.entity.Player; +import org.bukkit.craftbukkit.v1_10_R1.CraftWorld; public class ChunkHelper_v1_10_R1 implements ChunkHelper { @Override - public void refreshChunk(Chunk chunk) { - - PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 65535); - - for (Player player : chunk.getWorld().getPlayers()) { - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); + public void refreshChunkSections(Chunk chunk) { + PacketPlayOutMapChunk lowPacket = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 255); // 00000000 11111111 + PacketPlayOutMapChunk highPacket = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 65280); // 11111111 00000000 + PlayerChunk playerChunk = ((CraftWorld) chunk.getWorld()).getHandle().getPlayerChunkMap() + .getChunk(chunk.getX(), chunk.getZ()); + if (playerChunk == null) return; + for (EntityPlayer player : playerChunk.c) { + player.playerConnection.sendPacket(lowPacket); + player.playerConnection.sendPacket(highPacket); } - } @Override diff --git a/v1_11_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_11_R1.java b/v1_11_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_11_R1.java index f158a02fd2..55e6b00414 100644 --- a/v1_11_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_11_R1.java +++ b/v1_11_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_11_R1.java @@ -1,23 +1,26 @@ package net.aufdemrand.denizen.nms.helpers; import net.aufdemrand.denizen.nms.interfaces.ChunkHelper; +import net.minecraft.server.v1_11_R1.EntityPlayer; import net.minecraft.server.v1_11_R1.PacketPlayOutMapChunk; +import net.minecraft.server.v1_11_R1.PlayerChunk; import org.bukkit.Chunk; import org.bukkit.craftbukkit.v1_11_R1.CraftChunk; -import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer; -import org.bukkit.entity.Player; +import org.bukkit.craftbukkit.v1_11_R1.CraftWorld; public class ChunkHelper_v1_11_R1 implements ChunkHelper { @Override - public void refreshChunk(Chunk chunk) { - - PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 65535); - - for (Player player : chunk.getWorld().getPlayers()) { - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); + public void refreshChunkSections(Chunk chunk) { + PacketPlayOutMapChunk lowPacket = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 255); // 00000000 11111111 + PacketPlayOutMapChunk highPacket = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 65280); // 11111111 00000000 + PlayerChunk playerChunk = ((CraftWorld) chunk.getWorld()).getHandle().getPlayerChunkMap() + .getChunk(chunk.getX(), chunk.getZ()); + if (playerChunk == null) return; + for (EntityPlayer player : playerChunk.c) { + player.playerConnection.sendPacket(lowPacket); + player.playerConnection.sendPacket(highPacket); } - } @Override diff --git a/v1_12_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_12_R1.java b/v1_12_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_12_R1.java index c7e9e0d73d..379d8973ff 100644 --- a/v1_12_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_12_R1.java +++ b/v1_12_R1/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_12_R1.java @@ -1,23 +1,26 @@ package net.aufdemrand.denizen.nms.helpers; import net.aufdemrand.denizen.nms.interfaces.ChunkHelper; +import net.minecraft.server.v1_12_R1.EntityPlayer; import net.minecraft.server.v1_12_R1.PacketPlayOutMapChunk; +import net.minecraft.server.v1_12_R1.PlayerChunk; import org.bukkit.Chunk; import org.bukkit.craftbukkit.v1_12_R1.CraftChunk; -import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; -import org.bukkit.entity.Player; +import org.bukkit.craftbukkit.v1_12_R1.CraftWorld; public class ChunkHelper_v1_12_R1 implements ChunkHelper { @Override - public void refreshChunk(Chunk chunk) { - - PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 255); - - for (Player player : chunk.getWorld().getPlayers()) { - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); + public void refreshChunkSections(Chunk chunk) { + PacketPlayOutMapChunk lowPacket = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 255); // 00000000 11111111 + PacketPlayOutMapChunk highPacket = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 65280); // 11111111 00000000 + PlayerChunk playerChunk = ((CraftWorld) chunk.getWorld()).getHandle().getPlayerChunkMap() + .getChunk(chunk.getX(), chunk.getZ()); + if (playerChunk == null) return; + for (EntityPlayer player : playerChunk.c) { + player.playerConnection.sendPacket(lowPacket); + player.playerConnection.sendPacket(highPacket); } - } @Override diff --git a/v1_8_R3/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_8_R3.java b/v1_8_R3/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_8_R3.java index f748a1af35..abccb52798 100644 --- a/v1_8_R3/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_8_R3.java +++ b/v1_8_R3/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_8_R3.java @@ -1,23 +1,54 @@ package net.aufdemrand.denizen.nms.helpers; import net.aufdemrand.denizen.nms.interfaces.ChunkHelper; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.LongHashMap; import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk; +import net.minecraft.server.v1_8_R3.PlayerChunkMap; import org.bukkit.Chunk; import org.bukkit.craftbukkit.v1_8_R3.CraftChunk; -import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; -import org.bukkit.entity.Player; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; public class ChunkHelper_v1_8_R3 implements ChunkHelper { - @Override - public void refreshChunk(Chunk chunk) { + @SuppressWarnings("unchecked") + public List getPlayersWithChunkLoaded(Chunk chunk) { + PlayerChunkMap playerChunkMap = ((CraftWorld) chunk.getWorld()).getHandle().getPlayerChunkMap(); - PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), false, 65535); + if (!playerChunkMap.isChunkInUse(chunk.getX(), chunk.getZ())) { + return new ArrayList(); + } + + // Use reflection to grab list of players with the chunk loaded + try { + Field fieldMap = PlayerChunkMap.class.getDeclaredField("d"); + fieldMap.setAccessible(true); + + LongHashMap map = (LongHashMap) fieldMap.get(playerChunkMap); + long entry = (long) chunk.getX() + 2147483647L | (long) chunk.getZ() + 2147483647L << 32; + Object playerChunk = map.getEntry(entry); - for (Player player : chunk.getWorld().getPlayers()) { - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); + Field fieldPlayers = playerChunk.getClass().getDeclaredField("b"); + fieldPlayers.setAccessible(true); + + return (List) fieldPlayers.get(playerChunk); } + catch (NoSuchFieldException e) {} + catch (IllegalAccessException e) {} + + return new ArrayList(); + } + @Override + public void refreshChunkSections(Chunk chunk) { + PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), false, 65535); + for (EntityPlayer player : getPlayersWithChunkLoaded(chunk)) { + player.playerConnection.sendPacket(packet); + } } @Override diff --git a/v1_9_R2/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_9_R2.java b/v1_9_R2/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_9_R2.java index 76c9812d07..c05aeb7245 100644 --- a/v1_9_R2/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_9_R2.java +++ b/v1_9_R2/src/main/java/net/aufdemrand/denizen/nms/helpers/ChunkHelper_v1_9_R2.java @@ -1,26 +1,24 @@ package net.aufdemrand.denizen.nms.helpers; import net.aufdemrand.denizen.nms.interfaces.ChunkHelper; -import net.aufdemrand.denizencore.utilities.debugging.dB; import net.minecraft.server.v1_9_R2.*; import org.bukkit.Chunk; import org.bukkit.craftbukkit.v1_9_R2.CraftChunk; -import org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer; -import org.bukkit.entity.Player; - -import static sun.audio.AudioPlayer.player; +import org.bukkit.craftbukkit.v1_9_R2.CraftWorld; public class ChunkHelper_v1_9_R2 implements ChunkHelper { @Override - public void refreshChunk(Chunk chunk) { - - PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 65535); - - for (Player player : chunk.getWorld().getPlayers()) { - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); + public void refreshChunkSections(Chunk chunk) { + PacketPlayOutMapChunk lowPacket = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 255); // 00000000 11111111 + PacketPlayOutMapChunk highPacket = new PacketPlayOutMapChunk(((CraftChunk) chunk).getHandle(), 65280); // 11111111 00000000 + PlayerChunk playerChunk = ((CraftWorld) chunk.getWorld()).getHandle().getPlayerChunkMap() + .getChunk(chunk.getX(), chunk.getZ()); + if (playerChunk == null) return; + for (EntityPlayer player : playerChunk.c) { + player.playerConnection.sendPacket(lowPacket); + player.playerConnection.sendPacket(highPacket); } - } @Override