Just Enough API

- replace (most?) calls to deprecated JEI-API features
- improve rotation for the /c u angle command
This commit is contained in:
zelophed 2022-07-04 13:25:21 +02:00
parent 9b9e252bac
commit 2fb3081da7
26 changed files with 771 additions and 966 deletions

View file

@ -1,17 +1,23 @@
package com.simibubi.create.compat.jei; package com.simibubi.create.compat.jei;
import javax.annotation.ParametersAreNonnullByDefault;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.content.curiosities.tools.BlueprintAssignCompleteRecipePacket; import com.simibubi.create.content.curiosities.tools.BlueprintAssignCompleteRecipePacket;
import com.simibubi.create.content.curiosities.tools.BlueprintContainer; import com.simibubi.create.content.curiosities.tools.BlueprintContainer;
import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.AllPackets;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.recipe.transfer.IRecipeTransferError; import mezz.jei.api.recipe.transfer.IRecipeTransferError;
import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; import mezz.jei.api.recipe.transfer.IRecipeTransferHandler;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.CraftingRecipe;
@SuppressWarnings("rawtypes") @ParametersAreNonnullByDefault
public class BlueprintTransferHandler implements IRecipeTransferHandler<BlueprintContainer, Recipe> { @MethodsReturnNonnullByDefault
public class BlueprintTransferHandler implements IRecipeTransferHandler<BlueprintContainer, CraftingRecipe> {
@Override @Override
public Class<BlueprintContainer> getContainerClass() { public Class<BlueprintContainer> getContainerClass() {
@ -19,20 +25,16 @@ public class BlueprintTransferHandler implements IRecipeTransferHandler<Blueprin
} }
@Override @Override
public Class<Recipe> getRecipeClass() { public Class<CraftingRecipe> getRecipeClass() {
return Recipe.class; return CraftingRecipe.class;
} }
@Override @Override
public IRecipeTransferError transferRecipe(BlueprintContainer container, Recipe recipe, public @Nullable IRecipeTransferError transferRecipe(BlueprintContainer container, CraftingRecipe craftingRecipe, IRecipeSlotsView recipeSlots, Player player, boolean maxTransfer, boolean doTransfer) {
IRecipeLayout recipeLayout, Player player, boolean maxTransfer, boolean doTransfer) {
if (!(recipe instanceof Recipe))
return null;
if (!doTransfer) if (!doTransfer)
return null; return null;
Recipe<?> iRecipe = (Recipe<?>) recipe;
// Continued server-side in BlueprintItem.assignCompleteRecipe() AllPackets.channel.sendToServer(new BlueprintAssignCompleteRecipePacket(craftingRecipe.getId()));
AllPackets.channel.sendToServer(new BlueprintAssignCompleteRecipePacket(iRecipe.getId()));
return null; return null;
} }

View file

@ -8,11 +8,10 @@ import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import com.google.common.base.Predicates;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllFluids; import com.simibubi.create.AllFluids;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
@ -61,7 +60,7 @@ import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo;
import mezz.jei.api.IModPlugin; import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin; import mezz.jei.api.JeiPlugin;
import mezz.jei.api.constants.VanillaRecipeCategoryUid; import mezz.jei.api.constants.RecipeTypes;
import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.api.recipe.category.IRecipeCategory;
import mezz.jei.api.registration.IGuiHandlerRegistration; import mezz.jei.api.registration.IGuiHandlerRegistration;
import mezz.jei.api.registration.IRecipeCatalystRegistration; import mezz.jei.api.registration.IRecipeCatalystRegistration;
@ -83,6 +82,7 @@ import net.minecraftforge.fml.ModList;
@JeiPlugin @JeiPlugin
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ParametersAreNonnullByDefault
public class CreateJEI implements IModPlugin { public class CreateJEI implements IModPlugin {
private static final ResourceLocation ID = Create.asResource("jei_plugin"); private static final ResourceLocation ID = Create.asResource("jei_plugin");
@ -94,154 +94,154 @@ public class CreateJEI implements IModPlugin {
allCategories.clear(); allCategories.clear();
CreateRecipeCategory<?> CreateRecipeCategory<?>
milling = register("milling", MillingCategory::new).addTypedRecipes(AllRecipeTypes.MILLING) milling = register("milling", MillingCategory::new)
.catalyst(AllBlocks.MILLSTONE::get) .addTypedRecipes(AllRecipeTypes.MILLING)
.build(), .catalyst(AllBlocks.MILLSTONE::get)
.build(),
crushing = register("crushing", CrushingCategory::new).addTypedRecipes(AllRecipeTypes.CRUSHING) crushing = register("crushing", CrushingCategory::new)
.addTypedRecipesExcluding(AllRecipeTypes.MILLING::getType, AllRecipeTypes.CRUSHING::getType) .addTypedRecipes(AllRecipeTypes.CRUSHING)
.catalyst(AllBlocks.CRUSHING_WHEEL::get) .addTypedRecipesExcluding(AllRecipeTypes.MILLING::getType, AllRecipeTypes.CRUSHING::getType)
.build(), .catalyst(AllBlocks.CRUSHING_WHEEL::get)
.build(),
pressing = register("pressing", PressingCategory::new).addTypedRecipes(AllRecipeTypes.PRESSING) pressing = register("pressing", PressingCategory::new)
.catalyst(AllBlocks.MECHANICAL_PRESS::get) .addTypedRecipes(AllRecipeTypes.PRESSING)
.build(), .catalyst(AllBlocks.MECHANICAL_PRESS::get)
.build(),
washing = register("fan_washing", FanWashingCategory::new).addTypedRecipes(AllRecipeTypes.SPLASHING) washing = register("fan_washing", FanWashingCategory::new)
.catalystStack(ProcessingViaFanCategory.getFan("fan_washing")) .addTypedRecipes(AllRecipeTypes.SPLASHING)
.build(), .catalystStack(ProcessingViaFanCategory.getFan("fan_washing"))
.build(),
smoking = register("fan_smoking", FanSmokingCategory::new).addTypedRecipes(() -> RecipeType.SMOKING) smoking = register("fan_smoking", FanSmokingCategory::new)
.catalystStack(ProcessingViaFanCategory.getFan("fan_smoking")) .addTypedRecipes(() -> RecipeType.SMOKING)
.build(), .catalystStack(ProcessingViaFanCategory.getFan("fan_smoking"))
.build(),
blasting = register("fan_blasting", FanBlastingCategory::new) blasting = register("fan_blasting", FanBlastingCategory::new)
.addTypedRecipesExcluding(() -> RecipeType.SMELTING, () -> RecipeType.BLASTING) .addTypedRecipesExcluding(() -> RecipeType.SMELTING, () -> RecipeType.BLASTING)
.addTypedRecipes(() -> RecipeType.BLASTING) .addTypedRecipes(() -> RecipeType.BLASTING)
.removeRecipes(() -> RecipeType.SMOKING) .removeRecipes(() -> RecipeType.SMOKING)
.catalystStack(ProcessingViaFanCategory.getFan("fan_blasting")) .catalystStack(ProcessingViaFanCategory.getFan("fan_blasting"))
.build(), .build(),
haunting = register("fan_haunting", FanHauntingCategory::new).addTypedRecipes(AllRecipeTypes.HAUNTING) haunting = register("fan_haunting", FanHauntingCategory::new).addTypedRecipes(AllRecipeTypes.HAUNTING)
.catalystStack(ProcessingViaFanCategory.getFan("fan_haunting")) .catalystStack(ProcessingViaFanCategory.getFan("fan_haunting"))
.build(), .build(),
mixing = register("mixing", MixingCategory::standard).addTypedRecipes(AllRecipeTypes.MIXING) mixing = register("mixing", MixingCategory::standard).addTypedRecipes(AllRecipeTypes.MIXING)
.catalyst(AllBlocks.MECHANICAL_MIXER::get) .catalyst(AllBlocks.MECHANICAL_MIXER::get)
.catalyst(AllBlocks.BASIN::get) .catalyst(AllBlocks.BASIN::get)
.build(), .build(),
seqAssembly = register("sequenced_assembly", SequencedAssemblyCategory::new) seqAssembly = register("sequenced_assembly", SequencedAssemblyCategory::new)
.addTypedRecipes(AllRecipeTypes.SEQUENCED_ASSEMBLY) .addTypedRecipes(AllRecipeTypes.SEQUENCED_ASSEMBLY)
.build(), .build(),
autoShapeless = register("automatic_shapeless", MixingCategory::autoShapeless) autoShapeless = register("automatic_shapeless", MixingCategory::autoShapeless)
.addAllRecipesIf(r -> r instanceof CraftingRecipe && !(r instanceof IShapedRecipe<?>) .addAllRecipesIf(r -> r instanceof CraftingRecipe && !(r instanceof IShapedRecipe<?>)
&& r.getIngredients() && r.getIngredients()
.size() > 1 .size() > 1
&& !MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.shouldIgnoreInAutomation(r), && !MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.shouldIgnoreInAutomation(r),
BasinRecipe::convertShapeless) BasinRecipe::convertShapeless)
.catalyst(AllBlocks.MECHANICAL_MIXER::get) .catalyst(AllBlocks.MECHANICAL_MIXER::get)
.catalyst(AllBlocks.BASIN::get) .catalyst(AllBlocks.BASIN::get)
.enableWhen(c -> c.allowShapelessInMixer) .enableWhen(c -> c.allowShapelessInMixer)
.build(), .build(),
brewing = brewing = register("automatic_brewing", MixingCategory::autoBrewing).addRecipes(() -> PotionMixingRecipes.ALL)
register("automatic_brewing", MixingCategory::autoBrewing).addRecipes(() -> PotionMixingRecipes.ALL) .catalyst(AllBlocks.MECHANICAL_MIXER::get)
.catalyst(AllBlocks.MECHANICAL_MIXER::get) .catalyst(AllBlocks.BASIN::get)
.catalyst(AllBlocks.BASIN::get) .build(),
.build(),
sawing = register("sawing", SawingCategory::new).addTypedRecipes(AllRecipeTypes.CUTTING) sawing = register("sawing", SawingCategory::new).addTypedRecipes(AllRecipeTypes.CUTTING)
.catalyst(AllBlocks.MECHANICAL_SAW::get) .catalyst(AllBlocks.MECHANICAL_SAW::get)
.build(), .build(),
blockCutting = blockCutting = register("block_cutting", () -> new BlockCuttingCategory(Items.STONE_BRICK_STAIRS))
register("block_cutting", () -> new BlockCuttingCategory(Items.STONE_BRICK_STAIRS)) .addRecipes(() -> CondensedBlockCuttingRecipe.condenseRecipes(getTypedRecipesExcluding(RecipeType.STONECUTTING, AllRecipeTypes::shouldIgnoreInAutomation)))
.addRecipes(() -> CondensedBlockCuttingRecipe.condenseRecipes(getTypedRecipesExcluding( .catalyst(AllBlocks.MECHANICAL_SAW::get)
RecipeType.STONECUTTING, recipe -> AllRecipeTypes.shouldIgnoreInAutomation(recipe)))) .enableWhen(c -> c.allowStonecuttingOnSaw)
.catalyst(AllBlocks.MECHANICAL_SAW::get) .build(),
.enableWhen(c -> c.allowStonecuttingOnSaw)
.build(),
woodCutting = register("wood_cutting", () -> new BlockCuttingCategory(Items.OAK_STAIRS)) woodCutting = register("wood_cutting", () -> new BlockCuttingCategory(Items.OAK_STAIRS))
.addRecipes(() -> CondensedBlockCuttingRecipe .addRecipes(() -> CondensedBlockCuttingRecipe.condenseRecipes(getTypedRecipesExcluding(SawTileEntity.woodcuttingRecipeType.get(), AllRecipeTypes::shouldIgnoreInAutomation)))
.condenseRecipes(getTypedRecipesExcluding(SawTileEntity.woodcuttingRecipeType.get(), .catalyst(AllBlocks.MECHANICAL_SAW::get)
recipe -> AllRecipeTypes.shouldIgnoreInAutomation(recipe)))) .enableWhenBool(c -> c.allowWoodcuttingOnSaw.get() && ModList.get()
.catalyst(AllBlocks.MECHANICAL_SAW::get) .isLoaded("druidcraft"))
.enableWhenBool(c -> c.allowWoodcuttingOnSaw.get() && ModList.get() .build(),
.isLoaded("druidcraft"))
.build(),
packing = register("packing", PackingCategory::standard).addTypedRecipes(AllRecipeTypes.COMPACTING) packing = register("packing", PackingCategory::standard).addTypedRecipes(AllRecipeTypes.COMPACTING)
.catalyst(AllBlocks.MECHANICAL_PRESS::get) .catalyst(AllBlocks.MECHANICAL_PRESS::get)
.catalyst(AllBlocks.BASIN::get) .catalyst(AllBlocks.BASIN::get)
.build(), .build(),
autoSquare = register("automatic_packing", PackingCategory::autoSquare) autoSquare = register("automatic_packing", PackingCategory::autoSquare)
.addAllRecipesIf( .addAllRecipesIf(
r -> (r instanceof CraftingRecipe) && !(r instanceof MechanicalCraftingRecipe) r -> (r instanceof CraftingRecipe) && !(r instanceof MechanicalCraftingRecipe)
&& MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.shouldIgnoreInAutomation(r), && MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.shouldIgnoreInAutomation(r),
BasinRecipe::convertShapeless) BasinRecipe::convertShapeless)
.catalyst(AllBlocks.MECHANICAL_PRESS::get) .catalyst(AllBlocks.MECHANICAL_PRESS::get)
.catalyst(AllBlocks.BASIN::get) .catalyst(AllBlocks.BASIN::get)
.enableWhen(c -> c.allowShapedSquareInPress) .enableWhen(c -> c.allowShapedSquareInPress)
.build(), .build(),
polishing = register("sandpaper_polishing", PolishingCategory::new) polishing = register("sandpaper_polishing", PolishingCategory::new)
.addTypedRecipes(AllRecipeTypes.SANDPAPER_POLISHING) .addTypedRecipes(AllRecipeTypes.SANDPAPER_POLISHING)
.catalyst(AllItems.SAND_PAPER::get) .catalyst(AllItems.SAND_PAPER::get)
.catalyst(AllItems.RED_SAND_PAPER::get) .catalyst(AllItems.RED_SAND_PAPER::get)
.build(), .build(),
item_application = register("item_application", ItemApplicationCategory::new) item_application = register("item_application", ItemApplicationCategory::new)
.addTypedRecipes(AllRecipeTypes.ITEM_APPLICATION) .addTypedRecipes(AllRecipeTypes.ITEM_APPLICATION)
.addRecipes(LogStrippingFakeRecipes::createRecipes) .addRecipes(LogStrippingFakeRecipes::createRecipes)
.build(), .build(),
deploying = register("deploying", DeployingCategory::new).addTypedRecipes(AllRecipeTypes.DEPLOYING) deploying = register("deploying", DeployingCategory::new).addTypedRecipes(AllRecipeTypes.DEPLOYING)
.addTypedRecipes(AllRecipeTypes.SANDPAPER_POLISHING::getType, DeployerApplicationRecipe::convert) .addTypedRecipes(AllRecipeTypes.SANDPAPER_POLISHING::getType, DeployerApplicationRecipe::convert)
.addTypedRecipes(AllRecipeTypes.ITEM_APPLICATION::getType, ManualApplicationRecipe::asDeploying) .addTypedRecipes(AllRecipeTypes.ITEM_APPLICATION::getType, ManualApplicationRecipe::asDeploying)
.catalyst(AllBlocks.DEPLOYER::get) .catalyst(AllBlocks.DEPLOYER::get)
.catalyst(AllBlocks.DEPOT::get) .catalyst(AllBlocks.DEPOT::get)
.catalyst(AllItems.BELT_CONNECTOR::get) .catalyst(AllItems.BELT_CONNECTOR::get)
.build(), .build(),
mysteryConversion = register("mystery_conversion", MysteriousItemConversionCategory::new) mysteryConversion = register("mystery_conversion", MysteriousItemConversionCategory::new)
.addRecipes(() -> MysteriousItemConversionCategory.RECIPES) .addRecipes(() -> MysteriousItemConversionCategory.RECIPES)
.build(), .build(),
spoutFilling = register("spout_filling", SpoutCategory::new).addTypedRecipes(AllRecipeTypes.FILLING) spoutFilling = register("spout_filling", SpoutCategory::new).addTypedRecipes(AllRecipeTypes.FILLING)
.addRecipeListConsumer(recipes -> SpoutCategory.consumeRecipes(recipes::add, ingredientManager)) .addRecipeListConsumer(recipes -> SpoutCategory.consumeRecipes(recipes::add, ingredientManager))
.catalyst(AllBlocks.SPOUT::get) .catalyst(AllBlocks.SPOUT::get)
.build(), .build(),
draining = register("draining", ItemDrainCategory::new) draining = register("draining", ItemDrainCategory::new)
.addRecipeListConsumer(recipes -> ItemDrainCategory.consumeRecipes(recipes::add, ingredientManager)) .addRecipeListConsumer(recipes -> ItemDrainCategory.consumeRecipes(recipes::add, ingredientManager))
.addTypedRecipes(AllRecipeTypes.EMPTYING) .addTypedRecipes(AllRecipeTypes.EMPTYING)
.catalyst(AllBlocks.ITEM_DRAIN::get) .catalyst(AllBlocks.ITEM_DRAIN::get)
.build(), .build(),
autoShaped = register("automatic_shaped", MechanicalCraftingCategory::new) autoShaped = register("automatic_shaped", MechanicalCraftingCategory::new)
.addAllRecipesIf(r -> r instanceof CraftingRecipe && !(r instanceof IShapedRecipe<?>) .addAllRecipesIf(r -> r instanceof CraftingRecipe && !(r instanceof IShapedRecipe<?>)
&& r.getIngredients() && r.getIngredients()
.size() == 1 .size() == 1
&& !AllRecipeTypes.shouldIgnoreInAutomation(r)) && !AllRecipeTypes.shouldIgnoreInAutomation(r))
.addTypedRecipesIf(() -> RecipeType.CRAFTING, .addTypedRecipesIf(() -> RecipeType.CRAFTING,
recipe -> recipe instanceof IShapedRecipe<?> && !AllRecipeTypes.shouldIgnoreInAutomation(recipe)) recipe -> recipe instanceof IShapedRecipe<?> && !AllRecipeTypes.shouldIgnoreInAutomation(recipe))
.catalyst(AllBlocks.MECHANICAL_CRAFTER::get) .catalyst(AllBlocks.MECHANICAL_CRAFTER::get)
.enableWhen(c -> c.allowRegularCraftingInCrafter) .enableWhen(c -> c.allowRegularCraftingInCrafter)
.build(), .build(),
mechanicalCrafting = register("mechanical_crafting", MechanicalCraftingCategory::new) mechanicalCrafting = register("mechanical_crafting", MechanicalCraftingCategory::new)
.addTypedRecipes(AllRecipeTypes.MECHANICAL_CRAFTING) .addTypedRecipes(AllRecipeTypes.MECHANICAL_CRAFTING)
.catalyst(AllBlocks.MECHANICAL_CRAFTER::get) .catalyst(AllBlocks.MECHANICAL_CRAFTER::get)
.build(); .build();
} }
private <T extends Recipe<?>> CategoryBuilder<T> register(String name, Supplier<CreateRecipeCategory<T>> supplier) { private <T extends Recipe<?>> CategoryBuilder<T> register(String name, Supplier<CreateRecipeCategory<T>> supplier) {
return new CategoryBuilder<T>(name, supplier); return new CategoryBuilder<>(name, supplier);
} }
@Override @Override
@ -252,7 +252,7 @@ public class CreateJEI implements IModPlugin {
@Override @Override
public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) { public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) {
registration.addRecipeTransferHandler(new BlueprintTransferHandler(), VanillaRecipeCategoryUid.CRAFTING); registration.addRecipeTransferHandler(new BlueprintTransferHandler(), RecipeTypes.CRAFTING);
} }
@Override @Override
@ -272,15 +272,15 @@ public class CreateJEI implements IModPlugin {
@Override @Override
public void registerRecipes(IRecipeRegistration registration) { public void registerRecipes(IRecipeRegistration registration) {
ingredientManager = registration.getIngredientManager(); ingredientManager = registration.getIngredientManager();
allCategories.forEach(c -> c.recipes.forEach(s -> registration.addRecipes(s.get(), c.getUid())));
registration.addRecipes(ToolboxColoringRecipeMaker.createRecipes() allCategories.forEach(c -> c.registerRecipes(registration));
.collect(Collectors.toList()), VanillaRecipeCategoryUid.CRAFTING);
registration.addRecipes(RecipeTypes.CRAFTING, ToolboxColoringRecipeMaker.createRecipes().toList());
} }
@Override @Override
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
allCategories.forEach(c -> c.recipeCatalysts.forEach(s -> registration.addRecipeCatalyst(s.get(), c.getUid()))); allCategories.forEach(c -> c.recipeCatalysts.forEach(s -> registration.addRecipeCatalyst(s.get(), c.getRecipeType())));
} }
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({ "unchecked", "rawtypes" })
@ -295,29 +295,30 @@ public class CreateJEI implements IModPlugin {
} }
private class CategoryBuilder<T extends Recipe<?>> { private class CategoryBuilder<T extends Recipe<?>> {
private CreateRecipeCategory<T> category; private final CreateRecipeCategory<T> category;
private List<Consumer<List<Recipe<?>>>> recipeListConsumers = new ArrayList<>(); private final List<Consumer<List<T>>> recipeListConsumers = new ArrayList<>();
private Predicate<CRecipes> pred; private Predicate<CRecipes> predicate;
public CategoryBuilder(String name, Supplier<CreateRecipeCategory<T>> category) { public CategoryBuilder(String name, Supplier<CreateRecipeCategory<T>> category) {
this.category = category.get(); this.category = category.get();
this.category.setCategoryId(name); this.category.setCategoryId(name);
pred = Predicates.alwaysTrue(); mezz.jei.api.recipe.RecipeType<T> recipeType = this.category.getRecipeType();
predicate = cRecipes -> true;
} }
public CategoryBuilder<T> addRecipeListConsumer(Consumer<List<Recipe<?>>> consumer) { public CategoryBuilder<T> addRecipeListConsumer(Consumer<List<T>> consumer) {
recipeListConsumers.add(consumer); recipeListConsumers.add(consumer);
return this; return this;
} }
public CategoryBuilder<T> addRecipes(Supplier<Collection<? extends Recipe<?>>> collection) { public CategoryBuilder<T> addRecipes(Supplier<Collection<? extends T>> collection) {
return addRecipeListConsumer(recipes -> recipes.addAll(collection.get())); return addRecipeListConsumer(recipes -> recipes.addAll(collection.get()));
} }
public CategoryBuilder<T> addAllRecipesIf(Predicate<Recipe<?>> pred) { public CategoryBuilder<T> addAllRecipesIf(Predicate<Recipe<?>> pred) {
return addRecipeListConsumer(recipes -> consumeAllRecipes(recipe -> { return addRecipeListConsumer(recipes -> consumeAllRecipes(recipe -> {
if (pred.test(recipe)) { if (pred.test(recipe)) {
recipes.add(recipe); recipes.add((T) recipe);
} }
})); }));
} }
@ -335,19 +336,15 @@ public class CreateJEI implements IModPlugin {
} }
public CategoryBuilder<T> addTypedRecipes(Supplier<RecipeType<? extends T>> recipeType) { public CategoryBuilder<T> addTypedRecipes(Supplier<RecipeType<? extends T>> recipeType) {
return addRecipeListConsumer(recipes -> consumeTypedRecipes(recipes::add, recipeType.get())); return addRecipeListConsumer(recipes -> CreateJEI.<T>consumeTypedRecipes(recipes::add, recipeType.get()));
} }
public CategoryBuilder<T> addTypedRecipes(Supplier<RecipeType<? extends T>> recipeType, public CategoryBuilder<T> addTypedRecipes(Supplier<RecipeType<? extends T>> recipeType, Function<Recipe<?>, T> converter) {
Function<Recipe<?>, T> converter) { return addRecipeListConsumer(recipes -> CreateJEI.<T>consumeTypedRecipes(recipe -> recipes.add(converter.apply(recipe)), recipeType.get()));
return addRecipeListConsumer(recipes -> consumeTypedRecipes(recipe -> {
recipes.add(converter.apply(recipe));
}, recipeType.get()));
} }
public CategoryBuilder<T> addTypedRecipesIf(Supplier<RecipeType<? extends T>> recipeType, public CategoryBuilder<T> addTypedRecipesIf(Supplier<RecipeType<? extends T>> recipeType, Predicate<Recipe<?>> pred) {
Predicate<Recipe<?>> pred) { return addRecipeListConsumer(recipes -> CreateJEI.<T>consumeTypedRecipes(recipe -> {
return addRecipeListConsumer(recipes -> consumeTypedRecipes(recipe -> {
if (pred.test(recipe)) { if (pred.test(recipe)) {
recipes.add(recipe); recipes.add(recipe);
} }
@ -358,7 +355,7 @@ public class CreateJEI implements IModPlugin {
Supplier<RecipeType<? extends T>> excluded) { Supplier<RecipeType<? extends T>> excluded) {
return addRecipeListConsumer(recipes -> { return addRecipeListConsumer(recipes -> {
List<Recipe<?>> excludedRecipes = getTypedRecipes(excluded.get()); List<Recipe<?>> excludedRecipes = getTypedRecipes(excluded.get());
consumeTypedRecipes(recipe -> { CreateJEI.<T>consumeTypedRecipes(recipe -> {
for (Recipe<?> excludedRecipe : excludedRecipes) { for (Recipe<?> excludedRecipe : excludedRecipes) {
if (doInputsMatch(recipe, excludedRecipe)) { if (doInputsMatch(recipe, excludedRecipe)) {
return; return;
@ -394,21 +391,20 @@ public class CreateJEI implements IModPlugin {
} }
public CategoryBuilder<T> enableWhen(Function<CRecipes, ConfigBool> configValue) { public CategoryBuilder<T> enableWhen(Function<CRecipes, ConfigBool> configValue) {
pred = c -> configValue.apply(c) predicate = c -> configValue.apply(c).get();
.get();
return this; return this;
} }
public CategoryBuilder<T> enableWhenBool(Function<CRecipes, Boolean> configValue) { public CategoryBuilder<T> enableWhenBool(Function<CRecipes, Boolean> configValue) {
pred = configValue::apply; predicate = configValue::apply;
return this; return this;
} }
public CreateRecipeCategory<T> build() { public CreateRecipeCategory<T> build() {
if (pred.test(AllConfigs.SERVER.recipes)) if (predicate.test(AllConfigs.SERVER.recipes))
category.recipes.add(() -> { category.recipes.add(() -> {
List<Recipe<?>> recipes = new ArrayList<>(); List<T> recipes = new ArrayList<>();
for (Consumer<List<Recipe<?>>> consumer : recipeListConsumers) for (Consumer<List<T>> consumer : recipeListConsumers)
consumer.accept(recipes); consumer.accept(recipes);
return recipes; return recipes;
}); });
@ -426,13 +422,12 @@ public class CreateJEI implements IModPlugin {
.forEach(consumer); .forEach(consumer);
} }
public static void consumeTypedRecipes(Consumer<Recipe<?>> consumer, RecipeType<?> type) { public static <T extends Recipe<?>> void consumeTypedRecipes(Consumer<T> consumer, RecipeType<?> type) {
Map<ResourceLocation, Recipe<?>> map = Minecraft.getInstance() Map<ResourceLocation, Recipe<?>> map = Minecraft.getInstance()
.getConnection() .getConnection()
.getRecipeManager().recipes.get(type); .getRecipeManager().recipes.get(type);
if (map != null) { if (map != null) {
map.values() map.values().forEach(recipe -> consumer.accept((T) recipe));
.forEach(consumer);
} }
} }
@ -461,11 +456,9 @@ public class CreateJEI implements IModPlugin {
if (matchingStacks.length == 0) { if (matchingStacks.length == 0) {
return false; return false;
} }
if (recipe2.getIngredients() return recipe2.getIngredients()
.get(0) .get(0)
.test(matchingStacks[0])) .test(matchingStacks[0]);
return true;
return false;
} }
} }

View file

@ -2,7 +2,8 @@ package com.simibubi.create.compat.jei.category;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.mutable.MutableInt;
@ -11,6 +12,7 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.content.contraptions.processing.BasinRecipe; import com.simibubi.create.content.contraptions.processing.BasinRecipe;
import com.simibubi.create.content.contraptions.processing.HeatCondition; import com.simibubi.create.content.contraptions.processing.HeatCondition;
import com.simibubi.create.content.contraptions.processing.ProcessingOutput;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.fluid.FluidIngredient;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
@ -19,20 +21,20 @@ import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.Pair;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.RecipeIngredientRole;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Ingredient;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
@ParametersAreNonnullByDefault
public class BasinCategory extends CreateRecipeCategory<BasinRecipe> { public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
private boolean needsHeating; private final boolean needsHeating;
public BasinCategory(boolean needsHeating, IDrawable icon, IDrawable background) { public BasinCategory(boolean needsHeating, IDrawable icon, IDrawable background) {
super(icon, background); super(icon, background);
@ -45,129 +47,86 @@ public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
} }
@Override @Override
public void setIngredients(BasinRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, BasinRecipe recipe, IFocusGroup focuses) {
List<Ingredient> itemIngredients = new ArrayList<>(recipe.getIngredients()); List<Pair<Ingredient, MutableInt>> condensedIngredients = ItemHelper.condenseIngredients(recipe.getIngredients());
HeatCondition requiredHeat = recipe.getRequiredHeat(); int size = condensedIngredients.size() + recipe.getFluidIngredients().size();
if (!requiredHeat.testBlazeBurner(HeatLevel.NONE))
itemIngredients.add(Ingredient.of(AllBlocks.BLAZE_BURNER.get()));
if (!requiredHeat.testBlazeBurner(HeatLevel.KINDLED))
itemIngredients.add(Ingredient.of(AllItems.BLAZE_CAKE.get()));
ingredients.setInputIngredients(itemIngredients);
ingredients.setInputLists(VanillaTypes.FLUID, recipe.getFluidIngredients()
.stream()
.map(FluidIngredient::getMatchingFluidStacks)
.collect(Collectors.toList()));
if (!recipe.getRollableResults()
.isEmpty())
ingredients.setOutput(VanillaTypes.ITEM, recipe.getResultItem());
if (!recipe.getFluidResults()
.isEmpty())
ingredients.setOutputs(VanillaTypes.FLUID, recipe.getFluidResults());
}
@Override
public void setRecipe(IRecipeLayout recipeLayout, BasinRecipe recipe, IIngredients iingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
IGuiFluidStackGroup fluidStacks = recipeLayout.getFluidStacks();
NonNullList<FluidIngredient> fluidIngredients = recipe.getFluidIngredients();
List<Pair<Ingredient, MutableInt>> ingredients = ItemHelper.condenseIngredients(recipe.getIngredients());
List<ItemStack> itemOutputs = recipe.getRollableResultsAsItemStacks();
NonNullList<FluidStack> fluidOutputs = recipe.getFluidResults();
int size = ingredients.size() + fluidIngredients.size();
int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0; int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0;
int yOffset = 0; int i = 0;
int i; for (Pair<Ingredient, MutableInt> pair : condensedIngredients) {
for (i = 0; i < ingredients.size(); i++) {
itemStacks.init(i, true, 16 + xOffset + (i % 3) * 19, 50 - (i / 3) * 19 + yOffset);
List<ItemStack> stacks = new ArrayList<>(); List<ItemStack> stacks = new ArrayList<>();
Pair<Ingredient, MutableInt> pair = ingredients.get(i); for (ItemStack itemStack : pair.getFirst().getItems()) {
Ingredient ingredient = pair.getFirst(); ItemStack copy = itemStack.copy();
MutableInt amount = pair.getSecond(); copy.setCount(pair.getSecond().getValue());
stacks.add(copy);
for (ItemStack itemStack : ingredient.getItems()) {
ItemStack stack = itemStack.copy();
stack.setCount(amount.getValue());
stacks.add(stack);
} }
itemStacks.set(i, stacks); builder
.addSlot(RecipeIngredientRole.INPUT, 17 + xOffset + (i % 3) * 19, 51 - (i / 3) * 19)
.setBackground(getRenderedSlot(), -1, -1)
.addItemStacks(stacks);
i++;
}
for (FluidIngredient fluidIngredient : recipe.getFluidIngredients()) {
builder
.addSlot(RecipeIngredientRole.INPUT, 17 + xOffset + (i % 3) * 19, 51 - (i / 3) * 19)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredients(VanillaTypes.FLUID, withImprovedVisibility(fluidIngredient.getMatchingFluidStacks()))
.addTooltipCallback(addFluidTooltip(fluidIngredient.getRequiredAmount()));
i++;
} }
int j; size = recipe.getRollableResults().size() + recipe.getFluidResults().size();
for (j = 0; j < fluidIngredients.size(); j++) { i = 0;
int i2 = i + j;
fluidStacks.init(j, true, 17 + xOffset + (i2 % 3) * 19, 51 - (i2 / 3) * 19 + yOffset); for (ProcessingOutput result : recipe.getRollableResults()) {
List<FluidStack> stacks = fluidIngredients.get(j) int xPosition = 142 - (size % 2 != 0 && i == size - 1 ? 0 : i % 2 == 0 ? 10 : -9);
.getMatchingFluidStacks(); int yPosition = -19 * (i / 2) + 51;
fluidStacks.set(j, withImprovedVisibility(stacks));
builder
.addSlot(RecipeIngredientRole.OUTPUT, xPosition, yPosition)
.setBackground(getRenderedSlot(result), -1, -1)
.addItemStack(result.getStack())
.addTooltipCallback(addStochasticTooltip(result));
i++;
} }
int outSize = fluidOutputs.size() + recipe.getRollableResults() for (FluidStack fluidResult : recipe.getFluidResults()) {
.size(); int xPosition = 142 - (size % 2 != 0 && i == size - 1 ? 0 : i % 2 == 0 ? 10 : -9);
int outputIndex = 0; int yPosition = -19 * (i / 2) + 51;
if (!itemOutputs.isEmpty())
addStochasticTooltip(itemStacks, recipe.getRollableResults(), i);
for (; outputIndex < outSize; outputIndex++) {
int xPosition = 141 - (outSize % 2 != 0 && outputIndex == outSize - 1 ? 0 : outputIndex % 2 == 0 ? 10 : -9);
int yPosition = -19 * (outputIndex / 2) + 50 + yOffset;
if (itemOutputs.size() > outputIndex) {
itemStacks.init(i, false, xPosition, yPosition + yOffset);
itemStacks.set(i, itemOutputs.get(outputIndex));
i++;
} else {
fluidStacks.init(j, false, xPosition + 1, yPosition + 1 + yOffset);
fluidStacks.set(j, withImprovedVisibility(fluidOutputs.get(outputIndex - itemOutputs.size())));
j++;
}
builder
.addSlot(RecipeIngredientRole.OUTPUT, xPosition, yPosition)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredient(VanillaTypes.FLUID, withImprovedVisibility(fluidResult))
.addTooltipCallback(addFluidTooltip(fluidResult.getAmount()));
i++;
} }
addFluidTooltip(fluidStacks, fluidIngredients, fluidOutputs);
HeatCondition requiredHeat = recipe.getRequiredHeat(); HeatCondition requiredHeat = recipe.getRequiredHeat();
if (!requiredHeat.testBlazeBurner(HeatLevel.NONE)) { if (!requiredHeat.testBlazeBurner(HeatLevel.NONE)) {
itemStacks.init(i, true, 133, 80); builder
itemStacks.set(i, AllBlocks.BLAZE_BURNER.asStack()); .addSlot(RecipeIngredientRole.RENDER_ONLY, 134, 81)
i++; .addItemStack(AllBlocks.BLAZE_BURNER.asStack());
} }
if (!requiredHeat.testBlazeBurner(HeatLevel.KINDLED)) { if (!requiredHeat.testBlazeBurner(HeatLevel.KINDLED)) {
itemStacks.init(i, true, 152, 80); builder
itemStacks.set(i, AllItems.BLAZE_CAKE.asStack()); .addSlot(RecipeIngredientRole.CATALYST, 153, 81)
i++; .addItemStack(AllItems.BLAZE_CAKE.asStack());
} }
} }
@Override @Override
public void draw(BasinRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) { public void draw(BasinRecipe recipe, IRecipeSlotsView recipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
List<Pair<Ingredient, MutableInt>> actualIngredients = ItemHelper.condenseIngredients(recipe.getIngredients());
int size = actualIngredients.size() + recipe.getFluidIngredients()
.size();
int outSize = recipe.getFluidResults().size() + recipe.getRollableResults().size();
int xOffset = size < 3 ? (3 - size) * 19 / 2 : 0;
HeatCondition requiredHeat = recipe.getRequiredHeat(); HeatCondition requiredHeat = recipe.getRequiredHeat();
int yOffset = 0;
for (int i = 0; i < size; i++)
AllGuiTextures.JEI_SLOT.render(matrixStack, 16 + xOffset + (i % 3) * 19, 50 - (i / 3) * 19 + yOffset);
boolean noHeat = requiredHeat == HeatCondition.NONE; boolean noHeat = requiredHeat == HeatCondition.NONE;
int vRows = (1 + outSize) / 2; int vRows = (1 + recipe.getFluidResults().size() + recipe.getRollableResults().size()) / 2;
for (int i = 0; i < outSize; i++)
AllGuiTextures.JEI_SLOT.render(matrixStack,
141 - (outSize % 2 != 0 && i == outSize - 1 ? 0 : i % 2 == 0 ? 10 : -9), -19 * (i / 2) + 50 + yOffset);
if (vRows <= 2) if (vRows <= 2)
AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 136, -19 * (vRows - 1) + 32 + yOffset); AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 136, -19 * (vRows - 1) + 32);
AllGuiTextures shadow = noHeat ? AllGuiTextures.JEI_SHADOW : AllGuiTextures.JEI_LIGHT; AllGuiTextures shadow = noHeat ? AllGuiTextures.JEI_SHADOW : AllGuiTextures.JEI_LIGHT;
shadow.render(matrixStack, 81, 58 + (noHeat ? 10 : 30)); shadow.render(matrixStack, 81, 58 + (noHeat ? 10 : 30));
@ -178,7 +137,7 @@ public class BasinCategory extends CreateRecipeCategory<BasinRecipe> {
AllGuiTextures heatBar = noHeat ? AllGuiTextures.JEI_NO_HEAT_BAR : AllGuiTextures.JEI_HEAT_BAR; AllGuiTextures heatBar = noHeat ? AllGuiTextures.JEI_NO_HEAT_BAR : AllGuiTextures.JEI_HEAT_BAR;
heatBar.render(matrixStack, 4, 80); heatBar.render(matrixStack, 4, 80);
Minecraft.getInstance().font.draw(matrixStack, Lang.translate(requiredHeat.getTranslationKey()), 9, Minecraft.getInstance().font.draw(matrixStack, Lang.translate(requiredHeat.getTranslationKey()), 9,
86, requiredHeat.getColor()); 86, requiredHeat.getColor());
} }
} }

View file

@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.compat.jei.category.BlockCuttingCategory.CondensedBlockCuttingRecipe; import com.simibubi.create.compat.jei.category.BlockCuttingCategory.CondensedBlockCuttingRecipe;
@ -11,10 +13,10 @@ import com.simibubi.create.compat.jei.category.animations.AnimatedSaw;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.RecipeIngredientRole;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -22,9 +24,10 @@ import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.StonecutterRecipe; import net.minecraft.world.item.crafting.StonecutterRecipe;
@ParametersAreNonnullByDefault
public class BlockCuttingCategory extends CreateRecipeCategory<CondensedBlockCuttingRecipe> { public class BlockCuttingCategory extends CreateRecipeCategory<CondensedBlockCuttingRecipe> {
private AnimatedSaw saw = new AnimatedSaw(); private final AnimatedSaw saw = new AnimatedSaw();
public BlockCuttingCategory(Item symbol) { public BlockCuttingCategory(Item symbol) {
super(doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), symbol), emptyBackground(177, 70)); // Items.STONE_BRICK_STAIRS super(doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), symbol), emptyBackground(177, 70)); // Items.STONE_BRICK_STAIRS
@ -36,36 +39,29 @@ public class BlockCuttingCategory extends CreateRecipeCategory<CondensedBlockCut
} }
@Override @Override
public void setIngredients(CondensedBlockCuttingRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, CondensedBlockCuttingRecipe recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients());
ingredients.setOutputs(VanillaTypes.ITEM, recipe.getOutputs());
}
@Override
public void setRecipe(IRecipeLayout recipeLayout, CondensedBlockCuttingRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
itemStacks.init(0, true, 4, 4);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getItems()));
List<List<ItemStack>> results = recipe.getCondensedOutputs(); List<List<ItemStack>> results = recipe.getCondensedOutputs();
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) {
int xOffset = (outputIndex % 5) * 19;
int yOffset = (outputIndex / 5) * -19;
itemStacks.init(outputIndex + 1, false, 77 + xOffset, 47 + yOffset); builder
itemStacks.set(outputIndex + 1, results.get(outputIndex)); .addSlot(RecipeIngredientRole.INPUT, 5, 5)
.setBackground(getRenderedSlot(), -1 , -1)
.addItemStacks(Arrays.asList(recipe.getIngredients().get(0).getItems()));
int i = 0;
for (List<ItemStack> itemStacks : results) {
int xPos = 78 + (i % 5) * 19;
int yPos = 48 + (i / 5) * -19;
builder
.addSlot(RecipeIngredientRole.OUTPUT, xPos, yPos)
.setBackground(getRenderedSlot(), -1 , -1)
.addItemStacks(itemStacks);
i++;
} }
} }
@Override @Override
public void draw(CondensedBlockCuttingRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) { public void draw(CondensedBlockCuttingRecipe recipe, IRecipeSlotsView recipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.render(matrixStack, 4, 4);
int size = Math.min(recipe.getOutputs().size(), 15);
for (int i = 0; i < size; i++) {
int xOffset = (i % 5) * 19;
int yOffset = (i / 5) * -19;
AllGuiTextures.JEI_SLOT.render(matrixStack, 77 + xOffset, 47 + yOffset);
}
AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 31, 6); AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 31, 6);
AllGuiTextures.JEI_SHADOW.render(matrixStack, 33 - 17, 37 + 13); AllGuiTextures.JEI_SHADOW.render(matrixStack, 33 - 17, 37 + 13);
saw.draw(matrixStack, 33, 37); saw.draw(matrixStack, 33, 37);

View file

@ -2,26 +2,32 @@ package com.simibubi.create.compat.jei.category;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.ParametersAreNonnullByDefault;
import org.jetbrains.annotations.NotNull;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllFluids; import com.simibubi.create.AllFluids;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.compat.jei.DoubleItemIcon; import com.simibubi.create.compat.jei.DoubleItemIcon;
import com.simibubi.create.compat.jei.EmptyBackground; import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler;
import com.simibubi.create.content.contraptions.processing.ProcessingOutput; import com.simibubi.create.content.contraptions.processing.ProcessingOutput;
import com.simibubi.create.content.contraptions.processing.ProcessingRecipe;
import com.simibubi.create.foundation.fluid.FluidIngredient;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup;
import mezz.jei.api.gui.ingredient.IRecipeSlotTooltipCallback; import mezz.jei.api.gui.ingredient.IRecipeSlotTooltipCallback;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.category.IRecipeCategory; import mezz.jei.api.recipe.category.IRecipeCategory;
import mezz.jei.api.registration.IRecipeRegistration;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -30,15 +36,20 @@ import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.ItemLike;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public abstract class CreateRecipeCategory<T extends Recipe<?>> implements IRecipeCategory<T> { public abstract class CreateRecipeCategory<T extends Recipe<?>> implements IRecipeCategory<T> {
public final List<Supplier<List<? extends Recipe<?>>>> recipes = new ArrayList<>(); public final List<Supplier<List<T>>> recipes = new ArrayList<>();
public final List<Supplier<? extends ItemStack>> recipeCatalysts = new ArrayList<>(); public final List<Supplier<? extends ItemStack>> recipeCatalysts = new ArrayList<>();
protected ResourceLocation uid;
protected String name; protected String name;
private IDrawable background; protected RecipeType<T> type;
private IDrawable icon; private final IDrawable background;
private final IDrawable icon;
private static final IDrawable basicSlot = asDrawable(AllGuiTextures.JEI_SLOT);
private static final IDrawable chanceSlot = asDrawable(AllGuiTextures.JEI_CHANCE_SLOT);
public CreateRecipeCategory(IDrawable icon, IDrawable background) { public CreateRecipeCategory(IDrawable icon, IDrawable background) {
this.background = background; this.background = background;
@ -46,13 +57,22 @@ public abstract class CreateRecipeCategory<T extends Recipe<?>> implements IReci
} }
public void setCategoryId(String name) { public void setCategoryId(String name) {
this.uid = Create.asResource(name);
this.name = name; this.name = name;
this.type = RecipeType.create(Create.ID, name, getRecipeClass());
} }
@Override @Override
public ResourceLocation getUid() { public ResourceLocation getUid() {
return uid; return getRecipeType().getUid();
}
@Override
public abstract Class<? extends T> getRecipeClass();
@NotNull
@Override
public RecipeType<T> getRecipeType() {
return type;
} }
@Override @Override
@ -70,19 +90,23 @@ public abstract class CreateRecipeCategory<T extends Recipe<?>> implements IReci
return icon; return icon;
} }
public static AllGuiTextures getRenderedSlot(Recipe<?> recipe, int index) { public void registerRecipes(IRecipeRegistration registration) {
AllGuiTextures jeiSlot = AllGuiTextures.JEI_SLOT; recipes.forEach(s -> registration.addRecipes(getRecipeType(), s.get()));
if (!(recipe instanceof ProcessingRecipe)) }
return jeiSlot;
ProcessingRecipe<?> processingRecipe = (ProcessingRecipe<?>) recipe; public static IDrawable getRenderedSlot() {
List<ProcessingOutput> rollableResults = processingRecipe.getRollableResults(); return basicSlot;
if (rollableResults.size() <= index) }
return jeiSlot;
if (processingRecipe.getRollableResults() public static IDrawable getRenderedSlot(ProcessingOutput output) {
.get(index) return getRenderedSlot(output.getChance());
.getChance() == 1) }
return jeiSlot;
return AllGuiTextures.JEI_CHANCE_SLOT; public static IDrawable getRenderedSlot(float chance) {
if (chance == 1)
return basicSlot;
return chanceSlot;
} }
public static IDrawable emptyBackground(int width, int height) { public static IDrawable emptyBackground(int width, int height) {
@ -97,25 +121,6 @@ public abstract class CreateRecipeCategory<T extends Recipe<?>> implements IReci
return new DoubleItemIcon(() -> new ItemStack(item), () -> ItemStack.EMPTY); return new DoubleItemIcon(() -> new ItemStack(item), () -> ItemStack.EMPTY);
} }
public static void addStochasticTooltip(IGuiItemStackGroup itemStacks, List<ProcessingOutput> results) {
addStochasticTooltip(itemStacks, results, 1);
}
public static void addStochasticTooltip(IGuiItemStackGroup itemStacks, List<ProcessingOutput> results,
int startIndex) {
itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> {
if (input)
return;
if (slotIndex < startIndex)
return;
ProcessingOutput output = results.get(slotIndex - startIndex);
float chance = output.getChance();
if (chance != 1)
tooltip.add(1, Lang.translate("recipe.processing.chance", chance < 0.01 ? "<1" : (int) (chance * 100))
.withStyle(ChatFormatting.GOLD));
});
}
public static IRecipeSlotTooltipCallback addStochasticTooltip(ProcessingOutput output) { public static IRecipeSlotTooltipCallback addStochasticTooltip(ProcessingOutput output) {
return (view, tooltip) -> { return (view, tooltip) -> {
float chance = output.getChance(); float chance = output.getChance();
@ -138,46 +143,59 @@ public abstract class CreateRecipeCategory<T extends Recipe<?>> implements IReci
return display; return display;
} }
public static void addFluidTooltip(IGuiFluidStackGroup fluidStacks, List<FluidIngredient> inputs, public static IRecipeSlotTooltipCallback addFluidTooltip() {
List<FluidStack> outputs) { return addFluidTooltip(-1);
addFluidTooltip(fluidStacks, inputs, outputs, -1);
} }
public static void addFluidTooltip(IGuiFluidStackGroup fluidStacks, List<FluidIngredient> inputs, public static IRecipeSlotTooltipCallback addFluidTooltip(int mbAmount) {
List<FluidStack> outputs, int index) { return (view, tooltip) -> {
List<Integer> amounts = new ArrayList<>(); Optional<FluidStack> displayed = view.getDisplayedIngredient(VanillaTypes.FLUID);
inputs.forEach(f -> amounts.add(f.getRequiredAmount())); if (displayed.isEmpty())
outputs.forEach(f -> amounts.add(f.getAmount()));
fluidStacks.addTooltipCallback((slotIndex, input, fluid, tooltip) -> {
if (index != -1 && slotIndex != index)
return; return;
if (fluid.getFluid() FluidStack fluidStack = displayed.get();
.isSame(AllFluids.POTION.get())) {
Component name = fluid.getDisplayName(); if (fluidStack.getFluid().isSame(AllFluids.POTION.get())) {
Component name = fluidStack.getDisplayName();
if (tooltip.isEmpty()) if (tooltip.isEmpty())
tooltip.add(0, name); tooltip.add(0, name);
else else
tooltip.set(0, name); tooltip.set(0, name);
ArrayList<Component> potionTooltip = new ArrayList<>(); ArrayList<Component> potionTooltip = new ArrayList<>();
PotionFluidHandler.addPotionTooltip(fluid, potionTooltip, 1); PotionFluidHandler.addPotionTooltip(fluidStack, potionTooltip, 1);
tooltip.addAll(1, potionTooltip.stream() tooltip.addAll(1, potionTooltip.stream().toList());
.collect(Collectors.toList()));
} }
int amount = amounts.get(index != -1 ? 0 : slotIndex); int amount = mbAmount == -1 ? fluidStack.getAmount() : mbAmount;
Component text = new TextComponent(String.valueOf(amount)).append(Lang.translate("generic.unit.millibuckets")).withStyle(ChatFormatting.GOLD); Component text = new TextComponent(String.valueOf(amount)).append(Lang.translate("generic.unit.millibuckets")).withStyle(ChatFormatting.GOLD);
if (tooltip.isEmpty()) if (tooltip.isEmpty())
tooltip.add(0, text); tooltip.add(0, text);
else { else {
List<Component> siblings = tooltip.get(0) List<Component> siblings = tooltip.get(0).getSiblings();
.getSiblings();
siblings.add(new TextComponent(" ")); siblings.add(new TextComponent(" "));
siblings.add(text); siblings.add(text);
} }
}); };
}
private static IDrawable asDrawable(AllGuiTextures texture) {
return new IDrawable() {
@Override
public int getWidth() {
return texture.width;
}
@Override
public int getHeight() {
return texture.height;
}
@Override
public void draw(PoseStack poseStack, int xOffset, int yOffset) {
texture.render(poseStack, xOffset, yOffset);
}
};
} }
} }

View file

@ -1,24 +1,29 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.Arrays; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.compat.jei.category.animations.AnimatedCrushingWheels; import com.simibubi.create.compat.jei.category.animations.AnimatedCrushingWheels;
import com.simibubi.create.content.contraptions.components.crusher.AbstractCrushingRecipe; import com.simibubi.create.content.contraptions.components.crusher.AbstractCrushingRecipe;
import com.simibubi.create.content.contraptions.processing.ProcessingOutput; import com.simibubi.create.content.contraptions.processing.ProcessingOutput;
import com.simibubi.create.content.contraptions.processing.ProcessingRecipe;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.ponder.ui.LayoutHelper;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.RecipeIngredientRole;
@ParametersAreNonnullByDefault
public class CrushingCategory extends CreateRecipeCategory<AbstractCrushingRecipe> { public class CrushingCategory extends CreateRecipeCategory<AbstractCrushingRecipe> {
private AnimatedCrushingWheels crushingWheels = new AnimatedCrushingWheels(); private final AnimatedCrushingWheels crushingWheels = new AnimatedCrushingWheels();
public CrushingCategory() { public CrushingCategory() {
super(doubleItemIcon(AllBlocks.CRUSHING_WHEEL.get(), AllItems.CRUSHED_GOLD.get()), emptyBackground(177, 100)); super(doubleItemIcon(AllBlocks.CRUSHING_WHEEL.get(), AllItems.CRUSHED_GOLD.get()), emptyBackground(177, 100));
@ -30,41 +35,45 @@ public class CrushingCategory extends CreateRecipeCategory<AbstractCrushingRecip
} }
@Override @Override
public void setIngredients(AbstractCrushingRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, AbstractCrushingRecipe recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients()); builder
ingredients.setOutputs(VanillaTypes.ITEM, recipe.getRollableResultsAsItemStacks()); .addSlot(RecipeIngredientRole.INPUT, 51, 3)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredients(recipe.getIngredients().get(0));
int xOffset = getBackground().getWidth() / 2;
int yOffset = 86;
layoutOutput(recipe).forEach(layoutEntry -> builder
.addSlot(RecipeIngredientRole.OUTPUT, (xOffset) + layoutEntry.posX() + 1, yOffset + layoutEntry.posY() + 1)
.setBackground(getRenderedSlot(layoutEntry.output()), -1, -1)
.addItemStack(layoutEntry.output().getStack())
.addTooltipCallback(addStochasticTooltip(layoutEntry.output()))
);
} }
@Override private List<LayoutEntry> layoutOutput(ProcessingRecipe<?> recipe) {
public void setRecipe(IRecipeLayout recipeLayout, AbstractCrushingRecipe recipe, IIngredients ingredients) { int size = recipe.getRollableResults().size();
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); List<LayoutEntry> positions = new ArrayList<>(size);
itemStacks.init(0, true, 50, 2);
itemStacks.set(0, Arrays.asList(recipe.getIngredients()
.get(0)
.getItems()));
List<ProcessingOutput> results = recipe.getRollableResults(); LayoutHelper layout = LayoutHelper.centeredHorizontal(size, 1, 18, 18, 1);
int size = results.size(); for (ProcessingOutput result : recipe.getRollableResults()) {
int offset = -size * 19 / 2; positions.add(new LayoutEntry(result, layout.getX(), layout.getY()));
for (int outputIndex = 0; outputIndex < size; outputIndex++) { layout.next();
itemStacks.init(outputIndex + 1, false, getBackground().getWidth() / 2 + offset + 19 * outputIndex, 78);
itemStacks.set(outputIndex + 1, results.get(outputIndex)
.getStack());
} }
addStochasticTooltip(itemStacks, results); return positions;
} }
@Override private record LayoutEntry(
public void draw(AbstractCrushingRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) { ProcessingOutput output,
List<ProcessingOutput> results = recipe.getRollableResults(); int posX,
AllGuiTextures.JEI_SLOT.render(matrixStack, 50, 2); int posY
AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 72, 7); ) {}
int size = results.size(); @Override
int offset = -size * 19 / 2; public void draw(AbstractCrushingRecipe recipe, IRecipeSlotsView recipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 72, 7);
getRenderedSlot(recipe, outputIndex).render(matrixStack, getBackground().getWidth() / 2 + offset + 19 * outputIndex, 78);
crushingWheels.draw(matrixStack, 62, 59); crushingWheels.draw(matrixStack, 62, 59);
} }

View file

@ -1,29 +1,28 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.Arrays; import javax.annotation.ParametersAreNonnullByDefault;
import java.util.stream.Collectors;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.compat.jei.category.animations.AnimatedDeployer; import com.simibubi.create.compat.jei.category.animations.AnimatedDeployer;
import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe;
import com.simibubi.create.foundation.fluid.FluidIngredient;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.builder.IRecipeSlotBuilder;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
@ParametersAreNonnullByDefault
public class DeployingCategory extends CreateRecipeCategory<DeployerApplicationRecipe> { public class DeployingCategory extends CreateRecipeCategory<DeployerApplicationRecipe> {
AnimatedDeployer deployer; private final AnimatedDeployer deployer = new AnimatedDeployer();
public DeployingCategory() { public DeployingCategory() {
super(itemIcon(AllBlocks.DEPLOYER.get()), emptyBackground(177, 70)); super(itemIcon(AllBlocks.DEPLOYER.get()), emptyBackground(177, 70));
deployer = new AnimatedDeployer();
} }
@Override @Override
@ -32,49 +31,29 @@ public class DeployingCategory extends CreateRecipeCategory<DeployerApplicationR
} }
@Override @Override
public void setIngredients(DeployerApplicationRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, DeployerApplicationRecipe recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients()); builder
ingredients.setInputLists(VanillaTypes.FLUID, recipe.getFluidIngredients() .addSlot(RecipeIngredientRole.INPUT, 27, 51)
.stream() .setBackground(getRenderedSlot(), -1, -1)
.map(FluidIngredient::getMatchingFluidStacks) .addIngredients(recipe.getProcessedItem());
.collect(Collectors.toList())); IRecipeSlotBuilder handItemSlot = builder
.addSlot(RecipeIngredientRole.INPUT, 51, 5)
if (!recipe.getRollableResults() .setBackground(getRenderedSlot(), -1, -1)
.isEmpty()) .addIngredients(recipe.getRequiredHeldItem());
ingredients.setOutput(VanillaTypes.ITEM, recipe.getResultItem()); builder
} .addSlot(RecipeIngredientRole.OUTPUT, 132, 51)
.setBackground(getRenderedSlot(recipe.getRollableResults().get(0)), -1, -1)
@Override .addItemStack(recipe.getResultItem())
public void setRecipe(IRecipeLayout recipeLayout, DeployerApplicationRecipe recipe, IIngredients ingredients) { .addTooltipCallback(addStochasticTooltip(recipe.getRollableResults().get(0)));
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
itemStacks.init(0, true, 26, 50);
itemStacks.set(0, Arrays.asList(recipe.getProcessedItem()
.getItems()));
itemStacks.init(1, true, 50, 4);
itemStacks.set(1, Arrays.asList(recipe.getRequiredHeldItem()
.getItems()));
itemStacks.init(2, false, 131, 50);
itemStacks.set(2, recipe.getResultItem());
if (recipe.shouldKeepHeldItem()) { if (recipe.shouldKeepHeldItem()) {
itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> { handItemSlot.addTooltipCallback((recipeSlotView, tooltip) -> tooltip.add(1, Lang.translate("recipe.deploying.not_consumed").withStyle(ChatFormatting.GOLD)));
if (!input)
return;
if (slotIndex != 1)
return;
tooltip.add(1, Lang.translate("recipe.deploying.not_consumed")
.withStyle(ChatFormatting.GOLD));
});
} }
addStochasticTooltip(itemStacks, recipe.getRollableResults(), 2);
} }
@Override @Override
public void draw(DeployerApplicationRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) { public void draw(DeployerApplicationRecipe recipe, IRecipeSlotsView recipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.render(matrixStack, 50, 4);
AllGuiTextures.JEI_SLOT.render(matrixStack, 26, 50);
getRenderedSlot(recipe, 0).render(matrixStack, 131, 50);
AllGuiTextures.JEI_SHADOW.render(matrixStack, 62, 57); AllGuiTextures.JEI_SHADOW.render(matrixStack, 62, 57);
AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 126, 29); AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 126, 29);
deployer.draw(matrixStack, getBackground().getWidth() / 2 - 13, 22); deployer.draw(matrixStack, getBackground().getWidth() / 2 - 13, 22);

View file

@ -1,5 +1,7 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import org.jetbrains.annotations.NotNull;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
@ -27,7 +29,7 @@ public class FanBlastingCategory extends ProcessingViaFanCategory<AbstractCookin
} }
@Override @Override
protected void renderAttachedBlock(PoseStack matrixStack) { protected void renderAttachedBlock(@NotNull PoseStack matrixStack) {
GuiGameElement.of(Fluids.LAVA) GuiGameElement.of(Fluids.LAVA)
.scale(SCALE) .scale(SCALE)
.atLocal(0, 0, 2) .atLocal(0, 0, 2)

View file

@ -1,5 +1,7 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import org.jetbrains.annotations.NotNull;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
@ -27,7 +29,7 @@ public class FanHauntingCategory extends ProcessingViaFanCategory.MultiOutput<Ha
} }
@Override @Override
protected void renderAttachedBlock(PoseStack matrixStack) { protected void renderAttachedBlock(@NotNull PoseStack matrixStack) {
GuiGameElement.of(Blocks.SOUL_FIRE.defaultBlockState()) GuiGameElement.of(Blocks.SOUL_FIRE.defaultBlockState())
.scale(SCALE) .scale(SCALE)
.atLocal(0, 0, 2) .atLocal(0, 0, 2)

View file

@ -1,5 +1,7 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import org.jetbrains.annotations.NotNull;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
@ -27,7 +29,7 @@ public class FanSmokingCategory extends ProcessingViaFanCategory<SmokingRecipe>
} }
@Override @Override
protected void renderAttachedBlock(PoseStack matrixStack) { protected void renderAttachedBlock(@NotNull PoseStack matrixStack) {
GuiGameElement.of(Blocks.FIRE.defaultBlockState()) GuiGameElement.of(Blocks.FIRE.defaultBlockState())
.scale(SCALE) .scale(SCALE)
.atLocal(0, 0, 2) .atLocal(0, 0, 2)

View file

@ -1,5 +1,7 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import org.jetbrains.annotations.NotNull;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
@ -21,7 +23,7 @@ public class FanWashingCategory extends ProcessingViaFanCategory.MultiOutput<Spl
} }
@Override @Override
protected void renderAttachedBlock(PoseStack matrixStack) { protected void renderAttachedBlock(@NotNull PoseStack matrixStack) {
GuiGameElement.of(Fluids.WATER) GuiGameElement.of(Fluids.WATER)
.scale(SCALE) .scale(SCALE)
.atLocal(0, 0, 2) .atLocal(0, 0, 2)

View file

@ -1,8 +1,9 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.Arrays;
import java.util.Optional; import java.util.Optional;
import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Vector3f; import com.mojang.math.Vector3f;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
@ -23,6 +24,7 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
@ParametersAreNonnullByDefault
public class ItemApplicationCategory extends CreateRecipeCategory<ItemApplicationRecipe> { public class ItemApplicationCategory extends CreateRecipeCategory<ItemApplicationRecipe> {
public ItemApplicationCategory() { public ItemApplicationCategory() {
@ -37,31 +39,27 @@ public class ItemApplicationCategory extends CreateRecipeCategory<ItemApplicatio
@Override @Override
public void setRecipe(IRecipeLayoutBuilder builder, ItemApplicationRecipe recipe, IFocusGroup focuses) { public void setRecipe(IRecipeLayoutBuilder builder, ItemApplicationRecipe recipe, IFocusGroup focuses) {
builder.addSlot(RecipeIngredientRole.INPUT, 27, 38) builder.addSlot(RecipeIngredientRole.INPUT, 27, 38)
.addItemStacks(Arrays.asList(recipe.getProcessedItem() .setBackground(getRenderedSlot(), -1, -1)
.getItems())); .addIngredients(recipe.getProcessedItem());
builder.addSlot(RecipeIngredientRole.INPUT, 51, 5) builder.addSlot(RecipeIngredientRole.INPUT, 51, 5)
.addItemStacks(Arrays.asList(recipe.getRequiredHeldItem() .setBackground(getRenderedSlot(), -1, -1)
.getItems())) .addIngredients(recipe.getRequiredHeldItem())
.addTooltipCallback( .addTooltipCallback(
recipe.shouldKeepHeldItem() recipe.shouldKeepHeldItem()
? (view, tooltip) -> tooltip.add(1, Lang.translate("recipe.deploying.not_consumed") ? (view, tooltip) -> tooltip.add(1, Lang.translate("recipe.deploying.not_consumed")
.withStyle(ChatFormatting.GOLD)) .withStyle(ChatFormatting.GOLD))
: (view, tooltip) -> { : (view, tooltip) -> {}
}); );
builder.addSlot(RecipeIngredientRole.OUTPUT, 132, 38) builder.addSlot(RecipeIngredientRole.OUTPUT, 132, 38)
.addItemStack(recipe.getResultItem()) .setBackground(getRenderedSlot(recipe.getRollableResults().get(0)), -1, -1)
.addTooltipCallback(addStochasticTooltip(recipe.getRollableResults() .addItemStack(recipe.getResultItem())
.get(0))); .addTooltipCallback(addStochasticTooltip(recipe.getRollableResults().get(0)));
} }
@Override @Override
public void draw(ItemApplicationRecipe recipe, IRecipeSlotsView recipeSlotsView, PoseStack matrixStack, public void draw(ItemApplicationRecipe recipe, IRecipeSlotsView recipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.render(matrixStack, 50, 4);
AllGuiTextures.JEI_SLOT.render(matrixStack, 26, 37);
getRenderedSlot(recipe, 0).render(matrixStack, 131, 37);
AllGuiTextures.JEI_SHADOW.render(matrixStack, 62, 47); AllGuiTextures.JEI_SHADOW.render(matrixStack, 62, 47);
AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 74, 10); AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 74, 10);

View file

@ -1,11 +1,9 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import com.google.common.collect.ImmutableList; import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create; import com.simibubi.create.Create;
@ -16,10 +14,10 @@ import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuild
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.RecipeIngredientRole;
import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.api.runtime.IIngredientManager;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -32,6 +30,7 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
import net.minecraftforge.fluids.capability.IFluidHandlerItem; import net.minecraftforge.fluids.capability.IFluidHandlerItem;
@ParametersAreNonnullByDefault
public class ItemDrainCategory extends CreateRecipeCategory<EmptyingRecipe> { public class ItemDrainCategory extends CreateRecipeCategory<EmptyingRecipe> {
AnimatedItemDrain drain; AnimatedItemDrain drain;
@ -90,41 +89,24 @@ public class ItemDrainCategory extends CreateRecipeCategory<EmptyingRecipe> {
} }
@Override @Override
public void setIngredients(EmptyingRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, EmptyingRecipe recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients()); builder
.addSlot(RecipeIngredientRole.INPUT, 27, 8)
if (!recipe.getRollableResults() .setBackground(getRenderedSlot(), -1, -1)
.isEmpty()) .addIngredients(recipe.getIngredients().get(0));
ingredients.setOutput(VanillaTypes.ITEM, recipe.getResultItem()); builder
if (!recipe.getFluidResults() .addSlot(RecipeIngredientRole.OUTPUT, 132, 8)
.isEmpty()) .setBackground(getRenderedSlot(), -1, -1)
ingredients.setOutputs(VanillaTypes.FLUID, recipe.getFluidResults()); .addIngredient(VanillaTypes.FLUID, withImprovedVisibility(recipe.getResultingFluid()))
.addTooltipCallback(addFluidTooltip(recipe.getResultingFluid().getAmount()));
builder
.addSlot(RecipeIngredientRole.OUTPUT, 132, 27)
.setBackground(getRenderedSlot(), -1, -1)
.addItemStack(recipe.getResultItem());
} }
@Override @Override
public void setRecipe(IRecipeLayout recipeLayout, EmptyingRecipe recipe, IIngredients ingredients) { public void draw(EmptyingRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
IGuiFluidStackGroup fluidStacks = recipeLayout.getFluidStacks();
FluidStack fluidOutput = recipe.getResultingFluid();
List<ItemStack> matchingIngredients = Arrays.asList(recipe.getIngredients()
.get(0)
.getItems());
fluidStacks.init(0, false, 132, 8);
fluidStacks.set(0, withImprovedVisibility(fluidOutput));
itemStacks.init(0, true, 26, 7);
itemStacks.set(0, matchingIngredients);
itemStacks.init(1, false, 131, 26);
itemStacks.set(1, recipe.getResultItem());
addFluidTooltip(fluidStacks, Collections.emptyList(), ImmutableList.of(fluidOutput));
}
@Override
public void draw(EmptyingRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.render(matrixStack, 131, 7);
AllGuiTextures.JEI_SLOT.render(matrixStack, 26, 7);
getRenderedSlot(recipe, 0).render(matrixStack, 131, 26);
AllGuiTextures.JEI_SHADOW.render(matrixStack, 62, 37); AllGuiTextures.JEI_SHADOW.render(matrixStack, 62, 37);
AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 73, 4); AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 73, 4);
drain.withFluid(recipe.getResultingFluid()) drain.withFluid(recipe.getResultingFluid())

View file

@ -1,9 +1,12 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import org.jetbrains.annotations.NotNull;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
@ -11,15 +14,15 @@ import com.simibubi.create.compat.jei.category.animations.AnimatedCrafter;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.ingredients.IIngredientRenderer; import mezz.jei.api.ingredients.IIngredientRenderer;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.core.NonNullList;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
@ -29,6 +32,7 @@ import net.minecraft.world.item.crafting.CraftingRecipe;
import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Ingredient;
import net.minecraftforge.common.crafting.IShapedRecipe; import net.minecraftforge.common.crafting.IShapedRecipe;
@ParametersAreNonnullByDefault
public class MechanicalCraftingCategory extends CreateRecipeCategory<CraftingRecipe> { public class MechanicalCraftingCategory extends CreateRecipeCategory<CraftingRecipe> {
private final AnimatedCrafter crafter = new AnimatedCrafter(); private final AnimatedCrafter crafter = new AnimatedCrafter();
@ -38,35 +42,33 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<CraftingRec
} }
@Override @Override
public void setIngredients(CraftingRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, CraftingRecipe recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients()); builder
ingredients.setOutput(VanillaTypes.ITEM, recipe.getResultItem()); .addSlot(RecipeIngredientRole.OUTPUT, 134, 81)
} .addItemStack(recipe.getResultItem());
@Override
public void setRecipe(IRecipeLayout recipeLayout, CraftingRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
NonNullList<Ingredient> recipeIngredients = recipe.getIngredients();
itemStacks.init(0, false, 133, 80);
itemStacks.set(0, recipe.getResultItem());
int x = getXPadding(recipe); int x = getXPadding(recipe);
int y = getYPadding(recipe); int y = getYPadding(recipe);
float scale = getScale(recipe); float scale = getScale(recipe);
int size = recipeIngredients.size();
IIngredientRenderer<ItemStack> renderer = new CrafterIngredientRenderer(recipe);
for (int i = 0; i < size; i++) { IIngredientRenderer<ItemStack> renderer = new CrafterIngredientRenderer(recipe);
int i = 0;
for (Ingredient ingredient : recipe.getIngredients()) {
float f = 19 * scale; float f = 19 * scale;
int slotSize = (int) (16 * scale); int slotSize = (int) (16 * scale);
int xPosition = (int) (x + 1 + (i % getWidth(recipe)) * f); int xPosition = (int) (x + 1 + (i % getWidth(recipe)) * f);
int yPosition = (int) (y + 1 + (i / getWidth(recipe)) * f); int yPosition = (int) (y + 1 + (i / getWidth(recipe)) * f);
itemStacks.init(i + 1, true, renderer, xPosition, yPosition, slotSize, slotSize, 0, 0);
itemStacks.set(i + 1, Arrays.asList(recipeIngredients.get(i) builder
.getItems())); .addSlot(RecipeIngredientRole.INPUT, xPosition, yPosition)
.setCustomRenderer(VanillaTypes.ITEM, renderer)
.addIngredients(ingredient);
i++;
} }
} }
static int maxSize = 100; static int maxSize = 100;
@ -94,7 +96,7 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<CraftingRec
} }
@Override @Override
public void draw(CraftingRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) { public void draw(CraftingRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
matrixStack.pushPose(); matrixStack.pushPose();
float scale = getScale(recipe); float scale = getScale(recipe);
matrixStack.translate(getXPadding(recipe), getYPadding(recipe), 0); matrixStack.translate(getXPadding(recipe), getYPadding(recipe), 0);
@ -139,13 +141,15 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<CraftingRec
private static final class CrafterIngredientRenderer implements IIngredientRenderer<ItemStack> { private static final class CrafterIngredientRenderer implements IIngredientRenderer<ItemStack> {
private final CraftingRecipe recipe; private final CraftingRecipe recipe;
private final float scale;
public CrafterIngredientRenderer(CraftingRecipe recipe) { public CrafterIngredientRenderer(CraftingRecipe recipe) {
this.recipe = recipe; this.recipe = recipe;
scale = getScale(recipe);
} }
@Override @Override
public void render(PoseStack matrixStack, int xPosition, int yPosition, ItemStack ingredient) { public void render(PoseStack matrixStack, @NotNull ItemStack ingredient) {
matrixStack.pushPose(); matrixStack.pushPose();
float scale = getScale(recipe); float scale = getScale(recipe);
matrixStack.scale(scale, scale, scale); matrixStack.scale(scale, scale, scale);
@ -160,8 +164,8 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<CraftingRec
Minecraft minecraft = Minecraft.getInstance(); Minecraft minecraft = Minecraft.getInstance();
Font font = getFontRenderer(minecraft, ingredient); Font font = getFontRenderer(minecraft, ingredient);
ItemRenderer itemRenderer = minecraft.getItemRenderer(); ItemRenderer itemRenderer = minecraft.getItemRenderer();
itemRenderer.renderAndDecorateFakeItem(ingredient, xPosition, yPosition); itemRenderer.renderAndDecorateFakeItem(ingredient, 0, 0);
itemRenderer.renderGuiItemDecorations(font, ingredient, xPosition, yPosition, null); itemRenderer.renderGuiItemDecorations(font, ingredient, 0, 0, null);
RenderSystem.disableBlend(); RenderSystem.disableBlend();
modelViewStack.popPose(); modelViewStack.popPose();
RenderSystem.applyModelViewMatrix(); RenderSystem.applyModelViewMatrix();
@ -170,6 +174,16 @@ public class MechanicalCraftingCategory extends CreateRecipeCategory<CraftingRec
matrixStack.popPose(); matrixStack.popPose();
} }
@Override
public int getWidth() {
return (int) (16 * scale);
}
@Override
public int getHeight() {
return (int) (16 * scale);
}
@Override @Override
public List<Component> getTooltip(ItemStack ingredient, TooltipFlag tooltipFlag) { public List<Component> getTooltip(ItemStack ingredient, TooltipFlag tooltipFlag) {
Minecraft minecraft = Minecraft.getInstance(); Minecraft minecraft = Minecraft.getInstance();

View file

@ -1,8 +1,9 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
@ -11,14 +12,15 @@ import com.simibubi.create.content.contraptions.components.crusher.AbstractCrush
import com.simibubi.create.content.contraptions.processing.ProcessingOutput; import com.simibubi.create.content.contraptions.processing.ProcessingOutput;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.RecipeIngredientRole;
@ParametersAreNonnullByDefault
public class MillingCategory extends CreateRecipeCategory<AbstractCrushingRecipe> { public class MillingCategory extends CreateRecipeCategory<AbstractCrushingRecipe> {
private AnimatedMillstone millstone = new AnimatedMillstone(); private final AnimatedMillstone millstone = new AnimatedMillstone();
public MillingCategory() { public MillingCategory() {
super(doubleItemIcon(AllBlocks.MILLSTONE.get(), AllItems.WHEAT_FLOUR.get()), emptyBackground(177, 53)); super(doubleItemIcon(AllBlocks.MILLSTONE.get(), AllItems.WHEAT_FLOUR.get()), emptyBackground(177, 53));
@ -30,54 +32,34 @@ public class MillingCategory extends CreateRecipeCategory<AbstractCrushingRecipe
} }
@Override @Override
public void setIngredients(AbstractCrushingRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, AbstractCrushingRecipe recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients()); builder
ingredients.setOutputs(VanillaTypes.ITEM, recipe.getRollableResultsAsItemStacks()); .addSlot(RecipeIngredientRole.INPUT, 15, 9)
} .setBackground(getRenderedSlot(), -1, -1)
.addIngredients(recipe.getIngredients().get(0));
@Override
public void setRecipe(IRecipeLayout recipeLayout, AbstractCrushingRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
itemStacks.init(0, true, 14, 8);
itemStacks.set(0, Arrays.asList(recipe.getIngredients()
.get(0)
.getItems()));
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableResults();
boolean single = results.size() == 1; boolean single = results.size() == 1;
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { int i = 0;
int xOffset = outputIndex % 2 == 0 ? 0 : 19; for (ProcessingOutput output : results) {
int yOffset = (outputIndex / 2) * -19; int xOffset = i % 2 == 0 ? 0 : 19;
int yOffset = (i / 2) * -19;
itemStacks.init(outputIndex + 1, false, single ? 139 : 133 + xOffset, 27 + yOffset); builder
itemStacks.set(outputIndex + 1, results.get(outputIndex) .addSlot(RecipeIngredientRole.OUTPUT, single ? 139 : 133 + xOffset, 27 + yOffset)
.getStack()); .setBackground(getRenderedSlot(output), -1, -1)
.addItemStack(output.getStack())
.addTooltipCallback(addStochasticTooltip(output));
i++;
} }
addStochasticTooltip(itemStacks, results);
} }
@Override @Override
public void draw(AbstractCrushingRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) { public void draw(AbstractCrushingRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
int size = recipe.getRollableResultsAsItemStacks()
.size();
AllGuiTextures.JEI_SLOT.render(matrixStack, 14, 8);
AllGuiTextures.JEI_ARROW.render(matrixStack, 85, 32); AllGuiTextures.JEI_ARROW.render(matrixStack, 85, 32);
AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 43, 4); AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 43, 4);
millstone.draw(matrixStack, 48, 27); millstone.draw(matrixStack, 48, 27);
if (size == 1) {
getRenderedSlot(recipe, 0).render(matrixStack, 139, 27);
return;
}
for (int i = 0; i < size; i++) {
int xOffset = i % 2 == 0 ? 0 : 19;
int yOffset = (i / 2) * -19;
getRenderedSlot(recipe, i).render(matrixStack, 133 + xOffset, 27 + yOffset);
}
} }
} }

View file

@ -1,5 +1,7 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.compat.jei.category.animations.AnimatedBlazeBurner; import com.simibubi.create.compat.jei.category.animations.AnimatedBlazeBurner;
@ -7,10 +9,12 @@ import com.simibubi.create.compat.jei.category.animations.AnimatedMixer;
import com.simibubi.create.content.contraptions.processing.BasinRecipe; import com.simibubi.create.content.contraptions.processing.BasinRecipe;
import com.simibubi.create.content.contraptions.processing.HeatCondition; import com.simibubi.create.content.contraptions.processing.HeatCondition;
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
@ParametersAreNonnullByDefault
public class MixingCategory extends BasinCategory { public class MixingCategory extends BasinCategory {
private final AnimatedMixer mixer = new AnimatedMixer(); private final AnimatedMixer mixer = new AnimatedMixer();
@ -18,7 +22,7 @@ public class MixingCategory extends BasinCategory {
MixingType type; MixingType type;
enum MixingType { enum MixingType {
AUTO_SHAPELESS, MIXING, AUTO_BREWING; AUTO_SHAPELESS, MIXING, AUTO_BREWING
} }
public static MixingCategory autoShapeless() { public static MixingCategory autoShapeless() {
@ -40,8 +44,9 @@ public class MixingCategory extends BasinCategory {
} }
@Override @Override
public void draw(BasinRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) { public void draw(BasinRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
super.draw(recipe, matrixStack, mouseX, mouseY); super.draw(recipe, iRecipeSlotsView, matrixStack, mouseX, mouseY);
HeatCondition requiredHeat = recipe.getRequiredHeat(); HeatCondition requiredHeat = recipe.getRequiredHeat();
if (requiredHeat != HeatCondition.NONE) if (requiredHeat != HeatCondition.NONE)
heater.withHeat(requiredHeat.visualizeAsBlazeBurner()) heater.withHeat(requiredHeat.visualizeAsBlazeBurner())

View file

@ -1,21 +1,22 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.compat.jei.ConversionRecipe; import com.simibubi.create.compat.jei.ConversionRecipe;
import com.simibubi.create.content.contraptions.processing.ProcessingOutput;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.RecipeIngredientRole;
@ParametersAreNonnullByDefault
public class MysteriousItemConversionCategory extends CreateRecipeCategory<ConversionRecipe> { public class MysteriousItemConversionCategory extends CreateRecipeCategory<ConversionRecipe> {
public static final List<ConversionRecipe> RECIPES = new ArrayList<>(); public static final List<ConversionRecipe> RECIPES = new ArrayList<>();
@ -37,25 +38,19 @@ public class MysteriousItemConversionCategory extends CreateRecipeCategory<Conve
} }
@Override @Override
public void setIngredients(ConversionRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, ConversionRecipe recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients()); builder
ingredients.setOutputs(VanillaTypes.ITEM, recipe.getRollableResultsAsItemStacks()); .addSlot(RecipeIngredientRole.INPUT, 27, 17)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredients(recipe.getIngredients().get(0));
builder
.addSlot(RecipeIngredientRole.OUTPUT, 132, 17)
.setBackground(getRenderedSlot(), -1, -1)
.addItemStack(recipe.getRollableResults().get(0).getStack());
} }
@Override @Override
public void setRecipe(IRecipeLayout recipeLayout, ConversionRecipe recipe, IIngredients ingredients) { public void draw(ConversionRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
List<ProcessingOutput> results = recipe.getRollableResults();
itemStacks.init(0, true, 26, 16);
itemStacks.set(0, Arrays.asList(recipe.getIngredients().get(0).getItems()));
itemStacks.init(1, false, 131, 16);
itemStacks.set(1, results.get(0).getStack());
}
@Override
public void draw(ConversionRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.render(matrixStack, 26, 16);
AllGuiTextures.JEI_SLOT.render(matrixStack, 131, 16);
AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 52, 20); AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 52, 20);
AllGuiTextures.JEI_QUESTION_MARK.render(matrixStack, 77, 5); AllGuiTextures.JEI_QUESTION_MARK.render(matrixStack, 77, 5);
} }

View file

@ -1,6 +1,6 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.Arrays; import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
@ -10,22 +10,24 @@ import com.simibubi.create.content.contraptions.processing.BasinRecipe;
import com.simibubi.create.content.contraptions.processing.HeatCondition; import com.simibubi.create.content.contraptions.processing.HeatCondition;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import net.minecraft.core.NonNullList; import net.minecraft.core.NonNullList;
import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
@ParametersAreNonnullByDefault
public class PackingCategory extends BasinCategory { public class PackingCategory extends BasinCategory {
private AnimatedPress press = new AnimatedPress(true); private final AnimatedPress press = new AnimatedPress(true);
private final AnimatedBlazeBurner heater = new AnimatedBlazeBurner(); private final AnimatedBlazeBurner heater = new AnimatedBlazeBurner();
private PackingType type; private final PackingType type;
enum PackingType { enum PackingType {
AUTO_SQUARE, COMPACTING; AUTO_SQUARE, COMPACTING
} }
public static PackingCategory standard() { public static PackingCategory standard() {
@ -43,51 +45,49 @@ public class PackingCategory extends BasinCategory {
} }
@Override @Override
public void setRecipe(IRecipeLayout recipeLayout, BasinRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, BasinRecipe recipe, IFocusGroup focuses) {
if (type == PackingType.COMPACTING) { if (type == PackingType.COMPACTING) {
super.setRecipe(recipeLayout, recipe, ingredients); super.setRecipe(builder, recipe, focuses);
return; return;
} }
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
int i = 0; int i = 0;
NonNullList<Ingredient> ingredients = recipe.getIngredients();
NonNullList<Ingredient> ingredients2 = recipe.getIngredients(); int size = ingredients.size();
int size = ingredients2.size();
int rows = size == 4 ? 2 : 3; int rows = size == 4 ? 2 : 3;
while (i < size) { while (i < size) {
Ingredient ingredient = ingredients2.get(i); Ingredient ingredient = ingredients.get(i);
itemStacks.init(i, true, (rows == 2 ? 26 : 17) + (i % rows) * 19, 50 - (i / rows) * 19); builder
itemStacks.set(i, Arrays.asList(ingredient.getItems())); .addSlot(RecipeIngredientRole.INPUT, (rows == 2 ? 27 : 18) + (i % rows) * 19, 51 - (i / rows) * 19)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredients(ingredient);
i++; i++;
} }
itemStacks.init(i, false, 141, 50); builder
itemStacks.set(i, recipe.getResultItem()); .addSlot(RecipeIngredientRole.OUTPUT, 142, 51)
.setBackground(getRenderedSlot(), -1, -1)
.addItemStack(recipe.getResultItem());
} }
@Override @Override
public void draw(BasinRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) { public void draw(BasinRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
if (type == PackingType.COMPACTING) { if (type == PackingType.COMPACTING) {
super.draw(recipe, matrixStack, mouseX, mouseY); super.draw(recipe, iRecipeSlotsView, matrixStack, mouseX, mouseY);
} else { } else {
NonNullList<Ingredient> ingredients2 = recipe.getIngredients();
int size = ingredients2.size();
int rows = size == 4 ? 2 : 3;
for (int i = 0; i < size; i++)
AllGuiTextures.JEI_SLOT.render(matrixStack, (rows == 2 ? 26 : 17) + (i % rows) * 19,
50 - (i / rows) * 19);
AllGuiTextures.JEI_SLOT.render(matrixStack, 141, 50);
AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 136, 32); AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 136, 32);
AllGuiTextures.JEI_SHADOW.render(matrixStack, 81, 68); AllGuiTextures.JEI_SHADOW.render(matrixStack, 81, 68);
} }
HeatCondition requiredHeat = recipe.getRequiredHeat(); HeatCondition requiredHeat = recipe.getRequiredHeat();
if (requiredHeat != HeatCondition.NONE) if (requiredHeat != HeatCondition.NONE)
heater.withHeat(requiredHeat.visualizeAsBlazeBurner()) heater.withHeat(requiredHeat.visualizeAsBlazeBurner())
.draw(matrixStack, getBackground().getWidth() / 2 + 3, 55); .draw(matrixStack, getBackground().getWidth() / 2 + 3, 55);
press.draw(matrixStack, getBackground().getWidth() / 2 + 3, 34); press.draw(matrixStack, getBackground().getWidth() / 2 + 3, 34);
} }
} }

View file

@ -1,7 +1,6 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.Arrays; import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
@ -10,18 +9,19 @@ import com.simibubi.create.content.curiosities.tools.SandPaperPolishingRecipe;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.element.GuiGameElement;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.RecipeIngredientRole;
import net.minecraft.core.NonNullList; import net.minecraft.core.NonNullList;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Ingredient;
@ParametersAreNonnullByDefault
public class PolishingCategory extends CreateRecipeCategory<SandPaperPolishingRecipe> { public class PolishingCategory extends CreateRecipeCategory<SandPaperPolishingRecipe> {
private ItemStack renderedSandpaper; private final ItemStack renderedSandpaper;
public PolishingCategory() { public PolishingCategory() {
super(itemIcon(AllItems.SAND_PAPER.get()), emptyBackground(177, 55)); super(itemIcon(AllItems.SAND_PAPER.get()), emptyBackground(177, 55));
@ -34,31 +34,22 @@ public class PolishingCategory extends CreateRecipeCategory<SandPaperPolishingRe
} }
@Override @Override
public void setIngredients(SandPaperPolishingRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, SandPaperPolishingRecipe recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients()); builder
ingredients.setOutputs(VanillaTypes.ITEM, recipe.getRollableResultsAsItemStacks()); .addSlot(RecipeIngredientRole.INPUT, 27, 29)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredients(recipe.getIngredients().get(0));
ProcessingOutput output = recipe.getRollableResults().get(0);
builder
.addSlot(RecipeIngredientRole.OUTPUT, 132, 29)
.setBackground(getRenderedSlot(output), -1, -1)
.addItemStack(output.getStack())
.addTooltipCallback(addStochasticTooltip(output));
} }
@Override @Override
public void setRecipe(IRecipeLayout recipeLayout, SandPaperPolishingRecipe recipe, IIngredients ingredients) { public void draw(SandPaperPolishingRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
List<ProcessingOutput> results = recipe.getRollableResults();
itemStacks.init(0, true, 26, 28);
itemStacks.set(0, Arrays.asList(recipe.getIngredients()
.get(0)
.getItems()));
itemStacks.init(1, false, 131, 28);
itemStacks.set(1, results.get(0)
.getStack());
addStochasticTooltip(itemStacks, results);
}
@Override
public void draw(SandPaperPolishingRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.render(matrixStack, 26, 28);
getRenderedSlot(recipe, 0).render(matrixStack, 131, 28);
AllGuiTextures.JEI_SHADOW.render(matrixStack, 61, 21); AllGuiTextures.JEI_SHADOW.render(matrixStack, 61, 21);
AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 52, 32); AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 52, 32);

View file

@ -1,8 +1,9 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
@ -11,14 +12,15 @@ import com.simibubi.create.content.contraptions.components.press.PressingRecipe;
import com.simibubi.create.content.contraptions.processing.ProcessingOutput; import com.simibubi.create.content.contraptions.processing.ProcessingOutput;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.RecipeIngredientRole;
@ParametersAreNonnullByDefault
public class PressingCategory extends CreateRecipeCategory<PressingRecipe> { public class PressingCategory extends CreateRecipeCategory<PressingRecipe> {
private AnimatedPress press = new AnimatedPress(false); private final AnimatedPress press = new AnimatedPress(false);
public PressingCategory() { public PressingCategory() {
super(doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), AllItems.IRON_SHEET.get()), emptyBackground(177, 70)); super(doubleItemIcon(AllBlocks.MECHANICAL_PRESS.get(), AllItems.IRON_SHEET.get()), emptyBackground(177, 70));
@ -30,38 +32,28 @@ public class PressingCategory extends CreateRecipeCategory<PressingRecipe> {
} }
@Override @Override
public void setIngredients(PressingRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, PressingRecipe recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients()); builder
ingredients.setOutputs(VanillaTypes.ITEM, recipe.getRollableResultsAsItemStacks()); .addSlot(RecipeIngredientRole.INPUT, 27, 51)
} .setBackground(getRenderedSlot(), -1, -1)
.addIngredients(recipe.getIngredients().get(0));
@Override
public void setRecipe(IRecipeLayout recipeLayout, PressingRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
itemStacks.init(0, true, 26, 50);
itemStacks.set(0, Arrays.asList(recipe.getIngredients()
.get(0)
.getItems()));
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableResults();
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { int i = 0;
itemStacks.init(outputIndex + 1, false, 131 + 19 * outputIndex, 50); for (ProcessingOutput output : results) {
itemStacks.set(outputIndex + 1, results.get(outputIndex) builder.addSlot(RecipeIngredientRole.OUTPUT, 131 + 19 * i, 50)
.getStack()); .setBackground(getRenderedSlot(output), -1, -1)
.addItemStack(output.getStack())
.addTooltipCallback(addStochasticTooltip(output));
i++;
} }
addStochasticTooltip(itemStacks, results);
} }
@Override @Override
public void draw(PressingRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) { public void draw(PressingRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.render(matrixStack, 26, 50);
getRenderedSlot(recipe, 0).render(matrixStack, 131, 50);
if (recipe.getRollableResults()
.size() > 1)
getRenderedSlot(recipe, 1).render(matrixStack, 131 + 19, 50);
AllGuiTextures.JEI_SHADOW.render(matrixStack, 61, 41); AllGuiTextures.JEI_SHADOW.render(matrixStack, 61, 41);
AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 52, 54); AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 52, 54);
press.draw(matrixStack, getBackground().getWidth() / 2 - 17, 22); press.draw(matrixStack, getBackground().getWidth() / 2 - 17, 22);
} }

View file

@ -3,6 +3,8 @@ package com.simibubi.create.compat.jei.category;
import java.util.List; import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Vector3f; import com.mojang.math.Vector3f;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
@ -13,14 +15,15 @@ import com.simibubi.create.content.contraptions.processing.ProcessingRecipe;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.drawable.IDrawable; import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.Recipe;
@ParametersAreNonnullByDefault
public abstract class ProcessingViaFanCategory<T extends Recipe<?>> extends CreateRecipeCategory<T> { public abstract class ProcessingViaFanCategory<T extends Recipe<?>> extends CreateRecipeCategory<T> {
protected static final int SCALE = 24; protected static final int SCALE = 24;
@ -39,24 +42,19 @@ public abstract class ProcessingViaFanCategory<T extends Recipe<?>> extends Crea
} }
@Override @Override
public void setIngredients(T recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, T recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients()); builder
ingredients.setOutput(VanillaTypes.ITEM, recipe.getResultItem()); .addSlot(RecipeIngredientRole.INPUT, 21, 48)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredients(recipe.getIngredients().get(0));
builder
.addSlot(RecipeIngredientRole.OUTPUT, 141, 48)
.setBackground(getRenderedSlot(), -1, -1)
.addItemStack(recipe.getResultItem());
} }
@Override @Override
public void setRecipe(IRecipeLayout recipeLayout, T recipe, IIngredients ingredients) { public void draw(T recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
itemStacks.init(0, true, 20, 47);
itemStacks.set(0, ingredients.getInputs(VanillaTypes.ITEM).get(0));
itemStacks.init(1, false, 140, 47);
itemStacks.set(1, ingredients.getOutputs(VanillaTypes.ITEM).get(0));
}
@Override
public void draw(T recipe, PoseStack matrixStack, double mouseX, double mouseY) {
renderWidgets(matrixStack, recipe, mouseX, mouseY); renderWidgets(matrixStack, recipe, mouseX, mouseY);
matrixStack.pushPose(); matrixStack.pushPose();
@ -83,8 +81,6 @@ public abstract class ProcessingViaFanCategory<T extends Recipe<?>> extends Crea
AllGuiTextures.JEI_SHADOW.render(matrixStack, 46, 29); AllGuiTextures.JEI_SHADOW.render(matrixStack, 46, 29);
getBlockShadow().render(matrixStack, 65, 39); getBlockShadow().render(matrixStack, 65, 39);
AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 54, 51); AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 54, 51);
AllGuiTextures.JEI_SLOT.render(matrixStack, 20, 47);
AllGuiTextures.JEI_SLOT.render(matrixStack, 140, 47);
} }
protected AllGuiTextures getBlockShadow() { protected AllGuiTextures getBlockShadow() {
@ -103,57 +99,40 @@ public abstract class ProcessingViaFanCategory<T extends Recipe<?>> extends Crea
super(icon); super(icon);
} }
public MultiOutput(int width, IDrawable icon) {
super(width, icon);
}
@Override @Override
public void setIngredients(T recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, T recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients());
ingredients.setOutputs(VanillaTypes.ITEM, recipe.getRollableResultsAsItemStacks());
}
@Override
public void setRecipe(IRecipeLayout recipeLayout, T recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableResults();
int xOffsetAmount = 1 - Math.min(3, results.size()); int xOffsetAmount = 1 - Math.min(3, results.size());
itemStacks.init(0, true, 5 * xOffsetAmount + 20, 47); builder
itemStacks.set(0, ingredients.getInputs(VanillaTypes.ITEM).get(0)); .addSlot(RecipeIngredientRole.INPUT, 5 * xOffsetAmount + 21, 48)
.setBackground(getRenderedSlot(), -1, -1)
.addIngredients(recipe.getIngredients().get(0));
int xOffsetOutput = 9 * xOffsetAmount; int i = 0;
boolean excessive = results.size() > 9; boolean excessive = results.size() > 9;
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { for (ProcessingOutput output : results) {
int xOffset = (outputIndex % 3) * 19 + xOffsetOutput; int xOffset = (i % 3) * 19 + 9 * xOffsetAmount;
int yOffset = (outputIndex / 3) * -19 + (excessive ? 8 : 0); int yOffset = (i / 3) * -19 + (excessive ? 8 : 0);
itemStacks.init(outputIndex + 1, false, 140 + xOffset, 47 + yOffset); builder
itemStacks.set(outputIndex + 1, results.get(outputIndex).getStack()); .addSlot(RecipeIngredientRole.OUTPUT, 141 + xOffset, 48 + yOffset)
.setBackground(getRenderedSlot(output), -1, -1)
.addItemStack(output.getStack())
.addTooltipCallback(addStochasticTooltip(output));
i++;
} }
addStochasticTooltip(itemStacks, results);
} }
@Override @Override
protected void renderWidgets(PoseStack matrixStack, T recipe, double mouseX, double mouseY) { protected void renderWidgets(PoseStack matrixStack, T recipe, double mouseX, double mouseY) {
int size = recipe.getRollableResultsAsItemStacks() int size = recipe.getRollableResultsAsItemStacks().size();
.size();
int xOffsetAmount = 1 - Math.min(3, size); int xOffsetAmount = 1 - Math.min(3, size);
AllGuiTextures.JEI_SHADOW.render(matrixStack, 46, 29); AllGuiTextures.JEI_SHADOW.render(matrixStack, 46, 29);
getBlockShadow().render(matrixStack, 65, 39); getBlockShadow().render(matrixStack, 65, 39);
AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 7 * xOffsetAmount + 54, 51); AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 7 * xOffsetAmount + 54, 51);
AllGuiTextures.JEI_SLOT.render(matrixStack, 5 * xOffsetAmount + 20, 47);
int xOffsetOutput = 9 * xOffsetAmount;
boolean excessive = size > 9;
for (int i = 0; i < size; i++) {
int xOffset = (i % 3) * 19 + xOffsetOutput;
int yOffset = (i / 3) * -19 + (excessive ? 8 : 0);
getRenderedSlot(recipe, i).render(matrixStack, 140 + xOffset, 47 + yOffset);
}
} }
} }

