mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-09-02 18:37:55 +00:00
Update to Minecraft 1.26.1
Still one TODO left, but around data fixers, so fairly small.
- GUI rendering got a big overhaul. I avoided the worst of it with
9272e2efcd
, but things like terminals
and printouts still require some custom rendering.
- Item models are now de-duplicated when rendering in the UI, so we
need to keep track of their identity with
(appendModelidentityElement). I'm not sure I've got this entirely
right — whole thing feels unfortunately error-prone.
- BE serialisation now goes through a Value{Input,Output} class, rather
than using NBT directly. Fairly simple change, but has changed the
format of the GameProfile used in turtle's owners. Need a DFU patch
for this.
This commit is contained in:
@@ -15,4 +15,4 @@ isUnstable=true
|
|||||||
modVersion=1.115.1
|
modVersion=1.115.1
|
||||||
|
|
||||||
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
||||||
mcVersion=1.21.5
|
mcVersion=1.21.6
|
||||||
|
@@ -7,9 +7,9 @@
|
|||||||
# Minecraft
|
# Minecraft
|
||||||
# MC version is specified in gradle.properties, as we need that in settings.gradle.
|
# 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
|
# Remember to update corresponding versions in fabric.mod.json/neoforge.mods.toml
|
||||||
fabric-api = "0.122.0+1.21.5"
|
fabric-api = "0.127.0+1.21.6"
|
||||||
fabric-loader = "0.16.10"
|
fabric-loader = "0.16.14"
|
||||||
neoForge = "21.5.49-beta"
|
neoForge = "21.6.0-beta"
|
||||||
neoMergeTool = "2.0.0"
|
neoMergeTool = "2.0.0"
|
||||||
mixin = "0.8.5"
|
mixin = "0.8.5"
|
||||||
parchment = "2025.04.19"
|
parchment = "2025.04.19"
|
||||||
@@ -69,7 +69,7 @@ ideaExt = "1.1.7"
|
|||||||
illuaminate = "0.1.0-83-g1131f68"
|
illuaminate = "0.1.0-83-g1131f68"
|
||||||
lwjgl = "3.3.3"
|
lwjgl = "3.3.3"
|
||||||
minotaur = "2.8.7"
|
minotaur = "2.8.7"
|
||||||
modDevGradle = "2.0.82"
|
modDevGradle = "2.0.95"
|
||||||
nullAway = "0.12.7"
|
nullAway = "0.12.7"
|
||||||
shadow = "8.3.1"
|
shadow = "8.3.1"
|
||||||
spotless = "7.0.2"
|
spotless = "7.0.2"
|
||||||
|
@@ -61,6 +61,10 @@ public final class BasicUpgradeModel implements TurtleUpgradeModel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderForItem(UpgradeData<ITurtleUpgrade> upgrade, TurtleSide side, ItemStackRenderState renderer, ItemModelResolver resolver, ItemTransform transform, int seed) {
|
public void renderForItem(UpgradeData<ITurtleUpgrade> upgrade, TurtleSide side, ItemStackRenderState renderer, ItemModelResolver resolver, ItemTransform transform, int seed) {
|
||||||
|
renderer.appendModelIdentityElement(this);
|
||||||
|
renderer.appendModelIdentityElement(side);
|
||||||
|
renderer.appendModelIdentityElement(transform);
|
||||||
|
|
||||||
var layer = renderer.newLayer();
|
var layer = renderer.newLayer();
|
||||||
layer.setTransform(transform);
|
layer.setTransform(transform);
|
||||||
getModel(side).setupItemLayer(layer);
|
getModel(side).setupItemLayer(layer);
|
||||||
|
@@ -26,8 +26,11 @@ import net.minecraft.util.Mth;
|
|||||||
import net.minecraft.world.item.ItemDisplayContext;
|
import net.minecraft.world.item.ItemDisplayContext;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Vector3f;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A sic {@link TurtleUpgradeModel} that renders the upgrade's {@linkplain ITurtleUpgrade#getUpgradeItem(DataComponentPatch)
|
* A sic {@link TurtleUpgradeModel} that renders the upgrade's {@linkplain ITurtleUpgrade#getUpgradeItem(DataComponentPatch)
|
||||||
* upgrade item}.
|
* upgrade item}.
|
||||||
@@ -59,9 +62,14 @@ public final class ItemUpgradeModel implements TurtleUpgradeModel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderForItem(UpgradeData<ITurtleUpgrade> upgrade, TurtleSide side, ItemStackRenderState renderer, ItemModelResolver resolver, ItemTransform transform, int seed) {
|
public void renderForItem(UpgradeData<ITurtleUpgrade> upgrade, TurtleSide side, ItemStackRenderState renderer, ItemModelResolver resolver, ItemTransform transform, int seed) {
|
||||||
|
renderer.appendModelIdentityElement(this);
|
||||||
|
|
||||||
var childState = new ItemStackRenderState();
|
var childState = new ItemStackRenderState();
|
||||||
resolver.updateForTopItem(childState, upgrade.getUpgradeItem(), ItemDisplayContext.NONE, null, null, seed);
|
resolver.updateForTopItem(childState, upgrade.getUpgradeItem(), ItemDisplayContext.NONE, null, null, seed);
|
||||||
if (!childState.isEmpty()) {
|
if (!childState.isEmpty()) {
|
||||||
|
renderer.appendModelIdentityElement(childState.getModelIdentity());
|
||||||
|
renderer.appendModelIdentityElement(transform);
|
||||||
|
|
||||||
var layer = renderer.newLayer();
|
var layer = renderer.newLayer();
|
||||||
layer.setTransform(transform);
|
layer.setTransform(transform);
|
||||||
layer.setupSpecialModel(getRenderer(side), childState);
|
layer.setupSpecialModel(getRenderer(side), childState);
|
||||||
@@ -122,6 +130,10 @@ public final class ItemUpgradeModel implements TurtleUpgradeModel {
|
|||||||
poseStack.popPose();
|
poseStack.popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getExtents(Set<Vector3f> set) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable ItemStackRenderState extractArgument(ItemStack itemStack) {
|
public @Nullable ItemStackRenderState extractArgument(ItemStack itemStack) {
|
||||||
return null;
|
return null;
|
||||||
|
@@ -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.
|
* Render this upgrade to an {@link ItemStackRenderState}. This is used for rendering the item form of the upgrade.
|
||||||
|
* <p>
|
||||||
|
* Like with {@link ItemModel}, implementations must be careful to call {@link ItemStackRenderState#appendModelIdentityElement}
|
||||||
|
* where appropriate.
|
||||||
*
|
*
|
||||||
* @param upgrade The upgrade being rendered.
|
* @param upgrade The upgrade being rendered.
|
||||||
* @param side Which side of the turtle (left or right) the upgrade is equipped on.
|
* @param side Which side of the turtle (left or right) the upgrade is equipped on.
|
||||||
|
@@ -23,9 +23,11 @@ import dan200.computercraft.client.turtle.TurtleUpgradeModelManager;
|
|||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
||||||
import net.minecraft.client.color.item.ItemTintSource;
|
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.MenuScreens;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.client.gui.screens.inventory.MenuAccess;
|
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.BlockEntityRendererProvider;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
|
||||||
import net.minecraft.client.renderer.item.ItemModel;
|
import net.minecraft.client.renderer.item.ItemModel;
|
||||||
@@ -47,6 +49,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.BiFunction;
|
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
|
* Registers client-side objects, such as {@link BlockEntityRendererProvider}s and
|
||||||
@@ -188,4 +192,8 @@ public final class ClientRegistry {
|
|||||||
public static void registerConditionalItemProperties(BiConsumer<ResourceLocation, MapCodec<? extends ConditionalItemModelProperty>> register) {
|
public static void registerConditionalItemProperties(BiConsumer<ResourceLocation, MapCodec<? extends ConditionalItemModelProperty>> register) {
|
||||||
register.accept(TurtleShowElfOverlay.ID, TurtleShowElfOverlay.CODEC);
|
register.accept(TurtleShowElfOverlay.ID, TurtleShowElfOverlay.CODEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void registerPictureInPictureRenderers(Consumer<Function<MultiBufferSource.BufferSource, PictureInPictureRenderer<?>>> register) {
|
||||||
|
register.accept(PrintoutScreen.PrintoutPictureRenderer::new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@ import dan200.computercraft.client.gui.widgets.TerminalWidget;
|
|||||||
import dan200.computercraft.core.util.Nullability;
|
import dan200.computercraft.core.util.Nullability;
|
||||||
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
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.network.chat.Component;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
|
||||||
@@ -42,11 +42,12 @@ public final class ComputerScreen<T extends AbstractComputerMenu> extends Abstra
|
|||||||
var computerTextures = GuiSprites.getComputerTextures(family);
|
var computerTextures = GuiSprites.getComputerTextures(family);
|
||||||
|
|
||||||
graphics.blitSprite(
|
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
|
terminal.getX() - BORDER, terminal.getY() - BORDER, terminal.getWidth() + BORDER * 2, terminal.getHeight() + BORDER * 2
|
||||||
);
|
);
|
||||||
|
|
||||||
graphics.blitSprite(
|
graphics.blitSprite(
|
||||||
RenderType::guiTextured, Nullability.assertNonNull(computerTextures.sidebar()),
|
RenderPipelines.GUI_TEXTURED, Nullability.assertNonNull(computerTextures.sidebar()),
|
||||||
leftPos, topPos + sidebarYOffset, AbstractComputerMenu.SIDEBAR_WIDTH, ComputerSidebar.HEIGHT
|
leftPos, topPos + sidebarYOffset, AbstractComputerMenu.SIDEBAR_WIDTH, ComputerSidebar.HEIGHT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,7 @@ package dan200.computercraft.client.gui;
|
|||||||
import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveMenu;
|
import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveMenu;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
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.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
@@ -24,7 +24,7 @@ public class DiskDriveScreen extends AbstractContainerScreen<DiskDriveMenu> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
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
|
@Override
|
||||||
|
@@ -9,7 +9,7 @@ import net.minecraft.client.gui.Font;
|
|||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.components.toasts.Toast;
|
import net.minecraft.client.gui.components.toasts.Toast;
|
||||||
import net.minecraft.client.gui.components.toasts.ToastManager;
|
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.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.FormattedCharSequence;
|
import net.minecraft.util.FormattedCharSequence;
|
||||||
@@ -91,7 +91,7 @@ public class ItemToast implements Toast {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics graphics, Font font, long time) {
|
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;
|
var textX = MARGIN;
|
||||||
if (!stack.isEmpty()) {
|
if (!stack.isEmpty()) {
|
||||||
|
@@ -108,7 +108,7 @@ public class NoTermComputerScreen<T extends AbstractComputerMenu> extends Screen
|
|||||||
var lines = font.split(Component.translatable("gui.computercraft.pocket_computer_overlay"), (int) (width * 0.8));
|
var lines = font.split(Component.translatable("gui.computercraft.pocket_computer_overlay"), (int) (width * 0.8));
|
||||||
var y = 10;
|
var y = 10;
|
||||||
for (var line : lines) {
|
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;
|
y += 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,7 @@ import net.minecraft.client.gui.components.AbstractWidget;
|
|||||||
import net.minecraft.client.gui.components.Button;
|
import net.minecraft.client.gui.components.Button;
|
||||||
import net.minecraft.client.gui.components.MultiLineLabel;
|
import net.minecraft.client.gui.components.MultiLineLabel;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
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.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
@@ -88,13 +88,13 @@ public final class OptionScreen extends Screen {
|
|||||||
@Override
|
@Override
|
||||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
// Render the actual texture.
|
// Render the actual texture.
|
||||||
graphics.blit(RenderType::guiTextured, BACKGROUND, x, y, 0, 0, innerWidth, PADDING, 256, 256);
|
graphics.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND, x, y, 0, 0, innerWidth, PADDING, 256, 256);
|
||||||
graphics.blit(RenderType::guiTextured, BACKGROUND,
|
graphics.blit(RenderPipelines.GUI_TEXTURED, BACKGROUND,
|
||||||
x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2,
|
x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2,
|
||||||
innerWidth, PADDING,
|
innerWidth, PADDING,
|
||||||
256, 256
|
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);
|
assertNonNull(messageRenderer).renderLeftAlignedNoShadow(graphics, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040);
|
||||||
super.render(graphics, mouseX, mouseY, partialTicks);
|
super.render(graphics, mouseX, mouseY, partialTicks);
|
||||||
|
@@ -7,7 +7,7 @@ package dan200.computercraft.client.gui;
|
|||||||
import dan200.computercraft.shared.peripheral.printer.PrinterMenu;
|
import dan200.computercraft.shared.peripheral.printer.PrinterMenu;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
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.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
@@ -24,10 +24,10 @@ public class PrinterScreen extends AbstractContainerScreen<PrinterMenu> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
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()) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,18 +4,27 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui;
|
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.core.terminal.TextBuffer;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.media.PrintoutMenu;
|
import dan200.computercraft.shared.media.PrintoutMenu;
|
||||||
import dan200.computercraft.shared.media.items.PrintoutData;
|
import dan200.computercraft.shared.media.items.PrintoutData;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
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.gui.screens.inventory.AbstractContainerScreen;
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
import net.minecraft.world.inventory.ContainerListener;
|
import net.minecraft.world.inventory.ContainerListener;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.joml.Matrix3x2f;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -25,7 +34,7 @@ import static dan200.computercraft.client.render.PrintoutRenderer.*;
|
|||||||
/**
|
/**
|
||||||
* The GUI for printed pages and books.
|
* The GUI for printed pages and books.
|
||||||
*
|
*
|
||||||
* @see dan200.computercraft.client.render.PrintoutRenderer
|
* @see PrintoutRenderer
|
||||||
*/
|
*/
|
||||||
public final class PrintoutScreen extends AbstractContainerScreen<PrintoutMenu> implements ContainerListener {
|
public final class PrintoutScreen extends AbstractContainerScreen<PrintoutMenu> implements ContainerListener {
|
||||||
private PrintoutInfo printout = PrintoutInfo.DEFAULT;
|
private PrintoutInfo printout = PrintoutInfo.DEFAULT;
|
||||||
@@ -113,15 +122,11 @@ public final class PrintoutScreen extends AbstractContainerScreen<PrintoutMenu>
|
|||||||
@Override
|
@Override
|
||||||
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
||||||
// Push the printout slightly forward, to avoid clipping into the background.
|
// Push the printout slightly forward, to avoid clipping into the background.
|
||||||
graphics.pose().pushPose();
|
graphics.guiRenderState.submitPicturesInPictureState(new PrintoutRenderState(
|
||||||
graphics.pose().translate(0, 0, 1);
|
leftPos - COVER_SIZE - 32, leftPos + X_SIZE + COVER_SIZE + 32,
|
||||||
|
topPos - COVER_SIZE, topPos + Y_SIZE + COVER_SIZE,
|
||||||
graphics.drawSpecial(bufferSource -> {
|
printout, page, new Matrix3x2f(graphics.pose()), graphics.scissorStack.peek()
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -146,4 +151,56 @@ public final class PrintoutScreen extends AbstractContainerScreen<PrintoutMenu>
|
|||||||
return new PrintoutInfo(pages, book, text, colours);
|
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.
|
||||||
|
* <p>
|
||||||
|
* 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<PrintoutRenderState> {
|
||||||
|
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<PrintoutRenderState> getRenderStateClass() {
|
||||||
|
return PrintoutRenderState.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTextureLabel() {
|
||||||
|
return "Printout";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@ import dan200.computercraft.shared.computer.core.ComputerFamily;
|
|||||||
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu;
|
||||||
import dan200.computercraft.shared.turtle.inventory.TurtleMenu;
|
import dan200.computercraft.shared.turtle.inventory.TurtleMenu;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
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.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
@@ -50,7 +50,7 @@ public class TurtleScreen extends AbstractComputerScreen<TurtleMenu> {
|
|||||||
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) {
|
||||||
var advanced = family == ComputerFamily.ADVANCED;
|
var advanced = family == ComputerFamily.ADVANCED;
|
||||||
graphics.blit(
|
graphics.blit(
|
||||||
RenderType::guiTextured, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL,
|
RenderPipelines.GUI_TEXTURED, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL,
|
||||||
leftPos + AbstractComputerMenu.SIDEBAR_WIDTH, topPos, 0, 0,
|
leftPos + AbstractComputerMenu.SIDEBAR_WIDTH, topPos, 0, 0,
|
||||||
TEX_WIDTH, TEX_HEIGHT, FULL_TEX_SIZE, FULL_TEX_SIZE
|
TEX_WIDTH, TEX_HEIGHT, FULL_TEX_SIZE, FULL_TEX_SIZE
|
||||||
);
|
);
|
||||||
@@ -61,14 +61,14 @@ public class TurtleScreen extends AbstractComputerScreen<TurtleMenu> {
|
|||||||
var slotX = slot % 4;
|
var slotX = slot % 4;
|
||||||
var slotY = slot / 4;
|
var slotY = slot / 4;
|
||||||
graphics.blitSprite(
|
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
|
leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18, 22, 22
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render sidebar
|
// Render sidebar
|
||||||
graphics.blitSprite(
|
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
|
leftPos, topPos + sidebarYOffset, AbstractComputerMenu.SIDEBAR_WIDTH, ComputerSidebar.HEIGHT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@ import net.minecraft.ChatFormatting;
|
|||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.gui.components.Button;
|
import net.minecraft.client.gui.components.Button;
|
||||||
import net.minecraft.client.gui.components.Tooltip;
|
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.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
@@ -48,7 +48,7 @@ public class DynamicImageButton extends Button {
|
|||||||
setTooltip(message.tooltip());
|
setTooltip(message.tooltip());
|
||||||
|
|
||||||
var texture = this.texture.get(isHoveredOrFocused());
|
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) {
|
public record HintedMessage(Component message, Tooltip tooltip) {
|
||||||
|
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.gui.widgets;
|
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.gui.KeyConverter;
|
||||||
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
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.components.AbstractWidget;
|
||||||
import net.minecraft.client.gui.narration.NarratedElementType;
|
import net.minecraft.client.gui.narration.NarratedElementType;
|
||||||
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
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.gui.screens.Screen;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
import net.minecraft.client.renderer.RenderPipelines;
|
||||||
import net.minecraft.network.chat.Component;
|
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 org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
@@ -254,12 +264,23 @@ public class TerminalWidget extends AbstractWidget {
|
|||||||
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
|
||||||
if (!visible) return;
|
if (!visible) return;
|
||||||
|
|
||||||
graphics.drawSpecial(bufferSource -> {
|
var scissor = graphics.scissorStack.peek();
|
||||||
FixedWidthFontRenderer.drawTerminal(
|
var terminalPose = new Matrix3x2f(graphics.pose());
|
||||||
FixedWidthFontRenderer.toVertexConsumer(graphics.pose(), bufferSource.getBuffer(FixedWidthFontRenderer.TERMINAL_TEXT)),
|
var terminalTextures = TextureSetup.singleTextureWithLightmap(graphics.minecraft.getTextureManager().getTexture(FixedWidthFontRenderer.FONT).getTextureView());
|
||||||
(float) innerX, (float) innerY, terminal, (float) MARGIN, (float) MARGIN, (float) MARGIN, (float) MARGIN
|
|
||||||
);
|
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
|
@Override
|
||||||
@@ -274,4 +295,49 @@ public class TerminalWidget extends AbstractWidget {
|
|||||||
public static int getHeight(int termHeight) {
|
public static int getHeight(int termHeight) {
|
||||||
return termHeight * FONT_HEIGHT + MARGIN * 2;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -39,6 +39,9 @@ public record TurtleOverlayModel(ItemTransforms transforms) implements ItemModel
|
|||||||
var overlay = TurtleItem.getOverlay(stack);
|
var overlay = TurtleItem.getOverlay(stack);
|
||||||
if (overlay == null) return;
|
if (overlay == null) return;
|
||||||
|
|
||||||
|
state.appendModelIdentityElement(this);
|
||||||
|
state.appendModelIdentityElement(overlay);
|
||||||
|
|
||||||
var layer = state.newLayer();
|
var layer = state.newLayer();
|
||||||
TurtleOverlayManager.get(Minecraft.getInstance().getModelManager(), overlay).model().setupItemLayer(layer);
|
TurtleOverlayManager.get(Minecraft.getInstance().getModelManager(), overlay).model().setupItemLayer(layer);
|
||||||
layer.setTransform(transforms().getTransform(context));
|
layer.setTransform(transforms().getTransform(context));
|
||||||
|
@@ -29,7 +29,7 @@ public final class CableHighlightRenderer {
|
|||||||
*/
|
*/
|
||||||
public static boolean drawHighlight(PoseStack transform, MultiBufferSource bufferSource, Camera camera, BlockHitResult hit) {
|
public static boolean drawHighlight(PoseStack transform, MultiBufferSource bufferSource, Camera camera, BlockHitResult hit) {
|
||||||
var pos = hit.getBlockPos();
|
var pos = hit.getBlockPos();
|
||||||
var world = camera.getEntity().getCommandSenderWorld();
|
var world = camera.getEntity().level();
|
||||||
|
|
||||||
var state = world.getBlockState(pos);
|
var state = world.getBlockState(pos);
|
||||||
|
|
||||||
|
@@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
package dan200.computercraft.client.render.monitor;
|
package dan200.computercraft.client.render.monitor;
|
||||||
|
|
||||||
import com.mojang.blaze3d.buffers.BufferType;
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
import com.mojang.blaze3d.buffers.BufferUsage;
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.math.Axis;
|
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.ClientMonitor;
|
||||||
import dan200.computercraft.shared.peripheral.monitor.MonitorBlockEntity;
|
import dan200.computercraft.shared.peripheral.monitor.MonitorBlockEntity;
|
||||||
import dan200.computercraft.shared.util.DirectionUtil;
|
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.MultiBufferSource;
|
||||||
|
import net.minecraft.client.renderer.RenderPipelines;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
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.AABB;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Vector4f;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
@@ -148,11 +151,7 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl
|
|||||||
throw new IllegalStateException("Drew too many vertices. Expected " + maxVertexCount + ", drew " + vertexCountAfterCursor);
|
throw new IllegalStateException("Drew too many vertices. Expected " + maxVertexCount + ", drew " + vertexCountAfterCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
final int indexAfterBackground, indexAfterForeground, indexAfterCursor;
|
if (vertexCountAfterCursor != 0) {
|
||||||
if (vertexCountAfterCursor == 0) {
|
|
||||||
// If we have nothing to draw, just mark it as empty. We'll skip drawing in drawWithShader.
|
|
||||||
indexAfterBackground = indexAfterForeground = indexAfterCursor = 0;
|
|
||||||
} else {
|
|
||||||
renderState.register();
|
renderState.register();
|
||||||
|
|
||||||
var commandEncoder = RenderSystem.getDevice().createCommandEncoder();
|
var commandEncoder = RenderSystem.getDevice().createCommandEncoder();
|
||||||
@@ -174,25 +173,19 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl
|
|||||||
renderState.vertexBuffer = null;
|
renderState.vertexBuffer = null;
|
||||||
}
|
}
|
||||||
renderState.vertexBuffer = RenderSystem.getDevice().createBuffer(
|
renderState.vertexBuffer = RenderSystem.getDevice().createBuffer(
|
||||||
() -> "Monitor at " + monitor.getOrigin().getBlockPos(),
|
() -> "Monitor at " + monitor.getOrigin().getBlockPos(), GpuBuffer.USAGE_VERTEX | GpuBuffer.USAGE_COPY_DST, resultBuffer
|
||||||
BufferType.VERTICES, BufferUsage.STATIC_WRITE, resultBuffer
|
|
||||||
);
|
);
|
||||||
} else if (!renderState.vertexBuffer.isClosed()) {
|
} 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.vertexCountAfterBackground = vertexCountAfterBackground;
|
||||||
renderState.indexAfterBackground = indexAfterBackground;
|
renderState.vertexCountAfterForeground = vertexCountAfterForeground;
|
||||||
renderState.indexAfterCursor = indexAfterCursor;
|
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
|
// 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
|
// 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<MonitorBl
|
|||||||
// renderer is trying to avoid!). Instead, we just disable fog entirely by setting the fog start to an
|
// renderer is trying to avoid!). Instead, we just disable fog entirely by setting the fog start to an
|
||||||
// absurdly high value.
|
// absurdly high value.
|
||||||
var oldFog = RenderSystem.getShaderFog();
|
var oldFog = RenderSystem.getShaderFog();
|
||||||
RenderSystem.setShaderFog(FogParameters.NO_FOG);
|
RenderSystem.setShaderFog(Minecraft.getInstance().gameRenderer.fogRenderer.getBuffer(FogRenderer.FogMode.NONE));
|
||||||
|
|
||||||
// Compose the existing model view matrix with our transformation matrix.
|
// Compose the existing model view matrix with our transformation matrix.
|
||||||
RenderSystem.getModelViewStack().pushMatrix();
|
RenderSystem.getModelViewStack().pushMatrix();
|
||||||
RenderSystem.getModelViewStack().mul(matrix);
|
RenderSystem.getModelViewStack().mul(matrix);
|
||||||
|
|
||||||
// Render background geometry
|
// Render background geometry
|
||||||
drawWithShader(renderState, FixedWidthFontRenderer.TERMINAL_TEXT, 0, renderState.indexAfterBackground);
|
drawWithShader(renderState, FixedWidthFontRenderer.TERMINAL_TEXT, RenderPipelines.TEXT, 0, renderState.vertexCountAfterBackground);
|
||||||
drawWithShader(
|
drawWithShader(
|
||||||
renderState, FixedWidthFontRenderer.TERMINAL_TEXT_OFFSET, renderState.indexAfterBackground,
|
renderState, FixedWidthFontRenderer.TERMINAL_TEXT_OFFSET, RenderPipelines.TEXT_POLYGON_OFFSET, renderState.vertexCountAfterBackground,
|
||||||
(
|
(
|
||||||
FixedWidthFontRenderer.isCursorVisible(terminal) && FrameInfo.getGlobalCursorBlink()
|
FixedWidthFontRenderer.isCursorVisible(terminal) && FrameInfo.getGlobalCursorBlink()
|
||||||
? renderState.indexAfterCursor : renderState.indexAfterForeground
|
? renderState.vertexCountAfterCursor : renderState.vertexCountAfterForeground
|
||||||
) - renderState.indexAfterBackground
|
) - renderState.vertexCountAfterBackground
|
||||||
);
|
);
|
||||||
|
|
||||||
// Clear state
|
// Clear state
|
||||||
@@ -222,21 +215,39 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl
|
|||||||
RenderSystem.setShaderFog(oldFog);
|
RenderSystem.setShaderFog(oldFog);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void drawWithShader(MonitorRenderState renderState, RenderType renderType, int indexOffset, int indexCount) {
|
private static void drawWithShader(MonitorRenderState renderState, RenderType renderType, RenderPipeline pipeline, int vertexOffset, int vertexCount) {
|
||||||
if (renderState.vertexBuffer == null) {
|
if (renderState.vertexBuffer == null) {
|
||||||
throw new IllegalStateException("MonitorRenderState has not been initialised");
|
throw new IllegalStateException("MonitorRenderState has not been initialised");
|
||||||
}
|
}
|
||||||
if (indexCount == 0) return;
|
if (vertexCount == 0) return;
|
||||||
|
|
||||||
|
var transforms = RenderSystem.getDynamicUniforms().writeTransform(
|
||||||
|
RenderSystem.getModelViewMatrix(),
|
||||||
|
new Vector4f(1.0F, 1.0F, 1.0F, 1.0F),
|
||||||
|
RenderSystem.getModelOffset(),
|
||||||
|
RenderSystem.getTextureMatrix(),
|
||||||
|
RenderSystem.getShaderLineWidth()
|
||||||
|
);
|
||||||
|
|
||||||
renderType.setupRenderState();
|
renderType.setupRenderState();
|
||||||
|
|
||||||
var autoStorageBuffer = RenderSystem.getSequentialBuffer(renderType.mode());
|
var autoStorageBuffer = RenderSystem.getSequentialBuffer(renderType.mode());
|
||||||
var indexBuffer = autoStorageBuffer.getBuffer(indexOffset + indexCount);
|
var indexCount = FixedWidthFontRenderer.TERMINAL_TEXT.mode().indexCount(vertexCount);
|
||||||
|
var indexBuffer = autoStorageBuffer.getBuffer(indexCount);
|
||||||
|
|
||||||
|
var target = Minecraft.getInstance().getMainRenderTarget();
|
||||||
|
var colourTarget = RenderSystem.outputColorTextureOverride != null ? RenderSystem.outputColorTextureOverride : target.getColorTextureView();
|
||||||
|
var depthTarget = target.useDepth
|
||||||
|
? (RenderSystem.outputDepthTextureOverride != null ? RenderSystem.outputDepthTextureOverride : target.getDepthTextureView())
|
||||||
|
: null;
|
||||||
|
|
||||||
try (var renderPass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(
|
try (var renderPass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(
|
||||||
renderType.getRenderTarget().getColorTexture(), OptionalInt.empty(), renderType.getRenderTarget().getDepthTexture(), OptionalDouble.empty()
|
() -> "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.setVertexBuffer(0, renderState.vertexBuffer);
|
||||||
renderPass.setIndexBuffer(indexBuffer, autoStorageBuffer.type());
|
renderPass.setIndexBuffer(indexBuffer, autoStorageBuffer.type());
|
||||||
|
|
||||||
@@ -245,7 +256,7 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl
|
|||||||
if (gpuTexture != null) renderPass.bindSampler("Sampler" + j, gpuTexture);
|
if (gpuTexture != null) renderPass.bindSampler("Sampler" + j, gpuTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderPass.drawIndexed(indexOffset, indexCount);
|
renderPass.drawIndexed(vertexOffset, 0, indexCount, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderType.clearRenderState();
|
renderType.clearRenderState();
|
||||||
|
@@ -29,7 +29,7 @@ public final class MonitorHighlightRenderer {
|
|||||||
// Preserve normal behaviour when crouching.
|
// Preserve normal behaviour when crouching.
|
||||||
if (camera.getEntity().isCrouching()) return false;
|
if (camera.getEntity().isCrouching()) return false;
|
||||||
|
|
||||||
var world = camera.getEntity().getCommandSenderWorld();
|
var world = camera.getEntity().level();
|
||||||
var pos = hit.getBlockPos();
|
var pos = hit.getBlockPos();
|
||||||
|
|
||||||
if (!(world.getBlockEntity(pos) instanceof MonitorBlockEntity monitor)) return false;
|
if (!(world.getBlockEntity(pos) instanceof MonitorBlockEntity monitor)) return false;
|
||||||
|
@@ -31,9 +31,9 @@ public final class MonitorRenderState implements ClientMonitor.RenderState {
|
|||||||
@Nullable
|
@Nullable
|
||||||
GpuBuffer vertexBuffer;
|
GpuBuffer vertexBuffer;
|
||||||
|
|
||||||
int indexAfterBackground;
|
int vertexCountAfterBackground;
|
||||||
int indexAfterForeground;
|
int vertexCountAfterForeground;
|
||||||
int indexAfterCursor;
|
int vertexCountAfterCursor;
|
||||||
|
|
||||||
void register() {
|
void register() {
|
||||||
if (vertexBuffer != null) return;
|
if (vertexBuffer != null) return;
|
||||||
|
@@ -33,7 +33,7 @@ import org.joml.Vector3f;
|
|||||||
* {@link DirectFixedWidthFontRenderer}.
|
* {@link DirectFixedWidthFontRenderer}.
|
||||||
*/
|
*/
|
||||||
public final class FixedWidthFontRenderer {
|
public final class FixedWidthFontRenderer {
|
||||||
private static final ResourceLocation FONT = ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/term_font.png");
|
public static final ResourceLocation FONT = ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/term_font.png");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A render type for terminal text.
|
* A render type for terminal text.
|
||||||
|
@@ -48,7 +48,7 @@ public class SpeakerInstance {
|
|||||||
// Update the attenuation if the volume has changed: SoundEngine.tickNonPaused updates the volume
|
// Update the attenuation if the volume has changed: SoundEngine.tickNonPaused updates the volume
|
||||||
// itself, but leaves the attenuation unchanged. We mirror the logic of SoundEngine.play here.
|
// itself, but leaves the attenuation unchanged. We mirror the logic of SoundEngine.play here.
|
||||||
if (volumeChanged) {
|
if (volumeChanged) {
|
||||||
channel.linearAttenuation(Math.max(volume, 1) * sound.getSound().getAttenuationDistance());
|
channel.linearAttenuation(Math.max(volume, 1) * Nullability.assertNonNull(sound.getSound()).getAttenuationDistance());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -62,8 +62,8 @@ public final class DataProviders {
|
|||||||
generator.registries(fullRegistryPatch);
|
generator.registries(fullRegistryPatch);
|
||||||
generator.add(out -> new RecipeProvider.Runner(out, fullRegistries));
|
generator.add(out -> new RecipeProvider.Runner(out, fullRegistries));
|
||||||
|
|
||||||
var blockTags = generator.blockTags(TagProvider::blockTags);
|
generator.blockTags(TagProvider::blockTags);
|
||||||
generator.itemTags(TagProvider::itemTags, blockTags);
|
generator.itemTags(TagProvider::itemTags);
|
||||||
|
|
||||||
generator.add(out -> new net.minecraft.data.loot.LootTableProvider(out, Set.of(), LootTableProvider.getTables(), fullRegistries));
|
generator.add(out -> new net.minecraft.data.loot.LootTableProvider(out, Set.of(), LootTableProvider.getTables(), fullRegistries));
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ public final class DataProviders {
|
|||||||
|
|
||||||
TagsProvider<Block> blockTags(Consumer<TagProvider.TagConsumer<Block>> tags);
|
TagsProvider<Block> blockTags(Consumer<TagProvider.TagConsumer<Block>> tags);
|
||||||
|
|
||||||
TagsProvider<Item> itemTags(Consumer<TagProvider.ItemTagConsumer> tags, TagsProvider<Block> blocks);
|
TagsProvider<Item> itemTags(Consumer<TagProvider.TagConsumer<Item>> tags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build new dynamic registries and save them to a pack.
|
* Build new dynamic registries and save them to a pack.
|
||||||
|
@@ -7,13 +7,10 @@ package dan200.computercraft.data;
|
|||||||
import dan200.computercraft.api.ComputerCraftTags;
|
import dan200.computercraft.api.ComputerCraftTags;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.integration.ExternalModTags;
|
import dan200.computercraft.shared.integration.ExternalModTags;
|
||||||
import dan200.computercraft.shared.util.RegistryHelper;
|
import net.minecraft.data.tags.TagAppender;
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
import net.minecraft.data.tags.ItemTagsProvider;
|
|
||||||
import net.minecraft.data.tags.TagsProvider;
|
import net.minecraft.data.tags.TagsProvider;
|
||||||
import net.minecraft.tags.BlockTags;
|
import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.tags.ItemTags;
|
import net.minecraft.tags.ItemTags;
|
||||||
import net.minecraft.tags.TagBuilder;
|
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.Items;
|
import net.minecraft.world.item.Items;
|
||||||
@@ -28,14 +25,8 @@ import net.minecraft.world.level.block.Blocks;
|
|||||||
*/
|
*/
|
||||||
class TagProvider {
|
class TagProvider {
|
||||||
public static void blockTags(TagConsumer<Block> tags) {
|
public static void blockTags(TagConsumer<Block> tags) {
|
||||||
tags.tag(ComputerCraftTags.Blocks.COMPUTER).add(
|
itemAndBlockTags((b, i) -> tags.tag(b));
|
||||||
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());
|
|
||||||
tags.tag(ComputerCraftTags.Blocks.WIRED_MODEM).add(ModRegistry.Blocks.CABLE.get(), ModRegistry.Blocks.WIRED_MODEM_FULL.get());
|
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);
|
tags.tag(ComputerCraftTags.Blocks.PERIPHERAL_HUB_IGNORE).addTag(ComputerCraftTags.Blocks.WIRED_MODEM);
|
||||||
|
|
||||||
@@ -91,11 +82,9 @@ class TagProvider {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void itemTags(ItemTagConsumer tags) {
|
public static void itemTags(TagConsumer<Item> tags) {
|
||||||
tags.copy(ComputerCraftTags.Blocks.COMPUTER, ComputerCraftTags.Items.COMPUTER);
|
itemAndBlockTags((b, i) -> tags.tag(i).map(Block::asItem));
|
||||||
tags.copy(ComputerCraftTags.Blocks.TURTLE, ComputerCraftTags.Items.TURTLE);
|
|
||||||
tags.tag(ComputerCraftTags.Items.WIRED_MODEM).add(ModRegistry.Items.WIRED_MODEM.get(), ModRegistry.Items.WIRED_MODEM_FULL.get());
|
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.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());
|
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);
|
.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}.
|
* A wrapper over {@link TagsProvider}.
|
||||||
*
|
*
|
||||||
* @param <T> The type of object we're providing tags for.
|
* @param <T> The type of object we're providing tags for.
|
||||||
*/
|
*/
|
||||||
public interface TagConsumer<T> {
|
public interface TagConsumer<T> {
|
||||||
TagAppender<T> tag(TagKey<T> tag);
|
TagAppender<T, T> tag(TagKey<T> tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public record TagAppender<T>(Registry<T> registry, TagBuilder builder) {
|
private interface BlockItemTagConsumer {
|
||||||
public TagAppender<T> add(T object) {
|
TagAppender<Block, ?> tag(TagKey<Block> blockTag, TagKey<Item> itemTag);
|
||||||
builder.addElement(RegistryHelper.getKeyOrThrow(registry, object));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SafeVarargs
|
|
||||||
public final TagAppender<T> add(T... objects) {
|
|
||||||
for (var object : objects) add(object);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TagAppender<T> addTag(TagKey<T> tag) {
|
|
||||||
builder.addTag(tag.location());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper over {@link ItemTagsProvider}.
|
|
||||||
*/
|
|
||||||
public interface ItemTagConsumer extends TagConsumer<Item> {
|
|
||||||
void copy(TagKey<Block> block, TagKey<Item> item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,12 +12,11 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|||||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
import com.mojang.brigadier.suggestion.Suggestions;
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
|
import com.mojang.serialization.JsonOps;
|
||||||
import net.minecraft.commands.CommandBuildContext;
|
import net.minecraft.commands.CommandBuildContext;
|
||||||
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
|
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
|
||||||
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
|
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
|
||||||
import net.minecraft.core.RegistryAccess;
|
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.network.chat.Component;
|
|
||||||
import net.minecraft.network.chat.ComponentSerialization;
|
import net.minecraft.network.chat.ComponentSerialization;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -136,7 +135,7 @@ public final class RepeatArgumentType<T, U> implements ArgumentType<List<T>> {
|
|||||||
public void serializeToJson(RepeatArgumentType.Template arg, JsonObject json) {
|
public void serializeToJson(RepeatArgumentType.Template arg, JsonObject json) {
|
||||||
json.addProperty("flatten", arg.flatten);
|
json.addProperty("flatten", arg.flatten);
|
||||||
json.add("child", ArgumentUtils.serializeToJson(arg.child));
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,11 +20,9 @@ import dan200.computercraft.shared.platform.PlatformHelper;
|
|||||||
import dan200.computercraft.shared.util.*;
|
import dan200.computercraft.shared.util.*;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.HolderLookup;
|
|
||||||
import net.minecraft.core.component.DataComponentGetter;
|
import net.minecraft.core.component.DataComponentGetter;
|
||||||
import net.minecraft.core.component.DataComponentMap;
|
import net.minecraft.core.component.DataComponentMap;
|
||||||
import net.minecraft.core.component.DataComponents;
|
import net.minecraft.core.component.DataComponents;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
import net.minecraft.world.LockCode;
|
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.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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 org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -142,36 +142,36 @@ public abstract class AbstractComputerBlockEntity extends BlockEntity implements
|
|||||||
protected abstract void updateBlockState(ComputerState newState);
|
protected abstract void updateBlockState(ComputerState newState);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void saveAdditional(ValueOutput nbt) {
|
||||||
// Save ID, label and power state
|
// Save ID, label and power state
|
||||||
if (computerID >= 0) nbt.putInt(NBT_ID, computerID);
|
if (computerID >= 0) nbt.putInt(NBT_ID, computerID);
|
||||||
if (label != null) nbt.putString(NBT_LABEL, label);
|
if (label != null) nbt.putString(NBT_LABEL, label);
|
||||||
if (storageCapacity > 0) nbt.putLong(NBT_CAPACITY, storageCapacity);
|
if (storageCapacity > 0) nbt.putLong(NBT_CAPACITY, storageCapacity);
|
||||||
nbt.putBoolean(NBT_ON, on);
|
nbt.putBoolean(NBT_ON, on);
|
||||||
|
|
||||||
lockCode.addToTag(nbt, registries);
|
lockCode.addToTag(nbt);
|
||||||
|
|
||||||
super.saveAdditional(nbt, registries);
|
super.saveAdditional(nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
public final void loadAdditional(ValueInput nbt) {
|
||||||
super.loadAdditional(nbt, registries);
|
super.loadAdditional(nbt);
|
||||||
if (level != null && level.isClientSide) {
|
if (level != null && level.isClientSide) {
|
||||||
loadClient(nbt, registries);
|
loadClient(nbt);
|
||||||
} else {
|
} 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
|
// Load ID, label and power state
|
||||||
computerID = nbt.getIntOr(NBT_ID, -1);
|
computerID = nbt.getIntOr(NBT_ID, -1);
|
||||||
label = nbt.getStringOr(NBT_LABEL, null);
|
label = nbt.getStringOr(NBT_LABEL, null);
|
||||||
storageCapacity = nbt.getLongOr(NBT_CAPACITY, -1);
|
storageCapacity = nbt.getLongOr(NBT_CAPACITY, -1);
|
||||||
on = startOn = nbt.getBooleanOr(NBT_ON, false);
|
on = startOn = nbt.getBooleanOr(NBT_ON, false);
|
||||||
|
|
||||||
lockCode = LockCode.fromTag(nbt, registries);
|
lockCode = LockCode.fromTag(nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -204,12 +204,12 @@ public abstract class AbstractComputerBlockEntity extends BlockEntity implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void removeComponentsFromTag(CompoundTag tag) {
|
public void removeComponentsFromTag(ValueOutput tag) {
|
||||||
super.removeComponentsFromTag(tag);
|
super.removeComponentsFromTag(tag);
|
||||||
tag.remove(NBT_ID);
|
tag.discard(NBT_ID);
|
||||||
tag.remove(NBT_LABEL);
|
tag.discard(NBT_LABEL);
|
||||||
tag.remove(NBT_CAPACITY);
|
tag.discard(NBT_CAPACITY);
|
||||||
tag.remove(LockCode.TAG_LOCK);
|
tag.discard(LockCode.TAG_LOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isPeripheralBlockedOnSide(ComputerSide localSide) {
|
protected boolean isPeripheralBlockedOnSide(ComputerSide localSide) {
|
||||||
@@ -391,7 +391,7 @@ public abstract class AbstractComputerBlockEntity extends BlockEntity implements
|
|||||||
|
|
||||||
// Networking stuff
|
// Networking stuff
|
||||||
|
|
||||||
protected void loadClient(CompoundTag nbt, HolderLookup.Provider registries) {
|
protected void loadClient(ValueInput tag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void transferStateFrom(AbstractComputerBlockEntity copy) {
|
protected void transferStateFrom(AbstractComputerBlockEntity copy) {
|
||||||
|
@@ -13,19 +13,18 @@ import dan200.computercraft.shared.computer.core.ServerComputer;
|
|||||||
import dan200.computercraft.shared.computer.core.TerminalSize;
|
import dan200.computercraft.shared.computer.core.TerminalSize;
|
||||||
import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory;
|
import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory;
|
||||||
import dan200.computercraft.shared.config.ConfigSpec;
|
import dan200.computercraft.shared.config.ConfigSpec;
|
||||||
import dan200.computercraft.shared.util.NBTUtil;
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.HolderLookup;
|
|
||||||
import net.minecraft.core.component.DataComponentGetter;
|
import net.minecraft.core.component.DataComponentGetter;
|
||||||
import net.minecraft.core.component.DataComponentMap;
|
import net.minecraft.core.component.DataComponentMap;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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 org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
public class ComputerBlockEntity extends AbstractComputerBlockEntity {
|
public class ComputerBlockEntity extends AbstractComputerBlockEntity {
|
||||||
@@ -40,15 +39,15 @@ public class ComputerBlockEntity extends AbstractComputerBlockEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadServer(CompoundTag nbt, HolderLookup.Provider registries) {
|
protected void loadServer(ValueInput nbt) {
|
||||||
super.loadServer(nbt, registries);
|
super.loadServer(nbt);
|
||||||
terminalSize = NBTUtil.decodeFrom(TerminalSize.CODEC, registries, nbt, NBT_TERMINAL_SIZE);
|
terminalSize = nbt.read(NBT_TERMINAL_SIZE, TerminalSize.CODEC).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void saveAdditional(ValueOutput tag) {
|
||||||
super.saveAdditional(nbt, registries);
|
super.saveAdditional(tag);
|
||||||
NBTUtil.encodeTo(TerminalSize.CODEC, registries, nbt, NBT_TERMINAL_SIZE, terminalSize);
|
tag.storeNullable(NBT_TERMINAL_SIZE, TerminalSize.CODEC, terminalSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -65,9 +64,9 @@ public class ComputerBlockEntity extends AbstractComputerBlockEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void removeComponentsFromTag(CompoundTag tag) {
|
public void removeComponentsFromTag(ValueOutput tag) {
|
||||||
super.removeComponentsFromTag(tag);
|
super.removeComponentsFromTag(tag);
|
||||||
tag.remove(NBT_TERMINAL_SIZE);
|
tag.discard(NBT_TERMINAL_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -220,7 +220,7 @@ public final class ServerContext {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHostString() {
|
public String getHostString() {
|
||||||
var version = SharedConstants.getCurrentVersion().getName();
|
var version = SharedConstants.getCurrentVersion().name();
|
||||||
return String.format("ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), version);
|
return String.format("ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,7 +7,8 @@ package dan200.computercraft.shared.computer.terminal;
|
|||||||
import dan200.computercraft.core.terminal.Palette;
|
import dan200.computercraft.core.terminal.Palette;
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import dan200.computercraft.core.util.Colour;
|
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 class NetworkedTerminal extends Terminal {
|
||||||
public NetworkedTerminal(int width, int height, boolean colour) {
|
public NetworkedTerminal(int width, int height, boolean colour) {
|
||||||
@@ -76,7 +77,7 @@ public class NetworkedTerminal extends Terminal {
|
|||||||
setChanged();
|
setChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized CompoundTag writeToNBT(CompoundTag nbt) {
|
public synchronized void writeToNBT(ValueOutput nbt) {
|
||||||
nbt.putInt("term_cursorX", cursorX);
|
nbt.putInt("term_cursorX", cursorX);
|
||||||
nbt.putInt("term_cursorY", cursorY);
|
nbt.putInt("term_cursorY", cursorY);
|
||||||
nbt.putBoolean("term_cursorBlink", cursorBlink);
|
nbt.putBoolean("term_cursorBlink", cursorBlink);
|
||||||
@@ -91,11 +92,9 @@ public class NetworkedTerminal extends Terminal {
|
|||||||
var rgb8 = new int[Palette.PALETTE_SIZE];
|
var rgb8 = new int[Palette.PALETTE_SIZE];
|
||||||
for (var i = 0; i < Palette.PALETTE_SIZE; i++) rgb8[i] = Palette.encodeRGB8(palette.getColour(i));
|
for (var i = 0; i < Palette.PALETTE_SIZE; i++) rgb8[i] = Palette.encodeRGB8(palette.getColour(i));
|
||||||
nbt.putIntArray("term_palette", rgb8);
|
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);
|
cursorX = nbt.getIntOr("term_cursorX", 0);
|
||||||
cursorY = nbt.getIntOr("term_cursorY", 0);
|
cursorY = nbt.getIntOr("term_cursorY", 0);
|
||||||
cursorBlink = nbt.getBooleanOr("term_cursorBlink", false);
|
cursorBlink = nbt.getBooleanOr("term_cursorBlink", false);
|
||||||
@@ -104,29 +103,26 @@ public class NetworkedTerminal extends Terminal {
|
|||||||
|
|
||||||
for (var n = 0; n < height; n++) {
|
for (var n = 0; n < height; n++) {
|
||||||
text[n].fill(' ');
|
text[n].fill(' ');
|
||||||
if (nbt.contains("term_text_" + n)) {
|
var line = nbt.getStringOr("term_text_" + n, "");
|
||||||
text[n].write(nbt.getStringOr("term_text_" + n, ""));
|
if (!line.isEmpty()) text[n].write(line);
|
||||||
}
|
|
||||||
textColour[n].fill(BASE_16.charAt(cursorColour));
|
textColour[n].fill(BASE_16.charAt(cursorColour));
|
||||||
if (nbt.contains("term_textColour_" + n)) {
|
var fgLine = nbt.getStringOr("term_textColour_" + n, "");
|
||||||
textColour[n].write(nbt.getStringOr("term_textColour_" + n, ""));
|
if (!fgLine.isEmpty()) textColour[n].write(fgLine);
|
||||||
}
|
|
||||||
backgroundColour[n].fill(BASE_16.charAt(cursorBackgroundColour));
|
backgroundColour[n].fill(BASE_16.charAt(cursorBackgroundColour));
|
||||||
if (nbt.contains("term_textBgColour_" + n)) {
|
var bgLine = nbt.getStringOr("term_textBgColour_" + n, "");
|
||||||
backgroundColour[n].write(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();
|
setChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,8 +13,6 @@ import dan200.computercraft.shared.ModRegistry;
|
|||||||
import net.minecraft.util.datafix.fixes.DataComponentRemainderFix;
|
import net.minecraft.util.datafix.fixes.DataComponentRemainderFix;
|
||||||
import net.minecraft.util.datafix.fixes.FoodToConsumableFix;
|
import net.minecraft.util.datafix.fixes.FoodToConsumableFix;
|
||||||
import net.minecraft.util.datafix.fixes.References;
|
import net.minecraft.util.datafix.fixes.References;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
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")
|
dynamic -> dynamic.renameField("computercraft:pocket_upgrade", "computercraft:back_pocket_upgrade")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RenamePocketComputerUpgradeFix.class);
|
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@ import net.minecraft.network.protocol.Packet;
|
|||||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.util.ProblemReporter;
|
||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
import net.minecraft.world.SimpleMenuProvider;
|
import net.minecraft.world.SimpleMenuProvider;
|
||||||
import net.minecraft.world.entity.player.Player;
|
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.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.LecternBlockEntity;
|
import net.minecraft.world.level.block.entity.LecternBlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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.AbstractList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -41,6 +47,8 @@ import static dan200.computercraft.shared.lectern.CustomLecternBlock.dropItem;
|
|||||||
* @see LecternBlockEntity
|
* @see LecternBlockEntity
|
||||||
*/
|
*/
|
||||||
public final class CustomLecternBlockEntity extends BlockEntity {
|
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_ITEM = "Item";
|
||||||
private static final String NBT_PAGE = "Page";
|
private static final String NBT_PAGE = "Page";
|
||||||
|
|
||||||
@@ -107,19 +115,19 @@ public final class CustomLecternBlockEntity extends BlockEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
public void loadAdditional(ValueInput tag) {
|
||||||
super.loadAdditional(tag, registries);
|
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);
|
page = tag.getIntOr(NBT_PAGE, 0);
|
||||||
itemChanged();
|
itemChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
protected void saveAdditional(ValueOutput tag) {
|
||||||
super.saveAdditional(tag, registries);
|
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);
|
if (item.getItem() instanceof PrintoutItem) tag.putInt(NBT_PAGE, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,9 +138,11 @@ public final class CustomLecternBlockEntity extends BlockEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
|
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
|
||||||
var tag = super.getUpdateTag(registries);
|
try (var problems = new ProblemReporter.ScopedCollector(this.problemPath(), LOG)) {
|
||||||
if (!item.isEmpty()) tag.put(NBT_ITEM, item.save(registries));
|
var output = TagValueOutput.createWithContext(problems, registries);
|
||||||
return tag;
|
if (!item.isEmpty()) output.store(NBT_ITEM, ItemStack.CODEC, item);
|
||||||
|
return output.buildResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void openMenu(Player player) {
|
void openMenu(Player player) {
|
||||||
|
@@ -87,6 +87,7 @@ public class DiskRecipe extends AbstractCraftingRecipe {
|
|||||||
var stack = inv.getItem(i);
|
var stack = inv.getItem(i);
|
||||||
if (stack.isEmpty()) continue;
|
if (stack.isEmpty()) continue;
|
||||||
if (ColourUtils.getStackColour(stack) == null) {
|
if (ColourUtils.getStackColour(stack) == null) {
|
||||||
|
inputs++;
|
||||||
stackedContents.accountStack(stack, 1);
|
stackedContents.accountStack(stack, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,9 +17,7 @@ import dan200.computercraft.shared.network.server.ServerNetworking;
|
|||||||
import dan200.computercraft.shared.util.WorldUtil;
|
import dan200.computercraft.shared.util.WorldUtil;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.HolderLookup;
|
|
||||||
import net.minecraft.core.NonNullList;
|
import net.minecraft.core.NonNullList;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
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.LevelEvent;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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 net.minecraft.world.phys.Vec3;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@@ -114,17 +114,17 @@ public final class DiskDriveBlockEntity extends AbstractContainerBlockEntity imp
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void loadAdditional(ValueInput nbt) {
|
||||||
super.loadAdditional(nbt, registries);
|
super.loadAdditional(nbt);
|
||||||
setDiskStack(nbt.getCompound(NBT_ITEM).flatMap(x -> ItemStack.parse(registries, x)).orElse(ItemStack.EMPTY));
|
setDiskStack(nbt.read(NBT_ITEM, ItemStack.CODEC).orElse(ItemStack.EMPTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
public void saveAdditional(ValueOutput tag) {
|
||||||
super.saveAdditional(tag, registries);
|
super.saveAdditional(tag);
|
||||||
|
|
||||||
var stack = getDiskStack();
|
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() {
|
void serverTick() {
|
||||||
|
@@ -15,8 +15,6 @@ import dan200.computercraft.shared.util.DirectionUtil;
|
|||||||
import dan200.computercraft.shared.util.TickScheduler;
|
import dan200.computercraft.shared.util.TickScheduler;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.HolderLookup;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.entity.player.Player;
|
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.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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 net.minecraft.world.phys.Vec3;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@@ -144,15 +144,15 @@ public class CableBlockEntity extends BlockEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void loadAdditional(ValueInput nbt) {
|
||||||
super.loadAdditional(nbt, registries);
|
super.loadAdditional(nbt);
|
||||||
peripheral.read(nbt, "");
|
peripheral.read(nbt, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void saveAdditional(ValueOutput nbt) {
|
||||||
peripheral.write(nbt, "");
|
peripheral.write(nbt, "");
|
||||||
super.saveAdditional(nbt, registries);
|
super.saveAdditional(nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateBlockState() {
|
private void updateBlockState() {
|
||||||
|
@@ -15,8 +15,6 @@ import dan200.computercraft.shared.util.DirectionUtil;
|
|||||||
import dan200.computercraft.shared.util.TickScheduler;
|
import dan200.computercraft.shared.util.TickScheduler;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.HolderLookup;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.entity.player.Player;
|
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.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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 net.minecraft.world.phys.Vec3;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
@@ -155,15 +155,15 @@ public class WiredModemFullBlockEntity extends BlockEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void loadAdditional(ValueInput nbt) {
|
||||||
super.loadAdditional(nbt, registries);
|
super.loadAdditional(nbt);
|
||||||
for (var i = 0; i < peripherals.length; i++) peripherals[i].read(nbt, Integer.toString(i));
|
for (var i = 0; i < peripherals.length; i++) peripherals[i].read(nbt, Integer.toString(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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));
|
for (var i = 0; i < peripherals.length; i++) peripherals[i].write(nbt, Integer.toString(i));
|
||||||
super.saveAdditional(nbt, registries);
|
super.saveAdditional(nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void blockTick() {
|
void blockTick() {
|
||||||
|
@@ -11,8 +11,9 @@ import dan200.computercraft.shared.computer.core.ServerContext;
|
|||||||
import dan200.computercraft.shared.platform.ComponentAccess;
|
import dan200.computercraft.shared.platform.ComponentAccess;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.world.level.Level;
|
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 org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -97,12 +98,12 @@ public final class WiredModemLocalPeripheral {
|
|||||||
return peripheral == null ? Map.of() : Map.of(type + "_" + id, peripheral);
|
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 (id >= 0) tag.putInt(NBT_PERIPHERAL_ID + suffix, id);
|
||||||
if (type != null) tag.putString(NBT_PERIPHERAL_TYPE + suffix, type);
|
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);
|
id = tag.getIntOr(NBT_PERIPHERAL_ID + suffix, -1);
|
||||||
type = tag.getStringOr(NBT_PERIPHERAL_TYPE + suffix, null);
|
type = tag.getStringOr(NBT_PERIPHERAL_TYPE + suffix, null);
|
||||||
}
|
}
|
||||||
|
@@ -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.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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 net.minecraft.world.phys.AABB;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -107,17 +109,17 @@ public class MonitorBlockEntity extends BlockEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
public void saveAdditional(ValueOutput tag) {
|
||||||
tag.putInt(NBT_X, xIndex);
|
tag.putInt(NBT_X, xIndex);
|
||||||
tag.putInt(NBT_Y, yIndex);
|
tag.putInt(NBT_Y, yIndex);
|
||||||
tag.putInt(NBT_WIDTH, width);
|
tag.putInt(NBT_WIDTH, width);
|
||||||
tag.putInt(NBT_HEIGHT, height);
|
tag.putInt(NBT_HEIGHT, height);
|
||||||
super.saveAdditional(tag, registries);
|
super.saveAdditional(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void loadAdditional(ValueInput nbt) {
|
||||||
super.loadAdditional(nbt, registries);
|
super.loadAdditional(nbt);
|
||||||
|
|
||||||
var oldXIndex = xIndex;
|
var oldXIndex = xIndex;
|
||||||
var oldYIndex = yIndex;
|
var oldYIndex = yIndex;
|
||||||
|
@@ -15,9 +15,7 @@ import dan200.computercraft.shared.util.ColourUtils;
|
|||||||
import dan200.computercraft.shared.util.DataComponentUtil;
|
import dan200.computercraft.shared.util.DataComponentUtil;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.HolderLookup;
|
|
||||||
import net.minecraft.core.NonNullList;
|
import net.minecraft.core.NonNullList;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.world.ContainerHelper;
|
import net.minecraft.world.ContainerHelper;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
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.item.Items;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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 org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -55,8 +55,8 @@ public final class PrinterBlockEntity extends AbstractContainerBlockEntity imple
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void loadAdditional(ValueInput nbt) {
|
||||||
super.loadAdditional(nbt, registries);
|
super.loadAdditional(nbt);
|
||||||
|
|
||||||
// Read page
|
// Read page
|
||||||
synchronized (page) {
|
synchronized (page) {
|
||||||
@@ -66,11 +66,11 @@ public final class PrinterBlockEntity extends AbstractContainerBlockEntity imple
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read inventory
|
// Read inventory
|
||||||
ContainerHelper.loadAllItems(nbt, inventory, registries);
|
ContainerHelper.loadAllItems(nbt, inventory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
public void saveAdditional(ValueOutput tag) {
|
||||||
// Write page
|
// Write page
|
||||||
synchronized (page) {
|
synchronized (page) {
|
||||||
tag.putBoolean(NBT_PRINTING, printing);
|
tag.putBoolean(NBT_PRINTING, printing);
|
||||||
@@ -79,9 +79,9 @@ public final class PrinterBlockEntity extends AbstractContainerBlockEntity imple
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write inventory
|
// Write inventory
|
||||||
ContainerHelper.saveAllItems(tag, inventory, registries);
|
ContainerHelper.saveAllItems(tag, inventory);
|
||||||
|
|
||||||
super.saveAdditional(tag, registries);
|
super.saveAdditional(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isPrinting() {
|
boolean isPrinting() {
|
||||||
|
@@ -35,6 +35,7 @@ import net.minecraft.nbt.CompoundTag;
|
|||||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.util.ProblemReporter;
|
||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
import net.minecraft.world.ContainerHelper;
|
import net.minecraft.world.ContainerHelper;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
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.item.component.TooltipDisplay;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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 net.minecraft.world.phys.Vec3;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.function.IntSupplier;
|
import java.util.function.IntSupplier;
|
||||||
|
|
||||||
public class TurtleBlockEntity extends AbstractComputerBlockEntity implements BasicContainer {
|
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_SIZE = 16;
|
||||||
public static final int INVENTORY_WIDTH = 4;
|
public static final int INVENTORY_WIDTH = 4;
|
||||||
public static final int INVENTORY_HEIGHT = 4;
|
public static final int INVENTORY_HEIGHT = 4;
|
||||||
@@ -142,26 +150,26 @@ public class TurtleBlockEntity extends AbstractComputerBlockEntity implements Ba
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadServer(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void loadServer(ValueInput nbt) {
|
||||||
super.loadServer(nbt, registries);
|
super.loadServer(nbt);
|
||||||
|
|
||||||
// Read inventory
|
// 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());
|
for (var i = 0; i < inventory.size(); i++) inventorySnapshot.set(i, inventory.get(i).copy());
|
||||||
|
|
||||||
// Read state
|
// Read state
|
||||||
brain.readFromNBT(nbt, registries);
|
brain.readFromNBT(nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void saveAdditional(ValueOutput nbt) {
|
||||||
// Write inventory
|
// Write inventory
|
||||||
ContainerHelper.saveAllItems(nbt, inventory, registries);
|
ContainerHelper.saveAllItems(nbt, inventory);
|
||||||
|
|
||||||
// Write brain
|
// Write brain
|
||||||
brain.writeToNBT(nbt, registries);
|
brain.writeToNBT(nbt);
|
||||||
|
|
||||||
super.saveAdditional(nbt, registries);
|
super.saveAdditional(nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -197,13 +205,13 @@ public class TurtleBlockEntity extends AbstractComputerBlockEntity implements Ba
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void removeComponentsFromTag(CompoundTag tag) {
|
public void removeComponentsFromTag(ValueOutput tag) {
|
||||||
super.removeComponentsFromTag(tag);
|
super.removeComponentsFromTag(tag);
|
||||||
tag.remove(TurtleBrain.NBT_COLOUR);
|
tag.discard(TurtleBrain.NBT_COLOUR);
|
||||||
tag.remove(TurtleBrain.NBT_FUEL);
|
tag.discard(TurtleBrain.NBT_FUEL);
|
||||||
tag.remove(TurtleBrain.NBT_OVERLAY);
|
tag.discard(TurtleBrain.NBT_OVERLAY);
|
||||||
tag.remove(TurtleBrain.NBT_LEFT_UPGRADE);
|
tag.discard(TurtleBrain.NBT_LEFT_UPGRADE);
|
||||||
tag.remove(TurtleBrain.NBT_RIGHT_UPGRADE);
|
tag.discard(TurtleBrain.NBT_RIGHT_UPGRADE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -301,17 +309,19 @@ public class TurtleBlockEntity extends AbstractComputerBlockEntity implements Ba
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
|
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
|
||||||
var nbt = super.getUpdateTag(registries);
|
try (var problems = new ProblemReporter.ScopedCollector(problemPath(), LOG)) {
|
||||||
if (label != null) nbt.putString(NBT_LABEL, label);
|
var nbt = TagValueOutput.createWithContext(problems, registries);
|
||||||
brain.writeDescription(nbt, registries);
|
if (label != null) nbt.putString(NBT_LABEL, label);
|
||||||
return nbt;
|
brain.writeDescription(nbt);
|
||||||
|
return nbt.buildResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadClient(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void loadClient(ValueInput nbt) {
|
||||||
super.loadClient(nbt, registries);
|
super.loadClient(nbt);
|
||||||
label = nbt.getStringOr(NBT_LABEL, null);
|
label = nbt.getStringOr(NBT_LABEL, null);
|
||||||
brain.readDescription(nbt, registries);
|
brain.readDescription(nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Privates
|
// Privates
|
||||||
|
@@ -23,17 +23,15 @@ import dan200.computercraft.shared.container.InventoryDelegate;
|
|||||||
import dan200.computercraft.shared.turtle.blocks.TurtleBlockEntity;
|
import dan200.computercraft.shared.turtle.blocks.TurtleBlockEntity;
|
||||||
import dan200.computercraft.shared.util.BlockEntityHelpers;
|
import dan200.computercraft.shared.util.BlockEntityHelpers;
|
||||||
import dan200.computercraft.shared.util.Holiday;
|
import dan200.computercraft.shared.util.Holiday;
|
||||||
import dan200.computercraft.shared.util.NBTUtil;
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
import net.minecraft.core.HolderLookup;
|
|
||||||
import net.minecraft.core.component.DataComponentPatch;
|
import net.minecraft.core.component.DataComponentPatch;
|
||||||
import net.minecraft.core.particles.ParticleTypes;
|
import net.minecraft.core.particles.ParticleTypes;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.tags.FluidTags;
|
import net.minecraft.tags.FluidTags;
|
||||||
|
import net.minecraft.util.ExtraCodecs;
|
||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.MoverType;
|
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.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.material.PushReaction;
|
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.AABB;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.jspecify.annotations.Nullable;
|
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 java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static dan200.computercraft.shared.util.WaterloggableHelpers.WATERLOGGED;
|
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.
|
* Read common data for saving and client synchronisation.
|
||||||
*
|
*
|
||||||
* @param nbt The tag to read from
|
* @param nbt The tag to read from
|
||||||
* @param registries The current registries.
|
|
||||||
*/
|
*/
|
||||||
private void readCommon(CompoundTag nbt, HolderLookup.Provider registries) {
|
private void readCommon(ValueInput nbt) {
|
||||||
// Read fields
|
// Read fields
|
||||||
colourHex = nbt.getIntOr(NBT_COLOUR, -1);
|
colourHex = nbt.getIntOr(NBT_COLOUR, -1);
|
||||||
fuelLevel = nbt.getIntOr(NBT_FUEL, 0);
|
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
|
// Read upgrades
|
||||||
setUpgradeDirect(TurtleSide.LEFT, NBTUtil.decodeFrom(TurtleUpgrades.instance().upgradeDataCodec(), registries, nbt, NBT_LEFT_UPGRADE));
|
setUpgradeDirect(TurtleSide.LEFT, nbt.read(NBT_LEFT_UPGRADE, TurtleUpgrades.instance().upgradeDataCodec()).orElse(null));
|
||||||
setUpgradeDirect(TurtleSide.RIGHT, NBTUtil.decodeFrom(TurtleUpgrades.instance().upgradeDataCodec(), registries, nbt, NBT_RIGHT_UPGRADE));
|
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);
|
nbt.putInt(NBT_FUEL, fuelLevel);
|
||||||
if (colourHex != -1) nbt.putInt(NBT_COLOUR, colourHex);
|
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
|
// Write upgrades
|
||||||
NBTUtil.encodeTo(TurtleUpgrades.instance().upgradeDataCodec(), registries, nbt, NBT_LEFT_UPGRADE, getUpgradeWithData(TurtleSide.LEFT));
|
nbt.storeNullable(NBT_LEFT_UPGRADE, TurtleUpgrades.instance().upgradeDataCodec(), getUpgradeWithData(TurtleSide.LEFT));
|
||||||
NBTUtil.encodeTo(TurtleUpgrades.instance().upgradeDataCodec(), registries, nbt, NBT_RIGHT_UPGRADE, getUpgradeWithData(TurtleSide.RIGHT));
|
nbt.storeNullable(NBT_RIGHT_UPGRADE, TurtleUpgrades.instance().upgradeDataCodec(), getUpgradeWithData(TurtleSide.RIGHT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readFromNBT(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void readFromNBT(ValueInput nbt) {
|
||||||
readCommon(nbt, registries);
|
readCommon(nbt);
|
||||||
|
|
||||||
// Read state
|
// Read state
|
||||||
selectedSlot = nbt.getIntOr(NBT_SLOT, 0);
|
selectedSlot = nbt.getIntOr(NBT_SLOT, 0);
|
||||||
|
|
||||||
// Read owner
|
// Read owner
|
||||||
var owner = nbt.getCompound("Owner").orElse(null);
|
owningPlayer = nbt.read("Owner", ExtraCodecs.GAME_PROFILE).orElse(null);
|
||||||
if (owner != null) {
|
|
||||||
owningPlayer = new GameProfile(
|
|
||||||
new UUID(owner.getLongOr("UpperId", 0), owner.getLongOr("LowerId", 0)),
|
|
||||||
owner.getStringOr("Name", "")
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
owningPlayer = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeToNBT(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void writeToNBT(ValueOutput nbt) {
|
||||||
writeCommon(nbt, registries);
|
writeCommon(nbt);
|
||||||
|
|
||||||
// Write state
|
// Write state
|
||||||
nbt.putInt(NBT_SLOT, selectedSlot);
|
nbt.putInt(NBT_SLOT, selectedSlot);
|
||||||
|
nbt.storeNullable("Owner", ExtraCodecs.GAME_PROFILE, owningPlayer);
|
||||||
// Write owner
|
// TODO(1.21.6): Data fixer for this.
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readDescription(CompoundTag nbt, HolderLookup.Provider registries) {
|
public void readDescription(ValueInput nbt) {
|
||||||
readCommon(nbt, registries);
|
readCommon(nbt);
|
||||||
|
|
||||||
// Animation
|
// Animation
|
||||||
var anim = TurtleAnimation.values()[nbt.getIntOr("Animation", 0)];
|
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) {
|
public void writeDescription(ValueOutput nbt) {
|
||||||
writeCommon(nbt, registries);
|
writeCommon(nbt);
|
||||||
nbt.putInt("Animation", animation.ordinal());
|
nbt.putInt("Animation", animation.ordinal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -214,7 +214,7 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
|||||||
var baseDamage = (float) player.getAttributeValue(Attributes.ATTACK_DAMAGE) * spec.damageMultiplier();
|
var baseDamage = (float) player.getAttributeValue(Attributes.ATTACK_DAMAGE) * spec.damageMultiplier();
|
||||||
var tool = player.getWeaponItem();
|
var tool = player.getWeaponItem();
|
||||||
var source = player.damageSources().playerAttack(player);
|
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 this is a projectile, attempt to deflect it instead.
|
||||||
if (entity.getType().is(EntityTypeTags.REDIRECTABLE_PROJECTILE) && entity instanceof Projectile projectile &&
|
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.
|
// Compute the total damage, and deal it out.
|
||||||
var damage = baseDamage + bonusDamage + tool.getItem().getAttackDamageBonus(entity, baseDamage, source);
|
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
|
// 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
|
// 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 (knockBack > 0) {
|
||||||
if (entity instanceof LivingEntity target) {
|
if (entity instanceof LivingEntity target) {
|
||||||
target.knockback(knockBack * 0.5, -direction.getStepX(), -direction.getStepZ());
|
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);
|
var didHurt = entity instanceof LivingEntity target && tool.hurtEnemy(target, player);
|
||||||
|
|
||||||
// Apply remaining enchantments
|
// Apply remaining enchantments
|
||||||
EnchantmentHelper.doPostAttackEffects(player.serverLevel(), entity, source);
|
EnchantmentHelper.doPostAttackEffects(player.level(), entity, source);
|
||||||
|
|
||||||
// Damage the original item stack.
|
// Damage the original item stack.
|
||||||
if (!tool.isEmpty() && entity instanceof LivingEntity living && didHurt) {
|
if (!tool.isEmpty() && entity instanceof LivingEntity living && didHurt) {
|
||||||
|
@@ -6,9 +6,7 @@ package dan200.computercraft.shared.util;
|
|||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.io.BaseEncoding;
|
import com.google.common.io.BaseEncoding;
|
||||||
import com.mojang.serialization.Codec;
|
|
||||||
import dan200.computercraft.core.util.Nullability;
|
import dan200.computercraft.core.util.Nullability;
|
||||||
import net.minecraft.core.HolderLookup;
|
|
||||||
import net.minecraft.nbt.*;
|
import net.minecraft.nbt.*;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -30,14 +28,6 @@ public final class NBTUtil {
|
|||||||
private NBTUtil() {
|
private NBTUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> @Nullable T decodeFrom(Codec<T> codec, HolderLookup.Provider registries, CompoundTag tag, String key) {
|
|
||||||
return tag.read(key, codec, registries.createSerializationContext(NbtOps.INSTANCE)).orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> void encodeTo(Codec<T> 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) {
|
public static @Nullable Object toLua(@Nullable Tag tag) {
|
||||||
if (tag == null) return null;
|
if (tag == null) return null;
|
||||||
|
|
||||||
|
@@ -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/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/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;
|
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;
|
||||||
|
@@ -27,6 +27,12 @@ accessible field net/minecraft/client/sounds/SoundEngine executor Lnet/minecraft
|
|||||||
# Turtle model
|
# Turtle model
|
||||||
accessible class net/minecraft/util/datafix/fixes/ItemStackComponentizationFix$ItemStackData
|
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.
|
# 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_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;
|
accessible field net/minecraft/client/data/models/BlockModelGenerators ROTATION_HORIZONTAL_FACING Lnet/minecraft/client/data/models/blockstates/PropertyDispatch;
|
||||||
|
@@ -7,7 +7,7 @@ package dan200.computercraft.shared.computer.terminal;
|
|||||||
import dan200.computercraft.api.lua.LuaValues;
|
import dan200.computercraft.api.lua.LuaValues;
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import dan200.computercraft.test.core.CallCounter;
|
import dan200.computercraft.test.core.CallCounter;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import dan200.computercraft.test.shared.SerialisationUtils;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static dan200.computercraft.test.core.terminal.TerminalMatchers.*;
|
import static dan200.computercraft.test.core.terminal.TerminalMatchers.*;
|
||||||
@@ -24,13 +24,12 @@ class NetworkedTerminalTest {
|
|||||||
writeTerminal.setTextColour(3);
|
writeTerminal.setTextColour(3);
|
||||||
writeTerminal.setBackgroundColour(5);
|
writeTerminal.setBackgroundColour(5);
|
||||||
|
|
||||||
var nbt = new CompoundTag();
|
var nbt = SerialisationUtils.writeNBT(writeTerminal::writeToNBT);
|
||||||
writeTerminal.writeToNBT(nbt);
|
|
||||||
|
|
||||||
var callCounter = new CallCounter();
|
var callCounter = new CallCounter();
|
||||||
var readTerminal = new NetworkedTerminal(2, 1, true, callCounter);
|
var readTerminal = new NetworkedTerminal(2, 1, true, callCounter);
|
||||||
|
|
||||||
readTerminal.readFromNBT(nbt);
|
SerialisationUtils.readNBT(nbt, readTerminal::readFromNBT);
|
||||||
|
|
||||||
assertThat(readTerminal, allOf(
|
assertThat(readTerminal, allOf(
|
||||||
textMatches(new String[]{ "hi", }),
|
textMatches(new String[]{ "hi", }),
|
||||||
@@ -49,12 +48,11 @@ class NetworkedTerminalTest {
|
|||||||
void testReadWriteNBTEmpty() {
|
void testReadWriteNBTEmpty() {
|
||||||
var terminal = new NetworkedTerminal(0, 0, true);
|
var terminal = new NetworkedTerminal(0, 0, true);
|
||||||
|
|
||||||
var nbt = new CompoundTag();
|
var nbt = SerialisationUtils.writeNBT(terminal::writeToNBT);
|
||||||
terminal.writeToNBT(nbt);
|
|
||||||
|
|
||||||
var callCounter = new CallCounter();
|
var callCounter = new CallCounter();
|
||||||
terminal = new NetworkedTerminal(0, 1, true, callCounter);
|
terminal = new NetworkedTerminal(0, 1, true, callCounter);
|
||||||
terminal.readFromNBT(nbt);
|
SerialisationUtils.readNBT(nbt, terminal::readFromNBT);
|
||||||
|
|
||||||
assertThat(terminal, allOf(
|
assertThat(terminal, allOf(
|
||||||
textMatches(new String[]{ "", }),
|
textMatches(new String[]{ "", }),
|
||||||
|
@@ -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<ValueOutput> generate) {
|
||||||
|
var output = TagValueOutput.createWithoutContext(ProblemReporter.DISCARDING);
|
||||||
|
generate.accept(output);
|
||||||
|
return output.buildResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void readNBT(CompoundTag tag, Consumer<ValueInput> generate) {
|
||||||
|
generate.accept(TagValueInput.create(ProblemReporter.DISCARDING, RegistryAccess.EMPTY, tag));
|
||||||
|
}
|
||||||
|
}
|
@@ -16,12 +16,9 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
|||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
import dan200.computercraft.gametest.core.TestHooks;
|
import dan200.computercraft.gametest.core.TestHooks;
|
||||||
import dan200.computercraft.shared.util.PrettyJsonWriter;
|
import dan200.computercraft.shared.util.PrettyJsonWriter;
|
||||||
import dan200.computercraft.shared.util.RegistryHelper;
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
import net.minecraft.network.chat.Component;
|
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.RecipeType;
|
||||||
import net.minecraft.world.item.crafting.display.ShapedCraftingRecipeDisplay;
|
import net.minecraft.world.item.crafting.display.ShapedCraftingRecipeDisplay;
|
||||||
import net.minecraft.world.item.crafting.display.ShapelessCraftingRecipeDisplay;
|
import net.minecraft.world.item.crafting.display.ShapelessCraftingRecipeDisplay;
|
||||||
@@ -60,8 +57,8 @@ public class Exporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RenderSystem.assertOnRenderThread();
|
RenderSystem.assertOnRenderThread();
|
||||||
try (var renderer = new ImageRenderer()) {
|
try {
|
||||||
export(output, renderer);
|
export(output);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new UncheckedIOException(e);
|
throw new UncheckedIOException(e);
|
||||||
}
|
}
|
||||||
@@ -69,7 +66,7 @@ public class Exporter {
|
|||||||
Minecraft.getInstance().gui.getChat().addMessage(Component.literal("Export finished!"));
|
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();
|
var dump = new JsonDump();
|
||||||
|
|
||||||
// First find all CC items
|
// First find all CC items
|
||||||
@@ -121,21 +118,6 @@ public class Exporter {
|
|||||||
var itemDir = root.resolve("items");
|
var itemDir = root.resolve("items");
|
||||||
if (Files.exists(itemDir)) MoreFiles.deleteRecursively(itemDir, RecursiveDeleteOption.ALLOW_INSECURE);
|
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)) {
|
try (Writer writer = Files.newBufferedWriter(root.resolve("index.json")); var jsonWriter = new PrettyJsonWriter(writer)) {
|
||||||
GSON.toJson(dump, JsonDump.class, jsonWriter);
|
GSON.toJson(dump, JsonDump.class, jsonWriter);
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -6,6 +6,7 @@ package dan200.computercraft.gametest.core;
|
|||||||
|
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import dan200.computercraft.api.ComputerCraftAPI;
|
import dan200.computercraft.api.ComputerCraftAPI;
|
||||||
|
import dan200.computercraft.mixin.gametest.ArmorStandAccessor;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.util.NonNegativeId;
|
import dan200.computercraft.shared.util.NonNegativeId;
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
@@ -42,7 +43,7 @@ class CCTestCommand {
|
|||||||
dispatcher.register(choice("cctest")
|
dispatcher.register(choice("cctest")
|
||||||
.then(literal("marker").executes(context -> {
|
.then(literal("marker").executes(context -> {
|
||||||
var player = context.getSource().getPlayerOrException();
|
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");
|
if (pos == null) return error(context.getSource(), "No nearby test");
|
||||||
|
|
||||||
var test = player.level().getBlockEntity(pos, BlockEntityType.TEST_INSTANCE_BLOCK)
|
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");
|
if (test == null) return error(context.getSource(), "No nearby structure block");
|
||||||
|
|
||||||
// Kill the existing armor stand
|
// 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()))
|
level.getEntities(EntityType.ARMOR_STAND, x -> x.isAlive() && x.getName().getString().equals(test.location().getPath()))
|
||||||
.forEach(e -> e.kill(level));
|
.forEach(e -> e.kill(level));
|
||||||
|
|
||||||
@@ -59,7 +60,8 @@ class CCTestCommand {
|
|||||||
nbt.putBoolean("Marker", true);
|
nbt.putBoolean("Marker", true);
|
||||||
nbt.putBoolean("Invisible", true);
|
nbt.putBoolean("Invisible", true);
|
||||||
var armorStand = new ArmorStand(EntityType.ARMOR_STAND, level);
|
var armorStand = new ArmorStand(EntityType.ARMOR_STAND, level);
|
||||||
armorStand.readAdditionalSaveData(nbt);
|
armorStand.setInvisible(true);
|
||||||
|
((ArmorStandAccessor) armorStand).computercraft$setMarker(true);
|
||||||
armorStand.copyPosition(player);
|
armorStand.copyPosition(player);
|
||||||
armorStand.setCustomName(Component.literal(test.location().getPath()));
|
armorStand.setCustomName(Component.literal(test.location().getPath()));
|
||||||
level.addFreshEntity(armorStand);
|
level.addFreshEntity(armorStand);
|
||||||
@@ -70,7 +72,7 @@ class CCTestCommand {
|
|||||||
var item = context.getArgument("item", ItemInput.class);
|
var item = context.getArgument("item", ItemInput.class);
|
||||||
|
|
||||||
var player = context.getSource().getPlayerOrException();
|
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");
|
if (pos == null) return error(context.getSource(), "No nearby test");
|
||||||
|
|
||||||
var test = player.level().getBlockEntity(pos, BlockEntityType.TEST_INSTANCE_BLOCK)
|
var test = player.level().getBlockEntity(pos, BlockEntityType.TEST_INSTANCE_BLOCK)
|
||||||
|
@@ -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);
|
||||||
|
}
|
@@ -116,7 +116,7 @@ class ClientTestHelper {
|
|||||||
val minecraft: Minecraft = Minecraft.getInstance()
|
val minecraft: Minecraft = Minecraft.getInstance()
|
||||||
|
|
||||||
fun screenshot(name: String, callback: () -> Unit = {}) {
|
fun screenshot(name: String, callback: () -> Unit = {}) {
|
||||||
Screenshot.grab(minecraft.gameDirectory, name, minecraft.mainRenderTarget) { callback() }
|
Screenshot.grab(minecraft.gameDirectory, name, minecraft.mainRenderTarget, 1) { callback() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -15,6 +15,7 @@ import net.minecraft.client.gui.screens.TitleScreen
|
|||||||
import net.minecraft.client.tutorial.TutorialSteps
|
import net.minecraft.client.tutorial.TutorialSteps
|
||||||
import net.minecraft.core.registries.Registries
|
import net.minecraft.core.registries.Registries
|
||||||
import net.minecraft.gametest.framework.*
|
import net.minecraft.gametest.framework.*
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.server.MinecraftServer
|
import net.minecraft.server.MinecraftServer
|
||||||
import net.minecraft.server.level.ParticleStatus
|
import net.minecraft.server.level.ParticleStatus
|
||||||
import net.minecraft.sounds.SoundSource
|
import net.minecraft.sounds.SoundSource
|
||||||
@@ -196,8 +197,8 @@ object ClientTestHooks {
|
|||||||
val minecraft = Minecraft.getInstance()
|
val minecraft = Minecraft.getInstance()
|
||||||
minecraft.execute {
|
minecraft.execute {
|
||||||
LOG.info("Stopping client.")
|
LOG.info("Stopping client.")
|
||||||
minecraft.level!!.disconnect()
|
minecraft.level!!.disconnect(Component.empty())
|
||||||
minecraft.disconnect()
|
minecraft.disconnectWithSavingScreen()
|
||||||
minecraft.stop()
|
minecraft.stop()
|
||||||
|
|
||||||
exitProcess(
|
exitProcess(
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
|
"ArmorStandAccessor",
|
||||||
"GameTestHelperAccessor",
|
"GameTestHelperAccessor",
|
||||||
"GameTestInfoAccessor",
|
"GameTestInfoAccessor",
|
||||||
"GameTestSequenceAccessor",
|
"GameTestSequenceAccessor",
|
||||||
|
@@ -19,20 +19,21 @@ import dan200.computercraft.shared.config.ConfigSpec;
|
|||||||
import dan200.computercraft.shared.network.NetworkMessages;
|
import dan200.computercraft.shared.network.NetworkMessages;
|
||||||
import dan200.computercraft.shared.network.client.ClientNetworkContext;
|
import dan200.computercraft.shared.network.client.ClientNetworkContext;
|
||||||
import dan200.computercraft.shared.platform.FabricConfigFile;
|
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.ClientCommandRegistrationCallback;
|
||||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
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.event.lifecycle.v1.ClientTickEvents;
|
||||||
import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin;
|
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.model.loading.v1.UnbakedExtraModel;
|
||||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
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.fabric.api.client.rendering.v1.WorldRenderEvents;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.color.item.ItemTintSources;
|
import net.minecraft.client.color.item.ItemTintSources;
|
||||||
import net.minecraft.client.gui.screens.MenuScreens;
|
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.ItemModels;
|
||||||
import net.minecraft.client.renderer.item.properties.conditional.ConditionalItemModelProperties;
|
import net.minecraft.client.renderer.item.properties.conditional.ConditionalItemModelProperties;
|
||||||
import net.minecraft.client.renderer.item.properties.select.SelectItemModelProperties;
|
import net.minecraft.client.renderer.item.properties.select.SelectItemModelProperties;
|
||||||
@@ -74,11 +75,13 @@ public class ComputerCraftClient {
|
|||||||
}, state)
|
}, state)
|
||||||
);
|
);
|
||||||
|
|
||||||
BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.COMPUTER_NORMAL.get(), RenderType.cutout());
|
BlockRenderLayerMap.putBlock(ModRegistry.Blocks.COMPUTER_NORMAL.get(), ChunkSectionLayer.CUTOUT);
|
||||||
BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.COMPUTER_COMMAND.get(), RenderType.cutout());
|
BlockRenderLayerMap.putBlock(ModRegistry.Blocks.COMPUTER_COMMAND.get(), ChunkSectionLayer.CUTOUT);
|
||||||
BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.COMPUTER_ADVANCED.get(), RenderType.cutout());
|
BlockRenderLayerMap.putBlock(ModRegistry.Blocks.COMPUTER_ADVANCED.get(), ChunkSectionLayer.CUTOUT);
|
||||||
BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.MONITOR_NORMAL.get(), RenderType.cutout());
|
BlockRenderLayerMap.putBlock(ModRegistry.Blocks.MONITOR_NORMAL.get(), ChunkSectionLayer.CUTOUT);
|
||||||
BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.MONITOR_ADVANCED.get(), RenderType.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());
|
ClientTickEvents.START_CLIENT_TICK.register(client -> ClientHooks.onTick());
|
||||||
// This isn't 100% consistent with Forge, but not worth a mixin.
|
// This isn't 100% consistent with Forge, but not worth a mixin.
|
||||||
|
@@ -15,6 +15,7 @@ import org.spongepowered.asm.mixin.Unique;
|
|||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import static dan200.computercraft.core.util.Nullability.assertNonNull;
|
import static dan200.computercraft.core.util.Nullability.assertNonNull;
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ class SoundEngineMixin {
|
|||||||
|
|
||||||
@Inject(method = "play", at = @At(value = "HEAD"))
|
@Inject(method = "play", at = @At(value = "HEAD"))
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private void playSound(SoundInstance sound, CallbackInfo ci) {
|
private void playSound(SoundInstance sound, CallbackInfoReturnable<SoundEngine.PlayResult> ci) {
|
||||||
self = (SoundEngine) (Object) this;
|
self = (SoundEngine) (Object) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,12 +18,10 @@ import net.minecraft.client.data.models.ItemModelGenerators;
|
|||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
import net.minecraft.core.HolderLookup;
|
import net.minecraft.core.HolderLookup;
|
||||||
import net.minecraft.core.RegistrySetBuilder;
|
import net.minecraft.core.RegistrySetBuilder;
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
|
||||||
import net.minecraft.data.DataProvider;
|
import net.minecraft.data.DataProvider;
|
||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
import net.minecraft.data.tags.TagsProvider;
|
import net.minecraft.data.tags.TagsProvider;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.level.block.Block;
|
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) {
|
return addWithRegistries((out, registries) -> new FabricTagProvider.BlockTagProvider(out, registries) {
|
||||||
@Override
|
@Override
|
||||||
protected void addTags(HolderLookup.Provider registries) {
|
protected void addTags(HolderLookup.Provider registries) {
|
||||||
tags.accept(x -> new TagProvider.TagAppender<>(BuiltInRegistries.BLOCK, getOrCreateRawBuilder(x)));
|
tags.accept(this::valueLookupBuilder);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TagsProvider<Item> itemTags(Consumer<TagProvider.ItemTagConsumer> tags, TagsProvider<Block> blocks) {
|
public TagsProvider<Item> itemTags(Consumer<TagProvider.TagConsumer<Item>> tags) {
|
||||||
return addWithRegistries((out, registries) -> new FabricTagProvider.ItemTagProvider(out, registries, (FabricTagProvider.BlockTagProvider) blocks) {
|
return addWithRegistries((out, registries) -> new FabricTagProvider.ItemTagProvider(out, registries) {
|
||||||
@Override
|
@Override
|
||||||
protected void addTags(HolderLookup.Provider registries) {
|
protected void addTags(HolderLookup.Provider registries) {
|
||||||
var self = this;
|
tags.accept(this::valueLookupBuilder);
|
||||||
tags.accept(new TagProvider.ItemTagConsumer() {
|
|
||||||
@Override
|
|
||||||
public TagProvider.TagAppender<Item> tag(TagKey<Item> tag) {
|
|
||||||
return new TagProvider.TagAppender<>(BuiltInRegistries.ITEM, getOrCreateRawBuilder(tag));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void copy(TagKey<Block> block, TagKey<Item> item) {
|
|
||||||
self.copy(block, item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ import net.minecraft.server.level.ServerLevel;
|
|||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.item.ItemEntity;
|
import net.minecraft.world.entity.item.ItemEntity;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
@@ -17,12 +18,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
|||||||
@Mixin(Entity.class)
|
@Mixin(Entity.class)
|
||||||
class EntityMixin {
|
class EntityMixin {
|
||||||
@Inject(
|
@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"),
|
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"),
|
||||||
cancellable = true
|
cancellable = true
|
||||||
)
|
)
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private void spawnAtLocation(ServerLevel level, ItemStack stack, float yOffset, CallbackInfoReturnable<ItemEntity> cb) {
|
private void spawnAtLocation(ServerLevel level, ItemStack stack, Vec3 position, CallbackInfoReturnable<ItemEntity> cb) {
|
||||||
if (CommonHooks.onLivingDrop((Entity) (Object) this, stack)) cb.setReturnValue(null);
|
if (CommonHooks.onLivingDrop((Entity) (Object) this, stack)) cb.setReturnValue(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -49,9 +49,9 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=0.16.10",
|
"fabricloader": ">=0.16.14",
|
||||||
"fabric-api": ">=0.122.0",
|
"fabric-api": ">=0.127.0",
|
||||||
"minecraft": "=1.21.5"
|
"minecraft": "=1.21.6"
|
||||||
},
|
},
|
||||||
"accessWidener": "computercraft.accesswidener"
|
"accessWidener": "computercraft.accesswidener"
|
||||||
}
|
}
|
||||||
|
@@ -96,6 +96,11 @@ public final class ForgeClientRegistry {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void registerPictureInPictureRenderers(RegisterPictureInPictureRenderersEvent event) {
|
||||||
|
ClientRegistry.registerPictureInPictureRenderers(event::register);
|
||||||
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void setupClient(FMLClientSetupEvent event) {
|
public static void setupClient(FMLClientSetupEvent event) {
|
||||||
ClientRegistry.register();
|
ClientRegistry.register();
|
||||||
|
@@ -11,20 +11,18 @@ import net.minecraft.client.data.models.ItemModelGenerators;
|
|||||||
import net.minecraft.client.data.models.ModelProvider;
|
import net.minecraft.client.data.models.ModelProvider;
|
||||||
import net.minecraft.core.HolderLookup;
|
import net.minecraft.core.HolderLookup;
|
||||||
import net.minecraft.core.RegistrySetBuilder;
|
import net.minecraft.core.RegistrySetBuilder;
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
|
||||||
import net.minecraft.data.DataGenerator;
|
import net.minecraft.data.DataGenerator;
|
||||||
import net.minecraft.data.DataProvider;
|
import net.minecraft.data.DataProvider;
|
||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
import net.minecraft.data.tags.ItemTagsProvider;
|
|
||||||
import net.minecraft.data.tags.TagsProvider;
|
import net.minecraft.data.tags.TagsProvider;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.neoforged.bus.api.SubscribeEvent;
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
import net.neoforged.fml.common.EventBusSubscriber;
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
import net.neoforged.neoforge.common.data.BlockTagsProvider;
|
import net.neoforged.neoforge.common.data.BlockTagsProvider;
|
||||||
import net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider;
|
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.common.data.JsonCodecProvider;
|
||||||
import net.neoforged.neoforge.data.event.GatherDataEvent;
|
import net.neoforged.neoforge.data.event.GatherDataEvent;
|
||||||
|
|
||||||
@@ -65,28 +63,17 @@ public class ForgeDataProviders {
|
|||||||
return add(out -> new BlockTagsProvider(out, registries, ComputerCraftAPI.MOD_ID) {
|
return add(out -> new BlockTagsProvider(out, registries, ComputerCraftAPI.MOD_ID) {
|
||||||
@Override
|
@Override
|
||||||
protected void addTags(HolderLookup.Provider registries) {
|
protected void addTags(HolderLookup.Provider registries) {
|
||||||
tags.accept(x -> new TagProvider.TagAppender<>(BuiltInRegistries.BLOCK, getOrCreateRawBuilder(x)));
|
tags.accept(this::tag);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TagsProvider<Item> itemTags(Consumer<TagProvider.ItemTagConsumer> tags, TagsProvider<Block> blocks) {
|
public TagsProvider<Item> itemTags(Consumer<TagProvider.TagConsumer<Item>> tags) {
|
||||||
return add(out -> new ItemTagsProvider(out, registries, blocks.contentsGetter(), ComputerCraftAPI.MOD_ID) {
|
return add(out -> new ItemTagsProvider(out, registries, ComputerCraftAPI.MOD_ID) {
|
||||||
@Override
|
@Override
|
||||||
protected void addTags(HolderLookup.Provider registries) {
|
protected void addTags(HolderLookup.Provider registries) {
|
||||||
var self = this;
|
tags.accept(this::tag);
|
||||||
tags.accept(new TagProvider.ItemTagConsumer() {
|
|
||||||
@Override
|
|
||||||
public TagProvider.TagAppender<Item> tag(TagKey<Item> tag) {
|
|
||||||
return new TagProvider.TagAppender<>(BuiltInRegistries.ITEM, getOrCreateRawBuilder(tag));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void copy(TagKey<Block> block, TagKey<Item> item) {
|
|
||||||
self.copy(block, item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -15,3 +15,12 @@ public com.mojang.blaze3d.audio.Channel pumpBuffers(I)V
|
|||||||
public net.minecraft.client.sounds.SoundEngine executor
|
public net.minecraft.client.sounds.SoundEngine executor
|
||||||
|
|
||||||
public net.minecraft.util.datafix.fixes.ItemStackComponentizationFix$ItemStackData
|
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
|
||||||
|
@@ -26,7 +26,7 @@ CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles a
|
|||||||
[[dependencies.computercraft]]
|
[[dependencies.computercraft]]
|
||||||
modId="neoforge"
|
modId="neoforge"
|
||||||
type="required"
|
type="required"
|
||||||
versionRange="[${neoVersion},21.6)"
|
versionRange="[${neoVersion},21.7)"
|
||||||
ordering="NONE"
|
ordering="NONE"
|
||||||
side="BOTH"
|
side="BOTH"
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user