diff --git a/Itemutils/pom.xml b/Itemutils/pom.xml index 92a1268..b3f4778 100644 --- a/Itemutils/pom.xml +++ b/Itemutils/pom.xml @@ -10,13 +10,17 @@ 4.0.0 itemutils - 1.1-SNAPSHOT + 1.2-SNAPSHOT spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + dmulloy2-repo + http://repo.dmulloy2.net/content/groups/public/ + @@ -25,6 +29,12 @@ 1.10.2-R0.1-SNAPSHOT provided + + com.comphenix.protocol + ProtocolLib-API + 4.0 + provided + org.jetbrains annotations-java5 diff --git a/Itemutils/src/main/java/com/comphenix/packetwrapper/AbstractPacket.java b/Itemutils/src/main/java/com/comphenix/packetwrapper/AbstractPacket.java new file mode 100644 index 0000000..66e3646 --- /dev/null +++ b/Itemutils/src/main/java/com/comphenix/packetwrapper/AbstractPacket.java @@ -0,0 +1,107 @@ +/** + * PacketWrapper - ProtocolLib wrappers for Minecraft packets + * Copyright (C) dmulloy2 + * Copyright (C) Kristian S. Strangeland + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.comphenix.packetwrapper; + +import java.lang.reflect.InvocationTargetException; + +import org.bukkit.entity.Player; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import com.google.common.base.Objects; + +public abstract class AbstractPacket { + // The packet we will be modifying + protected PacketContainer handle; + + /** + * Constructs a new strongly typed wrapper for the given packet. + * + * @param handle - handle to the raw packet data. + * @param type - the packet type. + */ + protected AbstractPacket(PacketContainer handle, PacketType type) { + // Make sure we're given a valid packet + if (handle == null) + throw new IllegalArgumentException("Packet handle cannot be NULL."); + if (!Objects.equal(handle.getType(), type)) + throw new IllegalArgumentException(handle.getHandle() + + " is not a packet of type " + type); + + this.handle = handle; + } + + /** + * Retrieve a handle to the raw packet data. + * + * @return Raw packet data. + */ + public PacketContainer getHandle() { + return handle; + } + + /** + * Send the current packet to the given receiver. + * + * @param receiver - the receiver. + * @throws RuntimeException If the packet cannot be sent. + */ + public void sendPacket(Player receiver) { + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(receiver, + getHandle()); + } catch (InvocationTargetException e) { + throw new RuntimeException("Cannot send packet.", e); + } + } + + /** + * Simulate receiving the current packet from the given sender. + * + * @param sender - the sender. + * @throws RuntimeException If the packet cannot be received. + * @deprecated Misspelled. recieve -> receive + * @see #receivePacket(Player) + */ + @Deprecated + public void recievePacket(Player sender) { + try { + ProtocolLibrary.getProtocolManager().recieveClientPacket(sender, + getHandle()); + } catch (Exception e) { + throw new RuntimeException("Cannot recieve packet.", e); + } + } + + /** + * Simulate receiving the current packet from the given sender. + * + * @param sender - the sender. + * @throws RuntimeException if the packet cannot be received. + */ + public void receivePacket(Player sender) { + try { + ProtocolLibrary.getProtocolManager().recieveClientPacket(sender, + getHandle()); + } catch (Exception e) { + throw new RuntimeException("Cannot recieve packet.", e); + } + } +} diff --git a/Itemutils/src/main/java/com/comphenix/packetwrapper/WrapperPlayClientUpdateSign.java b/Itemutils/src/main/java/com/comphenix/packetwrapper/WrapperPlayClientUpdateSign.java new file mode 100644 index 0000000..2ea0996 --- /dev/null +++ b/Itemutils/src/main/java/com/comphenix/packetwrapper/WrapperPlayClientUpdateSign.java @@ -0,0 +1,79 @@ +/** + * PacketWrapper - ProtocolLib wrappers for Minecraft packets + * Copyright (C) dmulloy2 + * Copyright (C) Kristian S. Strangeland + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.comphenix.packetwrapper; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.wrappers.BlockPosition; + +public class WrapperPlayClientUpdateSign extends AbstractPacket { + public static final PacketType TYPE = PacketType.Play.Client.UPDATE_SIGN; + + public WrapperPlayClientUpdateSign() { + super(new PacketContainer(TYPE), TYPE); + handle.getModifier().writeDefaults(); + } + + public WrapperPlayClientUpdateSign(PacketContainer packet) { + super(packet, TYPE); + } + + /** + * Retrieve Location. + *

+ * Notes: block Coordinates + * + * @return The current Location + */ + public BlockPosition getLocation() { + return handle.getBlockPositionModifier().read(0); + } + + /** + * Set Location. + * + * @param value - new value. + */ + public void setLocation(BlockPosition value) { + handle.getBlockPositionModifier().write(0, value); + } + + /** + * Retrieve this sign's lines of text. + * + * @return The current lines + */ + public String[] getLines() { + return handle.getStringArrays().read(0); + } + + /** + * Set this sign's lines of text. + * + * @param value - Lines, must be 4 elements long + */ + public void setLines(String[] value) { + if (value == null) + throw new IllegalArgumentException("value cannot be null!"); + if (value.length != 4) + throw new IllegalArgumentException("value must have 4 elements!"); + + handle.getStringArrays().write(0, value); + } +} \ No newline at end of file diff --git a/Itemutils/src/main/java/com/comphenix/packetwrapper/WrapperPlayServerBlockChange.java b/Itemutils/src/main/java/com/comphenix/packetwrapper/WrapperPlayServerBlockChange.java new file mode 100644 index 0000000..5b72073 --- /dev/null +++ b/Itemutils/src/main/java/com/comphenix/packetwrapper/WrapperPlayServerBlockChange.java @@ -0,0 +1,88 @@ +/** + * PacketWrapper - ProtocolLib wrappers for Minecraft packets + * Copyright (C) dmulloy2 + * Copyright (C) Kristian S. Strangeland + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.comphenix.packetwrapper; + +import org.bukkit.Location; +import org.bukkit.World; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.wrappers.BlockPosition; +import com.comphenix.protocol.wrappers.WrappedBlockData; + +public class WrapperPlayServerBlockChange extends AbstractPacket { + public static final PacketType TYPE = PacketType.Play.Server.BLOCK_CHANGE; + + public WrapperPlayServerBlockChange() { + super(new PacketContainer(TYPE), TYPE); + handle.getModifier().writeDefaults(); + } + + public WrapperPlayServerBlockChange(PacketContainer packet) { + super(packet, TYPE); + } + + /** + * Retrieve Location. + *

+ * Notes: block Coordinates + * + * @return The current Location + */ + public BlockPosition getLocation() { + return handle.getBlockPositionModifier().read(0); + } + + /** + * Set Location. + * + * @param value - new value. + */ + public void setLocation(BlockPosition value) { + handle.getBlockPositionModifier().write(0, value); + } + + /** + * Retrieve the Bukkit Location. + * + * @param world World for the location + * @return Bukkit Location + */ + public Location getBukkitLocation(World world) { + return getLocation().toVector().toLocation(world); + } + + /** + * Retrieve Block Data. + * + * @return The current Block Data + */ + public WrappedBlockData getBlockData() { + return handle.getBlockData().read(0); + } + + /** + * Set Block Data. + * + * @param value - new value. + */ + public void setBlockData(WrappedBlockData value) { + handle.getBlockData().write(0, value); + } +} \ No newline at end of file diff --git a/Itemutils/src/main/java/com/comphenix/packetwrapper/WrapperPlayServerOpenSignEditor.java b/Itemutils/src/main/java/com/comphenix/packetwrapper/WrapperPlayServerOpenSignEditor.java new file mode 100644 index 0000000..7a61266 --- /dev/null +++ b/Itemutils/src/main/java/com/comphenix/packetwrapper/WrapperPlayServerOpenSignEditor.java @@ -0,0 +1,57 @@ +/** + * PacketWrapper - ProtocolLib wrappers for Minecraft packets + * Copyright (C) dmulloy2 + * Copyright (C) Kristian S. Strangeland + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.comphenix.packetwrapper; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.wrappers.BlockPosition; + +public class WrapperPlayServerOpenSignEditor extends AbstractPacket { + + public static final PacketType TYPE = + PacketType.Play.Server.OPEN_SIGN_EDITOR; + + public WrapperPlayServerOpenSignEditor() { + super(new PacketContainer(TYPE), TYPE); + handle.getModifier().writeDefaults(); + } + + public WrapperPlayServerOpenSignEditor(PacketContainer packet) { + super(packet, TYPE); + } + + /** + * Retrieve Location. + * + * @return The current Location + */ + public BlockPosition getLocation() { + return handle.getBlockPositionModifier().read(0); + } + + /** + * Set Location. + * + * @param value - new value. + */ + public void setLocation(BlockPosition value) { + handle.getBlockPositionModifier().write(0, value); + } + +} diff --git a/Itemutils/src/main/java/eu/mikroskeem/utils/itemutils/FakeSignFactory.java b/Itemutils/src/main/java/eu/mikroskeem/utils/itemutils/FakeSignFactory.java new file mode 100644 index 0000000..a411b4f --- /dev/null +++ b/Itemutils/src/main/java/eu/mikroskeem/utils/itemutils/FakeSignFactory.java @@ -0,0 +1,177 @@ +package eu.mikroskeem.utils.itemutils; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.comphenix.packetwrapper.WrapperPlayClientUpdateSign; +import com.comphenix.packetwrapper.WrapperPlayServerOpenSignEditor; +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.wrappers.BlockPosition; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.util.Vector; + +/** + * @author Mark V. + */ +public class FakeSignFactory { + private ProtocolManager protocolManager; + private PacketAdapter packetListener; + private Map listeners; + private Map signLocations; + + /** + * Construct FakeSignFactory + * + * @param plugin Plugin to register packet listeners on + */ + public FakeSignFactory(Plugin plugin) { + protocolManager = ProtocolLibrary.getProtocolManager(); + packetListener = new PacketListener(plugin); + protocolManager.addPacketListener(packetListener); + listeners = new ConcurrentHashMap<>(); + signLocations = new ConcurrentHashMap<>(); + } + + /** + * Open fake sign on player screen + * + * @param player Player to open sign on + * @param response Sign response callback + */ + public void open(Player player, FakeSignListener response) { + open(player, (Location)null, response); + } + + /** + * Open fake sign on player screen + * + * @param player Player to open sign on + * @param signLocation Fake sign location + * @param response Sign response callback + */ + public void open(Player player, Location signLocation, FakeSignListener response) { + int x = 0, y = 0, z = 0; + if (signLocation != null) { + x = signLocation.getBlockX(); + y = signLocation.getBlockY(); + z = signLocation.getBlockZ(); + } + + WrapperPlayServerOpenSignEditor openSignEditor = new WrapperPlayServerOpenSignEditor(); + openSignEditor.setLocation(new BlockPosition(x, y, z)); + + try { + protocolManager.sendServerPacket(player, openSignEditor.getHandle()); + signLocations.put(player.getName(), new Vector(x, y, z)); + listeners.put(player.getName(), response); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + + /** + * Open fake sign on player screen + * + * @param player Player to open sign on + * @param defaultText Sign default text + * @param response Sign response callback + */ + public void open(Player player, String[] defaultText, FakeSignListener response) { + List packets = new ArrayList<>(); + + int x = 0, y = 255, z = 0; + if (defaultText != null) { + x = player.getLocation().getBlockX(); + z = player.getLocation().getBlockZ(); + Location signLocation = new Location(player.getWorld(), (double)x, (double)y, (double)z); + + /* Send block change */ + player.sendBlockChange(signLocation, Material.WALL_SIGN, (byte)0); + + /* Set sign content */ + player.sendSignChange(signLocation, defaultText); + } + + /* Open sign editor */ + WrapperPlayServerOpenSignEditor openSignEditor = new WrapperPlayServerOpenSignEditor(); + openSignEditor.setLocation(new BlockPosition(x, y, z)); + packets.add(openSignEditor.getHandle()); + + try { + for (PacketContainer packet : packets) { + protocolManager.sendServerPacket(player, packet); + } + if (defaultText != null) { + /* Make sign disappear */ + Location signLocation = new Location(player.getWorld(), (double)x, (double)y, (double)z); + player.sendBlockChange(signLocation, Material.AIR, (byte)0); + } + signLocations.put(player.getName(), new Vector(x, y, z)); + listeners.put(player.getName(), response); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + + /** + * Destroy FakeSignFactory + */ + public void destroy() { + protocolManager.removePacketListener(packetListener); + listeners.clear(); + signLocations.clear(); + } + + interface FakeSignListener { + void onSignDone(Player player, String[] lines); + } + + private class PacketListener extends PacketAdapter { + Plugin plugin; + + public PacketListener(Plugin plugin) { + super(plugin, ListenerPriority.NORMAL, PacketType.Play.Client.UPDATE_SIGN); + this.plugin = plugin; + } + + @Override + public void onPacketReceiving(PacketEvent event) { + final Player player = event.getPlayer(); + + /* Check if it's sign update packet */ + PacketContainer packet = event.getPacket(); + if(packet.getType() == PacketType.Play.Client.UPDATE_SIGN){ + /* Wrap packet */ + final WrapperPlayClientUpdateSign updateSign = new WrapperPlayClientUpdateSign(packet); + Location signLocation = updateSign.getLocation().toLocation(player.getWorld()); + + /* Remove sign location from signLocations */ + Vector v = signLocations.remove(player.getName()); + if (v == null) return; + if (signLocation.getBlockX() != v.getBlockX() || + signLocation.getBlockY() != v.getBlockY() || + signLocation.getBlockZ() != v.getBlockZ()) return; + + /* Do callback */ + final FakeSignListener response = listeners.remove(event.getPlayer().getName()); + if (response != null) { + event.setCancelled(true); + plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, ()-> + response.onSignDone(player, updateSign.getLines())); + } + } + } + } +}