mirror of
https://github.com/AlmostReliable/almostunified.git
synced 2024-11-14 19:25:13 -05:00
Set up tests & clean up
This commit is contained in:
parent
ce9543c55d
commit
455d275508
29 changed files with 774 additions and 189 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -19,5 +19,6 @@ build
|
||||||
.gradle
|
.gradle
|
||||||
|
|
||||||
# other
|
# other
|
||||||
|
*.log
|
||||||
eclipse
|
eclipse
|
||||||
run
|
run
|
||||||
|
|
|
@ -45,6 +45,12 @@ dependencies {
|
||||||
* DON'T USE THIS! NEEDED TO COMPILE THIS PROJECT
|
* DON'T USE THIS! NEEDED TO COMPILE THIS PROJECT
|
||||||
*/
|
*/
|
||||||
modCompileOnly("net.fabricmc:fabric-loader:${fabricLoaderVersion}")
|
modCompileOnly("net.fabricmc:fabric-loader:${fabricLoaderVersion}")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test dependencies
|
||||||
|
*/
|
||||||
|
testImplementation ("org.junit.jupiter:junit-jupiter-api:5.8.1")
|
||||||
|
testRuntimeOnly ("org.junit.jupiter:junit-jupiter-engine:5.8.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.processResources {
|
tasks.processResources {
|
||||||
|
@ -75,3 +81,7 @@ buildConfig {
|
||||||
|
|
||||||
packageName(project.group as String)
|
packageName(project.group as String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType<Test> {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
|
@ -6,12 +6,12 @@ import com.almostreliable.unified.utils.ReplacementMap;
|
||||||
import com.almostreliable.unified.utils.TagMap;
|
import com.almostreliable.unified.utils.TagMap;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
|
||||||
import net.minecraft.tags.TagManager;
|
import net.minecraft.tags.TagManager;
|
||||||
import net.minecraft.world.item.Item;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public abstract class AlmostUnifiedRuntime {
|
public abstract class AlmostUnifiedRuntime {
|
||||||
|
|
||||||
|
@ -29,7 +29,8 @@ public abstract class AlmostUnifiedRuntime {
|
||||||
config.load();
|
config.load();
|
||||||
modPriorities = config.getModPriorities();
|
modPriorities = config.getModPriorities();
|
||||||
onRun();
|
onRun();
|
||||||
ReplacementMap replacementMap = createContext(config.getAllowedTags(), modPriorities);
|
TagMap tagMap = createTagMap();
|
||||||
|
ReplacementMap replacementMap = new ReplacementMap(tagMap, config.getAllowedTags(), modPriorities);
|
||||||
RecipeTransformer transformer = new RecipeTransformer(recipeHandlerFactory, replacementMap);
|
RecipeTransformer transformer = new RecipeTransformer(recipeHandlerFactory, replacementMap);
|
||||||
transformer.transformRecipes(recipes);
|
transformer.transformRecipes(recipes);
|
||||||
}
|
}
|
||||||
|
@ -46,26 +47,5 @@ public abstract class AlmostUnifiedRuntime {
|
||||||
return TagMap.create(tagManager);
|
return TagMap.create(tagManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ReplacementMap createContext(List<TagKey<Item>> allowedTags, List<String> modPriorities) {
|
|
||||||
TagMap tagMap = createTagMap();
|
|
||||||
Map<ResourceLocation, TagKey<Item>> itemToTagMapping = new HashMap<>(allowedTags.size());
|
|
||||||
|
|
||||||
for (TagKey<Item> tag : allowedTags) {
|
|
||||||
Collection<ResourceLocation> items = tagMap.getItems(tag);
|
|
||||||
for (ResourceLocation item : items) {
|
|
||||||
if (itemToTagMapping.containsKey(item)) {
|
|
||||||
AlmostUnified.LOG.warn("Item '{}' already has a tag '{}' for recipe replacement. Skipping this tag",
|
|
||||||
item,
|
|
||||||
tag);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
itemToTagMapping.put(item, tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ReplacementMap(tagMap, itemToTagMapping, modPriorities);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void onRun();
|
protected abstract void onRun();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
package com.almostreliable.unified;
|
package com.almostreliable.unified;
|
||||||
|
|
||||||
|
import com.almostreliable.unified.utils.UnifyTag;
|
||||||
import com.electronwill.nightconfig.core.Config;
|
import com.electronwill.nightconfig.core.Config;
|
||||||
import com.electronwill.nightconfig.core.ConfigSpec;
|
import com.electronwill.nightconfig.core.ConfigSpec;
|
||||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
import com.electronwill.nightconfig.core.file.FileConfig;
|
import com.electronwill.nightconfig.core.file.FileConfig;
|
||||||
import com.google.common.collect.HashMultimap;
|
import com.google.common.collect.HashMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import net.minecraft.core.Registry;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -164,13 +163,13 @@ public class ModConfig {
|
||||||
return currentConfig.get(UNIFICATION_MOD_PRIORITIES);
|
return currentConfig.get(UNIFICATION_MOD_PRIORITIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TagKey<Item>> getAllowedTags() {
|
public List<UnifyTag<Item>> getAllowedTags() {
|
||||||
if (currentConfig == null) {
|
if (currentConfig == null) {
|
||||||
throw new IllegalStateException("Config is not loaded");
|
throw new IllegalStateException("Config is not loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
Multimap<String, String> variables = compileVariables();
|
Multimap<String, String> variables = compileVariables();
|
||||||
List<TagKey<Item>> collectedPattern = new ArrayList<>();
|
List<UnifyTag<Item>> collectedPattern = new ArrayList<>();
|
||||||
|
|
||||||
Collection<String> patterns = currentConfig.get(UNIFICATION_PATTERN);
|
Collection<String> patterns = currentConfig.get(UNIFICATION_PATTERN);
|
||||||
for (String pattern : patterns) {
|
for (String pattern : patterns) {
|
||||||
|
@ -183,7 +182,7 @@ public class ModConfig {
|
||||||
if (rl == null) {
|
if (rl == null) {
|
||||||
AlmostUnified.LOG.warn("Invalid pattern: " + s);
|
AlmostUnified.LOG.warn("Invalid pattern: " + s);
|
||||||
} else {
|
} else {
|
||||||
TagKey<Item> tag = TagKey.create(Registry.ITEM_REGISTRY, rl);
|
UnifyTag<Item> tag = UnifyTag.item(rl);
|
||||||
collectedPattern.add(tag);
|
collectedPattern.add(tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,4 +10,5 @@ public class RecipeConstants {
|
||||||
public static final String OUTPUT = "output";
|
public static final String OUTPUT = "output";
|
||||||
public static final String RESULT = "result";
|
public static final String RESULT = "result";
|
||||||
public static final String RESULTS = "results";
|
public static final String RESULTS = "results";
|
||||||
|
public static final String VALUE = "value";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package com.almostreliable.unified.api.recipe;
|
package com.almostreliable.unified.api.recipe;
|
||||||
|
|
||||||
|
import com.almostreliable.unified.utils.UnifyTag;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
public interface RecipeContext {
|
public interface RecipeContext {
|
||||||
|
|
||||||
|
@ -13,19 +15,18 @@ public interface RecipeContext {
|
||||||
ResourceLocation getReplacementForItem(@Nullable ResourceLocation item);
|
ResourceLocation getReplacementForItem(@Nullable ResourceLocation item);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
ResourceLocation getPreferredItemByTag(TagKey<Item> tag);
|
ResourceLocation getPreferredItemByTag(@Nullable UnifyTag<Item> tag);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
TagKey<Item> getPreferredTagByItem(@Nullable ResourceLocation item);
|
UnifyTag<Item> getPreferredTagByItem(@Nullable ResourceLocation item);
|
||||||
|
|
||||||
JsonElement replaceIngredient(JsonElement element);
|
JsonElement createIngredientReplacement(@Nullable JsonElement element);
|
||||||
|
|
||||||
JsonElement replaceResult(JsonElement element);
|
@Nullable
|
||||||
|
JsonElement createResultReplacement(@Nullable JsonElement element);
|
||||||
|
|
||||||
ResourceLocation getType();
|
ResourceLocation getType();
|
||||||
|
|
||||||
ResourceLocation getId();
|
|
||||||
|
|
||||||
boolean hasProperty(String property);
|
boolean hasProperty(String property);
|
||||||
|
|
||||||
default String getModId() {
|
default String getModId() {
|
||||||
|
|
|
@ -9,10 +9,6 @@ public interface RecipeTransformations {
|
||||||
|
|
||||||
void forEachObject(String property, BiFunction<JsonObject, RecipeContext, JsonObject> consumer);
|
void forEachObject(String property, BiFunction<JsonObject, RecipeContext, JsonObject> consumer);
|
||||||
|
|
||||||
void replaceIngredient(String property);
|
|
||||||
|
|
||||||
void replaceResult(String property);
|
|
||||||
|
|
||||||
void put(String property, BiFunction<JsonElement, RecipeContext, JsonElement> consumer);
|
void put(String property, BiFunction<JsonElement, RecipeContext, JsonElement> consumer);
|
||||||
|
|
||||||
<T extends JsonElement> void put(String property, Class<T> type, BiFunction<T, RecipeContext, T> consumer);
|
<T extends JsonElement> void put(String property, Class<T> type, BiFunction<T, RecipeContext, T> consumer);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.almostreliable.unified.api.recipe;
|
package com.almostreliable.unified.api.recipe;
|
||||||
|
|
||||||
import com.almostreliable.unified.utils.TagMap;
|
import com.almostreliable.unified.utils.TagMap;
|
||||||
|
import com.almostreliable.unified.utils.UnifyTag;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
|
@ -19,5 +20,5 @@ public interface ReplacementFallbackStrategy {
|
||||||
* @throws IllegalStateException if returning the lookupItem
|
* @throws IllegalStateException if returning the lookupItem
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
ResourceLocation getFallback(TagKey<Item> tag, Collection<ResourceLocation> potentialItems, TagMap tags);
|
ResourceLocation getFallback(UnifyTag<Item> tag, Collection<ResourceLocation> potentialItems, TagMap tags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,28 +2,26 @@ package com.almostreliable.unified.recipe;
|
||||||
|
|
||||||
import com.almostreliable.unified.api.recipe.RecipeConstants;
|
import com.almostreliable.unified.api.recipe.RecipeConstants;
|
||||||
import com.almostreliable.unified.api.recipe.RecipeContext;
|
import com.almostreliable.unified.api.recipe.RecipeContext;
|
||||||
|
import com.almostreliable.unified.utils.JsonUtils;
|
||||||
import com.almostreliable.unified.utils.ReplacementMap;
|
import com.almostreliable.unified.utils.ReplacementMap;
|
||||||
|
import com.almostreliable.unified.utils.UnifyTag;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonPrimitive;
|
import com.google.gson.JsonPrimitive;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.function.UnaryOperator;
|
|
||||||
|
|
||||||
@SuppressWarnings("SameParameterValue")
|
@SuppressWarnings("SameParameterValue")
|
||||||
public class RecipeContextImpl implements RecipeContext {
|
public class RecipeContextImpl implements RecipeContext {
|
||||||
private final ResourceLocation type;
|
private final ResourceLocation type;
|
||||||
private final ResourceLocation id;
|
|
||||||
private final JsonObject currentRecipe;
|
private final JsonObject currentRecipe;
|
||||||
private final ReplacementMap replacementMap;
|
private final ReplacementMap replacementMap;
|
||||||
|
|
||||||
public RecipeContextImpl(ResourceLocation type, ResourceLocation id, JsonObject currentRecipe, ReplacementMap replacementMap) {
|
public RecipeContextImpl(ResourceLocation type, JsonObject currentRecipe, ReplacementMap replacementMap) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.id = id;
|
|
||||||
this.currentRecipe = currentRecipe;
|
this.currentRecipe = currentRecipe;
|
||||||
this.replacementMap = replacementMap;
|
this.replacementMap = replacementMap;
|
||||||
}
|
}
|
||||||
|
@ -40,13 +38,17 @@ public class RecipeContextImpl implements RecipeContext {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public ResourceLocation getPreferredItemByTag(TagKey<Item> tag) {
|
public ResourceLocation getPreferredItemByTag(@Nullable UnifyTag<Item> tag) {
|
||||||
|
if (tag == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return replacementMap.getPreferredItemByTag(tag);
|
return replacementMap.getPreferredItemByTag(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public TagKey<Item> getPreferredTagByItem(@Nullable ResourceLocation item) {
|
public UnifyTag<Item> getPreferredTagByItem(@Nullable ResourceLocation item) {
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -54,58 +56,74 @@ public class RecipeContextImpl implements RecipeContext {
|
||||||
return replacementMap.getPreferredTag(item);
|
return replacementMap.getPreferredTag(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
protected JsonElement depthReplace(JsonElement element, String potentialFrom, String potentialTo, UnaryOperator<JsonPrimitive> primitiveCallback) {
|
public JsonElement createIngredientReplacement(@Nullable JsonElement element) {
|
||||||
if (element instanceof JsonPrimitive primitive) {
|
if (element == null) {
|
||||||
return primitiveCallback.apply(primitive);
|
return null;
|
||||||
|
}
|
||||||
|
JsonElement copy = element.deepCopy();
|
||||||
|
tryReplacingItemInIngredient(copy);
|
||||||
|
return element.equals(copy) ? null : copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryReplacingItemInIngredient(@Nullable JsonElement element) {
|
||||||
|
if (element instanceof JsonArray array) {
|
||||||
|
for (JsonElement e : array) {
|
||||||
|
tryReplacingItemInIngredient(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element instanceof JsonObject object) {
|
if (element instanceof JsonObject object) {
|
||||||
JsonElement replace = depthReplace(object.get(potentialFrom),
|
tryReplacingItemInIngredient(object.get(RecipeConstants.VALUE));
|
||||||
potentialFrom,
|
tryReplacingItemInIngredient(object.get(RecipeConstants.INGREDIENT));
|
||||||
potentialTo,
|
|
||||||
primitiveCallback);
|
|
||||||
if (replace != null) {
|
|
||||||
object.remove(potentialFrom);
|
|
||||||
object.add(potentialTo, replace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element instanceof JsonArray array) {
|
if (object.get(RecipeConstants.ITEM) instanceof JsonPrimitive primitive) {
|
||||||
for (int i = 0; i < array.size(); i++) {
|
ResourceLocation item = ResourceLocation.tryParse(primitive.getAsString());
|
||||||
JsonElement replace = depthReplace(array.get(i), potentialFrom, potentialTo, primitiveCallback);
|
UnifyTag<Item> tag = getPreferredTagByItem(item);
|
||||||
if (replace != null) {
|
if (tag != null) {
|
||||||
array.set(i, replace);
|
object.remove(RecipeConstants.ITEM);
|
||||||
|
object.add(RecipeConstants.TAG, new JsonPrimitive(tag.location().toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public JsonElement replaceIngredient(JsonElement element) {
|
public JsonElement createResultReplacement(@Nullable JsonElement element) {
|
||||||
return depthReplace(element, RecipeConstants.ITEM, RecipeConstants.TAG, primitive -> {
|
if (element == null) {
|
||||||
ResourceLocation item = ResourceLocation.tryParse(primitive.getAsString());
|
|
||||||
TagKey<Item> tag = getPreferredTagByItem(item);
|
|
||||||
if (tag != null) {
|
|
||||||
return new JsonPrimitive(tag.location().toString());
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
});
|
}
|
||||||
|
JsonElement copy = element.deepCopy();
|
||||||
|
JsonElement result = tryCreateResultReplacement(copy);
|
||||||
|
return element.equals(result) ? null : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Nullable
|
||||||
public JsonElement replaceResult(JsonElement element) {
|
private JsonElement tryCreateResultReplacement(JsonElement element) {
|
||||||
return depthReplace(element, RecipeConstants.ITEM, RecipeConstants.ITEM, primitive -> {
|
if (element instanceof JsonPrimitive primitive) {
|
||||||
ResourceLocation item = ResourceLocation.tryParse(primitive.getAsString());
|
ResourceLocation item = ResourceLocation.tryParse(primitive.getAsString());
|
||||||
ResourceLocation replacement = getReplacementForItem(item);
|
ResourceLocation replacement = getReplacementForItem(item);
|
||||||
if (replacement != null) {
|
if (replacement != null) {
|
||||||
return new JsonPrimitive(replacement.toString());
|
return new JsonPrimitive(replacement.toString());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (element instanceof JsonArray array) {
|
||||||
|
if (JsonUtils.replaceOn(array, this::tryCreateResultReplacement)) {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element instanceof JsonObject object) {
|
||||||
|
if (JsonUtils.replaceOn(object, RecipeConstants.ITEM, this::tryCreateResultReplacement)) {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -113,11 +131,6 @@ public class RecipeContextImpl implements RecipeContext {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResourceLocation getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasProperty(String property) {
|
public boolean hasProperty(String property) {
|
||||||
return currentRecipe.has(property);
|
return currentRecipe.has(property);
|
||||||
|
|
|
@ -32,16 +32,6 @@ public class RecipeTransformationsImpl implements RecipeTransformations {
|
||||||
put(property, JsonArray.class, arrayConsumer);
|
put(property, JsonArray.class, arrayConsumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void replaceIngredient(String property) {
|
|
||||||
put(property, JsonElement.class, (jsonElement, context) -> context.replaceIngredient(jsonElement));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void replaceResult(String property) {
|
|
||||||
put(property, JsonElement.class, (jsonElement, context) -> context.replaceResult(jsonElement));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void put(String property, BiFunction<JsonElement, RecipeContext, JsonElement> consumer) {
|
public void put(String property, BiFunction<JsonElement, RecipeContext, JsonElement> consumer) {
|
||||||
consumers.put(property, new Entry<>(JsonElement.class, consumer));
|
consumers.put(property, new Entry<>(JsonElement.class, consumer));
|
||||||
|
@ -52,16 +42,37 @@ public class RecipeTransformationsImpl implements RecipeTransformations {
|
||||||
consumers.put(property, new Entry<>(type, consumer));
|
consumers.put(property, new Entry<>(type, consumer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void transform(JsonObject json, RecipeContext context) {
|
@Nullable
|
||||||
|
public JsonObject transform(JsonObject json, RecipeContext context) {
|
||||||
|
JsonObject changedValues = new JsonObject();
|
||||||
|
|
||||||
for (var e : json.entrySet()) {
|
for (var e : json.entrySet()) {
|
||||||
Entry<?> consumer = consumers.get(e.getKey());
|
Entry<?> consumer = consumers.get(e.getKey());
|
||||||
if (consumer != null) {
|
if (consumer != null) {
|
||||||
JsonElement result = consumer.apply(e.getValue(), context);
|
JsonElement currentElement = e.getValue();
|
||||||
if (result != null) {
|
JsonElement transformedElement = consumer.apply(currentElement.deepCopy(), context);
|
||||||
e.setValue(result);
|
if (transformedElement != null && !transformedElement.equals(currentElement)) {
|
||||||
|
changedValues.add(e.getKey(), transformedElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changedValues.size() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// helps to preserve the order of the elements
|
||||||
|
JsonObject result = new JsonObject();
|
||||||
|
for (var entry : json.entrySet()) {
|
||||||
|
JsonElement changedValue = changedValues.get(entry.getKey());
|
||||||
|
if (changedValue != null) {
|
||||||
|
result.add(entry.getKey(), changedValue);
|
||||||
|
} else {
|
||||||
|
result.add(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record Entry<T extends JsonElement>(Class<T> expectedType,
|
private record Entry<T extends JsonElement>(Class<T> expectedType,
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class RecipeTransformer {
|
||||||
long start = System.nanoTime();
|
long start = System.nanoTime();
|
||||||
for (var entry : recipes.entrySet()) {
|
for (var entry : recipes.entrySet()) {
|
||||||
if (entry.getValue() instanceof JsonObject json) {
|
if (entry.getValue() instanceof JsonObject json) {
|
||||||
JsonObject transformedJson = transformRecipe(entry.getKey(), json);
|
JsonObject transformedJson = transformRecipe(json);
|
||||||
if (transformedJson != null) {
|
if (transformedJson != null) {
|
||||||
transformedRecipes++;
|
transformedRecipes++;
|
||||||
entry.setValue(transformedJson);
|
entry.setValue(transformedJson);
|
||||||
|
@ -54,25 +54,24 @@ public class RecipeTransformer {
|
||||||
AlmostUnified.LOG.info("{}: {} | {}",
|
AlmostUnified.LOG.info("{}: {} | {}",
|
||||||
StringUtils.leftPad(e.getKey().toString(), 40),
|
StringUtils.leftPad(e.getKey().toString(), 40),
|
||||||
StringUtils.leftPad(String.valueOf(e.getValue().size()), 4),
|
StringUtils.leftPad(String.valueOf(e.getValue().size()), 4),
|
||||||
e.getValue().toString());
|
e.getValue().stream().map(rl -> "\"" + rl.toString() + "\"").toList().toString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public JsonObject transformRecipe(ResourceLocation id, JsonObject json) {
|
public JsonObject transformRecipe(JsonObject json) {
|
||||||
ResourceLocation recipeType = getRecipeType(json);
|
ResourceLocation recipeType = getRecipeType(json);
|
||||||
if (recipeType == null) {
|
if (recipeType == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
RecipeContextImpl ctx = new RecipeContextImpl(recipeType, id, json, replacementMap);
|
RecipeContextImpl ctx = new RecipeContextImpl(recipeType, json, replacementMap);
|
||||||
RecipeTransformationsImpl builder = new RecipeTransformationsImpl();
|
RecipeTransformationsImpl builder = new RecipeTransformationsImpl();
|
||||||
factory.create(builder, ctx);
|
factory.create(builder, ctx);
|
||||||
JsonObject copy = json.deepCopy();
|
JsonObject result = builder.transform(json, ctx);
|
||||||
builder.transform(copy, ctx);
|
if (result != null) {
|
||||||
if (!json.equals(copy)) {
|
return result;
|
||||||
return copy;
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
AlmostUnified.LOG.warn("Error transforming recipe type '{}': {}",
|
AlmostUnified.LOG.warn("Error transforming recipe type '{}': {}",
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.almostreliable.unified.recipe.fallbacks;
|
||||||
|
|
||||||
import com.almostreliable.unified.api.recipe.ReplacementFallbackStrategy;
|
import com.almostreliable.unified.api.recipe.ReplacementFallbackStrategy;
|
||||||
import com.almostreliable.unified.utils.TagMap;
|
import com.almostreliable.unified.utils.TagMap;
|
||||||
|
import com.almostreliable.unified.utils.UnifyTag;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
|
@ -12,7 +13,7 @@ import java.util.Comparator;
|
||||||
// TODO use config and not this :D
|
// TODO use config and not this :D
|
||||||
public class StoneStrataFallbackStrategy implements ReplacementFallbackStrategy {
|
public class StoneStrataFallbackStrategy implements ReplacementFallbackStrategy {
|
||||||
@Override
|
@Override
|
||||||
public ResourceLocation getFallback(TagKey<Item> tag, Collection<ResourceLocation> potentialItems, TagMap tags) {
|
public ResourceLocation getFallback(UnifyTag<Item> tag, Collection<ResourceLocation> potentialItems, TagMap tags) {
|
||||||
if (tag.location().getPath().contains("ores")) {
|
if (tag.location().getPath().contains("ores")) {
|
||||||
return potentialItems
|
return potentialItems
|
||||||
.stream()
|
.stream()
|
||||||
|
|
|
@ -18,11 +18,11 @@ public class GenericRecipeHandler implements RecipeHandler {
|
||||||
@Override
|
@Override
|
||||||
public void collectTransformations(RecipeTransformations builder) {
|
public void collectTransformations(RecipeTransformations builder) {
|
||||||
for (String inputKey : inputKeys) {
|
for (String inputKey : inputKeys) {
|
||||||
builder.replaceIngredient(inputKey);
|
builder.put(inputKey, (json, ctx) -> ctx.createIngredientReplacement(json));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String outputKey : outputKeys) {
|
for (String outputKey : outputKeys) {
|
||||||
builder.replaceResult(outputKey);
|
builder.put(outputKey, (json, ctx) -> ctx.createResultReplacement(json));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,15 @@ public class RecipeHandlerFactory {
|
||||||
ShapedRecipeKeyHandler.INSTANCE.collectTransformations(builder);
|
ShapedRecipeKeyHandler.INSTANCE.collectTransformations(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecipeHandler byType = transformersByType.get(context.getType());
|
|
||||||
if (byType != null) {
|
|
||||||
byType.collectTransformations(builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
RecipeHandler byMod = transformersByModId.get(context.getModId());
|
RecipeHandler byMod = transformersByModId.get(context.getModId());
|
||||||
if (byMod != null) {
|
if (byMod != null) {
|
||||||
byMod.collectTransformations(builder);
|
byMod.collectTransformations(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecipeHandler byType = transformersByType.get(context.getType());
|
||||||
|
if (byType != null) {
|
||||||
|
byType.collectTransformations(builder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerForType(ResourceLocation type, RecipeHandler transformer) {
|
public void registerForType(ResourceLocation type, RecipeHandler transformer) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class ShapedRecipeKeyHandler implements RecipeHandler {
|
||||||
public void collectTransformations(RecipeTransformations builder) {
|
public void collectTransformations(RecipeTransformations builder) {
|
||||||
builder.put(KEY_PROPERTY, JsonObject.class, (json, context) -> {
|
builder.put(KEY_PROPERTY, JsonObject.class, (json, context) -> {
|
||||||
for (var entry : json.entrySet()) {
|
for (var entry : json.entrySet()) {
|
||||||
JsonElement result = context.replaceIngredient(entry.getValue());
|
JsonElement result = context.createIngredientReplacement(entry.getValue());
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
entry.setValue(result);
|
entry.setValue(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
package com.almostreliable.unified.utils;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
public class JsonQuery {
|
||||||
|
|
||||||
|
private final JsonElement element;
|
||||||
|
|
||||||
|
public static JsonQuery of(JsonElement element) {
|
||||||
|
return new JsonQuery(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonQuery of(JsonElement element, String path) {
|
||||||
|
String[] parts = path.split("/");
|
||||||
|
JsonQuery current = of(element);
|
||||||
|
for (String part : parts) {
|
||||||
|
if(StringUtils.isNumeric(part)) {
|
||||||
|
current = current.get(Integer.parseInt(part));
|
||||||
|
} else {
|
||||||
|
current = current.get(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonQuery(JsonElement element) {
|
||||||
|
this.element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonQuery get(String identifier) {
|
||||||
|
if(!element.isJsonObject()) {
|
||||||
|
throw new IllegalArgumentException("Expected JsonObject, got " + element.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonElement child = element.getAsJsonObject().get(identifier);
|
||||||
|
if(child == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JsonQuery(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonQuery get(int index) {
|
||||||
|
if(!element.isJsonArray()) {
|
||||||
|
throw new IllegalArgumentException("Expected JsonArray, got " + element.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonElement child = element.getAsJsonArray().get(index);
|
||||||
|
if(child == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JsonQuery(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonQuery get(String identifier, int index) {
|
||||||
|
return get(identifier).get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonObject asObject() {
|
||||||
|
return element.getAsJsonObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonArray asArray() {
|
||||||
|
return element.getAsJsonArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String asString() {
|
||||||
|
return element.getAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int asInt() {
|
||||||
|
return element.getAsInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean asBoolean() {
|
||||||
|
return element.getAsBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float asFloat() {
|
||||||
|
return element.getAsFloat();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,9 +2,11 @@ package com.almostreliable.unified.utils;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
public class JsonUtils {
|
public class JsonUtils {
|
||||||
public static JsonArray arrayOrSelf(@Nullable JsonElement element) {
|
public static JsonArray arrayOrSelf(@Nullable JsonElement element) {
|
||||||
|
@ -28,4 +30,46 @@ public class JsonUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loops through the array and applies the given callback to each element.
|
||||||
|
* If the callback returns non-null, the element is replaced with the returned value.
|
||||||
|
*
|
||||||
|
* @param jsonArray The array to loop through.
|
||||||
|
* @param callback The callback to apply to each element.
|
||||||
|
* @return true if any elements were replaced, false otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean replaceOn(JsonArray jsonArray, UnaryOperator<JsonElement> callback) {
|
||||||
|
boolean changed = false;
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
JsonElement result = callback.apply(jsonArray.get(i));
|
||||||
|
if (result != null) {
|
||||||
|
jsonArray.set(i, result);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the element for the key through given callback.
|
||||||
|
* If the callback returns non-null, the element is replaced with the returned value.
|
||||||
|
*
|
||||||
|
* @param jsonObject The object to loop through.
|
||||||
|
* @param callback The callback to apply to each element.
|
||||||
|
* @return true if the element was replaced, false otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean replaceOn(JsonObject jsonObject, String key, UnaryOperator<JsonElement> callback) {
|
||||||
|
JsonElement element = jsonObject.get(key);
|
||||||
|
if (element == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonElement result = callback.apply(element);
|
||||||
|
if (result != null) {
|
||||||
|
jsonObject.add(key, result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.almostreliable.unified.utils;
|
package com.almostreliable.unified.utils;
|
||||||
|
|
||||||
|
import com.almostreliable.unified.AlmostUnified;
|
||||||
import com.almostreliable.unified.api.recipe.ReplacementFallbackStrategy;
|
import com.almostreliable.unified.api.recipe.ReplacementFallbackStrategy;
|
||||||
import com.almostreliable.unified.recipe.fallbacks.StoneStrataFallbackStrategy;
|
import com.almostreliable.unified.recipe.fallbacks.StoneStrataFallbackStrategy;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
@ -8,6 +9,7 @@ import net.minecraft.world.item.Item;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -15,24 +17,43 @@ public class ReplacementMap {
|
||||||
|
|
||||||
private final Collection<String> modPriorities;
|
private final Collection<String> modPriorities;
|
||||||
private final TagMap tagMap;
|
private final TagMap tagMap;
|
||||||
private final Map<ResourceLocation, TagKey<Item>> itemToTagMapping;
|
private final Map<ResourceLocation, UnifyTag<Item>> itemToTagMapping;
|
||||||
// TODO - In the future this may be a list of multiple fallbacks.
|
// TODO - In the future this may be a list of multiple fallbacks.
|
||||||
private final ReplacementFallbackStrategy fallbackStrategy = new StoneStrataFallbackStrategy();
|
private final ReplacementFallbackStrategy fallbackStrategy = new StoneStrataFallbackStrategy();
|
||||||
|
|
||||||
public ReplacementMap(TagMap tagMap, Map<ResourceLocation, TagKey<Item>> itemToTagMapping, List<String> modPriorities) {
|
public ReplacementMap(TagMap tagMap, List<UnifyTag<Item>> allowedTags, List<String> modPriorities) {
|
||||||
this.tagMap = tagMap;
|
this.tagMap = tagMap;
|
||||||
this.itemToTagMapping = itemToTagMapping;
|
|
||||||
this.modPriorities = modPriorities;
|
this.modPriorities = modPriorities;
|
||||||
|
this.itemToTagMapping = createItemMapping(allowedTags);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<ResourceLocation, UnifyTag<Item>> createItemMapping(List<UnifyTag<Item>> allowedTags) {
|
||||||
|
Map<ResourceLocation, UnifyTag<Item>> itemToTagMapping = new HashMap<>(allowedTags.size());
|
||||||
|
for (UnifyTag<Item> tag : allowedTags) {
|
||||||
|
Collection<ResourceLocation> items = tagMap.getItems(tag);
|
||||||
|
for (ResourceLocation item : items) {
|
||||||
|
if (itemToTagMapping.containsKey(item)) {
|
||||||
|
AlmostUnified.LOG.warn("Item '{}' already has a tag '{}' for recipe replacement. Skipping this tag",
|
||||||
|
item,
|
||||||
|
tag);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemToTagMapping.put(item, tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemToTagMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public TagKey<Item> getPreferredTag(ResourceLocation item) {
|
public UnifyTag<Item> getPreferredTag(ResourceLocation item) {
|
||||||
return itemToTagMapping.get(item);
|
return itemToTagMapping.get(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ResourceLocation getReplacementForItem(ResourceLocation item) {
|
public ResourceLocation getReplacementForItem(ResourceLocation item) {
|
||||||
TagKey<Item> tag = getPreferredTag(item);
|
UnifyTag<Item> tag = getPreferredTag(item);
|
||||||
if (tag == null) {
|
if (tag == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -46,13 +67,17 @@ public class ReplacementMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ResourceLocation getPreferredItemByTag(TagKey<Item> tag) {
|
public ResourceLocation getPreferredItemByTag(UnifyTag<Item> tag) {
|
||||||
return getPreferredItemByTag(tag, null);
|
return getPreferredItemByTag(tag, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ResourceLocation getPreferredItemByTag(TagKey<Item> tag, @Nullable String ignoredNamespace) {
|
public ResourceLocation getPreferredItemByTag(UnifyTag<Item> tag, @Nullable String ignoredNamespace) {
|
||||||
for (String mod : modPriorities) {
|
for (String mod : modPriorities) {
|
||||||
|
if(mod.equals(ignoredNamespace)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
List<ResourceLocation> sameModItems = tagMap
|
List<ResourceLocation> sameModItems = tagMap
|
||||||
.getItems(tag)
|
.getItems(tag)
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -62,7 +87,7 @@ public class ReplacementMap {
|
||||||
return sameModItems.get(0);
|
return sameModItems.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sameModItems.size() > 1 && !mod.equals(ignoredNamespace)) {
|
if (sameModItems.size() > 1) {
|
||||||
ResourceLocation fallback = fallbackStrategy.getFallback(tag, sameModItems, tagMap);
|
ResourceLocation fallback = fallbackStrategy.getFallback(tag, sameModItems, tagMap);
|
||||||
if (fallback != null) {
|
if (fallback != null) {
|
||||||
return fallback;
|
return fallback;
|
||||||
|
|
|
@ -12,8 +12,8 @@ import net.minecraft.world.item.Item;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class TagMap {
|
public class TagMap {
|
||||||
private final Map<TagKey<Item>, Set<ResourceLocation>> tagsToItems = new HashMap<>();
|
private final Map<UnifyTag<Item>, Set<ResourceLocation>> tagsToItems = new HashMap<>();
|
||||||
private final Map<ResourceLocation, Set<TagKey<Item>>> itemsToTags = new HashMap<>();
|
private final Map<ResourceLocation, Set<UnifyTag<Item>>> itemsToTags = new HashMap<>();
|
||||||
|
|
||||||
protected TagMap() {}
|
protected TagMap() {}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ public class TagMap {
|
||||||
TagMap tagMap = new TagMap();
|
TagMap tagMap = new TagMap();
|
||||||
|
|
||||||
for (var entry : tags.entrySet()) {
|
for (var entry : tags.entrySet()) {
|
||||||
TagKey<Item> tag = TagKey.create(Registry.ITEM_REGISTRY, entry.getKey());
|
UnifyTag<Item> tag = UnifyTag.item(entry.getKey());
|
||||||
Tag<? extends Holder<?>> holderTag = entry.getValue();
|
Tag<? extends Holder<?>> holderTag = entry.getValue();
|
||||||
|
|
||||||
for (Holder<?> holder : holderTag.getValues()) {
|
for (Holder<?> holder : holderTag.getValues()) {
|
||||||
|
@ -46,16 +46,24 @@ public class TagMap {
|
||||||
return tagMap;
|
return tagMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void put(TagKey<Item> tag, ResourceLocation item) {
|
protected void put(UnifyTag<Item> tag, ResourceLocation item) {
|
||||||
tagsToItems.computeIfAbsent(tag, k -> new HashSet<>()).add(item);
|
tagsToItems.computeIfAbsent(tag, k -> new HashSet<>()).add(item);
|
||||||
itemsToTags.computeIfAbsent(item, k -> new HashSet<>()).add(tag);
|
itemsToTags.computeIfAbsent(item, k -> new HashSet<>()).add(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<ResourceLocation> getItems(TagKey<Item> tag) {
|
public Collection<ResourceLocation> getItems(UnifyTag<Item> tag) {
|
||||||
return Collections.unmodifiableSet(tagsToItems.getOrDefault(tag, Collections.emptySet()));
|
return Collections.unmodifiableSet(tagsToItems.getOrDefault(tag, Collections.emptySet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<TagKey<Item>> getTags(ResourceLocation items) {
|
public Collection<UnifyTag<Item>> getTags(ResourceLocation items) {
|
||||||
return Collections.unmodifiableSet(itemsToTags.getOrDefault(items, Collections.emptySet()));
|
return Collections.unmodifiableSet(itemsToTags.getOrDefault(items, Collections.emptySet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int tagSize() {
|
||||||
|
return tagsToItems.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int itemSize() {
|
||||||
|
return itemsToTags.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.almostreliable.unified.utils;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
|
||||||
|
public record UnifyTag<T>(Class<T> boundType, ResourceLocation location) {
|
||||||
|
public static UnifyTag<Item> item(ResourceLocation location) {
|
||||||
|
return new UnifyTag<>(Item.class, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "UnifyTag[" + boundType.getSimpleName().toLowerCase() + " / " + location + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,9 +10,9 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
public static final ResourceLocation UNUSED_ID = new ResourceLocation(BuildConfig.MOD_ID, "unused_id");
|
public static final ResourceLocation UNUSED_ID = new ResourceLocation(BuildConfig.MOD_ID, "unused_id");
|
||||||
public static final TagKey<Item> UNUSED_TAG = TagKey.create(Registry.ITEM_REGISTRY, UNUSED_ID);
|
public static final UnifyTag<Item> UNUSED_TAG = UnifyTag.item(UNUSED_ID);
|
||||||
|
|
||||||
public static TagKey<Item> toItemTag(@Nullable String tag) {
|
public static UnifyTag<Item> toItemTag(@Nullable String tag) {
|
||||||
if (tag == null) {
|
if (tag == null) {
|
||||||
return UNUSED_TAG;
|
return UNUSED_TAG;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,6 @@ public class Utils {
|
||||||
return UNUSED_TAG;
|
return UNUSED_TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TagKey.create(Registry.ITEM_REGISTRY, rl);
|
return UnifyTag.item(rl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.almostreliable.unified;
|
||||||
|
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
public class FakeResourceKeyRegistry {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> ResourceKey<Registry<T>> create(String name) {
|
||||||
|
try {
|
||||||
|
Constructor<?> c = ResourceKey.class.getDeclaredConstructor(ResourceLocation.class, ResourceLocation.class);
|
||||||
|
c.setAccessible(true);
|
||||||
|
return (ResourceKey<Registry<T>>) c.newInstance(new ResourceLocation("test_registry"),
|
||||||
|
new ResourceLocation(name));
|
||||||
|
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.almostreliable.unified;
|
||||||
|
|
||||||
|
import com.almostreliable.unified.recipe.RecipeTransformer;
|
||||||
|
import com.almostreliable.unified.recipe.handler.RecipeHandlerFactory;
|
||||||
|
import com.almostreliable.unified.utils.ReplacementMap;
|
||||||
|
import com.almostreliable.unified.utils.TagMapTests;
|
||||||
|
import com.almostreliable.unified.utils.UnifyTag;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class TestUtils {
|
||||||
|
public static final String TEST_MOD_1 = "test_mod_1";
|
||||||
|
public static final String TEST_MOD_2 = "test_mod_2";
|
||||||
|
public static final String TEST_MOD_3 = "test_mod_3";
|
||||||
|
public static final String TEST_MOD_4 = "test_mod_4";
|
||||||
|
public static final String TEST_MOD_5 = "test_mod_5";
|
||||||
|
public static final List<String> TEST_MOD_PRIORITIES = List.of(TEST_MOD_1,
|
||||||
|
TEST_MOD_2,
|
||||||
|
TEST_MOD_3,
|
||||||
|
TEST_MOD_4,
|
||||||
|
TEST_MOD_5);
|
||||||
|
public static final ResourceKey<Registry<Item>> FAKE_ITEM_REGISTRY = FakeResourceKeyRegistry.create("item");
|
||||||
|
public static final UnifyTag<Item> BRONZE_ORES_TAG = tag("forge:ores/bronze");
|
||||||
|
public static final UnifyTag<Item> INVAR_ORES_TAG = tag("forge:ores/invar");
|
||||||
|
public static final UnifyTag<Item> TIN_ORES_TAG = tag("forge:ores/tin");
|
||||||
|
public static final UnifyTag<Item> SILVER_ORES_TAG = tag("forge:ores/silver");
|
||||||
|
public static final List<UnifyTag<Item>> TEST_ALLOWED_TAGS = List.of(BRONZE_ORES_TAG,
|
||||||
|
INVAR_ORES_TAG,
|
||||||
|
TIN_ORES_TAG,
|
||||||
|
SILVER_ORES_TAG);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ResourceKey is null because otherwise tests can't run because Minecraft is not bootstrapped ...
|
||||||
|
*
|
||||||
|
* @param name the name of the tag
|
||||||
|
* @return a TagKey for the given name
|
||||||
|
*/
|
||||||
|
public static UnifyTag<Item> tag(String name) {
|
||||||
|
return UnifyTag.item(new ResourceLocation(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourceLocation mod1RL(String name) {
|
||||||
|
return new ResourceLocation(TEST_MOD_1, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourceLocation mod2RL(String name) {
|
||||||
|
return new ResourceLocation(TEST_MOD_2, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourceLocation mod3RL(String name) {
|
||||||
|
return new ResourceLocation(TEST_MOD_3, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourceLocation mod4RL(String name) {
|
||||||
|
return new ResourceLocation(TEST_MOD_4, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourceLocation mod5RL(String name) {
|
||||||
|
return new ResourceLocation(TEST_MOD_5, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RecipeTransformer basicTransformer(Consumer<RecipeHandlerFactory> consumer) {
|
||||||
|
ReplacementMap map = new ReplacementMap(TagMapTests.testTagMap(),
|
||||||
|
TestUtils.TEST_ALLOWED_TAGS,
|
||||||
|
TestUtils.TEST_MOD_PRIORITIES);
|
||||||
|
RecipeHandlerFactory factory = new RecipeHandlerFactory();
|
||||||
|
consumer.accept(factory);
|
||||||
|
return new RecipeTransformer(factory, map);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.almostreliable.unified.recipe;
|
||||||
|
|
||||||
|
import com.almostreliable.unified.TestUtils;
|
||||||
|
import com.almostreliable.unified.utils.JsonQuery;
|
||||||
|
import com.almostreliable.unified.utils.ReplacementMap;
|
||||||
|
import com.almostreliable.unified.utils.TagMapTests;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
|
|
||||||
|
public class RecipeContextImplTest {
|
||||||
|
private static String testJson = """
|
||||||
|
{
|
||||||
|
"input": [
|
||||||
|
{
|
||||||
|
"tag": "tag_replace_me"
|
||||||
|
},
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"item": "item_replace_me"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"item": "item_replace_me"
|
||||||
|
},
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"item": "item_replace_me"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "tag_replace_me"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"results": {
|
||||||
|
"item": "item_replace_me"
|
||||||
|
}
|
||||||
|
}""";
|
||||||
|
|
||||||
|
public static String mekaTest = """
|
||||||
|
{
|
||||||
|
"type": "mekanism:combining",
|
||||||
|
"mainInput": { "amount": 8, "ingredient": { "tag": "forge:raw_materials/tin" } },
|
||||||
|
"extraInput": { "ingredient": { "tag": "forge:cobblestone/normal" } },
|
||||||
|
"output": { "item": "mekanism:tin_ore" }
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void depthReplace_MekaTest() {
|
||||||
|
JsonObject json = new Gson().fromJson(mekaTest, JsonObject.class);
|
||||||
|
ReplacementMap map = new ReplacementMap(TagMapTests.testTagMap(),
|
||||||
|
TestUtils.TEST_ALLOWED_TAGS,
|
||||||
|
TestUtils.TEST_MOD_PRIORITIES);
|
||||||
|
RecipeContextImpl context = new RecipeContextImpl(new ResourceLocation("test"), json, map);
|
||||||
|
JsonElement result = context.replaceResultOld(json.getAsJsonObject("output"));
|
||||||
|
assertNull(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void depthReplace_NothingReplaced() {
|
||||||
|
JsonObject json = new Gson().fromJson(testJson, JsonObject.class);
|
||||||
|
ReplacementMap map = new ReplacementMap(TagMapTests.testTagMap(),
|
||||||
|
TestUtils.TEST_ALLOWED_TAGS,
|
||||||
|
TestUtils.TEST_MOD_PRIORITIES);
|
||||||
|
RecipeContextImpl context = new RecipeContextImpl(new ResourceLocation("test"), json, map);
|
||||||
|
JsonElement result = context.depthReplace(json,
|
||||||
|
"not_existing",
|
||||||
|
"item",
|
||||||
|
primitive -> new JsonPrimitive("dont_find_this"));
|
||||||
|
assertNull(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void depthReplace_Items() {
|
||||||
|
JsonObject json = new Gson().fromJson(testJson, JsonObject.class);
|
||||||
|
ReplacementMap map = new ReplacementMap(TagMapTests.testTagMap(),
|
||||||
|
TestUtils.TEST_ALLOWED_TAGS,
|
||||||
|
TestUtils.TEST_MOD_PRIORITIES);
|
||||||
|
RecipeContextImpl context = new RecipeContextImpl(new ResourceLocation("test"), json, map);
|
||||||
|
JsonElement result = context.depthReplace(json,
|
||||||
|
"item",
|
||||||
|
"item",
|
||||||
|
primitive -> new JsonPrimitive("item_was_replaced"));
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(JsonQuery.of(result, "input/0/item").asString(), "item_was_replaced");
|
||||||
|
assertEquals(JsonQuery.of(result, "input/1/1/item").asString(), "item_was_replaced");
|
||||||
|
assertEquals(JsonQuery.of(result, "input/1/2/0/item").asString(), "item_was_replaced");
|
||||||
|
assertEquals(JsonQuery.of(result, "result/item").asString(), "item_was_replaced");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.almostreliable.unified.utils;
|
||||||
|
|
||||||
|
import com.almostreliable.unified.TestUtils;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class ReplacementMapTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getPreferredItemByTag() {
|
||||||
|
ReplacementMap map = new ReplacementMap(TagMapTests.testTagMap(),
|
||||||
|
TestUtils.TEST_ALLOWED_TAGS,
|
||||||
|
TestUtils.TEST_MOD_PRIORITIES);
|
||||||
|
assertEquals(map.getPreferredItemByTag(TestUtils.BRONZE_ORES_TAG), TestUtils.mod1RL("bronze_ore"));
|
||||||
|
assertNotEquals(map.getPreferredItemByTag(TestUtils.BRONZE_ORES_TAG), TestUtils.mod2RL("bronze_ore"));
|
||||||
|
assertEquals(map.getPreferredItemByTag(TestUtils.INVAR_ORES_TAG), TestUtils.mod1RL("invar_ore"));
|
||||||
|
assertNotEquals(map.getPreferredItemByTag(TestUtils.INVAR_ORES_TAG), TestUtils.mod2RL("invar_ore"));
|
||||||
|
assertEquals(map.getPreferredItemByTag(TestUtils.TIN_ORES_TAG), TestUtils.mod3RL("tin_ore"));
|
||||||
|
assertNotEquals(map.getPreferredItemByTag(TestUtils.TIN_ORES_TAG), TestUtils.mod4RL("tin_ore"));
|
||||||
|
assertEquals(map.getPreferredItemByTag(TestUtils.SILVER_ORES_TAG), TestUtils.mod3RL("silver_ore"));
|
||||||
|
assertNotEquals(map.getPreferredItemByTag(TestUtils.SILVER_ORES_TAG), TestUtils.mod4RL("silver_ore"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getPreferredItemByTag_ReversePriority() {
|
||||||
|
// We reverse the order. See `testTagMap` for the mapping.
|
||||||
|
List<String> reverse = Lists.reverse(TestUtils.TEST_MOD_PRIORITIES);
|
||||||
|
ReplacementMap reverseMap = new ReplacementMap(TagMapTests.testTagMap(), TestUtils.TEST_ALLOWED_TAGS, reverse);
|
||||||
|
assertEquals(reverseMap.getPreferredItemByTag(TestUtils.BRONZE_ORES_TAG), TestUtils.mod3RL("bronze_ore"));
|
||||||
|
assertEquals(reverseMap.getPreferredItemByTag(TestUtils.INVAR_ORES_TAG), TestUtils.mod4RL("invar_ore"));
|
||||||
|
assertEquals(reverseMap.getPreferredItemByTag(TestUtils.TIN_ORES_TAG), TestUtils.mod4RL("tin_ore"));
|
||||||
|
assertEquals(reverseMap.getPreferredItemByTag(TestUtils.SILVER_ORES_TAG), TestUtils.mod5RL("silver_ore"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getPreferredTag() {
|
||||||
|
ReplacementMap map = new ReplacementMap(TagMapTests.testTagMap(),
|
||||||
|
TestUtils.TEST_ALLOWED_TAGS,
|
||||||
|
TestUtils.TEST_MOD_PRIORITIES);
|
||||||
|
|
||||||
|
assertEquals(map.getPreferredTag(TestUtils.mod1RL("bronze_ore")), TestUtils.BRONZE_ORES_TAG);
|
||||||
|
assertNull(map.getPreferredTag(new ResourceLocation("minecraft:diamond")), "We don't have a tag for diamond");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.almostreliable.unified.utils;
|
||||||
|
|
||||||
|
import com.almostreliable.unified.TestUtils;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class TagMapTests {
|
||||||
|
|
||||||
|
public static TagMap testTagMap() {
|
||||||
|
TagMap tagMap = new TagMap();
|
||||||
|
UnifyTag<Item> bronzeOreTag = UnifyTag.item(new ResourceLocation("forge:ores/bronze"));
|
||||||
|
UnifyTag<Item> invarOreTag = UnifyTag.item(new ResourceLocation("forge:ores/invar"));
|
||||||
|
UnifyTag<Item> tinOreTag = UnifyTag.item(new ResourceLocation("forge:ores/tin"));
|
||||||
|
UnifyTag<Item> silverOreTag = UnifyTag.item(new ResourceLocation("forge:ores/silver"));
|
||||||
|
|
||||||
|
tagMap.put(bronzeOreTag, TestUtils.mod1RL("bronze_ore"));
|
||||||
|
tagMap.put(bronzeOreTag, TestUtils.mod2RL("bronze_ore"));
|
||||||
|
tagMap.put(bronzeOreTag, TestUtils.mod3RL("bronze_ore"));
|
||||||
|
|
||||||
|
tagMap.put(invarOreTag, TestUtils.mod1RL("invar_ore"));
|
||||||
|
tagMap.put(invarOreTag, TestUtils.mod2RL("invar_ore"));
|
||||||
|
tagMap.put(invarOreTag, TestUtils.mod3RL("invar_ore"));
|
||||||
|
tagMap.put(invarOreTag, TestUtils.mod4RL("invar_ore"));
|
||||||
|
|
||||||
|
tagMap.put(tinOreTag, TestUtils.mod3RL("tin_ore"));
|
||||||
|
tagMap.put(tinOreTag, TestUtils.mod4RL("tin_ore"));
|
||||||
|
|
||||||
|
tagMap.put(silverOreTag, TestUtils.mod3RL("silver_ore"));
|
||||||
|
tagMap.put(silverOreTag, TestUtils.mod4RL("silver_ore"));
|
||||||
|
tagMap.put(silverOreTag, TestUtils.mod5RL("silver_ore"));
|
||||||
|
return tagMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleCheck() {
|
||||||
|
TagMap tagMap = new TagMap();
|
||||||
|
UnifyTag<Item> bronzeOreTag = UnifyTag.item(new ResourceLocation("forge:ores/bronze"));
|
||||||
|
tagMap.put(bronzeOreTag, TestUtils.mod1RL("bronze_ore"));
|
||||||
|
tagMap.put(bronzeOreTag, TestUtils.mod2RL("bronze_ore"));
|
||||||
|
tagMap.put(bronzeOreTag, TestUtils.mod3RL("bronze_ore"));
|
||||||
|
tagMap.put(bronzeOreTag, TestUtils.mod4RL("bronze_ore"));
|
||||||
|
tagMap.put(bronzeOreTag, TestUtils.mod5RL("bronze_ore"));
|
||||||
|
|
||||||
|
assertEquals(tagMap.getItems(bronzeOreTag).size(), 5);
|
||||||
|
assertEquals(tagMap.getTags(TestUtils.mod1RL("bronze_ore")).size(), 1);
|
||||||
|
assertEquals(tagMap.getTags(TestUtils.mod2RL("bronze_ore")).size(), 1);
|
||||||
|
assertEquals(tagMap.getTags(TestUtils.mod3RL("bronze_ore")).size(), 1);
|
||||||
|
assertEquals(tagMap.getTags(TestUtils.mod4RL("bronze_ore")).size(), 1);
|
||||||
|
assertEquals(tagMap.getTags(TestUtils.mod5RL("bronze_ore")).size(), 1);
|
||||||
|
|
||||||
|
tagMap.put(UnifyTag.item(new ResourceLocation("forge:ores/invar")), TestUtils.mod1RL("invar_ore"));
|
||||||
|
|
||||||
|
assertEquals(tagMap.tagSize(), 2);
|
||||||
|
assertEquals(tagMap.itemSize(), 6);
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,6 +61,9 @@ minecraft {
|
||||||
|
|
||||||
sourceSets.main.get().resources.srcDir("src/generated/resources")
|
sourceSets.main.get().resources.srcDir("src/generated/resources")
|
||||||
|
|
||||||
|
// from millions of solutions, this is the only one which works... :-)
|
||||||
|
val commonTests: SourceSetOutput = project(":Common").sourceSets["test"].output
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
minecraft("net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}")
|
minecraft("net.minecraftforge:forge:${minecraftVersion}-${forgeVersion}")
|
||||||
compileOnly(project(":Common"))
|
compileOnly(project(":Common"))
|
||||||
|
@ -80,6 +83,14 @@ dependencies {
|
||||||
runtimeOnly(fg.deobf("curse.maven:nihilo-400012:3810814"))
|
runtimeOnly(fg.deobf("curse.maven:nihilo-400012:3810814"))
|
||||||
|
|
||||||
annotationProcessor("org.spongepowered:mixin:${mixinVersion}:processor")
|
annotationProcessor("org.spongepowered:mixin:${mixinVersion}:processor")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test dependencies
|
||||||
|
*/
|
||||||
|
testImplementation(project(":Common"))
|
||||||
|
testImplementation(commonTests)
|
||||||
|
testImplementation ("org.junit.jupiter:junit-jupiter-api:5.8.1")
|
||||||
|
testRuntimeOnly ("org.junit.jupiter:junit-jupiter-engine:5.8.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin {
|
mixin {
|
||||||
|
@ -101,6 +112,10 @@ tasks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType<Test> {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
register("mavenJava", MavenPublication::class) {
|
register("mavenJava", MavenPublication::class) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import com.almostreliable.unified.api.recipe.RecipeHandler;
|
||||||
import com.almostreliable.unified.api.recipe.RecipeTransformations;
|
import com.almostreliable.unified.api.recipe.RecipeTransformations;
|
||||||
import com.almostreliable.unified.utils.JsonUtils;
|
import com.almostreliable.unified.utils.JsonUtils;
|
||||||
import com.almostreliable.unified.utils.Utils;
|
import com.almostreliable.unified.utils.Utils;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
@ -20,79 +21,65 @@ public class IERecipeHandler implements RecipeHandler {
|
||||||
// TODO make it cleaner
|
// TODO make it cleaner
|
||||||
@Override
|
@Override
|
||||||
public void collectTransformations(RecipeTransformations builder) {
|
public void collectTransformations(RecipeTransformations builder) {
|
||||||
builder.put("input0", (json, context) -> {
|
builder.put("input0", this::replaceIEIngredient); // alloy recipes, refinery
|
||||||
replaceIEIngredient(json, context);
|
builder.put("input1", this::replaceIEIngredient); // alloy recipes, refinery
|
||||||
return json;
|
builder.put(RecipeConstants.INPUT,
|
||||||
}); // alloy recipes, refinery
|
this::replaceIEIngredient); // arc furnace, squeezer, cloche, coke oven, fermenter, fertilizer, metal_press
|
||||||
builder.put("input1", (json, context) -> {
|
builder.put("additives", this::replaceIEIngredient); // arc furnace
|
||||||
replaceIEIngredient(json, context);
|
builder.put(RecipeConstants.INPUTS, this::replaceIEIngredient); // blueprint, mixer
|
||||||
return json;
|
|
||||||
}); // alloy recipes, refinery
|
|
||||||
builder.put(RecipeConstants.INPUT, (json, context) -> {
|
|
||||||
replaceIEIngredient(json, context);
|
|
||||||
return json;
|
|
||||||
}); // arc furnace, squeezer, cloche, coke oven, fermenter, fertilizer, metal_press
|
|
||||||
builder.put("additives", (json, context) -> {
|
|
||||||
replaceIEIngredient(json, context);
|
|
||||||
return json;
|
|
||||||
}); // arc furnace
|
|
||||||
builder.put(RecipeConstants.INPUTS, (json, context) -> {
|
|
||||||
replaceIEIngredient(json, context);
|
|
||||||
return json;
|
|
||||||
}); // blueprint, mixer
|
|
||||||
|
|
||||||
// alloy recipes, crusher
|
// alloy recipes, crusher
|
||||||
builder.forEachObject("secondaries", (jsonObject, context) -> {
|
builder.forEachObject("secondaries",
|
||||||
replaceIEResult(jsonObject.get(RecipeConstants.OUTPUT), context);
|
(jsonObject, context) ->
|
||||||
return jsonObject;
|
replaceIEResult(jsonObject.get(RecipeConstants.OUTPUT), context) instanceof JsonObject
|
||||||
});
|
? jsonObject : null);
|
||||||
|
builder.put(RecipeConstants.RESULT, this::replaceIEResult);
|
||||||
builder.put(RecipeConstants.RESULT, (json, context) -> {
|
builder.put(RecipeConstants.RESULTS, this::replaceIEResult);
|
||||||
replaceIEResult(json, context);
|
|
||||||
return json;
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.put(RecipeConstants.RESULTS, (json, context) -> {
|
|
||||||
replaceIEResult(json, context);
|
|
||||||
return json;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void replaceIEResult(@Nullable JsonElement element, RecipeContext context) {
|
@Nullable
|
||||||
if (element == null) {
|
protected JsonElement replaceIEResult(@Nullable JsonElement element, RecipeContext context) {
|
||||||
return;
|
if (element instanceof JsonArray array) {
|
||||||
|
if (JsonUtils.replaceOn(array, e -> this.replaceIEResult(e, context))) {
|
||||||
|
return array;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonUtils.arrayForEach(element, JsonObject.class, json -> {
|
if (element instanceof JsonObject object) {
|
||||||
if (json.has(RecipeConstants.ITEM)) {
|
JsonElement tag = object.get(RecipeConstants.TAG);
|
||||||
context.replaceResult(json);
|
if (tag != null) {
|
||||||
} else if (json.has(RecipeConstants.TAG)) {
|
|
||||||
/*
|
/*
|
||||||
* Immersive Engineering allows tags in result and filters them. So we replace the tags with
|
* Immersive Engineering allows tags in result and filters them. So we replace the tags with
|
||||||
* the preferred item from our config.
|
* the preferred item from our config.
|
||||||
*/
|
*/
|
||||||
ResourceLocation item = context.getPreferredItemByTag(Utils.toItemTag(json
|
ResourceLocation item = context.getPreferredItemByTag(Utils.toItemTag(object
|
||||||
.get(RecipeConstants.TAG)
|
.get(RecipeConstants.TAG)
|
||||||
.getAsString()));
|
.getAsString()));
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
json.remove(RecipeConstants.TAG);
|
object.remove(RecipeConstants.TAG);
|
||||||
json.addProperty(RecipeConstants.ITEM, item.toString());
|
object.addProperty(RecipeConstants.ITEM, item.toString());
|
||||||
|
return object;
|
||||||
}
|
}
|
||||||
} else if (json.has(BASE_KEY)) {
|
|
||||||
replaceIEResult(json.get(BASE_KEY), context);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
JsonElement base = object.get(BASE_KEY);
|
||||||
|
if (base != null) {
|
||||||
|
JsonElement baseResult = replaceIEResult(base, context);
|
||||||
|
if (baseResult != null) {
|
||||||
|
object.add(BASE_KEY, baseResult);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.createResultReplacement(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void replaceIEIngredient(@Nullable JsonElement element, RecipeContext context) {
|
@Nullable
|
||||||
if (element == null) {
|
public JsonElement replaceIEIngredient(@Nullable JsonElement element, RecipeContext context) {
|
||||||
return;
|
if (element instanceof JsonObject json && json.has(BASE_KEY)) {
|
||||||
|
return context.createIngredientReplacement(json.get(BASE_KEY));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element instanceof JsonObject json && json.has(BASE_KEY)) {
|
return context.createIngredientReplacement(element);
|
||||||
context.replaceIngredient(json.get(BASE_KEY));
|
|
||||||
} else {
|
|
||||||
context.replaceIngredient(element);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
package com.almostreliable.unified.compat.ie;
|
||||||
|
|
||||||
|
import com.almostreliable.unified.TestUtils;
|
||||||
|
import com.almostreliable.unified.api.ModConstants;
|
||||||
|
import com.almostreliable.unified.recipe.RecipeTransformer;
|
||||||
|
import com.almostreliable.unified.utils.JsonQuery;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class IERecipeHandlerTest {
|
||||||
|
public final Gson gson = new Gson();
|
||||||
|
|
||||||
|
private final String simpleAlloyRecipe = """
|
||||||
|
{
|
||||||
|
"type": "immersiveengineering:alloy",
|
||||||
|
"time": 200,
|
||||||
|
"result": { "count": 2, "base_ingredient": { "tag": "forge:ingots/electrum" } },
|
||||||
|
"input0": { "tag": "forge:ingots/gold" },
|
||||||
|
"input1": { "tag": "forge:ingots/silver" }
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void notMatching() {
|
||||||
|
RecipeTransformer transformer = TestUtils.basicTransformer(f -> f.registerForMod(ModConstants.IE,
|
||||||
|
new IERecipeHandler()));
|
||||||
|
JsonObject alloy = gson.fromJson(simpleAlloyRecipe, JsonObject.class);
|
||||||
|
JsonObject result = transformer.transformRecipe(alloy);
|
||||||
|
assertNull(result, "Nothing to transform, so it should be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void resultTagMatches() {
|
||||||
|
RecipeTransformer transformer = TestUtils.basicTransformer(f -> f.registerForMod(ModConstants.IE,
|
||||||
|
new IERecipeHandler()));
|
||||||
|
JsonObject alloy = gson.fromJson(simpleAlloyRecipe, JsonObject.class);
|
||||||
|
alloy
|
||||||
|
.getAsJsonObject("result")
|
||||||
|
.getAsJsonObject("base_ingredient")
|
||||||
|
.addProperty("tag", TestUtils.BRONZE_ORES_TAG.location().toString());
|
||||||
|
JsonObject result = transformer.transformRecipe(alloy);
|
||||||
|
assertNotEquals(result, alloy, "Result should be different");
|
||||||
|
assertNotNull(result, "Result should not be null");
|
||||||
|
assertNull(JsonQuery.of(result, "result/base_ingredient/tag"), "Tag key should be removed");
|
||||||
|
assertEquals(JsonQuery.of(result, "result/base_ingredient/item").asString(),
|
||||||
|
TestUtils.mod1RL("bronze_ore").toString(),
|
||||||
|
"Result should be bronze_ore");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void resultItemMatches() {
|
||||||
|
RecipeTransformer transformer = TestUtils.basicTransformer(f -> f.registerForMod(ModConstants.IE,
|
||||||
|
new IERecipeHandler()));
|
||||||
|
JsonObject alloy = gson.fromJson(simpleAlloyRecipe, JsonObject.class);
|
||||||
|
alloy.getAsJsonObject("result").getAsJsonObject("base_ingredient").remove("tag");
|
||||||
|
alloy
|
||||||
|
.getAsJsonObject("result")
|
||||||
|
.getAsJsonObject("base_ingredient")
|
||||||
|
.addProperty("item", TestUtils.mod3RL("bronze_ore").toString());
|
||||||
|
JsonObject result = transformer.transformRecipe(alloy);
|
||||||
|
assertNotEquals(result, alloy, "Result should be different");
|
||||||
|
assertNotNull(result, "Result should not be null");
|
||||||
|
assertEquals(JsonQuery.of(result, ("result/base_ingredient/item")).asString(),
|
||||||
|
TestUtils.mod1RL("bronze_ore").toString(),
|
||||||
|
"Transformer should replace bronze_ore from mod3 with bronze_ore from mod1");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void inputAlloyItemMatches() {
|
||||||
|
RecipeTransformer transformer = TestUtils.basicTransformer(f -> f.registerForMod(ModConstants.IE,
|
||||||
|
new IERecipeHandler()));
|
||||||
|
JsonObject alloy = gson.fromJson(simpleAlloyRecipe, JsonObject.class);
|
||||||
|
alloy.getAsJsonObject("result").getAsJsonObject("base_ingredient").remove("tag");
|
||||||
|
alloy
|
||||||
|
.getAsJsonObject("result")
|
||||||
|
.getAsJsonObject("base_ingredient")
|
||||||
|
.addProperty("item", TestUtils.mod3RL("bronze_ore").toString());
|
||||||
|
JsonObject result = transformer.transformRecipe(alloy);
|
||||||
|
assertNotEquals(result, alloy, "Result should be different");
|
||||||
|
assertNotNull(result, "Result should not be null");
|
||||||
|
assertEquals(JsonQuery.of(result, ("result/base_ingredient/item")).asString(),
|
||||||
|
TestUtils.mod1RL("bronze_ore").toString(),
|
||||||
|
"Transformer should replace bronze_ore from mod3 with bronze_ore from mod1");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue