Skip to content

Commit

Permalink
datagen output method and rework recipeoutput wrapping
Browse files Browse the repository at this point in the history
  • Loading branch information
bconlon1 committed Jun 19, 2024
1 parent 4dd086f commit 0ea0339
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 17 deletions.
16 changes: 16 additions & 0 deletions patches/net/minecraft/data/DataProvider.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,19 @@
p_236070_.put("type", 0);
p_236070_.put("parent", 1);
p_236070_.defaultReturnValue(2);
@@ -34,6 +_,15 @@
CompletableFuture<?> run(CachedOutput p_236071_);

String getName();
+
+ static <T> CompletableFuture<?> saveStable(CachedOutput p_298323_, HolderLookup.Provider p_323556_, Codec<T> p_299231_, T p_298793_, Path p_298236_, net.minecraft.data.recipes.RecipeOutput recipeOutput) {
+ RegistryOps<JsonElement> registryops = p_323556_.createSerializationContext(JsonOps.INSTANCE);
+ JsonElement jsonelement = p_299231_.encodeStart(registryops, p_298793_).getOrThrow();
+ if (recipeOutput instanceof net.neoforged.neoforge.common.crafting.OverlappingRecipeOutput overlappingRecipeOutput && jsonelement instanceof com.google.gson.JsonObject jsonObject && overlappingRecipeOutput.getOutputOverride() != null) {
+ jsonObject.addProperty("neoforge:override", overlappingRecipeOutput.getOutputOverride().toString());
+ }
+ return saveStable(p_298323_, jsonelement, p_298236_);
+ }

