cn.nukkit.inventory.ShapelessRecipe Maven / Gradle / Ivy
package cn.nukkit.inventory;
import cn.nukkit.api.DeprecationDetails;
import cn.nukkit.api.PowerNukkitXOnly;
import cn.nukkit.api.Since;
import cn.nukkit.inventory.recipe.DefaultDescriptor;
import cn.nukkit.inventory.recipe.ItemDescriptor;
import cn.nukkit.inventory.recipe.ItemDescriptorType;
import cn.nukkit.inventory.recipe.ItemTagDescriptor;
import cn.nukkit.item.Item;
import java.util.*;
import static cn.nukkit.inventory.Recipe.matchItemList;
/**
* @author MagicDroidX (Nukkit Project)
*/
public class ShapelessRecipe implements CraftingRecipe {
private String recipeId;
private final Item output;
private long least, most;
@Deprecated
@DeprecationDetails(since = "1.19.50-r2", reason = "new ingredients format", replaceWith = "newIngredients")
private final List- ingredients = null;
private final List
- ingredientsAggregate;
@PowerNukkitXOnly
@Since("1.19.50-r2")
private final List
needTags;
@PowerNukkitXOnly
@Since("1.19.50-r2")
private final List newIngredients;
private final int priority;
public ShapelessRecipe(Item result, Collection- ingredients) {
this(null, 10, result, ingredients);
}
public ShapelessRecipe(String recipeId, int priority, Item result, Collection
- ingredients) {
this(recipeId, priority, result, ingredients.stream().map(item -> (ItemDescriptor) new DefaultDescriptor(item)).toList());
}
@PowerNukkitXOnly
@Since("1.19.50-r2")
public ShapelessRecipe(String recipeId, int priority, Item result, List
ingredients) {
this.recipeId = recipeId;
this.priority = priority;
this.output = result.clone();
if (ingredients.size() > 9) {
throw new IllegalArgumentException("Shapeless recipes cannot have more than 9 ingredients");
}
this.ingredientsAggregate = new ArrayList<>();
this.newIngredients = new ArrayList<>();
this.needTags = new ArrayList<>();
for (ItemDescriptor itemDescriptor : ingredients) {
newIngredients.add(itemDescriptor);
switch (itemDescriptor.getType()) {
case DEFAULT -> {
var item = itemDescriptor.toItem();
if (item.getCount() < 1) {
throw new IllegalArgumentException("Recipe '" + recipeId + "' Ingredient amount was not 1 (value: " + item.getCount() + ")");
}
boolean found = false;
for (Item existingIngredient : this.ingredientsAggregate) {
if (existingIngredient.equals(item, item.hasMeta(), item.hasCompoundTag())) {
existingIngredient.setCount(existingIngredient.getCount() + item.getCount());
found = true;
break;
}
}
if (!found)
this.ingredientsAggregate.add(item.clone());
this.ingredientsAggregate.sort(CraftingManager.recipeComparator);
}
case ITEM_TAG -> {
this.needTags.add(((ItemTagDescriptor) itemDescriptor).getItemTag());
}
default -> {
}
}
}
}
@Override
public Item getResult() {
return this.output.clone();
}
@Override
public String getRecipeId() {
return this.recipeId;
}
@Override
public UUID getId() {
return new UUID(least, most);
}
@Override
public void setId(UUID uuid) {
this.least = uuid.getLeastSignificantBits();
this.most = uuid.getMostSignificantBits();
if (this.recipeId == null) {
this.recipeId = this.getId().toString();
}
}
public List- getIngredientList() {
return this.newIngredients
.stream()
.filter(itemDescriptor -> itemDescriptor.getType().equals(ItemDescriptorType.DEFAULT))
.map(ItemDescriptor::toItem)
.toList();
}
public int getIngredientCount() {
return this.newIngredients.size();
}
@Override
public void registerToCraftingManager(CraftingManager manager) {
manager.registerShapelessRecipe(this);
}
@Override
public RecipeType getType() {
return RecipeType.SHAPELESS;
}
@Override
public boolean requiresCraftingTable() {
return this.newIngredients.size() > 4;
}
@Override
public List
- getExtraResults() {
return new ArrayList<>();
}
@Override
public List
- getAllResults() {
return null;
}
@Override
public int getPriority() {
return this.priority;
}
@Override
public boolean matchItems(List
- inputList, List
- extraOutputList, int multiplier) {
List
- haveInputs = new ArrayList<>();
for (Item item : inputList) {
if (item.isNull())
continue;
haveInputs.add(item.clone());
}
List
- needInputs = new ArrayList<>();
if (multiplier != 1) {
for (Item item : ingredientsAggregate) {
if (item.isNull())
continue;
Item itemClone = item.clone();
itemClone.setCount(itemClone.getCount() * multiplier);
needInputs.add(itemClone);
}
} else {
for (Item item : ingredientsAggregate) {
if (item.isNull())
continue;
needInputs.add(item.clone());
}
}
if (!matchItemList(haveInputs, needInputs)) {
if (!haveInputs.isEmpty()) {
Set
tags = new HashSet<>();
for (var hInput : haveInputs) {
var t = ItemTag.getTags(hInput.getNamespaceId());
if (t != null) tags.addAll(t);
}
if (!tags.containsAll(needTags)) return false;
} else return false;
}
List- haveOutputs = new ArrayList<>();
for (Item item : extraOutputList) {
if (item.isNull())
continue;
haveOutputs.add(item.clone());
}
haveOutputs.sort(CraftingManager.recipeComparator);
List
- needOutputs = new ArrayList<>();
if (multiplier != 1) {
for (Item item : getExtraResults()) {
if (item.isNull())
continue;
Item itemClone = item.clone();
itemClone.setCount(itemClone.getCount() * multiplier);
needOutputs.add(itemClone);
}
} else {
for (Item item : getExtraResults()) {
if (item.isNull())
continue;
needOutputs.add(item.clone());
}
}
needOutputs.sort(CraftingManager.recipeComparator);
return matchItemList(haveOutputs, needOutputs);
}
/**
* Returns whether the specified list of crafting grid inputs and outputs matches this recipe. Outputs DO NOT
* include the primary result item.
*
* @param inputList list of items taken from the crafting grid
* @param extraOutputList list of items put back into the crafting grid (secondary results)
* @return bool
*/
@Override
public boolean matchItems(List
- inputList, List
- extraOutputList) {
return matchItems(inputList, extraOutputList, 1);
}
@Override
public List
- getIngredientsAggregate() {
return ingredientsAggregate;
}
@PowerNukkitXOnly
@Since("1.19.50-r2")
public List
getNewIngredients() {
return newIngredients;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy