Curios API (Forge/NeoForge)

Curios API (Forge/NeoForge)

140M Downloads

[1.14.4] [QUESTION] Render (+ usage)

Shazuli opened this issue ยท 3 comments

commented

Hi

I got my Curio slots working fine and marked a few random items to be placed there. But I'm having issues with creating a new Curio vanity item that should render a texture on the player's head (mask).

ItemMask
public class ItemMask extends Item implements ICurio
{

    private final ResourceLocation texture;
    private final ModelMask model = new ModelMask();

    public ItemMask(String name, ResourceLocation texture)
    {
        super(new Item.Properties().group(ItemGroup.REDSTONE));

        this.texture = texture;
        setRegistryName(name);
    }


    @Override
    public void doRender(String identifier, LivingEntity entitylivingbaseIn, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale)
    {
        Minecraft.getInstance().getTextureManager().bindTexture(this.texture);

        ICurio.RenderHelper.followHeadRotations(entitylivingbaseIn, model.mask);

        model.render(entitylivingbaseIn,limbSwing,limbSwingAmount,ageInTicks,netHeadYaw,headPitch,scale);
    }

    @Override
    public void onCurioTick(String identifier, LivingEntity entityLivingBase)
    {
        System.out.println("Devilman!");
    }

    @Override
    public boolean hasRender(String identifier, LivingEntity entityLivingBase)
    {
        return true;
    }
}

I tried to just make it spam the console, but as that doesn't seem to happen I must've missed something.

commented

Don't implement ICurio directly on your item, use a capability provider to attach an implementation. Like this:

@Override
public ICapabilityProvider initCapabilities(ItemStack stack, CompoundNBT unused) {
return CapCurioItem.createProvider(new ICurio() {
private final ResourceLocation AMULET_TEXTURE =
new ResourceLocation(Curios.MODID, "textures/entity/amulet.png");
private Object model;
@Override
public void onCurioTick(String identifier, LivingEntity entityLivingBase) {
if (!entityLivingBase.getEntityWorld().isRemote &&
entityLivingBase.ticksExisted % 40 == 0) {
entityLivingBase.addPotionEffect(
new EffectInstance(Effects.REGENERATION, 80, 0, true, true));
}
}
@Override
public boolean hasRender(String identifier, LivingEntity entityLivingBase) {
return true;
}
@Override
public void doRender(String identifier, LivingEntity entitylivingbaseIn, float limbSwing,
float limbSwingAmount, float partialTicks, float ageInTicks,
float netHeadYaw, float headPitch, float scale) {
Minecraft.getInstance().getTextureManager().bindTexture(AMULET_TEXTURE);
ICurio.RenderHelper.rotateIfSneaking(entitylivingbaseIn);
if (!(this.model instanceof ModelAmulet)) {
this.model = new ModelAmulet();
}
((ModelAmulet) model).render(entitylivingbaseIn, limbSwing, limbSwingAmount, ageInTicks,
netHeadYaw, headPitch, scale);
}
});
}

Ignore the fact that the item itself also implements ICurio, that's some legacy code.

You don't need to use CapCurioItem#createProvider, and you probably shouldn't since it's an internal helper method, as long as you return your own ICapabilityProvider implementation.

If you need an example of that, I have a basic implementation in one of my Curio mods, although the context is slightly different because it's in an AttachCapabilitiesEvent event:
https://github.com/TheIllusiveC4/CurioOfUndying/blob/e92796467ad33abf80eaa7d6273446b81b9e3b26/src/main/java/top/theillusivec4/curioofundying/CurioOfUndying.java#L65-L84

commented

Thanks. Something I wonder though is how I make it run on a server. Whenever I try and join an account and I spawn in my item I get disconnected.
java.lang.RuntimeException: Attempted to load class net/minecraft/client/renderer/entity/model/EntityModel for invalid dist DEDICATED_SERVER

ItemMask
public class ItemMask extends Item
{

    private final ResourceLocation texture;
    private final boolean hideName;

    public ItemMask(String name, ResourceLocation texture, boolean hideName)
    {
        super(new Item.Properties().group(ItemGroup.REDSTONE));

        this.texture = texture;
        this.hideName = hideName;
        setRegistryName(name);
    }

    public boolean hidesIdentity()
    {
        return hideName;
    }

    @Nullable
    @Override
    public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundNBT nbt)
    {

        ICurio curio = new ICurio() {

            private final ModelMask model = ModelMask.modelMask;


            @Override
            public void onEquipped(String identifier, LivingEntity entityLivingBase)
            {
                if (hidesIdentity())
                    entityLivingBase.setCustomNameVisible(false);
            }

            @Override
            public void onUnequipped(String identifier, LivingEntity entityLivingBase)
            {
                if (hidesIdentity())
                    entityLivingBase.setCustomNameVisible(true);
            }

            @Override
            public void doRender(String identifier, LivingEntity entitylivingbaseIn, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale)
            {

                Minecraft.getInstance().getTextureManager().bindTexture(texture);

                ICurio.RenderHelper.followHeadRotations(entitylivingbaseIn,model.mask);
                model.render(entitylivingbaseIn,limbSwing,limbSwingAmount,ageInTicks,netHeadYaw,headPitch,scale);


            }

            @Override
            public boolean canRightClickEquip()
            {
                return true;
            }

            @Override
            public boolean hasRender(String identifier, LivingEntity entityLivingBase)
            {
                return true;
            }
        };

        ICapabilityProvider provider = new ICapabilityProvider() {
            private final LazyOptional<ICurio> curioOpt =
                    LazyOptional.of(() -> curio);

            @Nonnull
            @Override
            public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap,
                                                     @Nullable Direction side) {

                return CuriosCapability.ITEM.orEmpty(cap, curioOpt);
            }
        };
        return provider;
    }
}
ModelMask
public class ModelMask extends EntityModel
{

    public RendererModel mask;

    public static final ModelMask modelMask = new ModelMask();

    public ModelMask()
    {
        this.textureWidth = 24;
        this.textureHeight = 16;

        this.mask = new RendererModel(this,0,0);
        this.mask.setRotationPoint(0,0,0);
        this.mask.addBox(-4.0F, -8.0F, -4F, 8, 8, 8, 0.0F);

    }


    @Override
    public void render(Entity entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scale)
    {
        this.mask.render(scale);
    }
}

I thought I could avoid it by not initiating it in the capability provider, but that didn't work obviosly.

commented

That's because you're trying to load ModelMask server-side even though it's a client-only class. There are a few ways to avoid loading it server-side. You can do what I did (it's in the code above), which is to declare it as a generic Object object and then initialize it to the right instance in the doRender method. Alternatively, you can add @OnlyIn(Dist.CLIENT) annotations to your ModelMask variable and your doRender method to have them only load on the client.