How to get the skull with texture as itemstack correctly! (Alex head error)

Discussion in 'Plugin Development' started by Proxygames14, Aug 18, 2017.

Thread Status:
Not open for further replies.
  1. Im trying to make an instance of an playerhead!
    But for some reason it didnt worked since 1.8!
    Now when you use the SkullMeta method the skull texture will only be updated when place the block!
    So how to get the correct itemstack as variable to use in my GUI!?

    I tried
    Code:
        public ItemStack CreateSkull(Player p, String owner) {             
               name = owner;
               Location loc = p.getLocation();
               loc.getBlock().setType(Material.SKULL);          
               loc.getBlock().setData((byte) 3);
               Skull s = (Skull)loc.getBlock().getState();
               s.setOwner(owner);
               s.update();                     
              return loc.getBlock().getDrops().iterator().next();
        }
     
  2. Offline

    Zombie_Striker

    @Proxygames14
    Since 1.8, minecraft has changed the way skulls are updated. To get the skin, you will need to place the head somewhere in the world, for atleast one tick, and then update the inventory.
     
  3. I tried p.updateinventory();
    Still not working
     
  4. Offline

    Zombie_Striker

    @Proxygames14
    Are you placing the head somewhere in the world?
     
  5. @Proxygames14 @Zombie_Striker
    Actually, it is far simpler than having to place a block. You can just invoke the TileEntitySkull#b(GameProfile, Predicate) method. Do note that this will get the skin data on another thread, so you have to pass a callback to the method (the predicate is the callback, I'm not sure why they used a Predicate as a parameter, but whatever), and inside that callback do your code to give the item to the player.

    Here's an example which will give you my skin, without having to place it first:
    Code:java
    1. Player player = ...;
    2. TileEntitySkull.b(new GameProfile(null, "AlvinB"), gameProfile -> {
    3. ItemStack skull = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
    4. SkullMeta meta = (SkullMeta) skull.getItemMeta();
    5. meta.setOwner("AlvinB");
    6. skull.setItemMeta(meta);
    7. player.getInventory().addItem(skull);
    8. return false;
    9. });
     
    Zombie_Striker likes this.

  6. When I try it it gives me unkown errors. Could you make a public void Method from it ?
     
  7. @Proxygames14
    Well that's your job :p

    Just put it in an event or onCommand or whatever, just where you want the skull to be given.
     
  8. I mean the text "
    gameProfile -> {
    ItemStack
    "

    Is not allowed! Error!

    do I need to replace the gameprofile or something?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
  9. @Proxygames14
    Well, that is a lambda expression. Are you not using Java 8?
     
  10. @AlvinB
    Yes! But I get this

    https://ibb.co/dsy6XQ

    @AlvinB
    My libary is jre.1.8.0_131

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
  11. @Proxygames14
    Huh. That should work with Java 8. But you could try just replacing it with an anonymous subclass:
    Code:java
    1. TileEntitySkull.b(new GameProfile(null, "AlvinB"), new Predicate<GameProfile>() {
    2. @Override
    3. public boolean apply(@Nullable GameProfile gameProfile) {
    4. ItemStack skull = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
    5. SkullMeta meta = (SkullMeta) skull.getItemMeta();
    6. meta.setOwner("AlvinB");
    7. skull.setItemMeta(meta);
    8. player.getInventory().addItem(skull);
    9. return false;
    10. }
    11. });

    EDIT: Something you should also know is that this is version dependent and will break with every update unless you use Reflection.

    EDIT #2: I have now realized that this technique ONLY works on Spigot. Pardon my mistake.
     
    Last edited: Aug 19, 2017
  12. @Proxygames14
    I think you posted the wrong image, it's the same one as before.

    Also, are you compiling with CraftBukkit?
     
  13. I am! Bukkit 1.12. But Compiler is currently 1.7
     
  14. @Proxygames14
    What do you mean by 'Compiler is 1.7'? Are you compiling against 1.7?
     
  15. Im using Eclipse Juno And I think the compiler max go's to 1.7
     
  16. @Proxygames14
    Oh, Java Compiler, but that shouldn't be a problem if you're using the anonymous class instead of the lambda. Are you sure you have the CraftBukkit 1.12 jar referenced in your project?
     
  17. @AlvinB
    My builth path = Bukkit.1.12
    And Im switched to Version: Oxygen Release (4.7.0)
    1 minute ago!

    @AlvinB
    1 thing The GameProfile finaly worked because I switched to 1.8

    But the b() method still wont work!

    ERROR LOG:
    The method b(GameProfile) in the type TileEntitySkull is not applicable for the arguments (GameProfile, (<no type> gameProfile) -> {})

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
  18. @Proxygames14
    Could you post the full class, including imports?

    I suspect you might've imported java.util.function.Predicate instead of
    com.google.common.base.Predicate
     
  19. Code:
    package proxygames.ezchatmanager.CMDHandlers;
    
    
    import java.lang.reflect.InvocationTargetException;
    
    
    import org.bukkit.Material;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.craftbukkit.libs.jline.internal.Nullable;
    import org.bukkit.entity.Player;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.SkullMeta;
    
    import com.google.common.base.Predicate;
    import com.mojang.authlib.GameProfile;
    
    import net.minecraft.server.v1_12_R1.TileEntitySkull;
    import proxygames.ezchatmanager.AuctionsGUI.GUI;
    import proxygames.ezchatmanager.AuctionsGUI.SkullData;
    import proxygames.ezchatmanager.DataBase.Files.FileConfig;
    import proxygames.ezchatmanager.DataBase.Files.FileManager;
    import proxygames.ezchatmanager.DataBase.Files.Files;
    
    public class CommandManager implements CommandExecutor {
    
        @SuppressWarnings("deprecation")
        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String label,
            String[] a) {
    
            TileEntitySkull.b(new GameProfile(null, "AlvinB"), gameProfile -> {
               
            });
           
           
            TileEntitySkull.b(new GameProfile(null, "AlvinB"), gameProfile -> {
                ItemStack skull = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
                SkullMeta meta = (SkullMeta) skull.getItemMeta();
                meta.setOwner("AlvinB");
                skull.setItemMeta(meta);
                player.getInventory().addItem(skull);
                return false;
            });
           
           
           
            Player p = (Player) sender;
            int i  = 2;
            if(i==2) {
                try {
                   
                    p.getInventory().addItem(SkullData.CreateSkull(p));
                    p.updateInventory();
                    new FileManager().getFile(Files.CONFIG).set("test", SkullData.CreateSkull(p));
                    FileConfig.Save();
                } catch (ClassNotFoundException | NoSuchMethodException
                        | SecurityException | IllegalAccessException
                        | IllegalArgumentException | InvocationTargetException
                        | InstantiationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return false;
            }
    
    
            ItemStack skull = new ItemStack(397, 1, (short) 3);
            SkullMeta meta = (SkullMeta) skull.getItemMeta();
            meta.setOwner("Notch");
            skull.setItemMeta(meta);
            p.getInventory().addItem(skull);
           
           
            GUI gui = new GUI();
            try {
                gui.OpenGUI((Player) sender, a[0]);
            } catch (ClassNotFoundException | NoSuchMethodException
                    | SecurityException | IllegalAccessException
                    | IllegalArgumentException | InvocationTargetException
                    | InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return false;
    
       
    
        }
       
       
       
    }
    
     
  20. @Proxygames14
    Oh, I see what the error is. Apparently that method changed between 1.12 and 1.12.1. If you change your CraftBukkit dependency to 1.12.1, it should work.
     
  21. @AlvinB
    Thank you, I will definetely test it out now!
    1 more question for in the future!
    So the function only works when the bukkit version is up to date?
    So I always need to update the bukkit?
     
  22. @Proxygames14
    Well, this would only work when the Bukkit version you used to compile matches the Bukkit version on the server. There are however ways to get around this using reflection.
     
  23. @AlvinB
    I changed the builth path to 1.12.1
    And nothing changed about the error I gave you
     
  24. @Proxygames14
    Can you post the error, just to make sure?

    Also, are you absolutely sure you've removed 1.12 and added 1.12.1 as your dependency?

    EDIT: Turns out I am the stupid one. The functionality I am talking about only exists in Spigot. Just nevermind all of what I said unless you're using Spigot.
     
    Last edited: Aug 19, 2017
  25. @AlvinB
    Its ok.
    So my main question, Is there a bukkit method that works on bukkit:p
     
  26. @Proxygames14
    I feel a bit sorry that I lead you up the garden path, so I broke out the NBTUtil and Mojang API and put together this:
    Code:java
    1. MojangAPIUtil.getSkinData(UUID.fromString("da81fc75-503e-457f-b2d3-6fd739c91855"), (successful, result, exception) -> {
    2. if (successful && result != null) {
    3. ItemStack itemStack = NBTUtil.setItemNBT(new ItemStack(Material.SKULL_ITEM, 1, (short) 3), getSkullCompoundFromSkinData(result));
    4. player.getInventory().addItem(itemStack);
    5. } else {
    6. // Failed to get skin data! :(
    7. // In this case we use the SkullMeta method
    8. // so at least it'll work when the skull is
    9. // placed.
    10. ItemStack itemStack = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
    11. SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
    12. meta.setOwner("AlvinB");
    13. itemStack.setItemMeta(meta);
    14. player.getInventory().addItem(itemStack);
    15. }
    16. });
    17.  
    18. private NBTUtil.NBTTagCompound getSkullCompoundFromSkinData(MojangAPIUtil.SkinData skinData) {
    19. NBTUtil.NBTTagCompound compound = new NBTUtil.NBTTagCompound();
    20. NBTUtil.NBTTagCompound skullOwner = new NBTUtil.NBTTagCompound();
    21. skullOwner.setString("Name", skinData.getName());
    22. NBTUtil.NBTTagCompound properties = new NBTUtil.NBTTagCompound();
    23. NBTUtil.NBTTagCompound texture = new NBTUtil.NBTTagCompound();
    24. texture.setString("Value", skinData.getBase64());
    25. properties.setList("textures", Collections.singletonList(texture));
    26. skullOwner.set("Properties", properties);
    27. compound.set("SkullOwner", skullOwner);
    28. return compound;
    29. }
    That piece of code is functional on CraftBukkit (and Spigot!). However, the downside is that it requires these three util classes of mine:
    https://github.com/Alvin-LB/BukkitU...m/bringholm/reflectutil/v1_1/ReflectUtil.java
    https://github.com/Alvin-LB/BukkitU.../java/com/bringholm/nbtutil/v1_1/NBTUtil.java
    https://github.com/Alvin-LB/BukkitU...ingholm/mojangapiutil/v1_0/MojangAPIUtil.java

    It's also a very quick implementation I scrambled together, if you actually wanted to use this code, you should implement a caching system for the skins.
     
  27. @AlvinB
    Thank you so much for helping me!
     
Thread Status:
Not open for further replies.

Share This Page