-
-
Notifications
You must be signed in to change notification settings - Fork 119
/
IRecipeManager.java
247 lines (224 loc) · 9.12 KB
/
IRecipeManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
package com.blamejared.crafttweaker.api.managers;
import com.blamejared.crafttweaker.CraftTweaker;
import com.blamejared.crafttweaker.api.CraftTweakerAPI;
import com.blamejared.crafttweaker.api.annotations.ZenRegister;
import com.blamejared.crafttweaker.api.brackets.CommandStringDisplayable;
import com.blamejared.crafttweaker.api.data.IData;
import com.blamejared.crafttweaker.api.item.IItemStack;
import com.blamejared.crafttweaker.impl.actions.recipes.ActionAddRecipe;
import com.blamejared.crafttweaker.impl.actions.recipes.ActionRemoveAll;
import com.blamejared.crafttweaker.impl.actions.recipes.ActionRemoveRecipeByModid;
import com.blamejared.crafttweaker.impl.actions.recipes.ActionRemoveRecipeByName;
import com.blamejared.crafttweaker.impl.actions.recipes.ActionRemoveRecipeByOutput;
import com.blamejared.crafttweaker.impl.actions.recipes.ActionRemoveRecipeByRegex;
import com.blamejared.crafttweaker.impl.data.MapData;
import com.blamejared.crafttweaker.impl.managers.CTCraftingTableManager;
import com.blamejared.crafttweaker_annotations.annotations.Document;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.item.crafting.RecipeManager;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import org.openzen.zencode.java.ZenCodeType;
import java.util.Collections;
import java.util.Map;
/**
* Default interface for Registry based handlers as they can all remove recipes by ResourceLocation.
*
* @docParam this craftingTable
*/
@ZenRegister
@ZenCodeType.Name("crafttweaker.api.registries.IRecipeManager")
@Document("vanilla/api/managers/IRecipeManager")
public interface IRecipeManager extends CommandStringDisplayable {
Gson JSON_RECIPE_GSON = new GsonBuilder().create();
/**
* Adds a recipe based on a provided IData. The provided IData should represent a DataPack JSON, this effectively allows you to register recipes for any DataPack supporting IRecipeType systems.
*
* @param name name of the recipe
* @param data data representing the json file
*
* @docParam name "recipe_name"
* @docParam data {ingredient:{item:<item:minecraft:gold_ore>.registryName},result:<item:minecraft:cooked_porkchop>.registryName,experience:0.35 as float, cookingtime:100}
*/
@ZenCodeType.Method
default void addJSONRecipe(String name, IData data) {
name = validateRecipeName(name);
if(!(data instanceof MapData)) {
throw new IllegalArgumentException("Json recipe's IData should be a MapData!");
}
MapData mapData = (MapData) data;
JsonObject recipeObject = JSON_RECIPE_GSON.fromJson(mapData.toJsonString(), JsonObject.class);
String recipeTypeKey = getBracketResourceLocation().toString();
if(recipeObject.has("type")) {
if(!recipeObject.get("type").getAsString().equals(recipeTypeKey))
throw new IllegalArgumentException("Cannot override recipe type! Given: \"" + recipeObject.get("type").getAsString() + "\", Expected: \"" + recipeTypeKey + "\"");
} else {
recipeObject.addProperty("type", recipeTypeKey);
}
IRecipe<?> iRecipe = RecipeManager.deserializeRecipe(new ResourceLocation(CraftTweaker.MODID, name), recipeObject);
CraftTweakerAPI.apply(new ActionAddRecipe(this, iRecipe, ""));
}
/**
* Remove a recipe based on it's output.
*
* @param output output of the recipe
*
* @docParam output <item:minecraft:glass>
*/
@ZenCodeType.Method
default void removeRecipe(IItemStack output) {
CraftTweakerAPI.apply(new ActionRemoveRecipeByOutput(this, output));
}
/**
* Remove recipe based on Registry name
*
* @param name registry name of recipe to remove
*
* @docParam name "minecraft:furnace"
*/
@ZenCodeType.Method
default void removeByName(String name) {
CraftTweakerAPI.apply(new ActionRemoveRecipeByName(this, new ResourceLocation(name)));
}
/**
* Remove recipe based on Registry name modid
*
* @param modid modid of the recipes to remove
*
* @docParam modid "minecraft"
*/
@ZenCodeType.Method
default void removeByModid(String modid) {
CraftTweakerAPI.apply(new ActionRemoveRecipeByModid(this, modid));
}
/**
* Remove recipe based on Registry name modid with an added exclusion check, so you can remove the whole mod besides a few specified.
*
* @param modid modid of the recipes to remove
* @param exclude recipes to exlude from being removed.
*
* @docParam modid "minecraft"
* @docParam exclude (name as string) => {return name == "orange_wool";}
*/
@ZenCodeType.Method
default void removeByModid(String modid, RecipeFilter exclude) {
CraftTweakerAPI.apply(new ActionRemoveRecipeByModid(this, modid, exclude));
}
/**
* Remove recipe based on regex
*
* @param regex regex to match against
*
* @docParam regex "\\d_\\d"
*/
@ZenCodeType.Method
default void removeByRegex(String regex) {
CraftTweakerAPI.apply(new ActionRemoveRecipeByRegex(this, regex));
}
/**
* Remove all recipes in this registry
*/
@ZenCodeType.Method
default void removeAll() {
CraftTweakerAPI.apply(new ActionRemoveAll(this));
}
/**
* Gets the recipe type for the registry to remove from.
*
* @return IRecipeType of this registry.
*/
IRecipeType getRecipeType();
/**
* Gets all the vanilla IRecipes for this recipe type.
*
* @return Map of ResourceLocation to IRecipe for this recipe type.
*/
default Map<ResourceLocation, IRecipe<?>> getRecipes() {
return CTCraftingTableManager.recipeManager.recipes.getOrDefault(getRecipeType(), Collections.emptyMap());
}
/**
* Checks if the given name is a valid ResourceLocation path, used to ensure recipe names are correct
*
* @param name name to check
*/
default String validateRecipeName(String name) {
name = fixRecipeName(name);
if(!name.chars().allMatch((ch) -> ch == 95 || ch == 45 || ch >= 97 && ch <= 122 || ch >= 48 && ch <= 57 || ch == 47 || ch == 46)) {
throw new IllegalArgumentException("Given name does not fit the \"[a-z0-9/._-]\" regex! Name: \"" + name + "\"");
}
return name;
}
/**
* Fixes and logs some common errors that people run into with recipe names
*
* @param name name to check
*
* @return fixed name
*/
default String fixRecipeName(String name) {
String fixed = name;
if(fixed.indexOf(':') >= 0) {
String temp = fixed.replaceAll(":", ".");
CraftTweakerAPI.logWarning("Invalid recipe name \"%s\", recipe names cannot have a \":\"! New recipe name: \"%s\"", fixed, temp);
fixed = temp;
}
if(fixed.indexOf(' ') >= 0) {
String temp = fixed.replaceAll(" ", ".");
CraftTweakerAPI.logWarning("Invalid recipe name \"%s\", recipe names cannot have a \" \"! New recipe name: \"%s\"", fixed, temp);
fixed = temp;
}
if(!fixed.toLowerCase().equals(fixed)) {
String temp = fixed.toLowerCase();
CraftTweakerAPI.logWarning("Invalid recipe name \"%s\", recipe names have to be lowercase! New recipe name: \"%s\"", fixed, temp);
fixed = temp;
}
return fixed;
}
/**
* Gets the resource location to get this Recipe handler
* Default just looks up the Recipe Type key from the registry
*/
default ResourceLocation getBracketResourceLocation() {
return Registry.RECIPE_TYPE.getKey(getRecipeType());
}
@FunctionalInterface
@ZenRegister
@ZenCodeType.Name("crafttweaker.api.recipe.RecipeFilter")
@Document("vanilla/api/recipe/RecipeFilter")
interface RecipeFilter {
@ZenCodeType.Method
boolean test(String name);
}
@FunctionalInterface
@ZenRegister
@ZenCodeType.Name("crafttweaker.api.recipe.RecipeFunctionSingle")
@Document("vanilla/api/recipe/RecipeFunctionSingle")
interface RecipeFunctionSingle {
@ZenCodeType.Method
IItemStack process(IItemStack usualOut, IItemStack inputs);
}
@FunctionalInterface
@ZenRegister
@ZenCodeType.Name("crafttweaker.api.recipe.RecipeFunctionArray")
@Document("vanilla/api/recipe/RecipeFunctionArray")
interface RecipeFunctionArray {
@ZenCodeType.Method
IItemStack process(IItemStack usualOut, IItemStack[] inputs);
}
@FunctionalInterface
@ZenRegister
@ZenCodeType.Name("crafttweaker.api.recipe.RecipeFunctionMatrix")
@Document("vanilla/api/recipe/RecipeFunctionMatrix")
interface RecipeFunctionMatrix {
@ZenCodeType.Method
IItemStack process(IItemStack usualOut, IItemStack[][] inputs);
}
@Override
default String getCommandString() {
return "<recipetype:" + getRecipeType().toString() + ">";
}
}