diff --git a/src/main/groovy-tests/customRecipeClassTests.groovy b/src/main/groovy-tests/customRecipeClassTests.groovy index 925be0e..51403a0 100644 --- a/src/main/groovy-tests/customRecipeClassTests.groovy +++ b/src/main/groovy-tests/customRecipeClassTests.groovy @@ -1,5 +1,8 @@ import com.nomiceu.nomilabs.groovy.ShapedConversionRecipe import com.nomiceu.nomilabs.groovy.ShapedDummyRecipe +import net.minecraft.nbt.NBTTagCompound + +import static com.nomiceu.nomilabs.groovy.GroovyHelpers.NBTClearingRecipeCreators.* // Custom Recipe Classes. Goes in Post Init. @@ -35,3 +38,30 @@ crafting.shapedBuilder() .matrix([[item('minecraft:leaves')]]) .recipeClassFunction((output, width, height, ingredients) -> new ShapedDummyRecipe(output, ingredients, width, height, false)) .register() + +// Examples: NBT Clearing +// Note that provided OUTPUT must match the output item in ALL CASES for that recipe! +// Simplest Form, Same Item for Input and Output +nbtClearingRecipe(item('storagedrawers:compdrawers')) + +// Different Item for Input and Output +nbtClearingRecipe(item('forge:bucketfilled'), item('minecraft:bucket')) + +// Same Input/Output Item, Custom NBT Clearer +nbtClearingRecipe(item('storagedrawers:basicdrawers'), { + if (it.tagCompound == null) return + var material = it.tagCompound.getString('material') + + if (material.empty){ + it.tagCompound = null + return + } + var newTag = new NBTTagCompound() + newTag.setString('material', material) + it.tagCompound = newTag +}) + +// Different Input/Output Item, Custom NBT Clearer +nbtClearingRecipe(item('minecraft:water_bucket'), item('minecraft:bucket'), { + it.stackDisplayName = 'Old Water Bucket' +}) diff --git a/src/main/java/com/nomiceu/nomilabs/event/ClientProxy.java b/src/main/java/com/nomiceu/nomilabs/event/ClientProxy.java index 1452540..c23530b 100644 --- a/src/main/java/com/nomiceu/nomilabs/event/ClientProxy.java +++ b/src/main/java/com/nomiceu/nomilabs/event/ClientProxy.java @@ -74,6 +74,7 @@ public static void registerFluidModels(TextureStitchEvent.Pre event) { @SubscribeEvent public static void addTooltipNormal(ItemTooltipEvent event) { TooltipAdder.addTooltipNormal(event.getToolTip(), event.getItemStack()); + TooltipAdder.addTooltipClearing(event.getToolTip(), event.getItemStack(), event.getEntityPlayer()); } @SubscribeEvent diff --git a/src/main/java/com/nomiceu/nomilabs/event/CommonProxy.java b/src/main/java/com/nomiceu/nomilabs/event/CommonProxy.java index 3ff6b09..899c6a7 100644 --- a/src/main/java/com/nomiceu/nomilabs/event/CommonProxy.java +++ b/src/main/java/com/nomiceu/nomilabs/event/CommonProxy.java @@ -37,6 +37,7 @@ import com.nomiceu.nomilabs.gregtech.recipe.LabsRecipeMaps; import com.nomiceu.nomilabs.gregtech.recipe.PerfectGemsCutterRecipes; import com.nomiceu.nomilabs.groovy.GroovyScriptHandManager; +import com.nomiceu.nomilabs.groovy.NBTClearingRecipe; import com.nomiceu.nomilabs.groovy.NCActiveCoolerHelper; import com.nomiceu.nomilabs.integration.architecturecraft.LabsShapes; import com.nomiceu.nomilabs.integration.betterp2p.LabsBetterMemoryCardModes; @@ -213,6 +214,7 @@ public static void gsHandAdditions(GsHandEvent event) { public static void onScriptReload(ScriptRunEvent.Pre event) { JEIPlugin.onReload(); LabsTooltipHelper.clearAll(); + NBTClearingRecipe.NBT_CLEARERS.clear(); if (Loader.isModLoaded(LabsValues.NUCLEARCRAFT_MODID)) { NCActiveCoolerHelper.onReload(); diff --git a/src/main/java/com/nomiceu/nomilabs/groovy/GroovyHelpers.java b/src/main/java/com/nomiceu/nomilabs/groovy/GroovyHelpers.java index bbd7193..e3412e0 100644 --- a/src/main/java/com/nomiceu/nomilabs/groovy/GroovyHelpers.java +++ b/src/main/java/com/nomiceu/nomilabs/groovy/GroovyHelpers.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -17,6 +18,7 @@ import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.registry.ForgeRegistries; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -28,6 +30,8 @@ import com.cleanroommc.groovyscript.api.IIngredient; import com.cleanroommc.groovyscript.compat.mods.ModSupport; import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; +import com.cleanroommc.groovyscript.helper.recipe.RecipeName; +import com.cleanroommc.groovyscript.registry.ReloadableRegistryManager; import com.cleanroommc.groovyscript.sandbox.ClosureHelper; import com.nomiceu.nomilabs.LabsValues; import com.nomiceu.nomilabs.integration.jei.JEIPlugin; @@ -455,4 +459,37 @@ public static void removeDraconicFusionRecipe(ItemStack catalyst, ItemStack resu } } } + + public static class NBTClearingRecipeCreators { + + public static NBTClearingRecipe nbtClearingRecipe(ItemStack item) { + return nbtClearingRecipe(item, item, null); + } + + public static NBTClearingRecipe nbtClearingRecipe(ItemStack item, @Nullable Consumer clearer) { + return nbtClearingRecipe(item, item, clearer); + } + + public static NBTClearingRecipe nbtClearingRecipe(ItemStack input, ItemStack output) { + return nbtClearingRecipe(input, output, null); + } + + public static NBTClearingRecipe nbtClearingRecipe(ItemStack input, ItemStack exampleOutput, + @Nullable Consumer clearer) { + ResourceLocation name = RecipeName.generateRl("nomilabs_nbt_clearing"); + + GroovyLog.Msg msg = GroovyLog.msg("Error adding Minecraft Shaped Crafting recipe '{}'", name).error() + .add(IngredientHelper.isEmpty(input), () -> "Input must not be empty") + .add(IngredientHelper.isEmpty(exampleOutput), () -> "Output must not be empty") + .add(ReloadableRegistryManager.hasNonDummyRecipe(name), + () -> "a recipe with that name already exists! Remove the recipe first"); + if (msg.postIfNotEmpty()) return null; + + var recipe = new NBTClearingRecipe(input, exampleOutput, clearer); + NBTClearingRecipe.NBT_CLEARERS.put(new ItemMeta(exampleOutput), new ItemMeta(input)); + ReloadableRegistryManager.addRegistryEntry(ForgeRegistries.RECIPES, name, recipe); + TooltipHelpers.addTooltip(input, NBTClearingRecipe.CAN_CLEAR_TOOLTIP); + return recipe; + } + } } diff --git a/src/main/java/com/nomiceu/nomilabs/groovy/NBTClearingRecipe.java b/src/main/java/com/nomiceu/nomilabs/groovy/NBTClearingRecipe.java new file mode 100644 index 0000000..c89201a --- /dev/null +++ b/src/main/java/com/nomiceu/nomilabs/groovy/NBTClearingRecipe.java @@ -0,0 +1,95 @@ +package com.nomiceu.nomilabs.groovy; + +import java.util.Map; +import java.util.function.Consumer; + +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.util.NonNullList; +import net.minecraft.world.World; +import net.minecraftforge.registries.IForgeRegistryEntry; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.nomiceu.nomilabs.util.ItemMeta; +import com.nomiceu.nomilabs.util.LabsTranslate; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +public class NBTClearingRecipe extends IForgeRegistryEntry.Impl implements IRecipe { + + // Map of Output to Input + public static final Map NBT_CLEARERS = new Object2ObjectOpenHashMap<>(); + public static final LabsTranslate.Translatable WARNING_TOOLTIP = new LabsTranslate.Translatable( + "tooltip.nomilabs.recipe.clearing"); + public static final LabsTranslate.Translatable CAN_CLEAR_TOOLTIP = new LabsTranslate.Translatable( + "tooltip.nomilabs.item.can_clear"); + + @Nullable + private final Consumer nbtClearer; + private final ItemStack singleInput; + private final ItemStack exampleOutput; + + public NBTClearingRecipe(ItemStack input, ItemStack exampleOutput, @Nullable Consumer nbtClearer) { + this.singleInput = input; + this.exampleOutput = exampleOutput; + this.nbtClearer = nbtClearer; + } + + @Override + public boolean matches(@NotNull InventoryCrafting inv, @NotNull World worldIn) { + boolean found = false; + for (int i = 0; i < inv.getSizeInventory(); i++) { + var stack = inv.getStackInSlot(i); + if (stack.isEmpty()) continue; + + if (found || !ItemMeta.compare(inv.getStackInSlot(i), singleInput)) return false; + found = true; + } + return found; + } + + @Override + @NotNull + public ItemStack getCraftingResult(@NotNull InventoryCrafting inv) { + if (nbtClearer == null) return exampleOutput; + + var stack = ItemStack.EMPTY; + for (int i = 0; i < inv.getSizeInventory(); i++) { + stack = inv.getStackInSlot(i); + if (!stack.isEmpty()) break; + } + + if (stack.isEmpty()) return ItemStack.EMPTY; + var display = new ItemStack(exampleOutput.getItem(), stack.getCount(), exampleOutput.getMetadata()); + display.setTagCompound(stack.getTagCompound()); + nbtClearer.accept(display); + return display; + } + + @Override + public boolean canFit(int width, int height) { + return true; + } + + @Override + @NotNull + public ItemStack getRecipeOutput() { + return exampleOutput; + } + + /** + * Makes Buckets be Consumed + */ + @Override + @NotNull + public NonNullList getRemainingItems(InventoryCrafting inv) { + NonNullList ret = NonNullList.withSize(inv.getSizeInventory(), ItemStack.EMPTY); + for (int i = 0; i < ret.size(); i++) { + ret.set(i, inv.getStackInSlot(i)); + } + return ret; + } +} diff --git a/src/main/java/com/nomiceu/nomilabs/tooltip/LabsTooltipHelper.java b/src/main/java/com/nomiceu/nomilabs/tooltip/LabsTooltipHelper.java index 27bafc3..dc5597b 100644 --- a/src/main/java/com/nomiceu/nomilabs/tooltip/LabsTooltipHelper.java +++ b/src/main/java/com/nomiceu/nomilabs/tooltip/LabsTooltipHelper.java @@ -11,6 +11,7 @@ import org.lwjgl.input.Keyboard; import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.nomiceu.nomilabs.groovy.NBTClearingRecipe; import com.nomiceu.nomilabs.util.ItemMeta; import com.nomiceu.nomilabs.util.LabsTranslate; @@ -26,6 +27,7 @@ public class LabsTooltipHelper { private static final Map> TOOLTIPS = new Object2ObjectOpenHashMap<>(); private static final Map> CACHED_TOOLTIPS = new Object2ObjectOpenHashMap<>(); + public static String CACHED_NBT_CLEARER = NBTClearingRecipe.WARNING_TOOLTIP.translate(); public static boolean isShiftDown() { return Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); @@ -66,6 +68,7 @@ public static void clearAll() { public static void onLanguageChange() { CACHED_TOOLTIPS.clear(); + CACHED_NBT_CLEARER = NBTClearingRecipe.WARNING_TOOLTIP.translate(); } public static boolean shouldClear(ItemStack stack) { diff --git a/src/main/java/com/nomiceu/nomilabs/tooltip/TooltipAdder.java b/src/main/java/com/nomiceu/nomilabs/tooltip/TooltipAdder.java index f37f307..c2609df 100644 --- a/src/main/java/com/nomiceu/nomilabs/tooltip/TooltipAdder.java +++ b/src/main/java/com/nomiceu/nomilabs/tooltip/TooltipAdder.java @@ -7,15 +7,23 @@ import java.util.List; import java.util.Objects; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.ContainerPlayer; +import net.minecraft.inventory.ContainerWorkbench; +import net.minecraft.inventory.InventoryCraftResult; +import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Optional; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; import com.enderio.core.client.handlers.SpecialTooltipHandler; import com.nomiceu.nomilabs.LabsValues; import com.nomiceu.nomilabs.config.LabsConfig; +import com.nomiceu.nomilabs.groovy.NBTClearingRecipe; +import com.nomiceu.nomilabs.util.ItemMeta; import crazypants.enderio.api.capacitor.CapabilityCapacitorData; import crazypants.enderio.base.capacitor.CapacitorKey; @@ -36,6 +44,46 @@ public static void addTooltipNormal(List tooltip, ItemStack stack) { addTooltipEIO(tooltip, stack); } + public static void addTooltipClearing(List tooltip, ItemStack stack, EntityPlayer player) { + if (player == null) return; + + InventoryCrafting inv = null; + InventoryCraftResult result = null; + + if (player.openContainer instanceof ContainerWorkbench) { + inv = ((ContainerWorkbench) player.openContainer).craftMatrix; + result = ((ContainerWorkbench) player.openContainer).craftResult; + } else if (player.openContainer instanceof ContainerPlayer) { + inv = ((ContainerPlayer) player.openContainer).craftMatrix; + result = ((ContainerPlayer) player.openContainer).craftResult; + } + + if (inv == null || result == null) return; + + var resultStack = result.getStackInSlot(0); + if (IngredientHelper.isEmpty(resultStack) || resultStack != stack) return; + + // Can't use GetRecipeUsed, because on client. Check matrix + var resultItemMeta = new ItemMeta(resultStack); + if (!NBTClearingRecipe.NBT_CLEARERS.containsKey(resultItemMeta)) return; + + var inputItemMeta = NBTClearingRecipe.NBT_CLEARERS.get(resultItemMeta); + if (isNBTClearing(inv, inputItemMeta)) + tooltip.add(LabsTooltipHelper.CACHED_NBT_CLEARER); + } + + private static boolean isNBTClearing(InventoryCrafting inv, ItemMeta inputItemMeta) { + boolean found = false; + for (int i = 0; i < inv.getSizeInventory(); i++) { + var stack = inv.getStackInSlot(i); + if (stack.isEmpty()) continue; + + if (found || !inputItemMeta.compareWith(stack)) return false; + found = true; + } + return found; + } + @Optional.Method(modid = LabsValues.ENDER_IO_MODID) private static void addTooltipEIO(List tooltip, ItemStack stack) { if (stack.hasCapability(CapabilityCapacitorData.getCapNN(), null)) { diff --git a/src/main/resources/assets/nomilabs/lang/en_us.lang b/src/main/resources/assets/nomilabs/lang/en_us.lang index c01a305..4d15373 100644 --- a/src/main/resources/assets/nomilabs/lang/en_us.lang +++ b/src/main/resources/assets/nomilabs/lang/en_us.lang @@ -586,6 +586,8 @@ tooltip.nomilabs.general.press_ctrl_for_usages=Press [Ctrl] for More Usages. tooltip.nomilabs.general.press_shift_for_info=Press [Shift] for More Info. tooltip.nomilabs.general.press_ctrl_for_info=Press [Ctrl] for More Info. tooltip.nomilabs.general.crafting_component=§7Crafting Component Only.§r +tooltip.nomilabs.item.can_clear=Place in Crafting Grid to §eClear Contents§r! +tooltip.nomilabs.recipe.clearing=§cAll Contents Will be Cleared!§r # Items tooltip.nomilabs.excitationcoil.description=§7Crafting Component Only... Except:§r