package com.bergerkiller.bukkit.common.utils; import java.util.Arrays; import java.util.Collection; import net.minecraft.server.Packet; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import com.bergerkiller.bukkit.common.conversion.Conversion; import com.bergerkiller.bukkit.common.internal.CommonNMS; import com.bergerkiller.bukkit.common.internal.CommonPlugin; import com.bergerkiller.bukkit.common.protocol.CommonPacket; import com.bergerkiller.bukkit.common.protocol.PacketMonitor; import com.bergerkiller.bukkit.common.protocol.PacketType; import com.bergerkiller.bukkit.common.protocol.PacketListener; import com.bergerkiller.bukkit.common.reflection.classes.ChunkRef; public class PacketUtil { /** * Sends all the packets required to properly display a chunk to a player * * @param player to send to * @param chunk to send the information of */ public static void sendChunk(Player player, org.bukkit.Chunk chunk) { sendChunk(player, chunk, true); } /** * Sends all the packets required to properly display a chunk to a player. * To only send (Tile)Entity related information, use a 'sendPayload' of False. * * @param player to send to * @param chunk to send the information of * @param sendPayload - whether the block data is sent */ public static void sendChunk(final Player player, final org.bukkit.Chunk chunk, boolean sendPayload) { final Object chunkHandle = Conversion.toChunkHandle.convert(chunk); ChunkRef.seenByPlayer.set(chunkHandle, true); // Send payload if (sendPayload) { sendPacket(player, PacketType.OUT_MAP_CHUNK_BULK.newInstance(Arrays.asList(chunk))); } // Tile entities CommonPacket packet; for (Object tile : ChunkRef.tileEntities.get(chunkHandle).values()) { if ((packet = BlockUtil.getUpdatePacket(tile)) != null) { PacketUtil.sendPacket(player, packet); } } // Entity spawn messages CommonUtil.nextTick(new Runnable() { public void run() { WorldUtil.getTracker(player.getWorld()).spawnEntities(player, chunk); } }); } /** * Fakes a packet sent from the Client to the Server for a certain Player. * * @param player to receive a packet for * @param packet to receive */ public static void receivePacket(Player player, CommonPacket packet) { receivePacket(player, (Object) packet); } /** * Fakes a packet sent from the Client to the Server for a certain Player. * * @param player to receive a packet for * @param packet to receive */ public static void receivePacket(Player player, Object packet) { if (packet instanceof CommonPacket) { packet = ((CommonPacket) packet).getHandle(); } if (packet == null) { return; } CommonPlugin.getInstance().getPacketHandler().receivePacket(player, packet); } public static void sendPacket(Player player, CommonPacket packet) { sendPacket(player, packet, true); } public static void sendPacket(Player player, Object packet) { sendPacket(player, packet, true); } public static void sendPacket(Player player, CommonPacket packet, boolean throughListeners) { sendPacket(player, (Object) packet, throughListeners); } public static void sendPacket(Player player, Object packet, boolean throughListeners) { if (packet instanceof CommonPacket) { packet = ((CommonPacket) packet).getHandle(); } if (packet == null) { return; } CommonPlugin.getInstance().getPacketHandler().sendPacket(player, packet, throughListeners); } public static void broadcastBlockPacket(Block block, Object packet, boolean throughListeners) { broadcastBlockPacket(block.getWorld(), block.getX(), block.getZ(), packet, throughListeners); } public static void broadcastBlockPacket(org.bukkit.World world, final int x, final int z, Object packet, boolean throughListeners) { if (packet instanceof CommonPacket) { packet = ((CommonPacket) packet).getHandle(); } if (world == null || packet == null) { return; } for (Player player : WorldUtil.getPlayers(world)) { if (EntityUtil.isNearBlock(player, x, z, CommonUtil.BLOCKVIEW)) { sendPacket(player, packet, throughListeners); } } } public static void broadcastChunkPacket(org.bukkit.Chunk chunk, Object packet, boolean throughListeners) { if (packet instanceof CommonPacket) { packet = ((CommonPacket) packet).getHandle(); } if (chunk == null || packet == null) { return; } for (Player player : WorldUtil.getPlayers(chunk.getWorld())) { if (EntityUtil.isNearChunk(player, chunk.getX(), chunk.getZ(), CommonUtil.VIEW)) { sendPacket(player, packet, throughListeners); } } } public static void broadcastPacket(Object packet, boolean throughListeners) { if (packet instanceof CommonPacket) { packet = ((CommonPacket) packet).getHandle(); } for (Player player : CommonUtil.getOnlinePlayers()) { sendPacket(player, packet, throughListeners); } } /** * Adds a single packet monitor. Packet monitors only monitor (not change) packets. * * @param plugin to register for * @param monitor to register * @param packets to register for */ public static void addPacketMonitor(Plugin plugin, PacketMonitor monitor, PacketType... packets) { if (monitor == null || LogicUtil.nullOrEmpty(packets)) { return; } CommonPlugin.getInstance().getPacketHandler().addPacketMonitor(plugin, monitor, packets); } /** * Adds a single packet listener. Packet listeners can modify packets. * * @param plugin to register for * @param listener to register * @param packets to register for */ public static void addPacketListener(Plugin plugin, PacketListener listener, PacketType... packets) { if (listener == null || LogicUtil.nullOrEmpty(packets)) { return; } CommonPlugin.getInstance().getPacketHandler().addPacketListener(plugin, listener, packets); } /** * Removes all packet listeners AND monitors of a plugin * * @param plugin to remove the registered monitors and listeners of */ public static void removePacketListeners(Plugin plugin) { CommonPlugin.getInstance().getPacketHandler().removePacketListeners(plugin); } /** * Removes a single registered packet listener * * @param listener to remove */ public static void removePacketListener(PacketListener listener) { CommonPlugin.getInstance().getPacketHandler().removePacketListener(listener); } /** * Removes a single registered packet monitor * * @param monitor to remove */ public static void removePacketMonitor(PacketMonitor monitor) { CommonPlugin.getInstance().getPacketHandler().removePacketMonitor(monitor); } public static void broadcastPacketNearby(Location location, double radius, Object packet) { broadcastPacketNearby(location.getWorld(), location.getX(), location.getY(), location.getZ(), radius, packet); } public static void broadcastPacketNearby(org.bukkit.World world, double x, double y, double z, double radius, Object packet) { if (packet instanceof CommonPacket) { packet = ((CommonPacket) packet).getHandle(); } CommonNMS.getPlayerList().sendPacketNearby(x, y, z, radius, WorldUtil.getDimension(world), (Packet) packet); } /** * Obtains a collection of all plugins currently listening for the Packet type specified. * Packets of this type can be expected to be handled by these plugins when sending it. * * @param packetType to get the listening plugins for * @return collection of listening plugins */ public static Collection<Plugin> getListenerPlugins(PacketType packetType) { return CommonPlugin.getInstance().getPacketHandler().getListening(packetType); } /** * Gets the total amount of bytes of packet data that still has to be sent to the player * * @param player to get the pending bytes of * @return pending bytes */ public static long getPendingBytes(Player player) { return CommonPlugin.getInstance().getPacketHandler().getPendingBytes(player); } }