From 2c0d8263d375d575b993243e5679e01e20770c23 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Tue, 7 May 2024 22:58:25 +0100 Subject: [PATCH] Update to MC 1.20.6 - Update EMI and REI integration, and fix some issues with the upgrade crafting hooks. - Just use smooth stone for recipes, not #c:stone. We're mirroring redstone's crafting recipes here. - Some cleanup to printouts. - Remote upgrade data generators - these can be replaced with the standard registry data generators. - Remove the API's PlatformHelper - we no longer have any platform-specific code in the API. --- .../main/kotlin/cc-tweaked.forge.gradle.kts | 5 - .../cc-tweaked.java-convention.gradle.kts | 1 - gradle.properties | 2 +- gradle/libs.versions.toml | 16 +- projects/common-api/build.gradle.kts | 12 ++ .../api/pocket/IPocketUpgrade.java | 22 +-- .../api/pocket/PocketUpgradeDataProvider.java | 30 ---- .../api/turtle/ITurtleUpgrade.java | 42 +++-- .../api/turtle/TurtleToolBuilder.java | 157 ++++++++++++++++++ .../api/turtle/TurtleToolDurability.java | 2 +- .../api/turtle/TurtleUpgradeDataProvider.java | 151 ----------------- .../api/upgrades/UpgradeDataProvider.java | 154 ----------------- .../api/upgrades/UpgradeType.java | 34 +++- .../computercraft/impl/PlatformHelper.java | 54 ------ .../integration/emi/EMIComputerCraft.java | 7 + .../client/turtle/TurtleUpgradeModellers.java | 25 +-- .../data/computercraft/recipes/cable.json | 2 +- .../recipes/computer_normal.json | 2 +- .../computercraft/recipes/disk_drive.json | 2 +- .../computercraft/recipes/monitor_normal.json | 2 +- .../recipes/pocket_computer_normal.json | 6 +- .../data/computercraft/recipes/printer.json | 2 +- .../data/computercraft/recipes/speaker.json | 6 +- .../computercraft/recipes/wired_modem.json | 2 +- .../computercraft/data/DataProviders.java | 43 +++-- .../computercraft/data/LanguageProvider.java | 34 ++-- .../computercraft/data/ModelProvider.java | 2 +- .../data/PocketUpgradeProvider.java | 25 +-- .../computercraft/data/RecipeProvider.java | 68 ++++---- .../computercraft/data/TagProvider.java | 2 +- .../data/TurtleUpgradeProvider.java | 45 +++-- .../computercraft/impl/PocketUpgrades.java | 3 +- .../computercraft/impl/TurtleUpgrades.java | 3 +- .../computercraft/shared/ModRegistry.java | 10 +- .../command/arguments/ArgumentUtils.java | 2 +- .../shared/details/DetailHelpers.java | 2 +- .../shared/integration/RecipeModHelpers.java | 6 +- .../integration/UpgradeRecipeGenerator.java | 8 +- .../shared/media/items/PrintoutData.java | 6 + .../shared/media/items/PrintoutItem.java | 12 +- .../shared/media/recipes/PrintoutRecipe.java | 4 +- .../modem/wired/CableBlockItem.java | 2 +- .../printer/PrinterBlockEntity.java | 4 +- .../shared/platform/PlatformHelper.java | 44 ++--- .../shared/platform/RecipeIngredients.java | 2 - .../shared/recipe/BasicRecipeSerialiser.java | 2 +- .../shared/util}/RegistryHelper.java | 8 +- .../shared/util/SafeDispatchCodec.java | 1 - .../core/computercraft/monitor_tbo.json | 1 - .../computercraft/TestPlatformHelper.java | 18 +- .../dan200/computercraft/export/Exporter.java | 2 +- .../dan200/computercraft/export/JsonDump.java | 2 +- .../computercraft/gametest/Turtle_Test.kt | 6 +- .../gametest/api/ClientTestExtensions.kt | 2 +- .../gametest/api/TestExtensions.kt | 2 +- .../integration/rei/REIComputerCraft.java | 24 ++- .../rei/UpgradeDisplayGenerator.java | 3 +- .../recipes/wireless_modem_normal.json | 2 +- .../data/FabricDataGenerators.java | 93 +++-------- .../computercraft/shared/ComputerCraft.java | 6 +- .../shared/platform/PlatformHelperImpl.java | 31 +--- .../fabric/src/main/resources/fabric.mod.json | 2 +- projects/forge-api/build.gradle.kts | 5 + projects/forge/build.gradle.kts | 4 +- .../computercraft/recipes/printed_book.json | 2 +- .../recipes/wireless_modem_normal.json | 2 +- .../dan200/computercraft/ComputerCraft.java | 4 +- .../dan200/computercraft/data/Generators.java | 13 +- .../shared/platform/PlatformHelperImpl.java | 33 +--- .../resources/META-INF/neoforge.mods.toml | 2 +- 70 files changed, 513 insertions(+), 822 deletions(-) delete mode 100644 projects/common-api/src/main/java/dan200/computercraft/api/pocket/PocketUpgradeDataProvider.java create mode 100644 projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleToolBuilder.java delete mode 100644 projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeDataProvider.java delete mode 100644 projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeDataProvider.java delete mode 100644 projects/common-api/src/main/java/dan200/computercraft/impl/PlatformHelper.java rename projects/{common-api/src/main/java/dan200/computercraft/impl => common/src/main/java/dan200/computercraft/shared/util}/RegistryHelper.java (75%) diff --git a/buildSrc/src/main/kotlin/cc-tweaked.forge.gradle.kts b/buildSrc/src/main/kotlin/cc-tweaked.forge.gradle.kts index 84979f2df..faeb4ba1f 100644 --- a/buildSrc/src/main/kotlin/cc-tweaked.forge.gradle.kts +++ b/buildSrc/src/main/kotlin/cc-tweaked.forge.gradle.kts @@ -30,11 +30,6 @@ subsystems { } } -dependencies { - val libs = project.extensions.getByType().named("libs") - implementation("net.neoforged:neoforge:${libs.findVersion("neoForge").get()}") -} - MinecraftConfigurations.setup(project) extensions.configure(CCTweakedExtension::class.java) { diff --git a/buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts b/buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts index e6a5ce9ae..9f0fab660 100644 --- a/buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts +++ b/buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts @@ -56,7 +56,6 @@ repositories { includeGroup("mezz.jei") includeGroup("org.teavm") includeModule("com.terraformersmc", "modmenu") - includeModule("me.lucko", "fabric-permissions-api") } } } diff --git a/gradle.properties b/gradle.properties index 59593d1cb..4d7496e21 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,4 +13,4 @@ isUnstable=true modVersion=1.110.3 # Minecraft properties: We want to configure this here so we can read it in settings.gradle -mcVersion=1.20.5 +mcVersion=1.20.6 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c7387b4b2..eb9776515 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.97.6+1.20.5" +fabric-api = "0.98.0+1.20.6" fabric-loader = "0.15.10" -neoForge = "20.5.20-beta" +neoForge = "20.6.48-beta" neoForgeSpi = "8.0.1" mixin = "0.8.5" -parchment = "2024.04.14" -parchmentMc = "1.20.4" -yarn = "1.20.5+build.1" +parchment = "2024.05.01" +parchmentMc = "1.20.6" +yarn = "1.20.6+build.1" # Core dependencies (these versions are tied to the version Minecraft uses) fastutil = "8.5.12" @@ -36,14 +36,14 @@ kotlin-coroutines = "1.7.3" nightConfig = "3.6.7" # Minecraft mods -emi = "1.0.30+1.20.4" -fabricPermissions = "0.3.20230723" +emi = "1.1.5+1.20.6" +fabricPermissions = "0.3.1" iris = "1.6.14+1.20.4" jei = "17.3.0.48" modmenu = "9.0.0" moreRed = "4.0.0.4" oculus = "1.2.5" -rei = "14.0.688" +rei = "15.0.728" rubidium = "0.6.1" sodium = "mc1.20-0.4.10" mixinExtra = "0.3.5" diff --git a/projects/common-api/build.gradle.kts b/projects/common-api/build.gradle.kts index 3bdc0d282..6ce14aff7 100644 --- a/projects/common-api/build.gradle.kts +++ b/projects/common-api/build.gradle.kts @@ -21,4 +21,16 @@ tasks.javadoc { // Include the core-api in our javadoc export. This is wrong, but it means we can export a single javadoc dump. source(project(":core-api").sourceSets.main.map { it.allJava }) + + options { + this as StandardJavadocDocletOptions + addBooleanOption("-allow-script-in-comments", true) + bottom( + """ + + + + """.trimIndent(), + ) + } } diff --git a/projects/common-api/src/main/java/dan200/computercraft/api/pocket/IPocketUpgrade.java b/projects/common-api/src/main/java/dan200/computercraft/api/pocket/IPocketUpgrade.java index fe26f320d..7cfe90407 100644 --- a/projects/common-api/src/main/java/dan200/computercraft/api/pocket/IPocketUpgrade.java +++ b/projects/common-api/src/main/java/dan200/computercraft/api/pocket/IPocketUpgrade.java @@ -4,12 +4,14 @@ package dan200.computercraft.api.pocket; +import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.upgrades.UpgradeBase; import dan200.computercraft.api.upgrades.UpgradeType; import dan200.computercraft.impl.ComputerCraftAPIService; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import javax.annotation.Nullable; @@ -21,11 +23,11 @@ import javax.annotation.Nullable; * {@link UpgradeType} instance, which are then registered in a registry. *

* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and - * the upgrade automatically registered. It is recommended this is done via {@linkplain PocketUpgradeDataProvider data - * generators}. + * the upgrade automatically registered. It is recommended this is done via + * data generators. * *

Example

- *
{@code
+ * {@snippet lang="java" :
  * // We use Forge's DeferredRegister to register our upgrade type. Fabric mods may register their type directly.
  * static final DeferredRegister> POCKET_UPGRADES = DeferredRegister.create(IPocketUpgrade.typeRegistry(), "my_mod");
  *
@@ -35,19 +37,19 @@ import javax.annotation.Nullable;
  *
  * // Then in your constructor
  * POCKET_UPGRADES.register(bus);
- * }
+ * } *

