Merge cd9017f6c3 into a5d25a09f7
This commit is contained in:
commit
13a9a3fe25
|
|
@ -31,6 +31,7 @@ import net.minecraft.world.item.BlockItem;
|
|||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
|
|
@ -186,7 +187,7 @@ public abstract class AbstractCrucibleBlockEntity extends ETankBlockEntity {
|
|||
|
||||
// Gets a crucible recipe, using the cache if possible
|
||||
@Nullable
|
||||
protected abstract CrucibleRecipe getRecipe(ItemStack item);
|
||||
protected abstract RecipeHolder<? extends CrucibleRecipe> getRecipe(ItemStack item);
|
||||
|
||||
/**
|
||||
* Tries to melt the specified item into the crucible.
|
||||
|
|
@ -206,7 +207,7 @@ public abstract class AbstractCrucibleBlockEntity extends ETankBlockEntity {
|
|||
if (this.level != null && this.level.isClientSide) {
|
||||
return true;
|
||||
}
|
||||
var result = recipe.getResult();
|
||||
var result = recipe.value().getResult();
|
||||
var contained = this.tank.getFluid();
|
||||
var hadPendingSolids = this.solids > 0;
|
||||
shrinkAction.accept(item);
|
||||
|
|
@ -240,7 +241,7 @@ public abstract class AbstractCrucibleBlockEntity extends ETankBlockEntity {
|
|||
var recipe = getRecipe(item);
|
||||
|
||||
if (recipe != null) {
|
||||
var result = recipe.getResult();
|
||||
var result = recipe.value().getResult();
|
||||
var contained = this.tank.getFluid();
|
||||
|
||||
if (FluidStack.isSameFluidSameComponents(result, contained) || (contained.isEmpty() && canAddToPendingFluid(result))) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import net.minecraft.world.item.ItemStack;
|
|||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.alchemy.PotionContents;
|
||||
import net.minecraft.world.item.alchemy.Potions;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.BucketPickup;
|
||||
|
|
@ -84,7 +85,7 @@ public class BarrelBlockEntity extends ETankBlockEntity {
|
|||
public final boolean transparent;
|
||||
// Current transformation recipe
|
||||
@Nullable
|
||||
public FluidTransformationRecipe currentTransformRecipe = null;
|
||||
public RecipeHolder<FluidTransformationRecipe> currentTransformRecipe = null;
|
||||
|
||||
public BarrelBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(EBlockEntities.BARREL.get(), pos, state);
|
||||
|
|
@ -266,11 +267,12 @@ public class BarrelBlockEntity extends ETankBlockEntity {
|
|||
var itemFluidCap = playerItem.getCapability(Capabilities.FluidHandler.ITEM);
|
||||
if (itemFluidCap != null) {
|
||||
var itemFluid = itemFluidCap.drain(1000, IFluidHandler.FluidAction.SIMULATE);
|
||||
BarrelFluidMixingRecipe recipe = getRecipeCaches().getFluidMixingRecipe(this.tank.getFluid(), itemFluid.getFluid());
|
||||
var holder = getRecipeCaches().getFluidMixingRecipe(this.tank.getFluid(), itemFluid.getFluid());
|
||||
|
||||
// If draining item fluid was possible and tank has enough fluid to mix...
|
||||
if (recipe != null && this.tank.getFluidAmount() >= recipe.baseFluid().amount() && itemFluid.getAmount() == 1000) {
|
||||
if (holder != null && this.tank.getFluidAmount() >= holder.value().baseFluid().amount() && itemFluid.getAmount() == 1000) {
|
||||
if (!level.isClientSide) {
|
||||
var recipe = holder.value();
|
||||
this.tank.drain(recipe.baseFluid().amount(), IFluidHandler.FluidAction.EXECUTE);
|
||||
setItem(recipe.result().copy());
|
||||
|
||||
|
|
@ -370,9 +372,10 @@ public class BarrelBlockEntity extends ETankBlockEntity {
|
|||
return false;
|
||||
}
|
||||
|
||||
var recipe = getRecipeCaches().getBarrelMixingRecipe(this.level.getRecipeManager(), playerItem, this.tank.getFluid());
|
||||
var holder = getRecipeCaches().getBarrelMixingRecipe(this.level.getRecipeManager(), playerItem, this.tank.getFluid());
|
||||
|
||||
if (recipe != null) {
|
||||
if (holder != null) {
|
||||
var recipe = holder.value();
|
||||
if (!simulate) {
|
||||
// Empty barrel
|
||||
this.tank.drain(recipe.fluid.amount(), IFluidHandler.FluidAction.EXECUTE);
|
||||
|
|
@ -391,9 +394,9 @@ public class BarrelBlockEntity extends ETankBlockEntity {
|
|||
if (simulate) {
|
||||
return getRecipeCaches().isCompostable(stack);
|
||||
} else {
|
||||
var recipe = getRecipeCaches().getBarrelCompostRecipe(stack);
|
||||
if (recipe != null) {
|
||||
addCompost(stack, recipe.getVolume());
|
||||
var holder = getRecipeCaches().getBarrelCompostRecipe(stack);
|
||||
if (holder != null) {
|
||||
addCompost(stack, holder.value().getVolume());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
@ -437,9 +440,10 @@ public class BarrelBlockEntity extends ETankBlockEntity {
|
|||
var aboveFluid = aboveFluidState.getType();
|
||||
|
||||
if (aboveFluid != Fluids.EMPTY) {
|
||||
BarrelFluidMixingRecipe recipe = getRecipeCaches().getFluidMixingRecipe(this.tank.getFluid(), aboveFluid instanceof FlowingFluid flowing ? flowing.getSource() : aboveFluid);
|
||||
var holder = getRecipeCaches().getFluidMixingRecipe(this.tank.getFluid(), aboveFluid instanceof FlowingFluid flowing ? flowing.getSource() : aboveFluid);
|
||||
|
||||
if (recipe != null) {
|
||||
if (holder != null) {
|
||||
var recipe = holder.value();
|
||||
// If additive is not consumed, just craft
|
||||
// If additive is consumed, check that the additive can be consumed before crafting
|
||||
if (!recipe.consumesAdditive()) {
|
||||
|
|
@ -467,7 +471,7 @@ public class BarrelBlockEntity extends ETankBlockEntity {
|
|||
this.currentTransformRecipe = getRecipeCaches().getFluidTransformationRecipe(this.tank.getFluid().getFluid(), belowState);
|
||||
|
||||
if (this.currentTransformRecipe != null) {
|
||||
var color = this.currentTransformRecipe.resultColor();
|
||||
var color = this.currentTransformRecipe.value().resultColor();
|
||||
this.r = (short) ((color >> 16) & 0xff);
|
||||
this.g = (short) ((color >> 8) & 0xff);
|
||||
this.b = (short) ((color) & 0xff);
|
||||
|
|
@ -501,7 +505,7 @@ public class BarrelBlockEntity extends ETankBlockEntity {
|
|||
}
|
||||
barrel.markUpdated();
|
||||
} else if (barrel.currentTransformRecipe != null) {
|
||||
var recipe = barrel.currentTransformRecipe;
|
||||
var recipe = barrel.currentTransformRecipe.value();
|
||||
var catalysts = 0;
|
||||
|
||||
for (var cursor : BlockPos.betweenClosed(pos.getX() - 1, pos.getY() - 1, pos.getZ() - 1, pos.getX() + 1, pos.getY() - 1, pos.getZ() + 1)) {
|
||||
|
|
@ -528,7 +532,7 @@ public class BarrelBlockEntity extends ETankBlockEntity {
|
|||
if (catalysts == 0) {
|
||||
barrel.currentTransformRecipe = null;
|
||||
} else {
|
||||
barrel.progress += catalysts * (1.0f / barrel.currentTransformRecipe.duration());
|
||||
barrel.progress += catalysts * (1.0f / barrel.currentTransformRecipe.value().duration());
|
||||
|
||||
if (barrel.progress >= 1.0f - Mth.EPSILON) {
|
||||
// Reset progress
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package thedarkcolour.exdeorum.blockentity;
|
|||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
|
@ -35,11 +36,11 @@ public class LavaCrucibleBlockEntity extends AbstractCrucibleBlockEntity {
|
|||
|
||||
@Override
|
||||
public int getMeltingRate() {
|
||||
return getRecipeCaches().getHeatValue(this.level.getBlockState(getBlockPos().below()));
|
||||
return getRecipeCaches().getHeatRecipe(this.level.getBlockState(getBlockPos().below())).value().heatValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable CrucibleRecipe getRecipe(ItemStack item) {
|
||||
protected @Nullable RecipeHolder<CrucibleRecipe.Lava> getRecipe(ItemStack item) {
|
||||
return getRecipeCaches().getLavaCrucibleRecipe(item);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import net.minecraft.world.entity.player.Inventory;
|
|||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
|
@ -122,13 +123,13 @@ public class MechanicalHammerBlockEntity extends AbstractMachineBlockEntity<Mech
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private HammerRecipe canFitResultIntoOutput(ItemStack input) {
|
||||
private RecipeHolder<HammerRecipe> canFitResultIntoOutput(ItemStack input) {
|
||||
var output = this.inventory.getStackInSlot(OUTPUT_SLOT);
|
||||
|
||||
if (output.isEmpty() || output.getCount() < output.getMaxStackSize()) {
|
||||
var recipe = getRecipeCaches().getHammerRecipe(input.getItem());
|
||||
|
||||
if (recipe != null && (output.isEmpty() || ItemStack.isSameItemSameComponents(recipe.result, output))) {
|
||||
if (recipe != null && (output.isEmpty() || ItemStack.isSameItemSameComponents(recipe.value().result, output))) {
|
||||
return recipe;
|
||||
}
|
||||
}
|
||||
|
|
@ -149,13 +150,13 @@ public class MechanicalHammerBlockEntity extends AbstractMachineBlockEntity<Mech
|
|||
if (recipe != null) {
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
LootContext ctx = RecipeUtil.emptyLootContext((ServerLevel) this.level);
|
||||
var resultCount = recipe.resultAmount.getInt(ctx);
|
||||
var resultCount = recipe.value().resultAmount.getInt(ctx);
|
||||
if (!input.is(EItemTags.HAMMER_FORTUNE_BLACKLIST)) {
|
||||
resultCount += HammerLootModifier.calculateFortuneBonus(this.level.registryAccess(), this.inventory.getStackInSlot(HAMMER_SLOT), ctx.getRandom(), resultCount == 0);
|
||||
}
|
||||
var output = this.inventory.getStackInSlot(OUTPUT_SLOT);
|
||||
if (output.isEmpty()) {
|
||||
this.inventory.setStackInSlot(OUTPUT_SLOT, recipe.result.copyWithCount(resultCount));
|
||||
this.inventory.setStackInSlot(OUTPUT_SLOT, recipe.value().result.copyWithCount(resultCount));
|
||||
} else {
|
||||
output.setCount(Math.min(output.getMaxStackSize(), resultCount + output.getCount()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package thedarkcolour.exdeorum.blockentity;
|
|||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
|
@ -35,7 +36,7 @@ public class WaterCrucibleBlockEntity extends AbstractCrucibleBlockEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable CrucibleRecipe getRecipe(ItemStack item) {
|
||||
protected @Nullable RecipeHolder<CrucibleRecipe.Water> getRecipe(ItemStack item) {
|
||||
return getRecipeCaches().getWaterCrucibleRecipe(item);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package thedarkcolour.exdeorum.blockentity.logic;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -11,7 +12,7 @@ public class CompressedSieveLogic extends SieveLogic {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected List<? extends SieveRecipe> getDropsFor(ItemStack contents) {
|
||||
protected List<? extends RecipeHolder<? extends SieveRecipe>> getDropsFor(ItemStack contents) {
|
||||
return this.owner.getRecipeCaches().getCompressedSieveRecipes(this.mesh.getItem(), contents);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import net.minecraft.util.Mth;
|
|||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
|
|
@ -96,7 +97,8 @@ public class SieveLogic {
|
|||
var handledAnyDrops = false;
|
||||
var hasDrops = false;
|
||||
|
||||
for (SieveRecipe recipe : getDropsFor(this.contents)) {
|
||||
for (RecipeHolder<? extends SieveRecipe> holder : getDropsFor(this.contents)) {
|
||||
var recipe = holder.value();
|
||||
var amount = getResultAmount(recipe, context, rand);
|
||||
|
||||
// Split overflowing stacks (64+) into multiple stacks
|
||||
|
|
@ -129,7 +131,7 @@ public class SieveLogic {
|
|||
this.owner.markUpdated();
|
||||
}
|
||||
|
||||
protected List<? extends SieveRecipe> getDropsFor(ItemStack contents) {
|
||||
protected List<? extends RecipeHolder<? extends SieveRecipe>> getDropsFor(ItemStack contents) {
|
||||
return this.owner.getRecipeCaches().getSieveRecipes(this.mesh.getItem(), contents);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,11 +79,11 @@ public class CompatUtil {
|
|||
return materials;
|
||||
}
|
||||
|
||||
public static <C extends RecipeInput, R extends Recipe<C>, T> List<T> collectAllRecipes(RecipeManager recipeManager, RecipeType<R> recipeType, Function<R, T> mapper) {
|
||||
public static <C extends RecipeInput, R extends Recipe<C>, T> List<T> collectAllRecipes(RecipeManager recipeManager, RecipeType<R> recipeType, Function<RecipeHolder<R>, T> mapper) {
|
||||
var byType = recipeManager.byType(recipeType);
|
||||
List<T> recipes = new ObjectArrayList<>(byType.size());
|
||||
for (RecipeHolder<R> value : byType) {
|
||||
recipes.add(mapper.apply(value.value()));
|
||||
recipes.add(mapper.apply(value));
|
||||
}
|
||||
return recipes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@ import com.google.common.collect.ArrayListMultimap;
|
|||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Multimap;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
|
||||
|
|
@ -34,33 +36,45 @@ import thedarkcolour.exdeorum.recipe.RecipeUtil;
|
|||
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
|
||||
import thedarkcolour.exdeorum.registry.EItems;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
// Since no JEI code is used here, this can be reused for REI
|
||||
public record XeiSieveRecipe(Ingredient ingredient, ItemStack mesh, List<Result> results) {
|
||||
public record XeiSieveRecipe(ResourceLocation id, Ingredient ingredient, ItemStack mesh, List<Result> results) {
|
||||
public static final MutableInt SIEVE_ROWS = new MutableInt(0);
|
||||
public static final MutableInt COMPRESSED_SIEVE_ROWS = new MutableInt(0);
|
||||
|
||||
public static ImmutableList<XeiSieveRecipe> getAllRecipesGrouped(RecipeType<? extends SieveRecipe> recipeType, MutableInt maxRows) {
|
||||
public static <T extends SieveRecipe> ImmutableList<XeiSieveRecipe> getAllRecipesGrouped(RecipeType<T> recipeType, MutableInt maxRows) {
|
||||
int maxSieveRows = 1;
|
||||
|
||||
var recipes = CompatUtil.collectAllRecipes(RecipeUtil.getClientRecipeManager(), recipeType, Function.identity());
|
||||
Multimap<Ingredient, SieveRecipe> ingredientGrouper = ArrayListMultimap.create();
|
||||
var recipeHolders = CompatUtil.collectAllRecipes(RecipeUtil.getClientRecipeManager(), recipeType, Function.identity());
|
||||
var recipeTypeKey = Objects.requireNonNull(BuiltInRegistries.RECIPE_TYPE.getKey(recipeType));
|
||||
Multimap<Ingredient, RecipeHolder<T>> ingredientGrouper = ArrayListMultimap.create();
|
||||
|
||||
for (int i = 0; i < recipes.size(); i++) {
|
||||
var recipe = recipes.get(i);
|
||||
for (int i = 0; i < recipeHolders.size(); i++) {
|
||||
var holder = recipeHolders.get(i);
|
||||
var recipe = holder.value();
|
||||
|
||||
ingredientGrouper.put(recipe.ingredient(), recipe);
|
||||
ingredientGrouper.put(recipe.ingredient(), holder);
|
||||
|
||||
for (int j = i + 1; j < recipes.size(); j++) {
|
||||
var other = recipes.get(j);
|
||||
for (int j = i + 1; j < recipeHolders.size(); j++) {
|
||||
var otherHolder = recipeHolders.get(j);
|
||||
var other = otherHolder.value();
|
||||
|
||||
if (RecipeUtil.areIngredientsEqual(recipe.ingredient(), other.ingredient())) {
|
||||
ingredientGrouper.put(recipe.ingredient(), other);
|
||||
recipes.remove(other);
|
||||
ingredientGrouper.put(recipe.ingredient(), otherHolder);
|
||||
recipeHolders.remove(otherHolder);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
|
@ -74,13 +88,23 @@ public record XeiSieveRecipe(Ingredient ingredient, ItemStack mesh, List<Result>
|
|||
|
||||
// ingredients with common ingredients are grouped into lists (ex. dirt)
|
||||
for (var ingredient : ingredientGrouper.keySet()) {
|
||||
Multimap<Item, SieveRecipe> meshGrouper = ArrayListMultimap.create();
|
||||
Multimap<Item, RecipeHolder<T>> meshGrouper = ArrayListMultimap.create();
|
||||
var values = ingredientGrouper.get(ingredient);
|
||||
|
||||
// A unique ingredient ID, which can grow long. For same ingredient will always generate same ID, even over game restarts.
|
||||
var ingredientId = "ingredient-start " + Stream
|
||||
.of(ingredient.getItems())
|
||||
.map(ItemStack::getItem)
|
||||
.map(BuiltInRegistries.ITEM::getKey)
|
||||
.map(ResourceLocation::toString)
|
||||
.sorted()
|
||||
.collect(Collectors.joining(" - ")) + " ingredient-end ";
|
||||
|
||||
// these lists are grouped into sub lists based on their meshes (ex. dirt with string mesh)
|
||||
for (var recipe : values) {
|
||||
for (var holder : values) {
|
||||
var recipe = holder.value();
|
||||
for (var stack : recipe.mesh.getItems()) {
|
||||
meshGrouper.put(stack.getItem(), recipe);
|
||||
meshGrouper.put(stack.getItem(), holder);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,15 +115,22 @@ public record XeiSieveRecipe(Ingredient ingredient, ItemStack mesh, List<Result>
|
|||
for (var mesh : meshes) {
|
||||
var meshRecipes = meshGrouper.get(mesh);
|
||||
var results = new ArrayList<Result>(meshRecipes.size());
|
||||
var idList = new ArrayList<String>();
|
||||
idList.add(ingredientId);
|
||||
idList.add(BuiltInRegistries.ITEM.getKey(mesh).toString());
|
||||
|
||||
for (var recipe : meshRecipes) {
|
||||
int resultCount = recipe.resultAmount instanceof ConstantValue constant ? Math.round(constant.value()) : 1;
|
||||
results.add(new Result(recipe.result.copyWithCount(resultCount), recipe.resultAmount, recipe.byHandOnly));
|
||||
for (var holder : meshRecipes) {
|
||||
var recipe = holder.value();
|
||||
int resultCount = recipe.resultAmount instanceof ConstantValue(float value) ? Math.round(value) : 1;
|
||||
results.add(new Result(holder, recipe.result.copyWithCount(resultCount), recipe.resultAmount, recipe.byHandOnly));
|
||||
|
||||
idList.add(holder.id().toString());
|
||||
}
|
||||
|
||||
results.sort(resultSorter);
|
||||
var id = ResourceLocation.fromNamespaceAndPath(recipeTypeKey.getNamespace(), recipeTypeKey.getPath() + "/" + hash512(idList));
|
||||
|
||||
var jeiRecipe = new XeiSieveRecipe(ingredient, new ItemStack(mesh), results);
|
||||
results.sort(resultSorter);
|
||||
var jeiRecipe = new XeiSieveRecipe(id, ingredient, new ItemStack(mesh), results);
|
||||
jeiRecipes.add(jeiRecipe);
|
||||
|
||||
var rows = Mth.ceil((float) meshRecipes.size() / 9f);
|
||||
|
|
@ -132,13 +163,39 @@ public record XeiSieveRecipe(Ingredient ingredient, ItemStack mesh, List<Result>
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to hash a collection of strings using 512 bits precision.
|
||||
* The order of the input collection does not matter.
|
||||
* The idea behind this is to hash all recipes that make a recipe group and give the recipe group an ID.
|
||||
* We need to make sure the ID doesn't end up with any collisions, so we just use a cryptographic hash.
|
||||
* It's much more likely that 100 meteors strike ones house at the same time, than that two hashes collide,
|
||||
* so that should suffice for uniqueness...
|
||||
*/
|
||||
private static String hash512(Collection<String> inputs) {
|
||||
try {
|
||||
// make a unique string out of all inputs, regardless of the order they have.
|
||||
// we use a separator which is sure to be unique and never in any input: " ||| "
|
||||
var sortedInputs = inputs.stream().sorted().collect(Collectors.joining(" ||| "));
|
||||
var md = MessageDigest.getInstance("SHA-512");
|
||||
var digest = md.digest(sortedInputs.getBytes(StandardCharsets.UTF_8));
|
||||
// Create a bigint out of the digest and convert it to a hex string
|
||||
var bi = new BigInteger(1, digest);
|
||||
return bi.toString(16);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// This is pretty bad... This shouldn't happen
|
||||
throw new Error("Your java does not support SHA-512. Wat da hell? Report this to ExDeorum", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Result {
|
||||
public final RecipeHolder<? extends SieveRecipe> holder;
|
||||
public final ItemStack item;
|
||||
public final NumberProvider provider;
|
||||
public final boolean byHandOnly;
|
||||
private final double expectedCount;
|
||||
|
||||
Result(ItemStack item, NumberProvider provider, boolean byHandOnly) {
|
||||
Result(RecipeHolder<? extends SieveRecipe> holder, ItemStack item, NumberProvider provider, boolean byHandOnly) {
|
||||
this.holder = holder;
|
||||
this.item = item;
|
||||
this.provider = provider;
|
||||
this.byHandOnly = byHandOnly;
|
||||
|
|
|
|||
|
|
@ -29,11 +29,12 @@ import mezz.jei.api.recipe.category.IRecipeCategory;
|
|||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import thedarkcolour.exdeorum.compat.ClientXeiUtil;
|
||||
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||
import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
|
||||
|
||||
class BarrelCompostCategory implements IRecipeCategory<BarrelCompostRecipe> {
|
||||
class BarrelCompostCategory implements IRecipeCategory<RecipeHolder<BarrelCompostRecipe>> {
|
||||
public static final int WIDTH = 120;
|
||||
public static final int HEIGHT = 18;
|
||||
|
||||
|
|
@ -50,7 +51,7 @@ class BarrelCompostCategory implements IRecipeCategory<BarrelCompostRecipe> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<BarrelCompostRecipe> getRecipeType() {
|
||||
public RecipeType<RecipeHolder<BarrelCompostRecipe>> getRecipeType() {
|
||||
return ExDeorumJeiPlugin.BARREL_COMPOST;
|
||||
}
|
||||
|
||||
|
|
@ -70,15 +71,15 @@ class BarrelCompostCategory implements IRecipeCategory<BarrelCompostRecipe> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(IRecipeLayoutBuilder builder, BarrelCompostRecipe recipe, IFocusGroup focuses) {
|
||||
builder.addSlot(RecipeIngredientRole.INPUT, 1, 1).addIngredients(recipe.ingredient());
|
||||
public void setRecipe(IRecipeLayoutBuilder builder, RecipeHolder<BarrelCompostRecipe> holder, IFocusGroup focuses) {
|
||||
builder.addSlot(RecipeIngredientRole.INPUT, 1, 1).addIngredients(holder.value().ingredient());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(BarrelCompostRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics graphics, double mouseX, double mouseY) {
|
||||
public void draw(RecipeHolder<BarrelCompostRecipe> holder, IRecipeSlotsView recipeSlotsView, GuiGraphics graphics, double mouseX, double mouseY) {
|
||||
this.slot.draw(graphics);
|
||||
|
||||
var volume = recipe.getVolume();
|
||||
var volume = holder.value().getVolume();
|
||||
var volumeLabel = Component.translatable(TranslationKeys.BARREL_COMPOST_RECIPE_VOLUME, volume);
|
||||
|
||||
graphics.drawString(Minecraft.getInstance().font, volumeLabel, 24, 5, 0xff808080, false);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import net.minecraft.client.gui.GuiGraphics;
|
|||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import thedarkcolour.exdeorum.compat.ClientXeiUtil;
|
||||
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||
import thedarkcolour.exdeorum.material.DefaultMaterials;
|
||||
|
|
@ -81,25 +82,26 @@ public abstract class BarrelMixingCategory<T> implements IRecipeCategory<T> {
|
|||
this.slot.draw(graphics, 78, 0);
|
||||
}
|
||||
|
||||
public static class Items extends BarrelMixingCategory<BarrelMixingRecipe> {
|
||||
public static class Items extends BarrelMixingCategory<RecipeHolder<BarrelMixingRecipe>> {
|
||||
public Items(IGuiHelper helper, IDrawable plus, IDrawable arrow) {
|
||||
super(helper, plus, arrow, TranslationKeys.BARREL_MIXING_CATEGORY_TITLE, DefaultMaterials.OAK_BARREL.getItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(IRecipeLayoutBuilder builder, BarrelMixingRecipe recipe, IFocusGroup focuses) {
|
||||
public void setRecipe(IRecipeLayoutBuilder builder, RecipeHolder<BarrelMixingRecipe> holder, IFocusGroup focuses) {
|
||||
var recipe = holder.value();
|
||||
JeiUtil.addFluidIngredient(builder.addSlot(RecipeIngredientRole.INPUT, 1, 1), recipe.fluid).setFluidRenderer(1000, false, 16, 16);
|
||||
builder.addSlot(RecipeIngredientRole.INPUT, 33, 1).addIngredients(recipe.ingredient());
|
||||
builder.addSlot(RecipeIngredientRole.OUTPUT, 79, 1).addItemStack(recipe.result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<BarrelMixingRecipe> getRecipeType() {
|
||||
public RecipeType<RecipeHolder<BarrelMixingRecipe>> getRecipeType() {
|
||||
return ExDeorumJeiPlugin.BARREL_MIXING;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Fluids extends BarrelMixingCategory<BarrelFluidMixingRecipe> {
|
||||
public static class Fluids extends BarrelMixingCategory<RecipeHolder<BarrelFluidMixingRecipe>> {
|
||||
private static final Component CONTENTS_ARE_CONSUMED_TOOLTIP = Component.translatable(TranslationKeys.BARREL_FLUID_MIXING_CONTENTS_ARE_CONSUMED).withStyle(ChatFormatting.RED);
|
||||
|
||||
public Fluids(IGuiHelper helper, IDrawable plus, IDrawable arrow) {
|
||||
|
|
@ -107,7 +109,8 @@ public abstract class BarrelMixingCategory<T> implements IRecipeCategory<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(IRecipeLayoutBuilder builder, BarrelFluidMixingRecipe recipe, IFocusGroup focuses) {
|
||||
public void setRecipe(IRecipeLayoutBuilder builder, RecipeHolder<BarrelFluidMixingRecipe> holder, IFocusGroup focuses) {
|
||||
var recipe = holder.value();
|
||||
JeiUtil.addFluidIngredient(builder.addSlot(RecipeIngredientRole.INPUT, 1, 1), recipe.baseFluid())
|
||||
.setFluidRenderer(1000, false, 16, 16);
|
||||
var additiveSlot = JeiUtil.addFluidIngredient(builder.addSlot(RecipeIngredientRole.INPUT, 33, 1), recipe.additiveFluid(), 1000)
|
||||
|
|
@ -119,15 +122,15 @@ public abstract class BarrelMixingCategory<T> implements IRecipeCategory<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<BarrelFluidMixingRecipe> getRecipeType() {
|
||||
public RecipeType<RecipeHolder<BarrelFluidMixingRecipe>> getRecipeType() {
|
||||
return ExDeorumJeiPlugin.BARREL_FLUID_MIXING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(BarrelFluidMixingRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics graphics, double mouseX, double mouseY) {
|
||||
super.draw(recipe, recipeSlotsView, graphics, mouseX, mouseY);
|
||||
public void draw(RecipeHolder<BarrelFluidMixingRecipe> holder, IRecipeSlotsView recipeSlotsView, GuiGraphics graphics, double mouseX, double mouseY) {
|
||||
super.draw(holder, recipeSlotsView, graphics, mouseX, mouseY);
|
||||
|
||||
if (recipe.consumesAdditive()) {
|
||||
if (holder.value().consumesAdditive()) {
|
||||
ClientXeiUtil.renderAsterisk(graphics, 18 + 3 + 3 + 8, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package thedarkcolour.exdeorum.compat.jei;
|
||||
|
||||
import mezz.jei.api.helpers.IGuiHelper;
|
||||
import mezz.jei.api.helpers.IJeiHelpers;
|
||||
import mezz.jei.api.recipe.RecipeType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import thedarkcolour.exdeorum.compat.XeiSieveRecipe;
|
||||
|
|
@ -8,8 +8,8 @@ import thedarkcolour.exdeorum.data.TranslationKeys;
|
|||
import thedarkcolour.exdeorum.material.DefaultMaterials;
|
||||
|
||||
class CompressedSieveCategory extends SieveCategory {
|
||||
CompressedSieveCategory(IGuiHelper helper) {
|
||||
super(helper, DefaultMaterials.OAK_COMPRESSED_SIEVE, Component.translatable(TranslationKeys.COMPRESSED_SIEVE_CATEGORY_TITLE), XeiSieveRecipe.COMPRESSED_SIEVE_ROWS);
|
||||
CompressedSieveCategory(IJeiHelpers jeiHelpers) {
|
||||
super(jeiHelpers, DefaultMaterials.OAK_COMPRESSED_SIEVE, Component.translatable(TranslationKeys.COMPRESSED_SIEVE_CATEGORY_TITLE), XeiSieveRecipe.COMPRESSED_SIEVE_ROWS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -36,8 +36,10 @@ import net.minecraft.ChatFormatting;
|
|||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import thedarkcolour.exdeorum.compat.ClientXeiUtil;
|
||||
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||
import thedarkcolour.exdeorum.registry.EItems;
|
||||
|
|
@ -98,6 +100,11 @@ public class CrookCategory implements IRecipeCategory<CrookJeiRecipe> {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ResourceLocation getRegistryName(CrookJeiRecipe recipe) {
|
||||
return recipe.identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(CrookJeiRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics graphics, double mouseX, double mouseY) {
|
||||
this.timer.onDraw();
|
||||
|
|
|
|||
|
|
@ -23,9 +23,11 @@ import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
|
|||
import mezz.jei.api.recipe.RecipeIngredientRole;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
|
|
@ -39,11 +41,13 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
|
||||
public sealed abstract class CrookJeiRecipe {
|
||||
public final ResourceLocation identifier;
|
||||
public final List<BlockState> states;
|
||||
public ItemStack result;
|
||||
public float chance;
|
||||
|
||||
public CrookJeiRecipe(List<BlockState> states, ItemStack result, float chance) {
|
||||
public CrookJeiRecipe(ResourceLocation identifier, List<BlockState> states, ItemStack result, float chance) {
|
||||
this.identifier = identifier;
|
||||
this.states = states;
|
||||
this.result = result;
|
||||
this.chance = chance;
|
||||
|
|
@ -51,13 +55,15 @@ public sealed abstract class CrookJeiRecipe {
|
|||
|
||||
public abstract void addIngredients(IRecipeLayoutBuilder builder);
|
||||
|
||||
static CrookJeiRecipe create(CrookRecipe recipe) {
|
||||
static CrookJeiRecipe create(RecipeHolder<CrookRecipe> recipeHolder) {
|
||||
var recipe = recipeHolder.value();
|
||||
var id = recipeHolder.id();
|
||||
switch (recipe.blockPredicate()) {
|
||||
case BlockPredicate.BlockStatePredicate state -> {
|
||||
return new StatesRecipe(state, state.possibleStates().filter(blockState -> !blockState.hasProperty(BlockStateProperties.WATERLOGGED) || !blockState.getValue(BlockStateProperties.WATERLOGGED)).toList(), recipe.result(), recipe.chance());
|
||||
return new StatesRecipe(id, state, state.possibleStates().filter(blockState -> !blockState.hasProperty(BlockStateProperties.WATERLOGGED) || !blockState.getValue(BlockStateProperties.WATERLOGGED)).toList(), recipe.result(), recipe.chance());
|
||||
}
|
||||
case BlockPredicate.SingleBlockPredicate block -> {
|
||||
return new BlockRecipe(block.block(), recipe.result(), recipe.chance());
|
||||
return new BlockRecipe(id, block.block(), recipe.result(), recipe.chance());
|
||||
}
|
||||
case BlockPredicate.TagPredicate tag -> {
|
||||
var list = new ArrayList<BlockState>();
|
||||
|
|
@ -68,7 +74,7 @@ public sealed abstract class CrookJeiRecipe {
|
|||
}
|
||||
}
|
||||
|
||||
return new TagRecipe(tag.tag(), List.copyOf(list), recipe.result(), recipe.chance());
|
||||
return new TagRecipe(id, tag.tag(), List.copyOf(list), recipe.result(), recipe.chance());
|
||||
}
|
||||
default -> throw new IllegalArgumentException("Invalid crook recipe?? -> " + recipe);
|
||||
}
|
||||
|
|
@ -78,8 +84,8 @@ public sealed abstract class CrookJeiRecipe {
|
|||
private final List<ItemStack> itemIngredients;
|
||||
public final List<Component> requirements;
|
||||
|
||||
StatesRecipe(@Nullable BlockPredicate.BlockStatePredicate predicate, List<BlockState> states, ItemStack result, float chance) {
|
||||
super(states, result, chance);
|
||||
StatesRecipe(ResourceLocation identifier, @Nullable BlockPredicate.BlockStatePredicate predicate, List<BlockState> states, ItemStack result, float chance) {
|
||||
super(identifier, states, result, chance);
|
||||
ImmutableList.Builder<ItemStack> itemIngredients = ImmutableList.builder();
|
||||
|
||||
var blocks = new HashSet<Block>();
|
||||
|
|
@ -112,8 +118,8 @@ public sealed abstract class CrookJeiRecipe {
|
|||
static final class TagRecipe extends StatesRecipe {
|
||||
public final TagKey<Block> tag;
|
||||
|
||||
public TagRecipe(TagKey<Block> tag, List<BlockState> states, ItemStack result, float chance) {
|
||||
super(null, states, result, chance);
|
||||
public TagRecipe(ResourceLocation identifier, TagKey<Block> tag, List<BlockState> states, ItemStack result, float chance) {
|
||||
super(identifier, null, states, result, chance);
|
||||
this.tag = tag;
|
||||
}
|
||||
}
|
||||
|
|
@ -121,8 +127,8 @@ public sealed abstract class CrookJeiRecipe {
|
|||
static final class BlockRecipe extends CrookJeiRecipe {
|
||||
private final ItemStack itemIngredient;
|
||||
|
||||
BlockRecipe(Block block, ItemStack result, float chance) {
|
||||
super(ImmutableList.of(block.defaultBlockState()), result, chance);
|
||||
BlockRecipe(ResourceLocation identifier, Block block, ItemStack result, float chance) {
|
||||
super(identifier, ImmutableList.of(block.defaultBlockState()), result, chance);
|
||||
|
||||
var item = block.asItem();
|
||||
if (item == Items.AIR) {
|
||||
|
|
|
|||
|
|
@ -25,44 +25,47 @@ import mezz.jei.api.recipe.RecipeType;
|
|||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||
import thedarkcolour.exdeorum.material.DefaultMaterials;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
|
||||
|
||||
abstract class CrucibleCategory extends OneToOneCategory<CrucibleRecipe> {
|
||||
abstract class CrucibleCategory<T extends CrucibleRecipe> extends OneToOneCategory<RecipeHolder<T>> {
|
||||
public CrucibleCategory(IGuiHelper helper, IDrawable arrow, Item iconItem, String titleKey) {
|
||||
super(helper, arrow, helper.createDrawableItemStack(new ItemStack(iconItem)), Component.translatable(titleKey));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addInput(IRecipeSlotBuilder slot, CrucibleRecipe recipe) {
|
||||
protected void addInput(IRecipeSlotBuilder slot, RecipeHolder<T> holder) {
|
||||
var recipe = holder.value();
|
||||
slot.addIngredients(recipe.ingredient());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addOutput(IRecipeSlotBuilder slot, CrucibleRecipe recipe) {
|
||||
protected void addOutput(IRecipeSlotBuilder slot, RecipeHolder<T> holder) {
|
||||
var recipe = holder.value();
|
||||
slot.addFluidStack(recipe.getResult().getFluid(), recipe.getResult().getAmount())
|
||||
.setFluidRenderer(Math.max(1000, recipe.getResult().getAmount()), false, 16, 16);
|
||||
}
|
||||
|
||||
static class LavaCrucible extends CrucibleCategory {
|
||||
static class LavaCrucible extends CrucibleCategory<CrucibleRecipe.Lava> {
|
||||
public LavaCrucible(IGuiHelper helper, IDrawable arrow) {
|
||||
super(helper, arrow, DefaultMaterials.PORCELAIN_CRUCIBLE.getItem(), TranslationKeys.LAVA_CRUCIBLE_CATEGORY_TITLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<CrucibleRecipe> getRecipeType() {
|
||||
public RecipeType<RecipeHolder<CrucibleRecipe.Lava>> getRecipeType() {
|
||||
return ExDeorumJeiPlugin.LAVA_CRUCIBLE;
|
||||
}
|
||||
}
|
||||
|
||||
static class WaterCrucible extends CrucibleCategory {
|
||||
static class WaterCrucible extends CrucibleCategory<CrucibleRecipe.Water> {
|
||||
public WaterCrucible(IGuiHelper helper, IDrawable arrow) {
|
||||
super(helper, arrow, DefaultMaterials.OAK_CRUCIBLE.getItem(), TranslationKeys.WATER_CRUCIBLE_CATEGORY_TITLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<CrucibleRecipe> getRecipeType() {
|
||||
public RecipeType<RecipeHolder<CrucibleRecipe.Water>> getRecipeType() {
|
||||
return ExDeorumJeiPlugin.WATER_CRUCIBLE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,11 +19,13 @@
|
|||
package thedarkcolour.exdeorum.compat.jei;
|
||||
|
||||
import mezz.jei.api.ingredients.IIngredientType;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe;
|
||||
|
||||
final class CrucibleHeatSourceRecipe {
|
||||
private final int meltRate;
|
||||
private final RecipeHolder<CrucibleHeatRecipe> recipeHolder;
|
||||
private final BlockState blockState;
|
||||
@Nullable
|
||||
private final IIngredientType<Object> ingredientType;
|
||||
|
|
@ -31,15 +33,19 @@ final class CrucibleHeatSourceRecipe {
|
|||
private final Object ingredient;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
CrucibleHeatSourceRecipe(int meltRate, BlockState blockState, @Nullable IIngredientType ingredientType, @Nullable Object ingredient) {
|
||||
this.meltRate = meltRate;
|
||||
CrucibleHeatSourceRecipe(RecipeHolder<CrucibleHeatRecipe> recipeHolder, BlockState blockState, @Nullable IIngredientType ingredientType, @Nullable Object ingredient) {
|
||||
this.recipeHolder = recipeHolder;
|
||||
this.blockState = blockState;
|
||||
this.ingredientType = ingredientType;
|
||||
this.ingredient = ingredient;
|
||||
}
|
||||
|
||||
public RecipeHolder<CrucibleHeatRecipe> recipeHolder() {
|
||||
return this.recipeHolder;
|
||||
}
|
||||
|
||||
public int meltRate() {
|
||||
return this.meltRate;
|
||||
return this.recipeHolder.value().heatValue();
|
||||
}
|
||||
|
||||
public BlockState blockState() {
|
||||
|
|
|
|||
|
|
@ -35,8 +35,10 @@ import net.minecraft.client.Minecraft;
|
|||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import thedarkcolour.exdeorum.compat.ClientXeiUtil;
|
||||
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||
import thedarkcolour.exdeorum.material.DefaultMaterials;
|
||||
|
|
@ -106,6 +108,11 @@ class CrucibleHeatSourcesCategory implements IRecipeCategory<CrucibleHeatSourceR
|
|||
ClientXeiUtil.renderBlock(graphics, recipe.blockState(), 60, 24, 10, 20F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ResourceLocation getRegistryName(CrucibleHeatSourceRecipe recipe) {
|
||||
return recipe.recipeHolder().id();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Component> getTooltipStrings(CrucibleHeatSourceRecipe recipe, IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) {
|
||||
if (44.0 < mouseX && mouseX < 76.0 && 16 < mouseY && mouseY < 48) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
package thedarkcolour.exdeorum.compat.jei;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import mezz.jei.api.IModPlugin;
|
||||
import mezz.jei.api.JeiPlugin;
|
||||
import mezz.jei.api.constants.VanillaTypes;
|
||||
|
|
@ -37,6 +36,7 @@ import net.minecraft.resources.ResourceLocation;
|
|||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeInput;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
|
|
@ -44,7 +44,6 @@ import net.minecraft.world.level.block.LiquidBlock;
|
|||
import net.minecraft.world.level.block.WallTorchBlock;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.neoforge.fluids.FluidStack;
|
||||
import net.neoforged.neoforge.registries.DeferredHolder;
|
||||
import thedarkcolour.exdeorum.ExDeorum;
|
||||
import thedarkcolour.exdeorum.client.ClientsideCode;
|
||||
import thedarkcolour.exdeorum.client.screen.MechanicalHammerScreen;
|
||||
|
|
@ -58,6 +57,7 @@ import thedarkcolour.exdeorum.recipe.RecipeUtil;
|
|||
import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.hammer.CompressedHammerRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
|
||||
|
|
@ -68,6 +68,7 @@ import thedarkcolour.exdeorum.tag.EItemTags;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
|
@ -76,18 +77,23 @@ import java.util.function.Supplier;
|
|||
public class ExDeorumJeiPlugin implements IModPlugin {
|
||||
public static final ResourceLocation EX_DEORUM_JEI_TEXTURE = ExDeorum.loc("textures/gui/jei/enr_jei.png");
|
||||
|
||||
static final RecipeType<BarrelCompostRecipe> BARREL_COMPOST = recipeType("barrel_compost", BarrelCompostRecipe.class);
|
||||
static final RecipeType<BarrelMixingRecipe> BARREL_MIXING = recipeType("barrel_mixing", BarrelMixingRecipe.class);
|
||||
static final RecipeType<BarrelFluidMixingRecipe> BARREL_FLUID_MIXING = recipeType("barrel_fluid_mixing", BarrelFluidMixingRecipe.class);
|
||||
static final RecipeType<CrucibleRecipe> LAVA_CRUCIBLE = recipeType("lava_crucible", CrucibleRecipe.class);
|
||||
static final RecipeType<CrucibleRecipe> WATER_CRUCIBLE = recipeType("water_crucible", CrucibleRecipe.class);
|
||||
static final RecipeType<RecipeHolder<BarrelCompostRecipe>> BARREL_COMPOST = recipeType("barrel_compost");
|
||||
static final RecipeType<RecipeHolder<BarrelMixingRecipe>> BARREL_MIXING = recipeType("barrel_mixing");
|
||||
static final RecipeType<RecipeHolder<BarrelFluidMixingRecipe>> BARREL_FLUID_MIXING = recipeType("barrel_fluid_mixing");
|
||||
static final RecipeType<RecipeHolder<CrucibleRecipe.Lava>> LAVA_CRUCIBLE = recipeType("lava_crucible");
|
||||
static final RecipeType<RecipeHolder<CrucibleRecipe.Water>> WATER_CRUCIBLE = recipeType("water_crucible");
|
||||
static final RecipeType<CrucibleHeatSourceRecipe> CRUCIBLE_HEAT_SOURCES = recipeType("crucible_heat_sources", CrucibleHeatSourceRecipe.class);
|
||||
static final RecipeType<XeiSieveRecipe> SIEVE = recipeType("sieve", XeiSieveRecipe.class);
|
||||
static final RecipeType<XeiSieveRecipe> COMPRESSED_SIEVE = recipeType("compressed_sieve", XeiSieveRecipe.class);
|
||||
static final RecipeType<HammerRecipe> HAMMER = recipeType("hammer", HammerRecipe.class);
|
||||
static final RecipeType<HammerRecipe> COMPRESSED_HAMMER = recipeType("compressed_hammer", CompressedHammerRecipe.class);
|
||||
static final RecipeType<RecipeHolder<HammerRecipe>> HAMMER = recipeType("hammer");
|
||||
static final RecipeType<RecipeHolder<CompressedHammerRecipe>> COMPRESSED_HAMMER = recipeType("compressed_hammer");
|
||||
static final RecipeType<CrookJeiRecipe> CROOK = recipeType("crook", CrookJeiRecipe.class);
|
||||
|
||||
private static <T extends Recipe<?>> RecipeType<RecipeHolder<T>> recipeType(String path) {
|
||||
String namespace = ModList.get().isLoaded(ModIds.EMI) ? ExDeorum.ID + "_" + ModIds.EMI : ExDeorum.ID;
|
||||
return RecipeType.createRecipeHolderType(ResourceLocation.fromNamespaceAndPath(namespace, path));
|
||||
}
|
||||
|
||||
private static <T> RecipeType<T> recipeType(String path, Class<? extends T> type) {
|
||||
// use alternative namespace so that EMI doesn't skip JEI compatibility
|
||||
String namespace = ModList.get().isLoaded(ModIds.EMI) ? ExDeorum.ID + "_" + ModIds.EMI : ExDeorum.ID;
|
||||
|
|
@ -111,10 +117,10 @@ public class ExDeorumJeiPlugin implements IModPlugin {
|
|||
registration.addRecipeCategories(new CrucibleCategory.LavaCrucible(helper, arrow));
|
||||
registration.addRecipeCategories(new CrucibleCategory.WaterCrucible(helper, arrow));
|
||||
registration.addRecipeCategories(new CrucibleHeatSourcesCategory(registration.getJeiHelpers()));
|
||||
registration.addRecipeCategories(new SieveCategory(helper));
|
||||
registration.addRecipeCategories(new CompressedSieveCategory(helper));
|
||||
registration.addRecipeCategories(new HammerCategory(helper, arrow, EItems.DIAMOND_HAMMER, Component.translatable(TranslationKeys.HAMMER_CATEGORY_TITLE), HAMMER));
|
||||
registration.addRecipeCategories(new HammerCategory(helper, arrow, EItems.COMPRESSED_DIAMOND_HAMMER, Component.translatable(TranslationKeys.COMPRESSED_HAMMER_CATEGORY_TITLE), COMPRESSED_HAMMER));
|
||||
registration.addRecipeCategories(new SieveCategory(registration.getJeiHelpers()));
|
||||
registration.addRecipeCategories(new CompressedSieveCategory(registration.getJeiHelpers()));
|
||||
registration.addRecipeCategories(new HammerCategory<>(helper, arrow, EItems.DIAMOND_HAMMER, Component.translatable(TranslationKeys.HAMMER_CATEGORY_TITLE), HAMMER));
|
||||
registration.addRecipeCategories(new HammerCategory<>(helper, arrow, EItems.COMPRESSED_DIAMOND_HAMMER, Component.translatable(TranslationKeys.COMPRESSED_HAMMER_CATEGORY_TITLE), COMPRESSED_HAMMER));
|
||||
registration.addRecipeCategories(new CrookCategory(registration.getJeiHelpers(), arrow));
|
||||
}
|
||||
|
||||
|
|
@ -214,8 +220,7 @@ public class ExDeorumJeiPlugin implements IModPlugin {
|
|||
addRecipes(registration, LAVA_CRUCIBLE, ERecipeTypes.LAVA_CRUCIBLE);
|
||||
addRecipes(registration, WATER_CRUCIBLE, ERecipeTypes.WATER_CRUCIBLE);
|
||||
addRecipes(registration, HAMMER, ERecipeTypes.HAMMER);
|
||||
//noinspection rawtypes,unchecked
|
||||
addRecipes(registration, COMPRESSED_HAMMER, ((DeferredHolder) ERecipeTypes.COMPRESSED_HAMMER));
|
||||
addRecipes(registration, COMPRESSED_HAMMER, ERecipeTypes.COMPRESSED_HAMMER);
|
||||
registration.addRecipes(CROOK, CompatUtil.collectAllRecipes(RecipeUtil.getClientRecipeManager(), ERecipeTypes.CROOK.get(), CrookJeiRecipe::create));
|
||||
registration.addRecipes(SIEVE, XeiSieveRecipe.getAllRecipesGrouped(ERecipeTypes.SIEVE.get(), XeiSieveRecipe.SIEVE_ROWS));
|
||||
registration.addRecipes(COMPRESSED_SIEVE, XeiSieveRecipe.getAllRecipesGrouped(ERecipeTypes.COMPRESSED_SIEVE.get(), XeiSieveRecipe.COMPRESSED_SIEVE_ROWS));
|
||||
|
|
@ -224,7 +229,7 @@ public class ExDeorumJeiPlugin implements IModPlugin {
|
|||
}
|
||||
|
||||
private static void addCrucibleHeatSources(IRecipeRegistration registration) {
|
||||
var values = new Object2IntOpenHashMap<Block>();
|
||||
var values = new HashMap<Block, RecipeHolder<CrucibleHeatRecipe>>();
|
||||
for (var entry : ClientsideCode.getRecipeCaches().getHeatSources()) {
|
||||
var state = entry.getKey();
|
||||
var block = state.getBlock();
|
||||
|
|
@ -232,14 +237,19 @@ public class ExDeorumJeiPlugin implements IModPlugin {
|
|||
if (block instanceof WallTorchBlock) continue;
|
||||
|
||||
if (block != Blocks.AIR) {
|
||||
final int newValue = entry.getIntValue();
|
||||
final int newValue = entry.getValue().value().heatValue();
|
||||
if (newValue == 0) {
|
||||
// we don't want to display useless heat sources
|
||||
// why would people even create these?
|
||||
continue;
|
||||
}
|
||||
|
||||
values.computeInt(block, (key, value) -> {
|
||||
if (value != null) {
|
||||
return Math.max(value, newValue);
|
||||
} else {
|
||||
return newValue == 0 ? null : newValue;
|
||||
values.compute(block, (key, value) -> {
|
||||
if (value != null && value.value().heatValue() > newValue) {
|
||||
// Existing entry is a better heat source
|
||||
return value;
|
||||
}
|
||||
return entry.getValue();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -247,16 +257,17 @@ public class ExDeorumJeiPlugin implements IModPlugin {
|
|||
var fluidIngredientType = fluidHelper.getFluidIngredientType();
|
||||
var recipes = new ArrayList<CrucibleHeatSourceRecipe>();
|
||||
|
||||
for (var entry : values.object2IntEntrySet()) {
|
||||
for (var entry : values.entrySet()) {
|
||||
var holder = entry.getValue();
|
||||
if (entry.getKey() instanceof LiquidBlock liquid) {
|
||||
recipes.add(new CrucibleHeatSourceRecipe(entry.getIntValue(), entry.getKey().defaultBlockState(), fluidIngredientType, fluidHelper.create(Holder.direct(liquid.fluid), 1000)));
|
||||
recipes.add(new CrucibleHeatSourceRecipe(holder, entry.getKey().defaultBlockState(), fluidIngredientType, fluidHelper.create(Holder.direct(liquid.fluid), 1000)));
|
||||
} else {
|
||||
var itemForm = entry.getKey().asItem();
|
||||
|
||||
if (itemForm != Items.AIR) {
|
||||
recipes.add(new CrucibleHeatSourceRecipe(entry.getIntValue(), entry.getKey().defaultBlockState(), VanillaTypes.ITEM_STACK, new ItemStack(itemForm)));
|
||||
recipes.add(new CrucibleHeatSourceRecipe(holder, entry.getKey().defaultBlockState(), VanillaTypes.ITEM_STACK, new ItemStack(itemForm)));
|
||||
} else {
|
||||
recipes.add(new CrucibleHeatSourceRecipe(entry.getIntValue(), entry.getKey().defaultBlockState(), null, null));
|
||||
recipes.add(new CrucibleHeatSourceRecipe(holder, entry.getKey().defaultBlockState(), null, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -300,7 +311,7 @@ public class ExDeorumJeiPlugin implements IModPlugin {
|
|||
});
|
||||
}
|
||||
|
||||
private static <C extends RecipeInput, T extends Recipe<C>> void addRecipes(IRecipeRegistration registration, RecipeType<T> category, Supplier<net.minecraft.world.item.crafting.RecipeType<T>> type) {
|
||||
private static <C extends RecipeInput, T extends Recipe<C>> void addRecipes(IRecipeRegistration registration, RecipeType<RecipeHolder<T>> category, Supplier<net.minecraft.world.item.crafting.RecipeType<T>> type) {
|
||||
registration.addRecipes(category, CompatUtil.collectAllRecipes(RecipeUtil.getClientRecipeManager(), type.get(), Function.identity()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,34 +23,38 @@ import mezz.jei.api.gui.drawable.IDrawable;
|
|||
import mezz.jei.api.helpers.IGuiHelper;
|
||||
import mezz.jei.api.recipe.RecipeType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class HammerCategory extends OneToOneCategory<HammerRecipe> {
|
||||
private final RecipeType<HammerRecipe> recipeType;
|
||||
class HammerCategory<R extends HammerRecipe> extends OneToOneCategory<RecipeHolder<R>> {
|
||||
private final RecipeType<RecipeHolder<R>> recipeType;
|
||||
|
||||
public HammerCategory(IGuiHelper helper, IDrawable arrow, Supplier<? extends Item> icon, Component title, RecipeType<HammerRecipe> recipeType) {
|
||||
public HammerCategory(IGuiHelper helper, IDrawable arrow, Supplier<? extends Item> icon, Component title, RecipeType<RecipeHolder<R>> recipeType) {
|
||||
super(helper, arrow, helper.createDrawableItemStack(new ItemStack(icon.get())), title);
|
||||
|
||||
this.recipeType = recipeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeType<HammerRecipe> getRecipeType() {
|
||||
public RecipeType<RecipeHolder<R>> getRecipeType() {
|
||||
return this.recipeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addInput(IRecipeSlotBuilder slot, HammerRecipe recipe) {
|
||||
slot.addIngredients(recipe.ingredient());
|
||||
protected void addInput(IRecipeSlotBuilder slot, RecipeHolder<R> holder) {
|
||||
slot.addIngredients(holder.value().ingredient());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addOutput(IRecipeSlotBuilder slot, HammerRecipe recipe) {
|
||||
protected void addOutput(IRecipeSlotBuilder slot, RecipeHolder<R> holder) {
|
||||
var recipe = holder.value();
|
||||
if (recipe.resultAmount instanceof ConstantValue constant) {
|
||||
slot.addItemStack(recipe.result.getCount() == 1 ? recipe.result : recipe.result.copyWithCount((int) constant.value()));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -21,32 +21,59 @@ package thedarkcolour.exdeorum.compat.jei;
|
|||
import mezz.jei.api.constants.VanillaTypes;
|
||||
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
|
||||
import mezz.jei.api.gui.builder.IRecipeSlotBuilder;
|
||||
import mezz.jei.api.gui.builder.ITooltipBuilder;
|
||||
import mezz.jei.api.gui.drawable.IDrawable;
|
||||
import mezz.jei.api.gui.ingredient.IRecipeSlotRichTooltipCallback;
|
||||
import mezz.jei.api.gui.ingredient.IRecipeSlotView;
|
||||
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
|
||||
import mezz.jei.api.helpers.IGuiHelper;
|
||||
import mezz.jei.api.helpers.IJeiHelpers;
|
||||
import mezz.jei.api.helpers.IModIdHelper;
|
||||
import mezz.jei.api.ingredients.IIngredientHelper;
|
||||
import mezz.jei.api.ingredients.IIngredientType;
|
||||
import mezz.jei.api.ingredients.ITypedIngredient;
|
||||
import mezz.jei.api.recipe.IFocusGroup;
|
||||
import mezz.jei.api.recipe.RecipeIngredientRole;
|
||||
import mezz.jei.api.recipe.RecipeType;
|
||||
import mezz.jei.api.recipe.category.IRecipeCategory;
|
||||
import mezz.jei.api.runtime.IIngredientManager;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import thedarkcolour.exdeorum.compat.XeiSieveRecipe;
|
||||
import thedarkcolour.exdeorum.compat.XeiUtil;
|
||||
import thedarkcolour.exdeorum.data.TranslationKeys;
|
||||
import thedarkcolour.exdeorum.material.DefaultMaterials;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
class SieveCategory implements IRecipeCategory<XeiSieveRecipe> {
|
||||
private final IJeiHelpers jeiHelpers;
|
||||
private final IDrawable slot;
|
||||
private final IDrawable row;
|
||||
private final IDrawable icon;
|
||||
private final Component title;
|
||||
private final MutableInt rows;
|
||||
|
||||
SieveCategory(IGuiHelper helper, ItemLike icon, Component title, MutableInt rows) {
|
||||
/**
|
||||
* settingSlots is a workaround to prevent JEI from adding recipe tooltips with our generated recipe IDs.
|
||||
* They look ugly and clutter the screen, since they're pretty long.
|
||||
*/
|
||||
private boolean settingSlots = false;
|
||||
|
||||
SieveCategory(IJeiHelpers jeiHelpers, ItemLike icon, Component title, MutableInt rows) {
|
||||
this.jeiHelpers = jeiHelpers;
|
||||
var helper = jeiHelpers.getGuiHelper();
|
||||
this.slot = helper.getSlotDrawable();
|
||||
this.row = helper.createDrawable(ExDeorumJeiPlugin.EX_DEORUM_JEI_TEXTURE, 0, 0, 162, 18);
|
||||
this.icon = helper.createDrawableItemStack(new ItemStack(icon));
|
||||
|
|
@ -54,8 +81,8 @@ class SieveCategory implements IRecipeCategory<XeiSieveRecipe> {
|
|||
this.rows = rows;
|
||||
}
|
||||
|
||||
SieveCategory(IGuiHelper helper) {
|
||||
this(helper, DefaultMaterials.OAK_SIEVE, Component.translatable(TranslationKeys.SIEVE_CATEGORY_TITLE), XeiSieveRecipe.SIEVE_ROWS);
|
||||
SieveCategory(IJeiHelpers jeiHelpers) {
|
||||
this(jeiHelpers, DefaultMaterials.OAK_SIEVE, Component.translatable(TranslationKeys.SIEVE_CATEGORY_TITLE), XeiSieveRecipe.SIEVE_ROWS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -83,17 +110,26 @@ class SieveCategory implements IRecipeCategory<XeiSieveRecipe> {
|
|||
return this.icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ResourceLocation getRegistryName(XeiSieveRecipe recipe) {
|
||||
return settingSlots ? null : recipe.id();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(IRecipeLayoutBuilder builder, XeiSieveRecipe recipe, IFocusGroup focuses) {
|
||||
builder.addSlot(RecipeIngredientRole.INPUT, 59, 1).addIngredients(recipe.ingredient());
|
||||
builder.addSlot(RecipeIngredientRole.CATALYST, 87, 1).addItemStack(recipe.mesh());
|
||||
|
||||
settingSlots = true;
|
||||
for (int i = 0; i < recipe.results().size(); i++) {
|
||||
var result = recipe.results().get(i);
|
||||
var slot = builder.addSlot(RecipeIngredientRole.OUTPUT, 1 + (i % 9) * 18, 1 + XeiUtil.SIEVE_ROW_START + 18 * (i / 9)).addItemStack(result.item);
|
||||
|
||||
// Since we group recipes, we need to manually add the recipe ID tooltip for the given output item.
|
||||
slot.addRichTooltipCallback(new OutputSlotTooltipCallback(result.holder.id(), getRecipeType()));
|
||||
addTooltips(slot, result.byHandOnly, result.provider);
|
||||
}
|
||||
settingSlots = false;
|
||||
}
|
||||
|
||||
public static void addTooltips(IRecipeSlotBuilder slot, boolean byHandOnly, NumberProvider provider) {
|
||||
|
|
@ -116,4 +152,77 @@ class SieveCategory implements IRecipeCategory<XeiSieveRecipe> {
|
|||
this.row.draw(graphics, 0, 28 + i * 18);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copied almost 1:1 from class of same name in JEI. Since this is a JEI implementation detail, it's not exposed in the API.
|
||||
* Modified minimally to not use any of the other internals and compile.
|
||||
*/
|
||||
public class OutputSlotTooltipCallback implements IRecipeSlotRichTooltipCallback {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
private final ResourceLocation recipeName;
|
||||
private final boolean recipeFromSameModAsCategory;
|
||||
|
||||
public OutputSlotTooltipCallback(ResourceLocation recipeName, RecipeType<?> recipeType) {
|
||||
this.recipeName = recipeName;
|
||||
this.recipeFromSameModAsCategory = recipeName.getNamespace().equals(recipeType.getUid().getNamespace());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRichTooltip(IRecipeSlotView recipeSlotView, ITooltipBuilder tooltip) {
|
||||
if (recipeSlotView.getRole() != RecipeIngredientRole.OUTPUT) {
|
||||
return;
|
||||
}
|
||||
Optional<ITypedIngredient<?>> displayedIngredient = recipeSlotView.getDisplayedIngredient();
|
||||
if (displayedIngredient.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
addRecipeBy(tooltip, displayedIngredient.get());
|
||||
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
boolean showAdvanced = minecraft.options.advancedItemTooltips || Screen.hasShiftDown();
|
||||
if (showAdvanced) {
|
||||
MutableComponent recipeId = Component.translatable("jei.tooltip.recipe.id", Component.literal(recipeName.toString()));
|
||||
tooltip.add(recipeId.withStyle(ChatFormatting.DARK_GRAY));
|
||||
}
|
||||
}
|
||||
|
||||
private void addRecipeBy(ITooltipBuilder tooltip, ITypedIngredient<?> displayedIngredient) {
|
||||
if (recipeFromSameModAsCategory) {
|
||||
return;
|
||||
}
|
||||
IModIdHelper modIdHelper = jeiHelpers.getModIdHelper();
|
||||
if (!modIdHelper.isDisplayingModNameEnabled()) {
|
||||
return;
|
||||
}
|
||||
String ingredientModId = getDisplayModId(displayedIngredient);
|
||||
if (ingredientModId == null) {
|
||||
return;
|
||||
}
|
||||
String recipeModId = recipeName.getNamespace();
|
||||
if (recipeModId.equals(ingredientModId)) {
|
||||
return;
|
||||
}
|
||||
String modName = modIdHelper.getFormattedModNameForModId(recipeModId);
|
||||
MutableComponent recipeBy = Component.translatable("jei.tooltip.recipe.by", modName);
|
||||
tooltip.add(recipeBy.withStyle(ChatFormatting.GRAY));
|
||||
}
|
||||
|
||||
private <T> @Nullable String getDisplayModId(ITypedIngredient<T> typedIngredient) {
|
||||
IIngredientManager ingredientManager = jeiHelpers.getIngredientManager();
|
||||
|
||||
IIngredientType<T> type = typedIngredient.getType();
|
||||
T ingredient = typedIngredient.getIngredient();
|
||||
IIngredientHelper<T> ingredientHelper = ingredientManager.getIngredientHelper(type);
|
||||
try {
|
||||
return ingredientHelper.getDisplayModId(ingredient);
|
||||
} catch (RuntimeException e) {
|
||||
String ingredientInfo = ingredientHelper.getErrorInfo(ingredient);
|
||||
LOGGER.error("Caught exception from ingredient without a resource location: {}", ingredientInfo, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,14 @@ package thedarkcolour.exdeorum.loot;
|
|||
import com.mojang.serialization.MapCodec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
|
||||
import net.neoforged.neoforge.common.loot.IGlobalLootModifier;
|
||||
import net.neoforged.neoforge.common.loot.LootModifier;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import thedarkcolour.exdeorum.recipe.RecipeUtil;
|
||||
import thedarkcolour.exdeorum.recipe.hammer.CompressedHammerRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
|
||||
import thedarkcolour.exdeorum.tag.EItemTags;
|
||||
|
||||
|
|
@ -25,7 +27,7 @@ public class CompressedHammerLootModifier extends HammerLootModifier {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable HammerRecipe getRecipe(Item itemForm, LootContext context) {
|
||||
protected @Nullable RecipeHolder<CompressedHammerRecipe> getRecipe(Item itemForm, LootContext context) {
|
||||
return RecipeUtil.getCaches(context.getLevel()).getCompressedHammerRecipe(itemForm);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import net.minecraft.tags.BlockTags;
|
|||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
|
|
@ -58,7 +59,8 @@ public class CrookLootModifier extends LootModifier {
|
|||
var fortune = stack.getEnchantmentLevel(context.getLevel().holderLookup(Registries.ENCHANTMENT).getOrThrow(Enchantments.FORTUNE));
|
||||
var rolls = Math.max(1, Mth.ceil(fortune / 3f));
|
||||
|
||||
for (CrookRecipe recipe : RecipeUtil.getCaches(context.getLevel()).getCrookRecipes(state)) {
|
||||
for (RecipeHolder<CrookRecipe> holder : RecipeUtil.getCaches(context.getLevel()).getCrookRecipes(state)) {
|
||||
var recipe = holder.value();
|
||||
for (int i = 0; i < rolls; i++) {
|
||||
if (rand.nextFloat() < recipe.chance()) {
|
||||
generatedLoot.add(recipe.result().copy());
|
||||
|
|
|
|||
|
|
@ -22,12 +22,14 @@ import com.mojang.serialization.MapCodec;
|
|||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
||||
|
|
@ -69,10 +71,11 @@ public class HammerLootModifier extends LootModifier {
|
|||
return generatedLoot;
|
||||
}
|
||||
|
||||
var recipe = getRecipe(itemForm, context);
|
||||
if (recipe == null) {
|
||||
var holder = getRecipe(itemForm, context);
|
||||
if (holder == null) {
|
||||
return generatedLoot;
|
||||
}
|
||||
var recipe = holder.value();
|
||||
|
||||
ObjectArrayList<ItemStack> newLoot = new ObjectArrayList<>();
|
||||
var resultAmount = recipe.resultAmount.getInt(context);
|
||||
|
|
@ -91,7 +94,7 @@ public class HammerLootModifier extends LootModifier {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
protected HammerRecipe getRecipe(Item itemForm, LootContext context) {
|
||||
protected RecipeHolder<? extends HammerRecipe> getRecipe(Item itemForm, LootContext context) {
|
||||
return RecipeUtil.getCaches(context.getLevel()).getHammerRecipe(itemForm);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package thedarkcolour.exdeorum.recipe;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
|
|
@ -17,6 +15,7 @@ import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe;
|
|||
import thedarkcolour.exdeorum.recipe.barrel.FluidTransformationRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.cache.*;
|
||||
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.hammer.CompressedHammerRecipe;
|
||||
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
|
||||
|
|
@ -26,11 +25,13 @@ import thedarkcolour.exdeorum.registry.ERecipeTypes;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class RecipeCaches {
|
||||
private SingleIngredientRecipeCache<BarrelCompostRecipe> barrelCompostRecipeCache;
|
||||
private SingleIngredientRecipeCache<CrucibleRecipe> lavaCrucibleRecipeCache;
|
||||
private SingleIngredientRecipeCache<CrucibleRecipe> waterCrucibleRecipeCache;
|
||||
private SingleIngredientRecipeCache<CrucibleRecipe.Lava> lavaCrucibleRecipeCache;
|
||||
private SingleIngredientRecipeCache<CrucibleRecipe.Water> waterCrucibleRecipeCache;
|
||||
private SingleIngredientRecipeCache<HammerRecipe> hammerRecipeCache;
|
||||
private SingleIngredientRecipeCache<CompressedHammerRecipe> compressedHammerRecipeCache;
|
||||
private SieveRecipeCache<SieveRecipe> sieveRecipeCache;
|
||||
|
|
@ -40,31 +41,31 @@ public class RecipeCaches {
|
|||
private CrookRecipeCache crookRecipeCache;
|
||||
private CrucibleHeatRecipeCache crucibleHeatRecipeCache;
|
||||
|
||||
public List<SieveRecipe> getSieveRecipes(Item mesh, ItemStack item) {
|
||||
public List<RecipeHolder<SieveRecipe>> getSieveRecipes(Item mesh, ItemStack item) {
|
||||
return this.sieveRecipeCache.getRecipe(mesh, item);
|
||||
}
|
||||
|
||||
public List<CompressedSieveRecipe> getCompressedSieveRecipes(Item mesh, ItemStack item) {
|
||||
public List<RecipeHolder<CompressedSieveRecipe>> getCompressedSieveRecipes(Item mesh, ItemStack item) {
|
||||
return this.compressedSieveRecipeCache.getRecipe(mesh, item);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CrucibleRecipe getLavaCrucibleRecipe(ItemStack item) {
|
||||
public RecipeHolder<CrucibleRecipe.Lava> getLavaCrucibleRecipe(ItemStack item) {
|
||||
return this.lavaCrucibleRecipeCache.getRecipe(item);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CrucibleRecipe getWaterCrucibleRecipe(ItemStack item) {
|
||||
public RecipeHolder<CrucibleRecipe.Water> getWaterCrucibleRecipe(ItemStack item) {
|
||||
return this.waterCrucibleRecipeCache.getRecipe(item);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BarrelCompostRecipe getBarrelCompostRecipe(ItemStack item) {
|
||||
public RecipeHolder<BarrelCompostRecipe> getBarrelCompostRecipe(ItemStack item) {
|
||||
return this.barrelCompostRecipeCache.getRecipe(item);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public HammerRecipe getHammerRecipe(Item item) {
|
||||
public RecipeHolder<HammerRecipe> getHammerRecipe(Item item) {
|
||||
return this.hammerRecipeCache.getRecipe(item);
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +74,7 @@ public class RecipeCaches {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public CompressedHammerRecipe getCompressedHammerRecipe(Item item) {
|
||||
public RecipeHolder<CompressedHammerRecipe> getCompressedHammerRecipe(Item item) {
|
||||
return this.compressedHammerRecipeCache.getRecipe(item);
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ public class RecipeCaches {
|
|||
return this.compressedHammerRecipeCache.getAllRecipes();
|
||||
}
|
||||
|
||||
public List<CrookRecipe> getCrookRecipes(BlockState state) {
|
||||
public List<RecipeHolder<CrookRecipe>> getCrookRecipes(BlockState state) {
|
||||
return this.crookRecipeCache.getRecipes(state);
|
||||
}
|
||||
|
||||
|
|
@ -89,20 +90,20 @@ public class RecipeCaches {
|
|||
return this.barrelCompostRecipeCache != null && this.barrelCompostRecipeCache.getRecipe(stack) != null;
|
||||
}
|
||||
|
||||
public int getHeatValue(BlockState state) {
|
||||
return this.crucibleHeatRecipeCache.getValue(state);
|
||||
public RecipeHolder<CrucibleHeatRecipe> getHeatRecipe(BlockState state) {
|
||||
return this.crucibleHeatRecipeCache.getRecipe(state);
|
||||
}
|
||||
|
||||
public ObjectSet<Object2IntMap.Entry<BlockState>> getHeatSources() {
|
||||
public Set<Map.Entry<BlockState, RecipeHolder<CrucibleHeatRecipe>>> getHeatSources() {
|
||||
return this.crucibleHeatRecipeCache.getEntries();
|
||||
}
|
||||
|
||||
// todo stop using the RecipeManager
|
||||
@Nullable
|
||||
public BarrelMixingRecipe getBarrelMixingRecipe(RecipeManager recipes, ItemStack stack, FluidStack fluid) {
|
||||
public RecipeHolder<BarrelMixingRecipe> getBarrelMixingRecipe(RecipeManager recipes, ItemStack stack, FluidStack fluid) {
|
||||
for (var recipe : recipes.byType(ERecipeTypes.BARREL_MIXING.get())) {
|
||||
if (recipe.value().matches(stack, fluid)) {
|
||||
return recipe.value();
|
||||
return recipe;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -110,17 +111,17 @@ public class RecipeCaches {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public BarrelFluidMixingRecipe getFluidMixingRecipe(FluidStack base, Fluid additive) {
|
||||
var recipe = this.barrelFluidMixingRecipeCache.getRecipe(base.getFluid(), additive);
|
||||
if (recipe != null && base.getAmount() >= recipe.baseFluid().amount()) {
|
||||
return recipe;
|
||||
public RecipeHolder<BarrelFluidMixingRecipe> getFluidMixingRecipe(FluidStack base, Fluid additive) {
|
||||
var holder = this.barrelFluidMixingRecipeCache.getRecipe(base.getFluid(), additive);
|
||||
if (holder != null && base.getAmount() >= holder.value().baseFluid().amount()) {
|
||||
return holder;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FluidTransformationRecipe getFluidTransformationRecipe(Fluid baseFluid, BlockState catalystState) {
|
||||
public RecipeHolder<FluidTransformationRecipe> getFluidTransformationRecipe(Fluid baseFluid, BlockState catalystState) {
|
||||
if (baseFluid != Fluids.EMPTY) {
|
||||
return this.fluidTransformationRecipeCache.getRecipe(baseFluid, catalystState);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package thedarkcolour.exdeorum.recipe.cache;
|
||||
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
|
@ -31,14 +32,14 @@ import java.util.Map;
|
|||
public class BarrelFluidMixingRecipeCache {
|
||||
private RecipeManager recipeManager;
|
||||
@Nullable
|
||||
private Map<Fluid, Map<Fluid, BarrelFluidMixingRecipe>> recipes;
|
||||
private Map<Fluid, Map<Fluid, RecipeHolder<BarrelFluidMixingRecipe>>> recipes;
|
||||
|
||||
public BarrelFluidMixingRecipeCache(RecipeManager recipeManager) {
|
||||
this.recipeManager = recipeManager;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BarrelFluidMixingRecipe getRecipe(Fluid baseFluid, Fluid additive) {
|
||||
public RecipeHolder<BarrelFluidMixingRecipe> getRecipe(Fluid baseFluid, Fluid additive) {
|
||||
if (this.recipes == null) {
|
||||
buildRecipes();
|
||||
}
|
||||
|
|
@ -58,7 +59,7 @@ public class BarrelFluidMixingRecipeCache {
|
|||
var map = this.recipes.computeIfAbsent(baseStack.getFluid(), key -> new HashMap<>());
|
||||
|
||||
for (var additiveStack : recipe.additiveFluid().getStacks()) {
|
||||
map.put(additiveStack.getFluid(), recipe);
|
||||
map.put(additiveStack.getFluid(), holder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package thedarkcolour.exdeorum.recipe.cache;
|
||||
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
|
@ -29,13 +30,13 @@ import java.util.*;
|
|||
public class CrookRecipeCache {
|
||||
private RecipeManager recipeManager;
|
||||
@Nullable
|
||||
private Map<BlockState, List<CrookRecipe>> recipes;
|
||||
private Map<BlockState, List<RecipeHolder<CrookRecipe>>> recipes;
|
||||
|
||||
public CrookRecipeCache(RecipeManager recipeManager) {
|
||||
this.recipeManager = recipeManager;
|
||||
}
|
||||
|
||||
public List<CrookRecipe> getRecipes(BlockState state) {
|
||||
public List<RecipeHolder<CrookRecipe>> getRecipes(BlockState state) {
|
||||
if (this.recipes == null) {
|
||||
buildRecipes();
|
||||
}
|
||||
|
|
@ -46,15 +47,15 @@ public class CrookRecipeCache {
|
|||
this.recipes = new HashMap<>();
|
||||
|
||||
// state -> set of possible recipes
|
||||
var tempRecipes = new HashMap<BlockState, HashSet<CrookRecipe>>();
|
||||
var tempRecipes = new HashMap<BlockState, HashSet<RecipeHolder<CrookRecipe>>>();
|
||||
|
||||
for (var recipe : this.recipeManager.byType(ERecipeTypes.CROOK.get())) {
|
||||
recipe.value().blockPredicate().possibleStates().forEach(state -> {
|
||||
tempRecipes.computeIfAbsent(state, key -> new HashSet<>()).add(recipe.value());
|
||||
tempRecipes.computeIfAbsent(state, key -> new HashSet<>()).add(recipe);
|
||||
});
|
||||
}
|
||||
// map equal sets to a single list object instead of using a bunch of duplicate sets
|
||||
var dedupeMap = new HashMap<HashSet<CrookRecipe>, List<CrookRecipe>>();
|
||||
var dedupeMap = new HashMap<HashSet<RecipeHolder<CrookRecipe>>, List<RecipeHolder<CrookRecipe>>>();
|
||||
|
||||
for (var entry : tempRecipes.entrySet()) {
|
||||
this.recipes.put(entry.getKey(), dedupeMap.computeIfAbsent(entry.getValue(), List::copyOf));
|
||||
|
|
|
|||
|
|
@ -18,45 +18,48 @@
|
|||
|
||||
package thedarkcolour.exdeorum.recipe.cache;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe;
|
||||
import thedarkcolour.exdeorum.registry.ERecipeTypes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CrucibleHeatRecipeCache {
|
||||
private RecipeManager recipeManager;
|
||||
@Nullable
|
||||
private Object2IntMap<BlockState> recipes;
|
||||
private Map<BlockState, RecipeHolder<CrucibleHeatRecipe>> recipes;
|
||||
|
||||
public CrucibleHeatRecipeCache(RecipeManager recipeManager) {
|
||||
this.recipeManager = recipeManager;
|
||||
}
|
||||
|
||||
public int getValue(BlockState state) {
|
||||
public RecipeHolder<CrucibleHeatRecipe> getRecipe(BlockState state) {
|
||||
if (this.recipes == null) {
|
||||
buildRecipes();
|
||||
}
|
||||
return this.recipes.getInt(state);
|
||||
return this.recipes.get(state);
|
||||
}
|
||||
|
||||
private void buildRecipes() {
|
||||
this.recipes = new Object2IntOpenHashMap<>();
|
||||
this.recipes = new HashMap<>();
|
||||
|
||||
for (var holder : this.recipeManager.byType(ERecipeTypes.CRUCIBLE_HEAT_SOURCE.get())) {
|
||||
var recipe = holder.value();
|
||||
recipe.blockPredicate().possibleStates().forEach(state -> this.recipes.put(state, recipe.heatValue()));
|
||||
recipe.blockPredicate().possibleStates().forEach(state -> this.recipes.put(state, holder));
|
||||
}
|
||||
|
||||
this.recipeManager = null;
|
||||
}
|
||||
|
||||
public ObjectSet<Object2IntMap.Entry<BlockState>> getEntries() {
|
||||
public Set<Map.Entry<BlockState, RecipeHolder<CrucibleHeatRecipe>>> getEntries() {
|
||||
if (this.recipes == null) {
|
||||
buildRecipes();
|
||||
}
|
||||
return this.recipes.object2IntEntrySet();
|
||||
return this.recipes.entrySet();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package thedarkcolour.exdeorum.recipe.cache;
|
||||
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
|
|
@ -31,14 +32,14 @@ import java.util.Map;
|
|||
public class FluidTransformationRecipeCache {
|
||||
private RecipeManager recipeManager;
|
||||
@Nullable
|
||||
private Map<BlockState, Map<Fluid, FluidTransformationRecipe>> recipes;
|
||||
private Map<BlockState, Map<Fluid, RecipeHolder<FluidTransformationRecipe>>> recipes;
|
||||
|
||||
public FluidTransformationRecipeCache(RecipeManager manager) {
|
||||
this.recipeManager = manager;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FluidTransformationRecipe getRecipe(Fluid baseFluid, BlockState catalystState) {
|
||||
public RecipeHolder<FluidTransformationRecipe> getRecipe(Fluid baseFluid, BlockState catalystState) {
|
||||
if (this.recipes == null) {
|
||||
buildRecipes();
|
||||
}
|
||||
|
|
@ -56,12 +57,12 @@ public class FluidTransformationRecipeCache {
|
|||
var recipe = holder.value();
|
||||
recipe.catalyst().possibleStates().forEach(state -> {
|
||||
for (var stack : recipe.baseFluid().getStacks()) {
|
||||
this.recipes.computeIfAbsent(state, key -> new HashMap<>()).put(stack.getFluid(), recipe);
|
||||
this.recipes.computeIfAbsent(state, key -> new HashMap<>()).put(stack.getFluid(), holder);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var dedupe = new HashMap<Map<Fluid, FluidTransformationRecipe>, Map<Fluid, FluidTransformationRecipe>>();
|
||||
var dedupe = new HashMap<Map<Fluid, RecipeHolder<FluidTransformationRecipe>>, Map<Fluid, RecipeHolder<FluidTransformationRecipe>>>();
|
||||
for (var entry : this.recipes.entrySet()) {
|
||||
entry.setValue(dedupe.computeIfAbsent(entry.getValue(), Map::copyOf));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ package thedarkcolour.exdeorum.recipe.cache;
|
|||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
|
@ -43,7 +44,7 @@ public class SieveRecipeCache<T extends SieveRecipe> {
|
|||
this.recipeType = recipeType;
|
||||
}
|
||||
|
||||
public List<T> getRecipe(Item mesh, ItemStack input) {
|
||||
public List<RecipeHolder<T>> getRecipe(Item mesh, ItemStack input) {
|
||||
if (this.meshCaches == null) {
|
||||
buildRecipes();
|
||||
}
|
||||
|
|
@ -53,11 +54,11 @@ public class SieveRecipeCache<T extends SieveRecipe> {
|
|||
|
||||
private void buildRecipes() {
|
||||
// Group recipes based on their mesh
|
||||
var tempMap = new HashMap<Item, List<T>>();
|
||||
var tempMap = new HashMap<Item, List<RecipeHolder<T>>>();
|
||||
for (var holder : this.recipeManager.byType(this.recipeType.get())) {
|
||||
var recipe = holder.value();
|
||||
for (var stack : recipe.mesh.getItems()) {
|
||||
tempMap.computeIfAbsent(stack.getItem(), k -> new ArrayList<>()).add(recipe);
|
||||
tempMap.computeIfAbsent(stack.getItem(), k -> new ArrayList<>()).add(holder);
|
||||
}
|
||||
}
|
||||
this.meshCaches = new HashMap<>();
|
||||
|
|
@ -73,15 +74,16 @@ public class SieveRecipeCache<T extends SieveRecipe> {
|
|||
// certain enchantment). Thirdly, I do not see anybody needing this use case, and if they do, they should contact
|
||||
// me on GitHub or Discord so that I can get around to actually implementing it.
|
||||
private static class MeshRecipeCache<T extends SieveRecipe> {
|
||||
private final Map<Item, List<T>> simpleRecipes;
|
||||
private final Map<Item, List<RecipeHolder<T>>> simpleRecipes;
|
||||
|
||||
private MeshRecipeCache(List<T> recipes) {
|
||||
private MeshRecipeCache(List<RecipeHolder<T>> recipes) {
|
||||
this.simpleRecipes = new HashMap<>();
|
||||
var temp = new HashMap<Item, ImmutableList.Builder<T>>();
|
||||
var temp = new HashMap<Item, ImmutableList.Builder<RecipeHolder<T>>>();
|
||||
|
||||
for (var recipe : recipes) {
|
||||
for (var holder : recipes) {
|
||||
var recipe = holder.value();
|
||||
for (var item : recipe.ingredient.getItems()) {
|
||||
temp.computeIfAbsent(item.getItem(), k -> ImmutableList.builder()).add(recipe);
|
||||
temp.computeIfAbsent(item.getItem(), k -> ImmutableList.builder()).add(holder);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +92,7 @@ public class SieveRecipeCache<T extends SieveRecipe> {
|
|||
}
|
||||
}
|
||||
|
||||
public List<T> getRecipes(ItemStack input) {
|
||||
public List<RecipeHolder<T>> getRecipes(ItemStack input) {
|
||||
var result = this.simpleRecipes.get(input.getItem());
|
||||
return result == null ? List.of() : result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,15 +31,16 @@ import java.util.Collection;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SingleIngredientRecipeCache<T extends SingleIngredientRecipe> {
|
||||
private final Supplier<RecipeType<T>> recipeType;
|
||||
private RecipeManager recipeManager;
|
||||
@Nullable
|
||||
private Map<Item, T> simpleRecipes;
|
||||
private Map<Item, RecipeHolder<T>> simpleRecipes;
|
||||
@Nullable
|
||||
private List<T> complexRecipes;
|
||||
private List<RecipeHolder<T>> complexRecipes;
|
||||
@Nullable
|
||||
private Collection<RecipeHolder<T>> allRecipes;
|
||||
private boolean trackAllRecipes;
|
||||
|
|
@ -55,12 +56,12 @@ public class SingleIngredientRecipeCache<T extends SingleIngredientRecipe> {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public T getRecipe(Item item) {
|
||||
public RecipeHolder<T> getRecipe(Item item) {
|
||||
return getRecipe(new ItemStack(item));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T getRecipe(ItemStack item) {
|
||||
public RecipeHolder<T> getRecipe(ItemStack item) {
|
||||
if (this.simpleRecipes == null) {
|
||||
buildRecipes();
|
||||
}
|
||||
|
|
@ -70,7 +71,7 @@ public class SingleIngredientRecipeCache<T extends SingleIngredientRecipe> {
|
|||
// if there are complex recipes, test each one
|
||||
if (recipe == null && this.complexRecipes != null) {
|
||||
for (var complexRecipe : this.complexRecipes) {
|
||||
if (complexRecipe.ingredient().test(item)) {
|
||||
if (complexRecipe.value().ingredient().test(item)) {
|
||||
return complexRecipe;
|
||||
}
|
||||
}
|
||||
|
|
@ -86,7 +87,7 @@ public class SingleIngredientRecipeCache<T extends SingleIngredientRecipe> {
|
|||
if (this.simpleRecipes == null) {
|
||||
buildRecipes();
|
||||
}
|
||||
return this.allRecipes;
|
||||
return Objects.requireNonNull(this.allRecipes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -99,7 +100,7 @@ public class SingleIngredientRecipeCache<T extends SingleIngredientRecipe> {
|
|||
*/
|
||||
private void buildRecipes() {
|
||||
this.simpleRecipes = new HashMap<>();
|
||||
var complexRecipes = ImmutableList.<T>builder();
|
||||
var complexRecipes = ImmutableList.<RecipeHolder<T>>builder();
|
||||
|
||||
var allRecipes = this.recipeManager.byType(this.recipeType.get());
|
||||
|
||||
|
|
@ -109,10 +110,10 @@ public class SingleIngredientRecipeCache<T extends SingleIngredientRecipe> {
|
|||
|
||||
if (ingredient.isSimple()) {
|
||||
for (var item : ingredient.getItems()) {
|
||||
this.simpleRecipes.put(item.getItem(), recipe);
|
||||
this.simpleRecipes.put(item.getItem(), holder);
|
||||
}
|
||||
} else {
|
||||
complexRecipes.add(recipe);
|
||||
complexRecipes.add(holder);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ public class ERecipeTypes {
|
|||
public static final DeferredHolder<RecipeType<?>, RecipeType<BarrelFluidMixingRecipe>> BARREL_FLUID_MIXING = RECIPE_TYPES.register("barrel_fluid_mixing", () -> RecipeType.simple(ERecipeTypes.BARREL_FLUID_MIXING.getId()));
|
||||
public static final DeferredHolder<RecipeType<?>, RecipeType<FluidTransformationRecipe>> BARREL_FLUID_TRANSFORMATION = RECIPE_TYPES.register("barrel_fluid_transformation", () -> RecipeType.simple(ERecipeTypes.BARREL_FLUID_TRANSFORMATION.getId()));
|
||||
|
||||
public static final DeferredHolder<RecipeType<?>, RecipeType<CrucibleRecipe>> LAVA_CRUCIBLE = RECIPE_TYPES.register("lava_crucible", () -> RecipeType.simple(ERecipeTypes.LAVA_CRUCIBLE.getId()));
|
||||
public static final DeferredHolder<RecipeType<?>, RecipeType<CrucibleRecipe>> WATER_CRUCIBLE = RECIPE_TYPES.register("water_crucible", () -> RecipeType.simple(ERecipeTypes.WATER_CRUCIBLE.getId()));
|
||||
public static final DeferredHolder<RecipeType<?>, RecipeType<CrucibleRecipe.Lava>> LAVA_CRUCIBLE = RECIPE_TYPES.register("lava_crucible", () -> RecipeType.simple(ERecipeTypes.LAVA_CRUCIBLE.getId()));
|
||||
public static final DeferredHolder<RecipeType<?>, RecipeType<CrucibleRecipe.Water>> WATER_CRUCIBLE = RECIPE_TYPES.register("water_crucible", () -> RecipeType.simple(ERecipeTypes.WATER_CRUCIBLE.getId()));
|
||||
|
||||
public static final DeferredHolder<RecipeType<?>, RecipeType<HammerRecipe>> HAMMER = RECIPE_TYPES.register("hammer", () -> RecipeType.simple(ERecipeTypes.HAMMER.getId()));
|
||||
public static final DeferredHolder<RecipeType<?>, RecipeType<CompressedHammerRecipe>> COMPRESSED_HAMMER = RECIPE_TYPES.register("compressed_hammer", () -> RecipeType.simple(ERecipeTypes.COMPRESSED_HAMMER.getId()));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user