mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 21:52:59 +00:00 
			
		
		
		
	Update to 1.20
- Use GuiGraphics for rendering UI elements. Almost definitely some z-fighting issues slipped in here. - Use Forge's loot modifier system for handling treasure disks. I have mixed feelings about this - it's a nice system, but also is far less efficient than the previous approach. - Regenerate data. This is the brunt of the commit, but nothing especially interesting here.
This commit is contained in:
		| @@ -13,4 +13,4 @@ isUnstable=false | ||||
| modVersion=1.104.0 | ||||
|  | ||||
| # Minecraft properties: We want to configure this here so we can read it in settings.gradle | ||||
| mcVersion=1.19.4 | ||||
| mcVersion=1.20 | ||||
|   | ||||
| @@ -7,9 +7,9 @@ | ||||
| # Minecraft | ||||
| # MC version is specified in gradle.properties, as we need that in settings.gradle. | ||||
| # Remember to update corresponding versions in fabric.mod.json/mods.toml | ||||
| fabric-api = "0.80.0+1.19.4" | ||||
| fabric-loader = "0.14.19" | ||||
| forge = "45.0.42" | ||||
| fabric-api = "0.83.0+1.20" | ||||
| fabric-loader = "0.14.21" | ||||
| forge = "46.0.1" | ||||
| forgeSpi = "6.0.0" | ||||
| mixin = "0.8.5" | ||||
| parchment = "2023.03.12" | ||||
| @@ -150,10 +150,10 @@ kotlin = ["kotlin-stdlib", "kotlin-coroutines"] | ||||
| # Minecraft | ||||
| externalMods-common = ["jei-api", "nightConfig-core", "nightConfig-toml"] | ||||
| externalMods-forge-compile = ["oculus", "jei-api"] | ||||
| externalMods-forge-runtime = ["jei-forge"] | ||||
| externalMods-forge-runtime = [] | ||||
| externalMods-fabric = ["nightConfig-core", "nightConfig-toml"] | ||||
| externalMods-fabric-compile = ["iris", "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"] | ||||
|   | ||||
| @@ -4,7 +4,6 @@ | ||||
| 
 | ||||
| package dan200.computercraft.client.gui; | ||||
| 
 | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import dan200.computercraft.client.gui.widgets.ComputerSidebar; | ||||
