Fix render_type in block models not being used. Fixes #10294

This commit is contained in:
LexManos authored and GitHub committed 2025-01-13 13:27:47 -08:00
1 parent f63813d929
commit ec5ac91389
16 files changed
+306 -77

No files matched your search

@@ -17,17 +17,22 @@
this.parent = p_377823_.resolve(this.parentLocation);
}
}
@@ -110,6 +_,9 @@
@@ -110,14 +_,20 @@
public BakedModel bake(
TextureSlots p_378598_, ModelBaker p_378458_, ModelState p_111453_, boolean p_111455_, boolean p_377435_, ItemTransforms p_378085_
) {
+ if (this.customData.getCustomGeometry() != null)
+ return this.customData.getCustomGeometry().bake(customData, p_378458_, p_378598_, p_111453_);
+
+ var wrapped = net.minecraftforge.client.ForgeHooksClient.wrapRenderType(p_378458_, this.customData.getRenderType());
+
return this.elements.isEmpty() && this.parent != null
? this.parent.bake(p_378598_, p_378458_, p_111453_, p_111455_, p_377435_, p_378085_)
: SimpleBakedModel.bakeElements(this.elements, p_378598_, p_378458_.sprites(), p_111453_, p_111455_, p_377435_, true, p_378085_);
@@ -118,6 +_,7 @@
- ? this.parent.bake(p_378598_, p_378458_, p_111453_, p_111455_, p_377435_, p_378085_)
- : SimpleBakedModel.bakeElements(this.elements, p_378598_, p_378458_.sprites(), p_111453_, p_111455_, p_377435_, true, p_378085_);
+ ? this.parent.bake(p_378598_, wrapped, p_111453_, p_111455_, p_377435_, p_378085_)
+ : SimpleBakedModel.bakeElements(this.elements, p_378598_, p_378458_.sprites(), p_111453_, p_111455_, p_377435_, true, p_378085_, wrapped.renderType());
}
@Nullable
@VisibleForTesting
List<BlockElement> getElements() {
@@ -0,0 +1,13 @@
--- a/net/minecraft/client/resources/model/ModelBaker.java
+++ b/net/minecraft/client/resources/model/ModelBaker.java
@@ -13,4 +_,10 @@
@VisibleForDebug
ModelDebugName rootName();
+
+ /** Forge: Return the render type to use when baking this model, its a dirty hack to pass down this value to parents */
+ @org.jetbrains.annotations.Nullable
+ default net.minecraftforge.client.RenderTypeGroup renderType() {
+ return null;
+ }
}
@@ -1,55 +1,79 @@
--- a/net/minecraft/client/resources/model/SimpleBakedModel.java
+++ b/net/minecraft/client/resources/model/SimpleBakedModel.java
@@ -29,6 +_,19 @@
@@ -29,6 +_,17 @@
private final boolean usesBlockLight;
private final TextureAtlasSprite particleIcon;
private final ItemTransforms transforms;
+ /*
+ protected final net.minecraftforge.client.ChunkRenderTypeSet blockRenderTypes;
+ /*
+ protected final List<net.minecraft.client.renderer.RenderType> itemRenderTypes;
+ protected final List<net.minecraft.client.renderer.RenderType> fabulousItemRenderTypes;
+ */
+
+ /* @deprecated Forge: Use {@linkplain #SimpleBakedModel(List, Map, boolean, boolean, boolean, TextureAtlasSprite, ItemTransforms, net.minecraftforge.client.RenderTypeGroup) variant with RenderTypeGroup} **/
+ /*
+ /** @deprecated Forge: Use {@linkplain #SimpleBakedModel(List, Map, boolean, boolean, boolean, TextureAtlasSprite, ItemTransforms, net.minecraftforge.client.RenderTypeGroup) variant with RenderTypeGroup} **/
+ @Deprecated
+ public SimpleBakedModel(List<BakedQuad> p_119489_, Map<Direction, List<BakedQuad>> p_119490_, boolean p_119491_, boolean p_119492_, boolean p_119493_, TextureAtlasSprite p_119494_, ItemTransforms p_119495_) {
+ this(p_119489_, p_119490_, p_119491_, p_119492_, p_119493_, p_119494_, p_119495_, net.minecraftforge.client.RenderTypeGroup.EMPTY);
+ }
+ */
public SimpleBakedModel(
List<BakedQuad> p_119489_,
@@ -38,6 +_,7 @@
@@ -37,7 +_,8 @@
boolean p_119492_,
boolean p_119493_,
TextureAtlasSprite p_119494_,
ItemTransforms p_119495_
+ //net.minecraftforge.client.RenderTypeGroup renderTypes
- ItemTransforms p_119495_
+ ItemTransforms p_119495_,
+ net.minecraftforge.client.RenderTypeGroup renderTypes
) {
this.unculledFaces = p_119489_;
this.culledFaces = p_119490_;
@@ -46,6 +_,11 @@
@@ -46,6 +_,15 @@
this.usesBlockLight = p_119492_;
this.particleIcon = p_119494_;
this.transforms = p_119495_;
+ /*
+ this.blockRenderTypes = !renderTypes.isEmpty() ? net.minecraftforge.client.ChunkRenderTypeSet.of(renderTypes.block()) : null;
+ /*
+ this.itemRenderTypes = !renderTypes.isEmpty() ? List.of(renderTypes.entity()) : null;
+ this.fabulousItemRenderTypes = !renderTypes.isEmpty() ? List.of(renderTypes.entityFabulous()) : null;
+ */
+ }
+
+ public static BakedModel bakeElements(List<BlockElement> p_377425_, TextureSlots p_378525_, SpriteGetter p_375793_, ModelState p_376680_, boolean p_375745_, boolean p_376866_, boolean p_376846_, ItemTransforms p_376883_) {
+ return bakeElements(p_377425_, p_378525_, p_375793_, p_376680_, p_375745_, p_376866_, p_376846_, p_376883_, null);
}
public static BakedModel bakeElements(
@@ -56,7 +_,8 @@
boolean p_375745_,
boolean p_376866_,
boolean p_376846_,
- ItemTransforms p_376883_
+ ItemTransforms p_376883_,
+ @Nullable net.minecraftforge.client.RenderTypeGroup renderType
) {
TextureAtlasSprite textureatlassprite = findSprite(p_375793_, p_378525_, "particle");
SimpleBakedModel.Builder simplebakedmodel$builder = new SimpleBakedModel.Builder(p_375745_, p_376866_, p_376846_, p_376883_)
@@ -77,6 +_,9 @@
}
}
+ if (renderType != null)
+ simplebakedmodel$builder.renderTypes(renderType);
+
return simplebakedmodel$builder.build();
}
@@ -123,6 +_,27 @@
return this.transforms;
}
+ /*
+ @Override
+ public net.minecraftforge.client.ChunkRenderTypeSet getRenderTypes(BlockState state, RandomSource rand, net.minecraftforge.client.model.data.ModelData data) {
+ return blockRenderTypes != null ? blockRenderTypes : BakedModel.super.getRenderTypes(state, rand, data);
+ }
+
+ /*
+ @Override
+ public List<net.minecraft.client.renderer.RenderType> getRenderTypes(net.minecraft.world.item.ItemStack itemStack, boolean fabulous) {
+ if (!fabulous) {
@@ -68,17 +92,15 @@
@OnlyIn(Dist.CLIENT)
public static class Builder {
private final ImmutableList.Builder<BakedQuad> unculledFaces = ImmutableList.builder();
@@ -164,13 +_,21 @@
@@ -164,13 +_,19 @@
return this;
}
+ /*
+ private net.minecraftforge.client.RenderTypeGroup renderTypes = net.minecraftforge.client.RenderTypeGroup.EMPTY;
+ public SimpleBakedModel.Builder renderTypes(net.minecraftforge.client.RenderTypeGroup renderTypes) {
+ this.renderTypes = renderTypes;
+ return this;
+ }
+ */
+
public BakedModel build() {
if (this.particleIcon == null) {
@@ -87,7 +109,7 @@
Map<Direction, List<BakedQuad>> map = Maps.transformValues(this.culledFaces, ImmutableList.Builder::build);
return new SimpleBakedModel(
- this.unculledFaces.build(), new EnumMap<>(map), this.hasAmbientOcclusion, this.usesBlockLight, this.isGui3d, this.particleIcon, this.transforms
+ this.unculledFaces.build(), new EnumMap<>(map), this.hasAmbientOcclusion, this.usesBlockLight, this.isGui3d, this.particleIcon, this.transforms/*, this.renderTypes*/
+ this.unculledFaces.build(), new EnumMap<>(map), this.hasAmbientOcclusion, this.usesBlockLight, this.isGui3d, this.particleIcon, this.transforms, this.renderTypes
);
}
}
@@ -14,20 +14,14 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.platform.Window;
import com.mojang.blaze3d.shaders.FogShape;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator;
import com.mojang.datafixers.util.Either;
import com.mojang.math.Constants;
import com.mojang.math.Transformation;
import net.minecraft.ChatFormatting;
import net.minecraft.FileUtil;
import net.minecraft.Util;
import net.minecraft.client.Camera;
import net.minecraft.client.ClientRecipeBook;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Options;
import net.minecraft.client.color.block.BlockColors;
@@ -35,7 +29,6 @@ import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.ChatComponent;
import net.minecraft.client.gui.components.LerpingBossEvent;
import net.minecraft.client.gui.components.toasts.Toast;
import net.minecraft.client.gui.screens.ConfirmScreen;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.TitleScreen;
@@ -54,7 +47,6 @@ import net.minecraft.client.particle.ParticleRenderType;
import net.minecraft.client.player.ClientInput;
import net.minecraft.client.renderer.FogParameters;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
@@ -63,7 +55,6 @@ import net.minecraft.client.renderer.ShaderProgram;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.BlockElement;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.renderer.entity.state.HumanoidRenderState;
import net.minecraft.client.renderer.texture.SpriteContents;
import net.minecraft.client.renderer.texture.TextureAtlas;
@@ -71,14 +62,15 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.client.resources.metadata.animation.FrameSize;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.Material;
import net.minecraft.client.resources.model.ModelBaker;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelDebugName;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.client.resources.model.SpriteGetter;
import net.minecraft.client.resources.sounds.SoundInstance;
import net.minecraft.client.sounds.SoundEngine;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.locale.Language;
import net.minecraft.network.Connection;
import net.minecraft.network.chat.ChatType;
@@ -100,10 +92,8 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.InventoryMenu;
import net.minecraft.world.inventory.tooltip.TooltipComponent;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.block.Blocks;
@@ -113,20 +103,17 @@ import net.minecraft.world.level.material.FogType;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ClientChatEvent;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.client.event.ClientPauseChangeEvent;
import net.minecraftforge.client.event.ClientPlayerChangeGameTypeEvent;
import net.minecraftforge.client.event.SystemMessageReceivedEvent;
import net.minecraftforge.client.event.ComputeFovModifierEvent;
import net.minecraftforge.client.event.CustomizeGuiOverlayEvent;
import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.client.event.ForgeEventFactoryClient;
import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.client.event.ModelEvent;
import net.minecraftforge.client.event.MovementInputUpdateEvent;
import net.minecraftforge.client.event.RecipesUpdatedEvent;
import net.minecraftforge.client.event.RegisterClientReloadListenersEvent;
import net.minecraftforge.client.event.RegisterColorHandlersEvent;
import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
@@ -137,7 +124,6 @@ import net.minecraftforge.client.event.RenderHighlightEvent;
import net.minecraftforge.client.event.RenderTooltipEvent;
import net.minecraftforge.client.event.ScreenEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.event.ToastAddEvent;
import net.minecraftforge.client.event.ViewportEvent;
import net.minecraftforge.client.event.sound.PlaySoundEvent;
import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions;
@@ -150,16 +136,13 @@ import net.minecraftforge.client.model.geometry.GeometryLoaderManager;
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
import net.minecraftforge.client.textures.ForgeTextureMetadata;
import net.minecraftforge.client.textures.TextureAtlasSpriteLoaderManager;
import net.minecraftforge.common.ForgeConfig;
import net.minecraftforge.common.ForgeI18n;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.IExtensionPoint;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.VersionChecker;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.gametest.ForgeGameTestHooks;
import net.minecraftforge.network.NetworkContext;
import net.minecraftforge.network.NetworkInitialization;
@@ -174,13 +157,11 @@ import org.apache.logging.log4j.MarkerManager;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@@ -188,7 +169,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.Stack;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -934,4 +914,34 @@ public class ForgeHooksClient {
return model;
}
/** This is a dirty fucking hack, but it needs to send in the top most render type. */
public static ModelBaker wrapRenderType(ModelBaker parent, RenderTypeGroup group) {
if (group == null || group == RenderTypeGroup.EMPTY || parent.renderType() != null)
return parent;
return new WrapedModelBaker(parent, group);
}
// a record for performance reasons
private record WrapedModelBaker(ModelBaker parent, RenderTypeGroup group) implements ModelBaker {
@Override
public RenderTypeGroup renderType() {
return group;
}
@Override
public BakedModel bake(ResourceLocation name, ModelState state) {
return parent.bake(name, state);
}
@Override
public SpriteGetter sprites() {
return parent.sprites();
}
@Override
public ModelDebugName rootName() {
return parent.rootName();
}
}
}
@@ -213,7 +213,7 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel> {
}
private void addLayer(RenderTypeGroup renderTypes, List<BakedQuad> quads) {
var modelBuilder = IModelBuilder.of(isAmbientOcclusion, isSideLit, isGui3d, transforms, particle/*, renderTypes*/);
var modelBuilder = IModelBuilder.of(isAmbientOcclusion, isSideLit, isGui3d, transforms, particle, renderTypes);
quads.forEach(modelBuilder::addUnculledFace);
children.add(modelBuilder.build());
}
@@ -11,6 +11,8 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.SimpleBakedModel;
import net.minecraft.core.Direction;
import net.minecraftforge.client.RenderTypeGroup;
import java.util.List;
/**
@@ -30,7 +32,18 @@ public interface IModelBuilder<T extends IModelBuilder<T>> {
ItemTransforms transforms,
TextureAtlasSprite particle
){
return new Simple(hasAmbientOcclusion, usesBlockLight, isGui3d, transforms, particle);
return of(hasAmbientOcclusion, usesBlockLight, isGui3d, transforms, particle, RenderTypeGroup.EMPTY);
}
static IModelBuilder<?> of(
boolean hasAmbientOcclusion,
boolean usesBlockLight,
boolean isGui3d,
ItemTransforms transforms,
TextureAtlasSprite particle,
RenderTypeGroup renderTypes
){
return new Simple(hasAmbientOcclusion, usesBlockLight, isGui3d, transforms, particle, renderTypes);
}
/**
@@ -52,9 +65,10 @@ public interface IModelBuilder<T extends IModelBuilder<T>> {
private Simple(
boolean hasAmbientOcclusion, boolean usesBlockLight, boolean isGui3d,
ItemTransforms transforms, TextureAtlasSprite particle
ItemTransforms transforms, TextureAtlasSprite particle, RenderTypeGroup renderTypes
) {
this.builder = new SimpleBakedModel.Builder(hasAmbientOcclusion, usesBlockLight, isGui3d, transforms).particle(particle);
this.builder.renderTypes(renderTypes);
}
@Override
@@ -69,7 +83,6 @@ public interface IModelBuilder<T extends IModelBuilder<T>> {
return this;
}
@Deprecated
@Override
public BakedModel build() {
return builder.build();
@@ -11,31 +11,8 @@ import net.minecraft.client.resources.model.ModelState;
/**
* Simple implementation of {@link ModelState}.
*/
public final class SimpleModelState implements ModelState
{
private final Transformation transformation;
private final boolean uvLocked;
public SimpleModelState(Transformation transformation, boolean uvLocked)
{
this.transformation = transformation;
this.uvLocked = uvLocked;
}
public SimpleModelState(Transformation transformation)
{
public record SimpleModelState(Transformation getRotation, boolean isUvLocked) implements ModelState {
public SimpleModelState(Transformation transformation) {
this(transformation, false);
}
@Override
public Transformation getRotation()
{
return transformation;
}
@Override
public boolean isUvLocked()
{
return uvLocked;
}
}
@@ -68,4 +68,12 @@ public interface IGeometryBakingContext {
default RenderTypeGroup getRenderType(ResourceLocation name) {
return NamedRenderTypeManager.get(name);
}
/**
* {@return a {@link RenderTypeGroup} from the {@link #getRenderTypeHint()}, or the empty group if not found.}
*/
default RenderTypeGroup getRenderType() {
var hint = getRenderTypeHint();
return hint == null ? RenderTypeGroup.EMPTY : getRenderType(hint);
}
}
@@ -10,6 +10,7 @@ import net.minecraft.client.renderer.block.model.TextureSlots;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelBaker;
import net.minecraft.client.resources.model.ModelState;
import net.minecraftforge.client.RenderTypeGroup;
import net.minecraftforge.client.model.IModelBuilder;
/**
@@ -21,10 +22,8 @@ public abstract class SimpleUnbakedGeometry<T extends SimpleUnbakedGeometry<T>>
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, TextureSlots textures, ModelState modelState) {
var particle = baker.sprites().maybeMissing(textures, "particle");
//var renderTypeHint = context.getRenderTypeHint();
//var renderTypes = renderTypeHint != null ? context.getRenderType(renderTypeHint) : RenderTypeGroup.EMPTY;
IModelBuilder<?> builder = IModelBuilder.of(context.useAmbientOcclusion(), context.useBlockLight(), context.isGui3d(),
context.getTransforms(), particle/*, renderTypes*/);
context.getTransforms(), particle, context.getRenderType());
addQuads(context, builder, baker, textures, modelState);
@@ -301,6 +301,7 @@ protected net.minecraft.client.data.models.BlockModelGenerators$BlockFamilyProvi
protected net.minecraft.client.data.models.BlockModelGenerators$BlockFamilyProvider m_373633_(Lnet/minecraft/data/BlockFamily$Variant;Lnet/minecraft/world/level/block/Block;)V # lambda$generateFor$1
protected net.minecraft.client.data.models.BlockModelGenerators$BlockFamilyProvider m_373732_(Lnet/minecraft/world/level/block/Block;)Lnet/minecraft/client/data/models/BlockModelGenerators$BlockFamilyProvider; # fullBlockVariant
#endgroup
public net.minecraft.client.data.models.BlockModelGenerators$PlantType
public net.minecraft.client.data.models.BlockModelGenerators$WoodProvider
#group protected net.minecraft.client.data.models.ItemModelGenerators *()
protected net.minecraft.client.data.models.ItemModelGenerators m_372103_(Lnet/minecraft/world/item/Item;I)V # generateDyedItem
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "model_render_type:block/cutout_block"
}
}
}
@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "model_render_type:item/cutout_block"
}
}
@@ -0,0 +1,7 @@
{
"parent": "minecraft:block/cross",
"render_type": "minecraft:cutout",
"textures": {
"cross": "minecraft:block/acacia_sapling"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "minecraft:block/acacia_sapling"
}
}
@@ -128,7 +128,7 @@ public class AdditionalModelTest extends BaseTestMod {
var key = new ModelResourceLocation(rl("cow_head"), "");
var model = manager.getModel(key);
if (model == null)
if (model == null || model == manager.getMissingModel())
helper.fail("Failed to retreive " + key + " block model");
helper.succeed();
@@ -196,7 +196,7 @@ public class AdditionalModelTest extends BaseTestMod {
}
protected Stream<Block> getKnownBlocks() {
return Stream.of(PIG_HEAD.get(), COW_HEAD.get());
return Stream.of(COW_HEAD.get()); // We don't include PIG_HEAD because it doesn't need a blockstate file
}
protected Stream<Item> getKnownItems() {
@@ -0,0 +1,155 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.debug.client;
import net.minecraft.client.Minecraft;
import net.minecraft.client.data.models.BlockModelGenerators;
import net.minecraft.client.data.models.ItemModelGenerators;
import net.minecraft.client.data.models.model.ItemModelUtils;
import net.minecraft.client.data.models.model.ModelLocationUtils;
import net.minecraft.client.data.models.model.ModelTemplates;
import net.minecraft.client.data.models.model.TextureMapping;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.CachedOutput;
import net.minecraft.data.DataProvider;
import net.minecraft.data.PackOutput;
import net.minecraft.gametest.framework.GameTest;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SaplingBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.grower.TreeGrower;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.MapColor;
import net.minecraft.world.level.material.PushReaction;
import net.minecraftforge.client.model.data.ModelData;
import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.gametest.GameTestHolder;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.RegistryObject;
import net.minecraftforge.test.BaseTestMod;
import java.nio.file.Path;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
import com.google.gson.JsonElement;
@Mod(ModelRenderLayerTest.MODID)
@GameTestHolder("forge." + ModelRenderLayerTest.MODID)
public class ModelRenderLayerTest extends BaseTestMod {
public static final String MODID = "model_render_type";
private static final String BLOCK_NAME = "cutout_block";
private static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(Registries.BLOCK, MODID);
public static final RegistryObject<Block> BLOCK = BLOCKS.register(BLOCK_NAME,
() -> new SaplingBlock(
TreeGrower.ACACIA,
BlockBehaviour.Properties.of()
.setId(BLOCKS.key(BLOCK_NAME))
.mapColor(MapColor.PLANT)
.noCollission()
.randomTicks()
.instabreak()
.sound(SoundType.GRASS)
.pushReaction(PushReaction.DESTROY)
)
);
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(Registries.ITEM, MODID);
public static final RegistryObject<Item> ITEM = ITEMS.register(BLOCK_NAME, () -> new BlockItem(BLOCK.get(), new Item.Properties().setId(ITEMS.key(BLOCK_NAME))));
private static ResourceLocation rl(String path) {
return ResourceLocation.fromNamespaceAndPath(MODID, path);
}
public ModelRenderLayerTest(FMLJavaModLoadingContext context) {
super(context);
testItem(lookup -> new ItemStack(ITEM.get()));
}
@SubscribeEvent
public void runData(GatherDataEvent event) {
var out = event.getGenerator().getPackOutput();
event.getGenerator().addProvider(event.includeClient(), new ModelProvider(out));
}
@SuppressWarnings("resource")
@GameTest(template = "forge:empty3x3x3")
public static void type_from_model(GameTestHelper helper) {
var manager = Minecraft.getInstance().getModelManager();
var key = new ModelResourceLocation(rl(BLOCK_NAME), "stage=0");
var model = manager.getModel(key);
if (model == manager.getMissingModel())
helper.fail("Failed to retreive " + key + " block model");
var state = BLOCK.get().defaultBlockState();
var random = helper.getLevel().random;
var layer = model.getRenderTypes(state, random, ModelData.EMPTY);
if (!layer.contains(RenderType.cutout()))
helper.fail("Block model does not have cutout layer");
helper.succeed();
}
public class ModelProvider extends net.minecraft.client.data.models.ModelProvider {
public ModelProvider(PackOutput output) {
super(output);
}
protected Stream<Block> getKnownBlocks() {
return Stream.of(BLOCK.get());
}
protected Stream<Item> getKnownItems() {
return Stream.of(ITEM.get());
}
protected BlockModelGenerators getBlockModelGenerators(BlockStateGeneratorCollector blocks, ItemInfoCollector items, SimpleModelCollector models) {
return new BlockModelGenerators(blocks, items, models) {
@Override
public void run() {
var textures = PlantType.NOT_TINTED.getTextureMapping(Blocks.ACACIA_SAPLING);
var cutout = PlantType.NOT_TINTED.getCross().create(BLOCK.get(), textures, (name, model) -> {
var json = model.get().getAsJsonObject();
json.addProperty("render_type", "minecraft:cutout");
this.modelOutput.accept(name, () -> json);
});
this.blockStateOutput.accept(createSimpleBlock(BLOCK.get(), cutout));
var item = ModelTemplates.FLAT_ITEM.create(ITEM.get(), TextureMapping.layer0(Blocks.ACACIA_SAPLING), this.modelOutput);
this.itemModelOutput.accept(ITEM.get(), ItemModelUtils.plainModel(item));
}
};
}
protected ItemModelGenerators getItemModelGenerators(ItemInfoCollector items, SimpleModelCollector models) {
return new ItemModelGenerators(items, models) {
public void run() {
}
};
}
static <T> CompletableFuture<?> saveAll(CachedOutput p_378816_, Function<T, Path> p_377914_, Map<T, ? extends Supplier<JsonElement>> p_377836_) {
return DataProvider.saveAll(p_378816_, Supplier::get, p_377914_, p_377836_);
}
}
}