Public Access
Complete 26.3 parity acceptance and dual-version release workflow
Build and smoke / changes (push) Waiting to run
Build and smoke / changes (push) Waiting to run
This commit is contained in:
1 parent
41daff1e61
commit
4a59fb5d02
26 files changed
+1241
-369
No files matched your search
@@ -1,6 +1,6 @@
|
||||
# Minecraft 26.3 beta port workspace
|
||||
# Minecraft 26.3
|
||||
|
||||
The current **Minecraft 26.3 release is 26.3.0.1**, for NeoForge 26.3.0.99 and
|
||||
The current **Minecraft 26.3 release is 26.3.0.3**, for NeoForge 26.3.0.99 and
|
||||
Java 25. It uses Rivencraft's first-party Age backend, with no Dynamic Dimensions
|
||||
or Bad Packets dependency. The writing loop, authored/seeded Ages, generation
|
||||
features, weather/skies/celestials, libraries, crystal portals, live instability,
|
||||
@@ -16,11 +16,13 @@ with `book_previews.reborn_live_views` in `rivencraft-local.toml`.
|
||||
Reborn's Static Sky rendering issue remains tracked in
|
||||
[#116](https://git.paddedcell.org/dnorberg/rivencraft/issues/116).
|
||||
|
||||
This regular release is player-validated but does not claim complete 1.21.1 parity.
|
||||
Issues #100, #103 and #104 retain the final multiplayer/parity/release-workflow
|
||||
checks. Preview exploration controls and Create/Ponder scenes remain unported.
|
||||
Use matching client/server builds, keep saves separate from 1.21.1 and back up
|
||||
before updating. See [release notes](RELEASE_NOTES_26.3.0.1.md).
|
||||
The port feature and acceptance review is recorded in
|
||||
[the parity review](../../docs/MC263_PARITY_REVIEW.md). Book exploration matches
|
||||
1.21.1: use the eye for mouse look inside the book panel and right-click to return;
|
||||
movement is disabled. The final dedicated-server restart/return check passed.
|
||||
Create/Ponder scenes are not ported to this target. Use matching client/server
|
||||
builds, keep saves separate from 1.21.1 and back up before updating.
|
||||
See [release notes](RELEASE_NOTES_26.3.0.3.md).
|
||||
|
||||
The entries below record how the port was built, including earlier alpha-only
|
||||
limitations that were addressed by later slices.
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Rivencraft 26.3.0.3
|
||||
|
||||
For **Minecraft 26.3**, **NeoForge 26.3.0.99** and **Java 25**.
|
||||
|
||||
## Book preview exploration
|
||||
|
||||
- The eye button now matches 1.21.1: it grabs the mouse for look-only exploration
|
||||
while the destination view remains inside the book panel. Movement is disabled.
|
||||
- Right-click returns to the ordinary book controls without releasing the preview.
|
||||
Books on stands retain their disabled exploration button.
|
||||
- Fixed the exit crash caused by a forced render and duplicate Reborn render-target
|
||||
submission. Pending target submissions are reused until the renderer drains them.
|
||||
- Removed remaining Beta branding from the in-game mod name/description.
|
||||
|
||||
## Port acceptance and maintenance
|
||||
|
||||
- Completed dedicated-server restart/return-link acceptance for #100, following
|
||||
the two-client matrix and its manual handoff. The player confirmed return travel.
|
||||
- Added changed-target build/smoke workflows, sequential test-server exclusion and
|
||||
repeatable dual-version validation commands.
|
||||
- Hardened release uploads against mismatched filename, embedded version,
|
||||
Minecraft/Java target and accidental test-fixture packaging. The 1.21.1 metadata
|
||||
declares its required Dynamic Dimensions AR and Bad Packets dependencies.
|
||||
- Documented the feature parity review and ongoing independent support of 1.21.1.
|
||||
Existing 1.21.1 code and published artifacts are unchanged.
|
||||
|
||||
## Validation and known issues
|
||||
|
||||
The player passed the live-view exploration/right-click/re-entry check and the
|
||||
dedicated-server Age restart/Linking Book return check. The expanded-catalog
|
||||
two-client matrix passed creation/catalog/travel/stale-ack/lifecycle checks;
|
||||
its final return step stalled and was completed by the player, not retried.
|
||||
Release-tooling checks pass. No optional mod or test fixture is bundled.
|
||||
|
||||
**Known issue #116:** Static Sky can leak outside book previews with Reborn.
|
||||
It remains separately tracked. Other shared follow-ups remain open where needed.
|
||||
Create/Ponder is not ported to 26.3. Without Reborn, built-in animated previews
|
||||
and normal book/portal travel remain available. 1.21.1 saves are not imported.
|
||||
@@ -7,7 +7,7 @@ neo_version=26.3.0.99
|
||||
mod_id=rivencraft
|
||||
mod_name=Rivencraft
|
||||
mod_license=LGPL-3.0-or-later
|
||||
mod_version=26.3.0.1
|
||||
mod_version=26.3.0.3
|
||||
|
||||
jei_version=31.17.0.109
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
package net.dnorberg.rivencraft.client;
|
||||
|
||||
import net.dnorberg.rivencraft.Rivencraft;
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.Tooltip;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.EventBusSubscriber;
|
||||
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
||||
import net.neoforged.neoforge.client.event.InputEvent;
|
||||
import net.neoforged.neoforge.client.event.RenderGuiEvent;
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
|
||||
/** Matches 1.21.1: grabbed mouse look with the book drawn over the source world. */
|
||||
@EventBusSubscriber(modid = Rivencraft.MOD_ID, value = Dist.CLIENT)
|
||||
public final class PortBookExploration {
|
||||
private static PortBookExploration current;
|
||||
private final PortLegacyLinkPanel panel;
|
||||
private Screen owner;
|
||||
private Button eye;
|
||||
private Vec3 sourcePosition;
|
||||
private net.minecraft.client.multiplayer.ClientLevel sourceLevel;
|
||||
private int guiWidth, guiHeight;
|
||||
private boolean active;
|
||||
|
||||
PortBookExploration(PortLegacyLinkPanel panel) { this.panel = panel; }
|
||||
|
||||
void attach(Screen screen, java.util.function.Consumer<Button> add, int left, int top, boolean stand) {
|
||||
owner = screen;
|
||||
eye = Button.builder(Component.literal("👁"), button -> {
|
||||
var minecraft = Minecraft.getInstance();
|
||||
if (stand || !panel.canExplore() || minecraft.player == null) return;
|
||||
sourcePosition = minecraft.player.position();
|
||||
sourceLevel = minecraft.level;
|
||||
guiWidth = minecraft.getWindow().getGuiScaledWidth();
|
||||
guiHeight = minecraft.getWindow().getGuiScaledHeight();
|
||||
active = true;
|
||||
current = this;
|
||||
eye.visible = false;
|
||||
panel.exploring(true);
|
||||
KeyMapping.releaseAll();
|
||||
// Removing the screen grabs the mouse normally. removed() preserves this session.
|
||||
minecraft.gui.setScreen(null);
|
||||
}).bounds(left + 229, top + 145, 20, 20).build();
|
||||
eye.active = !stand;
|
||||
eye.setTooltip(Tooltip.create(Component.literal("Look around destination (right-click to return)")));
|
||||
add.accept(eye);
|
||||
}
|
||||
|
||||
void tick(boolean frontPage) {
|
||||
if (eye != null) eye.visible = !active && frontPage && panel.canExplore();
|
||||
}
|
||||
|
||||
boolean active() { return active; }
|
||||
|
||||
void stop() {
|
||||
active = false;
|
||||
if (current == this) current = null;
|
||||
sourcePosition = null;
|
||||
sourceLevel = null;
|
||||
panel.exploring(false);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void beforeTick(ClientTickEvent.Pre event) {
|
||||
if (current != null) KeyMapping.releaseAll();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void afterTick(ClientTickEvent.Post event) {
|
||||
var overlay = current;
|
||||
if (overlay == null) return;
|
||||
var minecraft = Minecraft.getInstance();
|
||||
if (minecraft.player == null || minecraft.level != overlay.sourceLevel || minecraft.gui.screen() != null) {
|
||||
overlay.stop();
|
||||
overlay.panel.close();
|
||||
return;
|
||||
}
|
||||
minecraft.player.setPos(overlay.sourcePosition);
|
||||
minecraft.player.setDeltaMovement(Vec3.ZERO);
|
||||
overlay.panel.tick();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void drawBook(RenderGuiEvent.Post event) {
|
||||
var overlay = current;
|
||||
var minecraft = Minecraft.getInstance();
|
||||
if (overlay == null || minecraft.gui.screen() != null) return;
|
||||
int width = minecraft.getWindow().getGuiScaledWidth();
|
||||
int height = minecraft.getWindow().getGuiScaledHeight();
|
||||
if (width != overlay.guiWidth || height != overlay.guiHeight) {
|
||||
overlay.guiWidth = width;
|
||||
overlay.guiHeight = height;
|
||||
overlay.owner.resize(width, height);
|
||||
overlay.eye.visible = false;
|
||||
}
|
||||
overlay.owner.extractRenderState(event.getGuiGraphics(), -1, -1,
|
||||
event.getPartialTick().getGameTimeDeltaPartialTick(false));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void mouseButton(InputEvent.MouseButton.Pre event) {
|
||||
var overlay = current;
|
||||
if (overlay == null || Minecraft.getInstance().gui.screen() != null) return;
|
||||
// Neither mouse button may use the held book or attack in the source world.
|
||||
event.setCanceled(true);
|
||||
if (event.getButton() == InputConstants.MOUSE_BUTTON_RIGHT && event.getAction() == InputConstants.PRESS) {
|
||||
overlay.stop();
|
||||
KeyMapping.releaseAll();
|
||||
// Unlike 1.21.1 setScreen, setScreenAndShow forces a render immediately.
|
||||
// Resume through the regular GUI lifecycle without nesting a new frame.
|
||||
Minecraft.getInstance().gui.setScreen(overlay.owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,8 @@ public final class PortBookPreview {
|
||||
void accept(net.dnorberg.rivencraft.item.LinkBookTarget destination);
|
||||
boolean render(GuiGraphicsExtractor graphics, int x, int y, int width, int height, float time);
|
||||
void close();
|
||||
default void exploring(boolean enabled) {}
|
||||
default void tick() {}
|
||||
}
|
||||
private static PortBookPreview active;
|
||||
private final UUID session = UUID.randomUUID();
|
||||
@@ -46,12 +48,16 @@ public final class PortBookPreview {
|
||||
}
|
||||
void tick() {
|
||||
ticks++;
|
||||
if (live != null) live.tick();
|
||||
if (ticks % (received ? 200 : 40) == 0) sendRequest();
|
||||
}
|
||||
boolean render(GuiGraphicsExtractor graphics, int x, int y, int width, int height, float partialTick) {
|
||||
if (closed || !received || live == null) return false;
|
||||
return live.render(graphics, x, y, width, height, ticks + partialTick);
|
||||
}
|
||||
boolean canExplore() { return live != null && received && !closed; }
|
||||
void exploring(boolean enabled) { if (live != null) live.exploring(enabled); }
|
||||
|
||||
public static void accept(BookPreviewPayload payload) {
|
||||
if (active == null || active.closed || active.live == null || !active.session.equals(payload.session())
|
||||
|| !payload.destination().valid()) return;
|
||||
|
||||
+8
-2
@@ -27,6 +27,7 @@ public final class PortDescriptiveBookScreen extends Screen {
|
||||
private final boolean bound;
|
||||
private final net.minecraft.resources.Identifier ageId;
|
||||
private final PortLegacyLinkPanel linkPanel = new PortLegacyLinkPanel();
|
||||
private final PortBookExploration exploration = new PortBookExploration(linkPanel);
|
||||
private final net.dnorberg.rivencraft.writing.DescriptiveBookPages pages;
|
||||
private int pageIndex;
|
||||
private net.dnorberg.rivencraft.network.UseBookStandPayload standSource;
|
||||
@@ -48,7 +49,11 @@ public final class PortDescriptiveBookScreen extends Screen {
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
if (bound) { linkPanel.open(hand, book, standSource); return; }
|
||||
if (bound) {
|
||||
linkPanel.open(hand, book, standSource);
|
||||
exploration.attach(this, this::addRenderableWidget, (width - WIDTH) / 2, (height - HEIGHT) / 2, standSource != null);
|
||||
return;
|
||||
}
|
||||
if (standSource != null) return;
|
||||
int left = (width - WIDTH) / 2;
|
||||
int top = (height - HEIGHT) / 2;
|
||||
@@ -183,9 +188,10 @@ public final class PortDescriptiveBookScreen extends Screen {
|
||||
|
||||
@Override public void tick() {
|
||||
if (bound) linkPanel.tick();
|
||||
exploration.tick(pageIndex == 0);
|
||||
}
|
||||
|
||||
@Override public void removed() { linkPanel.close(); super.removed(); }
|
||||
@Override public void removed() { if (!exploration.active()) { exploration.stop(); linkPanel.close(); } super.removed(); }
|
||||
|
||||
@Override
|
||||
public boolean isPauseScreen() {
|
||||
|
||||
@@ -19,7 +19,9 @@ final class PortLegacyLinkPanel {
|
||||
net.dnorberg.rivencraft.network.UseBookStandPayload stand) {
|
||||
if (preview == null) preview = new PortBookPreview(hand, book, stand);
|
||||
}
|
||||
void close() { if (preview != null) preview.close(); }
|
||||
void close() { if (preview != null) { preview.close(); preview = null; } }
|
||||
boolean canExplore() { return preview != null && preview.canExplore(); }
|
||||
void exploring(boolean value) { if (preview != null) preview.exploring(value); }
|
||||
|
||||
private static final int LINK_COLOR = 0xFF006666;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ public final class PortLinkingBookScreen extends Screen {
|
||||
private final Component destination;
|
||||
private int pageIndex;
|
||||
private final PortLegacyLinkPanel linkPanel = new PortLegacyLinkPanel();
|
||||
private final PortBookExploration exploration = new PortBookExploration(linkPanel);
|
||||
private net.dnorberg.rivencraft.network.UseBookStandPayload standSource;
|
||||
private EditBox titleInput;
|
||||
|
||||
@@ -53,7 +54,11 @@ public final class PortLinkingBookScreen extends Screen {
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
if (bound) { linkPanel.open(hand, book, standSource); return; }
|
||||
if (bound) {
|
||||
linkPanel.open(hand, book, standSource);
|
||||
exploration.attach(this, this::addRenderableWidget, (width - WIDTH) / 2, (height - HEIGHT) / 2, standSource != null);
|
||||
return;
|
||||
}
|
||||
if (standSource != null) return;
|
||||
int left = (width - WIDTH) / 2;
|
||||
int top = (height - HEIGHT) / 2;
|
||||
@@ -148,9 +153,10 @@ public final class PortLinkingBookScreen extends Screen {
|
||||
|
||||
@Override public void tick() {
|
||||
if (bound) linkPanel.tick();
|
||||
exploration.tick(pageIndex == 0);
|
||||
}
|
||||
|
||||
@Override public void removed() { linkPanel.close(); super.removed(); }
|
||||
@Override public void removed() { if (!exploration.active()) { exploration.stop(); linkPanel.close(); } super.removed(); }
|
||||
|
||||
@Override
|
||||
public boolean isPauseScreen() {
|
||||
|
||||
@@ -26,7 +26,28 @@ public final class RebornLiveBookPanel implements PortBookPreview.LivePanel {
|
||||
private static RebornLiveBookPanel queued;
|
||||
private LinkBookTarget destination;
|
||||
private boolean closed;
|
||||
private boolean exploring;
|
||||
private Vec3 explorePosition;
|
||||
private float yaw, pitch, playerYaw, playerPitch;
|
||||
|
||||
@Override public void exploring(boolean enabled) {
|
||||
exploring = enabled;
|
||||
if (enabled && destination != null) {
|
||||
explorePosition = new Vec3(destination.x(), destination.y() + 1.62, destination.z());
|
||||
yaw = destination.yaw(); pitch = destination.pitch();
|
||||
var player = Minecraft.getInstance().player;
|
||||
if (player != null) {
|
||||
explorePosition = new Vec3(destination.x(), destination.y() + player.getEyeHeight(), destination.z());
|
||||
playerYaw = player.getYRot(); playerPitch = player.getXRot();
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override public void tick() {
|
||||
var player = Minecraft.getInstance().player;
|
||||
if (!exploring || destination == null || player == null) return;
|
||||
yaw = destination.yaw() + net.minecraft.util.Mth.wrapDegrees(player.getYRot() - playerYaw);
|
||||
pitch = Math.clamp(destination.pitch() + player.getXRot() - playerPitch, -89, 89);
|
||||
}
|
||||
@Override public void accept(LinkBookTarget value) { destination = value; }
|
||||
@Override public boolean render(GuiGraphicsExtractor graphics, int x, int y, int width, int height, float time) {
|
||||
if (closed || destination == null || !ClientWorldLoader.getIsInitialized()) return false;
|
||||
@@ -40,16 +61,25 @@ public final class RebornLiveBookPanel implements PortBookPreview.LivePanel {
|
||||
Vec3 center = new Vec3(destination.x(), destination.y() + 2.5, destination.z());
|
||||
double angle = time * 0.012;
|
||||
Vec3 camera = center.add(Math.sin(angle) * 11, 5, Math.cos(angle) * 11);
|
||||
Matrix4f transform = new Matrix4f().rotateX((float) Math.toRadians(20))
|
||||
.rotateY((float) angle);
|
||||
Matrix4f transform;
|
||||
if (exploring && explorePosition != null) {
|
||||
camera = explorePosition;
|
||||
transform = new Matrix4f().rotateX((float) Math.toRadians(pitch))
|
||||
.rotateY((float) Math.toRadians(yaw + 180));
|
||||
} else transform = new Matrix4f().rotateX((float) Math.toRadians(20)).rotateY((float) angle);
|
||||
var info = new WorldRenderInfo.Builder().setWorld(world).setCameraPos(camera)
|
||||
.setCameraTransformation(transform).setOverwriteCameraTransformation(true)
|
||||
.setRenderDistance(Math.min(8, minecraft.options.getEffectiveRenderDistance()))
|
||||
.setDoRenderHand(false).setEnableViewBobbing(false).setDoRenderSky(true).setHasFog(true).build();
|
||||
// Submit first: Reborn may resize the target, invalidating its old texture view.
|
||||
// GPU clearing happens in beginRender(), after extraction but before remote rendering.
|
||||
GuiPortalRendering.submitNextFrameRendering(info, target);
|
||||
queued = this;
|
||||
// Overlay-to-screen transitions can extract this panel twice before Reborn
|
||||
// drains its queue. Its API accepts only one task per target until then.
|
||||
// Reuse that pending view for subsequent draws instead of submitting twice.
|
||||
if (queued == null) {
|
||||
// Submit first: Reborn may resize the target and invalidate its texture view.
|
||||
// GPU clearing happens in beginRender(), before remote rendering.
|
||||
GuiPortalRendering.submitNextFrameRendering(info, target);
|
||||
queued = this;
|
||||
}
|
||||
graphics.blit(target.getColorTextureView(), RenderSystem.getSamplerCache().getClampToEdge(FilterMode.LINEAR),
|
||||
x, y, x + width, y + height, 0, 1, 1, 0);
|
||||
graphics.outline(x, y, width, height, 0xFF7B6AA8);
|
||||
@@ -75,5 +105,5 @@ public final class RebornLiveBookPanel implements PortBookPreview.LivePanel {
|
||||
camera.update(minecraft.getDeltaTracker());
|
||||
}
|
||||
}
|
||||
@Override public void close() { closed = true; destination = null; }
|
||||
@Override public void close() { exploring(false); closed = true; destination = null; }
|
||||
}
|
||||
@@ -4,11 +4,11 @@ issueTrackerURL="https://git.paddedcell.org/dnorberg/rivencraft/issues"
|
||||
[[mods]]
|
||||
modId="${mod_id}"
|
||||
version="${mod_version}"
|
||||
displayName="${mod_name} 26.3 Beta"
|
||||
displayName="${mod_name}"
|
||||
displayURL="https://git.paddedcell.org/dnorberg/rivencraft"
|
||||
authors="dnorberg and contributors"
|
||||
description='''
|
||||
Experimental Minecraft 26.3 beta with books, writing stations and selected
|
||||
Minecraft 26.3 release with books, writing stations and selected
|
||||
authored Age generation. Full 1.21.1 gameplay parity is still in progress.
|
||||
Use a test world and keep backups; 1.21.1 worlds are not compatible.
|
||||
'''
|
||||
|
||||
Reference in new issue
Block a user