diff --git a/gradle.properties b/gradle.properties index b0d7e85fb..5eb09fe08 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,4 @@ isUnstable=true modVersion=1.115.1 # Minecraft properties: We want to configure this here so we can read it in settings.gradle -mcVersion=1.21.5 +mcVersion=1.21.6 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 18ba67008..f6b8708da 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,9 +7,9 @@ # Minecraft # MC version is specified in gradle.properties, as we need that in settings.gradle. # Remember to update corresponding versions in fabric.mod.json/neoforge.mods.toml -fabric-api = "0.122.0+1.21.5" -fabric-loader = "0.16.10" -neoForge = "21.5.49-beta" +fabric-api = "0.127.0+1.21.6" +fabric-loader = "0.16.14" +neoForge = "21.6.0-beta" neoMergeTool = "2.0.0" mixin = "0.8.5" parchment = "2025.04.19" @@ -69,7 +69,7 @@ ideaExt = "1.1.7" illuaminate = "0.1.0-83-g1131f68" lwjgl = "3.3.3" minotaur = "2.8.7" -modDevGradle = "2.0.82" +modDevGradle = "2.0.95" nullAway = "0.12.7" shadow = "8.3.1" spotless = "7.0.2" diff --git a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/BasicUpgradeModel.java b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/BasicUpgradeModel.java index 300e30d05..8b14f9721 100644 --- a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/BasicUpgradeModel.java +++ b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/BasicUpgradeModel.java @@ -61,6 +61,10 @@ public final class BasicUpgradeModel implements TurtleUpgradeModel { @Override public void renderForItem(UpgradeData upgrade, TurtleSide side, ItemStackRenderState renderer, ItemModelResolver resolver, ItemTransform transform, int seed) { + renderer.appendModelIdentityElement(this); + renderer.appendModelIdentityElement(side); + renderer.appendModelIdentityElement(transform); + var layer = renderer.newLayer(); layer.setTransform(transform); getModel(side).setupItemLayer(layer); diff --git a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/ItemUpgradeModel.java b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/ItemUpgradeModel.java index 5a23de62a..fb6e12afb 100644 --- a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/ItemUpgradeModel.java +++ b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/ItemUpgradeModel.java @@ -26,8 +26,11 @@ import net.minecraft.util.Mth; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import org.joml.Matrix4f; +import org.joml.Vector3f; import org.jspecify.annotations.Nullable; +import java.util.Set; + /** * A sic {@link TurtleUpgradeModel} that renders the upgrade's {@linkplain ITurtleUpgrade#getUpgradeItem(DataComponentPatch) * upgrade item}. @@ -59,9 +62,14 @@ public final class ItemUpgradeModel implements TurtleUpgradeModel { @Override public void renderForItem(UpgradeData upgrade, TurtleSide side, ItemStackRenderState renderer, ItemModelResolver resolver, ItemTransform transform, int seed) { + renderer.appendModelIdentityElement(this); + var childState = new ItemStackRenderState(); resolver.updateForTopItem(childState, upgrade.getUpgradeItem(), ItemDisplayContext.NONE, null, null, seed); if (!childState.isEmpty()) { + renderer.appendModelIdentityElement(childState.getModelIdentity()); + renderer.appendModelIdentityElement(transform); + var layer = renderer.newLayer(); layer.setTransform(transform); layer.setupSpecialModel(getRenderer(side), childState); @@ -122,6 +130,10 @@ public final class ItemUpgradeModel implements TurtleUpgradeModel { poseStack.popPose(); } + @Override + public void getExtents(Set set) { + } + @Override public @Nullable ItemStackRenderState extractArgument(ItemStack itemStack) { return null; diff --git a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModel.java b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModel.java index 49e75e602..097b7e9f7 100644 --- a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModel.java +++ b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModel.java @@ -57,6 +57,9 @@ public interface TurtleUpgradeModel { /** * Render this upgrade to an {@link ItemStackRenderState}. This is used for rendering the item form of the upgrade. + *

