|
2 | 2 |
|
3 | 3 | import java.util.ArrayList; |
4 | 4 | import java.util.List; |
5 | | -import java.util.Optional; |
6 | | -import java.util.function.Function; |
7 | 5 | import java.util.function.Supplier; |
8 | 6 | import java.util.stream.Collectors; |
9 | 7 |
|
10 | 8 | import javax.annotation.ParametersAreNonnullByDefault; |
11 | 9 |
|
| 10 | +import com.google.common.base.Joiner; |
12 | 11 | import com.mojang.serialization.DataResult; |
13 | 12 | import com.mojang.serialization.MapCodec; |
14 | 13 |
|
15 | | -import com.mojang.serialization.codecs.RecordCodecBuilder; |
16 | | -import com.simibubi.create.foundation.codec.ResourceLocationAwareOps; |
17 | | - |
18 | | -import net.minecraft.util.ExtraCodecs; |
19 | | - |
20 | | -import org.slf4j.Logger; |
21 | | - |
22 | | -import com.simibubi.create.Create; |
23 | 14 | import com.simibubi.create.foundation.fluid.FluidIngredient; |
24 | 15 | import com.simibubi.create.foundation.recipe.IRecipeTypeInfo; |
25 | 16 |
|
26 | 17 | import net.minecraft.MethodsReturnNonnullByDefault; |
27 | 18 | import net.minecraft.core.HolderLookup; |
28 | 19 | import net.minecraft.core.NonNullList; |
29 | | -import net.minecraft.resources.ResourceLocation; |
30 | 20 | import net.minecraft.world.item.ItemStack; |
31 | 21 | import net.minecraft.world.item.crafting.Ingredient; |
32 | 22 | import net.minecraft.world.item.crafting.Recipe; |
@@ -89,40 +79,37 @@ protected int getMaxFluidOutputCount() { |
89 | 79 | return 0; |
90 | 80 | } |
91 | 81 |
|
92 | | - //TODO: Recipe id is no longer avcailable on construct, |
93 | | - // validation should be called in a reload listener after RecipeManager if needed, |
94 | | - // currently only validates recipes created from builder for datagen |
95 | | - public void validate(ResourceLocation id) { |
96 | | - Logger logger = Create.LOGGER; |
97 | | - String messageHeader = "Your custom " + typeInfo.getId() + " recipe (" + id + ")"; |
| 82 | + public List<String> validate() { |
| 83 | + List<String> errors = new ArrayList<>(); |
98 | 84 | int ingredientCount = ingredients.size(); |
99 | 85 | int outputCount = results.size(); |
100 | 86 |
|
101 | 87 | if (ingredientCount > getMaxInputCount()) |
102 | | - logger.warn(messageHeader + " has more item inputs (" + ingredientCount + ") than supported (" |
| 88 | + errors.add("Recipe has more item inputs (" + ingredientCount + ") than supported (" |
103 | 89 | + getMaxInputCount() + ")."); |
104 | 90 |
|
105 | 91 | if (outputCount > getMaxOutputCount()) |
106 | | - logger.warn(messageHeader + " has more item outputs (" + outputCount + ") than supported (" |
| 92 | + errors.add("Recipe has more item outputs (" + outputCount + ") than supported (" |
107 | 93 | + getMaxOutputCount() + ")."); |
108 | 94 |
|
109 | 95 | ingredientCount = fluidIngredients.size(); |
110 | 96 | outputCount = fluidResults.size(); |
111 | 97 |
|
112 | 98 | if (ingredientCount > getMaxFluidInputCount()) |
113 | | - logger.warn(messageHeader + " has more fluid inputs (" + ingredientCount + ") than supported (" |
| 99 | + errors.add("Recipe has more fluid inputs (" + ingredientCount + ") than supported (" |
114 | 100 | + getMaxFluidInputCount() + ")."); |
115 | 101 |
|
116 | 102 | if (outputCount > getMaxFluidOutputCount()) |
117 | | - logger.warn(messageHeader + " has more fluid outputs (" + outputCount + ") than supported (" |
| 103 | + errors.add("Recipe has more fluid outputs (" + outputCount + ") than supported (" |
118 | 104 | + getMaxFluidOutputCount() + ")."); |
119 | 105 |
|
120 | 106 | if (processingDuration > 0 && !canSpecifyDuration()) |
121 | | - logger.warn(messageHeader + " specified a duration. Durations have no impact on this type of recipe."); |
| 107 | + errors.add("Recipe specified a duration. Durations have no impact on this type of recipe."); |
122 | 108 |
|
123 | 109 | if (requiredHeat != HeatCondition.NONE && !canRequireHeat()) |
124 | | - logger.warn( |
125 | | - messageHeader + " specified a heat condition. Heat conditions have no impact on this type of recipe."); |
| 110 | + errors.add("Recipe specified a heat condition. Heat conditions have no impact on this type of recipe."); |
| 111 | + |
| 112 | + return errors; |
126 | 113 | } |
127 | 114 |
|
128 | 115 | public P getParams() { |
@@ -226,16 +213,14 @@ public IRecipeTypeInfo getTypeInfo() { |
226 | 213 | public static <P extends ProcessingRecipeParams, R extends ProcessingRecipe<?, P>> MapCodec<R> codec( |
227 | 214 | Factory<P, R> factory, MapCodec<P> paramsCodec |
228 | 215 | ) { |
229 | | - return RecordCodecBuilder.mapCodec(instance -> instance.group( |
230 | | - paramsCodec.xmap(factory::create, recipe -> recipe.getParams()).forGetter(Function.identity()), |
231 | | - ExtraCodecs.retrieveContext(ops -> ops instanceof ResourceLocationAwareOps awareOps |
232 | | - ? DataResult.success(Optional.ofNullable(awareOps.getResourceLocation())) |
233 | | - : DataResult.success(Optional.<ResourceLocation>empty()) |
234 | | - ).forGetter(recipe -> Optional.empty()) |
235 | | - ).apply(instance, (recipe, id) -> { |
236 | | - id.ifPresent(recipe::validate); |
237 | | - return recipe; |
238 | | - })); |
| 216 | + return paramsCodec.xmap(factory::create, recipe -> recipe.getParams()) |
| 217 | + .validate(recipe -> { |
| 218 | + var errors = recipe.validate(); |
| 219 | + if (errors.isEmpty()) |
| 220 | + return DataResult.success(recipe); |
| 221 | + errors.add(recipe.getClass().getSimpleName() + " failed validation:"); |
| 222 | + return DataResult.error(() -> Joiner.on('\n').join(errors), recipe); |
| 223 | + }); |
239 | 224 | } |
240 | 225 |
|
241 | 226 | @FunctionalInterface |
|
0 commit comments