Purple glow on item without enchantments?

Discussion in 'Plugin Development' started by Rprrr, Jan 20, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    Rprrr

    Hi,

    I was wondering how I could add a purple glow, without adding an enchantment to an item. I'm pretty sure this is possible.. (I've seen it before), but if it isn't, I would also like to know how you can add an enchantment to an item, without having the enchantment's text popping up in the lore (I've experimented with earlier, but for some reason I never managed to remove it from the lore :s).

    Thanks in advance!

    - Rprrr
     
  2. Offline

    t7seven7t

    @Rprrr Comphenix and his plugin ProtocolLib has allowed plugins to remove enchantment effects so it might also help you add them.​
     
  3. Offline

    DerWisch

    I'm not sure how to do it in bukkit but items which are glowing without enchantment have an empty enchantment tag
    [​IMG]
     
    Comphenix likes this.
  4. Offline

    Cybermaxke

    Ye, it's very to do it on that way.
     
  5. Offline

    Comphenix

    ProtocolLib is absolutely not required for this, though it does have an NBT library that can be useful.

    Still, here's a method that works without ProtocolLib (download). It does have a significant downside, however:
    Code:java
    1. package com.comphenix.example;
    2.  
    3. import java.lang.reflect.Field;
    4.  
    5. import net.minecraft.server.v1_4_R1.ItemStack;
    6. import net.minecraft.server.v1_4_R1.NBTTagCompound;
    7. import net.minecraft.server.v1_4_R1.NBTTagList;
    8.  
    9. import org.bukkit.Material;
    10. import org.bukkit.command.Command;
    11. import org.bukkit.command.CommandSender;
    12. import org.bukkit.craftbukkit.v1_4_R1.inventory.CraftItemStack;
    13. import org.bukkit.entity.Player;
    14. import org.bukkit.plugin.java.JavaPlugin;
    15.  
    16. public class ExampleMod extends JavaPlugin {
    17. @Override
    18. public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
    19. if (sender instanceof Player) {
    20. Player player = (Player) sender;
    21. CraftItemStack test = CraftItemStack.asCraftCopy(new org.bukkit.inventory.ItemStack(Material.IRON_AXE, 1));
    22.  
    23. addGlow(test);
    24. player.getInventory().addItem(test);
    25. }
    26.  
    27. return true;
    28. }
    29.  
    30. private void addGlow(org.bukkit.inventory.ItemStack stack) {
    31. ItemStack nmsStack = (ItemStack) getField(stack, "handle");
    32. NBTTagCompound compound = nmsStack.tag;
    33.  
    34. // Initialize the compound if we need to
    35. if (compound == null) {
    36. compound = new NBTTagCompound();
    37. nmsStack.tag = compound;
    38. }
    39.  
    40. // Empty enchanting compound
    41. compound.set("ench", new NBTTagList());
    42. }
    43.  
    44. private Object getField(Object obj, String name) {
    45. try {
    46. Field field = obj.getClass().getDeclaredField(name);
    47. field.setAccessible(true);
    48.  
    49. return field.get(obj);
    50. } catch (Exception e) {
    51. // We don't care
    52. throw new RuntimeException("Unable to retrieve field content.", e);
    53. }
    54. }
    55. }

    The big problem is that you can't apply an ItemMeta without removing this effect. Any plugin that renames or modifies the name or lore of an item (such as ItemRenamer, etc.) will override the glow effect.

    Maybe using ProtocolLib is not such a bad idea after all (download):
    Code:java
    1. import org.bukkit.Material;
    2. import org.bukkit.command.Command;
    3. import org.bukkit.command.CommandSender;
    4. import org.bukkit.enchantments.Enchantment;
    5. import org.bukkit.entity.Player;
    6. import org.bukkit.inventory.ItemStack;
    7. import org.bukkit.plugin.java.JavaPlugin;
    8.  
    9. import com.comphenix.protocol.Packets;
    10. import com.comphenix.protocol.ProtocolLibrary;
    11. import com.comphenix.protocol.events.ConnectionSide;
    12. import com.comphenix.protocol.events.ListenerPriority;
    13. import com.comphenix.protocol.events.PacketAdapter;
    14. import com.comphenix.protocol.events.PacketEvent;
    15. import com.comphenix.protocol.utility.MinecraftReflection;
    16. import com.comphenix.protocol.wrappers.nbt.NbtCompound;
    17. import com.comphenix.protocol.wrappers.nbt.NbtFactory;
    18.  
    19. public class ExampleMod extends JavaPlugin {
    20. @Override
    21. public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
    22. if (sender instanceof Player) {
    23. Player player = (Player) sender;
    24.  
    25. // Get a CraftItemStack
    26. ItemStack stack = new ItemStack(Material.IRON_AXE, 1);
    27. stack = MinecraftReflection.getBukkitItemStack(stack);
    28.  
    29. // We'll co-op Silk Touch 32 (as it doesn't make much sense) to mark this item as glowing
    30. stack.addUnsafeEnchantment(Enchantment.SILK_TOUCH, 32);
    31. player.getInventory().addItem(stack);
    32. }
    33.  
    34. return true;
    35. }
    36.  
    37. @Override
    38. public void onEnable() {
    39. ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(
    40. this, ConnectionSide.SERVER_SIDE, ListenerPriority.HIGH,
    41. Packets.Server.SET_SLOT, Packets.Server.WINDOW_ITEMS) {
    42. @Override
    43. public void onPacketSending(PacketEvent event) {
    44. if (event.getPacketID() == Packets.Server.SET_SLOT) {
    45. addGlow(new ItemStack[] { event.getPacket().getItemModifier().read(0) });
    46. } else {
    47. addGlow(event.getPacket().getItemArrayModifier().read(0));
    48. }
    49. }
    50. });
    51. }
    52.  
    53. private void addGlow(ItemStack[] stacks) {
    54. for (ItemStack stack : stacks) {
    55. if (stack != null) {
    56. // Only update those stacks that have our flag enchantment
    57. if (stack.getEnchantmentLevel(Enchantment.SILK_TOUCH) == 32) {
    58. NbtCompound compound = (NbtCompound) NbtFactory.fromItemTag(stack);
    59. compound.put(NbtFactory.ofList("ench"));
    60. }
    61. }
    62. }
    63. }
    64. }

    Using ProtocolLib is slightly more complicated, but it does have a few additional advantages: you're no longer tied to a specific CraftBukkit version. That may be a reason enough to use PL.
     
    uyuyuy99 and Rprrr like this.
  6. Offline

    Rprrr

    Comphenix
    Alright, thanks for the suggestion (also thanks to everyone else that replied). I'll think I'll try ProtcolLib then. :)
     
    Comphenix likes this.
  7. Offline

    Goblom

    I am going to Necropost here (sorry)

    Comphenix That works perfectly but as soon as you open your inventory the glow effect is removed and doesn't come back (event after a relog)
     
  8. Offline

    Comphenix

    Looks like this doesn't work in creative mode, as I don't intercept SET_SLOT as I do in ItemRenamer.

    But you don't necessarily have to reproduce what ItemRenamer does - instead, you can depend on it using the new API introduced in 2.0.0, and do the following (download):
    Code:java
    1. private static final String EXAMPLE_MOD_GLOW = "[ExampleMod]glow";
    2.  
    3. @Override
    4. public void onEnable() {
    5. RenamerAPI.getAPI().addListener(this, RenamerPriority.POST_NORMAL, new ItemsListener() {
    6. @Override
    7. public void onItemsSending(Player player, RenamerSnapshot snapshot) {
    8. addGlow(snapshot);
    9. }
    10. });
    11. }
    12.  
    13. private void addGlow(RenamerSnapshot stacks) {
    14. for (ItemStack stack : stacks) {
    15. // Only update those stacks that have our flag lore
    16. if (stack != null && stack.hasItemMeta()) {
    17. List<String> lore = stack.getItemMeta().getLore();
    18.  
    19. if (Arrays.asList(EXAMPLE_MOD_GLOW).equals(lore)) {
    20. NbtCompound compound = (NbtCompound) NbtFactory.fromItemTag(stack);
    21. compound.put(NbtFactory.ofList("ench"));
    22. compound.getCompound("display").remove("Lore");
    23. }
    24. }
    25. }
    26. }
     
  9. Offline

    Goblom

    Comphenix Make me require all your plugins y don't cha. ;p

    So, with ProtocolLib & ItemRenamer what is the difference between the two on the GlowEffect? Besides the registering of Creative Mode.

    I would rather not have to depend on both.
     
  10. Offline

    Comphenix

    Heh, yeah, perhaps I got a bit too carried away. The ItemRenamer dependency is not technically necessary, as you can copy what it does in your plugin by looking at its source code.

    ProtocolLib is responsible for intercepting packets efficiently and on a wide array of different server types - MCPC+, Spigot, CraftBukkit, while ItemRenamer takes care of processing the inventory packets specifically, and ensures creative mode doesn't accidentally overwrite your items.

    You can do all of this yourself, but I would ask that you at least soft-depend on ProtocolLib - that is, revert to using ProtocolLib if its present. Otherwise you will conflict with other plugins that also manipulate the protocol.

    How? Take a look at this plugin, specifically InteceptorProtocolLib and InteceptorQueuedPackets. Combining that and ItemRenamer should give you a solution with no dependencies that is still compatible with PL.
     
  11. Comphenix Will this not break when 2 plugins are using it? I'm guessing so but since you surprise me each time with some kind of fix :p
     
  12. Offline

    Comphenix

    Well, not exactly. If both plugins are using the exact same class, they will create a kind of chain where each list element forwards method calls to the next, until we get to the internal Minecraft list:
    Code:
    // Plugins are ordered by load order
    packets.add() -> plugin2.add() -> plugin1.add() -> minecraft.add()
    And most of the time, plugins are unloaded in the exact reverse order they're loaded, so they should clean up the list correctly. Unfortunately, plugins that explicitly reload other plugins (outside the reload command) may break this, so you can't really rely on this behavior.

    The second problem is that there's nothing stopping other plugins being difficult (or safe, from their perspective) and either crash or remove your plugin-specific list from the network manager, silently stopping your packet interception. For instance, I think TagAPI should be compatible, but Orebfuscator isn't.

    Your best bet is to detect any interference and ask the admin to install ProtocolLib, to avoid any potential conflicts.
     
  13. Comphenix Oh I see... I also have another question about the way you use the FieldSetter. Why? I know it's to detect if the field has been changed by another plugin but why not just use something like:
    Code:java
    1. Object fieldValue;
    2. //initialize it here
    3. if(!fieldValue.getClass().getName().equals("your.package.class")
    4. throw new RuntimeException("Another plugin is fooling around with the networkmanager!");
    5.  

    Or wouldn't that work (well) ?
     
Thread Status:
Not open for further replies.

Share This Page