Checking if a skulls visually looks the same

Discussion in 'Spigot Plugin Development' started by RobiRami, May 4, 2015.

  1. Hi,

    I'm trying to look if a skull looks the same like a default Minecraft head (I would trigger a system after that that detects if there is a namechange).
    The owner of the skull is offline.
    I tried looking at some methods from the Skull class, but I had no luck.

    Regards,
    Robin
     
  2. I guess you could get the player's head using an API such as minotar as well as the default minecraft head.
    And then compare them using either an pixel-per-pixel comparison (would be pretty slow imo), or maybe hashing both images could improve execution time (not sure it will works). There may be other images comparison methods, I don't really have any knowledge about this.
     
  3. NathanWolf

    Supporter

    You won't be able to get the texture from anywhere in the API (the server never has the texture, nor does it care). You'd have to get the Skull's owner name and download the skin yourself- I think all you'd have to do at that point is see if the skin exists.

    Easiest way may be to use a URL like this: http://skins.minecraft.net/MinecraftSkins/NathanWolf.png - if that gives you a 404, then the player has the default skin.

    If you actually care about whether they've taken the default skin and uploaded it as their skin, you could also do a pixel-by-pixel compare or a hash compare as suggested above :)
     
  4. Not true. This changed in 1.8 where the texture data was changed so it was received from authentication. This was to make it so the server could have a sha1 sum of the file (the link it receives) and clients can cache individual links to reduce the load on the Mojang servers.

    With that said, skins.minecraft.net is deprecated, and it does not work for new accounts.
    http://skins.minecraft.net/MinecraftSkins/Coelho.png
     
  5. gigosaurus

    Supporter

    I quickly whipped this up, it might be of some use. It basically will ensure that the given skull has the latest skin of that player (by updating it if necessary).

    Code (Java):

    private void updateSkull(Skull skull) {
        //get the texture from the GameProfile of the skull
        GameProfile skullProfile = ((CraftSkull) skull).getTileEntity().getGameProfile();
        if (skullProfile == null) {
            //skull doesn't have a skin/profile/owner
            return;
        }

        Property property = Iterables.getFirst(skullProfile.getProperties().get("textures"), null);
        if (property == null) {
            //if a skull has a gameprofile with no textures, if that's even possible
            return;
        }

        String skullTexture = property.getValue();
        JSONObject currentTexture = lookupTexture(skullProfile.getId());

        if (currentTexture == null) {
            //failed to lookup texture
            return;
        }

        //get the SKIN url from each texture
        String skullTextureURL = getTextureURL(skullTexture);
        String uuidTextureURL = getTextureURL((String) currentTexture.get("value"));

        if (!skullTextureURL.equals(uuidTextureURL)) {
            //skin has changed, update the skull's texture with the one we retrieved
            Property newProperty = new Property((String) currentTexture.get("name"), (String) currentTexture.get("value"), (String) currentTexture.get("signature"));
            skullProfile.getProperties().put("textures", newProperty);
        }
    }

    private JSONObject lookupTexture(UUID uuid) {
        if (uuid == null) {
            return null;
        }
        //get the texture for the skull's GameProfile's UUID, from Mojang's server
        String url = "https://sessionserver.mojang.com/session/minecraft/profile/" + uuid.toString().replace("-", "");
        String response;

        //you might want to use a different method of obtaining the JSON from the url
        try (InputStream inputStream = new URL(url).openStream();
            Scanner in = new Scanner(inputStream)) {
            StringBuilder input = new StringBuilder(420);
            while (in.hasNext()) {
                input.append(in.next());
            }
            response = input.toString();
        } catch (IOException e) {
            //most likely due to mojang's stupid rate limit
            e.printStackTrace();
            return null;
        }

        //check if the texture in this response equals the skull's texture
        JSONObject obj = (JSONObject) JSONValue.parse(response);
        JSONArray prop = (JSONArray) obj.get("properties");
        return (JSONObject) prop.get(0);
    }

    private String getTextureURL(String texture) {
        JSONObject obj = (JSONObject) JSONValue.parse(new String(Base64.getDecoder().decode(texture)));
        return (String) ((JSONObject) ((JSONObject) obj.get("textures")).get("SKIN")).get("url");
    }
     
     
    #5 gigosaurus, May 5, 2015
    Last edited: May 5, 2015
  6. NathanWolf

    Supporter

    Game profiles have skin URLs in them, not the texture data itself.

    Awwwww.. is that true? :(

    Do you have a link/announcement or anything? I assume Coelho is your IGN ... it's been working for me, for relatively new accounts, and (with a long delay) still updates when I change my skin. :\
     
  7. I said that in my post.

    There was no announcement, but it does not work. It was deprecated, and is also no longer used in the client.
     
  8. Thanks for the many replies, guys !