Compare commits
20
Commits
25a19d7951
...
0.1.2-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd91f3844a | ||
|
|
b7cf3092da | ||
|
|
60afc12893 | ||
|
|
8677837a8f | ||
|
|
02f6cf7d71 | ||
|
|
85a46c0bba | ||
|
|
30f65bd914 | ||
|
|
bedb45c8aa | ||
|
|
1602520624 | ||
|
|
f69c379ae1 | ||
|
|
fbd0e23fb3 | ||
|
|
8dbb1d84c1 | ||
|
|
ab70c67a4f | ||
|
|
0a6aa90e23 | ||
|
|
22a7152f0d | ||
|
|
b5ca9dbc8f | ||
|
|
48118f6a84 | ||
|
|
771ed93992 | ||
|
|
a8e6f14022 | ||
|
|
84270c023a |
@@ -57,7 +57,8 @@ jobs:
|
||||
- name: Build all versions
|
||||
run: |
|
||||
chmod +x gradlew
|
||||
# buildAll remaps every versions/* project in parallel into build/allJars.
|
||||
# buildAll remaps every Minecraft version (two at a time, to stay within the
|
||||
# Gradle heap) into build/allJars.
|
||||
./gradlew buildAll --no-daemon --stacktrace
|
||||
|
||||
- name: Upload jars to the release
|
||||
|
||||
+2
-2
@@ -36,9 +36,9 @@ import net.minecraft.client.render.RenderSetup;
|
||||
|
||||
Stonecutter rewrites inactive code into its own layout when switching versions (a single inactive line becomes `//code`), so write it that way to begin with, or run a switch and a reset before committing.
|
||||
|
||||
When a newer version leaves something out that an older one implements, keep the older version's code behind a condition and mark the newer branch with a `TODO`, rather than dropping it for every version. `WorldFeatureImpl.getWorldAge` and `SaturnScreenFabric.resize` are examples. Search for `TODO` to find what newer versions still lack.
|
||||
When a newer version leaves something out that an older one implements, keep the older version's code behind a condition and mark the newer branch with a `TODO`, rather than dropping it for every version. The panorama in `SaturnScreenFabric.render` is an example. Search for `TODO` to find what newer versions still lack (tracked in #30), and remove the condition once a version gap is fixed.
|
||||
|
||||
A whole class that only exists for some versions (such as `NametagsMixin`, which hooks a method that 1.21.9 changed) can keep an empty class body on the other versions. An empty mixin changes nothing, and it keeps the mixin configs the same for every version, since JSON can't hold version comments.
|
||||
A whole class that only exists for some versions (such as `MatrixStackMixin`, which only makes sense before 1.21.6's GUI rewrite) can keep an empty class body on the other versions. Before splitting a class like that, look for a hook that works on every version: nametags used to hook label rendering, which 1.21.9 changed, and now replace the name while the render state is built (`LivingEntityRendererMixin`), with no version condition at all. An empty mixin changes nothing, and it keeps the mixin configs the same for every version, since JSON can't hold version comments.
|
||||
|
||||
Inactive code sits inside a `/* … */` comment, so it can't contain `/* … */` comments itself: use `//` comments in code that's only active for some versions. For the same reason, don't nest multi-line version blocks; use `//?} else if <condition> {` for more than two version ranges, as in `PlayerEntityRendererMixin` and `SaturnRenderState`.
|
||||
|
||||
|
||||
+1
-1
Submodule common updated: 15fa973553...ef0ead6bf8
+1
-1
@@ -6,7 +6,7 @@ org.gradle.caching=true
|
||||
# IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349
|
||||
org.gradle.configuration-cache=false
|
||||
|
||||
mod_version=0.1.1-beta
|
||||
mod_version=0.1.2-beta
|
||||
|
||||
# Saturn's emote library (git.selimaj.dev/saturnclientmc/emotes)
|
||||
emotes_version=0.1.0
|
||||
|
||||
@@ -12,10 +12,9 @@ import net.minecraft.entity.LivingEntity;
|
||||
* Fabric implementation of {@link EntityFeature}.
|
||||
*
|
||||
* Crosshair targeting is resolved via {@link MinecraftClient#crosshairTarget}.
|
||||
* Entity state for nametag rendering is supplied at render time by
|
||||
* {@link org.saturnclient.modules.mixins.LivingEntityRendererMixin} which
|
||||
* writes into the render state; {@link NametagsMixin} then constructs
|
||||
* a {@link RenderStateEntityState} from the already-extracted snapshot.
|
||||
* Entity state for nametags is built by LivingEntityRendererMixin, which
|
||||
* writes health into the render state and then constructs a
|
||||
* {@link RenderStateEntityState} from that snapshot for NametagsMod.
|
||||
*/
|
||||
public class EntityFeatureImpl implements EntityFeature {
|
||||
|
||||
@@ -43,7 +42,7 @@ public class EntityFeatureImpl implements EntityFeature {
|
||||
* Minecraft render-state object) as a platform-neutral
|
||||
* {@link EntityState} for use by {@link NametagsFeature}.
|
||||
*
|
||||
* This is constructed inside {@link NametagsMixin} where both the
|
||||
* This is constructed in LivingEntityRendererMixin, where both the
|
||||
* render-state mixin interface and the entity name are available.
|
||||
*/
|
||||
public static final class RenderStateEntityState implements EntityState {
|
||||
|
||||
@@ -7,8 +7,8 @@ import org.saturnclient.common.feature.EntityFeature;
|
||||
* {@link net.minecraft.client.render.entity.state.LivingEntityRenderState}.
|
||||
*
|
||||
* Carries the entity's health snapshot and classification into the render
|
||||
* pipeline so that {@link NametagsMixin} can read them without touching
|
||||
* the live entity again.
|
||||
* render state, so NametagsMod's replacement nametag (applied in
|
||||
* LivingEntityRendererMixin) can use them without touching the live entity again.
|
||||
*/
|
||||
public interface HealthRenderState {
|
||||
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
package org.saturnclient.impl.features.mixins.misc;
|
||||
|
||||
import net.minecraft.client.render.entity.EntityRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
//? if <1.21.9 {
|
||||
/*import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.entity.state.EntityRenderState;
|
||||
import net.minecraft.client.render.entity.state.LivingEntityRenderState;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import org.saturnclient.impl.features.entity.EntityFeatureImpl;
|
||||
import org.saturnclient.impl.features.entity.HealthRenderState;
|
||||
import org.saturnclient.impl.features.mixins.render.LivingEntityRenderStateMixin;
|
||||
import org.saturnclient.mod.mods.NametagsMod;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
*///?}
|
||||
|
||||
/**
|
||||
* Intercepts nametag rendering and replaces the displayed text with
|
||||
* the string produced by {@link NametagsMod#getNametagString}.
|
||||
*
|
||||
* Key changes from the original:
|
||||
*
|
||||
* <ul>
|
||||
* <li>The old {@code NametagsFabric.EntityStateImpl} bridge class is
|
||||
* replaced by {@link EntityFeatureImpl.RenderStateEntityState},
|
||||
* which wraps the {@link HealthRenderState} already injected into
|
||||
* the render state by {@link LivingEntityRenderStateMixin}.</li>
|
||||
* <li>The feature import changes from {@code Nametags} to
|
||||
* {@link NametagsMod}; the two static methods
|
||||
* ({@code shouldReplaceName} / {@code getNametagString}) are
|
||||
* unchanged in signature.</li>
|
||||
* <li>The entity's display name is extracted from the render state's
|
||||
* {@code nameVisible} / text fields where available, falling back
|
||||
* to the plain text string passed to this method.</li>
|
||||
* </ul>
|
||||
*
|
||||
* The re-entrancy guard ({@code saturn$rendering}) is kept intact to
|
||||
* prevent infinite recursion when we call {@code renderLabelIfPresent}
|
||||
* with the replacement text.
|
||||
*/
|
||||
@Mixin(EntityRenderer.class)
|
||||
public abstract class NametagsMixin {
|
||||
// TODO: 1.21.9 moved label rendering to the render queue (renderLabelIfPresent no longer takes a
|
||||
// VertexConsumerProvider), so custom nametags only work on older versions. On 1.21.9+ this mixin is
|
||||
// empty but stays registered, so features.mixins.json is the same for every version.
|
||||
//? if <1.21.9 {
|
||||
/*// Guards against the recursive call we make with the replacement text.
|
||||
@Unique
|
||||
private static final ThreadLocal<Boolean> saturn$rendering = ThreadLocal.withInitial(() -> false);
|
||||
|
||||
@Shadow
|
||||
protected abstract <S extends EntityRenderState> void renderLabelIfPresent(
|
||||
S state, Text text,
|
||||
MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light);
|
||||
|
||||
@Inject(method = "renderLabelIfPresent", at = @At("HEAD"), cancellable = true)
|
||||
private <S extends EntityRenderState> void saturn$replaceNametag(
|
||||
S state, Text text,
|
||||
MatrixStack matrices, VertexConsumerProvider vertexConsumers,
|
||||
int light, CallbackInfo ci) {
|
||||
|
||||
// Skip our own recursive call
|
||||
if (saturn$rendering.get())
|
||||
return;
|
||||
|
||||
if (!NametagsMod.shouldReplaceName())
|
||||
return;
|
||||
|
||||
// Only living entities carry health data
|
||||
if (!(state instanceof LivingEntityRenderState living))
|
||||
return;
|
||||
if (!(living instanceof HealthRenderState hrs))
|
||||
return;
|
||||
|
||||
// Build the platform-neutral EntityState from the render-state snapshot
|
||||
// (health/type were written by LivingEntityRendererMixin at extract time).
|
||||
String customName = text != null ? text.getString() : null;
|
||||
EntityFeatureImpl.RenderStateEntityState entityState = new EntityFeatureImpl.RenderStateEntityState(
|
||||
customName, hrs);
|
||||
|
||||
// Ask the feature for the replacement string
|
||||
String replacement = NametagsMod.getNametagString(entityState);
|
||||
if (replacement == null)
|
||||
return; // feature decided not to replace this entity
|
||||
|
||||
ci.cancel();
|
||||
saturn$rendering.set(true);
|
||||
try {
|
||||
renderLabelIfPresent(state, Text.literal(replacement), matrices, vertexConsumers, light);
|
||||
} finally {
|
||||
saturn$rendering.set(false);
|
||||
}
|
||||
}
|
||||
*///?}
|
||||
}
|
||||
@@ -1,12 +1,20 @@
|
||||
package org.saturnclient.impl.features.mixins.render;
|
||||
|
||||
//? if >=1.21.6
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
//? if >=1.21.6
|
||||
import net.minecraft.client.option.GameOptions;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
|
||||
//? if >=1.21.6
|
||||
import org.saturnclient.impl.ui.SaturnScreenFabric;
|
||||
import org.saturnclient.mod.mods.FreelookMod;
|
||||
import org.saturnclient.mod.mods.ZoomMod;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
//? if >=1.21.6
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
/**
|
||||
@@ -38,4 +46,18 @@ public class GameRendererMixin {
|
||||
cir.setReturnValue(zoomedFov);
|
||||
}
|
||||
}
|
||||
|
||||
//? if >=1.21.6 {
|
||||
// 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.
|
||||
@Redirect(method = "render", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/option/GameOptions;getMenuBackgroundBlurrinessValue()I"))
|
||||
private int useSaturnBlur(GameOptions options) {
|
||||
if (MinecraftClient.getInstance().currentScreen instanceof SaturnScreenFabric saturnScreen) {
|
||||
return saturnScreen.screen.getBackgroundBlur();
|
||||
}
|
||||
|
||||
return options.getMenuBackgroundBlurrinessValue();
|
||||
}
|
||||
//?}
|
||||
}
|
||||
|
||||
+2
-3
@@ -4,7 +4,6 @@ import net.minecraft.client.render.entity.state.LivingEntityRenderState;
|
||||
|
||||
import org.saturnclient.common.feature.EntityFeature;
|
||||
import org.saturnclient.impl.features.entity.HealthRenderState;
|
||||
import org.saturnclient.impl.features.mixins.misc.NametagsMixin;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
@@ -19,8 +18,8 @@ import org.spongepowered.asm.mixin.Unique;
|
||||
*
|
||||
* The stored values are written by
|
||||
* {@link LivingEntityRendererMixin#saturn$captureHealth} each time a
|
||||
* render state is extracted from a live entity, and read by
|
||||
* {@link NametagsMixin} at render time.
|
||||
* render state is extracted from a live entity, and read there right away for
|
||||
* NametagsMod's replacement nametag.
|
||||
*/
|
||||
@Mixin(LivingEntityRenderState.class)
|
||||
public class LivingEntityRenderStateMixin implements HealthRenderState {
|
||||
|
||||
+19
-8
@@ -6,24 +6,25 @@ import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.mob.HostileEntity;
|
||||
import net.minecraft.entity.passive.PassiveEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import org.saturnclient.common.feature.EntityFeature;
|
||||
import org.saturnclient.impl.features.entity.EntityFeatureImpl;
|
||||
import org.saturnclient.impl.features.entity.HealthRenderState;
|
||||
import org.saturnclient.mod.mods.NametagsMod;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* Captures each living entity's health and type into the render state
|
||||
* during {@code updateRenderState}, so that nametag rendering can read
|
||||
* them without touching the live entity again.
|
||||
* Captures each living entity's health and type into the render state during
|
||||
* {@code updateRenderState}, and applies {@link NametagsMod}'s replacement nametag to the state's
|
||||
* display name.
|
||||
*
|
||||
* Previously imported {@code NametagsInterface.EntityType}; now uses
|
||||
* {@link EntityFeature.EntityType} — the canonical enum shared across
|
||||
* the whole module system.
|
||||
*
|
||||
* The injection target and strategy are unchanged from the original.
|
||||
* Replacing the name here, while the render state is built, works the same on every version. Hooking
|
||||
* label rendering instead doesn't: 1.21.9 moved it to the render command queue. Player role icons are
|
||||
* added after this, in PlayerEntityRendererMixin.
|
||||
*/
|
||||
@Mixin(LivingEntityRenderer.class)
|
||||
public abstract class LivingEntityRendererMixin<T extends LivingEntity, S extends LivingEntityRenderState> {
|
||||
@@ -47,5 +48,15 @@ public abstract class LivingEntityRendererMixin<T extends LivingEntity, S extend
|
||||
type = EntityFeature.EntityType.OTHER;
|
||||
|
||||
hrs.saturn$setEntityType(type);
|
||||
|
||||
// Only entities that already show a label get a replacement one, as when this hooked label
|
||||
// rendering.
|
||||
if (NametagsMod.shouldReplaceName() && state.displayName != null) {
|
||||
String replacement = NametagsMod.getNametagString(
|
||||
new EntityFeatureImpl.RenderStateEntityState(state.displayName.getString(), hrs));
|
||||
if (replacement != null) {
|
||||
state.displayName = Text.literal(replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,10 +31,7 @@ public class WorldFeatureImpl implements WorldFeature {
|
||||
*/
|
||||
@Override
|
||||
public long getWorldAge() {
|
||||
//? if >=1.21.11 {
|
||||
// TODO: not implemented on 1.21.11 yet.
|
||||
return 0L;
|
||||
//?} else
|
||||
//return hasWorld() ? mc.world.getTime() : 0L;
|
||||
// World.getTime() was a shortcut for this, and 1.21.11 removed it.
|
||||
return hasWorld() ? mc.world.getLevelProperties().getTime() : 0L;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,17 @@ package org.saturnclient.impl.provider;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.toast.SystemToast;
|
||||
//? if >=1.21.9 {
|
||||
import net.minecraft.entity.player.SkinTextures;
|
||||
//?} else
|
||||
//import net.minecraft.client.util.SkinTextures;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import org.saturnclient.common.provider.SaturnProvider;
|
||||
import org.saturnclient.common.ref.asset.IdentifierRef;
|
||||
@@ -16,6 +22,9 @@ import org.saturnclient.impl.cosmetics.utils.IdentifierUtils;
|
||||
import org.saturnclient.saturnclient.SaturnClient;
|
||||
|
||||
public class SaturnProviderImpl implements SaturnProvider {
|
||||
/** Looks up the signed-in player's skin; made once, since the skin provider caches it */
|
||||
private Supplier<Identifier> playerSkin;
|
||||
|
||||
@Override
|
||||
public MinecraftClientRef getClient() {
|
||||
return (MinecraftClientRef) SaturnClient.client;
|
||||
@@ -50,6 +59,23 @@ public class SaturnProviderImpl implements SaturnProvider {
|
||||
/** 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);
|
||||
|
||||
@Override
|
||||
public IdentifierRef getPlayerSkin() {
|
||||
if (playerSkin == null) {
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
// 1.21.9 moved SkinTextures and renamed the skin provider's lookup.
|
||||
//? if >=1.21.9 {
|
||||
Supplier<SkinTextures> textures = client.getSkinProvider().supplySkinTextures(client.getGameProfile(), false);
|
||||
playerSkin = () -> textures.get().body().texturePath();
|
||||
//?} else {
|
||||
/*Supplier<SkinTextures> textures = client.getSkinProvider().getSkinTexturesSupplier(client.getGameProfile());
|
||||
playerSkin = () -> textures.get().texture();
|
||||
*///?}
|
||||
}
|
||||
|
||||
return (IdentifierRef) (Object) playerSkin.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModVersion() {
|
||||
return FabricLoader.getInstance().getModContainer(SaturnClient.MOD_ID)
|
||||
|
||||
@@ -7,7 +7,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
import org.saturnclient.saturnclient.SaturnClient;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.components.SkinPreview.EntityDrawer;
|
||||
|
||||
@@ -21,33 +20,32 @@ import net.minecraft.entity.LivingEntity;
|
||||
|
||||
public class EntityDrawerImpl implements EntityDrawer {
|
||||
@Override
|
||||
public void render(RenderScope renderScope, boolean negativeAngle, float angle, float scale, ElementContext ctx) {
|
||||
public boolean render(RenderScope renderScope, int width, int height, float yaw) {
|
||||
LivingEntity entity = SaturnClient.client.player;
|
||||
|
||||
if (entity != null) {
|
||||
drawEntity(renderScope, 0, 0, 75, 78, 30, 0.0625F, ctx.mouseX / scale, ctx.mouseY / scale,
|
||||
SaturnClient.client.player);
|
||||
}
|
||||
if (entity == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The player is about 1.8 blocks tall; leave some room above and below.
|
||||
drawEntity(renderScope, 0, 0, width, height, (int) (height / 2.2F), 0.0625F, yaw, entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Draws the entity in the box, turned by yaw degrees (0 faces the viewer) with its head straight.
|
||||
public static void drawEntity(RenderScope renderScope, int x1, int y1, int x2, int y2, int size, float scale,
|
||||
float mouseX, float mouseY, LivingEntity entity) {
|
||||
float f = (float) (x1 + x2) / 2.0F;
|
||||
float g = (float) (y1 + y2) / 2.0F;
|
||||
float yaw, LivingEntity entity) {
|
||||
renderScope.enableScissor(x1, y1, x2, y2);
|
||||
float h = (float) Math.atan((double) ((f - mouseX) / 40.0F));
|
||||
float i = (float) Math.atan((double) ((g - mouseY) / 40.0F));
|
||||
Quaternionf quaternionf = (new Quaternionf()).rotateZ((float) Math.PI);
|
||||
Quaternionf quaternionf2 = (new Quaternionf()).rotateX(i * 20.0F * ((float) Math.PI / 180F));
|
||||
quaternionf.mul(quaternionf2);
|
||||
Quaternionf quaternionf2 = new Quaternionf();
|
||||
float j = entity.bodyYaw;
|
||||
float k = entity.getYaw();
|
||||
float l = entity.getPitch();
|
||||
float m = entity.lastHeadYaw;
|
||||
float n = entity.headYaw;
|
||||
entity.bodyYaw = 180.0F + h * 20.0F;
|
||||
entity.setYaw(180.0F + h * 40.0F);
|
||||
entity.setPitch(-i * 20.0F);
|
||||
entity.bodyYaw = 180.0F + yaw;
|
||||
entity.setYaw(180.0F + yaw);
|
||||
entity.setPitch(0.0F);
|
||||
entity.headYaw = entity.getYaw();
|
||||
entity.lastHeadYaw = entity.getYaw();
|
||||
float o = entity.getScale();
|
||||
@@ -83,7 +81,6 @@ public class EntityDrawerImpl implements EntityDrawer {
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
import org.saturnclient.saturnclient.SaturnClient;
|
||||
import org.saturnclient.ui.ElementContext;
|
||||
import org.saturnclient.ui.RenderScope;
|
||||
import org.saturnclient.ui.components.SkinPreview.EntityDrawer;
|
||||
|
||||
@@ -92,14 +89,12 @@ import net.minecraft.client.render.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
|
||||
public class EntityDrawerImpl implements EntityDrawer {
|
||||
// Draws the entity in the box, turned by yaw degrees (0 faces the viewer) with its head straight.
|
||||
public static void drawEntity(RenderScope renderScope, int x1, int y1, int x2, int y2, int size, float f,
|
||||
float mouseX,
|
||||
float mouseY, LivingEntity entity, float angle, boolean negativeAngle) {
|
||||
float yaw, LivingEntity entity) {
|
||||
float g = (float) (x1 + x2) / 2.0F;
|
||||
float h = (float) (y1 + y2) / 2.0F;
|
||||
renderScope.enableScissor(0, 6, x2, y2);
|
||||
float i = (float) Math.atan((double) ((g - mouseX) / 40.0F));
|
||||
float j = (float) Math.atan((double) ((h - mouseY) / 40.0F));
|
||||
renderScope.enableScissor(x1, y1, x2, y2);
|
||||
Quaternionf quaternionf = (new Quaternionf()).rotateZ(3.1415927F);
|
||||
float k = entity.bodyYaw;
|
||||
float l = entity.getYaw();
|
||||
@@ -109,10 +104,10 @@ public class EntityDrawerImpl implements EntityDrawer {
|
||||
//? if <1.21.5
|
||||
//float n = entity.prevHeadYaw;
|
||||
float o = entity.headYaw;
|
||||
entity.setYaw(angle);
|
||||
entity.bodyYaw = angle;
|
||||
entity.setPitch(-(j * 20.0F));
|
||||
entity.headYaw = negativeAngle ? (i * 40.0F) + 180f : -(i * 40.0F);
|
||||
entity.setYaw(180.0F + yaw);
|
||||
entity.bodyYaw = 180.0F + yaw;
|
||||
entity.setPitch(0.0F);
|
||||
entity.headYaw = entity.getYaw();
|
||||
//? if >=1.21.5
|
||||
entity.lastHeadYaw = entity.getHeadYaw();
|
||||
//? if <1.21.5
|
||||
@@ -166,12 +161,15 @@ public class EntityDrawerImpl implements EntityDrawer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RenderScope renderScope, boolean negativeAngle, float angle, float scale, ElementContext ctx) {
|
||||
public boolean render(RenderScope renderScope, int width, int height, float yaw) {
|
||||
LivingEntity entity = SaturnClient.client.player;
|
||||
if (entity != null) {
|
||||
drawEntity(renderScope, 0, 0, 75, 78, 30, 0.0625F, ctx.mouseX / scale, ctx.mouseY / scale, entity, angle,
|
||||
negativeAngle);
|
||||
if (entity == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The player is about 1.8 blocks tall; leave some room above and below.
|
||||
drawEntity(renderScope, 0, 0, width, height, (int) (height / 2.2F), 0.0625F, yaw, entity);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*///?}
|
||||
|
||||
@@ -14,6 +14,12 @@ import net.minecraft.client.gui.CubeMapRenderer;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.RotatingCubeMapRenderer;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
//? if >=1.21.6 {
|
||||
import net.minecraft.client.texture.CubemapTexture;
|
||||
//?} else {
|
||||
/*import net.minecraft.client.texture.ResourceTexture;
|
||||
import net.minecraft.client.texture.TextureManager;
|
||||
*///?}
|
||||
//? if >=1.21.9
|
||||
import net.minecraft.client.input.KeyInput;
|
||||
//? if <1.21.6 {
|
||||
@@ -21,8 +27,6 @@ import net.minecraft.client.input.KeyInput;
|
||||
import net.minecraft.client.render.DefaultFramebufferSet;
|
||||
import net.minecraft.client.util.Pool;
|
||||
*///?}
|
||||
import net.minecraft.client.texture.ResourceTexture;
|
||||
import net.minecraft.client.texture.TextureManager;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
@@ -41,14 +45,25 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
|
||||
//private final Pool pool = new Pool(3);
|
||||
public final SaturnScreen screen;
|
||||
|
||||
/** Whether the panorama's textures are loaded; it isn't drawn before (e.g. under the splash). */
|
||||
private static volatile boolean panoramaReady = false;
|
||||
|
||||
public static void preload(MinecraftClient client) {
|
||||
TextureManager textureManager = client.getTextureManager();
|
||||
//? if >=1.21.6 {
|
||||
// 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
|
||||
// already happened by now, so register it through the overload that loads it right away.
|
||||
client.getTextureManager().registerTexture(PANORAMA, new CubemapTexture(PANORAMA));
|
||||
//?} else {
|
||||
/*TextureManager textureManager = client.getTextureManager();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
String var10001 = PANORAMA.getPath();
|
||||
Identifier tex = PANORAMA.withPath(var10001 + "_" + i + ".png");
|
||||
ResourceTexture resourceTexture = new ResourceTexture(tex);
|
||||
textureManager.registerTexture(tex, resourceTexture);
|
||||
}
|
||||
*///?}
|
||||
panoramaReady = true;
|
||||
}
|
||||
|
||||
public SaturnScreenFabric(SaturnScreen screen) {
|
||||
@@ -74,20 +89,18 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
|
||||
mouseX *= 2;
|
||||
mouseY *= 2;
|
||||
|
||||
// TODO: the panorama and the background blur (screen.backgroundBlur) are only drawn before
|
||||
// 1.21.6 so far. See also issue #23.
|
||||
if (client.world == null && client.getCurrentServerEntry() == null) {
|
||||
//? if <1.21.6
|
||||
//ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, screen.backgroundOpacity, delta);
|
||||
// From 1.21.6 the background, blur included, is drawn in renderBackground.
|
||||
//? if <1.21.6 {
|
||||
/*if (isShowingPanorama()) {
|
||||
ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, screen.backgroundOpacity, delta);
|
||||
}
|
||||
|
||||
//? if <1.21.6 {
|
||||
/*PostEffectProcessor postEffectProcessor = this.client.getShaderLoader().loadPostEffect(
|
||||
PostEffectProcessor postEffectProcessor = this.client.getShaderLoader().loadPostEffect(
|
||||
Identifier.ofVanilla("blur"),
|
||||
DefaultFramebufferSet.MAIN_ONLY);
|
||||
|
||||
if (postEffectProcessor != null) {
|
||||
float radius = screen.backgroundBlur * Math.min((float) elapsed / 700, 1.0f);
|
||||
float radius = screen.getBackgroundBlur();
|
||||
//? if >=1.21.5
|
||||
postEffectProcessor.render(this.client.getFramebuffer(), this.pool, pass -> pass.setUniform("Radius", radius));
|
||||
//? if <1.21.5
|
||||
@@ -102,6 +115,32 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
|
||||
screen.render(renderScope, mouseX, mouseY, delta, elapsed);
|
||||
}
|
||||
|
||||
//? if >=1.21.6 {
|
||||
// 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.
|
||||
@Override
|
||||
public void renderBackground(DrawContext 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
|
||||
// opaque.
|
||||
if (isShowingPanorama()) {
|
||||
ROTATING_PANORAMA_RENDERER.render(context, this.width, this.height, true);
|
||||
}
|
||||
|
||||
if (screen.getBackgroundBlur() >= 1) {
|
||||
context.applyBlur();
|
||||
}
|
||||
|
||||
if (client.world != null) {
|
||||
renderDarkening(context);
|
||||
}
|
||||
}
|
||||
//?}
|
||||
|
||||
/** Whether Saturn's panorama is behind the screen: outside a world, once it's loaded. */
|
||||
private boolean isShowingPanorama() {
|
||||
return panoramaReady && client.world == null && client.getCurrentServerEntry() == null;
|
||||
}
|
||||
|
||||
// 1.21.9 moved mouse and key events to Click and KeyInput.
|
||||
//? if >=1.21.9 {
|
||||
@Override
|
||||
@@ -115,8 +154,8 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged(Click click, double offsetX, double offsetY) {
|
||||
// TODO: 1.21.8 passes the drag deltas; check whether offsetX/offsetY are the same on 1.21.9+.
|
||||
if (screen.mouseDragged(click.x(), click.y(), click.button(), 0.0, 0.0)) {
|
||||
// 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)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -184,8 +223,13 @@ public class SaturnScreenFabric extends Screen implements ScreenProvider {
|
||||
}
|
||||
*///?}
|
||||
|
||||
// TODO: resize isn't hooked on 1.21.11 yet.
|
||||
//? if <1.21.11 {
|
||||
//? if >=1.21.11 {
|
||||
@Override
|
||||
public void resize(int width, int height) {
|
||||
screen.resize(width, height);
|
||||
super.resize(width, height);
|
||||
}
|
||||
//?} else {
|
||||
/*@Override
|
||||
public void resize(MinecraftClient client, int width, int height) {
|
||||
screen.resize(width, height);
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.saturnclient.saturnclient.SaturnClient;
|
||||
import org.saturnclient.common.provider.Providers;
|
||||
import org.saturnclient.client.ServiceClient;
|
||||
import org.saturnclient.emotes.fabric.Emotes;
|
||||
import org.saturnclient.impl.ui.SaturnScreenFabric;
|
||||
import org.saturnclient.ui.screens.EmoteWheel;
|
||||
import org.saturnclient.ui.screens.ShiftMenu;
|
||||
|
||||
@@ -51,12 +52,20 @@ public class KeyInputHandler {
|
||||
Providers.saturn.getClient().setScreen(new ShiftMenu());
|
||||
}
|
||||
|
||||
if (Config.openEmoteWheel.wasKeyPressed() && client.currentScreen == null
|
||||
// The emote wheel key opens the wheel, and closes it again while it's open. Closing it
|
||||
// from the screen's own key handling would reopen it on the next tick, since the key is
|
||||
// still down and no screen is open by then.
|
||||
if (Config.openEmoteWheel.wasKeyPressed()
|
||||
//? if >=1.21.9 {
|
||||
&& !InputUtil.isKeyPressed(client.getWindow(), GLFW.GLFW_KEY_F3)) {
|
||||
//?} else
|
||||
//&& !InputUtil.isKeyPressed(client.getWindow().getHandle(), GLFW.GLFW_KEY_F3)) {
|
||||
if (client.currentScreen == null) {
|
||||
Providers.saturn.getClient().setScreen(new EmoteWheel());
|
||||
} else if (client.currentScreen instanceof SaturnScreenFabric saturnScreen
|
||||
&& saturnScreen.screen instanceof EmoteWheel) {
|
||||
saturnScreen.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Sneaking cancels your own emote, for everyone.
|
||||
|
||||
@@ -40,16 +40,15 @@ public abstract class PlayerEntityRendererMixin
|
||||
this.addFeature(new CloakFeatureRenderer(this, ctx.getEquipmentModelLoader()));
|
||||
}
|
||||
|
||||
// Stores the SaturnPlayer in the render state and adds the role icon to the name. Render state
|
||||
// data only exists from 1.21.8.
|
||||
// TODO: 1.21.6 and 1.21.7 don't show the role icon in player names.
|
||||
// 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).
|
||||
//? if >=1.21.9 {
|
||||
@Inject(method = "updateRenderState", at = @At("TAIL"))
|
||||
public <A extends PlayerLikeEntity & ClientPlayerLikeEntity> void updateRenderState(
|
||||
A entity, PlayerEntityRenderState state, float f, CallbackInfo ci) {
|
||||
saturn$applyPlayer(entity, state);
|
||||
}
|
||||
//?} else if >=1.21.8 {
|
||||
//?} else {
|
||||
/*@Inject(method = "updateRenderState", at = @At("TAIL"))
|
||||
public void updateRenderState(
|
||||
AbstractClientPlayerEntity entity, PlayerEntityRenderState state, float f, CallbackInfo ci) {
|
||||
@@ -57,7 +56,6 @@ public abstract class PlayerEntityRendererMixin
|
||||
}
|
||||
*///?}
|
||||
|
||||
//? if >=1.21.8 {
|
||||
private void saturn$applyPlayer(Entity entity, PlayerEntityRenderState state) {
|
||||
if (entity == null) {
|
||||
return;
|
||||
@@ -65,6 +63,7 @@ public abstract class PlayerEntityRendererMixin
|
||||
|
||||
SaturnPlayer player = SaturnPlayer.get(entity.getUuid());
|
||||
|
||||
//? if >=1.21.8
|
||||
state.setData(SaturnRenderState.saturnDataKey, player);
|
||||
|
||||
if (player != null && state.displayName != null) {
|
||||
@@ -77,5 +76,4 @@ public abstract class PlayerEntityRendererMixin
|
||||
.append(state.displayName.copy());
|
||||
}
|
||||
}
|
||||
//?}
|
||||
}
|
||||
@@ -126,8 +126,9 @@ public abstract class SplashOverlayMixin {
|
||||
private void renderProgressBar(RenderScope scope, DrawContext context, int screenWidth, int screenHeight,
|
||||
int alpha) {
|
||||
int progressY = ((screenHeight - 5) / 2) + 25;
|
||||
// TODO: the loading bar's border isn't drawn on 1.21.9+ yet.
|
||||
//? if <1.21.9
|
||||
//? if >=1.21.9 {
|
||||
context.drawStrokedRectangle((screenWidth - 120) / 2, progressY, 120, 5, Theme.withAlpha(alpha, 0xFFFFFFFF));
|
||||
//?} else
|
||||
//context.drawBorder((screenWidth - 120) / 2, progressY, 120, 5, Theme.withAlpha(alpha, 0xFFFFFFFF));
|
||||
|
||||
int progressWidth = Math.min((int) (progress * 120), 120);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
"render.LivingEntityRendererMixin",
|
||||
"render.LivingEntityRenderStateMixin",
|
||||
"render.BackgroundRendererMixin",
|
||||
"misc.NametagsMixin",
|
||||
"render.RenderMixin",
|
||||
"world.TpsMixin",
|
||||
"entity.CameraMixin",
|
||||
|
||||
@@ -9,7 +9,7 @@ org.gradle.configuration-cache=false
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.21.10
|
||||
yarn_mappings=1.21.10+build.3
|
||||
loader_version=0.19.0
|
||||
loader_version=0.19.5
|
||||
|
||||
fabric_api_version=0.138.4+1.21.10
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ org.gradle.configuration-cache=false
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.21.11
|
||||
yarn_mappings=1.21.11+build.4
|
||||
loader_version=0.19.0
|
||||
loader_version=0.19.5
|
||||
|
||||
fabric_api_version=0.141.3+1.21.11
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ org.gradle.configuration-cache=false
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.21.4
|
||||
yarn_mappings=1.21.4+build.8
|
||||
loader_version=0.18.4
|
||||
loader_version=0.19.5
|
||||
|
||||
# Mod Properties
|
||||
maven_group=org.saturnclient
|
||||
|
||||
@@ -9,7 +9,7 @@ org.gradle.configuration-cache=false
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.21.5
|
||||
yarn_mappings=1.21.5+build.1
|
||||
loader_version=0.18.4
|
||||
loader_version=0.19.5
|
||||
|
||||
fabric_api_version=0.128.2+1.21.5
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ org.gradle.configuration-cache=false
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.21.6
|
||||
yarn_mappings=1.21.6+build.1
|
||||
loader_version=0.18.5
|
||||
loader_version=0.19.5
|
||||
|
||||
fabric_api_version=0.128.2+1.21.6
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ org.gradle.configuration-cache=false
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.21.7
|
||||
yarn_mappings=1.21.7+build.8
|
||||
loader_version=0.19.0
|
||||
loader_version=0.19.5
|
||||
|
||||
fabric_api_version=0.129.0+1.21.7
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ org.gradle.configuration-cache=false
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.21.8
|
||||
yarn_mappings=1.21.8+build.1
|
||||
loader_version=0.19.0
|
||||
loader_version=0.19.5
|
||||
|
||||
fabric_api_version=0.136.1+1.21.8
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ org.gradle.configuration-cache=false
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.21.9
|
||||
yarn_mappings=1.21.9+build.1
|
||||
loader_version=0.19.0
|
||||
loader_version=0.19.5
|
||||
|
||||
fabric_api_version=0.134.1+1.21.9
|
||||
|
||||
|
||||
Reference in New Issue
Block a user