Add imbuement altar 'recipes' to JEI
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
package electroblob.wizardry.integration.jei;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import mezz.jei.api.ingredients.IIngredients;
|
||||
import mezz.jei.api.ingredients.VanillaTypes;
|
||||
import mezz.jei.api.recipe.IRecipeWrapper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a 'recipe' for the imbuement altar.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.3
|
||||
*/
|
||||
public class ImbuementAltarRecipe implements IRecipeWrapper {
|
||||
|
||||
private final ItemStack result;
|
||||
|
||||
private final List<List<ItemStack>> inputs;
|
||||
|
||||
public ImbuementAltarRecipe(ItemStack centreStack, List<List<ItemStack>> dusts, ItemStack result){
|
||||
|
||||
this.result = result;
|
||||
|
||||
this.inputs = new ArrayList<>();
|
||||
this.inputs.add(Collections.singletonList(centreStack));
|
||||
|
||||
if(dusts.size() > 4){
|
||||
Wizardry.logger.warn("Tried to create an imbuement altar JEI recipe with more than 4 dust stacks, ignoring the rest");
|
||||
dusts = dusts.subList(0, 4);
|
||||
}else if(dusts.size() < 4){
|
||||
throw new IllegalArgumentException("Imbuement altar recipes require 4 stacks of dust");
|
||||
}
|
||||
|
||||
this.inputs.addAll(dusts);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getIngredients(IIngredients ingredients){
|
||||
ingredients.setInputLists(VanillaTypes.ITEM, inputs);
|
||||
ingredients.setOutput(VanillaTypes.ITEM, result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
package electroblob.wizardry.integration.jei;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.constants.Element;
|
||||
import electroblob.wizardry.item.ItemWizardArmour;
|
||||
import electroblob.wizardry.registry.WizardryBlocks;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.tileentity.TileEntityImbuementAltar;
|
||||
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.ingredients.VanillaTypes;
|
||||
import mezz.jei.api.recipe.IRecipeCategory;
|
||||
import mezz.jei.api.recipe.IRecipeCategoryRegistration;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* JEI recipe category implementation for all 'recipes' in the imbuement altar.
|
||||
*
|
||||
* @author Electroblob
|
||||
* @since Wizardry 4.3
|
||||
*/
|
||||
public class ImbuementAltarRecipeCategory implements IRecipeCategory<ImbuementAltarRecipe> {
|
||||
|
||||
static final String UID = "ebwizardry:imbuement_altar";
|
||||
static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/integration/jei/imbuement_altar_background.png");
|
||||
|
||||
static final int WIDTH = 134;
|
||||
static final int HEIGHT = 74;
|
||||
// Annoyingly, these seem to be for 18x18 slots rather than the actual highlighted area, unlike container slots
|
||||
static final int CENTRE_SLOT_X = 28;
|
||||
static final int CENTRE_SLOT_Y = 28;
|
||||
static final int SLOT_SPACING_X = 28;
|
||||
static final int SLOT_SPACING_Y = 28;
|
||||
static final int OUTPUT_SLOT_X = 112;
|
||||
static final int OUTPUT_SLOT_Y = 28;
|
||||
|
||||
private final IDrawable background;
|
||||
|
||||
public ImbuementAltarRecipeCategory(IRecipeCategoryRegistration registry){
|
||||
IGuiHelper helper = registry.getJeiHelpers().getGuiHelper();
|
||||
background = helper.createDrawable(TEXTURE, 0, 0, WIDTH, HEIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUid(){
|
||||
return UID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle(){
|
||||
// JEI is client-side, so client classes can safely be used here
|
||||
return I18n.format("integration.jei.category." + UID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModName(){
|
||||
return Wizardry.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDrawable getBackground(){
|
||||
return background;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecipe(IRecipeLayout recipeLayout, ImbuementAltarRecipe recipeWrapper, IIngredients ingredients){
|
||||
|
||||
// Okay, they're not technically *slots* but to all intents and purposes, that's how they behave
|
||||
IGuiItemStackGroup slots = recipeLayout.getItemStacks();
|
||||
|
||||
List<List<ItemStack>> inputs = ingredients.getInputs(VanillaTypes.ITEM);
|
||||
List<List<ItemStack>> outputs = ingredients.getOutputs(VanillaTypes.ITEM);
|
||||
|
||||
// Slot initialisation
|
||||
int i = 0;
|
||||
slots.init(i++, true, CENTRE_SLOT_X, CENTRE_SLOT_Y); // Centre
|
||||
slots.init(i++, true, CENTRE_SLOT_X, CENTRE_SLOT_Y - SLOT_SPACING_Y); // Top
|
||||
slots.init(i++, true, CENTRE_SLOT_X - SLOT_SPACING_X, CENTRE_SLOT_Y); // Left
|
||||
slots.init(i++, true, CENTRE_SLOT_X, CENTRE_SLOT_Y + SLOT_SPACING_Y); // Bottom
|
||||
slots.init(i++, true, CENTRE_SLOT_X + SLOT_SPACING_X, CENTRE_SLOT_Y); // Right
|
||||
slots.init(i++, false, OUTPUT_SLOT_X, OUTPUT_SLOT_Y); // Output
|
||||
|
||||
// Assign ingredients to slots
|
||||
for(int j = 0; j < inputs.size(); j++) slots.set(j, inputs.get(j));
|
||||
for(int k = 0; k < outputs.size(); k++) slots.set(inputs.size() + k, outputs.get(k));
|
||||
|
||||
}
|
||||
|
||||
/** Called to generate all of wizardry's imbuement altar 'recipes' for JEI. */
|
||||
public static Collection<ImbuementAltarRecipe> generateRecipes(){
|
||||
|
||||
List<ImbuementAltarRecipe> recipes = new ArrayList<>();
|
||||
|
||||
recipes.addAll(generateBookRecipes());
|
||||
recipes.addAll(generateCrystalRecipes());
|
||||
recipes.addAll(generateCrystalBlockRecipes());
|
||||
recipes.addAll(generateArmourRecipes());
|
||||
|
||||
return recipes;
|
||||
|
||||
}
|
||||
|
||||
private static Collection<ImbuementAltarRecipe> generateBookRecipes(){
|
||||
|
||||
List<ImbuementAltarRecipe> recipes = new ArrayList<>();
|
||||
|
||||
NonNullList<ItemStack> variants = NonNullList.create();
|
||||
WizardryItems.spectral_dust.getSubItems(WizardryItems.spectral_dust.getCreativeTab(), variants);
|
||||
List<List<ItemStack>> dusts = Collections.nCopies(4, variants);
|
||||
|
||||
recipes.add(new ImbuementAltarRecipe(new ItemStack(WizardryItems.ruined_spell_book), dusts, new ItemStack(WizardryItems.spell_book, 1, OreDictionary.WILDCARD_VALUE)));
|
||||
|
||||
return recipes;
|
||||
|
||||
}
|
||||
|
||||
private static Collection<ImbuementAltarRecipe> generateCrystalRecipes(){
|
||||
|
||||
List<ImbuementAltarRecipe> recipes = new ArrayList<>();
|
||||
|
||||
ItemStack input = new ItemStack(WizardryItems.magic_crystal);
|
||||
|
||||
for(int meta = 1; meta < Element.values().length; meta++){
|
||||
List<List<ItemStack>> dusts = Collections.nCopies(4, Collections.singletonList(new ItemStack(WizardryItems.spectral_dust, 1, meta)));
|
||||
ItemStack output = new ItemStack(WizardryItems.magic_crystal, 1, meta);
|
||||
recipes.add(new ImbuementAltarRecipe(input, dusts, output));
|
||||
}
|
||||
|
||||
return recipes;
|
||||
|
||||
}
|
||||
|
||||
private static Collection<ImbuementAltarRecipe> generateCrystalBlockRecipes(){
|
||||
|
||||
List<ImbuementAltarRecipe> recipes = new ArrayList<>();
|
||||
|
||||
ItemStack input = new ItemStack(WizardryBlocks.crystal_block);
|
||||
|
||||
for(int meta = 1; meta < Element.values().length; meta++){
|
||||
List<List<ItemStack>> dusts = Collections.nCopies(4, Collections.singletonList(new ItemStack(WizardryItems.spectral_dust, 1, meta)));
|
||||
ItemStack output = new ItemStack(WizardryBlocks.crystal_block, 1, meta);
|
||||
recipes.add(new ImbuementAltarRecipe(input, dusts, output));
|
||||
}
|
||||
|
||||
return recipes;
|
||||
|
||||
}
|
||||
|
||||
private static Collection<ImbuementAltarRecipe> generateArmourRecipes(){
|
||||
|
||||
List<ImbuementAltarRecipe> recipes = new ArrayList<>();
|
||||
|
||||
for(Item item : Item.REGISTRY){
|
||||
|
||||
if(item instanceof ItemWizardArmour){
|
||||
|
||||
ItemStack input = new ItemStack(item);
|
||||
|
||||
for(Element e : Element.values()){
|
||||
|
||||
if(e == Element.MAGIC) continue;
|
||||
|
||||
List<List<ItemStack>> dusts = Collections.nCopies(4, Collections.singletonList(new ItemStack(WizardryItems.spectral_dust, 1, e.ordinal())));
|
||||
ItemStack output = TileEntityImbuementAltar.getImbuementResult(input, new Element[]{e, e, e, e}, false, null, null);
|
||||
|
||||
if(!output.isEmpty()) recipes.add(new ImbuementAltarRecipe(input, dusts, output));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return recipes;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,6 +34,7 @@ public class WizardryJEIPlugin implements IModPlugin {
|
||||
if(!Wizardry.settings.jeiIntegration) return;
|
||||
|
||||
registry.addRecipeCategories(new ArcaneWorkbenchRecipeCategory(registry));
|
||||
registry.addRecipeCategories(new ImbuementAltarRecipeCategory(registry));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -43,11 +44,13 @@ public class WizardryJEIPlugin implements IModPlugin {
|
||||
|
||||
// Add arcane workbench as the item required to use arcane workbench recipes
|
||||
registry.addRecipeCatalyst(new ItemStack(WizardryBlocks.arcane_workbench), ArcaneWorkbenchRecipeCategory.UID);
|
||||
|
||||
registry.addRecipes(ArcaneWorkbenchRecipeCategory.generateRecipes(), ArcaneWorkbenchRecipeCategory.UID);
|
||||
|
||||
registry.getRecipeTransferRegistry().addRecipeTransferHandler(new ArcaneWorkbenchTransferHandler());
|
||||
|
||||
// Add imbuement altar as the item required to use imbuement altar recipes
|
||||
registry.addRecipeCatalyst(new ItemStack(WizardryBlocks.imbuement_altar), ImbuementAltarRecipeCategory.UID);
|
||||
registry.addRecipes(ImbuementAltarRecipeCategory.generateRecipes(), ImbuementAltarRecipeCategory.UID);
|
||||
|
||||
// Hide conjured items from JEI
|
||||
IIngredientBlacklist blacklist = registry.getJeiHelpers().getIngredientBlacklist();
|
||||
for(Item item : Item.REGISTRY){
|
||||
|
||||
@@ -22,6 +22,7 @@ import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.ITickable;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.storage.loot.LootContext;
|
||||
import net.minecraft.world.storage.loot.LootTable;
|
||||
@@ -134,55 +135,20 @@ public class TileEntityImbuementAltar extends TileEntity implements ITickable {
|
||||
|
||||
private ItemStack getResult(){
|
||||
|
||||
if(stack.getItem() instanceof ItemWizardArmour && ((ItemWizardArmour)stack.getItem()).element == null){
|
||||
boolean actuallyCrafting = imbuementTimer >= IMBUEMENT_DURATION - 1 && world instanceof WorldServer;
|
||||
Element[] elements = getReceptacleElements();
|
||||
|
||||
Element[] elements = getReceptacleElements();
|
||||
ItemStack result = getImbuementResult(stack, elements, actuallyCrafting, world, lastUser);
|
||||
|
||||
if(Arrays.stream(elements).distinct().count() == 1 && elements[0] != null){ // All the same element
|
||||
|
||||
ItemStack result = new ItemStack(WizardryItems.getArmour(elements[0], ((ItemWizardArmour)stack.getItem()).armorType));
|
||||
displayElement = elements[0];
|
||||
|
||||
result.setTagCompound(stack.getTagCompound());
|
||||
((IManaStoringItem)result.getItem()).setMana(result, ((ItemWizardArmour)stack.getItem()).getMana(stack));
|
||||
|
||||
return result;
|
||||
}
|
||||
if(result.isEmpty()){
|
||||
displayElement = null;
|
||||
}else if(Arrays.stream(elements).distinct().count() == 1){ // All the same element
|
||||
displayElement = elements[0];
|
||||
}else{
|
||||
displayElement = Element.MAGIC;
|
||||
}
|
||||
|
||||
if((stack.getItem() == WizardryItems.magic_crystal || stack.getItem() == Item.getItemFromBlock(WizardryBlocks.crystal_block))
|
||||
&& stack.getMetadata() == 0){
|
||||
|
||||
Element[] elements = getReceptacleElements();
|
||||
|
||||
if(Arrays.stream(elements).distinct().count() == 1 && elements[0] != null){ // All the same element
|
||||
displayElement = elements[0];
|
||||
return new ItemStack(stack.getItem(), stack.getCount(), elements[0].ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
if(stack.getItem() == WizardryItems.ruined_spell_book){
|
||||
|
||||
if(!ArrayUtils.contains(getReceptacleElements(), null)){ // All receptacles filled (any element)
|
||||
|
||||
if(imbuementTimer >= IMBUEMENT_DURATION - 1 && world instanceof WorldServer){
|
||||
|
||||
LootTable table = this.world.getLootTableManager().getLootTableFromLocation(WizardryLoot.RUINED_SPELL_BOOK_LOOT_TABLE);
|
||||
LootContext context = new LootContext.Builder((WorldServer)world).withPlayer(lastUser)
|
||||
.withLuck(lastUser == null ? 0 : lastUser.getLuck()).build();
|
||||
|
||||
List<ItemStack> stacks = table.generateLootForPools(world.rand, context);
|
||||
return stacks.isEmpty() ? ItemStack.EMPTY : stacks.get(0);
|
||||
}
|
||||
|
||||
displayElement = Element.MAGIC;
|
||||
|
||||
return new ItemStack(WizardryItems.spell_book); // No point generating loot every tick just to check the recipe
|
||||
}
|
||||
}
|
||||
|
||||
displayElement = null;
|
||||
return ItemStack.EMPTY;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Returns the elements of the 4 adjacent receptacles, in SWNE order. Null means an empty or missing receptacle. */
|
||||
@@ -253,4 +219,59 @@ public class TileEntityImbuementAltar extends TileEntity implements ITickable {
|
||||
readFromNBT(pkt.getNbtCompound());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stack that results from imbuing the given input with the given elements.
|
||||
* @param input The item stack being imbued
|
||||
* @param receptacleElements The elements of the four receptacles
|
||||
* @param fullLootGen True to perform full loot generation from loot tables, false if this is just being queried for
|
||||
* visuals or other purposes.
|
||||
* @param world A reference to the current world object (may be null if {@code fullLootGen} is false)
|
||||
* @param lastUser The player that last interacted with the imbuement altar, or null if there isn't one (or if this
|
||||
* is being queried for other reasons, e.g. JEI)
|
||||
* @return The resulting item stack, or an empty stack if the given combination is not a valid imbuement
|
||||
*/
|
||||
public static ItemStack getImbuementResult(ItemStack input, Element[] receptacleElements, boolean fullLootGen, World world, EntityPlayer lastUser){
|
||||
|
||||
if(input.getItem() instanceof ItemWizardArmour && ((ItemWizardArmour)input.getItem()).element == null){
|
||||
|
||||
if(Arrays.stream(receptacleElements).distinct().count() == 1 && receptacleElements[0] != null){ // All the same element
|
||||
|
||||
ItemStack result = new ItemStack(WizardryItems.getArmour(receptacleElements[0], ((ItemWizardArmour)input.getItem()).armorType));
|
||||
|
||||
result.setTagCompound(input.getTagCompound());
|
||||
((IManaStoringItem)result.getItem()).setMana(result, ((ItemWizardArmour)input.getItem()).getMana(input));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if((input.getItem() == WizardryItems.magic_crystal || input.getItem() == Item.getItemFromBlock(WizardryBlocks.crystal_block))
|
||||
&& input.getMetadata() == 0){
|
||||
|
||||
if(Arrays.stream(receptacleElements).distinct().count() == 1 && receptacleElements[0] != null){ // All the same element
|
||||
return new ItemStack(input.getItem(), input.getCount(), receptacleElements[0].ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
if(input.getItem() == WizardryItems.ruined_spell_book){
|
||||
|
||||
if(!ArrayUtils.contains(receptacleElements, null)){ // All receptacles filled (any element)
|
||||
|
||||
if(fullLootGen){
|
||||
|
||||
LootTable table = world.getLootTableManager().getLootTableFromLocation(WizardryLoot.RUINED_SPELL_BOOK_LOOT_TABLE);
|
||||
LootContext context = new LootContext.Builder((WorldServer)world).withPlayer(lastUser)
|
||||
.withLuck(lastUser == null ? 0 : lastUser.getLuck()).build();
|
||||
|
||||
List<ItemStack> stacks = table.generateLootForPools(world.rand, context);
|
||||
return stacks.isEmpty() ? ItemStack.EMPTY : stacks.get(0);
|
||||
}
|
||||
|
||||
return new ItemStack(WizardryItems.spell_book); // No point generating loot every tick just to check the recipe
|
||||
}
|
||||
}
|
||||
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1592,6 +1592,7 @@ config.ebwizardry.auto_place_underground_library_markers=Auto-Place Underground
|
||||
config.ebwizardry.auto_place_underground_library_markers.tooltip=Controls whether wizardry automatically places antique atlas markers at the locations of underground library ruins.
|
||||
|
||||
integration.jei.category.ebwizardry\:arcane_workbench=Arcane Workbench
|
||||
integration.jei.category.ebwizardry\:imbuement_altar=Imbuement Altar
|
||||
|
||||
integration.antiqueatlas.marker.ebwizardry.wizard_tower=Wizard Tower
|
||||
integration.antiqueatlas.marker.ebwizardry.obelisk=Obelisk
|
||||
|
||||
@@ -1592,6 +1592,7 @@ config.ebwizardry.auto_place_underground_library_markers=Auto-Place Underground
|
||||
config.ebwizardry.auto_place_underground_library_markers.tooltip=Controls whether wizardry automatically places antique atlas markers at the locations of underground library ruins.
|
||||
|
||||
integration.jei.category.ebwizardry\:arcane_workbench=Arcane Workbench
|
||||
integration.jei.category.ebwizardry\:imbuement_altar=Imbuement Altar
|
||||
|
||||
integration.antiqueatlas.marker.ebwizardry.wizard_tower=Wizard Tower
|
||||
integration.antiqueatlas.marker.ebwizardry.obelisk=Obelisk
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Reference in New Issue
Block a user