API Variant System - MarkusBordihn/BOs-Easy-NPC GitHub Wiki

Variant System API 🎨

Easy NPC exposes its variant system for external entities and renderers.

Back to API.

Overview

The variant system stores the selected variant name in synched entity data and resolves it back to an enum through getSkinVariantType(String name).

Relevant types:

  • de.markusbordihn.easynpc.api.skin.VariantTexture
  • de.markusbordihn.easynpc.entity.easynpc.data.VariantDataCapable
  • de.markusbordihn.easynpc.client.renderer.entity.EasyNPCEntityRenderer

Variant Enum

Implement VariantTexture on the enum:

public enum PigCompanionVariant implements VariantTexture {
  WHITE("white"),
  BROWN("brown"),
  BLACK("black");

  private final ResourceLocation textureLocation;

  PigCompanionVariant(String name) {
    this.textureLocation =
        new ResourceLocation("yourmod", "textures/entity/pig_companion/" + name + ".png");
  }

  @Override
  public ResourceLocation getTextureLocation() {
    return textureLocation;
  }
}

Entity Implementation

VariantDataCapable is parameterized with the entity type:

public class PigCompanion extends Pig
    implements EasyNPC<PigCompanion>, VariantDataCapable<PigCompanion> {

  @Override
  public void defineSynchedData() {
    super.defineSynchedData();
    defineSynchedVariantData();
  }

  @Override
  public PigCompanionVariant[] getSkinVariantTypes() {
    return PigCompanionVariant.values();
  }

  @Override
  public PigCompanionVariant getDefaultSkinVariantType() {
    return PigCompanionVariant.WHITE;
  }

  @Override
  public PigCompanionVariant getSkinVariantType(String name) {
    try {
      return PigCompanionVariant.valueOf(name);
    } catch (IllegalArgumentException exception) {
      return getDefaultSkinVariantType();
    }
  }
}

Renderer Implementation

Use EasyNPCEntityRenderer to reuse the built-in texture handling:

public class PigCompanionRenderer extends PigRenderer implements EasyNPCEntityRenderer {

  public PigCompanionRenderer(EntityRendererProvider.Context context) {
    super(context);
  }

  @Override
  public ResourceLocation getTextureLocation(Pig entity) {
    return getTextureLocationWithConfig(entity);
  }

  @Override
  public ResourceLocation getDefaultTexture() {
    return PigCompanionVariant.WHITE.getTextureLocation();
  }
}

Custom Models with Variant Textures

If you combine variants with custom geometry, the useful part is usually the texture mode selection.

Example:

public class ArmoredPigRenderer extends PigRawRenderer {

  public ArmoredPigRenderer(EntityRendererProvider.Context context) {
    super(
        context,
        OriginalModelConfig.withHidden(),
        CustomModelConfig.replacementUseVariantTexture(MyModModelLayers.ARMORED_PIG));
  }
}

This setup:

  • hides the original model
  • uses a custom baked model layer
  • resolves textures from the current variant only

Texture Selection Helpers

EasyNPCEntityRenderer currently provides:

  • getEntityTexture(easyNPC)
  • getVariantTexture(easyNPC)
  • getTextureByVariant(variant)
  • getTextureLocationWithConfig(entity)

getEntityTexture(...) respects skin types such as custom and remote textures. getVariantTexture(...) uses only the current variant texture.

Original Model Configuration

Use OriginalModelConfig when you want to change how the original model resolves its texture:

OriginalModelConfig.DEFAULT
OriginalModelConfig.withHidden()
OriginalModelConfig.withTexture(texture)
OriginalModelConfig.withVariantTexture()
OriginalModelConfig.withEntityTexture()

Custom Model Configuration

Use CustomModelConfig when you add a custom model layer:

CustomModelConfig.overlay(layer, texture)
CustomModelConfig.overlayUseEntityTexture(layer)
CustomModelConfig.overlayUseVariantTexture(layer)
CustomModelConfig.replacement(layer, texture)
CustomModelConfig.replacementUseEntityTexture(layer)
CustomModelConfig.replacementUseVariantTexture(layer)

Each of these factory methods requires a ModelLayerLocation.

Useful helpers on CustomModelConfig:

config.hasCustomModel()
config.shouldUseEntityTexture()
config.shouldUseVariantTexture()
config.shouldHideOriginal()

Sync Behavior

defineSynchedVariantData() registers the variant string in the Easy NPC synched data system.

Saved data is also written to and read from the VariantType NBT tag through:

  • addAdditionalVariantData(...)
  • readAdditionalVariantData(...)

In practice this means:

  • the selected variant is synced as a string
  • your entity resolves that string back to an enum
  • renderers can then use either full skin lookup or variant-only texture lookup

Notes

  • The default built-in fallback variant is HumanoidSkinVariant.STEVE.
  • Helper methods such as hasVariantTypeCrossedArms() and hasVariantTypeSaddled() are available on VariantDataCapable.
  • Villager-related helpers are also exposed through getVillagerProfession(...) and getVillagerType(...).