Skip to content

Commit 9bef42c

Browse files
committed
Add support for unknown recipes
1 parent dd608d8 commit 9bef42c

File tree

7 files changed

+90
-8
lines changed

7 files changed

+90
-8
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ repositories {
1717
}
1818

1919
dependencies {
20+
compileOnly("org.jetbrains:annotations:24.0.0")
2021
implementation("com.google.code.gson:gson:2.9.0")
2122
testImplementation("io.kotest:kotest-runner-junit5:5.3.1")
2223
}

src/main/java/io/github/moulberry/repo/NEURepository.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import com.google.gson.Gson;
44
import com.google.gson.GsonBuilder;
55
import com.google.gson.reflect.TypeToken;
6-
import io.github.moulberry.repo.vendored.RuntimeTypeAdapterFactory;
76
import io.github.moulberry.repo.data.*;
7+
import io.github.moulberry.repo.vendored.RuntimeTypeAdapterFactory;
88
import lombok.Getter;
99
import lombok.NonNull;
1010
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -23,6 +23,8 @@ public final class NEURepository {
2323

2424
final Gson gson = new GsonBuilder()
2525
.setPrettyPrinting()
26+
.registerTypeAdapter(new TypeToken<NEUUnknownRecipe>() {
27+
}.getType(), new NEUUnknownRecipe.Serializer())
2628
.registerTypeAdapter(new TypeToken<NEUIngredient>() {
2729
}.getType(), new NEUIngredient.Serializer())
2830
.registerTypeAdapter(new TypeToken<Coordinate>() {
@@ -32,12 +34,13 @@ public final class NEURepository {
3234
.registerTypeAdapter(new TypeToken<NEUCraftingRecipe>() {
3335
}.getType(), new NEUCraftingRecipe.Serializer())
3436
.registerTypeAdapterFactory(
35-
RuntimeTypeAdapterFactory.of(NEURecipe.class, "type")
37+
RuntimeTypeAdapterFactory.of(NEURecipe.class, "type", true)
3638
.registerSubtype(NEUForgeRecipe.class, "forge")
3739
.registerSubtype(NEUTradeRecipe.class, "trade")
3840
.registerSubtype(NEUCraftingRecipe.class, "crafting")
3941
.registerSubtype(NEUMobDropRecipe.class, "drops")
4042
.registerSubtype(NEUNpcShopRecipe.class, "npc_shop")
43+
.setFallbackType(NEUUnknownRecipe.class)
4144
.setDefaultTypeTag("crafting")
4245
)
4346
.create();

src/main/java/io/github/moulberry/repo/data/NEUIngredient.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
@Getter
1010
public class NEUIngredient {
1111
@NEUId String itemId;
12-
int amount;
12+
double amount;
1313
public static final String NEU_SENTINEL_EMPTY = "NEU_SENTINEL_EMPTY";
1414
public static final NEUIngredient SENTINEL_EMPTY = new NEUIngredient();
1515

@@ -32,7 +32,7 @@ public static NEUIngredient fromString(String string) {
3232
String[] parts = string.split(":");
3333
NEUIngredient ingredient = new NEUIngredient();
3434
if (parts.length == 2) {
35-
ingredient.amount = Integer.parseInt(parts[1]);
35+
ingredient.amount = Double.parseDouble(parts[1]);
3636
} else if (parts.length == 1) {
3737
ingredient.amount = 1;
3838
} else {
@@ -59,6 +59,6 @@ public NEUIngredient deserialize(JsonElement json, Type typeOfT, JsonDeserializa
5959

6060
@Override
6161
public String toString() {
62-
return String.format("NEUIngredient{%s:%d}", itemId, amount);
62+
return String.format("NEUIngredient{%s:%f}", itemId, amount);
6363
}
6464
}

src/main/java/io/github/moulberry/repo/data/NEURecipe.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package io.github.moulberry.repo.data;
22

3+
import org.jetbrains.annotations.ApiStatus;
4+
35
import java.util.Collection;
46

57
public interface NEURecipe {
68
/**
79
* This is to be called once, after deserialization by the item that contains this recipe. This will be done
810
* automatically by {@link NEUItem#getRecipes()}.
9-
* This method is deprecated because it should only be called by the Repository itself, not consumers of this library.
1011
*/
11-
@Deprecated
12+
@ApiStatus.OverrideOnly
1213
default void fillItemInfo(NEUItem item) {
1314
}
1415

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package io.github.moulberry.repo.data;
2+
3+
import com.google.gson.*;
4+
import lombok.Getter;
5+
import lombok.RequiredArgsConstructor;
6+
import org.jetbrains.annotations.Nullable;
7+
8+
import java.lang.reflect.Type;
9+
import java.util.Collection;
10+
import java.util.Collections;
11+
12+
@RequiredArgsConstructor
13+
public class NEUUnknownRecipe implements NEURecipe {
14+
/**
15+
* Type tag of the unknown recipe type.
16+
*/
17+
@Getter
18+
@Nullable
19+
final String type;
20+
21+
/**
22+
* The json tree of this unknown recipe.
23+
*/
24+
@Getter
25+
final JsonObject tree;
26+
27+
/**
28+
* Item associated with this recipe.
29+
*/
30+
@Getter
31+
NEUItem item;
32+
33+
@Override
34+
public Collection<NEUIngredient> getAllInputs() {
35+
return Collections.singleton(NEUIngredient.fromItem(item, 1));
36+
}
37+
38+
@Override
39+
public Collection<NEUIngredient> getAllOutputs() {
40+
return Collections.emptyList();
41+
}
42+
43+
@Override
44+
public void fillItemInfo(NEUItem item) {
45+
this.item = item;
46+
}
47+
48+
public static class Serializer implements JsonDeserializer<NEUUnknownRecipe> {
49+
50+
@Override
51+
public NEUUnknownRecipe deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
52+
JsonElement type = json.getAsJsonObject().get("type");
53+
return new NEUUnknownRecipe(type != null && type.isJsonPrimitive() ? type.getAsString() : null, json.getAsJsonObject());
54+
}
55+
}
56+
}

src/main/java/io/github/moulberry/repo/vendored/RuntimeTypeAdapterFactory.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
129129
private final Map<String, Class<?>> labelToSubtype = new LinkedHashMap<>();
130130
private final Map<Class<?>, String> subtypeToLabel = new LinkedHashMap<>();
131131
private final boolean maintainType;
132+
private Class<?> fallbackType = null;
132133
private String defaultType; // NEU modification
133134

134135
// NEU modification
@@ -187,6 +188,18 @@ public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type, Str
187188
return this;
188189
}
189190

191+
// NEU Modification
192+
193+
/**
194+
* Set a fallback type to be used if the read type tag is not registered
195+
*/
196+
public RuntimeTypeAdapterFactory<T> setFallbackType(Class<? extends T> fallbackType) {
197+
if (this.fallbackType != null)
198+
throw new IllegalArgumentException("Cannot set fallback type twice");
199+
this.fallbackType = fallbackType;
200+
return this;
201+
}
202+
190203
/**
191204
* Registers {@code type} identified by its {@link Class#getSimpleName simple name}. Labels are case sensitive.
192205
*
@@ -206,6 +219,8 @@ public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) {
206219
final TypeAdapter<JsonElement> jsonElementAdapter = gson.getAdapter(JsonElement.class);
207220
final Map<String, TypeAdapter<?>> labelToDelegate = new LinkedHashMap<>();
208221
final Map<Class<?>, TypeAdapter<?>> subtypeToDelegate = new LinkedHashMap<>();
222+
final TypeAdapter<?> fallbackAdapter = fallbackType != null ? gson.getDelegateAdapter(this, TypeToken.get(fallbackType)) : null;
223+
209224
for (Map.Entry<String, Class<?>> entry : labelToSubtype.entrySet()) {
210225
TypeAdapter<?> delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.getValue()));
211226
labelToDelegate.put(entry.getKey(), delegate);
@@ -240,7 +255,7 @@ public R read(JsonReader in) throws IOException {
240255
}
241256
String label = labelJsonElement.getAsString();
242257
@SuppressWarnings("unchecked") // registration requires that subtype extends T
243-
TypeAdapter<R> delegate = (TypeAdapter<R>) labelToDelegate.get(label);
258+
TypeAdapter<R> delegate = (TypeAdapter<R>) labelToDelegate.getOrDefault(label, fallbackAdapter);
244259
if (delegate == null) {
245260
throw new JsonParseException("cannot deserialize " + baseType + " subtype named "
246261
+ label + "; did you forget to register a subtype?");

src/test/java/TestMain.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.github.moulberry.repo.NEURepositoryVersion;
55
import io.github.moulberry.repo.data.NEUForgeRecipe;
66
import io.github.moulberry.repo.data.NEUMobDropRecipe;
7+
import io.github.moulberry.repo.data.NEUUnknownRecipe;
78

89
import java.nio.file.Paths;
910
import java.util.stream.Collectors;
@@ -17,6 +18,11 @@ public static void main(String[] args) throws NEURepositoryException {
1718
NEURepository repository = NEURepository.of(Paths.get("NotEnoughUpdates-REPO"));
1819
NEURecipeCache recipes = NEURecipeCache.forRepo(repository);
1920
repository.reload();
21+
System.out.println("unknown recipe types: " + repository.getItems().getItems().values().stream()
22+
.flatMap(it -> it.getRecipes().stream())
23+
.filter(it -> it instanceof NEUUnknownRecipe).map(it -> (NEUUnknownRecipe) it)
24+
.map(NEUUnknownRecipe::getType)
25+
.collect(Collectors.toSet()));
2026
System.out.println("pet mf (115): " + repository.getConstants().getBonuses().getPetRewards(115));
2127
System.out.println("skill reward (combat 60): " + repository.getConstants().getBonuses().getAccumulativeLevelingRewards("skill_combat", 60));
2228
System.out.println("parent of FLAWED_AMETHYST_GEM: " + repository.getConstants().getParents().getParent("FLAWED_AMETHYST_GEM"));

0 commit comments

Comments
 (0)