shaped crafting pattern matching (#2)

This commit is contained in:
Relentless 2022-08-25 18:10:32 +02:00
parent b406724fd8
commit 1b8c5dc7eb
No known key found for this signature in database
GPG key ID: 759D97B8C6F25265
5 changed files with 175 additions and 16 deletions

View file

@ -52,7 +52,7 @@ public class DuplicationConfig extends Config {
JsonCompare.CompareSettings defaultRules = safeGet(() -> createCompareSet(json.getAsJsonObject(
DEFAULT_DUPLICATE_RULES)),
defaultSet());
defaultSettings());
LinkedHashMap<ResourceLocation, JsonCompare.CompareSettings> overrideRules = safeGet(() -> json
.getAsJsonObject(OVERRIDE_DUPLICATE_RULES)
.entrySet()
@ -60,13 +60,13 @@ public class DuplicationConfig extends Config {
.collect(Collectors.toMap(entry -> new ResourceLocation(entry.getKey()),
entry -> createCompareSet(entry.getValue().getAsJsonObject()),
(a, b) -> b,
LinkedHashMap::new)), new LinkedHashMap<>());
LinkedHashMap::new)), defaultOverrides());
boolean strictMode = safeGet(() -> json.get(STRICT_MODE).getAsBoolean(), false);
return new DuplicationConfig(defaultRules, overrideRules, ignoreRecipeTypes, ignoreRecipes, strictMode);
}
private JsonCompare.CompareSettings defaultSet() {
private JsonCompare.CompareSettings defaultSettings() {
JsonCompare.CompareSettings result = new JsonCompare.CompareSettings();
result.ignoreField("conditions");
result.addRule("cookingtime", new JsonCompare.HigherRule());
@ -75,6 +75,16 @@ public class DuplicationConfig extends Config {
return result;
}
private LinkedHashMap<ResourceLocation, JsonCompare.CompareSettings> defaultOverrides() {
JsonCompare.CompareSettings result = new JsonCompare.CompareSettings();
result.ignoreField("conditions");
result.ignoreField("pattern");
result.ignoreField("key");
LinkedHashMap<ResourceLocation, JsonCompare.CompareSettings> resultMap = new LinkedHashMap<>();
resultMap.put(new ResourceLocation("minecraft", "crafting_shaped"), result);
return resultMap;
}
private JsonCompare.CompareSettings createCompareSet(JsonObject rules) {
JsonCompare.CompareSettings result = new JsonCompare.CompareSettings();
result.deserialize(rules);

View file

@ -44,21 +44,16 @@ public class RecipeLink {
JsonObject selfActual = first.getActual();
JsonObject toCompareActual = second.getActual();
if (JsonCompare.matches(selfActual, toCompareActual, compareSettings.getIgnoredFields())) {
JsonObject compare = JsonCompare.compare(compareSettings.getRules(), selfActual, toCompareActual);
if (compare == null) {
return null;
}
if (compare == selfActual) {
return first;
}
if (compare == toCompareActual) {
return second;
}
JsonObject compare = null;
if (first.getType().toString().equals("minecraft:crafting_shaped")) {
compare = JsonCompare.compareShaped(selfActual, toCompareActual, compareSettings.getIgnoredFields());
} else if (JsonCompare.matches(selfActual, toCompareActual, compareSettings.getIgnoredFields())) {
compare = JsonCompare.compare(compareSettings.getRules(), selfActual, toCompareActual);
}
if (compare == null) return null;
if (compare == selfActual) return first;
if (compare == toCompareActual) return second;
return null;
}

View file

@ -35,6 +35,54 @@ public final class JsonCompare {
return unsorted.get(0);
}
@Nullable
public static JsonObject compareShaped(JsonObject first, JsonObject second, Collection<String> ignoredFields) {
if (!matches(first, second, ignoredFields)) return null;
JsonArray firstPattern = JsonUtils.arrayOrSelf(first.get("pattern"));
JsonArray secondPattern = JsonUtils.arrayOrSelf(second.get("pattern"));
if (firstPattern.size() != secondPattern.size()) {
return null;
}
for (int i = 0; i < firstPattern.size(); i++) {
if (JsonUtils.stringOrSelf(firstPattern.get(i)).length() !=
JsonUtils.stringOrSelf(secondPattern.get(i)).length()) {
return null;
}
}
var firstKeyMap = createShapedKeyMap(first);
var secondKeyMap = createShapedKeyMap(second);
for (int i = 0; i < firstPattern.size(); i++) {
String firstPatternString = JsonUtils.stringOrSelf(firstPattern.get(i));
String secondPatternString = JsonUtils.stringOrSelf(secondPattern.get(i));
for (int j = 0; j < firstPatternString.length(); j++) {
char firstChar = firstPatternString.charAt(j);
char secondChar = secondPatternString.charAt(j);
if (!firstKeyMap.containsKey(firstChar) || !secondKeyMap.containsKey(secondChar)) {
return null;
}
if (!firstKeyMap.get(firstChar).equals(secondKeyMap.get(secondChar))) {
return null;
}
}
}
return first;
}
private static Map<Character, JsonObject> createShapedKeyMap(JsonObject json) {
JsonObject keys = JsonUtils.objectOrSelf(json.get("key"));
Map<Character, JsonObject> keyMap = new HashMap<>();
for (Map.Entry<String, JsonElement> patterKey : keys.entrySet()) {
keyMap.put(patterKey.getKey().charAt(0), JsonUtils.objectOrSelf(patterKey.getValue()));
}
return keyMap;
}
public static boolean matches(JsonObject first, JsonObject second, Collection<String> ignoredProperties) {
List<String> firstValidKeys = first
.keySet()

View file

@ -3,6 +3,7 @@ package com.almostreliable.unified.utils;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import javax.annotation.Nullable;
import java.util.List;
@ -36,6 +37,20 @@ public final class JsonUtils {
}
}
public static JsonObject objectOrSelf(@Nullable JsonElement element) {
if (element instanceof JsonObject jsonObject) {
return jsonObject;
}
return new JsonObject();
}
public static String stringOrSelf(@Nullable JsonElement element) {
if (element instanceof JsonPrimitive primitive) {
return primitive.getAsString();
}
return "";
}
/**
* 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.

View file

@ -112,4 +112,95 @@ public class JsonCompareTest {
boolean matches = JsonCompare.matches(first, second, List.of("experience"));
assertTrue(matches);
}
@Test
public void shapedNoMatch() {
String recipe1 = """
{
"type": "minecraft:crafting_shaped",
"pattern": [
"iii",
"ici",
"iii"
],
"key": {
"i": {
"tag": "forge:raw_materials/iron"
},
"k": {
"item": "minecraft:carrot"
}
},
"result": "minecraft:iron_ingot"
}
""";
String recipe2 = """
{
"type": "minecraft:crafting_shaped",
"pattern": [
"iii",
"ici",
"iii"
],
"key": {
"i": {
"tag": "forge:raw_materials/iron"
},
"k": {
"item": "minecraft:pumpkin"
}
},
"result": "minecraft:iron_ingot"
}
""";
JsonObject first = TestUtils.json(recipe1);
JsonObject second = TestUtils.json(recipe2);
JsonObject result = JsonCompare.compareShaped(first, second, List.of("pattern", "key"));
assertNull(result);
}
@Test
public void shapedMatch() {
String recipe1 = """
{
"type": "minecraft:crafting_shaped",
"pattern": [
"iii",
"iii",
"iii"
],
"key": {
"i": {
"tag": "forge:raw_materials/iron"
}
},
"result": "minecraft:iron_ingot"
}
""";
String recipe2 = """
{
"type": "minecraft:crafting_shaped",
"pattern": [
"iii",
"iki",
"iii"
],
"key": {
"i": {
"tag": "forge:raw_materials/iron"
},
"k": {
"tag": "forge:raw_materials/iron"
}
},
"result": "minecraft:iron_ingot"
}
""";
JsonObject first = TestUtils.json(recipe1);
JsonObject second = TestUtils.json(recipe2);
JsonObject result = JsonCompare.compareShaped(first, second, List.of("pattern", "key"));
assertEquals(first, result);
}
}