Ok so progress report:
I've started going in the direction of a ICustomModelLoader based on ModelDynBucket, but I'm still struggling to put the pieces together. It's clear that this model loader is registered properly, since I'm no longer getting errors about missing blockstate or item model .json files. I can also confirm that it accepts exactly 1 resource location (which I assume with relative certainty to be the item in question), and that it gets loadModel called, constructs a new model, and that the model then gets bake called, which constructs a new baked model
All that is well and good, but my custom ItemOverrideList doesn't seem to be getting utilized; neither getOverrides nor handleItemState get called. I don't see any place to register it, and I don't see anything different between my class and the ModelDynBucket class. If anyone has any insight on how to fix this, it would be greatly appreciated.
(Sidenote: I acknowledge that my current code for creating and storing the DynamicTexture in the process method is garbage, but one step at a time y'know)
package com.chaseoqueso.bitcrafting.rendering;
import com.chaseoqueso.bitcrafting.BitCraftingMod;
import com.chaseoqueso.bitcrafting.items.ItemBitSword;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.*;
import net.minecraft.client.renderer.texture.DynamicTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.client.model.*;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.TRSRTransformation;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.Function;
public class ModelBitSword implements IModel
{
public static final ModelResourceLocation LOCATION = new ModelResourceLocation(new ResourceLocation(BitCraftingMod.MODID, "itembitsword"), "inventory");
private DynamicTexture tempTexture;
@Nullable
private ResourceLocation textureLocation;
public ModelBitSword()
{
this(null);
}
public ModelBitSword(@Nullable ResourceLocation textureLocation)
{
this.textureLocation = textureLocation;
}
@Override
public Collection<ResourceLocation> getTextures()
{
ImmutableSet.Builder<ResourceLocation> builder = ImmutableSet.builder();
if (textureLocation != null)
builder.add(textureLocation);
return builder.build();
}
@Override
public IBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
{
ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transformMap = PerspectiveMapWrapper.getTransforms(state);
TRSRTransformation transform = state.apply(Optional.empty()).orElse(TRSRTransformation.identity());
TextureAtlasSprite fluidSprite = null;
TextureAtlasSprite particleSprite = null;
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
if (textureLocation != null)
{
IBakedModel model = (new ItemLayerModel(ImmutableList.of(textureLocation))).bake(state, format, bakedTextureGetter);
builder.addAll(model.getQuads(null, null, 0));
particleSprite = model.getParticleTexture();
}
return new ModelBitSword.BakedBitSword(this, builder.build(), particleSprite, format, Maps.immutableEnumMap(transformMap), Maps.newHashMap(), transform.isIdentity());
}
@Override
public ModelBitSword process(ImmutableMap<String, String> customData)
{
String colorArrayString = customData.get("colorArrayString");
String[] items = colorArrayString.split(",");
tempTexture = new DynamicTexture(16, 16);
int[] textureArray = tempTexture.getTextureData();
for (int i = 0; i < items.length; i++) {
try {
textureArray[i] = Integer.parseInt(items[i]);
} catch (NumberFormatException nfe) {
System.out.println("ERROR: Something went wrong with converting the sword's color data from string to int array");
};
}
tempTexture.updateDynamicTexture();
textureLocation = Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation("itembitsword/" + colorArrayString, tempTexture);
return new ModelBitSword(textureLocation);
}
@Override
public ModelBitSword retexture(ImmutableMap<String, String> textures)
{
ResourceLocation base = textureLocation;
if (textures.containsKey("base"))
base = new ResourceLocation(textures.get("base"));
return new ModelBitSword(base);
}
public enum LoaderBitSword implements ICustomModelLoader
{
INSTANCE;
@Override
public boolean accepts(ResourceLocation modelLocation)
{
if(modelLocation.getResourceDomain().equals(BitCraftingMod.MODID) && modelLocation.getResourcePath().contains("itembitsword")) System.out.println("Bit Sword Accepts");
return modelLocation.getResourceDomain().equals(BitCraftingMod.MODID) && modelLocation.getResourcePath().contains("itembitsword");
}
@Override
public IModel loadModel(ResourceLocation modelLocation)
{
return new ModelBitSword();
}
@Override
public void onResourceManagerReload(IResourceManager resourceManager)
{
//I think I need to clear the cache here but idk what that means or how to do it (probably something to do with BakedBitSword.cache but that's private so idk)
}
}
private static final class BakedBitSwordOverrideHandler extends ItemOverrideList
{
public static final ModelBitSword.BakedBitSwordOverrideHandler INSTANCE = new ModelBitSword.BakedBitSwordOverrideHandler();
private BakedBitSwordOverrideHandler()
{
super(ImmutableList.of());
}
@Override
public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity)
{
if (!(stack.getItem() instanceof ItemBitSword))
{
return originalModel;
}
ModelBitSword.BakedBitSword model = (ModelBitSword.BakedBitSword)originalModel;
String arrayString = ItemBitSword.getColorArrayAsString(stack);
if (!model.cache.containsKey(arrayString))
{
ModelBitSword parent = model.parent.process(ImmutableMap.of("colorArrayString", arrayString));
Function<ResourceLocation, TextureAtlasSprite> textureGetter;
textureGetter = location -> Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(location.toString());
IBakedModel bakedModel = parent.bake(new SimpleModelState(model.transforms), model.format, textureGetter);
model.cache.put(arrayString, bakedModel);
return bakedModel;
}
return model.cache.get(arrayString);
}
}
private static final class BakedBitSword extends BakedItemModel
{
private final ModelBitSword parent;
private final Map<String, IBakedModel> cache;
private final VertexFormat format;
private final ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transforms;
BakedBitSword(ModelBitSword parent,
ImmutableList<BakedQuad> quads,
TextureAtlasSprite particle,
VertexFormat format,
ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transforms,
Map<String, IBakedModel> cache,
boolean untransformed)
{
super(quads, particle, transforms, BakedBitSwordOverrideHandler.INSTANCE, untransformed);
this.transforms = transforms;
this.format = format;
this.parent = parent;
this.cache = cache;
}
}
}