From ef36fc18ae7ad7a345f76cc3b540a6d57134fefe Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Wed, 23 Oct 2024 20:21:04 +0100 Subject: [PATCH] Update to 1.21.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a very preliminary port. I can get in game and use computers, but I've not tested much beyond that (there's at least one failing game test). == Rendering == - Remove TBO monitor renderer: There was a big overhaul to how shaders are defined and loaded in 1.21.2. It might have been possible to update the monitor shader code to this version, it doesn't see much use nowadays, so let's just delete it. This is a real shame — the TBO renderer was one of my favourite projects I've worked on. Unfortunately, it just doesn't seem worth the ongoing maintenance burden. It lives on in the standalone emulator :D. - Similarly, the VBO rendering code got a bit of an overhaul. We no longer use a custom VBO subclass, and instead just hack vanilla's to support changing the number of vertices rendered. This does mean we need to construct a MeshData, rather than a raw ByteBuffer. This isn't too hard, but not sure how it'll play with Iris. Given recent vanilla performance improvements, maybe we can remove our Unsafe code and use a normal BufferBuilder now. - Move some textures to vanilla's GUI sprite sheet (from our own). We also move the turtle "selected slot" texture to a sprite sheet - would be good to do the other ones (printer progress, maybe printouts) in the future. - Remove our custom emissive model code, now that vanilla supports it. We should add emissive textures to some other models at some point. == Recipes == There were several major changes to ingredients this update. The code here hasn't been very well tested right now — might be nice to add some game tests for this. - Ingredients can no longer be constructed directly from a tag key (it needs to be fetched from the current registries), so the recipe generation code needs a bit of a reshuffle. - DiskRecipe now accepts a custom list of ingredients, rather than being hard-coded (fixes #1755). Recipes can now return custom `RecipeDisplay`s used to show a recipe in the crafting book. We use this to replace the impostor recipes. I'm not entirely sure how well this'll play with other recipe mods. Here's hoping. - Similarly, our recipe mod integration has been updated to use RecipeDisplay. We had to do this as ingredients no longer accept arbitrary ItemStacks (only a specific item), but the design is a little speculative - JEI/REI haven't updated yet. == Misc == - Blocks/items now need to know their ID ahead of time (so they can compute their description). This requires some reshuffling to the registration code, but it's pretty minor. - updateShape and neighborChanged have been tweaked slightly, I assume to work with the upcoming redstone changes. neighborChanged is currently commented out — we need to handle that properly. - All the positions were lowered by one in game tests. It's a good change (they now match the positions in structures), but annoying to update for! --- .../main/kotlin/cc-tweaked.fabric.gradle.kts | 10 +- gradle.properties | 2 +- gradle/libs.versions.toml | 16 +- gradle/wrapper/gradle-wrapper.jar | Bin 43504 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- .../api/client/TransformedModel.java | 2 +- .../client/turtle/TurtleUpgradeModeller.java | 2 +- .../client/turtle/TurtleUpgradeModellers.java | 2 +- projects/common/build.gradle.kts | 6 + .../computercraft/client/ClientHooks.java | 16 +- .../computercraft/client/ClientRegistry.java | 12 +- .../client/gui/AbstractComputerScreen.java | 2 +- .../client/gui/ComputerScreen.java | 17 +- .../client/gui/DiskDriveScreen.java | 3 +- .../computercraft/client/gui/GuiSprites.java | 12 +- .../computercraft/client/gui/ItemToast.java | 63 ++- .../client/gui/NoTermComputerScreen.java | 2 +- .../client/gui/OptionScreen.java | 10 +- .../client/gui/PrinterScreen.java | 7 +- .../client/gui/PrintoutScreen.java | 8 +- .../client/gui/TurtleScreen.java | 26 +- .../gui/widgets/DynamicImageButton.java | 15 +- .../client/gui/widgets/TerminalWidget.java | 13 +- .../client/integration/IrisShaderMod.java | 32 +- .../client/integration/ShaderMod.java | 16 +- .../client/model/turtle/ModelTransformer.java | 2 +- .../client/model/turtle/TurtleModelParts.java | 3 +- .../platform/ClientNetworkContextImpl.java | 10 +- .../client/render/ModelRenderer.java | 2 +- .../client/render/PocketItemRenderer.java | 12 +- .../client/render/PrintoutItemRenderer.java | 7 +- .../client/render/PrintoutRenderer.java | 14 +- .../client/render/RenderTypes.java | 102 ----- .../client/render/SpriteRenderer.java | 14 +- .../render/TurtleBlockEntityRenderer.java | 13 +- .../monitor/MonitorBlockEntityRenderer.java | 239 ++++------- .../render/monitor/MonitorRenderState.java | 74 +--- .../monitor/MonitorTextureBufferShader.java | 127 ------ .../text/DirectFixedWidthFontRenderer.java | 32 +- .../render/text/FixedWidthFontRenderer.java | 36 +- .../client/render/vbo/DirectBuffers.java | 71 ---- .../client/render/vbo/DirectVertexBuffer.java | 77 ---- .../data/client/ClientDataProviders.java | 29 +- .../assets/computercraft/atlases/gui.json | 6 - .../assets/computercraft/lang/en_us.json | 2 - .../redstone/{disk_1.json => disk.json} | 4 +- .../advancement/recipes/redstone/disk_10.json | 12 - .../advancement/recipes/redstone/disk_11.json | 12 - .../advancement/recipes/redstone/disk_12.json | 12 - .../advancement/recipes/redstone/disk_13.json | 12 - .../advancement/recipes/redstone/disk_14.json | 12 - .../advancement/recipes/redstone/disk_15.json | 12 - .../advancement/recipes/redstone/disk_16.json | 12 - .../advancement/recipes/redstone/disk_2.json | 12 - .../advancement/recipes/redstone/disk_3.json | 12 - .../advancement/recipes/redstone/disk_4.json | 12 - .../advancement/recipes/redstone/disk_5.json | 12 - .../advancement/recipes/redstone/disk_6.json | 12 - .../advancement/recipes/redstone/disk_7.json | 12 - .../advancement/recipes/redstone/disk_8.json | 12 - .../advancement/recipes/redstone/disk_9.json | 12 - .../redstone/wired_modem_full_from.json | 15 - .../recipes/redstone/wired_modem_full_to.json | 15 - .../data/computercraft/recipe/cable.json | 2 +- .../recipe/computer_advanced.json | 2 +- .../recipe/computer_advanced_upgrade.json | 4 +- .../recipe/computer_command.json | 6 +- .../computercraft/recipe/computer_normal.json | 2 +- .../data/computercraft/recipe/disk.json | 7 +- .../data/computercraft/recipe/disk_1.json | 11 - .../data/computercraft/recipe/disk_10.json | 11 - .../data/computercraft/recipe/disk_11.json | 11 - .../data/computercraft/recipe/disk_12.json | 11 - .../data/computercraft/recipe/disk_13.json | 15 - .../data/computercraft/recipe/disk_14.json | 11 - .../data/computercraft/recipe/disk_15.json | 11 - .../data/computercraft/recipe/disk_16.json | 11 - .../data/computercraft/recipe/disk_2.json | 11 - .../data/computercraft/recipe/disk_3.json | 11 - .../data/computercraft/recipe/disk_4.json | 11 - .../data/computercraft/recipe/disk_5.json | 11 - .../data/computercraft/recipe/disk_6.json | 11 - .../data/computercraft/recipe/disk_7.json | 11 - .../data/computercraft/recipe/disk_8.json | 15 - .../data/computercraft/recipe/disk_9.json | 11 - .../data/computercraft/recipe/disk_drive.json | 2 +- .../recipe/monitor_advanced.json | 2 +- .../computercraft/recipe/monitor_normal.json | 2 +- .../computercraft/speaker.json | 2 +- .../wireless_modem_advanced.json | 5 +- .../computercraft/wireless_modem_normal.json | 5 +- .../recipe/pocket_computer_advanced.json | 2 +- .../pocket_computer_advanced_upgrade.json | 6 +- .../recipe/pocket_computer_normal.json | 6 +- .../pocket_normal/computercraft/speaker.json | 2 +- .../wireless_modem_advanced.json | 5 +- .../computercraft/wireless_modem_normal.json | 5 +- .../computercraft/recipe/printed_book.json | 8 +- .../computercraft/recipe/printed_pages.json | 8 +- .../data/computercraft/recipe/printer.json | 2 +- .../computercraft/recipe/skull_cloudy.json | 2 +- .../computercraft/recipe/skull_dan200.json | 2 +- .../data/computercraft/recipe/speaker.json | 6 +- .../computercraft/recipe/turtle_advanced.json | 8 +- .../computercraft/speaker.json | 2 +- .../wireless_modem_advanced.json | 2 +- .../computercraft/wireless_modem_normal.json | 2 +- .../minecraft/crafting_table.json | 2 +- .../minecraft/diamond_axe.json | 2 +- .../minecraft/diamond_hoe.json | 2 +- .../minecraft/diamond_pickaxe.json | 2 +- .../minecraft/diamond_shovel.json | 2 +- .../minecraft/diamond_sword.json | 2 +- .../rainbow_flag.json | 18 +- .../turtle_advanced_overlays/trans_flag.json | 12 +- .../recipe/turtle_advanced_upgrade.json | 8 +- .../computercraft/recipe/turtle_normal.json | 8 +- .../turtle_normal/computercraft/speaker.json | 2 +- .../wireless_modem_advanced.json | 2 +- .../computercraft/wireless_modem_normal.json | 2 +- .../minecraft/crafting_table.json | 2 +- .../turtle_normal/minecraft/diamond_axe.json | 2 +- .../turtle_normal/minecraft/diamond_hoe.json | 2 +- .../minecraft/diamond_pickaxe.json | 2 +- .../minecraft/diamond_shovel.json | 2 +- .../minecraft/diamond_sword.json | 2 +- .../turtle_normal_overlays/rainbow_flag.json | 18 +- .../turtle_normal_overlays/trans_flag.json | 12 +- .../computercraft/recipe/wired_modem.json | 2 +- .../recipe/wireless_modem_advanced.json | 2 +- .../recipe/wireless_modem_normal.json | 2 +- .../wired_modem_from_wired_modem_full.json | 15 + .../wired_modem_full_from_wired_modem.json | 15 + .../wired_modem_from_wired_modem_full.json} | 4 +- .../wired_modem_full_from_wired_modem.json} | 4 +- .../computercraft/data/DataProviders.java | 2 +- .../computercraft/data/LanguageProvider.java | 5 +- .../computercraft/data/LootTableProvider.java | 4 +- .../computercraft/data/RecipeProvider.java | 391 ++++++++---------- .../data/recipe/AbstractRecipeBuilder.java | 19 +- .../data/recipe/ShapedSpecBuilder.java | 15 +- .../data/recipe/ShapelessSpecBuilder.java | 21 +- .../computercraft/mixin/V3818_3Mixin.java | 10 +- .../computercraft/shared/ModRegistry.java | 130 +++--- .../shared/command/CommandComputerCraft.java | 4 +- .../shared/common/ClearColourRecipe.java | 5 - .../shared/common/ColourableRecipe.java | 5 - .../common/HorizontalContainerBlock.java | 5 +- .../blocks/AbstractComputerBlock.java | 17 +- .../blocks/AbstractComputerBlockEntity.java | 4 +- .../shared/computer/blocks/ComputerBlock.java | 3 +- .../computercraft/shared/config/Config.java | 3 - .../shared/config/ConfigSpec.java | 9 - .../data/BlockNamedEntityLootCondition.java | 6 +- .../data/HasComputerIdLootCondition.java | 6 +- .../data/PlayerCreativeLootCondition.java | 6 +- .../integration/UpgradeRecipeGenerator.java | 53 ++- .../shared/lectern/CustomLecternBlock.java | 9 +- .../shared/media/items/PrintoutItem.java | 5 +- .../shared/media/recipes/DiskRecipe.java | 113 +++-- .../shared/media/recipes/PrintoutRecipe.java | 87 ++-- .../peripheral/diskdrive/DiskDriveBlock.java | 8 +- .../peripheral/modem/wired/CableBlock.java | 7 +- .../modem/wired/CableBlockItem.java | 21 +- .../modem/wired/WiredModemFullBlock.java | 9 +- .../modem/wireless/WirelessModemBlock.java | 9 +- .../wireless/WirelessModemPeripheral.java | 2 +- .../peripheral/monitor/MonitorBlock.java | 7 +- .../peripheral/speaker/SpeakerPeripheral.java | 4 +- .../shared/platform/PlatformHelper.java | 11 +- .../shared/platform/RecipeIngredients.java | 23 +- .../shared/platform/RegistryEntry.java | 2 +- .../pocket/items/PocketComputerItem.java | 7 +- .../recipes/PocketComputerUpgradeRecipe.java | 12 +- .../shared/recipe/AbstractCraftingRecipe.java | 34 ++ .../shared/recipe/BasicRecipeSerialiser.java | 6 + .../shared/recipe/CustomShapelessRecipe.java | 61 ++- .../shared/recipe/RecipeProperties.java | 5 +- .../shared/recipe/ShapelessRecipeSpec.java | 17 +- .../recipe/function/CopyComponents.java | 2 +- .../shared/turtle/FurnaceRefuelHandler.java | 8 +- .../shared/turtle/blocks/TurtleBlock.java | 22 +- .../shared/turtle/items/TurtleItem.java | 8 +- .../turtle/recipes/TurtleUpgradeRecipe.java | 12 +- .../upgrades/TurtleInventoryCrafting.java | 12 +- .../shared/turtle/upgrades/TurtleTool.java | 4 +- .../shared/util/ArgumentHelpers.java | 2 +- .../shared/util/ColourUtils.java | 2 +- .../shared/util/ComponentizationFixers.java | 28 +- .../shared/util/RedstoneUtil.java | 4 +- .../shared/util/RegistryHelper.java | 2 +- .../shared/util/WaterloggableHelpers.java | 17 +- .../models/block/computer_on.json | 5 +- .../textures/gui/border_advanced.png | Bin 334 -> 208 bytes .../textures/gui/border_colour.png | Bin 294 -> 199 bytes .../textures/gui/border_command.png | Bin 300 -> 189 bytes .../textures/gui/border_normal.png | Bin 299 -> 198 bytes .../textures/gui/buttons/terminate.png | Bin 145 -> 0 bytes .../textures/gui/buttons/terminate_hover.png | Bin 144 -> 0 bytes .../textures/gui/buttons/turned_off.png | Bin 145 -> 0 bytes .../textures/gui/buttons/turned_off_hover.png | Bin 145 -> 0 bytes .../textures/gui/pocket_bottom_advanced.png | Bin 223 -> 160 bytes .../textures/gui/pocket_bottom_colour.png | Bin 211 -> 157 bytes .../textures/gui/pocket_bottom_normal.png | Bin 216 -> 161 bytes .../textures/gui/sidebar_advanced.png | Bin 148 -> 144 bytes .../textures/gui/sidebar_normal.png | Bin 141 -> 139 bytes .../gui/sprites/buttons/terminate.png | Bin 0 -> 137 bytes .../gui/sprites/buttons/terminate_hover.png | Bin 0 -> 131 bytes .../gui/sprites/buttons/turned_off.png | Bin 0 -> 136 bytes .../gui/sprites/buttons/turned_off_hover.png | Bin 0 -> 135 bytes .../gui/{ => sprites}/buttons/turned_on.png | Bin .../{ => sprites}/buttons/turned_on_hover.png | Bin .../sprites/turtle_advanced_selected_slot.png | Bin 0 -> 461 bytes .../sprites/turtle_normal_selected_slot.png | Bin 0 -> 476 bytes .../textures/gui/turtle_advanced.png | Bin 1455 -> 738 bytes .../textures/gui/turtle_normal.png | Bin 1415 -> 695 bytes .../core/computercraft/monitor_tbo.fsh | 70 ---- .../core/computercraft/monitor_tbo.json | 18 - .../core/computercraft/monitor_tbo.vsh | 26 -- .../computercraft-common.accesswidener | 3 +- .../resources/computercraft.accesswidener | 10 +- .../main/resources/computercraft.mixins.json | 3 +- .../computercraft/TestPlatformHelper.java | 9 +- .../dan200/computercraft/export/Exporter.java | 35 +- .../computercraft/export/ImageRenderer.java | 21 +- .../dan200/computercraft/export/JsonDump.java | 16 +- .../gametest/core/CCTestCommand.java | 13 +- .../mixin/gametest/GameTestServerMixin.java | 40 ++ .../gametest/MinecraftServerAccessor.java | 19 + .../computercraft/gametest/Computer_Test.kt | 24 +- .../computercraft/gametest/Disk_Drive_Test.kt | 20 +- .../computercraft/gametest/Inventory_Test.kt | 8 +- .../computercraft/gametest/Loot_Test.kt | 2 +- .../computercraft/gametest/Modem_Test.kt | 24 +- .../computercraft/gametest/Monitor_Test.kt | 43 +- .../gametest/Pocket_Computer_Test.kt | 10 +- .../computercraft/gametest/Printer_Test.kt | 10 +- .../computercraft/gametest/Turtle_Test.kt | 124 +++--- .../gametest/api/TestExtensions.kt | 2 +- .../gametest/core/ClientTestHooks.kt | 10 +- .../computercraft-gametest.mixins.json | 2 + projects/fabric/build.gradle.kts | 8 + .../client/ComputerCraftClient.java | 1 - .../client/model/CustomModelLoader.java | 42 +- .../client/model/EmissiveBakedModel.java | 84 ---- .../client/model/turtle/TurtleModel.java | 21 +- .../model/turtle/UnbakedTurtleModel.java | 19 +- .../platform/ClientPlatformHelperImpl.java | 2 +- .../mixin/client/DebugScreenOverlayMixin.java | 6 - .../mixin/client/GameRendererMixin.java | 41 -- .../mixin/client/ItemFrameRendererMixin.java | 8 +- .../computercraft-client.fabric.mixins.json | 1 - .../computercraft/mixin/EntityMixin.java | 7 +- .../computercraft/mixin/V3818_3Mixin.java | 27 -- .../computercraft/shared/ComputerCraft.java | 5 +- .../shared/FabricCommonHooks.java | 2 +- .../shared/platform/PlatformHelperImpl.java | 37 +- .../fabric/src/main/resources/fabric.mod.json | 2 +- projects/forge/build.gradle.kts | 4 +- .../client/ForgeClientHooks.java | 3 +- .../client/ForgeClientRegistry.java | 11 +- .../client/model/FoiledModel.java | 4 +- .../client/model/turtle/TurtleModel.java | 2 +- .../model/turtle/TurtleModelLoader.java | 21 +- .../platform/ClientPlatformHelperImpl.java | 2 +- .../shared/platform/PlatformHelperImpl.java | 34 +- .../resources/META-INF/accesstransformer.cfg | 7 +- .../resources/META-INF/neoforge.mods.toml | 5 +- .../resources/computercraft.forge.mixins.json | 12 - 269 files changed, 1480 insertions(+), 2635 deletions(-) delete mode 100644 projects/common/src/client/java/dan200/computercraft/client/render/RenderTypes.java delete mode 100644 projects/common/src/client/java/dan200/computercraft/client/render/monitor/MonitorTextureBufferShader.java delete mode 100644 projects/common/src/client/java/dan200/computercraft/client/render/vbo/DirectBuffers.java delete mode 100644 projects/common/src/client/java/dan200/computercraft/client/render/vbo/DirectVertexBuffer.java rename projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/{disk_1.json => disk.json} (76%) delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_10.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_11.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_12.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_13.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_14.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_15.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_16.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_2.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_3.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_4.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_5.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_6.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_7.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_8.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/disk_9.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/wired_modem_full_from.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/advancement/recipes/redstone/wired_modem_full_to.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_1.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_10.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_11.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_12.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_13.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_14.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_15.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_16.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_2.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_3.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_4.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_5.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_6.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_7.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_8.json delete mode 100644 projects/common/src/generated/resources/data/computercraft/recipe/disk_9.json create mode 100644 projects/common/src/generated/resources/data/minecraft/advancement/recipes/misc/wired_modem_from_wired_modem_full.json create mode 100644 projects/common/src/generated/resources/data/minecraft/advancement/recipes/misc/wired_modem_full_from_wired_modem.json rename projects/common/src/generated/resources/data/{computercraft/recipe/wired_modem_full_to.json => minecraft/recipe/wired_modem_from_wired_modem_full.json} (54%) rename projects/common/src/generated/resources/data/{computercraft/recipe/wired_modem_full_from.json => minecraft/recipe/wired_modem_full_from_wired_modem.json} (56%) rename projects/{forge => common}/src/main/java/dan200/computercraft/mixin/V3818_3Mixin.java (68%) create mode 100644 projects/common/src/main/java/dan200/computercraft/shared/recipe/AbstractCraftingRecipe.java delete mode 100644 projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/terminate.png delete mode 100644 projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/terminate_hover.png delete mode 100644 projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_off.png delete mode 100644 projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_off_hover.png create mode 100644 projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/terminate.png create mode 100644 projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/terminate_hover.png create mode 100644 projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_off.png create mode 100644 projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_off_hover.png rename projects/common/src/main/resources/assets/computercraft/textures/gui/{ => sprites}/buttons/turned_on.png (100%) rename projects/common/src/main/resources/assets/computercraft/textures/gui/{ => sprites}/buttons/turned_on_hover.png (100%) create mode 100644 projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/turtle_advanced_selected_slot.png create mode 100644 projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/turtle_normal_selected_slot.png delete mode 100644 projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.fsh delete mode 100644 projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.json delete mode 100644 projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.vsh create mode 100644 projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/GameTestServerMixin.java create mode 100644 projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/MinecraftServerAccessor.java delete mode 100644 projects/fabric/src/client/java/dan200/computercraft/client/model/EmissiveBakedModel.java delete mode 100644 projects/fabric/src/client/java/dan200/computercraft/mixin/client/GameRendererMixin.java delete mode 100644 projects/fabric/src/main/java/dan200/computercraft/mixin/V3818_3Mixin.java delete mode 100644 projects/forge/src/main/resources/computercraft.forge.mixins.json diff --git a/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts b/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts index 7ef28a271..2750566fb 100644 --- a/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts +++ b/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts @@ -4,10 +4,8 @@ /** Default configuration for Fabric projects. */ -import cc.tweaked.gradle.CCTweakedExtension -import cc.tweaked.gradle.CCTweakedPlugin +import cc.tweaked.gradle.* import cc.tweaked.gradle.IdeaRunConfigurations -import cc.tweaked.gradle.MinecraftConfigurations plugins { `java-library` @@ -67,3 +65,9 @@ dependencies { tasks.ideaSyncTask { doLast { IdeaRunConfigurations(project).patch() } } + +tasks.named("checkDependencyConsistency", DependencyCheck::class.java) { + val libs = project.extensions.getByType().named("libs") + // Fabric forces asm to a more recent version + override(libs.findLibrary("asm").get(), "9.7.1") +} diff --git a/gradle.properties b/gradle.properties index f7f78fa35..26ef6f331 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,4 @@ isUnstable=true modVersion=1.113.1 # Minecraft properties: We want to configure this here so we can read it in settings.gradle -mcVersion=1.21.1 +mcVersion=1.21.3 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e5b6c2fd2..fed816303 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,14 +7,14 @@ # Minecraft # MC version is specified in gradle.properties, as we need that in settings.gradle. # Remember to update corresponding versions in fabric.mod.json/neoforge.mods.toml -fabric-api = "0.102.1+1.21.1" -fabric-loader = "0.15.11" -neoForge = "21.1.9" +fabric-api = "0.106.1+1.21.3" +fabric-loader = "0.16.7" +neoForge = "21.3.0-beta" neoForgeSpi = "8.0.1" mixin = "0.8.5" parchment = "2024.07.28" parchmentMc = "1.21" -yarn = "1.21.1+build.1" +yarn = "1.21.3+build.1" # Core dependencies (these versions are tied to the version Minecraft uses) fastutil = "8.5.12" @@ -62,14 +62,14 @@ checkstyle = "10.14.1" curseForgeGradle = "1.1.18" errorProne-core = "2.27.0" errorProne-plugin = "3.1.0" -fabric-loom = "1.7.1" +fabric-loom = "1.8.10" githubRelease = "2.5.2" gradleVersions = "0.50.0" ideaExt = "1.1.7" illuaminate = "0.1.0-73-g43ee16c" lwjgl = "3.3.3" minotaur = "2.8.7" -neoGradle = "7.0.152" +neoGradle = "7.0.165" nullAway = "0.10.25" shadow = "8.3.1" spotless = "6.23.3" @@ -186,9 +186,9 @@ kotlin = ["kotlin-stdlib", "kotlin-coroutines"] # Minecraft externalMods-common = ["iris-forge", "jei-api", "nightConfig-core", "nightConfig-toml"] externalMods-forge-compile = ["moreRed", "iris-forge", "jei-api"] -externalMods-forge-runtime = ["jei-forge"] +externalMods-forge-runtime = [] externalMods-fabric-compile = ["fabricPermissions", "iris-fabric", "jei-api", "rei-api", "rei-builtin"] -externalMods-fabric-runtime = ["jei-fabric", "modmenu"] +externalMods-fabric-runtime = [] # Testing test = ["junit-jupiter-api", "junit-jupiter-params", "hamcrest", "jqwik-api"] diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2c3521197d7c4586c843d1d3e9090525f1898cde..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 3990 zcmV;H4{7l5(*nQL0Kr1kzC=_KMxQY0|W5(lc#i zH*M1^P4B}|{x<+fkObwl)u#`$GxKKV&3pg*-y6R6txw)0qU|Clf9Uds3x{_-**c=7 z&*)~RHPM>Rw#Hi1R({;bX|7?J@w}DMF>dQQU2}9yj%iLjJ*KD6IEB2^n#gK7M~}6R zkH+)bc--JU^pV~7W=3{E*4|ZFpDpBa7;wh4_%;?XM-5ZgZNnVJ=vm!%a2CdQb?oTa z70>8rTb~M$5Tp!Se+4_OKWOB1LF+7gv~$$fGC95ToUM(I>vrd$>9|@h=O?eARj0MH zT4zo(M>`LWoYvE>pXvqG=d96D-4?VySz~=tPVNyD$XMshoTX(1ZLB5OU!I2OI{kb) zS8$B8Qm>wLT6diNnyJZC?yp{Kn67S{TCOt-!OonOK7$K)e-13U9GlnQXPAb&SJ0#3 z+vs~+4Qovv(%i8g$I#FCpCG^C4DdyQw3phJ(f#y*pvNDQCRZ~MvW<}fUs~PL=4??j zmhPyg<*I4RbTz|NHFE-DC7lf2=}-sGkE5e!RM%3ohM7_I^IF=?O{m*uUPH(V?gqyc(Rp?-Qu(3bBIL4Fz(v?=_Sh?LbK{nqZMD>#9D_hNhaV$0ef3@9V90|0u#|PUNTO>$F=qRhg1duaE z0`v~X3G{8RVT@kOa-pU+z8{JWyP6GF*u2e8eKr7a2t1fuqQy)@d|Qn(%YLZ62TWtoX@$nL}9?atE#Yw`rd(>cr0gY;dT9~^oL;u)zgHUvxc2I*b&ZkGM-iq=&(?kyO(3}=P! zRp=rErEyMT5UE9GjPHZ#T<`cnD)jyIL!8P{H@IU#`e8cAG5jMK zVyKw7--dAC;?-qEu*rMr$5@y535qZ6p(R#+fLA_)G~!wnT~~)|s`}&fA(s6xXN`9j zP#Fd3GBa#HeS{5&8p?%DKUyN^X9cYUc6vq}D_3xJ&d@=6j(6BZKPl?!k1?!`f3z&a zR4ZF60Mx7oBxLSxGuzA*Dy5n-d2K=+)6VMZh_0KetK|{e;E{8NJJ!)=_E~1uu=A=r zrn&gh)h*SFhsQJo!f+wKMIE;-EOaMSMB@aXRU(UcnJhZW^B^mgs|M9@5WF@s6B0p& zm#CTz)yiQCgURE{%hjxHcJ6G&>G9i`7MyftL!QQd5 z@RflRs?7)99?X`kHNt>W3l7YqscBpi*R2+fsgABor>KVOu(i(`03aytf2UA!&SC9v z!E}whj#^9~=XHMinFZ;6UOJjo=mmNaWkv~nC=qH9$s-8roGeyaW-E~SzZ3Gg>j zZ8}<320rg4=$`M0nxN!w(PtHUjeeU?MvYgWKZ6kkzABK;vMN0|U;X9abJleJA(xy<}5h5P(5 z{RzAFPvMnX2m0yH0Jn2Uo-p`daE|(O`YQiC#jB8;6bVIUf?SY(k$#C0`d6qT`>Xe0+0}Oj0=F&*D;PVe=Z<=0AGI<6$gYLwa#r` zm449x*fU;_+J>Mz!wa;T-wldoBB%&OEMJgtm#oaI60TSYCy7;+$5?q!zi5K`u66Wq zvg)Fx$s`V3Em{=OEY{3lmh_7|08ykS&U9w!kp@Ctuzqe1JFOGz6%i5}Kmm9>^=gih z?kRxqLA<3@e=}G4R_?phW{4DVr?`tPfyZSN@R=^;P;?!2bh~F1I|fB7P=V=9a6XU5 z<#0f>RS0O&rhc&nTRFOW7&QhevP0#>j0eq<1@D5yAlgMl5n&O9X|Vq}%RX}iNyRFF z7sX&u#6?E~bm~N|z&YikXC=I0E*8Z$v7PtWfjy)$e_Ez25fnR1Q=q1`;U!~U>|&YS zaOS8y!^ORmr2L4ik!IYR8@Dcx8MTC=(b4P6iE5CnrbI~7j7DmM8em$!da&D!6Xu)!vKPdLG z9f#)se|6=5yOCe)N6xDhPI!m81*dNe7u985zi%IVfOfJh69+#ag4ELzGne?o`eA`42K4T)h3S+s)5IT97%O>du- z0U54L8m4}rkRQ?QBfJ%DLssy^+a7Ajw;0&`NOTY4o;0-ivm9 zBz1C%nr_hQ)X)^QM6T1?=yeLkuG9Lf50(eH}`tFye;01&(p?8i+6h};VV-2B~qdxeC#=X z(JLlzy&fHkyi9Ksbcs~&r^%lh^2COldLz^H@X!s~mr9Dr6z!j+4?zkD@Ls7F8(t(f z9`U?P$Lmn*Y{K}aR4N&1N=?xtQ1%jqf1~pJyQ4SgBrEtR`j4lQuh7cqP49Em5cO=I zB(He2`iPN5M=Y0}h(IU$37ANTGx&|b-u1BYA*#dE(L-lptoOpo&th~E)_)y-`6kSH z3vvyVrcBwW^_XYReJ=JYd9OBQrzv;f2AQdZH#$Y{Y+Oa33M70XFI((fs;mB4e`<<{ ze4dv2B0V_?Ytsi>>g%qs*}oDGd5d(RNZ*6?7qNbdp7wP4T72=F&r?Ud#kZr8Ze5tB z_oNb7{G+(o2ajL$!69FW@jjPQ2a5C)m!MKKRirC$_VYIuVQCpf9rIms0GRDf)8AH${I`q^~5rjot@#3$2#zT2f`(N^P7Z;6(@EK$q*Jgif00I6*^ZGV+XB5uw*1R-@23yTw&WKD{s1;HTL;dO)%5i#`dc6b7;5@^{KU%N|A-$zsYw4)7LA{3`Zp>1 z-?K9_IE&z)dayUM)wd8K^29m-l$lFhi$zj0l!u~4;VGR6Y!?MAfBC^?QD53hy6VdD z@eUZIui}~L%#SmajaRq1J|#> z4m=o$vZ*34=ZWK2!QMNEcp2Lbc5N1q!lEDq(bz0b;WI9;e>l=CG9^n#ro`w>_0F$Q zfZ={2QyTkfByC&gy;x!r*NyXXbk=a%~~(#K?< zTke0HuF5{Q+~?@!KDXR|g+43$+;ab`^flS%miup_0OUTm=nIc%d5nLP)i308PIjl_YMF6cpQ__6&$n6it8K- z8PIjl_YMF6cpQ_!r)L8IivW`WdK8mBs6PXdjR2DYdK8nCs73=4j{uVadK8oNjwX|E wpAeHLsTu^*Y>Trk?aBtSQ(D-o$(D8Px^?ZI-PUB? z*1fv!{YdHme3Fc8%cR@*@zc5A_nq&2=R47Hp@$-JF4Fz*;SLw5}K^y>s-s;V!}b2i=5=M- zComP?ju>8Fe@=H@rlwe1l`J*6BTTo`9b$zjQ@HxrAhp0D#u?M~TxGC_!?ccCHCjt| zF*PgJf@kJB`|Ml}cmsyrAjO#Kjr^E5p29w+#>$C`Q|54BoDv$fQ9D?3n32P9LPMIzu?LjNqggOH=1@T{9bMn*u8(GI z!;MLTtFPHal^S>VcJdiYqX0VU|Rn@A}C1xOlxCribxes0~+n2 z6qDaIA2$?e`opx3_KW!rAgbpzU)gFdjAKXh|5w``#F0R|c)Y)Du0_Ihhz^S?k^pk% zP>9|pIDx)xHH^_~+aA=^$M!<8K~Hy(71nJGf6`HnjtS=4X4=Hk^O71oNia2V{HUCC zoN3RSBS?mZCLw;l4W4a+D8qc)XJS`pUJ5X-f^1ytxwr`@si$lAE?{4G|o; zO0l>`rr?;~c;{ZEFJ!!3=7=FdGJ?Q^xfNQh4A?i;IJ4}B+A?4olTK(fN++3CRBP97 ze~lG9h%oegkn)lpW-4F8o2`*WW0mZHwHez`ko@>U1_;EC_6ig|Drn@=DMV9YEUSCa zIf$kHei3(u#zm9I!Jf(4t`Vm1lltJ&lVHy(eIXE8sy9sUpmz%I_gA#8x^Zv8%w?r2 z{GdkX1SkzRIr>prRK@rqn9j2wG|rUvf6PJbbin=yy-TAXrguvzN8jL$hUrIXzr^s5 zVM?H4;eM-QeRFr06@ifV(ocvk?_)~N@1c2ien56UjWXid6W%6ievIh)>dk|rIs##^kY67ib8Kw%#-oVFaXG7$ERyA9(NSJUvWiOA5H(!{uOpcW zg&-?iqPhds%3%tFspHDqqr;A!e@B#iPQjHd=c>N1LoOEGRehVoPOdxJ>b6>yc#o#+ zl8s8!(|NMeqjsy@0x{8^j0d00SqRZjp{Kj)&4UHYGxG+z9b-)72I*&J70?+8e?p_@ z=>-(>l6z5vYlP~<2%DU02b!mA{7mS)NS_eLe=t)sm&+Pmk?asOEKlkPQ)EUvvfC=;4M&*|I!w}(@V_)eUKLA_t^%`o z0PM9LV|UKTLnk|?M3u!|f2S0?UqZsEIH9*NJS-8lzu;A6-rr-ot=dg9SASoluZUkFH$7X; zP=?kYX!K?JL-b~<#7wU;b;eS)O;@?h%sPPk{4xEBxb{!sm0AY|f9cNvx6>$3F!*0c z75H=dy8JvTyO8}g1w{$9T$p~5en}AeSLoCF>_RT9YPMpChUjl310o*$QocjbH& zbnwg#gssR#jDVN{uEi3n(PZ%PFZ|6J2 z5_rBf0-u>e4sFe0*Km49ATi7>Kn0f9!uc|rRMR1Dtt6m1LW8^>qFlo}h$@br=Rmpi z;mI&>OF64Be{dVeHI8utrh)v^wsZ0jii%x8UgZ8TC%K~@I(4E};GFW&(;WVov}3%H zH;IhRkfD^(vt^DjZz(MyHLZxv8}qzPc(%itBkBwf_fC~sDBgh<3XAv5cxxfF3<2U! z03Xe&z`is!JDHbe;mNmfkH+_LFE*I2^mdL@7(@9DfAcP6O04V-ko;Rpgp<%Cj5r8Z zd0`sXoIjV$j)--;jA6Zy^D5&5v$o^>e%>Q?9GLm{i~p^lAn!%ZtF$I~>39XVZxk0b zROh^Bk9cE0AJBLozZIEmy7xG(yHWGztvfnr0(2ro1%>zsGMS^EMu+S$r=_;9 zWwZkgf7Q7`H9sLf2Go^Xy6&h~a&%s2_T@_Csf19MntF$aVFiFkvE3_hUg(B@&Xw@YJ zpL$wNYf78=0c@!QU6_a$>CPiXT7QAGDM}7Z(0z#_ZA=fmLUj{2z7@Ypo71UDy8GHr z-&TLKf6a5WCf@Adle3VglBt4>Z>;xF}}-S~B7<(%B;Y z0QR55{z-buw>8ilNM3u6I+D$S%?)(p>=eBx-HpvZj{7c*_?K=d()*7q?93us}1dq%FAFYLsW8ZTQ_XZLh`P2*6(NgS}qGcfGXVWpwsp#Rs}IuKbk*`2}&) zI^Vsk6S&Q4@oYS?dJ`NwMVBs6f57+RxdqVub#PvMu?$=^OJy5xEl0<5SLsSRy%%a0 zi}Y#1-F3m;Ieh#Y12UgW?-R)|eX>ZuF-2cc!1>~NS|XSF-6In>zBoZg+ml!6%fk7U zw0LHcz8VQk(jOJ+Yu)|^|15ufl$KQd_1eUZZzj`aC%umU6F1&D5XVWce_wAe(qCSZ zpX-QF4e{EmEVN9~6%bR5U*UT{eMHfcUo`jw*u?4r2s_$`}U{?NjvEm(u&<>B|%mq$Q3weshxk z76<``8vh{+nX`@9CB6IE&z)I%IFjR^LH{s1p|eppv=x za(g_jLU|xjWMAn-V7th$f({|LG8zzIE0g?cyW;%Dmtv%C+0@xVxPE^ zyZzi9P%JAD6ynwHptuzP`Kox7*9h7XSMonCalv;Md0i9Vb-c*!f0ubfk?&T&T}AHh z4m8Bz{JllKcdNg?D^%a5MFQ;#1z|*}H^qHLzW)L}wp?2tY7RejtSh8<;Zw)QGJYUm z|MbTxyj*McKlStlT9I5XlSWtQGN&-LTr2XyNU+`490rg?LYLMRnz-@oKqT1hpCGqP zyRXt4=_Woj$%n5ee<3zhLF>5>`?m9a#xQH+Jk_+|RM8Vi;2*XbK- zEL6sCpaGPzP>k8f4Kh|##_imt#zJMB;ir|JrMPGW`rityK1vHXMLy18%qmMQAm4WZ zP)i30KR&5vs15)C+8dM66&$k~i|ZT;KR&5vs15)C+8dJ(sAmGPijyIz6_bsqKLSFH zlOd=TljEpH0>h4zA*dCTK&emy#FCRCs1=i^sZ9bFmXjf<6_X39E(XY)00000#N437 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9355b4155..df97d72b8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/projects/common-api/src/client/java/dan200/computercraft/api/client/TransformedModel.java b/projects/common-api/src/client/java/dan200/computercraft/api/client/TransformedModel.java index a632920b4..8ce025488 100644 --- a/projects/common-api/src/client/java/dan200/computercraft/api/client/TransformedModel.java +++ b/projects/common-api/src/client/java/dan200/computercraft/api/client/TransformedModel.java @@ -60,7 +60,7 @@ public record TransformedModel(BakedModel model, Transformation matrix) { } public static TransformedModel of(ItemStack item, Transformation transform) { - var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(item); + var model = Minecraft.getInstance().getItemRenderer().getModel(item, null, null, 0); return new TransformedModel(model, transform); } } diff --git a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModeller.java b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModeller.java index 4adfc8d91..5b9a4e91e 100644 --- a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModeller.java +++ b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModeller.java @@ -48,7 +48,7 @@ public interface TurtleUpgradeModeller { * by other means. * * @return A list of models that this modeller depends on. - * @see UnbakedModel#getDependencies() + * @see UnbakedModel#resolveDependencies(UnbakedModel.Resolver) */ default Stream getDependencies() { return Stream.of(); diff --git a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModellers.java b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModellers.java index 644c0a65a..71066c334 100644 --- a/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModellers.java +++ b/projects/common-api/src/client/java/dan200/computercraft/api/client/turtle/TurtleUpgradeModellers.java @@ -38,7 +38,7 @@ final class TurtleUpgradeModellers { @Override public TransformedModel getModel(ITurtleUpgrade upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, DataComponentPatch data) { var stack = upgrade.getUpgradeItem(data); - var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(stack); + var model = Minecraft.getInstance().getItemRenderer().getModel(stack, null, null, 0); if (stack.hasFoil()) model = ClientPlatformHelper.get().createdFoiledModel(model); return new TransformedModel(model, side == TurtleSide.LEFT ? leftTransform : rightTransform); } diff --git a/projects/common/build.gradle.kts b/projects/common/build.gradle.kts index 952639cbf..44a4c9074 100644 --- a/projects/common/build.gradle.kts +++ b/projects/common/build.gradle.kts @@ -15,6 +15,12 @@ sourceSets { main { resources.srcDir("src/generated/resources") } + client { + java { + exclude("dan200/computercraft/client/integration/emi") + exclude("dan200/computercraft/client/integration/jei") + } + } } minecraft { diff --git a/projects/common/src/client/java/dan200/computercraft/client/ClientHooks.java b/projects/common/src/client/java/dan200/computercraft/client/ClientHooks.java index bd45f9310..2bcae77d9 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/ClientHooks.java +++ b/projects/common/src/client/java/dan200/computercraft/client/ClientHooks.java @@ -11,7 +11,6 @@ import dan200.computercraft.client.pocket.ClientPocketComputers; import dan200.computercraft.client.render.CableHighlightRenderer; import dan200.computercraft.client.render.PocketItemRenderer; import dan200.computercraft.client.render.PrintoutItemRenderer; -import dan200.computercraft.client.render.monitor.MonitorBlockEntityRenderer; import dan200.computercraft.client.render.monitor.MonitorHighlightRenderer; import dan200.computercraft.client.render.monitor.MonitorRenderState; import dan200.computercraft.client.sound.SpeakerManager; @@ -29,11 +28,11 @@ import dan200.computercraft.shared.util.WorldUtil; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.state.ItemFrameRenderState; import net.minecraft.client.sounds.AudioStream; import net.minecraft.client.sounds.SoundEngine; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.decoration.ItemFrame; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; @@ -88,7 +87,7 @@ public final class ClientHooks { return false; } - public static boolean onRenderItemFrame(PoseStack transform, MultiBufferSource render, ItemFrame frame, ItemStack stack, int light) { + public static boolean onRenderItemFrame(PoseStack transform, MultiBufferSource render, ItemFrameRenderState frame, ItemStack stack, int light) { if (stack.getItem() instanceof PrintoutItem) { PrintoutItemRenderer.onRenderInFrame(transform, render, frame, stack, light); return true; @@ -132,17 +131,6 @@ public final class ClientHooks { if (upgrade != null) out.accept(String.format("Upgrade[%s]: %s", side, upgrade.holder().key().location())); } - /** - * Add additional information about the game to the debug screen. - * - * @param addText A callback which adds a single line of text. - */ - public static void addGameDebugInfo(Consumer addText) { - if (MonitorBlockEntityRenderer.hasRenderedThisFrame() && Minecraft.getInstance().getDebugOverlay().showDebugScreen()) { - addText.accept("[CC:T] Monitor renderer: " + MonitorBlockEntityRenderer.currentRenderer()); - } - } - public static @Nullable BlockState getBlockBreakingState(BlockState state, BlockPos pos) { // Only apply to cables which have both a cable and modem if (state.getBlock() != ModRegistry.Blocks.CABLE.get() diff --git a/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java b/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java index 46711d758..3dfb92444 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java +++ b/projects/common/src/client/java/dan200/computercraft/client/ClientRegistry.java @@ -14,7 +14,6 @@ import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller; import dan200.computercraft.client.gui.*; import dan200.computercraft.client.pocket.ClientPocketComputers; import dan200.computercraft.client.render.CustomLecternRenderer; -import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.client.render.TurtleBlockEntityRenderer; import dan200.computercraft.client.render.monitor.MonitorBlockEntityRenderer; import dan200.computercraft.client.turtle.TurtleModemModeller; @@ -34,7 +33,6 @@ import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.MenuAccess; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; import net.minecraft.client.renderer.item.ClampedItemPropertyFunction; @@ -42,8 +40,7 @@ import net.minecraft.client.renderer.item.ItemProperties; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.PreparableReloadListener; -import net.minecraft.server.packs.resources.ResourceProvider; -import net.minecraft.util.FastColor; +import net.minecraft.util.ARGB; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.MenuType; @@ -54,7 +51,6 @@ import net.minecraft.world.level.ItemLike; import javax.annotation.Nullable; import java.io.File; -import java.io.IOException; import java.util.Collection; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -182,7 +178,7 @@ public final class ClientRegistry { case 1 -> DyedItemColor.getOrDefault(stack, -1); // Frame colour case 2 -> { // Light colour var computer = ClientPocketComputers.get(stack); - yield computer == null || computer.getLightState() == -1 ? Colour.BLACK.getARGB() : FastColor.ARGB32.opaque(computer.getLightState()); + yield computer == null || computer.getLightState() == -1 ? Colour.BLACK.getARGB() : ARGB.opaque(computer.getLightState()); } }; } @@ -191,10 +187,6 @@ public final class ClientRegistry { return layer == 0 ? DyedItemColor.getOrDefault(stack, -1) : -1; } - public static void registerShaders(ResourceProvider resources, BiConsumer> load) throws IOException { - RenderTypes.registerShaders(resources, load); - } - private record UnclampedPropertyFunction( ClampedItemPropertyFunction function ) implements ClampedItemPropertyFunction { diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java index 6e4f39020..9d8485bed 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java @@ -99,7 +99,7 @@ public abstract class AbstractComputerScreen ext if (uploadNagDeadline != Long.MAX_VALUE && Util.getNanos() >= uploadNagDeadline) { new ItemToast(minecraft(), displayStack, NO_RESPONSE_TITLE, NO_RESPONSE_MSG, ItemToast.TRANSFER_NO_RESPONSE_TOKEN) - .showOrReplace(minecraft().getToasts()); + .showOrReplace(minecraft().getToastManager()); uploadNagDeadline = Long.MAX_VALUE; } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java index b398da342..45896e151 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/ComputerScreen.java @@ -7,7 +7,6 @@ package dan200.computercraft.client.gui; import dan200.computercraft.client.gui.widgets.ComputerSidebar; import dan200.computercraft.client.gui.widgets.TerminalWidget; import dan200.computercraft.client.render.ComputerBorderRenderer; -import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.client.render.SpriteRenderer; import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu; import net.minecraft.client.gui.GuiGraphics; @@ -40,14 +39,14 @@ public final class ComputerScreen extends Abstra public void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { // Draw a border around the terminal var terminal = getTerminal(); - var spriteRenderer = SpriteRenderer.createForGui(graphics, RenderTypes.GUI_SPRITES); - var computerTextures = GuiSprites.getComputerTextures(family); - ComputerBorderRenderer.render( - spriteRenderer, computerTextures, - terminal.getX(), terminal.getY(), terminal.getWidth(), terminal.getHeight(), false - ); - ComputerSidebar.renderBackground(spriteRenderer, computerTextures, leftPos, topPos + sidebarYOffset); - graphics.flush(); // Flush to ensure background textures are drawn before foreground. + SpriteRenderer.inGui(graphics, spriteRenderer -> { + var computerTextures = GuiSprites.getComputerTextures(family); + ComputerBorderRenderer.render( + spriteRenderer, computerTextures, + terminal.getX(), terminal.getY(), terminal.getWidth(), terminal.getHeight(), false + ); + ComputerSidebar.renderBackground(spriteRenderer, computerTextures, leftPos, topPos + sidebarYOffset); + }); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java index 70a8ed8db..b9f8d1884 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/DiskDriveScreen.java @@ -7,6 +7,7 @@ package dan200.computercraft.client.gui; import dan200.computercraft.shared.peripheral.diskdrive.DiskDriveMenu; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.RenderType; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; @@ -23,7 +24,7 @@ public class DiskDriveScreen extends AbstractContainerScreen { @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { - graphics.blit(BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight); + graphics.blit(RenderType::guiTextured, BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight, 256, 256); } @Override diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java b/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java index e6025c221..21bebbd72 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java @@ -35,8 +35,8 @@ public final class GuiSprites extends TextureAtlasHolder { private static ButtonTextures button(String name) { return new ButtonTextures( - ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name), - ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "gui/buttons/" + name + "_hover") + ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "buttons/" + name), + ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "buttons/" + name + "_hover") ); } @@ -97,12 +97,8 @@ public final class GuiSprites extends TextureAtlasHolder { * @param active The texture for the button when it is active (hovered or focused). */ public record ButtonTextures(ResourceLocation normal, ResourceLocation active) { - public TextureAtlasSprite get(boolean active) { - return GuiSprites.get(active ? this.active : normal); - } - - public Stream textures() { - return Stream.of(normal, active); + public ResourceLocation get(boolean active) { + return active ? this.active : normal; } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java b/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java index b3bfd4294..9adad3c34 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/ItemToast.java @@ -5,9 +5,11 @@ package dan200.computercraft.client.gui; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.toasts.Toast; -import net.minecraft.client.gui.components.toasts.ToastComponent; +import net.minecraft.client.gui.components.toasts.ToastManager; +import net.minecraft.client.renderer.RenderType; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.FormattedCharSequence; @@ -35,8 +37,9 @@ public class ItemToast implements Toast { private final Object token; private final int width; - private boolean isNew = true; - private long firstDisplay; + private boolean changed = true; + private long lastChanged; + private Visibility visibility = Visibility.HIDE; public ItemToast(Minecraft minecraft, ItemStack stack, Component title, Component message, Object token) { this.stack = stack; @@ -48,10 +51,10 @@ public class ItemToast implements Toast { width = Math.max(MAX_LINE_SIZE, this.message.stream().mapToInt(font::width).max().orElse(MAX_LINE_SIZE)) + MARGIN * 3 + IMAGE_SIZE; } - public void showOrReplace(ToastComponent toasts) { + public void showOrReplace(ToastManager toasts) { var existing = toasts.getToast(ItemToast.class, getToken()); if (existing != null) { - existing.isNew = true; + existing.changed = true; } else { toasts.addToast(this); } @@ -73,28 +76,22 @@ public class ItemToast implements Toast { } @Override - public Visibility render(GuiGraphics graphics, ToastComponent component, long time) { - if (isNew) { + public Visibility getWantedVisibility() { + return visibility; + } - firstDisplay = time; - isNew = false; + @Override + public void update(ToastManager toastManager, long time) { + if (changed) { + lastChanged = time; + changed = false; } + visibility = time - lastChanged < DISPLAY_TIME * toastManager.getNotificationDisplayTimeMultiplier() ? Visibility.SHOW : Visibility.HIDE; + } - if (width == 160 && message.size() <= 1) { - graphics.blitSprite(TEXTURE, 0, 0, width, height()); - } else { - - var height = height(); - - var bottom = Math.min(4, height - 28); - renderBackgroundRow(graphics, width, 0, 0, 28); - - for (var i = 28; i < height - bottom; i += 10) { - renderBackgroundRow(graphics, width, 16, i, Math.min(16, height - i - bottom)); - } - - renderBackgroundRow(graphics, width, 32 - bottom, height - bottom, bottom); - } + @Override + public void render(GuiGraphics graphics, Font font, long time) { + graphics.blitSprite(RenderType::guiTextured, TEXTURE, 0, 0, width(), height()); var textX = MARGIN; if (!stack.isEmpty()) { @@ -102,23 +99,9 @@ public class ItemToast implements Toast { graphics.renderFakeItem(stack, MARGIN, MARGIN + height() / 2 - IMAGE_SIZE); } - graphics.drawString(component.getMinecraft().font, title, textX, MARGIN, 0xff500050, false); + graphics.drawString(font, title, textX, MARGIN, 0xff500050, false); for (var i = 0; i < message.size(); ++i) { - graphics.drawString(component.getMinecraft().font, message.get(i), textX, LINE_SPACING + (i + 1) * LINE_SPACING, 0xff000000, false); + graphics.drawString(font, message.get(i), textX, LINE_SPACING + (i + 1) * LINE_SPACING, 0xff000000, false); } - - return time - firstDisplay < DISPLAY_TIME ? Visibility.SHOW : Visibility.HIDE; - } - - private static void renderBackgroundRow(GuiGraphics graphics, int x, int u, int y, int height) { - var leftOffset = u == 0 ? 20 : 5; - var rightOffset = Math.min(60, x - leftOffset); - - graphics.blitSprite(TEXTURE, 160, 32, 0, u, 0, y, leftOffset, height); - for (var k = leftOffset; k < x - rightOffset; k += 64) { - graphics.blitSprite(TEXTURE, 160, 32, 32, u, k, y, Math.min(64, x - k - rightOffset), height); - } - - graphics.blitSprite(TEXTURE, 160, 32, 160 - rightOffset, u, x - rightOffset, y, rightOffset, height); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java index 36467a45a..5472f9245 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/NoTermComputerScreen.java @@ -67,7 +67,7 @@ public class NoTermComputerScreen extends Screen @Override public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) { - Objects.requireNonNull(minecraft().player).getInventory().swapPaint(scrollY); + // FIXME(1.21.2): Objects.requireNonNull(minecraft().player).getInventory().setSelectedHotbarSlot(scrollY); return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY); } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java index 0cf39fa21..1e2c7bd75 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/OptionScreen.java @@ -10,6 +10,7 @@ import net.minecraft.client.gui.components.AbstractWidget; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.MultiLineLabel; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.renderer.RenderType; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; @@ -87,12 +88,13 @@ public final class OptionScreen extends Screen { @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { // Render the actual texture. - graphics.blit(BACKGROUND, x, y, 0, 0, innerWidth, PADDING); - graphics.blit(BACKGROUND, + graphics.blit(RenderType::guiTextured, BACKGROUND, x, y, 0, 0, innerWidth, PADDING, 256, 256); + graphics.blit(RenderType::guiTextured, BACKGROUND, x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2, - innerWidth, PADDING + innerWidth, PADDING, + 256, 256 ); - graphics.blit(BACKGROUND, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING); + graphics.blit(RenderType::guiTextured, BACKGROUND, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING, 256, 256); assertNonNull(messageRenderer).renderLeftAlignedNoShadow(graphics, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040); super.render(graphics, mouseX, mouseY, partialTicks); diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java index 70deac9c2..7710df1f0 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/PrinterScreen.java @@ -7,6 +7,7 @@ package dan200.computercraft.client.gui; import dan200.computercraft.shared.peripheral.printer.PrinterMenu; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.RenderType; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; @@ -23,9 +24,11 @@ public class PrinterScreen extends AbstractContainerScreen { @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { - graphics.blit(BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight); + graphics.blit(RenderType::guiTextured, BACKGROUND, leftPos, topPos, 0, 0, imageWidth, imageHeight, 256, 256); - if (getMenu().isPrinting()) graphics.blit(BACKGROUND, leftPos + 34, topPos + 21, 176, 0, 25, 45); + if (getMenu().isPrinting()) { + graphics.blit(RenderType::guiTextured, BACKGROUND, leftPos + 34, topPos + 21, 176, 0, 25, 45, 256, 256); + } } @Override diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java index 8df70c395..c8d1608ee 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/PrintoutScreen.java @@ -10,6 +10,7 @@ import dan200.computercraft.shared.media.PrintoutMenu; import dan200.computercraft.shared.media.items.PrintoutData; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.LightTexture; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -20,7 +21,6 @@ import org.lwjgl.glfw.GLFW; import java.util.Objects; import static dan200.computercraft.client.render.PrintoutRenderer.*; -import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP; /** * The GUI for printed pages and books. @@ -116,8 +116,10 @@ public final class PrintoutScreen extends AbstractContainerScreen graphics.pose().pushPose(); graphics.pose().translate(0, 0, 1); - drawBorder(graphics.pose(), graphics.bufferSource(), leftPos, topPos, 0, page, printout.pages(), printout.book(), FULL_BRIGHT_LIGHTMAP); - drawText(graphics.pose(), graphics.bufferSource(), leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutData.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, printout.text(), printout.colour()); + graphics.drawSpecial(bufferSource -> { + drawBorder(graphics.pose(), bufferSource, leftPos, topPos, 0, page, printout.pages(), printout.book(), LightTexture.FULL_BRIGHT); + drawText(graphics.pose(), bufferSource, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, PrintoutData.LINES_PER_PAGE * page, LightTexture.FULL_BRIGHT, printout.text(), printout.colour()); + }); graphics.pose().popPose(); } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java index 381bd6219..2aae0b5e9 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/TurtleScreen.java @@ -7,12 +7,12 @@ package dan200.computercraft.client.gui; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.client.gui.widgets.ComputerSidebar; import dan200.computercraft.client.gui.widgets.TerminalWidget; -import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.client.render.SpriteRenderer; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.inventory.AbstractComputerMenu; import dan200.computercraft.shared.turtle.inventory.TurtleMenu; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.RenderType; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; @@ -26,6 +26,9 @@ public class TurtleScreen extends AbstractComputerScreen { private static final ResourceLocation BACKGROUND_NORMAL = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_normal.png"); private static final ResourceLocation BACKGROUND_ADVANCED = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "textures/gui/turtle_advanced.png"); + private static final ResourceLocation SELECTED_NORMAL = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "turtle_normal_selected_slot"); + private static final ResourceLocation SELECTED_ADVANCED = ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "turtle_advanced_selected_slot"); + private static final int TEX_WIDTH = 278; private static final int TEX_HEIGHT = 217; @@ -46,23 +49,28 @@ public class TurtleScreen extends AbstractComputerScreen { @Override protected void renderBg(GuiGraphics graphics, float partialTicks, int mouseX, int mouseY) { var advanced = family == ComputerFamily.ADVANCED; - var texture = advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL; - graphics.blit(texture, leftPos + AbstractComputerMenu.SIDEBAR_WIDTH, topPos, 0, 0, 0, TEX_WIDTH, TEX_HEIGHT, FULL_TEX_SIZE, FULL_TEX_SIZE); + graphics.blit( + RenderType::guiTextured, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL, + leftPos + AbstractComputerMenu.SIDEBAR_WIDTH, topPos, 0, 0, + TEX_WIDTH, TEX_HEIGHT, FULL_TEX_SIZE, FULL_TEX_SIZE + ); // Render selected slot var slot = getMenu().getSelectedSlot(); if (slot >= 0) { var slotX = slot % 4; var slotY = slot / 4; - graphics.blit(texture, - leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18, 0, - 0, 217, 24, 24, FULL_TEX_SIZE, FULL_TEX_SIZE + + graphics.blitSprite( + RenderType::guiTextured, advanced ? SELECTED_ADVANCED : SELECTED_NORMAL, + leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18, + 22, 22 ); } // Render sidebar - var spriteRenderer = SpriteRenderer.createForGui(graphics, RenderTypes.GUI_SPRITES); - ComputerSidebar.renderBackground(spriteRenderer, GuiSprites.getComputerTextures(family), leftPos, topPos + sidebarYOffset); - graphics.flush(); // Flush to ensure background textures are drawn before foreground. + SpriteRenderer.inGui(graphics, spriteRenderer -> + ComputerSidebar.renderBackground(spriteRenderer, GuiSprites.getComputerTextures(family), leftPos, topPos + sidebarYOffset) + ); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java index 88f5f02d7..31a80922b 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/DynamicImageButton.java @@ -4,14 +4,14 @@ package dan200.computercraft.client.gui.widgets; -import com.mojang.blaze3d.systems.RenderSystem; import it.unimi.dsi.fastutil.booleans.Boolean2ObjectFunction; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Tooltip; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.RenderType; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.function.Supplier; @@ -21,11 +21,11 @@ import java.util.function.Supplier; * dynamically. */ public class DynamicImageButton extends Button { - private final Boolean2ObjectFunction texture; + private final Boolean2ObjectFunction texture; private final Supplier message; public DynamicImageButton( - int x, int y, int width, int height, Boolean2ObjectFunction texture, OnPress onPress, + int x, int y, int width, int height, Boolean2ObjectFunction texture, OnPress onPress, HintedMessage message ) { this(x, y, width, height, texture, onPress, () -> message); @@ -33,7 +33,7 @@ public class DynamicImageButton extends Button { public DynamicImageButton( int x, int y, int width, int height, - Boolean2ObjectFunction texture, + Boolean2ObjectFunction texture, OnPress onPress, Supplier message ) { super(x, y, width, height, Component.empty(), onPress, DEFAULT_NARRATION); @@ -48,10 +48,7 @@ public class DynamicImageButton extends Button { setTooltip(message.tooltip()); var texture = this.texture.get(isHoveredOrFocused()); - - RenderSystem.disableDepthTest(); - graphics.blit(getX(), getY(), 0, width, height, texture); - RenderSystem.enableDepthTest(); + graphics.blitSprite(RenderType::guiTextured, texture, getX(), getY(), width, height); } public record HintedMessage(Component message, Tooltip tooltip) { diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java index 50a0f35d4..0c35fa33b 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/widgets/TerminalWidget.java @@ -4,7 +4,6 @@ package dan200.computercraft.client.gui.widgets; -import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.client.render.text.FixedWidthFontRenderer; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.util.StringUtil; @@ -257,12 +256,12 @@ public class TerminalWidget extends AbstractWidget { public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { if (!visible) return; - var emitter = FixedWidthFontRenderer.toVertexConsumer(graphics.pose(), graphics.bufferSource().getBuffer(RenderTypes.TERMINAL)); - - FixedWidthFontRenderer.drawTerminal( - emitter, - (float) innerX, (float) innerY, terminal, (float) MARGIN, (float) MARGIN, (float) MARGIN, (float) MARGIN - ); + graphics.drawSpecial(bufferSource -> { + FixedWidthFontRenderer.drawTerminal( + FixedWidthFontRenderer.toVertexConsumer(graphics.pose(), bufferSource.getBuffer(FixedWidthFontRenderer.TERMINAL_TEXT)), + (float) innerX, (float) innerY, terminal, (float) MARGIN, (float) MARGIN, (float) MARGIN, (float) MARGIN + ); + }); } @Override diff --git a/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java b/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java index a8241d643..e9d5046ae 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java +++ b/projects/common/src/client/java/dan200/computercraft/client/integration/IrisShaderMod.java @@ -5,17 +5,18 @@ package dan200.computercraft.client.integration; import com.google.auto.service.AutoService; +import com.mojang.blaze3d.vertex.ByteBufferBuilder; import com.mojang.blaze3d.vertex.VertexFormat; -import dan200.computercraft.client.render.RenderTypes; import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer; import dan200.computercraft.shared.platform.PlatformHelper; import net.irisshaders.iris.api.v0.IrisApi; import net.irisshaders.iris.api.v0.IrisTextVertexSink; -import net.minecraft.util.FastColor; +import net.minecraft.client.renderer.LightTexture; +import org.lwjgl.system.MemoryUtil; +import javax.annotation.Nullable; import java.nio.ByteBuffer; import java.util.Optional; -import java.util.function.IntFunction; @AutoService(ShaderMod.Provider.class) public class IrisShaderMod implements ShaderMod.Provider { @@ -31,7 +32,7 @@ public class IrisShaderMod implements ShaderMod.Provider { } @Override - public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, IntFunction makeBuffer) { + public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, ByteBufferBuilder makeBuffer) { return IrisApi.getInstance().getMinorApiRevision() >= 1 ? new IrisQuadEmitter(vertexCount, makeBuffer) : super.getQuadEmitter(vertexCount, makeBuffer); @@ -39,25 +40,24 @@ public class IrisShaderMod implements ShaderMod.Provider { private static final class IrisQuadEmitter implements DirectFixedWidthFontRenderer.QuadEmitter { private final IrisTextVertexSink sink; + private @Nullable ByteBuffer buffer; - private IrisQuadEmitter(int vertexCount, IntFunction makeBuffer) { - sink = IrisApi.getInstance().createTextVertexSink(vertexCount, makeBuffer); + private IrisQuadEmitter(int vertexCount, ByteBufferBuilder builder) { + sink = IrisApi.getInstance().createTextVertexSink(vertexCount, i -> { + if (buffer != null) throw new IllegalStateException("Allocated multiple buffers"); + return buffer = MemoryUtil.memByteBuffer(builder.reserve(i), i); + }); + } + + @Override + public void quad(float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) { + sink.quad(x1, y1, x2, y2, z, colour, u1, v1, u2, v2, LightTexture.FULL_BRIGHT); } @Override public VertexFormat format() { return sink.getUnderlyingVertexFormat(); } - - @Override - public ByteBuffer buffer() { - return sink.getUnderlyingByteBuffer(); - } - - @Override - public void quad(float x1, float y1, float x2, float y2, float z, int colour, float u1, float v1, float u2, float v2) { - sink.quad(x1, y1, x2, y2, z, FastColor.ABGR32.fromArgb32(colour), u1, v1, u2, v2, RenderTypes.FULL_BRIGHT_LIGHTMAP); - } } } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java b/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java index 9c6a236ad..122f32489 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java +++ b/projects/common/src/client/java/dan200/computercraft/client/integration/ShaderMod.java @@ -4,14 +4,12 @@ package dan200.computercraft.client.integration; -import dan200.computercraft.client.render.RenderTypes; +import com.mojang.blaze3d.vertex.ByteBufferBuilder; +import com.mojang.blaze3d.vertex.VertexBuffer; import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer; -import dan200.computercraft.client.render.vbo.DirectVertexBuffer; -import java.nio.ByteBuffer; import java.util.Optional; import java.util.ServiceLoader; -import java.util.function.IntFunction; /** * Find the currently loaded shader mod (if present) and provides utilities for interacting with it. @@ -31,16 +29,14 @@ public class ShaderMod { } /** - * Get an appropriate quad emitter for use with {@link DirectVertexBuffer} and {@link DirectFixedWidthFontRenderer} . + * Get an appropriate quad emitter for use with {@link VertexBuffer} and {@link DirectFixedWidthFontRenderer} . * * @param vertexCount The number of vertices. - * @param makeBuffer A function to allocate a temporary buffer. + * @param buffer A function to allocate a temporary buffer. * @return The quad emitter. */ - public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, IntFunction makeBuffer) { - return new DirectFixedWidthFontRenderer.ByteBufferEmitter( - makeBuffer.apply(RenderTypes.TERMINAL.format().getVertexSize() * vertexCount * 4) - ); + public DirectFixedWidthFontRenderer.QuadEmitter getQuadEmitter(int vertexCount, ByteBufferBuilder buffer) { + return new DirectFixedWidthFontRenderer.ByteBufferEmitter(buffer); } public interface Provider { diff --git a/projects/common/src/client/java/dan200/computercraft/client/model/turtle/ModelTransformer.java b/projects/common/src/client/java/dan200/computercraft/client/model/turtle/ModelTransformer.java index 72c7e3bd5..3213c376d 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/model/turtle/ModelTransformer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/model/turtle/ModelTransformer.java @@ -80,7 +80,7 @@ public class ModelTransformer { } var direction = Direction.rotate(transformation, quad.getDirection()); - return new BakedQuad(outputData, quad.getTintIndex(), direction, quad.getSprite(), quad.isShade()); + return new BakedQuad(outputData, quad.getTintIndex(), direction, quad.getSprite(), quad.isShade(), 0); } public static int getVertexOffset(int vertex, boolean invert) { diff --git a/projects/common/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelParts.java b/projects/common/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelParts.java index a6ef119ca..977c673fc 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelParts.java +++ b/projects/common/src/client/java/dan200/computercraft/client/model/turtle/TurtleModelParts.java @@ -107,8 +107,7 @@ public final class TurtleModelParts { } private List buildModel(Combination combo) { - var mc = Minecraft.getInstance(); - var modelManager = mc.getItemRenderer().getItemModelShaper().getModelManager(); + var modelManager = Minecraft.getInstance().getModelManager(); var transformation = combo.flip ? flip : identity; var parts = new ArrayList(4); diff --git a/projects/common/src/client/java/dan200/computercraft/client/platform/ClientNetworkContextImpl.java b/projects/common/src/client/java/dan200/computercraft/client/platform/ClientNetworkContextImpl.java index 45fc090a2..7b8e3553c 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/platform/ClientNetworkContextImpl.java +++ b/projects/common/src/client/java/dan200/computercraft/client/platform/ClientNetworkContextImpl.java @@ -22,11 +22,13 @@ import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; +import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.JukeboxSong; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.LevelEvent; import javax.annotation.Nullable; import java.util.UUID; @@ -62,10 +64,14 @@ public final class ClientNetworkContextImpl implements ClientNetworkContext { @Override public void handlePlayRecord(BlockPos pos, @Nullable Holder song) { + var level = Minecraft.getInstance().level; + if (level == null) return; + if (song == null) { - Minecraft.getInstance().levelRenderer.stopJukeboxSongAndNotifyNearby(pos); + level.levelEvent(LevelEvent.SOUND_STOP_JUKEBOX_SONG, pos, 0); } else { - Minecraft.getInstance().levelRenderer.playJukeboxSong(song, pos); + var id = level.registryAccess().lookupOrThrow(Registries.JUKEBOX_SONG).getIdOrThrow(song.value()); + level.levelEvent(LevelEvent.SOUND_PLAY_JUKEBOX_SONG, pos, id); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/ModelRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/ModelRenderer.java index 4e4019430..1905bfae2 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/ModelRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/ModelRenderer.java @@ -70,7 +70,7 @@ public final class ModelRenderer { var matrix = pose.pose(); // It's a little dubious to transform using this matrix rather than the normal matrix. This mirrors the logic in // Direction.rotate (so not out of nowhere!), but is a little suspicious. - var dirNormal = quad.getDirection().getNormal(); + var dirNormal = quad.getDirection().getUnitVec3i(); var vector = new Vector4f(); matrix.transform(dirNormal.getX(), dirNormal.getY(), dirNormal.getZ(), 0.0f, vector).normalize(); diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/PocketItemRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/PocketItemRenderer.java index 60eaa1bcd..6fd55cf31 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/PocketItemRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/PocketItemRenderer.java @@ -13,8 +13,10 @@ import dan200.computercraft.core.util.Colour; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.config.Config; import dan200.computercraft.shared.pocket.items.PocketComputerItem; +import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.util.FastColor; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.util.ARGB; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.DyedItemColor; import org.joml.Matrix4f; @@ -72,7 +74,7 @@ public final class PocketItemRenderer extends ItemMapLikeRenderer { var lightColour = computer == null || computer.getLightState() == -1 ? Colour.BLACK.getHex() : computer.getLightState(); renderLight(transform, bufferSource, lightColour, width, height); - var quadEmitter = FixedWidthFontRenderer.toVertexConsumer(transform, bufferSource.getBuffer(RenderTypes.TERMINAL)); + var quadEmitter = FixedWidthFontRenderer.toVertexConsumer(transform, bufferSource.getBuffer(FixedWidthFontRenderer.TERMINAL_TEXT)); if (terminal == null) { FixedWidthFontRenderer.drawEmptyTerminal(quadEmitter, 0, 0, width, height); } else { @@ -89,16 +91,16 @@ public final class PocketItemRenderer extends ItemMapLikeRenderer { var g = (colour >>> 8) & 0xFF; var b = colour & 0xFF; - var spriteRenderer = new SpriteRenderer(transform, render.getBuffer(RenderTypes.GUI_SPRITES), 0, light, r, g, b); + var spriteRenderer = new SpriteRenderer(transform, render.getBuffer(RenderType.text(GuiSprites.TEXTURE)), 0, light, r, g, b); ComputerBorderRenderer.render(spriteRenderer, texture, 0, 0, width, height, true); } private static void renderLight(PoseStack transform, MultiBufferSource render, int colour, int width, int height) { - var buffer = render.getBuffer(RenderTypes.TERMINAL); + var buffer = render.getBuffer(FixedWidthFontRenderer.TERMINAL_TEXT); FixedWidthFontRenderer.drawQuad( FixedWidthFontRenderer.toVertexConsumer(transform, buffer), width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0.001f, LIGHT_HEIGHT * 2, LIGHT_HEIGHT, - FastColor.ARGB32.opaque(colour), RenderTypes.FULL_BRIGHT_LIGHTMAP + ARGB.opaque(colour), LightTexture.FULL_BRIGHT ); } } diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutItemRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutItemRenderer.java index 1a4fa829b..9e6a2046f 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutItemRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutItemRenderer.java @@ -10,8 +10,7 @@ import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.media.items.PrintoutData; import dan200.computercraft.shared.media.items.PrintoutItem; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.client.renderer.entity.state.ItemFrameRenderState; import net.minecraft.world.item.ItemStack; import static dan200.computercraft.client.render.PrintoutRenderer.*; @@ -38,14 +37,14 @@ public final class PrintoutItemRenderer extends ItemMapLikeRenderer { drawPrintout(transform, render, stack, light); } - public static void onRenderInFrame(PoseStack transform, MultiBufferSource render, ItemFrame frame, ItemStack stack, int packedLight) { + public static void onRenderInFrame(PoseStack transform, MultiBufferSource render, ItemFrameRenderState frame, ItemStack stack, int packedLight) { // Move a little bit forward to ensure we're not clipping with the frame transform.translate(0.0f, 0.0f, -0.001f); transform.mulPose(Axis.ZP.rotationDegrees(180f)); transform.scale(0.95f, 0.95f, -0.95f); transform.translate(-0.5f, -0.5f, 0.0f); - var light = frame.getType() == EntityType.GLOW_ITEM_FRAME ? 0xf000d2 : packedLight; // See getLightVal. + var light = frame.isGlowFrame ? 0xf000d2 : packedLight; // See getLightVal. drawPrintout(transform, render, stack, light); } diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java index 68bbfaacf..821e859e4 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/PrintoutRenderer.java @@ -11,6 +11,8 @@ import dan200.computercraft.core.terminal.Palette; import dan200.computercraft.core.terminal.TextBuffer; import dan200.computercraft.shared.media.items.PrintoutData; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.resources.ResourceLocation; import org.joml.Matrix4f; import java.util.List; @@ -23,6 +25,12 @@ import static dan200.computercraft.shared.media.items.PrintoutData.LINES_PER_PAG * {@linkplain PrintoutItemRenderer in-hand/item frame printouts}. */ public final class PrintoutRenderer { + /** + * Printout's background texture. {@link RenderType#text(ResourceLocation)} is a little questionable, but + * it is what maps use, so should behave the same as vanilla in both item frames and in-hand. + */ + private static final RenderType BACKGROUND = RenderType.text(ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/printout.png")); + private static final float BG_SIZE = 256.0f; /** @@ -62,7 +70,7 @@ public final class PrintoutRenderer { } public static void drawText(PoseStack transform, MultiBufferSource bufferSource, int x, int y, int start, int light, TextBuffer[] text, TextBuffer[] colours) { - var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_TEXT); + var buffer = bufferSource.getBuffer(FixedWidthFontRenderer.TERMINAL_TEXT); var emitter = FixedWidthFontRenderer.toVertexConsumer(transform, buffer); for (var line = 0; line < LINES_PER_PAGE && line < text.length; line++) { FixedWidthFontRenderer.drawString(emitter, @@ -73,7 +81,7 @@ public final class PrintoutRenderer { } public static void drawText(PoseStack transform, MultiBufferSource bufferSource, int x, int y, int start, int light, List lines) { - var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_TEXT); + var buffer = bufferSource.getBuffer(FixedWidthFontRenderer.TERMINAL_TEXT); var emitter = FixedWidthFontRenderer.toVertexConsumer(transform, buffer); for (var line = 0; line < LINES_PER_PAGE && line < lines.size(); line++) { var lineContents = lines.get(start + line); @@ -90,7 +98,7 @@ public final class PrintoutRenderer { var leftPages = page; var rightPages = pages - page - 1; - var buffer = bufferSource.getBuffer(RenderTypes.PRINTOUT_BACKGROUND); + var buffer = bufferSource.getBuffer(BACKGROUND); if (isBook) { // Border diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/RenderTypes.java b/projects/common/src/client/java/dan200/computercraft/client/render/RenderTypes.java deleted file mode 100644 index 3868c472d..000000000 --- a/projects/common/src/client/java/dan200/computercraft/client/render/RenderTypes.java +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.client.render; - -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.VertexFormat; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.client.gui.GuiSprites; -import dan200.computercraft.client.render.monitor.MonitorTextureBufferShader; -import dan200.computercraft.client.render.text.FixedWidthFontRenderer; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.RenderStateShard; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.ShaderInstance; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceProvider; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.util.Objects; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -/** - * Shared {@link RenderType}s used throughout the mod. - */ -public class RenderTypes { - public static final int FULL_BRIGHT_LIGHTMAP = (0xF << 4) | (0xF << 20); - - private static @Nullable MonitorTextureBufferShader monitorTboShader; - - /** - * Renders a fullbright terminal. - */ - public static final RenderType TERMINAL = RenderType.text(FixedWidthFontRenderer.FONT); - - /** - * Renders a monitor with the TBO shader. - * - * @see MonitorTextureBufferShader - */ - public static final RenderType MONITOR_TBO = Types.MONITOR_TBO; - - /** - * A variant of {@link #TERMINAL} which uses the lightmap rather than rendering fullbright. - */ - public static final RenderType PRINTOUT_TEXT = RenderType.text(FixedWidthFontRenderer.FONT); - - /** - * Printout's background texture. {@link RenderType#text(ResourceLocation)} is a little questionable, but - * it is what maps use, so should behave the same as vanilla in both item frames and in-hand. - */ - public static final RenderType PRINTOUT_BACKGROUND = RenderType.text(ResourceLocation.fromNamespaceAndPath("computercraft", "textures/gui/printout.png")); - - /** - * Render type for {@linkplain GuiSprites GUI sprites}. - */ - public static final RenderType GUI_SPRITES = RenderType.text(GuiSprites.TEXTURE); - - public static MonitorTextureBufferShader getMonitorTextureBufferShader() { - if (monitorTboShader == null) throw new NullPointerException("MonitorTboShader has not been registered"); - return monitorTboShader; - } - - public static ShaderInstance getTerminalShader() { - return Objects.requireNonNull(GameRenderer.getRendertypeTextShader(), "Text shader has not been registered"); - } - - public static void registerShaders(ResourceProvider resources, BiConsumer> load) throws IOException { - load.accept( - new MonitorTextureBufferShader( - resources, - ComputerCraftAPI.MOD_ID + "/monitor_tbo", - MONITOR_TBO.format() - ), - x -> monitorTboShader = (MonitorTextureBufferShader) x - ); - } - - private static final class Types extends RenderType { - private static final RenderStateShard.TextureStateShard TERM_FONT_TEXTURE = new TextureStateShard( - FixedWidthFontRenderer.FONT, - false, false // blur, minimap - ); - - static final RenderType MONITOR_TBO = RenderType.create( - "monitor_tbo", DefaultVertexFormat.POSITION_TEX, VertexFormat.Mode.TRIANGLE_STRIP, 128, - false, false, // useDelegate, needsSorting - RenderType.CompositeState.builder() - .setTextureState(TERM_FONT_TEXTURE) - .setShaderState(new ShaderStateShard(RenderTypes::getMonitorTextureBufferShader)) - .createCompositeState(false) - ); - - @SuppressWarnings("UnusedMethod") - private Types(String name, VertexFormat format, VertexFormat.Mode mode, int buffer, boolean crumbling, boolean sort, Runnable setup, Runnable teardown) { - super(name, format, mode, buffer, crumbling, sort, setup, teardown); - } - } -} diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/SpriteRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/SpriteRenderer.java index bb1a3d02e..3e39580f0 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/SpriteRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/SpriteRenderer.java @@ -5,11 +5,15 @@ package dan200.computercraft.client.render; import com.mojang.blaze3d.vertex.VertexConsumer; +import dan200.computercraft.client.gui.GuiSprites; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import org.joml.Matrix4f; +import java.util.function.Consumer; + /** * A {@link GuiGraphics}-equivalent which is suitable for both rendering in to a GUI and in-world (as part of an entity * renderer). @@ -34,11 +38,11 @@ public class SpriteRenderer { this.b = b; } - public static SpriteRenderer createForGui(GuiGraphics graphics, RenderType renderType) { - return new SpriteRenderer( - graphics.pose().last().pose(), graphics.bufferSource().getBuffer(renderType), - 0, RenderTypes.FULL_BRIGHT_LIGHTMAP, 255, 255, 255 - ); + public static void inGui(GuiGraphics graphics, Consumer renderer) { + graphics.drawSpecial(bufferSource -> renderer.accept(new SpriteRenderer( + graphics.pose().last().pose(), bufferSource.getBuffer(RenderType.guiTextured(GuiSprites.TEXTURE)), + 0, LightTexture.FULL_BRIGHT, 255, 255, 255 + ))); } /** diff --git a/projects/common/src/client/java/dan200/computercraft/client/render/TurtleBlockEntityRenderer.java b/projects/common/src/client/java/dan200/computercraft/client/render/TurtleBlockEntityRenderer.java index 03c2635aa..94afa48d4 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/render/TurtleBlockEntityRenderer.java +++ b/projects/common/src/client/java/dan200/computercraft/client/render/TurtleBlockEntityRenderer.java @@ -22,8 +22,9 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.ARGB; import net.minecraft.util.CommonColors; -import net.minecraft.util.FastColor; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; @@ -84,13 +85,13 @@ public class TurtleBlockEntityRenderer implements BlockEntityRenderer { - if (redraw) { - var terminalBuffer = getBuffer(width * height * 3); - MonitorTextureBufferShader.setTerminalData(terminalBuffer, terminal); - DirectBuffers.setBufferData(GL31.GL_TEXTURE_BUFFER, renderState.tboBuffer, terminalBuffer, GL20.GL_STATIC_DRAW); + var backgroundBuffer = assertNonNull(renderState.backgroundBuffer); + var foregroundBuffer = assertNonNull(renderState.foregroundBuffer); + if (redraw) { + var size = DirectFixedWidthFontRenderer.getVertexCount(terminal); - var uniformBuffer = getBuffer(MonitorTextureBufferShader.UNIFORM_SIZE); - MonitorTextureBufferShader.setUniformData(uniformBuffer, terminal); - DirectBuffers.setBufferData(GL31.GL_UNIFORM_BUFFER, renderState.tboUniform, uniformBuffer, GL20.GL_STATIC_DRAW); - } + // In an ideal world we could upload these both into one buffer. However, we can't render VBOs with + // and starting and ending offset, and so need to use two buffers instead. - // Nobody knows what they're doing! - var active = GlStateManager._getActiveTexture(); - RenderSystem.activeTexture(MonitorTextureBufferShader.TEXTURE_INDEX); - GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, renderState.tboTexture); - RenderSystem.activeTexture(active); + renderToBuffer(backgroundBuffer, size, sink -> + DirectFixedWidthFontRenderer.drawTerminalBackground(sink, 0, 0, terminal, yMargin, yMargin, xMargin, xMargin)); - var shader = RenderTypes.getMonitorTextureBufferShader(); - shader.setupUniform(renderState.tboUniform); - - var buffer = Tesselator.getInstance().begin(RenderTypes.MONITOR_TBO.mode(), RenderTypes.MONITOR_TBO.format()); - tboVertex(buffer, matrix, -xMargin, -yMargin); - tboVertex(buffer, matrix, -xMargin, pixelHeight + yMargin); - tboVertex(buffer, matrix, pixelWidth + xMargin, -yMargin); - tboVertex(buffer, matrix, pixelWidth + xMargin, pixelHeight + yMargin); - RenderTypes.MONITOR_TBO.draw(Nullability.assertNonNull(buffer.build())); - } - case VBO -> { - var backgroundBuffer = assertNonNull(renderState.backgroundBuffer); - var foregroundBuffer = assertNonNull(renderState.foregroundBuffer); - if (redraw) { - var size = DirectFixedWidthFontRenderer.getVertexCount(terminal); - - // In an ideal world we could upload these both into one buffer. However, we can't render VBOs with - // and starting and ending offset, and so need to use two buffers instead. - - renderToBuffer(backgroundBuffer, size, sink -> - DirectFixedWidthFontRenderer.drawTerminalBackground(sink, 0, 0, terminal, yMargin, yMargin, xMargin, xMargin)); - - renderToBuffer(foregroundBuffer, size, sink -> { - DirectFixedWidthFontRenderer.drawTerminalForeground(sink, 0, 0, terminal); - // If the cursor is visible, we append it to the end of our buffer. When rendering, we can either - // render n or n+1 quads and so toggle the cursor on and off. - DirectFixedWidthFontRenderer.drawCursor(sink, 0, 0, terminal); - }); - } - - // Our VBO renders coordinates in monitor-space rather than world space. A full sized monitor (8x6) will - // use positions from (0, 0) to (164*FONT_WIDTH, 81*FONT_HEIGHT) = (984, 729). This is far outside the - // normal render distance (~200), and the edges of the monitor fade out due to fog. - // There's not really a good way around this, at least without using a custom render type (which the VBO - // renderer is trying to avoid!). Instead, we just disable fog entirely by setting the fog start to an - // absurdly high value. - var oldFogStart = RenderSystem.getShaderFogStart(); - RenderSystem.setShaderFogStart(1e4f); - - RenderTypes.TERMINAL.setupRenderState(); - - // Compose the existing model view matrix with our transformation matrix. - var modelView = new Matrix4f(RenderSystem.getModelViewMatrix()).mul(matrix); - - // Render background geometry - backgroundBuffer.bind(); - backgroundBuffer.drawWithShader(modelView, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader()); - - // Render foreground geometry with glPolygonOffset enabled. - RenderSystem.polygonOffset(-1.0f, -10.0f); - RenderSystem.enablePolygonOffset(); - - foregroundBuffer.bind(); - foregroundBuffer.drawWithShader( - modelView, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader(), - // As mentioned in the above comment, render the extra cursor quad if it is visible this frame. Each - // // quad has an index count of 6. - FixedWidthFontRenderer.isCursorVisible(terminal) && FrameInfo.getGlobalCursorBlink() - ? foregroundBuffer.getIndexCount() + 6 : foregroundBuffer.getIndexCount() - ); - - // Clear state - RenderSystem.polygonOffset(0.0f, -0.0f); - RenderSystem.disablePolygonOffset(); - RenderTypes.TERMINAL.clearRenderState(); - VertexBuffer.unbind(); - - RenderSystem.setShaderFogStart(oldFogStart); - } - case BEST -> throw new IllegalStateException("Impossible: Should never use BEST renderer"); + renderToBuffer(foregroundBuffer, size + 4, sink -> { + DirectFixedWidthFontRenderer.drawTerminalForeground(sink, 0, 0, terminal); + // If the cursor is visible, we append it to the end of our buffer. When rendering, we can either + // render n or n+1 quads and so toggle the cursor on and off. + DirectFixedWidthFontRenderer.drawCursor(sink, 0, 0, terminal); + }); } + + // Our VBO renders coordinates in monitor-space rather than world space. A full sized monitor (8x6) will + // use positions from (0, 0) to (164*FONT_WIDTH, 81*FONT_HEIGHT) = (984, 729). This is far outside the + // normal render distance (~200), and the edges of the monitor fade out due to fog. + // There's not really a good way around this, at least without using a custom render type (which the VBO + // renderer is trying to avoid!). Instead, we just disable fog entirely by setting the fog start to an + // absurdly high value. + var oldFog = RenderSystem.getShaderFog(); + RenderSystem.setShaderFog(FogParameters.NO_FOG); + + FixedWidthFontRenderer.TERMINAL_TEXT.setupRenderState(); + + // Compose the existing model view matrix with our transformation matrix. + var modelView = new Matrix4f(RenderSystem.getModelViewMatrix()).mul(matrix); + + // Render background geometry + backgroundBuffer.bind(); + backgroundBuffer.drawWithShader(modelView, RenderSystem.getProjectionMatrix(), RenderSystem.getShader()); + + // Render foreground geometry with glPolygonOffset enabled. + RenderSystem.polygonOffset(-1.0f, -10.0f); + RenderSystem.enablePolygonOffset(); + + foregroundBuffer.bind(); + drawWithShader( + foregroundBuffer, modelView, RenderSystem.getProjectionMatrix(), RenderSystem.getShader(), + // As mentioned in the above comment, render the extra cursor quad if it is visible this frame. + FixedWidthFontRenderer.isCursorVisible(terminal) && FrameInfo.getGlobalCursorBlink() + ? foregroundBuffer.indexCount + : foregroundBuffer.indexCount - FixedWidthFontRenderer.TERMINAL_TEXT.mode().indexCount(4) + ); + + // Clear state + RenderSystem.polygonOffset(0.0f, -0.0f); + RenderSystem.disablePolygonOffset(); + FixedWidthFontRenderer.TERMINAL_TEXT.clearRenderState(); + VertexBuffer.unbind(); + + RenderSystem.setShaderFog(oldFog); } - private static void renderToBuffer(DirectVertexBuffer vbo, int size, Consumer draw) { - var sink = ShaderMod.get().getQuadEmitter(size, MonitorBlockEntityRenderer::getBuffer); - var buffer = sink.buffer(); - + private static void renderToBuffer(VertexBuffer vbo, int size, Consumer draw) { + var sink = ShaderMod.get().getQuadEmitter(size, backingBufferBuilder); draw.accept(sink); - buffer.flip(); - vbo.upload(buffer.limit() / sink.format().getVertexSize(), RenderTypes.TERMINAL.mode(), sink.format(), buffer); - } - private static void tboVertex(VertexConsumer builder, Matrix4f matrix, float x, float y) { - // We encode position in the UV, as that's not transformed by the matrix. - builder.addVertex(matrix, x, y, 0).setUv(x, y); - } - - private static ByteBuffer getBuffer(int capacity) { - var buffer = backingBuffer; - if (buffer == null || buffer.capacity() < capacity) { - buffer = backingBuffer = buffer == null ? MemoryUtil.memAlloc(capacity) : MemoryUtil.memRealloc(buffer, capacity); + var result = backingBufferBuilder.build(); + if (result == null) { + // If we have nothing to draw, just mark it as empty. We'll skip drawing in drawWithShader. + vbo.indexCount = 0; + return; } - buffer.clear(); - return buffer; + var buffer = result.byteBuffer(); + var vertices = buffer.limit() / sink.format().getVertexSize(); + + vbo.bind(); + vbo.upload(new MeshData(result, new MeshData.DrawState( + sink.format(), + vertices, FixedWidthFontRenderer.TERMINAL_TEXT.mode().indexCount(vertices), + FixedWidthFontRenderer.TERMINAL_TEXT.mode(), VertexFormat.IndexType.least(vertices) + ))); + } + + private static void drawWithShader(VertexBuffer buffer, Matrix4f modelView, Matrix4f projection, @Nullable CompiledShaderProgram compiledShaderProgram, int indicies) { + var originalIndexCount = buffer.indexCount; + if (originalIndexCount == 0) return; + + try { + buffer.indexCount = indicies; + buffer.drawWithShader(modelView, projection, compiledShaderProgram); + } finally { + buffer.indexCount = originalIndexCount; + } } @Override @@ -267,28 +226,4 @@ public class MonitorBlockEntityRenderer implements BlockEntityRenderer - * This extends Minecraft's default shader loading code to extract out the TBO buffer and handle our custom uniforms - * ({@code MonitorData}, {@code CursorBlink}). - *

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

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

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

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

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

