Posted December 4, 20168 yr Hello, I'm working on a mod that dynamically creates armor from registered blocks and I'm running into a bit of a snag (again). Currently I am creating, registering, naming, etc. the armor pieces that I want for different blocks dynamically. I've been trying to have each armor piece's inventory icon change to a different texture (that I have) depending on the block that the armor is for, but I haven't made much progress. Normally, an item's inventory texture is assigned in its models/item json, but I don't have the textures until runtime (I think after texture stitching, to be exact), so I can't assign the textures that way. Stuff I've tried: I've looked into DynamicTextures by studying the vanilla map code, but I'm not sure how to properly use them or if they would work properly for this. I tried experimenting with adding property overrides to each item to see if I could redirect the texture it gets there, but it looks like that only affects the models/item json instead of allowing me to just specify a texture. I've also tried using the TextureStitchEvent.Post to change texture of the armor pieces, but haven't been successful. I haven't found much documentation or many examples of how to use the event properly, so it's possible that I'm doing something wrong. I tried seeing if it's possible to change an item's TextureAtlasSprite from its IBakedModel, but haven't had any luck with that. Of everything I've tried, using the TextureStitchEvent seems the most promising. Does anyone have any idea how I can assign textures to my armor pieces at runtime? Thanks in advance! https://i.gyazo.com/9d22a3d74363977ac76d662e7c22effb.png[/img]
December 4, 20168 yr You'll probably need to generate textures and models at runtime like ModelDynBucket does. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
December 5, 20168 yr Author You'll probably need to generate textures and models at runtime like ModelDynBucket does. After a long day of tracing code and trying to understand it, I finally managed to do it using a class similar to ModelDynBucket. Thank you! For anyone else trying to do something similar, I can give you the highlights of how I did it (probably not the best way, but it works): How I registered items that I wanted to change texture: @SubscribeEvent public void modelBake(ModelBakeEvent event) { for (Item item : items) { //list of items to register ModelLoader.setCustomMeshDefinition(item, new ItemMeshDefinition() { @Override public ModelResourceLocation getModelLocation(ItemStack stack) { return ModelDynBlockArmor.LOCATION; } }); ModelBakery.registerItemVariants(item, ModelDynBlockArmor.LOCATION); } } My dynamic model class: public final class ModelDynBlockArmor implements IModel, IModelCustomData, IRetexturableModel { public static final ModelResourceLocation LOCATION = new ModelResourceLocation(BlockArmor.MODID+":block_armor", "inventory"); // minimal Z offset to prevent depth-fighting private static final float NORTH_Z_BASE = 7.496f / 16f; private static final float SOUTH_Z_BASE = 8.503f / 16f; private static final float NORTH_Z_FLUID = 7.498f / 16f; private static final float SOUTH_Z_FLUID = 8.502f / 16f; public static final IModel MODEL = new ModelDynBlockArmor(); public ModelDynBlockArmor() { } @Override public Collection<ResourceLocation> getDependencies() { return ImmutableList.of(); } @Override public Collection<ResourceLocation> getTextures() { ImmutableSet.Builder<ResourceLocation> builder = ImmutableSet.builder(); return builder.build(); } @Override public IBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) { return new BakedDynBlockArmor(format); } @Override public IModelState getDefaultState() { return TRSRTransformation.identity(); } @Override public ModelDynBlockArmor process(ImmutableMap<String, String> customData) { return new ModelDynBlockArmor(); } @Override public ModelDynBlockArmor retexture(ImmutableMap<String, String> textures) { return new ModelDynBlockArmor(); } public enum LoaderDynBlockArmor implements ICustomModelLoader { INSTANCE; @Override public boolean accepts(ResourceLocation modelLocation) { return (modelLocation.getResourceDomain().equals(BlockArmor.MODID) && (modelLocation.getResourcePath().contains("helmet") || modelLocation.getResourcePath().contains("chestplate") || modelLocation.getResourcePath().contains("leggings") || modelLocation.getResourcePath().contains("boots"))); } @Override public IModel loadModel(ResourceLocation modelLocation) { return MODEL; } @Override public void onResourceManagerReload(IResourceManager resourceManager) { } } private static final class BakedDynBlockArmorOverrideHandler extends ItemOverrideList { public static final BakedDynBlockArmorOverrideHandler INSTANCE = new BakedDynBlockArmorOverrideHandler(); private BakedDynBlockArmorOverrideHandler() { super(ImmutableList.<ItemOverride>of()); } @Override public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, World world, EntityLivingBase entity) { if (originalModel instanceof BakedDynBlockArmor && ArmorSet.getInventoryTextureLocation((ItemBlockArmor) stack.getItem()) != null) { ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder(); IModelState state = new SimpleModelState(((BakedDynBlockArmor)originalModel).transforms); TRSRTransformation transform = TRSRTransformation.identity(); state = new ModelStateComposition(state, transform); VertexFormat format = ((BakedDynBlockArmor)originalModel).format; //Full block texture ResourceLocation textureLocation = ArmorSet.getInventoryTextureLocation((ItemBlockArmor) stack.getItem()); TextureAtlasSprite blockTexture = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(textureLocation.toString()); //builder.add(ItemTextureQuadConverter.genQuad(format, transform, 0, 0, 16, 16, NORTH_Z_BASE, blockTexture, EnumFacing.NORTH, 0xffffffff)); //builder.add(ItemTextureQuadConverter.genQuad(format, transform, 0, 0, 16, 16, SOUTH_Z_BASE, blockTexture, EnumFacing.SOUTH, 0xffffffff)); String armorType = ""; EntityEquipmentSlot slot = ((ItemBlockArmor) stack.getItem()).getEquipmentSlot(); if (slot == EntityEquipmentSlot.HEAD) armorType = "helmet"; else if (slot == EntityEquipmentSlot.CHEST) armorType = "chestplate"; else if (slot == EntityEquipmentSlot.LEGS) armorType = "leggings"; else if (slot == EntityEquipmentSlot.FEET) armorType = "boots"; //Base texture and model ResourceLocation baseLocation = new ResourceLocation("blockarmor:items/block_armor_"+armorType+"_base"); IBakedModel model = (new ItemLayerModel(ImmutableList.of(baseLocation))).bake(state, format, new Function<ResourceLocation, TextureAtlasSprite>() { public TextureAtlasSprite apply(ResourceLocation location) { return Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(location.toString()); } }); builder.addAll(model.getQuads(null, null, 0)); //Template texture for left half String templateLocation = new ResourceLocation("blockarmor:items/block_armor_"+armorType+"1_template").toString(); TextureAtlasSprite templateTexture = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(templateLocation); builder.addAll(ItemTextureQuadConverter.convertTexture(format, transform, templateTexture, blockTexture, NORTH_Z_FLUID, EnumFacing.NORTH, 0xffffffff)); builder.addAll(ItemTextureQuadConverter.convertTexture(format, transform, templateTexture, blockTexture, SOUTH_Z_FLUID, EnumFacing.SOUTH, 0xffffffff)); //Template texture for right half templateLocation = new ResourceLocation("blockarmor:items/block_armor_"+armorType+"2_template").toString(); templateTexture = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(templateLocation); builder.addAll(ItemTextureQuadConverter.convertTexture(format, transform, templateTexture, blockTexture, NORTH_Z_FLUID, EnumFacing.NORTH, 0xffffffff)); builder.addAll(ItemTextureQuadConverter.convertTexture(format, transform, templateTexture, blockTexture, SOUTH_Z_FLUID, EnumFacing.SOUTH, 0xffffffff)); //Cover texture String coverLocation = new ResourceLocation("blockarmor:items/block_armor_"+armorType+"_cover").toString(); TextureAtlasSprite coverTexture = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(coverLocation); builder.add(ItemTextureQuadConverter.genQuad(format, transform, 0, 0, 16, 16, NORTH_Z_BASE, coverTexture, EnumFacing.NORTH, 0xffffffff)); builder.add(ItemTextureQuadConverter.genQuad(format, transform, 0, 0, 16, 16, SOUTH_Z_BASE, coverTexture, EnumFacing.SOUTH, 0xffffffff)); ((BakedDynBlockArmor)originalModel).quads = builder.build(); } return originalModel; } } private static final class BakedDynBlockArmor implements IPerspectiveAwareModel { private final ImmutableMap<TransformType, TRSRTransformation> transforms; private ImmutableList<BakedQuad> quads; private final VertexFormat format; public BakedDynBlockArmor(VertexFormat format) { this.format = format; ImmutableMap.Builder<TransformType, TRSRTransformation> builder = ImmutableMap.builder(); builder.put(TransformType.GROUND, new TRSRTransformation(new Vector3f(0.25f, 0.375f, 0.25f), new Quat4f(0.0f, 0.0f, 0.0f, 1.0f), new Vector3f(0.5f, 0.5f, 0.5f), new Quat4f(0.0f, 0.0f, 0.0f, 1.0f))); builder.put(TransformType.HEAD, new TRSRTransformation(new Vector3f(1.0f, 0.8125f, 1.4375f), new Quat4f(0.0f, 1.0f, 0.0f, -4.371139E-8f), new Vector3f(1.0f, 1.0f, 1.0f), new Quat4f(0.0f, 0.0f, 0.0f, 1.0f))); builder.put(TransformType.FIRST_PERSON_RIGHT_HAND, new TRSRTransformation(new Vector3f(0.910625f, 0.24816513f, 0.40617055f), new Quat4f(-0.15304594f, -0.6903456f, 0.15304594f, 0.6903456f), new Vector3f(0.68000007f, 0.68000007f, 0.68f), new Quat4f(0.0f, 0.0f, 0.0f, 1.0f))); builder.put(TransformType.FIRST_PERSON_LEFT_HAND, new TRSRTransformation(new Vector3f(0.910625f, 0.24816513f, 0.40617055f), new Quat4f(-0.15304594f, -0.6903456f, 0.15304594f, 0.6903456f), new Vector3f(0.68000007f, 0.68000007f, 0.68f), new Quat4f(0.0f, 0.0f, 0.0f, 1.0f))); builder.put(TransformType.THIRD_PERSON_RIGHT_HAND, new TRSRTransformation(new Vector3f(0.225f, 0.4125f, 0.2875f), new Quat4f(0.0f, 0.0f, 0.0f, 0.99999994f), new Vector3f(0.55f, 0.55f, 0.55f), new Quat4f(0.0f, 0.0f, 0.0f, 1.0f))); builder.put(TransformType.THIRD_PERSON_LEFT_HAND, new TRSRTransformation(new Vector3f(0.225f, 0.4125f, 0.2875f), new Quat4f(0.0f, 0.0f, 0.0f, 0.99999994f), new Vector3f(0.55f, 0.55f, 0.55f), new Quat4f(0.0f, 0.0f, 0.0f, 1.0f))); ImmutableMap<TransformType, TRSRTransformation> transformMap = builder.build(); this.transforms = Maps.immutableEnumMap(transformMap); } @Override public ItemOverrideList getOverrides() { return BakedDynBlockArmorOverrideHandler.INSTANCE; } @Override public Pair<? extends IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType) { return IPerspectiveAwareModel.MapWrapper.handlePerspective(this, transforms, cameraTransformType); } @Override public List<BakedQuad> getQuads(IBlockState state, EnumFacing side, long rand) { if(side == null) return quads; return ImmutableList.of(); } public boolean isAmbientOcclusion() { return true; } public boolean isGui3d() { return false; } public boolean isBuiltInRenderer() { return false; } public TextureAtlasSprite getParticleTexture() { return null; } public ItemCameraTransforms getItemCameraTransforms() { return ItemCameraTransforms.DEFAULT; } } } Some of the code is specific to the mod I'm working on, but hopefully it still helps other people. If you want to see it in context, the mod (currently WIP) is on github: https://github.com/2piradians/Block-Armor https://i.gyazo.com/9d22a3d74363977ac76d662e7c22effb.png[/img]
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.