diff --git a/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts b/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts index 7ef28a271..2750566fb 100644 --- a/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts +++ b/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts @@ -4,10 +4,8 @@ /** Default configuration for Fabric projects. */ -import cc.tweaked.gradle.CCTweakedExtension -import cc.tweaked.gradle.CCTweakedPlugin +import cc.tweaked.gradle.* import cc.tweaked.gradle.IdeaRunConfigurations -import cc.tweaked.gradle.MinecraftConfigurations plugins { `java-library` @@ -67,3 +65,9 @@ dependencies { tasks.ideaSyncTask { doLast { IdeaRunConfigurations(project).patch() } } + +tasks.named("checkDependencyConsistency", DependencyCheck::class.java) { + val libs = project.extensions.getByType().named("libs") + // Fabric forces asm to a more recent version + override(libs.findLibrary("asm").get(), "9.7.1") +} diff --git a/gradle.properties b/gradle.properties index f7f78fa35..26ef6f331 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,4 @@ isUnstable=true modVersion=1.113.1 # Minecraft properties: We want to configure this here so we can read it in settings.gradle -mcVersion=1.21.1 +mcVersion=1.21.3 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e5b6c2fd2..fed816303 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,14 +7,14 @@ # 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.102.1+1.21.1" -fabric-loader = "0.15.11" -neoForge = "21.1.9" +fabric-api = "0.106.1+1.21.3" +fabric-loader = "0.16.7" +neoForge = "21.3.0-beta" neoForgeSpi = "8.0.1" mixin = "0.8.5" parchment = "2024.07.28" parchmentMc = "1.21" -yarn = "1.21.1+build.1" +yarn = "1.21.3+build.1" # Core dependencies (these versions are tied to the version Minecraft uses) fastutil = "8.5.12" @@ -62,14 +62,14 @@ checkstyle = "10.14.1" curseForgeGradle = "1.1.18" errorProne-core = "2.27.0" errorProne-plugin = "3.1.0" -fabric-loom = "1.7.1" +fabric-loom = "1.8.10" githubRelease = "2.5.2" gradleVersions = "0.50.0" ideaExt = "1.1.7" illuaminate = "0.1.0-73-g43ee16c" lwjgl = "3.3.3" minotaur = "2.8.7" -neoGradle = "7.0.152" +neoGradle = "7.0.165" nullAway = "0.10.25" shadow = "8.3.1" spotless = "6.23.3" @@ -186,9 +186,9 @@ kotlin = ["kotlin-stdlib", "kotlin-coroutines"] # Minecraft externalMods-common = ["iris-forge", "jei-api", "nightConfig-core", "nightConfig-toml"] externalMods-forge-compile = ["moreRed", "iris-forge", "jei-api"] -externalMods-forge-runtime = ["jei-forge"] +externalMods-forge-runtime = [] externalMods-fabric-compile = ["fabricPermissions", "iris-fabric", "jei-api", "rei-api", "rei-builtin"] -externalMods-fabric-runtime = ["jei-fabric", "modmenu"] +externalMods-fabric-runtime = [] # Testing test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"] diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2c3521197..a4b76b953 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9355b4155..df97d72b8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/projects/common-api/src/client/java/dan200/computercraft/api/client/TransformedModel.java b/projects/common-api/src/client/java/dan200/computercraft/api/client/TransformedModel.java index a632920b4..8ce025488 100644 --- a/projects/common-api/src/client/java/dan200/computercraft/api/client/TransformedModel.java +++ b/projects/common-api/src/client/java/dan200/computercraft/api/client/TransformedModel.java @@ -60,7 +60,7 @@ public record TransformedModel(BakedModel model, Transformation matrix) { } public static TransformedModel of(ItemStack item, Transformation transform) { - var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(item); + var model = Minecraft.getInstance().getItemRenderer().getModel(item, null, null, 0); return new TransformedModel(model, transform); } } diff --git a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModeller.java b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModeller.java index 4adfc8d91..5b9a4e91e 100644 --- a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModeller.java +++ b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModeller.java @@ -48,7 +48,7 @@ public interface TurtleUpgradeModeller { * by other means. * * @return A list of models that this modeller depends on. - * @see UnbakedModel#getDependencies() + * @see UnbakedModel#resolveDependencies(UnbakedModel.Resolver) */ default Stream getDependencies() { return Stream.of(); diff --git a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModellers.java b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModellers.java index 644c0a65a..71066c334 100644 --- a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModellers.java +++ b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModellers.java @@ -38,7 +38,7 @@ final class TurtleUpgradeModellers { @Override public TransformedModel getModel(ITurtleUpgrade upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, DataComponentPatch data) { var stack = upgrade.getUpgradeItem(data); - var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(stack); + var model = Minecraft.getInstance().getItemRenderer().getModel(stack, null, null, 0); if (stack.hasFoil()) model = ClientPlatformHelper.get().createdFoiledModel(model); return new TransformedModel(model, side == TurtleSide.LEFT ? leftTransform : rightTransform); } diff --git a/projects/common/build.gradle.kts b/projects/common/build.gradle.kts index 952639cbf..44a4c9074 100644 --- a/projects/common/build.gradle.kts +++ b/projects/common/build.gradle.kts @@ -15,6 +15,12 @@ sourceSets { main { resources.srcDir("src/generated/resources") } + client { + java { + exclude("dan200/computercraft/client/integration/emi") + exclude("dan200/computercraft/client/integration/jei") + } + } } minecraft { diff --git a/projects/common/src/client/java/dan200/computercraft/client/ClientHooks.java b/projects/common/src/client/java/dan200/computercraft/client/ClientHooks.java index bd45f9310..2bcae77d9 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/ClientHooks.java +++ b/projects/common/src/client/java/dan200/computercraft/client/ClientHooks.java @@ -11,7 +11,6 @@ import dan200.computercraft.client.pocket.ClientPocketComputers; import dan200.computercraft.client.render.CableHighlightRenderer; import dan200.computercraft.client.render.PocketItemRenderer; import dan200.computercraft.client.render.PrintoutItemRenderer; -import dan200.computercraft.client.render.monitor.MonitorBlockEntityRenderer; import dan200.computercraft.client.render.monitor.MonitorHighlightRenderer; import dan200.computercraft.client.render.monitor.MonitorRenderState; import dan200.computercraft.client.sound.SpeakerManager; @@ -29,11 +28,11 @@ import dan200.computercraft.shared.util.WorldUtil; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.state.ItemFrameRenderState; import net.minecraft.client.sounds.AudioStream; import net.minecraft.client.sounds.SoundEngine; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.decoration.ItemFrame; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; @@ -88,7 +87,7 @@ public final class ClientHooks { return false; } - public static boolean onRenderItemFrame(PoseStack transform, MultiBufferSource render, ItemFrame frame, ItemStack stack, int light) { + public static boolean onRenderItemFrame(PoseStack transform, MultiBufferSource render, ItemFrameRenderState frame, ItemStack stack, int light) { if (stack.getItem() instanceof PrintoutItem) { PrintoutItemRenderer.onRenderInFrame(transform, render, frame, stack, light); return true; @@ -132,17 +131,6 @@ public final class ClientHooks { if (upgrade != null) out.accept(String.format("Upgrade[%s]: %s", side, upgrade.holder().key().location())); } - /** - * Add additional information about the game to the debug screen. - * - * @param addText A callback which adds a single line of text. - */ - public static void addGameDebugInfo(Consumer addText) { - if (MonitorBlockEntityRenderer.hasRenderedThisFrame() && Minecraft.getInstance().getDebugOverlay().showDebugScreen()) { - addText.accept("[CC:T] Monitor renderer: " + MonitorBlockEntityRenderer.currentRenderer()); - } - } - public static @Nullable BlockState getBlockBreakingState(BlockState state, BlockPos pos) { // Only apply to cables which have both a cable and modem if (state.getBlock() != ModRegistry.Blocks.CABLE.get() diff --git a/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java b/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java index 46711d758..3dfb92444 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java +++ b/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java @@ -14,7 +14,6 @@ import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller; import dan200.computercraft.client.gui.*; import dan200.computercraft.client.pocket.ClientPocketComputers; import dan200.computercraft.client.render.CustomLecternRenderer; -import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.client.render.TurtleBlockEntityRenderer; import dan200.computercraft.client.render.monitor.MonitorBlockEntityRenderer; import dan200.computercraft.client.turtle.TurtleModemModeller; @@ -34,7 +33,6 @@ 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.multiplayer.ClientLevel; -import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; import net.minecraft.client.renderer.item.ClampedItemPropertyFunction; @@ -42,8 +40,7 @@ import net.minecraft.client.renderer.item.ItemProperties; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.PreparableReloadListener; -import net.minecraft.server.packs.resources.ResourceProvider; -import net.minecraft.util.FastColor; +import net.minecraft.util.ARGB; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.MenuType; @@ -54,7 +51,6 @@ import net.minecraft.world.level.ItemLike; import javax.annotation.Nullable; import java.io.File; -import java.io.IOException; import java.util.Collection; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -182,7 +178,7 @@ public final class ClientRegistry { case 1 -> DyedItemColor.getOrDefault(stack, -1); // Frame colour case 2 -> { // Light colour var computer = ClientPocketComputers.get(stack); - yield computer == null || computer.getLightState() == -1 ? Colour.BLACK.getARGB() : FastColor.ARGB32.opaque(computer.getLightState()); + yield computer == null || computer.getLightState() == -1 ? Colour.BLACK.getARGB() : ARGB.opaque(computer.getLightState()); } }; } @@ -191,10 +187,6 @@ public final class ClientRegistry { return layer == 0 ? DyedItemColor.getOrDefault(stack, -1) : -1; } - public static void registerShaders(ResourceProvider resources, BiConsumer> load) throws IOException { - RenderTypes.registerShaders(resources, load); - } - private record UnclampedPropertyFunction( ClampedItemPropertyFunction function ) implements ClampedItemPropertyFunction { diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java index 6e4f39020..9d8485bed 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java @@ -99,7 +99,7 @@ public abstract class AbstractComputerScreen ext if (uploadNagDeadline != Long.MAX_VALUE && Util.getNanos() >= uploadNagDeadline) { new ItemToast(minecraft(), displayStack, NO_RESPONSE_TITLE, NO_RESPONSE_MSG, ItemToast.TRANSFER_NO_RESPONSE_TOKEN) - .showOrReplace(minecraft().getToasts()); + .showOrReplace(minecraft().getToastManager()); uploadNagDeadline = Long.MAX_VALUE; } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java index b398da342..45896e151 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java @@ -7,7 +7,6 @@ package dan200.computercraft.client.gui; import dan200.computercraft.client.gui.widgets.ComputerSidebar; import dan200.computercraft.client.gui.widgets.TerminalWidget; import dan200.computercraft.client.render.ComputerBorderRenderer; -import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.client.render.SpriteRenderer; import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu; import net.minecraft.client.gui.GuiGraphics; @@ -40,14 +39,14 @@ public final class ComputerScreen extends Abstra public void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { // Draw a border around the terminal var terminal = getTerminal(); - var spriteRenderer = SpriteRenderer.createForGui(graphics, RenderTypes.GUI_SPRITES); - var computerTextures = GuiSprites.getComputerTextures(family); - ComputerBorderRenderer.render( - spriteRenderer, computerTextures, - terminal.getX(), terminal.getY(), terminal.getWidth(), terminal.getHeight(), false - ); - ComputerSidebar.renderBackground(spriteRenderer, computerTextures, leftPos, topPos + sidebarYOffset); - graphics.flush(); // Flush to ensure background textures are drawn before foreground. + SpriteRenderer.inGui(graphics, spriteRenderer -> { + var computerTextures = GuiSprites.getComputerTextures(family); + ComputerBorderRenderer.render( + spriteRenderer, computerTextures, + terminal.getX(), terminal.getY(), terminal.getWidth(), terminal.getHeight(), false + ); + ComputerSidebar.renderBackground(spriteRenderer, computerTextures, leftPos, topPos + sidebarYOffset); + }); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java index 70a8ed8db..b9f8d1884 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java @@ -7,6 +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.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; @@ -23,7 +24,7 @@ public class DiskDriveScreen extends AbstractContainerScreen { @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { - graphics.blit(BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight); + graphics.blit(RenderType::guiTextured, BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight, 256, 256); } @Override diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java b/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java index e6025c221..21bebbd72 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java @@ -35,8 +35,8 @@ public final class GuiSprites extends TextureAtlasHolder { private static ButtonTextures button(String name) { return new ButtonTextures( - ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name), - ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name + "_hover") + ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "buttons/" + name), + ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "buttons/" + name + "_hover") ); } @@ -97,12 +97,8 @@ public final class GuiSprites extends TextureAtlasHolder { * @param active The texture for the button when it is active (hovered or focused). */ public record ButtonTextures(ResourceLocation normal, ResourceLocation active) { - public TextureAtlasSprite get(boolean active) { - return GuiSprites.get(active ? this.active : normal); - } - - public Stream textures() { - return Stream.of(normal, active); + public ResourceLocation get(boolean active) { + return active ? this.active : normal; } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java b/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java index b3bfd4294..9adad3c34 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java @@ -5,9 +5,11 @@ package dan200.computercraft.client.gui; import net.minecraft.client.Minecraft; +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.ToastComponent; +import net.minecraft.client.gui.components.toasts.ToastManager; +import net.minecraft.client.renderer.RenderType; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.FormattedCharSequence; @@ -35,8 +37,9 @@ public class ItemToast implements Toast { private final Object token; private final int width; - private boolean isNew = true; - private long firstDisplay; + private boolean changed = true; + private long lastChanged; + private Visibility visibility = Visibility.HIDE; public ItemToast(Minecraft minecraft, ItemStack stack, Component title, Component message, Object token) { this.stack = stack; @@ -48,10 +51,10 @@ public class ItemToast implements Toast { width = Math.max(MAX_LINE_SIZE, this.message.stream().mapToInt(font::width).max().orElse(MAX_LINE_SIZE)) + MARGIN * 3 + IMAGE_SIZE; } - public void showOrReplace(ToastComponent toasts) { + public void showOrReplace(ToastManager toasts) { var existing = toasts.getToast(ItemToast.class, getToken()); if (existing != null) { - existing.isNew = true; + existing.changed = true; } else { toasts.addToast(this); } @@ -73,28 +76,22 @@ public class ItemToast implements Toast { } @Override - public Visibility render(GuiGraphics graphics, ToastComponent component, long time) { - if (isNew) { + public Visibility getWantedVisibility() { + return visibility; + } - firstDisplay = time; - isNew = false; + @Override + public void update(ToastManager toastManager, long time) { + if (changed) { + lastChanged = time; + changed = false; } + visibility = time - lastChanged < DISPLAY_TIME * toastManager.getNotificationDisplayTimeMultiplier() ? Visibility.SHOW : Visibility.HIDE; + } - if (width == 160 && message.size() <= 1) { - graphics.blitSprite(TEXTURE, 0, 0, width, height()); - } else { - - var height = height(); - - var bottom = Math.min(4, height - 28); - renderBackgroundRow(graphics, width, 0, 0, 28); - - for (var i = 28; i < height - bottom; i += 10) { - renderBackgroundRow(graphics, width, 16, i, Math.min(16, height - i - bottom)); - } - - renderBackgroundRow(graphics, width, 32 - bottom, height - bottom, bottom); - } + @Override + public void render(GuiGraphics graphics, Font font, long time) { + graphics.blitSprite(RenderType::guiTextured, TEXTURE, 0, 0, width(), height()); var textX = MARGIN; if (!stack.isEmpty()) { @@ -102,23 +99,9 @@ public class ItemToast implements Toast { graphics.renderFakeItem(stack, MARGIN, MARGIN + height() / 2 - IMAGE_SIZE); } - graphics.drawString(component.getMinecraft().font, title, textX, MARGIN, 0xff500050, false); + graphics.drawString(font, title, textX, MARGIN, 0xff500050, false); for (var i = 0; i < message.size(); ++i) { - graphics.drawString(component.getMinecraft().font, message.get(i), textX, LINE_SPACING + (i + 1) * LINE_SPACING, 0xff000000, false); + graphics.drawString(font, message.get(i), textX, LINE_SPACING + (i + 1) * LINE_SPACING, 0xff000000, false); } - - return time - firstDisplay < DISPLAY_TIME ? Visibility.SHOW : Visibility.HIDE; - } - - private static void renderBackgroundRow(GuiGraphics graphics, int x, int u, int y, int height) { - var leftOffset = u == 0 ? 20 : 5; - var rightOffset = Math.min(60, x - leftOffset); - - graphics.blitSprite(TEXTURE, 160, 32, 0, u, 0, y, leftOffset, height); - for (var k = leftOffset; k < x - rightOffset; k += 64) { - graphics.blitSprite(TEXTURE, 160, 32, 32, u, k, y, Math.min(64, x - k - rightOffset), height); - } - - graphics.blitSprite(TEXTURE, 160, 32, 160 - rightOffset, u, x - rightOffset, y, rightOffset, height); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java index 36467a45a..5472f9245 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java @@ -67,7 +67,7 @@ public class NoTermComputerScreen extends Screen @Override public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) { - Objects.requireNonNull(minecraft().player).getInventory().swapPaint(scrollY); + // FIXME(1.21.2): Objects.requireNonNull(minecraft().player).getInventory().setSelectedHotbarSlot(scrollY); return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY); } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java index 0cf39fa21..1e2c7bd75 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java @@ -10,6 +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.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -87,12 +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(BACKGROUND, x, y, 0, 0, innerWidth, PADDING); - graphics.blit(BACKGROUND, + graphics.blit(RenderType::guiTextured, BACKGROUND, x, y, 0, 0, innerWidth, PADDING, 256, 256); + graphics.blit(RenderType::guiTextured, BACKGROUND, x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2, - innerWidth, PADDING + innerWidth, PADDING, + 256, 256 ); - graphics.blit(BACKGROUND, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING); + graphics.blit(RenderType::guiTextured, BACKGROUND, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING, 256, 256); assertNonNull(messageRenderer).renderLeftAlignedNoShadow(graphics, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040); super.render(graphics, mouseX, mouseY, partialTicks); diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java index 70deac9c2..7710df1f0 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java @@ -7,6 +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.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; @@ -23,9 +24,11 @@ public class PrinterScreen extends AbstractContainerScreen { @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { - graphics.blit(BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight); + graphics.blit(RenderType::guiTextured, BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight, 256, 256); - if (getMenu().isPrinting()) graphics.blit(BACKGROUND, leftPos + 34, topPos + 21, 176, 0, 25, 45); + if (getMenu().isPrinting()) { + graphics.blit(RenderType::guiTextured, BACKGROUND, leftPos + 34, topPos + 21, 176, 0, 25, 45, 256, 256); + } } @Override diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java index 8df70c395..c8d1608ee 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java @@ -10,6 +10,7 @@ import dan200.computercraft.shared.media.PrintoutMenu; import dan200.computercraft.shared.media.items.PrintoutData; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.LightTexture; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -20,7 +21,6 @@ import org.lwjgl.glfw.GLFW; import java.util.Objects; import static dan200.computercraft.client.render.PrintoutRenderer.*; -import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP; /** * The GUI for printed pages and books. @@ -116,8 +116,10 @@ public final class PrintoutScreen extends AbstractContainerScreen graphics.pose().pushPose(); graphics.pose().translate(0, 0, 1); - drawBorder(graphics.pose(), graphics.bufferSource(), leftPos, topPos, 0, page, printout.pages(), printout.book(), FULL_BRIGHT_LIGHTMAP); - drawText(graphics.pose(), graphics.bufferSource(), leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutData.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, printout.text(), printout.colour()); + 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(); } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java index 381bd6219..2aae0b5e9 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java @@ -7,12 +7,12 @@ package dan200.computercraft.client.gui; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.client.gui.widgets.ComputerSidebar; import dan200.computercraft.client.gui.widgets.TerminalWidget; -import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.client.render.SpriteRenderer; 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.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; @@ -26,6 +26,9 @@ public class TurtleScreen extends AbstractComputerScreen { private static final ResourceLocation BACKGROUND_NORMAL = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_normal.png"); private static final ResourceLocation BACKGROUND_ADVANCED = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_advanced.png"); + private static final ResourceLocation SELECTED_NORMAL = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "turtle_normal_selected_slot"); + private static final ResourceLocation SELECTED_ADVANCED = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "turtle_advanced_selected_slot"); + private static final int TEX_WIDTH = 278; private static final int TEX_HEIGHT = 217; @@ -46,23 +49,28 @@ public class TurtleScreen extends AbstractComputerScreen { @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { var advanced = family == ComputerFamily.ADVANCED; - var texture = advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL; - graphics.blit(texture, leftPos + AbstractComputerMenu.SIDEBAR_WIDTH, topPos, 0, 0, 0, TEX_WIDTH, TEX_HEIGHT, FULL_TEX_SIZE, FULL_TEX_SIZE); + graphics.blit( + RenderType::guiTextured, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL, + leftPos + AbstractComputerMenu.SIDEBAR_WIDTH, topPos, 0, 0, + TEX_WIDTH, TEX_HEIGHT, FULL_TEX_SIZE, FULL_TEX_SIZE + ); // Render selected slot var slot = getMenu().getSelectedSlot(); if (slot >= 0) { var slotX = slot % 4; var slotY = slot / 4; - graphics.blit(texture, - leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18, 0, - 0, 217, 24, 24, FULL_TEX_SIZE, FULL_TEX_SIZE + + graphics.blitSprite( + RenderType::guiTextured, advanced ? SELECTED_ADVANCED : SELECTED_NORMAL, + leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18, + 22, 22 ); } // Render sidebar - var spriteRenderer = SpriteRenderer.createForGui(graphics, RenderTypes.GUI_SPRITES); - ComputerSidebar.renderBackground(spriteRenderer, GuiSprites.getComputerTextures(family), leftPos, topPos + sidebarYOffset); - graphics.flush(); // Flush to ensure background textures are drawn before foreground. + SpriteRenderer.inGui(graphics, spriteRenderer -> + ComputerSidebar.renderBackground(spriteRenderer, GuiSprites.getComputerTextures(family), leftPos, topPos + sidebarYOffset) + ); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java index 88f5f02d7..31a80922b 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java @@ -4,14 +4,14 @@ package dan200.computercraft.client.gui.widgets; -import com.mojang.blaze3d.systems.RenderSystem; import it.unimi.dsi.fastutil.booleans.Boolean2ObjectFunction; 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.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.RenderType; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.function.Supplier; @@ -21,11 +21,11 @@ import java.util.function.Supplier; * dynamically. */ public class DynamicImageButton extends Button { - private final Boolean2ObjectFunction texture; + private final Boolean2ObjectFunction texture; private final Supplier message; public DynamicImageButton( - int x, int y, int width, int height, Boolean2ObjectFunction texture, OnPress onPress, + int x, int y, int width, int height, Boolean2ObjectFunction texture, OnPress onPress, HintedMessage message ) { this(x, y, width, height, texture, onPress, () -> message); @@ -33,7 +33,7 @@ public class DynamicImageButton extends Button { public DynamicImageButton( int x, int y, int width, int height, - Boolean2ObjectFunction texture, + Boolean2ObjectFunction texture, OnPress onPress, Supplier message ) { super(x, y, width, height, Component.empty(), onPress, DEFAULT_NARRATION); @@ -48,10 +48,7 @@ public class DynamicImageButton extends Button { setTooltip(message.tooltip()); var texture = this.texture.get(isHoveredOrFocused()); - - RenderSystem.disableDepthTest(); - graphics.blit(getX(), getY(), 0, width, height, texture); - RenderSystem.enableDepthTest(); + graphics.blitSprite(RenderType::guiTextured, texture, getX(), getY(), width, height); } public record HintedMessage(Component message, Tooltip tooltip) { diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java index 50a0f35d4..0c35fa33b 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java @@ -4,7 +4,6 @@ package dan200.computercraft.client.gui.widgets; -import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.client.render.text.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.util.StringUtil; @@ -257,12 +256,12 @@ public class TerminalWidget extends AbstractWidget { public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { if (!visible) return; - var emitter = FixedWidthFontRenderer.toVertexConsumer(graphics.pose(), graphics.bufferSource().getBuffer(RenderTypes.TERMINAL)); - - FixedWidthFontRenderer.drawTerminal( - emitter, - (float) innerX, (float) innerY, terminal, (float) MARGIN, (float) MARGIN, (float) MARGIN, (float) MARGIN - ); + 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 + ); + }); } @Override diff --git a/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java b/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java index a8241d643..e9d5046ae 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java +++ b/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java @@ -5,17 +5,18 @@ package dan200.computercraft.client.integration; import com.google.auto.service.AutoService; +import com.mojang.blaze3d.vertex.ByteBufferBuilder; import com.mojang.blaze3d.vertex.VertexFormat; -import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer; import dan200.computercraft.shared.platform.PlatformHelper; import net.irisshaders.iris.api.v0.IrisApi; import net.irisshaders.iris.api.v0.IrisTextVertexSink; -import net.minecraft.util.FastColor; +import net.minecraft.client.renderer.LightTexture; +import org.lwjgl.system.MemoryUtil; +import javax.annotation.Nullable; import java.nio.ByteBuffer; import java.util.Optional; -import java.util.function.IntFunction; @AutoService(ShaderMod.Provider.class) public class IrisShaderMod implements ShaderMod.Provider { @@ -31,7 +32,7 @@ public class IrisShaderMod implements ShaderMod.Provider { } @Override - public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, IntFunction makeBuffer) { + public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, ByteBufferBuilder makeBuffer) { return IrisApi.getInstance().getMinorApiRevision() >= 1 ? new IrisQuadEmitter(vertexCount, makeBuffer) : super.getQuadEmitter(vertexCount, makeBuffer); @@ -39,25 +40,24 @@ public class IrisShaderMod implements ShaderMod.Provider { private static final class IrisQuadEmitter implements DirectFixedWidthFontRenderer.QuadEmitter { private final IrisTextVertexSink sink; + private @Nullable ByteBuffer buffer; - private IrisQuadEmitter(int vertexCount, IntFunction makeBuffer) { - sink = IrisApi.getInstance().createTextVertexSink(vertexCount, makeBuffer); + private IrisQuadEmitter(int vertexCount, ByteBufferBuilder builder) { + sink = IrisApi.getInstance().createTextVertexSink(vertexCount, i -> { + if (buffer != null) throw new IllegalStateException("Allocated multiple buffers"); + return buffer = MemoryUtil.memByteBuffer(builder.reserve(i), i); + }); + } + + @Override + public void quad(float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) { + sink.quad(x1, y1, x2, y2, z, colour, u1, v1, u2, v2, LightTexture.FULL_BRIGHT); } @Override public VertexFormat format() { return sink.getUnderlyingVertexFormat(); } - - @Override - public ByteBuffer buffer() { - return sink.getUnderlyingByteBuffer(); - } - - @Override - public void quad(float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) { - sink.quad(x1, y1, x2, y2, z, FastColor.ABGR32.fromArgb32(colour), u1, v1, u2, v2, RenderTypes.FULL_BRIGHT_LIGHTMAP); - } } } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java b/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java index 9c6a236ad..122f32489 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java +++ b/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java @@ -4,14 +4,12 @@ package dan200.computercraft.client.integration; -import dan200.computercraft.client.render.RenderTypes; +import com.mojang.blaze3d.vertex.ByteBufferBuilder; +import com.mojang.blaze3d.vertex.VertexBuffer; import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer; -import dan200.computercraft.client.render.vbo.DirectVertexBuffer; -import java.nio.ByteBuffer; import java.util.Optional; import java.util.ServiceLoader; -import java.util.function.IntFunction; /** * Find the currently loaded shader mod (if present) and provides utilities for interacting with it. @@ -31,16 +29,14 @@ public class ShaderMod { } /** - * Get an appropriate quad emitter for use with {@link DirectVertexBuffer} and {@link DirectFixedWidthFontRenderer} . + * Get an appropriate quad emitter for use with {@link VertexBuffer} and {@link DirectFixedWidthFontRenderer} . * * @param vertexCount The number of vertices. - * @param makeBuffer A function to allocate a temporary buffer. + * @param buffer A function to allocate a temporary buffer. * @return The quad emitter. */ - public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, IntFunction makeBuffer) { - return new DirectFixedWidthFontRenderer.ByteBufferEmitter( - makeBuffer.apply(RenderTypes.TERMINAL.format().getVertexSize() * vertexCount * 4) - ); + public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, ByteBufferBuilder buffer) { + return new DirectFixedWidthFontRenderer.ByteBufferEmitter(buffer); } public interface Provider { diff --git a/projects/common/src/client/java/dan200/computercraft/client/model/turtle/ModelTransformer.java b/projects/common/src/client/java/dan200/computercraft/client/model/turtle/ModelTransformer.java index 72c7e3bd5..3213c376d 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/model/turtle/ModelTransformer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/model/turtle/ModelTransformer.java @@ -80,7 +80,7 @@ public class ModelTransformer { } var direction = Direction.rotate(transformation, quad.getDirection()); - return new BakedQuad(outputData, quad.getTintIndex(), direction, quad.getSprite(), quad.isShade()); + return new BakedQuad(outputData, quad.getTintIndex(), direction, quad.getSprite(), quad.isShade(), 0); } public static int getVertexOffset(int vertex, boolean invert) { diff --git a/projects/common/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelParts.java b/projects/common/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelParts.java index a6ef119ca..977c673fc 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelParts.java +++ b/projects/common/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelParts.java @@ -107,8 +107,7 @@ public final class TurtleModelParts { } private List buildModel(Combination combo) { - var mc = Minecraft.getInstance(); - var modelManager = mc.getItemRenderer().getItemModelShaper().getModelManager(); + var modelManager = Minecraft.getInstance().getModelManager(); var transformation = combo.flip ? flip : identity; var parts = new ArrayList(4); diff --git a/projects/common/src/client/java/dan200/computercraft/client/platform/ClientNetworkContextImpl.java b/projects/common/src/client/java/dan200/computercraft/client/platform/ClientNetworkContextImpl.java index 45fc090a2..7b8e3553c 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/platform/ClientNetworkContextImpl.java +++ b/projects/common/src/client/java/dan200/computercraft/client/platform/ClientNetworkContextImpl.java @@ -22,11 +22,13 @@ import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; +import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.JukeboxSong; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.LevelEvent; import javax.annotation.Nullable; import java.util.UUID; @@ -62,10 +64,14 @@ public final class ClientNetworkContextImpl implements ClientNetworkContext { @Override public void handlePlayRecord(BlockPos pos, @Nullable Holder song) { + var level = Minecraft.getInstance().level; + if (level == null) return; + if (song == null) { - Minecraft.getInstance().levelRenderer.stopJukeboxSongAndNotifyNearby(pos); + level.levelEvent(LevelEvent.SOUND_STOP_JUKEBOX_SONG, pos, 0); } else { - Minecraft.getInstance().levelRenderer.playJukeboxSong(song, pos); + var id = level.registryAccess().lookupOrThrow(Registries.JUKEBOX_SONG).getIdOrThrow(song.value()); + level.levelEvent(LevelEvent.SOUND_PLAY_JUKEBOX_SONG, pos, id); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/ModelRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/ModelRenderer.java index 4e4019430..1905bfae2 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/ModelRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/ModelRenderer.java @@ -70,7 +70,7 @@ public final class ModelRenderer { var matrix = pose.pose(); // It's a little dubious to transform using this matrix rather than the normal matrix. This mirrors the logic in // Direction.rotate (so not out of nowhere!), but is a little suspicious. - var dirNormal = quad.getDirection().getNormal(); + var dirNormal = quad.getDirection().getUnitVec3i(); var vector = new Vector4f(); matrix.transform(dirNormal.getX(), dirNormal.getY(), dirNormal.getZ(), 0.0f, vector).normalize(); diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/PocketItemRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/PocketItemRenderer.java index 60eaa1bcd..6fd55cf31 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/PocketItemRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/PocketItemRenderer.java @@ -13,8 +13,10 @@ import dan200.computercraft.core.util.Colour; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.config.Config; import dan200.computercraft.shared.pocket.items.PocketComputerItem; +import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.util.FastColor; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.util.ARGB; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.DyedItemColor; import org.joml.Matrix4f; @@ -72,7 +74,7 @@ public final class PocketItemRenderer extends ItemMapLikeRenderer { var lightColour = computer == null || computer.getLightState() == -1 ? Colour.BLACK.getHex() : computer.getLightState(); renderLight(transform, bufferSource, lightColour, width, height); - var quadEmitter = FixedWidthFontRenderer.toVertexConsumer(transform, bufferSource.getBuffer(RenderTypes.TERMINAL)); + var quadEmitter = FixedWidthFontRenderer.toVertexConsumer(transform, bufferSource.getBuffer(FixedWidthFontRenderer.TERMINAL_TEXT)); if (terminal == null) { FixedWidthFontRenderer.drawEmptyTerminal(quadEmitter, 0, 0, width, height); } else { @@ -89,16 +91,16 @@ public final class PocketItemRenderer extends ItemMapLikeRenderer { var g = (colour >>> 8) & 0xFF; var b = colour & 0xFF; - var spriteRenderer = new SpriteRenderer(transform, render.getBuffer(RenderTypes.GUI_SPRITES), 0, light, r, g, b); + var spriteRenderer = new SpriteRenderer(transform, render.getBuffer(RenderType.text(GuiSprites.TEXTURE)), 0, light, r, g, b); ComputerBorderRenderer.render(spriteRenderer, texture, 0, 0, width, height, true); } private static void renderLight(PoseStack transform, MultiBufferSource render, int colour, int width, int height) { - var buffer = render.getBuffer(RenderTypes.TERMINAL); + var buffer = render.getBuffer(FixedWidthFontRenderer.TERMINAL_TEXT); FixedWidthFontRenderer.drawQuad( FixedWidthFontRenderer.toVertexConsumer(transform, buffer), width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0.001f, LIGHT_HEIGHT * 2, LIGHT_HEIGHT, - FastColor.ARGB32.opaque(colour), RenderTypes.FULL_BRIGHT_LIGHTMAP + ARGB.opaque(colour), LightTexture.FULL_BRIGHT ); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutItemRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutItemRenderer.java index 1a4fa829b..9e6a2046f 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutItemRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutItemRenderer.java @@ -10,8 +10,7 @@ import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.media.items.PrintoutData; import dan200.computercraft.shared.media.items.PrintoutItem; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.client.renderer.entity.state.ItemFrameRenderState; import net.minecraft.world.item.ItemStack; import static dan200.computercraft.client.render.PrintoutRenderer.*; @@ -38,14 +37,14 @@ public final class PrintoutItemRenderer extends ItemMapLikeRenderer { drawPrintout(transform, render, stack, light); } - public static void onRenderInFrame(PoseStack transform, MultiBufferSource render, ItemFrame frame, ItemStack stack, int packedLight) { + public static void onRenderInFrame(PoseStack transform, MultiBufferSource render, ItemFrameRenderState frame, ItemStack stack, int packedLight) { // Move a little bit forward to ensure we're not clipping with the frame transform.translate(0.0f, 0.0f, -0.001f); transform.mulPose(Axis.ZP.rotationDegrees(180f)); transform.scale(0.95f, 0.95f, -0.95f); transform.translate(-0.5f, -0.5f, 0.0f); - var light = frame.getType() == EntityType.GLOW_ITEM_FRAME ? 0xf000d2 : packedLight; // See getLightVal. + var light = frame.isGlowFrame ? 0xf000d2 : packedLight; // See getLightVal. drawPrintout(transform, render, stack, light); } diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java index 68bbfaacf..821e859e4 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java @@ -11,6 +11,8 @@ import dan200.computercraft.core.terminal.Palette; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.media.items.PrintoutData; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.resources.ResourceLocation; import org.joml.Matrix4f; import java.util.List; @@ -23,6 +25,12 @@ import static dan200.computercraft.shared.media.items.PrintoutData.LINES_PER_PAG * {@linkplain PrintoutItemRenderer in-hand/item frame printouts}. */ public final class PrintoutRenderer { + /** + * Printout's background texture. {@link RenderType#text(ResourceLocation)} is a little questionable, but + * it is what maps use, so should behave the same as vanilla in both item frames and in-hand. + */ + private static final RenderType BACKGROUND = RenderType.text(ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/printout.png")); + private static final float BG_SIZE = 256.0f; /** @@ -62,7 +70,7 @@ public final class PrintoutRenderer { } public static void drawText(PoseStack transform, MultiBufferSource bufferSource, int x, int y, int start, int light, TextBuffer[] text, TextBuffer[] colours) { - var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_TEXT); + var buffer = bufferSource.getBuffer(FixedWidthFontRenderer.TERMINAL_TEXT); var emitter = FixedWidthFontRenderer.toVertexConsumer(transform, buffer); for (var line = 0; line < LINES_PER_PAGE && line < text.length; line++) { FixedWidthFontRenderer.drawString(emitter, @@ -73,7 +81,7 @@ public final class PrintoutRenderer { } public static void drawText(PoseStack transform, MultiBufferSource bufferSource, int x, int y, int start, int light, List lines) { - var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_TEXT); + var buffer = bufferSource.getBuffer(FixedWidthFontRenderer.TERMINAL_TEXT); var emitter = FixedWidthFontRenderer.toVertexConsumer(transform, buffer); for (var line = 0; line < LINES_PER_PAGE && line < lines.size(); line++) { var lineContents = lines.get(start + line); @@ -90,7 +98,7 @@ public final class PrintoutRenderer { var leftPages = page; var rightPages = pages - page - 1; - var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_BACKGROUND); + var buffer = bufferSource.getBuffer(BACKGROUND); if (isBook) { // Border diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/RenderTypes.java b/projects/common/src/client/java/dan200/computercraft/client/render/RenderTypes.java deleted file mode 100644 index 3868c472d..000000000 --- a/projects/common/src/client/java/dan200/computercraft/client/render/RenderTypes.java +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.client.render; - -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.VertexFormat; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.client.gui.GuiSprites; -import dan200.computercraft.client.render.monitor.MonitorTextureBufferShader; -import dan200.computercraft.client.render.text.FixedWidthFontRenderer; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.RenderStateShard; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.ShaderInstance; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceProvider; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.util.Objects; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -/** - * Shared {@link RenderType}s used throughout the mod. - */ -public class RenderTypes { - public static final int FULL_BRIGHT_LIGHTMAP = (0xF << 4) | (0xF << 20); - - private static @Nullable MonitorTextureBufferShader monitorTboShader; - - /** - * Renders a fullbright terminal. - */ - public static final RenderType TERMINAL = RenderType.text(FixedWidthFontRenderer.FONT); - - /** - * Renders a monitor with the TBO shader. - * - * @see MonitorTextureBufferShader - */ - public static final RenderType MONITOR_TBO = Types.MONITOR_TBO; - - /** - * A variant of {@link #TERMINAL} which uses the lightmap rather than rendering fullbright. - */ - public static final RenderType PRINTOUT_TEXT = RenderType.text(FixedWidthFontRenderer.FONT); - - /** - * Printout's background texture. {@link RenderType#text(ResourceLocation)} is a little questionable, but - * it is what maps use, so should behave the same as vanilla in both item frames and in-hand. - */ - public static final RenderType PRINTOUT_BACKGROUND = RenderType.text(ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/printout.png")); - - /** - * Render type for {@linkplain GuiSprites GUI sprites}. - */ - public static final RenderType GUI_SPRITES = RenderType.text(GuiSprites.TEXTURE); - - public static MonitorTextureBufferShader getMonitorTextureBufferShader() { - if (monitorTboShader == null) throw new NullPointerException("MonitorTboShader has not been registered"); - return monitorTboShader; - } - - public static ShaderInstance getTerminalShader() { - return Objects.requireNonNull(GameRenderer.getRendertypeTextShader(), "Text shader has not been registered"); - } - - public static void registerShaders(ResourceProvider resources, BiConsumer> load) throws IOException { - load.accept( - new MonitorTextureBufferShader( - resources, - ComputerCraftAPI.MOD_ID + "/monitor_tbo", - MONITOR_TBO.format() - ), - x -> monitorTboShader = (MonitorTextureBufferShader) x - ); - } - - private static final class Types extends RenderType { - private static final RenderStateShard.TextureStateShard TERM_FONT_TEXTURE = new TextureStateShard( - FixedWidthFontRenderer.FONT, - false, false // blur, minimap - ); - - static final RenderType MONITOR_TBO = RenderType.create( - "monitor_tbo", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.TRIANGLE_STRIP, 128, - false, false, // useDelegate, needsSorting - RenderType.CompositeState.builder() - .setTextureState(TERM_FONT_TEXTURE) - .setShaderState(new ShaderStateShard(RenderTypes::getMonitorTextureBufferShader)) - .createCompositeState(false) - ); - - @SuppressWarnings("UnusedMethod") - private Types(String name, VertexFormat format, VertexFormat.Mode mode, int buffer, boolean crumbling, boolean sort, Runnable setup, Runnable teardown) { - super(name, format, mode, buffer, crumbling, sort, setup, teardown); - } - } -} diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/SpriteRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/SpriteRenderer.java index bb1a3d02e..3e39580f0 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/SpriteRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/SpriteRenderer.java @@ -5,11 +5,15 @@ package dan200.computercraft.client.render; import com.mojang.blaze3d.vertex.VertexConsumer; +import dan200.computercraft.client.gui.GuiSprites; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import org.joml.Matrix4f; +import java.util.function.Consumer; + /** * A {@link GuiGraphics}-equivalent which is suitable for both rendering in to a GUI and in-world (as part of an entity * renderer). @@ -34,11 +38,11 @@ public class SpriteRenderer { this.b = b; } - public static SpriteRenderer createForGui(GuiGraphics graphics, RenderType renderType) { - return new SpriteRenderer( - graphics.pose().last().pose(), graphics.bufferSource().getBuffer(renderType), - 0, RenderTypes.FULL_BRIGHT_LIGHTMAP, 255, 255, 255 - ); + public static void inGui(GuiGraphics graphics, Consumer renderer) { + graphics.drawSpecial(bufferSource -> renderer.accept(new SpriteRenderer( + graphics.pose().last().pose(), bufferSource.getBuffer(RenderType.guiTextured(GuiSprites.TEXTURE)), + 0, LightTexture.FULL_BRIGHT, 255, 255, 255 + ))); } /** diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/TurtleBlockEntityRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/TurtleBlockEntityRenderer.java index 03c2635aa..94afa48d4 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/TurtleBlockEntityRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/TurtleBlockEntityRenderer.java @@ -22,8 +22,9 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.ARGB; import net.minecraft.util.CommonColors; -import net.minecraft.util.FastColor; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; @@ -84,13 +85,13 @@ public class TurtleBlockEntityRenderer implements BlockEntityRenderer { - if (redraw) { - var terminalBuffer = getBuffer(width * height * 3); - MonitorTextureBufferShader.setTerminalData(terminalBuffer, terminal); - DirectBuffers.setBufferData(GL31.GL_TEXTURE_BUFFER, renderState.tboBuffer, terminalBuffer, GL20.GL_STATIC_DRAW); + var backgroundBuffer = assertNonNull(renderState.backgroundBuffer); + var foregroundBuffer = assertNonNull(renderState.foregroundBuffer); + if (redraw) { + var size = DirectFixedWidthFontRenderer.getVertexCount(terminal); - var uniformBuffer = getBuffer(MonitorTextureBufferShader.UNIFORM_SIZE); - MonitorTextureBufferShader.setUniformData(uniformBuffer, terminal); - DirectBuffers.setBufferData(GL31.GL_UNIFORM_BUFFER, renderState.tboUniform, uniformBuffer, GL20.GL_STATIC_DRAW); - } + // In an ideal world we could upload these both into one buffer. However, we can't render VBOs with + // and starting and ending offset, and so need to use two buffers instead. - // Nobody knows what they're doing! - var active = GlStateManager._getActiveTexture(); - RenderSystem.activeTexture(MonitorTextureBufferShader.TEXTURE_INDEX); - GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, renderState.tboTexture); - RenderSystem.activeTexture(active); + renderToBuffer(backgroundBuffer, size, sink -> + DirectFixedWidthFontRenderer.drawTerminalBackground(sink, 0, 0, terminal, yMargin, yMargin, xMargin, xMargin)); - var shader = RenderTypes.getMonitorTextureBufferShader(); - shader.setupUniform(renderState.tboUniform); - - var buffer = Tesselator.getInstance().begin(RenderTypes.MONITOR_TBO.mode(), RenderTypes.MONITOR_TBO.format()); - tboVertex(buffer, matrix, -xMargin, -yMargin); - tboVertex(buffer, matrix, -xMargin, pixelHeight + yMargin); - tboVertex(buffer, matrix, pixelWidth + xMargin, -yMargin); - tboVertex(buffer, matrix, pixelWidth + xMargin, pixelHeight + yMargin); - RenderTypes.MONITOR_TBO.draw(Nullability.assertNonNull(buffer.build())); - } - case VBO -> { - var backgroundBuffer = assertNonNull(renderState.backgroundBuffer); - var foregroundBuffer = assertNonNull(renderState.foregroundBuffer); - if (redraw) { - var size = DirectFixedWidthFontRenderer.getVertexCount(terminal); - - // In an ideal world we could upload these both into one buffer. However, we can't render VBOs with - // and starting and ending offset, and so need to use two buffers instead. - - renderToBuffer(backgroundBuffer, size, sink -> - DirectFixedWidthFontRenderer.drawTerminalBackground(sink, 0, 0, terminal, yMargin, yMargin, xMargin, xMargin)); - - renderToBuffer(foregroundBuffer, size, sink -> { - DirectFixedWidthFontRenderer.drawTerminalForeground(sink, 0, 0, terminal); - // If the cursor is visible, we append it to the end of our buffer. When rendering, we can either - // render n or n+1 quads and so toggle the cursor on and off. - DirectFixedWidthFontRenderer.drawCursor(sink, 0, 0, terminal); - }); - } - - // 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 - // normal render distance (~200), and the edges of the monitor fade out due to fog. - // There's not really a good way around this, at least without using a custom render type (which the VBO - // renderer is trying to avoid!). Instead, we just disable fog entirely by setting the fog start to an - // absurdly high value. - var oldFogStart = RenderSystem.getShaderFogStart(); - RenderSystem.setShaderFogStart(1e4f); - - RenderTypes.TERMINAL.setupRenderState(); - - // Compose the existing model view matrix with our transformation matrix. - var modelView = new Matrix4f(RenderSystem.getModelViewMatrix()).mul(matrix); - - // Render background geometry - backgroundBuffer.bind(); - backgroundBuffer.drawWithShader(modelView, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader()); - - // Render foreground geometry with glPolygonOffset enabled. - RenderSystem.polygonOffset(-1.0f, -10.0f); - RenderSystem.enablePolygonOffset(); - - foregroundBuffer.bind(); - foregroundBuffer.drawWithShader( - modelView, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader(), - // As mentioned in the above comment, render the extra cursor quad if it is visible this frame. Each - // // quad has an index count of 6. - FixedWidthFontRenderer.isCursorVisible(terminal) && FrameInfo.getGlobalCursorBlink() - ? foregroundBuffer.getIndexCount() + 6 : foregroundBuffer.getIndexCount() - ); - - // Clear state - RenderSystem.polygonOffset(0.0f, -0.0f); - RenderSystem.disablePolygonOffset(); - RenderTypes.TERMINAL.clearRenderState(); - VertexBuffer.unbind(); - - RenderSystem.setShaderFogStart(oldFogStart); - } - case BEST -> throw new IllegalStateException("Impossible: Should never use BEST renderer"); + renderToBuffer(foregroundBuffer, size + 4, sink -> { + DirectFixedWidthFontRenderer.drawTerminalForeground(sink, 0, 0, terminal); + // If the cursor is visible, we append it to the end of our buffer. When rendering, we can either + // render n or n+1 quads and so toggle the cursor on and off. + DirectFixedWidthFontRenderer.drawCursor(sink, 0, 0, terminal); + }); } + + // 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 + // normal render distance (~200), and the edges of the monitor fade out due to fog. + // There's not really a good way around this, at least without using a custom render type (which the VBO + // 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); + + FixedWidthFontRenderer.TERMINAL_TEXT.setupRenderState(); + + // Compose the existing model view matrix with our transformation matrix. + var modelView = new Matrix4f(RenderSystem.getModelViewMatrix()).mul(matrix); + + // Render background geometry + backgroundBuffer.bind(); + backgroundBuffer.drawWithShader(modelView, RenderSystem.getProjectionMatrix(), RenderSystem.getShader()); + + // Render foreground geometry with glPolygonOffset enabled. + RenderSystem.polygonOffset(-1.0f, -10.0f); + RenderSystem.enablePolygonOffset(); + + foregroundBuffer.bind(); + drawWithShader( + foregroundBuffer, modelView, RenderSystem.getProjectionMatrix(), RenderSystem.getShader(), + // As mentioned in the above comment, render the extra cursor quad if it is visible this frame. + FixedWidthFontRenderer.isCursorVisible(terminal) && FrameInfo.getGlobalCursorBlink() + ? foregroundBuffer.indexCount + : foregroundBuffer.indexCount - FixedWidthFontRenderer.TERMINAL_TEXT.mode().indexCount(4) + ); + + // Clear state + RenderSystem.polygonOffset(0.0f, -0.0f); + RenderSystem.disablePolygonOffset(); + FixedWidthFontRenderer.TERMINAL_TEXT.clearRenderState(); + VertexBuffer.unbind(); + + RenderSystem.setShaderFog(oldFog); } - private static void renderToBuffer(DirectVertexBuffer vbo, int size, Consumer draw) { - var sink = ShaderMod.get().getQuadEmitter(size, MonitorBlockEntityRenderer::getBuffer); - var buffer = sink.buffer(); - + private static void renderToBuffer(VertexBuffer vbo, int size, Consumer draw) { + var sink = ShaderMod.get().getQuadEmitter(size, backingBufferBuilder); draw.accept(sink); - buffer.flip(); - vbo.upload(buffer.limit() / sink.format().getVertexSize(), RenderTypes.TERMINAL.mode(), sink.format(), buffer); - } - private static void tboVertex(VertexConsumer builder, Matrix4f matrix, float x, float y) { - // We encode position in the UV, as that's not transformed by the matrix. - builder.addVertex(matrix, x, y, 0).setUv(x, y); - } - - private static ByteBuffer getBuffer(int capacity) { - var buffer = backingBuffer; - if (buffer == null || buffer.capacity() < capacity) { - buffer = backingBuffer = buffer == null ? MemoryUtil.memAlloc(capacity) : MemoryUtil.memRealloc(buffer, capacity); + var result = backingBufferBuilder.build(); + if (result == null) { + // If we have nothing to draw, just mark it as empty. We'll skip drawing in drawWithShader. + vbo.indexCount = 0; + return; } - buffer.clear(); - return buffer; + var buffer = result.byteBuffer(); + var vertices = buffer.limit() / sink.format().getVertexSize(); + + vbo.bind(); + vbo.upload(new MeshData(result, new MeshData.DrawState( + sink.format(), + vertices, FixedWidthFontRenderer.TERMINAL_TEXT.mode().indexCount(vertices), + FixedWidthFontRenderer.TERMINAL_TEXT.mode(), VertexFormat.IndexType.least(vertices) + ))); + } + + private static void drawWithShader(VertexBuffer buffer, Matrix4f modelView, Matrix4f projection, @Nullable CompiledShaderProgram compiledShaderProgram, int indicies) { + var originalIndexCount = buffer.indexCount; + if (originalIndexCount == 0) return; + + try { + buffer.indexCount = indicies; + buffer.drawWithShader(modelView, projection, compiledShaderProgram); + } finally { + buffer.indexCount = originalIndexCount; + } } @Override @@ -267,28 +226,4 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer - * This extends Minecraft's default shader loading code to extract out the TBO buffer and handle our custom uniforms - * ({@code MonitorData}, {@code CursorBlink}). - *

- * See also {@code monitor_tbo.fsh} and {@code monitor_tbo.vsh} in the mod's resources. - * - * @see RenderTypes#getMonitorTextureBufferShader() - */ -public class MonitorTextureBufferShader extends ShaderInstance { - private static final Logger LOG = LoggerFactory.getLogger(MonitorTextureBufferShader.class); - - public static final int UNIFORM_SIZE = 4 * 4 * 16 + 4 + 4 + 2 * 4 + 4; - - static final int TEXTURE_INDEX = GL13.GL_TEXTURE3; - - private final int monitorData; - private int uniformBuffer = 0; - - private final @Nullable Uniform cursorBlink; - - public MonitorTextureBufferShader(ResourceProvider provider, String location, VertexFormat format) throws IOException { - super(provider, location, format); - monitorData = GL31.glGetUniformBlockIndex(getId(), "MonitorData"); - if (monitorData == -1) throw new IllegalStateException("Could not find MonitorData uniform."); - - cursorBlink = getUniformChecked("CursorBlink"); - - var tbo = getUniformChecked("Tbo"); - if (tbo != null) tbo.set(TEXTURE_INDEX - GL13.GL_TEXTURE0); - } - - public void setupUniform(int buffer) { - uniformBuffer = buffer; - - var cursorAlpha = FrameInfo.getGlobalCursorBlink() ? 1 : 0; - if (cursorBlink != null && cursorBlink.getIntBuffer().get(0) != cursorAlpha) cursorBlink.set(cursorAlpha); - } - - @Override - public void apply() { - super.apply(); - GL31.glBindBufferBase(GL31.GL_UNIFORM_BUFFER, monitorData, uniformBuffer); - } - - @Nullable - private Uniform getUniformChecked(String name) { - var uniform = getUniform(name); - if (uniform == null) { - LOG.warn("Monitor shader {} should have uniform {}, but it was not present.", getName(), name); - } - - return uniform; - } - - public static void setTerminalData(ByteBuffer buffer, Terminal terminal) { - int width = terminal.getWidth(), height = terminal.getHeight(); - - var pos = 0; - for (var y = 0; y < height; y++) { - TextBuffer text = terminal.getLine(y), textColour = terminal.getTextColourLine(y), background = terminal.getBackgroundColourLine(y); - for (var x = 0; x < width; x++) { - buffer.put(pos, (byte) (text.charAt(x) & 0xFF)); - buffer.put(pos + 1, (byte) getColour(textColour.charAt(x), Colour.WHITE)); - buffer.put(pos + 2, (byte) getColour(background.charAt(x), Colour.BLACK)); - pos += 3; - } - } - - buffer.limit(pos); - } - - public static void setUniformData(ByteBuffer buffer, Terminal terminal) { - var pos = 0; - var palette = terminal.getPalette(); - for (var i = 0; i < 16; i++) { - { - var colour = palette.getColour(i); - if (!terminal.isColour()) { - var f = FixedWidthFontRenderer.toGreyscale(colour); - buffer.putFloat(pos, f).putFloat(pos + 4, f).putFloat(pos + 8, f); - } else { - buffer.putFloat(pos, (float) colour[0]).putFloat(pos + 4, (float) colour[1]).putFloat(pos + 8, (float) colour[2]); - } - } - - pos += 4 * 4; // std140 requires these are 4-wide - } - - var showCursor = FixedWidthFontRenderer.isCursorVisible(terminal); - buffer - .putInt(pos, terminal.getWidth()).putInt(pos + 4, terminal.getHeight()) - .putInt(pos + 8, showCursor ? terminal.getCursorX() : -2) - .putInt(pos + 12, showCursor ? terminal.getCursorY() : -2) - .putInt(pos + 16, 15 - terminal.getTextColour()); - - buffer.limit(UNIFORM_SIZE); - } -} diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/text/DirectFixedWidthFontRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/text/DirectFixedWidthFontRenderer.java index 59c12f61b..6bb344868 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/text/DirectFixedWidthFontRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/text/DirectFixedWidthFontRenderer.java @@ -4,18 +4,17 @@ package dan200.computercraft.client.render.text; +import com.mojang.blaze3d.vertex.ByteBufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexFormat; -import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.core.terminal.Palette; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.core.util.Colour; -import net.minecraft.util.FastColor; +import net.minecraft.util.ARGB; import org.lwjgl.system.MemoryUtil; -import java.nio.ByteBuffer; import java.nio.ByteOrder; import static dan200.computercraft.client.render.text.FixedWidthFontRenderer.*; @@ -168,40 +167,38 @@ public final class DirectFixedWidthFontRenderer { public interface QuadEmitter { VertexFormat format(); - ByteBuffer buffer(); - void quad(float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2); } - public record ByteBufferEmitter(ByteBuffer buffer) implements QuadEmitter { + public record ByteBufferEmitter(ByteBufferBuilder builder) implements QuadEmitter { @Override public VertexFormat format() { - return RenderTypes.TERMINAL.format(); + return TERMINAL_TEXT.format(); } @Override public void quad(float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) { - DirectFixedWidthFontRenderer.quad(buffer, x1, y1, x2, y2, z, colour, u1, v1, u2, v2); + DirectFixedWidthFontRenderer.quad(builder, x1, y1, x2, y2, z, colour, u1, v1, u2, v2); } } - static void quad(ByteBuffer buffer, float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) { + static void quad(ByteBufferBuilder builder, float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) { // Emit a single quad to our buffer. This uses Unsafe (well, LWJGL's MemoryUtil) to directly blit bytes to the // underlying buffer. This allows us to have a single bounds check up-front, rather than one for every write. // This provides significant performance gains, at the cost of well, using Unsafe. - // Each vertex is 28 bytes, giving 112 bytes in total. Vertices are of the form (xyz:FFF)(rgba:BBBB)(uv1:FF)(uv2:SS), + // Each vertex is 28 bytes, giving 112 bytes in total. Vertices are of the form (xyz:FFF)(abgr:BBBB)(uv1:FF)(uv2:SS), // which matches the POSITION_COLOR_TEX_LIGHTMAP vertex format. - - var position = buffer.position(); - var addr = MemoryUtil.memAddress(buffer); + var addr = builder.reserve(112); // We're doing terrible unsafe hacks below, so let's be really sure that what we're doing is reasonable. - if (position < 0 || 112 > buffer.limit() - position) throw new IndexOutOfBoundsException(); // Require the pointer to be aligned to a 32-bit boundary. if ((addr & 3) != 0) throw new IllegalStateException("Memory is not aligned"); + if (TERMINAL_TEXT.format().getVertexSize() != 28) { + throw new IllegalStateException("Incorrect vertex size"); + } - // Pack colour so it is equivalent to rgba:BBBB. This matches the logic in BufferBuilder. - var colourAbgr = FastColor.ABGR32.fromArgb32(colour); + var colourAbgr = ARGB.toABGR(colour); + // Pack colour so it is equivalent to abgr:BBBB. This matches the logic in BufferBuilder. var nativeColour = IS_LITTLE_ENDIAN ? colourAbgr : Integer.reverseBytes(colourAbgr); memPutFloat(addr + 0, x1); @@ -240,9 +237,6 @@ public final class DirectFixedWidthFontRenderer { memPutShort(addr + 108, (short) 0xF0); memPutShort(addr + 110, (short) 0xF0); - // Finally increment the position. - buffer.position(position + 112); - // Well done for getting to the end of this method. I recommend you take a break and go look at cute puppies. } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/text/FixedWidthFontRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/text/FixedWidthFontRenderer.java index 7c6e1ed21..44d11bb55 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/text/FixedWidthFontRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/text/FixedWidthFontRenderer.java @@ -11,13 +11,13 @@ import dan200.computercraft.core.terminal.Palette; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.core.util.Colour; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.FastColor; +import net.minecraft.util.ARGB; import org.joml.Matrix4f; import org.joml.Vector3f; -import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP; - /** * Handles rendering fixed width text and computer terminals. *

@@ -33,7 +33,12 @@ import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMA * {@link DirectFixedWidthFontRenderer}. */ public final class FixedWidthFontRenderer { - public static final ResourceLocation FONT = ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/term_font.png"); + private static final ResourceLocation FONT = ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/term_font.png"); + + /** + * A render type for terminal text. + */ + public static final RenderType TERMINAL_TEXT = RenderType.text(FONT); public static final int FONT_HEIGHT = 9; public static final int FONT_WIDTH = 6; @@ -42,7 +47,7 @@ public final class FixedWidthFontRenderer { static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH; static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH; - private static final int BLACK = FastColor.ARGB32.color(255, byteColour(Colour.BLACK.getR()), byteColour(Colour.BLACK.getR()), byteColour(Colour.BLACK.getR())); + private static final int BLACK = ARGB.color(255, byteColour(Colour.BLACK.getR()), byteColour(Colour.BLACK.getR()), byteColour(Colour.BLACK.getR())); private static final float Z_OFFSET = 1e-3f; private FixedWidthFontRenderer() { @@ -137,7 +142,7 @@ public final class FixedWidthFontRenderer { var rowY = y + FONT_HEIGHT * i; drawString( emitter, x, rowY, terminal.getLine(i), terminal.getTextColourLine(i), - palette, FULL_BRIGHT_LIGHTMAP + palette, LightTexture.FULL_BRIGHT ); } } @@ -152,12 +157,12 @@ public final class FixedWidthFontRenderer { // Top and bottom margins drawBackground( emitter, x, y - topMarginSize, terminal.getBackgroundColourLine(0), palette, - leftMarginSize, rightMarginSize, topMarginSize, FULL_BRIGHT_LIGHTMAP + leftMarginSize, rightMarginSize, topMarginSize, LightTexture.FULL_BRIGHT ); drawBackground( emitter, x, y + height * FONT_HEIGHT, terminal.getBackgroundColourLine(height - 1), palette, - leftMarginSize, rightMarginSize, bottomMarginSize, FULL_BRIGHT_LIGHTMAP + leftMarginSize, rightMarginSize, bottomMarginSize, LightTexture.FULL_BRIGHT ); // The main text @@ -165,7 +170,7 @@ public final class FixedWidthFontRenderer { var rowY = y + FONT_HEIGHT * i; drawBackground( emitter, x, rowY, terminal.getBackgroundColourLine(i), palette, - leftMarginSize, rightMarginSize, FONT_HEIGHT, FULL_BRIGHT_LIGHTMAP + leftMarginSize, rightMarginSize, FONT_HEIGHT, LightTexture.FULL_BRIGHT ); } } @@ -181,7 +186,7 @@ public final class FixedWidthFontRenderer { public static void drawCursor(QuadEmitter emitter, float x, float y, Terminal terminal) { if (isCursorVisible(terminal) && FrameInfo.getGlobalCursorBlink()) { var colour = terminal.getPalette().getRenderColours(15 - terminal.getTextColour()); - drawChar(emitter, x + terminal.getCursorX() * FONT_WIDTH, y + terminal.getCursorY() * FONT_HEIGHT, '_', colour, FULL_BRIGHT_LIGHTMAP); + drawChar(emitter, x + terminal.getCursorX() * FONT_WIDTH, y + terminal.getCursorY() * FONT_HEIGHT, '_', colour, LightTexture.FULL_BRIGHT); } } @@ -207,7 +212,7 @@ public final class FixedWidthFontRenderer { } public static void drawEmptyTerminal(QuadEmitter emitter, float x, float y, float width, float height) { - drawQuad(emitter, x, y, 0, width, height, BLACK, FULL_BRIGHT_LIGHTMAP); + drawQuad(emitter, x, y, 0, width, height, BLACK, LightTexture.FULL_BRIGHT); } public record QuadEmitter(Matrix4f poseMatrix, VertexConsumer consumer) { @@ -220,11 +225,10 @@ public final class FixedWidthFontRenderer { private static void quad(QuadEmitter c, float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2, int light) { var poseMatrix = c.poseMatrix(); var consumer = c.consumer(); - int r = FastColor.ARGB32.red(colour), g = FastColor.ARGB32.green(colour), b = FastColor.ARGB32.blue(colour), a = FastColor.ARGB32.alpha(colour); - consumer.addVertex(poseMatrix, x1, y1, z).setColor(r, g, b, a).setUv(u1, v1).setLight(light); - consumer.addVertex(poseMatrix, x1, y2, z).setColor(r, g, b, a).setUv(u1, v2).setLight(light); - consumer.addVertex(poseMatrix, x2, y2, z).setColor(r, g, b, a).setUv(u2, v2).setLight(light); - consumer.addVertex(poseMatrix, x2, y1, z).setColor(r, g, b, a).setUv(u2, v1).setLight(light); + consumer.addVertex(poseMatrix, x1, y1, z).setColor(colour).setUv(u1, v1).setLight(light); + consumer.addVertex(poseMatrix, x1, y2, z).setColor(colour).setUv(u1, v2).setLight(light); + consumer.addVertex(poseMatrix, x2, y2, z).setColor(colour).setUv(u2, v2).setLight(light); + consumer.addVertex(poseMatrix, x2, y1, z).setColor(colour).setUv(u2, v1).setLight(light); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/vbo/DirectBuffers.java b/projects/common/src/client/java/dan200/computercraft/client/render/vbo/DirectBuffers.java deleted file mode 100644 index 0c04be326..000000000 --- a/projects/common/src/client/java/dan200/computercraft/client/render/vbo/DirectBuffers.java +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.client.render.vbo; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.BufferUploader; -import net.minecraft.Util; -import org.lwjgl.opengl.GL; -import org.lwjgl.opengl.GL15C; -import org.lwjgl.opengl.GL45C; - -import java.nio.ByteBuffer; - -/** - * Provides utilities to interact with OpenGL's buffer objects, either using direct state access or binding/unbinding - * it. - */ -public class DirectBuffers { - public static final boolean HAS_DSA; - static final boolean ON_LINUX = Util.getPlatform() == Util.OS.LINUX; - - static { - var capabilities = GL.getCapabilities(); - HAS_DSA = capabilities.OpenGL45 || capabilities.GL_ARB_direct_state_access; - } - - public static int createBuffer() { - return HAS_DSA ? GL45C.glCreateBuffers() : GL15C.glGenBuffers(); - } - - /** - * Delete a previously created buffer. - *

- * On Linux, {@link GlStateManager#_glDeleteBuffers(int)} clears a buffer before deleting it. However, this involves - * binding and unbinding the buffer, conflicting with {@link BufferUploader}'s cache. This deletion method uses - * our existing {@link #setEmptyBufferData(int, int, int)}, which correctly handles clearing the buffer. - * - * @param type The buffer's type. - * @param id The buffer's ID. - */ - public static void deleteBuffer(int type, int id) { - RenderSystem.assertOnRenderThread(); - if (ON_LINUX) DirectBuffers.setEmptyBufferData(type, id, GL15C.GL_DYNAMIC_DRAW); - GL15C.glDeleteBuffers(id); - } - - public static void setBufferData(int type, int id, ByteBuffer buffer, int flags) { - if (HAS_DSA) { - GL45C.glNamedBufferData(id, buffer, flags); - } else { - if (type == GL15C.GL_ARRAY_BUFFER) BufferUploader.reset(); - GlStateManager._glBindBuffer(type, id); - GlStateManager._glBufferData(type, buffer, flags); - GlStateManager._glBindBuffer(type, 0); - } - } - - public static void setEmptyBufferData(int type, int id, int flags) { - if (HAS_DSA) { - GL45C.glNamedBufferData(id, 0, flags); - } else { - if (type == GL15C.GL_ARRAY_BUFFER) BufferUploader.reset(); - GlStateManager._glBindBuffer(type, id); - GlStateManager._glBufferData(type, 0, flags); - GlStateManager._glBindBuffer(type, 0); - } - } -} diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/vbo/DirectVertexBuffer.java b/projects/common/src/client/java/dan200/computercraft/client/render/vbo/DirectVertexBuffer.java deleted file mode 100644 index 958ddfa0c..000000000 --- a/projects/common/src/client/java/dan200/computercraft/client/render/vbo/DirectVertexBuffer.java +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.client.render.vbo; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.BufferUploader; -import com.mojang.blaze3d.vertex.VertexBuffer; -import com.mojang.blaze3d.vertex.VertexFormat; -import net.minecraft.client.renderer.ShaderInstance; -import org.joml.Matrix4f; -import org.lwjgl.opengl.GL15; -import org.lwjgl.opengl.GL15C; -import org.lwjgl.opengl.GL45C; - -import java.nio.ByteBuffer; - -/** - * A version of {@link VertexBuffer} which allows uploading {@link ByteBuffer}s directly. - *

- * This should probably be its own class (rather than subclassing), but I need access to {@link VertexBuffer#drawWithShader}. - */ -public class DirectVertexBuffer extends VertexBuffer { - private int actualIndexCount; - - public DirectVertexBuffer() { - super(Usage.STATIC); - if (DirectBuffers.HAS_DSA) { - RenderSystem.glDeleteBuffers(vertexBufferId); - if (DirectBuffers.ON_LINUX) BufferUploader.reset(); // See comment on DirectBuffers.deleteBuffer. - vertexBufferId = GL45C.glCreateBuffers(); - } - } - - public void upload(int vertexCount, VertexFormat.Mode mode, VertexFormat format, ByteBuffer buffer) { - bind(); - - this.mode = mode; - actualIndexCount = indexCount = mode.indexCount(vertexCount); - indexType = VertexFormat.IndexType.SHORT; - - RenderSystem.assertOnRenderThread(); - - DirectBuffers.setBufferData(GL15.GL_ARRAY_BUFFER, vertexBufferId, buffer, GL15.GL_STATIC_DRAW); - if (format != this.format) { - if (this.format != null) this.format.clearBufferState(); - this.format = format; - - GL15C.glBindBuffer(GL15C.GL_ARRAY_BUFFER, vertexBufferId); - format.setupBufferState(); - GL15C.glBindBuffer(GL15C.GL_ARRAY_BUFFER, 0); - } - - var indexBuffer = RenderSystem.getSequentialBuffer(mode); - if (indexBuffer != sequentialIndices || !indexBuffer.hasStorage(indexCount)) { - indexBuffer.bind(indexCount); - sequentialIndices = indexBuffer; - } - } - - public void drawWithShader(Matrix4f modelView, Matrix4f projection, ShaderInstance shader, int indexCount) { - this.indexCount = indexCount; - drawWithShader(modelView, projection, shader); - this.indexCount = actualIndexCount; - } - - public int getIndexCount() { - return actualIndexCount; - } - - @Override - public void close() { - super.close(); - if (DirectBuffers.ON_LINUX) BufferUploader.reset(); // See comment on DirectBuffers.deleteBuffer. - } -} diff --git a/projects/common/src/client/java/dan200/computercraft/data/client/ClientDataProviders.java b/projects/common/src/client/java/dan200/computercraft/data/client/ClientDataProviders.java index 5d7b1a084..c3712a0fd 100644 --- a/projects/common/src/client/java/dan200/computercraft/data/client/ClientDataProviders.java +++ b/projects/common/src/client/java/dan200/computercraft/data/client/ClientDataProviders.java @@ -16,9 +16,11 @@ import net.minecraft.core.HolderLookup; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; +import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.function.Function; import java.util.stream.Stream; /** @@ -32,22 +34,21 @@ public final class ClientDataProviders { public static void add(DataProviders.GeneratorSink generator, CompletableFuture registries) { generator.addFromCodec("Block atlases", PackType.CLIENT_RESOURCES, "atlases", SpriteSources.FILE_CODEC, out -> { - out.accept(ResourceLocation.withDefaultNamespace("blocks"), List.of( - new SingleFile(UpgradeSlot.LEFT_UPGRADE, Optional.empty()), - new SingleFile(UpgradeSlot.RIGHT_UPGRADE, Optional.empty()), - new SingleFile(LecternPrintoutModel.TEXTURE, Optional.empty()) - )); - out.accept(GuiSprites.SPRITE_SHEET, Stream.of( - // Buttons - GuiSprites.TURNED_OFF.textures(), - GuiSprites.TURNED_ON.textures(), - GuiSprites.TERMINATE.textures(), + out.accept(ResourceLocation.withDefaultNamespace("blocks"), makeSprites(Stream.of( + // Upgrade slot backgrounds + UpgradeSlot.LEFT_UPGRADE, + UpgradeSlot.RIGHT_UPGRADE, + // Texture for lectern printouts + LecternPrintoutModel.TEXTURE + ))); + + out.accept(GuiSprites.SPRITE_SHEET, makeSprites( // Computers GuiSprites.COMPUTER_NORMAL.textures(), GuiSprites.COMPUTER_ADVANCED.textures(), GuiSprites.COMPUTER_COMMAND.textures(), GuiSprites.COMPUTER_COLOUR.textures() - ).flatMap(x -> x).map(x -> new SingleFile(x, Optional.empty())).toList()); + )); }); generator.add(pack -> new ExtraModelsProvider(pack, registries) { @@ -57,4 +58,10 @@ public final class ClientDataProviders { } }); } + + @SafeVarargs + @SuppressWarnings("varargs") + private static List makeSprites(final Stream... files) { + return Arrays.stream(files).flatMap(Function.identity()).map(x -> new SingleFile(x, Optional.empty())).toList(); + } } diff --git a/projects/common/src/generated/resources/assets/computercraft/atlases/gui.json b/projects/common/src/generated/resources/assets/computercraft/atlases/gui.json index 8ad965c9d..cbb2c9ee1 100644 --- a/projects/common/src/generated/resources/assets/computercraft/atlases/gui.json +++ b/projects/common/src/generated/resources/assets/computercraft/atlases/gui.json @@ -1,11 +1,5 @@ { "sources": [ - {"type": "minecraft:single", "resource": "computercraft:gui/buttons/turned_off"}, - {"type": "minecraft:single", "resource": "computercraft:gui/buttons/turned_off_hover"}, - {"type": "minecraft:single", "resource": "computercraft:gui/buttons/turned_on"}, - {"type": "minecraft:single", "resource": "computercraft:gui/buttons/turned_on_hover"}, - {"type": "minecraft:single", "resource": "computercraft:gui/buttons/terminate"}, - {"type": "minecraft:single", "resource": "computercraft:gui/buttons/terminate_hover"}, {"type": "minecraft:single", "resource": "computercraft:gui/border_normal"}, {"type": "minecraft:single", "resource": "computercraft:gui/pocket_bottom_normal"}, {"type": "minecraft:single", "resource": "computercraft:gui/sidebar_normal"}, diff --git a/projects/common/src/generated/resources/assets/computercraft/lang/en_us.json b/projects/common/src/generated/resources/assets/computercraft/lang/en_us.json index db6f6b97e..4dd4ab328 100644 --- a/projects/common/src/generated/resources/assets/computercraft/lang/en_us.json +++ b/projects/common/src/generated/resources/assets/computercraft/lang/en_us.json @@ -124,8 +124,6 @@ "gui.computercraft.config.maximum_open_files.tooltip": "Set how many files a computer can have open at the same time. Set to 0 for unlimited.\nRange: > 0", "gui.computercraft.config.monitor_distance": "Monitor distance", "gui.computercraft.config.monitor_distance.tooltip": "The maximum distance monitors will render at. This defaults to the standard tile\nentity limit, but may be extended if you wish to build larger monitors.\nRange: 16 ~ 1024", - "gui.computercraft.config.monitor_renderer": "Monitor renderer", - "gui.computercraft.config.monitor_renderer.tooltip": "The renderer to use for monitors. Generally this should be kept at \"best\" - if\nmonitors have performance issues, you may wish to experiment with alternative\nrenderers.\nAllowed Values: BEST, TBO, VBO", "gui.computercraft.config.peripheral": "Peripherals", "gui.computercraft.config.peripheral.command_block_enabled": "Enable command block peripheral", "gui.computercraft.config.peripheral.command_block_enabled.tooltip": "Enable Command Block peripheral support", diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_1.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk.json similarity index 76% rename from projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_1.json rename to projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk.json index 2a7291ff1..d23d78065 100644 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_1.json +++ b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk.json @@ -5,8 +5,8 @@ "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, "trigger": "minecraft:inventory_changed" }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_1"}, "trigger": "minecraft:recipe_unlocked"} + "has_the_recipe": {"conditions": {"recipe": "computercraft:disk"}, "trigger": "minecraft:recipe_unlocked"} }, "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_1"]} + "rewards": {"recipes": ["computercraft:disk"]} } diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_10.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_10.json deleted file mode 100644 index 742dc3be7..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_10.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_10"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_10"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_11.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_11.json deleted file mode 100644 index 86873eb07..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_11.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_11"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_11"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_12.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_12.json deleted file mode 100644 index d200eec09..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_12.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_12"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_12"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_13.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_13.json deleted file mode 100644 index c8e8dbec0..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_13.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_13"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_13"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_14.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_14.json deleted file mode 100644 index b08657cbf..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_14.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_14"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_14"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_15.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_15.json deleted file mode 100644 index 56444f527..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_15.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_15"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_15"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_16.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_16.json deleted file mode 100644 index b4a5255b3..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_16.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_16"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_16"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_2.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_2.json deleted file mode 100644 index e96d9280a..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_2.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_2"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_2"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_3.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_3.json deleted file mode 100644 index d63ba4171..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_3.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_3"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_3"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_4.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_4.json deleted file mode 100644 index dffcef439..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_4.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_4"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_4"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_5.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_5.json deleted file mode 100644 index 488c1220d..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_5.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_5"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_5"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_6.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_6.json deleted file mode 100644 index 1feaae00c..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_6.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_6"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_6"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_7.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_7.json deleted file mode 100644 index 6498b602a..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_7.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_7"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_7"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_8.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_8.json deleted file mode 100644 index ff252f732..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_8.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_8"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_8"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_9.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_9.json deleted file mode 100644 index 250094755..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_9.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_drive": { - "conditions": {"items": [{"items": "computercraft:disk_drive"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_9"}, "trigger": "minecraft:recipe_unlocked"} - }, - "requirements": [["has_the_recipe", "has_drive"]], - "rewards": {"recipes": ["computercraft:disk_9"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/wired_modem_full_from.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/wired_modem_full_from.json deleted file mode 100644 index 66f22c878..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/wired_modem_full_from.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_modem": { - "conditions": {"items": [{"items": "#computercraft:wired_modem"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": {"recipe": "computercraft:wired_modem_full_from"}, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [["has_the_recipe", "has_modem"]], - "rewards": {"recipes": ["computercraft:wired_modem_full_from"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/wired_modem_full_to.json b/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/wired_modem_full_to.json deleted file mode 100644 index e6ce46a27..000000000 --- a/projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/wired_modem_full_to.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_modem": { - "conditions": {"items": [{"items": "#computercraft:wired_modem"}]}, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": {"recipe": "computercraft:wired_modem_full_to"}, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [["has_the_recipe", "has_modem"]], - "rewards": {"recipes": ["computercraft:wired_modem_full_to"]} -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/cable.json b/projects/common/src/generated/resources/data/computercraft/recipe/cable.json index 89384fc4c..51017970a 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/cable.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/cable.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"item": "minecraft:stone"}, "R": {"tag": "c:dusts/redstone"}}, + "key": {"#": "minecraft:stone", "R": "#c:dusts/redstone"}, "pattern": [" # ", "#R#", " # "], "result": {"count": 6, "id": "computercraft:cable"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/computer_advanced.json b/projects/common/src/generated/resources/data/computercraft/recipe/computer_advanced.json index 9a335214f..863ffe653 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/computer_advanced.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/computer_advanced.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:ingots/gold"}, "G": {"tag": "c:glass_panes"}, "R": {"tag": "c:dusts/redstone"}}, + "key": {"#": "#c:ingots/gold", "G": "#c:glass_panes", "R": "#c:dusts/redstone"}, "pattern": ["###", "#R#", "#G#"], "result": {"count": 1, "id": "computercraft:computer_advanced"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/computer_advanced_upgrade.json b/projects/common/src/generated/resources/data/computercraft/recipe/computer_advanced_upgrade.json index 9af31459c..c6c0bb3f5 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/computer_advanced_upgrade.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/computer_advanced_upgrade.json @@ -1,8 +1,8 @@ { "type": "computercraft:transform_shaped", "category": "redstone", - "function": [{"type": "computercraft:copy_components", "from": {"item": "computercraft:computer_normal"}}], - "key": {"#": {"tag": "c:ingots/gold"}, "C": {"item": "computercraft:computer_normal"}}, + "function": [{"type": "computercraft:copy_components", "from": "computercraft:computer_normal"}], + "key": {"#": "#c:ingots/gold", "C": "computercraft:computer_normal"}, "pattern": ["###", "#C#", "# #"], "result": {"count": 1, "id": "computercraft:computer_advanced"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/computer_command.json b/projects/common/src/generated/resources/data/computercraft/recipe/computer_command.json index 4ad39c549..e24028d81 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/computer_command.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/computer_command.json @@ -1,11 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": { - "#": {"tag": "c:ingots/gold"}, - "G": {"tag": "c:glass_panes"}, - "R": {"item": "minecraft:command_block"} - }, + "key": {"#": "#c:ingots/gold", "G": "#c:glass_panes", "R": "minecraft:command_block"}, "pattern": ["###", "#R#", "#G#"], "result": {"count": 1, "id": "computercraft:computer_command"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/computer_normal.json b/projects/common/src/generated/resources/data/computercraft/recipe/computer_normal.json index 84117ee95..ebccce53a 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/computer_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/computer_normal.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"item": "minecraft:stone"}, "G": {"tag": "c:glass_panes"}, "R": {"tag": "c:dusts/redstone"}}, + "key": {"#": "minecraft:stone", "G": "#c:glass_panes", "R": "#c:dusts/redstone"}, "pattern": ["###", "#R#", "#G#"], "result": {"count": 1, "id": "computercraft:computer_normal"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk.json index 1c2e811fe..09c15083f 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/disk.json @@ -1 +1,6 @@ -{"type": "computercraft:disk", "category": "misc"} +{ + "type": "computercraft:disk", + "category": "redstone", + "group": "computercraft:disk", + "ingredients": ["#c:dusts/redstone", "minecraft:paper"] +} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_1.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_1.json deleted file mode 100644 index b7f19e31b..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_1.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:black_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 1118481, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_10.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_10.json deleted file mode 100644 index b427391b1..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_10.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:pink_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 15905484, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_11.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_11.json deleted file mode 100644 index fcc0b9b38..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_11.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:lime_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 8375321, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_12.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_12.json deleted file mode 100644 index 615cb1ddd..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_12.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:yellow_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 14605932, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_13.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_13.json deleted file mode 100644 index 50d462d73..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_13.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [ - {"tag": "c:dusts/redstone"}, - {"item": "minecraft:paper"}, - {"item": "minecraft:light_blue_dye"} - ], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 10072818, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_14.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_14.json deleted file mode 100644 index 3b1301f5b..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_14.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:magenta_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 15040472, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_15.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_15.json deleted file mode 100644 index 83beaae21..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_15.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:orange_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 15905331, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_16.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_16.json deleted file mode 100644 index 1d49329a2..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_16.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:white_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 15790320, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_2.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_2.json deleted file mode 100644 index 232d5ea43..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_2.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:red_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 13388876, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_3.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_3.json deleted file mode 100644 index 08da162d8..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_3.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:green_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 5744206, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_4.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_4.json deleted file mode 100644 index 795b1c0a6..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_4.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:brown_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 8349260, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_5.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_5.json deleted file mode 100644 index cd3c6716a..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_5.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:blue_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 3368652, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_6.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_6.json deleted file mode 100644 index 0832d11bb..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_6.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:purple_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 11691749, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_7.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_7.json deleted file mode 100644 index 3ba73a7dd..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_7.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:cyan_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 5020082, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_8.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_8.json deleted file mode 100644 index c1b111e67..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_8.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [ - {"tag": "c:dusts/redstone"}, - {"item": "minecraft:paper"}, - {"item": "minecraft:light_gray_dye"} - ], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 10066329, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_9.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_9.json deleted file mode 100644 index b6a22ced8..000000000 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_9.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "computercraft:impostor_shapeless", - "category": "redstone", - "group": "computercraft:disk", - "ingredients": [{"tag": "c:dusts/redstone"}, {"item": "minecraft:paper"}, {"item": "minecraft:gray_dye"}], - "result": { - "components": {"minecraft:dyed_color": {"rgb": 5000268, "show_in_tooltip": false}}, - "count": 1, - "id": "computercraft:disk" - } -} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/disk_drive.json b/projects/common/src/generated/resources/data/computercraft/recipe/disk_drive.json index 3a0026016..166f6231e 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/disk_drive.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/disk_drive.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"item": "minecraft:stone"}, "R": {"tag": "c:dusts/redstone"}}, + "key": {"#": "minecraft:stone", "R": "#c:dusts/redstone"}, "pattern": ["###", "#R#", "#R#"], "result": {"count": 1, "id": "computercraft:disk_drive"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/monitor_advanced.json b/projects/common/src/generated/resources/data/computercraft/recipe/monitor_advanced.json index 070392fe2..c999417c7 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/monitor_advanced.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/monitor_advanced.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:ingots/gold"}, "G": {"tag": "c:glass_panes"}}, + "key": {"#": "#c:ingots/gold", "G": "#c:glass_panes"}, "pattern": ["###", "#G#", "###"], "result": {"count": 4, "id": "computercraft:monitor_advanced"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/monitor_normal.json b/projects/common/src/generated/resources/data/computercraft/recipe/monitor_normal.json index a52103dd7..89f691cf8 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/monitor_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/monitor_normal.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"item": "minecraft:stone"}, "G": {"tag": "c:glass_panes"}}, + "key": {"#": "minecraft:stone", "G": "#c:glass_panes"}, "pattern": ["###", "#G#", "###"], "result": {"count": 1, "id": "computercraft:monitor_normal"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/speaker.json b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/speaker.json index 5848ae4c3..de0c09b5c 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/speaker.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/speaker.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:pocket_advanced", - "key": {"#": {"item": "computercraft:speaker"}, "P": {"item": "computercraft:pocket_computer_advanced"}}, + "key": {"#": "computercraft:speaker", "P": "computercraft:pocket_computer_advanced"}, "pattern": ["#", "P"], "result": { "components": {"computercraft:pocket_upgrade": {"id": "computercraft:speaker"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/wireless_modem_advanced.json b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/wireless_modem_advanced.json index c88b00878..d6798f026 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/wireless_modem_advanced.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/wireless_modem_advanced.json @@ -2,10 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:pocket_advanced", - "key": { - "#": {"item": "computercraft:wireless_modem_advanced"}, - "P": {"item": "computercraft:pocket_computer_advanced"} - }, + "key": {"#": "computercraft:wireless_modem_advanced", "P": "computercraft:pocket_computer_advanced"}, "pattern": ["#", "P"], "result": { "components": {"computercraft:pocket_upgrade": {"id": "computercraft:wireless_modem_advanced"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/wireless_modem_normal.json b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/wireless_modem_normal.json index 43180d4ff..f86914d72 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/wireless_modem_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_advanced/computercraft/wireless_modem_normal.json @@ -2,10 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:pocket_advanced", - "key": { - "#": {"item": "computercraft:wireless_modem_normal"}, - "P": {"item": "computercraft:pocket_computer_advanced"} - }, + "key": {"#": "computercraft:wireless_modem_normal", "P": "computercraft:pocket_computer_advanced"}, "pattern": ["#", "P"], "result": { "components": {"computercraft:pocket_upgrade": {"id": "computercraft:wireless_modem_normal"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_advanced.json b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_advanced.json index 911f07c81..1636bb255 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_advanced.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_advanced.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:ingots/gold"}, "A": {"item": "minecraft:golden_apple"}, "G": {"tag": "c:glass_panes"}}, + "key": {"#": "#c:ingots/gold", "A": "minecraft:golden_apple", "G": "#c:glass_panes"}, "pattern": ["###", "#A#", "#G#"], "result": {"count": 1, "id": "computercraft:pocket_computer_advanced"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_advanced_upgrade.json b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_advanced_upgrade.json index 52649787f..f008963b3 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_advanced_upgrade.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_advanced_upgrade.json @@ -1,10 +1,8 @@ { "type": "computercraft:transform_shaped", "category": "redstone", - "function": [ - {"type": "computercraft:copy_components", "from": {"item": "computercraft:pocket_computer_normal"}} - ], - "key": {"#": {"tag": "c:ingots/gold"}, "C": {"item": "computercraft:pocket_computer_normal"}}, + "function": [{"type": "computercraft:copy_components", "from": "computercraft:pocket_computer_normal"}], + "key": {"#": "#c:ingots/gold", "C": "computercraft:pocket_computer_normal"}, "pattern": ["###", "#C#", "# #"], "result": {"count": 1, "id": "computercraft:pocket_computer_advanced"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_normal.json b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_normal.json index 4bef87ac8..079c9752c 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_computer_normal.json @@ -1,11 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": { - "#": {"item": "minecraft:stone"}, - "A": {"item": "minecraft:golden_apple"}, - "G": {"tag": "c:glass_panes"} - }, + "key": {"#": "minecraft:stone", "A": "minecraft:golden_apple", "G": "#c:glass_panes"}, "pattern": ["###", "#A#", "#G#"], "result": {"count": 1, "id": "computercraft:pocket_computer_normal"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/speaker.json b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/speaker.json index f13b2cafa..3836d300c 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/speaker.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/speaker.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:pocket_normal", - "key": {"#": {"item": "computercraft:speaker"}, "P": {"item": "computercraft:pocket_computer_normal"}}, + "key": {"#": "computercraft:speaker", "P": "computercraft:pocket_computer_normal"}, "pattern": ["#", "P"], "result": { "components": {"computercraft:pocket_upgrade": {"id": "computercraft:speaker"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/wireless_modem_advanced.json b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/wireless_modem_advanced.json index 63f38c618..90ca2f8bb 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/wireless_modem_advanced.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/wireless_modem_advanced.json @@ -2,10 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:pocket_normal", - "key": { - "#": {"item": "computercraft:wireless_modem_advanced"}, - "P": {"item": "computercraft:pocket_computer_normal"} - }, + "key": {"#": "computercraft:wireless_modem_advanced", "P": "computercraft:pocket_computer_normal"}, "pattern": ["#", "P"], "result": { "components": {"computercraft:pocket_upgrade": {"id": "computercraft:wireless_modem_advanced"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/wireless_modem_normal.json b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/wireless_modem_normal.json index a875e7413..906bece74 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/wireless_modem_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/pocket_normal/computercraft/wireless_modem_normal.json @@ -2,10 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:pocket_normal", - "key": { - "#": {"item": "computercraft:wireless_modem_normal"}, - "P": {"item": "computercraft:pocket_computer_normal"} - }, + "key": {"#": "computercraft:wireless_modem_normal", "P": "computercraft:pocket_computer_normal"}, "pattern": ["#", "P"], "result": { "components": {"computercraft:pocket_upgrade": {"id": "computercraft:wireless_modem_normal"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/printed_book.json b/projects/common/src/generated/resources/data/computercraft/recipe/printed_book.json index 1f9d9b36b..8efc4f70a 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/printed_book.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/printed_book.json @@ -1,12 +1,8 @@ { "type": "computercraft:printout", "category": "redstone", - "ingredients": [{"tag": "c:leathers"}, {"tag": "c:strings"}], + "ingredients": ["#c:leathers", "#c:strings"], "min_printouts": 1, - "printout": [ - {"item": "computercraft:printed_page"}, - {"item": "computercraft:printed_pages"}, - {"item": "minecraft:paper"} - ], + "printout": ["computercraft:printed_page", "computercraft:printed_pages", "minecraft:paper"], "result": {"count": 1, "id": "computercraft:printed_book"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/printed_pages.json b/projects/common/src/generated/resources/data/computercraft/recipe/printed_pages.json index 6b8f2a00b..173aff16f 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/printed_pages.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/printed_pages.json @@ -1,12 +1,8 @@ { "type": "computercraft:printout", "category": "redstone", - "ingredients": [{"tag": "c:strings"}], + "ingredients": ["#c:strings"], "min_printouts": 2, - "printout": [ - {"item": "computercraft:printed_page"}, - {"item": "computercraft:printed_pages"}, - {"item": "minecraft:paper"} - ], + "printout": ["computercraft:printed_page", "computercraft:printed_pages", "minecraft:paper"], "result": {"count": 1, "id": "computercraft:printed_pages"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/printer.json b/projects/common/src/generated/resources/data/computercraft/recipe/printer.json index 6fb87d2c3..9b658c1ac 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/printer.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/printer.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"item": "minecraft:stone"}, "D": {"tag": "c:dyes"}, "R": {"tag": "c:dusts/redstone"}}, + "key": {"#": "minecraft:stone", "D": "#c:dyes", "R": "#c:dusts/redstone"}, "pattern": ["###", "#R#", "#D#"], "result": {"count": 1, "id": "computercraft:printer"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/skull_cloudy.json b/projects/common/src/generated/resources/data/computercraft/recipe/skull_cloudy.json index 6b32018d3..23d7b36f4 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/skull_cloudy.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/skull_cloudy.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shapeless", "category": "misc", - "ingredients": [{"tag": "minecraft:skulls"}, {"item": "computercraft:monitor_normal"}], + "ingredients": ["#minecraft:skulls", "computercraft:monitor_normal"], "result": { "components": { "minecraft:profile": {"id": [1829193526, -1310112904, -1449411193, 2005015708], "name": "Cloudhunter"} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/skull_dan200.json b/projects/common/src/generated/resources/data/computercraft/recipe/skull_dan200.json index 38dd3a135..517f7b485 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/skull_dan200.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/skull_dan200.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shapeless", "category": "misc", - "ingredients": [{"tag": "minecraft:skulls"}, {"item": "computercraft:computer_advanced"}], + "ingredients": ["#minecraft:skulls", "computercraft:computer_advanced"], "result": { "components": {"minecraft:profile": {"id": [-204941669, 125191442, -2076913230, 374933995], "name": "dan200"}}, "count": 1, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/speaker.json b/projects/common/src/generated/resources/data/computercraft/recipe/speaker.json index 0e61faa47..08dd768b0 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/speaker.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/speaker.json @@ -1,11 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": { - "#": {"item": "minecraft:stone"}, - "N": {"item": "minecraft:note_block"}, - "R": {"tag": "c:dusts/redstone"} - }, + "key": {"#": "minecraft:stone", "N": "minecraft:note_block", "R": "#c:dusts/redstone"}, "pattern": ["###", "#N#", "#R#"], "result": {"count": 1, "id": "computercraft:speaker"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced.json index 4e86b0316..5f9e88bf6 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced.json @@ -1,12 +1,8 @@ { "type": "computercraft:transform_shaped", "category": "redstone", - "function": [{"type": "computercraft:copy_components", "from": {"item": "computercraft:computer_advanced"}}], - "key": { - "#": {"tag": "c:ingots/gold"}, - "C": {"item": "computercraft:computer_advanced"}, - "I": {"tag": "c:chests/wooden"} - }, + "function": [{"type": "computercraft:copy_components", "from": "computercraft:computer_advanced"}], + "key": {"#": "#c:ingots/gold", "C": "computercraft:computer_advanced", "I": "#c:chests/wooden"}, "pattern": ["###", "#C#", "#I#"], "result": {"count": 1, "id": "computercraft:turtle_advanced"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/speaker.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/speaker.json index 521802cc8..b52ab3e1b 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/speaker.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/speaker.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_advanced", - "key": {"#": {"item": "computercraft:speaker"}, "T": {"item": "computercraft:turtle_advanced"}}, + "key": {"#": "computercraft:speaker", "T": "computercraft:turtle_advanced"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "computercraft:speaker"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/wireless_modem_advanced.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/wireless_modem_advanced.json index a6cda706d..47a4b7343 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/wireless_modem_advanced.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/wireless_modem_advanced.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_advanced", - "key": {"#": {"item": "computercraft:wireless_modem_advanced"}, "T": {"item": "computercraft:turtle_advanced"}}, + "key": {"#": "computercraft:wireless_modem_advanced", "T": "computercraft:turtle_advanced"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "computercraft:wireless_modem_advanced"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/wireless_modem_normal.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/wireless_modem_normal.json index 166cff86e..bb7db9582 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/wireless_modem_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/computercraft/wireless_modem_normal.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_advanced", - "key": {"#": {"item": "computercraft:wireless_modem_normal"}, "T": {"item": "computercraft:turtle_advanced"}}, + "key": {"#": "computercraft:wireless_modem_normal", "T": "computercraft:turtle_advanced"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "computercraft:wireless_modem_normal"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/crafting_table.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/crafting_table.json index 8866543ba..fc776b66a 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/crafting_table.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/crafting_table.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_advanced", - "key": {"#": {"item": "minecraft:crafting_table"}, "T": {"item": "computercraft:turtle_advanced"}}, + "key": {"#": "minecraft:crafting_table", "T": "computercraft:turtle_advanced"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:crafting_table"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_axe.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_axe.json index f7c255e29..7ec583c01 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_axe.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_axe.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_advanced", - "key": {"#": {"item": "minecraft:diamond_axe"}, "T": {"item": "computercraft:turtle_advanced"}}, + "key": {"#": "minecraft:diamond_axe", "T": "computercraft:turtle_advanced"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:diamond_axe"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_hoe.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_hoe.json index e921bba79..34e80ec03 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_hoe.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_hoe.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_advanced", - "key": {"#": {"item": "minecraft:diamond_hoe"}, "T": {"item": "computercraft:turtle_advanced"}}, + "key": {"#": "minecraft:diamond_hoe", "T": "computercraft:turtle_advanced"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:diamond_hoe"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_pickaxe.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_pickaxe.json index fc267afc0..a7cc3bab7 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_pickaxe.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_pickaxe.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_advanced", - "key": {"#": {"item": "minecraft:diamond_pickaxe"}, "T": {"item": "computercraft:turtle_advanced"}}, + "key": {"#": "minecraft:diamond_pickaxe", "T": "computercraft:turtle_advanced"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:diamond_pickaxe"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_shovel.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_shovel.json index 77bba7a39..cf622099e 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_shovel.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_shovel.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_advanced", - "key": {"#": {"item": "minecraft:diamond_shovel"}, "T": {"item": "computercraft:turtle_advanced"}}, + "key": {"#": "minecraft:diamond_shovel", "T": "computercraft:turtle_advanced"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:diamond_shovel"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_sword.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_sword.json index 53078aa9a..22ea4ad9b 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_sword.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced/minecraft/diamond_sword.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_advanced", - "key": {"#": {"item": "minecraft:diamond_sword"}, "T": {"item": "computercraft:turtle_advanced"}}, + "key": {"#": "minecraft:diamond_sword", "T": "computercraft:turtle_advanced"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:diamond_sword"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_overlays/rainbow_flag.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_overlays/rainbow_flag.json index 03790f733..4bfbc5f85 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_overlays/rainbow_flag.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_overlays/rainbow_flag.json @@ -5,19 +5,19 @@ { "type": "computercraft:copy_components", "exclude": ["computercraft:overlay"], - "from": {"item": "computercraft:turtle_advanced"} + "from": "computercraft:turtle_advanced" } ], "group": "computercraft:turtle_advanced_overlay", "ingredients": [ - {"tag": "c:dyes/red"}, - {"tag": "c:dyes/orange"}, - {"tag": "c:dyes/yellow"}, - {"tag": "c:dyes/green"}, - {"tag": "c:dyes/blue"}, - {"tag": "c:dyes/purple"}, - {"item": "minecraft:stick"}, - {"item": "computercraft:turtle_advanced"} + "#c:dyes/red", + "#c:dyes/orange", + "#c:dyes/yellow", + "#c:dyes/green", + "#c:dyes/blue", + "#c:dyes/purple", + "minecraft:stick", + "computercraft:turtle_advanced" ], "result": { "components": {"computercraft:overlay": "computercraft:rainbow_flag"}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_overlays/trans_flag.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_overlays/trans_flag.json index 9bd459124..dab1cbb2d 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_overlays/trans_flag.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_overlays/trans_flag.json @@ -5,16 +5,16 @@ { "type": "computercraft:copy_components", "exclude": ["computercraft:overlay"], - "from": {"item": "computercraft:turtle_advanced"} + "from": "computercraft:turtle_advanced" } ], "group": "computercraft:turtle_advanced_overlay", "ingredients": [ - {"tag": "c:dyes/light_blue"}, - {"tag": "c:dyes/pink"}, - {"tag": "c:dyes/white"}, - {"item": "minecraft:stick"}, - {"item": "computercraft:turtle_advanced"} + "#c:dyes/light_blue", + "#c:dyes/pink", + "#c:dyes/white", + "minecraft:stick", + "computercraft:turtle_advanced" ], "result": { "components": {"computercraft:overlay": "computercraft:trans_flag"}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_upgrade.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_upgrade.json index 34e794127..ec6e86979 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_upgrade.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_advanced_upgrade.json @@ -1,12 +1,8 @@ { "type": "computercraft:transform_shaped", "category": "redstone", - "function": [{"type": "computercraft:copy_components", "from": {"item": "computercraft:turtle_normal"}}], - "key": { - "#": {"tag": "c:ingots/gold"}, - "B": {"tag": "c:storage_blocks/gold"}, - "C": {"item": "computercraft:turtle_normal"} - }, + "function": [{"type": "computercraft:copy_components", "from": "computercraft:turtle_normal"}], + "key": {"#": "#c:ingots/gold", "B": "#c:storage_blocks/gold", "C": "computercraft:turtle_normal"}, "pattern": ["###", "#C#", " B "], "result": {"count": 1, "id": "computercraft:turtle_advanced"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal.json index 8c8312083..8fbd8c1e5 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal.json @@ -1,12 +1,8 @@ { "type": "computercraft:transform_shaped", "category": "redstone", - "function": [{"type": "computercraft:copy_components", "from": {"item": "computercraft:computer_normal"}}], - "key": { - "#": {"tag": "c:ingots/iron"}, - "C": {"item": "computercraft:computer_normal"}, - "I": {"tag": "c:chests/wooden"} - }, + "function": [{"type": "computercraft:copy_components", "from": "computercraft:computer_normal"}], + "key": {"#": "#c:ingots/iron", "C": "computercraft:computer_normal", "I": "#c:chests/wooden"}, "pattern": ["###", "#C#", "#I#"], "result": {"count": 1, "id": "computercraft:turtle_normal"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/speaker.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/speaker.json index cda30b349..ce89bd0e5 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/speaker.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/speaker.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_normal", - "key": {"#": {"item": "computercraft:speaker"}, "T": {"item": "computercraft:turtle_normal"}}, + "key": {"#": "computercraft:speaker", "T": "computercraft:turtle_normal"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "computercraft:speaker"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/wireless_modem_advanced.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/wireless_modem_advanced.json index ee6fa8db1..5240838ba 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/wireless_modem_advanced.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/wireless_modem_advanced.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_normal", - "key": {"#": {"item": "computercraft:wireless_modem_advanced"}, "T": {"item": "computercraft:turtle_normal"}}, + "key": {"#": "computercraft:wireless_modem_advanced", "T": "computercraft:turtle_normal"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "computercraft:wireless_modem_advanced"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/wireless_modem_normal.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/wireless_modem_normal.json index 845f47579..bf52ce69a 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/wireless_modem_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/computercraft/wireless_modem_normal.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_normal", - "key": {"#": {"item": "computercraft:wireless_modem_normal"}, "T": {"item": "computercraft:turtle_normal"}}, + "key": {"#": "computercraft:wireless_modem_normal", "T": "computercraft:turtle_normal"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "computercraft:wireless_modem_normal"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/crafting_table.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/crafting_table.json index 06d5e6e27..911f7b77d 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/crafting_table.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/crafting_table.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_normal", - "key": {"#": {"item": "minecraft:crafting_table"}, "T": {"item": "computercraft:turtle_normal"}}, + "key": {"#": "minecraft:crafting_table", "T": "computercraft:turtle_normal"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:crafting_table"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_axe.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_axe.json index 471d4ae22..c9a22f8a0 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_axe.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_axe.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_normal", - "key": {"#": {"item": "minecraft:diamond_axe"}, "T": {"item": "computercraft:turtle_normal"}}, + "key": {"#": "minecraft:diamond_axe", "T": "computercraft:turtle_normal"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:diamond_axe"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_hoe.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_hoe.json index cca3c656a..0e4625798 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_hoe.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_hoe.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_normal", - "key": {"#": {"item": "minecraft:diamond_hoe"}, "T": {"item": "computercraft:turtle_normal"}}, + "key": {"#": "minecraft:diamond_hoe", "T": "computercraft:turtle_normal"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:diamond_hoe"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_pickaxe.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_pickaxe.json index 7d9dd4e05..1f1c683ca 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_pickaxe.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_pickaxe.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_normal", - "key": {"#": {"item": "minecraft:diamond_pickaxe"}, "T": {"item": "computercraft:turtle_normal"}}, + "key": {"#": "minecraft:diamond_pickaxe", "T": "computercraft:turtle_normal"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:diamond_pickaxe"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_shovel.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_shovel.json index b358bb1fb..a02472c21 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_shovel.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_shovel.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_normal", - "key": {"#": {"item": "minecraft:diamond_shovel"}, "T": {"item": "computercraft:turtle_normal"}}, + "key": {"#": "minecraft:diamond_shovel", "T": "computercraft:turtle_normal"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:diamond_shovel"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_sword.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_sword.json index 145a44b99..ea860023f 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_sword.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal/minecraft/diamond_sword.json @@ -2,7 +2,7 @@ "type": "computercraft:impostor_shaped", "category": "redstone", "group": "computercraft:turtle_normal", - "key": {"#": {"item": "minecraft:diamond_sword"}, "T": {"item": "computercraft:turtle_normal"}}, + "key": {"#": "minecraft:diamond_sword", "T": "computercraft:turtle_normal"}, "pattern": ["#T"], "result": { "components": {"computercraft:right_turtle_upgrade": {"id": "minecraft:diamond_sword"}}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal_overlays/rainbow_flag.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal_overlays/rainbow_flag.json index 0e269ef6e..d9b21c9b5 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal_overlays/rainbow_flag.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal_overlays/rainbow_flag.json @@ -5,19 +5,19 @@ { "type": "computercraft:copy_components", "exclude": ["computercraft:overlay"], - "from": {"item": "computercraft:turtle_normal"} + "from": "computercraft:turtle_normal" } ], "group": "computercraft:turtle_normal_overlay", "ingredients": [ - {"tag": "c:dyes/red"}, - {"tag": "c:dyes/orange"}, - {"tag": "c:dyes/yellow"}, - {"tag": "c:dyes/green"}, - {"tag": "c:dyes/blue"}, - {"tag": "c:dyes/purple"}, - {"item": "minecraft:stick"}, - {"item": "computercraft:turtle_normal"} + "#c:dyes/red", + "#c:dyes/orange", + "#c:dyes/yellow", + "#c:dyes/green", + "#c:dyes/blue", + "#c:dyes/purple", + "minecraft:stick", + "computercraft:turtle_normal" ], "result": { "components": {"computercraft:overlay": "computercraft:rainbow_flag"}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal_overlays/trans_flag.json b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal_overlays/trans_flag.json index 76b8115ee..7981def31 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal_overlays/trans_flag.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/turtle_normal_overlays/trans_flag.json @@ -5,16 +5,16 @@ { "type": "computercraft:copy_components", "exclude": ["computercraft:overlay"], - "from": {"item": "computercraft:turtle_normal"} + "from": "computercraft:turtle_normal" } ], "group": "computercraft:turtle_normal_overlay", "ingredients": [ - {"tag": "c:dyes/light_blue"}, - {"tag": "c:dyes/pink"}, - {"tag": "c:dyes/white"}, - {"item": "minecraft:stick"}, - {"item": "computercraft:turtle_normal"} + "#c:dyes/light_blue", + "#c:dyes/pink", + "#c:dyes/white", + "minecraft:stick", + "computercraft:turtle_normal" ], "result": { "components": {"computercraft:overlay": "computercraft:trans_flag"}, diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/wired_modem.json b/projects/common/src/generated/resources/data/computercraft/recipe/wired_modem.json index 77c138e22..b37833ccd 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/wired_modem.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/wired_modem.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"item": "minecraft:stone"}, "R": {"tag": "c:dusts/redstone"}}, + "key": {"#": "minecraft:stone", "R": "#c:dusts/redstone"}, "pattern": ["###", "#R#", "###"], "result": {"count": 1, "id": "computercraft:wired_modem"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/wireless_modem_advanced.json b/projects/common/src/generated/resources/data/computercraft/recipe/wireless_modem_advanced.json index 0b1f48f57..05d5f9dd0 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/wireless_modem_advanced.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/wireless_modem_advanced.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:ingots/gold"}, "E": {"item": "minecraft:ender_eye"}}, + "key": {"#": "#c:ingots/gold", "E": "minecraft:ender_eye"}, "pattern": ["###", "#E#", "###"], "result": {"count": 1, "id": "computercraft:wireless_modem_advanced"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/wireless_modem_normal.json b/projects/common/src/generated/resources/data/computercraft/recipe/wireless_modem_normal.json index 1002c7bac..2cced2b4d 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/wireless_modem_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipe/wireless_modem_normal.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"item": "minecraft:stone"}, "E": {"tag": "c:ender_pearls"}}, + "key": {"#": "minecraft:stone", "E": "#c:ender_pearls"}, "pattern": ["###", "#E#", "###"], "result": {"count": 1, "id": "computercraft:wireless_modem_normal"} } diff --git a/projects/common/src/generated/resources/data/minecraft/advancement/recipes/misc/wired_modem_from_wired_modem_full.json b/projects/common/src/generated/resources/data/minecraft/advancement/recipes/misc/wired_modem_from_wired_modem_full.json new file mode 100644 index 000000000..87859d8bc --- /dev/null +++ b/projects/common/src/generated/resources/data/minecraft/advancement/recipes/misc/wired_modem_from_wired_modem_full.json @@ -0,0 +1,15 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": {"recipe": "minecraft:wired_modem_from_wired_modem_full"}, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wired_modem_full": { + "conditions": {"items": [{"items": "computercraft:wired_modem_full"}]}, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [["has_the_recipe", "has_wired_modem_full"]], + "rewards": {"recipes": ["minecraft:wired_modem_from_wired_modem_full"]} +} diff --git a/projects/common/src/generated/resources/data/minecraft/advancement/recipes/misc/wired_modem_full_from_wired_modem.json b/projects/common/src/generated/resources/data/minecraft/advancement/recipes/misc/wired_modem_full_from_wired_modem.json new file mode 100644 index 000000000..1bb401182 --- /dev/null +++ b/projects/common/src/generated/resources/data/minecraft/advancement/recipes/misc/wired_modem_full_from_wired_modem.json @@ -0,0 +1,15 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": {"recipe": "minecraft:wired_modem_full_from_wired_modem"}, + "trigger": "minecraft:recipe_unlocked" + }, + "has_wired_modem": { + "conditions": {"items": [{"items": "computercraft:wired_modem"}]}, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [["has_the_recipe", "has_wired_modem"]], + "rewards": {"recipes": ["minecraft:wired_modem_full_from_wired_modem"]} +} diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/wired_modem_full_to.json b/projects/common/src/generated/resources/data/minecraft/recipe/wired_modem_from_wired_modem_full.json similarity index 54% rename from projects/common/src/generated/resources/data/computercraft/recipe/wired_modem_full_to.json rename to projects/common/src/generated/resources/data/minecraft/recipe/wired_modem_from_wired_modem_full.json index 45c7673c0..ea7933ee8 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/wired_modem_full_to.json +++ b/projects/common/src/generated/resources/data/minecraft/recipe/wired_modem_from_wired_modem_full.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "redstone", - "ingredients": [{"item": "computercraft:wired_modem_full"}], + "category": "misc", + "ingredients": ["computercraft:wired_modem_full"], "result": {"count": 1, "id": "computercraft:wired_modem"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipe/wired_modem_full_from.json b/projects/common/src/generated/resources/data/minecraft/recipe/wired_modem_full_from_wired_modem.json similarity index 56% rename from projects/common/src/generated/resources/data/computercraft/recipe/wired_modem_full_from.json rename to projects/common/src/generated/resources/data/minecraft/recipe/wired_modem_full_from_wired_modem.json index 342c81ea3..09a9174f4 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipe/wired_modem_full_from.json +++ b/projects/common/src/generated/resources/data/minecraft/recipe/wired_modem_full_from_wired_modem.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "redstone", - "ingredients": [{"item": "computercraft:wired_modem"}], + "category": "misc", + "ingredients": ["computercraft:wired_modem"], "result": {"count": 1, "id": "computercraft:wired_modem_full"} } diff --git a/projects/common/src/main/java/dan200/computercraft/data/DataProviders.java b/projects/common/src/main/java/dan200/computercraft/data/DataProviders.java index dd68cf5b7..4459a95dd 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/DataProviders.java +++ b/projects/common/src/main/java/dan200/computercraft/data/DataProviders.java @@ -44,7 +44,7 @@ public final class DataProviders { var fullRegistries = fullRegistryPatch.thenApply(RegistrySetBuilder.PatchedRegistries::full); generator.registries(fullRegistryPatch); - generator.add(out -> new RecipeProvider(out, fullRegistries)); + generator.add(out -> new RecipeProvider.Runner(out, fullRegistries)); var blockTags = generator.blockTags(TagProvider::blockTags); generator.itemTags(TagProvider::itemTags, blockTags); diff --git a/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java b/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java index 35a59652f..f69172545 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java @@ -279,19 +279,18 @@ public final class LanguageProvider implements DataProvider { addConfigEntry(ConfigSpec.monitorWidth, "Max monitor width"); addConfigEntry(ConfigSpec.monitorHeight, "Max monitor height"); - addConfigEntry(ConfigSpec.monitorRenderer, "Monitor renderer"); addConfigEntry(ConfigSpec.monitorDistance, "Monitor distance"); addConfigEntry(ConfigSpec.uploadNagDelay, "Upload nag delay"); } private Stream getExpectedKeys(HolderLookup.Provider registries) { return Stream.of( - BuiltInRegistries.BLOCK.holders() + BuiltInRegistries.BLOCK.listElements() .filter(x -> x.key().location().getNamespace().equals(ComputerCraftAPI.MOD_ID)) .map(x -> x.value().getDescriptionId()) // Exclude blocks that just reuse vanilla translations, such as the lectern. .filter(x -> !x.startsWith("block.minecraft.")), - BuiltInRegistries.ITEM.holders() + BuiltInRegistries.ITEM.listElements() .filter(x -> x.key().location().getNamespace().equals(ComputerCraftAPI.MOD_ID)) .map(x -> x.value().getDescriptionId()), registries.lookupOrThrow(ITurtleUpgrade.REGISTRY).listElements().flatMap(x -> getTranslationKeys(x.value().getAdjective())), diff --git a/projects/common/src/main/java/dan200/computercraft/data/LootTableProvider.java b/projects/common/src/main/java/dan200/computercraft/data/LootTableProvider.java index fab4164b1..4da833bfd 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/LootTableProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/LootTableProvider.java @@ -59,7 +59,7 @@ class LootTableProvider { blockDrop(add, ModRegistry.Blocks.LECTERN, LootItem.lootTableItem(Items.LECTERN), ExplosionCondition.survivesExplosion()); - add.accept(ModRegistry.Blocks.CABLE.get().getLootTable(), LootTable + add.accept(ModRegistry.Blocks.CABLE.get().getLootTable().orElseThrow(), LootTable .lootTable() .withPool(LootPool.lootPool() .setRolls(ConstantValue.exactly(1)) @@ -114,7 +114,7 @@ class LootTableProvider { LootItemCondition.Builder condition ) { var block = wrapper.get(); - add.accept(block.getLootTable(), LootTable + add.accept(block.getLootTable().orElseThrow(), LootTable .lootTable() .withPool(LootPool.lootPool() .setRolls(ConstantValue.exactly(1)) diff --git a/projects/common/src/main/java/dan200/computercraft/data/RecipeProvider.java b/projects/common/src/main/java/dan200/computercraft/data/RecipeProvider.java index 257b0a881..c2a669565 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/RecipeProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/RecipeProvider.java @@ -4,14 +4,11 @@ package dan200.computercraft.data; -import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; -import com.mojang.serialization.JsonOps; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.upgrades.UpgradeData; -import dan200.computercraft.core.util.Colour; import dan200.computercraft.data.recipe.ShapedSpecBuilder; import dan200.computercraft.data.recipe.ShapelessSpecBuilder; import dan200.computercraft.shared.ModRegistry; @@ -24,7 +21,6 @@ import dan200.computercraft.shared.platform.RecipeIngredients; import dan200.computercraft.shared.pocket.items.PocketComputerItem; import dan200.computercraft.shared.pocket.recipes.PocketComputerUpgradeRecipe; import dan200.computercraft.shared.recipe.ImpostorShapedRecipe; -import dan200.computercraft.shared.recipe.ImpostorShapelessRecipe; import dan200.computercraft.shared.recipe.TransformShapedRecipe; import dan200.computercraft.shared.recipe.TransformShapelessRecipe; import dan200.computercraft.shared.recipe.function.CopyComponents; @@ -37,6 +33,7 @@ import dan200.computercraft.shared.util.RegistryHelper; import net.minecraft.advancements.Criterion; import net.minecraft.advancements.critereon.InventoryChangeTrigger; import net.minecraft.advancements.critereon.ItemPredicate; +import net.minecraft.core.HolderGetter; import net.minecraft.core.HolderLookup; import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.BuiltInRegistries; @@ -44,15 +41,14 @@ import net.minecraft.core.registries.Registries; import net.minecraft.data.PackOutput; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.RecipeOutput; -import net.minecraft.data.recipes.ShapedRecipeBuilder; -import net.minecraft.data.recipes.ShapelessRecipeBuilder; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; -import net.minecraft.util.GsonHelper; -import net.minecraft.world.item.*; -import net.minecraft.world.item.component.DyedItemColor; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.item.component.ResolvableProfile; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.Ingredient; @@ -62,68 +58,46 @@ import net.minecraft.world.level.ItemLike; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import java.util.function.Consumer; import static dan200.computercraft.api.ComputerCraftTags.Items.COMPUTER; import static dan200.computercraft.api.ComputerCraftTags.Items.WIRED_MODEM; final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { - private final RecipeIngredients ingredients = PlatformHelper.get().getRecipeIngredients(); + private final RecipeIngredients ingredients; + private final HolderGetter items; - private final CompletableFuture registries; - - RecipeProvider(PackOutput output, CompletableFuture registries) { - super(output, registries); - this.registries = registries; - } - - private HolderLookup.Provider registries() { - try { - return registries.get(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException("Interrupted"); - } catch (ExecutionException e) { - var cause = e.getCause(); - throw cause instanceof RuntimeException rt ? rt : new RuntimeException("Unexpected error", cause); - } + RecipeProvider(HolderLookup.Provider registries, RecipeOutput recipeOutput) { + super(registries, recipeOutput); + this.items = registries.lookupOrThrow(Registries.ITEM); + ingredients = PlatformHelper.get().getRecipeIngredients(); } @Override - public void buildRecipes(RecipeOutput add) { - var registries = registries(); + public void buildRecipes() { + basicRecipes(); + diskColours(); + pocketUpgrades(); + turtleUpgrades(); + turtleOverlays(); - basicRecipes(add); - diskColours(add); - pocketUpgrades(add, registries); - turtleUpgrades(add, registries); - turtleOverlays(add, registries); - - addSpecial(add, new DiskRecipe(CraftingBookCategory.MISC)); - addSpecial(add, new ColourableRecipe(CraftingBookCategory.MISC)); - addSpecial(add, new ClearColourRecipe(CraftingBookCategory.MISC)); - addSpecial(add, new TurtleUpgradeRecipe(CraftingBookCategory.MISC)); - addSpecial(add, new PocketComputerUpgradeRecipe(CraftingBookCategory.MISC)); + special(new ColourableRecipe(CraftingBookCategory.MISC)); + special(new ClearColourRecipe(CraftingBookCategory.MISC)); + special(new TurtleUpgradeRecipe(CraftingBookCategory.MISC)); + special(new PocketComputerUpgradeRecipe(CraftingBookCategory.MISC)); } /** - * Register a crafting recipe for a disk of every dye colour. - * - * @param output The callback to add recipes. + * Register a disk recipe. */ - private void diskColours(RecipeOutput output) { - for (var colour : Colour.VALUES) { - ShapelessSpecBuilder - .shapeless(RecipeCategory.REDSTONE, DataComponentUtil.createStack(ModRegistry.Items.DISK.get(), DataComponents.DYED_COLOR, new DyedItemColor(colour.getHex(), false))) - .requires(ingredients.redstone()) - .requires(Items.PAPER) - .requires(DyeItem.byColor(ofColour(colour))) - .group("computercraft:disk") - .unlockedBy("has_drive", inventoryChange(ModRegistry.Items.DISK_DRIVE.get())) - .build(ImpostorShapelessRecipe::new) - .save(output, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "disk_" + (colour.ordinal() + 1))); - } + private void diskColours() { + customShapeless(RecipeCategory.REDSTONE, ModRegistry.Items.DISK.get()) + .requires(ingredients.redstone()) + .requires(Items.PAPER) + .group("computercraft:disk") + .unlockedBy("has_drive", has(ModRegistry.Items.DISK_DRIVE.get())) + .build(d -> new DiskRecipe(d.properties(), d.ingredients())) + .save(output, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "disk")); } private static List turtleItems() { @@ -132,26 +106,22 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { /** * Register a crafting recipe for each turtle upgrade. - * - * @param add The callback to add recipes. - * @param registries The currently available registries. */ - private void turtleUpgrades(RecipeOutput add, HolderLookup.Provider registries) { + private void turtleUpgrades() { for (var turtleItem : turtleItems()) { var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, turtleItem); registries.lookupOrThrow(ITurtleUpgrade.REGISTRY).listElements().forEach(upgradeHolder -> { var upgrade = upgradeHolder.value(); - ShapedSpecBuilder - .shaped(RecipeCategory.REDSTONE, DataComponentUtil.createStack(turtleItem, ModRegistry.DataComponents.RIGHT_TURTLE_UPGRADE.get(), UpgradeData.ofDefault(upgradeHolder))) + customShaped(RecipeCategory.REDSTONE, DataComponentUtil.createStack(turtleItem, ModRegistry.DataComponents.RIGHT_TURTLE_UPGRADE.get(), UpgradeData.ofDefault(upgradeHolder))) .group(name.toString()) .pattern("#T") .define('T', turtleItem) .define('#', upgrade.getCraftingItem().getItem()) - .unlockedBy("has_items", inventoryChange(turtleItem, upgrade.getCraftingItem().getItem())) + .unlockedBy("has_items", has(turtleItem, upgrade.getCraftingItem().getItem())) .build(ImpostorShapedRecipe::new) .save( - add, + output, name.withSuffix(String.format("/%s/%s", upgradeHolder.key().location().getNamespace(), upgradeHolder.key().location().getPath())) ); }); @@ -164,44 +134,40 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { /** * Register a crafting recipe for each pocket upgrade. - * - * @param add The callback to add recipes. - * @param registries The currently available registries. */ - private void pocketUpgrades(RecipeOutput add, HolderLookup.Provider registries) { + private void pocketUpgrades() { for (var pocket : pocketComputerItems()) { var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, pocket).withPath(x -> x.replace("pocket_computer_", "pocket_")); registries.lookupOrThrow(IPocketUpgrade.REGISTRY).listElements().forEach(upgradeHolder -> { var upgrade = upgradeHolder.value(); - ShapedSpecBuilder - .shaped(RecipeCategory.REDSTONE, DataComponentUtil.createStack(pocket, ModRegistry.DataComponents.POCKET_UPGRADE.get(), UpgradeData.ofDefault(upgradeHolder))) + customShaped(RecipeCategory.REDSTONE, DataComponentUtil.createStack(pocket, ModRegistry.DataComponents.POCKET_UPGRADE.get(), UpgradeData.ofDefault(upgradeHolder))) .group(name.toString()) .pattern("#") .pattern("P") .define('P', pocket) .define('#', upgrade.getCraftingItem().getItem()) - .unlockedBy("has_items", inventoryChange(pocket, upgrade.getCraftingItem().getItem())) + .unlockedBy("has_items", has(pocket, upgrade.getCraftingItem().getItem())) .build(ImpostorShapedRecipe::new) .save( - add, + output, name.withSuffix(String.format("/%s/%s", upgradeHolder.key().location().getNamespace(), upgradeHolder.key().location().getPath())) ); }); } } - private void turtleOverlays(RecipeOutput add, HolderLookup.Provider registries) { - turtleOverlay(add, registries, TurtleOverlays.TRANS_FLAG, x -> x - .unlockedBy("has_dye", inventoryChange(itemPredicate(ingredients.dye()))) + private void turtleOverlays() { + turtleOverlay(TurtleOverlays.TRANS_FLAG, x -> x + .unlockedBy("has_dye", has(ingredients.dye())) .requires(ColourUtils.getDyeTag(DyeColor.LIGHT_BLUE)) .requires(ColourUtils.getDyeTag(DyeColor.PINK)) .requires(ColourUtils.getDyeTag(DyeColor.WHITE)) .requires(Items.STICK) ); - turtleOverlay(add, registries, TurtleOverlays.RAINBOW_FLAG, x -> x - .unlockedBy("has_dye", inventoryChange(itemPredicate(ingredients.dye()))) + turtleOverlay(TurtleOverlays.RAINBOW_FLAG, x -> x + .unlockedBy("has_dye", has(ingredients.dye())) .requires(ColourUtils.getDyeTag(DyeColor.RED)) .requires(ColourUtils.getDyeTag(DyeColor.ORANGE)) .requires(ColourUtils.getDyeTag(DyeColor.YELLOW)) @@ -212,264 +178,234 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { ); } - private void turtleOverlay(RecipeOutput add, HolderLookup.Provider registries, ResourceKey overlay, Consumer build) { + private void turtleOverlay(ResourceKey overlay, Consumer build) { var holder = registries.lookupOrThrow(overlay.registryKey()).getOrThrow(overlay); for (var turtleItem : turtleItems()) { var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, turtleItem); - var builder = ShapelessSpecBuilder - .shapeless(RecipeCategory.REDSTONE, DataComponentUtil.createStack(turtleItem, ModRegistry.DataComponents.OVERLAY.get(), holder)) + var builder = customShapeless(RecipeCategory.REDSTONE, DataComponentUtil.createStack(turtleItem, ModRegistry.DataComponents.OVERLAY.get(), holder)) .group(name.withSuffix("_overlay").toString()) - .unlockedBy("has_turtle", inventoryChange(turtleItem)); + .unlockedBy("has_turtle", has(turtleItem)); build.accept(builder); builder .requires(turtleItem) .build(s -> new TransformShapelessRecipe(s, List.of( CopyComponents.builder(turtleItem).exclude(ModRegistry.DataComponents.OVERLAY.get()).build() ))) - .save(add, name.withSuffix("_overlays/" + overlay.location().getPath())); + .save(output, name.withSuffix("_overlays/" + overlay.location().getPath())); } } - private void basicRecipes(RecipeOutput add) { - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.CABLE.get(), 6) + private void basicRecipes() { + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.CABLE.get(), 6) .pattern(" # ") .pattern("#R#") .pattern(" # ") .define('#', Items.STONE) .define('R', ingredients.redstone()) - .unlockedBy("has_computer", inventoryChange(COMPUTER)) - .unlockedBy("has_modem", inventoryChange(WIRED_MODEM)) - .save(add); + .unlockedBy("has_computer", has(COMPUTER)) + .unlockedBy("has_modem", has(WIRED_MODEM)) + .save(output); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_NORMAL.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_NORMAL.get()) .pattern("###") .pattern("#R#") .pattern("#G#") .define('#', Items.STONE) .define('R', ingredients.redstone()) .define('G', ingredients.glassPane()) - .unlockedBy("has_redstone", inventoryChange(itemPredicate(ingredients.redstone()))) - .save(add); + .unlockedBy("has_redstone", has(ingredients.redstone())) + .save(output); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_ADVANCED.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_ADVANCED.get()) .pattern("###") .pattern("#R#") .pattern("#G#") .define('#', ingredients.goldIngot()) .define('R', ingredients.redstone()) .define('G', ingredients.glassPane()) - .unlockedBy("has_components", inventoryChange(itemPredicate(ingredients.redstone()), itemPredicate(ingredients.goldIngot()))) - .save(add); + .unlockedBy("has_components", inventoryTrigger(itemPredicate(ingredients.redstone()), itemPredicate(ingredients.goldIngot()))) + .save(output); - ShapedSpecBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_ADVANCED.get()) + customShaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_ADVANCED.get()) .pattern("###") .pattern("#C#") .pattern("# #") .define('#', ingredients.goldIngot()) .define('C', ModRegistry.Items.COMPUTER_NORMAL.get()) - .unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.COMPUTER_NORMAL.get()), itemPredicate(ingredients.goldIngot()))) + .unlockedBy("has_components", inventoryTrigger(itemPredicate(ModRegistry.Items.COMPUTER_NORMAL.get()), itemPredicate(ingredients.goldIngot()))) .build(x -> new TransformShapedRecipe(x, List.of(new CopyComponents(ModRegistry.Items.COMPUTER_NORMAL.get())))) - .save(add, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "computer_advanced_upgrade")); + .save(output, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "computer_advanced_upgrade")); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_COMMAND.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_COMMAND.get()) .pattern("###") .pattern("#R#") .pattern("#G#") .define('#', ingredients.goldIngot()) .define('R', Items.COMMAND_BLOCK) .define('G', ingredients.glassPane()) - .unlockedBy("has_components", inventoryChange(Items.COMMAND_BLOCK)) - .save(add); + .unlockedBy("has_components", has(Items.COMMAND_BLOCK)) + .save(output); - ShapedSpecBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_NORMAL.get()) + customShaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_NORMAL.get()) .pattern("###") .pattern("#C#") .pattern("#I#") .define('#', ingredients.ironIngot()) .define('C', ModRegistry.Items.COMPUTER_NORMAL.get()) .define('I', ingredients.woodenChest()) - .unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_NORMAL.get())) + .unlockedBy("has_computer", has(ModRegistry.Items.COMPUTER_NORMAL.get())) .build(x -> new TransformShapedRecipe(x, List.of(new CopyComponents(ModRegistry.Items.COMPUTER_NORMAL.get())))) - .save(add); + .save(output); - ShapedSpecBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_ADVANCED.get()) + customShaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_ADVANCED.get()) .pattern("###") .pattern("#C#") .pattern("#I#") .define('#', ingredients.goldIngot()) .define('C', ModRegistry.Items.COMPUTER_ADVANCED.get()) .define('I', ingredients.woodenChest()) - .unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_NORMAL.get())) + .unlockedBy("has_computer", has(ModRegistry.Items.COMPUTER_NORMAL.get())) .build(x -> new TransformShapedRecipe(x, List.of(new CopyComponents(ModRegistry.Items.COMPUTER_ADVANCED.get())))) - .save(add); + .save(output); - ShapedSpecBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_ADVANCED.get()) + customShaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_ADVANCED.get()) .pattern("###") .pattern("#C#") .pattern(" B ") .define('#', ingredients.goldIngot()) .define('C', ModRegistry.Items.TURTLE_NORMAL.get()) .define('B', ingredients.goldBlock()) - .unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.TURTLE_NORMAL.get()), itemPredicate(ingredients.goldIngot()))) + .unlockedBy("has_components", inventoryTrigger(itemPredicate(ModRegistry.Items.TURTLE_NORMAL.get()), itemPredicate(ingredients.goldIngot()))) .build(x -> new TransformShapedRecipe(x, List.of(new CopyComponents(ModRegistry.Items.TURTLE_NORMAL.get())))) - .save(add, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "turtle_advanced_upgrade")); + .save(output, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "turtle_advanced_upgrade")); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.DISK_DRIVE.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.DISK_DRIVE.get()) .pattern("###") .pattern("#R#") .pattern("#R#") .define('#', Items.STONE) .define('R', ingredients.redstone()) - .unlockedBy("has_computer", inventoryChange(COMPUTER)) - .save(add); + .unlockedBy("has_computer", has(COMPUTER)) + .save(output); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.MONITOR_NORMAL.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.MONITOR_NORMAL.get()) .pattern("###") .pattern("#G#") .pattern("###") .define('#', Items.STONE) .define('G', ingredients.glassPane()) - .unlockedBy("has_computer", inventoryChange(COMPUTER)) - .save(add); + .unlockedBy("has_computer", has(COMPUTER)) + .save(output); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.MONITOR_ADVANCED.get(), 4) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.MONITOR_ADVANCED.get(), 4) .pattern("###") .pattern("#G#") .pattern("###") .define('#', ingredients.goldIngot()) .define('G', ingredients.glassPane()) - .unlockedBy("has_computer", inventoryChange(COMPUTER)) - .save(add); + .unlockedBy("has_computer", has(COMPUTER)) + .save(output); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.POCKET_COMPUTER_NORMAL.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.POCKET_COMPUTER_NORMAL.get()) .pattern("###") .pattern("#A#") .pattern("#G#") .define('#', Items.STONE) .define('A', Items.GOLDEN_APPLE) .define('G', ingredients.glassPane()) - .unlockedBy("has_computer", inventoryChange(COMPUTER)) - .unlockedBy("has_apple", inventoryChange(Items.GOLDEN_APPLE)) - .save(add); + .unlockedBy("has_computer", has(COMPUTER)) + .unlockedBy("has_apple", has(Items.GOLDEN_APPLE)) + .save(output); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get()) .pattern("###") .pattern("#A#") .pattern("#G#") .define('#', ingredients.goldIngot()) .define('A', Items.GOLDEN_APPLE) .define('G', ingredients.glassPane()) - .unlockedBy("has_computer", inventoryChange(COMPUTER)) - .unlockedBy("has_apple", inventoryChange(Items.GOLDEN_APPLE)) - .save(add); + .unlockedBy("has_computer", has(COMPUTER)) + .unlockedBy("has_apple", has(Items.GOLDEN_APPLE)) + .save(output); - ShapedSpecBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get()) + customShaped(RecipeCategory.REDSTONE, ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get()) .pattern("###") .pattern("#C#") .pattern("# #") .define('#', ingredients.goldIngot()) .define('C', ModRegistry.Items.POCKET_COMPUTER_NORMAL.get()) - .unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get()), itemPredicate(ingredients.goldIngot()))) + .unlockedBy("has_components", inventoryTrigger(itemPredicate(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get()), itemPredicate(ingredients.goldIngot()))) .build(x -> new TransformShapedRecipe(x, List.of(new CopyComponents(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get())))) - .save(add, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "pocket_computer_advanced_upgrade")); + .save(output, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "pocket_computer_advanced_upgrade")); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTER.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTER.get()) .pattern("###") .pattern("#R#") .pattern("#D#") .define('#', Items.STONE) .define('R', ingredients.redstone()) .define('D', ingredients.dye()) - .unlockedBy("has_computer", inventoryChange(COMPUTER)) - .save(add); + .unlockedBy("has_computer", has(COMPUTER)) + .save(output); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.SPEAKER.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.SPEAKER.get()) .pattern("###") .pattern("#N#") .pattern("#R#") .define('#', Items.STONE) .define('N', Items.NOTE_BLOCK) .define('R', ingredients.redstone()) - .unlockedBy("has_computer", inventoryChange(COMPUTER)) - .save(add); + .unlockedBy("has_computer", has(COMPUTER)) + .save(output); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.WIRED_MODEM.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.WIRED_MODEM.get()) .pattern("###") .pattern("#R#") .pattern("###") .define('#', Items.STONE) .define('R', ingredients.redstone()) - .unlockedBy("has_computer", inventoryChange(COMPUTER)) - .unlockedBy("has_cable", inventoryChange(ModRegistry.Items.CABLE.get())) - .save(add); + .unlockedBy("has_computer", has(COMPUTER)) + .unlockedBy("has_cable", has(ModRegistry.Items.CABLE.get())) + .save(output); - ShapelessRecipeBuilder - .shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.WIRED_MODEM_FULL.get()) - .requires(ModRegistry.Items.WIRED_MODEM.get()) - .unlockedBy("has_modem", inventoryChange(WIRED_MODEM)) - .save(add, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "wired_modem_full_from")); - ShapelessRecipeBuilder - .shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.WIRED_MODEM.get()) - .requires(ModRegistry.Items.WIRED_MODEM_FULL.get()) - .unlockedBy("has_modem", inventoryChange(WIRED_MODEM)) - .save(add, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "wired_modem_full_to")); + oneToOneConversionRecipe(ModRegistry.Items.WIRED_MODEM.get(), ModRegistry.Items.WIRED_MODEM_FULL.get(), null); + oneToOneConversionRecipe(ModRegistry.Items.WIRED_MODEM_FULL.get(), ModRegistry.Items.WIRED_MODEM.get(), null); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.WIRELESS_MODEM_NORMAL.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.WIRELESS_MODEM_NORMAL.get()) .pattern("###") .pattern("#E#") .pattern("###") .define('#', Items.STONE) .define('E', ingredients.enderPearl()) - .unlockedBy("has_computer", inventoryChange(COMPUTER)) - .save(add); + .unlockedBy("has_computer", has(COMPUTER)) + .save(output); - ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.WIRELESS_MODEM_ADVANCED.get()) + shaped(RecipeCategory.REDSTONE, ModRegistry.Items.WIRELESS_MODEM_ADVANCED.get()) .pattern("###") .pattern("#E#") .pattern("###") .define('#', ingredients.goldIngot()) .define('E', Items.ENDER_EYE) - .unlockedBy("has_computer", inventoryChange(COMPUTER)) - .unlockedBy("has_wireless", inventoryChange(ModRegistry.Items.WIRELESS_MODEM_NORMAL.get())) - .save(add); + .unlockedBy("has_computer", has(COMPUTER)) + .unlockedBy("has_wireless", has(ModRegistry.Items.WIRELESS_MODEM_NORMAL.get())) + .save(output); - ShapelessSpecBuilder - .shapeless(RecipeCategory.DECORATIONS, playerHead("Cloudhunter", "6d074736-b1e9-4378-a99b-bd8777821c9c")) + customShapeless(RecipeCategory.DECORATIONS, playerHead("Cloudhunter", "6d074736-b1e9-4378-a99b-bd8777821c9c")) .requires(ItemTags.SKULLS) .requires(ModRegistry.Items.MONITOR_NORMAL.get()) - .unlockedBy("has_monitor", inventoryChange(ModRegistry.Items.MONITOR_NORMAL.get())) + .unlockedBy("has_monitor", has(ModRegistry.Items.MONITOR_NORMAL.get())) .build() - .save(add, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "skull_cloudy")); + .save(output, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "skull_cloudy")); - ShapelessSpecBuilder - .shapeless(RecipeCategory.DECORATIONS, playerHead("dan200", "f3c8d69b-0776-4512-8434-d1b2165909eb")) + customShapeless(RecipeCategory.DECORATIONS, playerHead("dan200", "f3c8d69b-0776-4512-8434-d1b2165909eb")) .requires(ItemTags.SKULLS) .requires(ModRegistry.Items.COMPUTER_ADVANCED.get()) - .unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_ADVANCED.get())) + .unlockedBy("has_computer", has(ModRegistry.Items.COMPUTER_ADVANCED.get())) .build() - .save(add, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "skull_dan200")); + .save(output, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "skull_dan200")); var pages = Ingredient.of( ModRegistry.Items.PRINTED_PAGE.get(), @@ -477,65 +413,74 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { Items.PAPER ); - ShapelessSpecBuilder - .shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_PAGES.get()) + customShapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_PAGES.get()) .requires(ingredients.string()) - .unlockedBy("has_printer", inventoryChange(ModRegistry.Items.PRINTER.get())) + .unlockedBy("has_printer", has(ModRegistry.Items.PRINTER.get())) .build(x -> new PrintoutRecipe(x, pages, 2)) - .save(add); + .save(output); - ShapelessSpecBuilder - .shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_BOOK.get()) + customShapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_BOOK.get()) .requires(ingredients.leather()) .requires(ingredients.string()) - .unlockedBy("has_printer", inventoryChange(ModRegistry.Items.PRINTER.get())) + .unlockedBy("has_printer", has(ModRegistry.Items.PRINTER.get())) .build(x -> new PrintoutRecipe(x, pages, 1)) - .save(add); + .save(output); } - private static DyeColor ofColour(Colour colour) { - return DyeColor.byId(15 - colour.ordinal()); - } - - private static Criterion inventoryChange(TagKey stack) { - return InventoryChangeTrigger.TriggerInstance.hasItems(itemPredicate(stack)); - } - - private static Criterion inventoryChange(ItemLike... stack) { - return InventoryChangeTrigger.TriggerInstance.hasItems(stack); - } - - private static Criterion inventoryChange(ItemPredicate... items) { + private static Criterion has(ItemLike... items) { return InventoryChangeTrigger.TriggerInstance.hasItems(items); } - private static ItemPredicate itemPredicate(ItemLike item) { - return ItemPredicate.Builder.item().of(item).build(); + private ItemPredicate itemPredicate(ItemLike item) { + return ItemPredicate.Builder.item().of(items, item).build(); } - private static ItemPredicate itemPredicate(TagKey item) { - return ItemPredicate.Builder.item().of(item).build(); - } - - private static ItemPredicate itemPredicate(Ingredient ingredient) { - var json = Ingredient.CODEC_NONEMPTY.encodeStart(JsonOps.INSTANCE, ingredient).getOrThrow(); - if (!(json instanceof JsonObject object)) throw new IllegalStateException("Unknown ingredient " + json); - - if (object.has("item")) { - var item = ItemStack.SIMPLE_ITEM_CODEC.parse(JsonOps.INSTANCE, object).getOrThrow(); - return itemPredicate(item.getItem()); - } else if (object.has("tag")) { - return itemPredicate(TagKey.create(Registries.ITEM, ResourceLocation.parse(GsonHelper.getAsString(object, "tag")))); - } else { - throw new IllegalArgumentException("Unknown ingredient " + json); - } + private ItemPredicate itemPredicate(TagKey item) { + return ItemPredicate.Builder.item().of(items, item).build(); } private static ItemStack playerHead(String name, String uuid) { return DataComponentUtil.createStack(Items.PLAYER_HEAD, DataComponents.PROFILE, new ResolvableProfile(new GameProfile(UUID.fromString(uuid), name))); } - private static void addSpecial(RecipeOutput add, Recipe recipe) { - add.accept(RegistryHelper.getKeyOrThrow(BuiltInRegistries.RECIPE_SERIALIZER, recipe.getSerializer()), recipe, null); + private ShapedSpecBuilder customShaped(RecipeCategory category, ItemStack result) { + return new ShapedSpecBuilder(items, category, result); + } + + private ShapedSpecBuilder customShaped(RecipeCategory category, ItemLike result) { + return new ShapedSpecBuilder(items, category, new ItemStack(result)); + } + + private ShapelessSpecBuilder customShapeless(RecipeCategory category, ItemStack result) { + return new ShapelessSpecBuilder(items, category, result); + } + + private ShapelessSpecBuilder customShapeless(RecipeCategory category, ItemLike result) { + return new ShapelessSpecBuilder(items, category, new ItemStack(result)); + } + + private void special(Recipe recipe) { + var key = RegistryHelper.getKeyOrThrow(BuiltInRegistries.RECIPE_SERIALIZER, recipe.getSerializer()); + output.accept(recipeKey(key), recipe, null); + } + + public static ResourceKey> recipeKey(ResourceLocation key) { + return ResourceKey.create(Registries.RECIPE, key); + } + + static class Runner extends net.minecraft.data.recipes.RecipeProvider.Runner { + protected Runner(PackOutput output, CompletableFuture registries) { + super(output, registries); + } + + @Override + protected RecipeProvider createRecipeProvider(HolderLookup.Provider registries, RecipeOutput output) { + return new RecipeProvider(registries, output); + } + + @Override + public String getName() { + return "Recipes"; + } } } diff --git a/projects/common/src/main/java/dan200/computercraft/data/recipe/AbstractRecipeBuilder.java b/projects/common/src/main/java/dan200/computercraft/data/recipe/AbstractRecipeBuilder.java index 3b1e55590..5648d1731 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/recipe/AbstractRecipeBuilder.java +++ b/projects/common/src/main/java/dan200/computercraft/data/recipe/AbstractRecipeBuilder.java @@ -10,9 +10,12 @@ import net.minecraft.advancements.AdvancementRequirements; import net.minecraft.advancements.AdvancementRewards; import net.minecraft.advancements.Criterion; import net.minecraft.advancements.critereon.RecipeUnlockedTrigger; +import net.minecraft.core.HolderGetter; +import net.minecraft.core.registries.Registries; import net.minecraft.data.recipes.RecipeBuilder; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.RecipeOutput; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; @@ -30,12 +33,14 @@ import java.util.function.Function; * @see ShapelessSpecBuilder */ public abstract class AbstractRecipeBuilder, O> { + protected final HolderGetter items; private final RecipeCategory category; protected final ItemStack result; private String group = ""; private final Map> criteria = new LinkedHashMap<>(); - protected AbstractRecipeBuilder(RecipeCategory category, ItemStack result) { + protected AbstractRecipeBuilder(HolderGetter items, RecipeCategory category, ItemStack result) { + this.items = items; this.category = category; this.result = result; } @@ -112,17 +117,23 @@ public abstract class AbstractRecipeBuilder> recipeKey(ResourceLocation key) { + return ResourceKey.create(Registries.RECIPE, key); + } } diff --git a/projects/common/src/main/java/dan200/computercraft/data/recipe/ShapedSpecBuilder.java b/projects/common/src/main/java/dan200/computercraft/data/recipe/ShapedSpecBuilder.java index fbb2e97f5..200008a78 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/recipe/ShapedSpecBuilder.java +++ b/projects/common/src/main/java/dan200/computercraft/data/recipe/ShapedSpecBuilder.java @@ -6,6 +6,7 @@ package dan200.computercraft.data.recipe; import dan200.computercraft.shared.recipe.RecipeProperties; import dan200.computercraft.shared.recipe.ShapedRecipeSpec; +import net.minecraft.core.HolderGetter; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.ShapedRecipeBuilder; import net.minecraft.tags.TagKey; @@ -27,16 +28,8 @@ public final class ShapedSpecBuilder extends AbstractRecipeBuilder rows = new ArrayList<>(); private final Map key = new LinkedHashMap<>(); - private ShapedSpecBuilder(RecipeCategory category, ItemStack result) { - super(category, result); - } - - public static ShapedSpecBuilder shaped(RecipeCategory category, ItemStack result) { - return new ShapedSpecBuilder(category, result); - } - - public static ShapedSpecBuilder shaped(RecipeCategory category, ItemLike result) { - return new ShapedSpecBuilder(category, new ItemStack(result)); + public ShapedSpecBuilder(HolderGetter items, RecipeCategory category, ItemStack result) { + super(items, category, result); } public ShapedSpecBuilder define(char key, Ingredient ingredient) { @@ -48,7 +41,7 @@ public final class ShapedSpecBuilder extends AbstractRecipeBuilder tag) { - return this.define(key, Ingredient.of(tag)); + return this.define(key, Ingredient.of(items.getOrThrow(tag))); } public ShapedSpecBuilder define(char key, ItemLike item) { diff --git a/projects/common/src/main/java/dan200/computercraft/data/recipe/ShapelessSpecBuilder.java b/projects/common/src/main/java/dan200/computercraft/data/recipe/ShapelessSpecBuilder.java index 245eeb01a..f3932f68c 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/recipe/ShapelessSpecBuilder.java +++ b/projects/common/src/main/java/dan200/computercraft/data/recipe/ShapelessSpecBuilder.java @@ -6,6 +6,7 @@ package dan200.computercraft.data.recipe; import dan200.computercraft.shared.recipe.RecipeProperties; import dan200.computercraft.shared.recipe.ShapelessRecipeSpec; +import net.minecraft.core.HolderGetter; import net.minecraft.core.NonNullList; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.ShapelessRecipeBuilder; @@ -21,20 +22,12 @@ import net.minecraft.world.level.ItemLike; public final class ShapelessSpecBuilder extends AbstractRecipeBuilder { private final NonNullList ingredients = NonNullList.create(); - private ShapelessSpecBuilder(RecipeCategory category, ItemStack result) { - super(category, result); - } - - public static ShapelessSpecBuilder shapeless(RecipeCategory category, ItemStack result) { - return new ShapelessSpecBuilder(category, result); - } - - public static ShapelessSpecBuilder shapeless(RecipeCategory category, ItemLike result) { - return new ShapelessSpecBuilder(category, new ItemStack(result)); + public ShapelessSpecBuilder(HolderGetter items, RecipeCategory category, ItemStack result) { + super(items, category, result); } public ShapelessSpecBuilder requires(Ingredient ingredient, int count) { - for (int i = 0; i < count; i++) ingredients.add(ingredient); + for (var i = 0; i < count; i++) ingredients.add(ingredient); return this; } @@ -43,15 +36,15 @@ public final class ShapelessSpecBuilder extends AbstractRecipeBuilder item) { - return requires(Ingredient.of(item)); + return requires(Ingredient.of(items.getOrThrow(item))); } @Override diff --git a/projects/forge/src/main/java/dan200/computercraft/mixin/V3818_3Mixin.java b/projects/common/src/main/java/dan200/computercraft/mixin/V3818_3Mixin.java similarity index 68% rename from projects/forge/src/main/java/dan200/computercraft/mixin/V3818_3Mixin.java rename to projects/common/src/main/java/dan200/computercraft/mixin/V3818_3Mixin.java index 710f5c056..f93ead550 100644 --- a/projects/forge/src/main/java/dan200/computercraft/mixin/V3818_3Mixin.java +++ b/projects/common/src/main/java/dan200/computercraft/mixin/V3818_3Mixin.java @@ -12,6 +12,9 @@ import net.minecraft.util.datafix.schemas.V3818_3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import java.util.SequencedMap; +import java.util.function.Supplier; + /** * Add our custom data components to the datafixer system. *

@@ -19,9 +22,10 @@ import org.spongepowered.asm.mixin.injection.At; */ @Mixin(V3818_3.class) class V3818_3Mixin { - @ModifyReturnValue(method = "lambda$registerTypes$0", at = @At("TAIL")) + @ModifyReturnValue(method = "components", at = @At("TAIL")) @SuppressWarnings("UnusedMethod") - private static TypeTemplate addExtraTypes(TypeTemplate type, Schema schema) { - return ComponentizationFixers.addExtraTypes(type, schema); + private static SequencedMap> components(SequencedMap> types, Schema schema) { + ComponentizationFixers.addExtraTypes(types, schema); + return types; } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java b/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java index 72388e40d..56c56c1b5 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java @@ -103,6 +103,8 @@ import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.BlockItem; @@ -113,20 +115,16 @@ import net.minecraft.world.item.component.DyedItemColor; import net.minecraft.world.item.crafting.CustomRecipe; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.level.material.MapColor; import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; import java.util.Objects; -import java.util.function.BiFunction; -import java.util.function.Predicate; -import java.util.function.UnaryOperator; +import java.util.Set; +import java.util.function.*; /** * Registers ComputerCraft's registry entries and additional objects, such as {@link CauldronInteraction}s and @@ -141,6 +139,13 @@ public final class ModRegistry { public static final class Blocks { static final RegistrationHelper REGISTRY = PlatformHelper.get().createRegistrationHelper(Registries.BLOCK); + private static RegistryEntry register(String name, Function build, BlockBehaviour.Properties properties) { + return REGISTRY.register(name, () -> { + properties.setId(ResourceKey.create(Registries.BLOCK, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name))); + return build.apply(properties); + }); + } + private static BlockBehaviour.Properties properties() { return BlockBehaviour.Properties.of().strength(2); } @@ -159,46 +164,47 @@ public final class ModRegistry { return BlockBehaviour.Properties.of().strength(1.5f); } - public static final RegistryEntry> COMPUTER_NORMAL = REGISTRY.register("computer_normal", - () -> new ComputerBlock<>(computerProperties().mapColor(MapColor.STONE), BlockEntities.COMPUTER_NORMAL)); - public static final RegistryEntry> COMPUTER_ADVANCED = REGISTRY.register("computer_advanced", - () -> new ComputerBlock<>(computerProperties().mapColor(MapColor.GOLD), BlockEntities.COMPUTER_ADVANCED)); - public static final RegistryEntry> COMPUTER_COMMAND = REGISTRY.register("computer_command", - () -> new CommandComputerBlock<>(computerProperties().strength(-1, 6000000.0F), BlockEntities.COMPUTER_COMMAND)); + public static final RegistryEntry> COMPUTER_NORMAL = register("computer_normal", + p -> new ComputerBlock<>(p, BlockEntities.COMPUTER_NORMAL), computerProperties().mapColor(MapColor.STONE)); + public static final RegistryEntry> COMPUTER_ADVANCED = register("computer_advanced", + p -> new ComputerBlock<>(p, BlockEntities.COMPUTER_ADVANCED), computerProperties().mapColor(MapColor.GOLD)); + public static final RegistryEntry> COMPUTER_COMMAND = register("computer_command", + p -> new CommandComputerBlock<>(p, BlockEntities.COMPUTER_COMMAND), computerProperties().strength(-1, 6000000.0F)); - public static final RegistryEntry TURTLE_NORMAL = REGISTRY.register("turtle_normal", - () -> new TurtleBlock(turtleProperties().mapColor(MapColor.STONE), BlockEntities.TURTLE_NORMAL)); - public static final RegistryEntry TURTLE_ADVANCED = REGISTRY.register("turtle_advanced", - () -> new TurtleBlock(turtleProperties().mapColor(MapColor.GOLD).explosionResistance(TurtleBlock.IMMUNE_EXPLOSION_RESISTANCE), BlockEntities.TURTLE_ADVANCED)); + public static final RegistryEntry TURTLE_NORMAL = register("turtle_normal", + p -> new TurtleBlock(p, BlockEntities.TURTLE_NORMAL), turtleProperties().mapColor(MapColor.STONE)); + public static final RegistryEntry TURTLE_ADVANCED = register("turtle_advanced", + p -> new TurtleBlock(p, BlockEntities.TURTLE_ADVANCED), turtleProperties().mapColor(MapColor.GOLD).explosionResistance(TurtleBlock.IMMUNE_EXPLOSION_RESISTANCE)); - public static final RegistryEntry SPEAKER = REGISTRY.register("speaker", () -> new SpeakerBlock(properties().mapColor(MapColor.STONE))); - public static final RegistryEntry DISK_DRIVE = REGISTRY.register("disk_drive", () -> new DiskDriveBlock(properties().mapColor(MapColor.STONE))); - public static final RegistryEntry PRINTER = REGISTRY.register("printer", () -> new PrinterBlock(properties().mapColor(MapColor.STONE))); + public static final RegistryEntry SPEAKER = register("speaker", SpeakerBlock::new, properties().mapColor(MapColor.STONE)); + public static final RegistryEntry DISK_DRIVE = register("disk_drive", DiskDriveBlock::new, properties().mapColor(MapColor.STONE)); + public static final RegistryEntry PRINTER = register("printer", PrinterBlock::new, properties().mapColor(MapColor.STONE)); - public static final RegistryEntry MONITOR_NORMAL = REGISTRY.register("monitor_normal", - () -> new MonitorBlock(properties().mapColor(MapColor.STONE), BlockEntities.MONITOR_NORMAL)); - public static final RegistryEntry MONITOR_ADVANCED = REGISTRY.register("monitor_advanced", - () -> new MonitorBlock(properties().mapColor(MapColor.GOLD), BlockEntities.MONITOR_ADVANCED)); + public static final RegistryEntry MONITOR_NORMAL = register("monitor_normal", + p -> new MonitorBlock(p, BlockEntities.MONITOR_NORMAL), properties().mapColor(MapColor.STONE)); + public static final RegistryEntry MONITOR_ADVANCED = register("monitor_advanced", + p -> new MonitorBlock(p, BlockEntities.MONITOR_ADVANCED), properties().mapColor(MapColor.GOLD)); - public static final RegistryEntry WIRELESS_MODEM_NORMAL = REGISTRY.register("wireless_modem_normal", - () -> new WirelessModemBlock(properties().mapColor(MapColor.STONE), BlockEntities.WIRELESS_MODEM_NORMAL)); - public static final RegistryEntry WIRELESS_MODEM_ADVANCED = REGISTRY.register("wireless_modem_advanced", - () -> new WirelessModemBlock(properties().mapColor(MapColor.GOLD), BlockEntities.WIRELESS_MODEM_ADVANCED)); + public static final RegistryEntry WIRELESS_MODEM_NORMAL = register("wireless_modem_normal", + p -> new WirelessModemBlock(p, BlockEntities.WIRELESS_MODEM_NORMAL), properties().mapColor(MapColor.STONE)); + public static final RegistryEntry WIRELESS_MODEM_ADVANCED = register("wireless_modem_advanced", + p -> new WirelessModemBlock(p, BlockEntities.WIRELESS_MODEM_ADVANCED), properties().mapColor(MapColor.GOLD)); - public static final RegistryEntry WIRED_MODEM_FULL = REGISTRY.register("wired_modem_full", - () -> new WiredModemFullBlock(modemProperties().mapColor(MapColor.STONE))); - public static final RegistryEntry CABLE = REGISTRY.register("cable", () -> new CableBlock(modemProperties().mapColor(MapColor.STONE))); + public static final RegistryEntry WIRED_MODEM_FULL = register("wired_modem_full", + WiredModemFullBlock::new, modemProperties().mapColor(MapColor.STONE)); + public static final RegistryEntry CABLE = register("cable", CableBlock::new, modemProperties().mapColor(MapColor.STONE)); - public static final RegistryEntry LECTERN = REGISTRY.register("lectern", () -> new CustomLecternBlock( - BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.5F).sound(SoundType.WOOD).ignitedByLava() - )); + public static final RegistryEntry LECTERN = register("lectern", CustomLecternBlock::new, + BlockBehaviour.Properties.ofFullCopy(net.minecraft.world.level.block.Blocks.LECTERN) + .overrideDescription(net.minecraft.world.level.block.Blocks.LECTERN.getDescriptionId()) + ); } public static class BlockEntities { static final RegistrationHelper> REGISTRY = PlatformHelper.get().createRegistrationHelper(Registries.BLOCK_ENTITY_TYPE); private static RegistryEntry> ofBlock(RegistryEntry block, BlockEntityType.BlockEntitySupplier factory) { - return REGISTRY.register(block.id().getPath(), () -> BlockEntityType.Builder.of(factory, block.get()).build(null)); + return REGISTRY.register(block.id().getPath(), () -> new BlockEntityType<>(factory, Set.of(block.get()))); } public static final RegistryEntry> MONITOR_NORMAL = @@ -244,37 +250,45 @@ public final class ModRegistry { return new Item.Properties(); } + private static RegistryEntry register(String name, Function build, Supplier properties) { + return REGISTRY.register(name, () -> build.apply(properties.get().setId(ResourceKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name))))); + } + + private static RegistryEntry register(String name, Function build, Item.Properties properties) { + return register(name, build, () -> properties); + } + private static RegistryEntry ofBlock(RegistryEntry parent, BiFunction supplier) { - return REGISTRY.register(parent.id().getPath(), () -> supplier.apply(parent.get(), properties())); + return register(parent.id().getPath(), p -> supplier.apply(parent.get(), p), properties().useBlockDescriptionPrefix()); } public static final RegistryEntry COMPUTER_NORMAL = ofBlock(Blocks.COMPUTER_NORMAL, ComputerItem::new); public static final RegistryEntry COMPUTER_ADVANCED = ofBlock(Blocks.COMPUTER_ADVANCED, ComputerItem::new); public static final RegistryEntry COMPUTER_COMMAND = ofBlock(Blocks.COMPUTER_COMMAND, CommandComputerItem::new); - public static final RegistryEntry POCKET_COMPUTER_NORMAL = REGISTRY.register("pocket_computer_normal", - () -> new PocketComputerItem(properties().stacksTo(1), ComputerFamily.NORMAL)); - public static final RegistryEntry POCKET_COMPUTER_ADVANCED = REGISTRY.register("pocket_computer_advanced", - () -> new PocketComputerItem(properties().stacksTo(1), ComputerFamily.ADVANCED)); + public static final RegistryEntry POCKET_COMPUTER_NORMAL = register("pocket_computer_normal", + p -> new PocketComputerItem(p, ComputerFamily.NORMAL), properties().stacksTo(1)); + public static final RegistryEntry POCKET_COMPUTER_ADVANCED = register("pocket_computer_advanced", + p -> new PocketComputerItem(p, ComputerFamily.ADVANCED), properties().stacksTo(1)); public static final RegistryEntry TURTLE_NORMAL = ofBlock(Blocks.TURTLE_NORMAL, TurtleItem::new); public static final RegistryEntry TURTLE_ADVANCED = ofBlock(Blocks.TURTLE_ADVANCED, TurtleItem::new); public static final RegistryEntry DISK = - REGISTRY.register("disk", () -> new DiskItem(properties().stacksTo(1))); + register("disk", DiskItem::new, properties().stacksTo(1)); public static final RegistryEntry TREASURE_DISK = - REGISTRY.register("treasure_disk", () -> new TreasureDiskItem(properties().stacksTo(1))); + register("treasure_disk", TreasureDiskItem::new, properties().stacksTo(1)); private static Item.Properties printoutProperties() { return properties().stacksTo(1).component(DataComponents.PRINTOUT.get(), PrintoutData.EMPTY); } - public static final RegistryEntry PRINTED_PAGE = REGISTRY.register("printed_page", - () -> new PrintoutItem(printoutProperties(), PrintoutItem.Type.PAGE)); - public static final RegistryEntry PRINTED_PAGES = REGISTRY.register("printed_pages", - () -> new PrintoutItem(printoutProperties(), PrintoutItem.Type.PAGES)); - public static final RegistryEntry PRINTED_BOOK = REGISTRY.register("printed_book", - () -> new PrintoutItem(printoutProperties(), PrintoutItem.Type.BOOK)); + public static final RegistryEntry PRINTED_PAGE = register("printed_page", + p -> new PrintoutItem(p, PrintoutItem.Type.PAGE), Items::printoutProperties); + public static final RegistryEntry PRINTED_PAGES = register("printed_pages", + p -> new PrintoutItem(p, PrintoutItem.Type.PAGES), Items::printoutProperties); + public static final RegistryEntry PRINTED_BOOK = register("printed_book", + p -> new PrintoutItem(p, PrintoutItem.Type.BOOK), Items::printoutProperties); public static final RegistryEntry SPEAKER = ofBlock(Blocks.SPEAKER, BlockItem::new); public static final RegistryEntry DISK_DRIVE = ofBlock(Blocks.DISK_DRIVE, BlockItem::new); @@ -285,10 +299,10 @@ public final class ModRegistry { public static final RegistryEntry WIRELESS_MODEM_ADVANCED = ofBlock(Blocks.WIRELESS_MODEM_ADVANCED, BlockItem::new); public static final RegistryEntry WIRED_MODEM_FULL = ofBlock(Blocks.WIRED_MODEM_FULL, BlockItem::new); - public static final RegistryEntry CABLE = REGISTRY.register("cable", - () -> new CableBlockItem.Cable(Blocks.CABLE.get(), properties())); - public static final RegistryEntry WIRED_MODEM = REGISTRY.register("wired_modem", - () -> new CableBlockItem.WiredModem(Blocks.CABLE.get(), properties())); + public static final RegistryEntry CABLE = register("cable", + p -> new CableBlockItem.Cable(Blocks.CABLE.get(), p), properties().useBlockDescriptionPrefix()); + public static final RegistryEntry WIRED_MODEM = register("wired_modem", + p -> new CableBlockItem.WiredModem(Blocks.CABLE.get(), p), properties().useBlockDescriptionPrefix()); } public static final class DataComponents { @@ -481,8 +495,8 @@ public final class ModRegistry { public static class RecipeSerializers { static final RegistrationHelper> REGISTRY = PlatformHelper.get().createRegistrationHelper(Registries.RECIPE_SERIALIZER); - private static RegistryEntry> simple(String name, SimpleCraftingRecipeSerializer.Factory factory) { - return REGISTRY.register(name, () -> new SimpleCraftingRecipeSerializer<>(factory)); + private static RegistryEntry> simple(String name, CustomRecipe.Serializer.Factory factory) { + return REGISTRY.register(name, () -> new CustomRecipe.Serializer<>(factory)); } private static > RegistryEntry> register(String name, MapCodec codec, StreamCodec streamCodec) { @@ -495,12 +509,12 @@ public final class ModRegistry { public static final RegistryEntry> TRANSFORM_SHAPED = register("transform_shaped", TransformShapedRecipe.CODEC, TransformShapedRecipe.STREAM_CODEC); public static final RegistryEntry> TRANSFORM_SHAPELESS = register("transform_shapeless", TransformShapelessRecipe.CODEC, TransformShapelessRecipe.STREAM_CODEC); - public static final RegistryEntry> DYEABLE_ITEM = simple("colour", ColourableRecipe::new); - public static final RegistryEntry> DYEABLE_ITEM_CLEAR = simple("clear_colour", ClearColourRecipe::new); - public static final RegistryEntry> TURTLE_UPGRADE = simple("turtle_upgrade", TurtleUpgradeRecipe::new); - public static final RegistryEntry> POCKET_COMPUTER_UPGRADE = simple("pocket_computer_upgrade", PocketComputerUpgradeRecipe::new); + public static final RegistryEntry> DYEABLE_ITEM = simple("colour", ColourableRecipe::new); + public static final RegistryEntry> DYEABLE_ITEM_CLEAR = simple("clear_colour", ClearColourRecipe::new); + public static final RegistryEntry> TURTLE_UPGRADE = simple("turtle_upgrade", TurtleUpgradeRecipe::new); + public static final RegistryEntry> POCKET_COMPUTER_UPGRADE = simple("pocket_computer_upgrade", PocketComputerUpgradeRecipe::new); public static final RegistryEntry> PRINTOUT = register("printout", PrintoutRecipe.CODEC, PrintoutRecipe.STREAM_CODEC); - public static final RegistryEntry> DISK = simple("disk", DiskRecipe::new); + public static final RegistryEntry> DISK = register("disk", DiskRecipe.CODEC, DiskRecipe.STREAM_CODEC); } public static class RecipeFunctions { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java b/projects/common/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java index 5311b6063..04416698c 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java @@ -29,7 +29,7 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.world.MenuProvider; -import net.minecraft.world.entity.RelativeMovement; +import net.minecraft.world.entity.Relative; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -225,7 +225,7 @@ public final class CommandComputerCraft { private static int teleport(CommandSourceStack source, ServerComputer computer) throws CommandSyntaxException { var world = computer.getLevel(); var pos = Vec3.atBottomCenterOf(computer.getPosition()); - source.getEntityOrException().teleportTo(world, pos.x(), pos.y(), pos.z(), EnumSet.noneOf(RelativeMovement.class), 0, 0); + source.getEntityOrException().teleportTo(world, pos.x(), pos.y(), pos.z(), EnumSet.noneOf(Relative.class), 0, 0, true); return 1; } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/common/ClearColourRecipe.java b/projects/common/src/main/java/dan200/computercraft/shared/common/ClearColourRecipe.java index 396c30a9f..98436c763 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/common/ClearColourRecipe.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/common/ClearColourRecipe.java @@ -72,11 +72,6 @@ public final class ClearColourRecipe extends CustomRecipe { return remaining; } - @Override - public boolean canCraftInDimensions(int x, int y) { - return x * y >= 2; - } - @Override public RecipeSerializer getSerializer() { return ModRegistry.RecipeSerializers.DYEABLE_ITEM_CLEAR.get(); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java b/projects/common/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java index e643b8a41..cda3a7e21 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/common/ColourableRecipe.java @@ -70,11 +70,6 @@ public final class ColourableRecipe extends CustomRecipe { } - @Override - public boolean canCraftInDimensions(int x, int y) { - return x >= 2 && y >= 2; - } - @Override public RecipeSerializer getSerializer() { return ModRegistry.RecipeSerializers.DYEABLE_ITEM.get(); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/common/HorizontalContainerBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/common/HorizontalContainerBlock.java index 07a1f5472..8268e2f1d 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/common/HorizontalContainerBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/common/HorizontalContainerBlock.java @@ -5,6 +5,7 @@ package dan200.computercraft.shared.common; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.world.Containers; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; @@ -18,7 +19,7 @@ import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.phys.BlockHitResult; @@ -28,7 +29,7 @@ import net.minecraft.world.phys.BlockHitResult; * @see AbstractContainerBlockEntity The container class which should be used on the block entity. */ public abstract class HorizontalContainerBlock extends BaseEntityBlock { - public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + public static final EnumProperty FACING = BlockStateProperties.HORIZONTAL_FACING; public HorizontalContainerBlock(Properties properties) { super(properties); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlock.java index 23c4d5c9c..8bbcedcb8 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/AbstractComputerBlock.java @@ -11,13 +11,14 @@ import dan200.computercraft.shared.platform.RegistryEntry; import dan200.computercraft.shared.util.BlockEntityHelpers; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.ScheduledTickAccess; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.EntityBlock; @@ -26,6 +27,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityTicker; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.redstone.Orientation; import net.minecraft.world.phys.BlockHitResult; import javax.annotation.Nullable; @@ -123,16 +125,23 @@ public abstract class AbstractComputerBlock extends AbstractComput ).apply(instance, ComputerBlock::new)); public static final EnumProperty STATE = EnumProperty.create("state", ComputerState.class); - public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + public static final EnumProperty FACING = BlockStateProperties.HORIZONTAL_FACING; public ComputerBlock(Properties settings, RegistryEntry> type) { super(settings, type); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/config/Config.java b/projects/common/src/main/java/dan200/computercraft/shared/config/Config.java index b18d7cafd..7c3dbc1a8 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/config/Config.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/config/Config.java @@ -4,8 +4,6 @@ package dan200.computercraft.shared.config; -import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; - /** * ComputerCraft's global config. * @@ -23,7 +21,6 @@ public final class Config { public static int modemRangeDuringStorm = 64; public static int modemHighAltitudeRangeDuringStorm = 384; public static int maxNotesPerTick = 8; - public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST; public static int monitorDistance = 65; public static long monitorBandwidth = 1_000_000; diff --git a/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigSpec.java b/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigSpec.java index 1d28130e4..7c168137f 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigSpec.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigSpec.java @@ -11,7 +11,6 @@ import dan200.computercraft.core.Logging; import dan200.computercraft.core.apis.http.NetworkUtils; import dan200.computercraft.core.apis.http.options.ProxyType; import dan200.computercraft.core.computer.mainthread.MainThreadConfig; -import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; import dan200.computercraft.shared.platform.PlatformHelper; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Filter; @@ -78,7 +77,6 @@ public final class ConfigSpec { public static final ConfigFile clientSpec; - public static final ConfigFile.Value monitorRenderer; public static final ConfigFile.Value monitorDistance; public static final ConfigFile.Value uploadNagDelay; @@ -364,12 +362,6 @@ public final class ConfigSpec { serverSpec = builder.build(ConfigSpec::syncServer); var clientBuilder = PlatformHelper.get().createConfigBuilder(); - monitorRenderer = clientBuilder - .comment(""" - The renderer to use for monitors. Generally this should be kept at "best" - if - monitors have performance issues, you may wish to experiment with alternative - renderers.""") - .defineEnum("monitor_renderer", MonitorRenderer.BEST); monitorDistance = clientBuilder .comment(""" The maximum distance monitors will render at. This defaults to the standard tile @@ -446,7 +438,6 @@ public final class ConfigSpec { } public static void syncClient(@Nullable Path path) { - Config.monitorRenderer = monitorRenderer.get(); Config.monitorDistance = monitorDistance.get(); Config.uploadNagDelay = uploadNagDelay.get(); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/data/BlockNamedEntityLootCondition.java b/projects/common/src/main/java/dan200/computercraft/shared/data/BlockNamedEntityLootCondition.java index bec825a0e..686046439 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/data/BlockNamedEntityLootCondition.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/data/BlockNamedEntityLootCondition.java @@ -5,9 +5,9 @@ package dan200.computercraft.shared.data; import dan200.computercraft.shared.ModRegistry; +import net.minecraft.util.context.ContextKey; import net.minecraft.world.Nameable; import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParam; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; @@ -26,12 +26,12 @@ public final class BlockNamedEntityLootCondition implements LootItemCondition { @Override public boolean test(LootContext lootContext) { - var tile = lootContext.getParamOrNull(LootContextParams.BLOCK_ENTITY); + var tile = lootContext.getOptionalParameter(LootContextParams.BLOCK_ENTITY); return tile instanceof Nameable nameable && nameable.hasCustomName(); } @Override - public Set> getReferencedContextParams() { + public Set> getReferencedContextParams() { return Set.of(LootContextParams.BLOCK_ENTITY); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java b/projects/common/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java index cb1f4f319..b507b8dff 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/data/HasComputerIdLootCondition.java @@ -6,8 +6,8 @@ package dan200.computercraft.shared.data; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.computer.blocks.AbstractComputerBlockEntity; +import net.minecraft.util.context.ContextKey; import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParam; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; @@ -26,12 +26,12 @@ public final class HasComputerIdLootCondition implements LootItemCondition { @Override public boolean test(LootContext lootContext) { - var tile = lootContext.getParamOrNull(LootContextParams.BLOCK_ENTITY); + var tile = lootContext.getOptionalParameter(LootContextParams.BLOCK_ENTITY); return tile instanceof AbstractComputerBlockEntity computer && computer.getComputerID() >= 0; } @Override - public Set> getReferencedContextParams() { + public Set> getReferencedContextParams() { return Set.of(LootContextParams.BLOCK_ENTITY); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/data/PlayerCreativeLootCondition.java b/projects/common/src/main/java/dan200/computercraft/shared/data/PlayerCreativeLootCondition.java index db8bfc85d..7bb697ef5 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/data/PlayerCreativeLootCondition.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/data/PlayerCreativeLootCondition.java @@ -5,9 +5,9 @@ package dan200.computercraft.shared.data; import dan200.computercraft.shared.ModRegistry; +import net.minecraft.util.context.ContextKey; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParam; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; @@ -26,12 +26,12 @@ public final class PlayerCreativeLootCondition implements LootItemCondition { @Override public boolean test(LootContext lootContext) { - var entity = lootContext.getParamOrNull(LootContextParams.THIS_ENTITY); + var entity = lootContext.getOptionalParameter(LootContextParams.THIS_ENTITY); return entity instanceof Player player && player.isCreative(); } @Override - public Set> getReferencedContextParams() { + public Set> getReferencedContextParams() { return Set.of(LootContextParams.THIS_ENTITY); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/integration/UpgradeRecipeGenerator.java b/projects/common/src/main/java/dan200/computercraft/shared/integration/UpgradeRecipeGenerator.java index 792721c6a..d6b299c93 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/integration/UpgradeRecipeGenerator.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/integration/UpgradeRecipeGenerator.java @@ -15,13 +15,12 @@ import dan200.computercraft.shared.turtle.items.TurtleItem; import dan200.computercraft.shared.util.DataComponentUtil; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; -import net.minecraft.core.NonNullList; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.CraftingBookCategory; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.ShapedRecipe; -import net.minecraft.world.item.crafting.ShapedRecipePattern; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.display.RecipeDisplay; +import net.minecraft.world.item.crafting.display.ShapedCraftingRecipeDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplay; import javax.annotation.Nullable; import java.util.*; @@ -37,7 +36,9 @@ import static dan200.computercraft.shared.integration.RecipeModHelpers.*; * @see RecipeModHelpers */ public class UpgradeRecipeGenerator { - private final Function wrap; + private static final SlotDisplay CRAFTING_STATION = new SlotDisplay.ItemSlotDisplay(Items.CRAFTING_TABLE); + + private final Function wrap; private final HolderLookup.Provider registries; private final Map> upgradeItemLookup = new HashMap<>(); @@ -45,7 +46,7 @@ public class UpgradeRecipeGenerator { private final List turtleUpgrades = new ArrayList<>(); private boolean initialised = false; - public UpgradeRecipeGenerator(Function wrap, HolderLookup.Provider registries) { + public UpgradeRecipeGenerator(Function wrap, HolderLookup.Provider registries) { this.wrap = wrap; this.registries = registries; } @@ -117,7 +118,7 @@ public class UpgradeRecipeGenerator { if (left != null && right != null) return List.of(); List recipes = new ArrayList<>(); - var ingredient = Ingredient.of(stack); + var ingredient = new SlotDisplay.ItemStackSlotDisplay(stack); for (var upgrade : turtleUpgrades) { if (upgrade.turtle == null) throw new NullPointerException(); @@ -138,7 +139,7 @@ public class UpgradeRecipeGenerator { if (back != null) return List.of(); List recipes = new ArrayList<>(); - var ingredient = Ingredient.of(stack); + var ingredient = new SlotDisplay.ItemStackSlotDisplay(stack); for (var upgrade : pocketUpgrades) { if (upgrade.pocket == null) throw new NullPointerException(); recipes.add(pocket(upgrade.ingredient, ingredient, pocketWith(stack, UpgradeData.ofDefault(upgrade.pocket)))); @@ -190,16 +191,16 @@ public class UpgradeRecipeGenerator { // The turtle is facing towards us, so upgrades on the left are actually crafted on the right. if (left != null) { recipes.add(turtle( - Ingredient.of(turtleWith(stack, null, right)), - Ingredient.of(left.getUpgradeItem()), + new SlotDisplay.ItemStackSlotDisplay(turtleWith(stack, null, right)), + new SlotDisplay.ItemStackSlotDisplay(left.getUpgradeItem()), stack )); } if (right != null) { recipes.add(turtle( - Ingredient.of(right.getUpgradeItem()), - Ingredient.of(turtleWith(stack, left, null)), + new SlotDisplay.ItemStackSlotDisplay(right.getUpgradeItem()), + new SlotDisplay.ItemStackSlotDisplay(turtleWith(stack, left, null)), stack )); } @@ -210,7 +211,7 @@ public class UpgradeRecipeGenerator { var back = PocketComputerItem.getUpgradeWithData(stack); if (back != null) { - recipes.add(pocket(Ingredient.of(back.getUpgradeItem()), Ingredient.of(pocketWith(stack, null)), stack)); + recipes.add(pocket(new SlotDisplay.ItemStackSlotDisplay(back.getUpgradeItem()), new SlotDisplay.ItemStackSlotDisplay(pocketWith(stack, null)), stack)); } return Collections.unmodifiableList(recipes); @@ -232,25 +233,21 @@ public class UpgradeRecipeGenerator { return newStack; } - private T pocket(Ingredient upgrade, Ingredient pocketComputer, ItemStack result) { - return wrap.apply(new ShapedRecipe( - "", CraftingBookCategory.MISC, - new ShapedRecipePattern(1, 2, NonNullList.of(Ingredient.EMPTY, upgrade, pocketComputer), Optional.empty()), - result + private T pocket(SlotDisplay upgrade, SlotDisplay pocketComputer, ItemStack result) { + return wrap.apply(new ShapedCraftingRecipeDisplay( + 1, 2, List.of(upgrade, pocketComputer), new SlotDisplay.ItemStackSlotDisplay(result), CRAFTING_STATION )); } - private T turtle(Ingredient left, Ingredient right, ItemStack result) { - return wrap.apply(new ShapedRecipe( - "", CraftingBookCategory.MISC, - new ShapedRecipePattern(2, 1, NonNullList.of(Ingredient.EMPTY, left, right), Optional.empty()), - result + private T turtle(SlotDisplay left, SlotDisplay right, ItemStack result) { + return wrap.apply(new ShapedCraftingRecipeDisplay( + 2, 1, List.of(left, right), new SlotDisplay.ItemStackSlotDisplay(result), CRAFTING_STATION )); } private class UpgradeInfo { final ItemStack stack; - final Ingredient ingredient; + final SlotDisplay ingredient; final @Nullable Holder.Reference turtle; final @Nullable Holder.Reference pocket; final UpgradeBase upgrade; @@ -258,7 +255,7 @@ public class UpgradeRecipeGenerator { UpgradeInfo(ItemStack stack, UpgradeBase upgrade, @Nullable Holder.Reference turtle, @Nullable Holder.Reference pocket) { this.stack = stack; - ingredient = Ingredient.of(stack); + ingredient = new SlotDisplay.ItemStackSlotDisplay(stack); this.turtle = turtle; this.pocket = pocket; this.upgrade = upgrade; @@ -275,7 +272,7 @@ public class UpgradeRecipeGenerator { var turtleItem = turtleSupplier.get(); recipes.add(turtle( ingredient, // Right upgrade, recipe on left - Ingredient.of(new ItemStack(turtleItem)), + new SlotDisplay.ItemSlotDisplay(turtleItem), DataComponentUtil.createStack(turtleItem, ModRegistry.DataComponents.RIGHT_TURTLE_UPGRADE.get(), UpgradeData.ofDefault(turtle)) )); } @@ -286,7 +283,7 @@ public class UpgradeRecipeGenerator { var pocketItem = pocketSupplier.get(); recipes.add(pocket( ingredient, - Ingredient.of(pocketItem), + new SlotDisplay.ItemSlotDisplay(pocketItem), DataComponentUtil.createStack(pocketItem, ModRegistry.DataComponents.POCKET_UPGRADE.get(), UpgradeData.ofDefault(pocket)) )); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/lectern/CustomLecternBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/lectern/CustomLecternBlock.java index b3e0e1814..c2e1b34e3 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/lectern/CustomLecternBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/lectern/CustomLecternBlock.java @@ -50,7 +50,7 @@ public class CustomLecternBlock extends LecternBlock { public static InteractionResult tryPlaceItem(Player player, Level level, BlockPos pos, BlockState blockState, ItemStack item) { if (item.getItem() instanceof PrintoutItem) { if (!level.isClientSide) replaceLectern(player, level, pos, blockState, item); - return InteractionResult.sidedSuccess(level.isClientSide); + return InteractionResult.SUCCESS; } return InteractionResult.PASS; @@ -129,11 +129,6 @@ public class CustomLecternBlock extends LecternBlock { level.addFreshEntity(entity); } - @Override - public String getDescriptionId() { - return Blocks.LECTERN.getDescriptionId(); - } - @Override public CustomLecternBlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new CustomLecternBlockEntity(pos, state); @@ -158,6 +153,6 @@ public class CustomLecternBlock extends LecternBlock { player.awardStat(Stats.INTERACT_WITH_LECTERN); } - return InteractionResult.sidedSuccess(level.isClientSide); + return InteractionResult.SUCCESS; } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutItem.java b/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutItem.java index 0838e4de7..199107bf9 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutItem.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutItem.java @@ -9,7 +9,6 @@ import dan200.computercraft.shared.media.PrintoutMenu; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.SimpleMenuProvider; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; @@ -40,14 +39,14 @@ public class PrintoutItem extends Item { } @Override - public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { + public InteractionResult use(Level world, Player player, InteractionHand hand) { var stack = player.getItemInHand(hand); if (!world.isClientSide) { var title = PrintoutData.getOrEmpty(stack).title(); var displayTitle = Strings.isNullOrEmpty(title) ? stack.getDisplayName() : Component.literal(title); player.openMenu(new SimpleMenuProvider((id, playerInventory, p) -> PrintoutMenu.createInHand(id, p, hand), displayTitle)); } - return new InteractionResultHolder<>(InteractionResult.sidedSuccess(world.isClientSide), stack); + return InteractionResult.SUCCESS; } public Type getType() { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java b/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java index 1c7586bed..ea7eb23a2 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/DiskRecipe.java @@ -4,50 +4,101 @@ package dan200.computercraft.shared.media.recipes; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import dan200.computercraft.core.util.Colour; import dan200.computercraft.shared.ModRegistry; -import dan200.computercraft.shared.platform.PlatformHelper; +import dan200.computercraft.shared.recipe.AbstractCraftingRecipe; +import dan200.computercraft.shared.recipe.RecipeProperties; +import dan200.computercraft.shared.recipe.ShapelessRecipeSpec; import dan200.computercraft.shared.util.ColourTracker; import dan200.computercraft.shared.util.ColourUtils; import dan200.computercraft.shared.util.DataComponentUtil; import net.minecraft.core.HolderLookup; import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.world.entity.player.StackedItemContents; +import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.component.DyedItemColor; -import net.minecraft.world.item.crafting.*; +import net.minecraft.world.item.crafting.CraftingInput; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.PlacementInfo; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.display.RecipeDisplay; +import net.minecraft.world.item.crafting.display.ShapelessCraftingRecipeDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplay; import net.minecraft.world.level.Level; -public class DiskRecipe extends CustomRecipe { - private final Ingredient redstone; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; - public DiskRecipe(CraftingBookCategory category) { - super(category); - redstone = PlatformHelper.get().getRecipeIngredients().redstone(); +public class DiskRecipe extends AbstractCraftingRecipe { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + RecipeProperties.CODEC.forGetter(x -> x.properties), + ShapelessRecipeSpec.INGREDIENT_CODEC.fieldOf("ingredients").forGetter(x -> x.ingredients) + ).apply(instance, DiskRecipe::new)); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + RecipeProperties.STREAM_CODEC, x -> x.properties, + Ingredient.CONTENTS_STREAM_CODEC.apply(ByteBufCodecs.list()), x -> x.ingredients, + DiskRecipe::new + ); + + private final List ingredients; + private @Nullable PlacementInfo placementInfo; + + public DiskRecipe(RecipeProperties properties, List ingredients) { + super(properties); + this.ingredients = ingredients; + } + + @Override + public PlacementInfo placementInfo() { + if (placementInfo == null) placementInfo = PlacementInfo.create(ingredients); + return placementInfo; + } + + @Override + public List display() { + var dyes = ColourUtils.DYES; + List out = new ArrayList<>(dyes.size()); + for (var i = 0; i < dyes.size(); i++) { + var tracker = new ColourTracker(); + tracker.addColour(DyeColor.byId(i)); + + out.add(new ShapelessCraftingRecipeDisplay( + Stream.concat(ingredients.stream(), Stream.of(Ingredient.of(BuiltInRegistries.ITEM.getOrThrow(dyes.get(i))))) + .map(Ingredient::display).toList(), + new SlotDisplay.ItemStackSlotDisplay(DataComponentUtil.createStack( + ModRegistry.Items.DISK.get(), DataComponents.DYED_COLOR, new DyedItemColor(tracker.getColour(), false) + )), + new SlotDisplay.ItemSlotDisplay(Items.CRAFTING_TABLE) + )); + } + return out; } @Override public boolean matches(CraftingInput inv, Level world) { - var paperFound = false; - var redstoneFound = false; + var inputs = 0; + var stackedContents = new StackedItemContents(); - for (var i = 0; i < inv.size(); i++) { + for (var i = 0; i < inv.size(); ++i) { var stack = inv.getItem(i); - - if (!stack.isEmpty()) { - if (stack.getItem() == Items.PAPER) { - if (paperFound) return false; - paperFound = true; - } else if (redstone.test(stack)) { - if (redstoneFound) return false; - redstoneFound = true; - } else if (ColourUtils.getStackColour(stack) == null) { - return false; - } + if (stack.isEmpty()) continue; + if (ColourUtils.getStackColour(stack) == null) { + stackedContents.accountStack(stack, 1); } } - return redstoneFound && paperFound; + return inputs == ingredients.size() && stackedContents.canCraft(placementInfo().unpackedIngredients(), null); } @Override @@ -59,27 +110,15 @@ public class DiskRecipe extends CustomRecipe { if (stack.isEmpty()) continue; - if (stack.getItem() != Items.PAPER && !redstone.test(stack)) { - var dye = ColourUtils.getStackColour(stack); - if (dye != null) tracker.addColour(dye); - } + var dye = ColourUtils.getStackColour(stack); + if (dye != null) tracker.addColour(dye); } return DataComponentUtil.createStack(ModRegistry.Items.DISK.get(), DataComponents.DYED_COLOR, new DyedItemColor(tracker.hasColour() ? tracker.getColour() : Colour.BLUE.getHex(), false)); } @Override - public boolean canCraftInDimensions(int x, int y) { - return x >= 2 && y >= 2; - } - - @Override - public ItemStack getResultItem(HolderLookup.Provider registryAccess) { - return DataComponentUtil.createStack(ModRegistry.Items.DISK.get(), DataComponents.DYED_COLOR, new DyedItemColor(Colour.BLUE.getHex(), false)); - } - - @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() { return ModRegistry.RecipeSerializers.DISK.get(); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java b/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java index 8837e3256..e9715b50b 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java @@ -9,22 +9,23 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.media.items.PrintoutData; import dan200.computercraft.shared.media.items.PrintoutItem; -import dan200.computercraft.shared.recipe.RecipeProperties; +import dan200.computercraft.shared.recipe.AbstractCraftingRecipe; import dan200.computercraft.shared.recipe.ShapelessRecipeSpec; import net.minecraft.core.HolderLookup; -import net.minecraft.core.NonNullList; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.util.ExtraCodecs; -import net.minecraft.world.entity.player.StackedContents; +import net.minecraft.world.entity.player.StackedItemContents; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.ShapelessRecipe; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.*; +import net.minecraft.world.item.crafting.display.RecipeDisplay; +import net.minecraft.world.item.crafting.display.ShapelessCraftingRecipeDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplay; import net.minecraft.world.level.Level; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; @@ -36,10 +37,10 @@ import java.util.List; * @see PrintoutItem * @see PrintoutData */ -public final class PrintoutRecipe extends ShapelessRecipe { +public final class PrintoutRecipe extends AbstractCraftingRecipe { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( ShapelessRecipeSpec.CODEC.forGetter(PrintoutRecipe::toSpec), - Ingredient.CODEC_NONEMPTY.fieldOf("printout").forGetter(x -> x.printout), + Ingredient.CODEC.fieldOf("printout").forGetter(x -> x.printout), ExtraCodecs.POSITIVE_INT.fieldOf("min_printouts").forGetter(x -> x.minPrintouts) ).apply(instance, PrintoutRecipe::new)); @@ -50,12 +51,15 @@ public final class PrintoutRecipe extends ShapelessRecipe { PrintoutRecipe::new ); - private final NonNullList ingredients; + private final ShapelessRecipeSpec spec; + private final List ingredients; + private @Nullable PlacementInfo ingredientInfo; + + private final List placementIngredients; + private @Nullable PlacementInfo placementInfo; + private final Ingredient printout; private final int minPrintouts; - private final ShapelessRecipe innerRecipe; - - private final ItemStack result; /** * Construct a new {@link PrintoutRecipe}. @@ -67,34 +71,44 @@ public final class PrintoutRecipe extends ShapelessRecipe { public PrintoutRecipe( ShapelessRecipeSpec spec, Ingredient printout, int minPrintouts ) { - // We use the full list of ingredients in the recipe itself, so that it behaves sensibly with recipe mods. - super(spec.properties().group(), spec.properties().category(), spec.result(), concat(spec.ingredients(), printout, minPrintouts)); + super(spec.properties()); + this.spec = spec; this.ingredients = spec.ingredients(); + // We use the full list of ingredients for the display/placement information. + this.placementIngredients = concat(spec.ingredients(), printout, minPrintouts); + this.printout = printout; this.minPrintouts = minPrintouts; - this.result = spec.result(); - - // However, when testing whether the recipe matches, we only want to use the non-printout ingredients. To do - // that, we create a hidden recipe with the main ingredients. - this.innerRecipe = spec.create(); } - private static NonNullList concat(NonNullList first, Ingredient pages, int pagesRequired) { - var result = NonNullList.withSize(first.size() + pagesRequired, Ingredient.EMPTY); - var idx = 0; - for (var ingredient : first) result.set(idx++, ingredient); - for (var i = 0; i < pagesRequired; i++) result.set(idx++, pages); + private static List concat(List first, Ingredient pages, int pagesRequired) { + var result = new ArrayList(first.size() + pagesRequired); + result.addAll(first); + for (var i = 0; i < pagesRequired; i++) result.add(pages); return result; } - private ShapelessRecipeSpec toSpec() { - return new ShapelessRecipeSpec(RecipeProperties.of(this), ingredients, result); + @Override + public PlacementInfo placementInfo() { + if (placementInfo == null) placementInfo = PlacementInfo.create(placementIngredients); + return placementInfo; + } + + @Override + public List display() { + return List.of( + new ShapelessCraftingRecipeDisplay( + placementIngredients.stream().map(Ingredient::display).toList(), + new SlotDisplay.ItemStackSlotDisplay(spec.result()), + new SlotDisplay.ItemSlotDisplay(Items.CRAFTING_TABLE) + ) + ); } @Override public boolean matches(CraftingInput inv, Level world) { - var stackedContents = new StackedContents(); + var stackedContents = new StackedItemContents(); var inputs = 0; var printouts = 0; @@ -121,7 +135,14 @@ public final class PrintoutRecipe extends ShapelessRecipe { } return hasPrintout && printouts >= minPrintouts && pages <= PrintoutData.MAX_PAGES - && inputs == ingredients.size() && stackedContents.canCraft(innerRecipe, null); + && inputs == ingredients.size() && stackedContents.canCraft(getIngredientInfo().unpackedIngredients(), null); + } + + private PlacementInfo getIngredientInfo() { + // However, when testing whether the recipe matches, we only want to use the non-printout ingredients. To do + // that, we create a hidden recipe with the main ingredients. + if (ingredientInfo == null) ingredientInfo = PlacementInfo.create(ingredients); + return ingredientInfo; } @Override @@ -136,13 +157,17 @@ public final class PrintoutRecipe extends ShapelessRecipe { var lines = data.stream().flatMap(x -> x.lines().stream()).toList(); - var result = super.assemble(inv, registries); + var result = spec.result().copy(); result.set(ModRegistry.DataComponents.PRINTOUT.get(), new PrintoutData(data.getFirst().title(), lines)); return result; } + private ShapelessRecipeSpec toSpec() { + return spec; + } + @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() { return ModRegistry.RecipeSerializers.PRINTOUT.get(); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveBlock.java index ffab6ad79..ffeda0b8c 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveBlock.java @@ -11,7 +11,7 @@ import dan200.computercraft.shared.common.HorizontalContainerBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.InteractionHand; -import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -52,15 +52,15 @@ public class DiskDriveBlock extends HorizontalContainerBlock { } @Override - protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { + protected InteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { if (player.isCrouching() && level.getBlockEntity(pos) instanceof DiskDriveBlockEntity drive) { // Try to put a disk into the drive - if (stack.isEmpty()) return ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION; + if (stack.isEmpty()) return InteractionResult.TRY_WITH_EMPTY_HAND; if (!level.isClientSide && drive.getDiskStack().isEmpty() && MediaProviders.get(stack) != null) { drive.setDiskStack(stack.split(1)); } - return ItemInteractionResult.sidedSuccess(level.isClientSide); + return InteractionResult.SUCCESS; } return super.useItemOn(stack, state, level, pos, player, hand, hit); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlock.java index b23cd3d85..686d92d82 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlock.java @@ -169,8 +169,8 @@ public class CableBlock extends Block implements SimpleWaterloggedBlock, EntityB } @Override - protected BlockState updateShape(BlockState state, Direction side, BlockState otherState, LevelAccessor level, BlockPos pos, BlockPos otherPos) { - WaterloggableHelpers.updateShape(state, level, pos); + protected BlockState updateShape(BlockState state, LevelReader level, ScheduledTickAccess ticker, BlockPos pos, Direction side, BlockPos otherPos, BlockState neighborState, RandomSource randomSource) { + WaterloggableHelpers.updateShape(state, level, ticker, pos); // Should never happen, but handle the case where we've no modem or cable. if (!state.getValue(CABLE) && state.getValue(MODEM) == CableModemVariant.None) { @@ -247,10 +247,11 @@ public class CableBlock extends Block implements SimpleWaterloggedBlock, EntityB return world.getBlockEntity(pos) instanceof CableBlockEntity modem ? modem.use(player) : InteractionResult.PASS; } + /* @Override protected final void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighbourBlock, BlockPos neighbourPos, boolean isMoving) { if (world.getBlockEntity(pos) instanceof CableBlockEntity modem) modem.neighborChanged(neighbourPos); - } + }*/ @ForgeOverride public final void onNeighborChange(BlockState state, LevelReader world, BlockPos pos, BlockPos neighbour) { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlockItem.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlockItem.java index 3878f681e..ea1443c6c 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlockItem.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/CableBlockItem.java @@ -4,11 +4,8 @@ package dan200.computercraft.shared.peripheral.modem.wired; -import dan200.computercraft.shared.util.RegistryHelper; import dan200.computercraft.shared.ModRegistry; -import net.minecraft.Util; import net.minecraft.core.BlockPos; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.BlockItem; @@ -16,13 +13,9 @@ import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; -import javax.annotation.Nullable; - import static dan200.computercraft.shared.peripheral.modem.wired.CableBlock.*; public abstract class CableBlockItem extends BlockItem { - private @Nullable String translationKey; - public CableBlockItem(CableBlock block, Properties settings) { super(block, settings); } @@ -45,14 +38,6 @@ public abstract class CableBlockItem extends BlockItem { return placeAt(world, pos, correctConnections(world, pos, state)); } - @Override - public String getDescriptionId() { - if (translationKey == null) { - translationKey = Util.makeDescriptionId("block", RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, this)); - } - return translationKey; - } - public static class WiredModem extends CableBlockItem { public WiredModem(CableBlock block, Properties settings) { super(block, settings); @@ -75,7 +60,7 @@ public abstract class CableBlockItem extends BlockItem { .setValue(CONNECTIONS.get(side), existingState.getValue(CABLE)); if (placeAt(world, pos, newState)) { stack.shrink(1); - return InteractionResult.sidedSuccess(world.isClientSide); + return InteractionResult.SUCCESS; } } @@ -102,7 +87,7 @@ public abstract class CableBlockItem extends BlockItem { if (insideState.getBlock() == ModRegistry.Blocks.CABLE.get() && !insideState.getValue(CableBlock.CABLE) && placeAtCorrected(world, insidePos, insideState.setValue(CableBlock.CABLE, true))) { stack.shrink(1); - return InteractionResult.sidedSuccess(world.isClientSide); + return InteractionResult.SUCCESS; } // Try to add a cable to a modem adjacent to this block @@ -110,7 +95,7 @@ public abstract class CableBlockItem extends BlockItem { if (existingState.getBlock() == ModRegistry.Blocks.CABLE.get() && !existingState.getValue(CableBlock.CABLE) && placeAtCorrected(world, pos, existingState.setValue(CableBlock.CABLE, true))) { stack.shrink(1); - return InteractionResult.sidedSuccess(world.isClientSide); + return InteractionResult.SUCCESS; } return super.place(context); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemFullBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemFullBlock.java index 0ddc14523..749d3551e 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemFullBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemFullBlock.java @@ -13,8 +13,8 @@ import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.ScheduledTickAccess; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; @@ -48,20 +48,21 @@ public class WiredModemFullBlock extends Block implements EntityBlock { } @Override - protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) { + protected BlockState updateShape(BlockState state, LevelReader level, ScheduledTickAccess ticker, BlockPos pos, Direction direction, BlockPos otherPos, BlockState neighborState, RandomSource randomSource) { if (state.getValue(PERIPHERAL_ON) && level.getBlockEntity(pos) instanceof WiredModemFullBlockEntity modem) { modem.queueRefreshPeripheral(direction); } - return super.updateShape(state, direction, neighborState, level, pos, neighborPos); + return super.updateShape(state, level, ticker, pos, direction, otherPos, neighborState, randomSource); } + /* @Override protected final void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighbourBlock, BlockPos neighbourPos, boolean isMoving) { if (state.getValue(PERIPHERAL_ON) && level.getBlockEntity(pos) instanceof WiredModemFullBlockEntity modem) { modem.neighborChanged(neighbourPos); } - } + }*/ @ForgeOverride public final void onNeighborChange(BlockState state, LevelReader level, BlockPos pos, BlockPos neighbour) { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemBlock.java index f9c90612a..1bbe07949 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemBlock.java @@ -15,8 +15,8 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.ScheduledTickAccess; import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; @@ -69,10 +69,11 @@ public class WirelessModemBlock extends DirectionalBlock implements SimpleWaterl return WaterloggableHelpers.getFluidState(state); } + @Override - protected BlockState updateShape(BlockState state, Direction side, BlockState otherState, LevelAccessor world, BlockPos pos, BlockPos otherPos) { - WaterloggableHelpers.updateShape(state, world, pos); - return side == state.getValue(FACING) && !state.canSurvive(world, pos) + protected BlockState updateShape(BlockState state, LevelReader level, ScheduledTickAccess ticker, BlockPos pos, Direction side, BlockPos otherPos, BlockState neighborState, RandomSource randomSource) { + WaterloggableHelpers.updateShape(state, level, ticker, pos); + return side == state.getValue(FACING) && !state.canSurvive(level, pos) ? state.getFluidState().createLegacyBlock() : state; } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java index 3b0d7fa14..6a6e09172 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java @@ -42,7 +42,7 @@ public abstract class WirelessModemPeripheral extends ModemPeripheral { maxRange = Config.modemHighAltitudeRangeDuringStorm; } if (position.y > 96.0 && maxRange > minRange) { - return minRange + (position.y - 96.0) * ((maxRange - minRange) / ((world.getMaxBuildHeight() - 1) - 96.0)); + return minRange + (position.y - 96.0) * ((maxRange - minRange) / (world.getMaxY() - 96.0)); } return minRange; } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorBlock.java index 36dee39b0..9c14386cc 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorBlock.java @@ -27,7 +27,6 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.phys.BlockHitResult; @@ -36,10 +35,10 @@ import javax.annotation.Nullable; public class MonitorBlock extends HorizontalDirectionalBlock implements EntityBlock { private static final MapCodec CODEC = BlockCodecs.blockWithBlockEntityCodec(MonitorBlock::new, x -> x.type); - public static final DirectionProperty ORIENTATION = DirectionProperty.create("orientation", + public static final EnumProperty ORIENTATION = EnumProperty.create("orientation", Direction.class, Direction.UP, Direction.DOWN, Direction.NORTH); - public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + public static final EnumProperty FACING = BlockStateProperties.HORIZONTAL_FACING; public static final EnumProperty STATE = EnumProperty.create("state", MonitorEdgeState.class); private final RegistryEntry> type; @@ -114,7 +113,7 @@ public class MonitorBlock extends HorizontalDirectionalBlock implements EntityBl ); } - return InteractionResult.sidedSuccess(level.isClientSide); + return InteractionResult.SUCCESS; } @Override diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java index c57ed9205..a07af4b56 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java @@ -257,10 +257,10 @@ public abstract class SpeakerPeripheral implements IPeripheral { if (identifier == null) throw new LuaException("Malformed sound name '" + name + "' "); // Prevent playing music discs. - var soundEvent = BuiltInRegistries.SOUND_EVENT.get(identifier); + var soundEvent = BuiltInRegistries.SOUND_EVENT.getValue(identifier); // TODO: Build a set of sound events at server startup, and cache this. var level = Objects.requireNonNull(getPosition().level()); - if (soundEvent != null && level.registryAccess().registry(Registries.JUKEBOX_SONG).orElseThrow().stream().anyMatch(x -> x.soundEvent().value() == soundEvent)) { + if (soundEvent != null && level.registryAccess().lookupOrThrow(Registries.JUKEBOX_SONG).stream().anyMatch(x -> x.soundEvent().value() == soundEvent)) { return false; } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/platform/PlatformHelper.java b/projects/common/src/main/java/dan200/computercraft/shared/platform/PlatformHelper.java index 2892a8c8e..755593cc4 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/platform/PlatformHelper.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/platform/PlatformHelper.java @@ -19,6 +19,7 @@ import net.minecraft.core.Registry; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayerGameMode; @@ -34,7 +35,7 @@ import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -195,10 +196,12 @@ public interface PlatformHelper { /** * Get the amount of fuel an item provides. * - * @param stack The item to burn. + * @param server The current server. + * @param stack The item to burn. * @return The amount of fuel it provides. + * @see MinecraftServer#fuelValues() */ - int getBurnTime(ItemStack stack); + int getBurnTime(MinecraftServer server, ItemStack stack); /** * Create a builder for a new creative tab. @@ -225,7 +228,7 @@ public interface PlatformHelper { * @param container The crafting container. * @return A list of items to return to the player after crafting. */ - List getRecipeRemainingItems(ServerPlayer player, Recipe recipe, CraftingInput container); + List getRecipeRemainingItems(ServerPlayer player, CraftingRecipe recipe, CraftingInput container); /** * Fire an event after crafting has occurred. diff --git a/projects/common/src/main/java/dan200/computercraft/shared/platform/RecipeIngredients.java b/projects/common/src/main/java/dan200/computercraft/shared/platform/RecipeIngredients.java index b35cff0fd..fac69b2b8 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/platform/RecipeIngredients.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/platform/RecipeIngredients.java @@ -4,8 +4,9 @@ package dan200.computercraft.shared.platform; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.Ingredient; /** * Loader-specific recipe ingredients. These may either be tags or items, depending on which mod loader we're using. @@ -22,15 +23,15 @@ import net.minecraft.world.item.crafting.Ingredient; * @param woodenChest All wooden chests (both normal and trapped chests). */ public record RecipeIngredients( - Ingredient redstone, - Ingredient string, - Ingredient leather, - Ingredient glassPane, - Ingredient goldIngot, - Ingredient goldBlock, - Ingredient ironIngot, - Ingredient dye, - Ingredient enderPearl, - Ingredient woodenChest + TagKey redstone, + TagKey string, + TagKey leather, + TagKey glassPane, + TagKey goldIngot, + TagKey goldBlock, + TagKey ironIngot, + TagKey dye, + TagKey enderPearl, + TagKey woodenChest ) { } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/platform/RegistryEntry.java b/projects/common/src/main/java/dan200/computercraft/shared/platform/RegistryEntry.java index d2556bb56..703417607 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/platform/RegistryEntry.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/platform/RegistryEntry.java @@ -37,7 +37,7 @@ public interface RegistryEntry extends Supplier { return ResourceLocation.CODEC.flatXmap( id -> registry - .getHolder(ResourceKey.create(registry.key(), id)) + .get(ResourceKey.create(registry.key(), id)) .map(x -> DataResult.success(new HolderEntry<>(id, x))) .orElseGet(() -> DataResult.error(() -> "Unknown registry key in " + registry.key() + ": " + id)), holder -> DataResult.success(holder.id()) diff --git a/projects/common/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItem.java b/projects/common/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItem.java index a3d9eaecc..6cb7ce342 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItem.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/pocket/items/PocketComputerItem.java @@ -36,7 +36,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; @@ -132,7 +131,7 @@ public class PocketComputerItem extends Item implements IMedia { } @Override - public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { + public InteractionResult use(Level world, Player player, InteractionHand hand) { var stack = player.getItemInHand(hand); if (!world.isClientSide) { var holder = new PocketHolder.PlayerHolder((ServerPlayer) player, InventoryUtil.getHandSlot(player, hand)); @@ -154,12 +153,12 @@ public class PocketComputerItem extends Item implements IMedia { new ComputerContainerData(computer, stack).open(player, new PocketComputerMenuProvider(computer, stack, this, hand, isTypingOnly)); } } - return new InteractionResultHolder<>(InteractionResult.sidedSuccess(world.isClientSide), stack); + return InteractionResult.SUCCESS; } @Override public Component getName(ItemStack stack) { - var baseString = getDescriptionId(stack); + var baseString = getDescriptionId(); var upgrade = getUpgrade(stack); if (upgrade != null) { return Component.translatable(baseString + ".upgraded", upgrade.getAdjective()); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java b/projects/common/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java index 89927be37..2ca44bd31 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java @@ -22,16 +22,6 @@ public final class PocketComputerUpgradeRecipe extends CustomRecipe { super(category); } - @Override - public boolean canCraftInDimensions(int x, int y) { - return x >= 2 && y >= 2; - } - - @Override - public ItemStack getResultItem(HolderLookup.Provider registryAccess) { - return new ItemStack(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get()); - } - @Override public boolean matches(CraftingInput inventory, Level world) { return !assemble(inventory, world.registryAccess()).isEmpty(); @@ -85,7 +75,7 @@ public final class PocketComputerUpgradeRecipe extends CustomRecipe { } @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() { return ModRegistry.RecipeSerializers.POCKET_COMPUTER_UPGRADE.get(); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/recipe/AbstractCraftingRecipe.java b/projects/common/src/main/java/dan200/computercraft/shared/recipe/AbstractCraftingRecipe.java new file mode 100644 index 000000000..2e0167294 --- /dev/null +++ b/projects/common/src/main/java/dan200/computercraft/shared/recipe/AbstractCraftingRecipe.java @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.shared.recipe; + +import net.minecraft.world.item.crafting.CraftingBookCategory; +import net.minecraft.world.item.crafting.CraftingRecipe; + +/** + * An abstract {@link CraftingRecipe} that provides a skeleton implementation. + */ +public abstract class AbstractCraftingRecipe implements CraftingRecipe { + protected final RecipeProperties properties; + + protected AbstractCraftingRecipe(RecipeProperties properties) { + this.properties = properties; + } + + @Override + public final boolean showNotification() { + return properties.showNotification(); + } + + @Override + public final String group() { + return properties.group(); + } + + @Override + public final CraftingBookCategory category() { + return properties.category(); + } +} diff --git a/projects/common/src/main/java/dan200/computercraft/shared/recipe/BasicRecipeSerialiser.java b/projects/common/src/main/java/dan200/computercraft/shared/recipe/BasicRecipeSerialiser.java index b3bda8f9f..95eab7049 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/recipe/BasicRecipeSerialiser.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/recipe/BasicRecipeSerialiser.java @@ -38,4 +38,10 @@ public record BasicRecipeSerialiser>( + ", but was " + RegistryHelper.getKeyOrThrow(BuiltInRegistries.RECIPE_SERIALIZER, recipe.getSerializer()) ); } + + @Override + @Deprecated + public StreamCodec streamCodec() { + return streamCodec; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/recipe/CustomShapelessRecipe.java b/projects/common/src/main/java/dan200/computercraft/shared/recipe/CustomShapelessRecipe.java index b413008d9..c68cd59f0 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/recipe/CustomShapelessRecipe.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/recipe/CustomShapelessRecipe.java @@ -4,32 +4,65 @@ package dan200.computercraft.shared.recipe; +import net.minecraft.core.HolderLookup; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.ShapelessRecipe; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.*; +import net.minecraft.world.item.crafting.display.RecipeDisplay; +import net.minecraft.world.item.crafting.display.ShapelessCraftingRecipeDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplay; +import net.minecraft.world.level.Level; +import javax.annotation.Nullable; +import java.util.List; import java.util.function.Function; /** * A custom version of {@link ShapelessRecipe}, which can be converted to and from a {@link ShapelessRecipeSpec}. */ -public abstract class CustomShapelessRecipe extends ShapelessRecipe { - private final ItemStack result; - private final boolean showNotification; +public abstract class CustomShapelessRecipe extends AbstractCraftingRecipe { + private final ShapelessRecipeSpec spec; + private @Nullable PlacementInfo placementInfo; protected CustomShapelessRecipe(ShapelessRecipeSpec recipe) { - super(recipe.properties().group(), recipe.properties().category(), recipe.result(), recipe.ingredients()); - this.result = recipe.result(); - this.showNotification = recipe.properties().showNotification(); - } - - public final ShapelessRecipeSpec toSpec() { - return new ShapelessRecipeSpec(RecipeProperties.of(this), getIngredients(), result); + super(recipe.properties()); + this.spec = recipe; } @Override - public final boolean showNotification() { - return showNotification; + public PlacementInfo placementInfo() { + if (placementInfo == null) placementInfo = PlacementInfo.create(spec.ingredients()); + return placementInfo; + } + + @Override + public List display() { + return List.of( + new ShapelessCraftingRecipeDisplay( + spec.ingredients().stream().map(Ingredient::display).toList(), + new SlotDisplay.ItemStackSlotDisplay(spec.result()), + new SlotDisplay.ItemSlotDisplay(Items.CRAFTING_TABLE) + ) + ); + } + + @Override + public boolean matches(CraftingInput input, Level level) { + var ingredients = spec.ingredients(); + if (input.ingredientCount() != ingredients.size()) return false; + // Fast-path with a single item - just check the ingredient matches. + if (input.size() == 1 && ingredients.size() == 1) return ingredients.getFirst().test(input.getItem(0)); + // Otherwise check the stacked contents. + return input.stackedContents().canCraft(placementInfo().unpackedIngredients(), null); + } + + @Override + public ItemStack assemble(CraftingInput input, HolderLookup.Provider registries) { + return spec.result().copy(); + } + + protected final ShapelessRecipeSpec toSpec() { + return spec; } @Override diff --git a/projects/common/src/main/java/dan200/computercraft/shared/recipe/RecipeProperties.java b/projects/common/src/main/java/dan200/computercraft/shared/recipe/RecipeProperties.java index 459a34d29..5444b8d4d 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/recipe/RecipeProperties.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/recipe/RecipeProperties.java @@ -16,9 +16,10 @@ import net.minecraft.world.item.crafting.CraftingRecipe; /** * Common properties that appear in all {@link CraftingRecipe}s. * - * @param group The (optional) group of the recipe, see {@link CraftingRecipe#getGroup()}. + * @param group The (optional) group of the recipe, see {@link CraftingRecipe#group()}. * @param category The category the recipe appears in, see {@link CraftingRecipe#category()}. * @param showNotification Show notifications when the recipe is unlocked, see {@link CraftingRecipe#showNotification()}. + * @see AbstractCraftingRecipe */ public record RecipeProperties(String group, CraftingBookCategory category, boolean showNotification) { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( @@ -35,6 +36,6 @@ public record RecipeProperties(String group, CraftingBookCategory category, bool ); public static RecipeProperties of(CraftingRecipe recipe) { - return new RecipeProperties(recipe.getGroup(), recipe.category(), recipe.showNotification()); + return new RecipeProperties(recipe.group(), recipe.category(), recipe.showNotification()); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/recipe/ShapelessRecipeSpec.java b/projects/common/src/main/java/dan200/computercraft/shared/recipe/ShapelessRecipeSpec.java index ebf165556..20604dd29 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/recipe/ShapelessRecipeSpec.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/recipe/ShapelessRecipeSpec.java @@ -5,17 +5,17 @@ package dan200.computercraft.shared.recipe; import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import dan200.computercraft.shared.network.codec.MoreStreamCodecs; -import net.minecraft.core.NonNullList; import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.ShapelessRecipe; +import java.util.List; + /** * A description of a {@link ShapelessRecipe}. *

@@ -26,16 +26,11 @@ import net.minecraft.world.item.crafting.ShapelessRecipe; * @param ingredients The ingredients of the recipe. * @param result The result of the recipe. */ -public record ShapelessRecipeSpec(RecipeProperties properties, NonNullList ingredients, ItemStack result) { +public record ShapelessRecipeSpec(RecipeProperties properties, List ingredients, ItemStack result) { /** * A list of {@link Ingredient}s, usable in a {@linkplain ShapelessRecipe shapeless recipe}. */ - private static final Codec> INGREDIENT_CODEC = Ingredient.CODEC_NONEMPTY.listOf().flatXmap(list -> { - var ingredients = list.stream().filter(ingredient -> !ingredient.isEmpty()).toArray(Ingredient[]::new); - if (ingredients.length == 0) return DataResult.error(() -> "No ingredients for shapeless recipe"); - if (ingredients.length > 9) return DataResult.error(() -> "Too many ingredients for shapeless recipe"); - return DataResult.success(NonNullList.of(Ingredient.EMPTY, ingredients)); - }, DataResult::success); + public static final Codec> INGREDIENT_CODEC = Ingredient.CODEC.listOf(1, 9); public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( RecipeProperties.CODEC.forGetter(ShapelessRecipeSpec::properties), @@ -45,7 +40,7 @@ public record ShapelessRecipeSpec(RecipeProperties properties, NonNullList STREAM_CODEC = StreamCodec.composite( RecipeProperties.STREAM_CODEC, ShapelessRecipeSpec::properties, - MoreStreamCodecs.nonNullList(Ingredient.CONTENTS_STREAM_CODEC, Ingredient.EMPTY), ShapelessRecipeSpec::ingredients, + Ingredient.CONTENTS_STREAM_CODEC.apply(ByteBufCodecs.list()), ShapelessRecipeSpec::ingredients, ItemStack.STREAM_CODEC, ShapelessRecipeSpec::result, ShapelessRecipeSpec::new ); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/recipe/function/CopyComponents.java b/projects/common/src/main/java/dan200/computercraft/shared/recipe/function/CopyComponents.java index 8d7425304..ce2b01908 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/recipe/function/CopyComponents.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/recipe/function/CopyComponents.java @@ -31,7 +31,7 @@ import java.util.Set; */ public final class CopyComponents implements RecipeFunction { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - Ingredient.CODEC_NONEMPTY.fieldOf("from").forGetter(x -> x.from), + Ingredient.CODEC.fieldOf("from").forGetter(x -> x.from), DataComponentType.CODEC.listOf().optionalFieldOf("include").forGetter(x -> x.include), DataComponentType.CODEC.listOf().optionalFieldOf("exclude").forGetter(x -> x.exclude) ).apply(instance, CopyComponents::new)); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java index 6a5abe38e..a1119f075 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java @@ -7,6 +7,8 @@ package dan200.computercraft.shared.turtle; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleRefuelHandler; import dan200.computercraft.shared.platform.PlatformHelper; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import java.util.OptionalInt; @@ -14,7 +16,7 @@ import java.util.OptionalInt; public final class FurnaceRefuelHandler implements TurtleRefuelHandler { @Override public OptionalInt refuel(ITurtleAccess turtle, ItemStack currentStack, int slot, int limit) { - var fuelPerItem = getFuelPerItem(currentStack); + var fuelPerItem = getFuelPerItem(((ServerLevel) turtle.getLevel()).getServer(), currentStack); if (fuelPerItem <= 0) return OptionalInt.empty(); if (limit == 0) return OptionalInt.of(0); @@ -33,7 +35,7 @@ public final class FurnaceRefuelHandler implements TurtleRefuelHandler { return OptionalInt.of(fuelToGive); } - private static int getFuelPerItem(ItemStack stack) { - return (PlatformHelper.get().getBurnTime(stack) * 5) / 100; + private static int getFuelPerItem(MinecraftServer server, ItemStack stack) { + return (PlatformHelper.get().getBurnTime(server, stack) * 5) / 100; } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlock.java index f879fe3dd..17d33391f 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlock.java @@ -16,19 +16,17 @@ import dan200.computercraft.shared.util.WaterloggableHelpers; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.component.DataComponents; +import net.minecraft.util.RandomSource; import net.minecraft.world.Containers; import net.minecraft.world.InteractionHand; -import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.*; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.SimpleWaterloggedBlock; @@ -38,7 +36,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; @@ -57,7 +55,7 @@ public class TurtleBlock extends AbstractComputerBlock implem BlockCodecs.blockEntityCodec(x -> x.type) ).apply(instance, TurtleBlock::new)); - public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + public static final EnumProperty FACING = BlockStateProperties.HORIZONTAL_FACING; /** * The explosion resistance to use when a turtle is "immune" to explosions. @@ -120,9 +118,9 @@ public class TurtleBlock extends AbstractComputerBlock implem } @Override - protected BlockState updateShape(BlockState state, Direction side, BlockState otherState, LevelAccessor world, BlockPos pos, BlockPos otherPos) { - WaterloggableHelpers.updateShape(state, world, pos); - return state; + protected BlockState updateShape(BlockState state, LevelReader level, ScheduledTickAccess ticker, BlockPos pos, Direction side, BlockPos otherPos, BlockState neighborState, RandomSource randomSource) { + WaterloggableHelpers.updateShape(state, level, ticker, pos); + return super.updateShape(state, level, ticker, pos, side, otherPos, neighborState, randomSource); } @Override @@ -150,14 +148,14 @@ public class TurtleBlock extends AbstractComputerBlock implem } @Override - protected ItemInteractionResult useItemOn(ItemStack currentItem, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { + protected InteractionResult useItemOn(ItemStack currentItem, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { if (currentItem.getItem() == Items.NAME_TAG && currentItem.has(DataComponents.CUSTOM_NAME) && level.getBlockEntity(pos) instanceof AbstractComputerBlockEntity computer) { // Label to rename computer if (!level.isClientSide) { computer.setLabel(currentItem.getHoverName().getString()); currentItem.shrink(1); } - return ItemInteractionResult.sidedSuccess(level.isClientSide); + return InteractionResult.SUCCESS; } return super.useItemOn(currentItem, state, level, pos, player, hand, hit); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java index 0b73f436e..0c6e2c100 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java @@ -17,7 +17,7 @@ import dan200.computercraft.shared.turtle.blocks.TurtleBlock; import net.minecraft.core.cauldron.CauldronInteraction; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; -import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.LayeredCauldronBlock; @@ -30,7 +30,7 @@ public class TurtleItem extends AbstractComputerItem { @Override public Component getName(ItemStack stack) { - var baseString = getDescriptionId(stack); + var baseString = descriptionId; var left = getUpgrade(stack, TurtleSide.LEFT); var right = getUpgrade(stack, TurtleSide.RIGHT); if (left != null && right != null) { @@ -85,12 +85,12 @@ public class TurtleItem extends AbstractComputerItem { } public static final CauldronInteraction CAULDRON_INTERACTION = (blockState, level, pos, player, hand, stack) -> { - if (!stack.has(DataComponents.DYED_COLOR)) return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + if (!stack.has(DataComponents.DYED_COLOR)) return InteractionResult.TRY_WITH_EMPTY_HAND; if (!level.isClientSide) { stack.remove(DataComponents.DYED_COLOR); LayeredCauldronBlock.lowerFillLevel(blockState, level, pos); } - return ItemInteractionResult.sidedSuccess(level.isClientSide); + return InteractionResult.SUCCESS; }; } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java index 095bb29b6..5e137f72f 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java @@ -23,16 +23,6 @@ public final class TurtleUpgradeRecipe extends CustomRecipe { super(category); } - @Override - public boolean canCraftInDimensions(int x, int y) { - return x >= 3 && y >= 1; - } - - @Override - public ItemStack getResultItem(HolderLookup.Provider registryAccess) { - return new ItemStack(ModRegistry.Items.TURTLE_NORMAL.get()); - } - @Override public boolean matches(CraftingInput inventory, Level world) { return !assemble(inventory, world.registryAccess()).isEmpty(); @@ -126,7 +116,7 @@ public final class TurtleUpgradeRecipe extends CustomRecipe { } @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() { return ModRegistry.RecipeSerializers.TURTLE_UPGRADE.get(); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java index 1e66b71af..dad336fe0 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java @@ -12,9 +12,8 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Container; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.level.Level; import javax.annotation.Nullable; import java.util.AbstractList; @@ -29,7 +28,7 @@ public final class TurtleInventoryCrafting { private TurtleInventoryCrafting() { } - private static @Nullable FoundRecipe tryCrafting(Level level, Container inventory, int xStart, int yStart) { + private static @Nullable FoundRecipe tryCrafting(ServerLevel level, Container inventory, int xStart, int yStart) { // Check the non-relevant parts of the inventory are empty for (var x = 0; x < TurtleBlockEntity.INVENTORY_WIDTH; x++) { for (var y = 0; y < TurtleBlockEntity.INVENTORY_HEIGHT; y++) { @@ -56,14 +55,13 @@ public final class TurtleInventoryCrafting { return WIDTH * HEIGHT; } }); - var recipe = level.getRecipeManager().getRecipeFor(RecipeType.CRAFTING, input.input(), level).orElse(null); + var recipe = level.recipeAccess().getRecipeFor(RecipeType.CRAFTING, input.input(), level).orElse(null); return recipe == null ? null : new FoundRecipe(recipe.value(), input.input(), input.left() + xStart, input.top() + yStart); } @Nullable public static List craft(ITurtleAccess turtle, int maxCount) { - var level = turtle.getLevel(); - if (level.isClientSide || !(level instanceof ServerLevel)) return null; + if (!(turtle.getLevel() instanceof ServerLevel level)) return null; var inventory = turtle.getInventory(); @@ -124,6 +122,6 @@ public final class TurtleInventoryCrafting { return Collections.unmodifiableList(results); } - private record FoundRecipe(Recipe recipe, CraftingInput input, int xStart, int yStart) { + private record FoundRecipe(CraftingRecipe recipe, CraftingInput input, int xStart, int yStart) { } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java index afac649d5..af6043722 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java @@ -228,10 +228,10 @@ 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.hurt(source, damage)) return false; + if (!entity.hurtServer(player.serverLevel(), source, damage)) return false; // Special case for armor stands: attack twice to guarantee destroy - if (entity.isAlive() && entity instanceof ArmorStand) entity.hurt(source, damage); + if (entity.isAlive() && entity instanceof ArmorStand) entity.hurtServer(player.serverLevel(), source, damage); // Apply knockback var knockBack = EnchantmentHelper.modifyKnockback(player.serverLevel(), tool, entity, source, (float) player.getAttributeValue(Attributes.ATTACK_KNOCKBACK)); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/ArgumentHelpers.java b/projects/common/src/main/java/dan200/computercraft/shared/util/ArgumentHelpers.java index f4c4fb257..fce4b32a2 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/ArgumentHelpers.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/ArgumentHelpers.java @@ -28,7 +28,7 @@ public final class ArgumentHelpers { } T value; - if (id == null || (value = registry.get(id)) == null) { + if (id == null || (value = registry.getValue(id)) == null) { throw new LuaException(String.format("Unknown %s '%s'", typeName, name)); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/ColourUtils.java b/projects/common/src/main/java/dan200/computercraft/shared/util/ColourUtils.java index 8f66a6a0a..cdc607b82 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/ColourUtils.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/ColourUtils.java @@ -14,7 +14,7 @@ import javax.annotation.Nullable; import java.util.List; public final class ColourUtils { - private static final List> DYES = PlatformHelper.get().getDyeTags(); + public static final List> DYES = PlatformHelper.get().getDyeTags(); private ColourUtils() { } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/ComponentizationFixers.java b/projects/common/src/main/java/dan200/computercraft/shared/util/ComponentizationFixers.java index 83baa9868..b0560e4ab 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/ComponentizationFixers.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/ComponentizationFixers.java @@ -8,7 +8,6 @@ import com.mojang.datafixers.DSL; import com.mojang.datafixers.Typed; import com.mojang.datafixers.schemas.Schema; import com.mojang.datafixers.types.templates.TypeTemplate; -import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Dynamic; import com.mojang.serialization.OptionalDynamic; import dan200.computercraft.api.upgrades.UpgradeData; @@ -19,10 +18,11 @@ import net.minecraft.util.datafix.fixes.ItemStackComponentizationFix; import net.minecraft.util.datafix.fixes.References; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -207,31 +207,19 @@ public class ComponentizationFixers { /** * Add our custom data components to the datafixer system. * - * @param type The existing component type definition. + * @param types The component type definition. * @param schema The current schema. - * @return The new component type definition. * @see UpgradeManager#upgradeDataCodec() * @see ModRegistry.DataComponents#POCKET_UPGRADE * @see ModRegistry.DataComponents#LEFT_TURTLE_UPGRADE * @see ModRegistry.DataComponents#RIGHT_TURTLE_UPGRADE */ - public static TypeTemplate addExtraTypes(TypeTemplate type, Schema schema) { + public static void addExtraTypes(Map> types, Schema schema) { // Create a codec for UpgradeData - var upgradeData = DSL.optionalFields("components", References.DATA_COMPONENTS.in(schema)); + Supplier upgradeData = () -> DSL.optionalFields("components", References.DATA_COMPONENTS.in(schema)); - return extraOptionalFields(type, - Pair.of("computercraft:pocket_upgrade", upgradeData), - Pair.of("computercraft:left_turtle_upgrade", upgradeData), - Pair.of("computercraft:right_turtle_upgrade", upgradeData) - ); - } - - @SafeVarargs - @SuppressWarnings("varargs") - private static TypeTemplate extraOptionalFields(TypeTemplate base, Pair... fields) { - return DSL.and(Stream.concat( - Arrays.stream(fields).map(entry -> DSL.optional(DSL.field(entry.getFirst(), entry.getSecond()))), - Stream.of(base) - ).toList()); + types.put("computercraft:pocket_upgrade", upgradeData); + types.put("computercraft:left_turtle_upgrade", upgradeData); + types.put("computercraft:right_turtle_upgrade", upgradeData); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java b/projects/common/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java index 457fb444b..6a55e344c 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java @@ -12,6 +12,7 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.DiodeBlock; import net.minecraft.world.level.block.RedStoneWireBlock; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.redstone.ExperimentalRedstoneUtils; public final class RedstoneUtil { private RedstoneUtil() { @@ -49,7 +50,8 @@ public final class RedstoneUtil { if (!PlatformHelper.get().onNotifyNeighbour(world, pos, block, side)) return; var neighbourPos = pos.relative(side); - world.neighborChanged(neighbourPos, block.getBlock(), pos); + var orientation = ExperimentalRedstoneUtils.initialOrientation(world, side, Direction.UP); + world.neighborChanged(neighbourPos, block.getBlock(), orientation); // We intentionally use updateNeighborsAt here instead of updateNeighborsAtExceptFromFacing, as computers can // both send and receive redstone, and so also need to be updated. world.updateNeighborsAt(neighbourPos, block.getBlock()); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/RegistryHelper.java b/projects/common/src/main/java/dan200/computercraft/shared/util/RegistryHelper.java index 9d07a63e3..902c47d45 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/RegistryHelper.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/RegistryHelper.java @@ -27,7 +27,7 @@ public final class RegistryHelper { */ @SuppressWarnings("unchecked") public static Registry getRegistry(ResourceKey> id) { - var registry = (Registry) BuiltInRegistries.REGISTRY.get(id.location()); + var registry = (Registry) BuiltInRegistries.REGISTRY.getValue(id.location()); if (registry == null) throw new IllegalArgumentException("Unknown registry " + id); return registry; } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java b/projects/common/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java index eb2fd652f..05a3308d8 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java @@ -6,8 +6,10 @@ package dan200.computercraft.shared.util; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.ScheduledTickAccess; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BooleanProperty; @@ -34,15 +36,16 @@ public final class WaterloggableHelpers { } /** - * Call from {@link net.minecraft.world.level.block.Block#updateShape(BlockState, Direction, BlockState, LevelAccessor, BlockPos, BlockPos)}. + * Call from {@link net.minecraft.world.level.block.Block#updateShape(BlockState, LevelReader, ScheduledTickAccess, BlockPos, Direction, BlockPos, BlockState, RandomSource)}. * - * @param state The current state - * @param world The position of this block - * @param pos The world this block exists in + * @param state The current state + * @param level The position of this block + * @param ticker The ticker to schedule with. + * @param pos The world this block exists in */ - public static void updateShape(BlockState state, LevelAccessor world, BlockPos pos) { + public static void updateShape(BlockState state, LevelReader level, ScheduledTickAccess ticker, BlockPos pos) { if (state.getValue(WATERLOGGED)) { - world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + ticker.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); } } diff --git a/projects/common/src/main/resources/assets/computercraft/models/block/computer_on.json b/projects/common/src/main/resources/assets/computercraft/models/block/computer_on.json index a8518a768..238226997 100644 --- a/projects/common/src/main/resources/assets/computercraft/models/block/computer_on.json +++ b/projects/common/src/main/resources/assets/computercraft/models/block/computer_on.json @@ -1,7 +1,6 @@ { "parent": "minecraft:block/orientable", "render_type": "cutout", - "computercraft:emissive_texture": "cursor", "elements": [ { "from": [ 0, 0, 0 ], @@ -18,11 +17,11 @@ { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], + "light_emission": 15, "faces": { "north": { "texture": "#cursor", - "cullface": "north", - "neoforge_data": {"block_light": 15, "sky_light": 15} + "cullface": "north" } } } diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/border_advanced.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/border_advanced.png index 06394a48f..324503f7a 100644 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/border_advanced.png and b/projects/common/src/main/resources/assets/computercraft/textures/gui/border_advanced.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/border_colour.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/border_colour.png index 46a9a413c..5f53ff3ac 100644 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/border_colour.png and b/projects/common/src/main/resources/assets/computercraft/textures/gui/border_colour.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/border_command.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/border_command.png index 7060910d7..24a64f74f 100644 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/border_command.png and b/projects/common/src/main/resources/assets/computercraft/textures/gui/border_command.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/border_normal.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/border_normal.png index 7c47d250b..eb9b946e1 100644 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/border_normal.png and b/projects/common/src/main/resources/assets/computercraft/textures/gui/border_normal.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/terminate.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/terminate.png deleted file mode 100644 index b49ee2167..000000000 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/terminate.png and /dev/null differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/terminate_hover.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/terminate_hover.png deleted file mode 100644 index c14a27806..000000000 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/terminate_hover.png and /dev/null differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_off.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_off.png deleted file mode 100644 index bb556653e..000000000 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_off.png and /dev/null differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_off_hover.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_off_hover.png deleted file mode 100644 index 996d415a9..000000000 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_off_hover.png and /dev/null differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_advanced.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_advanced.png index fb8909c9c..b9ab35495 100644 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_advanced.png and b/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_advanced.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_colour.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_colour.png index 973339db4..6ab15cab1 100644 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_colour.png and b/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_colour.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_normal.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_normal.png index 0699e8a18..8b0233501 100644 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_normal.png and b/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_normal.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/sidebar_advanced.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sidebar_advanced.png index 8d96a99c8..a7f83eeea 100644 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/sidebar_advanced.png and b/projects/common/src/main/resources/assets/computercraft/textures/gui/sidebar_advanced.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/sidebar_normal.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sidebar_normal.png index 495c031a0..2e6f469de 100644 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/sidebar_normal.png and b/projects/common/src/main/resources/assets/computercraft/textures/gui/sidebar_normal.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/terminate.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/terminate.png new file mode 100644 index 000000000..c122e6fbb Binary files /dev/null and b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/terminate.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/terminate_hover.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/terminate_hover.png new file mode 100644 index 000000000..79f491e0a Binary files /dev/null and b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/terminate_hover.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_off.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_off.png new file mode 100644 index 000000000..76b3f369c Binary files /dev/null and b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_off.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_off_hover.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_off_hover.png new file mode 100644 index 000000000..1565d191d Binary files /dev/null and b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_off_hover.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_on.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_on.png similarity index 100% rename from projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_on.png rename to projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_on.png diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_on_hover.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_on_hover.png similarity index 100% rename from projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_on_hover.png rename to projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_on_hover.png diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/turtle_advanced_selected_slot.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/turtle_advanced_selected_slot.png new file mode 100644 index 000000000..1550ea4c6 Binary files /dev/null and b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/turtle_advanced_selected_slot.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/turtle_normal_selected_slot.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/turtle_normal_selected_slot.png new file mode 100644 index 000000000..bdf51ef11 Binary files /dev/null and b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/turtle_normal_selected_slot.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/turtle_advanced.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/turtle_advanced.png index 8f7d66500..e6deec51a 100644 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/turtle_advanced.png and b/projects/common/src/main/resources/assets/computercraft/textures/gui/turtle_advanced.png differ diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/turtle_normal.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/turtle_normal.png index f676c56b2..9426aa220 100644 Binary files a/projects/common/src/main/resources/assets/computercraft/textures/gui/turtle_normal.png and b/projects/common/src/main/resources/assets/computercraft/textures/gui/turtle_normal.png differ diff --git a/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.fsh b/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.fsh deleted file mode 100644 index 85e91499b..000000000 --- a/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.fsh +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -#version 150 - -#moj_import - -#define FONT_WIDTH 6.0 -#define FONT_HEIGHT 9.0 - -uniform sampler2D Sampler0; // Font -uniform usamplerBuffer Tbo; - -layout(std140) uniform MonitorData { - vec3 Palette[16]; - int Width; - int Height; - ivec2 CursorPos; - int CursorColour; -}; -uniform int CursorBlink; - -uniform vec4 ColorModulator; -uniform float FogStart; -uniform float FogEnd; -uniform vec4 FogColor; - -in float vertexDistance; -in vec2 fontPos; - -out vec4 fragColor; - -vec2 texture_corner(int index) { - float x = 1.0 + float(index % 16) * (FONT_WIDTH + 2.0); - float y = 1.0 + float(index / 16) * (FONT_HEIGHT + 2.0); - return vec2(x, y); -} - -vec4 recolour(vec4 texture, int colour) { - return vec4(texture.rgb * Palette[colour], texture.rgba); -} - -void main() { - vec2 term_pos = vec2(fontPos.x / FONT_WIDTH, fontPos.y / FONT_HEIGHT); - vec2 corner = floor(term_pos); - - ivec2 cell = ivec2(corner); - int index = 3 * (clamp(cell.x, 0, Width - 1) + clamp(cell.y, 0, Height - 1) * Width); - - // 1 if 0 <= x, y < Width, Height, 0 otherwise - vec2 outside = step(vec2(0.0, 0.0), vec2(cell)) * step(vec2(cell), vec2(float(Width) - 1.0, float(Height) - 1.0)); - float mult = outside.x * outside.y; - - int character = int(texelFetch(Tbo, index).r); - int fg = int(texelFetch(Tbo, index + 1).r); - int bg = int(texelFetch(Tbo, index + 2).r); - - vec2 pos = (term_pos - corner) * vec2(FONT_WIDTH, FONT_HEIGHT); - vec4 charTex = recolour(texture(Sampler0, (texture_corner(character) + pos) / 256.0), fg); - - // Applies the cursor on top of the current character if we're blinking and in the current cursor's cell. We do it - // this funky way to avoid branches. - vec4 cursorTex = recolour(texture(Sampler0, (texture_corner(95) + pos) / 256.0), CursorColour); // 95 = '_' - vec4 img = mix(charTex, cursorTex, cursorTex.a * float(CursorBlink) * (CursorPos == cell ? 1.0 : 0.0)); - - vec4 colour = vec4(mix(Palette[bg], img.rgb, img.a * mult), 1.0) * ColorModulator; - - fragColor = linear_fog(colour, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.json b/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.json deleted file mode 100644 index e29e42e1e..000000000 --- a/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "vertex": "computercraft/monitor_tbo", - "fragment": "computercraft/monitor_tbo", - "attributes": [ "Position" ], - "samplers": [ { "name": "Sampler0" } ], - "uniforms": [ - { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] }, - - { "name": "Tbo", "type": "int", "count": 1, "values": [ 3 ] }, - { "name": "CursorBlink", "type": "int", "count": 1, "values": [ 0 ] } - ] -} diff --git a/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.vsh b/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.vsh deleted file mode 100644 index 681f36cc3..000000000 --- a/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.vsh +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -#version 150 - -#moj_import - -in vec3 Position; -in vec2 UV0; - -uniform mat4 ModelViewMat; -uniform mat4 ProjMat; -uniform vec3 ChunkOffset; -uniform int FogShape; - -out float vertexDistance; -out vec2 fontPos; - -void main() { - vec3 pos = Position + ChunkOffset; - gl_Position = ProjMat * ModelViewMat * vec4(pos, 1.0); - - vertexDistance = fog_distance(pos, FogShape); - fontPos = UV0; -} diff --git a/projects/common/src/main/resources/computercraft-common.accesswidener b/projects/common/src/main/resources/computercraft-common.accesswidener index a0ffacef9..7ce5c025d 100644 --- a/projects/common/src/main/resources/computercraft-common.accesswidener +++ b/projects/common/src/main/resources/computercraft-common.accesswidener @@ -7,8 +7,6 @@ accessWidener v1 named # Additional access wideners for vanilla code. This is a effectively the subset of Fabric's transitive access wideners # that we actually use -accessible class net/minecraft/world/level/block/entity/BlockEntityType$BlockEntitySupplier - accessible method net/minecraft/client/renderer/blockentity/BlockEntityRenderers register (Lnet/minecraft/world/level/block/entity/BlockEntityType;Lnet/minecraft/client/renderer/blockentity/BlockEntityRendererProvider;)V accessible class net/minecraft/world/item/CreativeModeTab$Output accessible field net/minecraft/world/item/CreativeModeTabs OP_BLOCKS Lnet/minecraft/resources/ResourceKey; @@ -30,3 +28,4 @@ accessible field net/minecraft/data/models/ItemModelGenerators output Ljava/util accessible method net/minecraft/data/models/ItemModelGenerators generateFlatItem (Lnet/minecraft/world/item/Item;Lnet/minecraft/data/models/model/ModelTemplate;)V accessible method net/minecraft/data/models/ItemModelGenerators generateFlatItem (Lnet/minecraft/world/item/Item;Ljava/lang/String;Lnet/minecraft/data/models/model/ModelTemplate;)V accessible method net/minecraft/data/models/model/TextureSlot create (Ljava/lang/String;)Lnet/minecraft/data/models/model/TextureSlot; +accessible method net/minecraft/data/recipes/RecipeProvider inventoryTrigger ([Lnet/minecraft/advancements/critereon/ItemPredicate;)Lnet/minecraft/advancements/Criterion; diff --git a/projects/common/src/main/resources/computercraft.accesswidener b/projects/common/src/main/resources/computercraft.accesswidener index 081b21533..704b863c9 100644 --- a/projects/common/src/main/resources/computercraft.accesswidener +++ b/projects/common/src/main/resources/computercraft.accesswidener @@ -7,16 +7,14 @@ accessWidener v1 named # Shared vanilla and Fabric access wideners. This should not include things already exposed by Fabric's transitive # wideners. +accessible class net/minecraft/world/level/block/entity/BlockEntityType$BlockEntitySupplier +accessible method net/minecraft/world/level/block/entity/BlockEntityType (Lnet/minecraft/world/level/block/entity/BlockEntityType$BlockEntitySupplier;Ljava/util/Set;)V + accessible method net/minecraft/client/renderer/RenderType create (Ljava/lang/String;Lcom/mojang/blaze3d/vertex/VertexFormat;Lcom/mojang/blaze3d/vertex/VertexFormat$Mode;IZZLnet/minecraft/client/renderer/RenderType$CompositeState;)Lnet/minecraft/client/renderer/RenderType$CompositeRenderType; accessible method net/minecraft/world/level/storage/LevelResource (Ljava/lang/String;)V # DirectVertexBuffer -accessible field com/mojang/blaze3d/vertex/VertexBuffer vertexBufferId I -accessible field com/mojang/blaze3d/vertex/VertexBuffer indexType Lcom/mojang/blaze3d/vertex/VertexFormat$IndexType; accessible field com/mojang/blaze3d/vertex/VertexBuffer indexCount I -accessible field com/mojang/blaze3d/vertex/VertexBuffer mode Lcom/mojang/blaze3d/vertex/VertexFormat$Mode; -accessible field com/mojang/blaze3d/vertex/VertexBuffer sequentialIndices Lcom/mojang/blaze3d/systems/RenderSystem$AutoStorageIndexBuffer; -accessible field com/mojang/blaze3d/vertex/VertexBuffer format Lcom/mojang/blaze3d/vertex/VertexFormat; # ClientTableFormatter accessible field net/minecraft/client/gui/components/ChatComponent allMessages Ljava/util/List; @@ -31,6 +29,4 @@ accessible method com/mojang/blaze3d/audio/Channel pumpBuffers (I)V accessible field net/minecraft/client/sounds/SoundEngine executor Lnet/minecraft/client/sounds/SoundEngineExecutor; # Turtle model -accessible method net/minecraft/client/renderer/block/model/ItemOverrides ()V - accessible class net/minecraft/util/datafix/fixes/ItemStackComponentizationFix$ItemStackData diff --git a/projects/common/src/main/resources/computercraft.mixins.json b/projects/common/src/main/resources/computercraft.mixins.json index 84cd67612..4118cfb5a 100644 --- a/projects/common/src/main/resources/computercraft.mixins.json +++ b/projects/common/src/main/resources/computercraft.mixins.json @@ -8,6 +8,7 @@ }, "mixins": [ "ItemStackComponentizationFixMixin", - "V1460Mixin" + "V1460Mixin", + "V3818_3Mixin" ] } diff --git a/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java b/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java index fae335b78..9c30345ec 100644 --- a/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java +++ b/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java @@ -21,6 +21,7 @@ import net.minecraft.core.Registry; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.TagKey; @@ -35,7 +36,7 @@ import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -115,13 +116,13 @@ public class TestPlatformHelper extends AbstractComputerCraftAPI implements Plat } @Override - public int getBurnTime(ItemStack stack) { + public int getBurnTime(MinecraftServer server, ItemStack stack) { throw new UnsupportedOperationException("Cannot get burn time inside tests"); } @Override public ItemStack getCraftingRemainingItem(ItemStack stack) { - return new ItemStack(stack.getItem().getCraftingRemainingItem()); + return stack.getItem().getCraftingRemainder(); } @Override @@ -161,7 +162,7 @@ public class TestPlatformHelper extends AbstractComputerCraftAPI implements Plat } @Override - public List getRecipeRemainingItems(ServerPlayer player, Recipe recipe, CraftingInput container) { + public List getRecipeRemainingItems(ServerPlayer player, CraftingRecipe recipe, CraftingInput container) { throw new UnsupportedOperationException("Cannot query recipes inside tests"); } diff --git a/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java b/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java index 43b2b80a9..d223f1a00 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java +++ b/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java @@ -24,8 +24,9 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.item.crafting.ShapedRecipe; -import net.minecraft.world.item.crafting.ShapelessRecipe; +import net.minecraft.world.item.crafting.display.ShapedCraftingRecipeDisplay; +import net.minecraft.world.item.crafting.display.ShapelessCraftingRecipeDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplay; import java.io.File; import java.io.IOException; @@ -83,34 +84,36 @@ public class Exporter { } // Now find all CC recipes. - var level = Objects.requireNonNull(Minecraft.getInstance().level); - for (var recipe : level.getRecipeManager().getAllRecipesFor(RecipeType.CRAFTING)) { - var result = recipe.value().getResultItem(level.registryAccess()); - if (!RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, result.getItem()).getNamespace().equals(ComputerCraftAPI.MOD_ID)) { - continue; - } + var server = Objects.requireNonNull(Minecraft.getInstance().getSingleplayerServer()); + for (var recipe : server.getRecipeManager().getRecipes()) { + if (recipe.value().getType() != RecipeType.CRAFTING) continue; + if (!recipe.id().location().getNamespace().equals(ComputerCraftAPI.MOD_ID)) continue; + + var displayInfos = recipe.value().display(); + if (displayInfos.isEmpty()) continue; + var displayInfo = displayInfos.getFirst(); + + var result = ((SlotDisplay.ItemStackSlotDisplay) displayInfo.result()).stack(); if (!result.getComponentsPatch().isEmpty()) { TestHooks.LOG.warn("Skipping recipe {} as it has NBT", recipe.id()); continue; } - if (recipe.value() instanceof ShapedRecipe shaped) { + if (displayInfo instanceof ShapedCraftingRecipeDisplay shaped) { var converted = new JsonDump.Recipe(result); - for (var x = 0; x < shaped.getWidth(); x++) { - for (var y = 0; y < shaped.getHeight(); y++) { - var ingredient = shaped.getIngredients().get(x + y * shaped.getWidth()); - if (ingredient.isEmpty()) continue; - + for (var x = 0; x < shaped.width(); x++) { + for (var y = 0; y < shaped.height(); y++) { + var ingredient = shaped.ingredients().get(x + y * shaped.width()); converted.setInput(x + y * 3, ingredient, items); } } dump.recipes.put(recipe.id().toString(), converted); - } else if (recipe.value() instanceof ShapelessRecipe shapeless) { + } else if (displayInfo instanceof ShapelessCraftingRecipeDisplay shapeless) { var converted = new JsonDump.Recipe(result); - var ingredients = shapeless.getIngredients(); + var ingredients = shapeless.ingredients(); for (var i = 0; i < ingredients.size(); i++) { converted.setInput(i, ingredients.get(i), items); } diff --git a/projects/common/src/testMod/java/dan200/computercraft/export/ImageRenderer.java b/projects/common/src/testMod/java/dan200/computercraft/export/ImageRenderer.java index 0212ec0f5..995709f01 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/export/ImageRenderer.java +++ b/projects/common/src/testMod/java/dan200/computercraft/export/ImageRenderer.java @@ -4,12 +4,10 @@ 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 com.mojang.blaze3d.vertex.VertexSorting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.FogRenderer; import org.joml.Matrix4f; import org.lwjgl.opengl.GL12; @@ -25,39 +23,38 @@ public class ImageRenderer implements AutoCloseable { public static final int WIDTH = 64; public static final int HEIGHT = 64; - private final TextureTarget framebuffer = new TextureTarget(WIDTH, HEIGHT, true, Minecraft.ON_OSX); - private final NativeImage image = new NativeImage(WIDTH, HEIGHT, Minecraft.ON_OSX); + private final TextureTarget framebuffer = new TextureTarget(WIDTH, HEIGHT, true); + private final NativeImage image = new NativeImage(WIDTH, HEIGHT, true); private @Nullable Matrix4f projectionMatrix; public ImageRenderer() { framebuffer.setClearColor(0, 0, 0, 0); - framebuffer.clear(Minecraft.ON_OSX); + framebuffer.clear(); } public void setupState() { - projectionMatrix = RenderSystem.getProjectionMatrix(); - RenderSystem.setProjectionMatrix(new Matrix4f().identity().ortho(0, 16, 0, 16, 1000, 3000), VertexSorting.DISTANCE_TO_ORIGIN); + RenderSystem.backupProjectionMatrix(); + RenderSystem.setProjectionMatrix(new Matrix4f().identity().ortho(0, 16, 0, 16, 1000, 3000), ProjectionType.ORTHOGRAPHIC); var transform = RenderSystem.getModelViewStack(); transform.pushMatrix(); transform.identity(); transform.translate(0.0f, 0.0f, -2000.0f); - FogRenderer.setupNoFog(); + // FIXME: FogRenderer.toggleFog() } public void clearState() { if (projectionMatrix == null) throw new IllegalStateException("Not currently rendering"); - RenderSystem.setProjectionMatrix(projectionMatrix, VertexSorting.DISTANCE_TO_ORIGIN); - RenderSystem.getModelViewStack().popMatrix(); + RenderSystem.restoreProjectionMatrix(); } public void captureRender(Path output, Runnable render) throws IOException { Files.createDirectories(output.getParent()); framebuffer.bindWrite(true); - RenderSystem.clear(GL12.GL_COLOR_BUFFER_BIT | GL12.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX); + RenderSystem.clear(GL12.GL_COLOR_BUFFER_BIT | GL12.GL_DEPTH_BUFFER_BIT); render.run(); framebuffer.unbindWrite(); diff --git a/projects/common/src/testMod/java/dan200/computercraft/export/JsonDump.java b/projects/common/src/testMod/java/dan200/computercraft/export/JsonDump.java index fcad316ab..c773a4906 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/export/JsonDump.java +++ b/projects/common/src/testMod/java/dan200/computercraft/export/JsonDump.java @@ -6,10 +6,12 @@ package dan200.computercraft.export; import dan200.computercraft.shared.util.RegistryHelper; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.util.context.ContextMap; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.display.SlotDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplayContext; import java.util.Arrays; import java.util.Map; @@ -30,10 +32,10 @@ public class JsonDump { count = output.getCount(); } - public void setInput(int pos, Ingredient ingredient, Set trackedItems) { - if (ingredient.isEmpty()) return; + public void setInput(int pos, SlotDisplay ingredient, Set trackedItems) { + if (ingredient instanceof SlotDisplay.Empty) return; - var items = ingredient.getItems(); + var items = ingredient.resolveForStacks(new ContextMap.Builder().create(SlotDisplayContext.CONTEXT)); // First try to simplify some tags to something easier. for (var stack : items) { @@ -45,9 +47,9 @@ public class JsonDump { return; } - var itemIds = new String[items.length]; - for (var i = 0; i < items.length; i++) { - var item = items[i].getItem(); + var itemIds = new String[items.size()]; + for (var i = 0; i < items.size(); i++) { + var item = items.get(i).getItem(); trackedItems.add(item); itemIds[i] = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, item).toString(); } diff --git a/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java b/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java index 3b44cedb4..05672d002 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java +++ b/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java @@ -17,8 +17,8 @@ import net.minecraft.gametest.framework.StructureUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.StructureBlockEntity; import net.minecraft.world.level.storage.LevelResource; @@ -27,7 +27,6 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Path; -import static dan200.computercraft.core.util.Nullability.assertNonNull; import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.choice; import static net.minecraft.commands.Commands.literal; @@ -69,19 +68,19 @@ class CCTestCommand { var info = GameTestRegistry.getTestFunction(structureBlock.getMetaData()); // Kill the existing armor stand - player - .serverLevel().getEntities(EntityType.ARMOR_STAND, x -> x.isAlive() && x.getName().getString().equals(info.testName())) - .forEach(Entity::kill); + var level = player.serverLevel(); + level.getEntities(EntityType.ARMOR_STAND, x -> x.isAlive() && x.getName().getString().equals(info.testName())) + .forEach(e -> e.kill(level)); // And create a new one var nbt = new CompoundTag(); nbt.putBoolean("Marker", true); nbt.putBoolean("Invisible", true); - var armorStand = assertNonNull(EntityType.ARMOR_STAND.create(player.level())); + var armorStand = new ArmorStand(EntityType.ARMOR_STAND, level); armorStand.readAdditionalSaveData(nbt); armorStand.copyPosition(player); armorStand.setCustomName(Component.literal(info.testName())); - player.level().addFreshEntity(armorStand); + level.addFreshEntity(armorStand); return 0; })) diff --git a/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/GameTestServerMixin.java b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/GameTestServerMixin.java new file mode 100644 index 000000000..7efa7e960 --- /dev/null +++ b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/GameTestServerMixin.java @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.mixin.gametest; + +import com.mojang.datafixers.DataFixer; +import net.minecraft.gametest.framework.GameTestServer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.Services; +import net.minecraft.server.WorldStem; +import net.minecraft.server.level.progress.ChunkProgressListenerFactory; +import net.minecraft.server.packs.repository.PackRepository; +import net.minecraft.world.level.storage.LevelStorageSource; +import org.spongepowered.asm.mixin.Mixin; + +import java.net.Proxy; + +@Mixin(GameTestServer.class) +abstract class GameTestServerMixin extends MinecraftServer implements MinecraftServerAccessor { + GameTestServerMixin(Thread serverThread, LevelStorageSource.LevelStorageAccess storageSource, PackRepository packRepository, WorldStem worldStem, Proxy proxy, DataFixer fixerUpper, Services services, ChunkProgressListenerFactory progressListenerFactory) { + super(serverThread, storageSource, packRepository, worldStem, proxy, fixerUpper, services, progressListenerFactory); + } + + /** + * {@link GameTestServer} overrides {@code waitUntilNextTick} to tick as quickly as possible. This does not play + * well with computers, so we add back {@link MinecraftServer}'s implementation. + */ + @Override + public void waitUntilNextTick() { + runAllTasks(); + computercraft$setWaitingForNextTick(true); + + try { + this.managedBlock(() -> !computercraft$haveTime()); + } finally { + computercraft$setWaitingForNextTick(false); + } + } +} diff --git a/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/MinecraftServerAccessor.java b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/MinecraftServerAccessor.java new file mode 100644 index 000000000..19aac4d3d --- /dev/null +++ b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/MinecraftServerAccessor.java @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.mixin.gametest; + +import net.minecraft.server.MinecraftServer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(MinecraftServer.class) +public interface MinecraftServerAccessor { + @Accessor("waitingForNextTick") + void computercraft$setWaitingForNextTick(boolean value); + + @Invoker("haveTime") + boolean computercraft$haveTime(); +} diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt index 7a21696de..fcf496862 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt @@ -37,8 +37,8 @@ class Computer_Test { */ @GameTest fun No_through_signal(context: GameTestHelper) = context.sequence { - val lamp = BlockPos(2, 2, 4) - val lever = BlockPos(2, 2, 0) + val lamp = BlockPos(2, 1, 4) + val lever = BlockPos(2, 1, 0) thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should not be lit") context.modifyBlock(lever) { x -> x.setValue(LeverBlock.POWERED, true) } @@ -52,8 +52,8 @@ class Computer_Test { */ @GameTest fun No_through_signal_reverse(context: GameTestHelper) = context.sequence { - val lamp = BlockPos(2, 2, 4) - val lever = BlockPos(2, 2, 0) + val lamp = BlockPos(2, 1, 4) + val lever = BlockPos(2, 1, 0) thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should not be lit") context.modifyBlock(lever) { x -> x.setValue(LeverBlock.POWERED, true) } @@ -67,12 +67,12 @@ class Computer_Test { */ @GameTest fun Set_and_destroy(context: GameTestHelper) = context.sequence { - val lamp = BlockPos(2, 2, 3) + val lamp = BlockPos(2, 1, 3) thenOnComputer { getApi().setOutput(ComputerSide.BACK, true) } thenIdle(3) thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, true, "Lamp should be lit") } - thenExecute { context.setBlock(BlockPos(2, 2, 2), Blocks.AIR) } + thenExecute { context.setBlock(BlockPos(2, 1, 2), Blocks.AIR) } thenIdle(4) thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should not be lit") } } @@ -101,8 +101,8 @@ class Computer_Test { @GameTest fun Computer_peripheral(context: GameTestHelper) = context.sequence { thenExecute { - context.assertPeripheral(BlockPos(3, 2, 2), type = "computer") - context.assertPeripheral(BlockPos(1, 2, 2), type = "turtle") + context.assertPeripheral(BlockPos(3, 1, 2), type = "computer") + context.assertPeripheral(BlockPos(1, 1, 2), type = "turtle") } } @@ -112,7 +112,7 @@ class Computer_Test { @GameTest fun Chest_resizes_on_change(context: GameTestHelper) = context.sequence { thenOnComputer { callPeripheral("right", "size").assertArrayEquals(27) } - thenExecute { context.placeItemAt(ItemStack(Items.CHEST), BlockPos(2, 2, 2), Direction.WEST) } + thenExecute { context.placeItemAt(ItemStack(Items.CHEST), BlockPos(2, 1, 2), Direction.WEST) } thenIdle(1) thenOnComputer { callPeripheral("right", "size").assertArrayEquals(54) } } @@ -123,7 +123,7 @@ class Computer_Test { @GameTest fun Drops_on_explosion(context: GameTestHelper) = context.sequence { thenExecute { - val explosionPos = Vec3.atCenterOf(context.absolutePos(BlockPos(2, 2, 2))) + val explosionPos = Vec3.atCenterOf(context.absolutePos(BlockPos(2, 1, 2))) context.level.explode(null, explosionPos.x, explosionPos.y, explosionPos.z, 2.0f, Level.ExplosionInteraction.TNT) context.assertItemEntityCountIs(ModRegistry.Items.COMPUTER_NORMAL.get(), 1) @@ -153,8 +153,8 @@ class Computer_Test { } // Teleport the player to the computer and then open it. thenExecute { - context.positionAt(BlockPos(2, 2, 1)) - context.useBlock(BlockPos(2, 2, 2), context.level.randomPlayer!!) + context.positionAt(BlockPos(2, 1, 1)) + context.useBlock(BlockPos(2, 1, 2), context.level.randomPlayer!!) } // Assert the terminal is synced to the client. thenIdle(2) diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Disk_Drive_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Disk_Drive_Test.kt index 4dfad1ac1..60e6ecbd2 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Disk_Drive_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Disk_Drive_Test.kt @@ -60,7 +60,7 @@ class Disk_Drive_Test { @GameTest fun Ejects_disk(helper: GameTestHelper) = helper.sequence { - val stackAt = BlockPos(2, 2, 2) + val stackAt = BlockPos(2, 1, 2) thenOnComputer { callPeripheral("right", "ejectDisk") } thenWaitUntil { helper.assertItemEntityPresent(Items.MUSIC_DISC_13, stackAt, 0.0) } } @@ -70,7 +70,7 @@ class Disk_Drive_Test { */ @GameTest fun Queues_event(helper: GameTestHelper) = helper.sequence { - val pos = BlockPos(1, 2, 2) + val pos = BlockPos(1, 1, 2) var started = false var disk = false @@ -104,7 +104,7 @@ class Disk_Drive_Test { fun Adds_removes_mount(helper: GameTestHelper) = helper.sequence { thenOnComputer { } // Wait for the computer to start up thenExecute { - helper.setContainerItem(BlockPos(1, 2, 2), 0, ItemStack(ModRegistry.Items.DISK.get())) + helper.setContainerItem(BlockPos(1, 1, 2), 0, ItemStack(ModRegistry.Items.DISK.get())) } thenOnComputer { getApi().getDrive("disk").assertArrayEquals("right") @@ -119,7 +119,7 @@ class Disk_Drive_Test { */ @GameTest fun Creates_disk_id(helper: GameTestHelper) = helper.sequence { - val drivePos = BlockPos(2, 2, 2) + val drivePos = BlockPos(2, 1, 2) thenWaitUntil { val drive = helper.getBlockEntity(drivePos, ModRegistry.BlockEntities.DISK_DRIVE.get()) if (!drive.getItem(0).has(ModRegistry.DataComponents.DISK_ID.get())) { @@ -133,8 +133,8 @@ class Disk_Drive_Test { */ @GameTest fun Comparator(helper: GameTestHelper) = helper.sequence { - val drivePos = BlockPos(2, 2, 2) - val dustPos = BlockPos(2, 2, 4) + val drivePos = BlockPos(2, 1, 2) + val dustPos = BlockPos(2, 1, 4) // Adding items should provide power thenExecute { @@ -160,7 +160,7 @@ class Disk_Drive_Test { */ @GameTest fun Contents_updates_state(helper: GameTestHelper) = helper.sequence { - val pos = BlockPos(2, 2, 2) + val pos = BlockPos(2, 1, 2) thenExecute { val drive = helper.getBlockEntity(pos, ModRegistry.BlockEntities.DISK_DRIVE.get()) @@ -185,7 +185,7 @@ class Disk_Drive_Test { @GameTest fun Drops_contents(helper: GameTestHelper) = helper.sequence { thenExecute { - helper.level.destroyBlock(helper.absolutePos(BlockPos(2, 2, 2)), true) + helper.level.destroyBlock(helper.absolutePos(BlockPos(2, 1, 2)), true) helper.assertExactlyItems( DataComponentUtil.createStack(ModRegistry.Items.DISK_DRIVE.get(), DataComponents.CUSTOM_NAME, Component.literal("My Disk Drive")), ItemStack(ModRegistry.Items.TREASURE_DISK.get()), @@ -201,7 +201,7 @@ class Disk_Drive_Test { fun Data_fixers(helper: GameTestHelper) = helper.sequence { thenExecute { helper.assertContainerExactly( - BlockPos(1, 2, 2), + BlockPos(1, 1, 2), listOf( ItemStack(ModRegistry.Items.DISK.get()).also { it.applyComponents( @@ -215,7 +215,7 @@ class Disk_Drive_Test { ) helper.assertContainerExactly( - BlockPos(3, 2, 2), + BlockPos(3, 1, 2), listOf( ItemStack(ModRegistry.Items.TREASURE_DISK.get()).also { it.applyComponents( diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Inventory_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Inventory_Test.kt index 6fc9cad2f..1401db615 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Inventory_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Inventory_Test.kt @@ -40,8 +40,8 @@ class Inventory_Test { ).await().assertArrayEquals(0, message = "Does not move items") } thenExecute { - helper.assertContainerExactly(BlockPos(1, 2, 2), listOf()) - helper.assertContainerExactly(BlockPos(3, 2, 2), listOf(ItemStack(Items.SHULKER_BOX))) + helper.assertContainerExactly(BlockPos(1, 1, 2), listOf()) + helper.assertContainerExactly(BlockPos(3, 1, 2), listOf(ItemStack(Items.SHULKER_BOX))) } } @@ -66,8 +66,8 @@ class Inventory_Test { ).await().assertArrayEquals(0, message = "Does not move items") } thenExecute { - helper.assertContainerExactly(BlockPos(1, 2, 2), listOf(ItemStack.EMPTY, ItemStack.EMPTY, ItemStack(Items.IRON_INGOT))) - helper.assertContainerExactly(BlockPos(3, 2, 2), NonNullList.withSize(27, ItemStack(Items.POLISHED_ANDESITE))) + helper.assertContainerExactly(BlockPos(1, 1, 2), listOf(ItemStack.EMPTY, ItemStack.EMPTY, ItemStack(Items.IRON_INGOT))) + helper.assertContainerExactly(BlockPos(3, 1, 2), NonNullList.withSize(27, ItemStack(Items.POLISHED_ANDESITE))) } } diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Loot_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Loot_Test.kt index 0d8394189..9c68f2466 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Loot_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Loot_Test.kt @@ -21,7 +21,7 @@ class Loot_Test { @GameTest(template = Structures.DEFAULT, required = false) // FIXME: We may need to inject this as a datapack instead fun Chest_contains_disk(context: GameTestHelper) = context.sequence { thenExecute { - val pos = BlockPos(2, 2, 2) + val pos = BlockPos(2, 1, 2) context.setBlock(pos, Blocks.CHEST) val chest = context.getBlockEntity(pos) as ChestBlockEntity diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Modem_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Modem_Test.kt index 01170422f..be645d86e 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Modem_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Modem_Test.kt @@ -35,7 +35,7 @@ class Modem_Test { @GameTest fun Gains_peripherals(helper: GameTestHelper) = helper.sequence { - val position = BlockPos(2, 2, 2) + val position = BlockPos(2, 1, 2) thenOnComputer { assertEquals(listOf("back"), getPeripheralNames(), "Starts with peripherals") } @@ -84,8 +84,8 @@ class Modem_Test { @GameTest(setupTicks = 1) fun Full_modems_form_networks(helper: GameTestHelper) = helper.sequence { thenExecute { - val modem1 = helper.getBlockEntity(BlockPos(1, 2, 1), ModRegistry.BlockEntities.WIRED_MODEM_FULL.get()) - val modem2 = helper.getBlockEntity(BlockPos(3, 2, 1), ModRegistry.BlockEntities.WIRED_MODEM_FULL.get()) + val modem1 = helper.getBlockEntity(BlockPos(1, 1, 1), ModRegistry.BlockEntities.WIRED_MODEM_FULL.get()) + val modem2 = helper.getBlockEntity(BlockPos(3, 1, 1), ModRegistry.BlockEntities.WIRED_MODEM_FULL.get()) assertEquals((modem1.element.node as WiredNodeImpl).network, (modem2.element.node as WiredNodeImpl).network, "On the same network") } } @@ -101,7 +101,7 @@ class Modem_Test { // However, if we connect the network, the other modem does. thenExecute { helper.setBlock( - BlockPos(1, 2, 3), + BlockPos(1, 1, 3), ModRegistry.Blocks.CABLE.get().defaultBlockState().setValue(CableBlock.CABLE, true), ) } @@ -120,7 +120,7 @@ class Modem_Test { // However, if we connect the network, the other modem does. thenExecute { helper.setBlock( - BlockPos(1, 2, 3), + BlockPos(1, 1, 3), ModRegistry.Blocks.CABLE.get().defaultBlockState().setValue(CableBlock.CABLE, true), ) } @@ -134,9 +134,9 @@ class Modem_Test { @GameTest fun Modem_drops_when_neighbour_removed(helper: GameTestHelper) = helper.sequence { thenExecute { - helper.setBlock(BlockPos(2, 3, 2), Blocks.AIR) - helper.assertItemEntityPresent(ModRegistry.Items.WIRED_MODEM.get(), BlockPos(2, 2, 2), 0.0) - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 2)) + helper.setBlock(BlockPos(2, 2, 2), Blocks.AIR) + helper.assertItemEntityPresent(ModRegistry.Items.WIRED_MODEM.get(), BlockPos(2, 1, 2), 0.0) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 2)) } } @@ -146,9 +146,9 @@ class Modem_Test { @GameTest fun Modem_keeps_cable_when_neighbour_removed(helper: GameTestHelper) = helper.sequence { thenExecute { - helper.setBlock(BlockPos(2, 3, 2), Blocks.AIR) - helper.assertItemEntityPresent(ModRegistry.Items.WIRED_MODEM.get(), BlockPos(2, 2, 2), 0.0) - helper.assertBlockIs(BlockPos(2, 2, 2)) { + helper.setBlock(BlockPos(2, 2, 2), Blocks.AIR) + helper.assertItemEntityPresent(ModRegistry.Items.WIRED_MODEM.get(), BlockPos(2, 1, 2), 0.0) + helper.assertBlockIs(BlockPos(2, 1, 2)) { it.block == ModRegistry.Blocks.CABLE.get() && it.getValue(CableBlock.MODEM) == CableModemVariant.None && it.getValue(CableBlock.CABLE) } } @@ -162,7 +162,7 @@ class Modem_Test { thenOnComputer { callRemotePeripheral("minecraft:chest_0", "size").assertArrayEquals(27) } - thenExecute { context.placeItemAt(ItemStack(Items.CHEST), BlockPos(2, 2, 2), Direction.WEST) } + thenExecute { context.placeItemAt(ItemStack(Items.CHEST), BlockPos(2, 1, 2), Direction.WEST) } thenIdle(1) thenOnComputer { callRemotePeripheral("minecraft:chest_0", "size").assertArrayEquals(54) diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Monitor_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Monitor_Test.kt index afbf8d400..0d00484b8 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Monitor_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Monitor_Test.kt @@ -6,10 +6,8 @@ package dan200.computercraft.gametest import dan200.computercraft.gametest.api.* import dan200.computercraft.shared.ModRegistry -import dan200.computercraft.shared.config.Config import dan200.computercraft.shared.peripheral.monitor.MonitorBlock import dan200.computercraft.shared.peripheral.monitor.MonitorEdgeState -import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer import net.minecraft.commands.arguments.blocks.BlockInput import net.minecraft.core.BlockPos import net.minecraft.gametest.framework.GameTest @@ -17,15 +15,15 @@ import net.minecraft.gametest.framework.GameTestGenerator import net.minecraft.gametest.framework.GameTestHelper import net.minecraft.gametest.framework.TestFunction import net.minecraft.nbt.CompoundTag -import net.minecraft.world.entity.EntityType import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.GameType import net.minecraft.world.level.block.Blocks import org.junit.jupiter.api.Assertions.* class Monitor_Test { @GameTest fun Ensures_valid_on_place(context: GameTestHelper) = context.sequence { - val pos = BlockPos(2, 2, 2) + val pos = BlockPos(2, 1, 2) thenExecute { val tag = CompoundTag() @@ -57,9 +55,9 @@ class Monitor_Test { @GameTest fun Contract_on_destroy(helper: GameTestHelper) = helper.sequence { thenExecute { - helper.setBlock(BlockPos(2, 2, 2), Blocks.AIR.defaultBlockState()) - helper.assertBlockHas(BlockPos(1, 2, 2), MonitorBlock.STATE, MonitorEdgeState.NONE) - helper.assertBlockHas(BlockPos(3, 2, 2), MonitorBlock.STATE, MonitorEdgeState.NONE) + helper.setBlock(BlockPos(2, 1, 2), Blocks.AIR.defaultBlockState()) + helper.assertBlockHas(BlockPos(1, 1, 2), MonitorBlock.STATE, MonitorEdgeState.NONE) + helper.assertBlockHas(BlockPos(3, 1, 2), MonitorBlock.STATE, MonitorEdgeState.NONE) } } @@ -69,7 +67,7 @@ class Monitor_Test { @GameTest fun Creates_terminal(helper: GameTestHelper) = helper.sequence { fun monitorAt(x: Int) = - helper.getBlockEntity(BlockPos(x, 2, 2), ModRegistry.BlockEntities.MONITOR_ADVANCED.get()) + helper.getBlockEntity(BlockPos(x, 1, 2), ModRegistry.BlockEntities.MONITOR_ADVANCED.get()) thenExecute { for (i in 1..3) { @@ -80,20 +78,20 @@ class Monitor_Test { assertNotNull(monitorAt(1).cachedServerMonitor?.terminal, "Creating a peripheral creates a terminal") // Then remove the middle monitor and check it splits into two. - helper.setBlock(BlockPos(2, 2, 2), Blocks.AIR.defaultBlockState()) + helper.setBlock(BlockPos(2, 1, 2), Blocks.AIR.defaultBlockState()) assertNotNull(monitorAt(3).cachedServerMonitor, "Origin retains its monitor") assertNull(monitorAt(3).cachedServerMonitor!!.terminal, "Origin deletes the terminal") assertNotEquals(monitorAt(1).cachedServerMonitor, monitorAt(3).cachedServerMonitor, "Monitors are different") // Then set the monitor, check it rejoins and recreates the terminal. - val pos = BlockPos(2, 2, 2) + val pos = BlockPos(2, 1, 2) helper.setBlock(pos, ModRegistry.Blocks.MONITOR_ADVANCED.get()) ModRegistry.Blocks.MONITOR_ADVANCED.get().setPlacedBy( helper.level, helper.absolutePos(pos), helper.getBlockState(pos), - EntityType.COW.create(helper.level), + helper.makeMockPlayer(GameType.SURVIVAL), ItemStack.EMPTY, ) monitorAt(2).peripheral() @@ -109,7 +107,7 @@ class Monitor_Test { fun Render_monitor_tests(): List { val tests = mutableListOf() - fun addTest(label: String, renderer: MonitorRenderer, time: Long = Times.NOON, tag: String = TestTags.CLIENT) { + fun addTest(label: String, time: Long = Times.NOON, tag: String = TestTags.CLIENT) { if (!TestTags.isEnabled(tag)) return val className = this::class.java.simpleName.lowercase() @@ -123,32 +121,29 @@ class Monitor_Test { Timeouts.DEFAULT, 0, true, - ) { renderMonitor(it, renderer, time) }, + ) { renderMonitor(it, time) }, ) } - addTest("tbo_noon", MonitorRenderer.TBO, Times.NOON) - addTest("tbo_midnight", MonitorRenderer.TBO, Times.MIDNIGHT) - addTest("vbo_noon", MonitorRenderer.VBO, Times.NOON) - addTest("vbo_midnight", MonitorRenderer.VBO, Times.MIDNIGHT) + addTest("noon", Times.NOON) + addTest("midnight", Times.MIDNIGHT) - addTest("sodium_tbo", MonitorRenderer.TBO, tag = "sodium") - addTest("sodium_vbo", MonitorRenderer.VBO, tag = "sodium") + addTest("sodium_tbo", tag = "sodium") + addTest("sodium_vbo", tag = "sodium") - addTest("iris_noon", MonitorRenderer.BEST, Times.NOON, tag = "iris") - addTest("iris_midnight", MonitorRenderer.BEST, Times.MIDNIGHT, tag = "iris") + addTest("iris_noon", Times.NOON, tag = "iris") + addTest("iris_midnight", Times.MIDNIGHT, tag = "iris") return tests } - private fun renderMonitor(helper: GameTestHelper, renderer: MonitorRenderer, time: Long) = helper.sequence { + private fun renderMonitor(helper: GameTestHelper, time: Long) = helper.sequence { thenExecute { - Config.monitorRenderer = renderer helper.level.dayTime = time helper.positionAtArmorStand() // Get the monitor and peripheral. This forces us to create a server monitor at this location. - val monitor = helper.getBlockEntity(BlockPos(2, 2, 3), ModRegistry.BlockEntities.MONITOR_ADVANCED.get()) + val monitor = helper.getBlockEntity(BlockPos(2, 1, 3), ModRegistry.BlockEntities.MONITOR_ADVANCED.get()) monitor.peripheral() val terminal = monitor.cachedServerMonitor!!.terminal!! diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Pocket_Computer_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Pocket_Computer_Test.kt index f396a8599..e6297f948 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Pocket_Computer_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Pocket_Computer_Test.kt @@ -40,7 +40,7 @@ class Pocket_Computer_Test { // Give the player a pocket computer. thenExecute { - context.positionAt(BlockPos(2, 2, 2)) + context.positionAt(BlockPos(2, 1, 2)) context.givePocketComputer(unique) } // Write some text to the computer. @@ -82,7 +82,7 @@ class Pocket_Computer_Test { // Give the player a pocket computer. thenExecute { - context.positionAt(BlockPos(2, 2, 2), xRot = 90.0f) + context.positionAt(BlockPos(2, 1, 2), xRot = 90.0f) context.givePocketComputer(unique) } thenOnComputer(unique) { @@ -119,12 +119,12 @@ class Pocket_Computer_Test { @GameTest fun Data_fixers(helper: GameTestHelper) = helper.sequence { thenExecute { - val upgrade = helper.level.registryAccess().registryOrThrow(IPocketUpgrade.REGISTRY) - .getHolder(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "wireless_modem_normal")) + val upgrade = helper.level.registryAccess().lookupOrThrow(IPocketUpgrade.REGISTRY) + .get(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "wireless_modem_normal")) .orElseThrow() helper.assertContainerExactly( - BlockPos(2, 2, 2), + BlockPos(2, 1, 2), listOf( ItemStack(ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get()).also { DataComponentUtil.setCustomName(it, "Test") diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Printer_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Printer_Test.kt index 4034bba06..8e6789cf6 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Printer_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Printer_Test.kt @@ -28,8 +28,8 @@ class Printer_Test { */ @GameTest fun Comparator(helper: GameTestHelper) = helper.sequence { - val printerPos = BlockPos(2, 2, 2) - val dustPos = BlockPos(2, 2, 4) + val printerPos = BlockPos(2, 1, 2) + val dustPos = BlockPos(2, 1, 4) // Adding items should provide power thenExecute { @@ -56,7 +56,7 @@ class Printer_Test { */ @GameTest fun Contents_updates_state(helper: GameTestHelper) = helper.sequence { - val pos = BlockPos(2, 2, 2) + val pos = BlockPos(2, 1, 2) thenExecute { val drive = helper.getBlockEntity(pos, ModRegistry.BlockEntities.PRINTER.get()) @@ -89,7 +89,7 @@ class Printer_Test { @GameTest fun Drops_contents(helper: GameTestHelper) = helper.sequence { thenExecute { - helper.level.destroyBlock(helper.absolutePos(BlockPos(2, 2, 2)), true) + helper.level.destroyBlock(helper.absolutePos(BlockPos(2, 1, 2)), true) helper.assertExactlyItems( DataComponentUtil.createStack(ModRegistry.Items.PRINTER.get(), DataComponents.CUSTOM_NAME, Component.literal("My Printer")), ItemStack(Items.PAPER), @@ -105,7 +105,7 @@ class Printer_Test { @GameTest fun Data_fixers(helper: GameTestHelper) = helper.sequence { thenExecute { - val container = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.PRINTER.get()) + val container = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.PRINTER.get()) val contents = container.getItem(1) assertEquals(ModRegistry.Items.PRINTED_PAGE.get(), contents.item) diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt index 191152e74..e47d6214c 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt @@ -88,7 +88,7 @@ class Turtle_Test { turtle.placeDown(ObjectArguments()).await() .assertArrayEquals(true, message = "Placed lava") } - thenExecute { helper.assertBlockPresent(Blocks.LAVA, BlockPos(2, 2, 2)) } + thenExecute { helper.assertBlockPresent(Blocks.LAVA, BlockPos(2, 1, 2)) } } /** @@ -103,7 +103,7 @@ class Turtle_Test { .assertArrayEquals(true, message = "Placed sign") } thenExecute { - val sign = helper.getBlockEntity(BlockPos(2, 2, 1), BlockEntityType.SIGN) + val sign = helper.getBlockEntity(BlockPos(2, 1, 1), BlockEntityType.SIGN) val lines = listOf("", "Test", "message", "") for ((i, line) in lines.withIndex()) { assertEquals(line, sign.frontText.getMessage(i, false).string, "Line $i") @@ -126,8 +126,8 @@ class Turtle_Test { .assertArrayEquals(true, message = "Placed water") } thenExecute { - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 2)) - helper.assertBlockHas(BlockPos(2, 5, 2), BlockStateProperties.WATERLOGGED, true) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 2)) + helper.assertBlockHas(BlockPos(2, 4, 2), BlockStateProperties.WATERLOGGED, true) } } @@ -143,7 +143,7 @@ class Turtle_Test { .assertArrayEquals(true, message = "Placed oak fence") } thenExecute { - helper.assertBlockIs(BlockPos(2, 2, 2)) { it.block == Blocks.OAK_FENCE && it.getValue(FenceBlock.WATERLOGGED) } + helper.assertBlockIs(BlockPos(2, 1, 2)) { it.block == Blocks.OAK_FENCE && it.getValue(FenceBlock.WATERLOGGED) } } } @@ -160,7 +160,7 @@ class Turtle_Test { assertEquals("minecraft:lava_bucket", getTurtleItemDetail()["name"]) } - thenExecute { helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 2)) } + thenExecute { helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 2)) } } /** @@ -171,7 +171,7 @@ class Turtle_Test { @GameTest fun Hoe_dirt(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.dig(Optional.empty()).await().assertArrayEquals(true, message = "Dug with hoe") } - thenExecute { helper.assertBlockPresent(Blocks.FARMLAND, BlockPos(1, 2, 1)) } + thenExecute { helper.assertBlockPresent(Blocks.FARMLAND, BlockPos(1, 1, 1)) } } /** @@ -182,7 +182,7 @@ class Turtle_Test { @GameTest fun Hoe_dirt_below(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.digDown(Optional.empty()).await().assertArrayEquals(true, message = "Dug with hoe") } - thenExecute { helper.assertBlockPresent(Blocks.FARMLAND, BlockPos(1, 1, 1)) } + thenExecute { helper.assertBlockPresent(Blocks.FARMLAND, BlockPos(1, 0, 1)) } } /** @@ -194,7 +194,7 @@ class Turtle_Test { turtle.dig(Optional.empty()).await() .assertArrayEquals(false, "Nothing to dig here", message = "Dug with hoe") } - thenExecute { helper.assertBlockPresent(Blocks.DIRT, BlockPos(1, 2, 2)) } + thenExecute { helper.assertBlockPresent(Blocks.DIRT, BlockPos(1, 1, 2)) } } /** @@ -204,18 +204,18 @@ class Turtle_Test { fun Break_cable(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.dig(Optional.empty()).await() } thenExecute { - helper.assertBlockIs(BlockPos(2, 2, 3)) { + helper.assertBlockIs(BlockPos(2, 1, 3)) { it.block == ModRegistry.Blocks.CABLE.get() && !it.getValue(CableBlock.CABLE) && it.getValue(CableBlock.MODEM) == CableModemVariant.DownOff } - helper.assertContainerExactly(BlockPos(2, 2, 2), listOf(ItemStack(ModRegistry.Items.CABLE.get()))) + helper.assertContainerExactly(BlockPos(2, 1, 2), listOf(ItemStack(ModRegistry.Items.CABLE.get()))) } thenOnComputer { turtle.dig(Optional.empty()).await().assertArrayEquals(true) } thenExecute { - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 3)) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 3)) helper.assertContainerExactly( - BlockPos(2, 2, 2), + BlockPos(2, 1, 2), listOf( ItemStack(ModRegistry.Items.CABLE.get()), ItemStack(ModRegistry.Items.WIRED_MODEM.get()), @@ -231,14 +231,14 @@ class Turtle_Test { fun Dig_consume_durability(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.dig(Optional.empty()).await() } thenExecute { - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 3)) - helper.assertContainerExactly(BlockPos(2, 2, 2), listOf(ItemStack(Items.COBBLESTONE))) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 3)) + helper.assertContainerExactly(BlockPos(2, 1, 2), listOf(ItemStack(Items.COBBLESTONE))) - val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access + val turtle = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access val upgrade = turtle.getUpgrade(TurtleSide.LEFT) assertEquals( - helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) - .get(ResourceLocation.fromNamespaceAndPath("cctest", "wooden_pickaxe")), + helper.level.registryAccess().lookupOrThrow(ITurtleUpgrade.REGISTRY) + .getValue(ResourceLocation.fromNamespaceAndPath("cctest", "wooden_pickaxe")), upgrade, "Upgrade is a wooden pickaxe", ) @@ -256,18 +256,18 @@ class Turtle_Test { fun Dig_breaks_tool(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.dig(Optional.empty()).await() } thenExecute { - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 3)) - helper.assertContainerExactly(BlockPos(2, 2, 2), listOf(ItemStack(Items.COBBLESTONE))) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 3)) + helper.assertContainerExactly(BlockPos(2, 1, 2), listOf(ItemStack(Items.COBBLESTONE))) - val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access + val turtle = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access val upgrade = turtle.getUpgrade(TurtleSide.LEFT) assertEquals(null, upgrade, "Upgrade broke") helper.assertUpgradeItem( ItemStack(Items.WOODEN_PICKAXE), UpgradeData.ofDefault( - helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) - .getHolder(ResourceLocation.fromNamespaceAndPath("cctest", "wooden_pickaxe")).orElseThrow(), + helper.level.registryAccess().lookupOrThrow(ITurtleUpgrade.REGISTRY) + .get(ResourceLocation.fromNamespaceAndPath("cctest", "wooden_pickaxe")).orElseThrow(), ), ) } @@ -281,14 +281,14 @@ class Turtle_Test { fun Dig_enchanted_consume_durability(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.dig(Optional.empty()).await() } thenExecute { - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 3)) - helper.assertContainerExactly(BlockPos(2, 2, 2), listOf(ItemStack(Items.STONE))) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 3)) + helper.assertContainerExactly(BlockPos(2, 1, 2), listOf(ItemStack(Items.STONE))) - val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access + val turtle = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access val upgrade = turtle.getUpgrade(TurtleSide.LEFT) assertEquals( - helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) - .get(ResourceLocation.fromNamespaceAndPath("cctest", "netherite_pickaxe")), + helper.level.registryAccess().lookupOrThrow(ITurtleUpgrade.REGISTRY) + .getValue(ResourceLocation.fromNamespaceAndPath("cctest", "netherite_pickaxe")), upgrade, "Upgrade is a netherite pickaxe", ) @@ -296,8 +296,8 @@ class Turtle_Test { val item = ItemStack(Items.NETHERITE_PICKAXE) item.damageValue = 1 item.enchant( - helper.level.registryAccess().registryOrThrow(Registries.ENCHANTMENT) - .getHolderOrThrow(Enchantments.SILK_TOUCH), + helper.level.registryAccess().lookupOrThrow(Registries.ENCHANTMENT) + .getOrThrow(Enchantments.SILK_TOUCH), 1, ) @@ -327,7 +327,7 @@ class Turtle_Test { .assertArrayEquals(true, message = "Block was placed") } thenIdle(1) - thenExecute { helper.assertBlockHas(BlockPos(1, 2, 3), MonitorBlock.STATE, MonitorEdgeState.LR) } + thenExecute { helper.assertBlockHas(BlockPos(1, 1, 3), MonitorBlock.STATE, MonitorEdgeState.LR) } } /** @@ -389,15 +389,15 @@ class Turtle_Test { @GameTest fun Resists_explosions(helper: GameTestHelper) = helper.sequence { thenExecute { - val pos = helper.absolutePos(BlockPos(2, 2, 2)) + val pos = helper.absolutePos(BlockPos(2, 1, 2)) val tnt = PrimedTnt(helper.level, pos.x + 0.5, pos.y + 1.0, pos.z + 0.5, null) tnt.fuse = 1 helper.level.addFreshEntity(tnt) } thenWaitUntil { helper.assertEntityNotPresent(EntityType.TNT) } thenExecute { - helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_ADVANCED.get(), BlockPos(2, 2, 2)) - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 1)) + helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_ADVANCED.get(), BlockPos(2, 1, 2)) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 1)) } } @@ -409,8 +409,8 @@ class Turtle_Test { thenExecute { helper.getEntity(EntityType.CREEPER).ignite() } thenWaitUntil { helper.assertEntityNotPresent(EntityType.CREEPER) } thenExecute { - helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_ADVANCED.get(), BlockPos(2, 2, 2)) - helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 2, 1)) + helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_ADVANCED.get(), BlockPos(2, 1, 2)) + helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 1, 1)) } } @@ -419,8 +419,8 @@ class Turtle_Test { */ @GameTest fun Drop_into_chest(helper: GameTestHelper) = helper.sequence { - val turtlePos = BlockPos(2, 2, 2) - val chest = BlockPos(2, 2, 3) + val turtlePos = BlockPos(2, 1, 2) + val chest = BlockPos(2, 1, 3) thenOnComputer { turtle.drop(Optional.of(32)).await() @@ -445,7 +445,7 @@ class Turtle_Test { .assertArrayEquals(true, message = "Could not drop items") } thenExecute { - helper.assertContainerExactly(BlockPos(2, 2, 2), listOf(ItemStack(Blocks.DIRT, 32))) + helper.assertContainerExactly(BlockPos(2, 1, 2), listOf(ItemStack(Blocks.DIRT, 32))) helper.assertContainerExactly(helper.getEntity(EntityType.CHEST_MINECART), listOf(ItemStack(Blocks.DIRT, 48))) helper.assertEntityNotPresent(EntityType.ITEM) } @@ -456,7 +456,7 @@ class Turtle_Test { */ @GameTest fun Refuel_basic(helper: GameTestHelper) = helper.sequence { - val turtlePos = BlockPos(2, 2, 2) + val turtlePos = BlockPos(2, 1, 2) // Test refueling from slot 1 with no limit. thenOnComputer { @@ -484,7 +484,7 @@ class Turtle_Test { */ @GameTest fun Refuel_fail(helper: GameTestHelper) = helper.sequence { - val turtlePos = BlockPos(2, 2, 2) + val turtlePos = BlockPos(2, 1, 2) thenOnComputer { assertEquals(0, turtle.fuelLevel) @@ -501,7 +501,7 @@ class Turtle_Test { */ @GameTest fun Refuel_container(helper: GameTestHelper) = helper.sequence { - val turtlePos = BlockPos(2, 2, 2) + val turtlePos = BlockPos(2, 1, 2) // Test refueling from slot 1 with no limit. thenOnComputer { @@ -523,9 +523,9 @@ class Turtle_Test { fun Move_preserves_state(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.forward().await().assertArrayEquals(true, message = "Turtle moved forward") } thenExecute { - helper.assertContainerExactly(BlockPos(2, 2, 3), listOf(ItemStack(Items.DIRT, 32))) + helper.assertContainerExactly(BlockPos(2, 1, 3), listOf(ItemStack(Items.DIRT, 32))) - val turtle = helper.getBlockEntity(BlockPos(2, 2, 3), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) + val turtle = helper.getBlockEntity(BlockPos(2, 1, 3), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) assertEquals(1, turtle.computerID) assertEquals("turtle_test.move_preserves_state", turtle.label) assertEquals(79, turtle.access.fuelLevel) @@ -540,7 +540,7 @@ class Turtle_Test { @GameTest fun Move_replace(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.forward().await().assertArrayEquals(true, message = "Turtle moved forward") } - thenExecute { helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 2, 3)) } + thenExecute { helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 1, 3)) } } /** @@ -551,13 +551,13 @@ class Turtle_Test { thenOnComputer { turtle.forward().await().assertArrayEquals(true, message = "Turtle moved forward") } thenExecute { // Assert we're waterlogged. - helper.assertBlockHas(BlockPos(2, 2, 2), WaterloggableHelpers.WATERLOGGED, true) + helper.assertBlockHas(BlockPos(2, 1, 2), WaterloggableHelpers.WATERLOGGED, true) } thenOnComputer { turtle.forward().await().assertArrayEquals(true, message = "Turtle moved forward") } thenExecute { // Assert we're no longer waterlogged and we've left a source block. - helper.assertBlockIs(BlockPos(2, 2, 2)) { it.block == Blocks.WATER && it.fluidState.isSource } - helper.assertBlockHas(BlockPos(2, 2, 3), WaterloggableHelpers.WATERLOGGED, false) + helper.assertBlockIs(BlockPos(2, 1, 2)) { it.block == Blocks.WATER && it.fluidState.isSource } + helper.assertBlockHas(BlockPos(2, 1, 3), WaterloggableHelpers.WATERLOGGED, false) } } @@ -568,8 +568,8 @@ class Turtle_Test { fun Move_obstruct(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.forward().await().assertArrayEquals(false, "Movement obstructed") } thenExecute { - helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 2, 2)) - helper.assertBlockPresent(Blocks.DIRT, BlockPos(2, 2, 3)) + helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 1, 2)) + helper.assertBlockPresent(Blocks.DIRT, BlockPos(2, 1, 3)) } } @@ -578,7 +578,7 @@ class Turtle_Test { */ @GameTest fun Attack_entity(helper: GameTestHelper) = helper.sequence { - val turtlePos = BlockPos(2, 2, 2) + val turtlePos = BlockPos(2, 1, 2) thenOnComputer { turtle.attack(Optional.empty()).await().assertArrayEquals(true, message = "Attacked entity") } @@ -598,7 +598,7 @@ class Turtle_Test { @GameTest fun Attack_entity_destroy(helper: GameTestHelper) = helper.sequence { thenStartComputer { turtle.attack(Optional.empty()) } - thenWaitUntil { helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 2)) } + thenWaitUntil { helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 2)) } } /** @@ -663,12 +663,12 @@ class Turtle_Test { @GameTest fun Data_fixers(helper: GameTestHelper) = helper.sequence { thenExecute { - val overlay = helper.level.registryAccess().registryOrThrow(TurtleOverlay.REGISTRY) - .get(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "trans_flag"))!! - val upgrade = helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) - .get(ResourceLocation.withDefaultNamespace("diamond_pickaxe"))!! + val overlay = helper.level.registryAccess().lookupOrThrow(TurtleOverlay.REGISTRY) + .getValue(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "trans_flag"))!! + val upgrade = helper.level.registryAccess().lookupOrThrow(ITurtleUpgrade.REGISTRY) + .getValue(ResourceLocation.withDefaultNamespace("diamond_pickaxe"))!! - val turtleBe = helper.getBlockEntity(BlockPos(1, 2, 1), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) + val turtleBe = helper.getBlockEntity(BlockPos(1, 1, 1), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) assertEquals(overlay, turtleBe.overlay) assertEquals(upgrade, turtleBe.getUpgrade(TurtleSide.LEFT)) @@ -702,7 +702,7 @@ class Turtle_Test { callPeripheral("left", "craft", 1).assertArrayEquals(true) } thenExecute { - val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) + val turtle = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) assertThat( "Inventory is as expected.", turtle.items, @@ -725,10 +725,10 @@ class Turtle_Test { turtle.equipLeft().await().assertArrayEquals(true) } thenExecute { - val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) + val turtle = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) assertEquals( - helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) - .get(ResourceLocation.withDefaultNamespace("diamond_pickaxe")), + helper.level.registryAccess().lookupOrThrow(ITurtleUpgrade.REGISTRY) + .getValue(ResourceLocation.withDefaultNamespace("diamond_pickaxe")), turtle.getUpgrade(TurtleSide.LEFT), ) } @@ -742,7 +742,7 @@ class Turtle_Test { @GameTest fun Breaks_exploding_block(context: GameTestHelper) = context.sequence { thenOnComputer { turtle.dig(Optional.empty()) } - thenWaitUntil { context.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 2)) } + thenWaitUntil { context.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 2)) } thenExecute { context.assertItemEntityCountIs(ModRegistry.Items.TURTLE_NORMAL.get(), 1) context.assertItemEntityCountIs(Items.BONE_BLOCK, 65) diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/TestExtensions.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/TestExtensions.kt index 43d046ff9..58e5d967d 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/TestExtensions.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/TestExtensions.kt @@ -264,7 +264,7 @@ fun GameTestHelper.assertExactlyItems(vararg expected: ItemStack, message: Strin fun GameTestHelper.assertItemEntityCountIs(expected: Item, count: Int) { val actualCount = getEntities(EntityType.ITEM).sumOf { if (it.item.`is`(expected)) it.item.count else 0 } if (actualCount != count) { - throw GameTestAssertException("Expected $count ${expected.description.string} items to exist (found $actualCount)") + throw GameTestAssertException("Expected $count ${ItemStack(expected).itemName.string} items to exist (found $actualCount)") } } diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt index d410a1b9c..32fc729db 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt @@ -9,7 +9,6 @@ import dan200.computercraft.gametest.api.isRenderingStable import dan200.computercraft.gametest.api.setupForTest import net.minecraft.client.CloudStatus import net.minecraft.client.Minecraft -import net.minecraft.client.ParticleStatus import net.minecraft.client.gui.screens.AccessibilityOnboardingScreen import net.minecraft.client.gui.screens.Screen import net.minecraft.client.gui.screens.TitleScreen @@ -17,8 +16,10 @@ import net.minecraft.client.tutorial.TutorialSteps import net.minecraft.core.registries.Registries import net.minecraft.gametest.framework.* import net.minecraft.server.MinecraftServer +import net.minecraft.server.level.ParticleStatus import net.minecraft.sounds.SoundSource import net.minecraft.world.Difficulty +import net.minecraft.world.flag.FeatureFlagSet import net.minecraft.world.level.GameRules import net.minecraft.world.level.GameType import net.minecraft.world.level.LevelSettings @@ -84,7 +85,7 @@ object ClientTestHooks { minecraft.createWorldOpenFlows().openWorld(LEVEL_NAME) { minecraft.setScreen(screen) } } else { LOG.info("World does not exist, creating it.") - val rules = GameRules() + val rules = GameRules(FeatureFlagSet.of()) rules.getRule(GameRules.RULE_DOMOBSPAWNING).set(false, null) rules.getRule(GameRules.RULE_DAYLIGHT).set(false, null) rules.getRule(GameRules.RULE_WEATHER_CYCLE).set(false, null) @@ -93,7 +94,10 @@ object ClientTestHooks { LEVEL_NAME, LevelSettings("Test Level", GameType.CREATIVE, false, Difficulty.EASY, true, rules, WorldDataConfiguration.DEFAULT), WorldOptions(WorldOptions.randomSeed(), false, false), - { it.registryOrThrow(Registries.WORLD_PRESET).getOrThrow(WorldPresets.FLAT).createWorldDimensions() }, + { + it.lookupOrThrow(Registries.WORLD_PRESET).getOrThrow(WorldPresets.FLAT).value() + .createWorldDimensions() + }, screen, ) } diff --git a/projects/common/src/testMod/resources/computercraft-gametest.mixins.json b/projects/common/src/testMod/resources/computercraft-gametest.mixins.json index 803991da5..3f2053cb8 100644 --- a/projects/common/src/testMod/resources/computercraft-gametest.mixins.json +++ b/projects/common/src/testMod/resources/computercraft-gametest.mixins.json @@ -11,6 +11,8 @@ "GameTestInfoAccessor", "GameTestSequenceAccessor", "GameTestSequenceMixin", + "GameTestServerMixin", + "MinecraftServerAccessor", "StructureTemplateManagerMixin", "TestCommandAccessor" ], diff --git a/projects/fabric/build.gradle.kts b/projects/fabric/build.gradle.kts index 21ce836b3..0a328504e 100644 --- a/projects/fabric/build.gradle.kts +++ b/projects/fabric/build.gradle.kts @@ -20,6 +20,14 @@ cct { allProjects.forEach { externalSources(it) } } +sourceSets { + client { + java { + exclude("dan200/computercraft/client/integration/rei") + } + } +} + fun addRemappedConfiguration(name: String) { // There was a regression in Loom 1.1 which means that targetConfigurationName doesn't do anything, and remap // configurations just get added to the main source set (https://github.com/FabricMC/fabric-loom/issues/843). diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java index 224ac9bc5..2774d27ad 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java @@ -55,7 +55,6 @@ public class ComputerCraftClient { PreparableModelLoadingPlugin.register(CustomModelLoader::prepare, (state, context) -> { ClientRegistry.registerExtraModels(context::addModels, state.getExtraModels()); context.resolveModel().register(ctx -> state.loadModel(ctx.id())); - context.modifyModelAfterBake().register((model, ctx) -> model == null ? null : state.wrapModel(ctx, model)); }); BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.COMPUTER_NORMAL.get(), RenderType.cutout()); diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/model/CustomModelLoader.java b/projects/fabric/src/client/java/dan200/computercraft/client/model/CustomModelLoader.java index 7addcdced..62dea29d7 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/model/CustomModelLoader.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/model/CustomModelLoader.java @@ -8,11 +8,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.client.model.turtle.UnbakedTurtleModel; -import dan200.computercraft.mixin.client.BlockModelAccessor; -import net.fabricmc.fabric.api.client.model.loading.v1.ModelModifier; import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.resources.FileToIdConverter; import net.minecraft.resources.ResourceLocation; @@ -36,9 +32,8 @@ import java.util.concurrent.Executor; *

* This is used from a {@link PreparableModelLoadingPlugin}, which {@linkplain #prepare(ResourceManager, Executor) loads * data from disk} in parallel with other loader plugins, and then hooks into the model loading pipeline - * ({@link #loadModel(ResourceLocation)}, {@link #wrapModel(ModelModifier.AfterBake.Context, BakedModel)}). + * ({@link #loadModel(ResourceLocation)}). * - * @see EmissiveBakedModel * @see UnbakedTurtleModel */ public final class CustomModelLoader { @@ -46,7 +41,6 @@ public final class CustomModelLoader { private static final FileToIdConverter converter = FileToIdConverter.json("models"); private final Map models = new HashMap<>(); - private final Map emissiveModels = new HashMap<>(); private final Collection extraModels; private CustomModelLoader(Collection extraModels) { @@ -80,9 +74,6 @@ public final class CustomModelLoader { }; models.put(id, unbaked); } - - var emissive = GsonHelper.getAsString(model, "computercraft:emissive_texture", null); - if (emissive != null) emissiveModels.put(id, emissive); } catch (IllegalArgumentException | IOException | JsonParseException e) { LOG.error("Couldn't parse model file {} from {}", id, path, e); } @@ -101,35 +92,4 @@ public final class CustomModelLoader { public @Nullable UnbakedModel loadModel(ResourceLocation path) { return path.getNamespace().equals(ComputerCraftAPI.MOD_ID) ? models.get(path) : null; } - - /** - * Wrap a baked model. - *

- * This just finds models which specify an emissive texture ({@code computercraft:emissive_texture} in the JSON) and - * wraps them in a {@link EmissiveBakedModel}. - * - * @param ctx The current model loading context. - * @param baked The baked model to wrap. - * @return The wrapped model. - */ - public BakedModel wrapModel(ModelModifier.AfterBake.Context ctx, BakedModel baked) { - var id = ctx.resourceId(); - if (id == null || !id.getNamespace().equals(ComputerCraftAPI.MOD_ID)) return baked; - if (!(ctx.sourceModel() instanceof BlockModel model)) return baked; - - var emissive = getEmissive(id, model); - return emissive == null ? baked : EmissiveBakedModel.wrap(baked, ctx.textureGetter().apply(model.getMaterial(emissive))); - } - - private @Nullable String getEmissive(ResourceLocation id, BlockModel model) { - while (true) { - var emissive = emissiveModels.get(id); - if (emissive != null) return emissive; - - id = ((BlockModelAccessor) model).computercraft$getParentLocation(); - model = ((BlockModelAccessor) model).computercraft$getParent(); - - if (id == null || model == null) return null; - } - } } diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/model/EmissiveBakedModel.java b/projects/fabric/src/client/java/dan200/computercraft/client/model/EmissiveBakedModel.java deleted file mode 100644 index 3512eb896..000000000 --- a/projects/fabric/src/client/java/dan200/computercraft/client/model/EmissiveBakedModel.java +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.client.model; - -import net.fabricmc.fabric.api.renderer.v1.RendererAccess; -import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; -import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel; -import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper; -import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.util.RandomSource; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.state.BlockState; - -import javax.annotation.Nullable; -import java.util.function.Supplier; - -/** - * Wraps an arbitrary {@link BakedModel} to render a single texture as emissive. - *

- * While Fabric has a quite advanced rendering extension API (including support for custom materials), but unlike Forge - * it doesn't expose this in the model JSON (though externals mods like JMX - * do handle this). - *

- * Instead, we support emissive quads by injecting a {@linkplain CustomModelLoader custom model loader} which wraps the - * baked model in a {@link EmissiveBakedModel}, which renders specific quads as emissive. - */ -public final class EmissiveBakedModel extends ForwardingBakedModel { - private final TextureAtlasSprite emissiveTexture; - private final RenderMaterial defaultMaterial; - private final RenderMaterial emissiveMaterial; - - private EmissiveBakedModel(BakedModel wrapped, TextureAtlasSprite emissiveTexture, RenderMaterial defaultMaterial, RenderMaterial emissiveMaterial) { - this.wrapped = wrapped; - this.emissiveTexture = emissiveTexture; - this.defaultMaterial = defaultMaterial; - this.emissiveMaterial = emissiveMaterial; - } - - public static BakedModel wrap(BakedModel model, TextureAtlasSprite emissiveTexture) { - var renderer = RendererAccess.INSTANCE.getRenderer(); - return renderer == null ? model : new EmissiveBakedModel( - model, - emissiveTexture, - renderer.materialFinder().find(), - renderer.materialFinder().emissive(true).find() - ); - } - - @Override - public boolean isVanillaAdapter() { - return false; - } - - @Override - public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { - emitQuads(context, state, randomSupplier.get()); - } - - @Override - public void emitItemQuads(ItemStack stack, Supplier randomSupplier, RenderContext context) { - emitQuads(context, null, randomSupplier.get()); - } - - private void emitQuads(RenderContext context, @Nullable BlockState state, RandomSource random) { - var emitter = context.getEmitter(); - for (var faceIdx = 0; faceIdx <= ModelHelper.NULL_FACE_ID; faceIdx++) { - var cullFace = ModelHelper.faceFromIndex(faceIdx); - var quads = wrapped.getQuads(state, cullFace, random); - - var count = quads.size(); - for (var i = 0; i < count; i++) { - final var q = quads.get(i); - emitter.fromVanilla(q, q.getSprite() == emissiveTexture ? emissiveMaterial : defaultMaterial, cullFace); - emitter.emit(); - } - } - } -} diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/model/turtle/TurtleModel.java b/projects/fabric/src/client/java/dan200/computercraft/client/model/turtle/TurtleModel.java index 704350b1a..87f913786 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/model/turtle/TurtleModel.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/model/turtle/TurtleModel.java @@ -8,12 +8,14 @@ import dan200.computercraft.client.model.CompositeBakedModel; import dan200.computercraft.client.model.TransformedBakedModel; import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.renderer.block.model.BakedOverrides; import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelBaker; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import javax.annotation.Nullable; +import java.util.List; /** * The custom model for turtle items, which renders tools and overlays as part of the model. @@ -23,20 +25,21 @@ import javax.annotation.Nullable; public class TurtleModel extends ForwardingBakedModel { private final TurtleModelParts parts; - private final ItemOverrides overrides = new ItemOverrides() { - @Override - public BakedModel resolve(BakedModel model, ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) { - return parts.getModel(stack); - } - }; + private final BakedOverrides overrides; - public TurtleModel(BakedModel familyModel, BakedModel colourModel) { + public TurtleModel(ModelBaker baker, BakedModel familyModel, BakedModel colourModel) { wrapped = familyModel; parts = new TurtleModelParts<>(familyModel, colourModel, TransformedBakedModel::new, CompositeBakedModel::of); + overrides = new BakedOverrides(baker, List.of()) { + @Override + public @Nullable BakedModel findOverride(ItemStack stack, @Nullable ClientLevel clientLevel, @Nullable LivingEntity entity, int seed) { + return parts.getModel(stack); + } + }; } @Override - public ItemOverrides getOverrides() { + public BakedOverrides overrides() { return overrides; } } diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/model/turtle/UnbakedTurtleModel.java b/projects/fabric/src/client/java/dan200/computercraft/client/model/turtle/UnbakedTurtleModel.java index e04a7da2c..2d3afbe8f 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/model/turtle/UnbakedTurtleModel.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/model/turtle/UnbakedTurtleModel.java @@ -11,8 +11,6 @@ import net.minecraft.client.resources.model.*; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.GsonHelper; -import java.util.Collection; -import java.util.List; import java.util.function.Function; /** @@ -36,24 +34,15 @@ public final class UnbakedTurtleModel implements UnbakedModel { } @Override - public Collection getDependencies() { - return List.of(model, COLOUR_TURTLE_MODEL); - } - - @Override - public void resolveParents(Function function) { - function.apply(model).resolveParents(function); - function.apply(COLOUR_TURTLE_MODEL).resolveParents(function); + public void resolveDependencies(Resolver resolver) { + resolver.resolve(model); + resolver.resolve(COLOUR_TURTLE_MODEL); } @Override public BakedModel bake(ModelBaker bakery, Function spriteGetter, ModelState transform) { var mainModel = bakery.bake(model, transform); - if (mainModel == null) throw new NullPointerException(model + " failed to bake"); - var colourModel = bakery.bake(COLOUR_TURTLE_MODEL, transform); - if (colourModel == null) throw new NullPointerException(COLOUR_TURTLE_MODEL + " failed to bake"); - - return new TurtleModel(mainModel, colourModel); + return new TurtleModel(bakery, mainModel, colourModel); } } diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java b/projects/fabric/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java index b8eaee2d2..21e933425 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java @@ -44,7 +44,7 @@ public class ClientPlatformHelperImpl implements ClientPlatformHelper { public void renderBakedModel(PoseStack transform, MultiBufferSource buffers, BakedModel model, int lightmapCoord, int overlayLight, @Nullable int[] tints) { // Unfortunately we can't call Fabric's emitItemQuads here, as there's no way to obtain a RenderContext via the // API. Instead, we special case our FoiledModel, and just render everything else normally. - var buffer = ItemRenderer.getFoilBuffer(buffers, Sheets.translucentCullBlockSheet(), true, model instanceof FoiledModel); + var buffer = ItemRenderer.getFoilBuffer(buffers, Sheets.translucentItemSheet(), true, model instanceof FoiledModel); for (var faceIdx = 0; faceIdx <= ModelHelper.NULL_FACE_ID; faceIdx++) { var face = ModelHelper.faceFromIndex(faceIdx); diff --git a/projects/fabric/src/client/java/dan200/computercraft/mixin/client/DebugScreenOverlayMixin.java b/projects/fabric/src/client/java/dan200/computercraft/mixin/client/DebugScreenOverlayMixin.java index 301043a8a..ea92430f2 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/mixin/client/DebugScreenOverlayMixin.java +++ b/projects/fabric/src/client/java/dan200/computercraft/mixin/client/DebugScreenOverlayMixin.java @@ -20,10 +20,4 @@ class DebugScreenOverlayMixin { private void appendBlockDebugInfo(CallbackInfoReturnable> cir) { ClientHooks.addBlockDebugInfo(cir.getReturnValue()::add); } - - @Inject(method = "getGameInformation", at = @At("RETURN")) - @SuppressWarnings("UnusedMethod") - private void appendGameDebugInfo(CallbackInfoReturnable> cir) { - ClientHooks.addGameDebugInfo(cir.getReturnValue()::add); - } } diff --git a/projects/fabric/src/client/java/dan200/computercraft/mixin/client/GameRendererMixin.java b/projects/fabric/src/client/java/dan200/computercraft/mixin/client/GameRendererMixin.java deleted file mode 100644 index a7d123974..000000000 --- a/projects/fabric/src/client/java/dan200/computercraft/mixin/client/GameRendererMixin.java +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.mixin.client; - -import dan200.computercraft.client.ClientRegistry; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.ShaderInstance; -import net.minecraft.server.packs.resources.ResourceProvider; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.Map; - -@Mixin(GameRenderer.class) -class GameRendererMixin { - @Final - @Shadow - @SuppressWarnings("NullAway") - private Map shaders; - - @Inject(method = "reloadShaders", at = @At(value = "TAIL")) - @SuppressWarnings("unused") - private void onReloadShaders(ResourceProvider resourceManager, CallbackInfo ci) { - try { - ClientRegistry.registerShaders(resourceManager, (shader, callback) -> { - shaders.put(shader.getName(), shader); - callback.accept(shader); - }); - } catch (IOException e) { - throw new UncheckedIOException("Could not reload shaders", e); - } - } -} diff --git a/projects/fabric/src/client/java/dan200/computercraft/mixin/client/ItemFrameRendererMixin.java b/projects/fabric/src/client/java/dan200/computercraft/mixin/client/ItemFrameRendererMixin.java index 5be6df1b9..7b1ec3212 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/mixin/client/ItemFrameRendererMixin.java +++ b/projects/fabric/src/client/java/dan200/computercraft/mixin/client/ItemFrameRendererMixin.java @@ -8,7 +8,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import dan200.computercraft.client.ClientHooks; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.ItemFrameRenderer; -import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.client.renderer.entity.state.ItemFrameRenderState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -18,13 +18,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @SuppressWarnings("UnusedMethod") class ItemFrameRendererMixin { @Inject( - method = "render(Lnet/minecraft/world/entity/decoration/ItemFrame;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", + method = "render(Lnet/minecraft/client/renderer/entity/state/ItemFrameRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V", ordinal = 2, shift = At.Shift.AFTER), cancellable = true ) @SuppressWarnings("unused") - private void render(ItemFrame entity, float yaw, float partialTicks, PoseStack pose, MultiBufferSource buffers, int light, CallbackInfo ci) { - if (ClientHooks.onRenderItemFrame(pose, buffers, entity, entity.getItem(), light)) { + private void render(ItemFrameRenderState frame, PoseStack pose, MultiBufferSource buffers, int light, CallbackInfo ci) { + if (ClientHooks.onRenderItemFrame(pose, buffers, frame, frame.itemStack, light)) { ci.cancel(); pose.popPose(); } diff --git a/projects/fabric/src/client/resources/computercraft-client.fabric.mixins.json b/projects/fabric/src/client/resources/computercraft-client.fabric.mixins.json index a39cbc195..cb1d0660e 100644 --- a/projects/fabric/src/client/resources/computercraft-client.fabric.mixins.json +++ b/projects/fabric/src/client/resources/computercraft-client.fabric.mixins.json @@ -10,7 +10,6 @@ "BlockModelAccessor", "BlockRenderDispatcherMixin", "DebugScreenOverlayMixin", - "GameRendererMixin", "ItemFrameRendererMixin", "ItemInHandRendererMixin", "MinecraftMixin", diff --git a/projects/fabric/src/main/java/dan200/computercraft/mixin/EntityMixin.java b/projects/fabric/src/main/java/dan200/computercraft/mixin/EntityMixin.java index 8014b5dee..be503bbf6 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/mixin/EntityMixin.java +++ b/projects/fabric/src/main/java/dan200/computercraft/mixin/EntityMixin.java @@ -5,6 +5,7 @@ package dan200.computercraft.mixin; import dan200.computercraft.shared.CommonHooks; +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; @@ -16,12 +17,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Entity.class) class EntityMixin { @Inject( - method = "spawnAtLocation(Lnet/minecraft/world/item/ItemStack;F)Lnet/minecraft/world/entity/item/ItemEntity;", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"), + method = "spawnAtLocation(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;F)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(ItemStack stack, float yOffset, CallbackInfoReturnable cb) { + private void spawnAtLocation(ServerLevel level, ItemStack stack, float yOffset, CallbackInfoReturnable cb) { if (CommonHooks.onLivingDrop((Entity) (Object) this, stack)) cb.setReturnValue(null); } } diff --git a/projects/fabric/src/main/java/dan200/computercraft/mixin/V3818_3Mixin.java b/projects/fabric/src/main/java/dan200/computercraft/mixin/V3818_3Mixin.java deleted file mode 100644 index 26b7806db..000000000 --- a/projects/fabric/src/main/java/dan200/computercraft/mixin/V3818_3Mixin.java +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.mixin; - -import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import com.mojang.datafixers.schemas.Schema; -import com.mojang.datafixers.types.templates.TypeTemplate; -import dan200.computercraft.shared.util.ComponentizationFixers; -import net.minecraft.util.datafix.schemas.V3818_3; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -/** - * Add our custom data components to the datafixer system. - *

- * This mixin is identical between Fabric and NeoForge aside from using a different method name. - */ -@Mixin(V3818_3.class) -class V3818_3Mixin { - @ModifyReturnValue(method = "method_57277", at = @At("TAIL")) - @SuppressWarnings("UnusedMethod") - private static TypeTemplate addExtraTypes(TypeTemplate type, Schema schema) { - return ComponentizationFixers.addExtraTypes(type, schema); - } -} diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java b/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java index f1ad20411..e0cd05dc1 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java @@ -50,7 +50,6 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.PreparableReloadListener; import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.storage.LevelResource; @@ -158,8 +157,8 @@ public class ComputerCraft { } @Override - public CompletableFuture reload(PreparationBarrier preparationBarrier, ResourceManager resourceManager, ProfilerFiller preparationsProfiler, ProfilerFiller reloadProfiler, Executor backgroundExecutor, Executor gameExecutor) { - return listener.reload(preparationBarrier, resourceManager, preparationsProfiler, reloadProfiler, backgroundExecutor, gameExecutor); + public CompletableFuture reload(PreparationBarrier preparationBarrier, ResourceManager resourceManager, Executor backgroundExecutor, Executor gameExecutor) { + return listener.reload(preparationBarrier, resourceManager, backgroundExecutor, gameExecutor); } } } diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/FabricCommonHooks.java b/projects/fabric/src/main/java/dan200/computercraft/shared/FabricCommonHooks.java index bfcbf2b0c..a48681dce 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/FabricCommonHooks.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/FabricCommonHooks.java @@ -44,7 +44,7 @@ public class FabricCommonHooks { if (player.isSecondaryUseActive() && doesSneakBypassUse(player.getMainHandItem()) && doesSneakBypassUse(player.getOffhandItem())) { var result = block.useItemOn(player.getMainHandItem(), level, player, hand, hitResult); - if (result.consumesAction()) return result.result(); + if (result.consumesAction()) return result; } return InteractionResult.PASS; diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java index 35568523d..1a18ab647 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java @@ -23,7 +23,6 @@ import net.fabricmc.fabric.api.event.player.UseEntityCallback; import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; import net.fabricmc.fabric.api.lookup.v1.block.BlockApiCache; import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup; -import net.fabricmc.fabric.api.registry.FuelRegistry; import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType; import net.fabricmc.fabric.api.tag.convention.v2.ConventionalItemTags; @@ -40,6 +39,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.ItemTags; @@ -56,8 +56,7 @@ import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.*; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -87,7 +86,7 @@ public class PlatformHelperImpl implements PlatformHelper { @SuppressWarnings("unchecked") private static Registry getRegistry(ResourceKey> id) { - var registry = (Registry) BuiltInRegistries.REGISTRY.get(id.location()); + var registry = (Registry) BuiltInRegistries.REGISTRY.getValue(id.location()); if (registry == null) throw new IllegalArgumentException("Unknown registry " + id); return registry; } @@ -146,16 +145,16 @@ public class PlatformHelperImpl implements PlatformHelper { @Override public RecipeIngredients getRecipeIngredients() { return new RecipeIngredients( - Ingredient.of(ConventionalItemTags.REDSTONE_DUSTS), - Ingredient.of(ConventionalItemTags.STRINGS), - Ingredient.of(ConventionalItemTags.LEATHERS), - Ingredient.of(ConventionalItemTags.GLASS_PANES), - Ingredient.of(ConventionalItemTags.GOLD_INGOTS), - Ingredient.of(ConventionalItemTags.STORAGE_BLOCKS_GOLD), - Ingredient.of(ConventionalItemTags.IRON_INGOTS), - Ingredient.of(ConventionalItemTags.DYES), - Ingredient.of(ConventionalItemTags.ENDER_PEARLS), - Ingredient.of(ConventionalItemTags.WOODEN_CHESTS) + ConventionalItemTags.REDSTONE_DUSTS, + ConventionalItemTags.STRINGS, + ConventionalItemTags.LEATHERS, + ConventionalItemTags.GLASS_PANES, + ConventionalItemTags.GOLD_INGOTS, + ConventionalItemTags.STORAGE_BLOCKS_GOLD, + ConventionalItemTags.IRON_INGOTS, + ConventionalItemTags.DYES, + ConventionalItemTags.ENDER_PEARLS, + ConventionalItemTags.WOODEN_CHESTS ); } @@ -182,9 +181,8 @@ public class PlatformHelperImpl implements PlatformHelper { } @Override - public int getBurnTime(ItemStack stack) { - @Nullable var fuel = FuelRegistry.INSTANCE.get(stack.getItem()); - return fuel == null ? 0 : fuel; + public int getBurnTime(MinecraftServer server, ItemStack stack) { + return server.fuelValues().burnDuration(stack); } @Override @@ -198,7 +196,7 @@ public class PlatformHelperImpl implements PlatformHelper { } @Override - public List getRecipeRemainingItems(ServerPlayer player, Recipe recipe, CraftingInput container) { + public List getRecipeRemainingItems(ServerPlayer player, CraftingRecipe recipe, CraftingInput container) { return recipe.getRemainingItems(container); } @@ -230,6 +228,7 @@ public class PlatformHelperImpl implements PlatformHelper { @Override public boolean interactWithEntity(ServerPlayer player, Entity entity, Vec3 hitPos) { + // TODO: Properly handle return UseEntityCallback.EVENT.invoker().interact(player, entity.level(), InteractionHand.MAIN_HAND, entity, new EntityHitResult(entity, hitPos)).consumesAction() || entity.interactAt(player, hitPos.subtract(entity.position()), InteractionHand.MAIN_HAND).consumesAction() || player.interactOn(entity, InteractionHand.MAIN_HAND).consumesAction(); @@ -243,7 +242,7 @@ public class PlatformHelperImpl implements PlatformHelper { var block = player.level().getBlockState(hit.getBlockPos()); if (!block.isAir() && canUseBlock.test(block)) { var useResult = block.useItemOn(stack, player.level(), player, InteractionHand.MAIN_HAND, hit); - if (useResult.consumesAction()) return useResult.result(); + if (useResult.consumesAction()) return useResult; // TODO(1.20.5): Should we do this unconditionally now? Or at least a better way of configuring it. // TODO(1.20.5: What to do with useWithoutItem diff --git a/projects/fabric/src/main/resources/fabric.mod.json b/projects/fabric/src/main/resources/fabric.mod.json index 0e3f19a7e..fd5036d0d 100644 --- a/projects/fabric/src/main/resources/fabric.mod.json +++ b/projects/fabric/src/main/resources/fabric.mod.json @@ -47,7 +47,7 @@ "depends": { "fabricloader": ">=0.15.10", "fabric-api": ">=0.102.1", - "minecraft": "=1.21.1" + "minecraft": "=1.21.3" }, "accessWidener": "computercraft.accesswidener" } diff --git a/projects/forge/build.gradle.kts b/projects/forge/build.gradle.kts index 2b8f2feda..343de48e2 100644 --- a/projects/forge/build.gradle.kts +++ b/projects/forge/build.gradle.kts @@ -54,12 +54,12 @@ runs { val server by registering { workingDirectory(file("run/server")) - programArgument("--nogui") + argument("--nogui") } val data by registering { workingDirectory(file("run")) - programArguments.addAll( + arguments.addAll( "--mod", "computercraft", "--all", "--output", layout.buildDirectory.dir("generatedResources").getAbsolutePath(), "--existing", project(":common").file("src/main/resources/").absolutePath, diff --git a/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientHooks.java b/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientHooks.java index 722dbb203..221368fb3 100644 --- a/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientHooks.java +++ b/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientHooks.java @@ -47,7 +47,6 @@ public final class ForgeClientHooks { @SubscribeEvent public static void onRenderText(CustomizeGuiOverlayEvent.DebugText event) { - ClientHooks.addGameDebugInfo(event.getLeft()::add); ClientHooks.addBlockDebugInfo(event.getRight()::add); } @@ -64,7 +63,7 @@ public final class ForgeClientHooks { @SubscribeEvent public static void onRenderInFrame(RenderItemInFrameEvent event) { if (ClientHooks.onRenderItemFrame( - event.getPoseStack(), event.getMultiBufferSource(), event.getItemFrameEntity(), event.getItemStack(), event.getPackedLight() + event.getPoseStack(), event.getMultiBufferSource(), event.getItemFrameRenderState(), event.getItemStack(), event.getPackedLight() )) { event.setCanceled(true); } diff --git a/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientRegistry.java b/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientRegistry.java index 84704d7da..7023a622f 100644 --- a/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientRegistry.java +++ b/projects/forge/src/client/java/dan200/computercraft/client/ForgeClientRegistry.java @@ -18,9 +18,11 @@ import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.ModLoader; import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; -import net.neoforged.neoforge.client.event.*; +import net.neoforged.neoforge.client.event.ModelEvent; +import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent; +import net.neoforged.neoforge.client.event.RegisterColorHandlersEvent; +import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent; -import java.io.IOException; /** * Registers textures and models for items. @@ -62,11 +64,6 @@ public final class ForgeClientRegistry { ClientRegistry.registerExtraModels(x -> event.register(ModelResourceLocation.standalone(x)), extraModels); } - @SubscribeEvent - public static void registerShaders(RegisterShadersEvent event) throws IOException { - ClientRegistry.registerShaders(event.getResourceProvider(), event::registerShader); - } - @SubscribeEvent public static void onTurtleModellers(RegisterTurtleModellersEvent event) { ClientRegistry.registerTurtleModellers(event); diff --git a/projects/forge/src/client/java/dan200/computercraft/client/model/FoiledModel.java b/projects/forge/src/client/java/dan200/computercraft/client/model/FoiledModel.java index 430582937..9ac3eec75 100644 --- a/projects/forge/src/client/java/dan200/computercraft/client/model/FoiledModel.java +++ b/projects/forge/src/client/java/dan200/computercraft/client/model/FoiledModel.java @@ -34,8 +34,8 @@ public final class FoiledModel extends BakedModelWrapper { } @Override - public List getRenderTypes(ItemStack itemStack, boolean fabulous) { - return new ConsList<>(fabulous ? RenderType.glintTranslucent() : RenderType.glint(), super.getRenderTypes(itemStack, fabulous)); + public List getRenderTypes(ItemStack itemStack) { + return new ConsList<>(RenderType.glint(), super.getRenderTypes(itemStack)); } @Override diff --git a/projects/forge/src/client/java/dan200/computercraft/client/model/turtle/TurtleModel.java b/projects/forge/src/client/java/dan200/computercraft/client/model/turtle/TurtleModel.java index d1eec732b..76fb34dd3 100644 --- a/projects/forge/src/client/java/dan200/computercraft/client/model/turtle/TurtleModel.java +++ b/projects/forge/src/client/java/dan200/computercraft/client/model/turtle/TurtleModel.java @@ -34,7 +34,7 @@ public class TurtleModel extends BakedModelWrapper { } @Override - public List getRenderPasses(ItemStack stack, boolean fabulous) { + public List getRenderPasses(ItemStack stack) { return parts.getModel(stack); } } diff --git a/projects/forge/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelLoader.java b/projects/forge/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelLoader.java index 34a042428..bd0e9401d 100644 --- a/projects/forge/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelLoader.java +++ b/projects/forge/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelLoader.java @@ -7,18 +7,16 @@ package dan200.computercraft.client.model.turtle; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; import dan200.computercraft.api.ComputerCraftAPI; -import net.minecraft.client.renderer.block.model.ItemOverrides; +import net.minecraft.client.renderer.block.model.ItemOverride; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.Material; -import net.minecraft.client.resources.model.ModelBaker; -import net.minecraft.client.resources.model.ModelState; +import net.minecraft.client.resources.model.*; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.GsonHelper; import net.neoforged.neoforge.client.model.geometry.IGeometryBakingContext; import net.neoforged.neoforge.client.model.geometry.IGeometryLoader; import net.neoforged.neoforge.client.model.geometry.IUnbakedGeometry; +import java.util.List; import java.util.function.Function; /** @@ -49,13 +47,16 @@ public final class TurtleModelLoader implements IGeometryLoader spriteGetter, ModelState transform, ItemOverrides overrides) { + public void resolveDependencies(UnbakedModel.Resolver modelGetter, IGeometryBakingContext context) { + IUnbakedGeometry.super.resolveDependencies(modelGetter, context); + modelGetter.resolve(family); + modelGetter.resolve(COLOUR_TURTLE_MODEL); + } + + @Override + public BakedModel bake(IGeometryBakingContext context, ModelBaker bakery, Function spriteGetter, ModelState transform, List overrides) { var mainModel = bakery.bake(family, transform, spriteGetter); - if (mainModel == null) throw new NullPointerException(family + " failed to bake"); - var colourModel = bakery.bake(COLOUR_TURTLE_MODEL, transform, spriteGetter); - if (colourModel == null) throw new NullPointerException(COLOUR_TURTLE_MODEL + " failed to bake"); - return new TurtleModel(mainModel, colourModel); } } diff --git a/projects/forge/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java b/projects/forge/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java index 2e1c72ed6..08ef1c004 100644 --- a/projects/forge/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java +++ b/projects/forge/src/client/java/dan200/computercraft/client/platform/ClientPlatformHelperImpl.java @@ -43,7 +43,7 @@ public class ClientPlatformHelperImpl implements ClientPlatformHelper { @Override public void renderBakedModel(PoseStack transform, MultiBufferSource buffers, BakedModel model, int lightmapCoord, int overlayLight, @Nullable int[] tints) { - for (var renderType : model.getRenderTypes(ItemStack.EMPTY, true)) { + for (var renderType : model.getRenderTypes(ItemStack.EMPTY)) { var buffer = buffers.getBuffer(renderType); for (var face : directions) { random.setSeed(42); diff --git a/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java b/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java index d0698b576..ca7720292 100644 --- a/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java +++ b/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java @@ -27,6 +27,7 @@ import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.TagKey; @@ -43,8 +44,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -142,16 +142,16 @@ public class PlatformHelperImpl implements PlatformHelper { @Override public RecipeIngredients getRecipeIngredients() { return new RecipeIngredients( - Ingredient.of(Tags.Items.DUSTS_REDSTONE), - Ingredient.of(Tags.Items.STRINGS), - Ingredient.of(Tags.Items.LEATHERS), - Ingredient.of(Tags.Items.GLASS_PANES), - Ingredient.of(Tags.Items.INGOTS_GOLD), - Ingredient.of(Tags.Items.STORAGE_BLOCKS_GOLD), - Ingredient.of(Tags.Items.INGOTS_IRON), - Ingredient.of(Tags.Items.DYES), - Ingredient.of(Tags.Items.ENDER_PEARLS), - Ingredient.of(Tags.Items.CHESTS_WOODEN) + Tags.Items.DUSTS_REDSTONE, + Tags.Items.STRINGS, + Tags.Items.LEATHERS, + Tags.Items.GLASS_PANES, + Tags.Items.INGOTS_GOLD, + Tags.Items.STORAGE_BLOCKS_GOLD, + Tags.Items.INGOTS_IRON, + Tags.Items.DYES, + Tags.Items.ENDER_PEARLS, + Tags.Items.CHESTS_WOODEN ); } @@ -178,8 +178,8 @@ public class PlatformHelperImpl implements PlatformHelper { } @Override - public int getBurnTime(ItemStack stack) { - return stack.getBurnTime(null); + public int getBurnTime(MinecraftServer server, ItemStack stack) { + return stack.getBurnTime(null, server.fuelValues()); } @Override @@ -189,11 +189,11 @@ public class PlatformHelperImpl implements PlatformHelper { @Override public ItemStack getCraftingRemainingItem(ItemStack stack) { - return stack.getCraftingRemainingItem(); + return stack.getCraftingRemainder(); } @Override - public List getRecipeRemainingItems(ServerPlayer player, Recipe recipe, CraftingInput container) { + public List getRecipeRemainingItems(ServerPlayer player, CraftingRecipe recipe, CraftingInput container) { CommonHooks.setCraftingPlayer(player); var result = recipe.getRemainingItems(container); CommonHooks.setCraftingPlayer(null); @@ -253,7 +253,7 @@ public class PlatformHelperImpl implements PlatformHelper { var block = level.getBlockState(hit.getBlockPos()); if (!event.getUseBlock().isFalse() && !block.isAir() && canUseBlock.test(block)) { var useResult = block.useItemOn(stack, level, player, InteractionHand.MAIN_HAND, hit); - if (useResult.consumesAction()) return useResult.result(); + if (useResult.consumesAction()) return useResult; } return event.getUseItem().isFalse() ? InteractionResult.PASS : stack.useOn(context); diff --git a/projects/forge/src/main/resources/META-INF/accesstransformer.cfg b/projects/forge/src/main/resources/META-INF/accesstransformer.cfg index dcfea532f..11db6ffed 100644 --- a/projects/forge/src/main/resources/META-INF/accesstransformer.cfg +++ b/projects/forge/src/main/resources/META-INF/accesstransformer.cfg @@ -3,12 +3,7 @@ # SPDX-License-Identifier: MPL-2.0 # DirectVertexBuffer -protected com.mojang.blaze3d.vertex.VertexBuffer vertexBufferId -protected com.mojang.blaze3d.vertex.VertexBuffer indexType -protected com.mojang.blaze3d.vertex.VertexBuffer indexCount -protected com.mojang.blaze3d.vertex.VertexBuffer mode -protected com.mojang.blaze3d.vertex.VertexBuffer sequentialIndices -protected com.mojang.blaze3d.vertex.VertexBuffer format +public com.mojang.blaze3d.vertex.VertexBuffer indexCount # ClientTableFormatter public net.minecraft.client.gui.components.ChatComponent allMessages diff --git a/projects/forge/src/main/resources/META-INF/neoforge.mods.toml b/projects/forge/src/main/resources/META-INF/neoforge.mods.toml index 23444c070..d5ec86e85 100644 --- a/projects/forge/src/main/resources/META-INF/neoforge.mods.toml +++ b/projects/forge/src/main/resources/META-INF/neoforge.mods.toml @@ -26,15 +26,12 @@ CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles a [[dependencies.computercraft]] modId="neoforge" type="required" - versionRange="[${neoVersion},21.2)" + versionRange="[${neoVersion},21.4)" ordering="NONE" side="BOTH" [[mixins]] config = "computercraft.mixins.json" -[[mixins]] -config = "computercraft.forge.mixins.json" - [[mixins]] config = "computercraft-client.forge.mixins.json" diff --git a/projects/forge/src/main/resources/computercraft.forge.mixins.json b/projects/forge/src/main/resources/computercraft.forge.mixins.json deleted file mode 100644 index d6200c770..000000000 --- a/projects/forge/src/main/resources/computercraft.forge.mixins.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "required": true, - "package": "dan200.computercraft.mixin", - "minVersion": "0.8", - "compatibilityLevel": "JAVA_21", - "injectors": { - "defaultRequire": 1 - }, - "mixins": [ - "V3818_3Mixin" - ] -}