/* * Decompiled with CFR 0.152. * * Could not load the following classes: * it.unimi.dsi.fastutil.objects.ObjectOpenHashSet * org.joml.Vector3f */ package net.minecraft.client.renderer.feature; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator; import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import net.minecraft.SharedConstants; import net.minecraft.client.model.Model; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.OutlineBufferSource; import net.minecraft.client.renderer.SubmitNodeCollection; import net.minecraft.client.renderer.SubmitNodeStorage; import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.client.resources.model.ModelBakery; import org.joml.Vector3f; public class ModelFeatureRenderer { private final PoseStack poseStack = new PoseStack(); public void render(SubmitNodeCollection nodeCollection, MultiBufferSource.BufferSource bufferSource, OutlineBufferSource outlineBufferSource, MultiBufferSource.BufferSource crumblingBufferSource) { Storage storage = nodeCollection.getModelSubmits(); this.renderBatch(bufferSource, outlineBufferSource, storage.opaqueModelSubmits, crumblingBufferSource); storage.translucentModelSubmits.sort(Comparator.comparingDouble(submit -> -submit.position().lengthSquared())); this.renderTranslucents(bufferSource, outlineBufferSource, storage.translucentModelSubmits, crumblingBufferSource); } private void renderTranslucents(MultiBufferSource.BufferSource bufferSource, OutlineBufferSource outlineBufferSource, List> submits, MultiBufferSource.BufferSource crumblingBufferSource) { for (SubmitNodeStorage.TranslucentModelSubmit submit : submits) { this.renderModel(submit.modelSubmit(), submit.renderType(), bufferSource.getBuffer(submit.renderType()), outlineBufferSource, crumblingBufferSource); } } private void renderBatch(MultiBufferSource.BufferSource bufferSource, OutlineBufferSource outlineBufferSource, Map>> map, MultiBufferSource.BufferSource crumblingBufferSource) { Collection>>> entries; if (SharedConstants.DEBUG_SHUFFLE_MODELS) { ArrayList shuffledCopy = new ArrayList(map.entrySet()); Collections.shuffle(shuffledCopy); entries = shuffledCopy; } else { entries = map.entrySet(); } for (Map.Entry entry : entries) { VertexConsumer buffer = bufferSource.getBuffer((RenderType)entry.getKey()); for (SubmitNodeStorage.ModelSubmit submit : (List)entry.getValue()) { this.renderModel(submit, (RenderType)entry.getKey(), buffer, outlineBufferSource, crumblingBufferSource); } } } private void renderModel(SubmitNodeStorage.ModelSubmit submit, RenderType renderType, VertexConsumer buffer, OutlineBufferSource outlineBufferSource, MultiBufferSource.BufferSource crumblingBufferSource) { this.poseStack.pushPose(); this.poseStack.last().set(submit.pose()); Model model = submit.model(); VertexConsumer wrappedBuffer = submit.sprite() == null ? buffer : submit.sprite().wrap(buffer); model.setupAnim(submit.state()); model.renderToBuffer(this.poseStack, wrappedBuffer, submit.lightCoords(), submit.overlayCoords(), submit.tintedColor()); if (submit.outlineColor() != 0 && (renderType.outline().isPresent() || renderType.isOutline())) { outlineBufferSource.setColor(submit.outlineColor()); VertexConsumer outlineBuffer = outlineBufferSource.getBuffer(renderType); model.renderToBuffer(this.poseStack, submit.sprite() == null ? outlineBuffer : submit.sprite().wrap(outlineBuffer), submit.lightCoords(), submit.overlayCoords(), submit.tintedColor()); } if (submit.crumblingOverlay() != null && renderType.affectsCrumbling()) { SheetedDecalTextureGenerator breakingBuffer = new SheetedDecalTextureGenerator(crumblingBufferSource.getBuffer(ModelBakery.DESTROY_TYPES.get(submit.crumblingOverlay().progress())), submit.crumblingOverlay().cameraPose(), 1.0f); model.renderToBuffer(this.poseStack, submit.sprite() == null ? breakingBuffer : submit.sprite().wrap(breakingBuffer), submit.lightCoords(), submit.overlayCoords(), submit.tintedColor()); } this.poseStack.popPose(); } public static class Storage { private final Map>> opaqueModelSubmits = new HashMap(); private final List> translucentModelSubmits = new ArrayList(); private final Set usedModelSubmitBuckets = new ObjectOpenHashSet(); public void add(RenderType renderType, SubmitNodeStorage.ModelSubmit modelSubmit) { if (renderType.pipeline().getBlendFunction().isEmpty()) { this.opaqueModelSubmits.computeIfAbsent(renderType, ignored -> new ArrayList()).add(modelSubmit); } else { Vector3f position = modelSubmit.pose().pose().transformPosition(new Vector3f()); this.translucentModelSubmits.add(new SubmitNodeStorage.TranslucentModelSubmit(modelSubmit, renderType, position)); } } public void clear() { this.translucentModelSubmits.clear(); for (Map.Entry>> bucketEntry : this.opaqueModelSubmits.entrySet()) { List> bucket = bucketEntry.getValue(); if (bucket.isEmpty()) continue; this.usedModelSubmitBuckets.add(bucketEntry.getKey()); bucket.clear(); } } public void endFrame() { this.opaqueModelSubmits.keySet().removeIf(renderType -> !this.usedModelSubmitBuckets.contains(renderType)); this.usedModelSubmitBuckets.clear(); } } public record CrumblingOverlay(int progress, PoseStack.Pose cameraPose) { } }