2023-03-15 21:52:13 +00:00
|
|
|
// SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2020-01-29 16:41:26 +00:00
|
|
|
package dan200.computercraft.data;
|
|
|
|
|
2022-10-22 09:48:30 +00:00
|
|
|
import com.google.gson.JsonObject;
|
Try to make recipe serialisers more reusable
This attempts to reduce some duplication in recipe serialisation (and
deserialisation) by moving the structure of a recipe (group, category,
ingredients, result) into seprate types.
- Add ShapedRecipeSpec and ShapelessRecipeSpec, which store the core
properties of shaped and shapeless recipes. There's a couple of
additional classes here for handling some of the other shared or
complex logic.
- These classes are now used by two new Custom{Shaped,Shapeless}Recipe
classes, which are (mostly) equivalent to Minecraft's
shaped/shapeless recipes, just with support for nbt in results.
- All the other similar recipes now inherit from these base classes,
which allows us to reuse a lot of this serialisation code. Alas, the
total code size has still gone up - maybe there's too much
abstraction here :).
- Mostly unrelated, but fix the skull recipes using the wrong UUID
format.
This allows us to remove our mixin for nbt in recipes (as we just use
our custom recipe now) and simplify serialisation a bit - hopefully
making the switch to codecs a little easier.
2023-09-23 17:24:02 +00:00
|
|
|
import com.mojang.authlib.GameProfile;
|
2024-01-31 20:55:14 +00:00
|
|
|
import com.mojang.serialization.JsonOps;
|
2022-11-09 20:10:24 +00:00
|
|
|
import dan200.computercraft.api.ComputerCraftAPI;
|
Rewrite turtle upgrade registration to be more data driven (#967)
The feature nobody asked for, but we're getting anyway.
Old way to register a turtle/pocket computer upgrade:
ComputerCraftAPI.registerTurtleUpgrade(new MyUpgrade(new ResourceLocation("my_mod", "my_upgrade")));
New way to register a turtle/pocket computer upgrade:
First, define a serialiser for your turtle upgrade type:
static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
SERIALISERS.register(bus); // Call in your mod constructor.
Now either create a JSON string or use a data generator to register your upgrades:
class TurtleDataGenerator extends TurtleUpgradeDataProvider {
@Override
protected void addUpgrades( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade )
simple(new ResourceLocation("my_mod", my_upgrade"), MY_UPGRADE.get()).add(addUpgrade);
}
}
See much better! In all seriousness, this does offer some benefits,
namely that it's now possible to overwrite or create upgrades via
datapacks.
Actual changes:
- Remove ComputerCraftAPI.register{Turtle,Pocket}Upgrade functions.
- Instead add {Turtle,Pocket}UpgradeSerialiser classes, which are used
to load upgrades from JSON files in datapacks, and then read/write
them to network packets (much like recipe serialisers).
- The upgrade registries now subscribe to datapack reload events. They
find all JSON files in the
data/$mod_id/computercraft/{turtle,pocket}_upgrades directories,
parse them, and then register them as upgrades.
Once datapacks have fully reloaded, these upgrades are then sent over
the network to the client.
- Add data generators for turtle and pocket computer upgrades, to make
the creation of JSON files a bit easier.
- Port all of CC:T's upgrades over to use the new system.
2021-11-26 23:36:02 +00:00
|
|
|
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
|
|
|
|
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
|
2023-07-02 09:55:55 +00:00
|
|
|
import dan200.computercraft.api.upgrades.UpgradeData;
|
2022-11-06 18:27:21 +00:00
|
|
|
import dan200.computercraft.core.util.Colour;
|
2024-01-31 20:55:14 +00:00
|
|
|
import dan200.computercraft.data.recipe.ShapedSpecBuilder;
|
|
|
|
import dan200.computercraft.data.recipe.ShapelessSpecBuilder;
|
|
|
|
import dan200.computercraft.impl.RegistryHelper;
|
2022-11-06 17:14:53 +00:00
|
|
|
import dan200.computercraft.shared.ModRegistry;
|
2024-01-31 20:55:14 +00:00
|
|
|
import dan200.computercraft.shared.common.ClearColourRecipe;
|
|
|
|
import dan200.computercraft.shared.common.ColourableRecipe;
|
2024-04-25 20:32:48 +00:00
|
|
|
import dan200.computercraft.shared.computer.recipe.ComputerConvertRecipe;
|
2024-01-31 20:55:14 +00:00
|
|
|
import dan200.computercraft.shared.media.recipes.DiskRecipe;
|
|
|
|
import dan200.computercraft.shared.media.recipes.PrintoutRecipe;
|
2022-11-09 10:59:05 +00:00
|
|
|
import dan200.computercraft.shared.platform.PlatformHelper;
|
|
|
|
import dan200.computercraft.shared.platform.RecipeIngredients;
|
2023-06-04 10:24:04 +00:00
|
|
|
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
|
2024-01-31 20:55:14 +00:00
|
|
|
import dan200.computercraft.shared.pocket.recipes.PocketComputerUpgradeRecipe;
|
|
|
|
import dan200.computercraft.shared.recipe.ImpostorShapedRecipe;
|
|
|
|
import dan200.computercraft.shared.recipe.ImpostorShapelessRecipe;
|
2023-06-04 10:24:04 +00:00
|
|
|
import dan200.computercraft.shared.turtle.items.TurtleItem;
|
2024-01-31 20:55:14 +00:00
|
|
|
import dan200.computercraft.shared.turtle.recipes.TurtleOverlayRecipe;
|
|
|
|
import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe;
|
2023-03-31 17:14:44 +00:00
|
|
|
import dan200.computercraft.shared.util.ColourUtils;
|
2024-04-25 20:32:48 +00:00
|
|
|
import dan200.computercraft.shared.util.DataComponentUtil;
|
2024-01-31 20:55:14 +00:00
|
|
|
import net.minecraft.advancements.Criterion;
|
2021-08-03 20:46:53 +00:00
|
|
|
import net.minecraft.advancements.critereon.InventoryChangeTrigger;
|
|
|
|
import net.minecraft.advancements.critereon.ItemPredicate;
|
2024-04-25 20:32:48 +00:00
|
|
|
import net.minecraft.core.HolderLookup;
|
|
|
|
import net.minecraft.core.component.DataComponents;
|
2024-01-31 20:55:14 +00:00
|
|
|
import net.minecraft.core.registries.BuiltInRegistries;
|
2022-12-08 19:45:02 +00:00
|
|
|
import net.minecraft.core.registries.Registries;
|
|
|
|
import net.minecraft.data.PackOutput;
|
2024-01-31 20:55:14 +00:00
|
|
|
import net.minecraft.data.recipes.RecipeCategory;
|
|
|
|
import net.minecraft.data.recipes.RecipeOutput;
|
|
|
|
import net.minecraft.data.recipes.ShapedRecipeBuilder;
|
|
|
|
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
|
2021-08-03 20:46:53 +00:00
|
|
|
import net.minecraft.resources.ResourceLocation;
|
2024-04-25 20:32:48 +00:00
|
|
|
import net.minecraft.tags.ItemTags;
|
2022-03-03 09:17:18 +00:00
|
|
|
import net.minecraft.tags.TagKey;
|
2022-11-09 10:59:05 +00:00
|
|
|
import net.minecraft.util.GsonHelper;
|
Try to make recipe serialisers more reusable
This attempts to reduce some duplication in recipe serialisation (and
deserialisation) by moving the structure of a recipe (group, category,
ingredients, result) into seprate types.
- Add ShapedRecipeSpec and ShapelessRecipeSpec, which store the core
properties of shaped and shapeless recipes. There's a couple of
additional classes here for handling some of the other shared or
complex logic.
- These classes are now used by two new Custom{Shaped,Shapeless}Recipe
classes, which are (mostly) equivalent to Minecraft's
shaped/shapeless recipes, just with support for nbt in results.
- All the other similar recipes now inherit from these base classes,
which allows us to reuse a lot of this serialisation code. Alas, the
total code size has still gone up - maybe there's too much
abstraction here :).
- Mostly unrelated, but fix the skull recipes using the wrong UUID
format.
This allows us to remove our mixin for nbt in recipes (as we just use
our custom recipe now) and simplify serialisation a bit - hopefully
making the switch to codecs a little easier.
2023-09-23 17:24:02 +00:00
|
|
|
import net.minecraft.world.item.*;
|
2024-04-25 20:32:48 +00:00
|
|
|
import net.minecraft.world.item.component.DyedItemColor;
|
|
|
|
import net.minecraft.world.item.component.ResolvableProfile;
|
2024-01-31 20:55:14 +00:00
|
|
|
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
2022-11-09 10:59:05 +00:00
|
|
|
import net.minecraft.world.item.crafting.Ingredient;
|
2024-01-31 20:55:14 +00:00
|
|
|
import net.minecraft.world.item.crafting.Recipe;
|
2021-08-03 20:46:53 +00:00
|
|
|
import net.minecraft.world.level.ItemLike;
|
2022-11-09 10:59:05 +00:00
|
|
|
import net.minecraft.world.level.block.Blocks;
|
2020-01-29 16:41:26 +00:00
|
|
|
|
2023-06-04 10:24:04 +00:00
|
|
|
import java.util.List;
|
Try to make recipe serialisers more reusable
This attempts to reduce some duplication in recipe serialisation (and
deserialisation) by moving the structure of a recipe (group, category,
ingredients, result) into seprate types.
- Add ShapedRecipeSpec and ShapelessRecipeSpec, which store the core
properties of shaped and shapeless recipes. There's a couple of
additional classes here for handling some of the other shared or
complex logic.
- These classes are now used by two new Custom{Shaped,Shapeless}Recipe
classes, which are (mostly) equivalent to Minecraft's
shaped/shapeless recipes, just with support for nbt in results.
- All the other similar recipes now inherit from these base classes,
which allows us to reuse a lot of this serialisation code. Alas, the
total code size has still gone up - maybe there's too much
abstraction here :).
- Mostly unrelated, but fix the skull recipes using the wrong UUID
format.
This allows us to remove our mixin for nbt in recipes (as we just use
our custom recipe now) and simplify serialisation a bit - hopefully
making the switch to codecs a little easier.
2023-09-23 17:24:02 +00:00
|
|
|
import java.util.UUID;
|
2024-04-25 20:32:48 +00:00
|
|
|
import java.util.concurrent.CompletableFuture;
|
2020-01-29 16:41:26 +00:00
|
|
|
import java.util.function.Consumer;
|
|
|
|
|
Rewrite turtle upgrade registration to be more data driven (#967)
The feature nobody asked for, but we're getting anyway.
Old way to register a turtle/pocket computer upgrade:
ComputerCraftAPI.registerTurtleUpgrade(new MyUpgrade(new ResourceLocation("my_mod", "my_upgrade")));
New way to register a turtle/pocket computer upgrade:
First, define a serialiser for your turtle upgrade type:
static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
SERIALISERS.register(bus); // Call in your mod constructor.
Now either create a JSON string or use a data generator to register your upgrades:
class TurtleDataGenerator extends TurtleUpgradeDataProvider {
@Override
protected void addUpgrades( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade )
simple(new ResourceLocation("my_mod", my_upgrade"), MY_UPGRADE.get()).add(addUpgrade);
}
}
See much better! In all seriousness, this does offer some benefits,
namely that it's now possible to overwrite or create upgrades via
datapacks.
Actual changes:
- Remove ComputerCraftAPI.register{Turtle,Pocket}Upgrade functions.
- Instead add {Turtle,Pocket}UpgradeSerialiser classes, which are used
to load upgrades from JSON files in datapacks, and then read/write
them to network packets (much like recipe serialisers).
- The upgrade registries now subscribe to datapack reload events. They
find all JSON files in the
data/$mod_id/computercraft/{turtle,pocket}_upgrades directories,
parse them, and then register them as upgrades.
Once datapacks have fully reloaded, these upgrades are then sent over
the network to the client.
- Add data generators for turtle and pocket computer upgrades, to make
the creation of JSON files a bit easier.
- Port all of CC:T's upgrades over to use the new system.
2021-11-26 23:36:02 +00:00
|
|
|
import static dan200.computercraft.api.ComputerCraftTags.Items.COMPUTER;
|
|
|
|
import static dan200.computercraft.api.ComputerCraftTags.Items.WIRED_MODEM;
|
2021-10-27 18:16:32 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
2022-11-09 10:59:05 +00:00
|
|
|
private final RecipeIngredients ingredients = PlatformHelper.get().getRecipeIngredients();
|
Rewrite turtle upgrade registration to be more data driven (#967)
The feature nobody asked for, but we're getting anyway.
Old way to register a turtle/pocket computer upgrade:
ComputerCraftAPI.registerTurtleUpgrade(new MyUpgrade(new ResourceLocation("my_mod", "my_upgrade")));
New way to register a turtle/pocket computer upgrade:
First, define a serialiser for your turtle upgrade type:
static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
SERIALISERS.register(bus); // Call in your mod constructor.
Now either create a JSON string or use a data generator to register your upgrades:
class TurtleDataGenerator extends TurtleUpgradeDataProvider {
@Override
protected void addUpgrades( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade )
simple(new ResourceLocation("my_mod", my_upgrade"), MY_UPGRADE.get()).add(addUpgrade);
}
}
See much better! In all seriousness, this does offer some benefits,
namely that it's now possible to overwrite or create upgrades via
datapacks.
Actual changes:
- Remove ComputerCraftAPI.register{Turtle,Pocket}Upgrade functions.
- Instead add {Turtle,Pocket}UpgradeSerialiser classes, which are used
to load upgrades from JSON files in datapacks, and then read/write
them to network packets (much like recipe serialisers).
- The upgrade registries now subscribe to datapack reload events. They
find all JSON files in the
data/$mod_id/computercraft/{turtle,pocket}_upgrades directories,
parse them, and then register them as upgrades.
Once datapacks have fully reloaded, these upgrades are then sent over
the network to the client.
- Add data generators for turtle and pocket computer upgrades, to make
the creation of JSON files a bit easier.
- Port all of CC:T's upgrades over to use the new system.
2021-11-26 23:36:02 +00:00
|
|
|
private final TurtleUpgradeDataProvider turtleUpgrades;
|
|
|
|
private final PocketUpgradeDataProvider pocketUpgrades;
|
|
|
|
|
2024-04-25 20:32:48 +00:00
|
|
|
RecipeProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> registries, TurtleUpgradeDataProvider turtleUpgrades, PocketUpgradeDataProvider pocketUpgrades) {
|
|
|
|
super(output, registries);
|
Rewrite turtle upgrade registration to be more data driven (#967)
The feature nobody asked for, but we're getting anyway.
Old way to register a turtle/pocket computer upgrade:
ComputerCraftAPI.registerTurtleUpgrade(new MyUpgrade(new ResourceLocation("my_mod", "my_upgrade")));
New way to register a turtle/pocket computer upgrade:
First, define a serialiser for your turtle upgrade type:
static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
SERIALISERS.register(bus); // Call in your mod constructor.
Now either create a JSON string or use a data generator to register your upgrades:
class TurtleDataGenerator extends TurtleUpgradeDataProvider {
@Override
protected void addUpgrades( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade )
simple(new ResourceLocation("my_mod", my_upgrade"), MY_UPGRADE.get()).add(addUpgrade);
}
}
See much better! In all seriousness, this does offer some benefits,
namely that it's now possible to overwrite or create upgrades via
datapacks.
Actual changes:
- Remove ComputerCraftAPI.register{Turtle,Pocket}Upgrade functions.
- Instead add {Turtle,Pocket}UpgradeSerialiser classes, which are used
to load upgrades from JSON files in datapacks, and then read/write
them to network packets (much like recipe serialisers).
- The upgrade registries now subscribe to datapack reload events. They
find all JSON files in the
data/$mod_id/computercraft/{turtle,pocket}_upgrades directories,
parse them, and then register them as upgrades.
Once datapacks have fully reloaded, these upgrades are then sent over
the network to the client.
- Add data generators for turtle and pocket computer upgrades, to make
the creation of JSON files a bit easier.
- Port all of CC:T's upgrades over to use the new system.
2021-11-26 23:36:02 +00:00
|
|
|
this.turtleUpgrades = turtleUpgrades;
|
|
|
|
this.pocketUpgrades = pocketUpgrades;
|
2020-01-29 16:41:26 +00:00
|
|
|
}
|
|
|
|
|
2022-12-08 19:45:02 +00:00
|
|
|
@Override
|
2024-01-31 20:55:14 +00:00
|
|
|
public void buildRecipes(RecipeOutput add) {
|
2020-02-08 23:26:05 +00:00
|
|
|
basicRecipes(add);
|
2020-01-29 16:41:26 +00:00
|
|
|
diskColours(add);
|
|
|
|
pocketUpgrades(add);
|
|
|
|
turtleUpgrades(add);
|
2023-03-31 17:14:44 +00:00
|
|
|
turtleOverlays(add);
|
2022-11-03 23:43:14 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
addSpecial(add, new PrintoutRecipe(CraftingBookCategory.MISC));
|
|
|
|
addSpecial(add, new DiskRecipe(CraftingBookCategory.MISC));
|
|
|
|
addSpecial(add, new ColourableRecipe(CraftingBookCategory.MISC));
|
|
|
|
addSpecial(add, new ClearColourRecipe(CraftingBookCategory.MISC));
|
|
|
|
addSpecial(add, new TurtleUpgradeRecipe(CraftingBookCategory.MISC));
|
|
|
|
addSpecial(add, new PocketComputerUpgradeRecipe(CraftingBookCategory.MISC));
|
2020-01-29 16:41:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a crafting recipe for a disk of every dye colour.
|
|
|
|
*
|
2024-01-31 20:55:14 +00:00
|
|
|
* @param output The callback to add recipes.
|
2020-01-29 16:41:26 +00:00
|
|
|
*/
|
2024-01-31 20:55:14 +00:00
|
|
|
private void diskColours(RecipeOutput output) {
|
2020-01-29 16:41:26 +00:00
|
|
|
for (var colour : Colour.VALUES) {
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapelessSpecBuilder
|
2024-04-25 20:32:48 +00:00
|
|
|
.shapeless(RecipeCategory.REDSTONE, DataComponentUtil.createStack(ModRegistry.Items.DISK.get(), DataComponents.DYED_COLOR, new DyedItemColor(colour.getHex(), false)))
|
2022-11-09 10:59:05 +00:00
|
|
|
.requires(ingredients.redstone())
|
|
|
|
.requires(Items.PAPER)
|
2021-01-09 19:22:58 +00:00
|
|
|
.requires(DyeItem.byColor(ofColour(colour)))
|
|
|
|
.group("computercraft:disk")
|
2022-11-06 17:14:53 +00:00
|
|
|
.unlockedBy("has_drive", inventoryChange(ModRegistry.Blocks.DISK_DRIVE.get()))
|
2024-01-31 20:55:14 +00:00
|
|
|
.build(ImpostorShapelessRecipe::new)
|
|
|
|
.save(output, new ResourceLocation(ComputerCraftAPI.MOD_ID, "disk_" + (colour.ordinal() + 1)));
|
2020-01-29 16:41:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-04 10:24:04 +00:00
|
|
|
private static List<TurtleItem> turtleItems() {
|
|
|
|
return List.of(ModRegistry.Items.TURTLE_NORMAL.get(), ModRegistry.Items.TURTLE_ADVANCED.get());
|
|
|
|
}
|
|
|
|
|
2020-01-29 16:41:26 +00:00
|
|
|
/**
|
|
|
|
* Register a crafting recipe for each turtle upgrade.
|
|
|
|
*
|
|
|
|
* @param add The callback to add recipes.
|
|
|
|
*/
|
2024-01-31 20:55:14 +00:00
|
|
|
private void turtleUpgrades(RecipeOutput add) {
|
2023-06-04 10:24:04 +00:00
|
|
|
for (var turtleItem : turtleItems()) {
|
2024-01-31 20:55:14 +00:00
|
|
|
var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, turtleItem);
|
2022-11-03 23:43:14 +00:00
|
|
|
|
Rewrite turtle upgrade registration to be more data driven (#967)
The feature nobody asked for, but we're getting anyway.
Old way to register a turtle/pocket computer upgrade:
ComputerCraftAPI.registerTurtleUpgrade(new MyUpgrade(new ResourceLocation("my_mod", "my_upgrade")));
New way to register a turtle/pocket computer upgrade:
First, define a serialiser for your turtle upgrade type:
static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
SERIALISERS.register(bus); // Call in your mod constructor.
Now either create a JSON string or use a data generator to register your upgrades:
class TurtleDataGenerator extends TurtleUpgradeDataProvider {
@Override
protected void addUpgrades( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade )
simple(new ResourceLocation("my_mod", my_upgrade"), MY_UPGRADE.get()).add(addUpgrade);
}
}
See much better! In all seriousness, this does offer some benefits,
namely that it's now possible to overwrite or create upgrades via
datapacks.
Actual changes:
- Remove ComputerCraftAPI.register{Turtle,Pocket}Upgrade functions.
- Instead add {Turtle,Pocket}UpgradeSerialiser classes, which are used
to load upgrades from JSON files in datapacks, and then read/write
them to network packets (much like recipe serialisers).
- The upgrade registries now subscribe to datapack reload events. They
find all JSON files in the
data/$mod_id/computercraft/{turtle,pocket}_upgrades directories,
parse them, and then register them as upgrades.
Once datapacks have fully reloaded, these upgrades are then sent over
the network to the client.
- Add data generators for turtle and pocket computer upgrades, to make
the creation of JSON files a bit easier.
- Port all of CC:T's upgrades over to use the new system.
2021-11-26 23:36:02 +00:00
|
|
|
for (var upgrade : turtleUpgrades.getGeneratedUpgrades()) {
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapedSpecBuilder
|
2024-04-25 20:32:48 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, DataComponentUtil.createStack(turtleItem, ModRegistry.DataComponents.RIGHT_TURTLE_UPGRADE.get(), UpgradeData.ofDefault(upgrade)))
|
Remove several usages of ComputerFamily
While ComputerFamily is still useful, there's definitely some places
where it adds an extra layer of indirection. This commit attempts to
clean up some places where we no longer need it.
- Remove ComputerFamily from AbstractComputerBlock. The only place this
was needed is in TurtleBlock, and that can be replaced with normal
Minecraft explosion resistence!
- Pass in the fuel limit to the turtle block entity, rather than
deriving it from current family.
- The turtle BERs now derive their model from the turtle's item, rather
than the turtle's family.
- When creating upgrade/overlay recipes, use the item's name, rather
than {pocket,turtle}_family. This means we can drop getFamily() from
IComputerItem (it is still needed on to handle the UI).
- We replace IComputerItem.withFamily with a method to change to a
different item of the same type. ComputerUpgradeRecipe no longer
takes a family, and instead just uses the result's item.
- Computer blocks now use the normal Block.asItem() to find their
corresponding item, rather than looking it up via family.
The above means we can remove all the family-based XyzItem.create(...)
methods, which have always felt a little ugly.
We still need ComputerFamily for a couple of things:
- Permission checks for command computers.
- Checks for mouse/colour support in ServerComputer.
- UI textures.
2023-12-20 14:16:56 +00:00
|
|
|
.group(name.toString())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("#T")
|
2024-04-25 20:32:48 +00:00
|
|
|
.define('T', turtleItem)
|
2021-10-11 11:17:45 +00:00
|
|
|
.define('#', upgrade.getCraftingItem().getItem())
|
2024-04-25 20:32:48 +00:00
|
|
|
.unlockedBy("has_items", inventoryChange(turtleItem, upgrade.getCraftingItem().getItem()))
|
2024-01-31 20:55:14 +00:00
|
|
|
.build(ImpostorShapedRecipe::new)
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(
|
2024-01-31 20:55:14 +00:00
|
|
|
add,
|
Remove several usages of ComputerFamily
While ComputerFamily is still useful, there's definitely some places
where it adds an extra layer of indirection. This commit attempts to
clean up some places where we no longer need it.
- Remove ComputerFamily from AbstractComputerBlock. The only place this
was needed is in TurtleBlock, and that can be replaced with normal
Minecraft explosion resistence!
- Pass in the fuel limit to the turtle block entity, rather than
deriving it from current family.
- The turtle BERs now derive their model from the turtle's item, rather
than the turtle's family.
- When creating upgrade/overlay recipes, use the item's name, rather
than {pocket,turtle}_family. This means we can drop getFamily() from
IComputerItem (it is still needed on to handle the UI).
- We replace IComputerItem.withFamily with a method to change to a
different item of the same type. ComputerUpgradeRecipe no longer
takes a family, and instead just uses the result's item.
- Computer blocks now use the normal Block.asItem() to find their
corresponding item, rather than looking it up via family.
The above means we can remove all the family-based XyzItem.create(...)
methods, which have always felt a little ugly.
We still need ComputerFamily for a couple of things:
- Permission checks for command computers.
- Checks for mouse/colour support in ServerComputer.
- UI textures.
2023-12-20 14:16:56 +00:00
|
|
|
name.withSuffix(String.format("/%s/%s", upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()))
|
2020-01-29 16:41:26 +00:00
|
|
|
);
|
Rewrite turtle upgrade registration to be more data driven (#967)
The feature nobody asked for, but we're getting anyway.
Old way to register a turtle/pocket computer upgrade:
ComputerCraftAPI.registerTurtleUpgrade(new MyUpgrade(new ResourceLocation("my_mod", "my_upgrade")));
New way to register a turtle/pocket computer upgrade:
First, define a serialiser for your turtle upgrade type:
static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
SERIALISERS.register(bus); // Call in your mod constructor.
Now either create a JSON string or use a data generator to register your upgrades:
class TurtleDataGenerator extends TurtleUpgradeDataProvider {
@Override
protected void addUpgrades( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade )
simple(new ResourceLocation("my_mod", my_upgrade"), MY_UPGRADE.get()).add(addUpgrade);
}
}
See much better! In all seriousness, this does offer some benefits,
namely that it's now possible to overwrite or create upgrades via
datapacks.
Actual changes:
- Remove ComputerCraftAPI.register{Turtle,Pocket}Upgrade functions.
- Instead add {Turtle,Pocket}UpgradeSerialiser classes, which are used
to load upgrades from JSON files in datapacks, and then read/write
them to network packets (much like recipe serialisers).
- The upgrade registries now subscribe to datapack reload events. They
find all JSON files in the
data/$mod_id/computercraft/{turtle,pocket}_upgrades directories,
parse them, and then register them as upgrades.
Once datapacks have fully reloaded, these upgrades are then sent over
the network to the client.
- Add data generators for turtle and pocket computer upgrades, to make
the creation of JSON files a bit easier.
- Port all of CC:T's upgrades over to use the new system.
2021-11-26 23:36:02 +00:00
|
|
|
}
|
2020-01-29 16:41:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-04 10:24:04 +00:00
|
|
|
private static List<PocketComputerItem> pocketComputerItems() {
|
|
|
|
return List.of(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get(), ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get());
|
|
|
|
}
|
|
|
|
|
2020-01-29 16:41:26 +00:00
|
|
|
/**
|
|
|
|
* Register a crafting recipe for each pocket upgrade.
|
|
|
|
*
|
|
|
|
* @param add The callback to add recipes.
|
|
|
|
*/
|
2024-01-31 20:55:14 +00:00
|
|
|
private void pocketUpgrades(RecipeOutput add) {
|
2023-06-04 10:24:04 +00:00
|
|
|
for (var pocket : pocketComputerItems()) {
|
2024-01-31 20:55:14 +00:00
|
|
|
var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, pocket).withPath(x -> x.replace("pocket_computer_", "pocket_"));
|
2022-11-03 23:43:14 +00:00
|
|
|
|
Rewrite turtle upgrade registration to be more data driven (#967)
The feature nobody asked for, but we're getting anyway.
Old way to register a turtle/pocket computer upgrade:
ComputerCraftAPI.registerTurtleUpgrade(new MyUpgrade(new ResourceLocation("my_mod", "my_upgrade")));
New way to register a turtle/pocket computer upgrade:
First, define a serialiser for your turtle upgrade type:
static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
SERIALISERS.register(bus); // Call in your mod constructor.
Now either create a JSON string or use a data generator to register your upgrades:
class TurtleDataGenerator extends TurtleUpgradeDataProvider {
@Override
protected void addUpgrades( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade )
simple(new ResourceLocation("my_mod", my_upgrade"), MY_UPGRADE.get()).add(addUpgrade);
}
}
See much better! In all seriousness, this does offer some benefits,
namely that it's now possible to overwrite or create upgrades via
datapacks.
Actual changes:
- Remove ComputerCraftAPI.register{Turtle,Pocket}Upgrade functions.
- Instead add {Turtle,Pocket}UpgradeSerialiser classes, which are used
to load upgrades from JSON files in datapacks, and then read/write
them to network packets (much like recipe serialisers).
- The upgrade registries now subscribe to datapack reload events. They
find all JSON files in the
data/$mod_id/computercraft/{turtle,pocket}_upgrades directories,
parse them, and then register them as upgrades.
Once datapacks have fully reloaded, these upgrades are then sent over
the network to the client.
- Add data generators for turtle and pocket computer upgrades, to make
the creation of JSON files a bit easier.
- Port all of CC:T's upgrades over to use the new system.
2021-11-26 23:36:02 +00:00
|
|
|
for (var upgrade : pocketUpgrades.getGeneratedUpgrades()) {
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapedSpecBuilder
|
2024-04-25 20:32:48 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, DataComponentUtil.createStack(pocket, ModRegistry.DataComponents.POCKET_UPGRADE.get(), UpgradeData.ofDefault(upgrade)))
|
Remove several usages of ComputerFamily
While ComputerFamily is still useful, there's definitely some places
where it adds an extra layer of indirection. This commit attempts to
clean up some places where we no longer need it.
- Remove ComputerFamily from AbstractComputerBlock. The only place this
was needed is in TurtleBlock, and that can be replaced with normal
Minecraft explosion resistence!
- Pass in the fuel limit to the turtle block entity, rather than
deriving it from current family.
- The turtle BERs now derive their model from the turtle's item, rather
than the turtle's family.
- When creating upgrade/overlay recipes, use the item's name, rather
than {pocket,turtle}_family. This means we can drop getFamily() from
IComputerItem (it is still needed on to handle the UI).
- We replace IComputerItem.withFamily with a method to change to a
different item of the same type. ComputerUpgradeRecipe no longer
takes a family, and instead just uses the result's item.
- Computer blocks now use the normal Block.asItem() to find their
corresponding item, rather than looking it up via family.
The above means we can remove all the family-based XyzItem.create(...)
methods, which have always felt a little ugly.
We still need ComputerFamily for a couple of things:
- Permission checks for command computers.
- Checks for mouse/colour support in ServerComputer.
- UI textures.
2023-12-20 14:16:56 +00:00
|
|
|
.group(name.toString())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("#")
|
|
|
|
.pattern("P")
|
2024-04-25 20:32:48 +00:00
|
|
|
.define('P', pocket)
|
2021-10-11 11:17:45 +00:00
|
|
|
.define('#', upgrade.getCraftingItem().getItem())
|
2024-04-25 20:32:48 +00:00
|
|
|
.unlockedBy("has_items", inventoryChange(pocket, upgrade.getCraftingItem().getItem()))
|
2024-01-31 20:55:14 +00:00
|
|
|
.build(ImpostorShapedRecipe::new)
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(
|
2024-01-31 20:55:14 +00:00
|
|
|
add,
|
Remove several usages of ComputerFamily
While ComputerFamily is still useful, there's definitely some places
where it adds an extra layer of indirection. This commit attempts to
clean up some places where we no longer need it.
- Remove ComputerFamily from AbstractComputerBlock. The only place this
was needed is in TurtleBlock, and that can be replaced with normal
Minecraft explosion resistence!
- Pass in the fuel limit to the turtle block entity, rather than
deriving it from current family.
- The turtle BERs now derive their model from the turtle's item, rather
than the turtle's family.
- When creating upgrade/overlay recipes, use the item's name, rather
than {pocket,turtle}_family. This means we can drop getFamily() from
IComputerItem (it is still needed on to handle the UI).
- We replace IComputerItem.withFamily with a method to change to a
different item of the same type. ComputerUpgradeRecipe no longer
takes a family, and instead just uses the result's item.
- Computer blocks now use the normal Block.asItem() to find their
corresponding item, rather than looking it up via family.
The above means we can remove all the family-based XyzItem.create(...)
methods, which have always felt a little ugly.
We still need ComputerFamily for a couple of things:
- Permission checks for command computers.
- Checks for mouse/colour support in ServerComputer.
- UI textures.
2023-12-20 14:16:56 +00:00
|
|
|
name.withSuffix(String.format("/%s/%s", upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()))
|
2020-01-29 16:41:26 +00:00
|
|
|
);
|
Rewrite turtle upgrade registration to be more data driven (#967)
The feature nobody asked for, but we're getting anyway.
Old way to register a turtle/pocket computer upgrade:
ComputerCraftAPI.registerTurtleUpgrade(new MyUpgrade(new ResourceLocation("my_mod", "my_upgrade")));
New way to register a turtle/pocket computer upgrade:
First, define a serialiser for your turtle upgrade type:
static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
SERIALISERS.register(bus); // Call in your mod constructor.
Now either create a JSON string or use a data generator to register your upgrades:
class TurtleDataGenerator extends TurtleUpgradeDataProvider {
@Override
protected void addUpgrades( @Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade )
simple(new ResourceLocation("my_mod", my_upgrade"), MY_UPGRADE.get()).add(addUpgrade);
}
}
See much better! In all seriousness, this does offer some benefits,
namely that it's now possible to overwrite or create upgrades via
datapacks.
Actual changes:
- Remove ComputerCraftAPI.register{Turtle,Pocket}Upgrade functions.
- Instead add {Turtle,Pocket}UpgradeSerialiser classes, which are used
to load upgrades from JSON files in datapacks, and then read/write
them to network packets (much like recipe serialisers).
- The upgrade registries now subscribe to datapack reload events. They
find all JSON files in the
data/$mod_id/computercraft/{turtle,pocket}_upgrades directories,
parse them, and then register them as upgrades.
Once datapacks have fully reloaded, these upgrades are then sent over
the network to the client.
- Add data generators for turtle and pocket computer upgrades, to make
the creation of JSON files a bit easier.
- Port all of CC:T's upgrades over to use the new system.
2021-11-26 23:36:02 +00:00
|
|
|
}
|
2020-01-29 16:41:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
private void turtleOverlays(RecipeOutput add) {
|
2023-03-31 17:14:44 +00:00
|
|
|
turtleOverlay(add, "turtle_trans_overlay", x -> x
|
|
|
|
.unlockedBy("has_dye", inventoryChange(itemPredicate(ingredients.dye())))
|
|
|
|
.requires(ColourUtils.getDyeTag(DyeColor.LIGHT_BLUE))
|
|
|
|
.requires(ColourUtils.getDyeTag(DyeColor.PINK))
|
|
|
|
.requires(ColourUtils.getDyeTag(DyeColor.WHITE))
|
|
|
|
.requires(Items.STICK)
|
|
|
|
);
|
|
|
|
|
|
|
|
turtleOverlay(add, "turtle_rainbow_overlay", x -> x
|
|
|
|
.unlockedBy("has_dye", inventoryChange(itemPredicate(ingredients.dye())))
|
|
|
|
.requires(ColourUtils.getDyeTag(DyeColor.RED))
|
|
|
|
.requires(ColourUtils.getDyeTag(DyeColor.ORANGE))
|
|
|
|
.requires(ColourUtils.getDyeTag(DyeColor.YELLOW))
|
|
|
|
.requires(ColourUtils.getDyeTag(DyeColor.GREEN))
|
|
|
|
.requires(ColourUtils.getDyeTag(DyeColor.BLUE))
|
|
|
|
.requires(ColourUtils.getDyeTag(DyeColor.PURPLE))
|
|
|
|
.requires(Items.STICK)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
private void turtleOverlay(RecipeOutput add, String overlay, Consumer<ShapelessSpecBuilder> build) {
|
2023-06-04 10:24:04 +00:00
|
|
|
for (var turtleItem : turtleItems()) {
|
2024-01-31 20:55:14 +00:00
|
|
|
var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, turtleItem);
|
2023-03-31 17:14:44 +00:00
|
|
|
|
2024-04-25 20:32:48 +00:00
|
|
|
var builder = ShapelessSpecBuilder.shapeless(RecipeCategory.REDSTONE, new ItemStack(turtleItem))
|
Remove several usages of ComputerFamily
While ComputerFamily is still useful, there's definitely some places
where it adds an extra layer of indirection. This commit attempts to
clean up some places where we no longer need it.
- Remove ComputerFamily from AbstractComputerBlock. The only place this
was needed is in TurtleBlock, and that can be replaced with normal
Minecraft explosion resistence!
- Pass in the fuel limit to the turtle block entity, rather than
deriving it from current family.
- The turtle BERs now derive their model from the turtle's item, rather
than the turtle's family.
- When creating upgrade/overlay recipes, use the item's name, rather
than {pocket,turtle}_family. This means we can drop getFamily() from
IComputerItem (it is still needed on to handle the UI).
- We replace IComputerItem.withFamily with a method to change to a
different item of the same type. ComputerUpgradeRecipe no longer
takes a family, and instead just uses the result's item.
- Computer blocks now use the normal Block.asItem() to find their
corresponding item, rather than looking it up via family.
The above means we can remove all the family-based XyzItem.create(...)
methods, which have always felt a little ugly.
We still need ComputerFamily for a couple of things:
- Permission checks for command computers.
- Checks for mouse/colour support in ServerComputer.
- UI textures.
2023-12-20 14:16:56 +00:00
|
|
|
.group(name.withSuffix("_overlay").toString())
|
2024-04-25 20:32:48 +00:00
|
|
|
.unlockedBy("has_turtle", inventoryChange(turtleItem));
|
2023-03-31 17:14:44 +00:00
|
|
|
build.accept(builder);
|
|
|
|
builder
|
2024-04-25 20:32:48 +00:00
|
|
|
.requires(turtleItem)
|
2024-01-31 20:55:14 +00:00
|
|
|
.build(s -> new TurtleOverlayRecipe(s, new ResourceLocation(ComputerCraftAPI.MOD_ID, "block/" + overlay)))
|
|
|
|
.save(add, name.withSuffix("_overlays/" + overlay));
|
2023-03-31 17:14:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
private void basicRecipes(RecipeOutput add) {
|
2020-02-08 23:26:05 +00:00
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.CABLE.get(), 6)
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern(" # ")
|
|
|
|
.pattern("#R#")
|
|
|
|
.pattern(" # ")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.stone())
|
|
|
|
.define('R', ingredients.redstone())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(COMPUTER))
|
|
|
|
.unlockedBy("has_modem", inventoryChange(WIRED_MODEM))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.COMPUTER_NORMAL.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#R#")
|
|
|
|
.pattern("#G#")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.stone())
|
|
|
|
.define('R', ingredients.redstone())
|
|
|
|
.define('G', ingredients.glassPane())
|
|
|
|
.unlockedBy("has_redstone", inventoryChange(itemPredicate(ingredients.redstone())))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.COMPUTER_ADVANCED.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#R#")
|
|
|
|
.pattern("#G#")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.goldIngot())
|
|
|
|
.define('R', ingredients.redstone())
|
|
|
|
.define('G', ingredients.glassPane())
|
|
|
|
.unlockedBy("has_components", inventoryChange(itemPredicate(ingredients.redstone()), itemPredicate(ingredients.goldIngot())))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapedSpecBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_ADVANCED.get())
|
2022-10-22 09:48:30 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#C#")
|
|
|
|
.pattern("# #")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.goldIngot())
|
2022-11-21 19:08:23 +00:00
|
|
|
.define('C', ModRegistry.Items.COMPUTER_NORMAL.get())
|
2022-11-09 10:59:05 +00:00
|
|
|
.unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.COMPUTER_NORMAL.get()), itemPredicate(ingredients.goldIngot())))
|
2024-04-25 20:32:48 +00:00
|
|
|
.build(ComputerConvertRecipe::new)
|
2024-01-31 20:55:14 +00:00
|
|
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "computer_advanced_upgrade"));
|
2022-10-22 09:48:30 +00:00
|
|
|
|
2020-02-08 23:26:05 +00:00
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.COMPUTER_COMMAND.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#R#")
|
|
|
|
.pattern("#G#")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.goldIngot())
|
|
|
|
.define('R', Blocks.COMMAND_BLOCK)
|
|
|
|
.define('G', ingredients.glassPane())
|
|
|
|
.unlockedBy("has_components", inventoryChange(Blocks.COMMAND_BLOCK))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapedSpecBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_NORMAL.get())
|
2022-10-22 09:48:30 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#C#")
|
|
|
|
.pattern("#I#")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.ironIngot())
|
2022-11-06 17:14:53 +00:00
|
|
|
.define('C', ModRegistry.Items.COMPUTER_NORMAL.get())
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('I', ingredients.woodenChest())
|
2022-11-06 17:14:53 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_NORMAL.get()))
|
2024-04-25 20:32:48 +00:00
|
|
|
.build(ComputerConvertRecipe::new)
|
2024-01-31 20:55:14 +00:00
|
|
|
.save(add);
|
2022-10-22 09:48:30 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapedSpecBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_ADVANCED.get())
|
2022-10-22 09:48:30 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#C#")
|
|
|
|
.pattern("#I#")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.goldIngot())
|
2022-11-06 17:14:53 +00:00
|
|
|
.define('C', ModRegistry.Items.COMPUTER_ADVANCED.get())
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('I', ingredients.woodenChest())
|
2022-11-06 17:14:53 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_NORMAL.get()))
|
2024-04-25 20:32:48 +00:00
|
|
|
.build(ComputerConvertRecipe::new)
|
2024-01-31 20:55:14 +00:00
|
|
|
.save(add);
|
2022-10-22 09:48:30 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapedSpecBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_ADVANCED.get())
|
2022-10-22 09:48:30 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#C#")
|
|
|
|
.pattern(" B ")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.goldIngot())
|
2022-11-21 19:08:23 +00:00
|
|
|
.define('C', ModRegistry.Items.TURTLE_NORMAL.get())
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('B', ingredients.goldBlock())
|
|
|
|
.unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.TURTLE_NORMAL.get()), itemPredicate(ingredients.goldIngot())))
|
2024-04-25 20:32:48 +00:00
|
|
|
.build(ComputerConvertRecipe::new)
|
2024-01-31 20:55:14 +00:00
|
|
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_advanced_upgrade"));
|
2022-10-22 09:48:30 +00:00
|
|
|
|
2020-02-08 23:26:05 +00:00
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.DISK_DRIVE.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#R#")
|
|
|
|
.pattern("#R#")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.stone())
|
|
|
|
.define('R', ingredients.redstone())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(COMPUTER))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.MONITOR_NORMAL.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#G#")
|
|
|
|
.pattern("###")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.stone())
|
|
|
|
.define('G', ingredients.glassPane())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(COMPUTER))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.MONITOR_ADVANCED.get(), 4)
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#G#")
|
|
|
|
.pattern("###")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.goldIngot())
|
|
|
|
.define('G', ingredients.glassPane())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(COMPUTER))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.POCKET_COMPUTER_NORMAL.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#A#")
|
|
|
|
.pattern("#G#")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.stone())
|
|
|
|
.define('A', Items.GOLDEN_APPLE)
|
|
|
|
.define('G', ingredients.glassPane())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(COMPUTER))
|
2022-11-09 10:59:05 +00:00
|
|
|
.unlockedBy("has_apple", inventoryChange(Items.GOLDEN_APPLE))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#A#")
|
|
|
|
.pattern("#G#")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.goldIngot())
|
|
|
|
.define('A', Items.GOLDEN_APPLE)
|
|
|
|
.define('G', ingredients.glassPane())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(COMPUTER))
|
2022-11-09 10:59:05 +00:00
|
|
|
.unlockedBy("has_apple", inventoryChange(Items.GOLDEN_APPLE))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapedSpecBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get())
|
2022-10-22 09:48:30 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#C#")
|
|
|
|
.pattern("# #")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.goldIngot())
|
2022-11-06 17:14:53 +00:00
|
|
|
.define('C', ModRegistry.Items.POCKET_COMPUTER_NORMAL.get())
|
2022-11-09 10:59:05 +00:00
|
|
|
.unlockedBy("has_components", inventoryChange(itemPredicate(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get()), itemPredicate(ingredients.goldIngot())))
|
2024-04-25 20:32:48 +00:00
|
|
|
.build(ComputerConvertRecipe::new)
|
2024-01-31 20:55:14 +00:00
|
|
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_computer_advanced_upgrade"));
|
2022-10-22 09:48:30 +00:00
|
|
|
|
2020-02-08 23:26:05 +00:00
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.PRINTER.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#R#")
|
|
|
|
.pattern("#D#")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.stone())
|
|
|
|
.define('R', ingredients.redstone())
|
|
|
|
.define('D', ingredients.dye())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(COMPUTER))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.SPEAKER.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#N#")
|
|
|
|
.pattern("#R#")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.stone())
|
|
|
|
.define('N', Blocks.NOTE_BLOCK)
|
|
|
|
.define('R', ingredients.redstone())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(COMPUTER))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.WIRED_MODEM.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#R#")
|
|
|
|
.pattern("###")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.stone())
|
|
|
|
.define('R', ingredients.redstone())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(COMPUTER))
|
2022-11-06 17:14:53 +00:00
|
|
|
.unlockedBy("has_cable", inventoryChange(ModRegistry.Items.CABLE.get()))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
|
|
|
ShapelessRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Blocks.WIRED_MODEM_FULL.get())
|
2022-11-06 17:14:53 +00:00
|
|
|
.requires(ModRegistry.Items.WIRED_MODEM.get())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_modem", inventoryChange(WIRED_MODEM))
|
2022-11-09 20:10:24 +00:00
|
|
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "wired_modem_full_from"));
|
2020-02-08 23:26:05 +00:00
|
|
|
ShapelessRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.WIRED_MODEM.get())
|
2022-11-06 17:14:53 +00:00
|
|
|
.requires(ModRegistry.Blocks.WIRED_MODEM_FULL.get())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_modem", inventoryChange(WIRED_MODEM))
|
2022-11-09 20:10:24 +00:00
|
|
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "wired_modem_full_to"));
|
2020-02-08 23:26:05 +00:00
|
|
|
|
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.WIRELESS_MODEM_NORMAL.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#E#")
|
|
|
|
.pattern("###")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.stone())
|
|
|
|
.define('E', ingredients.enderPearl())
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(COMPUTER))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
|
|
|
|
ShapedRecipeBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.WIRELESS_MODEM_ADVANCED.get())
|
2021-01-09 19:22:58 +00:00
|
|
|
.pattern("###")
|
|
|
|
.pattern("#E#")
|
|
|
|
.pattern("###")
|
2022-11-09 10:59:05 +00:00
|
|
|
.define('#', ingredients.goldIngot())
|
|
|
|
.define('E', Items.ENDER_EYE)
|
2021-10-27 18:16:32 +00:00
|
|
|
.unlockedBy("has_computer", inventoryChange(COMPUTER))
|
2022-11-06 17:14:53 +00:00
|
|
|
.unlockedBy("has_wireless", inventoryChange(ModRegistry.Blocks.WIRELESS_MODEM_NORMAL.get()))
|
2021-01-09 19:22:58 +00:00
|
|
|
.save(add);
|
2021-08-21 14:50:01 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapelessSpecBuilder
|
|
|
|
.shapeless(RecipeCategory.DECORATIONS, playerHead("Cloudhunter", "6d074736-b1e9-4378-a99b-bd8777821c9c"))
|
2024-04-25 20:32:48 +00:00
|
|
|
.requires(ItemTags.SKULLS)
|
2022-11-06 17:14:53 +00:00
|
|
|
.requires(ModRegistry.Items.MONITOR_NORMAL.get())
|
|
|
|
.unlockedBy("has_monitor", inventoryChange(ModRegistry.Items.MONITOR_NORMAL.get()))
|
2024-04-25 20:32:48 +00:00
|
|
|
.build()
|
2024-01-31 20:55:14 +00:00
|
|
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_cloudy"));
|
2021-08-21 14:50:01 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapelessSpecBuilder
|
|
|
|
.shapeless(RecipeCategory.DECORATIONS, playerHead("dan200", "f3c8d69b-0776-4512-8434-d1b2165909eb"))
|
2024-04-25 20:32:48 +00:00
|
|
|
.requires(ItemTags.SKULLS)
|
2022-11-06 17:14:53 +00:00
|
|
|
.requires(ModRegistry.Items.COMPUTER_ADVANCED.get())
|
|
|
|
.unlockedBy("has_computer", inventoryChange(ModRegistry.Items.COMPUTER_ADVANCED.get()))
|
2024-04-25 20:32:48 +00:00
|
|
|
.build()
|
2024-01-31 20:55:14 +00:00
|
|
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_dan200"));
|
2021-08-21 14:50:01 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapelessSpecBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_PAGES.get())
|
2022-11-06 17:14:53 +00:00
|
|
|
.requires(ModRegistry.Items.PRINTED_PAGE.get(), 2)
|
2022-11-09 10:59:05 +00:00
|
|
|
.requires(ingredients.string())
|
2022-11-06 17:14:53 +00:00
|
|
|
.unlockedBy("has_printer", inventoryChange(ModRegistry.Blocks.PRINTER.get()))
|
2024-01-31 20:55:14 +00:00
|
|
|
.build(ImpostorShapelessRecipe::new)
|
|
|
|
.save(add);
|
2021-08-21 14:50:01 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
ShapelessSpecBuilder
|
2022-12-08 19:45:02 +00:00
|
|
|
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_BOOK.get())
|
2022-11-09 10:59:05 +00:00
|
|
|
.requires(ingredients.leather())
|
2022-11-06 17:14:53 +00:00
|
|
|
.requires(ModRegistry.Items.PRINTED_PAGE.get(), 1)
|
2022-11-09 10:59:05 +00:00
|
|
|
.requires(ingredients.string())
|
2022-11-06 17:14:53 +00:00
|
|
|
.unlockedBy("has_printer", inventoryChange(ModRegistry.Blocks.PRINTER.get()))
|
2024-01-31 20:55:14 +00:00
|
|
|
.build(ImpostorShapelessRecipe::new)
|
|
|
|
.save(add);
|
2020-02-08 23:26:05 +00:00
|
|
|
}
|
|
|
|
|
2020-01-29 16:41:26 +00:00
|
|
|
private static DyeColor ofColour(Colour colour) {
|
|
|
|
return DyeColor.byId(15 - colour.ordinal());
|
|
|
|
}
|
2020-02-08 23:26:05 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
private static Criterion<InventoryChangeTrigger.TriggerInstance> inventoryChange(TagKey<Item> stack) {
|
2022-10-25 21:36:21 +00:00
|
|
|
return InventoryChangeTrigger.TriggerInstance.hasItems(itemPredicate(stack));
|
2020-02-08 23:26:05 +00:00
|
|
|
}
|
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
private static Criterion<InventoryChangeTrigger.TriggerInstance> inventoryChange(ItemLike... stack) {
|
2021-08-03 20:46:53 +00:00
|
|
|
return InventoryChangeTrigger.TriggerInstance.hasItems(stack);
|
2020-02-08 23:26:05 +00:00
|
|
|
}
|
2021-08-21 14:50:01 +00:00
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
private static Criterion<InventoryChangeTrigger.TriggerInstance> inventoryChange(ItemPredicate... items) {
|
2022-10-25 21:36:21 +00:00
|
|
|
return InventoryChangeTrigger.TriggerInstance.hasItems(items);
|
2022-10-22 09:48:30 +00:00
|
|
|
}
|
|
|
|
|
2022-10-25 21:36:21 +00:00
|
|
|
private static ItemPredicate itemPredicate(ItemLike item) {
|
2022-10-22 09:48:30 +00:00
|
|
|
return ItemPredicate.Builder.item().of(item).build();
|
|
|
|
}
|
|
|
|
|
2022-10-25 21:36:21 +00:00
|
|
|
private static ItemPredicate itemPredicate(TagKey<Item> item) {
|
2022-10-22 09:48:30 +00:00
|
|
|
return ItemPredicate.Builder.item().of(item).build();
|
|
|
|
}
|
|
|
|
|
2022-11-09 10:59:05 +00:00
|
|
|
private static ItemPredicate itemPredicate(Ingredient ingredient) {
|
2024-04-25 20:32:48 +00:00
|
|
|
var json = Ingredient.CODEC_NONEMPTY.encodeStart(JsonOps.INSTANCE, ingredient).getOrThrow();
|
2022-11-09 10:59:05 +00:00
|
|
|
if (!(json instanceof JsonObject object)) throw new IllegalStateException("Unknown ingredient " + json);
|
|
|
|
|
|
|
|
if (object.has("item")) {
|
2024-04-25 20:32:48 +00:00
|
|
|
var item = ItemStack.SIMPLE_ITEM_CODEC.parse(JsonOps.INSTANCE, object).getOrThrow();
|
2024-01-31 20:55:14 +00:00
|
|
|
return itemPredicate(item.getItem());
|
2022-11-09 10:59:05 +00:00
|
|
|
} else if (object.has("tag")) {
|
2022-12-08 19:45:02 +00:00
|
|
|
return itemPredicate(TagKey.create(Registries.ITEM, new ResourceLocation(GsonHelper.getAsString(object, "tag"))));
|
2022-11-09 10:59:05 +00:00
|
|
|
} else {
|
|
|
|
throw new IllegalArgumentException("Unknown ingredient " + json);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
private static ItemStack playerHead(String name, String uuid) {
|
2024-04-25 20:32:48 +00:00
|
|
|
return DataComponentUtil.createStack(Items.PLAYER_HEAD, DataComponents.PROFILE, new ResolvableProfile(new GameProfile(UUID.fromString(uuid), name)));
|
2021-08-21 14:50:01 +00:00
|
|
|
}
|
|
|
|
|
2024-01-31 20:55:14 +00:00
|
|
|
private static void addSpecial(RecipeOutput add, Recipe<?> recipe) {
|
|
|
|
add.accept(RegistryHelper.getKeyOrThrow(BuiltInRegistries.RECIPE_SERIALIZER, recipe.getSerializer()), recipe, null);
|
2021-08-21 14:50:01 +00:00
|
|
|
}
|
2020-01-29 16:41:26 +00:00
|
|
|
}
|