View file

@ -1,8 +1,9 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.compat.jei.category.animations.AnimatedSaw; import com.simibubi.create.compat.jei.category.animations.AnimatedSaw;
@ -10,15 +11,16 @@ import com.simibubi.create.content.contraptions.components.saw.CuttingRecipe;
import com.simibubi.create.content.contraptions.processing.ProcessingOutput; import com.simibubi.create.content.contraptions.processing.ProcessingOutput;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.RecipeIngredientRole;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
@ParametersAreNonnullByDefault
public class SawingCategory extends CreateRecipeCategory<CuttingRecipe> { public class SawingCategory extends CreateRecipeCategory<CuttingRecipe> {
private AnimatedSaw saw = new AnimatedSaw(); private final AnimatedSaw saw = new AnimatedSaw();
public SawingCategory() { public SawingCategory() {
super(doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), Items.OAK_LOG), emptyBackground(177, 70)); super(doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), Items.OAK_LOG), emptyBackground(177, 70));
@ -30,44 +32,31 @@ public class SawingCategory extends CreateRecipeCategory<CuttingRecipe> {
} }
@Override @Override
public void setIngredients(CuttingRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, CuttingRecipe recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients()); builder
ingredients.setOutputs(VanillaTypes.ITEM, recipe.getRollableResultsAsItemStacks()); .addSlot(RecipeIngredientRole.INPUT, 44, 5)
} .setBackground(getRenderedSlot(), -1, -1)
.addIngredients(recipe.getIngredients().get(0));
@Override
public void setRecipe(IRecipeLayout recipeLayout, CuttingRecipe recipe, IIngredients ingredients) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
itemStacks.init(0, true, 43, 4);
itemStacks.set(0, Arrays.asList(recipe.getIngredients()
.get(0)
.getItems()));
List<ProcessingOutput> results = recipe.getRollableResults(); List<ProcessingOutput> results = recipe.getRollableResults();
for (int outputIndex = 0; outputIndex < results.size(); outputIndex++) { int i = 0;
int xOffset = outputIndex % 2 == 0 ? 0 : 19; for (ProcessingOutput output : results) {
int yOffset = (outputIndex / 2) * -19; int xOffset = i % 2 == 0 ? 0 : 19;
int yOffset = (i / 2) * -19;
itemStacks.init(outputIndex + 1, false, 117 + xOffset, 47 + yOffset); builder
itemStacks.set(outputIndex + 1, results.get(outputIndex) .addSlot(RecipeIngredientRole.OUTPUT, 118 + xOffset, 48 + yOffset)
.getStack()); .setBackground(getRenderedSlot(output), -1, -1)
.addItemStack(output.getStack())
.addTooltipCallback(addStochasticTooltip(output));
i++;
} }
addStochasticTooltip(itemStacks, results);
} }
@Override @Override
public void draw(CuttingRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) { public void draw(CuttingRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.render(matrixStack, 43, 4);
int size = recipe.getRollableResults()
.size();
for (int i = 0; i < size; i++) {
int xOffset = i % 2 == 0 ? 0 : 19;
int yOffset = (i / 2) * -19;
getRenderedSlot(recipe, i).render(matrixStack, 117 + xOffset, 47 + yOffset);
}
AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 70, 6); AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 70, 6);
AllGuiTextures.JEI_SHADOW.render(matrixStack, 72 - 17, 42 + 13); AllGuiTextures.JEI_SHADOW.render(matrixStack, 72 - 17, 42 + 13);
saw.draw(matrixStack, 72, 42); saw.draw(matrixStack, 72, 42);
} }

