Recipe search optimisation

This commit is contained in:
paulevsGitch 2022-05-06 16:44:43 +03:00
parent 6a5ba519c8
commit 470d4a6c1e
2 changed files with 27 additions and 11 deletions

View file

@ -11,10 +11,8 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.bclib.recipes.BCLRecipeManager;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -27,13 +25,6 @@ public abstract class RecipeManagerMixin {
@Inject(method = "getRecipeFor", at = @At(value = "HEAD"), cancellable = true)
private <C extends Container, T extends Recipe<C>> void bclib_getRecipeFor(RecipeType<T> type, C inventory, Level level, CallbackInfoReturnable<Optional<T>> info) {
Collection<Recipe<C>> values = byType(type).values();
List<Recipe<C>> list = new ArrayList<>(values);
list.sort((v1, v2) -> {
boolean b1 = v1.getId().getNamespace().equals("minecraft");
boolean b2 = v2.getId().getNamespace().equals("minecraft");
return b1 ^ b2 ? (b1 ? 1 : -1) : 0;
});
info.setReturnValue(list.stream().flatMap(recipe -> type.tryMatch(recipe, level, inventory).stream()).findFirst());
info.setReturnValue(BCLRecipeManager.getSortedRecipe(type, inventory, level, this::byType));
}
}

View file

@ -1,20 +1,44 @@
package ru.bclib.recipes;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.Container;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import ru.bclib.util.CollectionsUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Function;
public class BCLRecipeManager {
private static final Map<RecipeType<?>, Map<ResourceLocation, Recipe<?>>> RECIPES = Maps.newHashMap();
private static final Map<RecipeType<?>, Object> SORTED = Maps.newHashMap();
private static final String MINECRAFT = "minecraft";
public static <C extends Container, T extends Recipe<C>> Optional<T> getSortedRecipe(RecipeType<T> type, C inventory, Level level, Function<RecipeType<T>, Map<ResourceLocation, Recipe<C>>> getter) {
List<Recipe<C>> recipes = (List<Recipe<C>>) SORTED.computeIfAbsent(type, t -> {
Collection<Recipe<C>> values = getter.apply(type).values();
List<Recipe<C>> list = new ArrayList<>(values);
list.sort((v1, v2) -> {
boolean b1 = v1.getId().getNamespace().equals(MINECRAFT);
boolean b2 = v2.getId().getNamespace().equals(MINECRAFT);
return b1 ^ b2 ? (b1 ? 1 : -1) : 0;
});
return ImmutableList.copyOf(list);
});
return recipes.stream().flatMap(recipe -> type.tryMatch(recipe, level, inventory).stream()).findFirst();
}
public static void addRecipe(RecipeType<?> type, Recipe<?> recipe) {
Map<ResourceLocation, Recipe<?>> list = RECIPES.computeIfAbsent(type, i -> Maps.newHashMap());
@ -35,6 +59,7 @@ public class BCLRecipeManager {
result.put(type, typeList);
}
SORTED.clear();
RECIPES.forEach((type, list) -> {
if (list != null) {
Map<ResourceLocation, Recipe<?>> typeList = result.computeIfAbsent(type, i -> Maps.newHashMap());