diff --git a/main/src/main/java/net/citizensnpcs/EventListen.java b/main/src/main/java/net/citizensnpcs/EventListen.java index 4d14e9e66..d53ae6143 100644 --- a/main/src/main/java/net/citizensnpcs/EventListen.java +++ b/main/src/main/java/net/citizensnpcs/EventListen.java @@ -106,7 +106,6 @@ import net.citizensnpcs.trait.ClickRedirectTrait; import net.citizensnpcs.trait.CommandTrait; import net.citizensnpcs.trait.Controllable; import net.citizensnpcs.trait.CurrentLocation; -import net.citizensnpcs.trait.ScoreboardTrait; import net.citizensnpcs.trait.ShopTrait; import net.citizensnpcs.trait.SitTrait; import net.citizensnpcs.util.ChunkCoord; @@ -510,8 +509,7 @@ public class EventListen implements Listener { public void onPlayerJoin(PlayerJoinEvent event) { skinUpdateTracker.updatePlayer(event.getPlayer(), Setting.INITIAL_PLAYER_JOIN_SKIN_PACKET_DELAY_TICKS.asInt(), true); - - ScoreboardTrait.onPlayerJoin(event); + CitizensAPI.getLocationLookup().onJoin(event); } @EventHandler(ignoreCancelled = true) @@ -543,7 +541,7 @@ public class EventListen implements Listener { } } skinUpdateTracker.removePlayer(event.getPlayer().getUniqueId()); - ScoreboardTrait.onPlayerQuit(event); + CitizensAPI.getLocationLookup().onQuit(event); } @EventHandler(priority = EventPriority.MONITOR) diff --git a/main/src/main/java/net/citizensnpcs/trait/ScoreboardTrait.java b/main/src/main/java/net/citizensnpcs/trait/ScoreboardTrait.java index 0cf1016a4..5d2f78dbd 100644 --- a/main/src/main/java/net/citizensnpcs/trait/ScoreboardTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/ScoreboardTrait.java @@ -3,23 +3,18 @@ package net.citizensnpcs.trait; import java.util.HashSet; import java.util.Iterator; import java.util.Set; -import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Team; import org.bukkit.scoreboard.Team.Option; import org.bukkit.scoreboard.Team.OptionStatus; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.SetMultimap; - import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.LocationLookup.PerPlayerMetadata; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.trait.Trait; @@ -32,13 +27,25 @@ public class ScoreboardTrait extends Trait { private boolean changed; @Persist private ChatColor color; + private final PerPlayerMetadata metadata; private ChatColor previousGlowingColor; - @Persist private final Set tags = new HashSet(); public ScoreboardTrait() { super("scoreboardtrait"); + metadata = CitizensAPI.getLocationLookup().registerMetadata("scoreboard", (meta, event) -> { + for (NPC npc : CitizensAPI.getNPCRegistry()) { + ScoreboardTrait trait = npc.getTraitNullable(ScoreboardTrait.class); + if (trait == null) + continue; + Team team = trait.getTeam(); + if (team == null || meta.sent.containsEntry(event.getPlayer().getUniqueId(), team.getName())) + continue; + NMS.sendTeamPacket(event.getPlayer(), team, 0); + meta.sent.put(event.getPlayer().getUniqueId(), team.getName()); + } + }); } public void addTag(String tag) { @@ -87,7 +94,7 @@ public class ScoreboardTrait extends Trait { if (team.hasEntry(name)) { if (team.getSize() == 1) { for (Player player : Bukkit.getOnlinePlayers()) { - SENT_TEAMS.remove(player.getUniqueId(), team.getName()); + metadata.sent.remove(player.getUniqueId(), team.getName()); NMS.sendTeamPacket(player, team, 1); } team.unregister(); @@ -215,34 +222,16 @@ public class ScoreboardTrait extends Trait { for (Player player : Bukkit.getOnlinePlayers()) { if (player.hasMetadata("NPC")) continue; - if (SENT_TEAMS.containsEntry(player.getUniqueId(), team.getName())) { + if (metadata.sent.containsEntry(player.getUniqueId(), team.getName())) { NMS.sendTeamPacket(player, team, 2); } else { NMS.sendTeamPacket(player, team, 0); - SENT_TEAMS.put(player.getUniqueId(), team.getName()); + metadata.sent.put(player.getUniqueId(), team.getName()); } } } } - public static void onPlayerJoin(PlayerJoinEvent event) { - for (NPC npc : CitizensAPI.getNPCRegistry()) { - ScoreboardTrait trait = npc.getTraitNullable(ScoreboardTrait.class); - if (trait == null) - continue; - Team team = trait.getTeam(); - if (team == null || SENT_TEAMS.containsEntry(event.getPlayer().getUniqueId(), team.getName())) - continue; - NMS.sendTeamPacket(event.getPlayer(), team, 0); - SENT_TEAMS.put(event.getPlayer().getUniqueId(), team.getName()); - } - } - - public static void onPlayerQuit(PlayerQuitEvent event) { - SENT_TEAMS.removeAll(event.getPlayer().getUniqueId()); - } - - private static SetMultimap SENT_TEAMS = HashMultimap.create(); private static boolean SUPPORT_COLLIDABLE_SETOPTION = true; private static boolean SUPPORT_GLOWING_COLOR = true; private static boolean SUPPORT_TAGS = true; diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java index c1fc8f974..d05f4ef2d 100644 --- a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java +++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/NMSImpl.java @@ -21,6 +21,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.World; +import org.bukkit.block.BlockFace; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; import org.bukkit.boss.BossBar; @@ -67,6 +68,7 @@ import com.mojang.util.UUIDTypeAdapter; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.LocationLookup.PerPlayerMetadata; import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; @@ -1199,19 +1201,55 @@ public class NMSImpl implements NMSBridge { @Override public void sleep(Player entity, boolean sleep) { - EntityPlayer player = (EntityPlayer) getHandle(entity); + EntityPlayer from = (EntityPlayer) getHandle(entity); + PerPlayerMetadata meta = CitizensAPI.getLocationLookup().registerMetadata("sleeping", null); if (sleep) { - Location loc = player.getBukkitEntity().getLocation(); - PacketPlayOutBed bed = new PacketPlayOutBed(player, - new BlockPosition((int) player.locX, (int) player.locY, (int) player.locZ)); - for (Player nearby : CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64)) { - nearby.sendBlockChange(loc, Material.BED.getId(), (byte) 11); - sendPacket(nearby, bed); - nearby.sendBlockChange(loc, 0, (byte) 0); + List nearbyPlayers = Lists.newArrayList( + Iterables.filter(CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64), + (p) -> !meta.sent.containsEntry(p.getUniqueId(), entity.getUniqueId().toString()))); + if (nearbyPlayers.size() == 0) + return; + Location loc = from.getBukkitEntity().getLocation().clone(); + BlockFace[] axis = { BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST }; + BlockFace facing = axis[Math.round(loc.getYaw() / 90f) & 0x3].getOppositeFace(); + byte facingByte = 0; + switch (facing) { + case EAST: + facingByte = (byte) 1; + break; + case SOUTH: + facingByte = (byte) 2; + break; + case WEST: + facingByte = (byte) 3; + break; + } + Location bedLoc = loc.clone().add(0, -loc.getY(), 0); + PacketPlayOutBed bed = new PacketPlayOutBed(from, + new BlockPosition(bedLoc.getBlockX(), bedLoc.getBlockY(), bedLoc.getBlockZ())); + List> list = Lists.newArrayListWithCapacity(3); + from.locX = bedLoc.getBlockX(); + from.locY = bedLoc.getBlockY(); + from.locZ = bedLoc.getBlockZ(); + list.add(new PacketPlayOutEntityTeleport(from)); + list.add(bed); + from.locX = loc.getX(); + from.locY = loc.getY(); + from.locZ = loc.getZ(); + list.add(new PacketPlayOutEntityTeleport(from)); + for (Player nearby : nearbyPlayers) { + nearby.sendBlockChange(bedLoc, Material.BED_BLOCK, facingByte); + list.forEach((packet) -> sendPacket(nearby, packet)); + meta.sent.put(nearby.getUniqueId(), entity.getUniqueId().toString()); } } else { - PacketPlayOutAnimation packet = new PacketPlayOutAnimation(player, 2); + PacketPlayOutAnimation packet = new PacketPlayOutAnimation(from, 2); sendPacketNearby(entity, entity.getLocation(), packet, 64); + for (Player player : Bukkit.getOnlinePlayers()) { + if (meta.sent.remove(player.getUniqueId(), entity.getUniqueId().toString())) { + sendPacket(player, packet); + } + } } } diff --git a/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java b/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java index a75575b8b..e69b237bc 100644 --- a/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java +++ b/v1_11_R1/src/main/java/net/citizensnpcs/nms/v1_11_R1/util/NMSImpl.java @@ -21,6 +21,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.World; +import org.bukkit.block.BlockFace; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; import org.bukkit.boss.BossBar; @@ -67,6 +68,7 @@ import com.mojang.util.UUIDTypeAdapter; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.LocationLookup.PerPlayerMetadata; import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; @@ -1266,19 +1268,55 @@ public class NMSImpl implements NMSBridge { @Override public void sleep(Player entity, boolean sleep) { - EntityPlayer player = (EntityPlayer) getHandle(entity); + EntityPlayer from = (EntityPlayer) getHandle(entity); + PerPlayerMetadata meta = CitizensAPI.getLocationLookup().registerMetadata("sleeping", null); if (sleep) { - Location loc = player.getBukkitEntity().getLocation(); - PacketPlayOutBed bed = new PacketPlayOutBed(player, - new BlockPosition((int) player.locX, (int) player.locY, (int) player.locZ)); - for (Player nearby : CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64)) { - nearby.sendBlockChange(loc, Material.BED.getId(), (byte) 11); - sendPacket(nearby, bed); - nearby.sendBlockChange(loc, 0, (byte) 0); + List nearbyPlayers = Lists.newArrayList( + Iterables.filter(CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64), + (p) -> !meta.sent.containsEntry(p.getUniqueId(), entity.getUniqueId().toString()))); + if (nearbyPlayers.size() == 0) + return; + Location loc = from.getBukkitEntity().getLocation().clone(); + BlockFace[] axis = { BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST }; + BlockFace facing = axis[Math.round(loc.getYaw() / 90f) & 0x3].getOppositeFace(); + byte facingByte = 0; + switch (facing) { + case EAST: + facingByte = (byte) 1; + break; + case SOUTH: + facingByte = (byte) 2; + break; + case WEST: + facingByte = (byte) 3; + break; + } + Location bedLoc = loc.clone().add(0, -loc.getY(), 0); + PacketPlayOutBed bed = new PacketPlayOutBed(from, + new BlockPosition(bedLoc.getBlockX(), bedLoc.getBlockY(), bedLoc.getBlockZ())); + List> list = Lists.newArrayListWithCapacity(3); + from.locX = bedLoc.getBlockX(); + from.locY = bedLoc.getBlockY(); + from.locZ = bedLoc.getBlockZ(); + list.add(new PacketPlayOutEntityTeleport(from)); + list.add(bed); + from.locX = loc.getX(); + from.locY = loc.getY(); + from.locZ = loc.getZ(); + list.add(new PacketPlayOutEntityTeleport(from)); + for (Player nearby : nearbyPlayers) { + nearby.sendBlockChange(bedLoc, Material.BED_BLOCK, facingByte); + list.forEach((packet) -> sendPacket(nearby, packet)); + meta.sent.put(nearby.getUniqueId(), entity.getUniqueId().toString()); } } else { - PacketPlayOutAnimation packet = new PacketPlayOutAnimation(player, 2); + PacketPlayOutAnimation packet = new PacketPlayOutAnimation(from, 2); sendPacketNearby(entity, entity.getLocation(), packet, 64); + for (Player player : Bukkit.getOnlinePlayers()) { + if (meta.sent.remove(player.getUniqueId(), entity.getUniqueId().toString())) { + sendPacket(player, packet); + } + } } } diff --git a/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java b/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java index f2aa7858d..432ff3311 100644 --- a/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java +++ b/v1_12_R1/src/main/java/net/citizensnpcs/nms/v1_12_R1/util/NMSImpl.java @@ -21,6 +21,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.World; +import org.bukkit.block.BlockFace; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; import org.bukkit.boss.BossBar; @@ -67,6 +68,7 @@ import com.mojang.util.UUIDTypeAdapter; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.LocationLookup.PerPlayerMetadata; import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; @@ -1276,19 +1278,55 @@ public class NMSImpl implements NMSBridge { @Override public void sleep(Player entity, boolean sleep) { - EntityPlayer player = (EntityPlayer) getHandle(entity); + EntityPlayer from = (EntityPlayer) getHandle(entity); + PerPlayerMetadata meta = CitizensAPI.getLocationLookup().registerMetadata("sleeping", null); if (sleep) { - Location loc = player.getBukkitEntity().getLocation(); - PacketPlayOutBed bed = new PacketPlayOutBed(player, - new BlockPosition((int) player.locX, (int) player.locY, (int) player.locZ)); - for (Player nearby : CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64)) { - nearby.sendBlockChange(loc, Material.BED.getId(), (byte) 11); - sendPacket(nearby, bed); - nearby.sendBlockChange(loc, 0, (byte) 0); + List nearbyPlayers = Lists.newArrayList( + Iterables.filter(CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64), + (p) -> !meta.sent.containsEntry(p.getUniqueId(), entity.getUniqueId().toString()))); + if (nearbyPlayers.size() == 0) + return; + Location loc = from.getBukkitEntity().getLocation().clone(); + BlockFace[] axis = { BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST }; + BlockFace facing = axis[Math.round(loc.getYaw() / 90f) & 0x3].getOppositeFace(); + byte facingByte = 0; + switch (facing) { + case EAST: + facingByte = (byte) 1; + break; + case SOUTH: + facingByte = (byte) 2; + break; + case WEST: + facingByte = (byte) 3; + break; + } + Location bedLoc = loc.clone().add(0, -loc.getY(), 0); + PacketPlayOutBed bed = new PacketPlayOutBed(from, + new BlockPosition(bedLoc.getBlockX(), bedLoc.getBlockY(), bedLoc.getBlockZ())); + List> list = Lists.newArrayListWithCapacity(3); + from.locX = bedLoc.getBlockX(); + from.locY = bedLoc.getBlockY(); + from.locZ = bedLoc.getBlockZ(); + list.add(new PacketPlayOutEntityTeleport(from)); + list.add(bed); + from.locX = loc.getX(); + from.locY = loc.getY(); + from.locZ = loc.getZ(); + list.add(new PacketPlayOutEntityTeleport(from)); + for (Player nearby : nearbyPlayers) { + nearby.sendBlockChange(bedLoc, Material.BED_BLOCK, facingByte); + list.forEach((packet) -> sendPacket(nearby, packet)); + meta.sent.put(nearby.getUniqueId(), entity.getUniqueId().toString()); } } else { - PacketPlayOutAnimation packet = new PacketPlayOutAnimation(player, 2); + PacketPlayOutAnimation packet = new PacketPlayOutAnimation(from, 2); sendPacketNearby(entity, entity.getLocation(), packet, 64); + for (Player player : Bukkit.getOnlinePlayers()) { + if (meta.sent.remove(player.getUniqueId(), entity.getUniqueId().toString())) { + sendPacket(player, packet); + } + } } } diff --git a/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java b/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java index 59aa546f0..69113d0e9 100644 --- a/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java +++ b/v1_13_R2/src/main/java/net/citizensnpcs/nms/v1_13_R2/util/NMSImpl.java @@ -21,6 +21,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.World; +import org.bukkit.block.BlockFace; import org.bukkit.block.data.BlockData; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; @@ -69,6 +70,7 @@ import com.mojang.util.UUIDTypeAdapter; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.LocationLookup.PerPlayerMetadata; import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; @@ -1316,19 +1318,55 @@ public class NMSImpl implements NMSBridge { @Override public void sleep(Player entity, boolean sleep) { - EntityPlayer player = (EntityPlayer) getHandle(entity); + EntityPlayer from = (EntityPlayer) getHandle(entity); + PerPlayerMetadata meta = CitizensAPI.getLocationLookup().registerMetadata("sleeping", null); if (sleep) { - Location loc = player.getBukkitEntity().getLocation(); - PacketPlayOutBed bed = new PacketPlayOutBed(player, - new BlockPosition((int) player.locX, (int) player.locY, (int) player.locZ)); - for (Player nearby : CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64)) { - nearby.sendBlockChange(loc, Material.BLACK_BED, (byte) 11); - sendPacket(nearby, bed); - nearby.sendBlockChange(loc, Material.AIR, (byte) 0); + List nearbyPlayers = Lists.newArrayList( + Iterables.filter(CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64), + (p) -> !meta.sent.containsEntry(p.getUniqueId(), entity.getUniqueId().toString()))); + if (nearbyPlayers.size() == 0) + return; + Location loc = from.getBukkitEntity().getLocation().clone(); + BlockFace[] axis = { BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST }; + BlockFace facing = axis[Math.round(loc.getYaw() / 90f) & 0x3].getOppositeFace(); + byte facingByte = 0; + switch (facing) { + case EAST: + facingByte = (byte) 1; + break; + case SOUTH: + facingByte = (byte) 2; + break; + case WEST: + facingByte = (byte) 3; + break; + } + Location bedLoc = loc.clone().add(0, -loc.getY(), 0); + PacketPlayOutBed bed = new PacketPlayOutBed(from, + new BlockPosition(bedLoc.getBlockX(), bedLoc.getBlockY(), bedLoc.getBlockZ())); + List> list = Lists.newArrayListWithCapacity(3); + from.locX = bedLoc.getBlockX(); + from.locY = bedLoc.getBlockY(); + from.locZ = bedLoc.getBlockZ(); + list.add(new PacketPlayOutEntityTeleport(from)); + list.add(bed); + from.locX = loc.getX(); + from.locY = loc.getY(); + from.locZ = loc.getZ(); + list.add(new PacketPlayOutEntityTeleport(from)); + for (Player nearby : nearbyPlayers) { + nearby.sendBlockChange(bedLoc, Material.BLACK_BED, facingByte); + list.forEach((packet) -> sendPacket(nearby, packet)); + meta.sent.put(nearby.getUniqueId(), entity.getUniqueId().toString()); } } else { - PacketPlayOutAnimation packet = new PacketPlayOutAnimation(player, 2); + PacketPlayOutAnimation packet = new PacketPlayOutAnimation(from, 2); sendPacketNearby(entity, entity.getLocation(), packet, 64); + for (Player player : Bukkit.getOnlinePlayers()) { + if (meta.sent.remove(player.getUniqueId(), entity.getUniqueId().toString())) { + sendPacket(player, packet); + } + } } } diff --git a/v1_8_R3/pom.xml b/v1_8_R3/pom.xml index 5b667615e..55963db6b 100644 --- a/v1_8_R3/pom.xml +++ b/v1_8_R3/pom.xml @@ -42,8 +42,8 @@ maven-compiler-plugin 3.10.1 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java b/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java index 3e57094b5..2371de58a 100644 --- a/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java +++ b/v1_8_R3/src/main/java/net/citizensnpcs/nms/v1_8_R3/util/NMSImpl.java @@ -21,6 +21,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.World; +import org.bukkit.block.BlockFace; import org.bukkit.craftbukkit.v1_8_R3.CraftServer; import org.bukkit.craftbukkit.v1_8_R3.CraftSound; import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; @@ -64,6 +65,7 @@ import com.mojang.util.UUIDTypeAdapter; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.LocationLookup.PerPlayerMetadata; import net.citizensnpcs.api.ai.NavigatorParameters; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.command.CommandManager; @@ -1136,19 +1138,55 @@ public class NMSImpl implements NMSBridge { @Override public void sleep(Player entity, boolean sleep) { - EntityPlayer player = (EntityPlayer) getHandle(entity); + EntityPlayer from = (EntityPlayer) getHandle(entity); + PerPlayerMetadata meta = CitizensAPI.getLocationLookup().registerMetadata("sleeping", null); if (sleep) { - Location loc = player.getBukkitEntity().getLocation(); - PacketPlayOutBed bed = new PacketPlayOutBed(player, - new BlockPosition((int) player.locX, (int) player.locY, (int) player.locZ)); - for (Player nearby : CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64)) { - nearby.sendBlockChange(loc, Material.BED.getId(), (byte) 11); - sendPacket(nearby, bed); - nearby.sendBlockChange(loc, 0, (byte) 0); + List nearbyPlayers = Lists.newArrayList( + Iterables.filter(CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64), + (p) -> !meta.sent.containsEntry(p.getUniqueId(), entity.getUniqueId().toString()))); + if (nearbyPlayers.size() == 0) + return; + Location loc = from.getBukkitEntity().getLocation().clone(); + BlockFace[] axis = { BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST }; + BlockFace facing = axis[Math.round(loc.getYaw() / 90f) & 0x3].getOppositeFace(); + byte facingByte = 0; + switch (facing) { + case EAST: + facingByte = (byte) 1; + break; + case SOUTH: + facingByte = (byte) 2; + break; + case WEST: + facingByte = (byte) 3; + break; + } + Location bedLoc = loc.clone().add(0, -loc.getY(), 0); + PacketPlayOutBed bed = new PacketPlayOutBed(from, + new BlockPosition(bedLoc.getBlockX(), bedLoc.getBlockY(), bedLoc.getBlockZ())); + List> list = Lists.newArrayListWithCapacity(3); + from.locX = bedLoc.getBlockX(); + from.locY = bedLoc.getBlockY(); + from.locZ = bedLoc.getBlockZ(); + list.add(new PacketPlayOutEntityTeleport(from)); + list.add(bed); + from.locX = loc.getX(); + from.locY = loc.getY(); + from.locZ = loc.getZ(); + list.add(new PacketPlayOutEntityTeleport(from)); + for (Player nearby : nearbyPlayers) { + nearby.sendBlockChange(bedLoc, Material.BED_BLOCK, facingByte); + list.forEach((packet) -> sendPacket(nearby, packet)); + meta.sent.put(nearby.getUniqueId(), entity.getUniqueId().toString()); } } else { - PacketPlayOutAnimation packet = new PacketPlayOutAnimation(player, 2); + PacketPlayOutAnimation packet = new PacketPlayOutAnimation(from, 2); sendPacketNearby(entity, entity.getLocation(), packet, 64); + for (Player player : Bukkit.getOnlinePlayers()) { + if (meta.sent.remove(player.getUniqueId(), entity.getUniqueId().toString())) { + sendPacket(player, packet); + } + } } }