1.21.4-1.21.6 declared loader 0.18.x and the others 0.19.0, but the
bundled emotes-fabric pulls in loader 0.19.5, and its nested mod already
requires loader >=0.19. So the declared version was never what ran: in
dev, Loom's loader libraries came from the declared version while the
loader itself was 0.19.5, and 1.21.4/1.21.6 sometimes started with
sponge-mixin 0.17.0 and crashed (NoClassDefFoundError:
IAdviceProvider). Declaring 0.19.5 makes dev match what runs, and makes
fabric.mod.json's fabricloader requirement (>=0.19.5) honest.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Step 6 of #8. versions/1.21.4/src is gone, so all eight versions (1.21.4 to
1.21.11) build from src/.
1.21.4's differences from 1.21.5 are behind version comments:
- The end gateway render layer has no render pipeline before 1.21.5
(ShaderUtils: the pipeline field only exists from 1.21.5, and the layer
is a four-way chain).
- Hat head rotation, the NativeImageBackedTexture constructor, armor slots
(inventory.armor vs getEquippedStack), MatrixStackMixin's Quaternionf,
and inside the pre-1.21.6 implementations: prevHeadYaw, GUI lighting,
ModelTransformationMode, item depth, setShaderTexture and the blur
uniform call. Those are one-line version comments, since the pre-1.21.6
blocks are already inside /* */ on newer versions.
1.21.5's drawItem wrapped its body in a second isEmpty check after already
returning early for empty stacks; the redundant check is gone, so 1.21.4
and 1.21.5 share the body.
Freelook's zoom-out (FreelookMod.shouldZoomOut in GameRendererMixin) only
existed on 1.21.4. It doesn't depend on the Minecraft version, so it's
back on every version.
With no old copies left, the mc-<v> fallback in settings.gradle.kts and
scripts/port.sh are removed, and README and VERSION_GUIDE describe the
single layout.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
1.21.5 is the first version before the 1.21.6 GUI rewrite, which moved
GUI drawing from vertex consumers and a MatrixStack to render states and
a 2D Matrix3x2fStack.
- RenderScopeImpl and EntityDrawerImpl have two whole implementations,
one per side of 1.21.6 (a single >=1.21.6 / else split), instead of
conditionals scattered through them. Callers use RenderScopeImpl(context)
in every version; 1.21.5's did the same thing through its
(matrices, vertexConsumers) constructor.
- MatrixStackMixin (MatrixStack as a MatrixStackRef) is real before 1.21.6
and empty from 1.21.6, registered everywhere like NametagsMixin.
- DrawContextAccessor exposes the vertex consumers before 1.21.6 and the
GUI render state from it.
- Smaller changes: fog (BackgroundRenderer vs FogRenderer), the end
portal texture arguments (ShaderUtils, now a flat three-way chain), the
status effect sprite manager, and getIconId only from 1.21.6.
Features 1.21.6+ lacks stay on 1.21.5, with a TODO: the title panorama
behind Saturn screens and the background blur (screen.backgroundBlur,
see #23).
The 1.21.5 jar differs from the old one only in the helpers from earlier
steps, the RenderScopeImpl(context) calls, the empty SaturnRenderState
and unused Matrix3x2fStackRef, and 1.21.5's dead NameTagMixin (never
registered) being gone. 1.21.6-1.21.11 only gain the empty
MatrixStackMixin and its impl.mixins.json entry.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
1.21.6's copy only differed from 1.21.7's in RenderScopeImpl: item
rendering uses ItemRenderState, which 1.21.7 renamed to
KeyedItemRenderState. That's behind a version comment; 1.21.6 keeps its
older loader_version (0.18.5) in its gradle.properties.
Moving a version over leaves the old mc-<v> project's compiled classes in
the shared build/ folder, so a removed class (1.21.6's dead NameTagMixin)
still got packaged until a clean. VERSION_GUIDE now says to run
:<v>:clean once after moving a version.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Step 5 of #8. versions/1.21.7/src is gone; 1.21.7 builds from src/ as
:1.21.7.
1.21.7's copy differed from 1.21.8's in the player render state: Fabric
API's RenderStateDataKey only exists from 1.21.8 (fabric-rendering-v1
12.6.0), so 1.21.7 had no updateRenderState hook, no SaturnRenderState,
and looked players up by name for the cloak and hat. That stays the case:
- The cloak and hat use getData on >=1.21.8 and SaturnPlayer.get(name)
before that.
- PlayerEntityRendererMixin's updateRenderState exists only on >=1.21.8,
as flat ranges (>=1.21.9, else if >=1.21.8) calling a shared
saturn$applyPlayer helper, instead of nested version blocks.
- SaturnRenderState's key only exists on >=1.21.8; the class is empty
before.
- TODO: 1.21.6 and 1.21.7 still don't show the role icon in names.
1.21.7's NameTagMixin isn't carried over: it wasn't registered in any
mixin config, so it never ran.
The 1.21.7 jar differs from the old one only as 1.21.8's did in step 4
(entityAlpha and drawGroup helpers, getIconId, and the cloak getting its
buffer at the draw call), plus the empty SaturnRenderState and the
missing dead NameTagMixin. 1.21.8-1.21.11 only differ in
PlayerEntityRendererMixin (the helper).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Step 4 of #8, the first version before the 1.21.9 render queue.
versions/1.21.8/src is gone; 1.21.8 builds from src/ as :1.21.8.
API differences behind version comments (<1.21.9 / >=1.21.9):
- Player cosmetics: FeatureRenderer.render takes a VertexConsumerProvider
instead of the render queue. The cloak, hat and OBJ renderers name the
render target "output" in both, so only the parameter type and the final
draw call differ; the OBJ face loop moved into drawGroup.
- PlayerEntityRenderer.updateRenderState's entity type, the cape texture
accessor, GameProfile getName()/getId() vs name()/id(), fonts in
TextMixin, EntityRenderDispatcher vs EntityRenderManager, Screen input
events (Click/KeyInput), and KeyBinding categories and isKeyPressed.
Features 1.21.9+ lacks stay on 1.21.8, with a TODO for 1.21.9+:
- NametagsMixin moves into src/. It hooks renderLabelIfPresent with a
VertexConsumerProvider, which 1.21.9 changed, so on 1.21.9+ its body is
empty; it stays registered, so features.mixins.json is the same for
every version.
- The splash screen's loading-bar border, and the real drag deltas in
SaturnScreenFabric.mouseDragged.
- Status effect icons keep 1.21.8's GUI atlas sprite; 1.21.9+ draws the
texture instead (getIconId), as before.
Behaviour changes on 1.21.8: the cloak and hat read the Saturn player from
the render state (set by PlayerEntityRendererMixin, by UUID) instead of
looking it up by name, and the display-name null check applies.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Step 3 of #8. 1.21.9's copy was identical to the old 1.21.10 one, so the
existing version comments already cover it and no code changes: 1.21.9 is
added to stonecutterVersions and versions/1.21.9/src is removed.
Like 1.21.10 in step 2, 1.21.9 now renders hats (1.21.11's render-queue
implementation) and gets the display-name null check. The jar has the same
entries, fabric.mod.json and mixin configs as before; only those classes
and ShaderUtils's entityAlpha helper differ in bytecode.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Step 2 of #8. versions/1.21.10/src is gone; 1.21.10 builds from src/ as
:1.21.10, with versions/1.21.10 keeping only gradle.properties and run/.
API differences go behind version comments: render layers (ShaderUtils),
Camera.update's World vs BlockView (CameraMixin), the text and textured-quad
render states (RenderScopeImpl), Screen.init (SplashOverlayMixin) and
jspecify's @NonNull (SaturnRenderState).
Features 1.21.11 leaves out stay on 1.21.10, with a TODO for 1.21.11:
WorldFeatureImpl.getWorldAge, SaturnScreenFabric.resize and
EntityDrawerImpl clearing the hitbox.
Hats now render on 1.21.10: its HatFeatureRenderer overrode the
render-queue method with an empty body, and the working code sat in an old
VertexConsumerProvider method nothing called. 1.21.10 now uses 1.21.11's
render-queue implementation (HatFeatureRenderer, ObjModel, ObjRenderer),
and also gets 1.21.11's null check on the player's display name.
The 1.21.10 jar has the same entries, fabric.mod.json and mixin configs as
before; only those four classes and ShaderUtils (a helper method for
entityAlpha) have different bytecode. The 1.21.11 jar only differs in
ShaderUtils.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- settings.gradle, stonecutter.gradle and the root build.gradle become
.kts. Loom's version for the Stonecutter versions moves to the root
gradle.properties (loom_version), read by pluginManagement, since the
Kotlin plugins block can't read properties. The old mc-<v> projects keep
their Groovy scripts until they're folded in.
- buildAll ran all eight remapJar tasks at once. Each loads a Minecraft
classpath and remaps a ~50 MB jar, which doesn't fit in the 3 GB daemon
heap: a cold build stalled in garbage collection for 40+ minutes, and
earlier runs failed. A shared build service now lets two remaps run
together; a cold buildAll takes about 2 minutes.
- port.sh and VERSION_GUIDE follow the .kts file names.
The 1.21.11 jar is the same as with the Groovy scripts.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Step 1 of #8. 1.21.11's version-specific code moves from versions/1.21.11/src
to the top-level src/, built by Stonecutter as the project :1.21.11. The other
versions still build from their own copies as :mc-<v> until they're folded in.
- settings.gradle: applies Stonecutter (Groovy controller) with
stonecutterVersions = ["1.21.11"] and skips those folders when including
the old mc-<v> projects.
- The old root build.gradle becomes stonecutter.gradle (the root project's
script, with the shared repositories, common wiring and buildAll), and
1.21.11's build.gradle becomes the root build.gradle that Stonecutter runs
for each version. versions/1.21.11 keeps its gradle.properties and run/.
- The jar has the same 415 entries, fabric.mod.json and mixin configs as
before; the only class differences also appear when rebuilding an
untouched version today.
- scripts/port.sh treats src/ as the active Stonecutter version, so changes
port between it and the old copies both ways.
- README and VERSION_GUIDE describe the layout, version comments and how to
add a version.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Every version depends on org.saturnclient:emotes-fabric
(${emotes_version}+<mc>, bundled). playEmote plays Saturn's emotes
through it, and sneaking stops your own emote and tells the server.
Emotes now work on 1.21.6+ too, where player-animation-lib was
commented out.
- Removed every player-animation-lib and bendy-lib reference: the KoSmX
repository, the dependencies, the player_anim properties, and the old
(partly commented out) code in SaturnProviderImpl and KeyInputHandler.
- Build: Loom 1.15 -> 1.17.21 (the emotes jar is built with 1.17 and
older Loom refuses it), Gradle 9.3 -> 9.8 (needed by Loom 1.17), and
sourceSets moved out of the dependencies block in the root build.gradle,
which Gradle 9.8 rejects.
- common: points at the emote-library branch (saturnclientmc/common#5).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Implement SaturnProvider.getModVersion() (Fabric mod metadata) and
showWarning() (15 s SystemToast) in every version
- Bump mod_version to 0.1.0-beta3, the first version on the new
Mojang session-server authentication
- Point common at its merge commit for the new auth flow and version check
Fixes#7
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Replace JitPack (which can no longer build session-java since its GitHub
repo is gone) with the Gitea package registry in every build file, move
to dev.selimaj:session-java:0.2.0, and bump common for server reconnect
and request timeouts.
Fixes#4, fixes#5.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
TabListMixin @Overwrote PlayerListEntry.getDisplayName() and always
returned the bare profile name, dropping server-set display names (rank
prefixes, colours) and, by never returning null, vanilla's team
decoration, for every player. Inject at RETURN instead: non-Saturn
players keep the original value, and Saturn players get the icon in
front of the original name, or the team-decorated profile name when the
server set none.
Also bump common for the player-lookup and thread-safety fixes.
Fixes#3. Refs #2, #6.
Co-Authored-By: Claude Opus 5.5 <[email protected]>