174 lines
8.0 KiB
Java
174 lines
8.0 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.google.common.base.Suppliers
|
|
* com.mojang.datafixers.kinds.App
|
|
* com.mojang.datafixers.kinds.Applicative
|
|
* com.mojang.serialization.MapCodec
|
|
* com.mojang.serialization.codecs.RecordCodecBuilder
|
|
* org.joml.Vector3f
|
|
* org.jspecify.annotations.Nullable
|
|
*/
|
|
package net.minecraft.client.renderer.item;
|
|
|
|
import com.google.common.base.Suppliers;
|
|
import com.mojang.datafixers.kinds.App;
|
|
import com.mojang.datafixers.kinds.Applicative;
|
|
import com.mojang.serialization.MapCodec;
|
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.function.Function;
|
|
import java.util.function.Supplier;
|
|
import net.minecraft.client.color.item.ItemTintSource;
|
|
import net.minecraft.client.color.item.ItemTintSources;
|
|
import net.minecraft.client.multiplayer.ClientLevel;
|
|
import net.minecraft.client.renderer.ItemBlockRenderTypes;
|
|
import net.minecraft.client.renderer.Sheets;
|
|
import net.minecraft.client.renderer.block.model.BakedQuad;
|
|
import net.minecraft.client.renderer.block.model.FaceBakery;
|
|
import net.minecraft.client.renderer.block.model.TextureSlots;
|
|
import net.minecraft.client.renderer.chunk.ChunkSectionLayer;
|
|
import net.minecraft.client.renderer.item.ItemModel;
|
|
import net.minecraft.client.renderer.item.ItemModelResolver;
|
|
import net.minecraft.client.renderer.item.ItemStackRenderState;
|
|
import net.minecraft.client.renderer.item.ModelRenderProperties;
|
|
import net.minecraft.client.renderer.rendertype.RenderType;
|
|
import net.minecraft.client.renderer.texture.TextureAtlas;
|
|
import net.minecraft.client.resources.model.BlockModelRotation;
|
|
import net.minecraft.client.resources.model.ModelBaker;
|
|
import net.minecraft.client.resources.model.ResolvableModel;
|
|
import net.minecraft.client.resources.model.ResolvedModel;
|
|
import net.minecraft.resources.Identifier;
|
|
import net.minecraft.tags.ItemTags;
|
|
import net.minecraft.world.entity.ItemOwner;
|
|
import net.minecraft.world.item.BlockItem;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.world.item.ItemDisplayContext;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.Items;
|
|
import org.joml.Vector3f;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
public class BlockModelWrapper
|
|
implements ItemModel {
|
|
private static final Function<ItemStack, RenderType> ITEM_RENDER_TYPE_GETTER = stack -> Sheets.translucentItemSheet();
|
|
private static final Function<ItemStack, RenderType> BLOCK_RENDER_TYPE_GETTER = stack -> {
|
|
BlockItem blockItem;
|
|
ChunkSectionLayer blockLayer;
|
|
Item patt0$temp = stack.getItem();
|
|
if (patt0$temp instanceof BlockItem && (blockLayer = ItemBlockRenderTypes.getChunkRenderType((blockItem = (BlockItem)patt0$temp).getBlock().defaultBlockState())) == ChunkSectionLayer.TRANSLUCENT) {
|
|
return Sheets.translucentBlockItemSheet();
|
|
}
|
|
return Sheets.cutoutBlockSheet();
|
|
};
|
|
private final List<ItemTintSource> tints;
|
|
private final List<BakedQuad> quads;
|
|
private final Supplier<Vector3f[]> extents;
|
|
private final ModelRenderProperties properties;
|
|
private final boolean animated;
|
|
private final Function<ItemStack, RenderType> renderType;
|
|
|
|
private BlockModelWrapper(List<ItemTintSource> tints, List<BakedQuad> quads, ModelRenderProperties properties, Function<ItemStack, RenderType> renderType) {
|
|
this.tints = tints;
|
|
this.quads = quads;
|
|
this.properties = properties;
|
|
this.renderType = renderType;
|
|
this.extents = Suppliers.memoize(() -> BlockModelWrapper.computeExtents(this.quads));
|
|
boolean animated = false;
|
|
for (BakedQuad quad : quads) {
|
|
if (!quad.sprite().contents().isAnimated()) continue;
|
|
animated = true;
|
|
break;
|
|
}
|
|
this.animated = animated;
|
|
}
|
|
|
|
public static Vector3f[] computeExtents(List<BakedQuad> quads) {
|
|
HashSet result = new HashSet();
|
|
for (BakedQuad quad : quads) {
|
|
FaceBakery.extractPositions(quad.vertices(), result::add);
|
|
}
|
|
return (Vector3f[])result.toArray(Vector3f[]::new);
|
|
}
|
|
|
|
@Override
|
|
public void update(ItemStackRenderState output, ItemStack item, ItemModelResolver resolver, ItemDisplayContext displayContext, @Nullable ClientLevel level, @Nullable ItemOwner owner, int seed) {
|
|
output.appendModelIdentityElement(this);
|
|
ItemStackRenderState.LayerRenderState layer = output.newLayer();
|
|
if (item.hasFoil()) {
|
|
ItemStackRenderState.FoilType foilType = BlockModelWrapper.hasSpecialAnimatedTexture(item) ? ItemStackRenderState.FoilType.SPECIAL : ItemStackRenderState.FoilType.STANDARD;
|
|
layer.setFoilType(foilType);
|
|
output.setAnimated();
|
|
output.appendModelIdentityElement((Object)foilType);
|
|
}
|
|
int activeTints = this.tints.size();
|
|
int[] tintLayers = layer.prepareTintLayers(activeTints);
|
|
for (int i = 0; i < activeTints; ++i) {
|
|
int tint;
|
|
tintLayers[i] = tint = this.tints.get(i).calculate(item, level, owner == null ? null : owner.asLivingEntity());
|
|
output.appendModelIdentityElement(tint);
|
|
}
|
|
layer.setExtents(this.extents);
|
|
layer.setRenderType(this.renderType.apply(item));
|
|
this.properties.applyToLayer(layer, displayContext);
|
|
layer.prepareQuadList().addAll(this.quads);
|
|
if (this.animated) {
|
|
output.setAnimated();
|
|
}
|
|
}
|
|
|
|
private static Function<ItemStack, RenderType> detectRenderType(List<BakedQuad> quads) {
|
|
Iterator<BakedQuad> quadIterator = quads.iterator();
|
|
if (!quadIterator.hasNext()) {
|
|
return ITEM_RENDER_TYPE_GETTER;
|
|
}
|
|
Identifier expectedAtlas = quadIterator.next().sprite().atlasLocation();
|
|
while (quadIterator.hasNext()) {
|
|
BakedQuad quad = quadIterator.next();
|
|
Identifier quadAtlas = quad.sprite().atlasLocation();
|
|
if (quadAtlas.equals(expectedAtlas)) continue;
|
|
throw new IllegalStateException("Multiple atlases used in model, expected " + String.valueOf(expectedAtlas) + ", but also got " + String.valueOf(quadAtlas));
|
|
}
|
|
if (expectedAtlas.equals(TextureAtlas.LOCATION_ITEMS)) {
|
|
return ITEM_RENDER_TYPE_GETTER;
|
|
}
|
|
if (expectedAtlas.equals(TextureAtlas.LOCATION_BLOCKS)) {
|
|
return BLOCK_RENDER_TYPE_GETTER;
|
|
}
|
|
throw new IllegalArgumentException("Atlas " + String.valueOf(expectedAtlas) + " can't be usef for item models");
|
|
}
|
|
|
|
private static boolean hasSpecialAnimatedTexture(ItemStack itemStack) {
|
|
return itemStack.is(ItemTags.COMPASSES) || itemStack.is(Items.CLOCK);
|
|
}
|
|
|
|
public record Unbaked(Identifier model, List<ItemTintSource> tints) implements ItemModel.Unbaked
|
|
{
|
|
public static final MapCodec<Unbaked> MAP_CODEC = RecordCodecBuilder.mapCodec(i -> i.group((App)Identifier.CODEC.fieldOf("model").forGetter(Unbaked::model), (App)ItemTintSources.CODEC.listOf().optionalFieldOf("tints", List.of()).forGetter(Unbaked::tints)).apply((Applicative)i, Unbaked::new));
|
|
|
|
@Override
|
|
public void resolveDependencies(ResolvableModel.Resolver resolver) {
|
|
resolver.markDependency(this.model);
|
|
}
|
|
|
|
@Override
|
|
public ItemModel bake(ItemModel.BakingContext context) {
|
|
ModelBaker baker = context.blockModelBaker();
|
|
ResolvedModel resolvedModel = baker.getModel(this.model);
|
|
TextureSlots textureSlots = resolvedModel.getTopTextureSlots();
|
|
List<BakedQuad> quads = resolvedModel.bakeTopGeometry(textureSlots, baker, BlockModelRotation.IDENTITY).getAll();
|
|
ModelRenderProperties properties = ModelRenderProperties.fromResolvedModel(baker, resolvedModel, textureSlots);
|
|
Function<ItemStack, RenderType> renderTypeGetter = BlockModelWrapper.detectRenderType(quads);
|
|
return new BlockModelWrapper(this.tints, quads, properties, renderTypeGetter);
|
|
}
|
|
|
|
public MapCodec<Unbaked> type() {
|
|
return MAP_CODEC;
|
|
}
|
|
}
|
|
}
|
|
|