Prepare clean up

This commit is contained in:
LLytho 2022-06-17 17:56:32 +02:00
parent 977273241a
commit e699714835
6 changed files with 113 additions and 64 deletions

View file

@ -1,24 +1,19 @@
package com.almostreliable.unified; package com.almostreliable.unified;
import com.almostreliable.unified.api.RecipeTransformContext;
import com.almostreliable.unified.api.RecipeTransformer; import com.almostreliable.unified.api.RecipeTransformer;
import com.almostreliable.unified.api.RecipeTransformerFactory; import com.almostreliable.unified.api.RecipeTransformerFactory;
import com.almostreliable.unified.api.RecipeTransformerRegistry; import com.almostreliable.unified.api.RecipeTransformerRegistry;
import com.almostreliable.unified.api.ReplacementLookupHelper;
import com.almostreliable.unified.transformer.GenericRecipeTransformer;
import com.almostreliable.unified.transformer.GenericRecipeTransformerFactory; import com.almostreliable.unified.transformer.GenericRecipeTransformerFactory;
import com.google.common.collect.HashMultimap; import com.google.common.collect.BiMap;
import com.google.common.collect.Multimap; import com.google.common.collect.HashBiMap;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagManager; import net.minecraft.tags.TagManager;
import org.apache.commons.lang3.time.StopWatch;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -26,7 +21,6 @@ import java.util.Map;
public class AlmostUnifiedRuntime { public class AlmostUnifiedRuntime {
protected final ModConfig config; protected final ModConfig config;
protected final RecipeTransformer defaultTransformer = new GenericRecipeTransformer();
protected final RecipeTransformerFactory defaultFactory = new GenericRecipeTransformerFactory(); protected final RecipeTransformerFactory defaultFactory = new GenericRecipeTransformerFactory();
@Nullable protected TagManager tagManager; @Nullable protected TagManager tagManager;
@ -36,11 +30,11 @@ public class AlmostUnifiedRuntime {
public void run(Map<ResourceLocation, JsonElement> recipes) { public void run(Map<ResourceLocation, JsonElement> recipes) {
config.load(); config.load();
ReplacementLookupHelper helper = createHelper(config.getAllowedTags(), config.getModPriorities()); RecipeTransformContext helper = createContext(config.getAllowedTags(), config.getModPriorities());
transformRecipes(recipes, helper); // transformRecipes(recipes, helper);
} }
public void transformRecipes(Map<ResourceLocation, JsonElement> recipes, ReplacementLookupHelper helper) { public void transformRecipes(Map<ResourceLocation, JsonElement> recipes, RecipeTransformContext helper) {
int transformedRecipes = 0; int transformedRecipes = 0;
int transformedPropertiesInRecipes = 0; int transformedPropertiesInRecipes = 0;
long start = System.nanoTime(); long start = System.nanoTime();
@ -62,7 +56,7 @@ public class AlmostUnifiedRuntime {
timeElapsed / 1000_000D); timeElapsed / 1000_000D);
} }
public int transformRecipe(JsonObject json, ReplacementLookupHelper helper) { public int transformRecipe(JsonObject json, RecipeTransformContext helper) {
ResourceLocation recipeType = getRecipeType(json); ResourceLocation recipeType = getRecipeType(json);
if (recipeType == null) { if (recipeType == null) {
return 0; return 0;
@ -106,42 +100,29 @@ public class AlmostUnifiedRuntime {
this.tagManager = tagManager; this.tagManager = tagManager;
} }
protected ReplacementLookupHelper createHelper(List<ResourceLocation> allowedTags, List<String> modPriorities) { protected RecipeTransformContext createContext(List<ResourceLocation> allowedTags, List<String> modPriorities) {
if (tagManager == null) { if (tagManager == null) {
throw new IllegalStateException("Internal error. TagManager was not updated correctly"); throw new IllegalStateException("Internal error. TagManager was not updated correctly");
} }
var tags = tagManager
.getResult()
.stream()
.filter(result -> result.key().equals(Registry.ITEM_REGISTRY))
.findFirst()
.map(TagManager.LoadResult::tags)
.orElseThrow(() -> new IllegalStateException("No item tag result found"));
Map<ResourceLocation, ResourceLocation> itemTagMap = new HashMap<>(); TagMap tagMap = TagMap.create(tagManager);
Multimap<ResourceLocation, ResourceLocation> tagToEntry = HashMultimap.create(); Map<ResourceLocation, ResourceLocation> itemToTagMapping = new HashMap<>(allowedTags.size());
for (ResourceLocation allowedTag : allowedTags) { for (ResourceLocation tag : allowedTags) {
Tag<? extends Holder<?>> holderTag = tags.get(allowedTag); Collection<ResourceLocation> items = tagMap.getItems(tag);
if (holderTag == null) { for (ResourceLocation item : items) {
continue; if (itemToTagMapping.containsKey(item)) {
}
for (Holder<?> holder : holderTag.getValues()) {
ResourceLocation itemId = holder.unwrapKey().map(ResourceKey::location).orElse(null);
if (itemTagMap.containsKey(itemId)) {
AlmostUnified.LOG.warn("Item '{}' already has a tag '{}' for recipe replacement. Skipping this tag", AlmostUnified.LOG.warn("Item '{}' already has a tag '{}' for recipe replacement. Skipping this tag",
itemId, item,
allowedTag); tag);
continue; continue;
} }
itemTagMap.put(itemId, allowedTag); itemToTagMapping.put(item, tag);
tagToEntry.put(allowedTag, itemId);
} }
} }
return new LookupByModPriority(itemTagMap, tagToEntry, modPriorities); return new RecipeTransformContextImpl(tagMap, itemToTagMapping, modPriorities);
} }
} }

View file

@ -1,6 +1,6 @@
package com.almostreliable.unified; package com.almostreliable.unified;
import com.almostreliable.unified.api.ReplacementLookupHelper; import com.almostreliable.unified.api.RecipeTransformContext;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -8,20 +8,21 @@ import net.minecraft.resources.ResourceLocation;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.*; import java.util.*;
public class LookupByModPriority implements ReplacementLookupHelper { public class RecipeTransformContextImpl implements RecipeTransformContext {
private final Collection<String> modPriorities;
private final Map<ResourceLocation, ResourceLocation> itemToTag;
private final Multimap<ResourceLocation, ResourceLocation> tagToItem;
private final Collection<String> modPriorities;
private final TagMap tagMap;
private final Map<ResourceLocation, ResourceLocation> itemToTagMapping;
/** /**
* Cache for replacements. Key is the item to replace, value is the replacement. * Cache for replacements. Key is the item to replace, value is the replacement.
*/ */
private final Map<ResourceLocation, ResourceLocation> replacementCache = new HashMap<>(); private final Map<ResourceLocation, ResourceLocation> replacementCache = new HashMap<>();
private final Set<ResourceLocation> invalidCache = new HashSet<>(); private final Set<ResourceLocation> invalidCache = new HashSet<>();
public LookupByModPriority(Map<ResourceLocation, ResourceLocation> itemToTag, Multimap<ResourceLocation, ResourceLocation> tagToItem, Collection<String> modPriorities) {
this.itemToTag = itemToTag; public RecipeTransformContextImpl(TagMap tagMap, Map<ResourceLocation, ResourceLocation> itemToTagMapping, List<String> modPriorities) {
this.tagToItem = tagToItem; this.tagMap = tagMap;
this.itemToTagMapping = itemToTagMapping;
this.modPriorities = modPriorities; this.modPriorities = modPriorities;
} }
@ -38,12 +39,12 @@ public class LookupByModPriority implements ReplacementLookupHelper {
return replacement.toString(); return replacement.toString();
} }
ResourceLocation tagRL = itemToTag.get(asLocation); ResourceLocation tag = itemToTagMapping.get(asLocation);
if (!Registry.ITEM.containsKey(asLocation) || tagRL == null) { if (!Registry.ITEM.containsKey(asLocation) || tag == null) {
return null; return null;
} }
ResourceLocation modReplacement = computeReplacement(asLocation, tagToItem.get(tagRL)); ResourceLocation modReplacement = computeReplacement(asLocation, tag, tagMap.getItems(tag));
if(modReplacement == null || modReplacement.equals(asLocation)) { if(modReplacement == null || modReplacement.equals(asLocation)) {
invalidCache.add(asLocation); invalidCache.add(asLocation);
return null; return null;
@ -55,15 +56,26 @@ public class LookupByModPriority implements ReplacementLookupHelper {
} }
@Nullable @Nullable
private ResourceLocation computeReplacement(ResourceLocation toReplace, Collection<ResourceLocation> items) { public ResourceLocation computeReplacement(ResourceLocation toReplace, ResourceLocation tag, Collection<ResourceLocation> items) {
for (String mod : modPriorities) { for (String mod : modPriorities) {
for (ResourceLocation item : items) { List<ResourceLocation> sameModItems = tagMap
if (item.getNamespace().equals(mod) && Registry.ITEM.containsKey(item)) { .getItems(tag)
return item; .stream()
} .filter(item -> item.getNamespace().equals(mod) && Registry.ITEM.containsKey(item))
.toList();
if(sameModItems.size() == 1) {
return sameModItems.get(0);
}
if(sameModItems.size() > 1) {
return findFittingItem(toReplace, tag, sameModItems);
} }
} }
return null; return null;
} }
public ResourceLocation findFittingItem(ResourceLocation toReplace, ResourceLocation tag, List<ResourceLocation> sameModItems) {
return null;
}
} }

View file

@ -0,0 +1,58 @@
package com.almostreliable.unified;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagManager;
import java.util.*;
public class TagMap {
private final Map<ResourceLocation, Set<ResourceLocation>> tagsToItems = new HashMap<>();
private final Map<ResourceLocation, Set<ResourceLocation>> itemsToTags = new HashMap<>();
protected TagMap() {}
public static TagMap create(TagManager tagManager) {
Objects.requireNonNull(tagManager, "Requires a non-null tag manager");
var tags = tagManager
.getResult()
.stream()
.filter(result -> result.key().equals(Registry.ITEM_REGISTRY))
.findFirst()
.map(TagManager.LoadResult::tags)
.orElseThrow(() -> new IllegalStateException("No item tag result found"));
TagMap tagMap = new TagMap();
for (var entry : tags.entrySet()) {
ResourceLocation tag = entry.getKey();
Tag<? extends Holder<?>> holderTag = entry.getValue();
for (Holder<?> holder : holderTag.getValues()) {
ResourceLocation itemId = holder.unwrapKey().map(ResourceKey::location).orElse(null);
if (itemId != null) {
tagMap.put(tag, itemId);
}
}
}
return tagMap;
}
protected void put(ResourceLocation tag, ResourceLocation item) {
tagsToItems.computeIfAbsent(tag, k -> new HashSet<>()).add(item);
itemsToTags.computeIfAbsent(item, k -> new HashSet<>()).add(tag);
}
public Collection<ResourceLocation> getItems(ResourceLocation tag) {
return Collections.unmodifiableSet(tagsToItems.getOrDefault(tag, Collections.emptySet()));
}
public Collection<ResourceLocation> getTags(ResourceLocation items) {
return Collections.unmodifiableSet(itemsToTags.getOrDefault(items, Collections.emptySet()));
}
}

View file

@ -2,7 +2,7 @@ package com.almostreliable.unified.api;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public interface ReplacementLookupHelper { public interface RecipeTransformContext {
@Nullable @Nullable
String findReplacement(String id); String findReplacement(String id);

View file

@ -7,5 +7,5 @@ import javax.annotation.Nullable;
@FunctionalInterface @FunctionalInterface
public interface RecipeTransformer { public interface RecipeTransformer {
@Nullable @Nullable
JsonElement transformRecipe(JsonElement json, ReplacementLookupHelper helper); JsonElement transformRecipe(JsonElement json, RecipeTransformContext context);
} }

View file

@ -1,7 +1,7 @@
package com.almostreliable.unified.transformer; package com.almostreliable.unified.transformer;
import com.almostreliable.unified.api.RecipeTransformer; import com.almostreliable.unified.api.RecipeTransformer;
import com.almostreliable.unified.api.ReplacementLookupHelper; import com.almostreliable.unified.api.RecipeTransformContext;
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;
@ -9,28 +9,26 @@ import com.google.gson.JsonObject;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class GenericRecipeTransformer implements RecipeTransformer { public class GenericRecipeTransformer implements RecipeTransformer {
protected void replaceItems(JsonElement element, RecipeTransformContext context) {
protected void replaceItems(JsonElement element, ReplacementLookupHelper lookup) {
if (element instanceof JsonObject asObject) { if (element instanceof JsonObject asObject) {
if (asObject.has("item")) { if (asObject.has("item")) {
String newItem = lookup.findReplacement(asObject.get("item").getAsString()); String newItem = context.findReplacement(asObject.get("item").getAsString());
if (newItem != null) { if (newItem != null) {
asObject.addProperty("item", newItem); asObject.addProperty("item", newItem);
} }
} }
} else if (element instanceof JsonArray asArray) { } else if (element instanceof JsonArray asArray) {
for (JsonElement innerElement : asArray) { for (JsonElement innerElement : asArray) {
replaceItems(innerElement, lookup); replaceItems(innerElement, context);
} }
} }
} }
@Nullable @Nullable
@Override @Override
public JsonElement transformRecipe(JsonElement json, ReplacementLookupHelper helper) { public JsonElement transformRecipe(JsonElement json, RecipeTransformContext context) {
// TODO refactor // TODO refactor
replaceItems(json, helper); replaceItems(json, context);
return json; return json;
} }
} }