static <T> CompletableFuture<?> saveStable(CachedOutput p_298323_, HolderLookup.Provider p_323556_, Codec<T> p_299231_, T p_298793_, Path p_298236_) {
RegistryOps<JsonElement> registryops = p_323556_.createSerializationContext(JsonOps.INSTANCE);
2 changes: 1 addition & 1 deletion patches/net/minecraft/data/recipes/RecipeOutput.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
- void accept(ResourceLocation p_312249_, Recipe<?> p_312328_, @Nullable AdvancementHolder p_312176_);
+public interface RecipeOutput extends net.neoforged.neoforge.common.extensions.IRecipeOutputExtension {
+ default void accept(ResourceLocation p_312249_, Recipe<?> p_312328_, @Nullable AdvancementHolder p_312176_) {
+ accept(p_312249_, p_312328_, p_312176_, new net.neoforged.neoforge.common.conditions.ICondition[0]);
+ accept(p_312249_, p_312328_, p_312176_, this);
+ }

Advancement.Builder advancement();
Expand Down
6 changes: 3 additions & 3 deletions patches/net/minecraft/data/recipes/RecipeProvider.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
new RecipeOutput() {
@Override
- public void accept(ResourceLocation p_312039_, Recipe<?> p_312254_, @Nullable AdvancementHolder p_311794_) {
+ public void accept(ResourceLocation p_312039_, Recipe<?> p_312254_, @Nullable AdvancementHolder p_311794_, net.neoforged.neoforge.common.conditions.ICondition... conditions) {
+ public void accept(ResourceLocation p_312039_, Recipe<?> p_312254_, @Nullable AdvancementHolder p_311794_, RecipeOutput other) {
if (!set.add(p_312039_)) {
throw new IllegalStateException("Duplicate recipe " + p_312039_);
} else {
- list.add(DataProvider.saveStable(p_324494_, p_324248_, Recipe.CODEC, p_312254_, RecipeProvider.this.recipePathProvider.json(p_312039_)));
+ list.add(DataProvider.saveStable(p_324494_, p_324248_, Recipe.CONDITIONAL_CODEC, Optional.of(new net.neoforged.neoforge.common.conditions.WithConditions<>(p_312254_, conditions)), RecipeProvider.this.recipePathProvider.json(p_312039_)));
+ list.add(DataProvider.saveStable(p_324494_, p_324248_, Recipe.CONDITIONAL_CODEC, Optional.of(new net.neoforged.neoforge.common.conditions.WithConditions<>(p_312254_, other.getConditions())), RecipeProvider.this.recipePathProvider.json(p_312039_), other));
if (p_311794_ != null) {
list.add(
DataProvider.saveStable(
Expand All @@ -19,7 +19,7 @@
- Advancement.CODEC,
- p_311794_.value(),
+ Advancement.CONDITIONAL_CODEC,
+ Optional.of(new net.neoforged.neoforge.common.conditions.WithConditions<>(p_311794_.value(), conditions)),
+ Optional.of(new net.neoforged.neoforge.common.conditions.WithConditions<>(p_311794_.value(), other.getConditions())),
RecipeProvider.this.advancementPathProvider.json(p_311794_.id())
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,20 @@ public Advancement.Builder advancement() {
}

@Override
public void accept(ResourceLocation id, Recipe<?> recipe, @Nullable AdvancementHolder advancement, ICondition... conditions) {
public ICondition[] getConditions(ICondition... other) {
ICondition[] innerConditions;
if (conditions.length == 0) {
if (other.length == 0) {
innerConditions = this.conditions;
} else if (this.conditions.length == 0) {
innerConditions = conditions;
innerConditions = other;
} else {
innerConditions = ArrayUtils.addAll(this.conditions, conditions);
innerConditions = ArrayUtils.addAll(this.conditions, other);
}
inner.accept(id, recipe, advancement, innerConditions);
return innerConditions;
}

@Override
public void accept(ResourceLocation id, Recipe<?> recipe, @Nullable AdvancementHolder advancement, RecipeOutput other) {
inner.accept(id, recipe, advancement, this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.neoforge.common.crafting;

import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.AdvancementHolder;
import net.minecraft.data.recipes.RecipeOutput;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Recipe;
import org.jetbrains.annotations.Nullable;

public class OverlappingRecipeOutput implements RecipeOutput {
private final RecipeOutput inner;
@Nullable
private final ResourceLocation override;

public OverlappingRecipeOutput(RecipeOutput inner, ResourceLocation override) {
this.inner = inner;
this.override = override;
}

@Override
public Advancement.Builder advancement() {
return inner.advancement();
}

@Nullable
public ResourceLocation getOutputOverride() {
return override;
}

@Override
public void accept(ResourceLocation id, Recipe<?> recipe, @Nullable AdvancementHolder advancement, RecipeOutput other) {
inner.accept(id, recipe, advancement, this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import net.minecraft.world.level.block.Blocks;
import net.neoforged.fml.util.ObfuscationReflectionHelper;
import net.neoforged.neoforge.common.Tags;
import net.neoforged.neoforge.common.conditions.ICondition;
import org.jetbrains.annotations.Nullable;

public final class NeoForgeRecipeProvider extends VanillaRecipeProvider {
Expand Down Expand Up @@ -99,10 +98,10 @@ protected void buildRecipes(RecipeOutput recipeOutput) {

super.buildRecipes(new RecipeOutput() {
@Override
public void accept(ResourceLocation id, Recipe<?> recipe, @Nullable AdvancementHolder advancement, ICondition... conditions) {
public void accept(ResourceLocation id, Recipe<?> recipe, @Nullable AdvancementHolder advancement, RecipeOutput other) {
Recipe<?> modified = enhance(id, recipe);
if (modified != null)
recipeOutput.accept(id, modified, null, conditions);
recipeOutput.accept(id, modified, null, other);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import net.minecraft.world.item.crafting.Recipe;
import net.neoforged.neoforge.common.conditions.ICondition;
import net.neoforged.neoforge.common.crafting.ConditionalRecipeOutput;
import net.neoforged.neoforge.common.crafting.OverlappingRecipeOutput;
import org.jetbrains.annotations.Nullable;

/**
Expand All @@ -22,14 +23,30 @@ private RecipeOutput self() {
}

/**
* Generates a recipe with the given conditions.
* Generates a recipe with the given other recipe output.
*/
void accept(ResourceLocation id, Recipe<?> recipe, @Nullable AdvancementHolder advancement, ICondition... conditions);
void accept(ResourceLocation id, Recipe<?> recipe, @Nullable AdvancementHolder advancement, RecipeOutput other);

/**
* Builds a wrapper around this recipe output that adds conditions to all received recipes.
*/
default RecipeOutput withConditions(ICondition... conditions) {
return new ConditionalRecipeOutput(self(), conditions);
}

default ICondition[] getConditions(ICondition... other) {
return new ICondition[0];
}

/**
* Builds a wrapper around this recipe output that adds an output override to all received recipes.
*/
default RecipeOutput withOverrides(ResourceLocation outputOverride) {
return new OverlappingRecipeOutput(self(), outputOverride);
}

@Nullable
default ResourceLocation getOutputOverride() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_cherry_planks": {
"conditions": {
"items": [
{
"items": "minecraft:cherry_planks"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "minecraft:redstone_block"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_cherry_planks"
]
],
"rewards": {
"recipes": [
"minecraft:redstone_block"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"category": "misc",
"group": "bed",
"key": {
"#": {
"item": "minecraft:yellow_wool"
},
"X": {
"item": "minecraft:cherry_planks"
}
},
"neoforge:override": "minecraft:yellow_bed",
"pattern": [
"###",
"XXX"
],
"result": {
"count": 1,
"id": "minecraft:redstone_block"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
import net.minecraft.world.level.block.CrafterBlock;
import net.minecraft.world.level.block.entity.CrafterBlockEntity;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.neoforged.neoforge.common.conditions.ICondition;
import net.neoforged.neoforge.common.crafting.BlockTagIngredient;
import net.neoforged.neoforge.common.crafting.CompoundIngredient;
import net.neoforged.neoforge.common.crafting.DataComponentIngredient;
Expand Down Expand Up @@ -325,8 +324,8 @@ public Advancement.Builder advancement() {
}

@Override
public void accept(ResourceLocation id, Recipe<?> recipe, @Nullable AdvancementHolder advancement, ICondition... conditions) {
recipeOutput.accept(id, new CompressedShapelessRecipe((ShapelessRecipe) recipe), advancement, conditions);
public void accept(ResourceLocation id, Recipe<?> recipe, @Nullable AdvancementHolder advancement, RecipeOutput other) {
recipeOutput.accept(id, new CompressedShapelessRecipe((ShapelessRecipe) recipe), advancement, other);
}
}, location);
}
Expand Down Expand Up @@ -377,6 +376,57 @@ protected void buildRecipes(RecipeOutput output) {

.thenSucceed());
}

@GameTest
@EmptyTemplate
@TestHolder(description = "Serialization tests for overlap override recipes")
static void overlappingRecipeOutputSerialization(final DynamicTest test, final RegistrationHelper reg) {
reg.addProvider(event -> new RecipeProvider(event.getGenerator().getPackOutput(), event.getLookupProvider()) {
@Override
protected void buildRecipes(RecipeOutput output) {
ShapedRecipeBuilder.shaped(RecipeCategory.MISC, Blocks.REDSTONE_BLOCK)
.define('#', Blocks.YELLOW_WOOL)
.define('X', Blocks.CHERRY_PLANKS)
.pattern("###")
.pattern("XXX")
.group("bed")
.unlockedBy(getHasName(Blocks.CHERRY_PLANKS), has(Blocks.CHERRY_PLANKS))
.save(output.withOverrides(ResourceLocation.withDefaultNamespace("yellow_bed")));
}
});

test.onGameTest(helper -> helper
.startSequence()
.thenExecute(() -> helper.setBlock(1, 1, 1, Blocks.CRAFTER.defaultBlockState().setValue(BlockStateProperties.ORIENTATION, FrontAndTop.UP_NORTH).setValue(CrafterBlock.CRAFTING, true)))
.thenExecute(() -> helper.setBlock(1, 2, 1, Blocks.CHEST))

// Try to craft default bed recipe
.thenMap(() -> helper.requireBlockEntity(1, 1, 1, CrafterBlockEntity.class))
.thenExecute(crafter -> crafter.setItem(3, Items.YELLOW_WOOL.getDefaultInstance()))
.thenExecute(crafter -> crafter.setItem(4, Items.YELLOW_WOOL.getDefaultInstance()))
.thenExecute(crafter -> crafter.setItem(5, Items.YELLOW_WOOL.getDefaultInstance()))
.thenExecute(crafter -> crafter.setItem(6, Items.OAK_PLANKS.getDefaultInstance()))
.thenExecute(crafter -> crafter.setItem(7, Items.OAK_PLANKS.getDefaultInstance()))
.thenExecute(crafter -> crafter.setItem(8, Items.OAK_PLANKS.getDefaultInstance()))
.thenIdle(3)
.thenExecute(() -> helper.pulseRedstone(1, 1, 2, 2))
.thenExecuteAfter(7, () -> helper.assertContainerContains(1, 2, 1, Items.YELLOW_BED)) // Should craft yellow bed from recipe of yellow wool and oak planks (part of the #planks tag)

.thenIdle(5) // Crafter cooldown

// Try to craft recipe that overrides the default bed recipe
.thenExecute(crafter -> crafter.setItem(3, Items.YELLOW_WOOL.getDefaultInstance()))
.thenExecute(crafter -> crafter.setItem(4, Items.YELLOW_WOOL.getDefaultInstance()))
.thenExecute(crafter -> crafter.setItem(5, Items.YELLOW_WOOL.getDefaultInstance()))
.thenExecute(crafter -> crafter.setItem(6, Items.CHERRY_PLANKS.getDefaultInstance()))
.thenExecute(crafter -> crafter.setItem(7, Items.CHERRY_PLANKS.getDefaultInstance()))
.thenExecute(crafter -> crafter.setItem(8, Items.CHERRY_PLANKS.getDefaultInstance()))
.thenIdle(3)
.thenExecute(() -> helper.pulseRedstone(1, 1, 2, 2))
.thenExecuteAfter(7, () -> helper.assertContainerContains(1, 2, 1, Items.REDSTONE_BLOCK)) // Should craft the redstone block

.thenSucceed());
}
/*
@GameTest
@EmptyTemplate
Expand Down

0 comments on commit 0ea0339

Please sign in to comment.