package com.hypixel.hytale.builtin.crafting; import com.hypixel.hytale.protocol.BenchRequirement; import com.hypixel.hytale.protocol.ItemResourceType; import com.hypixel.hytale.server.core.asset.type.item.config.CraftingRecipe; import com.hypixel.hytale.server.core.inventory.ItemStack; import com.hypixel.hytale.server.core.inventory.MaterialQuantity; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.Map.Entry; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class BenchRecipeRegistry { private final String benchId; private final Map> categoryMap = new Object2ObjectOpenHashMap(); private final Map> itemToIncomingRecipe = new Object2ObjectOpenHashMap(); private final Set uncategorizedRecipes = new ObjectOpenHashSet(); private final Set allMaterialIds = new ObjectOpenHashSet(); private final Set allMaterialResourceType = new ObjectOpenHashSet(); public BenchRecipeRegistry(String benchId) { this.benchId = benchId; } public Iterable getIncomingRecipesForItem(@Nonnull String itemId) { Set recipes = this.itemToIncomingRecipe.get(itemId); return recipes == null ? Collections.emptySet() : recipes; } public void removeRecipe(@Nonnull String id) { this.uncategorizedRecipes.remove(id); for (Entry> entry : this.categoryMap.entrySet()) { entry.getValue().remove(id); } } public void addRecipe(@Nonnull BenchRequirement benchRequirement, @Nonnull CraftingRecipe recipe) { if (benchRequirement.categories != null && benchRequirement.categories.length != 0) { for (String category : benchRequirement.categories) { this.categoryMap.computeIfAbsent(category, k -> new ObjectOpenHashSet()).add(recipe.getId()); } } else { this.uncategorizedRecipes.add(recipe.getId()); } } public CraftingRecipe[] getAllRecipes() { Set allRecipeIds = new ObjectOpenHashSet(this.uncategorizedRecipes); for (Set recipes : this.categoryMap.values()) { allRecipeIds.addAll(recipes); } List allRecipes = new ObjectArrayList(allRecipeIds.size()); for (String recipeId : allRecipeIds) { CraftingRecipe recipe = CraftingRecipe.getAssetMap().getAsset(recipeId); if (recipe != null) { allRecipes.add(recipe); } } return allRecipes.toArray(CraftingRecipe[]::new); } @Nullable public Set getRecipesForCategory(@Nonnull String benchCategoryId) { return this.categoryMap.get(benchCategoryId); } public void recompute() { this.allMaterialIds.clear(); this.allMaterialResourceType.clear(); this.itemToIncomingRecipe.clear(); for (Set recipes : this.categoryMap.values()) { this.extractMaterialFromRecipes(recipes); } this.extractMaterialFromRecipes(this.uncategorizedRecipes); } private void extractMaterialFromRecipes(Set recipes) { for (String recipeId : recipes) { CraftingRecipe recipe = CraftingRecipe.getAssetMap().getAsset(recipeId); if (recipe != null) { BenchRequirement[] benchRequirements = recipe.getBenchRequirement(); if (benchRequirements != null) { boolean matchesRegistry = false; for (BenchRequirement requirement : benchRequirements) { if (requirement.id.equals(this.benchId)) { matchesRegistry = true; break; } } if (matchesRegistry) { for (MaterialQuantity material : recipe.getInput()) { if (material.getItemId() != null) { this.allMaterialIds.add(material.getItemId()); } if (material.getResourceTypeId() != null) { this.allMaterialResourceType.add(material.getResourceTypeId()); } } for (MaterialQuantity output : recipe.getOutputs()) { this.itemToIncomingRecipe.computeIfAbsent(output.getItemId(), k -> new ObjectOpenHashSet()).add(recipeId); } } } } } } public boolean isValidCraftingMaterial(@Nonnull ItemStack itemStack) { if (this.allMaterialIds.contains(itemStack.getItemId())) { return true; } else { ItemResourceType[] resourceTypeId = itemStack.getItem().getResourceTypes(); if (resourceTypeId != null) { for (ItemResourceType resTypeId : resourceTypeId) { if (this.allMaterialResourceType.contains(resTypeId.id)) { return true; } } } return false; } } @Override public boolean equals(Object o) { if (o != null && this.getClass() == o.getClass()) { BenchRecipeRegistry that = (BenchRecipeRegistry)o; return Objects.equals(this.benchId, that.benchId) && Objects.equals(this.categoryMap, that.categoryMap) && Objects.equals(this.uncategorizedRecipes, that.uncategorizedRecipes) && Objects.equals(this.allMaterialIds, that.allMaterialIds) && Objects.equals(this.allMaterialResourceType, that.allMaterialResourceType); } else { return false; } } @Override public int hashCode() { return Objects.hash(this.benchId, this.categoryMap, this.uncategorizedRecipes, this.allMaterialIds, this.allMaterialResourceType); } @Override public String toString() { return "BenchRecipeRegistry{benchId='" + this.benchId + "', categoryMap=" + this.categoryMap + ", uncategorizedRecipes=" + this.uncategorizedRecipes + ", allMaterialIds=" + this.allMaterialIds + ", allMaterialResourceType=" + this.allMaterialResourceType + "}"; } }