Solved Player skulls

Discussion in 'Spigot Plugin Development' started by MrIvanPlays, Feb 26, 2020.

  1. Any way I can set the skin manually of a skull? I need that because when I send a request to mojang api, and then bukkit sends because of SkullMeta#setOwningPlayer, bukkit will get TooManyRequestsException and so the head becomes alex or steve.
     
  2. FrostedSnowman

    Resource Staff

    If you have the encoded texture value, you can use that. There is a method in the underlying implementation:
    CraftSkullMeta::setProfile which lets you set the skull's GameProfile. You'll need to invoke this method via reflection. It takes a GameProfile as a parameter. The GameProfile you specify should include the texture you want the skull to have.

    Often you see people directly accessing & replacing the GameProfile of the skull via reflection, however; this does not account for the NBT change required and can result in some plugins breaking. Thus, you should use the method I mentioned above. For example:
    Code (Java):
    String textureValue = ...;

    GameProfile profile = new GameProfile(UUID.randomUUID(), "example");
    profile.getProperties().put("textures", new Property("textures", textureValue, ""));

    //Invoke setProfile through reflection--it's private--and provide the profile^ as the parameter
     
    • Agree Agree x 1
  3. I already have some modules due to bukkit skin setter, thanks for pointing me to the method tho. Don't need to use reflection
     
  4. Looks like I still don't have a solution :/ . I need it backwards compatible with 1.15.1 and 1.15, also with 1.14 - 1.14.4, 1.13.2 and 1.12

    I tried a code which in theory should have invoked the NBTTagCompound constructor, but I got that it can't find that constructor.
    Now I tried this:

    Code (Java):
        CraftOfflinePlayer player = (CraftOfflinePlayer) Bukkit.getOfflinePlayer(skin.getOwner());
        GameProfile profile = new GameProfile(skin.getOwner(), ownerName);
        profile
            .getProperties()
            .put("textures", new Property("textures", skin.getTexture(), skin.getSignature()));
        try {
          Field profileField = player.getClass().getField("profile");
          profileField.setAccessible(true);
          profileField.set(player, profile);
        } catch (IllegalAccessException | NoSuchFieldException e) {
          e.printStackTrace();
        }
    and I get NoSuchFieldException :/ . Any suggestions?
     
  5. I already have that. The thing is that java can't find the things im trying to modify/access.
     
  6. FrostedSnowman

    Resource Staff

    Class::getField is used for public fields. In your case, you need to use Class::getDeclaredField.
     
  7. Haven't used reflection for a while so I forgot that thing exists. That solution worked perfectly. Thanks

    Thread marked as solved. If you have any other suggestions you can feel free to post them./