Impelement fallback for stone stratas

This commit is contained in:
LLytho 2022-06-17 19:24:25 +02:00
parent 37bfeca84b
commit c6beabaf2e
7 changed files with 103 additions and 32 deletions

View file

@ -10,7 +10,9 @@ import com.google.common.collect.HashBiMap;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.tags.TagManager;
import net.minecraft.world.item.Item;
import javax.annotation.Nullable;
import java.util.Collection;
@ -30,8 +32,8 @@ public class AlmostUnifiedRuntime {
public void run(Map<ResourceLocation, JsonElement> recipes) {
config.load();
RecipeTransformContext helper = createContext(config.getAllowedTags(), config.getModPriorities());
// transformRecipes(recipes, helper);
RecipeTransformContext context = createContext(config.getAllowedTags(), config.getModPriorities());
transformRecipes(recipes, context);
}
public void transformRecipes(Map<ResourceLocation, JsonElement> recipes, RecipeTransformContext helper) {
@ -100,16 +102,16 @@ public class AlmostUnifiedRuntime {
this.tagManager = tagManager;
}
protected RecipeTransformContext createContext(List<ResourceLocation> allowedTags, List<String> modPriorities) {
protected RecipeTransformContext createContext(List<TagKey<Item>> allowedTags, List<String> modPriorities) {
if (tagManager == null) {
throw new IllegalStateException("Internal error. TagManager was not updated correctly");
}
TagMap tagMap = TagMap.create(tagManager);
Map<ResourceLocation, ResourceLocation> itemToTagMapping = new HashMap<>(allowedTags.size());
Map<ResourceLocation, TagKey<Item>> itemToTagMapping = new HashMap<>(allowedTags.size());
for (ResourceLocation tag : allowedTags) {
for (TagKey<Item> tag : allowedTags) {
Collection<ResourceLocation> items = tagMap.getItems(tag);
for (ResourceLocation item : items) {
if (itemToTagMapping.containsKey(item)) {

View file

@ -6,7 +6,10 @@ import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.electronwill.nightconfig.core.file.FileConfig;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import javax.annotation.Nullable;
import java.util.*;
@ -160,26 +163,27 @@ public class ModConfig {
return currentConfig.get(UNIFICATION_MOD_PRIORITIES);
}
public List<ResourceLocation> getAllowedTags() {
public List<TagKey<Item>> getAllowedTags() {
if(currentConfig == null) {
throw new IllegalStateException("Config is not loaded");
}
Multimap<String, String> variables = compileVariables();
List<ResourceLocation> collectedPattern = new ArrayList<>();
Collection<String> patterns = currentConfig.get(UNIFICATION_PATTERN);
List<TagKey<Item>> collectedPattern = new ArrayList<>();
Collection<String> patterns = currentConfig.get(UNIFICATION_PATTERN);
for (String pattern : patterns) {
Collection<String> compiledPattern = compilePattern(pattern, variables);
if (pattern.startsWith("!")) {
collectedPattern.removeIf(p -> compiledPattern.contains(p.toString()));
collectedPattern.removeIf(p -> compiledPattern.contains(p.location().toString()));
} else {
for (String s : compiledPattern) {
ResourceLocation rl = ResourceLocation.tryParse(s);
if (rl == null) {
AlmostUnified.LOG.warn("Invalid pattern: " + s);
} else {
collectedPattern.add(rl);
TagKey<Item> tag = TagKey.create(Registry.ITEM_REGISTRY, rl);
collectedPattern.add(tag);
}
}
}

View file

@ -1,9 +1,12 @@
package com.almostreliable.unified;
import com.almostreliable.unified.api.RecipeTransformContext;
import com.google.common.collect.Multimap;
import com.almostreliable.unified.api.ReplacementFallbackStrategy;
import com.almostreliable.unified.fallbacks.StoneStrataFallbackStrategy;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import javax.annotation.Nullable;
import java.util.*;
@ -12,15 +15,17 @@ public class RecipeTransformContextImpl implements RecipeTransformContext {
private final Collection<String> modPriorities;
private final TagMap tagMap;
private final Map<ResourceLocation, ResourceLocation> itemToTagMapping;
private final Map<ResourceLocation, TagKey<Item>> itemToTagMapping;
/**
* Cache for replacements. Key is the item to replace, value is the replacement.
*/
private final Map<ResourceLocation, ResourceLocation> replacementCache = new HashMap<>();
private final Set<ResourceLocation> invalidCache = new HashSet<>();
// TODO - In the future this may be a list of multiple fallbacks.
private final ReplacementFallbackStrategy fallbackStrategy = new StoneStrataFallbackStrategy();
public RecipeTransformContextImpl(TagMap tagMap, Map<ResourceLocation, ResourceLocation> itemToTagMapping, List<String> modPriorities) {
public RecipeTransformContextImpl(TagMap tagMap, Map<ResourceLocation, TagKey<Item>> itemToTagMapping, List<String> modPriorities) {
this.tagMap = tagMap;
this.itemToTagMapping = itemToTagMapping;
this.modPriorities = modPriorities;
@ -39,12 +44,12 @@ public class RecipeTransformContextImpl implements RecipeTransformContext {
return replacement.toString();
}
ResourceLocation tag = itemToTagMapping.get(asLocation);
TagKey<Item> tag = itemToTagMapping.get(asLocation);
if (!Registry.ITEM.containsKey(asLocation) || tag == null) {
return null;
}
ResourceLocation modReplacement = computeReplacement(asLocation, tag, tagMap.getItems(tag));
ResourceLocation modReplacement = computeReplacement(asLocation, tag);
if(modReplacement == null || modReplacement.equals(asLocation)) {
invalidCache.add(asLocation);
return null;
@ -56,26 +61,33 @@ public class RecipeTransformContextImpl implements RecipeTransformContext {
}
@Nullable
public ResourceLocation computeReplacement(ResourceLocation toReplace, ResourceLocation tag, Collection<ResourceLocation> items) {
public ResourceLocation computeReplacement(ResourceLocation item, TagKey<Item> tag) {
for (String mod : modPriorities) {
if(mod.equals(item.getNamespace())) {
return null;
}
List<ResourceLocation> sameModItems = tagMap
.getItems(tag)
.stream()
.filter(item -> item.getNamespace().equals(mod) && Registry.ITEM.containsKey(item))
.filter(i -> i.getNamespace().equals(mod) && Registry.ITEM.containsKey(i))
.toList();
if(sameModItems.size() == 1) {
return sameModItems.get(0);
}
if(sameModItems.size() > 1) {
return findFittingItem(toReplace, tag, sameModItems);
ResourceLocation fallback = fallbackStrategy.getFallback(item, tag, sameModItems, tagMap);
if(fallback != null) {
if(fallback.equals(item)) {
throw new IllegalStateException("Fallback for " + item + " is the same as the item itself. This is not allowed.");
}
return fallback;
}
}
}
return null;
}
public ResourceLocation findFittingItem(ResourceLocation toReplace, ResourceLocation tag, List<ResourceLocation> sameModItems) {
return null;
}
}

View file

@ -5,13 +5,15 @@ import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.Tag;
import net.minecraft.tags.TagKey;
import net.minecraft.tags.TagManager;
import net.minecraft.world.item.Item;
import java.util.*;
public class TagMap {
private final Map<ResourceLocation, Set<ResourceLocation>> tagsToItems = new HashMap<>();
private final Map<ResourceLocation, Set<ResourceLocation>> itemsToTags = new HashMap<>();
private final Map<TagKey<Item>, Set<ResourceLocation>> tagsToItems = new HashMap<>();
private final Map<ResourceLocation, Set<TagKey<Item>>> itemsToTags = new HashMap<>();
protected TagMap() {}
@ -29,30 +31,27 @@ public class TagMap {
TagMap tagMap = new TagMap();
for (var entry : tags.entrySet()) {
ResourceLocation tag = entry.getKey();
TagKey<Item> tag = TagKey.create(Registry.ITEM_REGISTRY, 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);
}
holder.unwrapKey().map(ResourceKey::location).ifPresent(itemId -> tagMap.put(tag, itemId));
}
}
return tagMap;
}
protected void put(ResourceLocation tag, ResourceLocation item) {
protected void put(TagKey<Item> 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) {
public Collection<ResourceLocation> getItems(TagKey<Item> tag) {
return Collections.unmodifiableSet(tagsToItems.getOrDefault(tag, Collections.emptySet()));
}
public Collection<ResourceLocation> getTags(ResourceLocation items) {
public Collection<TagKey<Item>> getTags(ResourceLocation items) {
return Collections.unmodifiableSet(itemsToTags.getOrDefault(items, Collections.emptySet()));
}
}

View file

@ -0,0 +1,24 @@
package com.almostreliable.unified.api;
import com.almostreliable.unified.TagMap;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import javax.annotation.Nullable;
import java.util.Collection;
public interface ReplacementFallbackStrategy {
/**
* Determine a fallback for the given item.
*
* @param lookupItem the item to lookup
* @param tag the tag to replace the item with
* @param potentialItems the potential items to replace with
* @param tags the tag map to use for lookup
* @return the fallback item, or null if no fallback is available
* @throws IllegalStateException if returning the lookupItem
*/
@Nullable
ResourceLocation getFallback(ResourceLocation lookupItem, TagKey<Item> tag, Collection<ResourceLocation> potentialItems, TagMap tags);
}

View file

@ -0,0 +1,24 @@
package com.almostreliable.unified.fallbacks;
import com.almostreliable.unified.TagMap;
import com.almostreliable.unified.api.ReplacementFallbackStrategy;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import java.util.Collection;
import java.util.Comparator;
// TODO use config and not this :D
public class StoneStrataFallbackStrategy implements ReplacementFallbackStrategy {
@Override
public ResourceLocation getFallback(ResourceLocation lookupItem, TagKey<Item> tag, Collection<ResourceLocation> potentialItems, TagMap tags) {
if (tag.location().getPath().contains("ores")) {
return potentialItems
.stream()
.min(Comparator.comparingInt(s -> s.getPath().length()))
.orElse(null);
}
return null;
}
}

View file

@ -0,0 +1,6 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.almostreliable.unified.fallbacks;
import net.minecraft.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;