mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-11-10 20:09:58 +00:00
Make printout recipes a little more flexible
Rather than having one single hard-coded recipe, we now have separate recipes for printed pages and printed books. These recipes are defined in terms of - A list of ingredients (like shapeless recipes). - A result item. - An ingredient defining the acceptable page items (so printed page(s), but not books). This cannot overlap with any of the main ingredients. - The minimum number of printouts required. We then override the shapeless recipe crafting logic to allow for multiple printouts to appear. It feels like it'd be nice to generalise this to a way of defining shapeless recipes with variable-count ingredients (for instance, the disk recipe could also be defined this way), but I don't think it's worth it right now. This solves some of the issues in #1755. Disk recipes have not been changed yet.
This commit is contained in:
parent
2c0d8263d3
commit
ad70e2ad90
@ -1,10 +1,12 @@
|
|||||||
{
|
{
|
||||||
"type": "computercraft:impostor_shapeless",
|
"type": "computercraft:printout",
|
||||||
"category": "redstone",
|
"category": "redstone",
|
||||||
"ingredients": [
|
"ingredients": [{"tag": "c:strings"}],
|
||||||
|
"min_printouts": 2,
|
||||||
|
"printout": [
|
||||||
{"item": "computercraft:printed_page"},
|
{"item": "computercraft:printed_page"},
|
||||||
{"item": "computercraft:printed_page"},
|
{"item": "computercraft:printed_pages"},
|
||||||
{"tag": "c:strings"}
|
{"item": "minecraft:paper"}
|
||||||
],
|
],
|
||||||
"result": {"count": 1, "id": "computercraft:printed_pages"}
|
"result": {"count": 1, "id": "computercraft:printed_pages"}
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
{"type": "computercraft:printout", "category": "misc"}
|
|
@ -98,7 +98,6 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
turtleUpgrades(add, registries);
|
turtleUpgrades(add, registries);
|
||||||
turtleOverlays(add);
|
turtleOverlays(add);
|
||||||
|
|
||||||
addSpecial(add, new PrintoutRecipe(CraftingBookCategory.MISC));
|
|
||||||
addSpecial(add, new DiskRecipe(CraftingBookCategory.MISC));
|
addSpecial(add, new DiskRecipe(CraftingBookCategory.MISC));
|
||||||
addSpecial(add, new ColourableRecipe(CraftingBookCategory.MISC));
|
addSpecial(add, new ColourableRecipe(CraftingBookCategory.MISC));
|
||||||
addSpecial(add, new ClearColourRecipe(CraftingBookCategory.MISC));
|
addSpecial(add, new ClearColourRecipe(CraftingBookCategory.MISC));
|
||||||
@ -470,21 +469,25 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
|||||||
.build()
|
.build()
|
||||||
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_dan200"));
|
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "skull_dan200"));
|
||||||
|
|
||||||
|
var pages = Ingredient.of(
|
||||||
|
ModRegistry.Items.PRINTED_PAGE.get(),
|
||||||
|
ModRegistry.Items.PRINTED_PAGES.get(),
|
||||||
|
Items.PAPER
|
||||||
|
);
|
||||||
|
|
||||||
ShapelessSpecBuilder
|
ShapelessSpecBuilder
|
||||||
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_PAGES.get())
|
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_PAGES.get())
|
||||||
.requires(ModRegistry.Items.PRINTED_PAGE.get(), 2)
|
|
||||||
.requires(ingredients.string())
|
.requires(ingredients.string())
|
||||||
.unlockedBy("has_printer", inventoryChange(ModRegistry.Blocks.PRINTER.get()))
|
.unlockedBy("has_printer", inventoryChange(ModRegistry.Items.PRINTER.get()))
|
||||||
.build(ImpostorShapelessRecipe::new)
|
.build(x -> new PrintoutRecipe(x, pages, 2))
|
||||||
.save(add);
|
.save(add);
|
||||||
|
|
||||||
ShapelessSpecBuilder
|
ShapelessSpecBuilder
|
||||||
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_BOOK.get())
|
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTED_BOOK.get())
|
||||||
.requires(ingredients.leather())
|
.requires(ingredients.leather())
|
||||||
.requires(ModRegistry.Items.PRINTED_PAGE.get(), 1)
|
|
||||||
.requires(ingredients.string())
|
.requires(ingredients.string())
|
||||||
.unlockedBy("has_printer", inventoryChange(ModRegistry.Blocks.PRINTER.get()))
|
.unlockedBy("has_printer", inventoryChange(ModRegistry.Items.PRINTER.get()))
|
||||||
.build(ImpostorShapelessRecipe::new)
|
.build(x -> new PrintoutRecipe(x, pages, 1))
|
||||||
.save(add);
|
.save(add);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ import net.minecraft.tags.TagKey;
|
|||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.crafting.Ingredient;
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
import net.minecraft.world.item.crafting.ShapelessRecipe;
|
|
||||||
import net.minecraft.world.level.ItemLike;
|
import net.minecraft.world.level.ItemLike;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,6 +60,6 @@ public final class ShapelessSpecBuilder extends AbstractRecipeBuilder<ShapelessS
|
|||||||
}
|
}
|
||||||
|
|
||||||
public FinishedRecipe build() {
|
public FinishedRecipe build() {
|
||||||
return build(spec -> new ShapelessRecipe(spec.properties().group(), spec.properties().category(), spec.result(), spec.ingredients()));
|
return build(ShapelessRecipeSpec::create);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,12 +249,16 @@ public final class ModRegistry {
|
|||||||
public static final RegistryEntry<TreasureDiskItem> TREASURE_DISK =
|
public static final RegistryEntry<TreasureDiskItem> TREASURE_DISK =
|
||||||
REGISTRY.register("treasure_disk", () -> new TreasureDiskItem(properties().stacksTo(1)));
|
REGISTRY.register("treasure_disk", () -> new TreasureDiskItem(properties().stacksTo(1)));
|
||||||
|
|
||||||
|
private static Item.Properties printoutProperties() {
|
||||||
|
return properties().stacksTo(1).component(DataComponents.PRINTOUT.get(), PrintoutData.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
public static final RegistryEntry<PrintoutItem> PRINTED_PAGE = REGISTRY.register("printed_page",
|
public static final RegistryEntry<PrintoutItem> PRINTED_PAGE = REGISTRY.register("printed_page",
|
||||||
() -> new PrintoutItem(properties().stacksTo(1), PrintoutItem.Type.PAGE));
|
() -> new PrintoutItem(printoutProperties(), PrintoutItem.Type.PAGE));
|
||||||
public static final RegistryEntry<PrintoutItem> PRINTED_PAGES = REGISTRY.register("printed_pages",
|
public static final RegistryEntry<PrintoutItem> PRINTED_PAGES = REGISTRY.register("printed_pages",
|
||||||
() -> new PrintoutItem(properties().stacksTo(1), PrintoutItem.Type.PAGES));
|
() -> new PrintoutItem(printoutProperties(), PrintoutItem.Type.PAGES));
|
||||||
public static final RegistryEntry<PrintoutItem> PRINTED_BOOK = REGISTRY.register("printed_book",
|
public static final RegistryEntry<PrintoutItem> PRINTED_BOOK = REGISTRY.register("printed_book",
|
||||||
() -> new PrintoutItem(properties().stacksTo(1), PrintoutItem.Type.BOOK));
|
() -> new PrintoutItem(printoutProperties(), PrintoutItem.Type.BOOK));
|
||||||
|
|
||||||
public static final RegistryEntry<BlockItem> SPEAKER = ofBlock(Blocks.SPEAKER, BlockItem::new);
|
public static final RegistryEntry<BlockItem> SPEAKER = ofBlock(Blocks.SPEAKER, BlockItem::new);
|
||||||
public static final RegistryEntry<BlockItem> DISK_DRIVE = ofBlock(Blocks.DISK_DRIVE, BlockItem::new);
|
public static final RegistryEntry<BlockItem> DISK_DRIVE = ofBlock(Blocks.DISK_DRIVE, BlockItem::new);
|
||||||
@ -488,7 +492,7 @@ public final class ModRegistry {
|
|||||||
public static final RegistryEntry<SimpleCraftingRecipeSerializer<ClearColourRecipe>> DYEABLE_ITEM_CLEAR = simple("clear_colour", ClearColourRecipe::new);
|
public static final RegistryEntry<SimpleCraftingRecipeSerializer<ClearColourRecipe>> DYEABLE_ITEM_CLEAR = simple("clear_colour", ClearColourRecipe::new);
|
||||||
public static final RegistryEntry<SimpleCraftingRecipeSerializer<TurtleUpgradeRecipe>> TURTLE_UPGRADE = simple("turtle_upgrade", TurtleUpgradeRecipe::new);
|
public static final RegistryEntry<SimpleCraftingRecipeSerializer<TurtleUpgradeRecipe>> TURTLE_UPGRADE = simple("turtle_upgrade", TurtleUpgradeRecipe::new);
|
||||||
public static final RegistryEntry<SimpleCraftingRecipeSerializer<PocketComputerUpgradeRecipe>> POCKET_COMPUTER_UPGRADE = simple("pocket_computer_upgrade", PocketComputerUpgradeRecipe::new);
|
public static final RegistryEntry<SimpleCraftingRecipeSerializer<PocketComputerUpgradeRecipe>> POCKET_COMPUTER_UPGRADE = simple("pocket_computer_upgrade", PocketComputerUpgradeRecipe::new);
|
||||||
public static final RegistryEntry<SimpleCraftingRecipeSerializer<PrintoutRecipe>> PRINTOUT = simple("printout", PrintoutRecipe::new);
|
public static final RegistryEntry<RecipeSerializer<PrintoutRecipe>> PRINTOUT = register("printout", PrintoutRecipe.CODEC, PrintoutRecipe.STREAM_CODEC);
|
||||||
public static final RegistryEntry<SimpleCraftingRecipeSerializer<DiskRecipe>> DISK = simple("disk", DiskRecipe::new);
|
public static final RegistryEntry<SimpleCraftingRecipeSerializer<DiskRecipe>> DISK = simple("disk", DiskRecipe::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,8 +564,8 @@ public final class ModRegistry {
|
|||||||
public static void register() {
|
public static void register() {
|
||||||
Blocks.REGISTRY.register();
|
Blocks.REGISTRY.register();
|
||||||
BlockEntities.REGISTRY.register();
|
BlockEntities.REGISTRY.register();
|
||||||
Items.REGISTRY.register();
|
|
||||||
DataComponents.REGISTRY.register();
|
DataComponents.REGISTRY.register();
|
||||||
|
Items.REGISTRY.register();
|
||||||
TurtleUpgradeTypes.REGISTRY.register();
|
TurtleUpgradeTypes.REGISTRY.register();
|
||||||
PocketUpgradeTypes.REGISTRY.register();
|
PocketUpgradeTypes.REGISTRY.register();
|
||||||
Menus.REGISTRY.register();
|
Menus.REGISTRY.register();
|
||||||
|
@ -4,115 +4,141 @@
|
|||||||
|
|
||||||
package dan200.computercraft.shared.media.recipes;
|
package dan200.computercraft.shared.media.recipes;
|
||||||
|
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
import dan200.computercraft.shared.ModRegistry;
|
import dan200.computercraft.shared.ModRegistry;
|
||||||
import dan200.computercraft.shared.media.items.PrintoutData;
|
import dan200.computercraft.shared.media.items.PrintoutData;
|
||||||
import dan200.computercraft.shared.media.items.PrintoutItem;
|
import dan200.computercraft.shared.media.items.PrintoutItem;
|
||||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
import dan200.computercraft.shared.recipe.RecipeProperties;
|
||||||
import dan200.computercraft.shared.util.DataComponentUtil;
|
import dan200.computercraft.shared.recipe.ShapelessRecipeSpec;
|
||||||
import net.minecraft.core.HolderLookup;
|
import net.minecraft.core.HolderLookup;
|
||||||
|
import net.minecraft.core.NonNullList;
|
||||||
|
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||||
|
import net.minecraft.network.codec.ByteBufCodecs;
|
||||||
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
|
import net.minecraft.util.ExtraCodecs;
|
||||||
|
import net.minecraft.world.entity.player.StackedContents;
|
||||||
import net.minecraft.world.inventory.CraftingContainer;
|
import net.minecraft.world.inventory.CraftingContainer;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.Items;
|
|
||||||
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
|
||||||
import net.minecraft.world.item.crafting.CustomRecipe;
|
|
||||||
import net.minecraft.world.item.crafting.Ingredient;
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||||
|
import net.minecraft.world.item.crafting.ShapelessRecipe;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public final class PrintoutRecipe extends CustomRecipe {
|
/**
|
||||||
private final Ingredient leather;
|
* A recipe for combining one or more printed pages together.
|
||||||
private final Ingredient string;
|
* <p>
|
||||||
|
* This behaves similarly to a {@link ShapelessRecipe}, but allows a variable number of pages to appear as ingredients.
|
||||||
|
*
|
||||||
|
* @see PrintoutItem
|
||||||
|
* @see PrintoutData
|
||||||
|
*/
|
||||||
|
public final class PrintoutRecipe extends ShapelessRecipe {
|
||||||
|
public static final MapCodec<PrintoutRecipe> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
|
||||||
|
ShapelessRecipeSpec.CODEC.forGetter(PrintoutRecipe::toSpec),
|
||||||
|
Ingredient.CODEC_NONEMPTY.fieldOf("printout").forGetter(x -> x.printout),
|
||||||
|
ExtraCodecs.POSITIVE_INT.fieldOf("min_printouts").forGetter(x -> x.minPrintouts)
|
||||||
|
).apply(instance, PrintoutRecipe::new));
|
||||||
|
|
||||||
public PrintoutRecipe(CraftingBookCategory category) {
|
public static final StreamCodec<RegistryFriendlyByteBuf, PrintoutRecipe> STREAM_CODEC = StreamCodec.composite(
|
||||||
super(category);
|
ShapelessRecipeSpec.STREAM_CODEC, PrintoutRecipe::toSpec,
|
||||||
|
Ingredient.CONTENTS_STREAM_CODEC, x -> x.printout,
|
||||||
var ingredients = PlatformHelper.get().getRecipeIngredients();
|
ByteBufCodecs.VAR_INT, x -> x.minPrintouts,
|
||||||
leather = ingredients.leather();
|
PrintoutRecipe::new
|
||||||
string = ingredients.string();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canCraftInDimensions(int x, int y) {
|
|
||||||
return x >= 3 && y >= 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack getResultItem(HolderLookup.Provider registryAccess) {
|
|
||||||
return new ItemStack(ModRegistry.Items.PRINTED_PAGES.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(CraftingContainer inventory, Level world) {
|
|
||||||
return !assemble(inventory, world.registryAccess()).isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack assemble(CraftingContainer inventory, HolderLookup.Provider registryAccess) {
|
|
||||||
// See if we match the recipe, and extract the input disk ID and dye colour
|
|
||||||
var numPages = 0;
|
|
||||||
var numPrintouts = 0;
|
|
||||||
ItemStack[] printouts = null;
|
|
||||||
var stringFound = false;
|
|
||||||
var leatherFound = false;
|
|
||||||
var printoutFound = false;
|
|
||||||
for (var y = 0; y < inventory.getHeight(); y++) {
|
|
||||||
for (var x = 0; x < inventory.getWidth(); x++) {
|
|
||||||
var stack = inventory.getItem(x + y * inventory.getWidth());
|
|
||||||
if (!stack.isEmpty()) {
|
|
||||||
if (stack.getItem() instanceof PrintoutItem printout && printout.getType() != PrintoutItem.Type.BOOK) {
|
|
||||||
if (printouts == null) printouts = new ItemStack[9];
|
|
||||||
printouts[numPrintouts] = stack;
|
|
||||||
numPages += PrintoutData.getOrEmpty(stack).pages();
|
|
||||||
numPrintouts++;
|
|
||||||
printoutFound = true;
|
|
||||||
} else if (stack.getItem() == Items.PAPER) {
|
|
||||||
if (printouts == null) {
|
|
||||||
printouts = new ItemStack[9];
|
|
||||||
}
|
|
||||||
printouts[numPrintouts] = stack;
|
|
||||||
numPages++;
|
|
||||||
numPrintouts++;
|
|
||||||
} else if (string.test(stack) && !stringFound) {
|
|
||||||
stringFound = true;
|
|
||||||
} else if (leather.test(stack) && !leatherFound) {
|
|
||||||
leatherFound = true;
|
|
||||||
} else {
|
|
||||||
return ItemStack.EMPTY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build some pages with what was passed in
|
|
||||||
if (numPages <= PrintoutData.MAX_PAGES && stringFound && printoutFound && numPrintouts >= (leatherFound ? 1 : 2)) {
|
|
||||||
if (printouts == null) throw new IllegalStateException("Printouts must be non-null");
|
|
||||||
var lines = new PrintoutData.Line[numPages * PrintoutData.LINES_PER_PAGE];
|
|
||||||
var line = 0;
|
|
||||||
|
|
||||||
for (var printout = 0; printout < numPrintouts; printout++) {
|
|
||||||
var pageText = printouts[printout].get(ModRegistry.DataComponents.PRINTOUT.get());
|
|
||||||
if (pageText != null) {
|
|
||||||
// Add a printout
|
|
||||||
for (var pageLine : pageText.lines()) lines[line++] = pageLine;
|
|
||||||
} else {
|
|
||||||
// Add a blank page
|
|
||||||
for (var pageLine = 0; pageLine < PrintoutData.LINES_PER_PAGE; pageLine++) {
|
|
||||||
lines[line++] = PrintoutData.Line.EMPTY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var title = PrintoutData.getOrEmpty(printouts[0]).title();
|
|
||||||
|
|
||||||
return DataComponentUtil.createStack(
|
|
||||||
leatherFound ? ModRegistry.Items.PRINTED_BOOK.get() : ModRegistry.Items.PRINTED_PAGES.get(),
|
|
||||||
ModRegistry.DataComponents.PRINTOUT.get(), new PrintoutData(title, List.of(lines))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private final NonNullList<Ingredient> ingredients;
|
||||||
|
private final Ingredient printout;
|
||||||
|
private final int minPrintouts;
|
||||||
|
private final ShapelessRecipe innerRecipe;
|
||||||
|
|
||||||
|
private final ItemStack result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new {@link PrintoutRecipe}.
|
||||||
|
*
|
||||||
|
* @param spec The base {@link ShapelessRecipeSpec} for this recipe.
|
||||||
|
* @param printout The items that will be treated as printed pages.
|
||||||
|
* @param minPrintouts The minimum number of pages required.
|
||||||
|
*/
|
||||||
|
public PrintoutRecipe(
|
||||||
|
ShapelessRecipeSpec spec, Ingredient printout, int minPrintouts
|
||||||
|
) {
|
||||||
|
// We use the full list of ingredients in the recipe itself, so that it behaves sensibly with recipe mods.
|
||||||
|
super(spec.properties().group(), spec.properties().category(), spec.result(), concat(spec.ingredients(), printout, minPrintouts));
|
||||||
|
|
||||||
|
this.ingredients = spec.ingredients();
|
||||||
|
this.printout = printout;
|
||||||
|
this.minPrintouts = minPrintouts;
|
||||||
|
this.result = spec.result();
|
||||||
|
|
||||||
|
// However, when testing whether the recipe matches, we only want to use the non-printout ingredients. To do
|
||||||
|
// that, we create a hidden recipe with the main ingredients.
|
||||||
|
this.innerRecipe = spec.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ItemStack.EMPTY;
|
private static NonNullList<Ingredient> concat(NonNullList<Ingredient> first, Ingredient pages, int pagesRequired) {
|
||||||
|
var result = NonNullList.withSize(first.size() + pagesRequired, Ingredient.EMPTY);
|
||||||
|
var idx = 0;
|
||||||
|
for (var ingredient : first) result.set(idx++, ingredient);
|
||||||
|
for (var i = 0; i < pagesRequired; i++) result.set(idx++, pages);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ShapelessRecipeSpec toSpec() {
|
||||||
|
return new ShapelessRecipeSpec(RecipeProperties.of(this), ingredients, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(CraftingContainer inv, Level world) {
|
||||||
|
var stackedContents = new StackedContents();
|
||||||
|
|
||||||
|
var inputs = 0;
|
||||||
|
var printouts = 0;
|
||||||
|
var pages = 0;
|
||||||
|
var hasPrintout = false;
|
||||||
|
|
||||||
|
for (var j = 0; j < inv.getContainerSize(); ++j) {
|
||||||
|
var stack = inv.getItem(j);
|
||||||
|
if (stack.isEmpty()) continue;
|
||||||
|
if (printout.test(stack)) {
|
||||||
|
printouts++;
|
||||||
|
|
||||||
|
var printout = stack.get(ModRegistry.DataComponents.PRINTOUT.get());
|
||||||
|
if (printout == null) {
|
||||||
|
pages++;
|
||||||
|
} else {
|
||||||
|
hasPrintout = true;
|
||||||
|
pages += printout.pages();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inputs++;
|
||||||
|
stackedContents.accountStack(stack, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasPrintout && printouts >= minPrintouts && pages <= PrintoutData.MAX_PAGES
|
||||||
|
&& inputs == ingredients.size() && stackedContents.canCraft(innerRecipe, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack assemble(CraftingContainer inv, HolderLookup.Provider registries) {
|
||||||
|
List<PrintoutData> data = new ArrayList<>();
|
||||||
|
for (var j = 0; j < inv.getContainerSize(); ++j) {
|
||||||
|
var stack = inv.getItem(j);
|
||||||
|
if (!stack.isEmpty() && printout.test(stack)) data.add(PrintoutData.getOrEmpty(stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.isEmpty()) throw new IllegalStateException("Printouts must be non-null");
|
||||||
|
|
||||||
|
var lines = data.stream().flatMap(x -> x.lines().stream()).toList();
|
||||||
|
|
||||||
|
var result = super.assemble(inv, registries);
|
||||||
|
result.set(ModRegistry.DataComponents.PRINTOUT.get(), new PrintoutData(data.getFirst().title(), lines));
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,4 +49,13 @@ public record ShapelessRecipeSpec(RecipeProperties properties, NonNullList<Ingre
|
|||||||
ItemStack.STREAM_CODEC, ShapelessRecipeSpec::result,
|
ItemStack.STREAM_CODEC, ShapelessRecipeSpec::result,
|
||||||
ShapelessRecipeSpec::new
|
ShapelessRecipeSpec::new
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a basic {@link ShapelessRecipe} from this spec.
|
||||||
|
*
|
||||||
|
* @return The newly constructed recipe.
|
||||||
|
*/
|
||||||
|
public ShapelessRecipe create() {
|
||||||
|
return new ShapelessRecipe(properties().group(), properties().category(), result(), ingredients());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,7 @@ loom {
|
|||||||
runs {
|
runs {
|
||||||
configureEach {
|
configureEach {
|
||||||
ideConfigGenerated(true)
|
ideConfigGenerated(true)
|
||||||
|
property("fabric-tag-conventions-v2.missingTagTranslationWarning", "VERBOSE")
|
||||||
}
|
}
|
||||||
|
|
||||||
named("client") {
|
named("client") {
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"type": "computercraft:impostor_shapeless",
|
"type": "computercraft:printout",
|
||||||
"category": "redstone",
|
"category": "redstone",
|
||||||
"ingredients": [{"item": "minecraft:leather"}, {"item": "computercraft:printed_page"}, {"tag": "c:strings"}],
|
"ingredients": [{"item": "minecraft:leather"}, {"tag": "c:strings"}],
|
||||||
|
"min_printouts": 1,
|
||||||
|
"printout": [
|
||||||
|
{"item": "computercraft:printed_page"},
|
||||||
|
{"item": "computercraft:printed_pages"},
|
||||||
|
{"item": "minecraft:paper"}
|
||||||
|
],
|
||||||
"result": {"count": 1, "id": "computercraft:printed_book"}
|
"result": {"count": 1, "id": "computercraft:printed_book"}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"type": "computercraft:impostor_shapeless",
|
"type": "computercraft:printout",
|
||||||
"category": "redstone",
|
"category": "redstone",
|
||||||
"ingredients": [{"tag": "c:leathers"}, {"item": "computercraft:printed_page"}, {"tag": "c:strings"}],
|
"ingredients": [{"tag": "c:leathers"}, {"tag": "c:strings"}],
|
||||||
|
"min_printouts": 1,
|
||||||
|
"printout": [
|
||||||
|
{"item": "computercraft:printed_page"},
|
||||||
|
{"item": "computercraft:printed_pages"},
|
||||||
|
{"item": "minecraft:paper"}
|
||||||
|
],
|
||||||
"result": {"count": 1, "id": "computercraft:printed_book"}
|
"result": {"count": 1, "id": "computercraft:printed_book"}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user