Merge pull request 'Build every version with Mojang mappings instead of Yarn' (#49) from mojang-mappings into master

Reviewed-on: #49
This commit was merged in pull request #49.
This commit is contained in:
2026-09-30 16:17:05 +00:00
58 changed files with 1082 additions and 972 deletions
+15 -7
View File
@@ -8,29 +8,37 @@ Every supported Minecraft version (1.21.4 to 1.21.11) builds from one copy of th
- `common/`: all version-independent code (mods, UI, cosmetics, the server client). It has no Minecraft dependency and reaches the game only through the interfaces in `org.saturnclient.common`. - `common/`: all version-independent code (mods, UI, cosmetics, the server client). It has no Minecraft dependency and reaches the game only through the interfaces in `org.saturnclient.common`.
- `src/`: the version-specific code (providers, refs, mixins and the three mixin configs), one copy for every version. Where Minecraft's API differs between versions, the code goes behind version comments (see below). - `src/`: the version-specific code (providers, refs, mixins and the three mixin configs), one copy for every version. Where Minecraft's API differs between versions, the code goes behind version comments (see below).
- `versions/<mc>/`: each version's `gradle.properties` (Minecraft, Yarn, Fabric Loader and Fabric API versions), plus its `build/` and `run/` folders. Each version is the Gradle project `:<mc>`. - `versions/<mc>/`: each version's `gradle.properties` (Minecraft, Fabric Loader and Fabric API versions), plus its `build/` and `run/` folders. Each version is the Gradle project `:<mc>`.
`settings.gradle.kts` lists the versions in `stonecutterVersions`. The root `build.gradle.kts` builds each version, and `stonecutter.gradle.kts` configures the root project (shared repositories, the `common` wiring and `buildAll`). Loom's version is `loom_version` in the root `gradle.properties`. `settings.gradle.kts` lists the versions in `stonecutterVersions`. The root `build.gradle.kts` builds each version, and `stonecutter.gradle.kts` configures the root project (shared repositories, the `common` wiring and `buildAll`). Loom's version is `loom_version` in the root `gradle.properties`.
## Mappings
Every version is built with Mojang's official names (`loom.officialMojangMappings()`), the names Minecraft itself ships from 26.1 on. Yarn isn't used any more: 1.21.11 has the last Yarn release.
Mojang renamed a few classes within 1.21.x. `src/` uses the newest names, and `stonecutter.gradle.kts` lists replacements that swap in the older name when Stonecutter processes an older version (for example `Identifier`, which was `ResourceLocation` before 1.21.11, and `AvatarRenderState`, which was `PlayerRenderState` before 1.21.9). Add a replacement there when a rename touches many lines. A class that only moved package needs just a version comment on its import, and a renamed method a version comment where it's called.
Released jars run on intermediary names (`method_1234`), not Mojang's, and Loom renames everything that refers to Minecraft when it builds them. So a mixin can't implement one of `common`'s Ref interfaces by relying on a vanilla method that happens to have the same name: the vanilla method is renamed in the jar, and the interface method is left without an implementation (`AbstractMethodError`). Shadow the vanilla method and implement the Ref method explicitly, as `WindowMixin` does. For the same reason, Ref methods mustn't share a name and parameters with a method of the class they're mixed into, or the mixin replaces the vanilla method in development.
## Version-specific code with Stonecutter ## Version-specific code with Stonecutter
The code in `src/` is always plain Java for the **active** version (1.21.11, set in `stonecutter.gradle.kts`). Code for other versions sits in comments that Stonecutter swaps before building each version: The code in `src/` is always plain Java for the **active** version (1.21.11, set in `stonecutter.gradle.kts`). Code for other versions sits in comments that Stonecutter swaps before building each version:
```java ```java
//? if >=1.21.9 { //? if >=1.21.9 {
public void render(MatrixStack matrices, OrderedRenderCommandQueue queue, int light, PlayerEntityRenderState state, float limbAngle, float limbDistance) { public void submit(PoseStack matrices, SubmitNodeCollector output, int light, AvatarRenderState state, float limbAngle, float limbDistance) {
//?} else //?} else
//public void render(MatrixStack matrices, VertexConsumerProvider consumers, int light, PlayerEntityRenderState state, float limbAngle, float limbDistance) { //public void render(PoseStack matrices, MultiBufferSource output, int light, AvatarRenderState state, float limbAngle, float limbDistance) {
``` ```
A condition without braces covers the next line only. For several lines, use braces and wrap the inactive block in `/* … */`: A condition without braces covers the next line only. For several lines, use braces and wrap the inactive block in `/* … */`:
```java ```java
//? if >=1.21.11 { //? if >=1.21.11 {
import net.minecraft.client.render.RenderLayers; import net.minecraft.client.renderer.rendertype.RenderTypes;
import net.minecraft.client.render.RenderSetup; import net.minecraft.client.renderer.rendertype.RenderSetup;
//?} else { //?} else {
/*import net.minecraft.client.render.RenderPhase.Textures; /*import net.minecraft.client.renderer.RenderStateShard.MultiTextureStateShard;
*///?} *///?}
``` ```
@@ -62,7 +70,7 @@ For bigger changes, `./gradlew buildAll` builds every version's jar into `build/
## Adding a Minecraft version ## Adding a Minecraft version
1. Create `versions/<new>/gradle.properties` with `minecraft_version`, `yarn_mappings`, `loader_version` and `fabric_api_version` (copy 1.21.11's and change the values; they're listed at <https://fabricmc.net/develop>). Loom's version is shared, in the root `gradle.properties`. 1. Create `versions/<new>/gradle.properties` with `minecraft_version`, `loader_version` and `fabric_api_version` (copy 1.21.11's and change the values; they're listed at <https://fabricmc.net/develop>). Loom's version is shared, in the root `gradle.properties`.
2. Add `<new>` to `stonecutterVersions` in `settings.gradle.kts`. 2. Add `<new>` to `stonecutterVersions` in `settings.gradle.kts`.
3. Build it with `./gradlew :<new>:compileJava` and put what Minecraft changed behind version comments. Check the mixin configs in `src/main/resources/*.mixins.json` as well: a mixin whose target changed fails at startup, not at compile time, so launch it with `./gradlew :<new>:runClient`. 3. Build it with `./gradlew :<new>:compileJava` and put what Minecraft changed behind version comments. Check the mixin configs in `src/main/resources/*.mixins.json` as well: a mixin whose target changed fails at startup, not at compile time, so launch it with `./gradlew :<new>:runClient`.
4. The release workflow builds everything through `buildAll`, and "Publish to Modrinth" takes the game version from each jar's name, so neither needs changing. 4. The release workflow builds everything through `buildAll`, and "Publish to Modrinth" takes the game version from each jar's name, so neither needs changing.
+1 -1
View File
@@ -17,7 +17,7 @@ base {
dependencies { dependencies {
minecraft("com.mojang:minecraft:$minecraftVersion") minecraft("com.mojang:minecraft:$minecraftVersion")
mappings("net.fabricmc:yarn:${property("yarn_mappings")}:v2") mappings(loom.officialMojangMappings())
modImplementation("net.fabricmc:fabric-loader:$loaderVersion") modImplementation("net.fabricmc:fabric-loader:$loaderVersion")
modImplementation("net.fabricmc.fabric-api:fabric-api:${property("fabric_api_version")}") modImplementation("net.fabricmc.fabric-api:fabric-api:${property("fabric_api_version")}")
+1 -1
Submodule common updated: b0d75af8c4...653738568a
+1 -1
View File
@@ -22,7 +22,7 @@ rootProject.name = "saturn-client"
include("common") include("common")
// Versions built by Stonecutter from the shared src/ (see stonecutter.gradle.kts). Each one's // Versions built by Stonecutter from the shared src/ (see stonecutter.gradle.kts). Each one's
// versions/<v>/gradle.properties holds its Minecraft, Yarn and Fabric API versions. // versions/<v>/gradle.properties holds its Minecraft, Fabric Loader and Fabric API versions.
val stonecutterVersions = listOf("1.21.4", "1.21.5", "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10", "1.21.11") val stonecutterVersions = listOf("1.21.4", "1.21.5", "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10", "1.21.11")
stonecutter { stonecutter {
@@ -22,28 +22,30 @@ import org.saturnclient.emotes.fabric.access.BendablePart;
import org.saturnclient.impl.cosmetics.utils.ShaderUtils; import org.saturnclient.impl.cosmetics.utils.ShaderUtils;
import org.saturnclient.saturnclient.SaturnRenderState; import org.saturnclient.saturnclient.SaturnRenderState;
import net.minecraft.client.model.ModelPart; import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.render.VertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer;
//? if >=1.21.9 { //? if >=1.21.9 {
import net.minecraft.client.render.command.OrderedRenderCommandQueue; import net.minecraft.client.renderer.SubmitNodeCollector;
//?} else //?} else
//import net.minecraft.client.render.VertexConsumerProvider; //import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.render.entity.equipment.EquipmentModel; import net.minecraft.client.resources.model.EquipmentClientInfo;
import net.minecraft.client.render.entity.equipment.EquipmentModelLoader; import net.minecraft.client.resources.model.EquipmentAssetManager;
import net.minecraft.client.render.entity.equipment.EquipmentModel.LayerType; import net.minecraft.client.resources.model.EquipmentClientInfo.LayerType;
import net.minecraft.client.render.entity.feature.FeatureRenderer; import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.client.render.entity.feature.FeatureRendererContext; import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.render.entity.model.PlayerEntityModel; //? if >=1.21.11 {
import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.client.model.player.PlayerModel;
import net.minecraft.client.util.math.MatrixStack; //?} else
import net.minecraft.component.DataComponentTypes; //import net.minecraft.client.model.PlayerModel;
import net.minecraft.component.type.EquippableComponent; import net.minecraft.client.renderer.entity.state.AvatarRenderState;
import net.minecraft.item.ItemStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.item.equipment.EquipmentAsset; import net.minecraft.core.component.DataComponents;
import net.minecraft.registry.RegistryKey; import net.minecraft.world.item.equipment.Equippable;
import net.minecraft.util.math.MathHelper; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.item.equipment.EquipmentAsset;
import net.minecraft.resources.ResourceKey;
import net.minecraft.util.Mth;
/** /**
* The cloak renderer * The cloak renderer
@@ -52,8 +54,8 @@ import net.minecraft.util.math.Vec3d;
* - **Curving**: Curves when player velocity increases. * - **Curving**: Curves when player velocity increases.
* - **Wavey**: Makes the cloak feel like wind, when jump sprinting. * - **Wavey**: Makes the cloak feel like wind, when jump sprinting.
*/ */
public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderState, PlayerEntityModel> { public class CloakFeatureRenderer extends RenderLayer<AvatarRenderState, PlayerModel> {
private final EquipmentModelLoader equipmentModelLoader; private final EquipmentAssetManager equipmentModelLoader;
private static final int PARTS = 24; private static final int PARTS = 24;
private final float[] segmentValues = new float[PARTS]; private final float[] segmentValues = new float[PARTS];
private static final int H_PARTS = 6; private static final int H_PARTS = 6;
@@ -96,19 +98,19 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
private static final PxRect TOP_RECT = new PxRect(8, 0, 80, 8); private static final PxRect TOP_RECT = new PxRect(8, 0, 80, 8);
private static final PxRect BOTTOM_RECT = new PxRect(88, 0, 80, 8); private static final PxRect BOTTOM_RECT = new PxRect(88, 0, 80, 8);
public CloakFeatureRenderer(FeatureRendererContext<PlayerEntityRenderState, PlayerEntityModel> context, public CloakFeatureRenderer(RenderLayerParent<AvatarRenderState, PlayerModel> context,
EquipmentModelLoader equipmentModelLoader) { EquipmentAssetManager equipmentModelLoader) {
super(context); super(context);
this.equipmentModelLoader = equipmentModelLoader; this.equipmentModelLoader = equipmentModelLoader;
Arrays.fill(segmentValues, 0.0f); Arrays.fill(segmentValues, 0.0f);
} }
private boolean hasCustomModelForLayer(ItemStack stack, EquipmentModel.LayerType layerType) { private boolean hasCustomModelForLayer(ItemStack stack, EquipmentClientInfo.LayerType layerType) {
EquippableComponent equippableComponent = (EquippableComponent) stack Equippable equippableComponent = (Equippable) stack
.get(DataComponentTypes.EQUIPPABLE); .get(DataComponents.EQUIPPABLE);
if (equippableComponent != null && !equippableComponent.assetId().isEmpty()) { if (equippableComponent != null && !equippableComponent.assetId().isEmpty()) {
EquipmentModel equipmentModel = this.equipmentModelLoader EquipmentClientInfo equipmentModel = this.equipmentModelLoader
.get((RegistryKey<EquipmentAsset>) equippableComponent.assetId().get()); .get((ResourceKey<EquipmentAsset>) equippableComponent.assetId().get());
return !equipmentModel.getLayers(layerType).isEmpty(); return !equipmentModel.getLayers(layerType).isEmpty();
} else { } else {
return false; return false;
@@ -116,7 +118,7 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
} }
private void vertex(VertexConsumer vc, Matrix4f posMat, Matrix3f normalMat, private void vertex(VertexConsumer vc, Matrix4f posMat, Matrix3f normalMat,
Vec3d pos, int color, net.minecraft.world.phys.Vec3 pos, int color,
float u, float v, int overlay, int light, float u, float v, int overlay, int light,
float nx, float ny, float nz) { float nx, float ny, float nz) {
@@ -126,7 +128,7 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
Vector3f n = new Vector3f(nx, ny, nz); Vector3f n = new Vector3f(nx, ny, nz);
n.mul(normalMat); n.mul(normalMat);
vc.vertex( vc.addVertex(
p.x(), p.y(), p.z(), p.x(), p.y(), p.z(),
color, color,
u, v, u, v,
@@ -134,13 +136,13 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
n.x(), n.y(), n.z()); n.x(), n.y(), n.z());
} }
private void renderCapeQuad(VertexConsumer vertexConsumer, MatrixStack.Entry entry, private void renderCapeQuad(VertexConsumer vertexConsumer, PoseStack.Pose entry,
Vec3d bottomLeft, Vec3d bottomRight, Vec3d topRight, Vec3d topLeft, net.minecraft.world.phys.Vec3 bottomLeft, net.minecraft.world.phys.Vec3 bottomRight, net.minecraft.world.phys.Vec3 topRight, net.minecraft.world.phys.Vec3 topLeft,
float u1, float v1, float u2, float v2, int light, int overlay, float u1, float v1, float u2, float v2, int light, int overlay,
float normalX, float normalY, float normalZ, boolean flipWinding) { float normalX, float normalY, float normalZ, boolean flipWinding) {
// Extract matrix (you must transform positions manually now) // Extract matrix (you must transform positions manually now)
Matrix4f pos = entry.getPositionMatrix(); Matrix4f pos = entry.pose();
Matrix3f normalMat = entry.getNormalMatrix(); Matrix3f normalMat = entry.normal();
int color = 0xFFFFFFFF; // white RGBA int color = 0xFFFFFFFF; // white RGBA
@@ -163,8 +165,8 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
} }
} }
private void renderCape(MatrixStack.Entry entry, VertexConsumer vertexConsumer, private void renderCape(PoseStack.Pose entry, VertexConsumer vertexConsumer,
PlayerEntityRenderState playerState, int light, int overlay) { AvatarRenderState playerState, int light, int overlay) {
float capeWidth = 10.0f / 16.0f; float capeWidth = 10.0f / 16.0f;
float capeHeight = 16.0f / 16.0f; float capeHeight = 16.0f / 16.0f;
@@ -226,8 +228,8 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
// 2. Grid // 2. Grid
// ============================= // =============================
Vec3d[][] inner = new Vec3d[H_PARTS + 1][PARTS + 1]; net.minecraft.world.phys.Vec3[][] inner = new net.minecraft.world.phys.Vec3[H_PARTS + 1][PARTS + 1];
Vec3d[][] outer = new Vec3d[H_PARTS + 1][PARTS + 1]; net.minecraft.world.phys.Vec3[][] outer = new net.minecraft.world.phys.Vec3[H_PARTS + 1][PARTS + 1];
for (int x = 0; x <= H_PARTS; x++) { for (int x = 0; x <= H_PARTS; x++) {
@@ -259,8 +261,8 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
float thickY = sinA * capeDepth; float thickY = sinA * capeDepth;
float thickZ = cosA * capeDepth; float thickZ = cosA * capeDepth;
inner[x][i] = new Vec3d(xPos, y - curveY, z - curveZ); inner[x][i] = new net.minecraft.world.phys.Vec3(xPos, y - curveY, z - curveZ);
outer[x][i] = new Vec3d(xPos, (y - curveY) - thickY, (z - curveZ) - thickZ); outer[x][i] = new net.minecraft.world.phys.Vec3(xPos, (y - curveY) - thickY, (z - curveZ) - thickZ);
} }
} }
@@ -285,15 +287,15 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
float bvStart = backV1 + backPartV * i; float bvStart = backV1 + backPartV * i;
float bvEnd = backV1 + backPartV * (i + 1); float bvEnd = backV1 + backPartV * (i + 1);
Vec3d innerTL = inner[x + 1][i]; net.minecraft.world.phys.Vec3 innerTL = inner[x + 1][i];
Vec3d innerTR = inner[x][i]; net.minecraft.world.phys.Vec3 innerTR = inner[x][i];
Vec3d innerBL = inner[x + 1][i + 1]; net.minecraft.world.phys.Vec3 innerBL = inner[x + 1][i + 1];
Vec3d innerBR = inner[x][i + 1]; net.minecraft.world.phys.Vec3 innerBR = inner[x][i + 1];
Vec3d outerTL = outer[x + 1][i]; net.minecraft.world.phys.Vec3 outerTL = outer[x + 1][i];
Vec3d outerTR = outer[x][i]; net.minecraft.world.phys.Vec3 outerTR = outer[x][i];
Vec3d outerBL = outer[x + 1][i + 1]; net.minecraft.world.phys.Vec3 outerBL = outer[x + 1][i + 1];
Vec3d outerBR = outer[x][i + 1]; net.minecraft.world.phys.Vec3 outerBR = outer[x][i + 1];
// FRONT // FRONT
renderCapeQuad(vertexConsumer, entry, renderCapeQuad(vertexConsumer, entry,
@@ -315,10 +317,10 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
for (int i = 0; i < PARTS; i++) { for (int i = 0; i < PARTS; i++) {
Vec3d innerTop = inner[H_PARTS][i]; net.minecraft.world.phys.Vec3 innerTop = inner[H_PARTS][i];
Vec3d innerBot = inner[H_PARTS][i + 1]; net.minecraft.world.phys.Vec3 innerBot = inner[H_PARTS][i + 1];
Vec3d outerTop = outer[H_PARTS][i]; net.minecraft.world.phys.Vec3 outerTop = outer[H_PARTS][i];
Vec3d outerBot = outer[H_PARTS][i + 1]; net.minecraft.world.phys.Vec3 outerBot = outer[H_PARTS][i + 1];
float vStart = leftV1 + leftPartV * i; float vStart = leftV1 + leftPartV * i;
float vEnd = leftV1 + leftPartV * (i + 1); float vEnd = leftV1 + leftPartV * (i + 1);
@@ -336,10 +338,10 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
for (int i = 0; i < PARTS; i++) { for (int i = 0; i < PARTS; i++) {
Vec3d innerTop = inner[0][i]; net.minecraft.world.phys.Vec3 innerTop = inner[0][i];
Vec3d innerBot = inner[0][i + 1]; net.minecraft.world.phys.Vec3 innerBot = inner[0][i + 1];
Vec3d outerTop = outer[0][i]; net.minecraft.world.phys.Vec3 outerTop = outer[0][i];
Vec3d outerBot = outer[0][i + 1]; net.minecraft.world.phys.Vec3 outerBot = outer[0][i + 1];
float vStart = rightV1 + rightPartV * i; float vStart = rightV1 + rightPartV * i;
float vEnd = rightV1 + rightPartV * (i + 1); float vEnd = rightV1 + rightPartV * (i + 1);
@@ -357,10 +359,10 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
for (int x = 0; x < H_PARTS; x++) { for (int x = 0; x < H_PARTS; x++) {
Vec3d outerL = outer[x][0]; net.minecraft.world.phys.Vec3 outerL = outer[x][0];
Vec3d outerR = outer[x + 1][0]; net.minecraft.world.phys.Vec3 outerR = outer[x + 1][0];
Vec3d innerR = inner[x + 1][0]; net.minecraft.world.phys.Vec3 innerR = inner[x + 1][0];
Vec3d innerL = inner[x][0]; net.minecraft.world.phys.Vec3 innerL = inner[x][0];
float uStart = topU1 + (topU2 - topU1) * ((float) x / H_PARTS); float uStart = topU1 + (topU2 - topU1) * ((float) x / H_PARTS);
float uEnd = topU1 + (topU2 - topU1) * ((float) (x + 1) / H_PARTS); float uEnd = topU1 + (topU2 - topU1) * ((float) (x + 1) / H_PARTS);
@@ -377,10 +379,10 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
for (int x = 0; x < H_PARTS; x++) { for (int x = 0; x < H_PARTS; x++) {
Vec3d innerL = inner[x][PARTS]; net.minecraft.world.phys.Vec3 innerL = inner[x][PARTS];
Vec3d innerR = inner[x + 1][PARTS]; net.minecraft.world.phys.Vec3 innerR = inner[x + 1][PARTS];
Vec3d outerR = outer[x + 1][PARTS]; net.minecraft.world.phys.Vec3 outerR = outer[x + 1][PARTS];
Vec3d outerL = outer[x][PARTS]; net.minecraft.world.phys.Vec3 outerL = outer[x][PARTS];
float uStart = bottomU1 + (bottomU2 - bottomU1) * ((float) x / H_PARTS); float uStart = bottomU1 + (bottomU2 - bottomU1) * ((float) x / H_PARTS);
float uEnd = bottomU1 + (bottomU2 - bottomU1) * ((float) (x + 1) / H_PARTS); float uEnd = bottomU1 + (bottomU2 - bottomU1) * ((float) (x + 1) / H_PARTS);
@@ -421,7 +423,7 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
* An emote that bends the torso a little leans the chest from the hips, so the cloak hangs from * An emote that bends the torso a little leans the chest from the hips, so the cloak hangs from
* where the top of the back ends up, turned as much as the torso is there. * where the top of the back ends up, turned as much as the torso is there.
*/ */
private static void followBend(MatrixStack matrices, ModelPart body) { private static void followBend(PoseStack matrices, ModelPart body) {
LimbBend bend = ((BendablePart) (Object) body).saturnEmotes$getBend(); LimbBend bend = ((BendablePart) (Object) body).saturnEmotes$getBend();
if (bend == null || bend.isStraight()) { if (bend == null || bend.isStraight()) {
return; return;
@@ -433,7 +435,7 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
matrices.translate(top[0] / 16.0f, top[1] / 16.0f, top[2] / 16.0f); matrices.translate(top[0] / 16.0f, top[1] / 16.0f, top[2] / 16.0f);
Vec3 axis = bend.axis(); Vec3 axis = bend.axis();
matrices.multiply(new Quaternionf().rotationAxis(bend.angleAt(0), axis.x(), axis.y(), axis.z())); matrices.mulPose(new Quaternionf().rotationAxis(bend.angleAt(0), axis.x(), axis.y(), axis.z()));
} }
// Shift array left and insert new value at the start // Shift array left and insert new value at the start
@@ -450,17 +452,20 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
private long lastUpdate = 0; private long lastUpdate = 0;
@Override @Override
public void render(MatrixStack matrices, //? if >=1.21.9 {
public void submit(PoseStack matrices,
//?} else
//public void render(PoseStack matrices,
//? if >=1.21.9 { //? if >=1.21.9 {
OrderedRenderCommandQueue output, SubmitNodeCollector output,
//?} else //?} else
//VertexConsumerProvider output, //MultiBufferSource output,
int light, PlayerEntityRenderState state, float limbAngle, float limbDistance) { int light, AvatarRenderState state, float limbAngle, float limbDistance) {
if (state.invisible || !state.capeVisible if (state.isInvisible || !state.showCape
//? if >=1.21.9 { //? if >=1.21.9 {
|| state.skinTextures.cape() != null) { || state.skin.cape() != null) {
//?} else //?} else
//|| state.skinTextures.capeTexture() != null) { //|| state.skin.capeTexture() != null) {
return; return;
} }
@@ -475,7 +480,7 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
IdentifierRef customCape = Cloaks.getCurrentCloakTexture(player.cloak); IdentifierRef customCape = Cloaks.getCurrentCloakTexture(player.cloak);
if (customCape == null if (customCape == null
|| this.hasCustomModelForLayer(state.equippedChestStack, LayerType.WINGS)) { || this.hasCustomModelForLayer(state.chestEquipment, LayerType.WINGS)) {
return; return;
} }
@@ -487,33 +492,33 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
skyLight = Math.max(skyLight, minBrightness); skyLight = Math.max(skyLight, minBrightness);
light = (skyLight << 20) | (blockLight << 4); light = (skyLight << 20) | (blockLight << 4);
matrices.push(); matrices.pushPose();
// On the back: the whole player (which emotes like the backflip turn), then the body's position // On the back: the whole player (which emotes like the backflip turn), then the body's position
// and turn (which crouching and emotes move), then the chest's lean when an emote bends the torso // and turn (which crouching and emotes move), then the chest's lean when an emote bends the torso
PlayerEntityModel model = this.getContextModel(); PlayerModel model = this.getParentModel();
//? if >=1.21.5 { //? if >=1.21.5 {
model.getRootPart().applyTransform(matrices); model.root().translateAndRotate(matrices);
model.body.applyTransform(matrices); model.body.translateAndRotate(matrices);
//?} else { //?} else {
/*model.getRootPart().rotate(matrices); /*model.root().translateAndRotate(matrices);
model.body.rotate(matrices); model.body.translateAndRotate(matrices);
*///?} *///?}
followBend(matrices, model.body); followBend(matrices, model.body);
matrices.translate(0.0f, 0.0f, 0.12f); matrices.translate(0.0f, 0.0f, 0.12f);
if (this.hasCustomModelForLayer(state.equippedChestStack, LayerType.HUMANOID)) { if (this.hasCustomModelForLayer(state.chestEquipment, LayerType.HUMANOID)) {
matrices.translate(0.0F, -0.053125F, 0.06875F); matrices.translate(0.0F, -0.053125F, 0.06875F);
} }
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
if (now - lastUpdate >= 20) { if (now - lastUpdate >= 20) {
float velX = Math.min(0.8f, state.field_53537 / 108.0f); float velX = Math.min(0.8f, state.capeLean / 108.0f);
float rawVelY = state.field_53536; float rawVelY = state.capeFlap;
float velY = (rawVelY > 3.4f ? rawVelY : rawVelY < -3.4f ? rawVelY : 0.0f) / 16; float velY = (rawVelY > 3.4f ? rawVelY : rawVelY < -3.4f ? rawVelY : 0.0f) / 16;
float value = Math.max(0.0f, Math.min(2.0f, state.isSwimming ? 0.0f : velX + velY)); float value = Math.max(0.0f, Math.min(2.0f, state.isVisuallySwimming ? 0.0f : velX + velY));
if (Config.cloakPhysics.value) { if (Config.cloakPhysics.value) {
updateSegmentValues(segmentValues[0] + (value - segmentValues[0]) * 0.3f); updateSegmentValues(segmentValues[0] + (value - segmentValues[0]) * 0.3f);
@@ -525,15 +530,15 @@ public class CloakFeatureRenderer extends FeatureRenderer<PlayerEntityRenderStat
final int l = light; final int l = light;
horizontalCurve = MathHelper.clamp(state.field_53537 / 150.0f, -1.0f, 1.0f); horizontalCurve = Mth.clamp(state.capeLean / 150.0f, -1.0f, 1.0f);
//? if >=1.21.9 { //? if >=1.21.9 {
output.submitCustom(matrices, ShaderUtils.getRenderLayer(customCape), (entry, vertexConsumer) -> { output.submitCustomGeometry(matrices, ShaderUtils.getRenderLayer(customCape), (entry, vertexConsumer) -> {
renderCape(entry, vertexConsumer, state, l, OverlayTexture.DEFAULT_UV); renderCape(entry, vertexConsumer, state, l, OverlayTexture.NO_OVERLAY);
}); });
//?} else //?} else
//renderCape(matrices.peek(), output.getBuffer(ShaderUtils.getRenderLayer(customCape)), state, l, OverlayTexture.DEFAULT_UV); //renderCape(matrices.last(), output.getBuffer(ShaderUtils.getRenderLayer(customCape)), state, l, OverlayTexture.NO_OVERLAY);
matrices.pop(); matrices.popPose();
} }
} }
@@ -5,55 +5,61 @@ import org.saturnclient.impl.cosmetics.obj.MtlLoader;
import org.saturnclient.impl.cosmetics.obj.ObjModel; import org.saturnclient.impl.cosmetics.obj.ObjModel;
import org.saturnclient.saturnclient.SaturnRenderState; import org.saturnclient.saturnclient.SaturnRenderState;
import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
//? if >=1.21.9 { //? if >=1.21.9 {
import net.minecraft.client.render.command.OrderedRenderCommandQueue; import net.minecraft.client.renderer.SubmitNodeCollector;
//?} else //?} else
//import net.minecraft.client.render.VertexConsumerProvider; //import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.render.entity.feature.FeatureRenderer; import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.client.render.entity.feature.FeatureRendererContext; import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.render.entity.model.PlayerEntityModel; //? if >=1.21.11 {
import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.client.model.player.PlayerModel;
import net.minecraft.client.util.math.MatrixStack; //?} else
//import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.renderer.entity.state.AvatarRenderState;
import com.mojang.blaze3d.vertex.PoseStack;
public class HatFeatureRenderer extends FeatureRenderer<PlayerEntityRenderState, PlayerEntityModel> { public class HatFeatureRenderer extends RenderLayer<AvatarRenderState, PlayerModel> {
public HatFeatureRenderer(FeatureRendererContext<PlayerEntityRenderState, PlayerEntityModel> context) { public HatFeatureRenderer(RenderLayerParent<AvatarRenderState, PlayerModel> context) {
super(context); super(context);
} }
@Override @Override
public void render(MatrixStack matrices, //? if >=1.21.9 {
public void submit(PoseStack matrices,
//?} else
//public void render(PoseStack matrices,
//? if >=1.21.9 { //? if >=1.21.9 {
OrderedRenderCommandQueue output, SubmitNodeCollector output,
//?} else //?} else
//VertexConsumerProvider output, //MultiBufferSource output,
int light, PlayerEntityRenderState state, float limbAngle, float limbDistance) { int light, AvatarRenderState state, float limbAngle, float limbDistance) {
//? if >=1.21.8 { //? if >=1.21.8 {
SaturnPlayer player = state.getData(SaturnRenderState.saturnDataKey); SaturnPlayer player = state.getData(SaturnRenderState.saturnDataKey);
//?} else //?} else
//SaturnPlayer player = SaturnPlayer.get(state.name); //SaturnPlayer player = SaturnPlayer.get(state.name);
if (state.invisible || player == null || player.hat.isEmpty()) { if (state.isInvisible || player == null || player.hat.isEmpty()) {
return; return;
} }
matrices.push(); matrices.pushPose();
// On the head, as vanilla places head items: the whole player (which emotes like the backflip // On the head, as vanilla places head items: the whole player (which emotes like the backflip
// turn), then the head's position, turn and scale (which crouching and emotes move) // turn), then the head's position, turn and scale (which crouching and emotes move)
PlayerEntityModel model = this.getContextModel(); PlayerModel model = this.getParentModel();
//? if >=1.21.5 { //? if >=1.21.5 {
model.getRootPart().applyTransform(matrices); model.root().translateAndRotate(matrices);
model.head.applyTransform(matrices); model.head.translateAndRotate(matrices);
//?} else { //?} else {
/*model.getRootPart().rotate(matrices); /*model.root().translateAndRotate(matrices);
model.head.rotate(matrices); model.head.translateAndRotate(matrices);
*///?} *///?}
ObjModel.cosmetic("hat", player.hat).render(MtlLoader.cosmetic(player.hat), ObjModel.cosmetic("hat", player.hat).render(MtlLoader.cosmetic(player.hat),
matrices, output, light, matrices, output, light,
OverlayTexture.DEFAULT_UV); OverlayTexture.NO_OVERLAY);
matrices.pop(); matrices.popPose();
} }
} }
@@ -8,15 +8,15 @@ import java.util.Map;
import de.javagl.obj.*; import de.javagl.obj.*;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
public class MtlLoader { public class MtlLoader {
static Map<Identifier, Map<String, Mtl>> loadedMtls = new HashMap<>(); static Map<Identifier, Map<String, Mtl>> loadedMtls = new HashMap<>();
static Map<String, Mtl> loadMtl(Identifier mtlId) throws IOException { static Map<String, Mtl> loadMtl(Identifier mtlId) throws IOException {
try (InputStream is = MinecraftClient.getInstance().getResourceManager() try (InputStream is = Minecraft.getInstance().getResourceManager()
.getResource(mtlId).get().getInputStream()) { .getResource(mtlId).get().open()) {
List<Mtl> mtlList = MtlReader.read(is); List<Mtl> mtlList = MtlReader.read(is);
Map<String, Mtl> mtlMap = new java.util.LinkedHashMap<>(); Map<String, Mtl> mtlMap = new java.util.LinkedHashMap<>();
for (Mtl mtl : mtlList) { for (Mtl mtl : mtlList) {
@@ -51,6 +51,6 @@ public class MtlLoader {
if (mtlId.isEmpty()) if (mtlId.isEmpty())
mtlId = "white"; mtlId = "white";
return of(Identifier.of("saturnclient", "models/cosmetic/materials/" + mtlId + ".mtl")); return of(Identifier.fromNamespaceAndPath("saturnclient", "models/cosmetic/materials/" + mtlId + ".mtl"));
} }
} }
@@ -12,15 +12,15 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import de.javagl.obj.Mtl; import de.javagl.obj.Mtl;
import de.javagl.obj.Obj; import de.javagl.obj.Obj;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
//? if >=1.21.9 { //? if >=1.21.9 {
import net.minecraft.client.render.command.OrderedRenderCommandQueue; import net.minecraft.client.renderer.SubmitNodeCollector;
//?} else //?} else
//import net.minecraft.client.render.VertexConsumerProvider; //import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.util.math.MatrixStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.resource.Resource; import net.minecraft.server.packs.resources.Resource;
import net.minecraft.resource.ResourceManager; import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
public class ObjModel { public class ObjModel {
private static final ObjectMapper MAPPER = new ObjectMapper(); private static final ObjectMapper MAPPER = new ObjectMapper();
@@ -46,7 +46,7 @@ public class ObjModel {
Config config; Config config;
public static ObjModel cosmetic(String cosmeticKind, String id) { public static ObjModel cosmetic(String cosmeticKind, String id) {
return of(Identifier.of("saturnclient", "models/cosmetic/" + cosmeticKind + "/" + id.split("_")[0] + "/model")); return of(Identifier.fromNamespaceAndPath("saturnclient", "models/cosmetic/" + cosmeticKind + "/" + id.split("_")[0] + "/model"));
} }
public static ObjModel of(Identifier obj) { public static ObjModel of(Identifier obj) {
@@ -59,8 +59,8 @@ public class ObjModel {
} }
ObjModel(Identifier identifier) { ObjModel(Identifier identifier) {
Identifier objId = Identifier.of(identifier.getNamespace(), identifier.getPath() + ".obj"); Identifier objId = Identifier.fromNamespaceAndPath(identifier.getNamespace(), identifier.getPath() + ".obj");
Identifier jsonId = Identifier.of(identifier.getNamespace(), identifier.getPath() + ".json"); Identifier jsonId = Identifier.fromNamespaceAndPath(identifier.getNamespace(), identifier.getPath() + ".json");
try { try {
this.obj = ObjRenderer.loadObj(objId); this.obj = ObjRenderer.loadObj(objId);
@@ -69,11 +69,11 @@ public class ObjModel {
} }
// Try loading JSON config if it exists // Try loading JSON config if it exists
ResourceManager resourceManager = MinecraftClient.getInstance().getResourceManager(); ResourceManager resourceManager = Minecraft.getInstance().getResourceManager();
Optional<Resource> resource = resourceManager.getResource(jsonId); Optional<Resource> resource = resourceManager.getResource(jsonId);
if (resource.isPresent()) { if (resource.isPresent()) {
try (InputStream stream = resource.get().getInputStream()) { try (InputStream stream = resource.get().open()) {
this.config = MAPPER.readValue(stream, Config.class); this.config = MAPPER.readValue(stream, Config.class);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -81,29 +81,29 @@ public class ObjModel {
} }
} }
public void render(Map<String, Mtl> mtlMap, MatrixStack matrices, public void render(Map<String, Mtl> mtlMap, PoseStack matrices,
//? if >=1.21.9 { //? if >=1.21.9 {
OrderedRenderCommandQueue output, SubmitNodeCollector output,
//?} else //?} else
//VertexConsumerProvider output, //MultiBufferSource output,
int light, int overlay) { int light, int overlay) {
matrices.push(); matrices.pushPose();
matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_X.rotationDegrees(180.0f)); matrices.mulPose(com.mojang.math.Axis.XP.rotationDegrees(180.0f));
matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Y.rotationDegrees(180.0f)); matrices.mulPose(com.mojang.math.Axis.YP.rotationDegrees(180.0f));
if (this.config != null) { if (this.config != null) {
matrices.translate(config.transform.x, config.transform.y, config.transform.z); matrices.translate(config.transform.x, config.transform.y, config.transform.z);
matrices.scale(config.scale.x, config.scale.y, config.scale.z); matrices.scale(config.scale.x, config.scale.y, config.scale.z);
matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_X.rotationDegrees(config.rotation.x)); matrices.mulPose(com.mojang.math.Axis.XP.rotationDegrees(config.rotation.x));
matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Y.rotationDegrees(config.rotation.y)); matrices.mulPose(com.mojang.math.Axis.YP.rotationDegrees(config.rotation.y));
matrices.multiply(net.minecraft.util.math.RotationAxis.POSITIVE_Z.rotationDegrees(config.rotation.z)); matrices.mulPose(com.mojang.math.Axis.ZP.rotationDegrees(config.rotation.z));
} }
ObjRenderer.renderObj(this.obj, mtlMap, matrices, output, light, overlay); ObjRenderer.renderObj(this.obj, mtlMap, matrices, output, light, overlay);
matrices.pop(); matrices.popPose();
} }
} }
@@ -9,32 +9,35 @@ import org.saturnclient.impl.cosmetics.utils.ShaderUtils;
import de.javagl.obj.*; import de.javagl.obj.*;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import net.minecraft.client.render.RenderLayer; //? if >=1.21.11 {
import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.renderer.rendertype.RenderType;
//? if >=1.21.9 {
import net.minecraft.client.render.command.OrderedRenderCommandQueue;
//?} else //?} else
//import net.minecraft.client.render.VertexConsumerProvider; //import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.util.math.MatrixStack; import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.util.Identifier; //? if >=1.21.9 {
import net.minecraft.client.renderer.SubmitNodeCollector;
//?} else
//import net.minecraft.client.renderer.MultiBufferSource;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.resources.Identifier;
public class ObjRenderer { public class ObjRenderer {
public static Obj loadObj(Identifier objId) throws IOException { public static Obj loadObj(Identifier objId) throws IOException {
try (InputStream is = MinecraftClient.getInstance().getResourceManager() try (InputStream is = Minecraft.getInstance().getResourceManager()
.getResource(objId).get().getInputStream()) { .getResource(objId).get().open()) {
return ObjReader.read(is); return ObjReader.read(is);
} }
} }
public static void renderObj(Obj obj, public static void renderObj(Obj obj,
Map<String, Mtl> mtlMap, Map<String, Mtl> mtlMap,
MatrixStack matrices, PoseStack matrices,
//? if >=1.21.9 { //? if >=1.21.9 {
OrderedRenderCommandQueue output, SubmitNodeCollector output,
//?} else //?} else
//VertexConsumerProvider output, //MultiBufferSource output,
int light, int light,
int overlay) { int overlay) {
@@ -65,20 +68,20 @@ public class ObjRenderer {
} }
} }
RenderLayer layer = ShaderUtils.getRenderLayer(texture); RenderType layer = ShaderUtils.getRenderLayer(texture);
final float fr = r, fg = g, fb = b; final float fr = r, fg = g, fb = b;
final Obj finalObj = groupObj; final Obj finalObj = groupObj;
//? if >=1.21.9 { //? if >=1.21.9 {
output.submitCustom(matrices, layer, output.submitCustomGeometry(matrices, layer,
(entry, consumer) -> drawGroup(finalObj, consumer, entry, light, overlay, fr, fg, fb)); (entry, consumer) -> drawGroup(finalObj, consumer, entry, light, overlay, fr, fg, fb));
//?} else //?} else
//drawGroup(finalObj, output.getBuffer(layer), matrices.peek(), light, overlay, fr, fg, fb); //drawGroup(finalObj, output.getBuffer(layer), matrices.last(), light, overlay, fr, fg, fb);
} }
} }
private static void drawGroup(Obj obj, VertexConsumer consumer, MatrixStack.Entry entry, int light, int overlay, private static void drawGroup(Obj obj, VertexConsumer consumer, PoseStack.Pose entry, int light, int overlay,
float r, float g, float b) { float r, float g, float b) {
int faces = obj.getNumFaces(); int faces = obj.getNumFaces();
@@ -93,7 +96,7 @@ public class ObjRenderer {
} }
private static void writeVertex(Obj obj, ObjFace face, int index, VertexConsumer consumer, private static void writeVertex(Obj obj, ObjFace face, int index, VertexConsumer consumer,
MatrixStack.Entry matrix, int light, int overlay, PoseStack.Pose matrix, int light, int overlay,
float r, float g, float b) { float r, float g, float b) {
FloatTuple pos = obj.getVertex(face.getVertexIndex(index)); FloatTuple pos = obj.getVertex(face.getVertexIndex(index));
@@ -118,11 +121,11 @@ public class ObjRenderer {
v = 1f - tc.getY(); // Flip V: OBJ bottom-left origin -> Minecraft top-left v = 1f - tc.getY(); // Flip V: OBJ bottom-left origin -> Minecraft top-left
} }
consumer.vertex(matrix, x, y, z) consumer.addVertex(matrix, x, y, z)
.color(r, g, b, 1f) .setColor(r, g, b, 1f)
.texture(u, v) .setUv(u, v)
.overlay(overlay) .setOverlay(overlay)
.light(light) .setLight(light)
.normal(matrix, nx, ny, nz); .setNormal(matrix, nx, ny, nz);
} }
} }
@@ -3,9 +3,9 @@ package org.saturnclient.impl.cosmetics.utils;
import org.saturnclient.common.ref.asset.IdentifierRef; import org.saturnclient.common.ref.asset.IdentifierRef;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.texture.NativeImage; import com.mojang.blaze3d.platform.NativeImage;
import net.minecraft.client.texture.NativeImageBackedTexture; import net.minecraft.client.renderer.texture.DynamicTexture;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt; import java.awt.image.DataBufferInt;
@@ -28,7 +28,7 @@ public class IdentifierUtils {
int index = 0; int index = 0;
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
nativeImage.setColorArgb(x, y, pixels[index++]); nativeImage.setPixel(x, y, pixels[index++]);
} }
} }
@@ -36,7 +36,7 @@ public class IdentifierUtils {
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
nativeImage.setColorArgb(x, y, bufferedImage.getRGB(x, y)); nativeImage.setPixel(x, y, bufferedImage.getRGB(x, y));
} }
} }
@@ -44,13 +44,13 @@ public class IdentifierUtils {
SaturnClient.client.execute(() -> { SaturnClient.client.execute(() -> {
//? if >=1.21.5 { //? if >=1.21.5 {
NativeImageBackedTexture texture = new NativeImageBackedTexture( DynamicTexture texture = new DynamicTexture(
() -> identifier.toString(), () -> identifier.toString(),
nativeImage); nativeImage);
//?} else //?} else
//NativeImageBackedTexture texture = new NativeImageBackedTexture(nativeImage); //DynamicTexture texture = new DynamicTexture(nativeImage);
SaturnClient.client.getTextureManager().registerTexture(identifier, texture); SaturnClient.client.getTextureManager().register(identifier, texture);
}); });
} catch (Exception e) { } catch (Exception e) {
@@ -7,29 +7,32 @@ import org.saturnclient.cosmetics.utils.GifUtils;
import com.mojang.blaze3d.pipeline.RenderPipeline; import com.mojang.blaze3d.pipeline.RenderPipeline;
//? if >=1.21.5 //? if >=1.21.5
import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.client.render.RenderLayer; //? if >=1.21.11 {
import net.minecraft.client.renderer.rendertype.RenderType;
//?} else
//import net.minecraft.client.renderer.RenderType;
//? if <1.21.5 { //? if <1.21.5 {
/*import net.minecraft.client.render.RenderPhase; /*import net.minecraft.client.renderer.RenderStateShard;
import net.minecraft.client.render.VertexFormat.DrawMode; import com.mojang.blaze3d.vertex.VertexFormat.Mode;
import net.minecraft.client.render.VertexFormats; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
*///?} *///?}
//? if >=1.21.11 { //? if >=1.21.11 {
import net.minecraft.client.render.RenderLayers; import net.minecraft.client.renderer.rendertype.RenderTypes;
import net.minecraft.client.render.RenderSetup; import net.minecraft.client.renderer.rendertype.RenderSetup;
import net.minecraft.client.render.block.entity.AbstractEndPortalBlockEntityRenderer; import net.minecraft.client.renderer.blockentity.AbstractEndPortalRenderer;
//?} else { //?} else {
/*import net.minecraft.client.render.RenderPhase.Textures; /*import net.minecraft.client.renderer.RenderStateShard.MultiTextureStateShard;
import net.minecraft.client.render.block.entity.EndPortalBlockEntityRenderer; import net.minecraft.client.renderer.blockentity.TheEndPortalRenderer;
*///?} *///?}
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
public class ShaderUtils { public class ShaderUtils {
// Render pipelines exist from 1.21.5; before that the layer names a shader program directly. // Render pipelines exist from 1.21.5; before that the layer names a shader program directly.
//? if >=1.21.5 { //? if >=1.21.5 {
public static final RenderPipeline END_GATEWAY_PIPELINE = RenderPipelines.register( public static final RenderPipeline END_GATEWAY_PIPELINE = RenderPipelines.register(
RenderPipeline.builder(new RenderPipeline.Snippet[] { RenderPipeline.builder(new RenderPipeline.Snippet[] {
RenderPipelines.RENDERTYPE_END_PORTAL_SNIPPET }) RenderPipelines.END_PORTAL_SNIPPET })
.withLocation("pipeline/end_gateway") .withLocation("pipeline/end_gateway")
.withShaderDefine("PORTAL_LAYERS", 16) .withShaderDefine("PORTAL_LAYERS", 16)
.withCull(false) .withCull(false)
@@ -37,43 +40,43 @@ public class ShaderUtils {
//?} //?}
//? if >=1.21.11 { //? if >=1.21.11 {
public static final RenderLayer END_GATEWAY = RenderLayer.of("end_gateway", public static final RenderType END_GATEWAY = RenderType.create("end_gateway",
RenderSetup.builder(END_GATEWAY_PIPELINE) RenderSetup.builder(END_GATEWAY_PIPELINE)
.texture("Sampler0", AbstractEndPortalBlockEntityRenderer.SKY_TEXTURE) .withTexture("Sampler0", AbstractEndPortalRenderer.END_SKY_LOCATION)
.texture("Sampler1", AbstractEndPortalBlockEntityRenderer.PORTAL_TEXTURE).build()); .withTexture("Sampler1", AbstractEndPortalRenderer.END_PORTAL_LOCATION).createRenderSetup());
//?} else if >=1.21.6 { //?} else if >=1.21.6 {
/*public static final RenderLayer END_GATEWAY = RenderLayer.of("end_gateway", 1536, false, false, /*public static final RenderType END_GATEWAY = RenderType.create("end_gateway", 1536, false, false,
END_GATEWAY_PIPELINE, END_GATEWAY_PIPELINE,
RenderLayer.MultiPhaseParameters.builder() RenderType.CompositeState.builder()
.texture(Textures.create().add(EndPortalBlockEntityRenderer.SKY_TEXTURE, false) .setTextureState(MultiTextureStateShard.builder().add(TheEndPortalRenderer.END_SKY_LOCATION, false)
.add(EndPortalBlockEntityRenderer.PORTAL_TEXTURE, false).build()) .add(TheEndPortalRenderer.END_PORTAL_LOCATION, false).build())
.build(false)); .createCompositeState(false));
*///?} else if >=1.21.5 { *///?} else if >=1.21.5 {
/*public static final RenderLayer END_GATEWAY = RenderLayer.of("end_gateway", 1536, false, false, /*public static final RenderType END_GATEWAY = RenderType.create("end_gateway", 1536, false, false,
END_GATEWAY_PIPELINE, END_GATEWAY_PIPELINE,
RenderLayer.MultiPhaseParameters.builder() RenderType.CompositeState.builder()
.texture(Textures.create().add(EndPortalBlockEntityRenderer.SKY_TEXTURE, false, false) .setTextureState(MultiTextureStateShard.builder().add(TheEndPortalRenderer.END_SKY_LOCATION, false, false)
.add(EndPortalBlockEntityRenderer.PORTAL_TEXTURE, false, false).build()) .add(TheEndPortalRenderer.END_PORTAL_LOCATION, false, false).build())
.build(false)); .createCompositeState(false));
*///?} else { *///?} else {
/*public static final RenderLayer END_GATEWAY = RenderLayer.of( /*public static final RenderType END_GATEWAY = RenderType.create(
"end_gateway", "end_gateway",
VertexFormats.POSITION, DefaultVertexFormat.POSITION,
DrawMode.QUADS, Mode.QUADS,
1536, 1536,
false, false,
false, false,
RenderLayer.MultiPhaseParameters.builder() RenderType.CompositeState.builder()
.program(RenderLayer.END_GATEWAY_PROGRAM) .setShaderState(RenderType.RENDERTYPE_END_GATEWAY_SHADER)
.texture(Textures.create() .setTextureState(MultiTextureStateShard.builder()
.add(EndPortalBlockEntityRenderer.SKY_TEXTURE, false, false) .add(TheEndPortalRenderer.END_SKY_LOCATION, false, false)
.add(EndPortalBlockEntityRenderer.PORTAL_TEXTURE, false, false) .add(TheEndPortalRenderer.END_PORTAL_LOCATION, false, false)
.build()) .build())
.cull(RenderPhase.DISABLE_CULLING) .setCullState(RenderStateShard.NO_CULL)
.build(false)); .createCompositeState(false));
*///?} *///?}
public static RenderLayer getRenderLayer(IdentifierRef texture) { public static RenderType getRenderLayer(IdentifierRef texture) {
String path = texture.toString(); String path = texture.toString();
if (path.endsWith(".gif")) { if (path.endsWith(".gif")) {
return entityAlpha((Identifier) (Object) GifUtils.get(texture)); return entityAlpha((Identifier) (Object) GifUtils.get(texture));
@@ -84,10 +87,10 @@ public class ShaderUtils {
} }
} }
private static RenderLayer entityAlpha(Identifier texture) { private static RenderType entityAlpha(Identifier texture) {
//? if >=1.21.11 { //? if >=1.21.11 {
return RenderLayers.entityAlpha(texture); return RenderTypes.dragonExplosionAlpha(texture);
//?} else //?} else
//return RenderLayer.getEntityAlpha(texture); //return RenderType.dragonExplosionAlpha(texture);
} }
} }
@@ -2,11 +2,11 @@ package org.saturnclient.impl.features.entity;
import org.saturnclient.common.feature.EntityFeature; import org.saturnclient.common.feature.EntityFeature;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.util.hit.EntityHitResult; import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.util.hit.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
/** /**
* Fabric implementation of {@link EntityFeature}. * Fabric implementation of {@link EntityFeature}.
@@ -18,15 +18,15 @@ import net.minecraft.entity.LivingEntity;
*/ */
public class EntityFeatureImpl implements EntityFeature { public class EntityFeatureImpl implements EntityFeature {
private final MinecraftClient mc; private final Minecraft mc;
public EntityFeatureImpl(MinecraftClient mc) { public EntityFeatureImpl(Minecraft mc) {
this.mc = mc; this.mc = mc;
} }
@Override @Override
public boolean isTargetingLivingEntity() { public boolean isTargetingLivingEntity() {
HitResult target = mc.crosshairTarget; HitResult target = mc.hitResult;
if (target == null || target.getType() != HitResult.Type.ENTITY) if (target == null || target.getType() != HitResult.Type.ENTITY)
return false; return false;
Entity hit = ((EntityHitResult) target).getEntity(); Entity hit = ((EntityHitResult) target).getEntity();
@@ -10,13 +10,13 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.render.Camera; import net.minecraft.client.Camera;
import net.minecraft.entity.Entity; import net.minecraft.world.entity.Entity;
//? if >=1.21.11 { //? if >=1.21.11 {
import net.minecraft.world.World; import net.minecraft.world.level.Level;
//?} else //?} else
//import net.minecraft.world.BlockView; //import net.minecraft.world.level.BlockGetter;
@Mixin(Camera.class) @Mixin(Camera.class)
public abstract class CameraMixin { public abstract class CameraMixin {
@@ -26,30 +26,30 @@ public abstract class CameraMixin {
@Shadow @Shadow
protected abstract void setRotation(float yaw, float pitch); protected abstract void setRotation(float yaw, float pitch);
@Inject(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;setRotation(FF)V", ordinal = 1, shift = At.Shift.AFTER)) @Inject(method = "setup", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;setRotation(FF)V", ordinal = 1, shift = At.Shift.AFTER))
public void lockRotation( public void lockRotation(
//? if >=1.21.11 { //? if >=1.21.11 {
World focusedBlock, Level focusedBlock,
//?} else //?} else
//BlockView focusedBlock, //BlockGetter focusedBlock,
Entity cameraEntity, Entity cameraEntity,
boolean isThirdPerson, boolean isThirdPerson,
boolean isFrontFacing, boolean isFrontFacing,
float tickDelta, float tickDelta,
CallbackInfo ci) { CallbackInfo ci) {
if (FreelookMod.isFreeLooking() && cameraEntity instanceof ClientPlayerEntity) { if (FreelookMod.isFreeLooking() && cameraEntity instanceof LocalPlayer) {
CameraOverriddenEntity cameraOverriddenEntity = (CameraOverriddenEntity) cameraEntity; CameraOverriddenEntity cameraOverriddenEntity = (CameraOverriddenEntity) cameraEntity;
if (firstTime && SaturnClient.client.player != null) { if (firstTime && SaturnClient.client.player != null) {
cameraOverriddenEntity.freelook$setCameraPitch(SaturnClient.client.player.getPitch()); cameraOverriddenEntity.freelook$setCameraPitch(SaturnClient.client.player.getXRot());
cameraOverriddenEntity.freelook$setCameraYaw(SaturnClient.client.player.getYaw()); cameraOverriddenEntity.freelook$setCameraYaw(SaturnClient.client.player.getYRot());
firstTime = false; firstTime = false;
} }
this.setRotation(cameraOverriddenEntity.freelook$getCameraYaw(), this.setRotation(cameraOverriddenEntity.freelook$getCameraYaw(),
cameraOverriddenEntity.freelook$getCameraPitch()); cameraOverriddenEntity.freelook$getCameraPitch());
} }
if (!FreelookMod.isFreeLooking() && cameraEntity instanceof ClientPlayerEntity) { if (!FreelookMod.isFreeLooking() && cameraEntity instanceof LocalPlayer) {
firstTime = true; firstTime = true;
} }
} }
@@ -8,9 +8,9 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.Mth;
@Mixin(Entity.class) @Mixin(Entity.class)
public class EntityMixin implements CameraOverriddenEntity { public class EntityMixin implements CameraOverriddenEntity {
@@ -20,15 +20,15 @@ public class EntityMixin implements CameraOverriddenEntity {
@Unique @Unique
private float cameraYaw; private float cameraYaw;
@Inject(method = "changeLookDirection", at = @At("HEAD"), cancellable = true) @Inject(method = "turn", at = @At("HEAD"), cancellable = true)
public void changeCameraLookDirection(double xDelta, double yDelta, CallbackInfo ci) { public void changeCameraLookDirection(double xDelta, double yDelta, CallbackInfo ci) {
// noinspection ConstantValue// IntelliJ is incorrect here, this code block is // noinspection ConstantValue// IntelliJ is incorrect here, this code block is
// reachable // reachable
if (FreelookMod.isFreeLooking() && (Object) this instanceof ClientPlayerEntity) { if (FreelookMod.isFreeLooking() && (Object) this instanceof LocalPlayer) {
double pitchDelta = (yDelta * 0.15); double pitchDelta = (yDelta * 0.15);
double yawDelta = (xDelta * 0.15); double yawDelta = (xDelta * 0.15);
this.cameraPitch = MathHelper.clamp(this.cameraPitch + (float) pitchDelta, -90.0f, 90.0f); this.cameraPitch = Mth.clamp(this.cameraPitch + (float) pitchDelta, -90.0f, 90.0f);
this.cameraYaw += (float) yawDelta; this.cameraYaw += (float) yawDelta;
ci.cancel(); ci.cancel();
@@ -1,22 +1,19 @@
package org.saturnclient.impl.features.mixins.render; package org.saturnclient.impl.features.mixins.render;
//? if >=1.21.6 { //? if >=1.21.6 {
import net.minecraft.client.render.fog.FogRenderer; import net.minecraft.client.renderer.fog.FogRenderer;
//?} else //?} else
//import net.minecraft.client.render.BackgroundRenderer; //import net.minecraft.client.renderer.FogRenderer;
import org.saturnclient.mod.mods.NoFogMod; import org.saturnclient.mod.mods.NoFogMod;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.ModifyVariable;
//? if >=1.21.6 {
@Mixin(FogRenderer.class) @Mixin(FogRenderer.class)
//?} else
//@Mixin(BackgroundRenderer.class)
public class BackgroundRendererMixin { public class BackgroundRendererMixin {
// fog // fog
@ModifyVariable(method = "applyFog", at = @At("HEAD"), ordinal = 0, argsOnly = true) @ModifyVariable(method = "setupFog", at = @At("HEAD"), ordinal = 0, argsOnly = true)
private static float modifyFogStart(float viewDistance) { private static float modifyFogStart(float viewDistance) {
if (NoFogMod.isActive()) { if (NoFogMod.isActive()) {
return viewDistance * 2.0f; return viewDistance * 2.0f;
@@ -1,10 +1,10 @@
package org.saturnclient.impl.features.mixins.render; package org.saturnclient.impl.features.mixins.render;
//? if >=1.21.6 //? if >=1.21.6
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
//? if >=1.21.6 //? if >=1.21.6
import net.minecraft.client.option.GameOptions; import net.minecraft.client.Options;
import net.minecraft.client.render.GameRenderer; import net.minecraft.client.renderer.GameRenderer;
//? if >=1.21.6 //? if >=1.21.6
import org.saturnclient.impl.ui.SaturnScreenFabric; import org.saturnclient.impl.ui.SaturnScreenFabric;
@@ -51,13 +51,13 @@ public class GameRendererMixin {
// From 1.21.6 the menu blur's strength is the vanilla setting, read here every frame. While a // From 1.21.6 the menu blur's strength is the vanilla setting, read here every frame. While a
// Saturn screen is open, it's Saturn's background blur instead, faded in with the screen. // Saturn screen is open, it's Saturn's background blur instead, faded in with the screen.
@Redirect(method = "render", at = @At(value = "INVOKE", @Redirect(method = "render", at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/option/GameOptions;getMenuBackgroundBlurrinessValue()I")) target = "Lnet/minecraft/client/Options;getMenuBackgroundBlurriness()I"))
private int useSaturnBlur(GameOptions options) { private int useSaturnBlur(Options options) {
if (MinecraftClient.getInstance().currentScreen instanceof SaturnScreenFabric saturnScreen) { if (Minecraft.getInstance().screen instanceof SaturnScreenFabric saturnScreen) {
return saturnScreen.screen.getBackgroundBlur(); return saturnScreen.screen.getBackgroundBlur();
} }
return options.getMenuBackgroundBlurrinessValue(); return options.getMenuBackgroundBlurriness();
} }
//?} //?}
} }
@@ -3,7 +3,7 @@ package org.saturnclient.impl.features.mixins.render;
// Code approach adapted from Gamma Utils: https://github.com/Sjouwer/gamma-utils // Code approach adapted from Gamma Utils: https://github.com/Sjouwer/gamma-utils
import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.renderer.LightTexture;
import org.saturnclient.mod.mods.FullbrightMod; import org.saturnclient.mod.mods.FullbrightMod;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -18,14 +18,14 @@ import org.spongepowered.asm.mixin.injection.At;
* it is now {@link FullbrightMod}. The injection target and * it is now {@link FullbrightMod}. The injection target and
* strategy are unchanged. * strategy are unchanged.
*/ */
@Mixin(LightmapTextureManager.class) @Mixin(LightTexture.class)
public class LightmapTextureManagerMixin { public class LightmapTextureManagerMixin {
/** /**
* If fullbright is active, substitute the feature's brightness * If fullbright is active, substitute the feature's brightness
* value for whatever vanilla calculated. * value for whatever vanilla calculated.
*/ */
@ModifyExpressionValue(method = "update", at = @At(value = "INVOKE", target = "Ljava/lang/Math;max(FF)F", ordinal = 0)) @ModifyExpressionValue(method = "updateLightTexture", at = @At(value = "INVOKE", target = "Ljava/lang/Math;max(FF)F", ordinal = 0))
private float modifyGamma(float original) { private float modifyGamma(float original) {
if (FullbrightMod.shouldOverrideBrightness()) { if (FullbrightMod.shouldOverrideBrightness()) {
return FullbrightMod.getBrightnessValue(); return FullbrightMod.getBrightnessValue();
@@ -1,6 +1,6 @@
package org.saturnclient.impl.features.mixins.render; package org.saturnclient.impl.features.mixins.render;
import net.minecraft.client.render.entity.state.LivingEntityRenderState; import net.minecraft.client.renderer.entity.state.LivingEntityRenderState;
import org.saturnclient.common.feature.EntityFeature; import org.saturnclient.common.feature.EntityFeature;
import org.saturnclient.impl.features.entity.HealthRenderState; import org.saturnclient.impl.features.entity.HealthRenderState;
@@ -1,12 +1,12 @@
package org.saturnclient.impl.features.mixins.render; package org.saturnclient.impl.features.mixins.render;
import net.minecraft.client.render.entity.LivingEntityRenderer; import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.client.render.entity.state.LivingEntityRenderState; import net.minecraft.client.renderer.entity.state.LivingEntityRenderState;
import net.minecraft.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.entity.mob.HostileEntity; import net.minecraft.world.entity.monster.Monster;
import net.minecraft.entity.passive.PassiveEntity; import net.minecraft.world.entity.AgeableMob;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.text.Text; import net.minecraft.network.chat.Component;
import org.saturnclient.common.feature.EntityFeature; import org.saturnclient.common.feature.EntityFeature;
import org.saturnclient.impl.features.entity.EntityFeatureImpl; import org.saturnclient.impl.features.entity.EntityFeatureImpl;
@@ -29,7 +29,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LivingEntityRenderer.class) @Mixin(LivingEntityRenderer.class)
public abstract class LivingEntityRendererMixin<T extends LivingEntity, S extends LivingEntityRenderState> { public abstract class LivingEntityRendererMixin<T extends LivingEntity, S extends LivingEntityRenderState> {
@Inject(method = "updateRenderState", at = @At("TAIL")) @Inject(method = "extractRenderState", at = @At("TAIL"))
private void saturn$captureHealth(T entity, S state, float tickDelta, CallbackInfo ci) { private void saturn$captureHealth(T entity, S state, float tickDelta, CallbackInfo ci) {
if (!(state instanceof HealthRenderState hrs)) if (!(state instanceof HealthRenderState hrs))
return; return;
@@ -38,11 +38,11 @@ public abstract class LivingEntityRendererMixin<T extends LivingEntity, S extend
// Classify entity type for the nametag feature's filtering logic // Classify entity type for the nametag feature's filtering logic
EntityFeature.EntityType type; EntityFeature.EntityType type;
if (entity instanceof PlayerEntity) if (entity instanceof Player)
type = EntityFeature.EntityType.PLAYER; type = EntityFeature.EntityType.PLAYER;
else if (entity instanceof HostileEntity) else if (entity instanceof Monster)
type = EntityFeature.EntityType.HOSTILE; type = EntityFeature.EntityType.HOSTILE;
else if (entity instanceof PassiveEntity) else if (entity instanceof AgeableMob)
type = EntityFeature.EntityType.PASSIVE; type = EntityFeature.EntityType.PASSIVE;
else else
type = EntityFeature.EntityType.OTHER; type = EntityFeature.EntityType.OTHER;
@@ -51,11 +51,11 @@ public abstract class LivingEntityRendererMixin<T extends LivingEntity, S extend
// Only entities that already show a label get a replacement one, as when this hooked label // Only entities that already show a label get a replacement one, as when this hooked label
// rendering. // rendering.
if (NametagsMod.shouldReplaceName() && state.displayName != null) { if (NametagsMod.shouldReplaceName() && state.nameTag != null) {
String replacement = NametagsMod.getNametagString( String replacement = NametagsMod.getNametagString(
new EntityFeatureImpl.RenderStateEntityState(state.displayName.getString(), hrs)); new EntityFeatureImpl.RenderStateEntityState(state.nameTag.getString(), hrs));
if (replacement != null) { if (replacement != null) {
state.displayName = Text.literal(replacement); state.nameTag = Component.literal(replacement);
} }
} }
} }
@@ -1,9 +1,9 @@
package org.saturnclient.impl.features.mixins.render; package org.saturnclient.impl.features.mixins.render;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.gui.Gui;
import net.minecraft.client.render.RenderTickCounter; import net.minecraft.client.DeltaTracker;
import org.saturnclient.impl.ui.RenderScopeImpl; import org.saturnclient.impl.ui.RenderScopeImpl;
import org.saturnclient.impl.ui.SaturnScreenFabric; import org.saturnclient.impl.ui.SaturnScreenFabric;
@@ -37,18 +37,18 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
* {@link SaturnScreenFabric} / {@link HudEditor} pair; that is * {@link SaturnScreenFabric} / {@link HudEditor} pair; that is
* unchanged infrastructure. * unchanged infrastructure.
*/ */
@Mixin(InGameHud.class) @Mixin(Gui.class)
public class RenderMixin { public class RenderMixin {
@Inject(method = "renderChat", at = @At("TAIL")) @Inject(method = "renderChat", at = @At("TAIL"))
public void renderMods(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { public void renderMods(GuiGraphics context, DeltaTracker tickCounter, CallbackInfo ci) {
TextRenderer textRenderer = SaturnClient.client.textRenderer; Font textRenderer = SaturnClient.client.font;
// Skip rendering while the HUD editor is open so the editor // Skip rendering while the HUD editor is open so the editor
// can draw its own preview layout without double-drawing. // can draw its own preview layout without double-drawing.
if (textRenderer == null) if (textRenderer == null)
return; return;
if (SaturnClient.client.currentScreen instanceof SaturnScreenFabric f if (SaturnClient.client.screen instanceof SaturnScreenFabric f
&& f.screen instanceof HudEditor) && f.screen instanceof HudEditor)
return; return;
@@ -1,7 +1,7 @@
package org.saturnclient.impl.features.mixins.world; package org.saturnclient.impl.features.mixins.world;
import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.packet.s2c.play.WorldTimeUpdateS2CPacket; import net.minecraft.network.protocol.game.ClientboundSetTimePacket;
import org.saturnclient.mod.mods.TpsMod; import org.saturnclient.mod.mods.TpsMod;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -20,11 +20,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
* The only change from the original is renaming the import from * The only change from the original is renaming the import from
* {@code feature.features.Tps} to {@link TpsMod}. * {@code feature.features.Tps} to {@link TpsMod}.
*/ */
@Mixin(ClientPlayNetworkHandler.class) @Mixin(ClientPacketListener.class)
public class TpsMixin { public class TpsMixin {
@Inject(method = "onWorldTimeUpdate", at = @At("HEAD")) @Inject(method = "handleSetTime", at = @At("HEAD"))
private void onWorldTimeUpdate(WorldTimeUpdateS2CPacket packet, CallbackInfo ci) { private void onWorldTimeUpdate(ClientboundSetTimePacket packet, CallbackInfo ci) {
TpsMod.onTimePacket(packet.time()); TpsMod.onTimePacket(packet.gameTime());
} }
} }
@@ -2,8 +2,8 @@ package org.saturnclient.impl.features.network;
import org.saturnclient.common.feature.NetworkFeature; import org.saturnclient.common.feature.NetworkFeature;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.multiplayer.PlayerInfo;
/** /**
* Fabric implementation of {@link NetworkFeature}. * Fabric implementation of {@link NetworkFeature}.
@@ -14,23 +14,23 @@ import net.minecraft.client.network.PlayerListEntry;
*/ */
public class NetworkFeatureImpl implements NetworkFeature { public class NetworkFeatureImpl implements NetworkFeature {
private final MinecraftClient mc; private final Minecraft mc;
public NetworkFeatureImpl(MinecraftClient mc) { public NetworkFeatureImpl(Minecraft mc) {
this.mc = mc; this.mc = mc;
} }
@Override @Override
public boolean hasNetwork() { public boolean hasNetwork() {
return mc.getNetworkHandler() != null; return mc.getConnection() != null;
} }
@Override @Override
public int getPing() { public int getPing() {
if (mc.player == null || mc.getNetworkHandler() == null) if (mc.player == null || mc.getConnection() == null)
return -1; return -1;
PlayerListEntry entry = mc.getNetworkHandler().getPlayerListEntry(mc.player.getUuid()); PlayerInfo entry = mc.getConnection().getPlayerInfo(mc.player.getUUID());
return entry != null ? entry.getLatency() : -1; return entry != null ? entry.getLatency() : -1;
} }
@@ -1,13 +1,13 @@
package org.saturnclient.impl.features.player; package org.saturnclient.impl.features.player;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.registry.Registries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
import org.saturnclient.common.feature.PlayerFeature; import org.saturnclient.common.feature.PlayerFeature;
import org.saturnclient.common.ref.game.EffectRef; import org.saturnclient.common.ref.game.EffectRef;
@@ -29,9 +29,9 @@ import java.util.List;
*/ */
public class PlayerFeatureImpl implements PlayerFeature { public class PlayerFeatureImpl implements PlayerFeature {
private final MinecraftClient mc; private final Minecraft mc;
public PlayerFeatureImpl(MinecraftClient mc) { public PlayerFeatureImpl(Minecraft mc) {
this.mc = mc; this.mc = mc;
} }
@@ -40,7 +40,7 @@ public class PlayerFeatureImpl implements PlayerFeature {
// --------------------------------------------------------------- // ---------------------------------------------------------------
/** Returns the local player, or {@code null} if one is not loaded. */ /** Returns the local player, or {@code null} if one is not loaded. */
private ClientPlayerEntity player() { private LocalPlayer player() {
return mc.player; return mc.player;
} }
@@ -78,42 +78,42 @@ public class PlayerFeatureImpl implements PlayerFeature {
@Override @Override
public boolean isForwardPressed() { public boolean isForwardPressed() {
return mc.options.forwardKey.isPressed(); return mc.options.keyUp.isDown();
} }
@Override @Override
public boolean isBackPressed() { public boolean isBackPressed() {
return mc.options.backKey.isPressed(); return mc.options.keyDown.isDown();
} }
@Override @Override
public boolean isLeftPressed() { public boolean isLeftPressed() {
return mc.options.leftKey.isPressed(); return mc.options.keyLeft.isDown();
} }
@Override @Override
public boolean isRightPressed() { public boolean isRightPressed() {
return mc.options.rightKey.isPressed(); return mc.options.keyRight.isDown();
} }
@Override @Override
public boolean isJumpPressed() { public boolean isJumpPressed() {
return mc.options.jumpKey.isPressed(); return mc.options.keyJump.isDown();
} }
@Override @Override
public boolean isAttackPressed() { public boolean isAttackPressed() {
return mc.options.attackKey.isPressed(); return mc.options.keyAttack.isDown();
} }
@Override @Override
public boolean isUsePressed() { public boolean isUsePressed() {
return mc.options.useKey.isPressed(); return mc.options.keyUse.isDown();
} }
@Override @Override
public boolean isSneaking() { public boolean isSneaking() {
return hasPlayer() && player().isSneaking(); return hasPlayer() && player().isShiftKeyDown();
} }
@Override @Override
@@ -128,7 +128,7 @@ public class PlayerFeatureImpl implements PlayerFeature {
@Override @Override
public boolean isOnGround() { public boolean isOnGround() {
return hasPlayer() && player().isOnGround(); return hasPlayer() && player().onGround();
} }
@Override @Override
@@ -145,7 +145,7 @@ public class PlayerFeatureImpl implements PlayerFeature {
public Velocity getVelocity() { public Velocity getVelocity() {
if (!hasPlayer()) if (!hasPlayer())
return Velocity.ZERO; return Velocity.ZERO;
var v = player().getVelocity(); var v = player().getDeltaMovement();
return new Velocity(v.x, v.y, v.z); return new Velocity(v.x, v.y, v.z);
} }
@@ -164,13 +164,13 @@ public class PlayerFeatureImpl implements PlayerFeature {
@Override @Override
public ItemStackRef getMainHand() { public ItemStackRef getMainHand() {
return wrap(hasPlayer() ? player().getMainHandStack() : ItemStack.EMPTY); return wrap(hasPlayer() ? player().getMainHandItem() : ItemStack.EMPTY);
} }
@Override @Override
public ItemStackRef getHelmet() { public ItemStackRef getHelmet() {
//? if >=1.21.5 { //? if >=1.21.5 {
return wrap(hasPlayer() ? player().getEquippedStack(EquipmentSlot.HEAD) : ItemStack.EMPTY); return wrap(hasPlayer() ? player().getItemBySlot(EquipmentSlot.HEAD) : ItemStack.EMPTY);
//?} else //?} else
//return wrap(hasPlayer() ? player().getInventory().armor.get(3) : ItemStack.EMPTY); //return wrap(hasPlayer() ? player().getInventory().armor.get(3) : ItemStack.EMPTY);
} }
@@ -178,7 +178,7 @@ public class PlayerFeatureImpl implements PlayerFeature {
@Override @Override
public ItemStackRef getChestplate() { public ItemStackRef getChestplate() {
//? if >=1.21.5 { //? if >=1.21.5 {
return wrap(hasPlayer() ? player().getEquippedStack(EquipmentSlot.CHEST) : ItemStack.EMPTY); return wrap(hasPlayer() ? player().getItemBySlot(EquipmentSlot.CHEST) : ItemStack.EMPTY);
//?} else //?} else
//return wrap(hasPlayer() ? player().getInventory().armor.get(2) : ItemStack.EMPTY); //return wrap(hasPlayer() ? player().getInventory().armor.get(2) : ItemStack.EMPTY);
} }
@@ -186,7 +186,7 @@ public class PlayerFeatureImpl implements PlayerFeature {
@Override @Override
public ItemStackRef getLeggings() { public ItemStackRef getLeggings() {
//? if >=1.21.5 { //? if >=1.21.5 {
return wrap(hasPlayer() ? player().getEquippedStack(EquipmentSlot.LEGS) : ItemStack.EMPTY); return wrap(hasPlayer() ? player().getItemBySlot(EquipmentSlot.LEGS) : ItemStack.EMPTY);
//?} else //?} else
//return wrap(hasPlayer() ? player().getInventory().armor.get(1) : ItemStack.EMPTY); //return wrap(hasPlayer() ? player().getInventory().armor.get(1) : ItemStack.EMPTY);
} }
@@ -194,7 +194,7 @@ public class PlayerFeatureImpl implements PlayerFeature {
@Override @Override
public ItemStackRef getBoots() { public ItemStackRef getBoots() {
//? if >=1.21.5 { //? if >=1.21.5 {
return wrap(hasPlayer() ? player().getEquippedStack(EquipmentSlot.FEET) : ItemStack.EMPTY); return wrap(hasPlayer() ? player().getItemBySlot(EquipmentSlot.FEET) : ItemStack.EMPTY);
//?} else //?} else
//return wrap(hasPlayer() ? player().getInventory().armor.get(0) : ItemStack.EMPTY); //return wrap(hasPlayer() ? player().getInventory().armor.get(0) : ItemStack.EMPTY);
} }
@@ -237,9 +237,9 @@ public class PlayerFeatureImpl implements PlayerFeature {
if (!hasPlayer()) if (!hasPlayer())
return Collections.emptyList(); return Collections.emptyList();
var effects = player().getActiveStatusEffects().values(); var effects = player().getActiveEffectsMap().values();
List<EffectRef> result = new ArrayList<>(effects.size()); List<EffectRef> result = new ArrayList<>(effects.size());
for (StatusEffectInstance instance : effects) { for (MobEffectInstance instance : effects) {
result.add((EffectRef) instance); result.add((EffectRef) instance);
} }
return result; return result;
@@ -248,12 +248,12 @@ public class PlayerFeatureImpl implements PlayerFeature {
@Override @Override
public List<? extends EffectRef> getDummyEffects() { public List<? extends EffectRef> getDummyEffects() {
return List.of( return List.of(
(EffectRef) new StatusEffectInstance( (EffectRef) new MobEffectInstance(
Registries.STATUS_EFFECT.getEntry(Identifier.ofVanilla("speed")).get(), 12000, 2), BuiltInRegistries.MOB_EFFECT.get(Identifier.withDefaultNamespace("speed")).get(), 12000, 2),
(EffectRef) new StatusEffectInstance( (EffectRef) new MobEffectInstance(
Registries.STATUS_EFFECT.getEntry(Identifier.ofVanilla("strength")).get(), 12000, 2), BuiltInRegistries.MOB_EFFECT.get(Identifier.withDefaultNamespace("strength")).get(), 12000, 2),
(EffectRef) new StatusEffectInstance( (EffectRef) new MobEffectInstance(
Registries.STATUS_EFFECT.getEntry(Identifier.ofVanilla("fire_resistance")).get(), 12000, 2)); BuiltInRegistries.MOB_EFFECT.get(Identifier.withDefaultNamespace("fire_resistance")).get(), 12000, 2));
} }
// --------------------------------------------------------------- // ---------------------------------------------------------------
@@ -2,8 +2,8 @@ package org.saturnclient.impl.features.render;
import org.saturnclient.common.feature.RenderFeature; import org.saturnclient.common.feature.RenderFeature;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import net.minecraft.client.option.Perspective; import net.minecraft.client.CameraType;
/** /**
* Fabric implementation of {@link RenderFeature}. * Fabric implementation of {@link RenderFeature}.
@@ -14,9 +14,9 @@ import net.minecraft.client.option.Perspective;
*/ */
public class RenderFeatureImpl implements RenderFeature { public class RenderFeatureImpl implements RenderFeature {
private final MinecraftClient mc; private final Minecraft mc;
public RenderFeatureImpl(MinecraftClient mc) { public RenderFeatureImpl(Minecraft mc) {
this.mc = mc; this.mc = mc;
} }
@@ -26,12 +26,12 @@ public class RenderFeatureImpl implements RenderFeature {
@Override @Override
public int getScaledWindowWidth() { public int getScaledWindowWidth() {
return mc.getWindow().getScaledWidth(); return mc.getWindow().getGuiScaledWidth();
} }
@Override @Override
public int getScaledWindowHeight() { public int getScaledWindowHeight() {
return mc.getWindow().getScaledHeight(); return mc.getWindow().getGuiScaledHeight();
} }
// --------------------------------------------------------------- // ---------------------------------------------------------------
@@ -40,7 +40,7 @@ public class RenderFeatureImpl implements RenderFeature {
@Override @Override
public int getFps() { public int getFps() {
return mc.getCurrentFps(); return mc.getFps();
} }
// --------------------------------------------------------------- // ---------------------------------------------------------------
@@ -49,16 +49,16 @@ public class RenderFeatureImpl implements RenderFeature {
@Override @Override
public boolean isFirstPerson() { public boolean isFirstPerson() {
return mc.options.getPerspective() == Perspective.FIRST_PERSON; return mc.options.getCameraType() == CameraType.FIRST_PERSON;
} }
@Override @Override
public void setFirstPerson() { public void setFirstPerson() {
mc.options.setPerspective(Perspective.FIRST_PERSON); mc.options.setCameraType(CameraType.FIRST_PERSON);
} }
@Override @Override
public void setThirdPersonBack() { public void setThirdPersonBack() {
mc.options.setPerspective(Perspective.THIRD_PERSON_BACK); mc.options.setCameraType(CameraType.THIRD_PERSON_BACK);
} }
} }
@@ -2,7 +2,7 @@ package org.saturnclient.impl.features.world;
import org.saturnclient.common.feature.WorldFeature; import org.saturnclient.common.feature.WorldFeature;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
/** /**
* Fabric implementation of {@link WorldFeature}. * Fabric implementation of {@link WorldFeature}.
@@ -12,15 +12,15 @@ import net.minecraft.client.MinecraftClient;
*/ */
public class WorldFeatureImpl implements WorldFeature { public class WorldFeatureImpl implements WorldFeature {
private final MinecraftClient mc; private final Minecraft mc;
public WorldFeatureImpl(MinecraftClient mc) { public WorldFeatureImpl(Minecraft mc) {
this.mc = mc; this.mc = mc;
} }
@Override @Override
public boolean hasWorld() { public boolean hasWorld() {
return mc.world != null; return mc.level != null;
} }
/** /**
@@ -32,6 +32,6 @@ public class WorldFeatureImpl implements WorldFeature {
@Override @Override
public long getWorldAge() { public long getWorldAge() {
// World.getTime() was a shortcut for this, and 1.21.11 removed it. // World.getTime() was a shortcut for this, and 1.21.11 removed it.
return hasWorld() ? mc.world.getLevelProperties().getTime() : 0L; return hasWorld() ? mc.level.getLevelData().getGameTime() : 0L;
} }
} }
@@ -4,7 +4,7 @@ import org.saturnclient.common.ref.asset.IdentifierRef;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
@Mixin(Identifier.class) @Mixin(Identifier.class)
public abstract class IdentifierMixin implements IdentifierRef { public abstract class IdentifierMixin implements IdentifierRef {
@@ -4,7 +4,7 @@ import org.saturnclient.common.ref.game.ItemStackRef;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.item.ItemStack; import net.minecraft.world.item.ItemStack;
@Mixin(ItemStack.class) @Mixin(ItemStack.class)
public abstract class ItemStackMixin implements ItemStackRef { public abstract class ItemStackMixin implements ItemStackRef {
@@ -15,5 +15,21 @@ public abstract class ItemStackMixin implements ItemStackRef {
public abstract int getMaxDamage(); public abstract int getMaxDamage();
@Shadow @Shadow
public abstract int getDamage(); public abstract int getDamageValue();
// ItemStackRef's methods delegate to ItemStack's, whose names production renames.
@Override
public boolean isEmptyStack() {
return isEmpty();
}
@Override
public int getMaxItemDamage() {
return getMaxDamage();
}
@Override
public int getItemDamage() {
return getDamageValue();
}
} }
@@ -1,6 +1,6 @@
package org.saturnclient.impl.mixins; package org.saturnclient.impl.mixins;
import net.minecraft.client.util.math.MatrixStack; import com.mojang.blaze3d.vertex.PoseStack;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
//? if <1.21.6 { //? if <1.21.6 {
/*import org.saturnclient.common.ref.render.MatrixStackRef; /*import org.saturnclient.common.ref.render.MatrixStackRef;
@@ -9,7 +9,7 @@ import org.joml.Quaternionfc;
//? if <1.21.5 //? if <1.21.5
//import org.joml.Quaternionf; //import org.joml.Quaternionf;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.util.math.RotationAxis; import com.mojang.math.Axis;
*///?} *///?}
/** /**
@@ -17,14 +17,14 @@ import net.minecraft.util.math.RotationAxis;
* Matrix3x2fStack (Matrix3x2fStackRef) instead, so this mixin is empty but stays registered, keeping * Matrix3x2fStack (Matrix3x2fStackRef) instead, so this mixin is empty but stays registered, keeping
* impl.mixins.json the same for every version. * impl.mixins.json the same for every version.
*/ */
@Mixin(MatrixStack.class) @Mixin(PoseStack.class)
//? if <1.21.6 { //? if <1.21.6 {
/*public abstract class MatrixStackMixin implements MatrixStackRef { /*public abstract class MatrixStackMixin implements MatrixStackRef {
@Shadow @Shadow
public abstract void push(); public abstract void pushPose();
@Shadow @Shadow
public abstract void pop(); public abstract void popPose();
@Shadow @Shadow
public abstract void translate(float x, float y, float z); public abstract void translate(float x, float y, float z);
@@ -34,15 +34,26 @@ import net.minecraft.util.math.RotationAxis;
@Shadow @Shadow
//? if >=1.21.5 //? if >=1.21.5
public abstract void multiply(Quaternionfc quaternion); public abstract void mulPose(Quaternionfc quaternion);
//? if <1.21.5 //? if <1.21.5
//public abstract void multiply(Quaternionf quaternion); //public abstract void mulPose(Quaternionf quaternion);
@Shadow @Shadow
//? if >=1.21.5 //? if >=1.21.5
public abstract void multiply(Quaternionfc quaternion, float originX, float originY, float originZ); public abstract void rotateAround(Quaternionfc quaternion, float originX, float originY, float originZ);
//? if <1.21.5 //? if <1.21.5
//public abstract void multiply(Quaternionf quaternion, float originX, float originY, float originZ); //public abstract void rotateAround(Quaternionf quaternion, float originX, float originY, float originZ);
// MatrixStackRef's methods delegate to PoseStack's, whose names production renames.
@Override
public void push() {
pushPose();
}
@Override
public void pop() {
popPose();
}
@Override @Override
public void translate(float x, float y) { public void translate(float x, float y) {
@@ -56,12 +67,12 @@ import net.minecraft.util.math.RotationAxis;
@Override @Override
public void rotate(float angle, float originX, float originY, float originZ) { public void rotate(float angle, float originX, float originY, float originZ) {
multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(angle), originX, originY, originZ); rotateAround(Axis.ZN.rotationDegrees(angle), originX, originY, originZ);
} }
@Override @Override
public void rotate(float angle) { public void rotate(float angle) {
multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(angle)); mulPose(Axis.ZN.rotationDegrees(angle));
} }
} }
*///?} else *///?} else
@@ -15,50 +15,54 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen;
import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.gui.screens.options.OptionsScreen;
import net.minecraft.client.gui.screen.world.SelectWorldScreen; import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen;
import net.minecraft.client.option.GameOptions; import net.minecraft.client.Options;
import net.minecraft.client.session.Session; import net.minecraft.client.User;
import net.minecraft.client.util.Window; import com.mojang.blaze3d.platform.Window;
import net.minecraft.resource.ReloadableResourceManagerImpl; import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
@Mixin(MinecraftClient.class) @Mixin(Minecraft.class)
public abstract class MinecraftClientMixin implements MinecraftClientRef { public abstract class MinecraftClientMixin implements MinecraftClientRef {
@Shadow @Shadow
public File runDirectory; public File gameDirectory;
@Shadow @Shadow
private Window window; private Window window;
@Shadow @Shadow
private ReloadableResourceManagerImpl resourceManager; private ReloadableResourceManager resourceManager;
@Shadow @Shadow
public GameOptions options; public Options options;
@Shadow @Shadow
private Session session; private User user;
@Shadow @Shadow
public abstract void setScreen(@Nullable Screen screen); public abstract void setScreen(@Nullable Screen screen);
@Shadow @Shadow
public abstract void stop();
@Override @Override
public abstract void scheduleStop(); public void scheduleStop() {
stop();
}
@Override @Override
public File getRunDirectory() { public File getRunDirectory() {
return runDirectory; return gameDirectory;
} }
@Override @Override
public InputStream getResource(IdentifierRef identifier) { public InputStream getResource(IdentifierRef identifier) {
try { try {
return resourceManager.getResource((Identifier) (Object) identifier).get().getInputStream(); return resourceManager.getResource((Identifier) (Object) identifier).get().open();
} catch (Exception e) { } catch (Exception e) {
return null; return null;
} }
@@ -84,7 +88,7 @@ public abstract class MinecraftClientMixin implements MinecraftClientRef {
break; break;
case Multiplayer: case Multiplayer:
this.setScreen(new MultiplayerScreen(exitTarget)); this.setScreen(new JoinMultiplayerScreen(exitTarget));
break; break;
case Options: case Options:
@@ -95,27 +99,27 @@ public abstract class MinecraftClientMixin implements MinecraftClientRef {
@Override @Override
public String getAccessToken() { public String getAccessToken() {
if (session == null) { if (user == null) {
return null; return null;
} }
return this.session.getAccessToken(); return this.user.getAccessToken();
} }
@Override @Override
public UUID getUuid() { public UUID getUuid() {
if (session == null) { if (user == null) {
return null; return null;
} }
return this.session.getUuidOrNull(); return this.user.getProfileId();
} }
@Override @Override
public String getUsername() { public String getUsername() {
if (session == null) { if (user == null) {
return null; return null;
} }
return this.session.getUsername(); return this.user.getName();
} }
@Override @Override
@@ -131,13 +135,13 @@ public abstract class MinecraftClientMixin implements MinecraftClientRef {
@Override @Override
@SuppressWarnings("resource") @SuppressWarnings("resource")
public String getPlayerListEntry(UUID uuid) { public String getPlayerListEntry(UUID uuid) {
var client = (MinecraftClient) (Object) this; var client = (Minecraft) (Object) this;
var handler = client.getNetworkHandler(); var handler = client.getConnection();
if (handler == null) if (handler == null)
return null; return null;
var entry = handler.getPlayerListEntry(uuid); var entry = handler.getPlayerInfo(uuid);
if (entry == null) if (entry == null)
return null; return null;
@@ -150,13 +154,13 @@ public abstract class MinecraftClientMixin implements MinecraftClientRef {
@Override @Override
@SuppressWarnings("resource") @SuppressWarnings("resource")
public UUID getPlayerListEntryUUID(String name) { public UUID getPlayerListEntryUUID(String name) {
var client = (MinecraftClient) (Object) this; var client = (Minecraft) (Object) this;
var handler = client.getNetworkHandler(); var handler = client.getConnection();
if (handler == null) if (handler == null)
return null; return null;
var entry = handler.getPlayerListEntry(name); var entry = handler.getPlayerInfo(name);
if (entry == null) if (entry == null)
return null; return null;
@@ -1,9 +1,9 @@
package org.saturnclient.impl.mixins; package org.saturnclient.impl.mixins;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import org.saturnclient.common.ref.asset.SpriteRef; import org.saturnclient.common.ref.asset.SpriteRef;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@Mixin(Sprite.class) @Mixin(TextureAtlasSprite.class)
public abstract class SpriteMixin implements SpriteRef { public abstract class SpriteMixin implements SpriteRef {
} }
@@ -8,26 +8,37 @@ import org.saturnclient.common.ref.game.EffectRef;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.gui.Gui;
import net.minecraft.entity.effect.StatusEffect; import net.minecraft.world.effect.MobEffect;
import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.core.Holder;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
@Mixin(StatusEffectInstance.class) @Mixin(MobEffectInstance.class)
public abstract class StatusEffectMixin implements EffectRef { public abstract class StatusEffectMixin implements EffectRef {
@Shadow @Shadow
public abstract boolean shouldShowIcon(); public abstract boolean showIcon();
@Shadow @Shadow
public abstract boolean isInfinite(); public abstract boolean isInfiniteDuration();
@Shadow @Shadow
public abstract int getDuration(); public abstract int getDuration();
@Shadow @Shadow
public abstract RegistryEntry<StatusEffect> getEffectType(); public abstract Holder<MobEffect> getEffect();
// EffectRef's methods delegate to MobEffectInstance's, whose names production renames.
@Override
public boolean shouldShowIcon() {
return showIcon();
}
@Override
public boolean isInfinite() {
return isInfiniteDuration();
}
@Override @Override
public SpriteRef getIcon() { public SpriteRef getIcon() {
@@ -35,16 +46,16 @@ public abstract class StatusEffectMixin implements EffectRef {
//? if >=1.21.9 { //? if >=1.21.9 {
return null; return null;
//?} else if >=1.21.6 { //?} else if >=1.21.6 {
//return (SpriteRef) SaturnClient.client.getGuiAtlasManager().getSprite((InGameHud.getEffectTexture(getEffectType()))); //return (SpriteRef) SaturnClient.client.getGuiSprites().getSprite((Gui.getMobEffectSprite(getEffect())));
//?} else //?} else
//return (SpriteRef) SaturnClient.client.getStatusEffectSpriteManager().getSprite(getEffectType()); //return (SpriteRef) SaturnClient.client.getMobEffectTextures().get(getEffect());
} }
// Before 1.21.6 there's no InGameHud.getEffectTexture; getIcon's sprite is used there instead. // Before 1.21.6 there's no InGameHud.getEffectTexture; getIcon's sprite is used there instead.
//? if >=1.21.6 { //? if >=1.21.6 {
@Override @Override
public IdentifierRef getIconId() { public IdentifierRef getIconId() {
Identifier id = InGameHud.getEffectTexture(getEffectType()); Identifier id = Gui.getMobEffectSprite(getEffect());
return IdentifierRef.of(id.getNamespace(), "textures/" + id.getPath() + ".png"); return IdentifierRef.of(id.getNamespace(), "textures/" + id.getPath() + ".png");
} }
@@ -5,25 +5,25 @@ import org.saturnclient.common.ref.render.TextRef;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.text.Style; import net.minecraft.network.chat.Style;
import net.minecraft.text.Text; import net.minecraft.network.chat.Component;
//? if >=1.21.9 //? if >=1.21.9
import net.minecraft.text.StyleSpriteSource.Font; import net.minecraft.network.chat.FontDescription.Resource;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
@Mixin(Text.class) @Mixin(Component.class)
public interface TextMixin extends TextRef { public interface TextMixin extends TextRef {
@Override @Override
public default TextRef withFont(IdentifierRef font) { public default TextRef withFont(IdentifierRef font) {
//? if >=1.21.9 { //? if >=1.21.9 {
return (TextRef) (Text) (((Text) this).copy().setStyle(Style.EMPTY.withFont(new Font((Identifier) (Object) font)))); return (TextRef) (Component) (((Component) this).copy().setStyle(Style.EMPTY.withFont(new Resource((Identifier) (Object) font))));
//?} else //?} else
//return (TextRef) (((Text) this).copy().setStyle(Style.EMPTY.withFont((Identifier) (Object) font))); //return (TextRef) (((Component) this).copy().setStyle(Style.EMPTY.withFont((Identifier) (Object) font)));
} }
@Override @Override
public default int getWidth() { public default int getWidth() {
return SaturnClient.client.textRenderer.getWidth((Text) this); return SaturnClient.client.font.width((Component) this);
} }
} }
@@ -4,19 +4,41 @@ import org.saturnclient.common.ref.render.WindowRef;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import net.minecraft.client.util.Window; import com.mojang.blaze3d.platform.Window;
@Mixin(Window.class) @Mixin(Window.class)
public abstract class WindowMixin implements WindowRef { public abstract class WindowMixin implements WindowRef {
@Shadow
public abstract int getScreenWidth();
@Shadow
public abstract int getScreenHeight();
// The framebuffer's size
@Shadow @Shadow
public abstract int getWidth(); public abstract int getWidth();
@Shadow @Shadow
public abstract int getHeight(); public abstract int getHeight();
@Shadow // WindowRef's methods delegate to Window's, whose names production renames.
public abstract int getFramebufferWidth(); @Override
public int getWindowWidth() {
return getScreenWidth();
}
@Shadow @Override
public abstract int getFramebufferHeight(); public int getWindowHeight() {
return getScreenHeight();
}
@Override
public int getFramebufferWidth() {
return getWidth();
}
@Override
public int getFramebufferHeight() {
return getHeight();
}
} }
@@ -1,6 +1,6 @@
package org.saturnclient.impl.provider; package org.saturnclient.impl.provider;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import org.saturnclient.common.feature.*; import org.saturnclient.common.feature.*;
import org.saturnclient.common.provider.FeatureProvider; import org.saturnclient.common.provider.FeatureProvider;
@@ -33,7 +33,7 @@ public class FeatureProviderFabric implements FeatureProvider {
private final RenderFeature render; private final RenderFeature render;
private final NetworkFeature network; private final NetworkFeature network;
public FeatureProviderFabric(MinecraftClient mc) { public FeatureProviderFabric(Minecraft mc) {
this.player = new PlayerFeatureImpl(mc); this.player = new PlayerFeatureImpl(mc);
this.world = new WorldFeatureImpl(mc); this.world = new WorldFeatureImpl(mc);
this.entity = new EntityFeatureImpl(mc); this.entity = new EntityFeatureImpl(mc);
@@ -7,8 +7,12 @@ import org.saturnclient.saturnclient.SaturnClient;
public class GLFWProviderImpl implements GLFWProvider { public class GLFWProviderImpl implements GLFWProvider {
@Override @Override
public boolean isKeyPressed(int key) { public boolean isKeyPressed(int key) {
return GLFW.glfwGetKey(SaturnClient.client.getWindow().getHandle(), key) == GLFW.GLFW_PRESS //? if >=1.21.9 {
&& SaturnClient.client.currentScreen == null; long window = SaturnClient.client.getWindow().handle();
//?} else
//long window = SaturnClient.client.getWindow().getWindow();
return GLFW.glfwGetKey(window, key) == GLFW.GLFW_PRESS
&& SaturnClient.client.screen == null;
} }
@Override @Override
@@ -4,22 +4,22 @@ import org.saturnclient.common.provider.RefConstructorProvider;
import org.saturnclient.common.ref.asset.IdentifierRef; import org.saturnclient.common.ref.asset.IdentifierRef;
import org.saturnclient.common.ref.render.TextRef; import org.saturnclient.common.ref.render.TextRef;
import net.minecraft.text.Text; import net.minecraft.network.chat.Component;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
public class RefConstructorImpl implements RefConstructorProvider { public class RefConstructorImpl implements RefConstructorProvider {
@Override @Override
public IdentifierRef identifier(String fullPath) { public IdentifierRef identifier(String fullPath) {
return (IdentifierRef) (Object) Identifier.of(fullPath); return (IdentifierRef) (Object) Identifier.parse(fullPath);
} }
@Override @Override
public IdentifierRef identifier(String namespace, String path) { public IdentifierRef identifier(String namespace, String path) {
return (IdentifierRef) (Object) Identifier.of(namespace, path); return (IdentifierRef) (Object) Identifier.fromNamespaceAndPath(namespace, path);
} }
@Override @Override
public TextRef text(String text) { public TextRef text(String text) {
return (TextRef) (Text) Text.literal(text); return (TextRef) (Component) Component.literal(text);
} }
} }
@@ -5,14 +5,14 @@ import java.util.UUID;
import java.util.function.Supplier; import java.util.function.Supplier;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import net.minecraft.client.toast.SystemToast; import net.minecraft.client.gui.components.toasts.SystemToast;
//? if >=1.21.9 { //? if >=1.21.9 {
import net.minecraft.entity.player.SkinTextures; import net.minecraft.world.entity.player.PlayerSkin;
//?} else //?} else
//import net.minecraft.client.util.SkinTextures; //import net.minecraft.client.resources.PlayerSkin;
import net.minecraft.text.Text; import net.minecraft.network.chat.Component;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
import org.saturnclient.common.provider.SaturnProvider; import org.saturnclient.common.provider.SaturnProvider;
import org.saturnclient.common.ref.asset.IdentifierRef; import org.saturnclient.common.ref.asset.IdentifierRef;
@@ -57,18 +57,18 @@ public class SaturnProviderImpl implements SaturnProvider {
} }
/** Shown longer than the vanilla default, since these ask the player to act. */ /** Shown longer than the vanilla default, since these ask the player to act. */
private static final SystemToast.Type WARNING_TOAST = new SystemToast.Type(15_000L); private static final SystemToast.SystemToastId WARNING_TOAST = new SystemToast.SystemToastId(15_000L);
@Override @Override
public IdentifierRef getPlayerSkin() { public IdentifierRef getPlayerSkin() {
if (playerSkin == null) { if (playerSkin == null) {
MinecraftClient client = MinecraftClient.getInstance(); Minecraft client = Minecraft.getInstance();
// 1.21.9 moved SkinTextures and renamed the skin provider's lookup. // 1.21.9 moved SkinTextures and renamed the skin provider's lookup.
//? if >=1.21.9 { //? if >=1.21.9 {
Supplier<SkinTextures> textures = client.getSkinProvider().supplySkinTextures(client.getGameProfile(), false); Supplier<PlayerSkin> textures = client.getSkinManager().createLookup(client.getGameProfile(), false);
playerSkin = () -> textures.get().body().texturePath(); playerSkin = () -> textures.get().body().texturePath();
//?} else { //?} else {
/*Supplier<SkinTextures> textures = client.getSkinProvider().getSkinTexturesSupplier(client.getGameProfile()); /*Supplier<PlayerSkin> textures = client.getSkinManager().lookupInsecure(client.getGameProfile());
playerSkin = () -> textures.get().texture(); playerSkin = () -> textures.get().texture();
*///?} *///?}
} }
@@ -85,9 +85,9 @@ public class SaturnProviderImpl implements SaturnProvider {
@Override @Override
public void showWarning(String title, String message) { public void showWarning(String title, String message) {
MinecraftClient client = MinecraftClient.getInstance(); Minecraft client = Minecraft.getInstance();
client.execute(() -> client.getToastManager().add( client.execute(() -> client.getToastManager().addToast(
SystemToast.create(client, WARNING_TOAST, Text.literal(title), Text.literal(message)))); SystemToast.multiline(client, WARNING_TOAST, Component.literal(title), Component.literal(message))));
} }
@Override @Override
@@ -11,12 +11,12 @@ import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.components.SkinPreview.EntityDrawer; import org.saturnclient.ui.components.SkinPreview.EntityDrawer;
//? if >=1.21.9 { //? if >=1.21.9 {
import net.minecraft.client.render.entity.EntityRenderManager; import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
//?} else //?} else
//import net.minecraft.client.render.entity.EntityRenderDispatcher; //import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.client.render.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.render.entity.state.EntityRenderState; import net.minecraft.client.renderer.entity.state.EntityRenderState;
import net.minecraft.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
public class EntityDrawerImpl implements EntityDrawer { public class EntityDrawerImpl implements EntityDrawer {
@Override @Override
@@ -38,25 +38,25 @@ public class EntityDrawerImpl implements EntityDrawer {
renderScope.enableScissor(x1, y1, x2, y2); renderScope.enableScissor(x1, y1, x2, y2);
Quaternionf quaternionf = (new Quaternionf()).rotateZ((float) Math.PI); Quaternionf quaternionf = (new Quaternionf()).rotateZ((float) Math.PI);
Quaternionf quaternionf2 = new Quaternionf(); Quaternionf quaternionf2 = new Quaternionf();
float j = entity.bodyYaw; float j = entity.yBodyRot;
float k = entity.getYaw(); float k = entity.getYRot();
float l = entity.getPitch(); float l = entity.getXRot();
float m = entity.lastHeadYaw; float m = entity.yHeadRotO;
float n = entity.headYaw; float n = entity.yHeadRot;
entity.bodyYaw = 180.0F + yaw; entity.yBodyRot = 180.0F + yaw;
entity.setYaw(180.0F + yaw); entity.setYRot(180.0F + yaw);
entity.setPitch(0.0F); entity.setXRot(0.0F);
entity.headYaw = entity.getYaw(); entity.yHeadRot = entity.getYRot();
entity.lastHeadYaw = entity.getYaw(); entity.yHeadRotO = entity.getYRot();
float o = entity.getScale(); float o = entity.getScale();
Vector3f vector3f = new Vector3f(0.0F, entity.getHeight() / 2.0F + scale * o, 0.0F); Vector3f vector3f = new Vector3f(0.0F, entity.getBbHeight() / 2.0F + scale * o, 0.0F);
float p = (float) size / o; float p = (float) size / o;
drawEntity(renderScope, x1, y1, x2, y2, p, vector3f, quaternionf, quaternionf2, entity); drawEntity(renderScope, x1, y1, x2, y2, p, vector3f, quaternionf, quaternionf2, entity);
entity.bodyYaw = j; entity.yBodyRot = j;
entity.setYaw(k); entity.setYRot(k);
entity.setPitch(l); entity.setXRot(l);
entity.lastHeadYaw = m; entity.yHeadRotO = m;
entity.headYaw = n; entity.yHeadRot = n;
renderScope.disableScissor(); renderScope.disableScissor();
} }
@@ -64,13 +64,13 @@ public class EntityDrawerImpl implements EntityDrawer {
Vector3f translation, Quaternionf rotation, @Nullable Quaternionf overrideCameraAngle, Vector3f translation, Quaternionf rotation, @Nullable Quaternionf overrideCameraAngle,
LivingEntity entity) { LivingEntity entity) {
//? if >=1.21.9 { //? if >=1.21.9 {
EntityRenderManager entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher(); EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher();
//?} else //?} else
//EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher(); //EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher();
EntityRenderer<? super LivingEntity, ?> entityRenderer = entityRenderDispatcher.getRenderer(entity); EntityRenderer<? super LivingEntity, ?> entityRenderer = entityRenderDispatcher.getRenderer(entity);
EntityRenderState entityRenderState = entityRenderer.getAndUpdateRenderState(entity, 1.0F); EntityRenderState entityRenderState = entityRenderer.createRenderState(entity, 1.0F);
//? if <1.21.11 //? if <1.21.11
//entityRenderState.hitbox = null; //entityRenderState.hitboxesRenderState = null;
if (renderScope instanceof RenderScopeImpl i) if (renderScope instanceof RenderScopeImpl i)
i.addEntity(entityRenderState, scale, translation, rotation, overrideCameraAngle, x1, y1, x2, y2); i.addEntity(entityRenderState, scale, translation, rotation, overrideCameraAngle, x1, y1, x2, y2);
@@ -84,9 +84,9 @@ import org.saturnclient.saturnclient.SaturnClient;
import org.saturnclient.ui.RenderScope; import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.components.SkinPreview.EntityDrawer; import org.saturnclient.ui.components.SkinPreview.EntityDrawer;
import net.minecraft.client.render.DiffuseLighting; import com.mojang.blaze3d.platform.Lighting;
import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
public class EntityDrawerImpl implements EntityDrawer { public class EntityDrawerImpl implements EntityDrawer {
// Draws the entity in the box, turned by yaw degrees (0 faces the viewer) with its head straight. // Draws the entity in the box, turned by yaw degrees (0 faces the viewer) with its head straight.
@@ -96,66 +96,66 @@ public class EntityDrawerImpl implements EntityDrawer {
float h = (float) (y1 + y2) / 2.0F; float h = (float) (y1 + y2) / 2.0F;
renderScope.enableScissor(x1, y1, x2, y2); renderScope.enableScissor(x1, y1, x2, y2);
Quaternionf quaternionf = (new Quaternionf()).rotateZ(3.1415927F); Quaternionf quaternionf = (new Quaternionf()).rotateZ(3.1415927F);
float k = entity.bodyYaw; float k = entity.yBodyRot;
float l = entity.getYaw(); float l = entity.getYRot();
float m = entity.getPitch(); float m = entity.getXRot();
//? if >=1.21.5 //? if >=1.21.5
float n = entity.lastHeadYaw; float n = entity.yHeadRotO;
//? if <1.21.5 //? if <1.21.5
//float n = entity.prevHeadYaw; //float n = entity.yHeadRotO;
float o = entity.headYaw; float o = entity.yHeadRot;
entity.setYaw(180.0F + yaw); entity.setYRot(180.0F + yaw);
entity.bodyYaw = 180.0F + yaw; entity.yBodyRot = 180.0F + yaw;
entity.setPitch(0.0F); entity.setXRot(0.0F);
entity.headYaw = entity.getYaw(); entity.yHeadRot = entity.getYRot();
//? if >=1.21.5 //? if >=1.21.5
entity.lastHeadYaw = entity.getHeadYaw(); entity.yHeadRotO = entity.getYHeadRot();
//? if <1.21.5 //? if <1.21.5
//entity.prevHeadYaw = entity.getHeadYaw(); //entity.yHeadRotO = entity.getYHeadRot();
entity.setCustomNameVisible(false); entity.setCustomNameVisible(false);
float p = entity.getScale(); float p = entity.getScale();
Vector3f vector3f = new Vector3f(0.0F, entity.getHeight() / 2.0F + f * p, 0.0F); Vector3f vector3f = new Vector3f(0.0F, entity.getBbHeight() / 2.0F + f * p, 0.0F);
float q = (float) size / p; float q = (float) size / p;
drawEntity(renderScope, g, h, q, vector3f, quaternionf, null, entity); drawEntity(renderScope, g, h, q, vector3f, quaternionf, null, entity);
entity.setCustomNameVisible(true); entity.setCustomNameVisible(true);
entity.bodyYaw = k; entity.yBodyRot = k;
entity.setYaw(l); entity.setYRot(l);
entity.setPitch(m); entity.setXRot(m);
//? if >=1.21.5 //? if >=1.21.5
entity.lastHeadYaw = n; entity.yHeadRotO = n;
//? if <1.21.5 //? if <1.21.5
//entity.prevHeadYaw = n; //entity.yHeadRotO = n;
entity.headYaw = o; entity.yHeadRot = o;
renderScope.disableScissor(); renderScope.disableScissor();
} }
public static void drawEntity(RenderScope renderScope, float x, float y, float size, Vector3f vector3f, public static void drawEntity(RenderScope renderScope, float x, float y, float size, Vector3f vector3f,
Quaternionf quaternionf, @Nullable Quaternionf quaternionf2, LivingEntity entity) { Quaternionf quaternionf, @Nullable Quaternionf quaternionf2, LivingEntity entity) {
if (renderScope instanceof RenderScopeImpl scopeImpl) { if (renderScope instanceof RenderScopeImpl scopeImpl) {
scopeImpl.matrices.push(); scopeImpl.matrices.pushPose();
scopeImpl.matrices.translate((double) x, (double) y, 0); scopeImpl.matrices.translate((double) x, (double) y, 0);
scopeImpl.matrices.scale(size, size, -size); scopeImpl.matrices.scale(size, size, -size);
scopeImpl.matrices.translate(vector3f.x, vector3f.y, vector3f.z); scopeImpl.matrices.translate(vector3f.x, vector3f.y, vector3f.z);
scopeImpl.matrices.multiply(quaternionf); scopeImpl.matrices.mulPose(quaternionf);
scopeImpl.draw(); scopeImpl.draw();
//? if >=1.21.5 //? if >=1.21.5
DiffuseLighting.disableGuiDepthLighting(); Lighting.setupForFlatItems();
//? if <1.21.5 //? if <1.21.5
//DiffuseLighting.method_34742(); //Lighting.setupForEntityInInventory();
EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher(); EntityRenderDispatcher entityRenderDispatcher = SaturnClient.client.getEntityRenderDispatcher();
entityRenderDispatcher.setRenderShadows(false); entityRenderDispatcher.setRenderShadow(false);
scopeImpl.draw((vertexConsumers) -> { scopeImpl.draw((vertexConsumers) -> {
entityRenderDispatcher.render(entity, 0.0, 0.0, 0.0, 1.0F, entityRenderDispatcher.render(entity, 0.0, 0.0, 0.0, 1.0F,
scopeImpl.matrices, vertexConsumers, 15728880); scopeImpl.matrices, vertexConsumers, 15728880);
}); });
scopeImpl.draw(); scopeImpl.draw();
entityRenderDispatcher.setRenderShadows(true); entityRenderDispatcher.setRenderShadow(true);
scopeImpl.getMatrixStack().pop(); scopeImpl.getMatrixStack().pop();
DiffuseLighting.enableGuiDepthLighting(); Lighting.setupFor3DItems();
} }
} }
@@ -31,36 +31,36 @@ import com.mojang.serialization.JsonOps;
import org.saturnclient.config.Config; import org.saturnclient.config.Config;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.gl.Framebuffer; import com.mojang.blaze3d.pipeline.RenderTarget;
import net.minecraft.client.gl.PostEffectPipeline; import net.minecraft.client.renderer.PostChainConfig;
import net.minecraft.client.gl.PostEffectProcessor; import net.minecraft.client.renderer.PostChain;
import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.client.gl.SimpleFramebuffer; import com.mojang.blaze3d.pipeline.TextureTarget;
import net.minecraft.client.render.DefaultFramebufferSet; import net.minecraft.client.renderer.LevelTargetBundle;
import net.minecraft.client.render.ProjectionMatrix2; import net.minecraft.client.renderer.CachedOrthoProjectionMatrixBuffer;
import net.minecraft.client.texture.AbstractTexture; import net.minecraft.client.renderer.texture.AbstractTexture;
import net.minecraft.client.texture.TextureSetup; import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.util.Pool; import com.mojang.blaze3d.resource.CrossFrameResourcePool;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
public final class GlassRenderer { public final class GlassRenderer {
public static final RenderPipeline PIPELINE = RenderPipeline.builder(RenderPipelines.POSITION_TEX_COLOR_SNIPPET) public static final RenderPipeline PIPELINE = RenderPipeline.builder(RenderPipelines.GUI_TEXTURED_SNIPPET)
.withLocation(Identifier.of("saturnclient", "pipeline/glass")) .withLocation(Identifier.fromNamespaceAndPath("saturnclient", "pipeline/glass"))
.withFragmentShader(Identifier.of("saturnclient", "core/glass")) .withFragmentShader(Identifier.fromNamespaceAndPath("saturnclient", "core/glass"))
.withSampler("Sampler1") .withSampler("Sampler1")
// The transforms block ends with LineWidth before 1.21.11 (see glass.fsh). // The transforms block ends with LineWidth before 1.21.11 (see glass.fsh).
//? if <1.21.11 //? if <1.21.11
//.withShaderDefine("HAS_LINE_WIDTH") //.withShaderDefine("HAS_LINE_WIDTH")
.build(); .build();
private static final Identifier BLUR = Identifier.ofVanilla("post_effect/blur.json"); private static final Identifier BLUR = Identifier.withDefaultNamespace("post_effect/blur.json");
private static final ProjectionMatrix2 PROJECTION = new ProjectionMatrix2("saturn glass", 0.1f, 1000f, false); private static final CachedOrthoProjectionMatrixBuffer PROJECTION = new CachedOrthoProjectionMatrixBuffer("saturn glass", 0.1f, 1000f, false);
// For the blurs' intermediate targets, freed once unused for a few frames // For the blurs' intermediate targets, freed once unused for a few frames
private static final Pool POOL = new Pool(3); private static final CrossFrameResourcePool POOL = new CrossFrameResourcePool(3);
// By blur strength. A blur that failed to load is kept as null, so it isn't retried every frame. // By blur strength. A blur that failed to load is kept as null, so it isn't retried every frame.
private static final Map<Integer, PostEffectProcessor> BLURS = new HashMap<>(); private static final Map<Integer, PostChain> BLURS = new HashMap<>();
private static final Map<Integer, SimpleFramebuffer> BACKDROPS = new HashMap<>(); private static final Map<Integer, TextureTarget> BACKDROPS = new HashMap<>();
private GlassRenderer() { private GlassRenderer() {
} }
@@ -68,38 +68,38 @@ public final class GlassRenderer {
// Copies the main framebuffer and blurs the copy by blur. Call once a frame for each blur, while // Copies the main framebuffer and blurs the copy by blur. Call once a frame for each blur, while
// the screen builds its GUI, before drawing glass with it. // the screen builds its GUI, before drawing glass with it.
public static void captureBackdrop(int blur) { public static void captureBackdrop(int blur) {
Framebuffer main = SaturnClient.client.getFramebuffer(); RenderTarget main = SaturnClient.client.getMainRenderTarget();
int width = main.textureWidth; int width = main.width;
int height = main.textureHeight; int height = main.height;
SimpleFramebuffer backdrop = BACKDROPS.get(blur); TextureTarget backdrop = BACKDROPS.get(blur);
if (backdrop == null) { if (backdrop == null) {
backdrop = new SimpleFramebuffer("Saturn glass " + blur, width, height, false); backdrop = new TextureTarget("Saturn glass " + blur, width, height, false);
BACKDROPS.put(blur, backdrop); BACKDROPS.put(blur, backdrop);
} else if (backdrop.textureWidth != width || backdrop.textureHeight != height) { } else if (backdrop.width != width || backdrop.height != height) {
backdrop.resize(width, height); backdrop.resize(width, height);
} }
//? if <1.21.11 //? if <1.21.11
//backdrop.getColorAttachment().setTextureFilter(FilterMode.LINEAR, false); //backdrop.getColorTexture().setTextureFilter(FilterMode.LINEAR, false);
RenderSystem.getDevice().createCommandEncoder().copyTextureToTexture( RenderSystem.getDevice().createCommandEncoder().copyTextureToTexture(
main.getColorAttachment(), backdrop.getColorAttachment(), 0, 0, 0, 0, 0, width, height); main.getColorTexture(), backdrop.getColorTexture(), 0, 0, 0, 0, 0, width, height);
PostEffectProcessor processor = getBlur(blur); PostChain processor = getBlur(blur);
if (processor != null) { if (processor != null) {
processor.render(backdrop, POOL); processor.process(backdrop, POOL);
} }
POOL.decrementLifespan(); POOL.endFrame();
release(blur); release(blur);
} }
// The mask, then the copy blurred by blur, as the glass pipeline samples them // The mask, then the copy blurred by blur, as the glass pipeline samples them
public static TextureSetup textures(AbstractTexture mask, int blur) { public static TextureSetup textures(AbstractTexture mask, int blur) {
GpuTextureView backdrop = BACKDROPS.get(blur).getColorAttachmentView(); GpuTextureView backdrop = BACKDROPS.get(blur).getColorTextureView();
//? if >=1.21.11 //? if >=1.21.11
return TextureSetup.of(mask.getGlTextureView(), mask.getSampler(), backdrop, RenderSystem.getSamplerCache().get(FilterMode.LINEAR)); return TextureSetup.doubleTexture(mask.getTextureView(), mask.getSampler(), backdrop, RenderSystem.getSamplerCache().getClampToEdge(FilterMode.LINEAR));
//? if <1.21.11 //? if <1.21.11
//return TextureSetup.of(mask.getGlTextureView(), backdrop); //return TextureSetup.doubleTexture(mask.getTextureView(), backdrop);
} }
// Frees the copies and blurs of strengths that are no longer set, besides kept // Frees the copies and blurs of strengths that are no longer set, besides kept
@@ -107,7 +107,7 @@ public final class GlassRenderer {
BACKDROPS.entrySet().removeIf(entry -> { BACKDROPS.entrySet().removeIf(entry -> {
boolean unused = entry.getKey() != kept && !isSet(entry.getKey()); boolean unused = entry.getKey() != kept && !isSet(entry.getKey());
if (unused) { if (unused) {
entry.getValue().delete(); entry.getValue().destroyBuffers();
} }
return unused; return unused;
}); });
@@ -124,7 +124,7 @@ public final class GlassRenderer {
return blur == Config.menuBlur.value || blur == Config.widgetBlur.value; return blur == Config.menuBlur.value || blur == Config.widgetBlur.value;
} }
private static PostEffectProcessor getBlur(int blur) { private static PostChain getBlur(int blur) {
if (!BLURS.containsKey(blur)) { if (!BLURS.containsKey(blur)) {
BLURS.put(blur, loadBlur(blur)); BLURS.put(blur, loadBlur(blur));
} }
@@ -133,14 +133,14 @@ public final class GlassRenderer {
// Vanilla's blur, with its radius set to blur. Vanilla's own leaves it at 0, which makes the shader // Vanilla's blur, with its radius set to blur. Vanilla's own leaves it at 0, which makes the shader
// read the menu blur setting (Saturn's animated background blur while a Saturn screen is open). // read the menu blur setting (Saturn's animated background blur while a Saturn screen is open).
private static PostEffectProcessor loadBlur(int blur) { private static PostChain loadBlur(int blur) {
try (Reader reader = SaturnClient.client.getResourceManager().getResourceOrThrow(BLUR).getReader()) { try (Reader reader = SaturnClient.client.getResourceManager().getResourceOrThrow(BLUR).openAsReader()) {
JsonElement json = JsonParser.parseReader(reader); JsonElement json = JsonParser.parseReader(reader);
setRadius(json, blur); setRadius(json, blur);
PostEffectPipeline pipeline = PostEffectPipeline.CODEC.parse(JsonOps.INSTANCE, json).getOrThrow(); PostChainConfig pipeline = PostChainConfig.CODEC.parse(JsonOps.INSTANCE, json).getOrThrow();
return PostEffectProcessor.parseEffect(pipeline, SaturnClient.client.getTextureManager(), return PostChain.load(pipeline, SaturnClient.client.getTextureManager(),
DefaultFramebufferSet.MAIN_ONLY, Identifier.of("saturnclient", "glass_blur_" + blur), PROJECTION); LevelTargetBundle.MAIN_TARGETS, Identifier.fromNamespaceAndPath("saturnclient", "glass_blur_" + blur), PROJECTION);
} catch (Exception e) { } catch (Exception e) {
SaturnClient.LOGGER.error("Couldn't load the glass blur", e); SaturnClient.LOGGER.error("Couldn't load the glass blur", e);
return null; return null;
@@ -171,68 +171,68 @@ import com.mojang.blaze3d.textures.FilterMode;
import org.saturnclient.config.Config; import org.saturnclient.config.Config;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.gl.Framebuffer; import com.mojang.blaze3d.pipeline.RenderTarget;
import net.minecraft.client.gl.PostEffectProcessor; import net.minecraft.client.renderer.PostChain;
import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.client.gl.SimpleFramebuffer; import com.mojang.blaze3d.pipeline.TextureTarget;
import net.minecraft.client.render.DefaultFramebufferSet; import net.minecraft.client.renderer.LevelTargetBundle;
import net.minecraft.client.render.RenderLayer; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.render.RenderPhase; import net.minecraft.client.renderer.RenderStateShard;
import net.minecraft.client.util.Pool; import com.mojang.blaze3d.resource.CrossFrameResourcePool;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
public final class GlassRenderer { public final class GlassRenderer {
private static final RenderPipeline PIPELINE = RenderPipeline.builder(RenderPipelines.POSITION_TEX_COLOR_SNIPPET) private static final RenderPipeline PIPELINE = RenderPipeline.builder(RenderPipelines.GUI_TEXTURED_SNIPPET)
.withLocation(Identifier.of("saturnclient", "pipeline/glass")) .withLocation(Identifier.fromNamespaceAndPath("saturnclient", "pipeline/glass"))
.withFragmentShader(Identifier.of("saturnclient", "core/glass_pre_1_21_6")) .withFragmentShader(Identifier.fromNamespaceAndPath("saturnclient", "core/glass_pre_1_21_6"))
.withSampler("Sampler1") .withSampler("Sampler1")
.build(); .build();
private static final Identifier BLUR = Identifier.ofVanilla("blur"); private static final Identifier BLUR = Identifier.withDefaultNamespace("blur");
// For the blur's intermediate target, freed once unused for a few frames // For the blur's intermediate target, freed once unused for a few frames
private static final Pool POOL = new Pool(3); private static final CrossFrameResourcePool POOL = new CrossFrameResourcePool(3);
private static final Map<Integer, SimpleFramebuffer> BACKDROPS = new HashMap<>(); private static final Map<Integer, TextureTarget> BACKDROPS = new HashMap<>();
// By mask and blur // By mask and blur
private static final Map<String, RenderLayer> LAYERS = new HashMap<>(); private static final Map<String, RenderType> LAYERS = new HashMap<>();
// The game behind the screen before the screen blurs it, which glass is blurred from // The game behind the screen before the screen blurs it, which glass is blurred from
private static SimpleFramebuffer background; private static TextureTarget background;
private GlassRenderer() { private GlassRenderer() {
} }
// Saves the main framebuffer for glass. Call each frame before the screen blurs its background. // Saves the main framebuffer for glass. Call each frame before the screen blurs its background.
public static void saveBackground() { public static void saveBackground() {
background = copy(SaturnClient.client.getFramebuffer(), background, "Saturn glass background"); background = copy(SaturnClient.client.getMainRenderTarget(), background, "Saturn glass background");
} }
// Copies the saved background and blurs the copy by blur. Call once a frame for each blur, before // Copies the saved background and blurs the copy by blur. Call once a frame for each blur, before
// drawing glass with it. // drawing glass with it.
public static void captureBackdrop(int blur) { public static void captureBackdrop(int blur) {
Framebuffer from = background != null ? background : SaturnClient.client.getFramebuffer(); RenderTarget from = background != null ? background : SaturnClient.client.getMainRenderTarget();
SimpleFramebuffer backdrop = copy(from, BACKDROPS.get(blur), "Saturn glass " + blur); TextureTarget backdrop = copy(from, BACKDROPS.get(blur), "Saturn glass " + blur);
BACKDROPS.put(blur, backdrop); BACKDROPS.put(blur, backdrop);
PostEffectProcessor processor = SaturnClient.client.getShaderLoader().loadPostEffect(BLUR, PostChain processor = SaturnClient.client.getShaderManager().getPostChain(BLUR,
DefaultFramebufferSet.MAIN_ONLY); LevelTargetBundle.MAIN_TARGETS);
if (processor != null) { if (processor != null) {
processor.render(backdrop, POOL, pass -> pass.setUniform("Radius", (float) blur)); processor.process(backdrop, POOL, pass -> pass.setUniform("Radius", (float) blur));
} }
POOL.decrementLifespan(); POOL.endFrame();
release(blur); release(blur);
} }
// Draws glass through mask with the copy blurred by blur // Draws glass through mask with the copy blurred by blur
public static RenderLayer getLayer(Identifier mask, int blur) { public static RenderType getLayer(Identifier mask, int blur) {
return LAYERS.computeIfAbsent(mask + " " + blur, key -> RenderLayer.of("saturn_glass", 786432, PIPELINE, return LAYERS.computeIfAbsent(mask + " " + blur, key -> RenderType.create("saturn_glass", 786432, PIPELINE,
RenderLayer.MultiPhaseParameters.builder() RenderType.CompositeState.builder()
.texture(new RenderPhase.TextureBase(() -> { .setTextureState(new RenderStateShard.EmptyTextureStateShard(() -> {
RenderSystem.setShaderTexture(0, RenderSystem.setShaderTexture(0,
SaturnClient.client.getTextureManager().getTexture(mask).getGlTexture()); SaturnClient.client.getTextureManager().getTexture(mask).getTexture());
RenderSystem.setShaderTexture(1, BACKDROPS.get(blur).getColorAttachment()); RenderSystem.setShaderTexture(1, BACKDROPS.get(blur).getColorTexture());
}, () -> { }, () -> {
})) }))
.build(false))); .createCompositeState(false)));
} }
// Frees the copies of strengths that are no longer set, besides kept // Frees the copies of strengths that are no longer set, besides kept
@@ -241,26 +241,26 @@ public final class GlassRenderer {
boolean unused = entry.getKey() != kept && entry.getKey() != Config.menuBlur.value boolean unused = entry.getKey() != kept && entry.getKey() != Config.menuBlur.value
&& entry.getKey() != Config.widgetBlur.value; && entry.getKey() != Config.widgetBlur.value;
if (unused) { if (unused) {
entry.getValue().delete(); entry.getValue().destroyBuffers();
} }
return unused; return unused;
}); });
} }
// Copies from into to, made or resized to match // Copies from into to, made or resized to match
private static SimpleFramebuffer copy(Framebuffer from, SimpleFramebuffer to, String name) { private static TextureTarget copy(RenderTarget from, TextureTarget to, String name) {
int width = from.textureWidth; int width = from.width;
int height = from.textureHeight; int height = from.height;
if (to == null) { if (to == null) {
to = new SimpleFramebuffer(name, width, height, false); to = new TextureTarget(name, width, height, false);
} else if (to.textureWidth != width || to.textureHeight != height) { } else if (to.width != width || to.height != height) {
to.resize(width, height); to.resize(width, height);
} }
to.getColorAttachment().setTextureFilter(FilterMode.LINEAR, false); to.getColorTexture().setTextureFilter(FilterMode.LINEAR, false);
RenderSystem.getDevice().createCommandEncoder().copyTextureToTexture( RenderSystem.getDevice().createCommandEncoder().copyTextureToTexture(
from.getColorAttachment(), to.getColorAttachment(), 0, 0, 0, 0, 0, width, height); from.getColorTexture(), to.getColorTexture(), 0, 0, 0, 0, 0, width, height);
return to; return to;
} }
} }
@@ -277,72 +277,72 @@ import com.mojang.blaze3d.systems.RenderSystem;
import org.saturnclient.config.Config; import org.saturnclient.config.Config;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
import net.minecraft.client.gl.Defines; import net.minecraft.client.renderer.ShaderDefines;
import net.minecraft.client.gl.Framebuffer; import com.mojang.blaze3d.pipeline.RenderTarget;
import net.minecraft.client.gl.PostEffectProcessor; import net.minecraft.client.renderer.PostChain;
import net.minecraft.client.gl.ShaderProgramKey; import net.minecraft.client.renderer.ShaderProgram;
import net.minecraft.client.gl.SimpleFramebuffer; import com.mojang.blaze3d.pipeline.TextureTarget;
import net.minecraft.client.render.DefaultFramebufferSet; import net.minecraft.client.renderer.LevelTargetBundle;
import net.minecraft.client.render.RenderLayer; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.render.RenderPhase; import net.minecraft.client.renderer.RenderStateShard;
import net.minecraft.client.render.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.render.VertexFormats; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import net.minecraft.client.util.Pool; import com.mojang.blaze3d.resource.CrossFrameResourcePool;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
public final class GlassRenderer { public final class GlassRenderer {
private static final ShaderProgramKey PROGRAM = new ShaderProgramKey(Identifier.of("saturnclient", "core/glass"), private static final ShaderProgram PROGRAM = new ShaderProgram(Identifier.fromNamespaceAndPath("saturnclient", "core/glass"),
VertexFormats.POSITION_TEXTURE_COLOR, Defines.EMPTY); DefaultVertexFormat.POSITION_TEX_COLOR, ShaderDefines.EMPTY);
private static final Identifier BLUR = Identifier.ofVanilla("blur"); private static final Identifier BLUR = Identifier.withDefaultNamespace("blur");
// For the blur's intermediate target, freed once unused for a few frames // For the blur's intermediate target, freed once unused for a few frames
private static final Pool POOL = new Pool(3); private static final CrossFrameResourcePool POOL = new CrossFrameResourcePool(3);
private static final Map<Integer, SimpleFramebuffer> BACKDROPS = new HashMap<>(); private static final Map<Integer, TextureTarget> BACKDROPS = new HashMap<>();
// By mask and blur // By mask and blur
private static final Map<String, RenderLayer> LAYERS = new HashMap<>(); private static final Map<String, RenderType> LAYERS = new HashMap<>();
// The game behind the screen before the screen blurs it, which glass is blurred from // The game behind the screen before the screen blurs it, which glass is blurred from
private static SimpleFramebuffer background; private static TextureTarget background;
private GlassRenderer() { private GlassRenderer() {
} }
// Saves the main framebuffer for glass. Call each frame before the screen blurs its background. // Saves the main framebuffer for glass. Call each frame before the screen blurs its background.
public static void saveBackground() { public static void saveBackground() {
background = copy(SaturnClient.client.getFramebuffer(), background); background = copy(SaturnClient.client.getMainRenderTarget(), background);
} }
// Copies the saved background and blurs the copy by blur. Call once a frame for each blur, before // Copies the saved background and blurs the copy by blur. Call once a frame for each blur, before
// drawing glass with it. // drawing glass with it.
public static void captureBackdrop(int blur) { public static void captureBackdrop(int blur) {
Framebuffer from = background != null ? background : SaturnClient.client.getFramebuffer(); RenderTarget from = background != null ? background : SaturnClient.client.getMainRenderTarget();
SimpleFramebuffer backdrop = copy(from, BACKDROPS.get(blur)); TextureTarget backdrop = copy(from, BACKDROPS.get(blur));
BACKDROPS.put(blur, backdrop); BACKDROPS.put(blur, backdrop);
PostEffectProcessor processor = SaturnClient.client.getShaderLoader().loadPostEffect(BLUR, PostChain processor = SaturnClient.client.getShaderManager().getPostChain(BLUR,
DefaultFramebufferSet.MAIN_ONLY); LevelTargetBundle.MAIN_TARGETS);
if (processor != null) { if (processor != null) {
processor.setUniforms("Radius", blur); processor.setUniform("Radius", blur);
processor.render(backdrop, POOL); processor.process(backdrop, POOL);
} }
POOL.decrementLifespan(); POOL.endFrame();
release(blur); release(blur);
SaturnClient.client.getFramebuffer().beginWrite(false); SaturnClient.client.getMainRenderTarget().bindWrite(false);
} }
// Draws glass through mask with the copy blurred by blur // Draws glass through mask with the copy blurred by blur
public static RenderLayer getLayer(Identifier mask, int blur) { public static RenderType getLayer(Identifier mask, int blur) {
return LAYERS.computeIfAbsent(mask + " " + blur, key -> RenderLayer.of("saturn_glass", return LAYERS.computeIfAbsent(mask + " " + blur, key -> RenderType.create("saturn_glass",
VertexFormats.POSITION_TEXTURE_COLOR, VertexFormat.DrawMode.QUADS, 786432, DefaultVertexFormat.POSITION_TEX_COLOR, VertexFormat.Mode.QUADS, 786432,
RenderLayer.MultiPhaseParameters.builder() RenderType.CompositeState.builder()
.texture(new RenderPhase.TextureBase(() -> { .setTextureState(new RenderStateShard.EmptyTextureStateShard(() -> {
RenderSystem.setShaderTexture(0, mask); RenderSystem.setShaderTexture(0, mask);
RenderSystem.setShaderTexture(1, BACKDROPS.get(blur).getColorAttachment()); RenderSystem.setShaderTexture(1, BACKDROPS.get(blur).getColorTextureId());
}, () -> { }, () -> {
})) }))
.program(new RenderPhase.ShaderProgram(PROGRAM)) .setShaderState(new RenderStateShard.ShaderStateShard(PROGRAM))
.transparency(RenderPhase.TRANSLUCENT_TRANSPARENCY) .setTransparencyState(RenderStateShard.TRANSLUCENT_TRANSPARENCY)
.build(false))); .createCompositeState(false)));
} }
// Frees the copies of strengths that are no longer set, besides kept // Frees the copies of strengths that are no longer set, besides kept
@@ -351,29 +351,29 @@ public final class GlassRenderer {
boolean unused = entry.getKey() != kept && entry.getKey() != Config.menuBlur.value boolean unused = entry.getKey() != kept && entry.getKey() != Config.menuBlur.value
&& entry.getKey() != Config.widgetBlur.value; && entry.getKey() != Config.widgetBlur.value;
if (unused) { if (unused) {
entry.getValue().delete(); entry.getValue().destroyBuffers();
} }
return unused; return unused;
}); });
} }
// Copies from into to, made or resized to match // Copies from into to, made or resized to match
private static SimpleFramebuffer copy(Framebuffer from, SimpleFramebuffer to) { private static TextureTarget copy(RenderTarget from, TextureTarget to) {
int width = from.textureWidth; int width = from.width;
int height = from.textureHeight; int height = from.height;
if (to == null) { if (to == null) {
to = new SimpleFramebuffer(width, height, false); to = new TextureTarget(width, height, false);
} else if (to.textureWidth != width || to.textureHeight != height) { } else if (to.width != width || to.height != height) {
to.resize(width, height); to.resize(width, height);
} }
to.setTexFilter(GL11.GL_LINEAR); to.setFilterMode(GL11.GL_LINEAR);
GlStateManager._glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, from.fbo); GlStateManager._glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, from.frameBufferId);
GlStateManager._glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, to.fbo); GlStateManager._glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, to.frameBufferId);
GlStateManager._glBlitFrameBuffer(0, 0, width, height, 0, 0, width, height, GL11.GL_COLOR_BUFFER_BIT, GlStateManager._glBlitFrameBuffer(0, 0, width, height, 0, 0, width, height, GL11.GL_COLOR_BUFFER_BIT,
GL11.GL_NEAREST); GL11.GL_NEAREST);
SaturnClient.client.getFramebuffer().beginWrite(false); SaturnClient.client.getMainRenderTarget().bindWrite(false);
return to; return to;
} }
} }
@@ -28,32 +28,32 @@ import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.resources.Fonts; import org.saturnclient.ui.resources.Fonts;
import org.saturnclient.ui.resources.SvgTexture; import org.saturnclient.ui.resources.SvgTexture;
import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.ScreenRect; import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.gui.render.state.ColoredQuadGuiElementRenderState; import net.minecraft.client.gui.render.state.ColoredRectangleRenderState;
import net.minecraft.client.gui.render.state.GuiRenderState; import net.minecraft.client.gui.render.state.GuiRenderState;
import net.minecraft.client.gui.render.state.ItemGuiElementRenderState; import net.minecraft.client.gui.render.state.GuiItemRenderState;
import net.minecraft.client.gui.render.state.TextGuiElementRenderState; import net.minecraft.client.gui.render.state.GuiTextRenderState;
import net.minecraft.client.gui.render.state.TexturedQuadGuiElementRenderState; import net.minecraft.client.gui.render.state.BlitRenderState;
import net.minecraft.client.gui.render.state.special.EntityGuiElementRenderState; import net.minecraft.client.gui.render.state.pip.GuiEntityRenderState;
import net.minecraft.client.render.entity.state.EntityRenderState; import net.minecraft.client.renderer.entity.state.EntityRenderState;
//? if >=1.21.7 { //? if >=1.21.7 {
import net.minecraft.client.render.item.KeyedItemRenderState; import net.minecraft.client.renderer.item.TrackingItemStackRenderState;
//?} else //?} else
//import net.minecraft.client.render.item.ItemRenderState; //import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.client.texture.AbstractTexture; import net.minecraft.client.renderer.texture.AbstractTexture;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.texture.TextureSetup; import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.item.ItemDisplayContext; import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.text.Text; import net.minecraft.network.chat.Component;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
import net.minecraft.util.crash.CrashException; import net.minecraft.ReportedException;
import net.minecraft.util.crash.CrashReport; import net.minecraft.CrashReport;
import net.minecraft.util.crash.CrashReportSection; import net.minecraft.CrashReportCategory;
import net.minecraft.world.World; import net.minecraft.world.level.Level;
public class RenderScopeImpl implements RenderScope { public class RenderScopeImpl implements RenderScope {
@@ -65,8 +65,8 @@ public class RenderScopeImpl implements RenderScope {
// The glass blurs made for this scope's frame // The glass blurs made for this scope's frame
private final Set<Integer> capturedBlurs = new HashSet<>(); private final Set<Integer> capturedBlurs = new HashSet<>();
public RenderScopeImpl(DrawContext context) { public RenderScopeImpl(GuiGraphics context) {
this(context.getMatrices(), ((DrawContextAccessor) (Object) context).getState()); this(context.pose(), ((DrawContextAccessor) (Object) context).getState());
} }
public RenderScopeImpl(Matrix3x2fStack matrices, GuiRenderState state) { public RenderScopeImpl(Matrix3x2fStack matrices, GuiRenderState state) {
@@ -95,10 +95,10 @@ public class RenderScopeImpl implements RenderScope {
@Override @Override
public void fill(int x1, int y1, int x2, int y2, int color) { public void fill(int x1, int y1, int x2, int y2, int color) {
this.state.addSimpleElement( this.state.submitGuiElement(
new ColoredQuadGuiElementRenderState( new ColoredRectangleRenderState(
RenderPipelines.GUI, RenderPipelines.GUI,
TextureSetup.empty(), TextureSetup.noTexture(),
new Matrix3x2f(this.matrices.stack), new Matrix3x2f(this.matrices.stack),
x1, y1, x2, y2, color, color, x1, y1, x2, y2, color, color,
this.scissorStack.peekLast())); this.scissorStack.peekLast()));
@@ -149,10 +149,10 @@ public class RenderScopeImpl implements RenderScope {
matrices.translate(x, y + (lineIndex * Fonts.getHeight())); matrices.translate(x, y + (lineIndex * Fonts.getHeight()));
matrices.scale(scale, scale); matrices.scale(scale, scale);
this.state.addText( this.state.submitText(
new TextGuiElementRenderState( new GuiTextRenderState(
SaturnClient.client.textRenderer, SaturnClient.client.font,
((Text) Fonts.setFont(line, font)).asOrderedText(), ((Component) Fonts.setFont(line, font)).getVisualOrderText(),
new Matrix3x2f(this.matrices.stack), new Matrix3x2f(this.matrices.stack),
0, font == 0 ? 1 : 8, 0, font == 0 ? 1 : 8,
//? if >=1.21.11 { //? if >=1.21.11 {
@@ -168,12 +168,12 @@ public class RenderScopeImpl implements RenderScope {
@Override @Override
public int getScaledWindowWidth() { public int getScaledWindowWidth() {
return SaturnClient.client.getWindow().getScaledWidth(); return SaturnClient.client.getWindow().getGuiScaledWidth();
} }
@Override @Override
public int getScaledWindowHeight() { public int getScaledWindowHeight() {
return SaturnClient.client.getWindow().getScaledHeight(); return SaturnClient.client.getWindow().getGuiScaledHeight();
} }
// Texture rendering // Texture rendering
@@ -217,17 +217,17 @@ public class RenderScopeImpl implements RenderScope {
} }
GpuTextureView gpuTextureView = SaturnClient.client.getTextureManager() GpuTextureView gpuTextureView = SaturnClient.client.getTextureManager()
.getTexture(sprite).getGlTextureView(); .getTexture(sprite).getTextureView();
//? if >=1.21.11 //? if >=1.21.11
AbstractTexture abstractTexture = SaturnClient.client.getTextureManager().getTexture(sprite); AbstractTexture abstractTexture = SaturnClient.client.getTextureManager().getTexture(sprite);
this.state.addSimpleElement(new TexturedQuadGuiElementRenderState( this.state.submitGuiElement(new BlitRenderState(
RenderPipelines.GUI_TEXTURED, RenderPipelines.GUI_TEXTURED,
//? if >=1.21.11 { //? if >=1.21.11 {
TextureSetup.of(gpuTextureView, abstractTexture.getSampler()), TextureSetup.singleTexture(gpuTextureView, abstractTexture.getSampler()),
//?} else //?} else
//TextureSetup.withoutGlTexture(gpuTextureView), //TextureSetup.singleTexture(gpuTextureView),
new Matrix3x2f(this.matrices.stack), new Matrix3x2f(this.matrices.stack),
x1, y1, x2, y2, u1, u2, v1, v2, color, x1, y1, x2, y2, u1, u2, v1, v2, color,
this.scissorStack.peekLast())); this.scissorStack.peekLast()));
@@ -244,7 +244,7 @@ public class RenderScopeImpl implements RenderScope {
} }
AbstractTexture maskTexture = SaturnClient.client.getTextureManager().getTexture((Identifier) (Object) mask); AbstractTexture maskTexture = SaturnClient.client.getTextureManager().getTexture((Identifier) (Object) mask);
this.state.addSimpleElement(new TexturedQuadGuiElementRenderState( this.state.submitGuiElement(new BlitRenderState(
GlassRenderer.PIPELINE, GlassRenderer.PIPELINE,
GlassRenderer.textures(maskTexture, blur), GlassRenderer.textures(maskTexture, blur),
new Matrix3x2f(this.matrices.stack), new Matrix3x2f(this.matrices.stack),
@@ -255,7 +255,7 @@ public class RenderScopeImpl implements RenderScope {
// Scissor management // Scissor management
@Override @Override
public void enableScissor(int x1, int y1, int x2, int y2) { public void enableScissor(int x1, int y1, int x2, int y2) {
ScreenRect rect = new ScreenRect(x1, y1, x2 - x1, y2 - y1).transform(this.matrices.stack); ScreenRectangle rect = new ScreenRectangle(x1, y1, x2 - x1, y2 - y1).transformAxisAligned(this.matrices.stack);
scissorStack.push(rect); scissorStack.push(rect);
} }
@@ -270,12 +270,12 @@ public class RenderScopeImpl implements RenderScope {
} }
public static class ScissorStack { public static class ScissorStack {
private final Deque<ScreenRect> stack = new ArrayDeque<>(); private final Deque<ScreenRectangle> stack = new ArrayDeque<>();
public ScreenRect push(ScreenRect rect) { public ScreenRectangle push(ScreenRectangle rect) {
ScreenRect last = stack.peekLast(); ScreenRectangle last = stack.peekLast();
if (last != null) { if (last != null) {
ScreenRect intersection = Objects.requireNonNullElse(rect.intersection(last), ScreenRect.empty()); ScreenRectangle intersection = Objects.requireNonNullElse(rect.intersection(last), ScreenRectangle.empty());
stack.addLast(intersection); stack.addLast(intersection);
return intersection; return intersection;
} else { } else {
@@ -285,7 +285,7 @@ public class RenderScopeImpl implements RenderScope {
} }
@Nullable @Nullable
public ScreenRect pop() { public ScreenRectangle pop() {
if (stack.isEmpty()) if (stack.isEmpty())
throw new IllegalStateException("Scissor stack underflow"); throw new IllegalStateException("Scissor stack underflow");
stack.removeLast(); stack.removeLast();
@@ -293,48 +293,48 @@ public class RenderScopeImpl implements RenderScope {
} }
@Nullable @Nullable
public ScreenRect peekLast() { public ScreenRectangle peekLast() {
return stack.peekLast(); return stack.peekLast();
} }
public boolean contains(int x, int y) { public boolean contains(int x, int y) {
return stack.isEmpty() || stack.peekLast().contains(x, y); return stack.isEmpty() || stack.peekLast().containsPoint(x, y);
} }
} }
// Item rendering // Item rendering
@Override @Override
public void drawItem(ItemStackRef stack, int x, int y) { public void drawItem(ItemStackRef stack, int x, int y) {
drawItem(null, SaturnClient.client.world, stack, x, y, 0); drawItem(null, SaturnClient.client.level, stack, x, y, 0);
} }
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStackRef stack, int x, int y, private void drawItem(@Nullable LivingEntity entity, @Nullable Level world, ItemStackRef stack, int x, int y,
int seed) { int seed) {
drawItem(entity, world, (ItemStack) (Object) stack, x, y, seed, 0); drawItem(entity, world, (ItemStack) (Object) stack, x, y, seed, 0);
} }
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, int seed, private void drawItem(@Nullable LivingEntity entity, @Nullable Level world, ItemStack stack, int x, int y, int seed,
int z) { int z) {
if (!stack.isEmpty()) { if (!stack.isEmpty()) {
//? if >=1.21.7 { //? if >=1.21.7 {
KeyedItemRenderState keyedItemRenderState = new KeyedItemRenderState(); TrackingItemStackRenderState keyedItemRenderState = new TrackingItemStackRenderState();
//?} else //?} else
//ItemRenderState keyedItemRenderState = new ItemRenderState(); //ItemStackRenderState keyedItemRenderState = new ItemStackRenderState();
SaturnClient.client.getItemModelManager().clearAndUpdate(keyedItemRenderState, stack, SaturnClient.client.getItemModelResolver().updateForTopItem(keyedItemRenderState, stack,
ItemDisplayContext.GUI, world, ItemDisplayContext.GUI, world,
entity, seed); entity, seed);
try { try {
this.state.addItem(new ItemGuiElementRenderState(stack.getItem().getName().toString(), this.state.submitItem(new GuiItemRenderState(stack.getItem().getName().toString(),
new Matrix3x2f(this.matrices.stack), keyedItemRenderState, x, y, new Matrix3x2f(this.matrices.stack), keyedItemRenderState, x, y,
this.scissorStack.peekLast())); this.scissorStack.peekLast()));
} catch (Throwable throwable) { } catch (Throwable throwable) {
CrashReport crashReport = CrashReport.create(throwable, "Rendering item"); CrashReport crashReport = CrashReport.forThrowable(throwable, "Rendering item");
CrashReportSection crashReportSection = crashReport.addElement("Item being rendered"); CrashReportCategory crashReportSection = crashReport.addCategory("Item being rendered");
crashReportSection.add("Item Type", () -> String.valueOf(stack.getItem())); crashReportSection.setDetail("Item Type", () -> String.valueOf(stack.getItem()));
crashReportSection.add("Item Components", () -> String.valueOf(stack.getComponents())); crashReportSection.setDetail("Item Components", () -> String.valueOf(stack.getComponents()));
crashReportSection.add("Item Foil", () -> String.valueOf(stack.hasGlint())); crashReportSection.setDetail("Item Foil", () -> String.valueOf(stack.hasFoil()));
throw new CrashException(crashReport); throw new ReportedException(crashReport);
} }
} }
} }
@@ -346,12 +346,12 @@ public class RenderScopeImpl implements RenderScope {
@Override @Override
public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height, int color) { public void drawSpriteStretched(SpriteRef sprite, int x, int y, int width, int height, int color) {
Sprite mcSprite = (Sprite) sprite; TextureAtlasSprite mcSprite = (TextureAtlasSprite) sprite;
if (color == 0 || width == 0 || height == 0) if (color == 0 || width == 0 || height == 0)
return; return;
drawTexturedQuad(mcSprite.getAtlasId(), x, x + width, y, y + height, drawTexturedQuad(mcSprite.atlasLocation(), x, x + width, y, y + height,
mcSprite.getMinU(), mcSprite.getMaxU(), mcSprite.getMinV(), mcSprite.getMaxV(), color); mcSprite.getU0(), mcSprite.getU1(), mcSprite.getV0(), mcSprite.getV1(), color);
} }
@Override @Override
@@ -382,7 +382,7 @@ public class RenderScopeImpl implements RenderScope {
float adjustedScale = scale * scaleX; // apply matrix scale to entity scale too float adjustedScale = scale * scaleX; // apply matrix scale to entity scale too
this.state.addSpecialElement(new EntityGuiElementRenderState(entityState, translation, rotation, this.state.submitPicturesInPictureState(new GuiEntityRenderState(entityState, translation, rotation,
overrideCameraAngle, adjustedX1, adjustedY1, adjustedX2, adjustedY2, adjustedScale, overrideCameraAngle, adjustedX1, adjustedY1, adjustedX2, adjustedY2, adjustedScale,
this.scissorStack.peekLast())); this.scissorStack.peekLast()));
} }
@@ -410,57 +410,57 @@ import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.resources.Fonts; import org.saturnclient.ui.resources.Fonts;
import org.saturnclient.ui.resources.SvgTexture; import org.saturnclient.ui.resources.SvgTexture;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.Font;
import net.minecraft.client.font.TextRenderer.TextLayerType; import net.minecraft.client.gui.Font.DisplayMode;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.ScreenRect; import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.render.DiffuseLighting; import com.mojang.blaze3d.platform.Lighting;
import net.minecraft.client.render.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.render.RenderLayer; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.render.VertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.render.item.ItemRenderState; import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.util.Window; import com.mojang.blaze3d.platform.Window;
import net.minecraft.client.util.math.MatrixStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
//? if >=1.21.5 //? if >=1.21.5
import net.minecraft.item.ItemDisplayContext; import net.minecraft.world.item.ItemDisplayContext;
//? if <1.21.5 //? if <1.21.5
//import net.minecraft.item.ModelTransformationMode; //import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.text.Text; import net.minecraft.network.chat.Component;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
import net.minecraft.util.crash.CrashException; import net.minecraft.ReportedException;
import net.minecraft.util.crash.CrashReport; import net.minecraft.CrashReport;
import net.minecraft.util.crash.CrashReportSection; import net.minecraft.CrashReportCategory;
import net.minecraft.world.World; import net.minecraft.world.level.Level;
public class RenderScopeImpl implements RenderScope { public class RenderScopeImpl implements RenderScope {
// ---------------------------- // ----------------------------
// Fields // Fields
// ---------------------------- // ----------------------------
public MatrixStack matrices; public PoseStack matrices;
public VertexConsumerProvider.Immediate vertexConsumers; public MultiBufferSource.BufferSource vertexConsumers;
private ScissorStack scissorStack = new ScissorStack(); private ScissorStack scissorStack = new ScissorStack();
private int opacity = 255 << 24; private int opacity = 255 << 24;
// The glass blurs made for this scope's frame // The glass blurs made for this scope's frame
private final Set<Integer> capturedBlurs = new HashSet<>(); private final Set<Integer> capturedBlurs = new HashSet<>();
private final ItemRenderState itemRenderState; private final ItemStackRenderState itemRenderState;
// ---------------------------- // ----------------------------
// Constructors // Constructors
// ---------------------------- // ----------------------------
public RenderScopeImpl(DrawContext context) { public RenderScopeImpl(GuiGraphics context) {
this(context.getMatrices(), ((DrawContextAccessor) context).getVertexConsumers()); this(context.pose(), ((DrawContextAccessor) context).getVertexConsumers());
} }
public RenderScopeImpl(MatrixStack matrices, VertexConsumerProvider.Immediate vertexConsumers) { public RenderScopeImpl(PoseStack matrices, MultiBufferSource.BufferSource vertexConsumers) {
this.matrices = matrices; this.matrices = matrices;
this.vertexConsumers = vertexConsumers; this.vertexConsumers = vertexConsumers;
this.scissorStack = new ScissorStack(); this.scissorStack = new ScissorStack();
this.itemRenderState = new ItemRenderState(); this.itemRenderState = new ItemStackRenderState();
} }
// ---------------------------- // ----------------------------
@@ -492,22 +492,22 @@ public class RenderScopeImpl implements RenderScope {
// ---------------------------- // ----------------------------
@Override @Override
public void draw() { public void draw() {
this.vertexConsumers.draw(); this.vertexConsumers.endBatch();
} }
@Override @Override
public int getScaledWindowWidth() { public int getScaledWindowWidth() {
return SaturnClient.client.getWindow().getScaledWidth(); return SaturnClient.client.getWindow().getGuiScaledWidth();
} }
@Override @Override
public int getScaledWindowHeight() { public int getScaledWindowHeight() {
return SaturnClient.client.getWindow().getScaledHeight(); return SaturnClient.client.getWindow().getGuiScaledHeight();
} }
public void draw(Consumer<VertexConsumerProvider> drawer) { public void draw(Consumer<MultiBufferSource> drawer) {
drawer.accept(this.vertexConsumers); drawer.accept(this.vertexConsumers);
this.vertexConsumers.draw(); this.vertexConsumers.endBatch();
} }
// ---------------------------- // ----------------------------
@@ -519,7 +519,7 @@ public class RenderScopeImpl implements RenderScope {
return; return;
color = getColor(color); color = getColor(color);
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix(); Matrix4f matrix4f = this.matrices.last().pose();
int x1 = x; int x1 = x;
int x2 = x + width; int x2 = x + width;
@@ -537,11 +537,11 @@ public class RenderScopeImpl implements RenderScope {
y2 = tmp; y2 = tmp;
} }
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(RenderLayer.getGui()); VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(RenderType.gui());
vertexConsumer.vertex(matrix4f, x1, y1, 0).color(color); vertexConsumer.addVertex(matrix4f, x1, y1, 0).setColor(color);
vertexConsumer.vertex(matrix4f, x1, y2, 0).color(color); vertexConsumer.addVertex(matrix4f, x1, y2, 0).setColor(color);
vertexConsumer.vertex(matrix4f, x2, y2, 0).color(color); vertexConsumer.addVertex(matrix4f, x2, y2, 0).setColor(color);
vertexConsumer.vertex(matrix4f, x2, y1, 0).color(color); vertexConsumer.addVertex(matrix4f, x2, y1, 0).setColor(color);
} }
@Override @Override
@@ -550,15 +550,15 @@ public class RenderScopeImpl implements RenderScope {
} }
public void fill(int x1, int y1, int x2, int y2, int z, int color) { public void fill(int x1, int y1, int x2, int y2, int z, int color) {
fill(RenderLayer.getGui(), x1, y1, x2, y2, z, color); fill(RenderType.gui(), x1, y1, x2, y2, z, color);
} }
public void fill(RenderLayer layer, int x1, int y1, int x2, int y2, int color) { public void fill(RenderType layer, int x1, int y1, int x2, int y2, int color) {
fill(layer, x1, y1, x2, y2, 0, color); fill(layer, x1, y1, x2, y2, 0, color);
} }
public void fill(RenderLayer layer, int x1, int y1, int x2, int y2, int z, int color) { public void fill(RenderType layer, int x1, int y1, int x2, int y2, int z, int color) {
Matrix4f matrix4f = this.matrices.peek().getPositionMatrix(); Matrix4f matrix4f = this.matrices.last().pose();
if (x1 < x2) { if (x1 < x2) {
int tmp = x1; int tmp = x1;
x1 = x2; x1 = x2;
@@ -571,10 +571,10 @@ public class RenderScopeImpl implements RenderScope {
} }
VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(layer); VertexConsumer vertexConsumer = this.vertexConsumers.getBuffer(layer);
vertexConsumer.vertex(matrix4f, x1, y1, z).color(color); vertexConsumer.addVertex(matrix4f, x1, y1, z).setColor(color);
vertexConsumer.vertex(matrix4f, x1, y2, z).color(color); vertexConsumer.addVertex(matrix4f, x1, y2, z).setColor(color);
vertexConsumer.vertex(matrix4f, x2, y2, z).color(color); vertexConsumer.addVertex(matrix4f, x2, y2, z).setColor(color);
vertexConsumer.vertex(matrix4f, x2, y1, z).color(color); vertexConsumer.addVertex(matrix4f, x2, y1, z).setColor(color);
} }
@Override @Override
@@ -603,13 +603,13 @@ public class RenderScopeImpl implements RenderScope {
int i = 0; int i = 0;
for (String line : text.split("\n")) { for (String line : text.split("\n")) {
color = getColor(color); color = getColor(color);
matrices.push(); matrices.pushPose();
matrices.translate(x, y + i * Fonts.getHeight(), 0); matrices.translate(x, y + i * Fonts.getHeight(), 0);
matrices.scale(scale, scale, 1.0f); matrices.scale(scale, scale, 1.0f);
TextRenderer textRenderer = SaturnClient.client.textRenderer; Font textRenderer = SaturnClient.client.font;
textRenderer.draw((Text) Fonts.setFont(line, font), 0, font == 0 ? 1 : 7, color, false, textRenderer.drawInBatch((Component) Fonts.setFont(line, font), 0, font == 0 ? 1 : 7, color, false,
matrices.peek().getPositionMatrix(), vertexConsumers, TextLayerType.NORMAL, 0, 15728880); matrices.last().pose(), vertexConsumers, DisplayMode.NORMAL, 0, 15728880);
matrices.pop(); matrices.popPose();
i++; i++;
} }
} }
@@ -648,12 +648,12 @@ public class RenderScopeImpl implements RenderScope {
@Override @Override
public void drawSpriteStretched(SpriteRef saturnSprite, int x, int y, int width, int height, int color) { public void drawSpriteStretched(SpriteRef saturnSprite, int x, int y, int width, int height, int color) {
Sprite sprite = (Sprite) saturnSprite; TextureAtlasSprite sprite = (TextureAtlasSprite) saturnSprite;
if (color == 0) if (color == 0)
return; return;
if (width != 0 && height != 0) { if (width != 0 && height != 0) {
drawTexturedQuad(sprite.getAtlasId(), x, x + width, y, y + height, drawTexturedQuad(sprite.atlasLocation(), x, x + width, y, y + height,
sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV(), color); sprite.getU0(), sprite.getU1(), sprite.getV0(), sprite.getV1(), color);
} }
} }
@@ -672,18 +672,18 @@ public class RenderScopeImpl implements RenderScope {
y2 *= 4; y2 *= 4;
color = getColor(color); color = getColor(color);
matrices.push(); matrices.pushPose();
matrices.scale(0.25f, 0.25f, 1.0f); matrices.scale(0.25f, 0.25f, 1.0f);
//? if <1.21.5 //? if <1.21.5
//RenderSystem.setShaderTexture(0, sprite); //RenderSystem.setShaderTexture(0, sprite);
RenderLayer renderLayer = RenderLayer.getGuiTextured(sprite); RenderType renderLayer = RenderType.guiTextured(sprite);
Matrix4f matrix4f = matrices.peek().getPositionMatrix(); Matrix4f matrix4f = matrices.last().pose();
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(renderLayer); VertexConsumer vertexConsumer = vertexConsumers.getBuffer(renderLayer);
vertexConsumer.vertex(matrix4f, x1, y1, 0).texture(u1, v1).color(color); vertexConsumer.addVertex(matrix4f, x1, y1, 0).setUv(u1, v1).setColor(color);
vertexConsumer.vertex(matrix4f, x1, y2, 0).texture(u1, v2).color(color); vertexConsumer.addVertex(matrix4f, x1, y2, 0).setUv(u1, v2).setColor(color);
vertexConsumer.vertex(matrix4f, x2, y2, 0).texture(u2, v2).color(color); vertexConsumer.addVertex(matrix4f, x2, y2, 0).setUv(u2, v2).setColor(color);
vertexConsumer.vertex(matrix4f, x2, y1, 0).texture(u2, v1).color(color); vertexConsumer.addVertex(matrix4f, x2, y1, 0).setUv(u2, v1).setColor(color);
matrices.pop(); matrices.popPose();
} }
@Override @Override
@@ -702,15 +702,15 @@ public class RenderScopeImpl implements RenderScope {
int y1 = y * 4; int y1 = y * 4;
int y2 = (y + height) * 4; int y2 = (y + height) * 4;
matrices.push(); matrices.pushPose();
matrices.scale(0.25f, 0.25f, 1.0f); matrices.scale(0.25f, 0.25f, 1.0f);
Matrix4f matrix4f = matrices.peek().getPositionMatrix(); Matrix4f matrix4f = matrices.last().pose();
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GlassRenderer.getLayer((Identifier) (Object) mask, blur)); VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GlassRenderer.getLayer((Identifier) (Object) mask, blur));
vertexConsumer.vertex(matrix4f, x1, y1, 0).texture(0, 0).color(color); vertexConsumer.addVertex(matrix4f, x1, y1, 0).setUv(0, 0).setColor(color);
vertexConsumer.vertex(matrix4f, x1, y2, 0).texture(0, 1).color(color); vertexConsumer.addVertex(matrix4f, x1, y2, 0).setUv(0, 1).setColor(color);
vertexConsumer.vertex(matrix4f, x2, y2, 0).texture(1, 1).color(color); vertexConsumer.addVertex(matrix4f, x2, y2, 0).setUv(1, 1).setColor(color);
vertexConsumer.vertex(matrix4f, x2, y1, 0).texture(1, 0).color(color); vertexConsumer.addVertex(matrix4f, x2, y1, 0).setUv(1, 0).setColor(color);
matrices.pop(); matrices.popPose();
} }
// ---------------------------- // ----------------------------
@@ -718,55 +718,55 @@ public class RenderScopeImpl implements RenderScope {
// ---------------------------- // ----------------------------
@Override @Override
public void drawItem(ItemStackRef item, int x, int y) { public void drawItem(ItemStackRef item, int x, int y) {
drawItem(SaturnClient.client.player, SaturnClient.client.world, item, x, y, 0); drawItem(SaturnClient.client.player, SaturnClient.client.level, item, x, y, 0);
} }
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStackRef stack, int x, int y, private void drawItem(@Nullable LivingEntity entity, @Nullable Level world, ItemStackRef stack, int x, int y,
int seed) { int seed) {
drawItem(entity, world, (ItemStack) (Object) stack, x, y, seed, 0); drawItem(entity, world, (ItemStack) (Object) stack, x, y, seed, 0);
} }
private void drawItem(@Nullable LivingEntity entity, @Nullable World world, ItemStack stack, int x, int y, int seed, private void drawItem(@Nullable LivingEntity entity, @Nullable Level world, ItemStack stack, int x, int y, int seed,
int z) { int z) {
if (stack.isEmpty()) if (stack.isEmpty())
return; return;
//? if >=1.21.5 //? if >=1.21.5
SaturnClient.client.getItemModelManager().update(itemRenderState, stack, ItemDisplayContext.GUI, world, entity, seed); SaturnClient.client.getItemModelResolver().appendItemLayers(itemRenderState, stack, ItemDisplayContext.GUI, world, entity, seed);
//? if >=1.21.5 //? if >=1.21.5
SaturnClient.client.getItemModelManager().clearAndUpdate(this.itemRenderState, stack, ItemDisplayContext.GUI, world, entity, seed); SaturnClient.client.getItemModelResolver().updateForTopItem(this.itemRenderState, stack, ItemDisplayContext.GUI, world, entity, seed);
//? if <1.21.5 //? if <1.21.5
//SaturnClient.client.getItemModelManager().update(itemRenderState, stack, ModelTransformationMode.GUI, false, world, entity, seed); //SaturnClient.client.getItemModelResolver().updateForTopItem(itemRenderState, stack, ItemDisplayContext.GUI, false, world, entity, seed);
this.matrices.push(); this.matrices.pushPose();
//? if >=1.21.5 //? if >=1.21.5
this.matrices.translate((float) (x + 8), (float) (y + 8), (float) (150 + z)); this.matrices.translate((float) (x + 8), (float) (y + 8), (float) (150 + z));
//? if <1.21.5 //? if <1.21.5
//this.matrices.translate(x + 8, y + 8, 150 + (itemRenderState.hasDepth() ? z : 0)); //this.matrices.translate(x + 8, y + 8, 150 + (itemRenderState.isGui3d() ? z : 0));
try { try {
this.matrices.scale(16.0F, -16.0F, 16.0F); this.matrices.scale(16.0F, -16.0F, 16.0F);
boolean bl = !this.itemRenderState.isSideLit(); boolean bl = !this.itemRenderState.usesBlockLight();
if (bl) { if (bl) {
this.draw(); this.draw();
DiffuseLighting.disableGuiDepthLighting(); Lighting.setupForFlatItems();
} }
this.itemRenderState.render(this.matrices, this.vertexConsumers, 15728880, OverlayTexture.DEFAULT_UV); this.itemRenderState.render(this.matrices, this.vertexConsumers, 15728880, OverlayTexture.NO_OVERLAY);
this.draw(); this.draw();
if (bl) { if (bl) {
DiffuseLighting.enableGuiDepthLighting(); Lighting.setupFor3DItems();
} }
} catch (Throwable throwable) { } catch (Throwable throwable) {
CrashReport crashReport = CrashReport.create(throwable, "Rendering item"); CrashReport crashReport = CrashReport.forThrowable(throwable, "Rendering item");
CrashReportSection crashReportSection = crashReport.addElement("Item being rendered"); CrashReportCategory crashReportSection = crashReport.addCategory("Item being rendered");
crashReportSection.add("Item Type", () -> String.valueOf(stack.getItem())); crashReportSection.setDetail("Item Type", () -> String.valueOf(stack.getItem()));
crashReportSection.add("Item Components", () -> String.valueOf(stack.getComponents())); crashReportSection.setDetail("Item Components", () -> String.valueOf(stack.getComponents()));
crashReportSection.add("Item Foil", () -> String.valueOf(stack.hasGlint())); crashReportSection.setDetail("Item Foil", () -> String.valueOf(stack.hasFoil()));
throw new CrashException(crashReport); throw new ReportedException(crashReport);
} }
this.matrices.pop(); this.matrices.popPose();
} }
// ---------------------------- // ----------------------------
@@ -774,8 +774,8 @@ public class RenderScopeImpl implements RenderScope {
// ---------------------------- // ----------------------------
@Override @Override
public void enableScissor(int x1, int y1, int x2, int y2) { public void enableScissor(int x1, int y1, int x2, int y2) {
ScreenRect screenRect = new ScreenRect(x1, y1, x2 - x1, y2 - y1) ScreenRectangle screenRect = new ScreenRectangle(x1, y1, x2 - x1, y2 - y1)
.transform(matrices.peek().getPositionMatrix()); .transformAxisAligned(matrices.last().pose());
setScissor(scissorStack.push(screenRect)); setScissor(scissorStack.push(screenRect));
} }
@@ -789,15 +789,15 @@ public class RenderScopeImpl implements RenderScope {
return scissorStack.containsPoint(x, y); return scissorStack.containsPoint(x, y);
} }
private void setScissor(@Nullable ScreenRect rect) { private void setScissor(@Nullable ScreenRectangle rect) {
draw(); draw();
if (rect != null) { if (rect != null) {
Window window = SaturnClient.client.getWindow(); Window window = SaturnClient.client.getWindow();
int framebufferHeight = window.getFramebufferHeight(); int framebufferHeight = window.getHeight();
double scaleFactor = window.getScaleFactor(); double scaleFactor = window.getGuiScale();
RenderSystem.enableScissor( RenderSystem.enableScissor(
(int) (rect.getLeft() * scaleFactor), (int) (rect.left() * scaleFactor),
(int) (framebufferHeight - rect.getBottom() * scaleFactor), (int) (framebufferHeight - rect.bottom() * scaleFactor),
Math.max(0, (int) (rect.width() * scaleFactor)), Math.max(0, (int) (rect.width() * scaleFactor)),
Math.max(0, (int) (rect.height() * scaleFactor))); Math.max(0, (int) (rect.height() * scaleFactor)));
} else { } else {
@@ -806,13 +806,13 @@ public class RenderScopeImpl implements RenderScope {
} }
static class ScissorStack { static class ScissorStack {
private final Deque<ScreenRect> stack = new ArrayDeque<>(); private final Deque<ScreenRectangle> stack = new ArrayDeque<>();
public ScreenRect push(ScreenRect p_281812_) { public ScreenRectangle push(ScreenRectangle p_281812_) {
ScreenRect screenrectangle = this.stack.peekLast(); ScreenRectangle screenrectangle = this.stack.peekLast();
if (screenrectangle != null) { if (screenrectangle != null) {
ScreenRect screenrectangle1 = Objects.requireNonNullElse(p_281812_.intersection(screenrectangle), ScreenRectangle screenrectangle1 = Objects.requireNonNullElse(p_281812_.intersection(screenrectangle),
ScreenRect.empty()); ScreenRectangle.empty());
this.stack.addLast(screenrectangle1); this.stack.addLast(screenrectangle1);
return screenrectangle1; return screenrectangle1;
} else { } else {
@@ -822,7 +822,7 @@ public class RenderScopeImpl implements RenderScope {
} }
@Nullable @Nullable
public ScreenRect pop() { public ScreenRectangle pop() {
if (this.stack.isEmpty()) { if (this.stack.isEmpty()) {
throw new IllegalStateException("Scissor stack underflow"); throw new IllegalStateException("Scissor stack underflow");
} else { } else {
@@ -832,7 +832,7 @@ public class RenderScopeImpl implements RenderScope {
} }
public boolean containsPoint(int p_329411_, int p_333404_) { public boolean containsPoint(int p_329411_, int p_333404_) {
return this.stack.isEmpty() ? true : this.stack.peek().contains(p_329411_, p_333404_); return this.stack.isEmpty() ? true : this.stack.peek().containsPoint(p_329411_, p_333404_);
} }
} }
} }
@@ -8,67 +8,67 @@ import org.saturnclient.ui.RenderScope;
import org.saturnclient.ui.SaturnScreen; import org.saturnclient.ui.SaturnScreen;
import org.saturnclient.ui.SaturnScreen.ScreenProvider; import org.saturnclient.ui.SaturnScreen.ScreenProvider;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
//? if >=1.21.9 //? if >=1.21.9
import net.minecraft.client.gui.Click; import net.minecraft.client.input.MouseButtonEvent;
import net.minecraft.client.gui.CubeMapRenderer; import net.minecraft.client.renderer.CubeMap;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.RotatingCubeMapRenderer; import net.minecraft.client.renderer.PanoramaRenderer;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screens.Screen;
//? if >=1.21.6 { //? if >=1.21.6 {
import net.minecraft.client.texture.CubemapTexture; import net.minecraft.client.renderer.texture.CubeMapTexture;
//?} else { //?} else {
/*import net.minecraft.client.texture.ResourceTexture; /*import net.minecraft.client.renderer.texture.SimpleTexture;
import net.minecraft.client.texture.TextureManager; import net.minecraft.client.renderer.texture.TextureManager;
*///?} *///?}
//? if >=1.21.9 //? if >=1.21.9
import net.minecraft.client.input.KeyInput; import net.minecraft.client.input.KeyEvent;
//? if <1.21.6 { //? if <1.21.6 {
/*import net.minecraft.client.gl.PostEffectProcessor; /*import net.minecraft.client.renderer.PostChain;
import net.minecraft.client.render.DefaultFramebufferSet; import net.minecraft.client.renderer.LevelTargetBundle;
import net.minecraft.client.util.Pool; import com.mojang.blaze3d.resource.CrossFrameResourcePool;
*///?} *///?}
import net.minecraft.text.Text; import net.minecraft.network.chat.Component;
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
public class SaturnScreenFabric extends Screen implements ScreenProvider { public class SaturnScreenFabric extends Screen implements ScreenProvider {
protected static final Identifier PANORAMA = Identifier.of("saturnclient", protected static final Identifier PANORAMA = Identifier.fromNamespaceAndPath("saturnclient",
"textures/gui/title/background/panorama"); "textures/gui/title/background/panorama");
protected static final CubeMapRenderer PANORAMA_RENDERER = new CubeMapRenderer(PANORAMA); protected static final CubeMap PANORAMA_RENDERER = new CubeMap(PANORAMA);
public static final RotatingCubeMapRenderer ROTATING_PANORAMA_RENDERER; public static final PanoramaRenderer ROTATING_PANORAMA_RENDERER;
static { static {
ROTATING_PANORAMA_RENDERER = new RotatingCubeMapRenderer(PANORAMA_RENDERER); ROTATING_PANORAMA_RENDERER = new PanoramaRenderer(PANORAMA_RENDERER);
} }
//? if <1.21.6 //? if <1.21.6
//private final Pool pool = new Pool(3); //private final CrossFrameResourcePool pool = new CrossFrameResourcePool(3);
public final SaturnScreen screen; public final SaturnScreen screen;
/** Whether the panorama's textures are loaded; it isn't drawn before (e.g. under the splash). */ /** Whether the panorama's textures are loaded; it isn't drawn before (e.g. under the splash). */
private static volatile boolean panoramaReady = false; private static volatile boolean panoramaReady = false;
public static void preload(MinecraftClient client) { public static void preload(Minecraft client) {
//? if >=1.21.6 { //? if >=1.21.6 {
// From 1.21.6 CubeMapRenderer draws from one cube map texture made of panorama_0..5.png. // From 1.21.6 CubeMapRenderer draws from one cube map texture made of panorama_0..5.png.
// CubeMapRenderer.registerTextures only stores it for the next resource reload, which has // CubeMapRenderer.registerTextures only stores it for the next resource reload, which has
// already happened by now, so register it through the overload that loads it right away. // already happened by now, so register it through the overload that loads it right away.
client.getTextureManager().registerTexture(PANORAMA, new CubemapTexture(PANORAMA)); client.getTextureManager().registerAndLoad(PANORAMA, new CubeMapTexture(PANORAMA));
//?} else { //?} else {
/*TextureManager textureManager = client.getTextureManager(); /*TextureManager textureManager = client.getTextureManager();
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
String var10001 = PANORAMA.getPath(); String var10001 = PANORAMA.getPath();
Identifier tex = PANORAMA.withPath(var10001 + "_" + i + ".png"); Identifier tex = PANORAMA.withPath(var10001 + "_" + i + ".png");
ResourceTexture resourceTexture = new ResourceTexture(tex); SimpleTexture resourceTexture = new SimpleTexture(tex);
textureManager.registerTexture(tex, resourceTexture); textureManager.registerAndLoad(tex, resourceTexture);
} }
*///?} *///?}
panoramaReady = true; panoramaReady = true;
} }
public SaturnScreenFabric(SaturnScreen screen) { public SaturnScreenFabric(SaturnScreen screen) {
super(Text.literal(screen.title)); super(Component.literal(screen.title));
screen.provider = this; screen.provider = this;
this.screen = screen; this.screen = screen;
} }
@@ -81,7 +81,7 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
//? if <1.21.6 //? if <1.21.6
//@SuppressWarnings("deprecation") //@SuppressWarnings("deprecation")
@Override @Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) { public void render(GuiGraphics context, int mouseX, int mouseY, float delta) {
if (screen.start == null) { if (screen.start == null) {
screen.start = Instant.now(); screen.start = Instant.now();
} }
@@ -100,22 +100,22 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
// Glass is blurred from the game as it is before this screen blurs it. // Glass is blurred from the game as it is before this screen blurs it.
if (Config.usesGlass()) { if (Config.usesGlass()) {
context.draw(); context.flush();
GlassRenderer.saveBackground(); GlassRenderer.saveBackground();
} }
float radius = screen.getBackgroundBlur(); float radius = screen.getBackgroundBlur();
PostEffectProcessor postEffectProcessor = radius < 1 ? null : this.client.getShaderLoader().loadPostEffect( PostChain postEffectProcessor = radius < 1 ? null : this.minecraft.getShaderManager().getPostChain(
Identifier.ofVanilla("blur"), Identifier.withDefaultNamespace("blur"),
DefaultFramebufferSet.MAIN_ONLY); LevelTargetBundle.MAIN_TARGETS);
if (postEffectProcessor != null) { if (postEffectProcessor != null) {
//? if >=1.21.5 //? if >=1.21.5
postEffectProcessor.render(this.client.getFramebuffer(), this.pool, pass -> pass.setUniform("Radius", radius)); postEffectProcessor.process(this.minecraft.getMainRenderTarget(), this.pool, pass -> pass.setUniform("Radius", radius));
//? if <1.21.5 //? if <1.21.5
//postEffectProcessor.setUniforms("Radius", radius); //postEffectProcessor.setUniform("Radius", radius);
//? if <1.21.5 //? if <1.21.5
//postEffectProcessor.render(this.client.getFramebuffer(), this.pool); //postEffectProcessor.process(this.minecraft.getMainRenderTarget(), this.pool);
} }
*///?} *///?}
@@ -128,7 +128,7 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
// Vanilla's background would cover Saturn's panorama, and blurs by the vanilla setting. The // Vanilla's background would cover Saturn's panorama, and blurs by the vanilla setting. The
// strength of this blur comes from GameRendererMixin, which gives Saturn's setting instead. // strength of this blur comes from GameRendererMixin, which gives Saturn's setting instead.
@Override @Override
public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { public void renderBackground(GuiGraphics context, int mouseX, int mouseY, float delta) {
// The panorama renderer has no opacity (and takes no delta) from 1.21.6, so it's drawn fully // The panorama renderer has no opacity (and takes no delta) from 1.21.6, so it's drawn fully
// opaque. // opaque.
if (isShowingPanorama()) { if (isShowingPanorama()) {
@@ -136,24 +136,24 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
} }
if (screen.getBackgroundBlur() >= 1) { if (screen.getBackgroundBlur() >= 1) {
context.applyBlur(); context.blurBeforeThisStratum();
} }
if (client.world != null) { if (minecraft.level != null) {
renderDarkening(context); renderMenuBackground(context);
} }
} }
//?} //?}
/** Whether Saturn's panorama is behind the screen: outside a world, once it's loaded. */ /** Whether Saturn's panorama is behind the screen: outside a world, once it's loaded. */
private boolean isShowingPanorama() { private boolean isShowingPanorama() {
return panoramaReady && client.world == null && client.getCurrentServerEntry() == null; return panoramaReady && minecraft.level == null && minecraft.getCurrentServer() == null;
} }
// 1.21.9 moved mouse and key events to Click and KeyInput. // 1.21.9 moved mouse and key events to Click and KeyInput.
//? if >=1.21.9 { //? if >=1.21.9 {
@Override @Override
public boolean mouseClicked(Click click, boolean doubled) { public boolean mouseClicked(MouseButtonEvent click, boolean doubled) {
if (screen.mouseClicked(click.x(), click.y(), click.button())) { if (screen.mouseClicked(click.x(), click.y(), click.button())) {
return true; return true;
} }
@@ -162,7 +162,7 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
} }
@Override @Override
public boolean mouseDragged(Click click, double offsetX, double offsetY) { public boolean mouseDragged(MouseButtonEvent click, double offsetX, double offsetY) {
// offsetX and offsetY are the drag deltas, as mouseDragged's deltaX and deltaY were before 1.21.9. // offsetX and offsetY are the drag deltas, as mouseDragged's deltaX and deltaY were before 1.21.9.
if (screen.mouseDragged(click.x(), click.y(), click.button(), offsetX, offsetY)) { if (screen.mouseDragged(click.x(), click.y(), click.button(), offsetX, offsetY)) {
return true; return true;
@@ -172,7 +172,7 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
} }
@Override @Override
public boolean mouseReleased(Click click) { public boolean mouseReleased(MouseButtonEvent click) {
if (screen.mouseReleased(click.x(), click.y(), click.button())) { if (screen.mouseReleased(click.x(), click.y(), click.button())) {
return true; return true;
} }
@@ -215,8 +215,8 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
//? if >=1.21.9 { //? if >=1.21.9 {
@Override @Override
public boolean keyPressed(KeyInput input) { public boolean keyPressed(KeyEvent input) {
if (screen.keyPressed(input.getKeycode(), input.scancode(), input.modifiers())) { if (screen.keyPressed(input.input(), input.scancode(), input.modifiers())) {
return true; return true;
} }
@@ -240,16 +240,22 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
} }
//?} else { //?} else {
/*@Override /*@Override
public void resize(MinecraftClient client, int width, int height) { public void resize(Minecraft client, int width, int height) {
screen.resize(width, height); screen.resize(width, height);
super.resize(client, width, height); super.resize(client, width, height);
} }
*///?} *///?}
@Override @Override
public void close() { public void onClose() {
this.screen.onClose(); this.screen.onClose();
super.close(); super.onClose();
}
// ScreenProvider's close, separate from the vanilla onClose above.
@Override
public void close() {
onClose();
} }
@Override @Override
@@ -3,7 +3,7 @@ package org.saturnclient.saturnclient;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import org.saturnclient.client.ServiceClient; import org.saturnclient.client.ServiceClient;
import org.saturnclient.cosmetics.Emotes; import org.saturnclient.cosmetics.Emotes;
@@ -29,12 +29,12 @@ public class SaturnClient implements ModInitializer {
public static final String MOD_ID = "saturnclient"; public static final String MOD_ID = "saturnclient";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
public static MinecraftClient client; public static Minecraft client;
@Override @Override
public void onInitialize() { public void onInitialize() {
LOGGER.info("Initializing " + MOD_ID); LOGGER.info("Initializing " + MOD_ID);
client = MinecraftClient.getInstance(); client = Minecraft.getInstance();
Providers.saturn = new SaturnProviderImpl(); Providers.saturn = new SaturnProviderImpl();
Providers.refConstructor = new RefConstructorImpl(); Providers.refConstructor = new RefConstructorImpl();
@@ -2,10 +2,10 @@ package org.saturnclient.saturnclient.event;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.minecraft.client.option.KeyBinding; import net.minecraft.client.KeyMapping;
import net.minecraft.client.util.InputUtil; import com.mojang.blaze3d.platform.InputConstants;
//? if >=1.21.9 //? if >=1.21.9
import net.minecraft.util.Identifier; import net.minecraft.resources.Identifier;
import org.saturnclient.config.Config; import org.saturnclient.config.Config;
import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClient;
@@ -24,31 +24,31 @@ import org.lwjgl.glfw.GLFW;
*/ */
public class KeyInputHandler { public class KeyInputHandler {
//? if >=1.21.9 { //? if >=1.21.9 {
private static final Identifier KEY_CATEGORY = Identifier.of("saturnclient", "key.category.saturnclient"); private static final Identifier KEY_CATEGORY = Identifier.fromNamespaceAndPath("saturnclient", "key.category.saturnclient");
//?} else //?} else
//private static final String KEY_CATEGORY = "key.category.saturnclient"; //private static final String KEY_CATEGORY = "key.category.saturnclient";
private static final String MAIN_MENU_KEY_ID = "key.saturnclient.main_menu"; private static final String MAIN_MENU_KEY_ID = "key.saturnclient.main_menu";
private static final int DEFAULT_MENU_KEY = GLFW.GLFW_KEY_RIGHT_SHIFT; private static final int DEFAULT_MENU_KEY = GLFW.GLFW_KEY_RIGHT_SHIFT;
private static KeyBinding mainMenuKeyBinding; private static KeyMapping mainMenuKeyBinding;
public static void register() { public static void register() {
//? if >=1.21.9 { //? if >=1.21.9 {
mainMenuKeyBinding = KeyBindingHelper.registerKeyBinding( mainMenuKeyBinding = KeyBindingHelper.registerKeyBinding(
new KeyBinding( new KeyMapping(
MAIN_MENU_KEY_ID, MAIN_MENU_KEY_ID,
DEFAULT_MENU_KEY, DEFAULT_MENU_KEY,
KeyBinding.Category.create(KEY_CATEGORY))); KeyMapping.Category.register(KEY_CATEGORY)));
//?} else { //?} else {
/*mainMenuKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding( /*mainMenuKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyMapping(
MAIN_MENU_KEY_ID, MAIN_MENU_KEY_ID,
InputUtil.Type.KEYSYM, InputConstants.Type.KEYSYM,
DEFAULT_MENU_KEY, DEFAULT_MENU_KEY,
KEY_CATEGORY)); KEY_CATEGORY));
*///?} *///?}
// Register the event handler for the main menu key // Register the event handler for the main menu key
ClientTickEvents.END_CLIENT_TICK.register(client -> { ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (mainMenuKeyBinding.wasPressed()) { if (mainMenuKeyBinding.consumeClick()) {
Providers.saturn.getClient().setScreen(new ShiftMenu()); Providers.saturn.getClient().setScreen(new ShiftMenu());
} }
@@ -57,21 +57,21 @@ public class KeyInputHandler {
// still down and no screen is open by then. // still down and no screen is open by then.
if (Config.openEmoteWheel.wasKeyPressed() if (Config.openEmoteWheel.wasKeyPressed()
//? if >=1.21.9 { //? if >=1.21.9 {
&& !InputUtil.isKeyPressed(client.getWindow(), GLFW.GLFW_KEY_F3)) { && !InputConstants.isKeyDown(client.getWindow(), GLFW.GLFW_KEY_F3)) {
//?} else //?} else
//&& !InputUtil.isKeyPressed(client.getWindow().getHandle(), GLFW.GLFW_KEY_F3)) { //&& !InputConstants.isKeyDown(client.getWindow().getWindow(), GLFW.GLFW_KEY_F3)) {
if (client.currentScreen == null) { if (client.screen == null) {
Providers.saturn.getClient().setScreen(new EmoteWheel()); Providers.saturn.getClient().setScreen(new EmoteWheel());
} else if (client.currentScreen instanceof SaturnScreenFabric saturnScreen } else if (client.screen instanceof SaturnScreenFabric saturnScreen
&& saturnScreen.screen instanceof EmoteWheel) { && saturnScreen.screen instanceof EmoteWheel) {
saturnScreen.close(); saturnScreen.onClose();
} }
} }
// Sneaking cancels your own emote, for everyone. // Sneaking cancels your own emote, for everyone.
if (SaturnClient.client.player != null && SaturnClient.client.player.isSneaking() if (SaturnClient.client.player != null && SaturnClient.client.player.isShiftKeyDown()
&& Emotes.playing(SaturnClient.client.player.getUuid()).isPresent()) { && Emotes.playing(SaturnClient.client.player.getUUID()).isPresent()) {
Emotes.stop(SaturnClient.client.player.getUuid()); Emotes.stop(SaturnClient.client.player.getUUID());
ServiceClient.emote(""); ServiceClient.emote("");
} }
}); });
@@ -1,20 +1,20 @@
package org.saturnclient.saturnclient.mixin; package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.GuiGraphics;
//? if >=1.21.6 { //? if >=1.21.6 {
import net.minecraft.client.gui.render.state.GuiRenderState; import net.minecraft.client.gui.render.state.GuiRenderState;
//?} else //?} else
//import net.minecraft.client.render.VertexConsumerProvider; //import net.minecraft.client.renderer.MultiBufferSource;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(DrawContext.class) @Mixin(GuiGraphics.class)
public interface DrawContextAccessor { public interface DrawContextAccessor {
//? if >=1.21.6 { //? if >=1.21.6 {
@Accessor("state") @Accessor("guiRenderState")
GuiRenderState getState(); GuiRenderState getState();
//?} else { //?} else {
/*@Accessor("vertexConsumers") /*@Accessor("bufferSource")
VertexConsumerProvider.Immediate getVertexConsumers(); MultiBufferSource.BufferSource getVertexConsumers();
*///?} *///?}
} }
@@ -1,20 +1,23 @@
package org.saturnclient.saturnclient.mixin; package org.saturnclient.saturnclient.mixin;
//? if >=1.21.9 { //? if >=1.21.9 {
import net.minecraft.client.network.ClientPlayerLikeEntity; import net.minecraft.client.entity.ClientAvatarEntity;
import net.minecraft.entity.PlayerLikeEntity; import net.minecraft.world.entity.Avatar;
//?} else //?} else
//import net.minecraft.client.network.AbstractClientPlayerEntity; //import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.render.entity.EntityRendererFactory; import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.render.entity.LivingEntityRenderer; import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.client.render.entity.PlayerEntityRenderer; import net.minecraft.client.renderer.entity.player.AvatarRenderer;
import net.minecraft.client.render.entity.model.PlayerEntityModel; //? if >=1.21.11 {
import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.client.model.player.PlayerModel;
import net.minecraft.entity.Entity; //?} else
import net.minecraft.entity.player.PlayerEntity; //import net.minecraft.client.model.PlayerModel;
import net.minecraft.text.MutableText; import net.minecraft.client.renderer.entity.state.AvatarRenderState;
import net.minecraft.text.Text; import net.minecraft.world.entity.Entity;
import net.minecraft.util.Formatting; import net.minecraft.world.entity.player.Player;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.ChatFormatting;
import org.saturnclient.client.player.Roles; import org.saturnclient.client.player.Roles;
import org.saturnclient.client.player.SaturnPlayer; import org.saturnclient.client.player.SaturnPlayer;
@@ -26,54 +29,54 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PlayerEntityRenderer.class) @Mixin(AvatarRenderer.class)
public abstract class PlayerEntityRendererMixin public abstract class PlayerEntityRendererMixin
extends LivingEntityRenderer<PlayerEntity, PlayerEntityRenderState, PlayerEntityModel> { extends LivingEntityRenderer<Player, AvatarRenderState, PlayerModel> {
protected PlayerEntityRendererMixin() { protected PlayerEntityRendererMixin() {
super(null, null, 0.0f); super(null, null, 0.0f);
} }
@Inject(method = "<init>", at = @At("TAIL")) @Inject(method = "<init>", at = @At("TAIL"))
private void addCustomFeatureRenderer(EntityRendererFactory.Context ctx, boolean slim, CallbackInfo ci) { private void addCustomFeatureRenderer(EntityRendererProvider.Context ctx, boolean slim, CallbackInfo ci) {
this.addFeature(new HatFeatureRenderer(this)); this.addLayer(new HatFeatureRenderer(this));
this.addFeature(new CloakFeatureRenderer(this, ctx.getEquipmentModelLoader())); this.addLayer(new CloakFeatureRenderer(this, ctx.getEquipmentAssets()));
} }
// Adds the role icon to the player's name, and stores the SaturnPlayer in the render state for the // Adds the role icon to the player's name, and stores the SaturnPlayer in the render state for the
// cloak and hat (Fabric API only has render state data from 1.21.8). // cloak and hat (Fabric API only has render state data from 1.21.8).
//? if >=1.21.9 { //? if >=1.21.9 {
@Inject(method = "updateRenderState", at = @At("TAIL")) @Inject(method = "extractRenderState", at = @At("TAIL"))
public <A extends PlayerLikeEntity & ClientPlayerLikeEntity> void updateRenderState( public <A extends Avatar & ClientAvatarEntity> void updateRenderState(
A entity, PlayerEntityRenderState state, float f, CallbackInfo ci) { A entity, AvatarRenderState state, float f, CallbackInfo ci) {
saturn$applyPlayer(entity, state); saturn$applyPlayer(entity, state);
} }
//?} else { //?} else {
/*@Inject(method = "updateRenderState", at = @At("TAIL")) /*@Inject(method = "extractRenderState", at = @At("TAIL"))
public void updateRenderState( public void updateRenderState(
AbstractClientPlayerEntity entity, PlayerEntityRenderState state, float f, CallbackInfo ci) { AbstractClientPlayer entity, AvatarRenderState state, float f, CallbackInfo ci) {
saturn$applyPlayer(entity, state); saturn$applyPlayer(entity, state);
} }
*///?} *///?}
private void saturn$applyPlayer(Entity entity, PlayerEntityRenderState state) { private void saturn$applyPlayer(Entity entity, AvatarRenderState state) {
if (entity == null) { if (entity == null) {
return; return;
} }
SaturnPlayer player = SaturnPlayer.get(entity.getUuid()); SaturnPlayer player = SaturnPlayer.get(entity.getUUID());
//? if >=1.21.8 //? if >=1.21.8
state.setData(SaturnRenderState.saturnDataKey, player); state.setData(SaturnRenderState.saturnDataKey, player);
if (player != null && state.displayName != null) { if (player != null && state.nameTag != null) {
MutableText iconText = Text.literal(Roles.getSaturnIndicator()) MutableComponent iconText = Component.literal(Roles.getSaturnIndicator())
.styled(style -> style.withColor(Roles.getIconColor(player.uuid))); .withStyle(style -> style.withColor(Roles.getIconColor(player.uuid)));
state.displayName = Text.empty() state.nameTag = Component.empty()
.append(iconText.copy()) .append(iconText.copy())
.append(Text.empty().formatted(Formatting.RESET)) .append(Component.empty().withStyle(ChatFormatting.RESET))
.append(state.displayName.copy()); .append(state.nameTag.copy());
} }
} }
} }
@@ -7,18 +7,18 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.ModifyVariable;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screens.TitleScreen;
@Mixin(MinecraftClient.class) @Mixin(Minecraft.class)
public class SetScreenMixin { public class SetScreenMixin {
@ModifyVariable(method = "setScreen", at = @At("HEAD"), argsOnly = true) @ModifyVariable(method = "setScreen", at = @At("HEAD"), argsOnly = true)
private Screen replaceTitleScreen(Screen screen) { private Screen replaceTitleScreen(Screen screen) {
if (Config.saturnTitleScreen.value) { if (Config.saturnTitleScreen.value) {
if (screen instanceof TitleScreen) if (screen instanceof TitleScreen)
return new SaturnScreenFabric(new TitleMenu()); return new SaturnScreenFabric(new TitleMenu());
if (screen == null && ((MinecraftClient) (Object) this).world == null) if (screen == null && ((Minecraft) (Object) this).level == null)
return new SaturnScreenFabric(new TitleMenu()); return new SaturnScreenFabric(new TitleMenu());
} }
@@ -12,67 +12,70 @@ import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screen.SplashOverlay; import net.minecraft.client.gui.screens.LoadingOverlay;
//? if >=1.21.11 //? if >=1.21.11
import net.minecraft.client.util.Window; import com.mojang.blaze3d.platform.Window;
import net.minecraft.resource.ResourceReload; import net.minecraft.server.packs.resources.ReloadInstance;
//? if >=1.21.11 {
import net.minecraft.util.Util; import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper; //?} else
//import net.minecraft.Util;
import net.minecraft.util.Mth;
@Mixin(SplashOverlay.class) @Mixin(LoadingOverlay.class)
public abstract class SplashOverlayMixin { public abstract class SplashOverlayMixin {
@Shadow @Shadow
private MinecraftClient client; private Minecraft minecraft;
@Shadow @Shadow
private ResourceReload reload; private ReloadInstance reload;
@Shadow @Shadow
private long reloadCompleteTime; private long fadeOutStart;
@Shadow @Shadow
private long reloadStartTime; private long fadeInStart;
@Shadow @Shadow
@Final @Final
private boolean reloading; private boolean fadeIn;
@Shadow @Shadow
@Final @Final
private Consumer<Optional<Throwable>> exceptionHandler; private Consumer<Optional<Throwable>> onFinish;
@Shadow @Shadow
private float progress; private float currentProgress;
/** /**
* @author SaturnClient * @author SaturnClient
* @reason Replace vanilla splash rendering completely but keep exit logic * @reason Replace vanilla splash rendering completely but keep exit logic
*/ */
@Overwrite @Overwrite
public void render(DrawContext context, int mouseX, int mouseY, float delta) { public void render(GuiGraphics context, int mouseX, int mouseY, float delta) {
int screenWidth = context.getScaledWindowWidth(); int screenWidth = context.guiWidth();
int screenHeight = context.getScaledWindowHeight(); int screenHeight = context.guiHeight();
long currentTime = Util.getMeasuringTimeMs(); long currentTime = Util.getMillis();
// Initialize reload start time if not set // Initialize reload start time if not set
if (reloadStartTime == -1L) { if (fadeInStart == -1L) {
reloadStartTime = currentTime; fadeInStart = currentTime;
} }
// Compute fade-out progress after reload completes // Compute fade-out progress after reload completes
float fadeOutProgress = reloadCompleteTime > -1L float fadeOutProgress = fadeOutStart > -1L
? (float) (currentTime - reloadCompleteTime) / 1000f ? (float) (currentTime - fadeOutStart) / 1000f
: -1f; : -1f;
int alpha = fadeOutProgress >= 0f int alpha = fadeOutProgress >= 0f
? MathHelper.ceil((1.0f - MathHelper.clamp(fadeOutProgress - 1f, 0f, 1f)) * 255f) ? Mth.ceil((1.0f - Mth.clamp(fadeOutProgress - 1f, 0f, 1f)) * 255f)
: 255; : 255;
// Compute fade-in progress while reloading // Compute fade-in progress while reloading
float reloadProgress = reloadStartTime > -1L float reloadProgress = fadeInStart > -1L
? (float) (currentTime - reloadStartTime) / 500f ? (float) (currentTime - fadeInStart) / 500f
: -1f; : -1f;
// Get render scope for better UI // Get render scope for better UI
@@ -84,7 +87,7 @@ public abstract class SplashOverlayMixin {
int overlayAlpha = computeOverlayAlpha(fadeOutProgress - 1f); int overlayAlpha = computeOverlayAlpha(fadeOutProgress - 1f);
scope.drawTexture(Textures.SPLASH, 0, 0, 0, 0, screenWidth, screenHeight, scope.drawTexture(Textures.SPLASH, 0, 0, 0, 0, screenWidth, screenHeight,
Theme.withAlpha(overlayAlpha, 0xFFFFFFFF)); Theme.withAlpha(overlayAlpha, 0xFFFFFFFF));
} else if (reloading) { } else if (fadeIn) {
if (reloadProgress < 1.0F) { if (reloadProgress < 1.0F) {
renderCurrentScreen(context, mouseX, mouseY, delta); renderCurrentScreen(context, mouseX, mouseY, delta);
} }
@@ -95,8 +98,8 @@ public abstract class SplashOverlayMixin {
Theme.withAlpha(alpha, 0xFFFFFFFF)); Theme.withAlpha(alpha, 0xFFFFFFFF));
} }
float u = this.reload.getProgress(); float u = this.reload.getActualProgress();
this.progress = MathHelper.clamp(this.progress * 0.95F + u * 0.050000012F, 0.0F, 1.0F); this.currentProgress = Mth.clamp(this.currentProgress * 0.95F + u * 0.050000012F, 0.0F, 1.0F);
// Draw central logo // Draw central logo
drawLogo(scope, screenWidth, screenHeight, alpha); drawLogo(scope, screenWidth, screenHeight, alpha);
@@ -104,16 +107,16 @@ public abstract class SplashOverlayMixin {
// Remove overlay after fade-out completes // Remove overlay after fade-out completes
if (fadeOutProgress >= 2.0F) { if (fadeOutProgress >= 2.0F) {
client.setOverlay(null); minecraft.setOverlay(null);
} }
// Handle reload completion and exceptions // Handle reload completion and exceptions
handleReloadCompletion(context); handleReloadCompletion(context);
} }
private void renderCurrentScreen(DrawContext context, int mouseX, int mouseY, float delta) { private void renderCurrentScreen(GuiGraphics context, int mouseX, int mouseY, float delta) {
if (client.currentScreen != null) { if (minecraft.screen != null) {
client.currentScreen.render(context, mouseX, mouseY, delta); minecraft.screen.render(context, mouseX, mouseY, delta);
} }
} }
@@ -123,15 +126,17 @@ public abstract class SplashOverlayMixin {
Theme.withAlpha(alpha, 0xFFFFFFFF)); Theme.withAlpha(alpha, 0xFFFFFFFF));
} }
private void renderProgressBar(RenderScope scope, DrawContext context, int screenWidth, int screenHeight, private void renderProgressBar(RenderScope scope, GuiGraphics context, int screenWidth, int screenHeight,
int alpha) { int alpha) {
int progressY = ((screenHeight - 5) / 2) + 25; int progressY = ((screenHeight - 5) / 2) + 25;
//? if >=1.21.9 { //? if >=1.21.11 {
context.drawStrokedRectangle((screenWidth - 120) / 2, progressY, 120, 5, Theme.withAlpha(alpha, 0xFFFFFFFF)); context.renderOutline((screenWidth - 120) / 2, progressY, 120, 5, Theme.withAlpha(alpha, 0xFFFFFFFF));
//?} else //?} else if >=1.21.9 {
//context.drawBorder((screenWidth - 120) / 2, progressY, 120, 5, Theme.withAlpha(alpha, 0xFFFFFFFF)); /*context.submitOutline((screenWidth - 120) / 2, progressY, 120, 5, Theme.withAlpha(alpha, 0xFFFFFFFF));
*///?} else
//context.renderOutline((screenWidth - 120) / 2, progressY, 120, 5, Theme.withAlpha(alpha, 0xFFFFFFFF));
int progressWidth = Math.min((int) (progress * 120), 120); int progressWidth = Math.min((int) (currentProgress * 120), 120);
int progressX = (screenWidth - 120) / 2; int progressX = (screenWidth - 120) / 2;
context.fill(progressX, progressY, progressX + progressWidth, progressY + 5, context.fill(progressX, progressY, progressX + progressWidth, progressY + 5,
@@ -140,31 +145,31 @@ public abstract class SplashOverlayMixin {
/** Compute overlay alpha from fade progress */ /** Compute overlay alpha from fade progress */
private int computeOverlayAlpha(float progress) { private int computeOverlayAlpha(float progress) {
return MathHelper.ceil((1.0F - MathHelper.clamp(progress, 0.0F, 1.0F)) * 255.0F); return Mth.ceil((1.0F - Mth.clamp(progress, 0.0F, 1.0F)) * 255.0F);
} }
/** Handle reload completion logic */ /** Handle reload completion logic */
private void handleReloadCompletion(DrawContext context) { private void handleReloadCompletion(GuiGraphics context) {
float reloadProgress = reloadStartTime > -1L ? (float) (Util.getMeasuringTimeMs() - reloadStartTime) / 500f float reloadProgress = fadeInStart > -1L ? (float) (Util.getMillis() - fadeInStart) / 500f
: -1f; : -1f;
if (reloadCompleteTime == -1L && reload.isComplete() && (!reloading || reloadProgress >= 2.0F)) { if (fadeOutStart == -1L && reload.isDone() && (!fadeIn || reloadProgress >= 2.0F)) {
try { try {
reload.throwException(); reload.checkExceptions();
exceptionHandler.accept(Optional.empty()); onFinish.accept(Optional.empty());
} catch (Throwable ex) { } catch (Throwable ex) {
exceptionHandler.accept(Optional.of(ex)); onFinish.accept(Optional.of(ex));
} }
reloadCompleteTime = Util.getMeasuringTimeMs(); fadeOutStart = Util.getMillis();
//? if >=1.21.11 //? if >=1.21.11
Window window = client.getWindow(); Window window = minecraft.getWindow();
if (client.currentScreen != null) { if (minecraft.screen != null) {
//? if >=1.21.11 { //? if >=1.21.11 {
client.currentScreen.init(window.getScaledWidth(), window.getScaledHeight()); minecraft.screen.init(window.getGuiScaledWidth(), window.getGuiScaledHeight());
//?} else //?} else
//client.currentScreen.init(client, context.getScaledWindowWidth(), context.getScaledWindowHeight()); //minecraft.screen.init(minecraft, context.guiWidth(), context.guiHeight());
} }
} }
} }
@@ -1,8 +1,8 @@
package org.saturnclient.saturnclient.mixin; package org.saturnclient.saturnclient.mixin;
import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.multiplayer.PlayerInfo;
import net.minecraft.scoreboard.Team; import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.text.Text; import net.minecraft.network.chat.Component;
import java.util.UUID; import java.util.UUID;
@@ -15,7 +15,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
@Mixin(PlayerListEntry.class) @Mixin(PlayerInfo.class)
public abstract class TabListMixin { public abstract class TabListMixin {
/** /**
@@ -23,9 +23,9 @@ public abstract class TabListMixin {
* Saturn Client, keeping any name, rank prefix or team formatting the server * Saturn Client, keeping any name, rank prefix or team formatting the server
* set. * set.
*/ */
@Inject(method = "getDisplayName", at = @At("RETURN"), cancellable = true) @Inject(method = "getTabListDisplayName", at = @At("RETURN"), cancellable = true)
private void saturn$addSaturnIcon(CallbackInfoReturnable<Text> cir) { private void saturn$addSaturnIcon(CallbackInfoReturnable<Component> cir) {
PlayerListEntry entry = (PlayerListEntry) (Object) this; PlayerInfo entry = (PlayerInfo) (Object) this;
GameProfile profile = entry.getProfile(); GameProfile profile = entry.getProfile();
//? if >=1.21.9 { //? if >=1.21.9 {
String name = profile.name(); String name = profile.name();
@@ -39,16 +39,16 @@ public abstract class TabListMixin {
return; return;
} }
Text displayName = cir.getReturnValue(); Component displayName = cir.getReturnValue();
// With no server-set name, vanilla shows the team-decorated profile name. // With no server-set name, vanilla shows the team-decorated profile name.
if (displayName == null) { if (displayName == null) {
displayName = Team.decorateName(entry.getScoreboardTeam(), Text.literal(name)); displayName = PlayerTeam.formatNameForTeam(entry.getTeam(), Component.literal(name));
} }
cir.setReturnValue(Text.empty() cir.setReturnValue(Component.empty()
.append(Text.literal(Roles.getSaturnIndicator()) .append(Component.literal(Roles.getSaturnIndicator())
.styled(style -> style.withColor(Roles.getIconColor(uuid)))) .withStyle(style -> style.withColor(Roles.getIconColor(uuid))))
.append(displayName)); .append(displayName));
} }
} }
@@ -12,14 +12,14 @@
package org.saturnclient.saturnclient.mixin; package org.saturnclient.saturnclient.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.client.render.entity.LivingEntityRenderer; import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.entity.Entity; import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@Mixin(LivingEntityRenderer.class) @Mixin(LivingEntityRenderer.class)
public class WhoAmI { public class WhoAmI {
@ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;getCameraEntity()Lnet/minecraft/entity/Entity;")) @ModifyExpressionValue(method = "shouldShowName(Lnet/minecraft/world/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getCameraEntity()Lnet/minecraft/world/entity/Entity;"))
public Entity obfuscateCameraEntity(Entity original) { public Entity obfuscateCameraEntity(Entity original) {
// hasLabel checks if the rendered entity is equal to the camera entity (aka our // hasLabel checks if the rendered entity is equal to the camera entity (aka our
// player), // player),
+14
View File
@@ -6,6 +6,20 @@ plugins {
// "Reset active project" before committing. // "Reset active project" before committing.
stonecutter active "1.21.11" stonecutter active "1.21.11"
// src/ uses the newest Mojang names. These classes were renamed in the versions given, so Stonecutter
// swaps in the older names when it processes an older version.
stonecutter parameters {
for ((since, old, new) in listOf(
Triple("1.21.11", "ResourceLocation", "Identifier"),
Triple("1.21.9", "PlayerRenderer", "AvatarRenderer"),
Triple("1.21.9", "PlayerRenderState", "AvatarRenderState"),
)) {
replacements.regex(eval(current.version, ">=$since")) {
replace("\\b$old\\b", new, "\\b$new\\b", old)
}
}
}
subprojects { subprojects {
apply(plugin = "java") apply(plugin = "java")
-1
View File
@@ -8,7 +8,6 @@ org.gradle.configuration-cache=false
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
minecraft_version=1.21.10 minecraft_version=1.21.10
yarn_mappings=1.21.10+build.3
loader_version=0.19.5 loader_version=0.19.5
fabric_api_version=0.138.4+1.21.10 fabric_api_version=0.138.4+1.21.10
-1
View File
@@ -8,7 +8,6 @@ org.gradle.configuration-cache=false
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
minecraft_version=1.21.11 minecraft_version=1.21.11
yarn_mappings=1.21.11+build.4
loader_version=0.19.5 loader_version=0.19.5
fabric_api_version=0.141.3+1.21.11 fabric_api_version=0.141.3+1.21.11
-1
View File
@@ -8,7 +8,6 @@ org.gradle.configuration-cache=false
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
minecraft_version=1.21.4 minecraft_version=1.21.4
yarn_mappings=1.21.4+build.8
loader_version=0.19.5 loader_version=0.19.5
# Mod Properties # Mod Properties
-1
View File
@@ -8,7 +8,6 @@ org.gradle.configuration-cache=false
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
minecraft_version=1.21.5 minecraft_version=1.21.5
yarn_mappings=1.21.5+build.1
loader_version=0.19.5 loader_version=0.19.5
fabric_api_version=0.128.2+1.21.5 fabric_api_version=0.128.2+1.21.5
-1
View File
@@ -8,7 +8,6 @@ org.gradle.configuration-cache=false
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
minecraft_version=1.21.6 minecraft_version=1.21.6
yarn_mappings=1.21.6+build.1
loader_version=0.19.5 loader_version=0.19.5
fabric_api_version=0.128.2+1.21.6 fabric_api_version=0.128.2+1.21.6
-1
View File
@@ -8,7 +8,6 @@ org.gradle.configuration-cache=false
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
minecraft_version=1.21.7 minecraft_version=1.21.7
yarn_mappings=1.21.7+build.8
loader_version=0.19.5 loader_version=0.19.5
fabric_api_version=0.129.0+1.21.7 fabric_api_version=0.129.0+1.21.7
-1
View File
@@ -8,7 +8,6 @@ org.gradle.configuration-cache=false
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
minecraft_version=1.21.8 minecraft_version=1.21.8
yarn_mappings=1.21.8+build.1
loader_version=0.19.5 loader_version=0.19.5
fabric_api_version=0.136.1+1.21.8 fabric_api_version=0.136.1+1.21.8
-1
View File
@@ -8,7 +8,6 @@ org.gradle.configuration-cache=false
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
minecraft_version=1.21.9 minecraft_version=1.21.9
yarn_mappings=1.21.9+build.1
loader_version=0.19.5 loader_version=0.19.5
fabric_api_version=0.134.1+1.21.9 fabric_api_version=0.134.1+1.21.9