package com.bioxx.tfc2.rendering.bakedmodels; import java.util.Collections; import java.util.List; import java.util.Map; import javax.vecmath.Matrix4f; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.*; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.world.World; import net.minecraftforge.client.model.IPerspectiveAwareModel; import net.minecraftforge.common.model.TRSRTransformation; import net.minecraftforge.common.property.IExtendedBlockState; import com.bioxx.tfc2.api.properties.PropertyItem; import com.bioxx.tfc2.blocks.BlockAnvil; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import org.apache.commons.lang3.tuple.Pair; /** * This class was *mostly* borrowed from TiCon, thanks! */ public class BakedAnvilModel implements IPerspectiveAwareModel { private final IPerspectiveAwareModel standard; private final Map<String, IBakedModel> cache = Maps.newHashMap(); private final VertexFormat format; private final ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transforms; public BakedAnvilModel(IPerspectiveAwareModel standard,VertexFormat format) { this.standard = standard; this.format = format; this.transforms = getTransforms(standard); } public static ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> getTransforms(IPerspectiveAwareModel model) { ImmutableMap.Builder<ItemCameraTransforms.TransformType, TRSRTransformation> builder = ImmutableMap.builder(); for(ItemCameraTransforms.TransformType type : ItemCameraTransforms.TransformType.values()) { TRSRTransformation transformation = new TRSRTransformation(model.handlePerspective(type).getRight()); if(!transformation.equals(TRSRTransformation.identity())) { builder.put(type, TRSRTransformation.blockCenterToCorner(transformation)); } } return builder.build(); } protected IBakedModel getActualModel(IBlockState state, List<PropertyItem.PItem> items, EnumFacing facing) { IBakedModel bakedModel = standard; // add all the items to display on the table if(items != null && !items.isEmpty()) { BakedCompositeModel.Builder builder = new BakedCompositeModel.Builder(); builder.add(bakedModel, null, 0); EnumFacing anvilFacing = state.getValue(BlockAnvil.FACING); for(PropertyItem.PItem item : items) { float rot = 0; /*if(state.getValue(BlockAnvil.FACING) == EnumFacing.NORTH || state.getValue(BlockAnvil.FACING) == EnumFacing.SOUTH) builder.add(new TRSRBakedModel(item.model, item.x, item.y +0.15f, item.z, item.r, (float) (Math.PI), 0.7853981633974483f, item.s), null, 0); else builder.add(new TRSRBakedModel(item.model, item.x, item.y + 0.15f, item.z, item.r, (float) (Math.PI), -0.7853981633974483f, item.s), null, 0);*/ if(anvilFacing == EnumFacing.NORTH) rot = (float)Math.toRadians(0); else if(anvilFacing == EnumFacing.SOUTH) rot = (float)Math.toRadians(180); else if(anvilFacing == EnumFacing.EAST) rot = (float)Math.toRadians(270); else if(anvilFacing == EnumFacing.WEST) rot = (float)Math.toRadians(90); builder.add(new TRSRBakedModel(item.model, item.x, item.y + 0.15f, item.z, item.r, (float) (Math.PI), rot, item.s), null, 0); } bakedModel = builder.build(bakedModel); } if(facing != null) { bakedModel = new TRSRBakedModel(bakedModel, facing); } return bakedModel; } @Override public List<BakedQuad> getQuads(IBlockState state, EnumFacing side, long rand) { List<PropertyItem.PItem> items = Collections.emptyList(); EnumFacing face = EnumFacing.SOUTH; if(state instanceof IExtendedBlockState) { IExtendedBlockState extendedState = (IExtendedBlockState) state; if(/*Config.renderTableItems &&*/ extendedState.getUnlistedNames().contains(BlockAnvil.INVENTORY)) { if(extendedState.getValue(BlockAnvil.INVENTORY) != null) { items = extendedState.getValue(BlockAnvil.INVENTORY).items; } } // remove all world specific data // This is so that the next call to getQuads from the transformed TRSRModel doesn't do this again // otherwise table models inside table model items recursively calls this with the state of the original table state = extendedState.withProperty(BlockAnvil.INVENTORY, PropertyItem.PropItems.EMPTY); } // models are symmetric, no need to rotate if there's nothing on it where rotation matters, so we just use default if(items == null) { return standard.getQuads(state, side, rand); } // the model returned by getActualModel should be a simple model with no special handling return getActualModel(state, items, face).getQuads(state, side, rand); } @Override public boolean isAmbientOcclusion() { return standard.isAmbientOcclusion(); } @Override public boolean isGui3d() { return standard.isGui3d(); } @Override public boolean isBuiltInRenderer() { return standard.isBuiltInRenderer(); } @Override public TextureAtlasSprite getParticleTexture() { return standard.getParticleTexture(); } @Override public ItemCameraTransforms getItemCameraTransforms() { return standard.getItemCameraTransforms(); } @Override public ItemOverrideList getOverrides() { return TableItemOverrideList.INSTANCE; } @Override public Pair<? extends IBakedModel, Matrix4f> handlePerspective(ItemCameraTransforms.TransformType cameraTransformType) { Pair<? extends IBakedModel, Matrix4f> pair = standard.handlePerspective(cameraTransformType); return Pair.of(this, pair.getRight()); } private static class TableItemOverrideList extends ItemOverrideList { static TableItemOverrideList INSTANCE = new TableItemOverrideList(); private TableItemOverrideList() { super(ImmutableList.<ItemOverride>of()); } @Override public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, World world, EntityLivingBase entity) { if(originalModel instanceof BakedAnvilModel) { return ((BakedAnvilModel) originalModel).getActualModel(null, Collections.<PropertyItem.PItem>emptyList(), null); } return originalModel; } } public static TextureAtlasSprite getTextureFromBlock(Block block, int meta) { IBlockState state = block.getStateFromMeta(meta); return Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getTexture(state); } }