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