Skip to content

Bigger On The Inside (for real this time) - #2184

Open
Loqor wants to merge 54 commits into
mainfrom
feat/bigger-on-the-inside
Open

Loqor wants to merge 54 commits into
mainfrom
feat/bigger-on-the-inside

Conversation

@Loqor

@Loqor Loqor commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

About the PR

Rewrite the entire system from the ground up to ensure functionality and compatibility. Will be tested by beta testers and on multiplayer for discrepancies.

Why / Balance

DOCTOR WHO TARDIS BAHAHAHAHA

Technical details

Media

Requirements

Breaking changes

Changelog

🆑

  • feat: Bigger. On. The. Inside.

Signed-off-by: Loqor <isaiahcrace@gmail.com>
@Loqor
Loqor requested a review from a team as a code owner August 22, 2026 19:49
@github-actions github-actions Bot added size/L Denotes a PR that changes 1000-4999 lines. S: Needs Review Status: Requires additional reviews before being fully accepted. labels Aug 22, 2026
@GSMPBot
GSMPBot requested a review from drtheodor August 22, 2026 19:49
@github-actions github-actions Bot added S: Untriaged Status: Indicates an item has not been triaged and doesn't have appropriate labels. A: Tardis Components Area: Tardis components & manager. S: Needs Review Status: Requires additional reviews before being fully accepted. and removed S: Untriaged Status: Indicates an item has not been triaged and doesn't have appropriate labels. S: Needs Review Status: Requires additional reviews before being fully accepted. labels Aug 22, 2026
Loqor added 2 commits August 22, 2026 15:40
fix: issues with disconnecting = crash
fix: log spam
fix: heads of entities would spin like crazy

Signed-off-by: Loqor <isaiahcrace@gmail.com>
Signed-off-by: Loqor <isaiahcrace@gmail.com>
Loqor added 6 commits August 23, 2026 00:24
fix: booth had incorrect transparent door boolean
fix: player animations now render
fix: entity heads no longer fritz out
bug: animated textures dont.. animate?
bug: particles dont render

Signed-off-by: Loqor <isaiahcrace@gmail.com>
…amera

Signed-off-by: Loqor <isaiahcrace@gmail.com>
…red() for no reason

Signed-off-by: Loqor <isaiahcrace@gmail.com>
…lock positions is apparently not accurate enough!

Signed-off-by: Loqor <isaiahcrace@gmail.com>
fix: block entity rendering
fix: block entities from ait are now animated!
fix: vortex and other skyboxes now render properly through portals, along with (fast) clouds

Signed-off-by: Loqor <isaiahcrace@gmail.com>
fix: isOpen is now the inverse of isClosed
fix: vortex and other skyboxes properly render
fix: entities render properly across both sides of the portal

Signed-off-by: Loqor <isaiahcrace@gmail.com>
@drtheodor drtheodor added the S: DO NOT MERGE Status: Open item that should NOT be merged. DNM. Allows test to run unlike draft. label Aug 27, 2026
@GSMPBot
GSMPBot requested a review from duzos August 28, 2026 21:43
Loqor and others added 8 commits August 28, 2026 22:54
The clear-by-draw fallback drew its full-screen quad at NDC z=1.0, exactly
on the far clip plane. The GL spec treats z==w as inside the frustum, so
NVIDIA keeps those fragments, but Apple's GL driver clips them away. With
zero fragments the stencil clear never ran (stale mask -> interior smear)
and the depth clear never ran (interior had no depth to test against and
drew over the whole screen -> world went white).

Draw the quad at z=0 instead, and clamp glDepthRange to [1,1] while writing
depth so every fragment still stores the far value without riding the clip
boundary.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Both glClear and clear-by-draw fail identically on the affected Mac with the
interior smearing full-screen, which is the signature of the afbo having no
usable stencil storage there (glStencilFunc(EQUAL,1) then always passes).
Dump the FBO status, stencil attachment type/bits and GL vendor/renderer once
so we can confirm before touching the clear path again. Revert after diagnosis.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Apple's GL-over-Metal rejects framebuffer attachment introspection
(GL_INVALID_ENUM), so the previous size/type queries were inconclusive.
Replace them with a functional probe: set stencil=1 in a tiny centre region,
paint red where stencil==1 over black, then read back a centre and a corner
pixel. corner red => stencil never gates (the smear); centre black => writes
dropped. Revert after diagnosis.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…temporary)

The functional probe proved stencil gating works on the affected M4, so the
clear was never the problem. Instrument the real pass instead: log the live
viewport/scissor/bound-fb at stencil-clear time, and read back the afbo's
actual stencil values right after the mask draw (centre vs corner). corner==1
means the mask spread stencil across the whole buffer -> the real smear cause.
Revert after diagnosis.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ary)

Two-point stencil sampling read 0/0 after the mask, but that is ambiguous:
the doorway may not sit under the sample pixels, and GL_STENCIL_INDEX readback
may be silently unreliable on Apple's GL-over-Metal. Add a self-test that reads
stencil back where the functional probe KNOWS it is 1, and replace the 2-point
sample with a full-buffer histogram (max/ones/nonzero) so we can tell whether
the mask wrote any stencil at all. Revert after diagnosis.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stencil, mask and gating are all correct on the M4 (23% doorway, clean), so
the smear is downstream in the blits. copyFramebuffer blits COLOR|DEPTH in one
call, but the main FB is DEPTH32F_STENCIL8 and the afbo is DEPTH24_STENCIL8 - a
depth blit with mismatched formats is GL_INVALID_OPERATION per spec and copies
nothing, which on Apple's strict driver would leave the never-cleared afbo
stale (the smear). Log glGetError after each blit to confirm. Revert after.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…Apple

Root cause of the Mac "smear", confirmed by instrumenting the real pass on an
M4 (stencil, mask and gating all measured correct; the depth-inclusive blits
returned GL_INVALID_OPERATION):

copyFramebuffer blitted GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT in one call,
but the main framebuffer and the afbo have different depth formats. A
glBlitFramebuffer that includes depth requires identical depth formats or it is
GL_INVALID_OPERATION and copies nothing - all or nothing. NVIDIA tolerates the
mismatch; Apple's GL-over-Metal enforces it, so the whole blit (including the
colour copy) failed. Because the afbo is never cleared, its colour never
refreshed and last frame's pixels accumulated -> the interior smeared across
the screen / white.

Blit colour and depth as separate calls so the colour refresh can never be
blocked by the depth copy failing, and swallow the depth blit's error on
drivers that reject the mismatched format (depth occlusion no-ops there; the
visible smear is fixed). NVIDIA behaviour is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Loqor and others added 25 commits August 31, 2026 16:07
Framebuffer-agnostic composite refactor across the four BOTI variants,
gated on an in-game instrumentation step that determines the correct hook.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t (Iris-safe)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nder-scale)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Loqor <isaiahcrace@gmail.com>
… (Phase B M1)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Phase B dep commit hardcoded a local nix-store JDK path, which breaks
other contributors and CI. Pass the JDK at invocation instead:
nix develop --command bash -lc './gradlew <task> -Dorg.gradle.java.home="$JAVA_HOME"'
The daemon-picks-JDK25 issue is a local ~/.gradle/gradle.properties override.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
M1 in-game gate: a nested WorldRenderer.render() double-composites the main
world (Iris's final pass writes to the main framebuffer) and avoiding it needs
deep Iris-internal render-target redirection. Pivoting to gbuffer-injection.
Iris modCompileOnly + isShaderPackInUse guard are kept (injection uses them).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tion design/plan

In-game gate: injecting the interior into the main gbuffer at AFTER_ENTITIES
with setPhase(TERRAIN_SOLID) comes out shaded by the pack, no doubling.
Adds the throwaway probe (IrisPhase, GbufferInjectionProbe,
WorldGeometryRenderer.debugInjectTerrainIntoGbuffer), the gbuffer-injection
design spec, and the M1 (doorway clip) plan. M1 reworks the probe into a real
clipped injector.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extract TardisDoorBOTI.drawDoorApertureMask() as a reusable static helper
that stamps stencil=1 into the doorway aperture using the exterior variant's
portal transform. GbufferInjectionProbe now uses it to clip the terrain
injection: logs GL_STENCIL_BITS once, draws the aperture into stencil with
the door's camera-relative transform, restricts the terrain draw to stencil==1,
then fully restores all GL stencil state. Falls back to unclipped draw if
GL_STENCIL_BITS==0 or no door is in the render queue.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Register WorldRenderEvents.START callback (Iris-only) that ensures
  client.getFramebuffer() has a stencil attachment before any draw this
  frame; setIsStencilEnabled is idempotent and handles shaderpack reloads.
- Remove GL11.glGetInteger(GL11.GL_STENCIL_BITS) from GbufferInjectionProbe
  (emitted GL_INVALID_ENUM in core GL profile); replace with
  AITRenderHelper.getIsStencilEnabled(client.getFramebuffer()).
- Add IrisPhase.setTerrainCutoutMipped() and setTerrainCutout(); refactor
  the set path to a private helper.
- Extend WorldGeometryRenderer.debugInjectTerrainIntoGbuffer() to draw
  RenderLayer.getCutoutMipped() and RenderLayer.getCutout() after solid,
  each wrapped in the matching IrisPhase + reset().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Cache lastPortalCamera + lastPortalWorld in WorldGeometryRenderer.render()
  for reuse by the gbuffer injector (one frame stale, acceptable for probe)
- IrisPhase: add setBlockEntities() and setEntities() wrapping the
  BLOCK_ENTITIES and ENTITIES WorldRenderingPhase values
- WorldGeometryRenderer.injectBlockEntitiesAndEntities(tickDelta): new
  public method that mirrors render()'s model-view+projection save/restore
  exactly, draws BEs wrapped in BLOCK_ENTITIES phase and entities in ENTITIES
  phase, with RenderSystem.depthMask(true) so injected geometry writes depth
- debugInjectTerrainIntoGbuffer: add enableDepthTest + depthMask(true) guard
- GbufferInjectionProbe: call injectBlockEntitiesAndEntities after terrain in
  both the stencil-clipped path and the unclipped fallback

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tity injection

Addresses task review: injectBlockEntitiesAndEntities left the BE/entity
dispatchers pointed at the portal world between AFTER_ENTITIES and END, and
both injection methods forced depthMask(true) without restoring it. Both now
restore in their finally blocks (dispatchers mirror render()'s restore).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ns the interior)

The inside-out door view was rendering twice under a shaderpack: Phase A's
unshaded afbo composite AND the shaded gbuffer injection ("two rendered
parts"). Keep geometry.render() (it caches the portal matrices/VBOs the
injection reuses) but skip only the afbo->screen blit when a shaderpack is
active, so the injection is the sole visible interior. The door frame is still
drawn (shaded) by the normal DoorRenderer pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ar (experimental)

Evidence-driven progress (all behind isShaderPackInUse):
- Confirmed Iris's bound gbuffer has 8 stencil bits (valid glGetFramebufferAttachmentParameteri query).
- Root-caused the clip bleed: DOOR_RENDER_QUEUE is empty at AFTER_ENTITIES under Sodium; now cache the
  interior door in BOTI.LAST_RENDERED_DOOR from TardisDoorBOTI (END) and reuse it in the injector.
- Added BOTI.clearDepthInStencilRegion() and punch a depth hole in the aperture so the portal draws over
  blocks behind the door.

KNOWN-OPEN (resume here): the aperture depth-clear corrupts the door frame's depth -> frame flicker;
smear persists (likely shaderpack TAA). Needs a frame-safe depth approach (tight aperture to the opening,
or re-render the door frame after injection) + a TAA decision. See ledger.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…gression)

Keeps this turn's real win - the injection now correctly stencil-clips to the
doorway (via the BOTI.LAST_RENDERED_DOOR cache; Iris's gbuffer confirmed to have
8 stencil bits). Removes the depth-clear that wiped the open door panels' depth
and made them flicker. Depth-occlusion of the portal by blocks behind the door,
and the frame-safe depth approach, are the next designed step (see ledger).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The door now correctly occludes the injected portal instead of flickering:
- clear depth in the aperture so the portal draws over the room/blocks behind
  the door;
- inject the portal world (shaded by Iris);
- re-render the door block entity on top, still stencil-clipped to the aperture,
  with normal depth test/write, so the open panels/frame occlude the portal and
  their pixels+depth (wiped by the clear/injection) are restored. Uses the
  block-entity dispatcher so the door's exact transform/animation are reused.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…iew + translucent occlusion)

- Clear the stencil buffer each frame before stamping the aperture. We added
  the stencil attachment ourselves and MC/Iris don't clear it, so it was
  accumulating every past door position -> the injection smeared across the
  screen. This fixes the smear.
- Recompute the portal view from the CURRENT camera at AFTER_ENTITIES
  (updatePortalView) instead of reusing the 1-frame-stale END-render view.
- Flatten the aperture depth to NEAR after injecting so translucent geometry
  behind the door (glass) is occluded by the portal instead of showing through.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…r, sky backdrop

- Only inject when the door is actually open (isRemoved + leftRot/transparent
  check), dropping the cache otherwise: no portal over closed/destroyed doors.
- Re-render the door with the CONTEXT matrix stack (camera view) instead of a
  fresh identity stack, which was rendering it billboarded to the camera; also
  re-clear aperture depth before it so it reliably occludes the portal.
- Paint the exterior fog colour as the sky backdrop in Iris's SKY phase so it's
  unlit (was blowing out to white as lit gbuffer geometry).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…dering

Signed-off-by: Loqor <isaiahcrace@gmail.com>
@github-actions github-actions Bot added the S: Merge Conflict Status: Needs to resolve merge conflicts before it can be accepted. label Sep 3, 2026
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

This pull request has conflicts, please resolve those before we can evaluate the pull request.

# Conflicts:
#	src/main/java/dev/amble/ait/client/AITModClient.java
#	src/main/java/dev/amble/ait/client/boti/BOTI.java
#	src/main/java/dev/amble/ait/client/boti/TardisDoorBOTI.java
#	src/main/java/dev/amble/ait/client/boti/TardisExteriorBOTI.java
#	src/main/resources/ait.mixins.json
Signed-off-by: Loqor <isaiahcrace@gmail.com>
@github-actions github-actions Bot removed the S: Merge Conflict Status: Needs to resolve merge conflicts before it can be accepted. label Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A: Tardis Components Area: Tardis components & manager. S: DO NOT MERGE Status: Open item that should NOT be merged. DNM. Allows test to run unlike draft. S: Needs Review Status: Requires additional reviews before being fully accepted. size/L Denotes a PR that changes 1000-4999 lines.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants