Skip to content

Commit

Permalink
Add support for anvil recipes (#732)
Browse files Browse the repository at this point in the history
  • Loading branch information
gigaherz authored and mezz committed Feb 15, 2017
1 parent 88c9405 commit 9891cbc
Show file tree
Hide file tree
Showing 11 changed files with 391 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ out/
build/*
/bin/
changelog.html
/classes
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ curse_project_id=238222

version_major=4
version_minor=2
version_patch=5
version_patch=6
9 changes: 9 additions & 0 deletions src/main/java/mezz/jei/api/IModRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ public interface IModRegistry {

void addDescription(List<ItemStack> itemStacks, String... descriptionKeys);

/**
* Adds an anvil recipe for the given inputs and output.
* @param leftInput The itemStack placed on the left slot.
* @param rightInputs The itemStack(s) placed on the right slot.
* @param outputs The resulting itemStack(s).
* @since JEI 4.2.6
*/
void addAnvilRecipe(ItemStack leftInput, List<ItemStack> rightInputs, List<ItemStack> outputs);

/**
* Get the registry for setting up recipe transfer.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ public class VanillaRecipeCategoryUid {
*/
public static final String BREWING = "minecraft.brewing";

/**
* The anvil recipe category.
* <p>
* This is a built-in category, you can add new recipes with {@link IModRegistry#addAnvilRecipe(ItemStack, List, List)}}
* @since JEI 4.2.6
*/
public static final String ANVIL = "minecraft.anvil";

/**
* The JEI description recipe category.
* <p>
Expand Down
16 changes: 14 additions & 2 deletions src/main/java/mezz/jei/plugins/vanilla/VanillaPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
import mezz.jei.api.ingredients.IModIngredientRegistration;
import mezz.jei.api.recipe.VanillaRecipeCategoryUid;
import mezz.jei.api.recipe.transfer.IRecipeTransferRegistry;
import mezz.jei.plugins.vanilla.anvil.AnvilRecipeCategory;
import mezz.jei.plugins.vanilla.anvil.AnvilRecipeHandler;
import mezz.jei.plugins.vanilla.anvil.AnvilRecipeMaker;
import mezz.jei.plugins.vanilla.brewing.BrewingRecipeCategory;
import mezz.jei.plugins.vanilla.brewing.BrewingRecipeHandler;
import mezz.jei.plugins.vanilla.brewing.BrewingRecipeMaker;
Expand All @@ -39,6 +42,7 @@
import mezz.jei.plugins.vanilla.ingredients.ItemStackRenderer;
import mezz.jei.transfer.PlayerRecipeTransferHandler;
import mezz.jei.util.StackHelper;
import net.minecraft.client.gui.GuiRepair;
import net.minecraft.client.gui.inventory.GuiBrewingStand;
import net.minecraft.client.gui.inventory.GuiCrafting;
import net.minecraft.client.gui.inventory.GuiFurnace;
Expand All @@ -47,6 +51,7 @@
import net.minecraft.init.Items;
import net.minecraft.inventory.ContainerBrewingStand;
import net.minecraft.inventory.ContainerFurnace;
import net.minecraft.inventory.ContainerRepair;
import net.minecraft.inventory.ContainerWorkbench;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.ItemBanner;
Expand Down Expand Up @@ -107,7 +112,8 @@ public void register(IModRegistry registry) {
new CraftingRecipeCategory(guiHelper),
new FurnaceFuelCategory(guiHelper),
new FurnaceSmeltingCategory(guiHelper),
new BrewingRecipeCategory(guiHelper)
new BrewingRecipeCategory(guiHelper),
new AnvilRecipeCategory(guiHelper)
);

registry.addRecipeHandlers(
Expand All @@ -118,13 +124,15 @@ public void register(IModRegistry registry) {
new TippedArrowRecipeHandler(),
new FuelRecipeHandler(),
new SmeltingRecipeHandler(),
new BrewingRecipeHandler()
new BrewingRecipeHandler(),
new AnvilRecipeHandler()
);

registry.addRecipeClickArea(GuiCrafting.class, 88, 32, 28, 23, VanillaRecipeCategoryUid.CRAFTING);
registry.addRecipeClickArea(GuiInventory.class, 137, 29, 10, 13, VanillaRecipeCategoryUid.CRAFTING);
registry.addRecipeClickArea(GuiBrewingStand.class, 97, 16, 14, 30, VanillaRecipeCategoryUid.BREWING);
registry.addRecipeClickArea(GuiFurnace.class, 78, 32, 28, 23, VanillaRecipeCategoryUid.SMELTING, VanillaRecipeCategoryUid.FUEL);
registry.addRecipeClickArea(GuiRepair.class, 102, 48, 22, 15, VanillaRecipeCategoryUid.ANVIL);

IRecipeTransferRegistry recipeTransferRegistry = registry.getRecipeTransferRegistry();

Expand All @@ -133,17 +141,21 @@ public void register(IModRegistry registry) {
recipeTransferRegistry.addRecipeTransferHandler(ContainerFurnace.class, VanillaRecipeCategoryUid.SMELTING, 0, 1, 3, 36);
recipeTransferRegistry.addRecipeTransferHandler(ContainerFurnace.class, VanillaRecipeCategoryUid.FUEL, 1, 1, 3, 36);
recipeTransferRegistry.addRecipeTransferHandler(ContainerBrewingStand.class, VanillaRecipeCategoryUid.BREWING, 0, 4, 5, 36);
recipeTransferRegistry.addRecipeTransferHandler(ContainerRepair.class, VanillaRecipeCategoryUid.ANVIL, 0, 2, 3, 36);

registry.addRecipeCategoryCraftingItem(new ItemStack(Blocks.CRAFTING_TABLE), VanillaRecipeCategoryUid.CRAFTING);
registry.addRecipeCategoryCraftingItem(new ItemStack(Blocks.FURNACE), VanillaRecipeCategoryUid.SMELTING, VanillaRecipeCategoryUid.FUEL);
registry.addRecipeCategoryCraftingItem(new ItemStack(Items.BREWING_STAND), VanillaRecipeCategoryUid.BREWING);
registry.addRecipeCategoryCraftingItem(new ItemStack(Blocks.ANVIL), VanillaRecipeCategoryUid.ANVIL);

registry.addRecipes(CraftingManager.getInstance().getRecipeList());
registry.addRecipes(SmeltingRecipeMaker.getFurnaceRecipes(jeiHelpers));
registry.addRecipes(FuelRecipeMaker.getFuelRecipes(ingredientRegistry, jeiHelpers));
registry.addRecipes(BrewingRecipeMaker.getBrewingRecipes(ingredientRegistry));
registry.addRecipes(TippedArrowRecipeMaker.getTippedArrowRecipes());

AnvilRecipeMaker.registerVanillaAnvilRecipes(registry);

IIngredientBlacklist ingredientBlacklist = registry.getJeiHelpers().getIngredientBlacklist();
// Game freezes when loading player skulls, see https://bugs.mojang.com/browse/MC-65587
ingredientBlacklist.addIngredientToBlacklist(new ItemStack(Items.SKULL, 1, 3));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package mezz.jei.plugins.vanilla.anvil;

import mezz.jei.api.IGuiHelper;
import mezz.jei.api.gui.IDrawable;
import mezz.jei.api.gui.IGuiItemStackGroup;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.ingredients.IIngredients;
import mezz.jei.api.recipe.BlankRecipeCategory;
import mezz.jei.api.recipe.VanillaRecipeCategoryUid;
import net.minecraft.init.Blocks;
import net.minecraft.util.ResourceLocation;

public class AnvilRecipeCategory extends BlankRecipeCategory<AnvilRecipeWrapper> {

private final IDrawable background;

public AnvilRecipeCategory(IGuiHelper guiHelper) {
ResourceLocation backgroundLocation = new ResourceLocation("textures/gui/container/anvil.png");
background = guiHelper.createDrawable(backgroundLocation, 16, 40, 145, 37);
}

@Override
public String getUid() {
return VanillaRecipeCategoryUid.ANVIL;
}

@Override
public String getTitle() {
return Blocks.ANVIL.getLocalizedName();
}

@Override
public IDrawable getBackground() {
return background;
}

@Override
public void setRecipe(IRecipeLayout recipeLayout, AnvilRecipeWrapper recipeWrapper, IIngredients ingredients) {
IGuiItemStackGroup guiItemStacks = recipeLayout.getItemStacks();

guiItemStacks.init(0, true, 10, 6);
guiItemStacks.init(1, true, 59, 6);
guiItemStacks.init(2, false, 117, 6);

guiItemStacks.set(ingredients);

recipeWrapper.setCurrentIngredients(guiItemStacks.getGuiIngredients());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package mezz.jei.plugins.vanilla.anvil;

import mezz.jei.api.recipe.IRecipeHandler;
import mezz.jei.api.recipe.IRecipeWrapper;
import mezz.jei.api.recipe.VanillaRecipeCategoryUid;

public class AnvilRecipeHandler implements IRecipeHandler<AnvilRecipeWrapper> {

@Override
public Class<AnvilRecipeWrapper> getRecipeClass() {
return AnvilRecipeWrapper.class;
}

@Override
public String getRecipeCategoryUid(AnvilRecipeWrapper recipe) {
return VanillaRecipeCategoryUid.ANVIL;
}

@Override
public IRecipeWrapper getRecipeWrapper(AnvilRecipeWrapper recipe) {
return recipe;
}

@Override
public boolean isRecipeValid(AnvilRecipeWrapper recipe) {
return true;
}
}
170 changes: 170 additions & 0 deletions src/main/java/mezz/jei/plugins/vanilla/anvil/AnvilRecipeMaker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package mezz.jei.plugins.vanilla.anvil;

import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import mezz.jei.api.IModRegistry;
import mezz.jei.util.FakeClientPlayer;
import mezz.jei.util.FakeClientWorld;
import mezz.jei.util.Log;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.inventory.ContainerRepair;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.oredict.OreDictionary;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class AnvilRecipeMaker {

public static void registerVanillaAnvilRecipes(IModRegistry registry) {
Stopwatch sw = Stopwatch.createStarted();
registerRepairRecipes(registry);
sw.stop();
Log.info("Registered vanilla repair recipes in {} ms", sw.elapsed(TimeUnit.MILLISECONDS));
sw.reset();
sw.start();
registerBookEnchantmentRecipes(registry);
sw.stop();
Log.info("Registered enchantment recipes in {} ms", sw.elapsed(TimeUnit.MILLISECONDS));
}

private static void registerBookEnchantmentRecipes(IModRegistry registry) {
List<ItemStack> ingredients = registry.getIngredientRegistry().getIngredients(ItemStack.class);
List<Enchantment> enchantments = ForgeRegistries.ENCHANTMENTS.getValues();
ItemStack book = new ItemStack(Items.ENCHANTED_BOOK);
for (ItemStack ingredient : ingredients) {
for (Enchantment enchantment : enchantments) {
if (enchantment.canApply(ingredient)) {
List<ItemStack> perLevelBooks = Lists.newArrayList();
List<ItemStack> perLevelOutputs = Lists.newArrayList();
for (int level = 1; level <= enchantment.getMaxLevel(); level++) {
ItemStack withEnchant = ingredient.copy();
ItemStack bookEnchant = book.copy();
Map<Enchantment, Integer> enchMap = Collections.singletonMap(enchantment, level);
EnchantmentHelper.setEnchantments(enchMap, withEnchant);
EnchantmentHelper.setEnchantments(enchMap, bookEnchant);
perLevelBooks.add(bookEnchant);
perLevelOutputs.add(withEnchant);
}
registry.addAnvilRecipe(ingredient, perLevelBooks, perLevelOutputs);
}
}
}
}

private static void registerRepairRecipes(IModRegistry registry) {
Map<ItemStack,List<ItemStack>> items = Maps.newHashMap();

ItemStack repairWood = new ItemStack(Blocks.PLANKS, 1, OreDictionary.WILDCARD_VALUE);
items.put(repairWood, Lists.newArrayList(
new ItemStack(Items.WOODEN_SWORD),
new ItemStack(Items.WOODEN_PICKAXE),
new ItemStack(Items.WOODEN_AXE),
new ItemStack(Items.WOODEN_SHOVEL),
new ItemStack(Items.WOODEN_HOE),
new ItemStack(Items.SHIELD)
));

ItemStack repairStone = new ItemStack(Blocks.COBBLESTONE);
items.put(repairStone, Lists.newArrayList(
new ItemStack(Items.STONE_SWORD),
new ItemStack(Items.STONE_PICKAXE),
new ItemStack(Items.STONE_AXE),
new ItemStack(Items.STONE_SHOVEL),
new ItemStack(Items.STONE_HOE)
));

ItemStack repairLeather = new ItemStack(Items.LEATHER);
items.put(repairLeather, Lists.newArrayList(
new ItemStack(Items.LEATHER_HELMET),
new ItemStack(Items.LEATHER_CHESTPLATE),
new ItemStack(Items.LEATHER_LEGGINGS),
new ItemStack(Items.LEATHER_BOOTS),
new ItemStack(Items.ELYTRA)
));

ItemStack repairIron = new ItemStack(Items.IRON_INGOT);
items.put(repairIron, Lists.newArrayList(
new ItemStack(Items.IRON_SWORD),
new ItemStack(Items.IRON_PICKAXE),
new ItemStack(Items.IRON_AXE),
new ItemStack(Items.IRON_SHOVEL),
new ItemStack(Items.IRON_HOE),
new ItemStack(Items.IRON_HELMET),
new ItemStack(Items.IRON_CHESTPLATE),
new ItemStack(Items.IRON_LEGGINGS),
new ItemStack(Items.IRON_BOOTS),
new ItemStack(Items.CHAINMAIL_HELMET),
new ItemStack(Items.CHAINMAIL_CHESTPLATE),
new ItemStack(Items.CHAINMAIL_LEGGINGS),
new ItemStack(Items.CHAINMAIL_BOOTS)
));

ItemStack repairGold = new ItemStack(Items.GOLD_INGOT);
items.put(repairGold, Lists.newArrayList(
new ItemStack(Items.GOLDEN_SWORD),
new ItemStack(Items.GOLDEN_PICKAXE),
new ItemStack(Items.GOLDEN_AXE),
new ItemStack(Items.GOLDEN_SHOVEL),
new ItemStack(Items.GOLDEN_HOE),
new ItemStack(Items.GOLDEN_HELMET),
new ItemStack(Items.GOLDEN_CHESTPLATE),
new ItemStack(Items.GOLDEN_LEGGINGS),
new ItemStack(Items.GOLDEN_BOOTS)
));

ItemStack repairDiamond = new ItemStack(Items.DIAMOND);
items.put(repairDiamond, Lists.newArrayList(
new ItemStack(Items.DIAMOND_SWORD),
new ItemStack(Items.DIAMOND_PICKAXE),
new ItemStack(Items.DIAMOND_AXE),
new ItemStack(Items.DIAMOND_SHOVEL),
new ItemStack(Items.DIAMOND_HOE),
new ItemStack(Items.DIAMOND_HELMET),
new ItemStack(Items.DIAMOND_CHESTPLATE),
new ItemStack(Items.DIAMOND_LEGGINGS),
new ItemStack(Items.DIAMOND_BOOTS)
));

for (Map.Entry<ItemStack,List<ItemStack>> entry : items.entrySet()) {

ItemStack repairMaterial = entry.getKey();

for (ItemStack ingredient : entry.getValue()) {

ItemStack damaged1 = ingredient.copy();
damaged1.setItemDamage(damaged1.getMaxDamage());
ItemStack damaged2 = ingredient.copy();
damaged2.setItemDamage(damaged2.getMaxDamage() * 3 / 4);
ItemStack damaged3 = ingredient.copy();
damaged3.setItemDamage(damaged3.getMaxDamage() * 2 / 4);

// Repair with material
registry.addAnvilRecipe(damaged1, Collections.singletonList(repairMaterial),
Collections.singletonList(damaged2));

// Repair with another of the same
registry.addAnvilRecipe(damaged2, Collections.singletonList(damaged2),
Collections.singletonList(damaged3));
}
}
}

public static int findLevelsCost(ItemStack leftStack, ItemStack rightStack)
{
FakeClientPlayer fakePlayer = FakeClientPlayer.getInstance();
InventoryPlayer fakeInventory = new InventoryPlayer(fakePlayer);
ContainerRepair repair = new ContainerRepair(fakeInventory, FakeClientWorld.getInstance(), fakePlayer);
repair.inventorySlots.get(0).putStack(leftStack);
repair.inventorySlots.get(1).putStack(rightStack);
return repair.maximumCost;
}
}
Loading

0 comments on commit 9891cbc

Please sign in to comment.