+ * Like with {@link ItemModel}, implementations must be careful to call {@link ItemStackRenderState#appendModelIdentityElement} + * where appropriate. * * @param upgrade The upgrade being rendered. * @param side Which side of the turtle (left or right) the upgrade is equipped on. diff --git a/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java b/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java index db3cf468e..169e41c15 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java +++ b/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java @@ -23,9 +23,11 @@ import dan200.computercraft.client.turtle.TurtleUpgradeModelManager; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu; import net.minecraft.client.color.item.ItemTintSource; +import net.minecraft.client.gui.render.pip.PictureInPictureRenderer; import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.MenuAccess; +import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; import net.minecraft.client.renderer.item.ItemModel; @@ -47,6 +49,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.function.BiConsumer; import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; /** * Registers client-side objects, such as {@link BlockEntityRendererProvider}s and @@ -188,4 +192,8 @@ public final class ClientRegistry { public static void registerConditionalItemProperties(BiConsumer> register) { register.accept(TurtleShowElfOverlay.ID, TurtleShowElfOverlay.CODEC); } + + public static void registerPictureInPictureRenderers(Consumer>> register) { + register.accept(PrintoutScreen.PrintoutPictureRenderer::new); + } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java index 118d6e6dc..a6c846a3f 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java @@ -9,7 +9,7 @@ import dan200.computercraft.client.gui.widgets.TerminalWidget; import dan200.computercraft.core.util.Nullability; import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu; import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; @@ -42,11 +42,12 @@ public final class ComputerScreen extends Abstra var computerTextures = GuiSprites.getComputerTextures(family); graphics.blitSprite( - RenderType::guiTextured, computerTextures.border(), + RenderPipelines.GUI_TEXTURED, computerTextures.border(), terminal.getX() - BORDER, terminal.getY() - BORDER, terminal.getWidth() + BORDER * 2, terminal.getHeight() + BORDER * 2 ); + graphics.blitSprite( - RenderType::guiTextured, Nullability.assertNonNull(computerTextures.sidebar()), + RenderPipelines.GUI_TEXTURED, Nullability.assertNonNull(computerTextures.sidebar()), leftPos, topPos + sidebarYOffset, AbstractComputerMenu.SIDEBAR_WIDTH, ComputerSidebar.HEIGHT ); } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java index b9f8d1884..dcdc7d12a 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java @@ -7,7 +7,7 @@ package dan200.computercraft.client.gui; import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveMenu; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; @@ -24,7 +24,7 @@ public class DiskDriveScreen extends AbstractContainerScreen { @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { - graphics.blit(RenderType::guiTextured, BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight, 256, 256); + graphics.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight, 256, 256); } @Override diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java b/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java index 9adad3c34..e1ae2d094 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java @@ -9,7 +9,7 @@ import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.toasts.Toast; import net.minecraft.client.gui.components.toasts.ToastManager; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.FormattedCharSequence; @@ -91,7 +91,7 @@ public class ItemToast implements Toast { @Override public void render(GuiGraphics graphics, Font font, long time) { - graphics.blitSprite(RenderType::guiTextured, TEXTURE, 0, 0, width(), height()); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, TEXTURE, 0, 0, width(), height()); var textX = MARGIN; if (!stack.isEmpty()) { diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java index f5626967b..ac241afc5 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java @@ -108,7 +108,7 @@ public class NoTermComputerScreen extends Screen var lines = font.split(Component.translatable("gui.computercraft.pocket_computer_overlay"), (int) (width * 0.8)); var y = 10; for (var line : lines) { - graphics.drawString(font, line, (width / 2) - (font.width(line) / 2), y, 0xFFFFFF, true); + graphics.drawString(font, line, (width / 2) - (font.width(line) / 2), y, 0xFFFFFFFF, true); y += 9; } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java index 706d2c5c8..cf7284636 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java @@ -10,7 +10,7 @@ import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.MultiLineLabel; import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import org.jspecify.annotations.Nullable; @@ -88,13 +88,13 @@ public final class OptionScreen extends Screen { @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { // Render the actual texture. - graphics.blit(RenderType::guiTextured, BACKGROUND, x, y, 0, 0, innerWidth, PADDING, 256, 256); - graphics.blit(RenderType::guiTextured, BACKGROUND, + graphics.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND, x, y, 0, 0, innerWidth, PADDING, 256, 256); + graphics.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND, x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2, innerWidth, PADDING, 256, 256 ); - graphics.blit(RenderType::guiTextured, BACKGROUND, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING, 256, 256); + graphics.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING, 256, 256); assertNonNull(messageRenderer).renderLeftAlignedNoShadow(graphics, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040); super.render(graphics, mouseX, mouseY, partialTicks); diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java index 7710df1f0..9e46aebc1 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java @@ -7,7 +7,7 @@ package dan200.computercraft.client.gui; import dan200.computercraft.shared.peripheral.printer.PrinterMenu; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; @@ -24,10 +24,10 @@ public class PrinterScreen extends AbstractContainerScreen { @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { - graphics.blit(RenderType::guiTextured, BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight, 256, 256); + graphics.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight, 256, 256); if (getMenu().isPrinting()) { - graphics.blit(RenderType::guiTextured, BACKGROUND, leftPos + 34, topPos + 21, 176, 0, 25, 45, 256, 256); + graphics.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND, leftPos + 34, topPos + 21, 176, 0, 25, 45, 256, 256); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java index df66e8296..9f468bf6d 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java @@ -4,18 +4,27 @@ package dan200.computercraft.client.gui; +import com.mojang.blaze3d.vertex.PoseStack; +import dan200.computercraft.client.render.PrintoutRenderer; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.media.PrintoutMenu; import dan200.computercraft.shared.media.items.PrintoutData; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.navigation.ScreenRectangle; +import net.minecraft.client.gui.render.pip.PictureInPictureRenderer; +import net.minecraft.client.gui.render.state.GuiElementRenderState; +import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ContainerListener; import net.minecraft.world.item.ItemStack; +import org.joml.Matrix3x2f; +import org.jspecify.annotations.Nullable; import org.lwjgl.glfw.GLFW; import java.util.Objects; @@ -25,7 +34,7 @@ import static dan200.computercraft.client.render.PrintoutRenderer.*; /** * The GUI for printed pages and books. * - * @see dan200.computercraft.client.render.PrintoutRenderer + * @see PrintoutRenderer */ public final class PrintoutScreen extends AbstractContainerScreen implements ContainerListener { private PrintoutInfo printout = PrintoutInfo.DEFAULT; @@ -113,15 +122,11 @@ public final class PrintoutScreen extends AbstractContainerScreen @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { // Push the printout slightly forward, to avoid clipping into the background. - graphics.pose().pushPose(); - graphics.pose().translate(0, 0, 1); - - graphics.drawSpecial(bufferSource -> { - drawBorder(graphics.pose(), bufferSource, leftPos, topPos, 0, page, printout.pages(), printout.book(), LightTexture.FULL_BRIGHT); - drawText(graphics.pose(), bufferSource, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutData.LINES_PER_PAGE * page, LightTexture.FULL_BRIGHT, printout.text(), printout.colour()); - }); - - graphics.pose().popPose(); + graphics.guiRenderState.submitPicturesInPictureState(new PrintoutRenderState( + leftPos - COVER_SIZE - 32, leftPos + X_SIZE + COVER_SIZE + 32, + topPos - COVER_SIZE, topPos + Y_SIZE + COVER_SIZE, + printout, page, new Matrix3x2f(graphics.pose()), graphics.scissorStack.peek() + )); } @Override @@ -146,4 +151,56 @@ public final class PrintoutScreen extends AbstractContainerScreen return new PrintoutInfo(pages, book, text, colours); } } + + public record PrintoutRenderState( + int x0, int x1, int y0, int y1, PrintoutInfo printout, int page, Matrix3x2f pose, + @Nullable ScreenRectangle scissorArea, @Nullable ScreenRectangle bounds + ) implements PictureInPictureRenderState { + private PrintoutRenderState( + int x0, int x1, int y0, int y1, PrintoutInfo printout, int page, Matrix3x2f pose, @Nullable ScreenRectangle scissorArea + ) { + this(x0, x1, y0, y1, printout, page, pose, scissorArea, PictureInPictureRenderState.getBounds(x0, x1, y0, y1, scissorArea)); + } + + @Override + public float scale() { + return 1.0f; + } + } + + /** + * PIP renderer for printouts. + *

+ * We prefer using a PIP (rather than a {@link GuiElementRenderState}), as {@link PrintoutRenderer} renders with + * multiple z-levels. + */ + public static final class PrintoutPictureRenderer extends PictureInPictureRenderer { + public PrintoutPictureRenderer(MultiBufferSource.BufferSource bufferSource) { + super(bufferSource); + } + + @Override + protected void renderToTexture(PrintoutRenderState state, PoseStack pose) { + pose.pushPose(); + pose.translate(-0.5f * X_SIZE, -(Y_SIZE + COVER_SIZE), 0); + pose.scale(1.0f, 1.0f, -1.0f); + + drawBorder(pose, bufferSource, 0, 0, 0, state.page(), state.printout().pages(), state.printout().book(), LightTexture.FULL_BRIGHT); + drawText( + pose, bufferSource, X_TEXT_MARGIN, Y_TEXT_MARGIN, PrintoutData.LINES_PER_PAGE * state.page(), LightTexture.FULL_BRIGHT, + state.printout().text(), state.printout().colour() + ); + pose.popPose(); + } + + @Override + public Class getRenderStateClass() { + return PrintoutRenderState.class; + } + + @Override + protected String getTextureLabel() { + return "Printout"; + } + } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java index 6b10c1bc4..965feef5b 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java @@ -12,7 +12,7 @@ import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu; import dan200.computercraft.shared.turtle.inventory.TurtleMenu; import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; @@ -50,7 +50,7 @@ public class TurtleScreen extends AbstractComputerScreen { protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { var advanced = family == ComputerFamily.ADVANCED; graphics.blit( - RenderType::guiTextured, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL, + RenderPipelines.GUI_TEXTURED, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL, leftPos + AbstractComputerMenu.SIDEBAR_WIDTH, topPos, 0, 0, TEX_WIDTH, TEX_HEIGHT, FULL_TEX_SIZE, FULL_TEX_SIZE ); @@ -61,14 +61,14 @@ public class TurtleScreen extends AbstractComputerScreen { var slotX = slot % 4; var slotY = slot / 4; graphics.blitSprite( - RenderType::guiTextured, advanced ? SELECTED_ADVANCED : SELECTED_NORMAL, + RenderPipelines.GUI_TEXTURED, advanced ? SELECTED_ADVANCED : SELECTED_NORMAL, leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18, 22, 22 ); } // Render sidebar graphics.blitSprite( - RenderType::guiTextured, Nullability.assertNonNull(GuiSprites.getComputerTextures(family).sidebar()), + RenderPipelines.GUI_TEXTURED, Nullability.assertNonNull(GuiSprites.getComputerTextures(family).sidebar()), leftPos, topPos + sidebarYOffset, AbstractComputerMenu.SIDEBAR_WIDTH, ComputerSidebar.HEIGHT ); } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java index 0571b831a..1744d1f11 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java @@ -9,7 +9,7 @@ import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Tooltip; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import org.jspecify.annotations.Nullable; @@ -48,7 +48,7 @@ public class DynamicImageButton extends Button { setTooltip(message.tooltip()); var texture = this.texture.get(isHoveredOrFocused()); - graphics.blitSprite(RenderType::guiTextured, texture, getX(), getY(), width, height); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, texture, getX(), getY(), width, height); } public record HintedMessage(Component message, Tooltip tooltip) { diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java index fcd3f8af4..c9e97ec6d 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java @@ -4,6 +4,8 @@ package dan200.computercraft.client.gui.widgets; +import com.mojang.blaze3d.pipeline.RenderPipeline; +import com.mojang.blaze3d.vertex.VertexConsumer; import dan200.computercraft.client.gui.KeyConverter; import dan200.computercraft.client.render.text.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.Terminal; @@ -14,8 +16,16 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.narration.NarratedElementType; import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.gui.navigation.ScreenRectangle; +import net.minecraft.client.gui.render.TextureSetup; +import net.minecraft.client.gui.render.state.GuiElementRenderState; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; +import org.joml.Matrix3x2f; +import org.joml.Matrix4f; +import org.jspecify.annotations.Nullable; import org.lwjgl.glfw.GLFW; import java.util.BitSet; @@ -254,12 +264,23 @@ public class TerminalWidget extends AbstractWidget { public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { if (!visible) return; - graphics.drawSpecial(bufferSource -> { - FixedWidthFontRenderer.drawTerminal( - FixedWidthFontRenderer.toVertexConsumer(graphics.pose(), bufferSource.getBuffer(FixedWidthFontRenderer.TERMINAL_TEXT)), - (float) innerX, (float) innerY, terminal, (float) MARGIN, (float) MARGIN, (float) MARGIN, (float) MARGIN - ); - }); + var scissor = graphics.scissorStack.peek(); + var terminalPose = new Matrix3x2f(graphics.pose()); + var terminalTextures = TextureSetup.singleTextureWithLightmap(graphics.minecraft.getTextureManager().getTexture(FixedWidthFontRenderer.FONT).getTextureView()); + + graphics.guiRenderState.submitGuiElement(new TerminalBackgroundRenderState( + innerX, innerY, terminal, terminalPose, terminalTextures, + maybeIntersect(scissor, new ScreenRectangle( + innerX, innerY, terminal.getWidth() * FONT_WIDTH, terminal.getHeight() * FONT_HEIGHT).transformMaxBounds(graphics.pose()) + ), + scissor + )); + + graphics.guiRenderState.submitGuiElement(new TerminalTextRenderState( + innerX, innerY, terminal, terminalPose, terminalTextures, + maybeIntersect(scissor, new ScreenRectangle(getX(), getY(), getWidth(), getHeight()).transformMaxBounds(graphics.pose())), + scissor + )); } @Override @@ -274,4 +295,49 @@ public class TerminalWidget extends AbstractWidget { public static int getHeight(int termHeight) { return termHeight * FONT_HEIGHT + MARGIN * 2; } + + private static @Nullable ScreenRectangle maybeIntersect(@Nullable ScreenRectangle scissor, ScreenRectangle bounds) { + return scissor == null ? bounds : bounds.intersection(scissor); + } + + private record TerminalBackgroundRenderState( + int x, int y, Terminal terminal, + Matrix3x2f pose, + TextureSetup textureSetup, + @Nullable ScreenRectangle bounds, + @Nullable ScreenRectangle scissorArea + ) implements GuiElementRenderState { + @Override + public void buildVertices(VertexConsumer vertexConsumer, float z) { + var quads = new FixedWidthFontRenderer.QuadEmitter(new Matrix4f().mul(pose).translate(0, 0, z), vertexConsumer); + FixedWidthFontRenderer.drawTerminalBackground(quads, x, y, terminal, MARGIN, MARGIN, MARGIN, MARGIN); + } + + @Override + public RenderPipeline pipeline() { + return RenderPipelines.TEXT; + } + } + + private record TerminalTextRenderState( + int x, int y, Terminal terminal, Matrix3x2f pose, TextureSetup textureSetup, + @Nullable ScreenRectangle bounds, @Nullable ScreenRectangle scissorArea + ) implements GuiElementRenderState { + @Override + public void buildVertices(VertexConsumer vertexConsumer, float z) { + var quads = new FixedWidthFontRenderer.QuadEmitter(new Matrix4f().mul(pose).translate(0, 0, z), vertexConsumer); + FixedWidthFontRenderer.drawTerminalForeground(quads, x, y, terminal); + FixedWidthFontRenderer.drawCursor(quads, x, y, terminal); + + // The GUI renderer requires that the buffer is non-empty. Add a zero-size vertex so we always have something. + for (var i = 0; i < 4; i++) { + vertexConsumer.addVertex(0, 0, z).setColor(0x00ffffff).setUv(0, 0).setLight(LightTexture.FULL_BRIGHT); + } + } + + @Override + public RenderPipeline pipeline() { + return RenderPipelines.TEXT; + } + } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/item/model/TurtleOverlayModel.java b/projects/common/src/client/java/dan200/computercraft/client/item/model/TurtleOverlayModel.java index b2daabfee..b46b51571 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/item/model/TurtleOverlayModel.java +++ b/projects/common/src/client/java/dan200/computercraft/client/item/model/TurtleOverlayModel.java @@ -39,6 +39,9 @@ public record TurtleOverlayModel(ItemTransforms transforms) implements ItemModel var overlay = TurtleItem.getOverlay(stack); if (overlay == null) return; + state.appendModelIdentityElement(this); + state.appendModelIdentityElement(overlay); + var layer = state.newLayer(); TurtleOverlayManager.get(Minecraft.getInstance().getModelManager(), overlay).model().setupItemLayer(layer); layer.setTransform(transforms().getTransform(context)); diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/CableHighlightRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/CableHighlightRenderer.java index 6c72cbc5b..adb66c2b7 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/CableHighlightRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/CableHighlightRenderer.java @@ -29,7 +29,7 @@ public final class CableHighlightRenderer { */ public static boolean drawHighlight(PoseStack transform, MultiBufferSource bufferSource, Camera camera, BlockHitResult hit) { var pos = hit.getBlockPos(); - var world = camera.getEntity().getCommandSenderWorld(); + var world = camera.getEntity().level(); var state = world.getBlockState(pos); diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java index a6ea0649b..5ebbbf95e 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorBlockEntityRenderer.java @@ -4,8 +4,8 @@ package dan200.computercraft.client.render.monitor; -import com.mojang.blaze3d.buffers.BufferType; -import com.mojang.blaze3d.buffers.BufferUsage; +import com.mojang.blaze3d.buffers.GpuBuffer; +import com.mojang.blaze3d.pipeline.RenderPipeline; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; @@ -19,14 +19,17 @@ import dan200.computercraft.shared.config.Config; import dan200.computercraft.shared.peripheral.monitor.ClientMonitor; import dan200.computercraft.shared.peripheral.monitor.MonitorBlockEntity; import dan200.computercraft.shared.util.DirectionUtil; -import net.minecraft.client.renderer.FogParameters; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.fog.FogRenderer; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; +import org.joml.Vector4f; import org.jspecify.annotations.Nullable; import org.lwjgl.system.MemoryUtil; @@ -148,11 +151,7 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer "Monitor at " + monitor.getOrigin().getBlockPos(), - BufferType.VERTICES, BufferUsage.STATIC_WRITE, resultBuffer + () -> "Monitor at " + monitor.getOrigin().getBlockPos(), GpuBuffer.USAGE_VERTEX | GpuBuffer.USAGE_COPY_DST, resultBuffer ); } else if (!renderState.vertexBuffer.isClosed()) { - commandEncoder.writeToBuffer(renderState.vertexBuffer, resultBuffer, 0); + commandEncoder.writeToBuffer(renderState.vertexBuffer.slice(), resultBuffer); } - - var mode = FixedWidthFontRenderer.TERMINAL_TEXT.mode(); - indexAfterBackground = mode.indexCount(vertexCountAfterBackground); - indexAfterForeground = mode.indexCount(vertexCountAfterForeground); - indexAfterCursor = mode.indexCount(vertexCountAfterCursor); } - renderState.indexAfterForeground = indexAfterForeground; - renderState.indexAfterBackground = indexAfterBackground; - renderState.indexAfterCursor = indexAfterCursor; + renderState.vertexCountAfterBackground = vertexCountAfterBackground; + renderState.vertexCountAfterForeground = vertexCountAfterForeground; + renderState.vertexCountAfterCursor = vertexCountAfterCursor; } - if (renderState.indexAfterCursor == 0) return; + if (renderState.vertexCountAfterCursor == 0) return; // Our VBO renders coordinates in monitor-space rather than world space. A full sized monitor (8x6) will // use positions from (0, 0) to (164*FONT_WIDTH, 81*FONT_HEIGHT) = (984, 729). This is far outside the @@ -201,20 +194,20 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer "Monitor", colourTarget, OptionalInt.empty(), depthTarget, OptionalDouble.empty() )) { - renderPass.setPipeline(renderType.getRenderPipeline()); + renderPass.setPipeline(pipeline); + + RenderSystem.bindDefaultUniforms(renderPass); + renderPass.setUniform("DynamicTransforms", transforms); renderPass.setVertexBuffer(0, renderState.vertexBuffer); renderPass.setIndexBuffer(indexBuffer, autoStorageBuffer.type()); @@ -245,7 +256,7 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer new RecipeProvider.Runner(out, fullRegistries)); - var blockTags = generator.blockTags(TagProvider::blockTags); - generator.itemTags(TagProvider::itemTags, blockTags); + generator.blockTags(TagProvider::blockTags); + generator.itemTags(TagProvider::itemTags); generator.add(out -> new net.minecraft.data.loot.LootTableProvider(out, Set.of(), LootTableProvider.getTables(), fullRegistries)); @@ -109,7 +109,7 @@ public final class DataProviders { TagsProvider blockTags(Consumer> tags); - TagsProvider itemTags(Consumer tags, TagsProvider blocks); + TagsProvider itemTags(Consumer> tags); /** * Build new dynamic registries and save them to a pack. diff --git a/projects/common/src/datagen/java/dan200/computercraft/data/TagProvider.java b/projects/common/src/datagen/java/dan200/computercraft/data/TagProvider.java index 984479491..23f1884e6 100644 --- a/projects/common/src/datagen/java/dan200/computercraft/data/TagProvider.java +++ b/projects/common/src/datagen/java/dan200/computercraft/data/TagProvider.java @@ -7,13 +7,10 @@ package dan200.computercraft.data; import dan200.computercraft.api.ComputerCraftTags; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.integration.ExternalModTags; -import dan200.computercraft.shared.util.RegistryHelper; -import net.minecraft.core.Registry; -import net.minecraft.data.tags.ItemTagsProvider; +import net.minecraft.data.tags.TagAppender; import net.minecraft.data.tags.TagsProvider; import net.minecraft.tags.BlockTags; import net.minecraft.tags.ItemTags; -import net.minecraft.tags.TagBuilder; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; @@ -28,14 +25,8 @@ import net.minecraft.world.level.block.Blocks; */ class TagProvider { public static void blockTags(TagConsumer tags) { - tags.tag(ComputerCraftTags.Blocks.COMPUTER).add( - ModRegistry.Blocks.COMPUTER_NORMAL.get(), - ModRegistry.Blocks.COMPUTER_ADVANCED.get(), - ModRegistry.Blocks.COMPUTER_COMMAND.get() - ); - tags.tag(ComputerCraftTags.Blocks.TURTLE).add(ModRegistry.Blocks.TURTLE_NORMAL.get(), ModRegistry.Blocks.TURTLE_ADVANCED.get()); + itemAndBlockTags((b, i) -> tags.tag(b)); tags.tag(ComputerCraftTags.Blocks.WIRED_MODEM).add(ModRegistry.Blocks.CABLE.get(), ModRegistry.Blocks.WIRED_MODEM_FULL.get()); - tags.tag(ComputerCraftTags.Blocks.MONITOR).add(ModRegistry.Blocks.MONITOR_NORMAL.get(), ModRegistry.Blocks.MONITOR_ADVANCED.get()); tags.tag(ComputerCraftTags.Blocks.PERIPHERAL_HUB_IGNORE).addTag(ComputerCraftTags.Blocks.WIRED_MODEM); @@ -91,11 +82,9 @@ class TagProvider { ); } - public static void itemTags(ItemTagConsumer tags) { - tags.copy(ComputerCraftTags.Blocks.COMPUTER, ComputerCraftTags.Items.COMPUTER); - tags.copy(ComputerCraftTags.Blocks.TURTLE, ComputerCraftTags.Items.TURTLE); + public static void itemTags(TagConsumer tags) { + itemAndBlockTags((b, i) -> tags.tag(i).map(Block::asItem)); tags.tag(ComputerCraftTags.Items.WIRED_MODEM).add(ModRegistry.Items.WIRED_MODEM.get(), ModRegistry.Items.WIRED_MODEM_FULL.get()); - tags.copy(ComputerCraftTags.Blocks.MONITOR, ComputerCraftTags.Items.MONITOR); tags.tag(ComputerCraftTags.Items.DISKS).add(ModRegistry.Items.DISK.get(), ModRegistry.Items.TREASURE_DISK.get()); tags.tag(ComputerCraftTags.Items.POCKET_COMPUTERS).add(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get(), ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get()); @@ -117,37 +106,32 @@ class TagProvider { .addTag(ItemTags.BOATS); } + private static void itemAndBlockTags(BlockItemTagConsumer tags) { + tags.tag(ComputerCraftTags.Blocks.COMPUTER, ComputerCraftTags.Items.COMPUTER).add( + ModRegistry.Blocks.COMPUTER_NORMAL.get(), + ModRegistry.Blocks.COMPUTER_ADVANCED.get(), + ModRegistry.Blocks.COMPUTER_COMMAND.get() + ); + tags.tag(ComputerCraftTags.Blocks.TURTLE, ComputerCraftTags.Items.TURTLE).add( + ModRegistry.Blocks.TURTLE_NORMAL.get(), + ModRegistry.Blocks.TURTLE_ADVANCED.get() + ); + tags.tag(ComputerCraftTags.Blocks.MONITOR, ComputerCraftTags.Items.MONITOR).add( + ModRegistry.Blocks.MONITOR_NORMAL.get(), + ModRegistry.Blocks.MONITOR_ADVANCED.get() + ); + } + /** * A wrapper over {@link TagsProvider}. * * @param The type of object we're providing tags for. */ public interface TagConsumer { - TagAppender tag(TagKey tag); + TagAppender tag(TagKey tag); } - public record TagAppender(Registry registry, TagBuilder builder) { - public TagAppender add(T object) { - builder.addElement(RegistryHelper.getKeyOrThrow(registry, object)); - return this; - } - - @SafeVarargs - public final TagAppender add(T... objects) { - for (var object : objects) add(object); - return this; - } - - public TagAppender addTag(TagKey tag) { - builder.addTag(tag.location()); - return this; - } - } - - /** - * A wrapper over {@link ItemTagsProvider}. - */ - public interface ItemTagConsumer extends TagConsumer { - void copy(TagKey block, TagKey item); + private interface BlockItemTagConsumer { + TagAppender tag(TagKey blockTag, TagKey itemTag); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/command/arguments/RepeatArgumentType.java b/projects/common/src/main/java/dan200/computercraft/shared/command/arguments/RepeatArgumentType.java index d1cdfb0a9..44087b7c6 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/command/arguments/RepeatArgumentType.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/command/arguments/RepeatArgumentType.java @@ -12,12 +12,11 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import com.mojang.serialization.JsonOps; import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.synchronization.ArgumentTypeInfo; import net.minecraft.commands.synchronization.ArgumentTypeInfos; -import net.minecraft.core.RegistryAccess; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; import net.minecraft.network.chat.ComponentSerialization; import java.util.ArrayList; @@ -136,7 +135,7 @@ public final class RepeatArgumentType implements ArgumentType> { public void serializeToJson(RepeatArgumentType.Template arg, JsonObject json) { json.addProperty("flatten", arg.flatten); json.add("child", ArgumentUtils.serializeToJson(arg.child)); - json.addProperty("error", Component.Serializer.toJson(ArgumentUtils.getMessage(arg.some), RegistryAccess.EMPTY)); + json.add("error", ComponentSerialization.CODEC.encodeStart(JsonOps.INSTANCE, ArgumentUtils.getMessage(arg.some)).getOrThrow()); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlockEntity.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlockEntity.java index d93a782d7..b8b48e6a1 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlockEntity.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlockEntity.java @@ -20,11 +20,9 @@ import dan200.computercraft.shared.platform.PlatformHelper; import dan200.computercraft.shared.util.*; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.HolderLookup; import net.minecraft.core.component.DataComponentGetter; import net.minecraft.core.component.DataComponentMap; import net.minecraft.core.component.DataComponents; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.Container; import net.minecraft.world.LockCode; @@ -35,6 +33,8 @@ import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import org.jspecify.annotations.Nullable; import java.util.Objects; @@ -142,36 +142,36 @@ public abstract class AbstractComputerBlockEntity extends BlockEntity implements protected abstract void updateBlockState(ComputerState newState); @Override - public void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) { + public void saveAdditional(ValueOutput nbt) { // Save ID, label and power state if (computerID >= 0) nbt.putInt(NBT_ID, computerID); if (label != null) nbt.putString(NBT_LABEL, label); if (storageCapacity > 0) nbt.putLong(NBT_CAPACITY, storageCapacity); nbt.putBoolean(NBT_ON, on); - lockCode.addToTag(nbt, registries); + lockCode.addToTag(nbt); - super.saveAdditional(nbt, registries); + super.saveAdditional(nbt); } @Override - public final void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) { - super.loadAdditional(nbt, registries); + public final void loadAdditional(ValueInput nbt) { + super.loadAdditional(nbt); if (level != null && level.isClientSide) { - loadClient(nbt, registries); + loadClient(nbt); } else { - loadServer(nbt, registries); + loadServer(nbt); } } - protected void loadServer(CompoundTag nbt, HolderLookup.Provider registries) { + protected void loadServer(ValueInput nbt) { // Load ID, label and power state computerID = nbt.getIntOr(NBT_ID, -1); label = nbt.getStringOr(NBT_LABEL, null); storageCapacity = nbt.getLongOr(NBT_CAPACITY, -1); on = startOn = nbt.getBooleanOr(NBT_ON, false); - lockCode = LockCode.fromTag(nbt, registries); + lockCode = LockCode.fromTag(nbt); } @Override @@ -204,12 +204,12 @@ public abstract class AbstractComputerBlockEntity extends BlockEntity implements @Override @Deprecated - public void removeComponentsFromTag(CompoundTag tag) { + public void removeComponentsFromTag(ValueOutput tag) { super.removeComponentsFromTag(tag); - tag.remove(NBT_ID); - tag.remove(NBT_LABEL); - tag.remove(NBT_CAPACITY); - tag.remove(LockCode.TAG_LOCK); + tag.discard(NBT_ID); + tag.discard(NBT_LABEL); + tag.discard(NBT_CAPACITY); + tag.discard(LockCode.TAG_LOCK); } protected boolean isPeripheralBlockedOnSide(ComputerSide localSide) { @@ -391,7 +391,7 @@ public abstract class AbstractComputerBlockEntity extends BlockEntity implements // Networking stuff - protected void loadClient(CompoundTag nbt, HolderLookup.Provider registries) { + protected void loadClient(ValueInput tag) { } protected void transferStateFrom(AbstractComputerBlockEntity copy) { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerBlockEntity.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerBlockEntity.java index 613c5532a..b5b596ac9 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerBlockEntity.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/ComputerBlockEntity.java @@ -13,19 +13,18 @@ import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.TerminalSize; import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory; import dan200.computercraft.shared.config.ConfigSpec; -import dan200.computercraft.shared.util.NBTUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.HolderLookup; import net.minecraft.core.component.DataComponentGetter; import net.minecraft.core.component.DataComponentMap; -import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import org.jspecify.annotations.Nullable; public class ComputerBlockEntity extends AbstractComputerBlockEntity { @@ -40,15 +39,15 @@ public class ComputerBlockEntity extends AbstractComputerBlockEntity { } @Override - protected void loadServer(CompoundTag nbt, HolderLookup.Provider registries) { - super.loadServer(nbt, registries); - terminalSize = NBTUtil.decodeFrom(TerminalSize.CODEC, registries, nbt, NBT_TERMINAL_SIZE); + protected void loadServer(ValueInput nbt) { + super.loadServer(nbt); + terminalSize = nbt.read(NBT_TERMINAL_SIZE, TerminalSize.CODEC).orElse(null); } @Override - public void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) { - super.saveAdditional(nbt, registries); - NBTUtil.encodeTo(TerminalSize.CODEC, registries, nbt, NBT_TERMINAL_SIZE, terminalSize); + public void saveAdditional(ValueOutput tag) { + super.saveAdditional(tag); + tag.storeNullable(NBT_TERMINAL_SIZE, TerminalSize.CODEC, terminalSize); } @Override @@ -65,9 +64,9 @@ public class ComputerBlockEntity extends AbstractComputerBlockEntity { @Override @Deprecated - public void removeComponentsFromTag(CompoundTag tag) { + public void removeComponentsFromTag(ValueOutput tag) { super.removeComponentsFromTag(tag); - tag.remove(NBT_TERMINAL_SIZE); + tag.discard(NBT_TERMINAL_SIZE); } @Override diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/core/ServerContext.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/core/ServerContext.java index 169b46527..9e4bb6d66 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/core/ServerContext.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/core/ServerContext.java @@ -220,7 +220,7 @@ public final class ServerContext { @Override public String getHostString() { - var version = SharedConstants.getCurrentVersion().getName(); + var version = SharedConstants.getCurrentVersion().name(); return String.format("ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), version); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/terminal/NetworkedTerminal.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/terminal/NetworkedTerminal.java index 2ce63f807..baa5129e4 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/terminal/NetworkedTerminal.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/terminal/NetworkedTerminal.java @@ -7,7 +7,8 @@ package dan200.computercraft.shared.computer.terminal; import dan200.computercraft.core.terminal.Palette; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.util.Colour; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; public class NetworkedTerminal extends Terminal { public NetworkedTerminal(int width, int height, boolean colour) { @@ -76,7 +77,7 @@ public class NetworkedTerminal extends Terminal { setChanged(); } - public synchronized CompoundTag writeToNBT(CompoundTag nbt) { + public synchronized void writeToNBT(ValueOutput nbt) { nbt.putInt("term_cursorX", cursorX); nbt.putInt("term_cursorY", cursorY); nbt.putBoolean("term_cursorBlink", cursorBlink); @@ -91,11 +92,9 @@ public class NetworkedTerminal extends Terminal { var rgb8 = new int[Palette.PALETTE_SIZE]; for (var i = 0; i < Palette.PALETTE_SIZE; i++) rgb8[i] = Palette.encodeRGB8(palette.getColour(i)); nbt.putIntArray("term_palette", rgb8); - - return nbt; } - public synchronized void readFromNBT(CompoundTag nbt) { + public synchronized void readFromNBT(ValueInput nbt) { cursorX = nbt.getIntOr("term_cursorX", 0); cursorY = nbt.getIntOr("term_cursorY", 0); cursorBlink = nbt.getBooleanOr("term_cursorBlink", false); @@ -104,29 +103,26 @@ public class NetworkedTerminal extends Terminal { for (var n = 0; n < height; n++) { text[n].fill(' '); - if (nbt.contains("term_text_" + n)) { - text[n].write(nbt.getStringOr("term_text_" + n, "")); - } + var line = nbt.getStringOr("term_text_" + n, ""); + if (!line.isEmpty()) text[n].write(line); + textColour[n].fill(BASE_16.charAt(cursorColour)); - if (nbt.contains("term_textColour_" + n)) { - textColour[n].write(nbt.getStringOr("term_textColour_" + n, "")); - } + var fgLine = nbt.getStringOr("term_textColour_" + n, ""); + if (!fgLine.isEmpty()) textColour[n].write(fgLine); + backgroundColour[n].fill(BASE_16.charAt(cursorBackgroundColour)); - if (nbt.contains("term_textBgColour_" + n)) { - backgroundColour[n].write(nbt.getStringOr("term_textBgColour_" + n, "")); + var bgLine = nbt.getStringOr("term_textBgColour_" + n, ""); + if (!bgLine.isEmpty()) backgroundColour[n].write(bgLine); + } + + var rgb8 = nbt.getIntArray("term_palette").orElse(null); + if (rgb8 != null && rgb8.length == Palette.PALETTE_SIZE) { + for (var i = 0; i < Palette.PALETTE_SIZE; i++) { + var colours = Palette.decodeRGB8(rgb8[i]); + palette.setColour(i, colours[0], colours[1], colours[2]); } } - if (nbt.contains("term_palette")) { - var rgb8 = nbt.getIntArray("term_palette").orElse(null); - if (rgb8 != null && rgb8.length == Palette.PALETTE_SIZE) { - for (var i = 0; i < Palette.PALETTE_SIZE; i++) { - var colours = Palette.decodeRGB8(rgb8[i]); - palette.setColour(i, colours[0], colours[1], colours[2]); - } - } - - } setChanged(); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/datafix/RenamePocketComputerUpgradeFix.java b/projects/common/src/main/java/dan200/computercraft/shared/datafix/RenamePocketComputerUpgradeFix.java index 9513c431c..c3bdb1ed1 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/datafix/RenamePocketComputerUpgradeFix.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/datafix/RenamePocketComputerUpgradeFix.java @@ -13,8 +13,6 @@ import dan200.computercraft.shared.ModRegistry; import net.minecraft.util.datafix.fixes.DataComponentRemainderFix; import net.minecraft.util.datafix.fixes.FoodToConsumableFix; import net.minecraft.util.datafix.fixes.References; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.Map; import java.util.function.Function; @@ -53,6 +51,4 @@ public final class RenamePocketComputerUpgradeFix extends DataFix { dynamic -> dynamic.renameField("computercraft:pocket_upgrade", "computercraft:back_pocket_upgrade") ); } - - private static final Logger LOG = LoggerFactory.getLogger(RenamePocketComputerUpgradeFix.class); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/lectern/CustomLecternBlockEntity.java b/projects/common/src/main/java/dan200/computercraft/shared/lectern/CustomLecternBlockEntity.java index e968d3964..a8b836a0d 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/lectern/CustomLecternBlockEntity.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/lectern/CustomLecternBlockEntity.java @@ -20,6 +20,7 @@ import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.util.Mth; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.Container; import net.minecraft.world.SimpleMenuProvider; import net.minecraft.world.entity.player.Player; @@ -29,6 +30,11 @@ import net.minecraft.world.level.block.LecternBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.LecternBlockEntity; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.TagValueOutput; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.AbstractList; import java.util.List; @@ -41,6 +47,8 @@ import static dan200.computercraft.shared.lectern.CustomLecternBlock.dropItem; * @see LecternBlockEntity */ public final class CustomLecternBlockEntity extends BlockEntity { + private static final Logger LOG = LoggerFactory.getLogger(CustomLecternBlockEntity.class); + private static final String NBT_ITEM = "Item"; private static final String NBT_PAGE = "Page"; @@ -107,19 +115,19 @@ public final class CustomLecternBlockEntity extends BlockEntity { } @Override - public void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { - super.loadAdditional(tag, registries); + public void loadAdditional(ValueInput tag) { + super.loadAdditional(tag); - item = tag.getCompound(NBT_ITEM).flatMap(x -> ItemStack.parse(registries, x)).orElse(ItemStack.EMPTY); + item = tag.read(NBT_ITEM, ItemStack.CODEC).orElse(ItemStack.EMPTY); page = tag.getIntOr(NBT_PAGE, 0); itemChanged(); } @Override - protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { - super.saveAdditional(tag, registries); + protected void saveAdditional(ValueOutput tag) { + super.saveAdditional(tag); - if (!item.isEmpty()) tag.put(NBT_ITEM, item.save(registries)); + if (!item.isEmpty()) tag.store(NBT_ITEM, ItemStack.CODEC, item); if (item.getItem() instanceof PrintoutItem) tag.putInt(NBT_PAGE, page); } @@ -130,9 +138,11 @@ public final class CustomLecternBlockEntity extends BlockEntity { @Override public CompoundTag getUpdateTag(HolderLookup.Provider registries) { - var tag = super.getUpdateTag(registries); - if (!item.isEmpty()) tag.put(NBT_ITEM, item.save(registries)); - return tag; + try (var problems = new ProblemReporter.ScopedCollector(this.problemPath(), LOG)) { + var output = TagValueOutput.createWithContext(problems, registries); + if (!item.isEmpty()) output.store(NBT_ITEM, ItemStack.CODEC, item); + return output.buildResult(); + } } void openMenu(Player player) { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java b/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java index baa8be346..1b05bcb37 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java @@ -87,6 +87,7 @@ public class DiskRecipe extends AbstractCraftingRecipe { var stack = inv.getItem(i); if (stack.isEmpty()) continue; if (ColourUtils.getStackColour(stack) == null) { + inputs++; stackedContents.accountStack(stack, 1); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveBlockEntity.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveBlockEntity.java index 8af9f9227..fb562d508 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveBlockEntity.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveBlockEntity.java @@ -17,9 +17,7 @@ import dan200.computercraft.shared.network.server.ServerNetworking; import dan200.computercraft.shared.util.WorldUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -27,6 +25,8 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.LevelEvent; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.Vec3; import org.jspecify.annotations.Nullable; @@ -114,17 +114,17 @@ public final class DiskDriveBlockEntity extends AbstractContainerBlockEntity imp } @Override - public void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) { - super.loadAdditional(nbt, registries); - setDiskStack(nbt.getCompound(NBT_ITEM).flatMap(x -> ItemStack.parse(registries, x)).orElse(ItemStack.EMPTY)); + public void loadAdditional(ValueInput nbt) { + super.loadAdditional(nbt); + setDiskStack(nbt.read(NBT_ITEM, ItemStack.CODEC).orElse(ItemStack.EMPTY)); } @Override - public void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { - super.saveAdditional(tag, registries); + public void saveAdditional(ValueOutput tag) { + super.saveAdditional(tag); var stack = getDiskStack(); - if (!stack.isEmpty()) tag.put(NBT_ITEM, stack.save(registries)); + if (!stack.isEmpty()) tag.store(NBT_ITEM, ItemStack.CODEC, stack); } void serverTick() { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlockEntity.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlockEntity.java index 4a9d7cd86..f847af156 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlockEntity.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlockEntity.java @@ -15,8 +15,6 @@ import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.TickScheduler; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; @@ -24,6 +22,8 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.Vec3; import org.jspecify.annotations.Nullable; @@ -144,15 +144,15 @@ public class CableBlockEntity extends BlockEntity { } @Override - public void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) { - super.loadAdditional(nbt, registries); + public void loadAdditional(ValueInput nbt) { + super.loadAdditional(nbt); peripheral.read(nbt, ""); } @Override - public void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) { + public void saveAdditional(ValueOutput nbt) { peripheral.write(nbt, ""); - super.saveAdditional(nbt, registries); + super.saveAdditional(nbt); } private void updateBlockState() { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemFullBlockEntity.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemFullBlockEntity.java index cb2d843de..306dcd97b 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemFullBlockEntity.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemFullBlockEntity.java @@ -15,8 +15,6 @@ import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.TickScheduler; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; @@ -24,6 +22,8 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.Vec3; import org.jspecify.annotations.Nullable; @@ -155,15 +155,15 @@ public class WiredModemFullBlockEntity extends BlockEntity { } @Override - public void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) { - super.loadAdditional(nbt, registries); + public void loadAdditional(ValueInput nbt) { + super.loadAdditional(nbt); for (var i = 0; i < peripherals.length; i++) peripherals[i].read(nbt, Integer.toString(i)); } @Override - public void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) { + public void saveAdditional(ValueOutput nbt) { for (var i = 0; i < peripherals.length; i++) peripherals[i].write(nbt, Integer.toString(i)); - super.saveAdditional(nbt, registries); + super.saveAdditional(nbt); } void blockTick() { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java index 29f129106..f00353933 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java @@ -11,8 +11,9 @@ import dan200.computercraft.shared.computer.core.ServerContext; import dan200.computercraft.shared.platform.ComponentAccess; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.Level; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import org.jspecify.annotations.Nullable; import java.util.Map; @@ -97,12 +98,12 @@ public final class WiredModemLocalPeripheral { return peripheral == null ? Map.of() : Map.of(type + "_" + id, peripheral); } - public void write(CompoundTag tag, String suffix) { + public void write(ValueOutput tag, String suffix) { if (id >= 0) tag.putInt(NBT_PERIPHERAL_ID + suffix, id); if (type != null) tag.putString(NBT_PERIPHERAL_TYPE + suffix, type); } - public void read(CompoundTag tag, String suffix) { + public void read(ValueInput tag, String suffix) { id = tag.getIntOr(NBT_PERIPHERAL_ID + suffix, -1); type = tag.getStringOr(NBT_PERIPHERAL_TYPE + suffix, null); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorBlockEntity.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorBlockEntity.java index a3e2c9d88..fe52a9c22 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorBlockEntity.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorBlockEntity.java @@ -22,6 +22,8 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.AABB; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; @@ -107,17 +109,17 @@ public class MonitorBlockEntity extends BlockEntity { } @Override - public void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { + public void saveAdditional(ValueOutput tag) { tag.putInt(NBT_X, xIndex); tag.putInt(NBT_Y, yIndex); tag.putInt(NBT_WIDTH, width); tag.putInt(NBT_HEIGHT, height); - super.saveAdditional(tag, registries); + super.saveAdditional(tag); } @Override - public void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) { - super.loadAdditional(nbt, registries); + public void loadAdditional(ValueInput nbt) { + super.loadAdditional(nbt); var oldXIndex = xIndex; var oldYIndex = yIndex; diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterBlockEntity.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterBlockEntity.java index f6836ac58..31f63b587 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterBlockEntity.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterBlockEntity.java @@ -15,9 +15,7 @@ import dan200.computercraft.shared.util.ColourUtils; import dan200.computercraft.shared.util.DataComponentUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.ContainerHelper; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -25,6 +23,8 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import org.jspecify.annotations.Nullable; import java.util.List; @@ -55,8 +55,8 @@ public final class PrinterBlockEntity extends AbstractContainerBlockEntity imple } @Override - public void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) { - super.loadAdditional(nbt, registries); + public void loadAdditional(ValueInput nbt) { + super.loadAdditional(nbt); // Read page synchronized (page) { @@ -66,11 +66,11 @@ public final class PrinterBlockEntity extends AbstractContainerBlockEntity imple } // Read inventory - ContainerHelper.loadAllItems(nbt, inventory, registries); + ContainerHelper.loadAllItems(nbt, inventory); } @Override - public void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { + public void saveAdditional(ValueOutput tag) { // Write page synchronized (page) { tag.putBoolean(NBT_PRINTING, printing); @@ -79,9 +79,9 @@ public final class PrinterBlockEntity extends AbstractContainerBlockEntity imple } // Write inventory - ContainerHelper.saveAllItems(tag, inventory, registries); + ContainerHelper.saveAllItems(tag, inventory); - super.saveAdditional(tag, registries); + super.saveAdditional(tag); } boolean isPrinting() { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlockEntity.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlockEntity.java index 675a06514..018c4bad5 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlockEntity.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlockEntity.java @@ -35,6 +35,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.Container; import net.minecraft.world.ContainerHelper; import net.minecraft.world.entity.player.Inventory; @@ -45,13 +46,20 @@ import net.minecraft.world.item.component.DyedItemColor; import net.minecraft.world.item.component.TooltipDisplay; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.TagValueOutput; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.Vec3; import org.jspecify.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.function.IntSupplier; public class TurtleBlockEntity extends AbstractComputerBlockEntity implements BasicContainer { + private static final Logger LOG = LoggerFactory.getLogger(TurtleBlockEntity.class); + public static final int INVENTORY_SIZE = 16; public static final int INVENTORY_WIDTH = 4; public static final int INVENTORY_HEIGHT = 4; @@ -142,26 +150,26 @@ public class TurtleBlockEntity extends AbstractComputerBlockEntity implements Ba } @Override - public void loadServer(CompoundTag nbt, HolderLookup.Provider registries) { - super.loadServer(nbt, registries); + public void loadServer(ValueInput nbt) { + super.loadServer(nbt); // Read inventory - ContainerHelper.loadAllItems(nbt, inventory, registries); + ContainerHelper.loadAllItems(nbt, inventory); for (var i = 0; i < inventory.size(); i++) inventorySnapshot.set(i, inventory.get(i).copy()); // Read state - brain.readFromNBT(nbt, registries); + brain.readFromNBT(nbt); } @Override - public void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) { + public void saveAdditional(ValueOutput nbt) { // Write inventory - ContainerHelper.saveAllItems(nbt, inventory, registries); + ContainerHelper.saveAllItems(nbt, inventory); // Write brain - brain.writeToNBT(nbt, registries); + brain.writeToNBT(nbt); - super.saveAdditional(nbt, registries); + super.saveAdditional(nbt); } @Override @@ -197,13 +205,13 @@ public class TurtleBlockEntity extends AbstractComputerBlockEntity implements Ba @Override @Deprecated - public void removeComponentsFromTag(CompoundTag tag) { + public void removeComponentsFromTag(ValueOutput tag) { super.removeComponentsFromTag(tag); - tag.remove(TurtleBrain.NBT_COLOUR); - tag.remove(TurtleBrain.NBT_FUEL); - tag.remove(TurtleBrain.NBT_OVERLAY); - tag.remove(TurtleBrain.NBT_LEFT_UPGRADE); - tag.remove(TurtleBrain.NBT_RIGHT_UPGRADE); + tag.discard(TurtleBrain.NBT_COLOUR); + tag.discard(TurtleBrain.NBT_FUEL); + tag.discard(TurtleBrain.NBT_OVERLAY); + tag.discard(TurtleBrain.NBT_LEFT_UPGRADE); + tag.discard(TurtleBrain.NBT_RIGHT_UPGRADE); } @Override @@ -301,17 +309,19 @@ public class TurtleBlockEntity extends AbstractComputerBlockEntity implements Ba @Override public CompoundTag getUpdateTag(HolderLookup.Provider registries) { - var nbt = super.getUpdateTag(registries); - if (label != null) nbt.putString(NBT_LABEL, label); - brain.writeDescription(nbt, registries); - return nbt; + try (var problems = new ProblemReporter.ScopedCollector(problemPath(), LOG)) { + var nbt = TagValueOutput.createWithContext(problems, registries); + if (label != null) nbt.putString(NBT_LABEL, label); + brain.writeDescription(nbt); + return nbt.buildResult(); + } } @Override - public void loadClient(CompoundTag nbt, HolderLookup.Provider registries) { - super.loadClient(nbt, registries); + public void loadClient(ValueInput nbt) { + super.loadClient(nbt); label = nbt.getStringOr(NBT_LABEL, null); - brain.readDescription(nbt, registries); + brain.readDescription(nbt); } // Privates diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java index fa4f79804..b41ba31a8 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java @@ -23,17 +23,15 @@ import dan200.computercraft.shared.container.InventoryDelegate; import dan200.computercraft.shared.turtle.blocks.TurtleBlockEntity; import dan200.computercraft.shared.util.BlockEntityHelpers; import dan200.computercraft.shared.util.Holiday; -import dan200.computercraft.shared.util.NBTUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Holder; -import net.minecraft.core.HolderLookup; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.FluidTags; +import net.minecraft.util.ExtraCodecs; import net.minecraft.world.Container; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.MoverType; @@ -41,11 +39,16 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.jspecify.annotations.Nullable; -import java.util.*; +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Objects; +import java.util.Queue; import java.util.concurrent.TimeUnit; import static dan200.computercraft.shared.util.WaterloggableHelpers.WATERLOGGED; @@ -127,67 +130,50 @@ public class TurtleBrain implements TurtleAccessInternal { /** * Read common data for saving and client synchronisation. * - * @param nbt The tag to read from - * @param registries The current registries. + * @param nbt The tag to read from */ - private void readCommon(CompoundTag nbt, HolderLookup.Provider registries) { + private void readCommon(ValueInput nbt) { // Read fields colourHex = nbt.getIntOr(NBT_COLOUR, -1); fuelLevel = nbt.getIntOr(NBT_FUEL, 0); - overlay = nbt.contains(NBT_OVERLAY) ? NBTUtil.decodeFrom(ResourceLocation.CODEC, registries, nbt, NBT_OVERLAY) : null; + overlay = nbt.read(NBT_OVERLAY, ResourceLocation.CODEC).orElse(null); // Read upgrades - setUpgradeDirect(TurtleSide.LEFT, NBTUtil.decodeFrom(TurtleUpgrades.instance().upgradeDataCodec(), registries, nbt, NBT_LEFT_UPGRADE)); - setUpgradeDirect(TurtleSide.RIGHT, NBTUtil.decodeFrom(TurtleUpgrades.instance().upgradeDataCodec(), registries, nbt, NBT_RIGHT_UPGRADE)); + setUpgradeDirect(TurtleSide.LEFT, nbt.read(NBT_LEFT_UPGRADE, TurtleUpgrades.instance().upgradeDataCodec()).orElse(null)); + setUpgradeDirect(TurtleSide.RIGHT, nbt.read(NBT_RIGHT_UPGRADE, TurtleUpgrades.instance().upgradeDataCodec()).orElse(null)); } - private void writeCommon(CompoundTag nbt, HolderLookup.Provider registries) { + private void writeCommon(ValueOutput nbt) { nbt.putInt(NBT_FUEL, fuelLevel); if (colourHex != -1) nbt.putInt(NBT_COLOUR, colourHex); - NBTUtil.encodeTo(ResourceLocation.CODEC, registries, nbt, NBT_OVERLAY, overlay); + nbt.storeNullable(NBT_OVERLAY, ResourceLocation.CODEC, overlay); // Write upgrades - NBTUtil.encodeTo(TurtleUpgrades.instance().upgradeDataCodec(), registries, nbt, NBT_LEFT_UPGRADE, getUpgradeWithData(TurtleSide.LEFT)); - NBTUtil.encodeTo(TurtleUpgrades.instance().upgradeDataCodec(), registries, nbt, NBT_RIGHT_UPGRADE, getUpgradeWithData(TurtleSide.RIGHT)); + nbt.storeNullable(NBT_LEFT_UPGRADE, TurtleUpgrades.instance().upgradeDataCodec(), getUpgradeWithData(TurtleSide.LEFT)); + nbt.storeNullable(NBT_RIGHT_UPGRADE, TurtleUpgrades.instance().upgradeDataCodec(), getUpgradeWithData(TurtleSide.RIGHT)); } - public void readFromNBT(CompoundTag nbt, HolderLookup.Provider registries) { - readCommon(nbt, registries); + public void readFromNBT(ValueInput nbt) { + readCommon(nbt); // Read state selectedSlot = nbt.getIntOr(NBT_SLOT, 0); // Read owner - var owner = nbt.getCompound("Owner").orElse(null); - if (owner != null) { - owningPlayer = new GameProfile( - new UUID(owner.getLongOr("UpperId", 0), owner.getLongOr("LowerId", 0)), - owner.getStringOr("Name", "") - ); - } else { - owningPlayer = null; - } + owningPlayer = nbt.read("Owner", ExtraCodecs.GAME_PROFILE).orElse(null); } - public void writeToNBT(CompoundTag nbt, HolderLookup.Provider registries) { - writeCommon(nbt, registries); + public void writeToNBT(ValueOutput nbt) { + writeCommon(nbt); // Write state nbt.putInt(NBT_SLOT, selectedSlot); - - // Write owner - if (owningPlayer != null) { - var owner = new CompoundTag(); - nbt.put("Owner", owner); - - owner.putLong("UpperId", owningPlayer.getId().getMostSignificantBits()); - owner.putLong("LowerId", owningPlayer.getId().getLeastSignificantBits()); - owner.putString("Name", owningPlayer.getName()); - } + nbt.storeNullable("Owner", ExtraCodecs.GAME_PROFILE, owningPlayer); + // TODO(1.21.6): Data fixer for this. } - public void readDescription(CompoundTag nbt, HolderLookup.Provider registries) { - readCommon(nbt, registries); + public void readDescription(ValueInput nbt) { + readCommon(nbt); // Animation var anim = TurtleAnimation.values()[nbt.getIntOr("Animation", 0)]; @@ -201,8 +187,8 @@ public class TurtleBrain implements TurtleAccessInternal { } } - public void writeDescription(CompoundTag nbt, HolderLookup.Provider registries) { - writeCommon(nbt, registries); + public void writeDescription(ValueOutput nbt) { + writeCommon(nbt); nbt.putInt("Animation", animation.ordinal()); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java index 764045849..9a6fee152 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java @@ -214,7 +214,7 @@ public class TurtleTool extends AbstractTurtleUpgrade { var baseDamage = (float) player.getAttributeValue(Attributes.ATTACK_DAMAGE) * spec.damageMultiplier(); var tool = player.getWeaponItem(); var source = player.damageSources().playerAttack(player); - var bonusDamage = EnchantmentHelper.modifyDamage(player.serverLevel(), tool, entity, source, baseDamage) - baseDamage; + var bonusDamage = EnchantmentHelper.modifyDamage(player.level(), tool, entity, source, baseDamage) - baseDamage; // If this is a projectile, attempt to deflect it instead. if (entity.getType().is(EntityTypeTags.REDIRECTABLE_PROJECTILE) && entity instanceof Projectile projectile && @@ -229,13 +229,13 @@ public class TurtleTool extends AbstractTurtleUpgrade { // Compute the total damage, and deal it out. var damage = baseDamage + bonusDamage + tool.getItem().getAttackDamageBonus(entity, baseDamage, source); - if (!entity.hurtServer(player.serverLevel(), source, damage)) return false; + if (!entity.hurtServer(player.level(), source, damage)) return false; // Special case for armor stands: attack twice to guarantee destroy - if (entity.isAlive() && entity instanceof ArmorStand) entity.hurtServer(player.serverLevel(), source, damage); + if (entity.isAlive() && entity instanceof ArmorStand) entity.hurtServer(player.level(), source, damage); // Apply knockback - var knockBack = EnchantmentHelper.modifyKnockback(player.serverLevel(), tool, entity, source, (float) player.getAttributeValue(Attributes.ATTACK_KNOCKBACK)); + var knockBack = EnchantmentHelper.modifyKnockback(player.level(), tool, entity, source, (float) player.getAttributeValue(Attributes.ATTACK_KNOCKBACK)); if (knockBack > 0) { if (entity instanceof LivingEntity target) { target.knockback(knockBack * 0.5, -direction.getStepX(), -direction.getStepZ()); @@ -253,7 +253,7 @@ public class TurtleTool extends AbstractTurtleUpgrade { var didHurt = entity instanceof LivingEntity target && tool.hurtEnemy(target, player); // Apply remaining enchantments - EnchantmentHelper.doPostAttackEffects(player.serverLevel(), entity, source); + EnchantmentHelper.doPostAttackEffects(player.level(), entity, source); // Damage the original item stack. if (!tool.isEmpty() && entity instanceof LivingEntity living && didHurt) { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/NBTUtil.java b/projects/common/src/main/java/dan200/computercraft/shared/util/NBTUtil.java index 911079319..86b4bc62c 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/NBTUtil.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/NBTUtil.java @@ -6,9 +6,7 @@ package dan200.computercraft.shared.util; import com.google.common.annotations.VisibleForTesting; import com.google.common.io.BaseEncoding; -import com.mojang.serialization.Codec; import dan200.computercraft.core.util.Nullability; -import net.minecraft.core.HolderLookup; import net.minecraft.nbt.*; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; @@ -30,14 +28,6 @@ public final class NBTUtil { private NBTUtil() { } - public static @Nullable T decodeFrom(Codec codec, HolderLookup.Provider registries, CompoundTag tag, String key) { - return tag.read(key, codec, registries.createSerializationContext(NbtOps.INSTANCE)).orElse(null); - } - - public static void encodeTo(Codec codec, HolderLookup.Provider registries, CompoundTag destination, String key, @Nullable T value) { - destination.storeNullable(key, codec, registries.createSerializationContext(NbtOps.INSTANCE), value); - } - public static @Nullable Object toLua(@Nullable Tag tag) { if (tag == null) return null; diff --git a/projects/common/src/main/resources/computercraft-common.accesswidener b/projects/common/src/main/resources/computercraft-common.accesswidener index f87364ba0..6eb85376b 100644 --- a/projects/common/src/main/resources/computercraft-common.accesswidener +++ b/projects/common/src/main/resources/computercraft-common.accesswidener @@ -36,3 +36,8 @@ accessible method net/minecraft/client/data/models/ItemModelGenerators generateF accessible method net/minecraft/client/data/models/ItemModelGenerators generateFlatItem (Lnet/minecraft/world/item/Item;Lnet/minecraft/client/data/models/model/ModelTemplate;)V accessible method net/minecraft/client/data/models/model/TextureSlot create (Ljava/lang/String;)Lnet/minecraft/client/data/models/model/TextureSlot; accessible method net/minecraft/data/recipes/RecipeProvider inventoryTrigger ([Lnet/minecraft/advancements/critereon/ItemPredicate;)Lnet/minecraft/advancements/Criterion; + +# GUI elements +accessible class net/minecraft/client/gui/GuiGraphics$ScissorStack +accessible field net/minecraft/client/gui/GuiGraphics guiRenderState Lnet/minecraft/client/gui/render/state/GuiRenderState; +accessible field net/minecraft/client/gui/GuiGraphics scissorStack Lnet/minecraft/client/gui/GuiGraphics$ScissorStack; diff --git a/projects/common/src/main/resources/computercraft.accesswidener b/projects/common/src/main/resources/computercraft.accesswidener index b61fcc967..0c13ce330 100644 --- a/projects/common/src/main/resources/computercraft.accesswidener +++ b/projects/common/src/main/resources/computercraft.accesswidener @@ -27,6 +27,12 @@ accessible field net/minecraft/client/sounds/SoundEngine executor Lnet/minecraft # Turtle model accessible class net/minecraft/util/datafix/fixes/ItemStackComponentizationFix$ItemStackData +# GUI elements +accessible field net/minecraft/client/gui/GuiGraphics minecraft Lnet/minecraft/client/Minecraft; + +# Fog +accessible field net/minecraft/client/renderer/GameRenderer fogRenderer Lnet/minecraft/client/renderer/fog/FogRenderer; + # TODO(1.21.5): Add these to Fabric. accessible field net/minecraft/client/data/models/BlockModelGenerators ROTATION_FACING Lnet/minecraft/client/data/models/blockstates/PropertyDispatch; accessible field net/minecraft/client/data/models/BlockModelGenerators ROTATION_HORIZONTAL_FACING Lnet/minecraft/client/data/models/blockstates/PropertyDispatch; diff --git a/projects/common/src/test/java/dan200/computercraft/shared/computer/terminal/NetworkedTerminalTest.java b/projects/common/src/test/java/dan200/computercraft/shared/computer/terminal/NetworkedTerminalTest.java index 36bf9a5bd..fb499076b 100644 --- a/projects/common/src/test/java/dan200/computercraft/shared/computer/terminal/NetworkedTerminalTest.java +++ b/projects/common/src/test/java/dan200/computercraft/shared/computer/terminal/NetworkedTerminalTest.java @@ -7,7 +7,7 @@ package dan200.computercraft.shared.computer.terminal; import dan200.computercraft.api.lua.LuaValues; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.test.core.CallCounter; -import net.minecraft.nbt.CompoundTag; +import dan200.computercraft.test.shared.SerialisationUtils; import org.junit.jupiter.api.Test; import static dan200.computercraft.test.core.terminal.TerminalMatchers.*; @@ -24,13 +24,12 @@ class NetworkedTerminalTest { writeTerminal.setTextColour(3); writeTerminal.setBackgroundColour(5); - var nbt = new CompoundTag(); - writeTerminal.writeToNBT(nbt); + var nbt = SerialisationUtils.writeNBT(writeTerminal::writeToNBT); var callCounter = new CallCounter(); var readTerminal = new NetworkedTerminal(2, 1, true, callCounter); - readTerminal.readFromNBT(nbt); + SerialisationUtils.readNBT(nbt, readTerminal::readFromNBT); assertThat(readTerminal, allOf( textMatches(new String[]{ "hi", }), @@ -49,12 +48,11 @@ class NetworkedTerminalTest { void testReadWriteNBTEmpty() { var terminal = new NetworkedTerminal(0, 0, true); - var nbt = new CompoundTag(); - terminal.writeToNBT(nbt); + var nbt = SerialisationUtils.writeNBT(terminal::writeToNBT); var callCounter = new CallCounter(); terminal = new NetworkedTerminal(0, 1, true, callCounter); - terminal.readFromNBT(nbt); + SerialisationUtils.readNBT(nbt, terminal::readFromNBT); assertThat(terminal, allOf( textMatches(new String[]{ "", }), diff --git a/projects/common/src/testFixtures/java/dan200/computercraft/test/shared/SerialisationUtils.java b/projects/common/src/testFixtures/java/dan200/computercraft/test/shared/SerialisationUtils.java new file mode 100644 index 000000000..87f898ce0 --- /dev/null +++ b/projects/common/src/testFixtures/java/dan200/computercraft/test/shared/SerialisationUtils.java @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2025 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.test.shared; + +import net.minecraft.core.RegistryAccess; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.ProblemReporter; +import net.minecraft.world.level.storage.TagValueInput; +import net.minecraft.world.level.storage.TagValueOutput; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; + +import java.util.function.Consumer; + +/*** + * Helpers for serialising and unserialising values. + */ +public final class SerialisationUtils { + private SerialisationUtils() { + } + + public static CompoundTag writeNBT(Consumer generate) { + var output = TagValueOutput.createWithoutContext(ProblemReporter.DISCARDING); + generate.accept(output); + return output.buildResult(); + } + + public static void readNBT(CompoundTag tag, Consumer generate) { + generate.accept(TagValueInput.create(ProblemReporter.DISCARDING, RegistryAccess.EMPTY, tag)); + } +} diff --git a/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java b/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java index cbf9e0dda..f27528ba8 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java +++ b/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java @@ -16,12 +16,9 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.gametest.core.TestHooks; import dan200.computercraft.shared.util.PrettyJsonWriter; -import dan200.computercraft.shared.util.RegistryHelper; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.item.crafting.display.ShapedCraftingRecipeDisplay; import net.minecraft.world.item.crafting.display.ShapelessCraftingRecipeDisplay; @@ -60,8 +57,8 @@ public class Exporter { } RenderSystem.assertOnRenderThread(); - try (var renderer = new ImageRenderer()) { - export(output, renderer); + try { + export(output); } catch (IOException e) { throw new UncheckedIOException(e); } @@ -69,7 +66,7 @@ public class Exporter { Minecraft.getInstance().gui.getChat().addMessage(Component.literal("Export finished!")); } - private static void export(Path root, ImageRenderer renderer) throws IOException { + private static void export(Path root) throws IOException { var dump = new JsonDump(); // First find all CC items @@ -121,21 +118,6 @@ public class Exporter { var itemDir = root.resolve("items"); if (Files.exists(itemDir)) MoreFiles.deleteRecursively(itemDir, RecursiveDeleteOption.ALLOW_INSECURE); - for (var item : items) { - var stack = new ItemStack(item); - var location = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, item); - - dump.itemNames.put(location.toString(), stack.getHoverName().getString()); - renderer.captureRender(itemDir.resolve(location.getNamespace()).resolve(location.getPath() + ".png"), - () -> { - - var graphics = new GuiGraphics(Minecraft.getInstance(), Minecraft.getInstance().renderBuffers().bufferSource()); - graphics.renderItem(stack, 0, 0); - graphics.flush(); - } - ); - } - try (Writer writer = Files.newBufferedWriter(root.resolve("index.json")); var jsonWriter = new PrettyJsonWriter(writer)) { GSON.toJson(dump, JsonDump.class, jsonWriter); } diff --git a/projects/common/src/testMod/java/dan200/computercraft/export/ImageRenderer.java b/projects/common/src/testMod/java/dan200/computercraft/export/ImageRenderer.java deleted file mode 100644 index 38afead7d..000000000 --- a/projects/common/src/testMod/java/dan200/computercraft/export/ImageRenderer.java +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.export; - -import com.mojang.blaze3d.ProjectionType; -import com.mojang.blaze3d.pipeline.TextureTarget; -import com.mojang.blaze3d.platform.NativeImage; -import com.mojang.blaze3d.systems.RenderSystem; -import org.joml.Matrix4f; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; - -/** - * Utilities for saving OpenGL output to an image rather than displaying it on the screen. - */ -public class ImageRenderer implements AutoCloseable { - public static final int WIDTH = 64; - public static final int HEIGHT = 64; - - private final TextureTarget framebuffer = new TextureTarget("Export", WIDTH, HEIGHT, true); - private final NativeImage image = new NativeImage(WIDTH, HEIGHT, true); - - public ImageRenderer() { - // framebuffer.setFilterMode(0, 0, 0, 0); - // framebuffer.clear(); - } - - public void captureRender(Path output, Runnable render) throws IOException { - Files.createDirectories(output.getParent()); - - // RenderSystem.clear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); - // framebuffer.bindWrite(true); - - // Setup rendering state - RenderSystem.backupProjectionMatrix(); - RenderSystem.setProjectionMatrix(new Matrix4f().identity().ortho(0, 16, 16, 0, 1000, 3000), ProjectionType.ORTHOGRAPHIC); - - var transform = RenderSystem.getModelViewStack(); - transform.pushMatrix(); - transform.identity(); - transform.translate(0.0f, 0.0f, -2000.0f); - - // Render - render.run(); - - // Restore rendering state - RenderSystem.restoreProjectionMatrix(); - transform.popMatrix(); - - // framebuffer.unbindWrite(); - // Minecraft.getInstance().getMainRenderTarget().bindWrite(true); - - // And save the image - // framebuffer.bindRead(); - // image.downloadTexture(0, false); - // image.flipY(); - // framebuffer.unbindRead(); - - image.writeToFile(output); - } - - @Override - public void close() { - image.close(); - framebuffer.destroyBuffers(); - } -} diff --git a/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java b/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java index 480503e65..fffc4bf88 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java +++ b/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java @@ -6,6 +6,7 @@ package dan200.computercraft.gametest.core; import com.mojang.brigadier.CommandDispatcher; import dan200.computercraft.api.ComputerCraftAPI; +import dan200.computercraft.mixin.gametest.ArmorStandAccessor; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.util.NonNegativeId; import net.minecraft.ChatFormatting; @@ -42,7 +43,7 @@ class CCTestCommand { dispatcher.register(choice("cctest") .then(literal("marker").executes(context -> { var player = context.getSource().getPlayerOrException(); - var pos = StructureUtils.findNearestTest(player.blockPosition(), 15, player.serverLevel()).orElse(null); + var pos = StructureUtils.findNearestTest(player.blockPosition(), 15, player.level()).orElse(null); if (pos == null) return error(context.getSource(), "No nearby test"); var test = player.level().getBlockEntity(pos, BlockEntityType.TEST_INSTANCE_BLOCK) @@ -50,7 +51,7 @@ class CCTestCommand { if (test == null) return error(context.getSource(), "No nearby structure block"); // Kill the existing armor stand - var level = player.serverLevel(); + var level = player.level(); level.getEntities(EntityType.ARMOR_STAND, x -> x.isAlive() && x.getName().getString().equals(test.location().getPath())) .forEach(e -> e.kill(level)); @@ -59,7 +60,8 @@ class CCTestCommand { nbt.putBoolean("Marker", true); nbt.putBoolean("Invisible", true); var armorStand = new ArmorStand(EntityType.ARMOR_STAND, level); - armorStand.readAdditionalSaveData(nbt); + armorStand.setInvisible(true); + ((ArmorStandAccessor) armorStand).computercraft$setMarker(true); armorStand.copyPosition(player); armorStand.setCustomName(Component.literal(test.location().getPath())); level.addFreshEntity(armorStand); @@ -70,7 +72,7 @@ class CCTestCommand { var item = context.getArgument("item", ItemInput.class); var player = context.getSource().getPlayerOrException(); - var pos = StructureUtils.findNearestTest(player.blockPosition(), 15, player.serverLevel()).orElse(null); + var pos = StructureUtils.findNearestTest(player.blockPosition(), 15, player.level()).orElse(null); if (pos == null) return error(context.getSource(), "No nearby test"); var test = player.level().getBlockEntity(pos, BlockEntityType.TEST_INSTANCE_BLOCK) diff --git a/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/ArmorStandAccessor.java b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/ArmorStandAccessor.java new file mode 100644 index 000000000..e2a658b71 --- /dev/null +++ b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/ArmorStandAccessor.java @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2025 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.mixin.gametest; + +import net.minecraft.world.entity.decoration.ArmorStand; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(ArmorStand.class) +public interface ArmorStandAccessor { + @Invoker("setMarker") + void computercraft$setMarker(boolean marker); +} diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/ClientTestExtensions.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/ClientTestExtensions.kt index fd024cde9..15597948a 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/ClientTestExtensions.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/ClientTestExtensions.kt @@ -116,7 +116,7 @@ class ClientTestHelper { val minecraft: Minecraft = Minecraft.getInstance() fun screenshot(name: String, callback: () -> Unit = {}) { - Screenshot.grab(minecraft.gameDirectory, name, minecraft.mainRenderTarget) { callback() } + Screenshot.grab(minecraft.gameDirectory, name, minecraft.mainRenderTarget, 1) { callback() } } /** diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt index 7d9478e98..e760bb4c0 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt @@ -15,6 +15,7 @@ import net.minecraft.client.gui.screens.TitleScreen import net.minecraft.client.tutorial.TutorialSteps import net.minecraft.core.registries.Registries import net.minecraft.gametest.framework.* +import net.minecraft.network.chat.Component import net.minecraft.server.MinecraftServer import net.minecraft.server.level.ParticleStatus import net.minecraft.sounds.SoundSource @@ -196,8 +197,8 @@ object ClientTestHooks { val minecraft = Minecraft.getInstance() minecraft.execute { LOG.info("Stopping client.") - minecraft.level!!.disconnect() - minecraft.disconnect() + minecraft.level!!.disconnect(Component.empty()) + minecraft.disconnectWithSavingScreen() minecraft.stop() exitProcess( diff --git a/projects/common/src/testMod/resources/computercraft-gametest.mixins.json b/projects/common/src/testMod/resources/computercraft-gametest.mixins.json index dc6f7cb5d..7077f2e1f 100644 --- a/projects/common/src/testMod/resources/computercraft-gametest.mixins.json +++ b/projects/common/src/testMod/resources/computercraft-gametest.mixins.json @@ -7,6 +7,7 @@ "defaultRequire": 1 }, "mixins": [ + "ArmorStandAccessor", "GameTestHelperAccessor", "GameTestInfoAccessor", "GameTestSequenceAccessor", diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java index d72952e95..e8ca4909e 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java @@ -19,20 +19,21 @@ import dan200.computercraft.shared.config.ConfigSpec; import dan200.computercraft.shared.network.NetworkMessages; import dan200.computercraft.shared.network.client.ClientNetworkContext; import dan200.computercraft.shared.platform.FabricConfigFile; -import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin; import net.fabricmc.fabric.api.client.model.loading.v1.UnbakedExtraModel; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.client.rendering.v1.BlockRenderLayerMap; +import net.fabricmc.fabric.api.client.rendering.v1.SpecialGuiElementRegistry; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.color.item.ItemTintSources; import net.minecraft.client.gui.screens.MenuScreens; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; import net.minecraft.client.renderer.item.ItemModels; import net.minecraft.client.renderer.item.properties.conditional.ConditionalItemModelProperties; import net.minecraft.client.renderer.item.properties.select.SelectItemModelProperties; @@ -74,11 +75,13 @@ public class ComputerCraftClient { }, state) ); - BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.COMPUTER_NORMAL.get(), RenderType.cutout()); - BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.COMPUTER_COMMAND.get(), RenderType.cutout()); - BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.COMPUTER_ADVANCED.get(), RenderType.cutout()); - BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.MONITOR_NORMAL.get(), RenderType.cutout()); - BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.MONITOR_ADVANCED.get(), RenderType.cutout()); + BlockRenderLayerMap.putBlock(ModRegistry.Blocks.COMPUTER_NORMAL.get(), ChunkSectionLayer.CUTOUT); + BlockRenderLayerMap.putBlock(ModRegistry.Blocks.COMPUTER_COMMAND.get(), ChunkSectionLayer.CUTOUT); + BlockRenderLayerMap.putBlock(ModRegistry.Blocks.COMPUTER_ADVANCED.get(), ChunkSectionLayer.CUTOUT); + BlockRenderLayerMap.putBlock(ModRegistry.Blocks.MONITOR_NORMAL.get(), ChunkSectionLayer.CUTOUT); + BlockRenderLayerMap.putBlock(ModRegistry.Blocks.MONITOR_ADVANCED.get(), ChunkSectionLayer.CUTOUT); + + ClientRegistry.registerPictureInPictureRenderers(f -> SpecialGuiElementRegistry.register(c -> f.apply(c.vertexConsumers()))); ClientTickEvents.START_CLIENT_TICK.register(client -> ClientHooks.onTick()); // This isn't 100% consistent with Forge, but not worth a mixin. diff --git a/projects/fabric/src/client/java/dan200/computercraft/mixin/client/SoundEngineMixin.java b/projects/fabric/src/client/java/dan200/computercraft/mixin/client/SoundEngineMixin.java index b1d079e8f..4d41acbb6 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/mixin/client/SoundEngineMixin.java +++ b/projects/fabric/src/client/java/dan200/computercraft/mixin/client/SoundEngineMixin.java @@ -15,6 +15,7 @@ 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; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import static dan200.computercraft.core.util.Nullability.assertNonNull; @@ -26,7 +27,7 @@ class SoundEngineMixin { @Inject(method = "play", at = @At(value = "HEAD")) @SuppressWarnings("unused") - private void playSound(SoundInstance sound, CallbackInfo ci) { + private void playSound(SoundInstance sound, CallbackInfoReturnable ci) { self = (SoundEngine) (Object) this; } diff --git a/projects/fabric/src/datagen/java/dan200/computercraft/data/FabricDataProviders.java b/projects/fabric/src/datagen/java/dan200/computercraft/data/FabricDataProviders.java index 918677e07..922fdb0b6 100644 --- a/projects/fabric/src/datagen/java/dan200/computercraft/data/FabricDataProviders.java +++ b/projects/fabric/src/datagen/java/dan200/computercraft/data/FabricDataProviders.java @@ -18,12 +18,10 @@ import net.minecraft.client.data.models.ItemModelGenerators; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; import net.minecraft.core.RegistrySetBuilder; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.DataProvider; import net.minecraft.data.PackOutput; import net.minecraft.data.tags.TagsProvider; import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; @@ -74,28 +72,17 @@ public class FabricDataProviders implements DataGeneratorEntrypoint { return addWithRegistries((out, registries) -> new FabricTagProvider.BlockTagProvider(out, registries) { @Override protected void addTags(HolderLookup.Provider registries) { - tags.accept(x -> new TagProvider.TagAppender<>(BuiltInRegistries.BLOCK, getOrCreateRawBuilder(x))); + tags.accept(this::valueLookupBuilder); } }); } @Override - public TagsProvider itemTags(Consumer tags, TagsProvider blocks) { - return addWithRegistries((out, registries) -> new FabricTagProvider.ItemTagProvider(out, registries, (FabricTagProvider.BlockTagProvider) blocks) { + public TagsProvider itemTags(Consumer> tags) { + return addWithRegistries((out, registries) -> new FabricTagProvider.ItemTagProvider(out, registries) { @Override protected void addTags(HolderLookup.Provider registries) { - var self = this; - tags.accept(new TagProvider.ItemTagConsumer() { - @Override - public TagProvider.TagAppender tag(TagKey tag) { - return new TagProvider.TagAppender<>(BuiltInRegistries.ITEM, getOrCreateRawBuilder(tag)); - } - - @Override - public void copy(TagKey block, TagKey item) { - self.copy(block, item); - } - }); + tags.accept(this::valueLookupBuilder); } }); } diff --git a/projects/fabric/src/main/java/dan200/computercraft/mixin/EntityMixin.java b/projects/fabric/src/main/java/dan200/computercraft/mixin/EntityMixin.java index be503bbf6..6f0fb54e0 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/mixin/EntityMixin.java +++ b/projects/fabric/src/main/java/dan200/computercraft/mixin/EntityMixin.java @@ -9,6 +9,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -17,12 +18,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Entity.class) class EntityMixin { @Inject( - method = "spawnAtLocation(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;F)Lnet/minecraft/world/entity/item/ItemEntity;", + method = "spawnAtLocation(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/entity/item/ItemEntity;", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"), cancellable = true ) @SuppressWarnings("unused") - private void spawnAtLocation(ServerLevel level, ItemStack stack, float yOffset, CallbackInfoReturnable cb) { + private void spawnAtLocation(ServerLevel level, ItemStack stack, Vec3 position, CallbackInfoReturnable cb) { if (CommonHooks.onLivingDrop((Entity) (Object) this, stack)) cb.setReturnValue(null); } } diff --git a/projects/fabric/src/main/resources/fabric.mod.json b/projects/fabric/src/main/resources/fabric.mod.json index 7a2ae64d1..757c95745 100644 --- a/projects/fabric/src/main/resources/fabric.mod.json +++ b/projects/fabric/src/main/resources/fabric.mod.json @@ -49,9 +49,9 @@ } ], "depends": { - "fabricloader": ">=0.16.10", - "fabric-api": ">=0.122.0", - "minecraft": "=1.21.5" + "fabricloader": ">=0.16.14", + "fabric-api": ">=0.127.0", + "minecraft": "=1.21.6" }, "accessWidener": "computercraft.accesswidener" } diff --git a/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientRegistry.java b/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientRegistry.java index 6a6bd2fde..43df90c8b 100644 --- a/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientRegistry.java +++ b/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientRegistry.java @@ -96,6 +96,11 @@ public final class ForgeClientRegistry { }); } + @SubscribeEvent + public static void registerPictureInPictureRenderers(RegisterPictureInPictureRenderersEvent event) { + ClientRegistry.registerPictureInPictureRenderers(event::register); + } + @SubscribeEvent public static void setupClient(FMLClientSetupEvent event) { ClientRegistry.register(); diff --git a/projects/forge/src/datagen/java/dan200/computercraft/data/ForgeDataProviders.java b/projects/forge/src/datagen/java/dan200/computercraft/data/ForgeDataProviders.java index eba6ca10e..839e72807 100644 --- a/projects/forge/src/datagen/java/dan200/computercraft/data/ForgeDataProviders.java +++ b/projects/forge/src/datagen/java/dan200/computercraft/data/ForgeDataProviders.java @@ -11,20 +11,18 @@ import net.minecraft.client.data.models.ItemModelGenerators; import net.minecraft.client.data.models.ModelProvider; import net.minecraft.core.HolderLookup; import net.minecraft.core.RegistrySetBuilder; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.DataGenerator; import net.minecraft.data.DataProvider; import net.minecraft.data.PackOutput; -import net.minecraft.data.tags.ItemTagsProvider; import net.minecraft.data.tags.TagsProvider; import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.common.data.BlockTagsProvider; import net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider; +import net.neoforged.neoforge.common.data.ItemTagsProvider; import net.neoforged.neoforge.common.data.JsonCodecProvider; import net.neoforged.neoforge.data.event.GatherDataEvent; @@ -65,28 +63,17 @@ public class ForgeDataProviders { return add(out -> new BlockTagsProvider(out, registries, ComputerCraftAPI.MOD_ID) { @Override protected void addTags(HolderLookup.Provider registries) { - tags.accept(x -> new TagProvider.TagAppender<>(BuiltInRegistries.BLOCK, getOrCreateRawBuilder(x))); + tags.accept(this::tag); } }); } @Override - public TagsProvider itemTags(Consumer tags, TagsProvider blocks) { - return add(out -> new ItemTagsProvider(out, registries, blocks.contentsGetter(), ComputerCraftAPI.MOD_ID) { + public TagsProvider itemTags(Consumer> tags) { + return add(out -> new ItemTagsProvider(out, registries, ComputerCraftAPI.MOD_ID) { @Override protected void addTags(HolderLookup.Provider registries) { - var self = this; - tags.accept(new TagProvider.ItemTagConsumer() { - @Override - public TagProvider.TagAppender tag(TagKey tag) { - return new TagProvider.TagAppender<>(BuiltInRegistries.ITEM, getOrCreateRawBuilder(tag)); - } - - @Override - public void copy(TagKey block, TagKey item) { - self.copy(block, item); - } - }); + tags.accept(this::tag); } }); } diff --git a/projects/forge/src/main/resources/META-INF/accesstransformer.cfg b/projects/forge/src/main/resources/META-INF/accesstransformer.cfg index 240a3ab71..d485d56db 100644 --- a/projects/forge/src/main/resources/META-INF/accesstransformer.cfg +++ b/projects/forge/src/main/resources/META-INF/accesstransformer.cfg @@ -15,3 +15,12 @@ public com.mojang.blaze3d.audio.Channel pumpBuffers(I)V public net.minecraft.client.sounds.SoundEngine executor public net.minecraft.util.datafix.fixes.ItemStackComponentizationFix$ItemStackData + +# GUI elements +public net.minecraft.client.gui.GuiGraphics$ScissorStack +public net.minecraft.client.gui.GuiGraphics guiRenderState +public net.minecraft.client.gui.GuiGraphics scissorStack +public net.minecraft.client.gui.GuiGraphics minecraft + +# Fog +public net.minecraft.client.renderer.GameRenderer fogRenderer diff --git a/projects/forge/src/main/resources/META-INF/neoforge.mods.toml b/projects/forge/src/main/resources/META-INF/neoforge.mods.toml index 2bb0827d4..178e5328c 100644 --- a/projects/forge/src/main/resources/META-INF/neoforge.mods.toml +++ b/projects/forge/src/main/resources/META-INF/neoforge.mods.toml @@ -26,7 +26,7 @@ CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles a [[dependencies.computercraft]] modId="neoforge" type="required" - versionRange="[${neoVersion},21.6)" + versionRange="[${neoVersion},21.7)" ordering="NONE" side="BOTH"