* We can then define a new upgrade using JSON by placing the following in - * {@code data//computercraft/pocket_upgrades/.json}. - *

{@code
+ * {@code data//computercraft/pocket_upgrade/.json}.
+ * {@snippet lang="json" :
  * {
- *     "type": my_mod:my_upgrade",
+ *     "type": "my_mod:my_upgrade"
+ * }
  * }
- * }
- *

- * {@link PocketUpgradeDataProvider} provides a data provider to aid with generating these JSON files. */ public interface IPocketUpgrade extends UpgradeBase { + ResourceKey> REGISTRY = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_upgrade")); + /** * The registry key for pocket upgrade types. * diff --git a/projects/common-api/src/main/java/dan200/computercraft/api/pocket/PocketUpgradeDataProvider.java b/projects/common-api/src/main/java/dan200/computercraft/api/pocket/PocketUpgradeDataProvider.java deleted file mode 100644 index e9685fb8e..000000000 --- a/projects/common-api/src/main/java/dan200/computercraft/api/pocket/PocketUpgradeDataProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.api.pocket; - -import dan200.computercraft.api.upgrades.UpgradeDataProvider; -import dan200.computercraft.api.upgrades.UpgradeType; -import dan200.computercraft.impl.ComputerCraftAPIService; -import dan200.computercraft.impl.RegistryHelper; -import net.minecraft.data.DataGenerator; -import net.minecraft.data.PackOutput; - -import java.util.function.Consumer; - -/** - * A data provider to generate pocket computer upgrades. - *

- * This should be subclassed and registered to a {@link DataGenerator.PackGenerator}. Override the - * {@link #addUpgrades(Consumer)} function, construct each upgrade, and pass them off to the provided consumer to - * generate them. - * - * @see IPocketUpgrade - * @see UpgradeType - */ -public abstract class PocketUpgradeDataProvider extends UpgradeDataProvider { - public PocketUpgradeDataProvider(PackOutput output) { - super(output, "Pocket Computer Upgrades", RegistryHelper.POCKET_UPGRADE, ComputerCraftAPIService.get().pocketUpgradeCodec()); - } -} diff --git a/projects/common-api/src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java b/projects/common-api/src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java index 08c54ca29..b5b138343 100644 --- a/projects/common-api/src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java +++ b/projects/common-api/src/main/java/dan200/computercraft/api/turtle/ITurtleUpgrade.java @@ -4,6 +4,7 @@ package dan200.computercraft.api.turtle; +import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.upgrades.UpgradeBase; import dan200.computercraft.api.upgrades.UpgradeType; @@ -12,6 +13,7 @@ import net.minecraft.core.Direction; import net.minecraft.core.Registry; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; @@ -23,11 +25,11 @@ import javax.annotation.Nullable; * {@link UpgradeType} instance, which are then registered in a registry. *

* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and - * the upgrade automatically registered. It is recommended this is done via {@linkplain TurtleUpgradeDataProvider data - * generators}. + * the upgrade automatically registered. It is recommended this is done via + * data generators. * *

Example

- *
{@code
+ * {@snippet lang="java" :
  * // We use Forge's DeferredRegister to register our upgrade type. Fabric mods may register their type directly.
  * static final DeferredRegister> TURTLE_UPGRADES = DeferredRegister.create(ITurtleUpgrade.typeRegistry(), "my_mod");
  *
@@ -37,28 +39,38 @@ import javax.annotation.Nullable;
  *
  * // Then in your constructor
  * TURTLE_UPGRADES.register(bus);
- * }
+ * } *

* We can then define a new upgrade using JSON by placing the following in - * {@literal data//computercraft/turtle_upgrades/.json}}. - * - *

{@code
+ * {@code data//computercraft/turtle_upgrade/.json}.
+ * 

+ * {@snippet lang="json" : * { * "type": "my_mod:my_upgrade" * } - * }

- *

- * {@link TurtleUpgradeDataProvider} provides a data provider to aid with generating these JSON files. + * } *

* Finally, we need to register a model for our upgrade, see * {@link dan200.computercraft.api.client.turtle.TurtleUpgradeModeller} for more information. - * - *

{@code
- * // Register our model inside FMLClientSetupEvent
- * ComputerCraftAPIClient.registerTurtleUpgradeModeller(MY_UPGRADE.get(), TurtleUpgradeModeller.flatItem())
- * }
*/ public interface ITurtleUpgrade extends UpgradeBase { + /** + * The registry in which turtle upgrades are stored. + */ + ResourceKey> REGISTRY = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_upgrade")); + + /** + * Create a {@link ResourceKey} for a turtle upgrade given a {@link ResourceLocation}. + *

+ * This should only be called from within data generation code. Do not hard code references to your upgrades! + * + * @param id The id of the turtle upgrade. + * @return The upgrade registry key. + */ + static ResourceKey createKey(ResourceLocation id) { + return ResourceKey.create(REGISTRY, id); + } + /** * The registry key for turtle upgrade types. * diff --git a/projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleToolBuilder.java b/projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleToolBuilder.java new file mode 100644 index 000000000..735718bf1 --- /dev/null +++ b/projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleToolBuilder.java @@ -0,0 +1,157 @@ +// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.api.turtle; + +import dan200.computercraft.api.ComputerCraftTags; +import dan200.computercraft.api.upgrades.UpgradeBase; +import dan200.computercraft.impl.ComputerCraftAPIService; +import dan200.computercraft.impl.upgrades.TurtleToolSpec; +import net.minecraft.core.component.DataComponents; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; + +import javax.annotation.Nullable; +import java.util.Optional; + +/** + * A builder for custom turtle tool upgrades. + *

+ * This can be used from your data generator code in order to + * register turtle tools for your mod's tools. + * + *

Example:

+ * {@snippet lang = "java": + * import net.minecraft.data.worldgen.BootstrapContext; + * import net.minecraft.resources.ResourceLocation; + * import net.minecraft.world.item.Items; + * + * public void registerTool(BootstrapContext upgrades) { + * TurtleToolBuilder.tool(new ResourceLocation("my_mod", "wooden_pickaxe"), Items.WOODEN_PICKAXE).register(upgrades); + * } + *} + */ +public final class TurtleToolBuilder { + private final ResourceKey id; + private final Item item; + private Component adjective; + private float damageMultiplier = TurtleToolSpec.DEFAULT_DAMAGE_MULTIPLIER; + private @Nullable TagKey breakable; + private boolean allowEnchantments = false; + private TurtleToolDurability consumeDurability = TurtleToolDurability.NEVER; + + private TurtleToolBuilder(ResourceKey id, Item item) { + this.id = id; + adjective = Component.translatable(UpgradeBase.getDefaultAdjective(id.location())); + this.item = item; + } + + public static TurtleToolBuilder tool(ResourceLocation id, Item item) { + return new TurtleToolBuilder(ITurtleUpgrade.createKey(id), item); + } + + public static TurtleToolBuilder tool(ResourceKey id, Item item) { + return new TurtleToolBuilder(id, item); + } + + /** + * Get the id for this turtle tool. + * + * @return The upgrade id. + */ + public ResourceKey id() { + return id; + } + + /** + * Specify a custom adjective for this tool. By default this takes its adjective from the upgrade id. + * + * @param adjective The new adjective to use. + * @return The tool builder, for further use. + */ + public TurtleToolBuilder adjective(Component adjective) { + this.adjective = adjective; + return this; + } + + /** + * The amount of damage a swing of this tool will do. This is multiplied by {@link Attributes#ATTACK_DAMAGE} to + * get the final damage. + * + * @param damageMultiplier The damage multiplier. + * @return The tool builder, for further use. + */ + public TurtleToolBuilder damageMultiplier(float damageMultiplier) { + this.damageMultiplier = damageMultiplier; + return this; + } + + /** + * Indicate that this upgrade allows items which have been {@linkplain ItemStack#isEnchanted() enchanted} or have + * {@linkplain DataComponents#ATTRIBUTE_MODIFIERS custom attribute modifiers}. + * + * @return The tool builder, for further use. + */ + public TurtleToolBuilder allowEnchantments() { + allowEnchantments = true; + return this; + } + + /** + * Set when the tool will consume durability. + * + * @param durability The durability predicate. + * @return The tool builder, for further use. + */ + public TurtleToolBuilder consumeDurability(TurtleToolDurability durability) { + consumeDurability = durability; + return this; + } + + /** + * Provide a list of breakable blocks. If not given, the tool can break all blocks. If given, only blocks + * in this tag, those in {@link ComputerCraftTags.Blocks#TURTLE_ALWAYS_BREAKABLE} and "insta-mine" ones can + * be broken. + * + * @param breakable The tag containing all blocks breakable by this item. + * @return The tool builder, for further use. + * @see ComputerCraftTags.Blocks + */ + public TurtleToolBuilder breakable(TagKey breakable) { + this.breakable = breakable; + return this; + } + + /** + * Build the turtle tool upgrade. + * + * @return The constructed upgrade. + */ + public ITurtleUpgrade build() { + return ComputerCraftAPIService.get().createTurtleTool(new TurtleToolSpec( + adjective, + item, + damageMultiplier, + allowEnchantments, + consumeDurability, + Optional.ofNullable(breakable) + )); + } + + /** + * Build this upgrade and register it for datagen. + * + * @param upgrades The registry this upgrade should be added to. + */ + public void register(BootstrapContext upgrades) { + upgrades.register(id(), build()); + } +} diff --git a/projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleToolDurability.java b/projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleToolDurability.java index 543f98731..554fb5237 100644 --- a/projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleToolDurability.java +++ b/projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleToolDurability.java @@ -11,7 +11,7 @@ import net.minecraft.world.item.ItemStack; /** * Indicates if an equipped turtle item will consume durability. * - * @see TurtleUpgradeDataProvider.ToolBuilder#consumeDurability(TurtleToolDurability) + * @see TurtleToolBuilder#consumeDurability(TurtleToolDurability) */ public enum TurtleToolDurability implements StringRepresentable { /** diff --git a/projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeDataProvider.java b/projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeDataProvider.java deleted file mode 100644 index 96c648087..000000000 --- a/projects/common-api/src/main/java/dan200/computercraft/api/turtle/TurtleUpgradeDataProvider.java +++ /dev/null @@ -1,151 +0,0 @@ -// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.api.turtle; - -import dan200.computercraft.api.ComputerCraftTags; -import dan200.computercraft.api.upgrades.UpgradeBase; -import dan200.computercraft.api.upgrades.UpgradeDataProvider; -import dan200.computercraft.impl.ComputerCraftAPIService; -import dan200.computercraft.impl.RegistryHelper; -import dan200.computercraft.impl.upgrades.TurtleToolSpec; -import net.minecraft.core.component.DataComponents; -import net.minecraft.data.DataGenerator; -import net.minecraft.data.PackOutput; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; - -import javax.annotation.Nullable; -import java.util.Optional; -import java.util.function.Consumer; - -/** - * A data provider to generate turtle upgrades. - *

- * This should be subclassed and registered to a {@link DataGenerator.PackGenerator}. Override the - * {@link #addUpgrades(Consumer)} function, construct each upgrade, and pass them off to the provided consumer to - * generate them. - * - * @see ITurtleUpgrade - */ -public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider { - public TurtleUpgradeDataProvider(PackOutput output) { - super(output, "Turtle Upgrades", RegistryHelper.TURTLE_UPGRADE, ComputerCraftAPIService.get().turtleUpgradeCodec()); - } - - /** - * Create a new turtle tool upgrade, such as a pickaxe or shovel. - * - * @param id The ID of this tool. - * @param item The item used for tool actions. Note, this doesn't inherit all properties of the tool, you may need - * to specify {@link ToolBuilder#damageMultiplier(float)} and {@link ToolBuilder#breakable(TagKey)}. - * @return A tool builder, - */ - public final ToolBuilder tool(ResourceLocation id, Item item) { - return new ToolBuilder(id, item); - } - - /** - * A builder for custom turtle tool upgrades. - * - * @see #tool(ResourceLocation, Item) - */ - public final class ToolBuilder { - private final ResourceLocation id; - private final Item item; - private Component adjective; - private @Nullable Item craftingItem; - private float damageMultiplier = TurtleToolSpec.DEFAULT_DAMAGE_MULTIPLIER; - private @Nullable TagKey breakable; - private boolean allowEnchantments = false; - private TurtleToolDurability consumeDurability = TurtleToolDurability.NEVER; - - ToolBuilder(ResourceLocation id, Item item) { - this.id = id; - adjective = Component.translatable(UpgradeBase.getDefaultAdjective(id)); - this.item = item; - craftingItem = null; - } - - /** - * Specify a custom adjective for this tool. By default this takes its adjective from the upgrade id. - * - * @param adjective The new adjective to use. - * @return The tool builder, for further use. - */ - public ToolBuilder adjective(Component adjective) { - this.adjective = adjective; - return this; - } - - /** - * The amount of damage a swing of this tool will do. This is multiplied by {@link Attributes#ATTACK_DAMAGE} to - * get the final damage. - * - * @param damageMultiplier The damage multiplier. - * @return The tool builder, for further use. - */ - public ToolBuilder damageMultiplier(float damageMultiplier) { - this.damageMultiplier = damageMultiplier; - return this; - } - - /** - * Indicate that this upgrade allows items which have been {@linkplain ItemStack#isEnchanted() enchanted} or have - * {@linkplain DataComponents#ATTRIBUTE_MODIFIERS custom attribute modifiers}. - * - * @return The tool builder, for further use. - */ - public ToolBuilder allowEnchantments() { - allowEnchantments = true; - return this; - } - - /** - * Set when the tool will consume durability. - * - * @param durability The durability predicate. - * @return The tool builder, for further use. - */ - public ToolBuilder consumeDurability(TurtleToolDurability durability) { - consumeDurability = durability; - return this; - } - - /** - * Provide a list of breakable blocks. If not given, the tool can break all blocks. If given, only blocks - * in this tag, those in {@link ComputerCraftTags.Blocks#TURTLE_ALWAYS_BREAKABLE} and "insta-mine" ones can - * be broken. - * - * @param breakable The tag containing all blocks breakable by this item. - * @return The tool builder, for further use. - * @see ComputerCraftTags.Blocks - */ - public ToolBuilder breakable(TagKey breakable) { - this.breakable = breakable; - return this; - } - - /** - * Register this as an upgrade. - * - * @param add The callback given to {@link #addUpgrades(Consumer)}. - */ - public void add(Consumer> add) { - upgrade(id, ComputerCraftAPIService.get().createTurtleTool(new TurtleToolSpec( - adjective, - item, - damageMultiplier, - allowEnchantments, - consumeDurability, - Optional.ofNullable(breakable) - ))).add(add); - } - } -} diff --git a/projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeDataProvider.java b/projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeDataProvider.java deleted file mode 100644 index 685d5e0e8..000000000 --- a/projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeDataProvider.java +++ /dev/null @@ -1,154 +0,0 @@ -// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.api.upgrades; - -import com.google.gson.JsonObject; -import com.mojang.serialization.Codec; -import com.mojang.serialization.JsonOps; -import dan200.computercraft.impl.PlatformHelper; -import net.minecraft.Util; -import net.minecraft.core.Registry; -import net.minecraft.data.CachedOutput; -import net.minecraft.data.DataProvider; -import net.minecraft.data.PackOutput; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; - -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; - -/** - * A data generator/provider for turtle and pocket computer upgrades. This should not be extended directly, instead see - * the other subclasses. - * - * @param The base class of upgrades. - */ -public abstract class UpgradeDataProvider implements DataProvider { - private final PackOutput output; - private final String name; - private final ResourceKey> registryName; - private final Codec codec; - - private @Nullable Map, T> upgrades; - - @ApiStatus.Internal - protected UpgradeDataProvider(PackOutput output, String name, ResourceKey> registryName, Codec codec) { - this.output = output; - this.name = name; - this.registryName = registryName; - this.codec = codec; - } - - /** - * Add a new upgrade. - * - * @param id The ID of the upgrade to create. - * @param upgrade The upgrade to add. - * @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer. - */ - protected final Upgrade upgrade(ResourceLocation id, T upgrade) { - return new Upgrade<>(id, upgrade, j -> { - }); - } - - /** - * Add all turtle or pocket computer upgrades. - *

- * Example usage: - *

{@code
-     * protected void addUpgrades(Consumer> addUpgrade) {
-     *     upgrade(new ResourceLocation("mymod", "speaker"), new TurtleSpeaker(new ItemStack(Items.NOTE_BLOCK))).add(addUpgrade);
-     * }
-     * }
- * - * @param addUpgrade A callback used to register an upgrade. - */ - protected abstract void addUpgrades(Consumer> addUpgrade); - - @Override - public CompletableFuture run(CachedOutput cache) { - var base = output.createPathProvider(PackOutput.Target.DATA_PACK, registryName.location().getNamespace() + "/" + registryName.location().getPath()); - - Map, T> upgrades = new LinkedHashMap<>(); - - List> futures = new ArrayList<>(); - addUpgrades(upgrade -> { - var id = ResourceKey.create(registryName, upgrade.id); - if (upgrades.containsKey(id)) throw new IllegalStateException("Duplicate upgrade " + upgrade.id); - - var json = (JsonObject) codec.encodeStart(JsonOps.INSTANCE, upgrade.upgrade).getOrThrow(); - upgrade.serialise.accept(json); - - futures.add(DataProvider.saveStable(cache, json, base.json(upgrade.id))); - - upgrades.put(id, upgrade.upgrade); - }); - - this.upgrades = Collections.unmodifiableMap(upgrades); - - return Util.sequenceFailFast(futures); - } - - @Override - public final String getName() { - return name; - } - - /** - * Get all registered upgrades. - * - * @return The map of registered upgrades. - */ - public Map, T> getGeneratedUpgrades() { - var upgrades = this.upgrades; - if (upgrades == null) throw new IllegalStateException("Upgrades are not available yet"); - return upgrades; - } - - /** - * A constructed upgrade instance, produced {@link #addUpgrades(Consumer)}. - * - * @param The type of upgrade. - */ - public static final class Upgrade { - private final ResourceLocation id; - private final T upgrade; - private final Consumer serialise; - - private Upgrade(ResourceLocation id, T upgrade, Consumer serialise) { - this.id = id; - this.upgrade = upgrade; - this.serialise = serialise; - } - - /** - * Convenience method for registering an upgrade. - * - * @param add The callback given to {@link #addUpgrades(Consumer)} - */ - public void add(Consumer> add) { - add.accept(this); - } - - /** - * Return a new {@link Upgrade} which requires the given mod to be present. - *

- * This uses mod-loader-specific hooks (Forge's crafting conditions and Fabric's resource conditions). If using - * this in a multi-loader setup, you must generate resources separately for the two loaders. - * - * @param modId The id of the mod. - * @return A new upgrade instance. - */ - public Upgrade requireMod(String modId) { - return new Upgrade<>(id, upgrade, json -> { - PlatformHelper.get().addRequiredModCondition(json, modId); - serialise.accept(json); - }); - } - } -} diff --git a/projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeType.java b/projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeType.java index 561255690..0d6781e4b 100644 --- a/projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeType.java +++ b/projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeType.java @@ -6,11 +6,10 @@ package dan200.computercraft.api.upgrades; import com.mojang.serialization.MapCodec; import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.api.pocket.PocketUpgradeDataProvider; import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider; import dan200.computercraft.impl.upgrades.UpgradeTypeImpl; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.data.registries.RegistryPatchGenerator; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.level.storage.loot.functions.LootItemFunction; @@ -33,8 +32,35 @@ import java.util.function.Function; * {@link IPocketUpgrade#typeRegistry()}). *

* In order to register the actual upgrade, a JSON file referencing your upgrade type should be added to a datapack. It - * is recommended to do this via the data generators (see {@link TurtleUpgradeDataProvider} and - * {@link PocketUpgradeDataProvider}). + * is recommended to do this via the data generators. + * + *

Data Generation

+ * As turtle and pocket upgrades are just loaded using vanilla's dynamic loaders, one may use the same data generation + * tools as you would for any other dynamic registry. + *

+ * This can typically be done by extending vanilla's built-in registries using {@link RegistryPatchGenerator}, and then + * writing out the new registries using {@code net.fabricmc.fabric.api.datagen.v1.provider.FabricDynamicRegistryProvider} + * on Fabric or {@code net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider} on Forge. + *

+ * {@snippet lang="java" : + * import dan200.computercraft.api.turtle.ITurtleUpgrade; + * import net.minecraft.Util; + * import net.minecraft.core.HolderLookup; + * import net.minecraft.core.RegistrySetBuilder; + * import net.minecraft.data.DataGenerator; + * import net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider; + * + * import java.util.concurrent.CompletableFuture; + * + * public void generate(DataGenerator.PackGenerator output, CompletableFuture registries) { + * var newRegistries = RegistryPatchGenerator.createLookup(registries, Util.make(new RegistrySetBuilder(), builder -> { + * builder.add(ITurtleUpgrade.REGISTRY, upgrades -> { + * upgrades.register(ITurtleUpgrade.createKey(new ResourceLocation("my_mod", "my_upgrade")), new MyUpgrade()); + * }); + * })); + * output.addProvider(o -> new DatapackBuiltinEntriesProvider(o, newRegistries, Set.of("my_mod"))); + * } + * } * * @param The upgrade subclass that this upgrade type represents. * @see ITurtleUpgrade diff --git a/projects/common-api/src/main/java/dan200/computercraft/impl/PlatformHelper.java b/projects/common-api/src/main/java/dan200/computercraft/impl/PlatformHelper.java deleted file mode 100644 index 675008a56..000000000 --- a/projects/common-api/src/main/java/dan200/computercraft/impl/PlatformHelper.java +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.impl; - -import com.google.gson.JsonObject; -import dan200.computercraft.api.upgrades.UpgradeDataProvider; -import org.jetbrains.annotations.ApiStatus; - -import javax.annotation.Nullable; - -/** - * Abstraction layer for Forge and Fabric. See implementations for more details. - *

- * Do NOT directly reference this class. It exists for internal use by the API. - */ -@ApiStatus.Internal -public interface PlatformHelper { - /** - * Get the current {@link PlatformHelper} instance. - * - * @return The current instance. - */ - static PlatformHelper get() { - var instance = Instance.INSTANCE; - return instance == null ? Services.raise(PlatformHelper.class, Instance.ERROR) : instance; - } - - /** - * Add a resource condition which requires a mod to be loaded. This should be used by data providers such as - * {@link UpgradeDataProvider}. - * - * @param object The JSON object we're generating. - * @param modId The mod ID that we require. - */ - void addRequiredModCondition(JsonObject object, String modId); - - final class Instance { - static final @Nullable PlatformHelper INSTANCE; - static final @Nullable Throwable ERROR; - - static { - // We don't want class initialisation to fail here (as that results in confusing errors). Instead, capture - // the error and rethrow it when accessing. This should be JITted away in the common case. - var helper = Services.tryLoad(PlatformHelper.class); - INSTANCE = helper.instance(); - ERROR = helper.error(); - } - - private Instance() { - } - } -} diff --git a/projects/common/src/client/java/dan200/computercraft/client/integration/emi/EMIComputerCraft.java b/projects/common/src/client/java/dan200/computercraft/client/integration/emi/EMIComputerCraft.java index f6e19ebef..e96729f86 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/integration/emi/EMIComputerCraft.java +++ b/projects/common/src/client/java/dan200/computercraft/client/integration/emi/EMIComputerCraft.java @@ -6,12 +6,15 @@ package dan200.computercraft.client.integration.emi; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.ModRegistry; +import dan200.computercraft.shared.integration.RecipeModHelpers; import dan200.computercraft.shared.pocket.items.PocketComputerItem; import dan200.computercraft.shared.turtle.items.TurtleItem; import dev.emi.emi.api.EmiEntrypoint; import dev.emi.emi.api.EmiPlugin; import dev.emi.emi.api.EmiRegistry; import dev.emi.emi.api.stack.Comparison; +import dev.emi.emi.api.stack.EmiStack; +import net.minecraft.client.Minecraft; import net.minecraft.world.item.ItemStack; import java.util.function.BiPredicate; @@ -25,6 +28,10 @@ public class EMIComputerCraft implements EmiPlugin { registry.setDefaultComparison(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get(), pocketComparison); registry.setDefaultComparison(ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get(), pocketComparison); + + for (var stack : RecipeModHelpers.getExtraStacks(Minecraft.getInstance().level.registryAccess())) { + registry.addEmiStack(EmiStack.of(stack)); + } } private static final Comparison turtleComparison = compareStacks((left, right) diff --git a/projects/common/src/client/java/dan200/computercraft/client/turtle/TurtleUpgradeModellers.java b/projects/common/src/client/java/dan200/computercraft/client/turtle/TurtleUpgradeModellers.java index e15fc2bca..ec5fa842f 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/turtle/TurtleUpgradeModellers.java +++ b/projects/common/src/client/java/dan200/computercraft/client/turtle/TurtleUpgradeModellers.java @@ -11,14 +11,12 @@ import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.api.upgrades.UpgradeType; -import dan200.computercraft.impl.RegistryHelper; -import dan200.computercraft.impl.UpgradeManager; +import dan200.computercraft.shared.util.RegistryHelper; import net.minecraft.client.Minecraft; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.resources.ResourceLocation; import java.util.Map; -import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; @@ -32,14 +30,6 @@ public final class TurtleUpgradeModellers { private static final Map, TurtleUpgradeModeller> turtleModels = new ConcurrentHashMap<>(); private static volatile boolean fetchedModels; - /** - * In order to avoid a double lookup of {@link ITurtleUpgrade} to {@link UpgradeManager.UpgradeWrapper} to - * {@link TurtleUpgradeModeller}, we maintain a cache here. - *

- * Turtle upgrades may be removed as part of datapack reloads, so we use a weak map to avoid the memory leak. - */ - private static final WeakHashMap> modelCache = new WeakHashMap<>(); - private TurtleUpgradeModellers() { } @@ -57,20 +47,17 @@ public final class TurtleUpgradeModellers { } public static TransformedModel getModel(ITurtleUpgrade upgrade, ITurtleAccess access, TurtleSide side) { - @SuppressWarnings("unchecked") - var modeller = (TurtleUpgradeModeller) modelCache.computeIfAbsent(upgrade, TurtleUpgradeModellers::getModeller); - return modeller.getModel(upgrade, access, side, access.getUpgradeData(side)); + return getModeller(upgrade).getModel(upgrade, access, side, access.getUpgradeData(side)); } public static TransformedModel getModel(ITurtleUpgrade upgrade, DataComponentPatch data, TurtleSide side) { - @SuppressWarnings("unchecked") - var modeller = (TurtleUpgradeModeller) modelCache.computeIfAbsent(upgrade, TurtleUpgradeModellers::getModeller); - return modeller.getModel(upgrade, null, side, data); + return getModeller(upgrade).getModel(upgrade, null, side, data); } - private static TurtleUpgradeModeller getModeller(ITurtleUpgrade upgrade) { + @SuppressWarnings("unchecked") + private static TurtleUpgradeModeller getModeller(T upgrade) { var modeller = turtleModels.get(upgrade.getType()); - return modeller == null ? NULL_TURTLE_MODELLER : modeller; + return (TurtleUpgradeModeller) (modeller == null ? NULL_TURTLE_MODELLER : modeller); } public static Stream getDependencies() { diff --git a/projects/common/src/generated/resources/data/computercraft/recipes/cable.json b/projects/common/src/generated/resources/data/computercraft/recipes/cable.json index f78318384..89384fc4c 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipes/cable.json +++ b/projects/common/src/generated/resources/data/computercraft/recipes/cable.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:stones"}, "R": {"tag": "c:dusts/redstone"}}, + "key": {"#": {"item": "minecraft:stone"}, "R": {"tag": "c:dusts/redstone"}}, "pattern": [" # ", "#R#", " # "], "result": {"count": 6, "id": "computercraft:cable"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipes/computer_normal.json b/projects/common/src/generated/resources/data/computercraft/recipes/computer_normal.json index 60812a6af..84117ee95 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipes/computer_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipes/computer_normal.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:stones"}, "G": {"tag": "c:glass_panes"}, "R": {"tag": "c:dusts/redstone"}}, + "key": {"#": {"item": "minecraft:stone"}, "G": {"tag": "c:glass_panes"}, "R": {"tag": "c:dusts/redstone"}}, "pattern": ["###", "#R#", "#G#"], "result": {"count": 1, "id": "computercraft:computer_normal"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipes/disk_drive.json b/projects/common/src/generated/resources/data/computercraft/recipes/disk_drive.json index 5c15cc926..3a0026016 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipes/disk_drive.json +++ b/projects/common/src/generated/resources/data/computercraft/recipes/disk_drive.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:stones"}, "R": {"tag": "c:dusts/redstone"}}, + "key": {"#": {"item": "minecraft:stone"}, "R": {"tag": "c:dusts/redstone"}}, "pattern": ["###", "#R#", "#R#"], "result": {"count": 1, "id": "computercraft:disk_drive"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipes/monitor_normal.json b/projects/common/src/generated/resources/data/computercraft/recipes/monitor_normal.json index 2d12170d1..a52103dd7 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipes/monitor_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipes/monitor_normal.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:stones"}, "G": {"tag": "c:glass_panes"}}, + "key": {"#": {"item": "minecraft:stone"}, "G": {"tag": "c:glass_panes"}}, "pattern": ["###", "#G#", "###"], "result": {"count": 1, "id": "computercraft:monitor_normal"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipes/pocket_computer_normal.json b/projects/common/src/generated/resources/data/computercraft/recipes/pocket_computer_normal.json index 74c02e1c6..4bef87ac8 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipes/pocket_computer_normal.json +++ b/projects/common/src/generated/resources/data/computercraft/recipes/pocket_computer_normal.json @@ -1,7 +1,11 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:stones"}, "A": {"item": "minecraft:golden_apple"}, "G": {"tag": "c:glass_panes"}}, + "key": { + "#": {"item": "minecraft:stone"}, + "A": {"item": "minecraft:golden_apple"}, + "G": {"tag": "c:glass_panes"} + }, "pattern": ["###", "#A#", "#G#"], "result": {"count": 1, "id": "computercraft:pocket_computer_normal"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipes/printer.json b/projects/common/src/generated/resources/data/computercraft/recipes/printer.json index 119ef07f1..6fb87d2c3 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipes/printer.json +++ b/projects/common/src/generated/resources/data/computercraft/recipes/printer.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:stones"}, "D": {"tag": "c:dyes"}, "R": {"tag": "c:dusts/redstone"}}, + "key": {"#": {"item": "minecraft:stone"}, "D": {"tag": "c:dyes"}, "R": {"tag": "c:dusts/redstone"}}, "pattern": ["###", "#R#", "#D#"], "result": {"count": 1, "id": "computercraft:printer"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipes/speaker.json b/projects/common/src/generated/resources/data/computercraft/recipes/speaker.json index e635b8f9d..0e61faa47 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipes/speaker.json +++ b/projects/common/src/generated/resources/data/computercraft/recipes/speaker.json @@ -1,7 +1,11 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:stones"}, "N": {"item": "minecraft:note_block"}, "R": {"tag": "c:dusts/redstone"}}, + "key": { + "#": {"item": "minecraft:stone"}, + "N": {"item": "minecraft:note_block"}, + "R": {"tag": "c:dusts/redstone"} + }, "pattern": ["###", "#N#", "#R#"], "result": {"count": 1, "id": "computercraft:speaker"} } diff --git a/projects/common/src/generated/resources/data/computercraft/recipes/wired_modem.json b/projects/common/src/generated/resources/data/computercraft/recipes/wired_modem.json index ebd15829a..77c138e22 100644 --- a/projects/common/src/generated/resources/data/computercraft/recipes/wired_modem.json +++ b/projects/common/src/generated/resources/data/computercraft/recipes/wired_modem.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:stones"}, "R": {"tag": "c:dusts/redstone"}}, + "key": {"#": {"item": "minecraft:stone"}, "R": {"tag": "c:dusts/redstone"}}, "pattern": ["###", "#R#", "###"], "result": {"count": 1, "id": "computercraft:wired_modem"} } 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 3c7008209..898f119f8 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/DataProviders.java +++ b/projects/common/src/main/java/dan200/computercraft/data/DataProviders.java @@ -5,7 +5,9 @@ package dan200.computercraft.data; import com.mojang.serialization.Codec; -import dan200.computercraft.shared.ModRegistry; +import dan200.computercraft.api.pocket.IPocketUpgrade; +import dan200.computercraft.api.turtle.ITurtleUpgrade; +import net.minecraft.Util; import net.minecraft.core.HolderLookup; import net.minecraft.core.RegistrySetBuilder; import net.minecraft.data.DataProvider; @@ -20,7 +22,6 @@ import net.minecraft.world.level.block.Block; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; -import java.util.function.BiFunction; import java.util.function.Consumer; /** @@ -32,25 +33,25 @@ public final class DataProviders { } public static void add(GeneratorSink generator) { - var turtleUpgrades = generator.add(TurtleUpgradeProvider::new); - var pocketUpgrades = generator.add(PocketUpgradeProvider::new); + var fullRegistryPatch = RegistryPatchGenerator.createLookup( + generator.registries(), + Util.make(new RegistrySetBuilder(), builder -> { + builder.add(ITurtleUpgrade.REGISTRY, TurtleUpgradeProvider::addUpgrades); + builder.add(IPocketUpgrade.REGISTRY, PocketUpgradeProvider::addUpgrades); + })); + var fullRegistries = fullRegistryPatch.thenApply(RegistrySetBuilder.PatchedRegistries::full); - generator.add((out, registries) -> { - var builder = new RegistrySetBuilder(); - builder.add(ModRegistry.TURTLE_UPGRADE, bs -> turtleUpgrades.getGeneratedUpgrades().forEach(bs::register)); - builder.add(ModRegistry.POCKET_UPGRADE, bs -> pocketUpgrades.getGeneratedUpgrades().forEach(bs::register)); - - return new RecipeProvider(out, generator.createPatchedRegistries(registries, builder).thenApply(RegistrySetBuilder.PatchedRegistries::full)); - }); + generator.registries(fullRegistryPatch); + generator.add(out -> new RecipeProvider(out, fullRegistries)); var blockTags = generator.blockTags(TagProvider::blockTags); generator.itemTags(TagProvider::itemTags, blockTags); - generator.add((out, registries) -> new net.minecraft.data.loot.LootTableProvider(out, Set.of(), LootTableProvider.getTables(), registries)); + generator.add(out -> new net.minecraft.data.loot.LootTableProvider(out, Set.of(), LootTableProvider.getTables(), fullRegistries)); generator.add(out -> new ModelProvider(out, BlockModelProvider::addBlockModels, ItemModelProvider::addItemModels)); - generator.add(out -> new LanguageProvider(out, turtleUpgrades, pocketUpgrades)); + generator.add(out -> new LanguageProvider(out, fullRegistries)); // Unfortunately we rely on some client-side classes in this code. We just load in the client side data provider // and invoke that. @@ -63,9 +64,9 @@ public final class DataProviders { } public interface GeneratorSink { - T add(DataProvider.Factory factory); + CompletableFuture registries(); - T add(BiFunction, T> factory); + T add(DataProvider.Factory factory); void addFromCodec(String name, PackType type, String directory, Codec codec, Consumer> output); @@ -74,16 +75,10 @@ public final class DataProviders { TagsProvider itemTags(Consumer tags, TagsProvider blocks); /** - * Extend our registries with additional entries. + * Build new dynamic registries and save them to a pack. * - * @param registries The existing registries. - * @param patch The new registries to apply. - * @return The built registries. + * @param registries The patched registries to write. */ - default CompletableFuture createPatchedRegistries( - CompletableFuture registries, RegistrySetBuilder patch - ) { - return RegistryPatchGenerator.createLookup(registries, patch); - } + void registries(CompletableFuture registries); } } 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 6d6a22c4d..ca3f09f6b 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java @@ -7,8 +7,8 @@ package dan200.computercraft.data; import com.google.gson.JsonObject; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.ComputerCraftTags; -import dan200.computercraft.api.pocket.PocketUpgradeDataProvider; -import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider; +import dan200.computercraft.api.pocket.IPocketUpgrade; +import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.core.metrics.Metric; import dan200.computercraft.core.metrics.Metrics; import dan200.computercraft.shared.ModRegistry; @@ -17,6 +17,7 @@ import dan200.computercraft.shared.computer.metrics.basic.Aggregate; import dan200.computercraft.shared.computer.metrics.basic.AggregatedMetric; import dan200.computercraft.shared.config.ConfigFile; import dan200.computercraft.shared.config.ConfigSpec; +import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.CachedOutput; import net.minecraft.data.DataProvider; @@ -34,27 +35,28 @@ import java.util.stream.Stream; public final class LanguageProvider implements DataProvider { private final PackOutput output; - private final TurtleUpgradeDataProvider turtleUpgrades; - private final PocketUpgradeDataProvider pocketUpgrades; + private final CompletableFuture registries; private final Map translations = new HashMap<>(); - public LanguageProvider(PackOutput output, TurtleUpgradeDataProvider turtleUpgrades, PocketUpgradeDataProvider pocketUpgrades) { + public LanguageProvider(PackOutput output, CompletableFuture registries) { this.output = output; - this.turtleUpgrades = turtleUpgrades; - this.pocketUpgrades = pocketUpgrades; + this.registries = registries; } @Override public CompletableFuture run(CachedOutput cachedOutput) { addTranslations(); - getExpectedKeys().forEach(x -> { - if (!translations.containsKey(x)) throw new IllegalStateException("No translation for " + x); - }); - var json = new JsonObject(); - for (var pair : translations.entrySet()) json.addProperty(pair.getKey(), pair.getValue()); - return DataProvider.saveStable(cachedOutput, json, output.getOutputFolder().resolve("assets/" + ComputerCraftAPI.MOD_ID + "/lang/en_us.json")); + return registries.thenCompose(registries -> { + getExpectedKeys(registries).forEach(x -> { + if (!translations.containsKey(x)) throw new IllegalStateException("No translation for " + x); + }); + + var json = new JsonObject(); + for (var pair : translations.entrySet()) json.addProperty(pair.getKey(), pair.getValue()); + return DataProvider.saveStable(cachedOutput, json, output.getOutputFolder().resolve("assets/" + ComputerCraftAPI.MOD_ID + "/lang/en_us.json")); + }); } @Override @@ -280,7 +282,7 @@ public final class LanguageProvider implements DataProvider { addConfigEntry(ConfigSpec.uploadNagDelay, "Upload nag delay"); } - private Stream getExpectedKeys() { + private Stream getExpectedKeys(HolderLookup.Provider registries) { return Stream.of( BuiltInRegistries.BLOCK.holders() .filter(x -> x.key().location().getNamespace().equals(ComputerCraftAPI.MOD_ID)) @@ -288,8 +290,8 @@ public final class LanguageProvider implements DataProvider { BuiltInRegistries.ITEM.holders() .filter(x -> x.key().location().getNamespace().equals(ComputerCraftAPI.MOD_ID)) .map(x -> x.value().getDescriptionId()), - turtleUpgrades.getGeneratedUpgrades().values().stream().flatMap(x -> getTranslationKeys(x.getAdjective())), - pocketUpgrades.getGeneratedUpgrades().values().stream().flatMap(x -> getTranslationKeys(x.getAdjective())), + registries.lookupOrThrow(ITurtleUpgrade.REGISTRY).listElements().flatMap(x -> getTranslationKeys(x.value().getAdjective())), + registries.lookupOrThrow(IPocketUpgrade.REGISTRY).listElements().flatMap(x -> getTranslationKeys(x.value().getAdjective())), Metric.metrics().values().stream().map(x -> AggregatedMetric.TRANSLATION_PREFIX + x.name() + ".name"), ConfigSpec.serverSpec.entries().map(ConfigFile.Entry::translationKey), ConfigSpec.clientSpec.entries().map(ConfigFile.Entry::translationKey), diff --git a/projects/common/src/main/java/dan200/computercraft/data/ModelProvider.java b/projects/common/src/main/java/dan200/computercraft/data/ModelProvider.java index 357fdfe40..89e37d2a2 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/ModelProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/ModelProvider.java @@ -5,7 +5,7 @@ package dan200.computercraft.data; import com.google.gson.JsonElement; -import dan200.computercraft.impl.RegistryHelper; +import dan200.computercraft.shared.util.RegistryHelper; import net.minecraft.Util; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.CachedOutput; diff --git a/projects/common/src/main/java/dan200/computercraft/data/PocketUpgradeProvider.java b/projects/common/src/main/java/dan200/computercraft/data/PocketUpgradeProvider.java index 74c7a080c..7481598d0 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/PocketUpgradeProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/PocketUpgradeProvider.java @@ -6,30 +6,23 @@ package dan200.computercraft.data; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.api.pocket.PocketUpgradeDataProvider; import dan200.computercraft.shared.pocket.peripherals.PocketModem; import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker; -import net.minecraft.data.PackOutput; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; -import java.util.function.Consumer; - import static dan200.computercraft.shared.ModRegistry.Items; -class PocketUpgradeProvider extends PocketUpgradeDataProvider { - PocketUpgradeProvider(PackOutput output) { - super(output); +class PocketUpgradeProvider { + public static void addUpgrades(BootstrapContext upgrades) { + upgrades.register(id("speaker"), new PocketSpeaker(new ItemStack(Items.SPEAKER.get()))); + upgrades.register(id("wireless_modem_normal"), new PocketModem(new ItemStack(Items.WIRELESS_MODEM_NORMAL.get()), false)); + upgrades.register(id("wireless_modem_advanced"), new PocketModem(new ItemStack(Items.WIRELESS_MODEM_ADVANCED.get()), true)); } - @Override - protected void addUpgrades(Consumer> addUpgrade) { - upgrade(id("speaker"), new PocketSpeaker(new ItemStack(Items.SPEAKER.get()))).add(addUpgrade); - upgrade(id("wireless_modem_normal"), new PocketModem(new ItemStack(Items.WIRELESS_MODEM_NORMAL.get()), false)).add(addUpgrade); - upgrade(id("wireless_modem_advanced"), new PocketModem(new ItemStack(Items.WIRELESS_MODEM_ADVANCED.get()), true)).add(addUpgrade); - } - - private static ResourceLocation id(String id) { - return new ResourceLocation(ComputerCraftAPI.MOD_ID, id); + private static ResourceKey id(String id) { + return ResourceKey.create(IPocketUpgrade.REGISTRY, new ResourceLocation(ComputerCraftAPI.MOD_ID, id)); } } 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 bc2f6f139..cc287f471 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/RecipeProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/RecipeProvider.java @@ -8,11 +8,13 @@ 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.impl.RegistryHelper; +import dan200.computercraft.shared.util.RegistryHelper; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.common.ClearColourRecipe; import dan200.computercraft.shared.common.ColourableRecipe; @@ -54,14 +56,12 @@ import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.level.ItemLike; -import net.minecraft.world.level.block.Blocks; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; -import java.util.stream.Stream; import static dan200.computercraft.api.ComputerCraftTags.Items.COMPUTER; import static dan200.computercraft.api.ComputerCraftTags.Items.WIRED_MODEM; @@ -119,7 +119,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { .requires(Items.PAPER) .requires(DyeItem.byColor(ofColour(colour))) .group("computercraft:disk") - .unlockedBy("has_drive", inventoryChange(ModRegistry.Blocks.DISK_DRIVE.get())) + .unlockedBy("has_drive", inventoryChange(ModRegistry.Items.DISK_DRIVE.get())) .build(ImpostorShapelessRecipe::new) .save(output, new ResourceLocation(ComputerCraftAPI.MOD_ID, "disk_" + (colour.ordinal() + 1))); } @@ -139,7 +139,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { for (var turtleItem : turtleItems()) { var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, turtleItem); - registries.lookup(ModRegistry.TURTLE_UPGRADE).map(HolderLookup::listElements).orElse(Stream.empty()).forEach(upgradeHolder -> { + 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))) @@ -171,7 +171,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { for (var pocket : pocketComputerItems()) { var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, pocket).withPath(x -> x.replace("pocket_computer_", "pocket_")); - registries.lookup(ModRegistry.POCKET_UPGRADE).map(HolderLookup::listElements).orElse(Stream.empty()).forEach(upgradeHolder -> { + 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))) @@ -238,25 +238,25 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { .pattern(" # ") .pattern("#R#") .pattern(" # ") - .define('#', ingredients.stone()) + .define('#', Items.STONE) .define('R', ingredients.redstone()) .unlockedBy("has_computer", inventoryChange(COMPUTER)) .unlockedBy("has_modem", inventoryChange(WIRED_MODEM)) .save(add); ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.COMPUTER_NORMAL.get()) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_NORMAL.get()) .pattern("###") .pattern("#R#") .pattern("#G#") - .define('#', ingredients.stone()) + .define('#', Items.STONE) .define('R', ingredients.redstone()) .define('G', ingredients.glassPane()) .unlockedBy("has_redstone", inventoryChange(itemPredicate(ingredients.redstone()))) .save(add); ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.COMPUTER_ADVANCED.get()) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_ADVANCED.get()) .pattern("###") .pattern("#R#") .pattern("#G#") @@ -278,18 +278,18 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { .save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "computer_advanced_upgrade")); ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.COMPUTER_COMMAND.get()) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_COMMAND.get()) .pattern("###") .pattern("#R#") .pattern("#G#") .define('#', ingredients.goldIngot()) - .define('R', Blocks.COMMAND_BLOCK) + .define('R', Items.COMMAND_BLOCK) .define('G', ingredients.glassPane()) - .unlockedBy("has_components", inventoryChange(Blocks.COMMAND_BLOCK)) + .unlockedBy("has_components", inventoryChange(Items.COMMAND_BLOCK)) .save(add); ShapedSpecBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_NORMAL.get()) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_NORMAL.get()) .pattern("###") .pattern("#C#") .pattern("#I#") @@ -301,7 +301,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { .save(add); ShapedSpecBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_ADVANCED.get()) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_ADVANCED.get()) .pattern("###") .pattern("#C#") .pattern("#I#") @@ -313,7 +313,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { .save(add); ShapedSpecBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_ADVANCED.get()) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_ADVANCED.get()) .pattern("###") .pattern("#C#") .pattern(" B ") @@ -325,27 +325,27 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { .save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_advanced_upgrade")); ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.DISK_DRIVE.get()) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.DISK_DRIVE.get()) .pattern("###") .pattern("#R#") .pattern("#R#") - .define('#', ingredients.stone()) + .define('#', Items.STONE) .define('R', ingredients.redstone()) .unlockedBy("has_computer", inventoryChange(COMPUTER)) .save(add); ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.MONITOR_NORMAL.get()) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.MONITOR_NORMAL.get()) .pattern("###") .pattern("#G#") .pattern("###") - .define('#', ingredients.stone()) + .define('#', Items.STONE) .define('G', ingredients.glassPane()) .unlockedBy("has_computer", inventoryChange(COMPUTER)) .save(add); ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.MONITOR_ADVANCED.get(), 4) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.MONITOR_ADVANCED.get(), 4) .pattern("###") .pattern("#G#") .pattern("###") @@ -359,7 +359,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { .pattern("###") .pattern("#A#") .pattern("#G#") - .define('#', ingredients.stone()) + .define('#', Items.STONE) .define('A', Items.GOLDEN_APPLE) .define('G', ingredients.glassPane()) .unlockedBy("has_computer", inventoryChange(COMPUTER)) @@ -390,23 +390,23 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { .save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_computer_advanced_upgrade")); ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.PRINTER.get()) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTER.get()) .pattern("###") .pattern("#R#") .pattern("#D#") - .define('#', ingredients.stone()) + .define('#', Items.STONE) .define('R', ingredients.redstone()) .define('D', ingredients.dye()) .unlockedBy("has_computer", inventoryChange(COMPUTER)) .save(add); ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.SPEAKER.get()) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.SPEAKER.get()) .pattern("###") .pattern("#N#") .pattern("#R#") - .define('#', ingredients.stone()) - .define('N', Blocks.NOTE_BLOCK) + .define('#', Items.STONE) + .define('N', Items.NOTE_BLOCK) .define('R', ingredients.redstone()) .unlockedBy("has_computer", inventoryChange(COMPUTER)) .save(add); @@ -416,42 +416,42 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider { .pattern("###") .pattern("#R#") .pattern("###") - .define('#', ingredients.stone()) + .define('#', Items.STONE) .define('R', ingredients.redstone()) .unlockedBy("has_computer", inventoryChange(COMPUTER)) .unlockedBy("has_cable", inventoryChange(ModRegistry.Items.CABLE.get())) .save(add); ShapelessRecipeBuilder - .shapeless(RecipeCategory.REDSTONE, ModRegistry.Blocks.WIRED_MODEM_FULL.get()) + .shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.WIRED_MODEM_FULL.get()) .requires(ModRegistry.Items.WIRED_MODEM.get()) .unlockedBy("has_modem", inventoryChange(WIRED_MODEM)) .save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "wired_modem_full_from")); ShapelessRecipeBuilder .shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.WIRED_MODEM.get()) - .requires(ModRegistry.Blocks.WIRED_MODEM_FULL.get()) + .requires(ModRegistry.Items.WIRED_MODEM_FULL.get()) .unlockedBy("has_modem", inventoryChange(WIRED_MODEM)) .save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "wired_modem_full_to")); ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.WIRELESS_MODEM_NORMAL.get()) + .shaped(RecipeCategory.REDSTONE, ModRegistry.Items.WIRELESS_MODEM_NORMAL.get()) .pattern("###") .pattern("#E#") .pattern("###") - .define('#', ingredients.stone()) + .define('#', Items.STONE) .define('E', ingredients.enderPearl()) .unlockedBy("has_computer", inventoryChange(COMPUTER)) .save(add); ShapedRecipeBuilder - .shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.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.Blocks.WIRELESS_MODEM_NORMAL.get())) + .unlockedBy("has_wireless", inventoryChange(ModRegistry.Items.WIRELESS_MODEM_NORMAL.get())) .save(add); ShapelessSpecBuilder diff --git a/projects/common/src/main/java/dan200/computercraft/data/TagProvider.java b/projects/common/src/main/java/dan200/computercraft/data/TagProvider.java index dce38ac3c..69f07de5b 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/TagProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/TagProvider.java @@ -5,7 +5,7 @@ package dan200.computercraft.data; import dan200.computercraft.api.ComputerCraftTags; -import dan200.computercraft.impl.RegistryHelper; +import dan200.computercraft.shared.util.RegistryHelper; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.integration.ExternalModTags; import net.minecraft.core.Registry; diff --git a/projects/common/src/main/java/dan200/computercraft/data/TurtleUpgradeProvider.java b/projects/common/src/main/java/dan200/computercraft/data/TurtleUpgradeProvider.java index b740b85f4..001ca3485 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/TurtleUpgradeProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/TurtleUpgradeProvider.java @@ -5,45 +5,40 @@ package dan200.computercraft.data; import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.ComputerCraftTags.Blocks; +import dan200.computercraft.api.ComputerCraftTags; import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.turtle.upgrades.TurtleCraftingTable; import dan200.computercraft.shared.turtle.upgrades.TurtleModem; import dan200.computercraft.shared.turtle.upgrades.TurtleSpeaker; -import net.minecraft.data.PackOutput; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import java.util.function.Consumer; +import static dan200.computercraft.api.turtle.TurtleToolBuilder.tool; -class TurtleUpgradeProvider extends TurtleUpgradeDataProvider { - TurtleUpgradeProvider(PackOutput output) { - super(output); +class TurtleUpgradeProvider { + public static void addUpgrades(BootstrapContext upgrades) { + upgrades.register(id("speaker"), new TurtleSpeaker(new ItemStack(ModRegistry.Items.SPEAKER.get()))); + upgrades.register(vanilla("crafting_table"), new TurtleCraftingTable(new ItemStack(Items.CRAFTING_TABLE))); + upgrades.register(id("wireless_modem_normal"), new TurtleModem(new ItemStack(ModRegistry.Items.WIRELESS_MODEM_NORMAL.get()), false)); + upgrades.register(id("wireless_modem_advanced"), new TurtleModem(new ItemStack(ModRegistry.Items.WIRELESS_MODEM_ADVANCED.get()), true)); + + tool(vanilla("diamond_axe").location(), Items.DIAMOND_AXE).damageMultiplier(6.0f).register(upgrades); + tool(vanilla("diamond_pickaxe"), Items.DIAMOND_PICKAXE).register(upgrades); + tool(vanilla("diamond_hoe"), Items.DIAMOND_HOE).breakable(ComputerCraftTags.Blocks.TURTLE_HOE_BREAKABLE).register(upgrades); + tool(vanilla("diamond_shovel"), Items.DIAMOND_SHOVEL).breakable(ComputerCraftTags.Blocks.TURTLE_SHOVEL_BREAKABLE).register(upgrades); + tool(vanilla("diamond_sword"), Items.DIAMOND_SWORD).breakable(ComputerCraftTags.Blocks.TURTLE_SWORD_BREAKABLE).damageMultiplier(9.0f).register(upgrades); } - @Override - protected void addUpgrades(Consumer> addUpgrade) { - upgrade(id("speaker"), new TurtleSpeaker(new ItemStack(ModRegistry.Items.SPEAKER.get()))).add(addUpgrade); - upgrade(vanilla("crafting_table"), new TurtleCraftingTable(new ItemStack(Items.CRAFTING_TABLE))).add(addUpgrade); - upgrade(id("wireless_modem_normal"), new TurtleModem(new ItemStack(ModRegistry.Items.WIRELESS_MODEM_NORMAL.get()), false)).add(addUpgrade); - upgrade(id("wireless_modem_advanced"), new TurtleModem(new ItemStack(ModRegistry.Items.WIRELESS_MODEM_ADVANCED.get()), true)).add(addUpgrade); - - tool(vanilla("diamond_axe"), Items.DIAMOND_AXE).damageMultiplier(6.0f).add(addUpgrade); - tool(vanilla("diamond_pickaxe"), Items.DIAMOND_PICKAXE).add(addUpgrade); - tool(vanilla("diamond_hoe"), Items.DIAMOND_HOE).breakable(Blocks.TURTLE_HOE_BREAKABLE).add(addUpgrade); - tool(vanilla("diamond_shovel"), Items.DIAMOND_SHOVEL).breakable(Blocks.TURTLE_SHOVEL_BREAKABLE).add(addUpgrade); - tool(vanilla("diamond_sword"), Items.DIAMOND_SWORD).breakable(Blocks.TURTLE_SWORD_BREAKABLE).damageMultiplier(9.0f).add(addUpgrade); + private static ResourceKey id(String id) { + return ITurtleUpgrade.createKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, id)); } - private static ResourceLocation id(String id) { - return new ResourceLocation(ComputerCraftAPI.MOD_ID, id); - } - - private static ResourceLocation vanilla(String id) { + private static ResourceKey vanilla(String id) { // Naughty, please don't do this. Mostly here for some semblance of backwards compatibility. - return new ResourceLocation("minecraft", id); + return ITurtleUpgrade.createKey(new ResourceLocation("minecraft", id)); } } diff --git a/projects/common/src/main/java/dan200/computercraft/impl/PocketUpgrades.java b/projects/common/src/main/java/dan200/computercraft/impl/PocketUpgrades.java index e77856a92..0b55c8a19 100644 --- a/projects/common/src/main/java/dan200/computercraft/impl/PocketUpgrades.java +++ b/projects/common/src/main/java/dan200/computercraft/impl/PocketUpgrades.java @@ -5,11 +5,10 @@ package dan200.computercraft.impl; import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.shared.ModRegistry; public final class PocketUpgrades { private static final UpgradeManager registry = new UpgradeManager<>( - IPocketUpgrade.typeRegistry(), ModRegistry.POCKET_UPGRADE, IPocketUpgrade::getType + IPocketUpgrade.typeRegistry(), IPocketUpgrade.REGISTRY, IPocketUpgrade::getType ); private PocketUpgrades() { diff --git a/projects/common/src/main/java/dan200/computercraft/impl/TurtleUpgrades.java b/projects/common/src/main/java/dan200/computercraft/impl/TurtleUpgrades.java index 523d9a602..cb9025ed7 100644 --- a/projects/common/src/main/java/dan200/computercraft/impl/TurtleUpgrades.java +++ b/projects/common/src/main/java/dan200/computercraft/impl/TurtleUpgrades.java @@ -5,11 +5,10 @@ package dan200.computercraft.impl; import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.shared.ModRegistry; public final class TurtleUpgrades { private static final UpgradeManager registry = new UpgradeManager<>( - ITurtleUpgrade.typeRegistry(), ModRegistry.TURTLE_UPGRADE, ITurtleUpgrade::getType + ITurtleUpgrade.typeRegistry(), ITurtleUpgrade.REGISTRY, ITurtleUpgrade::getType ); private TurtleUpgrades() { 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 fad9f1b12..08b3b69b0 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java @@ -18,7 +18,6 @@ import dan200.computercraft.api.upgrades.UpgradeData; import dan200.computercraft.api.upgrades.UpgradeType; import dan200.computercraft.core.util.Colour; import dan200.computercraft.impl.PocketUpgrades; -import dan200.computercraft.impl.RegistryHelper; import dan200.computercraft.shared.command.UserLevel; import dan200.computercraft.shared.command.arguments.ComputerArgumentType; import dan200.computercraft.shared.command.arguments.RepeatArgumentType; @@ -91,7 +90,6 @@ import net.minecraft.commands.synchronization.ArgumentTypeInfo; import net.minecraft.commands.synchronization.SingletonArgumentInfo; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; -import net.minecraft.core.Registry; import net.minecraft.core.cauldron.CauldronInteraction; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.Registries; @@ -99,7 +97,6 @@ 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; @@ -130,9 +127,6 @@ public final class ModRegistry { private ModRegistry() { } - public static final ResourceKey> TURTLE_UPGRADE = RegistryHelper.TURTLE_UPGRADE; - public static final ResourceKey> POCKET_UPGRADE = RegistryHelper.POCKET_UPGRADE; - public static final class Blocks { static final RegistrationHelper REGISTRY = PlatformHelper.get().createRegistrationHelper(Registries.BLOCK); @@ -602,7 +596,7 @@ public final class ModRegistry { private static void addTurtle(CreativeModeTab.Output out, TurtleItem turtle, HolderLookup.Provider registries) { out.accept(new ItemStack(turtle)); - registries.lookupOrThrow(TURTLE_UPGRADE).listElements() + registries.lookupOrThrow(ITurtleUpgrade.REGISTRY).listElements() .filter(ModRegistry::isOurUpgrade) .map(x -> DataComponentUtil.createStack(turtle, DataComponents.RIGHT_TURTLE_UPGRADE.get(), UpgradeData.ofDefault(x))) .forEach(out::accept); @@ -610,7 +604,7 @@ public final class ModRegistry { private static void addPocket(CreativeModeTab.Output out, PocketComputerItem pocket, HolderLookup.Provider registries) { out.accept(new ItemStack(pocket)); - registries.lookupOrThrow(POCKET_UPGRADE).listElements() + registries.lookupOrThrow(IPocketUpgrade.REGISTRY).listElements() .filter(ModRegistry::isOurUpgrade) .map(x -> DataComponentUtil.createStack(pocket, DataComponents.POCKET_UPGRADE.get(), UpgradeData.ofDefault(x))).forEach(out::accept); } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/command/arguments/ArgumentUtils.java b/projects/common/src/main/java/dan200/computercraft/shared/command/arguments/ArgumentUtils.java index 25a8a6068..e834f4890 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/command/arguments/ArgumentUtils.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/command/arguments/ArgumentUtils.java @@ -8,7 +8,7 @@ import com.google.gson.JsonObject; import com.mojang.brigadier.Message; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import dan200.computercraft.impl.RegistryHelper; +import dan200.computercraft.shared.util.RegistryHelper; import net.minecraft.commands.synchronization.ArgumentTypeInfo; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; diff --git a/projects/common/src/main/java/dan200/computercraft/shared/details/DetailHelpers.java b/projects/common/src/main/java/dan200/computercraft/shared/details/DetailHelpers.java index 1fc3f28c1..f2ba58e16 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/details/DetailHelpers.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/details/DetailHelpers.java @@ -4,7 +4,7 @@ package dan200.computercraft.shared.details; -import dan200.computercraft.impl.RegistryHelper; +import dan200.computercraft.shared.util.RegistryHelper; import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.tags.TagKey; diff --git a/projects/common/src/main/java/dan200/computercraft/shared/integration/RecipeModHelpers.java b/projects/common/src/main/java/dan200/computercraft/shared/integration/RecipeModHelpers.java index 869b2036a..a5408a1f7 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/integration/RecipeModHelpers.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/integration/RecipeModHelpers.java @@ -5,6 +5,8 @@ package dan200.computercraft.shared.integration; 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.shared.ModRegistry; import dan200.computercraft.shared.pocket.items.PocketComputerItem; @@ -60,14 +62,14 @@ public final class RecipeModHelpers { List upgradeItems = new ArrayList<>(); for (var turtleSupplier : TURTLES) { var turtle = turtleSupplier.get(); - forEachRegistry(registries, ModRegistry.TURTLE_UPGRADE, upgrade -> + forEachRegistry(registries, ITurtleUpgrade.REGISTRY, upgrade -> upgradeItems.add(DataComponentUtil.createStack(turtle, ModRegistry.DataComponents.RIGHT_TURTLE_UPGRADE.get(), UpgradeData.ofDefault(upgrade))) ); } for (var pocketSupplier : POCKET_COMPUTERS) { var pocket = pocketSupplier.get(); - forEachRegistry(registries, ModRegistry.POCKET_UPGRADE, upgrade -> + forEachRegistry(registries, IPocketUpgrade.REGISTRY, upgrade -> upgradeItems.add(DataComponentUtil.createStack(pocket, ModRegistry.DataComponents.POCKET_UPGRADE.get(), UpgradeData.ofDefault(upgrade))) ); } 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 6995716df..792721c6a 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 @@ -57,7 +57,7 @@ public class UpgradeRecipeGenerator { if (initialised) return; initialised = true; - forEachRegistry(registries, ModRegistry.TURTLE_UPGRADE, holder -> { + forEachRegistry(registries, ITurtleUpgrade.REGISTRY, holder -> { var upgrade = holder.value(); var stack = upgrade.getCraftingItem(); if (stack.isEmpty()) return; @@ -67,7 +67,7 @@ public class UpgradeRecipeGenerator { turtleUpgrades.add(info); }); - forEachRegistry(registries, ModRegistry.POCKET_UPGRADE, holder -> { + forEachRegistry(registries, IPocketUpgrade.REGISTRY, holder -> { var upgrade = holder.value(); var stack = upgrade.getCraftingItem(); if (stack.isEmpty()) return; @@ -223,13 +223,13 @@ public class UpgradeRecipeGenerator { var newStack = stack.copyWithCount(1); newStack.set(ModRegistry.DataComponents.LEFT_TURTLE_UPGRADE.get(), left); newStack.set(ModRegistry.DataComponents.RIGHT_TURTLE_UPGRADE.get(), right); - return stack; + return newStack; } private static ItemStack pocketWith(ItemStack stack, @Nullable UpgradeData back) { var newStack = stack.copyWithCount(1); newStack.set(ModRegistry.DataComponents.POCKET_UPGRADE.get(), back); - return stack; + return newStack; } private T pocket(Ingredient upgrade, Ingredient pocketComputer, ItemStack result) { diff --git a/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutData.java b/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutData.java index 680867810..873ace0af 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutData.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/media/items/PrintoutData.java @@ -8,7 +8,9 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.codecs.RecordCodecBuilder; import dan200.computercraft.core.terminal.Terminal; +import dan200.computercraft.shared.ModRegistry; import io.netty.buffer.ByteBuf; +import net.minecraft.core.component.DataComponentHolder; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; @@ -93,6 +95,10 @@ public record PrintoutData(String title, List lines) { return DataResult.success(lines); } + public static PrintoutData getOrEmpty(DataComponentHolder holder) { + return holder.getOrDefault(ModRegistry.DataComponents.PRINTOUT.get(), EMPTY); + } + /** * Get the number of pages in this printout. * 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 39af29be0..f9867406c 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 @@ -35,7 +35,7 @@ public class PrintoutItem extends Item { @Override public void appendHoverText(ItemStack stack, TooltipContext context, List list, TooltipFlag options) { - var title = getTitle(stack); + var title = PrintoutData.getOrEmpty(stack).title(); if (!title.isEmpty()) list.add(Component.literal(title)); } @@ -51,14 +51,4 @@ public class PrintoutItem extends Item { public Type getType() { return type; } - - public static String getTitle(ItemStack stack) { - var nbt = stack.get(ModRegistry.DataComponents.PRINTOUT.get()); - return nbt == null ? "" : nbt.title(); - } - - public static int getPageCount(ItemStack stack) { - var nbt = stack.get(ModRegistry.DataComponents.PRINTOUT.get()); - return nbt == null ? 1 : nbt.pages(); - } } 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 adc5895ea..7ba2ef59b 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 @@ -64,7 +64,7 @@ public final class PrintoutRecipe extends CustomRecipe { if (stack.getItem() instanceof PrintoutItem printout && printout.getType() != PrintoutItem.Type.BOOK) { if (printouts == null) printouts = new ItemStack[9]; printouts[numPrintouts] = stack; - numPages += PrintoutItem.getPageCount(stack); + numPages += PrintoutData.getOrEmpty(stack).pages(); numPrintouts++; printoutFound = true; } else if (stack.getItem() == Items.PAPER) { @@ -104,7 +104,7 @@ public final class PrintoutRecipe extends CustomRecipe { } } - var title = PrintoutItem.getTitle(printouts[0]); + var title = PrintoutData.getOrEmpty(printouts[0]).title(); return DataComponentUtil.createStack( leatherFound ? ModRegistry.Items.PRINTED_BOOK.get() : ModRegistry.Items.PRINTED_PAGES.get(), 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 56c7ce8ef..3878f681e 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,7 +4,7 @@ package dan200.computercraft.shared.peripheral.modem.wired; -import dan200.computercraft.impl.RegistryHelper; +import dan200.computercraft.shared.util.RegistryHelper; import dan200.computercraft.shared.ModRegistry; import net.minecraft.Util; import net.minecraft.core.BlockPos; diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterBlockEntity.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterBlockEntity.java index 624db28b1..0b324e380 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterBlockEntity.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/printer/PrinterBlockEntity.java @@ -11,7 +11,6 @@ import dan200.computercraft.shared.computer.terminal.NetworkedTerminal; import dan200.computercraft.shared.container.BasicContainer; import dan200.computercraft.shared.container.BasicWorldlyContainer; import dan200.computercraft.shared.media.items.PrintoutData; -import dan200.computercraft.shared.media.items.PrintoutItem; import dan200.computercraft.shared.util.ColourUtils; import dan200.computercraft.shared.util.DataComponentUtil; import net.minecraft.core.BlockPos; @@ -172,8 +171,7 @@ public final class PrinterBlockEntity extends AbstractContainerBlockEntity imple static boolean isPaper(ItemStack stack) { var item = stack.getItem(); - return item == Items.PAPER - || (item instanceof PrintoutItem printout && printout.getType() == PrintoutItem.Type.PAGE); + return item == Items.PAPER || item == ModRegistry.Items.PRINTED_PAGE.get(); } private boolean canInputPage() { 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 7e9265af7..278e34f51 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 @@ -4,11 +4,11 @@ package dan200.computercraft.shared.platform; -import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import com.mojang.brigadier.arguments.ArgumentType; import dan200.computercraft.api.network.wired.WiredElement; import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.impl.Services; import dan200.computercraft.shared.config.ConfigFile; import dan200.computercraft.shared.network.container.ContainerData; import dan200.computercraft.shared.util.InventoryUtil; @@ -47,26 +47,19 @@ import java.util.function.Consumer; import java.util.function.Predicate; /** - * This extends {@linkplain dan200.computercraft.impl.PlatformHelper the API's loader abstraction layer}, adding - * additional methods used by the actual mod. + * Abstraction layer for Forge and Fabric. See implementations for more details. */ -public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper { +public interface PlatformHelper { /** * Get the current {@link PlatformHelper} instance. * * @return The current instance. */ static PlatformHelper get() { - return (PlatformHelper) dan200.computercraft.impl.PlatformHelper.get(); + var instance = Instance.INSTANCE; + return instance == null ? Services.raise(PlatformHelper.class, Instance.ERROR) : instance; } - /** - * Check if we're running in a development environment. - * - * @return If we're running in a development environment. - */ - boolean isDevelopmentEnvironment(); - /** * Create a new config builder. * @@ -83,16 +76,6 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper */ RegistrationHelper createRegistrationHelper(ResourceKey> registry); - /** - * Determine if this resource should be loaded, based on platform-specific loot conditions. - *

- * This should only be called from the {@code apply} stage of a reload listener. - * - * @param object The root JSON object of this resource. - * @return If this resource should be loaded. - */ - boolean shouldLoadResource(JsonObject object); - /** * Register a new argument type. * @@ -328,4 +311,21 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper * @see ServerPlayerGameMode#useItemOn(ServerPlayer, Level, ItemStack, InteractionHand, BlockHitResult) */ InteractionResult useOn(ServerPlayer player, ItemStack stack, BlockHitResult hit, Predicate canUseBlock); + + + final class Instance { + static final @Nullable PlatformHelper INSTANCE; + static final @Nullable Throwable ERROR; + + static { + // We don't want class initialisation to fail here (as that results in confusing errors). Instead, capture + // the error and rethrow it when accessing. This should be JITted away in the common case. + var helper = Services.tryLoad(PlatformHelper.class); + INSTANCE = helper.instance(); + ERROR = helper.error(); + } + + private Instance() { + } + } } 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 ba660386e..b35cff0fd 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 @@ -13,7 +13,6 @@ import net.minecraft.world.item.crafting.Ingredient; * @param redstone All {@link Items#REDSTONE} items. * @param string All {@link Items#STRING} items. * @param leather All {@link Items#LEATHER} items. - * @param stone All {@link Items#STONE} items. * @param glassPane All {@link Items#GLASS_PANE} items. * @param goldIngot All {@link Items#GOLD_INGOT} items. * @param goldBlock All {@link Items#GOLD_BLOCK} items. @@ -26,7 +25,6 @@ public record RecipeIngredients( Ingredient redstone, Ingredient string, Ingredient leather, - Ingredient stone, Ingredient glassPane, Ingredient goldIngot, Ingredient goldBlock, 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 62f1fd8c3..b3bda8f9f 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 @@ -6,7 +6,7 @@ package dan200.computercraft.shared.recipe; import com.mojang.serialization.DataResult; import com.mojang.serialization.MapCodec; -import dan200.computercraft.impl.RegistryHelper; +import dan200.computercraft.shared.util.RegistryHelper; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; diff --git a/projects/common-api/src/main/java/dan200/computercraft/impl/RegistryHelper.java b/projects/common/src/main/java/dan200/computercraft/shared/util/RegistryHelper.java similarity index 75% rename from projects/common-api/src/main/java/dan200/computercraft/impl/RegistryHelper.java rename to projects/common/src/main/java/dan200/computercraft/shared/util/RegistryHelper.java index 8d64b1ca7..9d07a63e3 100644 --- a/projects/common-api/src/main/java/dan200/computercraft/impl/RegistryHelper.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/RegistryHelper.java @@ -2,11 +2,8 @@ // // SPDX-License-Identifier: MPL-2.0 -package dan200.computercraft.impl; +package dan200.computercraft.shared.util; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.api.turtle.ITurtleUpgrade; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceKey; @@ -18,9 +15,6 @@ import org.jetbrains.annotations.ApiStatus; */ @ApiStatus.Internal public final class RegistryHelper { - public static final ResourceKey> TURTLE_UPGRADE = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_upgrade")); - public static final ResourceKey> POCKET_UPGRADE = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_upgrade")); - private RegistryHelper() { } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/SafeDispatchCodec.java b/projects/common/src/main/java/dan200/computercraft/shared/util/SafeDispatchCodec.java index 929474655..4f7acc9aa 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/SafeDispatchCodec.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/SafeDispatchCodec.java @@ -6,7 +6,6 @@ package dan200.computercraft.shared.util; import com.mojang.serialization.*; import com.mojang.serialization.codecs.KeyDispatchCodec; -import dan200.computercraft.impl.RegistryHelper; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; 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 index e6ae648c4..e29e42e1e 100644 --- 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 @@ -6,7 +6,6 @@ "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": "IViewRotMat", "type": "matrix3x3", "count": 9, "values": [ 1.0, 0.0, 0.0, 0.0, 1.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 ] }, diff --git a/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java b/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java index 91b07fd40..36cf80a8e 100644 --- a/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java +++ b/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java @@ -5,7 +5,6 @@ package dan200.computercraft; import com.google.auto.service.AutoService; -import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import com.mojang.brigadier.arguments.ArgumentType; import dan200.computercraft.api.network.wired.WiredElement; @@ -48,13 +47,8 @@ import java.util.List; import java.util.function.Consumer; import java.util.function.Predicate; -@AutoService({ PlatformHelper.class, dan200.computercraft.impl.PlatformHelper.class, ComputerCraftAPIService.class }) +@AutoService({ PlatformHelper.class, ComputerCraftAPIService.class }) public class TestPlatformHelper extends AbstractComputerCraftAPI implements PlatformHelper { - @Override - public boolean isDevelopmentEnvironment() { - return true; - } - @Override public ConfigFile.Builder createConfigBuilder() { throw new UnsupportedOperationException("Cannot create config file inside tests"); @@ -65,16 +59,6 @@ public class TestPlatformHelper extends AbstractComputerCraftAPI implements Plat throw new UnsupportedOperationException("Cannot query registry inside tests"); } - @Override - public boolean shouldLoadResource(JsonObject object) { - throw new UnsupportedOperationException("Cannot use resource conditions"); - } - - @Override - public void addRequiredModCondition(JsonObject object, String modId) { - throw new UnsupportedOperationException("Cannot use resource conditions"); - } - @Override public , T extends ArgumentTypeInfo.Template, I extends ArgumentTypeInfo> I registerArgumentTypeInfo(Class klass, I info) { throw new UnsupportedOperationException("Cannot register ArgumentTypeInfo 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 be7b56b43..43b2b80a9 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java +++ b/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java @@ -17,7 +17,7 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.data.PrettyJsonWriter; import dan200.computercraft.gametest.core.TestHooks; -import dan200.computercraft.impl.RegistryHelper; +import dan200.computercraft.shared.util.RegistryHelper; import net.minecraft.client.Minecraft; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; 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 aa996c905..fcad316ab 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/export/JsonDump.java +++ b/projects/common/src/testMod/java/dan200/computercraft/export/JsonDump.java @@ -4,7 +4,7 @@ package dan200.computercraft.export; -import dan200.computercraft.impl.RegistryHelper; +import dan200.computercraft.shared.util.RegistryHelper; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; 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 df558ff7b..b99606217 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 @@ -233,7 +233,7 @@ class Turtle_Test { val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access val upgrade = turtle.getUpgrade(TurtleSide.LEFT) assertEquals( - helper.level.registryAccess().registryOrThrow(ModRegistry.TURTLE_UPGRADE) + helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) .get(ResourceLocation("cctest", "wooden_pickaxe")), upgrade, "Upgrade is a wooden pickaxe", @@ -262,7 +262,7 @@ class Turtle_Test { helper.assertUpgradeItem( ItemStack(Items.WOODEN_PICKAXE), UpgradeData.ofDefault( - helper.level.registryAccess().registryOrThrow(ModRegistry.TURTLE_UPGRADE) + helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) .getHolder(ResourceLocation("cctest", "wooden_pickaxe")).orElseThrow(), ), ) @@ -283,7 +283,7 @@ class Turtle_Test { val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access val upgrade = turtle.getUpgrade(TurtleSide.LEFT) assertEquals( - helper.level.registryAccess().registryOrThrow(ModRegistry.TURTLE_UPGRADE) + helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY) .get(ResourceLocation("cctest", "netherite_pickaxe")), upgrade, "Upgrade is a netherite pickaxe", diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/ClientTestExtensions.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/ClientTestExtensions.kt index 1df5dcd68..b605ee4c9 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/ClientTestExtensions.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/api/ClientTestExtensions.kt @@ -5,8 +5,8 @@ package dan200.computercraft.gametest.api import dan200.computercraft.gametest.core.MinecraftExtensions -import dan200.computercraft.impl.RegistryHelper import dan200.computercraft.mixin.gametest.GameTestSequenceAccessor +import dan200.computercraft.shared.util.RegistryHelper import net.minecraft.client.Minecraft import net.minecraft.client.Screenshot import net.minecraft.client.gui.screens.inventory.MenuAccess 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 ed76bae18..60fecc0f4 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 @@ -6,10 +6,10 @@ package dan200.computercraft.gametest.api import dan200.computercraft.api.peripheral.IPeripheral import dan200.computercraft.gametest.core.ManagedComputers -import dan200.computercraft.impl.RegistryHelper import dan200.computercraft.mixin.gametest.GameTestInfoAccessor import dan200.computercraft.mixin.gametest.GameTestSequenceAccessor import dan200.computercraft.shared.platform.PlatformHelper +import dan200.computercraft.shared.util.RegistryHelper import dan200.computercraft.test.core.computer.LuaTaskContext import dan200.computercraft.test.shared.ItemStackMatcher.isStack import net.minecraft.commands.arguments.blocks.BlockInput diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/integration/rei/REIComputerCraft.java b/projects/fabric/src/client/java/dan200/computercraft/client/integration/rei/REIComputerCraft.java index 7a4be36eb..ca17d209f 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/integration/rei/REIComputerCraft.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/integration/rei/REIComputerCraft.java @@ -7,15 +7,22 @@ package dan200.computercraft.client.integration.rei; import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.integration.RecipeModHelpers; +import dan200.computercraft.shared.platform.RegistryEntry; import dan200.computercraft.shared.pocket.items.PocketComputerItem; import dan200.computercraft.shared.turtle.items.TurtleItem; import dev.architectury.event.EventResult; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; +import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry; import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; +import me.shedaniel.rei.api.common.display.basic.BasicDisplay; import me.shedaniel.rei.api.common.entry.comparison.ItemComparatorRegistry; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.plugin.common.BuiltinPlugin; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.DyedItemColor; /** * REI integration for ComputerCraft. @@ -40,15 +47,30 @@ public class REIComputerCraft implements REIClientPlugin { var upgrade = PocketComputerItem.getUpgradeWithData(stack); return upgrade == null ? 1 : upgrade.holder().key().location().hashCode(); }, ModRegistry.Items.POCKET_COMPUTER_NORMAL.get(), ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get()); + + registry.register((context, stack) -> DyedItemColor.getOrDefault(stack, -1), ModRegistry.Items.DISK.get()); } @Override public void registerEntries(EntryRegistry registry) { - for (var stack : RecipeModHelpers.getExtraStacks(RecipeModHelpers.getEmptyRegistryAccess())) { + for (var stack : RecipeModHelpers.getExtraStacks(BasicDisplay.registryAccess())) { registry.addEntry(EntryStacks.of(stack)); } } + @Override + public void registerCollapsibleEntries(CollapsibleEntryRegistry registry) { + addCollapsableGroup(registry, ModRegistry.Items.TURTLE_NORMAL); + addCollapsableGroup(registry, ModRegistry.Items.TURTLE_ADVANCED); + addCollapsableGroup(registry, ModRegistry.Items.POCKET_COMPUTER_NORMAL); + addCollapsableGroup(registry, ModRegistry.Items.POCKET_COMPUTER_ADVANCED); + } + + private static void addCollapsableGroup(CollapsibleEntryRegistry registry, RegistryEntry holder) { + var item = holder.get(); + registry.group(holder.id(), new ItemStack(item).getDisplayName(), VanillaEntryTypes.ITEM, x -> x.getValue().is(item)); + } + @Override public void registerDisplays(DisplayRegistry registry) { registry.registerDisplayGenerator(BuiltinPlugin.CRAFTING, new UpgradeDisplayGenerator()); diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/integration/rei/UpgradeDisplayGenerator.java b/projects/fabric/src/client/java/dan200/computercraft/client/integration/rei/UpgradeDisplayGenerator.java index ebfdb2224..d21b5d3dc 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/integration/rei/UpgradeDisplayGenerator.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/integration/rei/UpgradeDisplayGenerator.java @@ -4,7 +4,6 @@ package dan200.computercraft.client.integration.rei; -import dan200.computercraft.shared.integration.RecipeModHelpers; import dan200.computercraft.shared.integration.UpgradeRecipeGenerator; import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator; import me.shedaniel.rei.api.common.display.basic.BasicDisplay; @@ -24,7 +23,7 @@ import java.util.Optional; * Provides custom recipe and usage hints for pocket/turtle upgrades. */ class UpgradeDisplayGenerator implements DynamicDisplayGenerator> { - private final UpgradeRecipeGenerator> resolver = new UpgradeRecipeGenerator<>(GeneratedShapedDisplay::new, RecipeModHelpers.getEmptyRegistryAccess()); + private final UpgradeRecipeGenerator> resolver = new UpgradeRecipeGenerator<>(GeneratedShapedDisplay::new, BasicDisplay.registryAccess()); @Override public Optional>> getRecipeFor(EntryStack entry) { diff --git a/projects/fabric/src/generated/resources/data/computercraft/recipes/wireless_modem_normal.json b/projects/fabric/src/generated/resources/data/computercraft/recipes/wireless_modem_normal.json index 1223d741e..f22a0d925 100644 --- a/projects/fabric/src/generated/resources/data/computercraft/recipes/wireless_modem_normal.json +++ b/projects/fabric/src/generated/resources/data/computercraft/recipes/wireless_modem_normal.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:stones"}, "E": {"item": "minecraft:ender_pearl"}}, + "key": {"#": {"item": "minecraft:stone"}, "E": {"item": "minecraft:ender_pearl"}}, "pattern": ["###", "#E#", "###"], "result": {"count": 1, "id": "computercraft:wireless_modem_normal"} } diff --git a/projects/fabric/src/main/java/dan200/computercraft/data/FabricDataGenerators.java b/projects/fabric/src/main/java/dan200/computercraft/data/FabricDataGenerators.java index 6748fe23e..ff1014890 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/data/FabricDataGenerators.java +++ b/projects/fabric/src/main/java/dan200/computercraft/data/FabricDataGenerators.java @@ -5,41 +5,40 @@ package dan200.computercraft.data; import com.mojang.serialization.Codec; -import com.mojang.serialization.Lifecycle; import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.provider.FabricCodecDataProvider; +import net.fabricmc.fabric.api.datagen.v1.provider.FabricDynamicRegistryProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider; import net.fabricmc.fabric.api.event.registry.DynamicRegistries; -import net.minecraft.core.*; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.RegistrySetBuilder; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.DataProvider; import net.minecraft.data.PackOutput; import net.minecraft.data.tags.TagsProvider; -import net.minecraft.resources.RegistryDataLoader; -import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; -import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; -import java.util.function.BiFunction; import java.util.function.Consumer; -import java.util.stream.Stream; public class FabricDataGenerators implements DataGeneratorEntrypoint { @Override public void onInitializeDataGenerator(FabricDataGenerator generator) { - var pack = new PlatformGeneratorsImpl(generator.createPack()); + var pack = new PlatformGeneratorsImpl(generator.createPack(), generator.getRegistries()); DataProviders.add(pack); } - private record PlatformGeneratorsImpl(FabricDataGenerator.Pack generator) implements DataProviders.GeneratorSink { + private record PlatformGeneratorsImpl( + FabricDataGenerator.Pack generator, CompletableFuture registries + ) implements DataProviders.GeneratorSink { public T addWithFabricOutput(FabricDataGenerator.Pack.Factory factory) { return generator.addProvider((FabricDataOutput p) -> new PrettyDataProvider<>(factory.create(p))).provider(); } @@ -53,11 +52,6 @@ public class FabricDataGenerators implements DataGeneratorEntrypoint { return addWithFabricOutput(factory::create); } - @Override - public T add(BiFunction, T> factory) { - return addWithRegistries(factory::apply); - } - @Override public void addFromCodec(String name, PackType type, String directory, Codec codec, Consumer> output) { addWithRegistries((out, registries) -> { @@ -111,61 +105,24 @@ public class FabricDataGenerators implements DataGeneratorEntrypoint { } @Override - public CompletableFuture createPatchedRegistries(CompletableFuture registries, RegistrySetBuilder patch) { - return registries.thenApply(oldRegistries -> { - var factory = new Cloner.Factory(); - DynamicRegistries.getDynamicRegistries().forEach(registryData -> registryData.runWithArguments(factory::addCodec)); - return patch.buildPatch(RegistryAccess.fromRegistryOfRegistries(BuiltInRegistries.REGISTRY), new DynamicRegistryLookup(oldRegistries), factory); + public void registries(CompletableFuture registries) { + addWithFabricOutput(out -> new FabricDynamicRegistryProvider(out, registries.thenApply(RegistrySetBuilder.PatchedRegistries::patches)) { + @Override + public String getName() { + return "Registries"; + } + + @Override + protected void configure(HolderLookup.Provider registries, Entries entries) { + for (var reg : DynamicRegistries.getDynamicRegistries()) { + registries.lookupOrThrow(reg.key()).listElements().forEach(x -> register(entries, x)); + } + } + + private static void register(Entries entries, Holder.Reference reference) { + entries.add(reference.key(), reference.value()); + } }); } - - /** - * A {@link HolderLookup.Provider} implementation that adds any Fabric dynamic registry, if missing. - * - * @param parent The parent registry. - */ - private record DynamicRegistryLookup(HolderLookup.Provider parent) implements HolderLookup.Provider { - @Override - public Stream>> listRegistries() { - return Stream.concat( - parent.listRegistries(), - DynamicRegistries.getDynamicRegistries().stream().map(RegistryDataLoader.RegistryData::key) - ).distinct(); - } - - @Override - public Optional> lookup(ResourceKey> registryKey) { - return parent.lookup(registryKey).or(() -> Optional.of(new EmptyRegistry<>(registryKey))); - } - } - - private record EmptyRegistry( - ResourceKey> key - ) implements HolderLookup.RegistryLookup { - @Override - public Lifecycle registryLifecycle() { - return Lifecycle.stable(); - } - - @Override - public Stream> listElements() { - return Stream.empty(); - } - - @Override - public Stream> listTags() { - return Stream.empty(); - } - - @Override - public Optional> get(ResourceKey resourceKey) { - return Optional.empty(); - } - - @Override - public Optional> get(TagKey tagKey) { - return Optional.empty(); - } - } } } 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 425349db2..4a459cf2e 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java @@ -8,6 +8,8 @@ import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.detail.FabricDetailRegistries; import dan200.computercraft.api.network.wired.WiredElementLookup; import dan200.computercraft.api.peripheral.PeripheralLookup; +import dan200.computercraft.api.pocket.IPocketUpgrade; +import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.impl.Peripherals; import dan200.computercraft.impl.PocketUpgrades; import dan200.computercraft.impl.TurtleUpgrades; @@ -66,8 +68,8 @@ public class ComputerCraft { FabricRegistryBuilder.createSimple(RecipeFunction.REGISTRY).attribute(RegistryAttribute.SYNCED).buildAndRegister(); - DynamicRegistries.registerSynced(ModRegistry.TURTLE_UPGRADE, TurtleUpgrades.instance().upgradeCodec()); - DynamicRegistries.registerSynced(ModRegistry.POCKET_UPGRADE, PocketUpgrades.instance().upgradeCodec()); + DynamicRegistries.registerSynced(ITurtleUpgrade.REGISTRY, TurtleUpgrades.instance().upgradeCodec()); + DynamicRegistries.registerSynced(IPocketUpgrade.REGISTRY, PocketUpgrades.instance().upgradeCodec()); ModRegistry.register(); ModRegistry.registerMainThread(); 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 bc13cc7f6..c38c23a2d 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 @@ -5,11 +5,8 @@ package dan200.computercraft.shared.platform; import com.google.auto.service.AutoService; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.serialization.JsonOps; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.network.wired.WiredElement; import dan200.computercraft.api.network.wired.WiredElementLookup; @@ -27,14 +24,11 @@ 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.resource.conditions.v1.ResourceCondition; -import net.fabricmc.fabric.api.resource.conditions.v1.ResourceConditions; 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; import net.fabricmc.fabric.api.transfer.v1.item.InventoryStorage; import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage; -import net.fabricmc.loader.api.FabricLoader; import net.minecraft.commands.synchronization.ArgumentTypeInfo; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -49,7 +43,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; -import net.minecraft.util.GsonHelper; import net.minecraft.world.Container; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -79,13 +72,8 @@ import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.Supplier; -@AutoService(dan200.computercraft.impl.PlatformHelper.class) +@AutoService(PlatformHelper.class) public class PlatformHelperImpl implements PlatformHelper { - @Override - public boolean isDevelopmentEnvironment() { - return FabricLoader.getInstance().isDevelopmentEnvironment(); - } - @Override public ConfigFile.Builder createConfigBuilder() { return new FabricConfigFile.Builder(); @@ -103,22 +91,6 @@ public class PlatformHelperImpl implements PlatformHelper { return new RegistrationHelperImpl<>(getRegistry(registry)); } - @Override - public boolean shouldLoadResource(JsonObject object) { - return true; // Done by default in Fabric, so can be skipped - } - - @Override - public void addRequiredModCondition(JsonObject object, String modId) { - var conditions = GsonHelper.getAsJsonArray(object, ResourceConditions.CONDITIONS_KEY, null); - if (conditions == null) { - conditions = new JsonArray(); - object.add(ResourceConditions.CONDITIONS_KEY, conditions); - } - - conditions.add(ResourceCondition.CODEC.encodeStart(JsonOps.INSTANCE, ResourceConditions.allModsLoaded(modId)).getOrThrow()); - } - @Override public , T extends ArgumentTypeInfo.Template, I extends ArgumentTypeInfo> I registerArgumentTypeInfo(Class klass, I info) { ArgumentTypeInfosAccessor.classMap().put(klass, info); @@ -171,7 +143,6 @@ public class PlatformHelperImpl implements PlatformHelper { Ingredient.of(ConventionalItemTags.REDSTONE_DUSTS), Ingredient.of(ConventionalItemTags.STRINGS), Ingredient.of(Items.LEATHER), - Ingredient.of(ConventionalItemTags.STONES), Ingredient.of(ConventionalItemTags.GLASS_PANES), Ingredient.of(ConventionalItemTags.GOLD_INGOTS), Ingredient.of(ConventionalItemTags.STORAGE_BLOCKS_GOLD), diff --git a/projects/fabric/src/main/resources/fabric.mod.json b/projects/fabric/src/main/resources/fabric.mod.json index ee31e2f46..63268f2b8 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.97.3", - "minecraft": ">=1.20.5 <1.20.7" + "minecraft": "=1.20.6" }, "accessWidener": "computercraft.accesswidener" } diff --git a/projects/forge-api/build.gradle.kts b/projects/forge-api/build.gradle.kts index 388124590..6430b1de6 100644 --- a/projects/forge-api/build.gradle.kts +++ b/projects/forge-api/build.gradle.kts @@ -15,6 +15,11 @@ cct.inlineProject(":common-api") dependencies { api(project(":core-api")) + + // FIXME: This should be implementation (and in the common Forge config) + // but NeoGradle does weird things and we end up with two Forge deps on the + // classpath - https://github.com/neoforged/NeoGradle/issues/162. + compileOnly("net.neoforged:neoforge:${libs.versions.neoForge.get()}") } tasks.javadoc { diff --git a/projects/forge/build.gradle.kts b/projects/forge/build.gradle.kts index 675070fcd..5ce56c5f5 100644 --- a/projects/forge/build.gradle.kts +++ b/projects/forge/build.gradle.kts @@ -89,7 +89,7 @@ runs { } val gameTestClient by registering { - configure(runTypes.client) + configure(runTypes.named("client")) workingDirectory(file("run/testClient")) configureForGameTest() @@ -121,6 +121,8 @@ dependencies { compileOnly(libs.bundles.externalMods.forge.compile) runtimeOnly(libs.bundles.externalMods.forge.runtime) { cct.exclude(this) } + implementation("net.neoforged:neoforge:${libs.versions.neoForge.get()}") + // Depend on our other projects. api(commonClasses(project(":forge-api"))) { cct.exclude(this) } clientApi(clientClasses(project(":forge-api"))) { cct.exclude(this) } diff --git a/projects/forge/src/generated/resources/data/computercraft/recipes/printed_book.json b/projects/forge/src/generated/resources/data/computercraft/recipes/printed_book.json index 3023f6311..796495877 100644 --- a/projects/forge/src/generated/resources/data/computercraft/recipes/printed_book.json +++ b/projects/forge/src/generated/resources/data/computercraft/recipes/printed_book.json @@ -1,6 +1,6 @@ { "type": "computercraft:impostor_shapeless", "category": "redstone", - "ingredients": [{"tag": "c:leather"}, {"item": "computercraft:printed_page"}, {"tag": "c:strings"}], + "ingredients": [{"tag": "c:leathers"}, {"item": "computercraft:printed_page"}, {"tag": "c:strings"}], "result": {"count": 1, "id": "computercraft:printed_book"} } diff --git a/projects/forge/src/generated/resources/data/computercraft/recipes/wireless_modem_normal.json b/projects/forge/src/generated/resources/data/computercraft/recipes/wireless_modem_normal.json index 93b0e0017..1002c7bac 100644 --- a/projects/forge/src/generated/resources/data/computercraft/recipes/wireless_modem_normal.json +++ b/projects/forge/src/generated/resources/data/computercraft/recipes/wireless_modem_normal.json @@ -1,7 +1,7 @@ { "type": "minecraft:crafting_shaped", "category": "redstone", - "key": {"#": {"tag": "c:stones"}, "E": {"tag": "c:ender_pearls"}}, + "key": {"#": {"item": "minecraft:stone"}, "E": {"tag": "c:ender_pearls"}}, "pattern": ["###", "#E#", "###"], "result": {"count": 1, "id": "computercraft:wireless_modem_normal"} } diff --git a/projects/forge/src/main/java/dan200/computercraft/ComputerCraft.java b/projects/forge/src/main/java/dan200/computercraft/ComputerCraft.java index 1d2de4570..d4351b17c 100644 --- a/projects/forge/src/main/java/dan200/computercraft/ComputerCraft.java +++ b/projects/forge/src/main/java/dan200/computercraft/ComputerCraft.java @@ -90,8 +90,8 @@ public final class ComputerCraft { @SubscribeEvent public static void registerDynamicRegistries(DataPackRegistryEvent.NewRegistry event) { - event.dataPackRegistry(ModRegistry.TURTLE_UPGRADE, TurtleUpgrades.instance().upgradeCodec(), TurtleUpgrades.instance().upgradeCodec()); - event.dataPackRegistry(ModRegistry.POCKET_UPGRADE, PocketUpgrades.instance().upgradeCodec(), PocketUpgrades.instance().upgradeCodec()); + event.dataPackRegistry(ITurtleUpgrade.REGISTRY, TurtleUpgrades.instance().upgradeCodec(), TurtleUpgrades.instance().upgradeCodec()); + event.dataPackRegistry(IPocketUpgrade.REGISTRY, PocketUpgrades.instance().upgradeCodec(), PocketUpgrades.instance().upgradeCodec()); } @SubscribeEvent diff --git a/projects/forge/src/main/java/dan200/computercraft/data/Generators.java b/projects/forge/src/main/java/dan200/computercraft/data/Generators.java index 00fde1e7a..ea6f0b744 100644 --- a/projects/forge/src/main/java/dan200/computercraft/data/Generators.java +++ b/projects/forge/src/main/java/dan200/computercraft/data/Generators.java @@ -7,6 +7,7 @@ package dan200.computercraft.data; import com.mojang.serialization.Codec; import dan200.computercraft.api.ComputerCraftAPI; import net.minecraft.core.HolderLookup; +import net.minecraft.core.RegistrySetBuilder; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.DataGenerator; import net.minecraft.data.DataProvider; @@ -21,13 +22,13 @@ import net.minecraft.world.level.block.Block; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.common.data.BlockTagsProvider; +import net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider; import net.neoforged.neoforge.common.data.ExistingFileHelper; import net.neoforged.neoforge.common.data.JsonCodecProvider; import net.neoforged.neoforge.data.event.GatherDataEvent; import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; -import java.util.function.BiFunction; import java.util.function.Consumer; @EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) @@ -48,11 +49,6 @@ public class Generators { return generator.addProvider(p -> new PrettyDataProvider<>(factory.create(p))).provider(); } - @Override - public T add(BiFunction, T> factory) { - return generator.addProvider(p -> new PrettyDataProvider<>(factory.apply(p, registries))).provider(); - } - @Override public void addFromCodec(String name, PackType type, String directory, Codec codec, Consumer> output) { add(out -> { @@ -99,5 +95,10 @@ public class Generators { } }); } + + @Override + public void registries(CompletableFuture registries) { + add(out -> new DatapackBuiltinEntriesProvider(out, registries, null)); + } } } 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 9c37bbec3..c841d4aab 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 @@ -5,11 +5,8 @@ package dan200.computercraft.shared.platform; import com.google.auto.service.AutoService; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.serialization.JsonOps; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.network.wired.WiredElement; @@ -32,7 +29,6 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.TagKey; -import net.minecraft.util.GsonHelper; import net.minecraft.world.Container; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -54,16 +50,12 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.neoforged.bus.api.Event; -import net.neoforged.fml.loading.FMLLoader; import net.neoforged.neoforge.capabilities.BlockCapability; import net.neoforged.neoforge.capabilities.BlockCapabilityCache; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.common.CommonHooks; import net.neoforged.neoforge.common.Tags; import net.neoforged.neoforge.common.ToolActions; -import net.neoforged.neoforge.common.conditions.ConditionalOps; -import net.neoforged.neoforge.common.conditions.ICondition; -import net.neoforged.neoforge.common.conditions.ModLoadedCondition; import net.neoforged.neoforge.common.extensions.IMenuTypeExtension; import net.neoforged.neoforge.event.EventHooks; import net.neoforged.neoforge.items.wrapper.InvWrapper; @@ -78,13 +70,8 @@ import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.Supplier; -@AutoService(dan200.computercraft.impl.PlatformHelper.class) +@AutoService(PlatformHelper.class) public class PlatformHelperImpl implements PlatformHelper { - @Override - public boolean isDevelopmentEnvironment() { - return !FMLLoader.isProduction(); - } - @Override public ConfigFile.Builder createConfigBuilder() { return new ForgeConfigFile.Builder(); @@ -95,23 +82,6 @@ public class PlatformHelperImpl implements PlatformHelper { return new RegistrationHelperImpl<>(DeferredRegister.create(registry, ComputerCraftAPI.MOD_ID)); } - @Override - public boolean shouldLoadResource(JsonObject object) { - return ICondition.conditionsMatched(JsonOps.INSTANCE, object); - } - - @Override - public void addRequiredModCondition(JsonObject object, String modId) { - // FIXME: Test this, though maybe this should be implemented a different way anyway? - var conditions = GsonHelper.getAsJsonArray(object, ConditionalOps.DEFAULT_CONDITIONS_KEY, null); - if (conditions == null) { - conditions = new JsonArray(); - object.add(ConditionalOps.DEFAULT_CONDITIONS_KEY, conditions); - } - - conditions.add(ICondition.CODEC.encodeStart(JsonOps.INSTANCE, new ModLoadedCondition(modId)).getOrThrow()); - } - @Override public , T extends ArgumentTypeInfo.Template, I extends ArgumentTypeInfo> I registerArgumentTypeInfo(Class klass, I info) { return ArgumentTypeInfos.registerByClass(klass, info); @@ -169,7 +139,6 @@ public class PlatformHelperImpl implements PlatformHelper { Ingredient.of(Tags.Items.DUSTS_REDSTONE), Ingredient.of(Tags.Items.STRINGS), Ingredient.of(Tags.Items.LEATHERS), - Ingredient.of(Tags.Items.STONES), Ingredient.of(Tags.Items.GLASS_PANES), Ingredient.of(Tags.Items.INGOTS_GOLD), Ingredient.of(Tags.Items.STORAGE_BLOCKS_GOLD), 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 f4712babe..726ecfe82 100644 --- a/projects/forge/src/main/resources/META-INF/neoforge.mods.toml +++ b/projects/forge/src/main/resources/META-INF/neoforge.mods.toml @@ -26,7 +26,7 @@ CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles a [[dependencies.computercraft]] modId="neoforge" type="required" - versionRange="[${neoVersion},20.6)" + versionRange="[${neoVersion},20.7)" ordering="NONE" side="BOTH"