Fixes #2470: Implement rendering of the crafting output for encoded patterns when shift is being held.
This commit is contained in:
parent
c427fa04a7
commit
dacce3e7bd
|
@ -0,0 +1,233 @@
|
|||
package appeng.client.render.crafting;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.vecmath.Matrix4f;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrideList;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
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 appeng.items.misc.ItemEncodedPattern;
|
||||
|
||||
|
||||
/**
|
||||
* This special model handles switching between rendering the crafting output of an encoded pattern (when shift is being held), and
|
||||
* showing the encoded pattern itself. Matters are further complicated by only wanting to show the crafting output when the pattern is being
|
||||
* rendered in the GUI, and not anywhere else.
|
||||
*/
|
||||
class ItemEncodedPatternBakedModel implements IPerspectiveAwareModel
|
||||
{
|
||||
private final IBakedModel baseModel;
|
||||
|
||||
private final ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transforms;
|
||||
|
||||
private final CustomOverrideList overrides;
|
||||
|
||||
ItemEncodedPatternBakedModel( IBakedModel baseModel, ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transforms )
|
||||
{
|
||||
this.baseModel = baseModel;
|
||||
this.transforms = transforms;
|
||||
this.overrides = new CustomOverrideList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads( @Nullable IBlockState state, @Nullable EnumFacing side, long rand )
|
||||
{
|
||||
return baseModel.getQuads( state, side, rand );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion()
|
||||
{
|
||||
return baseModel.isAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
return baseModel.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
return baseModel.isBuiltInRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
return baseModel.getParticleTexture();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public ItemCameraTransforms getItemCameraTransforms()
|
||||
{
|
||||
return baseModel.getItemCameraTransforms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides()
|
||||
{
|
||||
return overrides;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<? extends IBakedModel, Matrix4f> handlePerspective( ItemCameraTransforms.TransformType cameraTransformType )
|
||||
{
|
||||
if( baseModel instanceof IPerspectiveAwareModel )
|
||||
{
|
||||
return ( (IPerspectiveAwareModel) baseModel ).handlePerspective( cameraTransformType );
|
||||
}
|
||||
|
||||
return IPerspectiveAwareModel.MapWrapper.handlePerspective( this, transforms, cameraTransformType );
|
||||
}
|
||||
|
||||
/**
|
||||
* Since the ItemOverrideList handling comes before handling the perspective awareness (which is the first place where we
|
||||
* know how we are being rendered) we need to remember the model of the crafting output, and make the decision on which to render later on.
|
||||
* Sadly, Forge is pretty inconsistent when it will call the handlePerspective method, so some methods are called even on this interim-model.
|
||||
* Usually those methods only matter for rendering on the ground and other cases, where we wouldn't render the crafting output model anyway,
|
||||
* so in those cases we delegate to the model of the encoded pattern.
|
||||
*/
|
||||
private class ShiftHoldingModelWrapper implements IPerspectiveAwareModel
|
||||
{
|
||||
|
||||
private final IBakedModel outputModel;
|
||||
|
||||
private ShiftHoldingModelWrapper( IBakedModel outputModel )
|
||||
{
|
||||
this.outputModel = outputModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<? extends IBakedModel, Matrix4f> handlePerspective( ItemCameraTransforms.TransformType cameraTransformType )
|
||||
{
|
||||
final IBakedModel selectedModel;
|
||||
|
||||
// No need to re-check for shift being held since this model is only handed out in that case
|
||||
if( cameraTransformType == ItemCameraTransforms.TransformType.GUI )
|
||||
{
|
||||
selectedModel = outputModel;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedModel = baseModel;
|
||||
}
|
||||
|
||||
// Now retroactively handle the isGui3d call, for which we always return false below
|
||||
if( selectedModel.isGui3d() != baseModel.isGui3d() )
|
||||
{
|
||||
GlStateManager.enableLighting();
|
||||
}
|
||||
|
||||
if( selectedModel instanceof IPerspectiveAwareModel )
|
||||
{
|
||||
return ( (IPerspectiveAwareModel) selectedModel ).handlePerspective( cameraTransformType );
|
||||
}
|
||||
|
||||
return IPerspectiveAwareModel.MapWrapper.handlePerspective( this, transforms, cameraTransformType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads( @Nullable IBlockState state, @Nullable EnumFacing side, long rand )
|
||||
{
|
||||
// This may be called for items on the ground, in which case we will always fall back to the pattern
|
||||
return baseModel.getQuads( state, side, rand );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion()
|
||||
{
|
||||
return baseModel.isAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
// NOTE: Sadly, Forge will let Minecraft call this method before handling the perspective awareness
|
||||
return baseModel.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
// This may be called for items on the ground, in which case we will always fall back to the pattern
|
||||
return baseModel.isBuiltInRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
// This may be called for items on the ground, in which case we will always fall back to the pattern
|
||||
return baseModel.getParticleTexture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms()
|
||||
{
|
||||
// This may be called for items on the ground, in which case we will always fall back to the pattern
|
||||
return baseModel.getItemCameraTransforms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides()
|
||||
{
|
||||
// This may be called for items on the ground, in which case we will always fall back to the pattern
|
||||
return baseModel.getOverrides();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Item Override Lists are the only point during item rendering where we can access the item stack that is being rendered.
|
||||
* So this is the point where we actually check if shift is being held, and if so, determine the crafting output model.
|
||||
*/
|
||||
private class CustomOverrideList extends ItemOverrideList
|
||||
{
|
||||
|
||||
CustomOverrideList()
|
||||
{
|
||||
super( baseModel.getOverrides().getOverrides() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBakedModel handleItemState( IBakedModel originalModel, ItemStack stack, World world, EntityLivingBase entity )
|
||||
{
|
||||
boolean shiftHeld = Keyboard.isKeyDown( Keyboard.KEY_LSHIFT ) || Keyboard.isKeyDown( Keyboard.KEY_RSHIFT );
|
||||
if( shiftHeld )
|
||||
{
|
||||
ItemEncodedPattern iep = (ItemEncodedPattern) stack.getItem();
|
||||
ItemStack output = iep.getOutput( stack );
|
||||
if( output != null )
|
||||
{
|
||||
IBakedModel realModel = Minecraft.getMinecraft().getRenderItem().getItemModelMesher().getItemModel( output );
|
||||
// Give the item model a chance to handle the overrides as well
|
||||
realModel = realModel.getOverrides().handleItemState( realModel, output, world, entity );
|
||||
return new ShiftHoldingModelWrapper( realModel );
|
||||
}
|
||||
}
|
||||
|
||||
return baseModel.getOverrides().handleItemState( originalModel, stack, world, entity );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package appeng.client.render.crafting;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.IModel;
|
||||
import net.minecraftforge.client.model.IPerspectiveAwareModel;
|
||||
import net.minecraftforge.client.model.ModelLoaderRegistry;
|
||||
import net.minecraftforge.common.model.IModelState;
|
||||
import net.minecraftforge.common.model.TRSRTransformation;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
|
||||
|
||||
/**
|
||||
* Simple model for the encoded pattern built-in baked model.
|
||||
*/
|
||||
class ItemEncodedPatternModel implements IModel
|
||||
{
|
||||
|
||||
private static final ResourceLocation BASE_MODEL = new ResourceLocation( AppEng.MOD_ID, "item/encoded_pattern" );
|
||||
|
||||
@Override
|
||||
public Collection<ResourceLocation> getDependencies()
|
||||
{
|
||||
return Collections.singletonList( BASE_MODEL );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ResourceLocation> getTextures()
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBakedModel bake( IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
|
||||
{
|
||||
IBakedModel baseModel;
|
||||
try
|
||||
{
|
||||
baseModel = ModelLoaderRegistry.getModel( BASE_MODEL ).bake( state, format, bakedTextureGetter );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
|
||||
ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transforms = IPerspectiveAwareModel.MapWrapper.getTransforms(state);
|
||||
|
||||
return new ItemEncodedPatternBakedModel( baseModel, transforms );
|
||||
}
|
||||
|
||||
@Override
|
||||
public IModelState getDefaultState()
|
||||
{
|
||||
return TRSRTransformation.identity();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package appeng.client.render.crafting;
|
||||
|
||||
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
|
||||
import appeng.bootstrap.IItemRendering;
|
||||
import appeng.bootstrap.ItemRenderingCustomizer;
|
||||
import appeng.core.AppEng;
|
||||
|
||||
|
||||
public class ItemEncodedPatternRendering extends ItemRenderingCustomizer
|
||||
{
|
||||
|
||||
private static final ResourceLocation MODEL = new ResourceLocation( AppEng.MOD_ID, "builtin/encoded_pattern" );
|
||||
|
||||
@Override
|
||||
@SideOnly( Side.CLIENT )
|
||||
public void customize( IItemRendering rendering )
|
||||
{
|
||||
rendering.builtInModel( "models/item/builtin/encoded_pattern", new ItemEncodedPatternModel() );
|
||||
rendering.model( new ModelResourceLocation( MODEL, "inventory" ) ).variants( MODEL );
|
||||
}
|
||||
|
||||
}
|
|
@ -23,6 +23,7 @@ import appeng.api.definitions.IItemDefinition;
|
|||
import appeng.api.definitions.IItems;
|
||||
import appeng.api.util.AEColoredItemDefinition;
|
||||
import appeng.bootstrap.FeatureFactory;
|
||||
import appeng.client.render.crafting.ItemEncodedPatternRendering;
|
||||
import appeng.core.CreativeTabFacade;
|
||||
import appeng.core.features.AEFeature;
|
||||
import appeng.debug.ToolDebugCard;
|
||||
|
@ -190,7 +191,10 @@ public final class ApiItems implements IItems
|
|||
.build();
|
||||
|
||||
// rv1
|
||||
this.encodedPattern = registry.item( "encoded_pattern", ItemEncodedPattern::new ).features( AEFeature.Patterns ).build();
|
||||
this.encodedPattern = registry.item( "encoded_pattern", ItemEncodedPattern::new )
|
||||
.features( AEFeature.Patterns )
|
||||
.rendering( new ItemEncodedPatternRendering() )
|
||||
.build();
|
||||
|
||||
this.paintBall = registry.item( "paint_ball", ItemPaintBall::new )
|
||||
.features( AEFeature.PaintBalls )
|
||||
|
|
Loading…
Reference in New Issue