CitizensDev / Citizens2

Citizens - the premier plugin and API for creating server-side NPCs in Minecraft.
https://citizensnpcs.co
Open Software License 3.0
601 stars 315 forks source link

NPCs resetting skin or not setting skin at all #1138

Closed Mrtenz closed 6 years ago

Mrtenz commented 7 years ago

I am trying to use the API to set skins of player NPCs, using a texture and signature value. I tried using persistent NPC data, changing the GameProfile of SkinnableEntity and changing the GameProfile of the actual entity. Nothing seems to work consistently. The NPC will either reset the skin to what the skin of the Minecraft player with the name is, or reset it to Steve/Alex.

After looking through the source code of SkinnableEntity and the /npc skin command I still can't figure out how to properly set the NPC skin using a texture and signature.

Is this possible and if so, how would I do it?

seedie commented 7 years ago

My npcs always lose their skins after a while and return to steve/alex. Another method of setting skins to prevent this would be very useful if any of the developers can manage it.

fullwall commented 7 years ago

Yes, I agree - the API is not very well designed (came from a pull request).

You need to set a bunch of NPC properties and then respawn the NPC or call SkinnableEntity.apply

npc.data().set(NPC.PLAYER_SKIN_UUID_METADATA, "uuid"); npc.data().set(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_METADATA, "texture"); npc.data().set(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_SIGN_METADATA, "sign");

fullwall commented 7 years ago

You can also go through the code at https://github.com/CitizensDev/Citizens2/tree/master/main/src/main/java/net/citizensnpcs/npc/skin

Mrtenz commented 7 years ago

I did go through the code, but haven't been able to fix this.

I was already using npc.data().set(...). I tried your code, like this:

        npc.data().set(NPC.PLAYER_SKIN_UUID_METADATA, UUID.randomUUID().toString());
        npc.data().set(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_METADATA, texture);
        npc.data().set(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_SIGN_METADATA, signature);

...doesn't work. Setting the UUID to the UUID of the original skin holder doesn't work either. The NPC will show up as Alex/Steve. When setting _Skin.CACHED_SKIN_UUID_NAMEMETADATA, the actual skin shows up for about 0.1s, then shows as some random skin.

fullwall commented 7 years ago

It may be related to this code: https://github.com/CitizensDev/Citizens2/blob/master/main/src/main/java/net/citizensnpcs/npc/skin/Skin.java#L85

Mrtenz commented 7 years ago

I see, how would I fix this? Is it possible to manually cache a skin?

I tried the following:

        String randomName = UUID.randomUUID().toString();
        Skin skin = Skin.get(randomName, false);

        npc.data().set(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_METADATA, texture);
        npc.data().set(NPC.PLAYER_SKIN_TEXTURE_PROPERTIES_SIGN_METADATA, signature);
        npc.data().set(Skin.CACHED_SKIN_UUID_NAME_METADATA, randomName);
        npc.data().set(NPC.PLAYER_SKIN_USE_LATEST, false);

        SkinnableEntity entity = (SkinnableEntity) npc.getEntity();
        skin.apply(entity);
        npc.despawn(DespawnReason.PENDING_RESPAWN);
        npc.spawn(npc.getStoredLocation());

It still only shows Steve/Alex.

fullwall commented 7 years ago

Did skin.apply return true or false?

Mrtenz commented 7 years ago

It returns true.

Mrtenz commented 7 years ago

Some help would be appreciated. I haven't managed to fix this yet...

seedie commented 7 years ago

Im not sure if its relevant but this happens whenever i teleport to a place with citizens there http://i.imgur.com/M4lbmnV.jpg I noticed 'tablistremover.jar' and remembered a version of citizens where the NPC's skins worked flawlessly, apart from their names appearing on the tablist. The version released after had broken the skins again (would randomly reset to Steve/Alex, still do even in the latest version for 1.12) however the tablist was fixed. Perhaps our problem is something to do with the tablist remover?

mcmonkey4eva commented 6 years ago

NPC skins require tablist interaction to properly set. Any plugins interfering with that are potential issues with that working.

Also, SkinnableEntity is a more properly capably API now than it was before (has a way to directly apply texture data), which should suffice to properly solve your issue.

Also, eh, do actually set legitimate texture+signature+name groups, not a randomly generated uuid. The minecraft client will validate them.