[SPIGOT-4820] Villager.getType() and villager.setType() Created: 30/Apr/19  Updated: 01/May/19  Resolved: 01/May/19

Status: Resolved
Project: Spigot
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Minor
Reporter: Linus Närkling Assignee: Unassigned
Resolution: Fixed Votes: 2
Labels: 1.14, API, feature, villager

Attachments: PNG File outfits.png    
Version: This server is running CraftBukkit version git-Spigot-e4be9b0-5736cdc (MC: 1.14) (Implementing API version 1.14-R0.1-SNAPSHOT)
Guidelines Read: Yes

 Description   

It is currently possible to manage a Villager's profession using Villager.getProfession​() and Villager.setProfession​(Villager.Profession). It is however not possible to set a Villager's Type (NBT VillagerData > type). Therefore it is not possible using the API to set a Villager to use any of the available skins - see "Outfits" under https://minecraft.gamepedia.com/Villager#Professions

Similarly to Profession, it would probably be an enum named something like Villager.Type and contain DESERT, JUNGLE, PLAINS, SAVANNA, SNOWY, SWAMP, and TAIGA.

As also noted in comments in SPIGOT-4766, something like Villager.setLevel() would also be required to get the profession to retain.

Edit:

A possible name other than "Villager.Type" could be "Villager.Outfit", "Villager.OutfitType", "Villager.Biome", "Villager.BiomeOutfit", or "Villager.BiomeType". The first is more consistent to what they're called in the NBT, but outfit type is more appropriate to what it's referring to. Villager.getType() is already used by Entity.getType(), so would have to be a different name I think.

Edit 2:

This seems like it should be relatively easy to implement.

Adding something like this to org.bukkit.entity.Villager:

// Internally the VillagerData constructor ensures this is not lesser than 1.
public int getLevel();

// Should this throw an exception if level is set to lesser than 1? Or just silently let the VillagerData constructor reset it to 1?
public void setLevel(int level);

// Not sure about name yet
@NotNull
public OutfitType getOutfitType();

// Not sure about name yet
public void setOutfitType(@NotNull OutfitType outfitType);

// Not sure about the name yet. Type? Outfit? OutfitType? Other?
public enum OutfitType {
    DESERT,
    JUNGLE,
    PLAINS,
    SAVANNA,
    SNOWY,
    SWAMP,
    TAIGA;
}

And then in org.bukkit.craftbukkit.entity.CraftVillager:

@Override
public int getLevel() {
    return getHandle().getVillagerData().getLevel();
}

@Override
public void setLevel(int level) {
    getHandler().setVillagerData(getHandle().getVillagerData().withLevel(level));
}

@Override
public OutfitType getOutfitType() {
    return OutfitType.valueOf(IRegistry.VILLAGER_TYPE.getKey(getHandle().getVillagerData().getType()).getKey().toUpperCase(Locale.ROOT));
}

@Override
public void setOutfitType(OutfitType outfitType) {
    Validate.notNull(outfitType);
    getHandle().setVillagerData(getHandle().getVillagerData().withType(IRegistry.VILLAGER_TYPE.get(new MinecraftKey(outfitType.name().toLowerCase(Locale.ROOT)))));
}

Obviously, this would need javadocs as well and some other tweaks. Might not compile as is either, I haven't tested it. I tried doing basically this but with NMS and it seems to work just fine. I'll consider trying to create a pull request but I have never contributed to Spigot before so it's pretty daunting. I don't really know how to compile Spigot after making changes so can't test it atm. I wouldn't know what to name the VillagerType things anyways. They're "getType()" in VillagerData but "getType()" is already used in the Villager interface.



 Comments   
Comment by Linus Närkling [ 30/Apr/19 ]

I added a potential implementation suggestion, but tbh I don't really know what I'm doing 😬

Generated at Tue Apr 22 05:09:39 UTC 2025 using Jira 10.3.5#10030005-sha1:190c783f2bd6c69cd5accdb70f97e48812a78d14.