Files
saturnclient/src/main/java/org/saturnclient/impl/ui/RenderScopeImpl.java
T
selimaj-devandclaude 4fb48cc647 Build for Minecraft 26.1
Adds 26.1 as a Stonecutter version (step 3 of #39). Its jar also
loads on the 26.1.1 and 26.1.2 hotfixes.

Most of 26.1's changes are renames: the GUI's render methods became
extract methods and GuiGraphics became GuiGraphicsExtractor, which
Stonecutter replacements cover along with the moved render state
package and GuiRenderState's add methods. The rest are version
comments:

- The menu panorama is drawn by GuiRenderer from vanilla's cube map;
  the new GuiRendererMixin swaps in Saturn's while a Saturn screen is
  open (empty on older versions).
- The camera works out the FOV and aligns with its entity in
  alignWithEntity, so the zoom and freelook hooks move to CameraMixin.
- Gamma and the menu blur are read while extracting render state.
- The glass blur's post chain takes a Projection and its buffer.
- The dragon's alpha render type is gone; capes use entityCutout.
- Fabric API renamed KeyBindingHelper to KeyMappingHelper.

The docs describe the 26.x build and Java 25.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 19:15:10 +02:00

843 lines
31 KiB
Java

package org.saturnclient.impl.ui;
// 1.21.6 rewrote GUI rendering: render states and a 2D matrix stack (Matrix3x2fStack) instead of
// drawing into vertex consumers with a MatrixStack. This file has one implementation for each side.
//? if >=1.21.6 {
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3x2f;
import org.joml.Matrix3x2fStack;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import com.mojang.blaze3d.textures.GpuTextureView;
import org.saturnclient.common.ref.asset.IdentifierRef;
import org.saturnclient.common.ref.asset.SpriteRef;
import org.saturnclient.common.ref.game.ItemStackRef;
import org.saturnclient.common.ref.render.MatrixStackRef;
import org.saturnclient.impl.ref.Matrix3x2fStackRef;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.resources.Fonts;
import org.saturnclient.ui.resources.SvgTexture;
import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.gui.render.state.ColoredRectangleRenderState;
import net.minecraft.client.gui.render.state.GuiRenderState;
import net.minecraft.client.gui.render.state.GuiItemRenderState;
import net.minecraft.client.gui.render.state.GuiTextRenderState;
import net.minecraft.client.gui.render.state.BlitRenderState;
import net.minecraft.client.gui.render.state.pip.GuiEntityRenderState;
import net.minecraft.client.renderer.entity.state.EntityRenderState;
//? if >=1.21.7 {
import net.minecraft.client.renderer.item.TrackingItemStackRenderState;
//?} else
//import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.client.renderer.texture.AbstractTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.Identifier;
import net.minecraft.ReportedException;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.world.level.Level;
public class RenderScopeImpl implements RenderScope {
public final Matrix3x2fStackRef matrices;
public final GuiRenderState state;
private ScissorStack scissorStack;
private int opacity = 0xFF << 24;
// The glass blurs made for this scope's frame
private final Set<Integer> capturedBlurs = new HashSet<>();
public RenderScopeImpl(GuiGraphics context) {
this(context.pose(), ((DrawContextAccessor) (Object) context).getState());
}
public RenderScopeImpl(Matrix3x2fStack matrices, GuiRenderState state) {
this.matrices = new Matrix3x2fStackRef(matrices);
this.state = state;
this.scissorStack = new ScissorStack();
}
@Override
public MatrixStackRef getMatrixStack() {
return matrices;
}
@Override
public void setOpacity(float alpha) {
this.opacity = ((int) (alpha * 255)) << 24;
}
@Override
public int getColor(int color) {
int originalAlpha = (color >>> 24) & 0xFF;
int newAlpha = (opacity >>> 24) & 0xFF;
int mixedAlpha = (originalAlpha * newAlpha) / 255;
return (mixedAlpha << 24) | (color & 0x00FFFFFF);
}
@Override
public void fill(int x1, int y1, int x2, int y2, int color) {
this.state.submitGuiElement(
new ColoredRectangleRenderState(
RenderPipelines.GUI,
TextureSetup.noTexture(),
new Matrix3x2f(this.matrices.stack),
x1, y1, x2, y2, color, color,
this.scissorStack.peekLast()));
}
@Override
public void drawRectangle(int x, int y, int width, int height, int color) {
if (color == 0)
return;
color = getColor(color);
int x1 = x;
int x2 = x + width;
int y1 = y;
int y2 = y + height;
if (x2 < x1) {
int tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y2 < y1) {
int tmp = y1;
y1 = y2;
y2 = tmp;
}
this.fill(x1, y1, x2, y2, color);
}
@Override
public void drawText(String text, int x, int y, int font, int color) {
drawText(1.0f, text, x, y, font, color);
}
@Override
public void drawText(float scale, String text, int x, int y, int font, int color) {
if (color == 0)
return;
if (font == 0)
scale *= 2;
int lineIndex = 0;
for (String line : text.split("\n")) {
int finalColor = getColor(color);
matrices.push();
matrices.translate(x, y + (lineIndex * Fonts.getHeight()));
matrices.scale(scale, scale);
this.state.submitText(
new GuiTextRenderState(
SaturnClient.client.font,
((Component) Fonts.setFont(line, font)).getVisualOrderText(),
new Matrix3x2f(this.matrices.stack),
0, font == 0 ? 1 : 8,
//? if >=1.21.11 {
finalColor, 0, false, false, this.scissorStack.peekLast()));
//?} else
//finalColor, 0, false, this.scissorStack.peekLast()));
matrices.pop();
lineIndex++;
}
}
@Override
public int getScaledWindowWidth() {
return SaturnClient.client.getWindow().getGuiScaledWidth();
}
@Override
public int getScaledWindowHeight() {
return SaturnClient.client.getWindow().getGuiScaledHeight();
}
// Texture rendering
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height) {
drawTexture(sprite, x, y, u, v, width, height, -1);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height, int color) {
drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height,
int regionWidth, int regionHeight, int textureWidth, int textureHeight) {
drawTexture(sprite, x, y, u, v, width, height, regionWidth, regionHeight, textureWidth, textureHeight, -1);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height,
int regionWidth, int regionHeight, int textureWidth, int textureHeight, int color) {
drawTexturedQuad((Identifier) (Object) sprite, x, x + width, y, y + height,
(u + 0f) / textureWidth,
(u + regionWidth) / textureWidth,
(v + 0f) / textureHeight,
(v + regionHeight) / textureHeight,
color);
}
private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2,
float u1, float u2, float v1, float v2, int color) {
if (color == 0)
return;
color = getColor(color);
if (sprite.getPath().endsWith(".svg")) {
sprite = (Identifier) (Object) SvgTexture.getSvg(
(IdentifierRef) (Object) sprite,
(x2 - x1) * 2, (y2 - y1) * 2);
}
GpuTextureView gpuTextureView = SaturnClient.client.getTextureManager()
.getTexture(sprite).getTextureView();
//? if >=1.21.11
AbstractTexture abstractTexture = SaturnClient.client.getTextureManager().getTexture(sprite);
this.state.submitGuiElement(new BlitRenderState(
RenderPipelines.GUI_TEXTURED,
//? if >=1.21.11 {
TextureSetup.singleTexture(gpuTextureView, abstractTexture.getSampler()),
//?} else
//TextureSetup.singleTexture(gpuTextureView),
new Matrix3x2f(this.matrices.stack),
x1, y1, x2, y2, u1, u2, v1, v2, color,
this.scissorStack.peekLast()));
}
@Override
public void drawGlass(IdentifierRef mask, int x, int y, int width, int height, int blur) {
int color = getColor(0xFFFFFFFF);
if (mask == null || color >>> 24 == 0)
return;
if (capturedBlurs.add(blur)) {
GlassRenderer.captureBackdrop(blur);
}
AbstractTexture maskTexture = SaturnClient.client.getTextureManager().getTexture((Identifier) (Object) mask);
this.state.submitGuiElement(new BlitRenderState(
GlassRenderer.PIPELINE,
GlassRenderer.textures(maskTexture, blur),
new Matrix3x2f(this.matrices.stack),
x, y, x + width, y + height, 0, 1, 0, 1, color,
this.scissorStack.peekLast()));
}
// Scissor management
@Override
public void enableScissor(int x1, int y1, int x2, int y2) {
ScreenRectangle rect = new ScreenRectangle(x1, y1, x2 - x1, y2 - y1).transformAxisAligned(this.matrices.stack);
scissorStack.push(rect);
}
@Override
public void disableScissor() {
scissorStack.pop();
}
@Override
public boolean scissorContains(int x, int y) {
return scissorStack.contains(x, y);
}
public static class ScissorStack {
private final Deque<ScreenRectangle> stack = new ArrayDeque<>();
public ScreenRectangle push(ScreenRectangle rect) {
ScreenRectangle last = stack.peekLast();
if (last != null) {
ScreenRectangle intersection = Objects.requireNonNullElse(rect.intersection(last), ScreenRectangle.empty());
stack.addLast(intersection);
return intersection;
} else {
stack.addLast(rect);
return rect;
}
}
@Nullable
public ScreenRectangle pop() {
if (stack.isEmpty())
throw new IllegalStateException("Scissor stack underflow");
stack.removeLast();
return stack.peekLast();
}
@Nullable
public ScreenRectangle peekLast() {
return stack.peekLast();
}
public boolean contains(int x, int y) {
return stack.isEmpty() || stack.peekLast().containsPoint(x, y);
}
}
// Item rendering
@Override
public void drawItem(ItemStackRef stack, int x, int y) {
drawItem(null, SaturnClient.client.level, stack, x, y, 0);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable Level world, ItemStackRef stack, int x, int y,
int seed) {
drawItem(entity, world, (ItemStack) (Object) stack, x, y, seed, 0);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable Level world, ItemStack stack, int x, int y, int seed,
int z) {
if (!stack.isEmpty()) {
//? if >=1.21.7 {
TrackingItemStackRenderState keyedItemRenderState = new TrackingItemStackRenderState();
//?} else
//ItemStackRenderState keyedItemRenderState = new ItemStackRenderState();
SaturnClient.client.getItemModelResolver().updateForTopItem(keyedItemRenderState, stack,
ItemDisplayContext.GUI, world,
entity, seed);
try {
//? if >=26.1 {
/*this.state.submitItem(new GuiItemRenderState(
*///?} else
this.state.submitItem(new GuiItemRenderState(stack.getItem().getName().toString(),
new Matrix3x2f(this.matrices.stack), keyedItemRenderState, x, y,
this.scissorStack.peekLast()));
} catch (Throwable throwable) {
CrashReport crashReport = CrashReport.forThrowable(throwable, "Rendering item");
CrashReportCategory crashReportSection = crashReport.addCategory("Item being rendered");
crashReportSection.setDetail("Item Type", () -> String.valueOf(stack.getItem()));
crashReportSection.setDetail("Item Components", () -> String.valueOf(stack.getComponents()));
crashReportSection.setDetail("Item Foil", () -> String.valueOf(stack.hasFoil()));
throw new ReportedException(crashReport);
}
}
}
@Override
public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height) {
drawSpriteStretched(sprite, x, y, width, height, -1);
}
@Override
public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height, int color) {
TextureAtlasSprite mcSprite = (TextureAtlasSprite) sprite;
if (color == 0 || width == 0 || height == 0)
return;
drawTexturedQuad(mcSprite.atlasLocation(), x, x + width, y, y + height,
mcSprite.getU0(), mcSprite.getU1(), mcSprite.getV0(), mcSprite.getV1(), color);
}
@Override
public void draw() {
// No-op for now
}
public void drawBorder(int x, int y, int width, int height, int color) {
fill(x, y, x + width, y + 1, color);
fill(x, y + height - 1, x + width, y + height, color);
fill(x, y + 1, x + 1, y + height - 1, color);
fill(x + width - 1, y + 1, x + width, y + height - 1, color);
}
public void addEntity(EntityRenderState entityState, float scale, Vector3f translation, Quaternionf rotation,
@Nullable Quaternionf overrideCameraAngle, int x1, int y1, int x2, int y2) {
Matrix3x2f mat = this.matrices.stack;
float offsetX = mat.m20;
float offsetY = mat.m21;
float scaleX = mat.m00; // current matrix X scale
float scaleY = mat.m11; // current matrix Y scale
int adjustedX1 = (int) (x1 * scaleX + offsetX);
int adjustedY1 = (int) (y1 * scaleY + offsetY);
int adjustedX2 = (int) (x2 * scaleX + offsetX);
int adjustedY2 = (int) (y2 * scaleY + offsetY);
float adjustedScale = scale * scaleX; // apply matrix scale to entity scale too
this.state.submitPicturesInPictureState(new GuiEntityRenderState(entityState, translation, rotation,
overrideCameraAngle, adjustedX1, adjustedY1, adjustedX2, adjustedY2, adjustedScale,
this.scissorStack.peekLast()));
}
}
//?} else {
/*import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
import com.mojang.blaze3d.systems.RenderSystem;
import org.saturnclient.common.ref.asset.IdentifierRef;
import org.saturnclient.common.ref.asset.SpriteRef;
import org.saturnclient.common.ref.game.ItemStackRef;
import org.saturnclient.common.ref.render.MatrixStackRef;
import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.saturnclient.mixin.DrawContextAccessor;
import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.resources.Fonts;
import org.saturnclient.ui.resources.SvgTexture;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.Font.DisplayMode;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.navigation.ScreenRectangle;
import com.mojang.blaze3d.platform.Lighting;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.RenderType;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import com.mojang.blaze3d.platform.Window;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.world.entity.LivingEntity;
//? if >=1.21.5
import net.minecraft.world.item.ItemDisplayContext;
//? if <1.21.5
//import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.Identifier;
import net.minecraft.ReportedException;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.world.level.Level;
public class RenderScopeImpl implements RenderScope {
// ----------------------------
// Fields
// ----------------------------
public PoseStack matrices;
public MultiBufferSource.BufferSource vertexConsumers;
private ScissorStack scissorStack = new ScissorStack();
private int opacity = 255 << 24;
// The glass blurs made for this scope's frame
private final Set<Integer> capturedBlurs = new HashSet<>();
private final ItemStackRenderState itemRenderState;
// ----------------------------
// Constructors
// ----------------------------
public RenderScopeImpl(GuiGraphics context) {
this(context.pose(), ((DrawContextAccessor) context).getVertexConsumers());
}
public RenderScopeImpl(PoseStack matrices, MultiBufferSource.BufferSource vertexConsumers) {
this.matrices = matrices;
this.vertexConsumers = vertexConsumers;
this.scissorStack = new ScissorStack();
this.itemRenderState = new ItemStackRenderState();
}
// ----------------------------
// Matrix & Transform
// ----------------------------
@Override
public MatrixStackRef getMatrixStack() {
return (MatrixStackRef) matrices;
}
// ----------------------------
// Color & Opacity
// ----------------------------
@Override
public void setOpacity(float alpha) {
this.opacity = (int) (alpha * 255) << 24;
}
@Override
public int getColor(int color) {
int originalAlpha = (color >>> 24) & 0xFF;
int newAlpha = (opacity >>> 24) & 0xFF;
int mixedAlpha = (originalAlpha * newAlpha) / 255;
return (mixedAlpha << 24) | (color & 0x00FFFFFF);
}
// ----------------------------
// Draw / Window Info
// ----------------------------
@Override
public void draw() {
this.vertexConsumers.endBatch();
}
@Override
public int getScaledWindowWidth() {
return SaturnClient.client.getWindow().getGuiScaledWidth();
}
@Override
public int getScaledWindowHeight() {
return SaturnClient.client.getWindow().getGuiScaledHeight();
}
public void draw(Consumer<MultiBufferSource> drawer) {
drawer.accept(this.vertexConsumers);
this.vertexConsumers.endBatch();
}
// ----------------------------
// Shapes
// ----------------------------
@Override
public void drawRectangle(int x, int y, int width, int height, int color) {
if (color == 0)
return;
color = getColor(color);
Matrix4f matrix4f = this.matrices.last().pose();
int x1 = x;
int x2 = x + width;
int y1 = y;
int y2 = y + height;
if (x1 < x2) {
int tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y1 < y2) {
int tmp = y1;
y1 = y2;
y2 = tmp;
}
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(RenderType.gui());
vertexConsumer.addVertex(matrix4f, x1, y1, 0).setColor(color);
vertexConsumer.addVertex(matrix4f, x1, y2, 0).setColor(color);
vertexConsumer.addVertex(matrix4f, x2, y2, 0).setColor(color);
vertexConsumer.addVertex(matrix4f, x2, y1, 0).setColor(color);
}
@Override
public void fill(int x1, int y1, int x2, int y2, int color) {
fill(x1, y1, x2, y2, 0, color);
}
public void fill(int x1, int y1, int x2, int y2, int z, int color) {
fill(RenderType.gui(), x1, y1, x2, y2, z, color);
}
public void fill(RenderType layer, int x1, int y1, int x2, int y2, int color) {
fill(layer, x1, y1, x2, y2, 0, color);
}
public void fill(RenderType layer, int x1, int y1, int x2, int y2, int z, int color) {
Matrix4f matrix4f = this.matrices.last().pose();
if (x1 < x2) {
int tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y1 < y2) {
int tmp = y1;
y1 = y2;
y2 = tmp;
}
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(layer);
vertexConsumer.addVertex(matrix4f, x1, y1, z).setColor(color);
vertexConsumer.addVertex(matrix4f, x1, y2, z).setColor(color);
vertexConsumer.addVertex(matrix4f, x2, y2, z).setColor(color);
vertexConsumer.addVertex(matrix4f, x2, y1, z).setColor(color);
}
@Override
public void drawBorder(int x, int y, int width, int height, int color) {
fill(x, y, x + width, y + 1, color);
fill(x, y + height - 1, x + width, y + height, color);
fill(x, y + 1, x + 1, y + height - 1, color);
fill(x + width - 1, y + 1, x + width, y + height - 1, color);
}
// ----------------------------
// Text
// ----------------------------
@Override
public void drawText(String text, int x, int y, int font, int color) {
drawText(1.0f, text, x, y, font, color);
}
@Override
public void drawText(float scale, String text, int x, int y, int font, int color) {
if (color == 0)
return;
if (font == 0)
scale *= 2;
int i = 0;
for (String line : text.split("\n")) {
color = getColor(color);
matrices.pushPose();
matrices.translate(x, y + i * Fonts.getHeight(), 0);
matrices.scale(scale, scale, 1.0f);
Font textRenderer = SaturnClient.client.font;
textRenderer.drawInBatch((Component) Fonts.setFont(line, font), 0, font == 0 ? 1 : 7, color, false,
matrices.last().pose(), vertexConsumers, DisplayMode.NORMAL, 0, 15728880);
matrices.popPose();
i++;
}
}
// ----------------------------
// Textures & Sprites
// ----------------------------
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height) {
drawTexture(sprite, x, y, u, v, width, height, width, height, width, height);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height, int color) {
drawTexture(sprite, x, y, u, v, width, height, width, height, width, height, color);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height,
int regionWidth, int regionHeight, int textureWidth, int textureHeight) {
drawTexture(sprite, x, y, u, v, width, height, regionWidth, regionHeight, textureWidth, textureHeight, -1);
}
@Override
public void drawTexture(IdentifierRef sprite, int x, int y, float u, float v, int width, int height,
int regionWidth, int regionHeight, int textureWidth, int textureHeight, int color) {
drawTexturedQuad((Identifier) (Object) sprite, x, x + width, y, y + height,
(u + 0.0f) / textureWidth, (u + regionWidth) / textureWidth,
(v + 0.0f) / textureHeight, (v + regionHeight) / textureHeight, color);
}
@Override
public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height) {
drawSpriteStretched(sprite, x, y, width, height, -1);
}
@Override
public void drawSpriteStretched(SpriteRef saturnSprite, int x, int y, int width, int height, int color) {
TextureAtlasSprite sprite = (TextureAtlasSprite) saturnSprite;
if (color == 0)
return;
if (width != 0 && height != 0) {
drawTexturedQuad(sprite.atlasLocation(), x, x + width, y, y + height,
sprite.getU0(), sprite.getU1(), sprite.getV0(), sprite.getV1(), color);
}
}
private void drawTexturedQuad(Identifier sprite, int x1, int x2, int y1, int y2,
float u1, float u2, float v1, float v2, int color) {
if (sprite.toString().endsWith(".svg")) {
sprite = (Identifier) (Object) SvgTexture.getSvg((IdentifierRef) (Object) sprite, (x2 - x1) * 2,
(y2 - y1) * 2);
}
if (color == 0)
return;
x1 *= 4;
x2 *= 4;
y1 *= 4;
y2 *= 4;
color = getColor(color);
matrices.pushPose();
matrices.scale(0.25f, 0.25f, 1.0f);
//? if <1.21.5
//RenderSystem.setShaderTexture(0, sprite);
RenderType renderLayer = RenderType.guiTextured(sprite);
Matrix4f matrix4f = matrices.last().pose();
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(renderLayer);
vertexConsumer.addVertex(matrix4f, x1, y1, 0).setUv(u1, v1).setColor(color);
vertexConsumer.addVertex(matrix4f, x1, y2, 0).setUv(u1, v2).setColor(color);
vertexConsumer.addVertex(matrix4f, x2, y2, 0).setUv(u2, v2).setColor(color);
vertexConsumer.addVertex(matrix4f, x2, y1, 0).setUv(u2, v1).setColor(color);
matrices.popPose();
}
@Override
public void drawGlass(IdentifierRef mask, int x, int y, int width, int height, int blur) {
int color = getColor(0xFFFFFFFF);
if (mask == null || color >>> 24 == 0)
return;
if (capturedBlurs.add(blur)) {
GlassRenderer.captureBackdrop(blur);
}
// In quarter units, as drawTexturedQuad draws
int x1 = x * 4;
int x2 = (x + width) * 4;
int y1 = y * 4;
int y2 = (y + height) * 4;
matrices.pushPose();
matrices.scale(0.25f, 0.25f, 1.0f);
Matrix4f matrix4f = matrices.last().pose();
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GlassRenderer.getLayer((Identifier) (Object) mask, blur));
vertexConsumer.addVertex(matrix4f, x1, y1, 0).setUv(0, 0).setColor(color);
vertexConsumer.addVertex(matrix4f, x1, y2, 0).setUv(0, 1).setColor(color);
vertexConsumer.addVertex(matrix4f, x2, y2, 0).setUv(1, 1).setColor(color);
vertexConsumer.addVertex(matrix4f, x2, y1, 0).setUv(1, 0).setColor(color);
matrices.popPose();
}
// ----------------------------
// Items
// ----------------------------
@Override
public void drawItem(ItemStackRef item, int x, int y) {
drawItem(SaturnClient.client.player, SaturnClient.client.level, item, x, y, 0);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable Level world, ItemStackRef stack, int x, int y,
int seed) {
drawItem(entity, world, (ItemStack) (Object) stack, x, y, seed, 0);
}
private void drawItem(@Nullable LivingEntity entity, @Nullable Level world, ItemStack stack, int x, int y, int seed,
int z) {
if (stack.isEmpty())
return;
//? if >=1.21.5
SaturnClient.client.getItemModelResolver().appendItemLayers(itemRenderState, stack, ItemDisplayContext.GUI, world, entity, seed);
//? if >=1.21.5
SaturnClient.client.getItemModelResolver().updateForTopItem(this.itemRenderState, stack, ItemDisplayContext.GUI, world, entity, seed);
//? if <1.21.5
//SaturnClient.client.getItemModelResolver().updateForTopItem(itemRenderState, stack, ItemDisplayContext.GUI, false, world, entity, seed);
this.matrices.pushPose();
//? if >=1.21.5
this.matrices.translate((float) (x + 8), (float) (y + 8), (float) (150 + z));
//? if <1.21.5
//this.matrices.translate(x + 8, y + 8, 150 + (itemRenderState.isGui3d() ? z : 0));
try {
this.matrices.scale(16.0F, -16.0F, 16.0F);
boolean bl = !this.itemRenderState.usesBlockLight();
if (bl) {
this.draw();
Lighting.setupForFlatItems();
}
this.itemRenderState.render(this.matrices, this.vertexConsumers, 15728880, OverlayTexture.NO_OVERLAY);
this.draw();
if (bl) {
Lighting.setupFor3DItems();
}
} catch (Throwable throwable) {
CrashReport crashReport = CrashReport.forThrowable(throwable, "Rendering item");
CrashReportCategory crashReportSection = crashReport.addCategory("Item being rendered");
crashReportSection.setDetail("Item Type", () -> String.valueOf(stack.getItem()));
crashReportSection.setDetail("Item Components", () -> String.valueOf(stack.getComponents()));
crashReportSection.setDetail("Item Foil", () -> String.valueOf(stack.hasFoil()));
throw new ReportedException(crashReport);
}
this.matrices.popPose();
}
// ----------------------------
// Scissor / Clipping
// ----------------------------
@Override
public void enableScissor(int x1, int y1, int x2, int y2) {
ScreenRectangle screenRect = new ScreenRectangle(x1, y1, x2 - x1, y2 - y1)
.transformAxisAligned(matrices.last().pose());
setScissor(scissorStack.push(screenRect));
}
@Override
public void disableScissor() {
setScissor(scissorStack.pop());
}
@Override
public boolean scissorContains(int x, int y) {
return scissorStack.containsPoint(x, y);
}
private void setScissor(@Nullable ScreenRectangle rect) {
draw();
if (rect != null) {
Window window = SaturnClient.client.getWindow();
int framebufferHeight = window.getHeight();
double scaleFactor = window.getGuiScale();
RenderSystem.enableScissor(
(int) (rect.left() * scaleFactor),
(int) (framebufferHeight - rect.bottom() * scaleFactor),
Math.max(0, (int) (rect.width() * scaleFactor)),
Math.max(0, (int) (rect.height() * scaleFactor)));
} else {
RenderSystem.disableScissor();
}
}
static class ScissorStack {
private final Deque<ScreenRectangle> stack = new ArrayDeque<>();
public ScreenRectangle push(ScreenRectangle p_281812_) {
ScreenRectangle screenrectangle = this.stack.peekLast();
if (screenrectangle != null) {
ScreenRectangle screenrectangle1 = Objects.requireNonNullElse(p_281812_.intersection(screenrectangle),
ScreenRectangle.empty());
this.stack.addLast(screenrectangle1);
return screenrectangle1;
} else {
this.stack.addLast(p_281812_);
return p_281812_;
}
}
@Nullable
public ScreenRectangle pop() {
if (this.stack.isEmpty()) {
throw new IllegalStateException("Scissor stack underflow");
} else {
this.stack.removeLast();
return this.stack.peekLast();
}
}
public boolean containsPoint(int p_329411_, int p_333404_) {
return this.stack.isEmpty() ? true : this.stack.peek().containsPoint(p_329411_, p_333404_);
}
}
}
*///?}