View file

@ -1,29 +1,28 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import com.google.common.collect.ImmutableList; import javax.annotation.ParametersAreNonnullByDefault;
import org.jetbrains.annotations.NotNull;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.compat.jei.EmptyBackground; import com.simibubi.create.compat.jei.EmptyBackground;
import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory;
import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe;
import com.simibubi.create.content.contraptions.itemAssembly.SequencedRecipe; import com.simibubi.create.content.contraptions.itemAssembly.SequencedRecipe;
import com.simibubi.create.foundation.fluid.FluidIngredient;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.recipe.RecipeIngredientRole;
import mezz.jei.api.ingredients.IIngredients;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
@ -31,9 +30,8 @@ import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
@ParametersAreNonnullByDefault
public class SequencedAssemblyCategory extends CreateRecipeCategory<SequencedAssemblyRecipe> { public class SequencedAssemblyCategory extends CreateRecipeCategory<SequencedAssemblyRecipe> {
Map<ResourceLocation, SequencedAssemblySubCategory> subCategories = new HashMap<>(); Map<ResourceLocation, SequencedAssemblySubCategory> subCategories = new HashMap<>();
@ -48,31 +46,26 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory<SequencedAss
} }
@Override @Override
public void setIngredients(SequencedAssemblyRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, SequencedAssemblyRecipe recipe, IFocusGroup focuses) {
List<Ingredient> assemblyIngredients = getAllItemIngredients(recipe); boolean noRandomOutput = recipe.getOutputChance() == 1;
List<FluidIngredient> assemblyFluidIngredients = getAllFluidIngredients(recipe); int xOffset = noRandomOutput ? 0 : -7;
ingredients.setInputIngredients(assemblyIngredients);
if (!assemblyFluidIngredients.isEmpty())
ingredients.setInputLists(VanillaTypes.FLUID, assemblyFluidIngredients.stream()
.map(FluidIngredient::getMatchingFluidStacks)
.collect(Collectors.toList()));
ingredients.setOutputs(VanillaTypes.ITEM,
ImmutableList.of(recipe.getResultItem(), recipe.getTransitionalItem()));
}
@Override builder
public void setRecipe(IRecipeLayout recipeLayout, SequencedAssemblyRecipe recipe, IIngredients ingredients) { .addSlot(RecipeIngredientRole.INPUT, 27 + xOffset, 91)
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks(); .setBackground(getRenderedSlot(), -1, -1)
IGuiFluidStackGroup fluidStacks = recipeLayout.getFluidStacks(); .addItemStacks(List.of(recipe.getIngredient().getItems()));
int xOffset = recipe.getOutputChance() == 1 ? 0 : -7; builder
.addSlot(RecipeIngredientRole.OUTPUT, 132 + xOffset, 91)
.setBackground(getRenderedSlot(recipe.getOutputChance()), -1 , -1)
.addItemStack(recipe.getResultItem())
.addTooltipCallback((recipeSlotView, tooltip) -> {
if (noRandomOutput)
return;
itemStacks.init(0, true, 26 + xOffset, 90); float chance = recipe.getOutputChance();
itemStacks.set(0, Arrays.asList(recipe.getIngredient() tooltip.add(1, Lang.translate("recipe.processing.chance", chance < 0.01 ? "<1" : (int) (chance * 100))
.getItems())); .withStyle(ChatFormatting.GOLD));
});
ItemStack result = recipe.getResultItem();
itemStacks.init(1, false, 131 + xOffset, 90);
itemStacks.set(1, result);
int width = 0; int width = 0;
int margin = 3; int margin = 3;
@ -80,34 +73,12 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory<SequencedAss
width += getSubCategory(sequencedRecipe).getWidth() + margin; width += getSubCategory(sequencedRecipe).getWidth() + margin;
width -= margin; width -= margin;
int x = width / -2 + getBackground().getWidth() / 2; int x = width / -2 + getBackground().getWidth() / 2;
int index = 2;
int fluidIndex = 0;
for (SequencedRecipe<?> sequencedRecipe : recipe.getSequence()) { for (SequencedRecipe<?> sequencedRecipe : recipe.getSequence()) {
SequencedAssemblySubCategory subCategory = getSubCategory(sequencedRecipe); SequencedAssemblySubCategory subCategory = getSubCategory(sequencedRecipe);
index += subCategory.addItemIngredients(sequencedRecipe, itemStacks, x, index); subCategory.setRecipe(builder, sequencedRecipe, focuses, x);
fluidIndex += subCategory.addFluidIngredients(sequencedRecipe, fluidStacks, x, fluidIndex);
x += subCategory.getWidth() + margin; x += subCategory.getWidth() + margin;
} }
// In case machines should be displayed as ingredients
// List<List<ItemStack>> inputs = ingredients.getInputs(VanillaTypes.ITEM);
// int catalystX = -2;
// int catalystY = 14;
// for (; index < inputs.size(); index++) {
// itemStacks.init(index, true, catalystX, catalystY);
// itemStacks.set(index, inputs.get(index));
// catalystY += 19;
// }
itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> {
if (slotIndex != 1)
return;
float chance = recipe.getOutputChance();
if (chance != 1)
tooltip.add(1, Lang.translate("recipe.processing.chance", chance < 0.01 ? "<1" : (int) (chance * 100))
.withStyle(ChatFormatting.GOLD));
});
} }
private SequencedAssemblySubCategory getSubCategory(SequencedRecipe<?> sequencedRecipe) { private SequencedAssemblySubCategory getSubCategory(SequencedRecipe<?> sequencedRecipe) {
@ -124,7 +95,7 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory<SequencedAss
final String[] romans = { "I", "II", "III", "IV", "V", "VI", "-" }; final String[] romans = { "I", "II", "III", "IV", "V", "VI", "-" };
@Override @Override
public void draw(SequencedAssemblyRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) { public void draw(SequencedAssemblyRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
Font font = Minecraft.getInstance().font; Font font = Minecraft.getInstance().font;
matrixStack.pushPose(); matrixStack.pushPose();
@ -133,8 +104,6 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory<SequencedAss
matrixStack.translate(0, 15, 0); matrixStack.translate(0, 15, 0);
boolean singleOutput = recipe.getOutputChance() == 1; boolean singleOutput = recipe.getOutputChance() == 1;
int xOffset = singleOutput ? 0 : -7; int xOffset = singleOutput ? 0 : -7;
AllGuiTextures.JEI_SLOT.render(matrixStack, 26 + xOffset, 75);
(singleOutput ? AllGuiTextures.JEI_SLOT : AllGuiTextures.JEI_CHANCE_SLOT).render(matrixStack, 131 + xOffset, 75);
AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 52 + xOffset, 79); AllGuiTextures.JEI_LONG_ARROW.render(matrixStack, 52 + xOffset, 79);
if (!singleOutput) { if (!singleOutput) {
AllGuiTextures.JEI_CHANCE_SLOT.render(matrixStack, 150 + xOffset, 75); AllGuiTextures.JEI_CHANCE_SLOT.render(matrixStack, 150 + xOffset, 75);
@ -178,8 +147,9 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory<SequencedAss
} }
@Override @Override
public List<Component> getTooltipStrings(SequencedAssemblyRecipe recipe, double mouseX, double mouseY) { @NotNull
List<Component> tooltip = new ArrayList<Component>(); public List<Component> getTooltipStrings(SequencedAssemblyRecipe recipe, IRecipeSlotsView iRecipeSlotsView, double mouseX, double mouseY) {
List<Component> tooltip = new ArrayList<>();
TranslatableComponent junk = Lang.translate("recipe.assembly.junk"); TranslatableComponent junk = Lang.translate("recipe.assembly.junk");
@ -235,19 +205,4 @@ public class SequencedAssemblyCategory extends CreateRecipeCategory<SequencedAss
return tooltip; return tooltip;
} }
private List<FluidIngredient> getAllFluidIngredients(SequencedAssemblyRecipe recipe) {
List<FluidIngredient> assemblyFluidIngredients = new ArrayList<>();
recipe.addAdditionalFluidIngredients(assemblyFluidIngredients);
return assemblyFluidIngredients;
}
private List<Ingredient> getAllItemIngredients(SequencedAssemblyRecipe recipe) {
List<Ingredient> assemblyIngredients = new ArrayList<>();
assemblyIngredients.add(recipe.getIngredient());
assemblyIngredients.add(Ingredient.of(recipe.getTransitionalItem()));
recipe.addAdditionalIngredientsAndMachines(assemblyIngredients);
return assemblyIngredients;
}
} }

View file

@ -1,13 +1,10 @@
package com.simibubi.create.compat.jei.category; package com.simibubi.create.compat.jei.category;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors;
import com.google.common.collect.ImmutableList; import javax.annotation.ParametersAreNonnullByDefault;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create; import com.simibubi.create.Create;
@ -20,10 +17,10 @@ import com.simibubi.create.foundation.fluid.FluidIngredient;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup; import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.ingredients.IIngredients; import mezz.jei.api.recipe.RecipeIngredientRole;
import mezz.jei.api.runtime.IIngredientManager; import mezz.jei.api.runtime.IIngredientManager;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -36,9 +33,10 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
import net.minecraftforge.fluids.capability.IFluidHandlerItem; import net.minecraftforge.fluids.capability.IFluidHandlerItem;
@ParametersAreNonnullByDefault
public class SpoutCategory extends CreateRecipeCategory<FillingRecipe> { public class SpoutCategory extends CreateRecipeCategory<FillingRecipe> {
AnimatedSpout spout; private final AnimatedSpout spout;
public SpoutCategory() { public SpoutCategory() {
super(doubleItemIcon(AllBlocks.SPOUT.get(), Items.WATER_BUCKET), emptyBackground(177, 70)); super(doubleItemIcon(AllBlocks.SPOUT.get(), Items.WATER_BUCKET), emptyBackground(177, 70));
@ -102,45 +100,24 @@ public class SpoutCategory extends CreateRecipeCategory<FillingRecipe> {
} }
@Override @Override
public void setIngredients(FillingRecipe recipe, IIngredients ingredients) { public void setRecipe(IRecipeLayoutBuilder builder, FillingRecipe recipe, IFocusGroup focuses) {
ingredients.setInputIngredients(recipe.getIngredients()); builder
ingredients.setInputLists(VanillaTypes.FLUID, recipe.getFluidIngredients() .addSlot(RecipeIngredientRole.INPUT, 27, 51)
.stream() .setBackground(getRenderedSlot(), -1, -1)
.map(FluidIngredient::getMatchingFluidStacks) .addIngredients(recipe.getIngredients().get(0));
.collect(Collectors.toList())); builder
.addSlot(RecipeIngredientRole.INPUT, 27, 32)
if (!recipe.getRollableResults() .setBackground(getRenderedSlot(), -1, -1)
.isEmpty()) .addIngredients(VanillaTypes.FLUID, withImprovedVisibility(recipe.getRequiredFluid().getMatchingFluidStacks()))
ingredients.setOutput(VanillaTypes.ITEM, recipe.getResultItem()); .addTooltipCallback(addFluidTooltip(recipe.getRequiredFluid().getRequiredAmount()));
if (!recipe.getFluidResults() builder
.isEmpty()) .addSlot(RecipeIngredientRole.OUTPUT, 132, 51)
ingredients.setOutputs(VanillaTypes.FLUID, recipe.getFluidResults()); .setBackground(getRenderedSlot(), -1, -1)
.addItemStack(recipe.getResultItem());
} }
@Override @Override
public void setRecipe(IRecipeLayout recipeLayout, FillingRecipe recipe, IIngredients ingredients) { public void draw(FillingRecipe recipe, IRecipeSlotsView iRecipeSlotsView, PoseStack matrixStack, double mouseX, double mouseY) {
IGuiItemStackGroup itemStacks = recipeLayout.getItemStacks();
IGuiFluidStackGroup fluidStacks = recipeLayout.getFluidStacks();
FluidIngredient fluidIngredient = recipe.getRequiredFluid();
List<ItemStack> matchingIngredients = Arrays.asList(recipe.getIngredients()
.get(0)
.getItems());
fluidStacks.init(0, true, 27, 32);
fluidStacks.set(0, withImprovedVisibility(fluidIngredient.getMatchingFluidStacks()));
itemStacks.init(0, true, 26, 50);
itemStacks.set(0, matchingIngredients);
itemStacks.init(1, false, 131, 50);
itemStacks.set(1, recipe.getResultItem());
addFluidTooltip(fluidStacks, ImmutableList.of(fluidIngredient), Collections.emptyList());
}
@Override
public void draw(FillingRecipe recipe, PoseStack matrixStack, double mouseX, double mouseY) {
AllGuiTextures.JEI_SLOT.render(matrixStack, 26, 31);
AllGuiTextures.JEI_SLOT.render(matrixStack, 26, 50);
getRenderedSlot(recipe, 0).render(matrixStack, 131, 50);
AllGuiTextures.JEI_SHADOW.render(matrixStack, 62, 57); AllGuiTextures.JEI_SHADOW.render(matrixStack, 62, 57);
AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 126, 29); AllGuiTextures.JEI_DOWN_ARROW.render(matrixStack, 126, 29);
spout.withFluids(recipe.getRequiredFluid() spout.withFluids(recipe.getRequiredFluid()

View file

@ -1,9 +1,5 @@
package com.simibubi.create.compat.jei.category.sequencedAssembly; package com.simibubi.create.compat.jei.category.sequencedAssembly;
import java.util.Arrays;
import java.util.Collections;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.compat.jei.category.CreateRecipeCategory; import com.simibubi.create.compat.jei.category.CreateRecipeCategory;
import com.simibubi.create.compat.jei.category.animations.AnimatedDeployer; import com.simibubi.create.compat.jei.category.animations.AnimatedDeployer;
@ -11,19 +7,20 @@ import com.simibubi.create.compat.jei.category.animations.AnimatedPress;
import com.simibubi.create.compat.jei.category.animations.AnimatedSaw; import com.simibubi.create.compat.jei.category.animations.AnimatedSaw;
import com.simibubi.create.compat.jei.category.animations.AnimatedSpout; import com.simibubi.create.compat.jei.category.animations.AnimatedSpout;
import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe;
import com.simibubi.create.content.contraptions.itemAssembly.IAssemblyRecipe;
import com.simibubi.create.content.contraptions.itemAssembly.SequencedRecipe; import com.simibubi.create.content.contraptions.itemAssembly.SequencedRecipe;
import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.fluid.FluidIngredient;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import mezz.jei.api.gui.ingredient.IGuiFluidStackGroup; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.builder.IRecipeSlotBuilder;
import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
public abstract class SequencedAssemblySubCategory { public abstract class SequencedAssemblySubCategory {
private int width; private final int width;
public SequencedAssemblySubCategory(int width) { public SequencedAssemblySubCategory(int width) {
this.width = width; this.width = width;
@ -33,13 +30,7 @@ public abstract class SequencedAssemblySubCategory {
return width; return width;
} }
public int addItemIngredients(SequencedRecipe<?> recipe, IGuiItemStackGroup itemStacks, int x, int index) { public void setRecipe(IRecipeLayoutBuilder builder, SequencedRecipe<?> recipe, IFocusGroup focuses, int x) {}
return 0;
}
public int addFluidIngredients(SequencedRecipe<?> recipe, IGuiFluidStackGroup fluidStacks, int x, int index) {
return 0;
}
public abstract void draw(SequencedRecipe<?> recipe, PoseStack ms, double mouseX, double mouseY, int index); public abstract void draw(SequencedRecipe<?> recipe, PoseStack ms, double mouseX, double mouseY, int index);
@ -74,22 +65,21 @@ public abstract class SequencedAssemblySubCategory {
} }
@Override @Override
public int addFluidIngredients(SequencedRecipe<?> recipe, IGuiFluidStackGroup fluidStacks, int x, int index) { public void setRecipe(IRecipeLayoutBuilder builder, SequencedRecipe<?> recipe, IFocusGroup focuses, int x) {
FluidIngredient fluidIngredient = recipe.getRecipe() FluidIngredient fluidIngredient = recipe.getRecipe()
.getFluidIngredients() .getFluidIngredients()
.get(0); .get(0);
fluidStacks.init(index, true, x + 4, 15);
fluidStacks.set(index, builder
CreateRecipeCategory.withImprovedVisibility(fluidIngredient.getMatchingFluidStacks())); .addSlot(RecipeIngredientRole.INPUT, x + 4, 15)
CreateRecipeCategory.addFluidTooltip(fluidStacks, ImmutableList.of(fluidIngredient), .setBackground(CreateRecipeCategory.getRenderedSlot(), -1, -1)
Collections.emptyList(), index); .addIngredients(VanillaTypes.FLUID, CreateRecipeCategory.withImprovedVisibility(fluidIngredient.getMatchingFluidStacks()))
return 1; .addTooltipCallback(CreateRecipeCategory.addFluidTooltip(fluidIngredient.getRequiredAmount()));
} }
@Override @Override
public void draw(SequencedRecipe<?> recipe, PoseStack ms, double mouseX, double mouseY, int index) { public void draw(SequencedRecipe<?> recipe, PoseStack ms, double mouseX, double mouseY, int index) {
spout.offset = index; spout.offset = index;
AllGuiTextures.JEI_SLOT.render(ms, 3, 14);
ms.pushPose(); ms.pushPose();
ms.translate(-7, 50, 0); ms.translate(-7, 50, 0);
ms.scale(.75f, .75f, .75f); ms.scale(.75f, .75f, .75f);
@ -113,26 +103,17 @@ public abstract class SequencedAssemblySubCategory {
} }
@Override @Override
public int addItemIngredients(SequencedRecipe<?> recipe, IGuiItemStackGroup itemStacks, int x, int index) { public void setRecipe(IRecipeLayoutBuilder builder, SequencedRecipe<?> recipe, IFocusGroup focuses, int x) {
itemStacks.init(index, true, x + 3, 14); IRecipeSlotBuilder slot = builder
itemStacks.set(index, Arrays.asList(recipe.getRecipe() .addSlot(RecipeIngredientRole.INPUT, x + 4, 15)
.getIngredients() .setBackground(CreateRecipeCategory.getRenderedSlot(), -1, -1)
.get(1) .addIngredients(recipe.getRecipe().getIngredients().get(1));
.getItems()));
IAssemblyRecipe contained = recipe.getAsAssemblyRecipe(); if (recipe.getAsAssemblyRecipe() instanceof DeployerApplicationRecipe deployerRecipe && deployerRecipe.shouldKeepHeldItem()) {
if (contained instanceof DeployerApplicationRecipe && ((DeployerApplicationRecipe) contained).shouldKeepHeldItem()) { slot.addTooltipCallback(
itemStacks.addTooltipCallback((slotIndex, input, ingredient, tooltip) -> { (recipeSlotView, tooltip) -> tooltip.add(1, Lang.translate("recipe.deploying.not_consumed").withStyle(ChatFormatting.GOLD))
if (!input) );
return;
if (slotIndex != index)
return;
tooltip.add(1, Lang.translate("recipe.deploying.not_consumed")
.withStyle(ChatFormatting.GOLD));
});
} }
return 1;
} }
@Override @Override
@ -143,7 +124,6 @@ public abstract class SequencedAssemblySubCategory {
ms.scale(.75f, .75f, .75f); ms.scale(.75f, .75f, .75f);
deployer.draw(ms, getWidth() / 2, 0); deployer.draw(ms, getWidth() / 2, 0);
ms.popPose(); ms.popPose();
AllGuiTextures.JEI_SLOT.render(ms, 3, 14);
} }
} }

View file

@ -3,6 +3,7 @@ package com.simibubi.create.foundation.utility;
import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.util.Mth;
public class CameraAngleAnimationService { public class CameraAngleAnimationService {
@ -14,6 +15,9 @@ public class CameraAngleAnimationService {
public static void tick() { public static void tick() {
yRotation.tickChaser();
xRotation.tickChaser();
if (Minecraft.getInstance().player != null) { if (Minecraft.getInstance().player != null) {
if (!yRotation.settled()) if (!yRotation.settled())
Minecraft.getInstance().player.setYRot(yRotation.getValue(1)); Minecraft.getInstance().player.setYRot(yRotation.getValue(1));
@ -21,9 +25,6 @@ public class CameraAngleAnimationService {
if (!xRotation.settled()) if (!xRotation.settled())
Minecraft.getInstance().player.setXRot(xRotation.getValue(1)); Minecraft.getInstance().player.setXRot(xRotation.getValue(1));
} }
yRotation.tickChaser();
xRotation.tickChaser();
} }
public static boolean isYawAnimating() { public static boolean isYawAnimating() {
@ -51,27 +52,28 @@ public class CameraAngleAnimationService {
} }
public static void setYawTarget(float yaw) { public static void setYawTarget(float yaw) {
yRotation.startWithValue(getCurrentYaw()); float currentYaw = getCurrentYaw();
setupChaser(yRotation, yaw); yRotation.startWithValue(currentYaw);
setupChaser(yRotation, currentYaw + AngleHelper.getShortestAngleDiff(currentYaw, Mth.wrapDegrees(yaw)));
} }
public static void setPitchTarget(float pitch) { public static void setPitchTarget(float pitch) {
xRotation.startWithValue(getCurrentPitch()); float currentPitch = getCurrentPitch();
setupChaser(xRotation, pitch); xRotation.startWithValue(currentPitch);
setupChaser(xRotation, currentPitch + AngleHelper.getShortestAngleDiff(currentPitch, Mth.wrapDegrees(pitch)));
} }
private static float getCurrentYaw() { private static float getCurrentYaw() {
if (Minecraft.getInstance().player == null) if (Minecraft.getInstance().player == null)
return 0; return 0;
return Mth.wrapDegrees(Minecraft.getInstance().player.getYRot());
return Minecraft.getInstance().player.getYRot();
} }
private static float getCurrentPitch() { private static float getCurrentPitch() {
if (Minecraft.getInstance().player == null) if (Minecraft.getInstance().player == null)
return 0; return 0;
return Minecraft.getInstance().player.getXRot(); return Mth.wrapDegrees(Minecraft.getInstance().player.getXRot());
} }
private static void setupChaser(LerpedFloat rotation, float target) { private static void setupChaser(LerpedFloat rotation, float target) {