-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathRecipeLink.java
214 lines (175 loc) · 7.11 KB
/
RecipeLink.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
package com.almostreliable.unified.unification.recipe;
import net.minecraft.resources.ResourceLocation;
import com.almostreliable.unified.api.unification.recipe.RecipeData;
import com.almostreliable.unified.utils.JsonCompare;
import com.google.common.base.Preconditions;
import com.google.gson.JsonObject;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
public class RecipeLink implements RecipeData {
private final ResourceLocation id;
private final ResourceLocation type;
private final JsonObject originalRecipe;
@Nullable private DuplicateLink duplicateLink;
@Nullable private JsonObject unifiedRecipe;
public RecipeLink(ResourceLocation id, JsonObject originalRecipe) {
this.id = id;
this.originalRecipe = originalRecipe;
try {
this.type = ResourceLocation.parse(originalRecipe.get("type").getAsString());
} catch (Exception e) {
throw new IllegalArgumentException("could not detect recipe type for recipe " + id);
}
}
/**
* Compare two recipes for equality with given rules. Keys from rules will automatically count as ignored field for the base comparison.
* If base comparison succeed then the recipes will be compared for equality with rules from {@link JsonCompare.Rule}.
* Rules are sorted, first rule with the highest priority will be used.
*
* @param first first recipe to compare
* @param second second recipe to compare
* @param compareSettings Settings to use for comparison.
* @return the recipe where rules are applied and the recipes are compared for equality, or null if the recipes are not equal
*/
@Nullable
public static RecipeLink compare(RecipeLink first, RecipeLink second, JsonCompare.CompareSettings compareSettings) {
JsonObject selfActual = first.getActual();
JsonObject toCompareActual = second.getActual();
JsonObject compare = null;
if (first.getType().toString().equals("minecraft:crafting_shaped")) {
compare = JsonCompare.compareShaped(selfActual, toCompareActual, compareSettings);
} else if (JsonCompare.matches(selfActual, toCompareActual, compareSettings)) {
compare = JsonCompare.compare(compareSettings.getRules(), selfActual, toCompareActual);
}
if (compare == null) return null;
if (compare == selfActual) return first;
if (compare == toCompareActual) return second;
return null;
}
@Override
public ResourceLocation getId() {
return id;
}
@Override
public ResourceLocation getType() {
return type;
}
@Override
public boolean hasProperty(String key) {
return getOriginal().has(key);
}
public JsonObject getOriginal() {
return originalRecipe;
}
public boolean hasDuplicateLink() {
return duplicateLink != null;
}
@Nullable
public DuplicateLink getDuplicateLink() {
return duplicateLink;
}
private void updateDuplicateLink(@Nullable DuplicateLink duplicateLink) {
Preconditions.checkNotNull(duplicateLink);
if (hasDuplicateLink() && getDuplicateLink() != duplicateLink) {
throw new IllegalStateException("recipe is already linked to " + getDuplicateLink());
}
this.duplicateLink = duplicateLink;
this.duplicateLink.addDuplicate(this);
}
@Nullable
public JsonObject getUnified() {
return unifiedRecipe;
}
public boolean isUnified() {
return unifiedRecipe != null;
}
void setUnified(JsonObject json) {
Preconditions.checkNotNull(json);
if (isUnified()) {
throw new IllegalStateException("recipe already unified");
}
this.unifiedRecipe = json;
}
@Override
public String toString() {
String duplicate = duplicateLink != null ? " (duplicate)" : "";
String unified = unifiedRecipe != null ? " (unified)" : "";
return String.format("['%s'] %s%s%s", type, id, duplicate, unified);
}
/**
* Checks for duplicate against given recipe data. If recipe data already has a duplicate link,
* the master from the link will be used. Otherwise, we will create a new link if needed.
*
* @param otherRecipe Recipe data to check for duplicate against.
* @param compareSettings Settings to use for comparison.
* @return True if recipe is a duplicate, false otherwise.
*/
public boolean handleDuplicate(RecipeLink otherRecipe, JsonCompare.CompareSettings compareSettings) {
DuplicateLink selfDuplicate = getDuplicateLink();
DuplicateLink otherDuplicate = otherRecipe.getDuplicateLink();
if (selfDuplicate != null && otherDuplicate != null) {
return selfDuplicate == otherDuplicate;
}
if (selfDuplicate == null && otherDuplicate == null) {
RecipeLink compare = compare(this, otherRecipe, compareSettings);
if (compare == null) {
return false;
}
DuplicateLink newLink = new DuplicateLink(compare);
updateDuplicateLink(newLink);
otherRecipe.updateDuplicateLink(newLink);
return true;
}
if (otherDuplicate != null) {
RecipeLink compare = compare(this, otherDuplicate.getMaster(), compareSettings);
if (compare == null) {
return false;
}
otherDuplicate.updateMaster(compare);
updateDuplicateLink(otherDuplicate);
return true;
}
// selfDuplicate != null
RecipeLink compare = compare(selfDuplicate.getMaster(), otherRecipe, compareSettings);
if (compare == null) {
return false;
}
selfDuplicate.updateMaster(compare);
otherRecipe.updateDuplicateLink(selfDuplicate);
return true;
}
public JsonObject getActual() {
return getUnified() != null ? getUnified() : getOriginal();
}
public static final class DuplicateLink {
private final Set<RecipeLink> recipes = new HashSet<>();
private RecipeLink currentMaster;
private DuplicateLink(RecipeLink master) {
updateMaster(master);
}
private void updateMaster(RecipeLink master) {
Preconditions.checkNotNull(master);
addDuplicate(master);
this.currentMaster = master;
}
private void addDuplicate(RecipeLink recipe) {
recipes.add(recipe);
}
public RecipeLink getMaster() {
return currentMaster;
}
public Set<RecipeLink> getRecipes() {
return Collections.unmodifiableSet(recipes);
}
public Set<RecipeLink> getRecipesWithoutMaster() {
return recipes.stream().filter(recipe -> recipe != currentMaster).collect(Collectors.toSet());
}
@Override
public String toString() {
return "Link{currentMaster=" + currentMaster + ", recipes=" + recipes.size() + "}";
}
}
}