@@ -26,16 +26,11 @@ import net.minecraft.world.item.crafting.ShapelessRecipe; * @param ingredients The ingredients of the recipe. * @param result The result of the recipe. */ -public record ShapelessRecipeSpec(RecipeProperties properties, NonNullList ingredients, ItemStack result) { +public record ShapelessRecipeSpec(RecipeProperties properties, List ingredients, ItemStack result) { /** * A list of {@link Ingredient}s, usable in a {@linkplain ShapelessRecipe shapeless recipe}. */ - private static final Codec> INGREDIENT_CODEC = Ingredient.CODEC_NONEMPTY.listOf().flatXmap(list -> { - var ingredients = list.stream().filter(ingredient -> !ingredient.isEmpty()).toArray(Ingredient[]::new); - if (ingredients.length == 0) return DataResult.error(() -> "No ingredients for shapeless recipe"); - if (ingredients.length > 9) return DataResult.error(() -> "Too many ingredients for shapeless recipe"); - return DataResult.success(NonNullList.of(Ingredient.EMPTY, ingredients)); - }, DataResult::success); + public static final Codec> INGREDIENT_CODEC = Ingredient.CODEC.listOf(1, 9); public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( RecipeProperties.CODEC.forGetter(ShapelessRecipeSpec::properties), @@ -45,7 +40,7 @@ public record ShapelessRecipeSpec(RecipeProperties properties, NonNullList STREAM_CODEC = StreamCodec.composite( RecipeProperties.STREAM_CODEC, ShapelessRecipeSpec::properties, - MoreStreamCodecs.nonNullList(Ingredient.CONTENTS_STREAM_CODEC, Ingredient.EMPTY), ShapelessRecipeSpec::ingredients, + Ingredient.CONTENTS_STREAM_CODEC.apply(ByteBufCodecs.list()), ShapelessRecipeSpec::ingredients, ItemStack.STREAM_CODEC, ShapelessRecipeSpec::result, ShapelessRecipeSpec::new ); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/recipe/function/CopyComponents.java b/projects/common/src/main/java/dan200/computercraft/shared/recipe/function/CopyComponents.java index 8d7425304..ce2b01908 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/recipe/function/CopyComponents.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/recipe/function/CopyComponents.java @@ -31,7 +31,7 @@ import java.util.Set; */ public final class CopyComponents implements RecipeFunction { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - Ingredient.CODEC_NONEMPTY.fieldOf("from").forGetter(x -> x.from), + Ingredient.CODEC.fieldOf("from").forGetter(x -> x.from), DataComponentType.CODEC.listOf().optionalFieldOf("include").forGetter(x -> x.include), DataComponentType.CODEC.listOf().optionalFieldOf("exclude").forGetter(x -> x.exclude) ).apply(instance, CopyComponents::new)); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java index 6a5abe38e..a1119f075 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java @@ -7,6 +7,8 @@ package dan200.computercraft.shared.turtle; import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.TurtleRefuelHandler; import dan200.computercraft.shared.platform.PlatformHelper; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import java.util.OptionalInt; @@ -14,7 +16,7 @@ import java.util.OptionalInt; public final class FurnaceRefuelHandler implements TurtleRefuelHandler { @Override public OptionalInt refuel(ITurtleAccess turtle, ItemStack currentStack, int slot, int limit) { - var fuelPerItem = getFuelPerItem(currentStack); + var fuelPerItem = getFuelPerItem(((ServerLevel) turtle.getLevel()).getServer(), currentStack); if (fuelPerItem <= 0) return OptionalInt.empty(); if (limit == 0) return OptionalInt.of(0); @@ -33,7 +35,7 @@ public final class FurnaceRefuelHandler implements TurtleRefuelHandler { return OptionalInt.of(fuelToGive); } - private static int getFuelPerItem(ItemStack stack) { - return (PlatformHelper.get().getBurnTime(stack) * 5) / 100; + private static int getFuelPerItem(MinecraftServer server, ItemStack stack) { + return (PlatformHelper.get().getBurnTime(server, stack) * 5) / 100; } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlock.java index f879fe3dd..17d33391f 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlock.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/blocks/TurtleBlock.java @@ -16,19 +16,17 @@ import dan200.computercraft.shared.util.WaterloggableHelpers; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.component.DataComponents; +import net.minecraft.util.RandomSource; import net.minecraft.world.Containers; import net.minecraft.world.InteractionHand; -import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.*; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.SimpleWaterloggedBlock; @@ -38,7 +36,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; @@ -57,7 +55,7 @@ public class TurtleBlock extends AbstractComputerBlock implem BlockCodecs.blockEntityCodec(x -> x.type) ).apply(instance, TurtleBlock::new)); - public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + public static final EnumProperty FACING = BlockStateProperties.HORIZONTAL_FACING; /** * The explosion resistance to use when a turtle is "immune" to explosions. @@ -120,9 +118,9 @@ public class TurtleBlock extends AbstractComputerBlock implem } @Override - protected BlockState updateShape(BlockState state, Direction side, BlockState otherState, LevelAccessor world, BlockPos pos, BlockPos otherPos) { - WaterloggableHelpers.updateShape(state, world, pos); - return state; + protected BlockState updateShape(BlockState state, LevelReader level, ScheduledTickAccess ticker, BlockPos pos, Direction side, BlockPos otherPos, BlockState neighborState, RandomSource randomSource) { + WaterloggableHelpers.updateShape(state, level, ticker, pos); + return super.updateShape(state, level, ticker, pos, side, otherPos, neighborState, randomSource); } @Override @@ -150,14 +148,14 @@ public class TurtleBlock extends AbstractComputerBlock implem } @Override - protected ItemInteractionResult useItemOn(ItemStack currentItem, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { + protected InteractionResult useItemOn(ItemStack currentItem, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { if (currentItem.getItem() == Items.NAME_TAG && currentItem.has(DataComponents.CUSTOM_NAME) && level.getBlockEntity(pos) instanceof AbstractComputerBlockEntity computer) { // Label to rename computer if (!level.isClientSide) { computer.setLabel(currentItem.getHoverName().getString()); currentItem.shrink(1); } - return ItemInteractionResult.sidedSuccess(level.isClientSide); + return InteractionResult.SUCCESS; } return super.useItemOn(currentItem, state, level, pos, player, hand, hit); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java index 0b73f436e..0c6e2c100 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/items/TurtleItem.java @@ -17,7 +17,7 @@ import dan200.computercraft.shared.turtle.blocks.TurtleBlock; import net.minecraft.core.cauldron.CauldronInteraction; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; -import net.minecraft.world.ItemInteractionResult; +import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.LayeredCauldronBlock; @@ -30,7 +30,7 @@ public class TurtleItem extends AbstractComputerItem { @Override public Component getName(ItemStack stack) { - var baseString = getDescriptionId(stack); + var baseString = descriptionId; var left = getUpgrade(stack, TurtleSide.LEFT); var right = getUpgrade(stack, TurtleSide.RIGHT); if (left != null && right != null) { @@ -85,12 +85,12 @@ public class TurtleItem extends AbstractComputerItem { } public static final CauldronInteraction CAULDRON_INTERACTION = (blockState, level, pos, player, hand, stack) -> { - if (!stack.has(DataComponents.DYED_COLOR)) return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; + if (!stack.has(DataComponents.DYED_COLOR)) return InteractionResult.TRY_WITH_EMPTY_HAND; if (!level.isClientSide) { stack.remove(DataComponents.DYED_COLOR); LayeredCauldronBlock.lowerFillLevel(blockState, level, pos); } - return ItemInteractionResult.sidedSuccess(level.isClientSide); + return InteractionResult.SUCCESS; }; } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java index 095bb29b6..5e137f72f 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java @@ -23,16 +23,6 @@ public final class TurtleUpgradeRecipe extends CustomRecipe { super(category); } - @Override - public boolean canCraftInDimensions(int x, int y) { - return x >= 3 && y >= 1; - } - - @Override - public ItemStack getResultItem(HolderLookup.Provider registryAccess) { - return new ItemStack(ModRegistry.Items.TURTLE_NORMAL.get()); - } - @Override public boolean matches(CraftingInput inventory, Level world) { return !assemble(inventory, world.registryAccess()).isEmpty(); @@ -126,7 +116,7 @@ public final class TurtleUpgradeRecipe extends CustomRecipe { } @Override - public RecipeSerializer getSerializer() { + public RecipeSerializer getSerializer() { return ModRegistry.RecipeSerializers.TURTLE_UPGRADE.get(); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java index 1e66b71af..dad336fe0 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java @@ -12,9 +12,8 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Container; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.level.Level; import javax.annotation.Nullable; import java.util.AbstractList; @@ -29,7 +28,7 @@ public final class TurtleInventoryCrafting { private TurtleInventoryCrafting() { } - private static @Nullable FoundRecipe tryCrafting(Level level, Container inventory, int xStart, int yStart) { + private static @Nullable FoundRecipe tryCrafting(ServerLevel level, Container inventory, int xStart, int yStart) { // Check the non-relevant parts of the inventory are empty for (var x = 0; x < TurtleBlockEntity.INVENTORY_WIDTH; x++) { for (var y = 0; y < TurtleBlockEntity.INVENTORY_HEIGHT; y++) { @@ -56,14 +55,13 @@ public final class TurtleInventoryCrafting { return WIDTH * HEIGHT; } }); - var recipe = level.getRecipeManager().getRecipeFor(RecipeType.CRAFTING, input.input(), level).orElse(null); + var recipe = level.recipeAccess().getRecipeFor(RecipeType.CRAFTING, input.input(), level).orElse(null); return recipe == null ? null : new FoundRecipe(recipe.value(), input.input(), input.left() + xStart, input.top() + yStart); } @Nullable public static List craft(ITurtleAccess turtle, int maxCount) { - var level = turtle.getLevel(); - if (level.isClientSide || !(level instanceof ServerLevel)) return null; + if (!(turtle.getLevel() instanceof ServerLevel level)) return null; var inventory = turtle.getInventory(); @@ -124,6 +122,6 @@ public final class TurtleInventoryCrafting { return Collections.unmodifiableList(results); } - private record FoundRecipe(Recipe recipe, CraftingInput input, int xStart, int yStart) { + private record FoundRecipe(CraftingRecipe recipe, CraftingInput input, int xStart, int yStart) { } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java index afac649d5..af6043722 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java @@ -228,10 +228,10 @@ public class TurtleTool extends AbstractTurtleUpgrade { // Compute the total damage, and deal it out. var damage = baseDamage + bonusDamage + tool.getItem().getAttackDamageBonus(entity, baseDamage, source); - if (!entity.hurt(source, damage)) return false; + if (!entity.hurtServer(player.serverLevel(), source, damage)) return false; // Special case for armor stands: attack twice to guarantee destroy - if (entity.isAlive() && entity instanceof ArmorStand) entity.hurt(source, damage); + if (entity.isAlive() && entity instanceof ArmorStand) entity.hurtServer(player.serverLevel(), source, damage); // Apply knockback var knockBack = EnchantmentHelper.modifyKnockback(player.serverLevel(), tool, entity, source, (float) player.getAttributeValue(Attributes.ATTACK_KNOCKBACK)); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/ArgumentHelpers.java b/projects/common/src/main/java/dan200/computercraft/shared/util/ArgumentHelpers.java index f4c4fb257..fce4b32a2 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/ArgumentHelpers.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/ArgumentHelpers.java @@ -28,7 +28,7 @@ public final class ArgumentHelpers { } T value; - if (id == null || (value = registry.get(id)) == null) { + if (id == null || (value = registry.getValue(id)) == null) { throw new LuaException(String.format("Unknown %s '%s'", typeName, name)); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/ColourUtils.java b/projects/common/src/main/java/dan200/computercraft/shared/util/ColourUtils.java index 8f66a6a0a..cdc607b82 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/ColourUtils.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/ColourUtils.java @@ -14,7 +14,7 @@ import javax.annotation.Nullable; import java.util.List; public final class ColourUtils { - private static final List> DYES = PlatformHelper.get().getDyeTags(); + public static final List> DYES = PlatformHelper.get().getDyeTags(); private ColourUtils() { } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/ComponentizationFixers.java b/projects/common/src/main/java/dan200/computercraft/shared/util/ComponentizationFixers.java index 83baa9868..b0560e4ab 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/ComponentizationFixers.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/ComponentizationFixers.java @@ -8,7 +8,6 @@ import com.mojang.datafixers.DSL; import com.mojang.datafixers.Typed; import com.mojang.datafixers.schemas.Schema; import com.mojang.datafixers.types.templates.TypeTemplate; -import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Dynamic; import com.mojang.serialization.OptionalDynamic; import dan200.computercraft.api.upgrades.UpgradeData; @@ -19,10 +18,11 @@ import net.minecraft.util.datafix.fixes.ItemStackComponentizationFix; import net.minecraft.util.datafix.fixes.References; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -207,31 +207,19 @@ public class ComponentizationFixers { /** * Add our custom data components to the datafixer system. * - * @param type The existing component type definition. + * @param types The component type definition. * @param schema The current schema. - * @return The new component type definition. * @see UpgradeManager#upgradeDataCodec() * @see ModRegistry.DataComponents#POCKET_UPGRADE * @see ModRegistry.DataComponents#LEFT_TURTLE_UPGRADE * @see ModRegistry.DataComponents#RIGHT_TURTLE_UPGRADE */ - public static TypeTemplate addExtraTypes(TypeTemplate type, Schema schema) { + public static void addExtraTypes(Map> types, Schema schema) { // Create a codec for UpgradeData - var upgradeData = DSL.optionalFields("components", References.DATA_COMPONENTS.in(schema)); + Supplier upgradeData = () -> DSL.optionalFields("components", References.DATA_COMPONENTS.in(schema)); - return extraOptionalFields(type, - Pair.of("computercraft:pocket_upgrade", upgradeData), - Pair.of("computercraft:left_turtle_upgrade", upgradeData), - Pair.of("computercraft:right_turtle_upgrade", upgradeData) - ); - } - - @SafeVarargs - @SuppressWarnings("varargs") - private static TypeTemplate extraOptionalFields(TypeTemplate base, Pair... fields) { - return DSL.and(Stream.concat( - Arrays.stream(fields).map(entry -> DSL.optional(DSL.field(entry.getFirst(), entry.getSecond()))), - Stream.of(base) - ).toList()); + types.put("computercraft:pocket_upgrade", upgradeData); + types.put("computercraft:left_turtle_upgrade", upgradeData); + types.put("computercraft:right_turtle_upgrade", upgradeData); } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java b/projects/common/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java index 457fb444b..6a55e344c 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/RedstoneUtil.java @@ -12,6 +12,7 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.DiodeBlock; import net.minecraft.world.level.block.RedStoneWireBlock; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.redstone.ExperimentalRedstoneUtils; public final class RedstoneUtil { private RedstoneUtil() { @@ -49,7 +50,8 @@ public final class RedstoneUtil { if (!PlatformHelper.get().onNotifyNeighbour(world, pos, block, side)) return; var neighbourPos = pos.relative(side); - world.neighborChanged(neighbourPos, block.getBlock(), pos); + var orientation = ExperimentalRedstoneUtils.initialOrientation(world, side, Direction.UP); + world.neighborChanged(neighbourPos, block.getBlock(), orientation); // We intentionally use updateNeighborsAt here instead of updateNeighborsAtExceptFromFacing, as computers can // both send and receive redstone, and so also need to be updated. world.updateNeighborsAt(neighbourPos, block.getBlock()); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/RegistryHelper.java b/projects/common/src/main/java/dan200/computercraft/shared/util/RegistryHelper.java index 9d07a63e3..902c47d45 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/RegistryHelper.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/RegistryHelper.java @@ -27,7 +27,7 @@ public final class RegistryHelper { */ @SuppressWarnings("unchecked") public static Registry getRegistry(ResourceKey> id) { - var registry = (Registry) BuiltInRegistries.REGISTRY.get(id.location()); + var registry = (Registry) BuiltInRegistries.REGISTRY.getValue(id.location()); if (registry == null) throw new IllegalArgumentException("Unknown registry " + id); return registry; } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java b/projects/common/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java index eb2fd652f..05a3308d8 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/WaterloggableHelpers.java @@ -6,8 +6,10 @@ package dan200.computercraft.shared.util; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.ScheduledTickAccess; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BooleanProperty; @@ -34,15 +36,16 @@ public final class WaterloggableHelpers { } /** - * Call from {@link net.minecraft.world.level.block.Block#updateShape(BlockState, Direction, BlockState, LevelAccessor, BlockPos, BlockPos)}. + * Call from {@link net.minecraft.world.level.block.Block#updateShape(BlockState, LevelReader, ScheduledTickAccess, BlockPos, Direction, BlockPos, BlockState, RandomSource)}. * - * @param state The current state - * @param world The position of this block - * @param pos The world this block exists in + * @param state The current state + * @param level The position of this block + * @param ticker The ticker to schedule with. + * @param pos The world this block exists in */ - public static void updateShape(BlockState state, LevelAccessor world, BlockPos pos) { + public static void updateShape(BlockState state, LevelReader level, ScheduledTickAccess ticker, BlockPos pos) { if (state.getValue(WATERLOGGED)) { - world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + ticker.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); } } diff --git a/projects/common/src/main/resources/assets/computercraft/models/block/computer_on.json b/projects/common/src/main/resources/assets/computercraft/models/block/computer_on.json index a8518a768..238226997 100644 --- a/projects/common/src/main/resources/assets/computercraft/models/block/computer_on.json +++ b/projects/common/src/main/resources/assets/computercraft/models/block/computer_on.json @@ -1,7 +1,6 @@ { "parent": "minecraft:block/orientable", "render_type": "cutout", - "computercraft:emissive_texture": "cursor", "elements": [ { "from": [ 0, 0, 0 ], @@ -18,11 +17,11 @@ { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], + "light_emission": 15, "faces": { "north": { "texture": "#cursor", - "cullface": "north", - "neoforge_data": {"block_light": 15, "sky_light": 15} + "cullface": "north" } } } diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/border_advanced.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/border_advanced.png index 06394a48f8808bc1b992742b9bad73f3e9bfbaa3..324503f7a74c97b613990e2e07871f21642ff0c6 100644 GIT binary patch delta 192 zcmX@dbb)b#L_G^L0|SGwUh8TgB^}@s;tHf05G9d{Qk}x3&6Ou3?2?ywZ20(so$|bAXulxD6JPxRZLYSzZ5SK8zGh{*% zCL~c@==?Y1I5;p(XN%Nz9iE;a3uzsxfUgc#UDriL+GYz5Ofvt&!KbD*O^^8(FT6BL^l e7(|^CVPRM|{l#>abrOp~uJLsBb6Mw<&;$Sidpx}W delta 279 zcmV+y0qFk60j2_w7=H)`0002t0GOBn008YtL_t(|ob8xB4udcZM!!U;*Qij~xl!(x z+=D}~2UXcScB(4UA>v0YHb@W#za>cV@P^<|wyG-t0QA!&6k?2nn!Z(C0k0oY`V{j) z(>Ak|0?NuvOj61ilR_Wni};S0%Xser0M0q+^+gGpEt)R57Jm_<5Fv_+TR8oiN3qtj z>exa+?h{7{ePFi~zR))x!?5HI2V?eSEaloaXvXAz=@TMho>iVg+gbeBag3!Z=<8Gt_UlOwBd@Sd>s=E zMHDzC9c>o3=^SBTI~>h%`F7d`4(SULPE5z#c+`B(9b3WhLO9h#F~KOs$$KUbLrTEn U>HyIYL69>%UHx3vIVCg!02k3T3IG5A delta 285 zcmV+&0pk9>0jvU$7=H)`0002t0GOBn008qzL_t(|obA{l4udch#__L&E5HSw!*K~N zFpcK`^9y=nb{b~60FyfaQxi*i0r0a-Y>-hXqAndk9S)=fZM0^;&b zC)SVduNNgzU^LGd1OR2z{)DOW%y>(&0s+%=$0XY`a&v1)KwJXi5)hYwxCF#yeU>eK zf3pHrdA5{e%ovnJ!78_s&8;B;aS4daIcR>HQNU-jD~bZw)7}YcsBGHthZTsZPvg)j jMr*AmSDG#S))spMm7_!)f_6nu00000NkvXXu0mjfigSFR diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/border_normal.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/border_normal.png index 7c47d250bf035cc4647efddae2552ebcaeb9c522..eb9b946e12511da61deb035d83dd5ffaa999f7b8 100644 GIT binary patch delta 182 zcmZ3@bc}I=L_G^L0|SGwUh8TgB^uxp;tHgJKv`KiBqSs%D(dLbqyPT>oB8qGOQ0xY zNswPKgTu2MX+TcAr;B5V#`)xg04G*19-f}e6$+h=jy%2^p^c8Zx+1JB(uOOR@^wt$ z7E$1|bhKIArgMaWO<|$H@`qY2FLTW^dU!K<6!jUCmD!dhBr7x=k?ddRxj d+cM=O1H;Kr%Vu44x%e979#2<4mvv4FO#r`dItBm$ delta 284 zcmV+%0ptG00jmO#7=H)`0002t0GOBn008nyL_t(|ob8xFu7n^AhJTImA`J)dTpWg# z7vM6+l?Ncbhzofehm3Dt(mFFwT=ZL&(1b66P)dUxBFd-)GdGX;5#(*#D(L{uxgyop zmH~hmW7(mOhz^s}G+izfLclN#0Fc|-GQVl%lxr~|2@{g&w10`?IDWK{_gv{7Bw<1l)rCR`hjGWujdL!?7+)s;;`u?Y;rY_jP&x=A%KMi{6`^HW iz|75|rMbhm-W3nacTNObmLzKc0000Nn>NP zjqK$>A;yv*zhDN3XE)M-90N}m$B>FSs%H-JGB|KBIXbDf{Oh*4bNRT0@~K$YrEN=; oA2hv7$bGh!Nv}iZ2I^(-boFyt=akR{0LdRKbN~PV diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/terminate_hover.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/terminate_hover.png deleted file mode 100644 index c14a278061db7b6e0c949d0da8fe5df8f87017b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=%3?!FCJ6-`&`~f~8u0UEuL_}Fxd1*<>Nn>NP zjqK$>A;yv*zhDN3XE)M-9DPq0$B>FSs%H)gG8k|$Ilf@{m2XyY@wio=M!D!zsY!he n+`F2$&fLzmL!s!%|IO^3R?JRag|GU7S{XcD{an^LB{Ts5Z)GWX diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_off.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_off.png deleted file mode 100644 index bb556653efc5e29fc3304fabbe06566fb24bd89c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=%3?!FCJ6-`&`~f~8u0UEuL_}Fxd1*<>Nn>NP zjqK$>A;yv*zhDN3XE)M-90N}m$B>FSrDrzsG8phMIZp9Zy20>%|Ll#y&u6b@xU*o= nX@S%>?fLpon0PkxP3Nn>NP zjqK$>A;yv*zhDN3XE)M-90N}m$B>FSrDrzsG8phMIc{?fLpon0PkxP32 delta 207 zcmV;=05Jcc0p9_T7=H)`0002xdY?4_005>*L_t(|obA@V4Z<)GhT-p`Y+{Kqu7fcw zF$1i@0Ct%XC<&DXGk~zJ=Vu60MX6#FiO9`8r7fLbcSpvU)Sq?$fY;}aDIq-IU7Wnn zIrn=!-?!{+0PrrNojZ7GKL;_dvcLS7X7Lwh(x4IzD$$@44M-}{pb`x#sU9@!LW5RV zXuUb4uIq5Q9xG*y8UPR$ves4&@h(DGh_D?GO)#lekgyN{d;#%oF4eEvLH7Uv002ov JPDHLkV1h@HRj4#O}Eh2iI@_n4-X??ypA z)`&xLgrOdyJOSoCLo!rtr1dJT3h_rH*?*YHd*AYs0RXZJ_QYodC*FNOl9#N`1^`Zs z;q2h6{TvjgaQMrAahGp6$$~T%q_H541!*iuV?mnkLE9~~89b^K8XseeF=Bqrow7b0 x08}XyLg*U8iBY8x-M>yWck``RP?bUe@CMDkFt{0`X+8h|002ovPDHLkV1jSvQ?md7 diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_normal.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/pocket_bottom_normal.png index 0699e8a18d3fc418e1b0b98c010ea99a33d5c8e7..8b02335019d6d6bae957478a852b793d37419f97 100644 GIT binary patch delta 145 zcmcb?xR7yzL_G^L0|SG2ND~{75(@AMaRt)K%E}=jAyH9LM~@!;_wQf!?eFh_qKqX$ ze!&b5&u*jvIkuiIjv*44lLdGS3kwZJSeOG9E_+U7)Jc)zV)StGNC@Fzn<649F?UMC u0SO)lodp8T0<$JCFf%V!&`MxnIJ+qD`TkR$RtyYW3=E#GelF{r5}E))t}C(t delta 200 zcmV;(05|`k0oVbM7=H)`0002xdY?4_005s!L_t(|obA@J2?QY!h2iJ1*vMc3)@3n9 zHefSiGzG{sV&X-@!QJW!yKLeY$tuoowu*>aDFpzKQo@-K0&>o$`y-{4;oaVQ001-N zSiSgee+N0|hOfNJ>-GtYcF@cYn%O}!J7{JH&Fr9=$AkL6P(gQyh%&~s7~|LGFIwxR zfwk79^Qte1s99?t3u0!7h*F;)iKs12yO4+|0C)qkoiqV;#9Jx=00009!zjhUIv&7#|plSxG4 b0RzL2DKaH1LOlb3`WQT2{an^LB{Ts5>Q5uD delta 131 zcmbQhIE8V7L=6WU0|Ud!x8Jt_sc26Z$B>FS$tfNw2?;aKfB1jzZYIwYCO0;=Q#=VE z5EvHbCRp+F7u(4;gTO3?HpM4RfzBBz9H;N@E`K=3xjk><%SkS5ZmLgpx?&EUn81;! iAs_V5f1~0Q28N4E#C#(wi|zoeVeoYIb6Mw<&;$T+95iMC diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/sidebar_normal.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sidebar_normal.png index 495c031a04e29819964ec8780b88eed7e0894f72..2e6f469dea17bef65384b78ef0fcf453c76cceca 100644 GIT binary patch delta 122 zcmeBW>}H%GQOv^3z`$UA_*FZQ;t%i%aRt)K%E}=jAxDoM{rB(RpL;4CKq1DGAirP+ zhi5m^fE+DP7sn8e>&XcMEewooZsHsT2?CBulFf~b%^k*}5q@3?3l1FMNIw|Mz~Hb- VblQc8Z*4$b44$rjF6*2UngHs^Cb|Fs delta 124 zcmeBX>}8xFQOd!_z`$_w?e{G}D#X*pF{ENna!LbJYUaWjEq{M6H6%22=?T>y12$Dj a0R|~vUuO@t6~BPyGkCiCxvXfiWE|9}m z666=m;PC858jz#s>Eal|ASXYA^>bP0l+XkK+Z`l4 literal 0 HcmV?d00001 diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/terminate_hover.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/terminate_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..79f491e0a2bb8c71f9312ae8d5018e8867c1c74a GIT binary patch literal 131 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=-3?y@QpIZW?*aCb)T!FNRh)9>sMsFaCu_VYZ zn8D%MjWi%f+tbA{gyVYhiuwZ|{xctDXKs^c<0zopr0QROO`Tzg` literal 0 HcmV?d00001 diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_on.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_on.png similarity index 100% rename from projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_on.png rename to projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_on.png diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_on_hover.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_on_hover.png similarity index 100% rename from projects/common/src/main/resources/assets/computercraft/textures/gui/buttons/turned_on_hover.png rename to projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/buttons/turned_on_hover.png diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/turtle_advanced_selected_slot.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/sprites/turtle_advanced_selected_slot.png new file mode 100644 index 0000000000000000000000000000000000000000..1550ea4c6e1dfffe0fffc85e8f0552a606b266f5 GIT binary patch literal 461 zcmV;;0W$uHP)M*O1uQklWgk+uM`f+>@M3$%y~}00DGTPE!Ct=GbNc006;BL_t&- z8EwHmPQySHM$tRpJbUa!A{}KKw!!{4LW@8+277*u5Zxr_xL1nH(@Gkguc+-4@L|Ur zq!Et!EBu^dh=C!$TjR5(F`I*}?%A4ncFv6UO(yX#0_O$YMtWyPk?2L5c%*3K5zX8) zgwa#kMWJV04q4ZEbCCZf=;-Y1?DqEd`1ttw`T6|({Qdp?|Ns9{Wh%x10004WQchCvx)bA*%UAHV8(>8AwFeYm9Z zRM}orm+7iz+*i>T#?1_;PcZDZYG;U@^UbW8!J3gp!`9*UksB$(3NPXv=KD6x=nhnE zU|`};tjyIR-xkQMBjYTpQ6cNfDT8 zu+zMF3c`dJS~5NP`$>h7MZ!|l?yud!&0GQZxUaAXC`@MXWn)|wDy-4W@Y2f2VXk9C kmY@bBEL~AbADFX`(Qk#6&>f|DKR{-Ay85}Sb4q9e01)EIga7~l literal 1455 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&w@L)Zt|+CxF!L0G|+7APoWW@wN$xwuwo0 zNy+xfN%qOf_9?0Msc8;rsZQysjv47r85vF)na){RF1gvRxp{7Rxo-LS?!`r(on0Qi zy)F|b#7vnSH)DFj%o&L@XC}^?l{9;H^6WV&b7m*ao$EVyZtA?bY4he~%%7jWU_r*h z1(^#MWG`BnvuIJ?;zhYjmK3aB9kP2@?Y_Nr`}WuG-&cQNf5X88jfW049Xix>_;B-) zBP~adwjMjycKk%%iQ{c2Pqv>r*>?I=`?<4S*RD>uaecy#8xwBdnt1#6+RjMe!_tg4G;5|U6v0J5$55v z781|9Tgmv!^)>H~&uj*Tj}I;3v=@Ex{z~hn1+qykNfP^>NBT`}v;16kF0(kJyTfSG zs%DKveexE(DG@eu8>TxACJLg6Q0R|=@a$w+KU{qjWX#nx5%XuKj6p?24*NGvH znaUhCYz%kKBCE@qqXK5m12zEpqxs$kX+zfA-7od5pmzND#q{cp=aM%SN; z=gzcTmpN+S&nVV-k5z%;(tci>sM>_@Pa0)!-hOg_=l;uoa_aliYovGV{&e8sboR28 zEhqPXe$bX~Ein^UFv&Hp{>!kteRaRh7UloXZ(iDYOLR_-`vu?g+x82eEMrx_D_D}@ zKEV_etXTa2Va83tDKYP49nZeu=sK}UnIoHlaf20eN({@cEAJTA{h#WRec*|`gkg@| zoY&u(f>tYAcRMiNxp(QuQ@#ZTb;}r7pfR@PjBFW;?(O}`9oPOAy-+J>S$gZ|=k3-G z**64JcpDgQd=V*Fz4PnIpKWPRcE5Z4^j&ttwl`eIL@?s}|B~F_jBhx+(-eZ2Xz`s0HY0()QbGf!4)uxk6d#e8*F z$LFI**Q`2ip;7ZcdLF~774C*R%ig@~EIj$y@<3$$+Z&f(NX{@}T(jqwveL0>$7eES z7?~SnGVL&7+sS+*%i@NqUgxrgud8Fv9b;4TXV}~(eV`a*cvkIEbI;xG8p#Zw+oB!5 z@cPVRsQP$DBZV(PYVOwN%PSjC7PCjJiGMp!Q^B8M`P}*0-3K-$CtPB=us>q=t>#I0s31_&V+CwExS_3Omf<^J5d7u79lC@5mbK z*XMK@g;))2<{nvdukU2x))&_%*G+j^^w2z!kzr7P2D9I+3hvyWEB`eA06ECh)z4*} HQ$iB}5aAYx diff --git a/projects/common/src/main/resources/assets/computercraft/textures/gui/turtle_normal.png b/projects/common/src/main/resources/assets/computercraft/textures/gui/turtle_normal.png index f676c56b20d2173381b54b6ecef670edc0c0b78c..9426aa22025285bfb41aa83b5649219b7c89e098 100644 GIT binary patch literal 695 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7+9Er6kFKIlR!#3z$e5NNCSbHnOR6kNLN?a z(W6Iy|Ni~=@85s_{-szaivi^rOM?7@862M7NCO(+<>}%WQgQ3;UBkRX1|kiK&)FPh zPo3e_$_o%(Y5YLBKwwqWqZ_dSh1+>N=Qr=qKP8a*Lv`{C%_Ew*Oud@-3b;#h6%Lpg zIY>rxOn5x!o)kv_i@<{K498=8oQ)Zq<}rC0GbZJ^H8U`AC^S%uIP=t0?|>@^nTY=3mVlmwH~V4Z1&Tx&w>WF-)2+uPUI zH!(3WJ3A|pNap9~7Zw&47Z;b7mZVatOeR}iUS3&Qk;~<)tE&oyVr^|rsZ^>|s*Q~e zjYhM#w|8)GaCmsA*Xs=igVAU-nM`K0nHM%wYgr89UMG?OUOCSI08I%d_>pfdYGtw; z(m-c;m3>-UR*mOGp8XwlB?2{UL(R-_2|vlXF*P%p8Jg8QP?2LF<`nu6jhj^Ozh4+1 zEvPy_BXCwYUci13aNN+lUl)?3Q6M3aqMkq$6h^_S$~VaRVs#T~~L^ z@>;)Ux|C;r3r?VxbZT;4kC*dd`l=SP2Pk{k)8g^K8bIy<4TFC@kQ<;EUCs`ObX!Ln z|ACBaaHU>1Ju5GN8?H#(EhuUK@tMS*4=$ZCtVazOn5y@GK|1q8$#_r6O(gi>PTy0N z=P33`A3)=ucYextHOVvdZ?@^&-G)e;X}2Itq6os{}}Y5p1qn%&=C z1~&8bI{+bxBUo!UFP*8?lf*={(Wg#Le&pm=iR}H;RYgidWX9tNbT|j|I%c}qT?3&< z$2{Fs?u0)LDmQ>Qp0J zK(tCI_XQ}qv`$pr)UEE%M z>5zf;v2O6hcSFvlzGZicgPri2!1&xHBn%3>P-Usp{N%RmM-}+ z>vmy3?#*OWv^LOZI8zmsUI+MdNp|T^b1&BflK51$mzpxitxq%joYCt26$2Xz{G~#3 ztX)?@*X4H|D6+XBE5BmYylHOop`dYy)gMq0ONg?q-2wj-8?7-~ - -#define FONT_WIDTH 6.0 -#define FONT_HEIGHT 9.0 - -uniform sampler2D Sampler0; // Font -uniform usamplerBuffer Tbo; - -layout(std140) uniform MonitorData { - vec3 Palette[16]; - int Width; - int Height; - ivec2 CursorPos; - int CursorColour; -}; -uniform int CursorBlink; - -uniform vec4 ColorModulator; -uniform float FogStart; -uniform float FogEnd; -uniform vec4 FogColor; - -in float vertexDistance; -in vec2 fontPos; - -out vec4 fragColor; - -vec2 texture_corner(int index) { - float x = 1.0 + float(index % 16) * (FONT_WIDTH + 2.0); - float y = 1.0 + float(index / 16) * (FONT_HEIGHT + 2.0); - return vec2(x, y); -} - -vec4 recolour(vec4 texture, int colour) { - return vec4(texture.rgb * Palette[colour], texture.rgba); -} - -void main() { - vec2 term_pos = vec2(fontPos.x / FONT_WIDTH, fontPos.y / FONT_HEIGHT); - vec2 corner = floor(term_pos); - - ivec2 cell = ivec2(corner); - int index = 3 * (clamp(cell.x, 0, Width - 1) + clamp(cell.y, 0, Height - 1) * Width); - - // 1 if 0 <= x, y < Width, Height, 0 otherwise - vec2 outside = step(vec2(0.0, 0.0), vec2(cell)) * step(vec2(cell), vec2(float(Width) - 1.0, float(Height) - 1.0)); - float mult = outside.x * outside.y; - - int character = int(texelFetch(Tbo, index).r); - int fg = int(texelFetch(Tbo, index + 1).r); - int bg = int(texelFetch(Tbo, index + 2).r); - - vec2 pos = (term_pos - corner) * vec2(FONT_WIDTH, FONT_HEIGHT); - vec4 charTex = recolour(texture(Sampler0, (texture_corner(character) + pos) / 256.0), fg); - - // Applies the cursor on top of the current character if we're blinking and in the current cursor's cell. We do it - // this funky way to avoid branches. - vec4 cursorTex = recolour(texture(Sampler0, (texture_corner(95) + pos) / 256.0), CursorColour); // 95 = '_' - vec4 img = mix(charTex, cursorTex, cursorTex.a * float(CursorBlink) * (CursorPos == cell ? 1.0 : 0.0)); - - vec4 colour = vec4(mix(Palette[bg], img.rgb, img.a * mult), 1.0) * ColorModulator; - - fragColor = linear_fog(colour, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.json b/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.json deleted file mode 100644 index e29e42e1e..000000000 --- a/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "vertex": "computercraft/monitor_tbo", - "fragment": "computercraft/monitor_tbo", - "attributes": [ "Position" ], - "samplers": [ { "name": "Sampler0" } ], - "uniforms": [ - { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, - { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] }, - - { "name": "Tbo", "type": "int", "count": 1, "values": [ 3 ] }, - { "name": "CursorBlink", "type": "int", "count": 1, "values": [ 0 ] } - ] -} diff --git a/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.vsh b/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.vsh deleted file mode 100644 index 681f36cc3..000000000 --- a/projects/common/src/main/resources/assets/minecraft/shaders/core/computercraft/monitor_tbo.vsh +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -#version 150 - -#moj_import - -in vec3 Position; -in vec2 UV0; - -uniform mat4 ModelViewMat; -uniform mat4 ProjMat; -uniform vec3 ChunkOffset; -uniform int FogShape; - -out float vertexDistance; -out vec2 fontPos; - -void main() { - vec3 pos = Position + ChunkOffset; - gl_Position = ProjMat * ModelViewMat * vec4(pos, 1.0); - - vertexDistance = fog_distance(pos, FogShape); - fontPos = UV0; -} diff --git a/projects/common/src/main/resources/computercraft-common.accesswidener b/projects/common/src/main/resources/computercraft-common.accesswidener index a0ffacef9..7ce5c025d 100644 --- a/projects/common/src/main/resources/computercraft-common.accesswidener +++ b/projects/common/src/main/resources/computercraft-common.accesswidener @@ -7,8 +7,6 @@ accessWidener v1 named # Additional access wideners for vanilla code. This is a effectively the subset of Fabric's transitive access wideners # that we actually use -accessible class net/minecraft/world/level/block/entity/BlockEntityType$BlockEntitySupplier - accessible method net/minecraft/client/renderer/blockentity/BlockEntityRenderers register (Lnet/minecraft/world/level/block/entity/BlockEntityType;Lnet/minecraft/client/renderer/blockentity/BlockEntityRendererProvider;)V accessible class net/minecraft/world/item/CreativeModeTab$Output accessible field net/minecraft/world/item/CreativeModeTabs OP_BLOCKS Lnet/minecraft/resources/ResourceKey; @@ -30,3 +28,4 @@ accessible field net/minecraft/data/models/ItemModelGenerators output Ljava/util accessible method net/minecraft/data/models/ItemModelGenerators generateFlatItem (Lnet/minecraft/world/item/Item;Lnet/minecraft/data/models/model/ModelTemplate;)V accessible method net/minecraft/data/models/ItemModelGenerators generateFlatItem (Lnet/minecraft/world/item/Item;Ljava/lang/String;Lnet/minecraft/data/models/model/ModelTemplate;)V accessible method net/minecraft/data/models/model/TextureSlot create (Ljava/lang/String;)Lnet/minecraft/data/models/model/TextureSlot; +accessible method net/minecraft/data/recipes/RecipeProvider inventoryTrigger ([Lnet/minecraft/advancements/critereon/ItemPredicate;)Lnet/minecraft/advancements/Criterion; diff --git a/projects/common/src/main/resources/computercraft.accesswidener b/projects/common/src/main/resources/computercraft.accesswidener index 081b21533..704b863c9 100644 --- a/projects/common/src/main/resources/computercraft.accesswidener +++ b/projects/common/src/main/resources/computercraft.accesswidener @@ -7,16 +7,14 @@ accessWidener v1 named # Shared vanilla and Fabric access wideners. This should not include things already exposed by Fabric's transitive # wideners. +accessible class net/minecraft/world/level/block/entity/BlockEntityType$BlockEntitySupplier +accessible method net/minecraft/world/level/block/entity/BlockEntityType (Lnet/minecraft/world/level/block/entity/BlockEntityType$BlockEntitySupplier;Ljava/util/Set;)V + accessible method net/minecraft/client/renderer/RenderType create (Ljava/lang/String;Lcom/mojang/blaze3d/vertex/VertexFormat;Lcom/mojang/blaze3d/vertex/VertexFormat$Mode;IZZLnet/minecraft/client/renderer/RenderType$CompositeState;)Lnet/minecraft/client/renderer/RenderType$CompositeRenderType; accessible method net/minecraft/world/level/storage/LevelResource (Ljava/lang/String;)V # DirectVertexBuffer -accessible field com/mojang/blaze3d/vertex/VertexBuffer vertexBufferId I -accessible field com/mojang/blaze3d/vertex/VertexBuffer indexType Lcom/mojang/blaze3d/vertex/VertexFormat$IndexType; accessible field com/mojang/blaze3d/vertex/VertexBuffer indexCount I -accessible field com/mojang/blaze3d/vertex/VertexBuffer mode Lcom/mojang/blaze3d/vertex/VertexFormat$Mode; -accessible field com/mojang/blaze3d/vertex/VertexBuffer sequentialIndices Lcom/mojang/blaze3d/systems/RenderSystem$AutoStorageIndexBuffer; -accessible field com/mojang/blaze3d/vertex/VertexBuffer format Lcom/mojang/blaze3d/vertex/VertexFormat; # ClientTableFormatter accessible field net/minecraft/client/gui/components/ChatComponent allMessages Ljava/util/List; @@ -31,6 +29,4 @@ accessible method com/mojang/blaze3d/audio/Channel pumpBuffers (I)V accessible field net/minecraft/client/sounds/SoundEngine executor Lnet/minecraft/client/sounds/SoundEngineExecutor; # Turtle model -accessible method net/minecraft/client/renderer/block/model/ItemOverrides ()V - accessible class net/minecraft/util/datafix/fixes/ItemStackComponentizationFix$ItemStackData diff --git a/projects/common/src/main/resources/computercraft.mixins.json b/projects/common/src/main/resources/computercraft.mixins.json index 84cd67612..4118cfb5a 100644 --- a/projects/common/src/main/resources/computercraft.mixins.json +++ b/projects/common/src/main/resources/computercraft.mixins.json @@ -8,6 +8,7 @@ }, "mixins": [ "ItemStackComponentizationFixMixin", - "V1460Mixin" + "V1460Mixin", + "V3818_3Mixin" ] } diff --git a/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java b/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java index fae335b78..9c30345ec 100644 --- a/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java +++ b/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java @@ -21,6 +21,7 @@ import net.minecraft.core.Registry; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.TagKey; @@ -35,7 +36,7 @@ import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingInput; -import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -115,13 +116,13 @@ public class TestPlatformHelper extends AbstractComputerCraftAPI implements Plat } @Override - public int getBurnTime(ItemStack stack) { + public int getBurnTime(MinecraftServer server, ItemStack stack) { throw new UnsupportedOperationException("Cannot get burn time inside tests"); } @Override public ItemStack getCraftingRemainingItem(ItemStack stack) { - return new ItemStack(stack.getItem().getCraftingRemainingItem()); + return stack.getItem().getCraftingRemainder(); } @Override @@ -161,7 +162,7 @@ public class TestPlatformHelper extends AbstractComputerCraftAPI implements Plat } @Override - public List getRecipeRemainingItems(ServerPlayer player, Recipe recipe, CraftingInput container) { + public List getRecipeRemainingItems(ServerPlayer player, CraftingRecipe recipe, CraftingInput container) { throw new UnsupportedOperationException("Cannot query recipes inside tests"); } diff --git a/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java b/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java index 43b2b80a9..d223f1a00 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java +++ b/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java @@ -24,8 +24,9 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.item.crafting.ShapedRecipe; -import net.minecraft.world.item.crafting.ShapelessRecipe; +import net.minecraft.world.item.crafting.display.ShapedCraftingRecipeDisplay; +import net.minecraft.world.item.crafting.display.ShapelessCraftingRecipeDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplay; import java.io.File; import java.io.IOException; @@ -83,34 +84,36 @@ public class Exporter { } // Now find all CC recipes. - var level = Objects.requireNonNull(Minecraft.getInstance().level); - for (var recipe : level.getRecipeManager().getAllRecipesFor(RecipeType.CRAFTING)) { - var result = recipe.value().getResultItem(level.registryAccess()); - if (!RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, result.getItem()).getNamespace().equals(ComputerCraftAPI.MOD_ID)) { - continue; - } + var server = Objects.requireNonNull(Minecraft.getInstance().getSingleplayerServer()); + for (var recipe : server.getRecipeManager().getRecipes()) { + if (recipe.value().getType() != RecipeType.CRAFTING) continue; + if (!recipe.id().location().getNamespace().equals(ComputerCraftAPI.MOD_ID)) continue; + + var displayInfos = recipe.value().display(); + if (displayInfos.isEmpty()) continue; + var displayInfo = displayInfos.getFirst(); + + var result = ((SlotDisplay.ItemStackSlotDisplay) displayInfo.result()).stack(); if (!result.getComponentsPatch().isEmpty()) { TestHooks.LOG.warn("Skipping recipe {} as it has NBT", recipe.id()); continue; } - if (recipe.value() instanceof ShapedRecipe shaped) { + if (displayInfo instanceof ShapedCraftingRecipeDisplay shaped) { var converted = new JsonDump.Recipe(result); - for (var x = 0; x < shaped.getWidth(); x++) { - for (var y = 0; y < shaped.getHeight(); y++) { - var ingredient = shaped.getIngredients().get(x + y * shaped.getWidth()); - if (ingredient.isEmpty()) continue; - + for (var x = 0; x < shaped.width(); x++) { + for (var y = 0; y < shaped.height(); y++) { + var ingredient = shaped.ingredients().get(x + y * shaped.width()); converted.setInput(x + y * 3, ingredient, items); } } dump.recipes.put(recipe.id().toString(), converted); - } else if (recipe.value() instanceof ShapelessRecipe shapeless) { + } else if (displayInfo instanceof ShapelessCraftingRecipeDisplay shapeless) { var converted = new JsonDump.Recipe(result); - var ingredients = shapeless.getIngredients(); + var ingredients = shapeless.ingredients(); for (var i = 0; i < ingredients.size(); i++) { converted.setInput(i, ingredients.get(i), items); } diff --git a/projects/common/src/testMod/java/dan200/computercraft/export/ImageRenderer.java b/projects/common/src/testMod/java/dan200/computercraft/export/ImageRenderer.java index 0212ec0f5..995709f01 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/export/ImageRenderer.java +++ b/projects/common/src/testMod/java/dan200/computercraft/export/ImageRenderer.java @@ -4,12 +4,10 @@ package dan200.computercraft.export; +import com.mojang.blaze3d.ProjectionType; import com.mojang.blaze3d.pipeline.TextureTarget; import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.VertexSorting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.FogRenderer; import org.joml.Matrix4f; import org.lwjgl.opengl.GL12; @@ -25,39 +23,38 @@ public class ImageRenderer implements AutoCloseable { public static final int WIDTH = 64; public static final int HEIGHT = 64; - private final TextureTarget framebuffer = new TextureTarget(WIDTH, HEIGHT, true, Minecraft.ON_OSX); - private final NativeImage image = new NativeImage(WIDTH, HEIGHT, Minecraft.ON_OSX); + private final TextureTarget framebuffer = new TextureTarget(WIDTH, HEIGHT, true); + private final NativeImage image = new NativeImage(WIDTH, HEIGHT, true); private @Nullable Matrix4f projectionMatrix; public ImageRenderer() { framebuffer.setClearColor(0, 0, 0, 0); - framebuffer.clear(Minecraft.ON_OSX); + framebuffer.clear(); } public void setupState() { - projectionMatrix = RenderSystem.getProjectionMatrix(); - RenderSystem.setProjectionMatrix(new Matrix4f().identity().ortho(0, 16, 0, 16, 1000, 3000), VertexSorting.DISTANCE_TO_ORIGIN); + RenderSystem.backupProjectionMatrix(); + RenderSystem.setProjectionMatrix(new Matrix4f().identity().ortho(0, 16, 0, 16, 1000, 3000), ProjectionType.ORTHOGRAPHIC); var transform = RenderSystem.getModelViewStack(); transform.pushMatrix(); transform.identity(); transform.translate(0.0f, 0.0f, -2000.0f); - FogRenderer.setupNoFog(); + // FIXME: FogRenderer.toggleFog() } public void clearState() { if (projectionMatrix == null) throw new IllegalStateException("Not currently rendering"); - RenderSystem.setProjectionMatrix(projectionMatrix, VertexSorting.DISTANCE_TO_ORIGIN); - RenderSystem.getModelViewStack().popMatrix(); + RenderSystem.restoreProjectionMatrix(); } public void captureRender(Path output, Runnable render) throws IOException { Files.createDirectories(output.getParent()); framebuffer.bindWrite(true); - RenderSystem.clear(GL12.GL_COLOR_BUFFER_BIT | GL12.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX); + RenderSystem.clear(GL12.GL_COLOR_BUFFER_BIT | GL12.GL_DEPTH_BUFFER_BIT); render.run(); framebuffer.unbindWrite(); diff --git a/projects/common/src/testMod/java/dan200/computercraft/export/JsonDump.java b/projects/common/src/testMod/java/dan200/computercraft/export/JsonDump.java index fcad316ab..c773a4906 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/export/JsonDump.java +++ b/projects/common/src/testMod/java/dan200/computercraft/export/JsonDump.java @@ -6,10 +6,12 @@ package dan200.computercraft.export; import dan200.computercraft.shared.util.RegistryHelper; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.util.context.ContextMap; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.display.SlotDisplay; +import net.minecraft.world.item.crafting.display.SlotDisplayContext; import java.util.Arrays; import java.util.Map; @@ -30,10 +32,10 @@ public class JsonDump { count = output.getCount(); } - public void setInput(int pos, Ingredient ingredient, Set trackedItems) { - if (ingredient.isEmpty()) return; + public void setInput(int pos, SlotDisplay ingredient, Set trackedItems) { + if (ingredient instanceof SlotDisplay.Empty) return; - var items = ingredient.getItems(); + var items = ingredient.resolveForStacks(new ContextMap.Builder().create(SlotDisplayContext.CONTEXT)); // First try to simplify some tags to something easier. for (var stack : items) { @@ -45,9 +47,9 @@ public class JsonDump { return; } - var itemIds = new String[items.length]; - for (var i = 0; i < items.length; i++) { - var item = items[i].getItem(); + var itemIds = new String[items.size()]; + for (var i = 0; i < items.size(); i++) { + var item = items.get(i).getItem(); trackedItems.add(item); itemIds[i] = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, item).toString(); } diff --git a/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java b/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java index 3b44cedb4..05672d002 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java +++ b/projects/common/src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java @@ -17,8 +17,8 @@ import net.minecraft.gametest.framework.StructureUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.StructureBlockEntity; import net.minecraft.world.level.storage.LevelResource; @@ -27,7 +27,6 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Path; -import static dan200.computercraft.core.util.Nullability.assertNonNull; import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.choice; import static net.minecraft.commands.Commands.literal; @@ -69,19 +68,19 @@ class CCTestCommand { var info = GameTestRegistry.getTestFunction(structureBlock.getMetaData()); // Kill the existing armor stand - player - .serverLevel().getEntities(EntityType.ARMOR_STAND, x -> x.isAlive() && x.getName().getString().equals(info.testName())) - .forEach(Entity::kill); + var level = player.serverLevel(); + level.getEntities(EntityType.ARMOR_STAND, x -> x.isAlive() && x.getName().getString().equals(info.testName())) + .forEach(e -> e.kill(level)); // And create a new one var nbt = new CompoundTag(); nbt.putBoolean("Marker", true); nbt.putBoolean("Invisible", true); - var armorStand = assertNonNull(EntityType.ARMOR_STAND.create(player.level())); + var armorStand = new ArmorStand(EntityType.ARMOR_STAND, level); armorStand.readAdditionalSaveData(nbt); armorStand.copyPosition(player); armorStand.setCustomName(Component.literal(info.testName())); - player.level().addFreshEntity(armorStand); + level.addFreshEntity(armorStand); return 0; })) diff --git a/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/GameTestServerMixin.java b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/GameTestServerMixin.java new file mode 100644 index 000000000..7efa7e960 --- /dev/null +++ b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/GameTestServerMixin.java @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.mixin.gametest; + +import com.mojang.datafixers.DataFixer; +import net.minecraft.gametest.framework.GameTestServer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.Services; +import net.minecraft.server.WorldStem; +import net.minecraft.server.level.progress.ChunkProgressListenerFactory; +import net.minecraft.server.packs.repository.PackRepository; +import net.minecraft.world.level.storage.LevelStorageSource; +import org.spongepowered.asm.mixin.Mixin; + +import java.net.Proxy; + +@Mixin(GameTestServer.class) +abstract class GameTestServerMixin extends MinecraftServer implements MinecraftServerAccessor { + GameTestServerMixin(Thread serverThread, LevelStorageSource.LevelStorageAccess storageSource, PackRepository packRepository, WorldStem worldStem, Proxy proxy, DataFixer fixerUpper, Services services, ChunkProgressListenerFactory progressListenerFactory) { + super(serverThread, storageSource, packRepository, worldStem, proxy, fixerUpper, services, progressListenerFactory); + } + + /** + * {@link GameTestServer} overrides {@code waitUntilNextTick} to tick as quickly as possible. This does not play + * well with computers, so we add back {@link MinecraftServer}'s implementation. + */ + @Override + public void waitUntilNextTick() { + runAllTasks(); + computercraft$setWaitingForNextTick(true); + + try { + this.managedBlock(() -> !computercraft$haveTime()); + } finally { + computercraft$setWaitingForNextTick(false); + } + } +} diff --git a/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/MinecraftServerAccessor.java b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/MinecraftServerAccessor.java new file mode 100644 index 000000000..19aac4d3d --- /dev/null +++ b/projects/common/src/testMod/java/dan200/computercraft/mixin/gametest/MinecraftServerAccessor.java @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.mixin.gametest; + +import net.minecraft.server.MinecraftServer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(MinecraftServer.class) +public interface MinecraftServerAccessor { + @Accessor("waitingForNextTick") + void computercraft$setWaitingForNextTick(boolean value); + + @Invoker("haveTime") + boolean computercraft$haveTime(); +} diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt index 7a21696de..fcf496862 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Computer_Test.kt @@ -37,8 +37,8 @@ class Computer_Test { */ @GameTest fun No_through_signal(context: GameTestHelper) = context.sequence { - val lamp = BlockPos(2, 2, 4) - val lever = BlockPos(2, 2, 0) + val lamp = BlockPos(2, 1, 4) + val lever = BlockPos(2, 1, 0) thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should not be lit") context.modifyBlock(lever) { x -> x.setValue(LeverBlock.POWERED, true) } @@ -52,8 +52,8 @@ class Computer_Test { */ @GameTest fun No_through_signal_reverse(context: GameTestHelper) = context.sequence { - val lamp = BlockPos(2, 2, 4) - val lever = BlockPos(2, 2, 0) + val lamp = BlockPos(2, 1, 4) + val lever = BlockPos(2, 1, 0) thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should not be lit") context.modifyBlock(lever) { x -> x.setValue(LeverBlock.POWERED, true) } @@ -67,12 +67,12 @@ class Computer_Test { */ @GameTest fun Set_and_destroy(context: GameTestHelper) = context.sequence { - val lamp = BlockPos(2, 2, 3) + val lamp = BlockPos(2, 1, 3) thenOnComputer { getApi().setOutput(ComputerSide.BACK, true) } thenIdle(3) thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, true, "Lamp should be lit") } - thenExecute { context.setBlock(BlockPos(2, 2, 2), Blocks.AIR) } + thenExecute { context.setBlock(BlockPos(2, 1, 2), Blocks.AIR) } thenIdle(4) thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should not be lit") } } @@ -101,8 +101,8 @@ class Computer_Test { @GameTest fun Computer_peripheral(context: GameTestHelper) = context.sequence { thenExecute { - context.assertPeripheral(BlockPos(3, 2, 2), type = "computer") - context.assertPeripheral(BlockPos(1, 2, 2), type = "turtle") + context.assertPeripheral(BlockPos(3, 1, 2), type = "computer") + context.assertPeripheral(BlockPos(1, 1, 2), type = "turtle") } } @@ -112,7 +112,7 @@ class Computer_Test { @GameTest fun Chest_resizes_on_change(context: GameTestHelper) = context.sequence { thenOnComputer { callPeripheral("right", "size").assertArrayEquals(27) } - thenExecute { context.placeItemAt(ItemStack(Items.CHEST), BlockPos(2, 2, 2), Direction.WEST) } + thenExecute { context.placeItemAt(ItemStack(Items.CHEST), BlockPos(2, 1, 2), Direction.WEST) } thenIdle(1) thenOnComputer { callPeripheral("right", "size").assertArrayEquals(54) } } @@ -123,7 +123,7 @@ class Computer_Test { @GameTest fun Drops_on_explosion(context: GameTestHelper) = context.sequence { thenExecute { - val explosionPos = Vec3.atCenterOf(context.absolutePos(BlockPos(2, 2, 2))) + val explosionPos = Vec3.atCenterOf(context.absolutePos(BlockPos(2, 1, 2))) context.level.explode(null, explosionPos.x, explosionPos.y, explosionPos.z, 2.0f, Level.ExplosionInteraction.TNT) context.assertItemEntityCountIs(ModRegistry.Items.COMPUTER_NORMAL.get(), 1) @@ -153,8 +153,8 @@ class Computer_Test { } // Teleport the player to the computer and then open it. thenExecute { - context.positionAt(BlockPos(2, 2, 1)) - context.useBlock(BlockPos(2, 2, 2), context.level.randomPlayer!!) + context.positionAt(BlockPos(2, 1, 1)) + context.useBlock(BlockPos(2, 1, 2), context.level.randomPlayer!!) } // Assert the terminal is synced to the client. thenIdle(2) diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Disk_Drive_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Disk_Drive_Test.kt index 4dfad1ac1..60e6ecbd2 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Disk_Drive_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Disk_Drive_Test.kt @@ -60,7 +60,7 @@ class Disk_Drive_Test { @GameTest fun Ejects_disk(helper: GameTestHelper) = helper.sequence { - val stackAt = BlockPos(2, 2, 2) + val stackAt = BlockPos(2, 1, 2) thenOnComputer { callPeripheral("right", "ejectDisk") } thenWaitUntil { helper.assertItemEntityPresent(Items.MUSIC_DISC_13, stackAt, 0.0) } } @@ -70,7 +70,7 @@ class Disk_Drive_Test { */ @GameTest fun Queues_event(helper: GameTestHelper) = helper.sequence { - val pos = BlockPos(1, 2, 2) + val pos = BlockPos(1, 1, 2) var started = false var disk = false @@ -104,7 +104,7 @@ class Disk_Drive_Test { fun Adds_removes_mount(helper: GameTestHelper) = helper.sequence { thenOnComputer { } // Wait for the computer to start up thenExecute { - helper.setContainerItem(BlockPos(1, 2, 2), 0, ItemStack(ModRegistry.Items.DISK.get())) + helper.setContainerItem(BlockPos(1, 1, 2), 0, ItemStack(ModRegistry.Items.DISK.get())) } thenOnComputer { getApi().getDrive("disk").assertArrayEquals("right") @@ -119,7 +119,7 @@ class Disk_Drive_Test { */ @GameTest fun Creates_disk_id(helper: GameTestHelper) = helper.sequence { - val drivePos = BlockPos(2, 2, 2) + val drivePos = BlockPos(2, 1, 2) thenWaitUntil { val drive = helper.getBlockEntity(drivePos, ModRegistry.BlockEntities.DISK_DRIVE.get()) if (!drive.getItem(0).has(ModRegistry.DataComponents.DISK_ID.get())) { @@ -133,8 +133,8 @@ class Disk_Drive_Test { */ @GameTest fun Comparator(helper: GameTestHelper) = helper.sequence { - val drivePos = BlockPos(2, 2, 2) - val dustPos = BlockPos(2, 2, 4) + val drivePos = BlockPos(2, 1, 2) + val dustPos = BlockPos(2, 1, 4) // Adding items should provide power thenExecute { @@ -160,7 +160,7 @@ class Disk_Drive_Test { */ @GameTest fun Contents_updates_state(helper: GameTestHelper) = helper.sequence { - val pos = BlockPos(2, 2, 2) + val pos = BlockPos(2, 1, 2) thenExecute { val drive = helper.getBlockEntity(pos, ModRegistry.BlockEntities.DISK_DRIVE.get()) @@ -185,7 +185,7 @@ class Disk_Drive_Test { @GameTest fun Drops_contents(helper: GameTestHelper) = helper.sequence { thenExecute { - helper.level.destroyBlock(helper.absolutePos(BlockPos(2, 2, 2)), true) + helper.level.destroyBlock(helper.absolutePos(BlockPos(2, 1, 2)), true) helper.assertExactlyItems( DataComponentUtil.createStack(ModRegistry.Items.DISK_DRIVE.get(), DataComponents.CUSTOM_NAME, Component.literal("My Disk Drive")), ItemStack(ModRegistry.Items.TREASURE_DISK.get()), @@ -201,7 +201,7 @@ class Disk_Drive_Test { fun Data_fixers(helper: GameTestHelper) = helper.sequence { thenExecute { helper.assertContainerExactly( - BlockPos(1, 2, 2), + BlockPos(1, 1, 2), listOf( ItemStack(ModRegistry.Items.DISK.get()).also { it.applyComponents( @@ -215,7 +215,7 @@ class Disk_Drive_Test { ) helper.assertContainerExactly( - BlockPos(3, 2, 2), + BlockPos(3, 1, 2), listOf( ItemStack(ModRegistry.Items.TREASURE_DISK.get()).also { it.applyComponents( diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Inventory_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Inventory_Test.kt index 6fc9cad2f..1401db615 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Inventory_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Inventory_Test.kt @@ -40,8 +40,8 @@ class Inventory_Test { ).await().assertArrayEquals(0, message = "Does not move items") } thenExecute { - helper.assertContainerExactly(BlockPos(1, 2, 2), listOf()) - helper.assertContainerExactly(BlockPos(3, 2, 2), listOf(ItemStack(Items.SHULKER_BOX))) + helper.assertContainerExactly(BlockPos(1, 1, 2), listOf()) + helper.assertContainerExactly(BlockPos(3, 1, 2), listOf(ItemStack(Items.SHULKER_BOX))) } } @@ -66,8 +66,8 @@ class Inventory_Test { ).await().assertArrayEquals(0, message = "Does not move items") } thenExecute { - helper.assertContainerExactly(BlockPos(1, 2, 2), listOf(ItemStack.EMPTY, ItemStack.EMPTY, ItemStack(Items.IRON_INGOT))) - helper.assertContainerExactly(BlockPos(3, 2, 2), NonNullList.withSize(27, ItemStack(Items.POLISHED_ANDESITE))) + helper.assertContainerExactly(BlockPos(1, 1, 2), listOf(ItemStack.EMPTY, ItemStack.EMPTY, ItemStack(Items.IRON_INGOT))) + helper.assertContainerExactly(BlockPos(3, 1, 2), NonNullList.withSize(27, ItemStack(Items.POLISHED_ANDESITE))) } } diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Loot_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Loot_Test.kt index 0d8394189..9c68f2466 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Loot_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Loot_Test.kt @@ -21,7 +21,7 @@ class Loot_Test { @GameTest(template = Structures.DEFAULT, required = false) // FIXME: We may need to inject this as a datapack instead fun Chest_contains_disk(context: GameTestHelper) = context.sequence { thenExecute { - val pos = BlockPos(2, 2, 2) + val pos = BlockPos(2, 1, 2) context.setBlock(pos, Blocks.CHEST) val chest = context.getBlockEntity(pos) as ChestBlockEntity diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Modem_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Modem_Test.kt index 01170422f..be645d86e 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Modem_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Modem_Test.kt @@ -35,7 +35,7 @@ class Modem_Test { @GameTest fun Gains_peripherals(helper: GameTestHelper) = helper.sequence { - val position = BlockPos(2, 2, 2) + val position = BlockPos(2, 1, 2) thenOnComputer { assertEquals(listOf("back"), getPeripheralNames(), "Starts with peripherals") } @@ -84,8 +84,8 @@ class Modem_Test { @GameTest(setupTicks = 1) fun Full_modems_form_networks(helper: GameTestHelper) = helper.sequence { thenExecute { - val modem1 = helper.getBlockEntity(BlockPos(1, 2, 1), ModRegistry.BlockEntities.WIRED_MODEM_FULL.get()) - val modem2 = helper.getBlockEntity(BlockPos(3, 2, 1), ModRegistry.BlockEntities.WIRED_MODEM_FULL.get()) + val modem1 = helper.getBlockEntity(BlockPos(1, 1, 1), ModRegistry.BlockEntities.WIRED_MODEM_FULL.get()) + val modem2 = helper.getBlockEntity(BlockPos(3, 1, 1), ModRegistry.BlockEntities.WIRED_MODEM_FULL.get()) assertEquals((modem1.element.node as WiredNodeImpl).network, (modem2.element.node as WiredNodeImpl).network, "On the same network") } } @@ -101,7 +101,7 @@ class Modem_Test { // However, if we connect the network, the other modem does. thenExecute { helper.setBlock( - BlockPos(1, 2, 3), + BlockPos(1, 1, 3), ModRegistry.Blocks.CABLE.get().defaultBlockState().setValue(CableBlock.CABLE, true), ) } @@ -120,7 +120,7 @@ class Modem_Test { // However, if we connect the network, the other modem does. thenExecute { helper.setBlock( - BlockPos(1, 2, 3), + BlockPos(1, 1, 3), ModRegistry.Blocks.CABLE.get().defaultBlockState().setValue(CableBlock.CABLE, true), ) } @@ -134,9 +134,9 @@ class Modem_Test { @GameTest fun Modem_drops_when_neighbour_removed(helper: GameTestHelper) = helper.sequence { thenExecute { - helper.setBlock(BlockPos(2, 3, 2), Blocks.AIR) - helper.assertItemEntityPresent(ModRegistry.Items.WIRED_MODEM.get(), BlockPos(2, 2, 2), 0.0) - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 2)) + helper.setBlock(BlockPos(2, 2, 2), Blocks.AIR) + helper.assertItemEntityPresent(ModRegistry.Items.WIRED_MODEM.get(), BlockPos(2, 1, 2), 0.0) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 2)) } } @@ -146,9 +146,9 @@ class Modem_Test { @GameTest fun Modem_keeps_cable_when_neighbour_removed(helper: GameTestHelper) = helper.sequence { thenExecute { - helper.setBlock(BlockPos(2, 3, 2), Blocks.AIR) - helper.assertItemEntityPresent(ModRegistry.Items.WIRED_MODEM.get(), BlockPos(2, 2, 2), 0.0) - helper.assertBlockIs(BlockPos(2, 2, 2)) { + helper.setBlock(BlockPos(2, 2, 2), Blocks.AIR) + helper.assertItemEntityPresent(ModRegistry.Items.WIRED_MODEM.get(), BlockPos(2, 1, 2), 0.0) + helper.assertBlockIs(BlockPos(2, 1, 2)) { it.block == ModRegistry.Blocks.CABLE.get() && it.getValue(CableBlock.MODEM) == CableModemVariant.None && it.getValue(CableBlock.CABLE) } } @@ -162,7 +162,7 @@ class Modem_Test { thenOnComputer { callRemotePeripheral("minecraft:chest_0", "size").assertArrayEquals(27) } - thenExecute { context.placeItemAt(ItemStack(Items.CHEST), BlockPos(2, 2, 2), Direction.WEST) } + thenExecute { context.placeItemAt(ItemStack(Items.CHEST), BlockPos(2, 1, 2), Direction.WEST) } thenIdle(1) thenOnComputer { callRemotePeripheral("minecraft:chest_0", "size").assertArrayEquals(54) diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Monitor_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Monitor_Test.kt index afbf8d400..0d00484b8 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Monitor_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Monitor_Test.kt @@ -6,10 +6,8 @@ package dan200.computercraft.gametest import dan200.computercraft.gametest.api.* import dan200.computercraft.shared.ModRegistry -import dan200.computercraft.shared.config.Config import dan200.computercraft.shared.peripheral.monitor.MonitorBlock import dan200.computercraft.shared.peripheral.monitor.MonitorEdgeState -import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer import net.minecraft.commands.arguments.blocks.BlockInput import net.minecraft.core.BlockPos import net.minecraft.gametest.framework.GameTest @@ -17,15 +15,15 @@ import net.minecraft.gametest.framework.GameTestGenerator import net.minecraft.gametest.framework.GameTestHelper import net.minecraft.gametest.framework.TestFunction import net.minecraft.nbt.CompoundTag -import net.minecraft.world.entity.EntityType import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.GameType import net.minecraft.world.level.block.Blocks import org.junit.jupiter.api.Assertions.* class Monitor_Test { @GameTest fun Ensures_valid_on_place(context: GameTestHelper) = context.sequence { - val pos = BlockPos(2, 2, 2) + val pos = BlockPos(2, 1, 2) thenExecute { val tag = CompoundTag() @@ -57,9 +55,9 @@ class Monitor_Test { @GameTest fun Contract_on_destroy(helper: GameTestHelper) = helper.sequence { thenExecute { - helper.setBlock(BlockPos(2, 2, 2), Blocks.AIR.defaultBlockState()) - helper.assertBlockHas(BlockPos(1, 2, 2), MonitorBlock.STATE, MonitorEdgeState.NONE) - helper.assertBlockHas(BlockPos(3, 2, 2), MonitorBlock.STATE, MonitorEdgeState.NONE) + helper.setBlock(BlockPos(2, 1, 2), Blocks.AIR.defaultBlockState()) + helper.assertBlockHas(BlockPos(1, 1, 2), MonitorBlock.STATE, MonitorEdgeState.NONE) + helper.assertBlockHas(BlockPos(3, 1, 2), MonitorBlock.STATE, MonitorEdgeState.NONE) } } @@ -69,7 +67,7 @@ class Monitor_Test { @GameTest fun Creates_terminal(helper: GameTestHelper) = helper.sequence { fun monitorAt(x: Int) = - helper.getBlockEntity(BlockPos(x, 2, 2), ModRegistry.BlockEntities.MONITOR_ADVANCED.get()) + helper.getBlockEntity(BlockPos(x, 1, 2), ModRegistry.BlockEntities.MONITOR_ADVANCED.get()) thenExecute { for (i in 1..3) { @@ -80,20 +78,20 @@ class Monitor_Test { assertNotNull(monitorAt(1).cachedServerMonitor?.terminal, "Creating a peripheral creates a terminal") // Then remove the middle monitor and check it splits into two. - helper.setBlock(BlockPos(2, 2, 2), Blocks.AIR.defaultBlockState()) + helper.setBlock(BlockPos(2, 1, 2), Blocks.AIR.defaultBlockState()) assertNotNull(monitorAt(3).cachedServerMonitor, "Origin retains its monitor") assertNull(monitorAt(3).cachedServerMonitor!!.terminal, "Origin deletes the terminal") assertNotEquals(monitorAt(1).cachedServerMonitor, monitorAt(3).cachedServerMonitor, "Monitors are different") // Then set the monitor, check it rejoins and recreates the terminal. - val pos = BlockPos(2, 2, 2) + val pos = BlockPos(2, 1, 2) helper.setBlock(pos, ModRegistry.Blocks.MONITOR_ADVANCED.get()) ModRegistry.Blocks.MONITOR_ADVANCED.get().setPlacedBy( helper.level, helper.absolutePos(pos), helper.getBlockState(pos), - EntityType.COW.create(helper.level), + helper.makeMockPlayer(GameType.SURVIVAL), ItemStack.EMPTY, ) monitorAt(2).peripheral() @@ -109,7 +107,7 @@ class Monitor_Test { fun Render_monitor_tests(): List { val tests = mutableListOf() - fun addTest(label: String, renderer: MonitorRenderer, time: Long = Times.NOON, tag: String = TestTags.CLIENT) { + fun addTest(label: String, time: Long = Times.NOON, tag: String = TestTags.CLIENT) { if (!TestTags.isEnabled(tag)) return val className = this::class.java.simpleName.lowercase() @@ -123,32 +121,29 @@ class Monitor_Test { Timeouts.DEFAULT, 0, true, - ) { renderMonitor(it, renderer, time) }, + ) { renderMonitor(it, time) }, ) } - addTest("tbo_noon", MonitorRenderer.TBO, Times.NOON) - addTest("tbo_midnight", MonitorRenderer.TBO, Times.MIDNIGHT) - addTest("vbo_noon", MonitorRenderer.VBO, Times.NOON) - addTest("vbo_midnight", MonitorRenderer.VBO, Times.MIDNIGHT) + addTest("noon", Times.NOON) + addTest("midnight", Times.MIDNIGHT) - addTest("sodium_tbo", MonitorRenderer.TBO, tag = "sodium") - addTest("sodium_vbo", MonitorRenderer.VBO, tag = "sodium") + addTest("sodium_tbo", tag = "sodium") + addTest("sodium_vbo", tag = "sodium") - addTest("iris_noon", MonitorRenderer.BEST, Times.NOON, tag = "iris") - addTest("iris_midnight", MonitorRenderer.BEST, Times.MIDNIGHT, tag = "iris") + addTest("iris_noon", Times.NOON, tag = "iris") + addTest("iris_midnight", Times.MIDNIGHT, tag = "iris") return tests } - private fun renderMonitor(helper: GameTestHelper, renderer: MonitorRenderer, time: Long) = helper.sequence { + private fun renderMonitor(helper: GameTestHelper, time: Long) = helper.sequence { thenExecute { - Config.monitorRenderer = renderer helper.level.dayTime = time helper.positionAtArmorStand() // Get the monitor and peripheral. This forces us to create a server monitor at this location. - val monitor = helper.getBlockEntity(BlockPos(2, 2, 3), ModRegistry.BlockEntities.MONITOR_ADVANCED.get()) + val monitor = helper.getBlockEntity(BlockPos(2, 1, 3), ModRegistry.BlockEntities.MONITOR_ADVANCED.get()) monitor.peripheral() val terminal = monitor.cachedServerMonitor!!.terminal!! diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Pocket_Computer_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Pocket_Computer_Test.kt index f396a8599..e6297f948 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Pocket_Computer_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Pocket_Computer_Test.kt @@ -40,7 +40,7 @@ class Pocket_Computer_Test { // Give the player a pocket computer. thenExecute { - context.positionAt(BlockPos(2, 2, 2)) + context.positionAt(BlockPos(2, 1, 2)) context.givePocketComputer(unique) } // Write some text to the computer. @@ -82,7 +82,7 @@ class Pocket_Computer_Test { // Give the player a pocket computer. thenExecute { - context.positionAt(BlockPos(2, 2, 2), xRot = 90.0f) + context.positionAt(BlockPos(2, 1, 2), xRot = 90.0f) context.givePocketComputer(unique) } thenOnComputer(unique) { @@ -119,12 +119,12 @@ class Pocket_Computer_Test { @GameTest fun Data_fixers(helper: GameTestHelper) = helper.sequence { thenExecute { - val upgrade = helper.level.registryAccess().registryOrThrow(IPocketUpgrade.REGISTRY) - .getHolder(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "wireless_modem_normal")) + val upgrade = helper.level.registryAccess().lookupOrThrow(IPocketUpgrade.REGISTRY) + .get(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "wireless_modem_normal")) .orElseThrow() helper.assertContainerExactly( - BlockPos(2, 2, 2), + BlockPos(2, 1, 2), listOf( ItemStack(ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get()).also { DataComponentUtil.setCustomName(it, "Test") diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Printer_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Printer_Test.kt index 4034bba06..8e6789cf6 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Printer_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Printer_Test.kt @@ -28,8 +28,8 @@ class Printer_Test { */ @GameTest fun Comparator(helper: GameTestHelper) = helper.sequence { - val printerPos = BlockPos(2, 2, 2) - val dustPos = BlockPos(2, 2, 4) + val printerPos = BlockPos(2, 1, 2) + val dustPos = BlockPos(2, 1, 4) // Adding items should provide power thenExecute { @@ -56,7 +56,7 @@ class Printer_Test { */ @GameTest fun Contents_updates_state(helper: GameTestHelper) = helper.sequence { - val pos = BlockPos(2, 2, 2) + val pos = BlockPos(2, 1, 2) thenExecute { val drive = helper.getBlockEntity(pos, ModRegistry.BlockEntities.PRINTER.get()) @@ -89,7 +89,7 @@ class Printer_Test { @GameTest fun Drops_contents(helper: GameTestHelper) = helper.sequence { thenExecute { - helper.level.destroyBlock(helper.absolutePos(BlockPos(2, 2, 2)), true) + helper.level.destroyBlock(helper.absolutePos(BlockPos(2, 1, 2)), true) helper.assertExactlyItems( DataComponentUtil.createStack(ModRegistry.Items.PRINTER.get(), DataComponents.CUSTOM_NAME, Component.literal("My Printer")), ItemStack(Items.PAPER), @@ -105,7 +105,7 @@ class Printer_Test { @GameTest fun Data_fixers(helper: GameTestHelper) = helper.sequence { thenExecute { - val container = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.PRINTER.get()) + val container = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.PRINTER.get()) val contents = container.getItem(1) assertEquals(ModRegistry.Items.PRINTED_PAGE.get(), contents.item) diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt index 191152e74..e47d6214c 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt @@ -88,7 +88,7 @@ class Turtle_Test { turtle.placeDown(ObjectArguments()).await() .assertArrayEquals(true, message = "Placed lava") } - thenExecute { helper.assertBlockPresent(Blocks.LAVA, BlockPos(2, 2, 2)) } + thenExecute { helper.assertBlockPresent(Blocks.LAVA, BlockPos(2, 1, 2)) } } /** @@ -103,7 +103,7 @@ class Turtle_Test { .assertArrayEquals(true, message = "Placed sign") } thenExecute { - val sign = helper.getBlockEntity(BlockPos(2, 2, 1), BlockEntityType.SIGN) + val sign = helper.getBlockEntity(BlockPos(2, 1, 1), BlockEntityType.SIGN) val lines = listOf("", "Test", "message", "") for ((i, line) in lines.withIndex()) { assertEquals(line, sign.frontText.getMessage(i, false).string, "Line $i") @@ -126,8 +126,8 @@ class Turtle_Test { .assertArrayEquals(true, message = "Placed water") } thenExecute { - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 2)) - helper.assertBlockHas(BlockPos(2, 5, 2), BlockStateProperties.WATERLOGGED, true) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 2)) + helper.assertBlockHas(BlockPos(2, 4, 2), BlockStateProperties.WATERLOGGED, true) } } @@ -143,7 +143,7 @@ class Turtle_Test { .assertArrayEquals(true, message = "Placed oak fence") } thenExecute { - helper.assertBlockIs(BlockPos(2, 2, 2)) { it.block == Blocks.OAK_FENCE && it.getValue(FenceBlock.WATERLOGGED) } + helper.assertBlockIs(BlockPos(2, 1, 2)) { it.block == Blocks.OAK_FENCE && it.getValue(FenceBlock.WATERLOGGED) } } } @@ -160,7 +160,7 @@ class Turtle_Test { assertEquals("minecraft:lava_bucket", getTurtleItemDetail()["name"]) } - thenExecute { helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 2)) } + thenExecute { helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 2)) } } /** @@ -171,7 +171,7 @@ class Turtle_Test { @GameTest fun Hoe_dirt(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.dig(Optional.empty()).await().assertArrayEquals(true, message = "Dug with hoe") } - thenExecute { helper.assertBlockPresent(Blocks.FARMLAND, BlockPos(1, 2, 1)) } + thenExecute { helper.assertBlockPresent(Blocks.FARMLAND, BlockPos(1, 1, 1)) } } /** @@ -182,7 +182,7 @@ class Turtle_Test { @GameTest fun Hoe_dirt_below(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.digDown(Optional.empty()).await().assertArrayEquals(true, message = "Dug with hoe") } - thenExecute { helper.assertBlockPresent(Blocks.FARMLAND, BlockPos(1, 1, 1)) } + thenExecute { helper.assertBlockPresent(Blocks.FARMLAND, BlockPos(1, 0, 1)) } } /** @@ -194,7 +194,7 @@ class Turtle_Test { turtle.dig(Optional.empty()).await() .assertArrayEquals(false, "Nothing to dig here", message = "Dug with hoe") } - thenExecute { helper.assertBlockPresent(Blocks.DIRT, BlockPos(1, 2, 2)) } + thenExecute { helper.assertBlockPresent(Blocks.DIRT, BlockPos(1, 1, 2)) } } /** @@ -204,18 +204,18 @@ class Turtle_Test { fun Break_cable(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.dig(Optional.empty()).await() } thenExecute { - helper.assertBlockIs(BlockPos(2, 2, 3)) { + helper.assertBlockIs(BlockPos(2, 1, 3)) { it.block == ModRegistry.Blocks.CABLE.get() && !it.getValue(CableBlock.CABLE) && it.getValue(CableBlock.MODEM) == CableModemVariant.DownOff } - helper.assertContainerExactly(BlockPos(2, 2, 2), listOf(ItemStack(ModRegistry.Items.CABLE.get()))) + helper.assertContainerExactly(BlockPos(2, 1, 2), listOf(ItemStack(ModRegistry.Items.CABLE.get()))) } thenOnComputer { turtle.dig(Optional.empty()).await().assertArrayEquals(true) } thenExecute { - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 3)) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 3)) helper.assertContainerExactly( - BlockPos(2, 2, 2), + BlockPos(2, 1, 2), listOf( ItemStack(ModRegistry.Items.CABLE.get()), ItemStack(ModRegistry.Items.WIRED_MODEM.get()), @@ -231,14 +231,14 @@ class Turtle_Test { fun Dig_consume_durability(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.dig(Optional.empty()).await() } thenExecute { - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 3)) - helper.assertContainerExactly(BlockPos(2, 2, 2), listOf(ItemStack(Items.COBBLESTONE))) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 3)) + helper.assertContainerExactly(BlockPos(2, 1, 2), listOf(ItemStack(Items.COBBLESTONE))) - val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access + val turtle = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access val upgrade = turtle.getUpgrade(TurtleSide.LEFT) assertEquals( - helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) - .get(ResourceLocation.fromNamespaceAndPath("cctest", "wooden_pickaxe")), + helper.level.registryAccess().lookupOrThrow(ITurtleUpgrade.REGISTRY) + .getValue(ResourceLocation.fromNamespaceAndPath("cctest", "wooden_pickaxe")), upgrade, "Upgrade is a wooden pickaxe", ) @@ -256,18 +256,18 @@ class Turtle_Test { fun Dig_breaks_tool(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.dig(Optional.empty()).await() } thenExecute { - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 3)) - helper.assertContainerExactly(BlockPos(2, 2, 2), listOf(ItemStack(Items.COBBLESTONE))) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 3)) + helper.assertContainerExactly(BlockPos(2, 1, 2), listOf(ItemStack(Items.COBBLESTONE))) - val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access + val turtle = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access val upgrade = turtle.getUpgrade(TurtleSide.LEFT) assertEquals(null, upgrade, "Upgrade broke") helper.assertUpgradeItem( ItemStack(Items.WOODEN_PICKAXE), UpgradeData.ofDefault( - helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) - .getHolder(ResourceLocation.fromNamespaceAndPath("cctest", "wooden_pickaxe")).orElseThrow(), + helper.level.registryAccess().lookupOrThrow(ITurtleUpgrade.REGISTRY) + .get(ResourceLocation.fromNamespaceAndPath("cctest", "wooden_pickaxe")).orElseThrow(), ), ) } @@ -281,14 +281,14 @@ class Turtle_Test { fun Dig_enchanted_consume_durability(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.dig(Optional.empty()).await() } thenExecute { - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 3)) - helper.assertContainerExactly(BlockPos(2, 2, 2), listOf(ItemStack(Items.STONE))) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 3)) + helper.assertContainerExactly(BlockPos(2, 1, 2), listOf(ItemStack(Items.STONE))) - val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access + val turtle = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access val upgrade = turtle.getUpgrade(TurtleSide.LEFT) assertEquals( - helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) - .get(ResourceLocation.fromNamespaceAndPath("cctest", "netherite_pickaxe")), + helper.level.registryAccess().lookupOrThrow(ITurtleUpgrade.REGISTRY) + .getValue(ResourceLocation.fromNamespaceAndPath("cctest", "netherite_pickaxe")), upgrade, "Upgrade is a netherite pickaxe", ) @@ -296,8 +296,8 @@ class Turtle_Test { val item = ItemStack(Items.NETHERITE_PICKAXE) item.damageValue = 1 item.enchant( - helper.level.registryAccess().registryOrThrow(Registries.ENCHANTMENT) - .getHolderOrThrow(Enchantments.SILK_TOUCH), + helper.level.registryAccess().lookupOrThrow(Registries.ENCHANTMENT) + .getOrThrow(Enchantments.SILK_TOUCH), 1, ) @@ -327,7 +327,7 @@ class Turtle_Test { .assertArrayEquals(true, message = "Block was placed") } thenIdle(1) - thenExecute { helper.assertBlockHas(BlockPos(1, 2, 3), MonitorBlock.STATE, MonitorEdgeState.LR) } + thenExecute { helper.assertBlockHas(BlockPos(1, 1, 3), MonitorBlock.STATE, MonitorEdgeState.LR) } } /** @@ -389,15 +389,15 @@ class Turtle_Test { @GameTest fun Resists_explosions(helper: GameTestHelper) = helper.sequence { thenExecute { - val pos = helper.absolutePos(BlockPos(2, 2, 2)) + val pos = helper.absolutePos(BlockPos(2, 1, 2)) val tnt = PrimedTnt(helper.level, pos.x + 0.5, pos.y + 1.0, pos.z + 0.5, null) tnt.fuse = 1 helper.level.addFreshEntity(tnt) } thenWaitUntil { helper.assertEntityNotPresent(EntityType.TNT) } thenExecute { - helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_ADVANCED.get(), BlockPos(2, 2, 2)) - helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 1)) + helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_ADVANCED.get(), BlockPos(2, 1, 2)) + helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 1)) } } @@ -409,8 +409,8 @@ class Turtle_Test { thenExecute { helper.getEntity(EntityType.CREEPER).ignite() } thenWaitUntil { helper.assertEntityNotPresent(EntityType.CREEPER) } thenExecute { - helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_ADVANCED.get(), BlockPos(2, 2, 2)) - helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 2, 1)) + helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_ADVANCED.get(), BlockPos(2, 1, 2)) + helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 1, 1)) } } @@ -419,8 +419,8 @@ class Turtle_Test { */ @GameTest fun Drop_into_chest(helper: GameTestHelper) = helper.sequence { - val turtlePos = BlockPos(2, 2, 2) - val chest = BlockPos(2, 2, 3) + val turtlePos = BlockPos(2, 1, 2) + val chest = BlockPos(2, 1, 3) thenOnComputer { turtle.drop(Optional.of(32)).await() @@ -445,7 +445,7 @@ class Turtle_Test { .assertArrayEquals(true, message = "Could not drop items") } thenExecute { - helper.assertContainerExactly(BlockPos(2, 2, 2), listOf(ItemStack(Blocks.DIRT, 32))) + helper.assertContainerExactly(BlockPos(2, 1, 2), listOf(ItemStack(Blocks.DIRT, 32))) helper.assertContainerExactly(helper.getEntity(EntityType.CHEST_MINECART), listOf(ItemStack(Blocks.DIRT, 48))) helper.assertEntityNotPresent(EntityType.ITEM) } @@ -456,7 +456,7 @@ class Turtle_Test { */ @GameTest fun Refuel_basic(helper: GameTestHelper) = helper.sequence { - val turtlePos = BlockPos(2, 2, 2) + val turtlePos = BlockPos(2, 1, 2) // Test refueling from slot 1 with no limit. thenOnComputer { @@ -484,7 +484,7 @@ class Turtle_Test { */ @GameTest fun Refuel_fail(helper: GameTestHelper) = helper.sequence { - val turtlePos = BlockPos(2, 2, 2) + val turtlePos = BlockPos(2, 1, 2) thenOnComputer { assertEquals(0, turtle.fuelLevel) @@ -501,7 +501,7 @@ class Turtle_Test { */ @GameTest fun Refuel_container(helper: GameTestHelper) = helper.sequence { - val turtlePos = BlockPos(2, 2, 2) + val turtlePos = BlockPos(2, 1, 2) // Test refueling from slot 1 with no limit. thenOnComputer { @@ -523,9 +523,9 @@ class Turtle_Test { fun Move_preserves_state(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.forward().await().assertArrayEquals(true, message = "Turtle moved forward") } thenExecute { - helper.assertContainerExactly(BlockPos(2, 2, 3), listOf(ItemStack(Items.DIRT, 32))) + helper.assertContainerExactly(BlockPos(2, 1, 3), listOf(ItemStack(Items.DIRT, 32))) - val turtle = helper.getBlockEntity(BlockPos(2, 2, 3), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) + val turtle = helper.getBlockEntity(BlockPos(2, 1, 3), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) assertEquals(1, turtle.computerID) assertEquals("turtle_test.move_preserves_state", turtle.label) assertEquals(79, turtle.access.fuelLevel) @@ -540,7 +540,7 @@ class Turtle_Test { @GameTest fun Move_replace(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.forward().await().assertArrayEquals(true, message = "Turtle moved forward") } - thenExecute { helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 2, 3)) } + thenExecute { helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 1, 3)) } } /** @@ -551,13 +551,13 @@ class Turtle_Test { thenOnComputer { turtle.forward().await().assertArrayEquals(true, message = "Turtle moved forward") } thenExecute { // Assert we're waterlogged. - helper.assertBlockHas(BlockPos(2, 2, 2), WaterloggableHelpers.WATERLOGGED, true) + helper.assertBlockHas(BlockPos(2, 1, 2), WaterloggableHelpers.WATERLOGGED, true) } thenOnComputer { turtle.forward().await().assertArrayEquals(true, message = "Turtle moved forward") } thenExecute { // Assert we're no longer waterlogged and we've left a source block. - helper.assertBlockIs(BlockPos(2, 2, 2)) { it.block == Blocks.WATER && it.fluidState.isSource } - helper.assertBlockHas(BlockPos(2, 2, 3), WaterloggableHelpers.WATERLOGGED, false) + helper.assertBlockIs(BlockPos(2, 1, 2)) { it.block == Blocks.WATER && it.fluidState.isSource } + helper.assertBlockHas(BlockPos(2, 1, 3), WaterloggableHelpers.WATERLOGGED, false) } } @@ -568,8 +568,8 @@ class Turtle_Test { fun Move_obstruct(helper: GameTestHelper) = helper.sequence { thenOnComputer { turtle.forward().await().assertArrayEquals(false, "Movement obstructed") } thenExecute { - helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 2, 2)) - helper.assertBlockPresent(Blocks.DIRT, BlockPos(2, 2, 3)) + helper.assertBlockPresent(ModRegistry.Blocks.TURTLE_NORMAL.get(), BlockPos(2, 1, 2)) + helper.assertBlockPresent(Blocks.DIRT, BlockPos(2, 1, 3)) } } @@ -578,7 +578,7 @@ class Turtle_Test { */ @GameTest fun Attack_entity(helper: GameTestHelper) = helper.sequence { - val turtlePos = BlockPos(2, 2, 2) + val turtlePos = BlockPos(2, 1, 2) thenOnComputer { turtle.attack(Optional.empty()).await().assertArrayEquals(true, message = "Attacked entity") } @@ -598,7 +598,7 @@ class Turtle_Test { @GameTest fun Attack_entity_destroy(helper: GameTestHelper) = helper.sequence { thenStartComputer { turtle.attack(Optional.empty()) } - thenWaitUntil { helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 2)) } + thenWaitUntil { helper.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 2)) } } /** @@ -663,12 +663,12 @@ class Turtle_Test { @GameTest fun Data_fixers(helper: GameTestHelper) = helper.sequence { thenExecute { - val overlay = helper.level.registryAccess().registryOrThrow(TurtleOverlay.REGISTRY) - .get(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "trans_flag"))!! - val upgrade = helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) - .get(ResourceLocation.withDefaultNamespace("diamond_pickaxe"))!! + val overlay = helper.level.registryAccess().lookupOrThrow(TurtleOverlay.REGISTRY) + .getValue(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "trans_flag"))!! + val upgrade = helper.level.registryAccess().lookupOrThrow(ITurtleUpgrade.REGISTRY) + .getValue(ResourceLocation.withDefaultNamespace("diamond_pickaxe"))!! - val turtleBe = helper.getBlockEntity(BlockPos(1, 2, 1), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) + val turtleBe = helper.getBlockEntity(BlockPos(1, 1, 1), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) assertEquals(overlay, turtleBe.overlay) assertEquals(upgrade, turtleBe.getUpgrade(TurtleSide.LEFT)) @@ -702,7 +702,7 @@ class Turtle_Test { callPeripheral("left", "craft", 1).assertArrayEquals(true) } thenExecute { - val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) + val turtle = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) assertThat( "Inventory is as expected.", turtle.items, @@ -725,10 +725,10 @@ class Turtle_Test { turtle.equipLeft().await().assertArrayEquals(true) } thenExecute { - val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) + val turtle = helper.getBlockEntity(BlockPos(2, 1, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()) assertEquals( - helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) - .get(ResourceLocation.withDefaultNamespace("diamond_pickaxe")), + helper.level.registryAccess().lookupOrThrow(ITurtleUpgrade.REGISTRY) + .getValue(ResourceLocation.withDefaultNamespace("diamond_pickaxe")), turtle.getUpgrade(TurtleSide.LEFT), ) } @@ -742,7 +742,7 @@ class Turtle_Test { @GameTest fun Breaks_exploding_block(context: GameTestHelper) = context.sequence { thenOnComputer { turtle.dig(Optional.empty()) } - thenWaitUntil { context.assertBlockPresent(Blocks.AIR, BlockPos(2, 2, 2)) } + thenWaitUntil { context.assertBlockPresent(Blocks.AIR, BlockPos(2, 1, 2)) } thenExecute { context.assertItemEntityCountIs(ModRegistry.Items.TURTLE_NORMAL.get(), 1) context.assertItemEntityCountIs(Items.BONE_BLOCK, 65) diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/TestExtensions.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/TestExtensions.kt index 43d046ff9..58e5d967d 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/TestExtensions.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/TestExtensions.kt @@ -264,7 +264,7 @@ fun GameTestHelper.assertExactlyItems(vararg expected: ItemStack, message: Strin fun GameTestHelper.assertItemEntityCountIs(expected: Item, count: Int) { val actualCount = getEntities(EntityType.ITEM).sumOf { if (it.item.`is`(expected)) it.item.count else 0 } if (actualCount != count) { - throw GameTestAssertException("Expected $count ${expected.description.string} items to exist (found $actualCount)") + throw GameTestAssertException("Expected $count ${ItemStack(expected).itemName.string} items to exist (found $actualCount)") } } diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt index d410a1b9c..32fc729db 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/core/ClientTestHooks.kt @@ -9,7 +9,6 @@ import dan200.computercraft.gametest.api.isRenderingStable import dan200.computercraft.gametest.api.setupForTest import net.minecraft.client.CloudStatus import net.minecraft.client.Minecraft -import net.minecraft.client.ParticleStatus import net.minecraft.client.gui.screens.AccessibilityOnboardingScreen import net.minecraft.client.gui.screens.Screen import net.minecraft.client.gui.screens.TitleScreen @@ -17,8 +16,10 @@ import net.minecraft.client.tutorial.TutorialSteps import net.minecraft.core.registries.Registries import net.minecraft.gametest.framework.* import net.minecraft.server.MinecraftServer +import net.minecraft.server.level.ParticleStatus import net.minecraft.sounds.SoundSource import net.minecraft.world.Difficulty +import net.minecraft.world.flag.FeatureFlagSet import net.minecraft.world.level.GameRules import net.minecraft.world.level.GameType import net.minecraft.world.level.LevelSettings @@ -84,7 +85,7 @@ object ClientTestHooks { minecraft.createWorldOpenFlows().openWorld(LEVEL_NAME) { minecraft.setScreen(screen) } } else { LOG.info("World does not exist, creating it.") - val rules = GameRules() + val rules = GameRules(FeatureFlagSet.of()) rules.getRule(GameRules.RULE_DOMOBSPAWNING).set(false, null) rules.getRule(GameRules.RULE_DAYLIGHT).set(false, null) rules.getRule(GameRules.RULE_WEATHER_CYCLE).set(false, null) @@ -93,7 +94,10 @@ object ClientTestHooks { LEVEL_NAME, LevelSettings("Test Level", GameType.CREATIVE, false, Difficulty.EASY, true, rules, WorldDataConfiguration.DEFAULT), WorldOptions(WorldOptions.randomSeed(), false, false), - { it.registryOrThrow(Registries.WORLD_PRESET).getOrThrow(WorldPresets.FLAT).createWorldDimensions() }, + { + it.lookupOrThrow(Registries.WORLD_PRESET).getOrThrow(WorldPresets.FLAT).value() + .createWorldDimensions() + }, screen, ) } diff --git a/projects/common/src/testMod/resources/computercraft-gametest.mixins.json b/projects/common/src/testMod/resources/computercraft-gametest.mixins.json index 803991da5..3f2053cb8 100644 --- a/projects/common/src/testMod/resources/computercraft-gametest.mixins.json +++ b/projects/common/src/testMod/resources/computercraft-gametest.mixins.json @@ -11,6 +11,8 @@ "GameTestInfoAccessor", "GameTestSequenceAccessor", "GameTestSequenceMixin", + "GameTestServerMixin", + "MinecraftServerAccessor", "StructureTemplateManagerMixin", "TestCommandAccessor" ], diff --git a/projects/fabric/build.gradle.kts b/projects/fabric/build.gradle.kts index 21ce836b3..0a328504e 100644 --- a/projects/fabric/build.gradle.kts +++ b/projects/fabric/build.gradle.kts @@ -20,6 +20,14 @@ cct { allProjects.forEach { externalSources(it) } } +sourceSets { + client { + java { + exclude("dan200/computercraft/client/integration/rei") + } + } +} + fun addRemappedConfiguration(name: String) { // There was a regression in Loom 1.1 which means that targetConfigurationName doesn't do anything, and remap // configurations just get added to the main source set (https://github.com/FabricMC/fabric-loom/issues/843). diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java index 224ac9bc5..2774d27ad 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java @@ -55,7 +55,6 @@ public class ComputerCraftClient { PreparableModelLoadingPlugin.register(CustomModelLoader::prepare, (state, context) -> { ClientRegistry.registerExtraModels(context::addModels, state.getExtraModels()); context.resolveModel().register(ctx -> state.loadModel(ctx.id())); - context.modifyModelAfterBake().register((model, ctx) -> model == null ? null : state.wrapModel(ctx, model)); }); BlockRenderLayerMap.INSTANCE.putBlock(ModRegistry.Blocks.COMPUTER_NORMAL.get(), RenderType.cutout()); diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/model/CustomModelLoader.java b/projects/fabric/src/client/java/dan200/computercraft/client/model/CustomModelLoader.java index 7addcdced..62dea29d7 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/model/CustomModelLoader.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/model/CustomModelLoader.java @@ -8,11 +8,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.client.model.turtle.UnbakedTurtleModel; -import dan200.computercraft.mixin.client.BlockModelAccessor; -import net.fabricmc.fabric.api.client.model.loading.v1.ModelModifier; import net.fabricmc.fabric.api.client.model.loading.v1.PreparableModelLoadingPlugin; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.resources.FileToIdConverter; import net.minecraft.resources.ResourceLocation; @@ -36,9 +32,8 @@ import java.util.concurrent.Executor; *

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

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

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

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

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