Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/release-notes/changelog.json
Original file line number Diff line number Diff line change
Expand Up @@ -2613,6 +2613,22 @@
"released": true,
"released_in": "v0.367.0",
"released_at": "2026-06-26T09:52:26Z"
},
{
"id": "book-screen-no-pause",
"version": "0.368.0",
"type": "fix",
"title": "Reading a book no longer freezes a moving train",
"summary": "Reading a written book on the train no longer pauses (and autosaves) your singleplayer game, which previously caused nearby carriages to vanish until a world reload. The train now keeps moving while you read.",
"highlights": [
"Books no longer pause singleplayer mid-ride",
"Fixes carriages vanishing after reading a book on the train"
],
"pr": 597,
"date": "2026-06-26",
"released": false,
"released_in": null,
"released_at": null
}
]
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ loader_version_range=[1,)
mod_id=dungeontrain
mod_name=Dungeon Train
mod_license=PolyForm Shield 1.0.0
mod_version=0.367.0
mod_version=0.368.0
mod_group_id=games.brennan.dungeontrain
mod_authors=Brennan Hatton
mod_description=A Minecraft port of Dungeon Train (brennanhatton.itch.io/dungeontrain) - a moving train that hosts procedurally generated dungeons.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package games.brennan.dungeontrain.mixin.client;

import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.BookViewScreen;
import net.minecraft.network.chat.Component;
import org.spongepowered.asm.mixin.Mixin;

/**
* Makes the vanilla written-book reader ({@link BookViewScreen}) non-pausing.
*
* <p>Vanilla {@code Screen.isPauseScreen()} defaults to {@code true} and
* {@code BookViewScreen} does not override it, so reading a book in
* singleplayer pauses the integrated server and triggers a full autosave.
* On a moving Sable train that autosave shuffles the train's sub-levels
* through holding chunks and the resume (book close) fails to restore the
* sub-levels around the player, making nearby carriages vanish until a
* world reload. Reading a book should not pause a run mid-ride, so we add
* the {@code isPauseScreen() == false} override Mojang omitted.</p>
*
* <p>Singleplayer-only effect by nature — multiplayer never pauses on a
* screen. Trade-off: the world keeps ticking while the book is open, so the
* player can take damage / be attacked while reading (acceptable, arguably
* more correct, on a constantly-moving roguelite train).</p>
*
* <p>Implemented as an added override (a method merge), not an {@code @Inject}
* — {@code BookViewScreen} inherits {@code isPauseScreen()} from {@code Screen}
* rather than declaring it, so an {@code @Inject} targeting this class would
* fail to resolve at apply-time. Extending {@code Screen} lets the compiler
* verify the {@code @Override}; the private constructor is mixin boilerplate
* to satisfy {@code Screen}'s {@code protected Screen(Component)} ctor and is
* discarded at apply-time.</p>
*/
@Mixin(BookViewScreen.class)
public abstract class BookViewScreenNoPauseMixin extends Screen {

private BookViewScreenNoPauseMixin(Component title) {
super(title);
}

@Override
public boolean isPauseScreen() {
return false;
}
}
1 change: 1 addition & 0 deletions src/main/resources/dungeontrain.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"client.AdvancementsScreenAccessor",
"client.AdvancementWidgetHideDescMixin",
"client.DeathScreenMoveTextMixin",
"client.BookViewScreenNoPauseMixin",
"client.CameraCinematicMixin",
"client.GameRendererSnapshotMixin",
"client.LevelRendererVoidSkyMixin",
Expand Down
Loading