This guide will cover rendering an item with a 2d in the GUI and creating a custom renderer.
Override renderInGui
in Your Item Renderer
Copy @ Override
protected void renderInGui( ModelTransformationMode transformType , MatrixStack matrixStack , VertexConsumerProvider bufferSource , int packedLight , int packedOverlay) {
// No custom rendering code here
}
Copy public class TwoDItemRenderer implements BuiltinItemRendererRegistry . DynamicItemRenderer , IdentifiableResourceReloadListener {
private final Identifier id;
private final Identifier itemId;
private ItemRenderer itemRenderer;
private BakedModel inventoryModel;
public TwoDItemRenderer ( Identifier itemId) {
this . id = new Identifier( itemId . getNamespace() , itemId . getPath() + "_renderer" ) ;
this . itemId = itemId;
}
@ Override
public CompletableFuture < Void > reload ( Synchronizer synchronizer , ResourceManager manager , Profiler prepareProfiler , Profiler applyProfiler , Executor prepareExecutor , Executor applyExecutor) {
return synchronizer . whenPrepared ( Unit . INSTANCE ) . thenRunAsync (() -> {
applyProfiler . startTick ();
applyProfiler . push ( "listener" );
final MinecraftClient client = MinecraftClient . getInstance ();
this . itemRenderer = client . getItemRenderer ();
this . inventoryModel = client . getBakedModelManager () . getModel ( new ModelIdentifier( itemId . withPath( itemId . getPath() + "_gui" ) , "inventory" ) );
applyProfiler . pop ();
applyProfiler . endTick ();
} , applyExecutor);
}
@ Override
public void render ( ItemStack stack , ModelTransformationMode mode , MatrixStack matrices , VertexConsumerProvider vertexConsumers , int light , int overlay) {
matrices . pop ();
matrices . push ();
if (mode != ModelTransformationMode . FIRST_PERSON_LEFT_HAND && mode != ModelTransformationMode . FIRST_PERSON_RIGHT_HAND && mode != ModelTransformationMode . THIRD_PERSON_LEFT_HAND && mode != ModelTransformationMode . THIRD_PERSON_RIGHT_HAND ) {
if ( this . itemRenderer == null ) {
this . itemRenderer = MinecraftClient . getInstance () . getItemRenderer ();
}
if ( this . inventoryModel == null ) {
this . inventoryModel = MinecraftClient . getInstance () . getBakedModelManager () . getModel ( new ModelIdentifier( itemId . withPath( itemId . getPath() + "_gui" ) , "inventory" ) );
}
DiffuseLighting . enableGuiDepthLighting ();
renderItem(itemRenderer , stack , mode , false , matrices , vertexConsumers , CAVUtils . MAX_LIGHT , overlay , this . inventoryModel ) ;
DiffuseLighting . disableGuiDepthLighting ();
}
}
public void renderItem ( ItemRenderer itemRenderer , ItemStack stack , ModelTransformationMode renderMode , boolean leftHanded , MatrixStack matrices , VertexConsumerProvider vertexConsumers , int light , int overlay , BakedModel model) {
if ( ! stack . isEmpty ()) {
matrices . push ();
model . getTransformation () . getTransformation (renderMode) . apply (leftHanded , matrices);
matrices . translate ( - 0.5F , - 0.5F , - 0.5F );
if ( ! model . isBuiltin ()) {
RenderLayer renderLayer = RenderLayers . getItemLayer (stack , true );
VertexConsumer vertexConsumer = ItemRenderer . getDirectItemGlintConsumer (vertexConsumers , renderLayer , true , stack . hasGlint ());
itemRenderer . renderBakedItemModel (model , stack , light , overlay , matrices , vertexConsumer);
}
matrices . pop ();
}
}
@ Override
public Identifier getFabricId () {
return id;
}
}
Register your custom renderer and model reloading on the client side.
Copy static void registerRenderer( Item item) {
Identifier itemId = Registries . ITEM . getId (item);
var renderer = new TwoDItemRenderer(itemId) ;
ResourceManagerHelper . get ( ResourceType . CLIENT_RESOURCES ) . registerReloadListener ((IdentifiableResourceReloadListener) renderer);
BuiltinItemRendererRegistry . INSTANCE . register (item , ( BuiltinItemRendererRegistry . DynamicItemRenderer ) renderer);
ModelLoadingRegistry . INSTANCE . registerModelProvider ((manager , out) -> {
out . accept ( new ModelIdentifier( itemId . withPath( itemId . getPath() + "_handheld" ) , "inventory" ) );
out . accept ( new ModelIdentifier( itemId . withPath( itemId . getPath() + "_gui" ) , "inventory" ) );
});
}
Copy @ Mixin ( ItemRenderer . class )
public class ItemRendererMixin {
@ Shadow
@ Final
private ItemModels models;
@ Inject (method = "getModel" , at = @ At ( "HEAD" ) , cancellable = true )
private void cav$ getHeldItemModel ( ItemStack stack , World world , LivingEntity entity , int seed , CallbackInfoReturnable < BakedModel > cir) {
if ( stack . getItem () instanceof YourCoolGeoDualModelItem) {
Identifier itemId = Registries . ITEM . getId ( stack . getItem ());
var m = new ModelIdentifier( itemId . withPath( itemId . getPath() + "_handheld" ) , "inventory" ) ;
BakedModel bakedModel = models . getModelManager () . getModel (m);
ClientWorld clientWorld = world instanceof ClientWorld ? (ClientWorld) world : null ;
BakedModel bakedModel2 = bakedModel . getOverrides () . apply (bakedModel , stack , clientWorld , entity , seed);
cir . setReturnValue (bakedModel2 == null ? this . models . getModelManager () . getMissingModel () : bakedModel2);
}
}
}
Creating Model JSON Files
Create the necessary model files for your item.
models/item/blunderbuss_gui.json
Copy {
"parent" : "item/generated" ,
"textures" : {
"layer0" : "modid:item/blunderbuss_item"
}
}
Copy {
"parent" : "builtin/entity" ,
"texture_size" : [
...
] ,
"display" : {
...
}
}