Last active
August 29, 2015 14:00
-
-
Save aadnk/11198274 to your computer and use it in GitHub Desktop.
Cancel inventory clicks with TinyProtocol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.comphenix.example; | |
import org.bukkit.entity.Player; | |
import org.bukkit.event.Listener; | |
import org.bukkit.inventory.ItemStack; | |
import org.bukkit.plugin.java.JavaPlugin; | |
import com.comphenix.example.Reflection.FieldAccessor; | |
import com.comphenix.example.Reflection.MethodInvoker; | |
import net.minecraft.util.io.netty.channel.Channel; | |
public class CancelInventoryClick extends JavaPlugin { | |
// net.minecraft.server.ItemStack | |
private Class<Object> nmsStackClass = Reflection.getUntypedClass("{nms}.ItemStack"); | |
// Explosion packet | |
private Class<?> inventoryClickPacket = Reflection.getClass("{nms}.PacketPlayInWindowClick"); | |
// Convert an NMS item stack to a CraftBukkit item stack | |
private MethodInvoker getItemStack = Reflection.getMethod("{obc}.inventory.CraftItemStack", "asCraftMirror", nmsStackClass); | |
// 0 is the player inventory | |
private FieldAccessor<Integer> windowId = Reflection.getField(inventoryClickPacket, int.class, 0); | |
private FieldAccessor<Integer> slotIndex = Reflection.getField(inventoryClickPacket, int.class, 1); | |
private FieldAccessor<Integer> button = Reflection.getField(inventoryClickPacket, int.class, 2); | |
private FieldAccessor<Short> actionNumber = Reflection.getField(inventoryClickPacket, short.class, 0); | |
private FieldAccessor<Object> itemStack = Reflection.getField(inventoryClickPacket, nmsStackClass, 0); | |
private FieldAccessor<Integer> clickMode = Reflection.getField(inventoryClickPacket, int.class, 3); | |
private TinyProtocol protocol; | |
@Override | |
public void onEnable() { | |
protocol = new TinyProtocol(this) { | |
@Override | |
public Object onPacketInAsync(final Player sender, Channel channel, Object packet) { | |
if (windowId.hasField(packet)) { | |
ItemStack stack = (ItemStack) getItemStack.invoke(null, itemStack.get(packet)); | |
int index = slotIndex.get(packet); | |
System.out.println("Clicked: " + stack + " at " + index); | |
// To cancel | |
if (index == 0) { | |
// THE CURRENT METHOD IS ASYNC, SO WE CANNOT CALL BUKKIT API DIRECTLY. | |
// Instead, we have to use the scheduler | |
getServer().getScheduler().scheduleSyncDelayedTask(CancelInventoryClick.this, new Runnable() { | |
@SuppressWarnings("deprecation") | |
@Override | |
public void run() { | |
// This is needed to properly restore the inventory state on the client side | |
sender.updateInventory(); | |
} | |
}); | |
return null; | |
} | |
} | |
return packet; | |
} | |
@Override | |
public Object onPacketOutAsync(Player reciever, Channel channel, Object packet) { | |
return packet; | |
} | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment