Skip to content

Instantly share code, notes, and snippets.

@aadnk
Created December 28, 2013 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aadnk/8159934 to your computer and use it in GitHub Desktop.
Save aadnk/8159934 to your computer and use it in GitHub Desktop.
Allow players to edit signs through a command.
package com.comphenix.example;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ConcurrentMap;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.injector.BukkitUnwrapper;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.google.common.base.Objects;
import com.google.common.collect.MapMaker;
public class SignEditorPlugin extends JavaPlugin implements Listener {
private ConcurrentMap<Player, Location> editing = new MapMaker().weakKeys().makeMap();
// For accessing the underlying tile entity
private FieldAccessor tileEntityAccessor;
private FieldAccessor booleanAccessor;
private FieldAccessor humanAccessor;
@Override
public void onEnable() {
ProtocolLibrary.getProtocolManager().getAsynchronousManager().registerAsyncHandler(
new PacketAdapter(this, PacketType.Play.Client.UPDATE_SIGN) {
@Override
public void onPacketReceiving(PacketEvent event) {
Player player = event.getPlayer();
StructureModifier<Integer> ints = event.getPacket().getIntegers();
Location loc = new Location(player.getWorld(), ints.read(0), ints.read(1), ints.read(2));
// Allow
if (Objects.equal(editing.get(player), loc)) {
setEditingPlayer((Sign) loc.getBlock().getState(), player);
}
}
}).syncStart();
}
private void setEditingPlayer(Sign sign, Player player) {
// Extract a TileEntitySign from a CraftSign
if (tileEntityAccessor == null) {
Class<?> tileEntity = MinecraftReflection.getMinecraftClass("TileEntitySign");
Class<?> humanClass = MinecraftReflection.getMinecraftClass("EntityHuman");
tileEntityAccessor = Accessors.getFieldAccessor(sign.getClass(), tileEntity, true);
booleanAccessor = Accessors.getFieldAccessor(tileEntity, boolean.class, true);
humanAccessor = Accessors.getFieldAccessor(tileEntity, humanClass, true);
}
Object tileEntity = tileEntityAccessor.get(sign);
booleanAccessor.set(tileEntity, true);
humanAccessor.set(tileEntity, BukkitUnwrapper.getInstance().unwrapItem(player));
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (sender instanceof Player) {
Player player = (Player) sender;
@SuppressWarnings("deprecation")
Block block = player.getTargetBlock(null, 50);
if (block != null) {
displaySignEditor(player, block);
}
}
return true;
}
/**
* Display a sign editor for the given player.
* <p>
* The block could also be client-side.
* @
* @param sign - the sign to edit.
*/
private void displaySignEditor(Player player, Block sign) {
if (!player.getWorld().equals(sign.getWorld()))
throw new IllegalArgumentException("Player and sign must be in the same world.");
PacketContainer editSignPacket = new PacketContainer(PacketType.Play.Server.OPEN_SIGN_ENTITY);
// Permit this
editing.put(player, sign.getLocation());
editSignPacket.getIntegers().
write(0, sign.getX()).
write(1, sign.getY()).
write(2, sign.getZ());
try {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, editSignPacket);
} catch (InvocationTargetException e) {
throw new RuntimeException("Cannot send packet.", e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment