Model system improvements:
- Port some things I did in 1.14 which I couldn't do in 1.15 due to breaking changes. - Fix multi-layer block models not working (1.16 RenderType doesn't override toString the same way anymore) - Implement multi-layer item rendering. - Improve CompositeModel submodel data passing.
This commit is contained in:
parent
45152c6073
commit
ce3d8b40cf
17 changed files with 749 additions and 202 deletions
|
@ -18,16 +18,30 @@
|
||||||
p_229111_4_.func_227861_a_(-0.5D, -0.5D, -0.5D);
|
p_229111_4_.func_227861_a_(-0.5D, -0.5D, -0.5D);
|
||||||
if (!p_229111_8_.func_188618_c() && (p_229111_1_.func_77973_b() != Items.field_203184_eO || flag)) {
|
if (!p_229111_8_.func_188618_c() && (p_229111_1_.func_77973_b() != Items.field_203184_eO || flag)) {
|
||||||
boolean flag1;
|
boolean flag1;
|
||||||
@@ -132,7 +132,7 @@
|
@@ -105,7 +105,8 @@
|
||||||
|
} else {
|
||||||
|
flag1 = true;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+ if (p_229111_8_.isLayered()) { net.minecraftforge.client.ForgeHooksClient.drawItemLayered(this, p_229111_8_, p_229111_1_, p_229111_4_, p_229111_5_, p_229111_6_, p_229111_7_, flag1); }
|
||||||
|
+ else {
|
||||||
|
RenderType rendertype = RenderTypeLookup.func_239219_a_(p_229111_1_, flag1);
|
||||||
|
IVertexBuilder ivertexbuilder;
|
||||||
|
if (p_229111_1_.func_77973_b() == Items.field_151111_aL && p_229111_1_.func_77962_s()) {
|
||||||
|
@@ -129,10 +130,10 @@
|
||||||
|
} else {
|
||||||
|
ivertexbuilder = func_229113_a_(p_229111_5_, rendertype, true, p_229111_1_.func_77962_s());
|
||||||
|
}
|
||||||
|
-
|
||||||
this.func_229114_a_(p_229111_8_, p_229111_1_, p_229111_6_, p_229111_7_, p_229111_4_, ivertexbuilder);
|
this.func_229114_a_(p_229111_8_, p_229111_1_, p_229111_6_, p_229111_7_, p_229111_4_, ivertexbuilder);
|
||||||
|
+ }
|
||||||
} else {
|
} else {
|
||||||
- ItemStackTileEntityRenderer.field_147719_a.func_239207_a_(p_229111_1_, p_229111_2_, p_229111_4_, p_229111_5_, p_229111_6_, p_229111_7_);
|
- ItemStackTileEntityRenderer.field_147719_a.func_239207_a_(p_229111_1_, p_229111_2_, p_229111_4_, p_229111_5_, p_229111_6_, p_229111_7_);
|
||||||
+ p_229111_1_.func_77973_b().getItemStackTileEntityRenderer().func_239207_a_(p_229111_1_, p_229111_2_, p_229111_4_, p_229111_5_, p_229111_6_, p_229111_7_);
|
+ p_229111_1_.func_77973_b().getItemStackTileEntityRenderer().func_239207_a_(p_229111_1_, p_229111_2_, p_229111_4_, p_229111_5_, p_229111_6_, p_229111_7_);
|
||||||
}
|
}
|
||||||
|
|
||||||
p_229111_4_.func_227865_b_();
|
p_229111_4_.func_227865_b_();
|
||||||
@@ -172,7 +172,7 @@
|
@@ -172,7 +173,7 @@
|
||||||
float f = (float)(i >> 16 & 255) / 255.0F;
|
float f = (float)(i >> 16 & 255) / 255.0F;
|
||||||
float f1 = (float)(i >> 8 & 255) / 255.0F;
|
float f1 = (float)(i >> 8 & 255) / 255.0F;
|
||||||
float f2 = (float)(i & 255) / 255.0F;
|
float f2 = (float)(i & 255) / 255.0F;
|
||||||
|
@ -36,7 +50,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -263,6 +263,7 @@
|
@@ -263,6 +264,7 @@
|
||||||
crashreportcategory.func_189529_a("Item Type", () -> {
|
crashreportcategory.func_189529_a("Item Type", () -> {
|
||||||
return String.valueOf((Object)p_239387_2_.func_77973_b());
|
return String.valueOf((Object)p_239387_2_.func_77973_b());
|
||||||
});
|
});
|
||||||
|
@ -44,7 +58,7 @@
|
||||||
crashreportcategory.func_189529_a("Item Damage", () -> {
|
crashreportcategory.func_189529_a("Item Damage", () -> {
|
||||||
return String.valueOf(p_239387_2_.func_77952_i());
|
return String.valueOf(p_239387_2_.func_77952_i());
|
||||||
});
|
});
|
||||||
@@ -294,18 +295,16 @@
|
@@ -294,18 +296,16 @@
|
||||||
irendertypebuffer$impl.func_228461_a_();
|
irendertypebuffer$impl.func_228461_a_();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +81,7 @@
|
||||||
this.func_181565_a(bufferbuilder, p_180453_3_ + 2, p_180453_4_ + 13, 13, 2, 0, 0, 0, 255);
|
this.func_181565_a(bufferbuilder, p_180453_3_ + 2, p_180453_4_ + 13, 13, 2, 0, 0, 0, 255);
|
||||||
this.func_181565_a(bufferbuilder, p_180453_3_ + 2, p_180453_4_ + 13, i, 1, j >> 16 & 255, j >> 8 & 255, j & 255, 255);
|
this.func_181565_a(bufferbuilder, p_180453_3_ + 2, p_180453_4_ + 13, i, 1, j >> 16 & 255, j >> 8 & 255, j & 255, 255);
|
||||||
RenderSystem.enableBlend();
|
RenderSystem.enableBlend();
|
||||||
@@ -343,4 +342,9 @@
|
@@ -343,4 +343,9 @@
|
||||||
public void func_195410_a(IResourceManager p_195410_1_) {
|
public void func_195410_a(IResourceManager p_195410_1_) {
|
||||||
this.field_175059_m.func_178085_b();
|
this.field_175059_m.func_178085_b();
|
||||||
}
|
}
|
||||||
|
|
|
@ -810,4 +810,17 @@ public class ForgeHooksClient
|
||||||
MinecraftForge.EVENT_BUS.post(event);
|
MinecraftForge.EVENT_BUS.post(event);
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void drawItemLayered(ItemRenderer renderer, IBakedModel modelIn, ItemStack itemStackIn, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int combinedLightIn, int combinedOverlayIn, boolean fabulous)
|
||||||
|
{
|
||||||
|
for(com.mojang.datafixers.util.Pair<IBakedModel,RenderType> layerModel : modelIn.getLayerModels(itemStackIn, fabulous)) {
|
||||||
|
modelIn = layerModel.getFirst();
|
||||||
|
RenderType rendertype = layerModel.getSecond();
|
||||||
|
net.minecraftforge.client.ForgeHooksClient.setRenderLayer(rendertype); // neded for compatibility with MultiLayerModels
|
||||||
|
|
||||||
|
IVertexBuilder ivertexbuilder = ItemRenderer.getBuffer(bufferIn, rendertype, true, itemStackIn.hasEffect());
|
||||||
|
renderer.renderModel(modelIn, itemStackIn, combinedLightIn, combinedOverlayIn, matrixStackIn, ivertexbuilder);
|
||||||
|
}
|
||||||
|
net.minecraftforge.client.ForgeHooksClient.setRenderLayer(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
142
src/main/java/net/minecraftforge/client/ForgeRenderTypes.java
Normal file
142
src/main/java/net/minecraftforge/client/ForgeRenderTypes.java
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* Minecraft Forge
|
||||||
|
* Copyright (c) 2016-2020.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation version 2.1
|
||||||
|
* of the License.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.minecraftforge.client;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.RenderState;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.texture.AtlasTexture;
|
||||||
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
|
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.common.util.NonNullLazy;
|
||||||
|
import net.minecraftforge.common.util.NonNullSupplier;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
public enum ForgeRenderTypes
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A cached copy of {@link ForgeRenderTypes#getUnsortedTranslucent(ResourceLocation)}
|
||||||
|
* for use in item models and TileEntityRenderers that use the block/item atlas.
|
||||||
|
*/
|
||||||
|
ITEM_UNSORTED_TRANSLUCENT(()-> getUnsortedTranslucent(AtlasTexture.LOCATION_BLOCKS_TEXTURE)),
|
||||||
|
ITEM_UNLIT_TRANSLUCENT(()-> getUnlitTranslucent(AtlasTexture.LOCATION_BLOCKS_TEXTURE)),
|
||||||
|
ITEM_UNSORTED_UNLIT_TRANSLUCENT(()-> getUnlitTranslucent(AtlasTexture.LOCATION_BLOCKS_TEXTURE, false));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A RenderType fit for translucent item/entity rendering, but with depth sorting disabled.
|
||||||
|
*/
|
||||||
|
public static RenderType getUnsortedTranslucent(ResourceLocation textureLocation)
|
||||||
|
{
|
||||||
|
return Internal.unsortedTranslucent(textureLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A RenderType fit for translucent item/entity rendering, but with diffuse lighting disabled
|
||||||
|
* so that fullbright quads look correct.
|
||||||
|
*/
|
||||||
|
public static RenderType getUnlitTranslucent(ResourceLocation textureLocation)
|
||||||
|
{
|
||||||
|
return getUnlitTranslucent(textureLocation, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A RenderType fit for translucent item/entity rendering, but with diffuse lighting disabled
|
||||||
|
* so that fullbright quads look correct.
|
||||||
|
* @param sortingEnabled If false, depth sorting will not be performed.
|
||||||
|
*/
|
||||||
|
public static RenderType getUnlitTranslucent(ResourceLocation textureLocation, boolean sortingEnabled)
|
||||||
|
{
|
||||||
|
return Internal.unlitTranslucent(textureLocation, sortingEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Same as {@link RenderType#getEntityCutout(ResourceLocation)}, but with mipmapping enabled.
|
||||||
|
*/
|
||||||
|
public static RenderType getEntityCutoutMipped(ResourceLocation textureLocation)
|
||||||
|
{
|
||||||
|
return Internal.entityCutoutMipped(textureLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// Implementation details below this line
|
||||||
|
// ----------------------------------------
|
||||||
|
|
||||||
|
private final NonNullSupplier<RenderType> renderTypeSupplier;
|
||||||
|
|
||||||
|
ForgeRenderTypes(NonNullSupplier<RenderType> renderTypeSupplier)
|
||||||
|
{
|
||||||
|
// Wrap in a Lazy<> to avoid running the supplier more than once.
|
||||||
|
this.renderTypeSupplier = NonNullLazy.of(renderTypeSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderType get()
|
||||||
|
{
|
||||||
|
return renderTypeSupplier.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Internal extends RenderType
|
||||||
|
{
|
||||||
|
private Internal(String name, VertexFormat fmt, int glMode, int size, boolean doCrumbling, boolean depthSorting, Runnable onEnable, Runnable onDisable)
|
||||||
|
{
|
||||||
|
super(name, fmt, glMode, size, doCrumbling, depthSorting, onEnable, onDisable);
|
||||||
|
throw new IllegalStateException("This class must not be instantiated");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RenderType unsortedTranslucent(ResourceLocation textureLocation)
|
||||||
|
{
|
||||||
|
final boolean sortingEnabled = false;
|
||||||
|
State renderState = State.getBuilder()
|
||||||
|
.texture(new TextureState(textureLocation, false, false))
|
||||||
|
.transparency(TRANSLUCENT_TRANSPARENCY)
|
||||||
|
.diffuseLighting(DIFFUSE_LIGHTING_ENABLED)
|
||||||
|
.alpha(DEFAULT_ALPHA)
|
||||||
|
.cull(CULL_DISABLED)
|
||||||
|
.lightmap(LIGHTMAP_ENABLED)
|
||||||
|
.overlay(OVERLAY_ENABLED)
|
||||||
|
.build(true);
|
||||||
|
return makeType("entity_unsorted_translucent", DefaultVertexFormats.ENTITY, GL11.GL_QUADS, 256, true, sortingEnabled, renderState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RenderType unlitTranslucent(ResourceLocation textureLocation, boolean sortingEnabled)
|
||||||
|
{
|
||||||
|
State renderState = State.getBuilder()
|
||||||
|
.texture(new TextureState(textureLocation, false, false))
|
||||||
|
.transparency(TRANSLUCENT_TRANSPARENCY)
|
||||||
|
.alpha(DEFAULT_ALPHA)
|
||||||
|
.cull(CULL_DISABLED)
|
||||||
|
.lightmap(LIGHTMAP_ENABLED)
|
||||||
|
.overlay(OVERLAY_ENABLED)
|
||||||
|
.build(true);
|
||||||
|
return makeType("entity_unlit_translucent", DefaultVertexFormats.ENTITY, GL11.GL_QUADS, 256, true, sortingEnabled, renderState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RenderType entityCutoutMipped(ResourceLocation locationIn) {
|
||||||
|
RenderType.State rendertype$state = RenderType.State.getBuilder()
|
||||||
|
.texture(new RenderState.TextureState(locationIn, false, true))
|
||||||
|
.transparency(NO_TRANSPARENCY)
|
||||||
|
.diffuseLighting(DIFFUSE_LIGHTING_ENABLED)
|
||||||
|
.alpha(DEFAULT_ALPHA)
|
||||||
|
.lightmap(LIGHTMAP_ENABLED)
|
||||||
|
.overlay(OVERLAY_ENABLED)
|
||||||
|
.build(true);
|
||||||
|
return makeType("entity_cutout_mipped", DefaultVertexFormats.ENTITY, 7, 256, true, false, rendertype$state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,19 +19,25 @@
|
||||||
|
|
||||||
package net.minecraftforge.client.extensions;
|
package net.minecraftforge.client.extensions;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.RenderTypeLookup;
|
||||||
import net.minecraft.client.renderer.model.BakedQuad;
|
import net.minecraft.client.renderer.model.BakedQuad;
|
||||||
import net.minecraft.client.renderer.model.IBakedModel;
|
import net.minecraft.client.renderer.model.IBakedModel;
|
||||||
import net.minecraft.client.renderer.model.ItemCameraTransforms;
|
import net.minecraft.client.renderer.model.ItemCameraTransforms;
|
||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.IBlockDisplayReader;
|
import net.minecraft.world.IBlockDisplayReader;
|
||||||
|
@ -75,4 +81,20 @@ public interface IForgeBakedModel
|
||||||
{
|
{
|
||||||
return getBakedModel().getParticleTexture();
|
return getBakedModel().getParticleTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override to true, to tell forge to call the getLayerModels method below.
|
||||||
|
*/
|
||||||
|
default boolean isLayered()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If {@see isLayered()} returns true, this is called to get the list of layers to draw.
|
||||||
|
*/
|
||||||
|
default List<Pair<IBakedModel, RenderType>> getLayerModels(ItemStack itemStack, boolean fabulous)
|
||||||
|
{
|
||||||
|
return Collections.singletonList(Pair.of(getBakedModel(), RenderTypeLookup.func_239219_a_(itemStack, fabulous)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,17 +38,17 @@ public interface IForgeVertexBuilder
|
||||||
{
|
{
|
||||||
default IVertexBuilder getVertexBuilder() { return (IVertexBuilder)this; }
|
default IVertexBuilder getVertexBuilder() { return (IVertexBuilder)this; }
|
||||||
|
|
||||||
// Copy of func_227889_a_, but enables tinting
|
// Copy of addQuad, but enables tinting and per-vertex alpha
|
||||||
default void addVertexData(MatrixStack.Entry matrixStack, BakedQuad bakedQuad, float red, float green, float blue, int lightmapCoord, int overlayColor, boolean readExistingColor) {
|
default void addVertexData(MatrixStack.Entry matrixStack, BakedQuad bakedQuad, float red, float green, float blue, int lightmapCoord, int overlayColor, boolean readExistingColor) {
|
||||||
getVertexBuilder().addQuad(matrixStack, bakedQuad, new float[]{1.0F, 1.0F, 1.0F, 1.0F}, red, green, blue, new int[]{lightmapCoord, lightmapCoord, lightmapCoord, lightmapCoord}, overlayColor, readExistingColor);
|
addVertexData(matrixStack, bakedQuad, red, green, blue, 1.0f, lightmapCoord, overlayColor, readExistingColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy of func_227889_a_ with alpha support
|
// Copy of addQuad with alpha support
|
||||||
default void addVertexData(MatrixStack.Entry matrixEntry, BakedQuad bakedQuad, float red, float green, float blue, float alpha, int lightmapCoord, int overlayColor) {
|
default void addVertexData(MatrixStack.Entry matrixEntry, BakedQuad bakedQuad, float red, float green, float blue, float alpha, int lightmapCoord, int overlayColor) {
|
||||||
addVertexData(matrixEntry, bakedQuad, new float[]{1.0F, 1.0F, 1.0F, 1.0F}, red, green, blue, alpha, new int[]{lightmapCoord, lightmapCoord, lightmapCoord, lightmapCoord}, overlayColor, false);
|
addVertexData(matrixEntry, bakedQuad, new float[]{1.0F, 1.0F, 1.0F, 1.0F}, red, green, blue, alpha, new int[]{lightmapCoord, lightmapCoord, lightmapCoord, lightmapCoord}, overlayColor, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy of func_227889_a_ with alpha support
|
// Copy of addQuad with alpha support
|
||||||
default void addVertexData(MatrixStack.Entry matrixEntry, BakedQuad bakedQuad, float red, float green, float blue, float alpha, int lightmapCoord, int overlayColor, boolean readExistingColor) {
|
default void addVertexData(MatrixStack.Entry matrixEntry, BakedQuad bakedQuad, float red, float green, float blue, float alpha, int lightmapCoord, int overlayColor, boolean readExistingColor) {
|
||||||
addVertexData(matrixEntry, bakedQuad, new float[]{1.0F, 1.0F, 1.0F, 1.0F}, red, green, blue, alpha, new int[]{lightmapCoord, lightmapCoord, lightmapCoord, lightmapCoord}, overlayColor, readExistingColor);
|
addVertexData(matrixEntry, bakedQuad, new float[]{1.0F, 1.0F, 1.0F, 1.0F}, red, green, blue, alpha, new int[]{lightmapCoord, lightmapCoord, lightmapCoord, lightmapCoord}, overlayColor, readExistingColor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,10 +31,9 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
import net.minecraft.resources.IResourceManager;
|
import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraftforge.client.model.data.IDynamicBakedModel;
|
import net.minecraft.world.IBlockDisplayReader;
|
||||||
import net.minecraftforge.client.model.data.IModelData;
|
import net.minecraftforge.client.model.data.*;
|
||||||
import net.minecraftforge.client.model.data.ModelProperty;
|
|
||||||
import net.minecraftforge.client.model.geometry.IModelGeometryPart;
|
import net.minecraftforge.client.model.geometry.IModelGeometryPart;
|
||||||
import net.minecraftforge.client.model.geometry.IMultipartModelGeometry;
|
import net.minecraftforge.client.model.geometry.IMultipartModelGeometry;
|
||||||
|
|
||||||
|
@ -45,20 +44,20 @@ import java.util.function.Function;
|
||||||
|
|
||||||
public class CompositeModel implements IDynamicBakedModel
|
public class CompositeModel implements IDynamicBakedModel
|
||||||
{
|
{
|
||||||
public static final ModelProperty<SubmodelModelData> SUBMODEL_DATA = new ModelProperty<>();
|
|
||||||
|
|
||||||
private final ImmutableMap<String, IBakedModel> bakedParts;
|
private final ImmutableMap<String, IBakedModel> bakedParts;
|
||||||
private final boolean isAmbientOcclusion;
|
private final boolean isAmbientOcclusion;
|
||||||
private final boolean isGui3d;
|
private final boolean isGui3d;
|
||||||
|
private final boolean isSideLit;
|
||||||
private final TextureAtlasSprite particle;
|
private final TextureAtlasSprite particle;
|
||||||
private final ItemOverrideList overrides;
|
private final ItemOverrideList overrides;
|
||||||
private final IModelTransform transforms;
|
private final IModelTransform transforms;
|
||||||
|
|
||||||
public CompositeModel(boolean isGui3d, boolean isAmbientOcclusion, TextureAtlasSprite particle, ImmutableMap<String, IBakedModel> bakedParts, IModelTransform combinedTransform, ItemOverrideList overrides)
|
public CompositeModel(boolean isGui3d, boolean isSideLit, boolean isAmbientOcclusion, TextureAtlasSprite particle, ImmutableMap<String, IBakedModel> bakedParts, IModelTransform combinedTransform, ItemOverrideList overrides)
|
||||||
{
|
{
|
||||||
this.bakedParts = bakedParts;
|
this.bakedParts = bakedParts;
|
||||||
this.isAmbientOcclusion = isAmbientOcclusion;
|
this.isAmbientOcclusion = isAmbientOcclusion;
|
||||||
this.isGui3d = isGui3d;
|
this.isGui3d = isGui3d;
|
||||||
|
this.isSideLit = isSideLit;
|
||||||
this.particle = particle;
|
this.particle = particle;
|
||||||
this.overrides = overrides;
|
this.overrides = overrides;
|
||||||
this.transforms = combinedTransform;
|
this.transforms = combinedTransform;
|
||||||
|
@ -71,12 +70,23 @@ public class CompositeModel implements IDynamicBakedModel
|
||||||
List<BakedQuad> quads = new ArrayList<>();
|
List<BakedQuad> quads = new ArrayList<>();
|
||||||
for(Map.Entry<String, IBakedModel> entry : bakedParts.entrySet())
|
for(Map.Entry<String, IBakedModel> entry : bakedParts.entrySet())
|
||||||
{
|
{
|
||||||
// TODO: Some way to provide submodel data?
|
quads.addAll(entry.getValue().getQuads(state, side, rand, CompositeModelData.get(extraData, entry.getKey())));
|
||||||
quads.addAll(entry.getValue().getQuads(state, side, rand, getSubmodelData(extraData, entry.getKey())));
|
|
||||||
}
|
}
|
||||||
return quads;
|
return quads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public IModelData getModelData(@Nonnull IBlockDisplayReader world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull IModelData tileData)
|
||||||
|
{
|
||||||
|
CompositeModelData composite = new CompositeModelData();
|
||||||
|
for(Map.Entry<String, IBakedModel> entry : bakedParts.entrySet())
|
||||||
|
{
|
||||||
|
composite.putSubmodelData(entry.getKey(), entry.getValue().getModelData(world, pos, state, ModelDataWrapper.wrap(tileData)));
|
||||||
|
}
|
||||||
|
return composite;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAmbientOcclusion()
|
public boolean isAmbientOcclusion()
|
||||||
{
|
{
|
||||||
|
@ -92,8 +102,7 @@ public class CompositeModel implements IDynamicBakedModel
|
||||||
@Override
|
@Override
|
||||||
public boolean func_230044_c_()
|
public boolean func_230044_c_()
|
||||||
{
|
{
|
||||||
// TODO: Forge: Auto-generated method stub
|
return isSideLit;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -132,29 +141,6 @@ public class CompositeModel implements IDynamicBakedModel
|
||||||
return bakedParts.get(name);
|
return bakedParts.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IModelData getSubmodelData(IModelData extraData, String name)
|
|
||||||
{
|
|
||||||
SubmodelModelData data = extraData.getData(SUBMODEL_DATA);
|
|
||||||
if (data == null)
|
|
||||||
return EmptyModelData.INSTANCE;
|
|
||||||
return data.getSubmodelData(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SubmodelModelData
|
|
||||||
{
|
|
||||||
private final Map<String, IModelData> parts = new HashMap<>();
|
|
||||||
|
|
||||||
public IModelData getSubmodelData(String name)
|
|
||||||
{
|
|
||||||
return parts.getOrDefault(name, EmptyModelData.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putSubmodelData(String name, IModelData data)
|
|
||||||
{
|
|
||||||
parts.put(name, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Submodel implements IModelGeometryPart
|
private static class Submodel implements IModelGeometryPart
|
||||||
{
|
{
|
||||||
private final String name;
|
private final String name;
|
||||||
|
@ -228,7 +214,7 @@ public class CompositeModel implements IDynamicBakedModel
|
||||||
continue;
|
continue;
|
||||||
bakedParts.put(part.getKey(), submodel.bakeModel(bakery, spriteGetter, modelTransform, modelLocation));
|
bakedParts.put(part.getKey(), submodel.bakeModel(bakery, spriteGetter, modelTransform, modelLocation));
|
||||||
}
|
}
|
||||||
return new CompositeModel(owner.isShadedInGui(), owner.useSmoothLighting(), particle, bakedParts.build(), owner.getCombinedTransform(), overrides);
|
return new CompositeModel(owner.isShadedInGui(), owner.useSmoothLighting(), owner.isSideLit(), particle, bakedParts.build(), owner.getCombinedTransform(), overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -273,4 +259,116 @@ public class CompositeModel implements IDynamicBakedModel
|
||||||
return new Geometry(parts.build());
|
return new Geometry(parts.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A model data container which stores data for child components.
|
||||||
|
*/
|
||||||
|
public static class CompositeModelData extends ModelDataMap
|
||||||
|
{
|
||||||
|
public static final ModelProperty<CompositeModelData> SUBMODEL_DATA = new ModelProperty<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to get the CompositeModelData from an unknown IModelData instance.
|
||||||
|
* @param modelData The undetermined instance to get data from
|
||||||
|
* @return An optional representing the composite data, if present.
|
||||||
|
*/
|
||||||
|
public static Optional<CompositeModelData> get(IModelData modelData)
|
||||||
|
{
|
||||||
|
return Optional.ofNullable(modelData.getData(SUBMODEL_DATA));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to get child data from an unknown IModelData instance.
|
||||||
|
* @param modelData The undetermined instance to get data from
|
||||||
|
* @param name The name of the child part to get data for.
|
||||||
|
* @return The data for the child, or empty if not available.
|
||||||
|
*/
|
||||||
|
public static IModelData get(IModelData modelData, String name)
|
||||||
|
{
|
||||||
|
return get(modelData).map(data -> data.getSubmodelData(name))
|
||||||
|
.orElse(EmptyModelData.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation
|
||||||
|
|
||||||
|
private final Map<String, IModelData> parts = new HashMap<>();
|
||||||
|
|
||||||
|
public IModelData getSubmodelData(String name)
|
||||||
|
{
|
||||||
|
if (parts.containsKey(name))
|
||||||
|
return parts.get(name);
|
||||||
|
return EmptyModelData.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putSubmodelData(String name, IModelData data)
|
||||||
|
{
|
||||||
|
parts.put(name, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasProperty(ModelProperty<?> prop)
|
||||||
|
{
|
||||||
|
return prop == SUBMODEL_DATA ||super.hasProperty(prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T> T getData(ModelProperty<T> prop)
|
||||||
|
{
|
||||||
|
if (prop == SUBMODEL_DATA)
|
||||||
|
return (T)this;
|
||||||
|
return super.getData(prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T> T setData(ModelProperty<T> prop, T data)
|
||||||
|
{
|
||||||
|
if (prop == SUBMODEL_DATA)
|
||||||
|
return (T)this;
|
||||||
|
return super.setData(prop, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for an IModelData instance which allows forwarding queries to the parent,
|
||||||
|
* but stores any new/modified values itself, avoiding modifications to the parent.
|
||||||
|
*/
|
||||||
|
private static class ModelDataWrapper extends ModelDataMap
|
||||||
|
{
|
||||||
|
private final IModelData parent;
|
||||||
|
|
||||||
|
public static IModelData wrap(IModelData parent)
|
||||||
|
{
|
||||||
|
return new ModelDataWrapper(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModelDataWrapper(IModelData parent)
|
||||||
|
{
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasProperty(ModelProperty<?> prop)
|
||||||
|
{
|
||||||
|
return super.hasProperty(prop) || parent.hasProperty(prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T> T getData(ModelProperty<T> prop)
|
||||||
|
{
|
||||||
|
return super.hasProperty(prop) ? super.getData(prop) : parent.getData(prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T> T setData(ModelProperty<T> prop, T data)
|
||||||
|
{
|
||||||
|
// We do not want to delegate setting to the parent
|
||||||
|
return super.setData(prop, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,7 @@
|
||||||
|
|
||||||
package net.minecraftforge.client.model;
|
package net.minecraftforge.client.model;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.*;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
@ -31,7 +28,6 @@ import net.minecraft.util.math.vector.Quaternion;
|
||||||
import net.minecraft.util.math.vector.TransformationMatrix;
|
import net.minecraft.util.math.vector.TransformationMatrix;
|
||||||
import net.minecraft.client.renderer.model.*;
|
import net.minecraft.client.renderer.model.*;
|
||||||
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
||||||
import net.minecraft.client.renderer.texture.MissingTextureSprite;
|
|
||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.fluid.Fluid;
|
import net.minecraft.fluid.Fluid;
|
||||||
|
@ -40,29 +36,24 @@ import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.resources.IResourceManager;
|
import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.world.World;
|
|
||||||
import net.minecraftforge.client.ForgeHooksClient;
|
import net.minecraftforge.client.ForgeHooksClient;
|
||||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||||
import net.minecraftforge.fluids.FluidUtil;
|
import net.minecraftforge.fluids.FluidUtil;
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
import net.minecraftforge.resource.IResourceType;
|
import net.minecraftforge.resource.IResourceType;
|
||||||
import net.minecraftforge.resource.VanillaResourceType;
|
import net.minecraftforge.resource.VanillaResourceType;
|
||||||
import net.minecraftforge.versions.forge.ForgeVersion;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public final class DynamicBucketModel implements IModelGeometry<DynamicBucketModel>
|
public final class DynamicBucketModel implements IModelGeometry<DynamicBucketModel>
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
public static final ModelResourceLocation LOCATION = new ModelResourceLocation(new ResourceLocation(ForgeVersion.MOD_ID, "dynbucket"), "inventory");
|
|
||||||
|
|
||||||
// minimal Z offset to prevent depth-fighting
|
// minimal Z offset to prevent depth-fighting
|
||||||
private static final float NORTH_Z_COVER = 7.496f / 16f;
|
private static final float NORTH_Z_COVER = 7.496f / 16f;
|
||||||
|
@ -76,13 +67,21 @@ public final class DynamicBucketModel implements IModelGeometry<DynamicBucketMod
|
||||||
private final boolean flipGas;
|
private final boolean flipGas;
|
||||||
private final boolean tint;
|
private final boolean tint;
|
||||||
private final boolean coverIsMask;
|
private final boolean coverIsMask;
|
||||||
|
private final boolean applyFluidLuminosity;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public DynamicBucketModel(Fluid fluid, boolean flipGas, boolean tint, boolean coverIsMask)
|
public DynamicBucketModel(Fluid fluid, boolean flipGas, boolean tint, boolean coverIsMask)
|
||||||
|
{
|
||||||
|
this(fluid, flipGas, tint, coverIsMask, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DynamicBucketModel(Fluid fluid, boolean flipGas, boolean tint, boolean coverIsMask, boolean applyFluidLuminosity)
|
||||||
{
|
{
|
||||||
this.fluid = fluid;
|
this.fluid = fluid;
|
||||||
this.flipGas = flipGas;
|
this.flipGas = flipGas;
|
||||||
this.tint = tint;
|
this.tint = tint;
|
||||||
this.coverIsMask = coverIsMask;
|
this.coverIsMask = coverIsMask;
|
||||||
|
this.applyFluidLuminosity = applyFluidLuminosity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,63 +90,46 @@ public final class DynamicBucketModel implements IModelGeometry<DynamicBucketMod
|
||||||
*/
|
*/
|
||||||
public DynamicBucketModel withFluid(Fluid newFluid)
|
public DynamicBucketModel withFluid(Fluid newFluid)
|
||||||
{
|
{
|
||||||
return new DynamicBucketModel(newFluid, flipGas, tint, coverIsMask);
|
return new DynamicBucketModel(newFluid, flipGas, tint, coverIsMask, applyFluidLuminosity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<RenderMaterial, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation)
|
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<RenderMaterial, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation)
|
||||||
{
|
{
|
||||||
RenderMaterial particleLocation = owner.resolveTexture("particle");
|
RenderMaterial particleLocation = owner.isTexturePresent("particle") ? owner.resolveTexture("particle") : null;
|
||||||
if (MissingTextureSprite.getLocation().equals(particleLocation.getTextureLocation()))
|
RenderMaterial baseLocation = owner.isTexturePresent("base") ? owner.resolveTexture("base") : null;
|
||||||
{
|
RenderMaterial fluidMaskLocation = owner.isTexturePresent("fluid") ? owner.resolveTexture("fluid") : null;
|
||||||
particleLocation = null;
|
RenderMaterial coverLocation = owner.isTexturePresent("fluid") ? owner.resolveTexture("cover") : null;
|
||||||
}
|
|
||||||
|
|
||||||
RenderMaterial baseLocation = owner.resolveTexture("base");
|
|
||||||
if (MissingTextureSprite.getLocation().equals(baseLocation.getTextureLocation()))
|
|
||||||
{
|
|
||||||
baseLocation = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderMaterial fluidMaskLocation = owner.resolveTexture("fluid");
|
|
||||||
if (MissingTextureSprite.getLocation().equals(fluidMaskLocation.getTextureLocation()))
|
|
||||||
{
|
|
||||||
fluidMaskLocation = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderMaterial coverLocation = owner.resolveTexture("cover");
|
|
||||||
if (!MissingTextureSprite.getLocation().equals(coverLocation.getTextureLocation()))
|
|
||||||
{
|
|
||||||
// cover (the actual item around the other two)
|
|
||||||
coverLocation = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
IModelTransform transformsFromModel = owner.getCombinedTransform();
|
IModelTransform transformsFromModel = owner.getCombinedTransform();
|
||||||
|
|
||||||
ImmutableMap<TransformType, TransformationMatrix> transformMap = transformsFromModel != null ?
|
TextureAtlasSprite fluidSprite = fluid != Fluids.EMPTY ? spriteGetter.apply(ForgeHooksClient.getBlockMaterial(fluid.getAttributes().getStillTexture())) : null;
|
||||||
PerspectiveMapWrapper.getTransforms(new ModelTransformComposition(transformsFromModel, modelTransform)) :
|
TextureAtlasSprite coverSprite = (coverLocation != null && (!coverIsMask || baseLocation != null)) ? spriteGetter.apply(coverLocation) : null;
|
||||||
PerspectiveMapWrapper.getTransforms(modelTransform);
|
|
||||||
|
ImmutableMap<TransformType, TransformationMatrix> transformMap =
|
||||||
|
PerspectiveMapWrapper.getTransforms(new ModelTransformComposition(transformsFromModel, modelTransform));
|
||||||
|
|
||||||
TextureAtlasSprite particleSprite = particleLocation != null ? spriteGetter.apply(particleLocation) : null;
|
TextureAtlasSprite particleSprite = particleLocation != null ? spriteGetter.apply(particleLocation) : null;
|
||||||
|
|
||||||
|
if (particleSprite == null) particleSprite = fluidSprite;
|
||||||
|
if (particleSprite == null && !coverIsMask) particleSprite = coverSprite;
|
||||||
|
|
||||||
// if the fluid is lighter than air, will manipulate the initial state to be rotated 180deg to turn it upside down
|
// if the fluid is lighter than air, will manipulate the initial state to be rotated 180deg to turn it upside down
|
||||||
if (flipGas && fluid != Fluids.EMPTY && fluid.getAttributes().isLighterThanAir())
|
if (flipGas && fluid != Fluids.EMPTY && fluid.getAttributes().isLighterThanAir())
|
||||||
{
|
{
|
||||||
modelTransform = new ModelTransformComposition(modelTransform, new SimpleModelTransform(new TransformationMatrix(null, new Quaternion(0, 0, 1, 0), null, null)));
|
modelTransform = new SimpleModelTransform(
|
||||||
|
modelTransform.getRotation().blockCornerToCenter().composeVanilla(
|
||||||
|
new TransformationMatrix(null, new Quaternion(0, 0, 1, 0), null, null)).blockCenterToCorner());
|
||||||
}
|
}
|
||||||
|
|
||||||
TransformationMatrix transform = modelTransform.getRotation();
|
TransformationMatrix transform = modelTransform.getRotation();
|
||||||
|
|
||||||
TextureAtlasSprite fluidSprite = fluid != Fluids.EMPTY ? spriteGetter.apply(ForgeHooksClient.getBlockMaterial(fluid.getAttributes().getStillTexture())) : null;
|
ItemMultiLayerBakedModel.Builder builder = ItemMultiLayerBakedModel.builder(owner, particleSprite, new ContainedFluidOverrideHandler(overrides, bakery, owner, this), transformMap);
|
||||||
|
|
||||||
if (particleSprite == null) particleSprite = fluidSprite;
|
|
||||||
|
|
||||||
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
|
|
||||||
|
|
||||||
if (baseLocation != null)
|
if (baseLocation != null)
|
||||||
{
|
{
|
||||||
// build base (insidest)
|
// build base (insidest)
|
||||||
builder.addAll(ItemLayerModel.getQuadsForSprites(ImmutableList.of(baseLocation), transform, spriteGetter));
|
builder.addQuads(ItemLayerModel.getLayerRenderType(false), ItemLayerModel.getQuadsForSprites(ImmutableList.of(baseLocation), transform, spriteGetter));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fluidMaskLocation != null && fluidSprite != null)
|
if (fluidMaskLocation != null && fluidSprite != null)
|
||||||
|
@ -156,36 +138,34 @@ public final class DynamicBucketModel implements IModelGeometry<DynamicBucketMod
|
||||||
if (templateSprite != null)
|
if (templateSprite != null)
|
||||||
{
|
{
|
||||||
// build liquid layer (inside)
|
// build liquid layer (inside)
|
||||||
builder.addAll(ItemTextureQuadConverter.convertTexture(transform, templateSprite, fluidSprite, NORTH_Z_FLUID, Direction.NORTH, tint ? fluid.getAttributes().getColor() : 0xFFFFFFFF, 1));
|
int luminosity = applyFluidLuminosity ? fluid.getAttributes().getLuminosity() : 0;
|
||||||
builder.addAll(ItemTextureQuadConverter.convertTexture(transform, templateSprite, fluidSprite, SOUTH_Z_FLUID, Direction.SOUTH, tint ? fluid.getAttributes().getColor() : 0xFFFFFFFF, 1));
|
int color = tint ? fluid.getAttributes().getColor() : 0xFFFFFFFF;
|
||||||
|
builder.addQuads(ItemLayerModel.getLayerRenderType(luminosity > 0), ItemTextureQuadConverter.convertTexture(transform, templateSprite, fluidSprite, NORTH_Z_FLUID, Direction.NORTH, color, 1, luminosity));
|
||||||
|
builder.addQuads(ItemLayerModel.getLayerRenderType(luminosity > 0), ItemTextureQuadConverter.convertTexture(transform, templateSprite, fluidSprite, SOUTH_Z_FLUID, Direction.SOUTH, color, 1, luminosity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coverLocation != null && (!coverIsMask || baseLocation != null))
|
if (coverIsMask)
|
||||||
|
{
|
||||||
|
if (coverSprite != null && baseLocation != null)
|
||||||
|
{
|
||||||
|
TextureAtlasSprite baseSprite = spriteGetter.apply(baseLocation);
|
||||||
|
builder.addQuads(ItemLayerModel.getLayerRenderType(false), ItemTextureQuadConverter.convertTexture(transform, coverSprite, baseSprite, NORTH_Z_COVER, Direction.NORTH, 0xFFFFFFFF, 2));
|
||||||
|
builder.addQuads(ItemLayerModel.getLayerRenderType(false), ItemTextureQuadConverter.convertTexture(transform, coverSprite, baseSprite, SOUTH_Z_COVER, Direction.SOUTH, 0xFFFFFFFF, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// cover (the actual item around the other two)
|
|
||||||
TextureAtlasSprite coverSprite = spriteGetter.apply(coverLocation);
|
|
||||||
if (coverSprite != null)
|
if (coverSprite != null)
|
||||||
{
|
{
|
||||||
if (coverIsMask)
|
builder.addQuads(ItemLayerModel.getLayerRenderType(false), ItemTextureQuadConverter.genQuad(transform, 0, 0, 16, 16, NORTH_Z_COVER, coverSprite, Direction.NORTH, 0xFFFFFFFF, 2));
|
||||||
{
|
builder.addQuads(ItemLayerModel.getLayerRenderType(false), ItemTextureQuadConverter.genQuad(transform, 0, 0, 16, 16, SOUTH_Z_COVER, coverSprite, Direction.SOUTH, 0xFFFFFFFF, 2));
|
||||||
TextureAtlasSprite baseSprite = spriteGetter.apply(baseLocation);
|
|
||||||
builder.addAll(ItemTextureQuadConverter.convertTexture(transform, coverSprite, baseSprite, NORTH_Z_COVER, Direction.NORTH, 0xFFFFFFFF, 1));
|
|
||||||
builder.addAll(ItemTextureQuadConverter.convertTexture(transform, coverSprite, baseSprite, SOUTH_Z_COVER, Direction.SOUTH, 0xFFFFFFFF, 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
builder.add(ItemTextureQuadConverter.genQuad(transform, 0, 0, 16, 16, NORTH_Z_COVER, coverSprite, Direction.NORTH, 0xFFFFFFFF, 2));
|
|
||||||
builder.add(ItemTextureQuadConverter.genQuad(transform, 0, 0, 16, 16, SOUTH_Z_COVER, coverSprite, Direction.SOUTH, 0xFFFFFFFF, 2));
|
|
||||||
if (particleSprite == null)
|
|
||||||
{
|
|
||||||
particleSprite = coverSprite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BakedModel(bakery, owner, this, builder.build(), particleSprite, Maps.immutableEnumMap(transformMap), Maps.newHashMap(), transform.isIdentity(), modelTransform, owner.isSideLit());
|
builder.setParticle(particleSprite);
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -193,10 +173,10 @@ public final class DynamicBucketModel implements IModelGeometry<DynamicBucketMod
|
||||||
{
|
{
|
||||||
Set<RenderMaterial> texs = Sets.newHashSet();
|
Set<RenderMaterial> texs = Sets.newHashSet();
|
||||||
|
|
||||||
texs.add(owner.resolveTexture("particle"));
|
if (owner.isTexturePresent("particle")) texs.add(owner.resolveTexture("particle"));
|
||||||
texs.add(owner.resolveTexture("base"));
|
if (owner.isTexturePresent("base")) texs.add(owner.resolveTexture("base"));
|
||||||
texs.add(owner.resolveTexture("fluid"));
|
if (owner.isTexturePresent("fluid")) texs.add(owner.resolveTexture("fluid"));
|
||||||
texs.add(owner.resolveTexture("cover"));
|
if (owner.isTexturePresent("cover")) texs.add(owner.resolveTexture("cover"));
|
||||||
|
|
||||||
return texs;
|
return texs;
|
||||||
}
|
}
|
||||||
|
@ -251,70 +231,55 @@ public final class DynamicBucketModel implements IModelGeometry<DynamicBucketMod
|
||||||
coverIsMask = modelContents.get("coverIsMask").getAsBoolean();
|
coverIsMask = modelContents.get("coverIsMask").getAsBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean applyFluidLuminosity = true;
|
||||||
|
if (modelContents.has("applyFluidLuminosity"))
|
||||||
|
{
|
||||||
|
applyFluidLuminosity = modelContents.get("applyFluidLuminosity").getAsBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
// create new model with correct liquid
|
// create new model with correct liquid
|
||||||
return new DynamicBucketModel(fluid, flip, tint, coverIsMask);
|
return new DynamicBucketModel(fluid, flip, tint, coverIsMask, applyFluidLuminosity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class ContainedFluidOverrideHandler extends ItemOverrideList
|
private static final class ContainedFluidOverrideHandler extends ItemOverrideList
|
||||||
{
|
{
|
||||||
|
private final Map<String, IBakedModel> cache = Maps.newHashMap(); // contains all the baked models since they'll never change
|
||||||
|
private final ItemOverrideList nested;
|
||||||
private final ModelBakery bakery;
|
private final ModelBakery bakery;
|
||||||
|
private final IModelConfiguration owner;
|
||||||
private ContainedFluidOverrideHandler(ModelBakery bakery)
|
private final DynamicBucketModel parent;
|
||||||
|
|
||||||
|
private ContainedFluidOverrideHandler(ItemOverrideList nested, ModelBakery bakery, IModelConfiguration owner, DynamicBucketModel parent)
|
||||||
{
|
{
|
||||||
|
this.nested = nested;
|
||||||
this.bakery = bakery;
|
this.bakery = bakery;
|
||||||
|
this.owner = owner;
|
||||||
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBakedModel func_239290_a_(IBakedModel originalModel, ItemStack stack, @Nullable ClientWorld world, @Nullable LivingEntity entity)
|
public IBakedModel func_239290_a_(IBakedModel originalModel, ItemStack stack, @Nullable ClientWorld world, @Nullable LivingEntity entity)
|
||||||
{
|
{
|
||||||
|
IBakedModel overriden = nested.func_239290_a_(originalModel, stack, world, entity);
|
||||||
|
if (overriden != originalModel) return overriden;
|
||||||
return FluidUtil.getFluidContained(stack)
|
return FluidUtil.getFluidContained(stack)
|
||||||
.map(fluidStack -> {
|
.map(fluidStack -> {
|
||||||
BakedModel model = (BakedModel)originalModel;
|
|
||||||
|
|
||||||
Fluid fluid = fluidStack.getFluid();
|
Fluid fluid = fluidStack.getFluid();
|
||||||
String name = fluid.getRegistryName().toString();
|
String name = fluid.getRegistryName().toString();
|
||||||
|
|
||||||
if (!model.cache.containsKey(name))
|
if (!cache.containsKey(name))
|
||||||
{
|
{
|
||||||
DynamicBucketModel parent = model.parent.withFluid(fluid);
|
DynamicBucketModel unbaked = this.parent.withFluid(fluid);
|
||||||
IBakedModel bakedModel = parent.bake(model.owner, bakery, ModelLoader.defaultTextureGetter(), model.originalTransform, model.getOverrides(), new ResourceLocation("forge:bucket_override"));
|
IBakedModel bakedModel = unbaked.bake(owner, bakery, ModelLoader.defaultTextureGetter(), ModelRotation.X0_Y0, this, new ResourceLocation("forge:bucket_override"));
|
||||||
model.cache.put(name, bakedModel);
|
cache.put(name, bakedModel);
|
||||||
return bakedModel;
|
return bakedModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
return model.cache.get(name);
|
return cache.get(name);
|
||||||
})
|
})
|
||||||
// not a fluid item apparently
|
// not a fluid item apparently
|
||||||
.orElse(originalModel); // empty bucket
|
.orElse(originalModel); // empty bucket
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the dynamic bucket is based on the empty bucket
|
|
||||||
private static final class BakedModel extends BakedItemModel
|
|
||||||
{
|
|
||||||
private final IModelConfiguration owner;
|
|
||||||
private final DynamicBucketModel parent;
|
|
||||||
private final Map<String, IBakedModel> cache; // contains all the baked models since they'll never change
|
|
||||||
private final IModelTransform originalTransform;
|
|
||||||
private final boolean isSideLit;
|
|
||||||
|
|
||||||
BakedModel(ModelBakery bakery,
|
|
||||||
IModelConfiguration owner, DynamicBucketModel parent,
|
|
||||||
ImmutableList<BakedQuad> quads,
|
|
||||||
TextureAtlasSprite particle,
|
|
||||||
ImmutableMap<TransformType, TransformationMatrix> transforms,
|
|
||||||
Map<String, IBakedModel> cache,
|
|
||||||
boolean untransformed,
|
|
||||||
IModelTransform originalTransform, boolean isSideLit)
|
|
||||||
{
|
|
||||||
super(quads, particle, transforms, new ContainedFluidOverrideHandler(bakery), untransformed, isSideLit);
|
|
||||||
this.owner = owner;
|
|
||||||
this.parent = parent;
|
|
||||||
this.cache = cache;
|
|
||||||
this.originalTransform = originalTransform;
|
|
||||||
this.isSideLit = isSideLit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
|
// TODO: Write a model loader and test/fix as needed
|
||||||
public final class FluidModel implements IModelGeometry<FluidModel>
|
public final class FluidModel implements IModelGeometry<FluidModel>
|
||||||
{
|
{
|
||||||
public static final FluidModel WATER = new FluidModel(Fluids.WATER);
|
public static final FluidModel WATER = new FluidModel(Fluids.WATER);
|
||||||
|
|
|
@ -76,7 +76,6 @@ public interface IModelConfiguration {
|
||||||
* Gets the vanilla camera transforms data.
|
* Gets the vanilla camera transforms data.
|
||||||
* Do not use for non-vanilla code. For general usage, prefer getCombinedState.
|
* Do not use for non-vanilla code. For general usage, prefer getCombinedState.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
ItemCameraTransforms getCameraTransforms();
|
ItemCameraTransforms getCameraTransforms();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,18 +19,13 @@
|
||||||
|
|
||||||
package net.minecraftforge.client.model;
|
package net.minecraftforge.client.model;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.*;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.util.math.vector.TransformationMatrix;
|
|
||||||
import net.minecraft.client.renderer.model.*;
|
import net.minecraft.client.renderer.model.*;
|
||||||
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
|
||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||||
import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
||||||
|
@ -38,6 +33,8 @@ import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.JSONUtils;
|
import net.minecraft.util.JSONUtils;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.math.vector.TransformationMatrix;
|
||||||
|
import net.minecraftforge.client.ForgeRenderTypes;
|
||||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||||
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||||
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
|
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
|
||||||
|
@ -55,7 +52,6 @@ import java.util.function.Function;
|
||||||
* - Various fixes in the baking logic.
|
* - Various fixes in the baking logic.
|
||||||
* - Not limited to 4 layers maximum.
|
* - Not limited to 4 layers maximum.
|
||||||
*/
|
*/
|
||||||
// TODO: Implement as new model loader
|
|
||||||
public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
||||||
{
|
{
|
||||||
public static final ItemLayerModel INSTANCE = new ItemLayerModel(ImmutableList.of());
|
public static final ItemLayerModel INSTANCE = new ItemLayerModel(ImmutableList.of());
|
||||||
|
@ -93,16 +89,31 @@ public final class ItemLayerModel implements IModelGeometry<ItemLayerModel>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<RenderMaterial, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation)
|
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
|
||||||
|
Function<RenderMaterial, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
|
||||||
|
ItemOverrideList overrides, ResourceLocation modelLocation)
|
||||||
{
|
{
|
||||||
//TODO: Verify
|
ImmutableMap<ItemCameraTransforms.TransformType, TransformationMatrix> transformMap =
|
||||||
|
PerspectiveMapWrapper.getTransforms(new ModelTransformComposition(owner.getCombinedTransform(), modelTransform));
|
||||||
TransformationMatrix transform = modelTransform.getRotation();
|
TransformationMatrix transform = modelTransform.getRotation();
|
||||||
ImmutableList<BakedQuad> quads = getQuadsForSprites(textures, transform, spriteGetter, fullbrightLayers);
|
|
||||||
TextureAtlasSprite particle = spriteGetter.apply(
|
TextureAtlasSprite particle = spriteGetter.apply(
|
||||||
owner.isTexturePresent("particle") ? owner.resolveTexture("particle") : textures.get(0)
|
owner.isTexturePresent("particle") ? owner.resolveTexture("particle") : textures.get(0)
|
||||||
);
|
);
|
||||||
ImmutableMap<TransformType, TransformationMatrix> map = PerspectiveMapWrapper.getTransforms(modelTransform);
|
|
||||||
return new BakedItemModel(quads, particle, map, overrides, transform.isIdentity(), owner.isSideLit());
|
ItemMultiLayerBakedModel.Builder builder = ItemMultiLayerBakedModel.builder(owner, particle, overrides, transformMap);
|
||||||
|
for(int i = 0; i < textures.size(); i++)
|
||||||
|
{
|
||||||
|
TextureAtlasSprite tas = spriteGetter.apply(textures.get(i));
|
||||||
|
RenderType rt = getLayerRenderType(fullbrightLayers.contains(i));
|
||||||
|
builder.addQuads(rt, getQuadsForSprite(i, tas, transform, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RenderType getLayerRenderType(boolean isFullbright)
|
||||||
|
{
|
||||||
|
return isFullbright ? ForgeRenderTypes.ITEM_UNSORTED_UNLIT_TRANSLUCENT.get() : ForgeRenderTypes.ITEM_UNSORTED_TRANSLUCENT.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImmutableList<BakedQuad> getQuadsForSprites(List<RenderMaterial> textures, TransformationMatrix transform, Function<RenderMaterial, TextureAtlasSprite> spriteGetter)
|
public static ImmutableList<BakedQuad> getQuadsForSprites(List<RenderMaterial> textures, TransformationMatrix transform, Function<RenderMaterial, TextureAtlasSprite> spriteGetter)
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
/*
|
||||||
|
* Minecraft Forge
|
||||||
|
* Copyright (c) 2016-2020.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation version 2.1
|
||||||
|
* of the License.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.minecraftforge.client.model;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.client.renderer.model.BakedQuad;
|
||||||
|
import net.minecraft.client.renderer.model.IBakedModel;
|
||||||
|
import net.minecraft.client.renderer.model.ItemCameraTransforms;
|
||||||
|
import net.minecraft.client.renderer.model.ItemOverrideList;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.vector.TransformationMatrix;
|
||||||
|
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class ItemMultiLayerBakedModel implements IBakedModel
|
||||||
|
{
|
||||||
|
private final boolean smoothLighting;
|
||||||
|
private final boolean shadedInGui;
|
||||||
|
private final boolean sideLit;
|
||||||
|
private final TextureAtlasSprite particle;
|
||||||
|
private final ItemOverrideList overrides;
|
||||||
|
private final ImmutableList<Pair<IBakedModel, RenderType>> layerModels;
|
||||||
|
private final ImmutableMap<ItemCameraTransforms.TransformType, TransformationMatrix> cameraTransforms;
|
||||||
|
|
||||||
|
public ItemMultiLayerBakedModel(boolean smoothLighting, boolean shadedInGui, boolean sideLit,
|
||||||
|
TextureAtlasSprite particle, ItemOverrideList overrides,
|
||||||
|
ImmutableMap<ItemCameraTransforms.TransformType, TransformationMatrix> cameraTransforms,
|
||||||
|
ImmutableList<Pair<IBakedModel, RenderType>> layerModels)
|
||||||
|
{
|
||||||
|
this.smoothLighting = smoothLighting;
|
||||||
|
this.shadedInGui = shadedInGui;
|
||||||
|
this.sideLit = sideLit;
|
||||||
|
this.particle = particle;
|
||||||
|
this.overrides = overrides;
|
||||||
|
this.layerModels = layerModels;
|
||||||
|
this.cameraTransforms = cameraTransforms;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand)
|
||||||
|
{
|
||||||
|
List<BakedQuad> quads = Lists.newArrayList();
|
||||||
|
layerModels.forEach(lm -> quads.addAll(lm.getFirst().getQuads(state, side, rand, EmptyModelData.INSTANCE)));
|
||||||
|
return quads;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAmbientOcclusion()
|
||||||
|
{
|
||||||
|
return smoothLighting;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGui3d()
|
||||||
|
{
|
||||||
|
return shadedInGui;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean func_230044_c_()
|
||||||
|
{
|
||||||
|
return sideLit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBuiltInRenderer()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TextureAtlasSprite getParticleTexture()
|
||||||
|
{
|
||||||
|
return particle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemOverrideList getOverrides()
|
||||||
|
{
|
||||||
|
return overrides;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doesHandlePerspectives()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBakedModel handlePerspective(ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat)
|
||||||
|
{
|
||||||
|
return PerspectiveMapWrapper.handlePerspective(this, cameraTransforms, cameraTransformType, mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
//@Override
|
||||||
|
public boolean isLayered()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//@Override
|
||||||
|
public List<Pair<IBakedModel, RenderType>> getLayerModels(ItemStack itemStack, boolean fabulous)
|
||||||
|
{
|
||||||
|
return layerModels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder(IModelConfiguration owner, TextureAtlasSprite particle, ItemOverrideList overrides,
|
||||||
|
ImmutableMap<ItemCameraTransforms.TransformType, TransformationMatrix> cameraTransforms)
|
||||||
|
{
|
||||||
|
return new Builder(owner, particle, overrides, cameraTransforms);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder
|
||||||
|
{
|
||||||
|
private final ImmutableList.Builder<Pair<IBakedModel, RenderType>> builder = ImmutableList.builder();
|
||||||
|
private final List<BakedQuad> quads = Lists.newArrayList();
|
||||||
|
private final ItemOverrideList overrides;
|
||||||
|
private final ImmutableMap<ItemCameraTransforms.TransformType, TransformationMatrix> cameraTransforms;
|
||||||
|
private final IModelConfiguration owner;
|
||||||
|
private TextureAtlasSprite particle;
|
||||||
|
private RenderType lastRt = null;
|
||||||
|
|
||||||
|
private Builder(IModelConfiguration owner, TextureAtlasSprite particle, ItemOverrideList overrides,
|
||||||
|
ImmutableMap<ItemCameraTransforms.TransformType, TransformationMatrix> cameraTransforms)
|
||||||
|
{
|
||||||
|
this.owner = owner;
|
||||||
|
this.particle = particle;
|
||||||
|
this.overrides = overrides;
|
||||||
|
this.cameraTransforms = cameraTransforms;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addLayer(ImmutableList.Builder<Pair<IBakedModel, RenderType>> builder, List<BakedQuad> quads, RenderType rt)
|
||||||
|
{
|
||||||
|
IBakedModel model = new BakedItemModel(ImmutableList.copyOf(quads), particle, ImmutableMap.of(), ItemOverrideList.EMPTY, true, owner.isSideLit());
|
||||||
|
builder.add(Pair.of(model, rt));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flushQuads(RenderType rt)
|
||||||
|
{
|
||||||
|
if (rt != lastRt)
|
||||||
|
{
|
||||||
|
if (quads.size() > 0)
|
||||||
|
{
|
||||||
|
addLayer(builder, quads, lastRt);
|
||||||
|
quads.clear();
|
||||||
|
}
|
||||||
|
lastRt = rt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setParticle(TextureAtlasSprite particleSprite)
|
||||||
|
{
|
||||||
|
this.particle = particleSprite;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addQuads(RenderType rt, BakedQuad... quadsToAdd)
|
||||||
|
{
|
||||||
|
flushQuads(rt);
|
||||||
|
Collections.addAll(quads, quadsToAdd);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addQuads(RenderType rt, Collection<BakedQuad> quadsToAdd)
|
||||||
|
{
|
||||||
|
flushQuads(rt);
|
||||||
|
quads.addAll(quadsToAdd);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBakedModel build()
|
||||||
|
{
|
||||||
|
if (quads.size() > 0)
|
||||||
|
{
|
||||||
|
addLayer(builder, quads, lastRt);
|
||||||
|
}
|
||||||
|
return new ItemMultiLayerBakedModel(owner.useSmoothLighting(), owner.isShadedInGui(), owner.isSideLit(),
|
||||||
|
particle, overrides, cameraTransforms, builder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,11 +21,12 @@ package net.minecraftforge.client.model;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import net.minecraft.util.math.vector.TransformationMatrix;
|
|
||||||
import net.minecraft.client.renderer.model.BakedQuad;
|
import net.minecraft.client.renderer.model.BakedQuad;
|
||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||||
|
import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.vector.TransformationMatrix;
|
||||||
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||||
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
|
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
|
||||||
import net.minecraftforge.client.model.pipeline.TRSRTransformer;
|
import net.minecraftforge.client.model.pipeline.TRSRTransformer;
|
||||||
|
@ -47,15 +48,18 @@ public final class ItemTextureQuadConverter
|
||||||
* The resulting list of quads is the texture represented as a list of horizontal OR vertical quads,
|
* The resulting list of quads is the texture represented as a list of horizontal OR vertical quads,
|
||||||
* depending on which creates less quads. If the amount of quads is equal, horizontal is preferred.
|
* depending on which creates less quads. If the amount of quads is equal, horizontal is preferred.
|
||||||
*
|
*
|
||||||
* @param format
|
|
||||||
* @param template The input texture to convert
|
* @param template The input texture to convert
|
||||||
* @param sprite The texture whose UVs shall be used
|
* @param sprite The texture whose UVs shall be used
|
||||||
* @return The generated quads.
|
* @return The generated quads.
|
||||||
*/
|
*/
|
||||||
public static List<BakedQuad> convertTexture(TransformationMatrix transform, TextureAtlasSprite template, TextureAtlasSprite sprite, float z, Direction facing, int color, int tint)
|
public static List<BakedQuad> convertTexture(TransformationMatrix transform, TextureAtlasSprite template, TextureAtlasSprite sprite, float z, Direction facing, int color, int tint)
|
||||||
{
|
{
|
||||||
List<BakedQuad> horizontal = convertTextureHorizontal(transform, template, sprite, z, facing, color, tint);
|
return convertTexture(transform, template, sprite, z, facing, color, tint, 0);
|
||||||
List<BakedQuad> vertical = convertTextureVertical(transform, template, sprite, z, facing, color, tint);
|
}
|
||||||
|
public static List<BakedQuad> convertTexture(TransformationMatrix transform, TextureAtlasSprite template, TextureAtlasSprite sprite, float z, Direction facing, int color, int tint, int luminosity)
|
||||||
|
{
|
||||||
|
List<BakedQuad> horizontal = convertTextureHorizontal(transform, template, sprite, z, facing, color, tint, luminosity);
|
||||||
|
List<BakedQuad> vertical = convertTextureVertical(transform, template, sprite, z, facing, color, tint, luminosity);
|
||||||
|
|
||||||
return horizontal.size() <= vertical.size() ? horizontal : vertical;
|
return horizontal.size() <= vertical.size() ? horizontal : vertical;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +69,10 @@ public final class ItemTextureQuadConverter
|
||||||
* The height of the strips is as big as possible.
|
* The height of the strips is as big as possible.
|
||||||
*/
|
*/
|
||||||
public static List<BakedQuad> convertTextureHorizontal(TransformationMatrix transform, TextureAtlasSprite template, TextureAtlasSprite sprite, float z, Direction facing, int color, int tint)
|
public static List<BakedQuad> convertTextureHorizontal(TransformationMatrix transform, TextureAtlasSprite template, TextureAtlasSprite sprite, float z, Direction facing, int color, int tint)
|
||||||
|
{
|
||||||
|
return convertTextureHorizontal(transform, template, sprite, z, facing, color, tint, 0);
|
||||||
|
}
|
||||||
|
public static List<BakedQuad> convertTextureHorizontal(TransformationMatrix transform, TextureAtlasSprite template, TextureAtlasSprite sprite, float z, Direction facing, int color, int tint, int luminosity)
|
||||||
{
|
{
|
||||||
int w = template.getWidth();
|
int w = template.getWidth();
|
||||||
int h = template.getHeight();
|
int h = template.getHeight();
|
||||||
|
@ -115,7 +123,7 @@ public final class ItemTextureQuadConverter
|
||||||
(float)y * hScale,
|
(float)y * hScale,
|
||||||
(float)x * wScale,
|
(float)x * wScale,
|
||||||
(float)endY * hScale,
|
(float)endY * hScale,
|
||||||
z, sprite, facing, color, tint));
|
z, sprite, facing, color, tint, luminosity));
|
||||||
|
|
||||||
// update Y if all the rows match. no need to rescan
|
// update Y if all the rows match. no need to rescan
|
||||||
if (endY - y > 1)
|
if (endY - y > 1)
|
||||||
|
@ -136,6 +144,10 @@ public final class ItemTextureQuadConverter
|
||||||
* The width of the strips is as big as possible.
|
* The width of the strips is as big as possible.
|
||||||
*/
|
*/
|
||||||
public static List<BakedQuad> convertTextureVertical(TransformationMatrix transform, TextureAtlasSprite template, TextureAtlasSprite sprite, float z, Direction facing, int color, int tint)
|
public static List<BakedQuad> convertTextureVertical(TransformationMatrix transform, TextureAtlasSprite template, TextureAtlasSprite sprite, float z, Direction facing, int color, int tint)
|
||||||
|
{
|
||||||
|
return convertTextureVertical(transform, template, sprite, z, facing, color, tint, 0);
|
||||||
|
}
|
||||||
|
public static List<BakedQuad> convertTextureVertical(TransformationMatrix transform, TextureAtlasSprite template, TextureAtlasSprite sprite, float z, Direction facing, int color, int tint, int luminosity)
|
||||||
{
|
{
|
||||||
int w = template.getWidth();
|
int w = template.getWidth();
|
||||||
int h = template.getHeight();
|
int h = template.getHeight();
|
||||||
|
@ -186,7 +198,7 @@ public final class ItemTextureQuadConverter
|
||||||
(float)start * hScale,
|
(float)start * hScale,
|
||||||
(float)endX * wScale,
|
(float)endX * wScale,
|
||||||
(float)y * hScale,
|
(float)y * hScale,
|
||||||
z, sprite, facing, color, tint));
|
z, sprite, facing, color, tint, luminosity));
|
||||||
|
|
||||||
// update X if all the columns match. no need to rescan
|
// update X if all the columns match. no need to rescan
|
||||||
if (endX - x > 1)
|
if (endX - x > 1)
|
||||||
|
@ -212,6 +224,10 @@ public final class ItemTextureQuadConverter
|
||||||
* Coordinates are [0,16] to match the usual coordinates used in TextureAtlasSprites
|
* Coordinates are [0,16] to match the usual coordinates used in TextureAtlasSprites
|
||||||
*/
|
*/
|
||||||
public static BakedQuad genQuad(TransformationMatrix transform, float x1, float y1, float x2, float y2, float z, TextureAtlasSprite sprite, Direction facing, int color, int tint)
|
public static BakedQuad genQuad(TransformationMatrix transform, float x1, float y1, float x2, float y2, float z, TextureAtlasSprite sprite, Direction facing, int color, int tint)
|
||||||
|
{
|
||||||
|
return genQuad(transform, x1, y1, x2, y2, z, sprite, facing, color, tint, 0);
|
||||||
|
}
|
||||||
|
public static BakedQuad genQuad(TransformationMatrix transform, float x1, float y1, float x2, float y2, float z, TextureAtlasSprite sprite, Direction facing, int color, int tint, int luminosity)
|
||||||
{
|
{
|
||||||
float u1 = sprite.getInterpolatedU(x1);
|
float u1 = sprite.getInterpolatedU(x1);
|
||||||
float v1 = sprite.getInterpolatedV(y1);
|
float v1 = sprite.getInterpolatedV(y1);
|
||||||
|
@ -227,17 +243,18 @@ public final class ItemTextureQuadConverter
|
||||||
y1 = 1f - y2;
|
y1 = 1f - y2;
|
||||||
y2 = 1f - tmp;
|
y2 = 1f - tmp;
|
||||||
|
|
||||||
return putQuad(transform, facing, sprite, color, tint, x1, y1, x2, y2, z, u1, v1, u2, v2);
|
return putQuad(transform, facing, sprite, color, tint, x1, y1, x2, y2, z, u1, v1, u2, v2, luminosity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BakedQuad putQuad(TransformationMatrix transform, Direction side, TextureAtlasSprite sprite, int color, int tint,
|
private static BakedQuad putQuad(TransformationMatrix transform, Direction side, TextureAtlasSprite sprite, int color, int tint,
|
||||||
float x1, float y1, float x2, float y2, float z,
|
float x1, float y1, float x2, float y2, float z,
|
||||||
float u1, float v1, float u2, float v2)
|
float u1, float v1, float u2, float v2, int luminosity)
|
||||||
{
|
{
|
||||||
BakedQuadBuilder builder = new BakedQuadBuilder(sprite);
|
BakedQuadBuilder builder = new BakedQuadBuilder(sprite);
|
||||||
|
|
||||||
builder.setQuadTint(tint);
|
builder.setQuadTint(tint);
|
||||||
builder.setQuadOrientation(side);
|
builder.setQuadOrientation(side);
|
||||||
|
builder.setApplyDiffuseLighting(luminosity == 0);
|
||||||
|
|
||||||
// only apply the transform if it's not identity
|
// only apply the transform if it's not identity
|
||||||
boolean hasTransform = !transform.isIdentity();
|
boolean hasTransform = !transform.isIdentity();
|
||||||
|
@ -245,28 +262,29 @@ public final class ItemTextureQuadConverter
|
||||||
|
|
||||||
if (side == Direction.SOUTH)
|
if (side == Direction.SOUTH)
|
||||||
{
|
{
|
||||||
putVertex(consumer, side, x1, y1, z, u1, v2, color);
|
putVertex(consumer, side, x1, y1, z, u1, v2, color, luminosity);
|
||||||
putVertex(consumer, side, x2, y1, z, u2, v2, color);
|
putVertex(consumer, side, x2, y1, z, u2, v2, color, luminosity);
|
||||||
putVertex(consumer, side, x2, y2, z, u2, v1, color);
|
putVertex(consumer, side, x2, y2, z, u2, v1, color, luminosity);
|
||||||
putVertex(consumer, side, x1, y2, z, u1, v1, color);
|
putVertex(consumer, side, x1, y2, z, u1, v1, color, luminosity);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
putVertex(consumer, side, x1, y1, z, u1, v2, color);
|
putVertex(consumer, side, x1, y1, z, u1, v2, color, luminosity);
|
||||||
putVertex(consumer, side, x1, y2, z, u1, v1, color);
|
putVertex(consumer, side, x1, y2, z, u1, v1, color, luminosity);
|
||||||
putVertex(consumer, side, x2, y2, z, u2, v1, color);
|
putVertex(consumer, side, x2, y2, z, u2, v1, color, luminosity);
|
||||||
putVertex(consumer, side, x2, y1, z, u2, v2, color);
|
putVertex(consumer, side, x2, y1, z, u2, v2, color, luminosity);
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void putVertex(IVertexConsumer consumer, Direction side,
|
private static void putVertex(IVertexConsumer consumer, Direction side,
|
||||||
float x, float y, float z, float u, float v, int color)
|
float x, float y, float z, float u, float v, int color, int luminosity)
|
||||||
{
|
{
|
||||||
VertexFormat format = consumer.getVertexFormat();
|
VertexFormat format = consumer.getVertexFormat();
|
||||||
for (int e = 0; e < format.getElements().size(); e++)
|
for (int e = 0; e < format.getElements().size(); e++)
|
||||||
{
|
{
|
||||||
switch (format.getElements().get(e).getUsage())
|
VertexFormatElement element = format.getElements().get(e);
|
||||||
|
switch (element.getUsage())
|
||||||
{
|
{
|
||||||
case POSITION:
|
case POSITION:
|
||||||
consumer.put(e, x, y, z, 1f);
|
consumer.put(e, x, y, z, 1f);
|
||||||
|
@ -285,11 +303,16 @@ public final class ItemTextureQuadConverter
|
||||||
consumer.put(e, offX, offY, offZ, 0f);
|
consumer.put(e, offX, offY, offZ, 0f);
|
||||||
break;
|
break;
|
||||||
case UV:
|
case UV:
|
||||||
if (format.getElements().get(e).getIndex() == 0)
|
if (element.getIndex() == 0)
|
||||||
{
|
{
|
||||||
consumer.put(e, u, v, 0f, 1f);
|
consumer.put(e, u, v, 0f, 1f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (element.getIndex() == 2)
|
||||||
|
{
|
||||||
|
consumer.put(e, (luminosity<<4)/32768.0f, (luminosity<<4)/32768.0f, 0f, 1f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
// else fallthrough to default
|
// else fallthrough to default
|
||||||
default:
|
default:
|
||||||
consumer.put(e);
|
consumer.put(e);
|
||||||
|
|
|
@ -24,7 +24,7 @@ import java.util.*;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.*;
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
@ -34,11 +34,14 @@ import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.util.math.vector.TransformationMatrix;
|
import net.minecraft.util.math.vector.TransformationMatrix;
|
||||||
import net.minecraft.client.renderer.model.*;
|
import net.minecraft.client.renderer.model.*;
|
||||||
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
|
||||||
|
import net.minecraft.client.renderer.texture.AtlasTexture;
|
||||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.resources.IResourceManager;
|
import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.JSONUtils;
|
import net.minecraft.util.JSONUtils;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.client.ForgeRenderTypes;
|
||||||
import net.minecraftforge.client.MinecraftForgeClient;
|
import net.minecraftforge.client.MinecraftForgeClient;
|
||||||
|
|
||||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||||
|
@ -48,9 +51,7 @@ import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A model that can be rendered in multiple {@link RenderType}.
|
* A model that can be rendered in multiple {@link RenderType}.
|
||||||
|
@ -92,11 +93,12 @@ public final class MultiLayerModel implements IModelGeometry<MultiLayerModel>
|
||||||
IUnbakedModel missing = ModelLoader.instance().getMissingModel();
|
IUnbakedModel missing = ModelLoader.instance().getMissingModel();
|
||||||
|
|
||||||
return new MultiLayerBakedModel(
|
return new MultiLayerBakedModel(
|
||||||
owner.useSmoothLighting(), owner.isShadedInGui(),
|
owner.useSmoothLighting(), owner.isShadedInGui(), owner.isSideLit(),
|
||||||
owner.isSideLit(), spriteGetter.apply(owner.resolveTexture("particle")), overrides,
|
spriteGetter.apply(owner.resolveTexture("particle")), overrides, true,
|
||||||
buildModels(models, modelTransform, bakery, spriteGetter, modelLocation),
|
|
||||||
missing.bakeModel(bakery, spriteGetter, modelTransform, modelLocation),
|
missing.bakeModel(bakery, spriteGetter, modelTransform, modelLocation),
|
||||||
PerspectiveMapWrapper.getTransforms(new ModelTransformComposition(owner.getCombinedTransform(), modelTransform)));
|
buildModels(models, modelTransform, bakery, spriteGetter, modelLocation),
|
||||||
|
PerspectiveMapWrapper.getTransforms(new ModelTransformComposition(owner.getCombinedTransform(), modelTransform))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class MultiLayerBakedModel implements IBakedModel
|
private static final class MultiLayerBakedModel implements IBakedModel
|
||||||
|
@ -109,10 +111,13 @@ public final class MultiLayerModel implements IModelGeometry<MultiLayerModel>
|
||||||
protected final TextureAtlasSprite particle;
|
protected final TextureAtlasSprite particle;
|
||||||
protected final ItemOverrideList overrides;
|
protected final ItemOverrideList overrides;
|
||||||
private final IBakedModel missing;
|
private final IBakedModel missing;
|
||||||
|
private final boolean convertRenderTypes;
|
||||||
|
private final List<Pair<IBakedModel, RenderType>> itemLayers;
|
||||||
|
|
||||||
public MultiLayerBakedModel(
|
public MultiLayerBakedModel(
|
||||||
boolean ambientOcclusion, boolean isGui3d, boolean isSideLit, TextureAtlasSprite particle, ItemOverrideList overrides,
|
boolean ambientOcclusion, boolean isGui3d, boolean isSideLit, TextureAtlasSprite particle, ItemOverrideList overrides,
|
||||||
ImmutableMap<RenderType, IBakedModel> models, IBakedModel missing, ImmutableMap<TransformType, TransformationMatrix> cameraTransforms)
|
boolean convertRenderTypes, IBakedModel missing, ImmutableMap<RenderType, IBakedModel> models,
|
||||||
|
ImmutableMap<TransformType, TransformationMatrix> cameraTransforms)
|
||||||
{
|
{
|
||||||
this.isSideLit = isSideLit;
|
this.isSideLit = isSideLit;
|
||||||
this.models = models;
|
this.models = models;
|
||||||
|
@ -122,6 +127,12 @@ public final class MultiLayerModel implements IModelGeometry<MultiLayerModel>
|
||||||
this.gui3d = isGui3d;
|
this.gui3d = isGui3d;
|
||||||
this.particle = particle;
|
this.particle = particle;
|
||||||
this.overrides = overrides;
|
this.overrides = overrides;
|
||||||
|
this.convertRenderTypes = convertRenderTypes;
|
||||||
|
this.itemLayers = models.entrySet().stream().map(kv -> {
|
||||||
|
RenderType rt = kv.getKey();
|
||||||
|
if (convertRenderTypes) rt = ITEM_RENDER_TYPE_MAPPING.getOrDefault(rt, rt);
|
||||||
|
return Pair.of(kv.getValue(), rt);
|
||||||
|
}).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -144,6 +155,9 @@ public final class MultiLayerModel implements IModelGeometry<MultiLayerModel>
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
// support for item layer rendering
|
||||||
|
if (state == null && convertRenderTypes)
|
||||||
|
layer = ITEM_RENDER_TYPE_MAPPING.inverse().getOrDefault(layer, layer);
|
||||||
// assumes that child model will handle this state properly. FIXME?
|
// assumes that child model will handle this state properly. FIXME?
|
||||||
return models.getOrDefault(layer, missing).getQuads(state, side, rand, extraData);
|
return models.getOrDefault(layer, missing).getQuads(state, side, rand, extraData);
|
||||||
}
|
}
|
||||||
|
@ -201,10 +215,38 @@ public final class MultiLayerModel implements IModelGeometry<MultiLayerModel>
|
||||||
{
|
{
|
||||||
return ItemOverrideList.EMPTY;
|
return ItemOverrideList.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLayered()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Pair<IBakedModel, RenderType>> getLayerModels(ItemStack itemStack, boolean fabulous)
|
||||||
|
{
|
||||||
|
return itemLayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BiMap<RenderType, RenderType> ITEM_RENDER_TYPE_MAPPING = HashBiMap.create();
|
||||||
|
static {
|
||||||
|
ITEM_RENDER_TYPE_MAPPING.put(RenderType.getSolid(), RenderType.getEntitySolid(AtlasTexture.LOCATION_BLOCKS_TEXTURE));
|
||||||
|
ITEM_RENDER_TYPE_MAPPING.put(RenderType.getCutout(), RenderType.getEntityCutout(AtlasTexture.LOCATION_BLOCKS_TEXTURE));
|
||||||
|
ITEM_RENDER_TYPE_MAPPING.put(RenderType.getCutoutMipped(), ForgeRenderTypes.getEntityCutoutMipped(AtlasTexture.LOCATION_BLOCKS_TEXTURE));
|
||||||
|
ITEM_RENDER_TYPE_MAPPING.put(RenderType.getTranslucent(), RenderType.getEntityTranslucent(AtlasTexture.LOCATION_BLOCKS_TEXTURE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Loader implements IModelLoader<MultiLayerModel>
|
public static final class Loader implements IModelLoader<MultiLayerModel>
|
||||||
{
|
{
|
||||||
|
public static final Map<String, RenderType> BLOCK_LAYERS = ImmutableMap.<String,RenderType>builder()
|
||||||
|
.put("solid", RenderType.getSolid())
|
||||||
|
.put("cutout", RenderType.getCutout())
|
||||||
|
.put("cutout_mipped", RenderType.getCutoutMipped())
|
||||||
|
.put("translucent", RenderType.getTranslucent())
|
||||||
|
.put("tripwire", RenderType.func_241715_r_())
|
||||||
|
.build();
|
||||||
|
|
||||||
public static final Loader INSTANCE = new Loader();
|
public static final Loader INSTANCE = new Loader();
|
||||||
|
|
||||||
private Loader() {}
|
private Loader() {}
|
||||||
|
@ -220,12 +262,12 @@ public final class MultiLayerModel implements IModelGeometry<MultiLayerModel>
|
||||||
{
|
{
|
||||||
ImmutableMap.Builder<RenderType, IUnbakedModel> builder = ImmutableMap.builder();
|
ImmutableMap.Builder<RenderType, IUnbakedModel> builder = ImmutableMap.builder();
|
||||||
JsonObject layersObject = JSONUtils.getJsonObject(modelContents, "layers");
|
JsonObject layersObject = JSONUtils.getJsonObject(modelContents, "layers");
|
||||||
for(RenderType layer : RenderType.getBlockRenderTypes()) // block layers
|
for(Map.Entry<String, RenderType> layer : BLOCK_LAYERS.entrySet()) // block layers
|
||||||
{
|
{
|
||||||
String layerName = layer.toString(); // mc overrides toString to return the ID for the layer
|
String layerName = layer.getKey(); // mc overrides toString to return the ID for the layer
|
||||||
if(layersObject.has(layerName))
|
if(layersObject.has(layerName))
|
||||||
{
|
{
|
||||||
builder.put(layer, deserializationContext.deserialize(JSONUtils.getJsonObject(layersObject, layerName), BlockModel.class));
|
builder.put(layer.getValue(), deserializationContext.deserialize(JSONUtils.getJsonObject(layersObject, layerName), BlockModel.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImmutableMap<RenderType, IUnbakedModel> models = builder.build();
|
ImmutableMap<RenderType, IUnbakedModel> models = builder.build();
|
||||||
|
|
|
@ -31,7 +31,7 @@ import net.minecraft.client.renderer.model.IBakedModel;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience interface with default implementation of {@link IBakedModel#getQuads(net.minecraft.block.state.IBlockState, net.minecraft.util.EnumFacing, java.util.Random)}.
|
* Convenience interface with default implementation of {@link IBakedModel#getQuads(net.minecraft.block.BlockState, net.minecraft.util.Direction, java.util.Random)}.
|
||||||
*/
|
*/
|
||||||
public interface IDynamicBakedModel extends IBakedModel
|
public interface IDynamicBakedModel extends IBakedModel
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,7 +32,12 @@ public class ModelDataMap implements IModelData
|
||||||
{
|
{
|
||||||
this.backingMap = new IdentityHashMap<>(map);
|
this.backingMap = new IdentityHashMap<>(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ModelDataMap()
|
||||||
|
{
|
||||||
|
this.backingMap = new IdentityHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasProperty(ModelProperty<?> prop)
|
public boolean hasProperty(ModelProperty<?> prop)
|
||||||
{
|
{
|
||||||
|
|
|
@ -150,6 +150,7 @@ public net.minecraft.client.particle.ParticleManager$IParticleMetaFactory
|
||||||
public net.minecraft.client.renderer.GameRenderer func_175069_a(Lnet/minecraft/util/ResourceLocation;)V #loadShader
|
public net.minecraft.client.renderer.GameRenderer func_175069_a(Lnet/minecraft/util/ResourceLocation;)V #loadShader
|
||||||
private net.minecraft.client.renderer.ItemModelMesher field_199313_a #force public -> private
|
private net.minecraft.client.renderer.ItemModelMesher field_199313_a #force public -> private
|
||||||
public net.minecraft.client.renderer.ItemRenderer func_229112_a_(Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;Ljava/util/List;Lnet/minecraft/item/ItemStack;II)V # renderQuads
|
public net.minecraft.client.renderer.ItemRenderer func_229112_a_(Lcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;Ljava/util/List;Lnet/minecraft/item/ItemStack;II)V # renderQuads
|
||||||
|
public net.minecraft.client.renderer.ItemRenderer func_229114_a_(Lnet/minecraft/client/renderer/model/IBakedModel;Lnet/minecraft/item/ItemStack;IILcom/mojang/blaze3d/matrix/MatrixStack;Lcom/mojang/blaze3d/vertex/IVertexBuilder;)V # renderModel
|
||||||
public net.minecraft.client.renderer.entity.EntityRendererManager field_78729_o #renderers
|
public net.minecraft.client.renderer.entity.EntityRendererManager field_78729_o #renderers
|
||||||
public net.minecraft.client.renderer.entity.EntityRendererManager func_229087_a_(Lnet/minecraft/entity/EntityType;Lnet/minecraft/client/renderer/entity/EntityRenderer;)V # addRenderer
|
public net.minecraft.client.renderer.entity.EntityRendererManager func_229087_a_(Lnet/minecraft/entity/EntityType;Lnet/minecraft/client/renderer/entity/EntityRenderer;)V # addRenderer
|
||||||
protected net.minecraft.client.renderer.entity.ItemRenderer func_177078_a(Lnet/minecraft/item/ItemStack;)I # getMiniItemCount
|
protected net.minecraft.client.renderer.entity.ItemRenderer func_177078_a(Lnet/minecraft/item/ItemStack;)I # getMiniItemCount
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"solid": {
|
"solid": {
|
||||||
"parent": "block/cube_all",
|
"parent": "block/cube_all",
|
||||||
"textures": { "all": "block/slime_block" },
|
"textures": { "all": "block/slime_block" },
|
||||||
"transform": { "scale": 0.5, "translation": [-0.25,-0.25,-0.25] }
|
"transform": { "origin":"center", "scale": 0.625 }
|
||||||
},
|
},
|
||||||
"translucent": {
|
"translucent": {
|
||||||
"parent": "block/cube_all",
|
"parent": "block/cube_all",
|
||||||
|
|
Loading…
Reference in a new issue