| import dan200.computercraft.client.gui.widgets.DynamicImageButton; | ||||
| import dan200.computercraft.client.gui.widgets.TerminalWidget; | ||||
| @@ -19,6 +18,7 @@ import dan200.computercraft.shared.config.Config; | ||||
| import dan200.computercraft.shared.network.server.UploadFileMessage; | ||||
| import net.minecraft.ChatFormatting; | ||||
| import net.minecraft.Util; | ||||
| import net.minecraft.client.gui.GuiGraphics; | ||||
| import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; | ||||
| import net.minecraft.network.chat.Component; | ||||
| import net.minecraft.world.entity.player.Inventory; | ||||
| @@ -124,10 +124,10 @@ public abstract class AbstractComputerScreen<T extends AbstractComputerMenu> ext | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void render(PoseStack stack, int mouseX, int mouseY, float partialTicks) { | ||||
|         renderBackground(stack); | ||||
|         super.render(stack, mouseX, mouseY, partialTicks); | ||||
|         renderTooltip(stack, mouseX, mouseY); | ||||
|     public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { | ||||
|         renderBackground(graphics); | ||||
|         super.render(graphics, mouseX, mouseY, partialTicks); | ||||
|         renderTooltip(graphics, mouseX, mouseY); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| @@ -147,7 +147,7 @@ public abstract class AbstractComputerScreen<T extends AbstractComputerMenu> ext | ||||
| 
 | ||||
| 
 | ||||
|     @Override | ||||
|     protected void renderLabels(PoseStack transform, int mouseX, int mouseY) { | ||||
|     protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) { | ||||
|         // Skip rendering labels. | ||||
|     } | ||||
| 
 | ||||
|   | ||||
| @@ -4,11 +4,11 @@ | ||||
| 
 | ||||
| package dan200.computercraft.client.gui; | ||||
| 
 | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import dan200.computercraft.client.gui.widgets.ComputerSidebar; | ||||
| import dan200.computercraft.client.gui.widgets.TerminalWidget; | ||||
| import dan200.computercraft.client.render.ComputerBorderRenderer; | ||||
| import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu; | ||||
| import net.minecraft.client.gui.GuiGraphics; | ||||
| import net.minecraft.network.chat.Component; | ||||
| import net.minecraft.world.entity.player.Inventory; | ||||
| 
 | ||||
| @@ -36,13 +36,14 @@ public final class ComputerScreen<T extends AbstractComputerMenu> extends Abstra | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void renderBg(PoseStack stack, float partialTicks, int mouseX, int mouseY) { | ||||
|     public void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { | ||||
|         // Draw a border around the terminal | ||||
|         var terminal = getTerminal(); | ||||
|         var texture = ComputerBorderRenderer.getTexture(family); | ||||
|         ComputerBorderRenderer.render( | ||||
|             stack.last().pose(), ComputerBorderRenderer.getTexture(family), terminal.getX(), terminal.getY(), | ||||
|             graphics.pose().last().pose(), texture, terminal.getX(), terminal.getY(), | ||||
|             FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight() | ||||
|         ); | ||||
|         ComputerSidebar.renderBackground(stack, leftPos, topPos + sidebarYOffset); | ||||
|         ComputerSidebar.renderBackground(graphics, texture, leftPos, topPos + sidebarYOffset); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,9 +4,8 @@ | ||||
| 
 | ||||
| package dan200.computercraft.client.gui; | ||||
| 
 | ||||
| import com.mojang.blaze3d.systems.RenderSystem; | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveMenu; | ||||
| import net.minecraft.client.gui.GuiGraphics; | ||||
| import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; | ||||
| import net.minecraft.network.chat.Component; | ||||
| import net.minecraft.resources.ResourceLocation; | ||||
| @@ -23,16 +22,14 @@ public class DiskDriveScreen extends AbstractContainerScreen<DiskDriveMenu> { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void renderBg(PoseStack transform, float partialTicks, int mouseX, int mouseY) { | ||||
|         RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); | ||||
|         RenderSystem.setShaderTexture(0, BACKGROUND); | ||||
|         blit(transform, leftPos, topPos, 0, 0, imageWidth, imageHeight); | ||||
|     protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { | ||||
|         graphics.blit(BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void render(PoseStack transform, int mouseX, int mouseY, float partialTicks) { | ||||
|         renderBackground(transform); | ||||
|         super.render(transform, mouseX, mouseY, partialTicks); | ||||
|         renderTooltip(transform, mouseX, mouseY); | ||||
|     public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { | ||||
|         renderBackground(graphics); | ||||
|         super.render(graphics, mouseX, mouseY, partialTicks); | ||||
|         renderTooltip(graphics, mouseX, mouseY); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,10 +4,8 @@ | ||||
| 
 | ||||
| package dan200.computercraft.client.gui; | ||||
| 
 | ||||
| import com.mojang.blaze3d.systems.RenderSystem; | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.client.gui.GuiComponent; | ||||
| 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.network.chat.Component; | ||||
| @@ -73,55 +71,52 @@ public class ItemToast implements Toast { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Visibility render(PoseStack transform, ToastComponent component, long time) { | ||||
|     public Visibility render(GuiGraphics graphics, ToastComponent component, long time) { | ||||
|         if (isNew) { | ||||
| 
 | ||||
|             firstDisplay = time; | ||||
|             isNew = false; | ||||
|         } | ||||
| 
 | ||||
|         RenderSystem.setShaderTexture(0, TEXTURE); | ||||
|         RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); | ||||
| 
 | ||||
|         if (width == 160 && message.size() <= 1) { | ||||
|             GuiComponent.blit(transform, 0, 0, 0, 64, width, height()); | ||||
|             graphics.blit(TEXTURE, 0, 0, 0, 64, width, height()); | ||||
|         } else { | ||||
| 
 | ||||
|             var height = height(); | ||||
| 
 | ||||
|             var bottom = Math.min(4, height - 28); | ||||
|             renderBackgroundRow(transform, component, width, 0, 0, 28); | ||||
|             renderBackgroundRow(graphics, width, 0, 0, 28); | ||||
| 
 | ||||
|             for (var i = 28; i < height - bottom; i += 10) { | ||||
|                 renderBackgroundRow(transform, component, width, 16, i, Math.min(16, height - i - bottom)); | ||||
|                 renderBackgroundRow(graphics, width, 16, i, Math.min(16, height - i - bottom)); | ||||
|             } | ||||
| 
 | ||||
|             renderBackgroundRow(transform, component, width, 32 - bottom, height - bottom, bottom); | ||||
|             renderBackgroundRow(graphics, width, 32 - bottom, height - bottom, bottom); | ||||
|         } | ||||
| 
 | ||||
|         var textX = MARGIN; | ||||
|         if (!stack.isEmpty()) { | ||||
|             textX += MARGIN + IMAGE_SIZE; | ||||
|             component.getMinecraft().getItemRenderer().renderAndDecorateFakeItem(transform, stack, MARGIN, MARGIN + height() / 2 - IMAGE_SIZE); | ||||
|             graphics.renderFakeItem(stack, MARGIN, MARGIN + height() / 2 - IMAGE_SIZE); | ||||
|         } | ||||
| 
 | ||||
|         component.getMinecraft().font.draw(transform, title, textX, MARGIN, 0xff500050); | ||||
|         graphics.drawString(component.getMinecraft().font, title, textX, MARGIN, 0xff500050); | ||||
|         for (var i = 0; i < message.size(); ++i) { | ||||
|             component.getMinecraft().font.draw(transform, message.get(i), textX, (float) (LINE_SPACING + (i + 1) * LINE_SPACING), 0xff000000); | ||||
|             graphics.drawString(component.getMinecraft().font, message.get(i), textX, LINE_SPACING + (i + 1) * LINE_SPACING, 0xff000000); | ||||
|         } | ||||
| 
 | ||||
|         return time - firstDisplay < DISPLAY_TIME ? Visibility.SHOW : Visibility.HIDE; | ||||
|     } | ||||
| 
 | ||||
|     private static void renderBackgroundRow(PoseStack transform, ToastComponent component, int x, int u, int y, int height) { | ||||
|     private static void renderBackgroundRow(GuiGraphics graphics, int x, int u, int y, int height) { | ||||
|         var leftOffset = 5; | ||||
|         var rightOffset = Math.min(60, x - leftOffset); | ||||
| 
 | ||||
|         GuiComponent.blit(transform, 0, y, 0, 32 + u, leftOffset, height); | ||||
|         graphics.blit(TEXTURE, 0, y, 0, 32 + u, leftOffset, height); | ||||
|         for (var k = leftOffset; k < x - rightOffset; k += 64) { | ||||
|             GuiComponent.blit(transform, k, y, 32, 32 + u, Math.min(64, x - k - rightOffset), height); | ||||
|             graphics.blit(TEXTURE, k, y, 32, 32 + u, Math.min(64, x - k - rightOffset), height); | ||||
|         } | ||||
| 
 | ||||
|         GuiComponent.blit(transform, x - rightOffset, y, 160 - rightOffset, 32 + u, rightOffset, height); | ||||
|         graphics.blit(TEXTURE, x - rightOffset, y, 160 - rightOffset, 32 + u, rightOffset, height); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,11 +4,11 @@ | ||||
| 
 | ||||
| package dan200.computercraft.client.gui; | ||||
| 
 | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import dan200.computercraft.client.gui.widgets.TerminalWidget; | ||||
| import dan200.computercraft.core.terminal.Terminal; | ||||
| import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu; | ||||
| import net.minecraft.client.KeyMapping; | ||||
| import net.minecraft.client.gui.GuiGraphics; | ||||
| import net.minecraft.client.gui.screens.Screen; | ||||
| import net.minecraft.client.gui.screens.inventory.MenuAccess; | ||||
| import net.minecraft.network.chat.Component; | ||||
| @@ -42,7 +42,7 @@ public class NoTermComputerScreen<T extends AbstractComputerMenu> extends Screen | ||||
| 
 | ||||
|     @Override | ||||
|     protected void init() { | ||||
|         passEvents = true; // Pass mouse vents through to the game's mouse handler. | ||||
|         // FIXME: passEvents = true; // Pass mouse vents through to the game's mouse handler. | ||||
|         // First ensure we're still grabbing the mouse, so the user can look around. Then reset bits of state that | ||||
|         // grabbing unsets. | ||||
|         minecraft.mouseHandler.grabMouse(); | ||||
| @@ -91,15 +91,15 @@ public class NoTermComputerScreen<T extends AbstractComputerMenu> extends Screen | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void render(PoseStack transform, int mouseX, int mouseY, float partialTicks) { | ||||
|         super.render(transform, mouseX, mouseY, partialTicks); | ||||
|     public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { | ||||
|         super.render(graphics, mouseX, mouseY, partialTicks); | ||||
| 
 | ||||
|         var font = minecraft.font; | ||||
|         var lines = font.split(Component.translatable("gui.computercraft.pocket_computer_overlay"), (int) (width * 0.8)); | ||||
|         var y = 10.0f; | ||||
|         var y = 10; | ||||
|         for (var line : lines) { | ||||
|             font.drawShadow(transform, line, (float) ((width / 2) - (minecraft.font.width(line) / 2)), y, 0xFFFFFF); | ||||
|             y += 9.0f; | ||||
|             graphics.drawString(font, line, (width / 2) - (minecraft.font.width(line) / 2), y, 0xFFFFFF, true); | ||||
|             y += 9; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,9 +4,8 @@ | ||||
| 
 | ||||
| package dan200.computercraft.client.gui; | ||||
| 
 | ||||
| import com.mojang.blaze3d.systems.RenderSystem; | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.client.gui.GuiGraphics; | ||||
| import net.minecraft.client.gui.components.AbstractWidget; | ||||
| import net.minecraft.client.gui.components.Button; | ||||
| import net.minecraft.client.gui.components.MultiLineLabel; | ||||
| @@ -86,20 +85,19 @@ public final class OptionScreen extends Screen { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void render(PoseStack transform, int mouseX, int mouseY, float partialTicks) { | ||||
|         renderBackground(transform); | ||||
|     public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { | ||||
|         renderBackground(graphics); | ||||
| 
 | ||||
|         // Render the actual texture. | ||||
|         RenderSystem.setShaderTexture(0, BACKGROUND); | ||||
|         blit(transform, x, y, 0, 0, innerWidth, PADDING); | ||||
|         blit(transform, | ||||
|         graphics.blit(BACKGROUND, x, y, 0, 0, innerWidth, PADDING); | ||||
|         graphics.blit(BACKGROUND, | ||||
|             x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2, | ||||
|             innerWidth, PADDING | ||||
|         ); | ||||
|         blit(transform, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING); | ||||
|         graphics.blit(BACKGROUND, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING); | ||||
| 
 | ||||
|         assertNonNull(messageRenderer).renderLeftAlignedNoShadow(transform, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040); | ||||
|         super.render(transform, mouseX, mouseY, partialTicks); | ||||
|         assertNonNull(messageRenderer).renderLeftAlignedNoShadow(graphics, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040); | ||||
|         super.render(graphics, mouseX, mouseY, partialTicks); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|   | ||||
| @@ -4,9 +4,8 @@ | ||||
| 
 | ||||
| package dan200.computercraft.client.gui; | ||||
| 
 | ||||
| import com.mojang.blaze3d.systems.RenderSystem; | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import dan200.computercraft.shared.peripheral.printer.PrinterMenu; | ||||
| import net.minecraft.client.gui.GuiGraphics; | ||||
| import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; | ||||
| import net.minecraft.network.chat.Component; | ||||
| import net.minecraft.resources.ResourceLocation; | ||||
| @@ -23,18 +22,16 @@ public class PrinterScreen extends AbstractContainerScreen<PrinterMenu> { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void renderBg(PoseStack transform, float partialTicks, int mouseX, int mouseY) { | ||||
|         RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); | ||||
|         RenderSystem.setShaderTexture(0, BACKGROUND); | ||||
|         blit(transform, leftPos, topPos, 0, 0, imageWidth, imageHeight); | ||||
|     protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { | ||||
|         graphics.blit(BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight); | ||||
| 
 | ||||
|         if (getMenu().isPrinting()) blit(transform, leftPos + 34, topPos + 21, 176, 0, 25, 45); | ||||
|         if (getMenu().isPrinting()) graphics.blit(BACKGROUND, leftPos + 34, topPos + 21, 176, 0, 25, 45); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void render(PoseStack stack, int mouseX, int mouseY, float partialTicks) { | ||||
|         renderBackground(stack); | ||||
|         super.render(stack, mouseX, mouseY, partialTicks); | ||||
|         renderTooltip(stack, mouseX, mouseY); | ||||
|     public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { | ||||
|         renderBackground(graphics); | ||||
|         super.render(graphics, mouseX, mouseY, partialTicks); | ||||
|         renderTooltip(graphics, mouseX, mouseY); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,12 +4,11 @@ | ||||
| 
 | ||||
| package dan200.computercraft.client.gui; | ||||
| 
 | ||||
| import com.mojang.blaze3d.systems.RenderSystem; | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import com.mojang.blaze3d.vertex.Tesselator; | ||||
| import dan200.computercraft.core.terminal.TextBuffer; | ||||
| import dan200.computercraft.shared.common.HeldItemMenu; | ||||
| import dan200.computercraft.shared.media.items.PrintoutItem; | ||||
| import net.minecraft.client.gui.GuiGraphics; | ||||
| import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; | ||||
| import net.minecraft.client.renderer.MultiBufferSource; | ||||
| import net.minecraft.network.chat.Component; | ||||
| @@ -83,30 +82,27 @@ public class PrintoutScreen extends AbstractContainerScreen<HeldItemMenu> { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void renderBg(PoseStack transform, float partialTicks, int mouseX, int mouseY) { | ||||
|     protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { | ||||
|         // Draw the printout | ||||
|         RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); | ||||
|         RenderSystem.enableDepthTest(); | ||||
| 
 | ||||
|         var renderer = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder()); | ||||
|         drawBorder(transform, renderer, leftPos, topPos, 0, page, pages, book, FULL_BRIGHT_LIGHTMAP); | ||||
|         drawText(transform, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutItem.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours); | ||||
|         drawBorder(graphics.pose(), renderer, leftPos, topPos, 0, page, pages, book, FULL_BRIGHT_LIGHTMAP); | ||||
|         drawText(graphics.pose(), renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutItem.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours); | ||||
|         renderer.endBatch(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void render(PoseStack stack, int mouseX, int mouseY, float partialTicks) { | ||||
|     public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { | ||||
|         // We must take the background further back in order to not overlap with our printed pages. | ||||
|         stack.pushPose(); | ||||
|         stack.translate(0, 0, -1); | ||||
|         renderBackground(stack); | ||||
|         stack.popPose(); | ||||
|         graphics.pose().pushPose(); | ||||
|         graphics.pose().translate(0, 0, -1); | ||||
|         renderBackground(graphics); | ||||
|         graphics.pose().popPose(); | ||||
| 
 | ||||
|         super.render(stack, mouseX, mouseY, partialTicks); | ||||
|         super.render(graphics, mouseX, mouseY, partialTicks); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void renderLabels(PoseStack transform, int mouseX, int mouseY) { | ||||
|     protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) { | ||||
|         // Skip rendering labels. | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,8 +4,6 @@ | ||||
| 
 | ||||
| package dan200.computercraft.client.gui; | ||||
| 
 | ||||
| import com.mojang.blaze3d.systems.RenderSystem; | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import dan200.computercraft.api.ComputerCraftAPI; | ||||
| import dan200.computercraft.client.gui.widgets.ComputerSidebar; | ||||
| import dan200.computercraft.client.gui.widgets.TerminalWidget; | ||||
| @@ -13,6 +11,7 @@ import dan200.computercraft.client.render.ComputerBorderRenderer; | ||||
| 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.network.chat.Component; | ||||
| import net.minecraft.resources.ResourceLocation; | ||||
| import net.minecraft.world.entity.player.Inventory; | ||||
| @@ -42,23 +41,21 @@ public class TurtleScreen extends AbstractComputerScreen<TurtleMenu> { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void renderBg(PoseStack transform, float partialTicks, int mouseX, int mouseY) { | ||||
|     protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { | ||||
|         var advanced = family == ComputerFamily.ADVANCED; | ||||
|         RenderSystem.setShaderTexture(0, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL); | ||||
|         blit(transform, leftPos + AbstractComputerMenu.SIDEBAR_WIDTH, topPos, 0, 0, TEX_WIDTH, TEX_HEIGHT); | ||||
|         var texture = advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL; | ||||
|         graphics.blit(texture, leftPos + AbstractComputerMenu.SIDEBAR_WIDTH, topPos, 0, 0, TEX_WIDTH, TEX_HEIGHT); | ||||
| 
 | ||||
|         var slot = getMenu().getSelectedSlot(); | ||||
|         if (slot >= 0) { | ||||
|             RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); | ||||
|             var slotX = slot % 4; | ||||
|             var slotY = slot / 4; | ||||
|             blit(transform, | ||||
|             graphics.blit(texture, | ||||
|                 leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18, | ||||
|                 0, 217, 24, 24 | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         RenderSystem.setShaderTexture(0, advanced ? ComputerBorderRenderer.BACKGROUND_ADVANCED : ComputerBorderRenderer.BACKGROUND_NORMAL); | ||||
|         ComputerSidebar.renderBackground(transform, leftPos, topPos + sidebarYOffset); | ||||
|         ComputerSidebar.renderBackground(graphics, ComputerBorderRenderer.getTexture(family), leftPos, topPos + sidebarYOffset); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,14 +4,13 @@ | ||||
| 
 | ||||
| package dan200.computercraft.client.gui.widgets; | ||||
| 
 | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import dan200.computercraft.api.ComputerCraftAPI; | ||||
| import dan200.computercraft.client.gui.widgets.DynamicImageButton.HintedMessage; | ||||
| import dan200.computercraft.client.render.ComputerBorderRenderer; | ||||
| import dan200.computercraft.shared.computer.core.InputHandler; | ||||
| import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu; | ||||
| import net.minecraft.client.gui.GuiGraphics; | ||||
| import net.minecraft.client.gui.components.AbstractWidget; | ||||
| import net.minecraft.client.gui.screens.Screen; | ||||
| import net.minecraft.network.chat.Component; | ||||
| import net.minecraft.resources.ResourceLocation; | ||||
| 
 | ||||
| @@ -68,19 +67,19 @@ public final class ComputerSidebar { | ||||
|         )); | ||||
|     } | ||||
| 
 | ||||
|     public static void renderBackground(PoseStack transform, int x, int y) { | ||||
|         Screen.blit(transform, | ||||
|     public static void renderBackground(GuiGraphics graphics, ResourceLocation texture, int x, int y) { | ||||
|         graphics.blit(texture, | ||||
|             x, y, 0, 102, AbstractComputerMenu.SIDEBAR_WIDTH, FULL_BORDER, | ||||
|             ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE | ||||
|         ); | ||||
| 
 | ||||
|         Screen.blit(transform, | ||||
|         graphics.blit(texture, | ||||
|             x, y + FULL_BORDER, AbstractComputerMenu.SIDEBAR_WIDTH, HEIGHT - FULL_BORDER * 2, | ||||
|             0, 107, AbstractComputerMenu.SIDEBAR_WIDTH, 4, | ||||
|             ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE | ||||
|         ); | ||||
| 
 | ||||
|         Screen.blit(transform, | ||||
|         graphics.blit(texture, | ||||
|             x, y + HEIGHT - FULL_BORDER, 0, 111, AbstractComputerMenu.SIDEBAR_WIDTH, FULL_BORDER, | ||||
|             ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE | ||||
|         ); | ||||
|   | ||||
| @@ -5,8 +5,8 @@ | ||||
| package dan200.computercraft.client.gui.widgets; | ||||
| 
 | ||||
| import com.mojang.blaze3d.systems.RenderSystem; | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| 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.network.chat.Component; | ||||
| @@ -57,15 +57,14 @@ public class DynamicImageButton extends Button { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void renderWidget(PoseStack stack, int mouseX, int mouseY, float partialTicks) { | ||||
|         RenderSystem.setShaderTexture(0, texture); | ||||
|         RenderSystem.disableDepthTest(); | ||||
|     public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { | ||||
|         RenderSystem.enableBlend(); | ||||
|         RenderSystem.enableDepthTest(); | ||||
| 
 | ||||
|         var yTex = yTexStart; | ||||
|         if (isHoveredOrFocused()) yTex += yDiffTex; | ||||
| 
 | ||||
|         blit(stack, getX(), getY(), xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight); | ||||
|         RenderSystem.enableDepthTest(); | ||||
|         graphics.blit(texture, getX(), getY(), xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| @@ -74,9 +73,9 @@ public class DynamicImageButton extends Button { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void render(PoseStack stack, int mouseX, int mouseY, float partialTicks) { | ||||
|     public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { | ||||
|         setTooltip(message.get().tooltip()); | ||||
|         super.render(stack, mouseX, mouseY, partialTicks); | ||||
|         super.render(graphics, mouseX, mouseY, partialTicks); | ||||
|     } | ||||
| 
 | ||||
|     public record HintedMessage(Component message, Tooltip tooltip) { | ||||
|   | ||||
| @@ -4,7 +4,6 @@ | ||||
| 
 | ||||
| package dan200.computercraft.client.gui.widgets; | ||||
| 
 | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import com.mojang.blaze3d.vertex.Tesselator; | ||||
| import dan200.computercraft.client.render.RenderTypes; | ||||
| import dan200.computercraft.client.render.text.FixedWidthFontRenderer; | ||||
| @@ -12,6 +11,7 @@ import dan200.computercraft.core.terminal.Terminal; | ||||
| import dan200.computercraft.shared.computer.core.InputHandler; | ||||
| import net.minecraft.SharedConstants; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.client.gui.GuiGraphics; | ||||
| import net.minecraft.client.gui.components.AbstractWidget; | ||||
| import net.minecraft.client.gui.narration.NarratedElementType; | ||||
| import net.minecraft.client.gui.narration.NarrationElementOutput; | ||||
| @@ -271,11 +271,11 @@ public class TerminalWidget extends AbstractWidget { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void renderWidget(PoseStack transform, int mouseX, int mouseY, float partialTicks) { | ||||
|     public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { | ||||
|         if (!visible) return; | ||||
| 
 | ||||
|         var bufferSource = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder()); | ||||
|         var emitter = FixedWidthFontRenderer.toVertexConsumer(transform, bufferSource.getBuffer(RenderTypes.TERMINAL)); | ||||
|         var emitter = FixedWidthFontRenderer.toVertexConsumer(graphics.pose(), bufferSource.getBuffer(RenderTypes.TERMINAL)); | ||||
| 
 | ||||
|         FixedWidthFontRenderer.drawTerminal( | ||||
|             emitter, | ||||
|   | ||||
| @@ -52,7 +52,7 @@ public abstract class AbstractClientNetworkContext implements ClientNetworkConte | ||||
|         var player = Minecraft.getInstance().player; | ||||
|         if (player == null) return; | ||||
| 
 | ||||
|         var te = player.level.getBlockEntity(pos); | ||||
|         var te = player.level().getBlockEntity(pos); | ||||
|         if (!(te instanceof MonitorBlockEntity monitor)) return; | ||||
| 
 | ||||
|         monitor.read(terminal); | ||||
|   | ||||
| @@ -18,9 +18,9 @@ import org.joml.Matrix4f; | ||||
|  * {@linkplain PocketItemRenderer in-hand pocket computers}. | ||||
|  */ | ||||
| public class ComputerBorderRenderer { | ||||
|     public static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/corners_normal.png"); | ||||
|     public static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/corners_advanced.png"); | ||||
|     public static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/corners_command.png"); | ||||
|     private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/corners_normal.png"); | ||||
|     private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/corners_advanced.png"); | ||||
|     private static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/corners_command.png"); | ||||
|     public static final ResourceLocation BACKGROUND_COLOUR = new ResourceLocation(ComputerCraftAPI.MOD_ID, "textures/gui/corners_colour.png"); | ||||
| 
 | ||||
|     /** | ||||
|   | ||||
| @@ -7,10 +7,7 @@ package dan200.computercraft.client.render.monitor; | ||||
| import com.mojang.blaze3d.platform.GlStateManager; | ||||
| import com.mojang.blaze3d.platform.MemoryTracker; | ||||
| import com.mojang.blaze3d.systems.RenderSystem; | ||||
| import com.mojang.blaze3d.vertex.PoseStack; | ||||
| import com.mojang.blaze3d.vertex.Tesselator; | ||||
| import com.mojang.blaze3d.vertex.VertexBuffer; | ||||
| import com.mojang.blaze3d.vertex.VertexConsumer; | ||||
| import com.mojang.blaze3d.vertex.*; | ||||
| import com.mojang.math.Axis; | ||||
| import dan200.computercraft.client.FrameInfo; | ||||
| import dan200.computercraft.client.integration.ShaderMod; | ||||
| @@ -170,7 +167,7 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer<MonitorBl | ||||
|                 tboVertex(buffer, matrix, -xMargin, pixelHeight + yMargin); | ||||
|                 tboVertex(buffer, matrix, pixelWidth + xMargin, -yMargin); | ||||
|                 tboVertex(buffer, matrix, pixelWidth + xMargin, pixelHeight + yMargin); | ||||
|                 RenderTypes.MONITOR_TBO.end(buffer, 0, 0, 0); | ||||
|                 RenderTypes.MONITOR_TBO.end(buffer, VertexSorting.DISTANCE_TO_ORIGIN); | ||||
|             } | ||||
|             case VBO -> { | ||||
|                 var backgroundBuffer = assertNonNull(renderState.backgroundBuffer); | ||||
|   | ||||
| @@ -25,6 +25,7 @@ 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. | ||||
|   | ||||
| @@ -23,7 +23,7 @@ import net.minecraft.world.level.storage.loot.entries.LootItem; | ||||
| import net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer; | ||||
| import net.minecraft.world.level.storage.loot.functions.CopyNameFunction; | ||||
| import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; | ||||
| import net.minecraft.world.level.storage.loot.predicates.AlternativeLootItemCondition; | ||||
| import net.minecraft.world.level.storage.loot.predicates.AnyOfCondition; | ||||
| import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition; | ||||
| import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition; | ||||
| import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; | ||||
| @@ -79,7 +79,7 @@ class LootTableProvider { | ||||
|     } | ||||
| 
 | ||||
|     private static void registerGeneric(BiConsumer<ResourceLocation, LootTable.Builder> add) { | ||||
|         add.accept(CommonHooks.LOOT_TREASURE_DISK, LootTable.lootTable()); | ||||
|         add.accept(CommonHooks.TREASURE_DISK_LOOT, LootTable.lootTable()); | ||||
|     } | ||||
| 
 | ||||
|     private static void selfDrop(BiConsumer<ResourceLocation, LootTable.Builder> add, Supplier<? extends Block> wrapper) { | ||||
| @@ -98,7 +98,7 @@ class LootTableProvider { | ||||
|         blockDrop( | ||||
|             add, block, | ||||
|             DynamicLoot.dynamicEntry(new ResourceLocation(ComputerCraftAPI.MOD_ID, "computer")), | ||||
|             AlternativeLootItemCondition.alternative( | ||||
|             AnyOfCondition.anyOf( | ||||
|                 BlockNamedEntityLootCondition.BUILDER, | ||||
|                 HasComputerIdLootCondition.BUILDER, | ||||
|                 PlayerCreativeLootCondition.BUILDER.invert() | ||||
|   | ||||
| @@ -23,13 +23,7 @@ import net.minecraft.world.entity.Entity; | ||||
| import net.minecraft.world.item.ItemStack; | ||||
| import net.minecraft.world.level.chunk.LevelChunk; | ||||
| import net.minecraft.world.level.storage.loot.BuiltInLootTables; | ||||
| import net.minecraft.world.level.storage.loot.LootPool; | ||||
| import net.minecraft.world.level.storage.loot.entries.LootTableReference; | ||||
| import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; | ||||
| 
 | ||||
| import javax.annotation.Nullable; | ||||
| import java.util.Arrays; | ||||
| import java.util.HashSet; | ||||
| import java.util.Set; | ||||
| import java.util.function.BiConsumer; | ||||
| 
 | ||||
| @@ -75,9 +69,9 @@ public final class CommonHooks { | ||||
|         MonitorWatcher.onWatch(chunk, player); | ||||
|     } | ||||
| 
 | ||||
|     public static final ResourceLocation LOOT_TREASURE_DISK = new ResourceLocation(ComputerCraftAPI.MOD_ID, "treasure_disk"); | ||||
|     public static final ResourceLocation TREASURE_DISK_LOOT = new ResourceLocation(ComputerCraftAPI.MOD_ID, "treasure_disk"); | ||||
| 
 | ||||
|     private static final Set<ResourceLocation> TABLES = new HashSet<>(Arrays.asList( | ||||
|     public static final Set<ResourceLocation> TREASURE_DISK_LOOT_TABLES = Set.of( | ||||
|         BuiltInLootTables.SIMPLE_DUNGEON, | ||||
|         BuiltInLootTables.ABANDONED_MINESHAFT, | ||||
|         BuiltInLootTables.STRONGHOLD_CORRIDOR, | ||||
| @@ -88,16 +82,7 @@ public final class CommonHooks { | ||||
|         BuiltInLootTables.IGLOO_CHEST, | ||||
|         BuiltInLootTables.WOODLAND_MANSION, | ||||
|         BuiltInLootTables.VILLAGE_CARTOGRAPHER | ||||
|     )); | ||||
| 
 | ||||
| 
 | ||||
|     public static @Nullable LootPool.Builder getExtraLootPool(ResourceLocation lootTable) { | ||||
|         if (!lootTable.getNamespace().equals("minecraft") || !TABLES.contains(lootTable)) return null; | ||||
| 
 | ||||
|         return LootPool.lootPool() | ||||
|             .add(LootTableReference.lootTableReference(LOOT_TREASURE_DISK)) | ||||
|             .setRolls(ConstantValue.exactly(1)); | ||||
|     } | ||||
|     ); | ||||
| 
 | ||||
|     public static void onDatapackReload(BiConsumer<String, PreparableReloadListener> addReload) { | ||||
|         addReload.accept("mounts", ResourceMount.RELOAD_LISTENER); | ||||
|   | ||||
| @@ -93,7 +93,7 @@ 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.BlockState; | ||||
| import net.minecraft.world.level.material.Material; | ||||
| import net.minecraft.world.level.material.MapColor; | ||||
| import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; | ||||
| 
 | ||||
| import java.util.function.BiFunction; | ||||
| @@ -112,7 +112,7 @@ public final class ModRegistry { | ||||
|         static final RegistrationHelper<Block> REGISTRY = PlatformHelper.get().createRegistrationHelper(Registries.BLOCK); | ||||
| 
 | ||||
|         private static BlockBehaviour.Properties properties() { | ||||
|             return BlockBehaviour.Properties.of(Material.STONE).strength(2); | ||||
|             return BlockBehaviour.Properties.of().strength(2); | ||||
|         } | ||||
| 
 | ||||
|         private static BlockBehaviour.Properties computerProperties() { | ||||
| @@ -122,17 +122,17 @@ public final class ModRegistry { | ||||
|         } | ||||
| 
 | ||||
|         private static BlockBehaviour.Properties turtleProperties() { | ||||
|             return BlockBehaviour.Properties.of(Material.STONE).strength(2.5f); | ||||
|             return BlockBehaviour.Properties.of().strength(2.5f); | ||||
|         } | ||||
| 
 | ||||
|         private static BlockBehaviour.Properties modemProperties() { | ||||
|             return BlockBehaviour.Properties.of(Material.STONE).strength(1.5f); | ||||
|             return BlockBehaviour.Properties.of().strength(1.5f); | ||||
|         } | ||||
| 
 | ||||
|         public static final RegistryEntry<ComputerBlock<ComputerBlockEntity>> COMPUTER_NORMAL = REGISTRY.register("computer_normal", | ||||
|             () -> new ComputerBlock<>(computerProperties(), ComputerFamily.NORMAL, BlockEntities.COMPUTER_NORMAL)); | ||||
|             () -> new ComputerBlock<>(computerProperties().mapColor(MapColor.STONE), ComputerFamily.NORMAL, BlockEntities.COMPUTER_NORMAL)); | ||||
|         public static final RegistryEntry<ComputerBlock<ComputerBlockEntity>> COMPUTER_ADVANCED = REGISTRY.register("computer_advanced", | ||||
|             () -> new ComputerBlock<>(computerProperties(), ComputerFamily.ADVANCED, BlockEntities.COMPUTER_ADVANCED)); | ||||
|             () -> new ComputerBlock<>(computerProperties().mapColor(MapColor.GOLD), ComputerFamily.ADVANCED, BlockEntities.COMPUTER_ADVANCED)); | ||||
| 
 | ||||
|         public static final RegistryEntry<ComputerBlock<CommandComputerBlockEntity>> COMPUTER_COMMAND = REGISTRY.register("computer_command", () -> new ComputerBlock<>( | ||||
|             computerProperties().strength(-1, 6000000.0F), | ||||
| @@ -140,27 +140,27 @@ public final class ModRegistry { | ||||
|         )); | ||||
| 
 | ||||
|         public static final RegistryEntry<TurtleBlock> TURTLE_NORMAL = REGISTRY.register("turtle_normal", | ||||
|             () -> new TurtleBlock(turtleProperties(), ComputerFamily.NORMAL, BlockEntities.TURTLE_NORMAL)); | ||||
|             () -> new TurtleBlock(turtleProperties().mapColor(MapColor.STONE), ComputerFamily.NORMAL, BlockEntities.TURTLE_NORMAL)); | ||||
|         public static final RegistryEntry<TurtleBlock> TURTLE_ADVANCED = REGISTRY.register("turtle_advanced", | ||||
|             () -> new TurtleBlock(turtleProperties(), ComputerFamily.ADVANCED, BlockEntities.TURTLE_ADVANCED)); | ||||
|             () -> new TurtleBlock(turtleProperties().mapColor(MapColor.GOLD), ComputerFamily.ADVANCED, BlockEntities.TURTLE_ADVANCED)); | ||||
| 
 | ||||
|         public static final RegistryEntry<SpeakerBlock> SPEAKER = REGISTRY.register("speaker", () -> new SpeakerBlock(properties())); | ||||
|         public static final RegistryEntry<DiskDriveBlock> DISK_DRIVE = REGISTRY.register("disk_drive", () -> new DiskDriveBlock(properties())); | ||||
|         public static final RegistryEntry<PrinterBlock> PRINTER = REGISTRY.register("printer", () -> new PrinterBlock(properties())); | ||||
|         public static final RegistryEntry<SpeakerBlock> SPEAKER = REGISTRY.register("speaker", () -> new SpeakerBlock(properties().mapColor(MapColor.STONE))); | ||||
|         public static final RegistryEntry<DiskDriveBlock> DISK_DRIVE = REGISTRY.register("disk_drive", () -> new DiskDriveBlock(properties().mapColor(MapColor.STONE))); | ||||
|         public static final RegistryEntry<PrinterBlock> PRINTER = REGISTRY.register("printer", () -> new PrinterBlock(properties().mapColor(MapColor.STONE))); | ||||
| 
 | ||||
|         public static final RegistryEntry<MonitorBlock> MONITOR_NORMAL = REGISTRY.register("monitor_normal", | ||||
|             () -> new MonitorBlock(properties(), BlockEntities.MONITOR_NORMAL)); | ||||
|             () -> new MonitorBlock(properties().mapColor(MapColor.STONE), BlockEntities.MONITOR_NORMAL)); | ||||
|         public static final RegistryEntry<MonitorBlock> MONITOR_ADVANCED = REGISTRY.register("monitor_advanced", | ||||
|             () -> new MonitorBlock(properties(), BlockEntities.MONITOR_ADVANCED)); | ||||
|             () -> new MonitorBlock(properties().mapColor(MapColor.GOLD), BlockEntities.MONITOR_ADVANCED)); | ||||
| 
 | ||||
|         public static final RegistryEntry<WirelessModemBlock> WIRELESS_MODEM_NORMAL = REGISTRY.register("wireless_modem_normal", | ||||
|             () -> new WirelessModemBlock(properties(), BlockEntities.WIRELESS_MODEM_NORMAL)); | ||||
|             () -> new WirelessModemBlock(properties().mapColor(MapColor.STONE), BlockEntities.WIRELESS_MODEM_NORMAL)); | ||||
|         public static final RegistryEntry<WirelessModemBlock> WIRELESS_MODEM_ADVANCED = REGISTRY.register("wireless_modem_advanced", | ||||
|             () -> new WirelessModemBlock(properties(), BlockEntities.WIRELESS_MODEM_ADVANCED)); | ||||
|             () -> new WirelessModemBlock(properties().mapColor(MapColor.GOLD), BlockEntities.WIRELESS_MODEM_ADVANCED)); | ||||
| 
 | ||||
|         public static final RegistryEntry<WiredModemFullBlock> WIRED_MODEM_FULL = REGISTRY.register("wired_modem_full", | ||||
|             () -> new WiredModemFullBlock(modemProperties())); | ||||
|         public static final RegistryEntry<CableBlock> CABLE = REGISTRY.register("cable", () -> new CableBlock(modemProperties())); | ||||
|             () -> new WiredModemFullBlock(modemProperties().mapColor(MapColor.STONE))); | ||||
|         public static final RegistryEntry<CableBlock> CABLE = REGISTRY.register("cable", () -> new CableBlock(modemProperties().mapColor(MapColor.STONE))); | ||||
|     } | ||||
| 
 | ||||
|     public static class BlockEntities { | ||||
| @@ -365,50 +365,11 @@ public final class ModRegistry { | ||||
|         public static final RegistryEntry<ImpostorShapelessRecipe.Serializer> IMPOSTOR_SHAPELESS = REGISTRY.register("impostor_shapeless", ImpostorShapelessRecipe.Serializer::new); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Register any objects which don't have to be done on the main thread. | ||||
|      */ | ||||
|     public static void register() { | ||||
|         Blocks.REGISTRY.register(); | ||||
|         BlockEntities.REGISTRY.register(); | ||||
|         Items.REGISTRY.register(); | ||||
|         TurtleSerialisers.REGISTRY.register(); | ||||
|         PocketUpgradeSerialisers.REGISTRY.register(); | ||||
|         Menus.REGISTRY.register(); | ||||
|         ArgumentTypes.REGISTRY.register(); | ||||
|         LootItemConditionTypes.REGISTRY.register(); | ||||
|         RecipeSerializers.REGISTRY.register(); | ||||
|     static class CreativeTabs { | ||||
|         static final RegistrationHelper<CreativeModeTab> REGISTRY = PlatformHelper.get().createRegistrationHelper(Registries.CREATIVE_MODE_TAB); | ||||
| 
 | ||||
|         // Register bundled power providers | ||||
|         ComputerCraftAPI.registerBundledRedstoneProvider(new DefaultBundledRedstoneProvider()); | ||||
|         ComputerCraftAPI.registerRefuelHandler(new FurnaceRefuelHandler()); | ||||
|         ComputerCraftAPI.registerMediaProvider(stack -> { | ||||
|             var item = stack.getItem(); | ||||
|             if (item instanceof IMedia media) return media; | ||||
|             if (item instanceof RecordItem) return RecordMedia.INSTANCE; | ||||
|             return null; | ||||
|         }); | ||||
| 
 | ||||
|         VanillaDetailRegistries.ITEM_STACK.addProvider(ItemDetails::fill); | ||||
|         VanillaDetailRegistries.BLOCK_IN_WORLD.addProvider(BlockDetails::fill); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Register any objects which must be done on the main thread. | ||||
|      */ | ||||
|     public static void registerMainThread() { | ||||
|         CauldronInteraction.WATER.put(ModRegistry.Items.TURTLE_NORMAL.get(), TurtleItem.CAULDRON_INTERACTION); | ||||
|         CauldronInteraction.WATER.put(ModRegistry.Items.TURTLE_ADVANCED.get(), TurtleItem.CAULDRON_INTERACTION); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Configure a {@link CreativeModeTab.Builder} to contain all of ComputerCraft's items. | ||||
|      * | ||||
|      * @param builder The builder to configure. | ||||
|      * @return The same building, for calling {@link CreativeModeTab.Builder#build()} on. | ||||
|      */ | ||||
|     public static CreativeModeTab.Builder registerCreativeTab(CreativeModeTab.Builder builder) { | ||||
|         return builder | ||||
|         @SuppressWarnings("unused") | ||||
|         private static final RegistryEntry<CreativeModeTab> TAB = REGISTRY.register("tab", () -> PlatformHelper.get().newCreativeModeTab() | ||||
|             .icon(() -> new ItemStack(Items.COMPUTER_NORMAL.get())) | ||||
|             .title(Component.translatable("itemGroup.computercraft")) | ||||
|             .displayItems((context, out) -> { | ||||
| @@ -440,7 +401,45 @@ public final class ModRegistry { | ||||
|                 for (var colour = 0; colour < 16; colour++) { | ||||
|                     out.accept(DiskItem.createFromIDAndColour(-1, null, Colour.VALUES[colour].getHex())); | ||||
|                 } | ||||
|             }) | ||||
|             .build()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Register any objects which don't have to be done on the main thread. | ||||
|      */ | ||||
|     public static void register() { | ||||
|         Blocks.REGISTRY.register(); | ||||
|         BlockEntities.REGISTRY.register(); | ||||
|         Items.REGISTRY.register(); | ||||
|         TurtleSerialisers.REGISTRY.register(); | ||||
|         PocketUpgradeSerialisers.REGISTRY.register(); | ||||
|         Menus.REGISTRY.register(); | ||||
|         ArgumentTypes.REGISTRY.register(); | ||||
|         LootItemConditionTypes.REGISTRY.register(); | ||||
|         RecipeSerializers.REGISTRY.register(); | ||||
|         CreativeTabs.REGISTRY.register(); | ||||
| 
 | ||||
|         // Register bundled power providers | ||||
|         ComputerCraftAPI.registerBundledRedstoneProvider(new DefaultBundledRedstoneProvider()); | ||||
|         ComputerCraftAPI.registerRefuelHandler(new FurnaceRefuelHandler()); | ||||
|         ComputerCraftAPI.registerMediaProvider(stack -> { | ||||
|             var item = stack.getItem(); | ||||
|             if (item instanceof IMedia media) return media; | ||||
|             if (item instanceof RecordItem) return RecordMedia.INSTANCE; | ||||
|             return null; | ||||
|         }); | ||||
| 
 | ||||
|         VanillaDetailRegistries.ITEM_STACK.addProvider(ItemDetails::fill); | ||||
|         VanillaDetailRegistries.BLOCK_IN_WORLD.addProvider(BlockDetails::fill); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Register any objects which must be done on the main thread. | ||||
|      */ | ||||
|     public static void registerMainThread() { | ||||
|         CauldronInteraction.WATER.put(ModRegistry.Items.TURTLE_NORMAL.get(), TurtleItem.CAULDRON_INTERACTION); | ||||
|         CauldronInteraction.WATER.put(ModRegistry.Items.TURTLE_ADVANCED.get(), TurtleItem.CAULDRON_INTERACTION); | ||||
|     } | ||||
| 
 | ||||
|     private static void addTurtle(CreativeModeTab.Output out, TurtleItem turtle) { | ||||
|   | ||||
| @@ -124,7 +124,9 @@ public final class CommandComputerCraft { | ||||
|                         if (computer.isOn()) shutdown++; | ||||
|                         computer.shutdown(); | ||||
|                     } | ||||
|                     context.getSource().sendSuccess(Component.translatable("commands.computercraft.shutdown.done", shutdown, computers.size()), false); | ||||
| 
 | ||||
|                     var didShutdown = shutdown; | ||||
|                     context.getSource().sendSuccess(() -> Component.translatable("commands.computercraft.shutdown.done", didShutdown, computers.size()), false); | ||||
|                     return shutdown; | ||||
|                 })) | ||||
| 
 | ||||
| @@ -138,7 +140,9 @@ public final class CommandComputerCraft { | ||||
|                         if (!computer.isOn()) on++; | ||||
|                         computer.turnOn(); | ||||
|                     } | ||||
|                     context.getSource().sendSuccess(Component.translatable("commands.computercraft.turn_on.done", on, computers.size()), false); | ||||
| 
 | ||||
|                     var didOn = on; | ||||
|                     context.getSource().sendSuccess(() -> Component.translatable("commands.computercraft.turn_on.done", didOn, computers.size()), false); | ||||
|                     return on; | ||||
|                 })) | ||||
| 
 | ||||
| @@ -213,7 +217,7 @@ public final class CommandComputerCraft { | ||||
|                         getMetricsInstance(context.getSource()).start(); | ||||
| 
 | ||||
|                         var stopCommand = "/computercraft track stop"; | ||||
|                         context.getSource().sendSuccess(Component.translatable( | ||||
|                         context.getSource().sendSuccess(() -> Component.translatable( | ||||
|                             "commands.computercraft.track.start.stop", | ||||
|                             link(text(stopCommand), stopCommand, Component.translatable("commands.computercraft.track.stop.action")) | ||||
|                         ), false); | ||||
|   | ||||
| @@ -129,14 +129,14 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<Command | ||||
| 
 | ||||
|         @Override | ||||
|         public int run(CommandContext<CommandSourceStack> context) { | ||||
|             context.getSource().sendSuccess(getHelp(context, assertNonNull(node), id, command), false); | ||||
|             context.getSource().sendSuccess(() -> getHelp(context, assertNonNull(node), id, command), false); | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private static Command<CommandSourceStack> helpForChild(CommandNode<CommandSourceStack> node, String id, String command) { | ||||
|         return context -> { | ||||
|             context.getSource().sendSuccess(getHelp(context, node, id + "." + node.getName().replace('-', '_'), command + " " + node.getName()), false); | ||||
|             context.getSource().sendSuccess(() -> getHelp(context, node, id + "." + node.getName().replace('-', '_'), command + " " + node.getName()), false); | ||||
|             return 0; | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -37,6 +37,6 @@ public class ServerTableFormatter implements TableFormatter { | ||||
| 
 | ||||
|     @Override | ||||
|     public void writeLine(String label, Component component) { | ||||
|         source.sendSuccess(component, false); | ||||
|         source.sendSuccess(() -> component, false); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -32,7 +32,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.storage.loot.LootContext; | ||||
| import net.minecraft.world.level.storage.loot.LootParams; | ||||
| import net.minecraft.world.level.storage.loot.parameters.LootContextParams; | ||||
| import net.minecraft.world.phys.BlockHitResult; | ||||
| import net.minecraft.world.phys.Vec3; | ||||
| @@ -138,13 +138,12 @@ public abstract class AbstractComputerBlock<T extends AbstractComputerBlockEntit | ||||
| 
 | ||||
|         var tile = world.getBlockEntity(pos); | ||||
|         if (tile instanceof AbstractComputerBlockEntity computer) { | ||||
|             var context = new LootContext.Builder(serverWorld) | ||||
|                 .withRandom(world.random) | ||||
|             var context = new LootParams.Builder(serverWorld) | ||||
|                 .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)) | ||||
|                 .withParameter(LootContextParams.TOOL, player.getMainHandItem()) | ||||
|                 .withParameter(LootContextParams.THIS_ENTITY, player) | ||||
|                 .withParameter(LootContextParams.BLOCK_ENTITY, tile) | ||||
|                 .withDynamicDrop(DROP, (ctx, out) -> out.accept(getItem(computer))); | ||||
|                 .withDynamicDrop(DROP, out -> out.accept(getItem(computer))); | ||||
|             for (var item : state.getDrops(context)) { | ||||
|                 popResource(world, pos, item); | ||||
|             } | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import com.google.gson.JsonParseException; | ||||
| import dan200.computercraft.shared.platform.PlatformHelper; | ||||
| import dan200.computercraft.shared.platform.RegistryWrappers; | ||||
| import dan200.computercraft.shared.util.NBTUtil; | ||||
| import net.minecraft.core.registries.Registries; | ||||
| import net.minecraft.nbt.ListTag; | ||||
| import net.minecraft.nbt.Tag; | ||||
| import net.minecraft.network.chat.Component; | ||||
| @@ -96,9 +97,7 @@ public class ItemDetails { | ||||
|             .map(group -> { | ||||
|                 Map<String, Object> groupData = new HashMap<>(2); | ||||
| 
 | ||||
|                 var id = PlatformHelper.get().getCreativeTabId(group); | ||||
|                 if (id != null) groupData.put("id", id.toString()); | ||||
| 
 | ||||
|                 groupData.put("id", PlatformHelper.get().getRegistryKey(Registries.CREATIVE_MODE_TAB, group).toString()); | ||||
|                 groupData.put("displayName", group.getDisplayName().getString()); | ||||
|                 return groupData; | ||||
|             }) | ||||
|   | ||||
| @@ -19,7 +19,7 @@ public record SpeakerPosition(@Nullable Level level, Vec3 position, @Nullable En | ||||
|     } | ||||
| 
 | ||||
|     public static SpeakerPosition of(Entity entity) { | ||||
|         return new SpeakerPosition(entity.level, entity.getEyePosition(1), entity); | ||||
|         return new SpeakerPosition(entity.level(), entity.getEyePosition(1), entity); | ||||
|     } | ||||
| 
 | ||||
|     public boolean withinDistance(SpeakerPosition other, double distanceSq) { | ||||
|   | ||||
| @@ -274,13 +274,11 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper | ||||
|     int getBurnTime(ItemStack stack); | ||||
| 
 | ||||
|     /** | ||||
|      * Get a unique identifier for this creative tab. | ||||
|      * Create a builder for a new creative tab. | ||||
|      * | ||||
|      * @param tab The tab to get | ||||
|      * @return The unique identifier, or {@code null} if not available. | ||||
|      * @return The creative tab builder. | ||||
|      */ | ||||
|     @Nullable | ||||
|     ResourceLocation getCreativeTabId(CreativeModeTab tab); | ||||
|     CreativeModeTab.Builder newCreativeModeTab(); | ||||
| 
 | ||||
|     /** | ||||
|      * Get the "container" item to be returned after crafting. For instance, crafting with a lava bucket should return | ||||
|   | ||||
| @@ -153,7 +153,7 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces | ||||
|         super.tickServer(); | ||||
| 
 | ||||
|         // Find any players which have gone missing and remove them from the tracking list. | ||||
|         tracking.removeIf(player -> !player.isAlive() || player.level != getLevel()); | ||||
|         tracking.removeIf(player -> !player.isAlive() || player.level() != getLevel()); | ||||
| 
 | ||||
|         // And now find any new players, add them to the tracking list, and broadcast state where appropriate. | ||||
|         var sendState = hasOutputChanged() || lightChanged; | ||||
|   | ||||
| @@ -48,7 +48,7 @@ public class PocketComputerMenuProvider implements MenuProvider { | ||||
|             isTypingOnly ? ModRegistry.Menus.POCKET_COMPUTER_NO_TERM.get() : ModRegistry.Menus.POCKET_COMPUTER.get(), id, inventory, | ||||
|             p -> { | ||||
|                 var stack = p.getItemInHand(hand); | ||||
|                 return stack.getItem() == item && PocketComputerItem.getServerComputer(assertNonNull(entity.level.getServer()), stack) == computer; | ||||
|                 return stack.getItem() == item && PocketComputerItem.getServerComputer(assertNonNull(entity.level().getServer()), stack) == computer; | ||||
|             }, | ||||
|             computer, item.getFamily() | ||||
|         ); | ||||
|   | ||||
| @@ -122,10 +122,11 @@ public class PocketComputerItem extends Item implements IComputerItem, IMedia, I | ||||
| 
 | ||||
|     @ForgeOverride | ||||
|     public boolean onEntityItemUpdate(ItemStack stack, ItemEntity entity) { | ||||
|         if (entity.level.isClientSide || entity.level.getServer() == null) return false; | ||||
|         var level = entity.level(); | ||||
|         if (level.isClientSide || level.getServer() == null) return false; | ||||
| 
 | ||||
|         var computer = getServerComputer(entity.level.getServer(), stack); | ||||
|         if (computer != null && tick(stack, entity.level, entity, computer)) entity.setItem(stack.copy()); | ||||
|         var computer = getServerComputer(level.getServer(), stack); | ||||
|         if (computer != null && tick(stack, entity.level(), entity, computer)) entity.setItem(stack.copy()); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|   | ||||
| @@ -37,7 +37,7 @@ public class PocketSpeakerPeripheral extends UpgradeSpeakerPeripheral { | ||||
|     public void update() { | ||||
|         var entity = access.getEntity(); | ||||
|         if (entity != null) { | ||||
|             level = entity.level; | ||||
|             level = entity.level(); | ||||
|             position = entity.position(); | ||||
|         } | ||||
| 
 | ||||
|   | ||||
| @@ -44,7 +44,7 @@ public class TurtleMoveCommand implements TurtleCommand { | ||||
|         var state = oldWorld.getBlockState(newPosition); | ||||
|         if (!oldWorld.isEmptyBlock(newPosition) && | ||||
|             !WorldUtil.isLiquidBlock(oldWorld, newPosition) && | ||||
|             !state.getMaterial().isReplaceable()) { | ||||
|             !state.canBeReplaced()) { | ||||
|             return TurtleCommandResult.failure("Movement obstructed"); | ||||
|         } | ||||
| 
 | ||||
|   | ||||
| @@ -29,6 +29,7 @@ import net.minecraft.world.level.Level; | ||||
| import net.minecraft.world.level.block.Block; | ||||
| import net.minecraft.world.level.block.entity.BlockEntity; | ||||
| import net.minecraft.world.level.block.entity.SignBlockEntity; | ||||
| import net.minecraft.world.level.block.entity.SignText; | ||||
| import net.minecraft.world.level.block.state.BlockState; | ||||
| import net.minecraft.world.phys.BlockHitResult; | ||||
| import net.minecraft.world.phys.EntityHitResult; | ||||
| @@ -210,7 +211,7 @@ public class TurtlePlaceCommand implements TurtleCommand { | ||||
|         ); | ||||
|         if (result != InteractionResult.PASS) return result; | ||||
| 
 | ||||
|         var level = turtlePlayer.player().level; | ||||
|         var level = turtlePlayer.player().level(); | ||||
| 
 | ||||
|         // We special case some items which we allow to place "normally". Yes, this is very ugly. | ||||
|         var item = stack.getItem(); | ||||
| @@ -225,18 +226,18 @@ public class TurtlePlaceCommand implements TurtleCommand { | ||||
|         var signTile = (SignBlockEntity) tile; | ||||
|         var split = Splitter.on('\n').splitToList(message); | ||||
|         var firstLine = split.size() <= 2 ? 1 : 0; | ||||
| 
 | ||||
|         var signText = new SignText(); | ||||
|         for (var i = 0; i < 4; i++) { | ||||
|             if (i >= firstLine && i < firstLine + split.size()) { | ||||
|                 var line = split.get(i - firstLine); | ||||
|                 signTile.setMessage(i, line.length() > 15 | ||||
|                 signText.setMessage(i, line.length() > 15 | ||||
|                     ? Component.literal(line.substring(0, 15)) | ||||
|                     : Component.literal(line) | ||||
|                 ); | ||||
|             } else { | ||||
|                 signTile.setMessage(i, Component.literal("")); | ||||
|             } | ||||
|         } | ||||
|         signTile.setChanged(); | ||||
|         signTile.setText(signText, true); | ||||
|         world.sendBlockUpdated(tile.getBlockPos(), tile.getBlockState(), tile.getBlockState(), Block.UPDATE_ALL); | ||||
|     } | ||||
| 
 | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import dan200.computercraft.shared.turtle.blocks.TurtleBlockEntity; | ||||
| import dan200.computercraft.shared.turtle.core.TurtlePlayer; | ||||
| import net.minecraft.server.level.ServerLevel; | ||||
| import net.minecraft.world.entity.player.Player; | ||||
| import net.minecraft.world.entity.player.StackedContents; | ||||
| import net.minecraft.world.inventory.CraftingContainer; | ||||
| import net.minecraft.world.item.ItemStack; | ||||
| import net.minecraft.world.item.crafting.Recipe; | ||||
| @@ -17,20 +18,22 @@ import net.minecraft.world.item.crafting.RecipeType; | ||||
| import net.minecraft.world.level.Level; | ||||
| 
 | ||||
| import javax.annotation.Nullable; | ||||
| import java.util.AbstractList; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class TurtleInventoryCrafting extends CraftingContainer { | ||||
| public class TurtleInventoryCrafting implements CraftingContainer { | ||||
|     public static final int WIDTH = 3; | ||||
|     public static final int HEIGHT = 3; | ||||
|     public static final int SIZE = WIDTH * HEIGHT; | ||||
| 
 | ||||
|     private final ITurtleAccess turtle; | ||||
|     private int xStart = 0; | ||||
|     private int yStart = 0; | ||||
| 
 | ||||
|     @SuppressWarnings("ConstantConditions") | ||||
|     public TurtleInventoryCrafting(ITurtleAccess turtle) { | ||||
|         // Passing null in here is evil, but we don't have a container present. We override most methods in order to | ||||
|         // avoid throwing any NPEs. | ||||
|         super(null, 0, 0); | ||||
|         this.turtle = turtle; | ||||
|     } | ||||
| 
 | ||||
| @@ -96,7 +99,7 @@ public class TurtleInventoryCrafting extends CraftingContainer { | ||||
|                 // afterwards). | ||||
|                 if (existing.isEmpty()) { | ||||
|                     setItem(slot, remainder); | ||||
|                 } else if (ItemStack.isSame(existing, remainder) && ItemStack.tagMatches(existing, remainder)) { | ||||
|                 } else if (ItemStack.isSameItemSameTags(existing, remainder)) { | ||||
|                     remainder.grow(existing.getCount()); | ||||
|                     setItem(slot, remainder); | ||||
|                 } else { | ||||
| @@ -110,12 +113,12 @@ public class TurtleInventoryCrafting extends CraftingContainer { | ||||
| 
 | ||||
|     @Override | ||||
|     public int getWidth() { | ||||
|         return 3; | ||||
|         return WIDTH; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int getHeight() { | ||||
|         return 3; | ||||
|         return HEIGHT; | ||||
|     } | ||||
| 
 | ||||
|     private int modifyIndex(int index) { | ||||
| @@ -126,35 +129,37 @@ public class TurtleInventoryCrafting extends CraftingContainer { | ||||
|             : -1; | ||||
|     } | ||||
| 
 | ||||
|     // IInventory implementation | ||||
|     @Override | ||||
|     public boolean isEmpty() { | ||||
|         for (int i = 0; i < SIZE; i++) { | ||||
|             if (!getItem(i).isEmpty()) return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int getContainerSize() { | ||||
|         return getWidth() * getHeight(); | ||||
|         return SIZE; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public ItemStack getItem(int i) { | ||||
|         i = modifyIndex(i); | ||||
|         return turtle.getInventory().getItem(i); | ||||
|         return turtle.getInventory().getItem(modifyIndex(i)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public ItemStack removeItemNoUpdate(int i) { | ||||
|         i = modifyIndex(i); | ||||
|         return turtle.getInventory().removeItemNoUpdate(i); | ||||
|         return turtle.getInventory().removeItemNoUpdate(modifyIndex(i)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public ItemStack removeItem(int i, int size) { | ||||
|         i = modifyIndex(i); | ||||
|         return turtle.getInventory().removeItem(i, size); | ||||
|         return turtle.getInventory().removeItem(modifyIndex(i), size); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setItem(int i, ItemStack stack) { | ||||
|         i = modifyIndex(i); | ||||
|         turtle.getInventory().setItem(i, stack); | ||||
|         turtle.getInventory().setItem(modifyIndex(i), stack); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| @@ -174,15 +179,34 @@ public class TurtleInventoryCrafting extends CraftingContainer { | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean canPlaceItem(int i, ItemStack stack) { | ||||
|         i = modifyIndex(i); | ||||
|         return turtle.getInventory().canPlaceItem(i, stack); | ||||
|         return turtle.getInventory().canPlaceItem(modifyIndex(i), stack); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void clearContent() { | ||||
|         for (var i = 0; i < getContainerSize(); i++) { | ||||
|         for (var i = 0; i < SIZE; i++) { | ||||
|             var j = modifyIndex(i); | ||||
|             turtle.getInventory().setItem(j, ItemStack.EMPTY); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void fillStackedContents(StackedContents contents) { | ||||
|         for (int i = 0; i < SIZE; i++) contents.accountSimpleStack(getItem(i)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public List<ItemStack> getItems() { | ||||
|         return new AbstractList<>() { | ||||
|             @Override | ||||
|             public ItemStack get(int index) { | ||||
|                 return getItem(index); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public int size() { | ||||
|                 return SIZE; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -33,7 +33,7 @@ public final class DropConsumer { | ||||
|         dropConsumer = consumer; | ||||
|         remainingDrops = new ArrayList<>(); | ||||
|         dropEntity = entity; | ||||
|         dropWorld = entity.level; | ||||
|         dropWorld = entity.level(); | ||||
|         dropBounds = new AABB(entity.blockPosition()).inflate(2, 2, 2); | ||||
|     } | ||||
| 
 | ||||
| @@ -70,7 +70,7 @@ public final class DropConsumer { | ||||
| 
 | ||||
|     public static boolean onEntitySpawn(Entity entity) { | ||||
|         // Capture any nearby item spawns | ||||
|         if (dropWorld == entity.getLevel() && entity instanceof ItemEntity | ||||
|         if (dropWorld == entity.level() && entity instanceof ItemEntity | ||||
|             && assertNonNull(dropBounds).contains(entity.position())) { | ||||
|             handleDrops(((ItemEntity) entity).getItem()); | ||||
|             return true; | ||||
|   | ||||
| @@ -90,6 +90,6 @@ public final class InventoryUtil { | ||||
|         if (stack1.getItem() != stack2.getItem()) return false; | ||||
|         if (stack1.getDamageValue() != stack2.getDamageValue()) return false; | ||||
|         if (stack1.getCount() > stack1.getMaxStackSize()) return false; | ||||
|         return ItemStack.tagMatches(stack1, stack2); | ||||
|         return ItemStack.isSameItemSameTags(stack1, stack2); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -35,7 +35,7 @@ public final class WorldUtil { | ||||
| 
 | ||||
|     public static boolean isLiquidBlock(Level world, BlockPos pos) { | ||||
|         if (!world.isInWorldBounds(pos)) return false; | ||||
|         return world.getBlockState(pos).getMaterial().isLiquid(); | ||||
|         return world.getBlockState(pos).liquid(); | ||||
|     } | ||||
| 
 | ||||
|     public static boolean isVecInside(VoxelShape shape, Vec3 vec) { | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "pack": { | ||||
|         "pack_format": 12, | ||||
|         "pack_format": 15, | ||||
|         "description": "CC: Tweaked" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -165,11 +165,9 @@ public class TestPlatformHelper extends AbstractComputerCraftAPI implements Plat | ||||
|         throw new UnsupportedOperationException("Cannot interact with the world inside tests"); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     @Nullable | ||||
|     @Override | ||||
|     public ResourceLocation getCreativeTabId(CreativeModeTab tab) { | ||||
|         return null; | ||||
|     public CreativeModeTab.Builder newCreativeModeTab() { | ||||
|         throw new IllegalStateException("Cannot create creative tab inside tests"); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|   | ||||
| @@ -130,7 +130,9 @@ public class Exporter { | ||||
| 
 | ||||
|             dump.itemNames.put(location.toString(), stack.getHoverName().getString()); | ||||
|             renderer.captureRender(itemDir.resolve(location.getNamespace()).resolve(location.getPath() + ".png"), | ||||
|                 () -> Minecraft.getInstance().getItemRenderer().renderAndDecorateFakeItem(transform, stack, 0, 0) | ||||
|                 () -> { | ||||
|                     // TODO: Minecraft.getInstance().getItemRenderer().ren(transform, stack, 0, 0) | ||||
|                 } | ||||
|             ); | ||||
|         } | ||||
|         renderer.clearState(); | ||||
|   | ||||
| @@ -7,6 +7,7 @@ package dan200.computercraft.export; | ||||
| 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; | ||||
| @@ -36,7 +37,7 @@ public class ImageRenderer implements AutoCloseable { | ||||
| 
 | ||||
|     public void setupState() { | ||||
|         projectionMatrix = RenderSystem.getProjectionMatrix(); | ||||
|         RenderSystem.setProjectionMatrix(new Matrix4f().identity().ortho(0, 16, 0, 16, 1000, 3000)); | ||||
|         RenderSystem.setProjectionMatrix(new Matrix4f().identity().ortho(0, 16, 0, 16, 1000, 3000), VertexSorting.DISTANCE_TO_ORIGIN); | ||||
| 
 | ||||
|         var transform = RenderSystem.getModelViewStack(); | ||||
|         transform.pushPose(); | ||||
| @@ -48,7 +49,7 @@ public class ImageRenderer implements AutoCloseable { | ||||
| 
 | ||||
|     public void clearState() { | ||||
|         if (projectionMatrix == null) throw new IllegalStateException("Not currently rendering"); | ||||
|         RenderSystem.setProjectionMatrix(projectionMatrix); | ||||
|         RenderSystem.setProjectionMatrix(projectionMatrix, VertexSorting.DISTANCE_TO_ORIGIN); | ||||
|         RenderSystem.getModelViewStack().popPose(); | ||||
|     } | ||||
| 
 | ||||
|   | ||||
| @@ -58,36 +58,36 @@ class CCTestCommand { | ||||
| 
 | ||||
|             .then(literal("marker").executes(context -> { | ||||
|                 var player = context.getSource().getPlayerOrException(); | ||||
|                 var pos = StructureUtils.findNearestStructureBlock(player.blockPosition(), 15, player.getLevel()); | ||||
|                 var pos = StructureUtils.findNearestStructureBlock(player.blockPosition(), 15, player.serverLevel()); | ||||
|                 if (pos == null) return error(context.getSource(), "No nearby test"); | ||||
| 
 | ||||
|                 var structureBlock = (StructureBlockEntity) player.getLevel().getBlockEntity(pos); | ||||
|                 var structureBlock = (StructureBlockEntity) player.level().getBlockEntity(pos); | ||||
|                 if (structureBlock == null) return error(context.getSource(), "No nearby structure block"); | ||||
|                 var info = GameTestRegistry.getTestFunction(structureBlock.getStructurePath()); | ||||
| 
 | ||||
|                 // Kill the existing armor stand | ||||
|                 player | ||||
|                     .getLevel().getEntities(EntityType.ARMOR_STAND, x -> x.isAlive() && x.getName().getString().equals(info.getTestName())) | ||||
|                     .serverLevel().getEntities(EntityType.ARMOR_STAND, x -> x.isAlive() && x.getName().getString().equals(info.getTestName())) | ||||
|                     .forEach(Entity::kill); | ||||
| 
 | ||||
|                 // 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.getLevel())); | ||||
|                 var armorStand = assertNonNull(EntityType.ARMOR_STAND.create(player.level())); | ||||
|                 armorStand.readAdditionalSaveData(nbt); | ||||
|                 armorStand.copyPosition(player); | ||||
|                 armorStand.setCustomName(Component.literal(info.getTestName())); | ||||
|                 player.getLevel().addFreshEntity(armorStand); | ||||
|                 player.level().addFreshEntity(armorStand); | ||||
|                 return 0; | ||||
|             })) | ||||
| 
 | ||||
|             .then(literal("give-computer").executes(context -> { | ||||
|                 var player = context.getSource().getPlayerOrException(); | ||||
|                 var pos = StructureUtils.findNearestStructureBlock(player.blockPosition(), 15, player.getLevel()); | ||||
|                 var pos = StructureUtils.findNearestStructureBlock(player.blockPosition(), 15, player.serverLevel()); | ||||
|                 if (pos == null) return error(context.getSource(), "No nearby test"); | ||||
| 
 | ||||
|                 var structureBlock = (StructureBlockEntity) player.getLevel().getBlockEntity(pos); | ||||
|                 var structureBlock = (StructureBlockEntity) player.level().getBlockEntity(pos); | ||||
|                 if (structureBlock == null) return error(context.getSource(), "No nearby structure block"); | ||||
|                 var info = GameTestRegistry.getTestFunction(structureBlock.getStructurePath()); | ||||
| 
 | ||||
|   | ||||
| @@ -13,8 +13,8 @@ import net.minecraft.gametest.framework.GameTestHelper | ||||
| import net.minecraft.nbt.CompoundTag | ||||
| import net.minecraft.world.entity.player.Player | ||||
| import net.minecraft.world.inventory.AbstractContainerMenu | ||||
| import net.minecraft.world.inventory.CraftingContainer | ||||
| import net.minecraft.world.inventory.MenuType | ||||
| import net.minecraft.world.inventory.TransientCraftingContainer | ||||
| import net.minecraft.world.item.ItemStack | ||||
| import net.minecraft.world.item.Items | ||||
| import net.minecraft.world.item.crafting.CraftingRecipe | ||||
| @@ -31,7 +31,7 @@ class Recipe_Test { | ||||
|     @GameTest(template = Structures.DEFAULT) | ||||
|     fun Craft_result_has_nbt(context: GameTestHelper) = context.sequence { | ||||
|         thenExecute { | ||||
|             val container = CraftingContainer(DummyMenu, 3, 3) | ||||
|             val container = TransientCraftingContainer(DummyMenu, 3, 3) | ||||
|             container.setItem(0, ItemStack(Items.SKELETON_SKULL)) | ||||
|             container.setItem(1, ItemStack(ModRegistry.Items.COMPUTER_ADVANCED.get())) | ||||
| 
 | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "pack": { | ||||
|         "pack_format": 12, | ||||
|         "pack_format": 15, | ||||
|         "description": "CC: Test" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -42,10 +42,13 @@ dependencies { | ||||
|         exclude("net.fabricmc", "fabric-loader") | ||||
|         exclude("net.fabricmc.fabric-api") | ||||
|     } | ||||
|     /* | ||||
| 
 | ||||
|     modClientRuntimeOnly(libs.bundles.externalMods.fabric.runtime) { | ||||
|         exclude("net.fabricmc", "fabric-loader") | ||||
|         exclude("net.fabricmc.fabric-api") | ||||
|     } | ||||
|     */ | ||||
| 
 | ||||
|     "modTestWithSodium"(libs.sodium) | ||||
|     "modTestWithIris"(libs.iris) | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_monitor", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:skull_cloudy"]} | ||||
|   "rewards": {"recipes": ["computercraft:skull_cloudy"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_computer", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:skull_dan200"]} | ||||
|   "rewards": {"recipes": ["computercraft:skull_dan200"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -12,5 +12,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:cable"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_computer", "has_modem", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:cable"]} | ||||
|   "rewards": {"recipes": ["computercraft:cable"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_components", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:computer_advanced"]} | ||||
|   "rewards": {"recipes": ["computercraft:computer_advanced"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_components", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:computer_advanced_upgrade"]} | ||||
|   "rewards": {"recipes": ["computercraft:computer_advanced_upgrade"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_components", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:computer_command"]} | ||||
|   "rewards": {"recipes": ["computercraft:computer_command"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_redstone", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:computer_normal"]} | ||||
|   "rewards": {"recipes": ["computercraft:computer_normal"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_1"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_1"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_1"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_10"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_10"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_10"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_11"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_11"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_11"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_12"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_12"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_12"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_13"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_13"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_13"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_14"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_14"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_14"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_15"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_15"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_15"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_16"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_16"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_16"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_2"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_2"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_2"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_3"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_3"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_3"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_4"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_4"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_4"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_5"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_5"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_5"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_6"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_6"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_6"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_7"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_7"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_7"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_8"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_8"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_8"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_9"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_drive", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_9"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_9"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:disk_drive"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_computer", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:disk_drive"]} | ||||
|   "rewards": {"recipes": ["computercraft:disk_drive"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_computer", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:monitor_advanced"]} | ||||
|   "rewards": {"recipes": ["computercraft:monitor_advanced"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_computer", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:monitor_normal"]} | ||||
|   "rewards": {"recipes": ["computercraft:monitor_normal"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -13,5 +13,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:pocket_advanced/computercraft/speaker"]} | ||||
|   "rewards": {"recipes": ["computercraft:pocket_advanced/computercraft/speaker"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -16,5 +16,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:pocket_advanced/computercraft/wireless_modem_advanced"]} | ||||
|   "rewards": {"recipes": ["computercraft:pocket_advanced/computercraft/wireless_modem_advanced"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -16,5 +16,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:pocket_advanced/computercraft/wireless_modem_normal"]} | ||||
|   "rewards": {"recipes": ["computercraft:pocket_advanced/computercraft/wireless_modem_normal"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -15,5 +15,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_computer", "has_apple", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:pocket_computer_advanced"]} | ||||
|   "rewards": {"recipes": ["computercraft:pocket_computer_advanced"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_components", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:pocket_computer_advanced_upgrade"]} | ||||
|   "rewards": {"recipes": ["computercraft:pocket_computer_advanced_upgrade"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -15,5 +15,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_computer", "has_apple", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:pocket_computer_normal"]} | ||||
|   "rewards": {"recipes": ["computercraft:pocket_computer_normal"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -13,5 +13,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:pocket_normal/computercraft/speaker"]} | ||||
|   "rewards": {"recipes": ["computercraft:pocket_normal/computercraft/speaker"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -16,5 +16,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:pocket_normal/computercraft/wireless_modem_advanced"]} | ||||
|   "rewards": {"recipes": ["computercraft:pocket_normal/computercraft/wireless_modem_advanced"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -16,5 +16,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:pocket_normal/computercraft/wireless_modem_normal"]} | ||||
|   "rewards": {"recipes": ["computercraft:pocket_normal/computercraft/wireless_modem_normal"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_printer", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:printed_book"]} | ||||
|   "rewards": {"recipes": ["computercraft:printed_book"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_printer", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:printed_pages"]} | ||||
|   "rewards": {"recipes": ["computercraft:printed_pages"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:printer"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_computer", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:printer"]} | ||||
|   "rewards": {"recipes": ["computercraft:printer"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     "has_the_recipe": {"conditions": {"recipe": "computercraft:speaker"}, "trigger": "minecraft:recipe_unlocked"} | ||||
|   }, | ||||
|   "requirements": [["has_computer", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:speaker"]} | ||||
|   "rewards": {"recipes": ["computercraft:speaker"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_computer", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -13,5 +13,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/computercraft/speaker"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/computercraft/speaker"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -16,5 +16,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/computercraft/wireless_modem_advanced"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/computercraft/wireless_modem_advanced"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -16,5 +16,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/computercraft/wireless_modem_normal"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/computercraft/wireless_modem_normal"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -13,5 +13,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/crafting_table"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/crafting_table"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -13,5 +13,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/diamond_axe"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/diamond_axe"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -13,5 +13,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/diamond_hoe"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/diamond_hoe"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -13,5 +13,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/diamond_pickaxe"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/diamond_pickaxe"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -13,5 +13,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/diamond_shovel"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/diamond_shovel"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -13,5 +13,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/diamond_sword"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced/minecraft/diamond_sword"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -12,5 +12,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_turtle", "has_dye", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced_overlays/turtle_rainbow_overlay"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced_overlays/turtle_rainbow_overlay"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -12,5 +12,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_turtle", "has_dye", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced_overlays/turtle_trans_overlay"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced_overlays/turtle_trans_overlay"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_components", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced_upgrade"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_advanced_upgrade"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -11,5 +11,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_computer", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_normal"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_normal"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
| @@ -13,5 +13,6 @@ | ||||
|     } | ||||
|   }, | ||||
|   "requirements": [["has_items", "has_the_recipe"]], | ||||
|   "rewards": {"recipes": ["computercraft:turtle_normal/computercraft/speaker"]} | ||||
|   "rewards": {"recipes": ["computercraft:turtle_normal/computercraft/speaker"]}, | ||||
|   "sends_telemetry_event": false | ||||
| } | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates