So I managed to get the models to load (they render as dirt when returning the sane thing as dirt in all methods), but when I try to make the BakedQuads I get an IndexOutOfBoundsException
Model class:
/** Runes of Wizardry Mod for Minecraft
* Licensed under the GNU GPL version 3
*
* this file was created by Xilef11 on 2015-09-06
*/
package com.zpig333.runesofwizardry.client.model;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javafx.scene.shape.VertexFormat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.FaceBakery;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import org.apache.commons.lang3.ArrayUtils;
import com.zpig333.runesofwizardry.api.IDustStorageBlock;
import com.zpig333.runesofwizardry.client.TextureStitchEventHandler;
import com.zpig333.runesofwizardry.core.References;
import com.zpig333.runesofwizardry.core.WizardryLogger;
/**
* @author Xilef11
*
*/
public class ModelDustStorage implements IBakedModel {
private static Map<String,ModelResourceLocation> resourceMap = new HashMap<String, ModelResourceLocation>();
private IDustStorageBlock block;
private int meta;
private int bgColor,fgColor;
// create a tag (ModelResourceLocation) for our model.
public final ModelResourceLocation modelResourceLocation;
public ModelDustStorage(IDustStorageBlock block, int meta) {
WizardryLogger.logInfo("Creating model for block: "+block.getName()+" "+meta);
this.block=block;
this.meta=meta;
this.modelResourceLocation = new ModelResourceLocation(getModelResourceLocationPath(block,meta));
this.bgColor = block.getIDust().getPrimaryColor(new ItemStack(block.getIDust(),1,meta));
this.fgColor = block.getIDust().getSecondaryColor(new ItemStack(block.getIDust(),1,meta));
}
public static String getModelResourceLocationPath(IDustStorageBlock block, int meta){
return References.texture_path+block.getName()+"_"+meta;
}
public static ModelResourceLocation getModelResourceLocation(String path){
ModelResourceLocation current = resourceMap.get(path);
if(current==null){
current=new ModelResourceLocation(path);
resourceMap.put(path, current);
}
return current;
}
public static ModelResourceLocation getModelResourceLocation(IDustStorageBlock block, int meta){
return getModelResourceLocation(getModelResourceLocationPath(block, meta));
}
/* (non-Javadoc)
* @see net.minecraft.client.resources.model.IBakedModel#getFaceQuads(net.minecraft.util.EnumFacing)
*/
@Override
public List getFaceQuads(EnumFacing face) {
List r = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelForState(Blocks.dirt.getDefaultState()).getFaceQuads(face);
List<BakedQuad> result = new LinkedList<BakedQuad>();
int[] bg =null;
int[] fg = null;
TextureAtlasSprite bgTex = TextureStitchEventHandler.getDustStorageBG();
TextureAtlasSprite fgTex = TextureStitchEventHandler.getDustStorageFG();
//looks like a bakedquad is a full square, and we have to pass it all its vertices in the int array...
//also, tintindex should be -1
//FIXME no more crash, but rendering is broken again
//Feels like the ints are not in the right order...
if(face==EnumFacing.EAST){
//BG color
bg = ArrayUtils.addAll(bg, vertexToInts(1, 0, 0, bgColor, bgTex, 16, 16));
bg = ArrayUtils.addAll(bg, vertexToInts(1, 1, 0, bgColor, bgTex, 16, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(1, 1, 1, bgColor, bgTex, 0, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(1, 0, 1, bgColor, bgTex, 0, 16));
//fg
fg = ArrayUtils.addAll(fg, vertexToInts(1.001F, 0, 0, fgColor, fgTex, 16, 16));
fg = ArrayUtils.addAll(fg, vertexToInts(1.001F, 1, 0, fgColor, fgTex, 16, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(1.001F, 1, 1, fgColor, fgTex, 0, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(1.001F, 0, 1, fgColor, fgTex, 0, 16));
}else if(face==EnumFacing.WEST){
//BG color
bg = ArrayUtils.addAll(bg, vertexToInts(0, 0, 1, bgColor, bgTex, 16, 16));
bg = ArrayUtils.addAll(bg, vertexToInts(0, 1, 1, bgColor, bgTex, 16, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(0, 1, 0, bgColor, bgTex, 0, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(0, 0, 0, bgColor, bgTex, 0, 16));
//fg
fg = ArrayUtils.addAll(fg, vertexToInts(-0.001F, 0, 1, fgColor, fgTex, 16, 16));
fg = ArrayUtils.addAll(fg, vertexToInts(-0.001F, 1, 1, fgColor, fgTex, 16, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(-0.001F, 1, 0, fgColor, fgTex, 0, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(-0.001F, 0, 0, fgColor, fgTex, 0, 16));
}else if(face==EnumFacing.NORTH){
//BG color
bg = ArrayUtils.addAll(bg, vertexToInts(0, 0, 0, bgColor, bgTex, 16, 16));
bg = ArrayUtils.addAll(bg, vertexToInts(0, 1, 0, bgColor, bgTex, 16, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(1, 1, 0, bgColor, bgTex, 0, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(1, 0, 0, bgColor, bgTex, 0, 16));
//fg
fg = ArrayUtils.addAll(fg, vertexToInts(0, 0, -0.001F, fgColor, fgTex, 16, 16));
fg = ArrayUtils.addAll(fg, vertexToInts(0, 1, -0.001F, fgColor, fgTex, 16, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(1, 1, -0.001F, fgColor, fgTex, 0, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(1, 0, -0.001F, fgColor, fgTex, 0, 16));
}else if(face==EnumFacing.SOUTH){
//BG color
bg = ArrayUtils.addAll(bg, vertexToInts(1, 0, 1, bgColor, bgTex, 16, 16));
bg = ArrayUtils.addAll(bg, vertexToInts(1, 1, 1, bgColor, bgTex, 16, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(0, 1, 1, bgColor, bgTex, 0, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(0, 0, 1, bgColor, bgTex, 0, 16));
//fg
fg = ArrayUtils.addAll(fg, vertexToInts(1, 0, 1.001F, fgColor, fgTex, 16, 16));
fg = ArrayUtils.addAll(fg, vertexToInts(1, 1, 1.001F, fgColor, fgTex, 16, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(0, 1, 1.001F, fgColor, fgTex, 0, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(0, 0, 1.001F, fgColor, fgTex, 0, 16));
}else if(face==EnumFacing.DOWN){
//BG color
bg = ArrayUtils.addAll(bg, vertexToInts(1, 0, 0, bgColor, bgTex, 16, 16));
bg = ArrayUtils.addAll(bg, vertexToInts(1, 0, 1, bgColor, bgTex, 16, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(0, 0, 1, bgColor, bgTex, 0, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(0, 0, 0, bgColor, bgTex, 0, 16));
//fg
fg = ArrayUtils.addAll(fg, vertexToInts(1,-0.001F,0, fgColor, fgTex, 16, 16));
fg = ArrayUtils.addAll(fg, vertexToInts(1,-0.001F,1, fgColor, fgTex, 16, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(0, -0.001F,1, fgColor, fgTex, 0, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(0, -0.001F,0, fgColor, fgTex, 0, 16));
}else if(face==EnumFacing.UP){
//BG color
bg = ArrayUtils.addAll(bg, vertexToInts(1, 1, 1, bgColor, bgTex, 16, 16));
bg = ArrayUtils.addAll(bg, vertexToInts(1, 1, 0, bgColor, bgTex, 16, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(0, 1, 0, bgColor, bgTex, 0, 0));
bg = ArrayUtils.addAll(bg, vertexToInts(0, 1, 1, bgColor, bgTex, 0, 16));
//fg
fg = ArrayUtils.addAll(fg, vertexToInts(1,1.001F,1, fgColor, fgTex, 16, 16));
fg = ArrayUtils.addAll(fg, vertexToInts(1,1.001F,0, fgColor, fgTex, 16, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(0, 1.001F,0, fgColor, fgTex, 0, 0));
fg = ArrayUtils.addAll(fg, vertexToInts(0, 1.001F,1, fgColor, fgTex, 0, 16));
}else{
throw new IllegalArgumentException("Wrong EnumFacing: "+face);//is that even possible...
}
//int[] test = ArrayUtils.addAll(new int[]{1,2,3,4},new int[]{5,6,7,8});
result.add(new BakedQuad(bg, -1, face));
result.add(new BakedQuad(fg, -1, face));
return result;
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see net.minecraft.client.resources.model.IBakedModel#getGeneralQuads()
*/
@Override
public List getGeneralQuads() {
List<BakedQuad> res = new LinkedList<BakedQuad>();
for(EnumFacing face : EnumFacing.VALUES){
res.addAll(getFaceQuads(face));
}
//return res;
// TODO Auto-generated method stub
List r = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelForState(Blocks.dirt.getDefaultState()).getGeneralQuads();
return r;
}
/* (non-Javadoc)
* @see net.minecraft.client.resources.model.IBakedModel#isAmbientOcclusion()
*/
@Override
public boolean isAmbientOcclusion() {
//return true;
return false;
}
/* (non-Javadoc)
* @see net.minecraft.client.resources.model.IBakedModel#isGui3d()
*/
@Override
public boolean isGui3d() {
return true;
}
/* (non-Javadoc)
* @see net.minecraft.client.resources.model.IBakedModel#isBuiltInRenderer()
*/
@Override
public boolean isBuiltInRenderer() {
return false;
}
/* (non-Javadoc)
* @see net.minecraft.client.resources.model.IBakedModel#getTexture()
*/
@Override
public TextureAtlasSprite getTexture() {
//TODO getTexture might need to get tweaked
return TextureStitchEventHandler.getDustStorageBG();
}
/* (non-Javadoc)
* @see net.minecraft.client.resources.model.IBakedModel#getItemCameraTransforms()
*/
@Override
public ItemCameraTransforms getItemCameraTransforms() {
return ItemCameraTransforms.DEFAULT;
}
/**
* Converts the vertex information to the int array format expected by BakedQuads.
* @param x x coordinate
* @param y y coordinate
* @param z z coordinate
* @param color RGBA colour format - white for no effect, non-white to tint the face with the specified colour
* @param texture the texture to use for the face
* @param u u-coordinate of the texture (0 - 16) corresponding to [x,y,z]
* @param v v-coordinate of the texture (0 - 16) corresponding to [x,y,z]
* @return
*/
private static int[] vertexToInts(float x, float y, float z, int color, TextureAtlasSprite texture, float u, float v)
{
return new int[] {
Float.floatToRawIntBits(x),
Float.floatToRawIntBits(y),
Float.floatToRawIntBits(z),
color,
Float.floatToRawIntBits(texture.getInterpolatedU(u)),
Float.floatToRawIntBits(texture.getInterpolatedV(v)),
0
};
}
}
ModelBake Event Handler
/** Runes of Wizardry Mod for Minecraft
* Licensed under the GNU GPL version 3
*
* this file was created by Xilef11 on 2015-09-06
*/
package com.zpig333.runesofwizardry.client;
import com.zpig333.runesofwizardry.api.DustRegistry;
import com.zpig333.runesofwizardry.api.IDustStorageBlock;
import com.zpig333.runesofwizardry.client.model.ModelDustStorage;
import com.zpig333.runesofwizardry.core.WizardryLogger;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
/**
* @author Xilef11
*
*/
public class ModelBakeEventHandler {
public static final ModelBakeEventHandler instance=new ModelBakeEventHandler();
private ModelBakeEventHandler() {};
@SubscribeEvent
public void onModelBake(ModelBakeEvent event){
WizardryLogger.logInfo("Registering models on ModelBakeEvent");
// Find the existing mapping for the block - it will have been added automatically because
// we registered a custom BlockStateMapper for it (using ModelLoader.setCustomStateMapper)
// Replace the mapping with our ISmartBlockModel.
for(IDustStorageBlock block: DustRegistry.getAllBlocks()){
WizardryLogger.logInfo("ModelBake: processing "+block.getName());//XXX this happens
for(int meta : block.getIDust().getMetaValues()){
WizardryLogger.logInfo("meta is "+meta);//XXX this happens
ModelResourceLocation location = ModelDustStorage.getModelResourceLocation(block, meta);
Object object = event.modelRegistry.getObject(location);
WizardryLogger.logInfo("object is "+object);
if (object instanceof IBakedModel) {//FIXME object is null
IBakedModel existingModel = (IBakedModel)object;
ModelDustStorage customModel = new ModelDustStorage(block, meta);
event.modelRegistry.putObject(location, customModel);
}else if(object==null){
ModelDustStorage model = new ModelDustStorage(block, meta);
event.modelRegistry.putObject(location, model);
}
}
}
}
}
Methods (in client proxy) that load the stuff...
/* (non-Javadoc)
* @see com.zpig333.runesofwizardry.proxy.CommonProxy#registerDustStorageRendering()
*/
@Override
public void registerDustStorageRendering() {
WizardryLogger.logInfo("Registering Dust Storage rendering");
// We need to tell Forge how to map our BlockCamouflage's IBlockState to a ModelResourceLocation.
// For example, the BlockStone granite variant has a BlockStateMap entry that looks like
// "stone[variant=granite]" (iBlockState) -> "minecraft:granite#normal" (ModelResourceLocation)
// For the camouflage block, we ignore the iBlockState completely and always return the same ModelResourceLocation,
// which is done using the anonymous class below
for(final IDustStorageBlock block : DustRegistry.getAllBlocks()){
WizardryLogger.logInfo("Creating StateMapper for "+block.getName());//XXX This happens
StateMapperBase mapper = new StateMapperBase() {
@Override
protected ModelResourceLocation getModelResourceLocation(IBlockState iBlockState) {
int meta = (Integer) iBlockState.getValue(IDustStorageBlock.PROPERTYMETA);
return ModelDustStorage.getModelResourceLocation(block, meta);
}
};
ModelLoader.setCustomStateMapper(block, mapper);
}
// ModelBakeEvent will be used to add our ISmartBlockModel to the ModelManager's registry (the
// registry used to map all the ModelResourceLocations to IBlockModels). For the stone example there is a map from
// ModelResourceLocation("minecraft:granite#normal") to an IBakedModel created from models/block/granite.json.
// For the camouflage block, it will map from
// CamouflageISmartBlockModelFactory.modelResourceLocation to our CamouflageISmartBlockModelFactory instance
MinecraftForge.EVENT_BUS.register(ModelBakeEventHandler.instance);
//register the handler to create the textures
MinecraftForge.EVENT_BUS.register(new TextureStitchEventHandler());
}
public void registerDustStorageItemRendering() {
WizardryLogger.logInfo("Registering dust storage item rendering");
// This is currently necessary in order to make your block render properly when it is an item (i.e. in the inventory
// or in your hand or thrown on the ground).
// Minecraft knows to look for the item model based on the GameRegistry.registerBlock. However the registration of
// the model for each item is normally done by RenderItem.registerItems(), and this is not currently aware
// of any extra items you have created. Hence you have to do it manually. This will probably change in future.
// It must be done in the init phase, not preinit, and must be done on client only.
for(IDustStorageBlock b:DustRegistry.getAllBlocks()){
WizardryLogger.logInfo("Processing item: "+b.getName());
Item itemBlockDustStorage = GameRegistry.findItem(References.modid, b.getName());
for(int meta: b.getIDust().getMetaValues()){
WizardryLogger.logInfo("meta: "+meta);
//ModelResourceLocation itemModelResourceLocation = new ModelResourceLocation(ModelDustStorage.getModelResourceLocationPath(b, meta), "inventory");
ModelResourceLocation itemModelResourceLocation = ModelDustStorage.getModelResourceLocation(b, meta); Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(itemBlockDustStorage, meta, itemModelResourceLocation);
}
}
}
TextureStitch Event Handler
package com.zpig333.runesofwizardry.client;
import com.zpig333.runesofwizardry.core.References;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
public class TextureStitchEventHandler {
private static TextureAtlasSprite dust_storage_bg, dust_storage_fg;
public static TextureAtlasSprite getDustStorageBG(){
return dust_storage_bg;
}
public static TextureAtlasSprite getDustStorageFG(){
return dust_storage_fg;
}
@SubscribeEvent
public void onTextureStitch(TextureStitchEvent.pre event){
dust_storage_bg = event.map.registerSprite(new ResourceLocation(References.texture_path+"blocks/dustStorage_bg"));
dust_storage_fg = event.map.registerSprite(new ResourceLocation(References.texture_path+"blocks/dustStorage_fg"));
}
}
EDIT: Turns out I derped and didn't notice the int[] was supposed to contian the data for all four vertices of the quad... I no longer crash, but the blocks get rendered in dark colors with no texture
EDIT2: textures were fixed, I had to register for TextureStitchEvent.pre . However, the two layers don't blend (alpha in the foreground renders as black) and the colors are off.