diff --git a/src/main/java/WayofTime/bloodmagic/api/IBloodMagicAPI.java b/src/main/java/WayofTime/bloodmagic/api/IBloodMagicAPI.java index a439d73e..daede4d1 100644 --- a/src/main/java/WayofTime/bloodmagic/api/IBloodMagicAPI.java +++ b/src/main/java/WayofTime/bloodmagic/api/IBloodMagicAPI.java @@ -3,6 +3,8 @@ package WayofTime.bloodmagic.api; import net.minecraft.block.state.IBlockState; import net.minecraft.util.ResourceLocation; +import javax.annotation.Nonnull; + public interface IBloodMagicAPI { /** @@ -10,9 +12,13 @@ public interface IBloodMagicAPI { * * @return the active blacklist instance */ + @Nonnull IBloodMagicBlacklist getBlacklist(); - void setSacrificialValue(ResourceLocation entityId, int value); + @Nonnull + IBloodMagicRecipeRegistrar getRecipeRegistrar(); - void registerAltarComponent(IBlockState state, String componentType); + void setSacrificialValue(@Nonnull ResourceLocation entityId, int value); + + void registerAltarComponent(@Nonnull IBlockState state, @Nonnull String componentType); } diff --git a/src/main/java/WayofTime/bloodmagic/api/IBloodMagicRecipeRegistrar.java b/src/main/java/WayofTime/bloodmagic/api/IBloodMagicRecipeRegistrar.java new file mode 100644 index 00000000..07e25481 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/api/IBloodMagicRecipeRegistrar.java @@ -0,0 +1,22 @@ +package WayofTime.bloodmagic.api; + +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + +public interface IBloodMagicRecipeRegistrar { + + void addBloodAltar(@Nonnull Ingredient input, @Nonnull ItemStack output, @Nonnegative int minimumTier, @Nonnegative int syphon, @Nonnegative int consumeRate, @Nonnegative int drainRate); + + boolean removeBloodAltar(@Nonnull ItemStack input); + + void addAlchemyTable(@Nonnull ItemStack output, @Nonnegative int syphon, @Nonnegative int ticks, @Nonnegative int minimumTier, @Nonnull Ingredient... input); + + boolean removeAlchemyTable(@Nonnull ItemStack... input); + + void addTartaricForge(@Nonnull ItemStack output, @Nonnegative double minimumSouls, @Nonnegative double soulDrain, @Nonnull Ingredient... input); + + boolean removeTartaricForge(@Nonnull ItemStack... input); +} diff --git a/src/main/java/WayofTime/bloodmagic/api/event/BloodMagicCraftedEvent.java b/src/main/java/WayofTime/bloodmagic/api/event/BloodMagicCraftedEvent.java new file mode 100644 index 00000000..507a3c30 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/api/event/BloodMagicCraftedEvent.java @@ -0,0 +1,49 @@ +package WayofTime.bloodmagic.api.event; + +import WayofTime.bloodmagic.api.impl.recipe.RecipeBloodAltar; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.common.eventhandler.Event; + +public class BloodMagicCraftedEvent extends Event { + + private final boolean modifiable; + private ItemStack output; + + public BloodMagicCraftedEvent(ItemStack output, boolean modifiable) { + this.modifiable = modifiable; + this.output = output; + } + + public boolean isModifiable() { + return modifiable; + } + + public ItemStack getOutput() { + return output; + } + + public void setOutput(ItemStack output) { + if (isModifiable()) + this.output = output; + } + + /** + * Fired whenever a craft is completed in a BloodAltar. + *

+ * It is not cancelable, however you can modify the output stack. + */ + public static class Altar extends BloodMagicCraftedEvent { + + private final RecipeBloodAltar recipe; + + public Altar(RecipeBloodAltar recipe, ItemStack output) { + super(output, true); + + this.recipe = recipe; + } + + public RecipeBloodAltar getRecipe() { + return recipe; + } + } +} diff --git a/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicAPI.java b/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicAPI.java index a8e9426e..353e8771 100644 --- a/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicAPI.java +++ b/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicAPI.java @@ -9,6 +9,7 @@ import com.google.common.collect.Multimap; import net.minecraft.block.state.IBlockState; import net.minecraft.util.ResourceLocation; +import javax.annotation.Nonnull; import java.util.*; public class BloodMagicAPI implements IBloodMagicAPI { @@ -16,27 +17,36 @@ public class BloodMagicAPI implements IBloodMagicAPI { public static final BloodMagicAPI INSTANCE = new BloodMagicAPI(); private final BloodMagicBlacklist blacklist; + private final BloodMagicRecipeRegistrar recipeRegistrar; private final Map sacrificialValues; private final Multimap altarComponents; public BloodMagicAPI() { this.blacklist = new BloodMagicBlacklist(); + this.recipeRegistrar = new BloodMagicRecipeRegistrar(); this.sacrificialValues = Maps.newHashMap(); this.altarComponents = ArrayListMultimap.create(); } + @Nonnull @Override public BloodMagicBlacklist getBlacklist() { return blacklist; } + @Nonnull @Override - public void setSacrificialValue(ResourceLocation entityId, int value) { + public BloodMagicRecipeRegistrar getRecipeRegistrar() { + return recipeRegistrar; + } + + @Override + public void setSacrificialValue(@Nonnull ResourceLocation entityId, int value) { sacrificialValues.put(entityId, value); } @Override - public void registerAltarComponent(IBlockState state, String componentType) { + public void registerAltarComponent(@Nonnull IBlockState state, @Nonnull String componentType) { EnumAltarComponent component = EnumAltarComponent.NOTAIR; for (EnumAltarComponent type : EnumAltarComponent.VALUES) { if (type.name().equalsIgnoreCase(componentType)) { @@ -48,10 +58,12 @@ public class BloodMagicAPI implements IBloodMagicAPI { altarComponents.put(component, state); } + @Nonnull public Map getSacrificialValues() { return ImmutableMap.copyOf(sacrificialValues); } + @Nonnull public List getComponentStates(EnumAltarComponent component) { return (List) altarComponents.get(component); } diff --git a/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicCorePlugin.java b/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicCorePlugin.java index 659a87d6..1cfadc41 100644 --- a/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicCorePlugin.java +++ b/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicCorePlugin.java @@ -11,6 +11,7 @@ import WayofTime.bloodmagic.block.BlockDecorative; import WayofTime.bloodmagic.block.enums.EnumBloodRune; import WayofTime.bloodmagic.block.enums.EnumDecorative; import WayofTime.bloodmagic.core.RegistrarBloodMagicBlocks; +import WayofTime.bloodmagic.core.RegistrarBloodMagicRecipes; import net.minecraft.block.Block; import net.minecraft.block.properties.IProperty; import net.minecraft.block.state.BlockStateContainer; @@ -60,6 +61,10 @@ public class BloodMagicCorePlugin implements IBloodMagicPlugin { BlockBloodRune bloodRune = (BlockBloodRune) RegistrarBloodMagicBlocks.BLOOD_RUNE; for (EnumBloodRune runeType : EnumBloodRune.values()) api.registerAltarComponent(bloodRune.getDefaultState().withProperty(bloodRune.getProperty(), runeType), EnumAltarComponent.BLOODRUNE.name()); + + RegistrarBloodMagicRecipes.registerAltarRecipes(((BloodMagicAPI) api).getRecipeRegistrar()); + RegistrarBloodMagicRecipes.registerAlchemyTableRecipes(((BloodMagicAPI) api).getRecipeRegistrar()); + RegistrarBloodMagicRecipes.registerTartaricForgeRecipes(((BloodMagicAPI) api).getRecipeRegistrar()); } private static void handleConfigValues(IBloodMagicAPI api) { diff --git a/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicRecipeRegistrar.java b/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicRecipeRegistrar.java new file mode 100644 index 00000000..ce789e78 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/api/impl/BloodMagicRecipeRegistrar.java @@ -0,0 +1,211 @@ +package WayofTime.bloodmagic.api.impl; + +import WayofTime.bloodmagic.api.IBloodMagicRecipeRegistrar; +import WayofTime.bloodmagic.api.impl.recipe.RecipeAlchemyTable; +import WayofTime.bloodmagic.api.impl.recipe.RecipeBloodAltar; +import WayofTime.bloodmagic.api.impl.recipe.RecipeTartaricForge; +import WayofTime.bloodmagic.apibutnotreally.orb.IBloodOrb; +import WayofTime.bloodmagic.core.recipe.IngredientBloodOrb; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.NonNullList; +import net.minecraftforge.common.crafting.CraftingHelper; + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Set; + +public class BloodMagicRecipeRegistrar implements IBloodMagicRecipeRegistrar { + + private final Set altarRecipes; + private final Set alchemyRecipes; + private final Set tartaricForgeRecipes; + + public BloodMagicRecipeRegistrar() { + this.altarRecipes = Sets.newHashSet(); + this.alchemyRecipes = Sets.newHashSet(); + this.tartaricForgeRecipes = Sets.newHashSet(); + } + + @Override + public void addBloodAltar(@Nonnull Ingredient input, @Nonnull ItemStack output, @Nonnegative int minimumTier, @Nonnegative int syphon, @Nonnegative int consumeRate, @Nonnegative int drainRate) { + Preconditions.checkNotNull(input, "input cannot be null."); + Preconditions.checkNotNull(output, "output cannot be null."); + Preconditions.checkArgument(minimumTier >= 0, "minimumTier cannot be negative."); + Preconditions.checkArgument(syphon >= 0, "syphon cannot be negative."); + Preconditions.checkArgument(consumeRate >= 0, "consumeRate cannot be negative."); + Preconditions.checkArgument(drainRate >= 0, "drainRate cannot be negative."); + + altarRecipes.add(new RecipeBloodAltar(input, output, minimumTier, syphon, consumeRate, drainRate)); + } + + @Override + public boolean removeBloodAltar(@Nonnull ItemStack input) { + Preconditions.checkNotNull(input, "input cannot be null."); + + return altarRecipes.remove(getBloodAltar(input)); + } + + @Override + public void addAlchemyTable(@Nonnull ItemStack output, @Nonnegative int syphon, @Nonnegative int ticks, @Nonnegative int minimumTier, @Nonnull Ingredient... input) { + Preconditions.checkNotNull(output, "output cannot be null."); + Preconditions.checkArgument(syphon >= 0, "syphon cannot be negative."); + Preconditions.checkArgument(ticks >= 0, "ticks cannot be negative."); + Preconditions.checkArgument(minimumTier >= 0, "minimumTier cannot be negative."); + Preconditions.checkNotNull(input, "input cannot be null."); + + NonNullList inputs = NonNullList.from(Ingredient.EMPTY, input); + alchemyRecipes.add(new RecipeAlchemyTable(inputs, output, syphon, ticks, minimumTier)); + } + + public void addAlchemyTable(@Nonnull ItemStack output, @Nonnegative int syphon, @Nonnegative int ticks, @Nonnegative int minimumTier, @Nonnull Object... input) { + Preconditions.checkNotNull(output, "output cannot be null."); + Preconditions.checkArgument(syphon >= 0, "syphon cannot be negative."); + Preconditions.checkArgument(ticks >= 0, "ticks cannot be negative."); + Preconditions.checkArgument(minimumTier >= 0, "minimumTier cannot be negative."); + Preconditions.checkNotNull(input, "input cannot be null."); + + List ingredients = Lists.newArrayList(); + for (Object object : input) { + if (object instanceof ItemStack && ((ItemStack) object).getItem() instanceof IBloodOrb) { + ingredients.add(new IngredientBloodOrb(((IBloodOrb) ((ItemStack) object).getItem()).getOrb((ItemStack) object))); + continue; + } + + ingredients.add(CraftingHelper.getIngredient(object)); + } + + addAlchemyTable(output, syphon, ticks, minimumTier, ingredients.toArray(new Ingredient[0])); + } + + public void addAlchemyTable(RecipeAlchemyTable recipe) { + alchemyRecipes.add(recipe); + } + + @Override + public boolean removeAlchemyTable(@Nonnull ItemStack... input) { + Preconditions.checkNotNull(input, "inputs cannot be null."); + + for (ItemStack stack : input) + Preconditions.checkNotNull(stack, "input cannot be null."); + + return alchemyRecipes.remove(getAlchemyTable(Lists.newArrayList(input))); + } + + @Override + public void addTartaricForge(@Nonnull ItemStack output, @Nonnegative double minimumSouls, @Nonnegative double soulDrain, @Nonnull Ingredient... input) { + Preconditions.checkNotNull(output, "output cannot be null."); + Preconditions.checkArgument(minimumSouls >= 0, "minimumSouls cannot be negative."); + Preconditions.checkArgument(soulDrain >= 0, "soulDrain cannot be negative."); + Preconditions.checkNotNull(input, "input cannot be null."); + + NonNullList inputs = NonNullList.from(Ingredient.EMPTY, input); + tartaricForgeRecipes.add(new RecipeTartaricForge(inputs, output, minimumSouls, soulDrain)); + } + + @Override + public boolean removeTartaricForge(@Nonnull ItemStack... input) { + Preconditions.checkNotNull(input, "inputs cannot be null."); + + for (ItemStack stack : input) + Preconditions.checkNotNull(stack, "input cannot be null."); + + return tartaricForgeRecipes.remove(getTartaricForge(Lists.newArrayList(input))); + } + + public void addTartaricForge(@Nonnull ItemStack output, @Nonnegative double minimumSouls, @Nonnegative double soulDrain, @Nonnull Object... input) { + Preconditions.checkNotNull(output, "output cannot be null."); + Preconditions.checkArgument(minimumSouls >= 0, "minimumSouls cannot be negative."); + Preconditions.checkArgument(soulDrain >= 0, "soulDrain cannot be negative."); + Preconditions.checkNotNull(input, "input cannot be null."); + + List ingredients = Lists.newArrayList(); + for (Object object : input) { + if (object instanceof ItemStack && ((ItemStack) object).getItem() instanceof IBloodOrb) { + ingredients.add(new IngredientBloodOrb(((IBloodOrb) ((ItemStack) object).getItem()).getOrb((ItemStack) object))); + continue; + } + + ingredients.add(CraftingHelper.getIngredient(object)); + } + + addTartaricForge(output, minimumSouls, soulDrain, ingredients.toArray(new Ingredient[0])); + } + + @Nullable + public RecipeBloodAltar getBloodAltar(@Nonnull ItemStack input) { + Preconditions.checkNotNull(input, "input cannot be null."); + if (input.isEmpty()) + return null; + + for (RecipeBloodAltar recipe : altarRecipes) + if (recipe.getInput().test(input)) + return recipe; + + return null; + } + + @Nullable + public RecipeAlchemyTable getAlchemyTable(@Nonnull List input) { + Preconditions.checkNotNull(input, "input cannot be null."); + if (input.isEmpty()) + return null; + + mainLoop: + for (RecipeAlchemyTable recipe : alchemyRecipes) { + if (recipe.getInput().size() != input.size()) + continue; + + for (int i = 0; i < input.size(); i++) { + Ingredient ingredient = recipe.getInput().get(i); + if (!ingredient.apply(input.get(i))) + continue mainLoop; + } + + return recipe; + } + + return null; + } + + @Nullable + public RecipeTartaricForge getTartaricForge(@Nonnull List input) { + Preconditions.checkNotNull(input, "input cannot be null."); + if (input.isEmpty()) + return null; + + mainLoop: + for (RecipeTartaricForge recipe : tartaricForgeRecipes) { + if (recipe.getInput().size() != input.size()) + continue; + + for (int i = 0; i < input.size(); i++) { + Ingredient ingredient = recipe.getInput().get(i); + if (!ingredient.apply(input.get(i))) + continue mainLoop; + } + + return recipe; + } + + return null; + } + + public Set getAltarRecipes() { + return ImmutableSet.copyOf(altarRecipes); + } + + public Set getAlchemyRecipes() { + return ImmutableSet.copyOf(alchemyRecipes); + } + + public Set getTartaricForgeRecipes() { + return ImmutableSet.copyOf(tartaricForgeRecipes); + } +} diff --git a/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeAlchemyTable.java b/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeAlchemyTable.java new file mode 100644 index 00000000..7fe572b0 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeAlchemyTable.java @@ -0,0 +1,59 @@ +package WayofTime.bloodmagic.api.impl.recipe; + +import com.google.common.base.Preconditions; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.NonNullList; + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + +public class RecipeAlchemyTable { + + @Nonnull + private final NonNullList input; + @Nonnull + private final ItemStack output; + @Nonnegative + private final int syphon; + @Nonnegative + private final int ticks; + @Nonnegative + private final int minimumTier; + + public RecipeAlchemyTable(@Nonnull NonNullList input, @Nonnull ItemStack output, int syphon, int ticks, int minimumTier) { + Preconditions.checkNotNull(input, "input cannot be null."); + Preconditions.checkNotNull(output, "output cannot be null."); + Preconditions.checkArgument(syphon >= 0, "syphon cannot be negative."); + Preconditions.checkArgument(ticks >= 0, "ticks cannot be negative."); + Preconditions.checkArgument(minimumTier >= 0, "minimumTier cannot be negative."); + + this.input = input; + this.output = output; + this.syphon = syphon; + this.ticks = ticks; + this.minimumTier = minimumTier; + } + + @Nonnull + public final NonNullList getInput() { + return input; + } + + @Nonnull + public final ItemStack getOutput() { + return output; + } + + public final int getSyphon() { + return syphon; + } + + public final int getTicks() { + return ticks; + } + + public final int getMinimumTier() { + return minimumTier; + } +} diff --git a/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeBloodAltar.java b/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeBloodAltar.java new file mode 100644 index 00000000..40f01944 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeBloodAltar.java @@ -0,0 +1,72 @@ +package WayofTime.bloodmagic.api.impl.recipe; + +import WayofTime.bloodmagic.apibutnotreally.altar.EnumAltarTier; +import com.google.common.base.Preconditions; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + +public class RecipeBloodAltar { + + @Nonnull + private final Ingredient input; + @Nonnull + private final ItemStack output; + @Nonnull + private final EnumAltarTier minimumTier; + @Nonnegative + private final int syphon; + @Nonnegative + private final int consumeRate; + @Nonnegative + private final int drainRate; + + public RecipeBloodAltar(@Nonnull Ingredient input, @Nonnull ItemStack output, @Nonnegative int minimumTier, @Nonnegative int syphon, @Nonnegative int consumeRate, @Nonnegative int drainRate) { + Preconditions.checkNotNull(input, "input cannot be null."); + Preconditions.checkNotNull(output, "output cannot be null."); + Preconditions.checkArgument(minimumTier >= 0, "minimumTier cannot be negative."); + Preconditions.checkArgument(minimumTier <= EnumAltarTier.MAXTIERS, "minimumTier cannot be higher than max tier"); + Preconditions.checkArgument(syphon >= 0, "syphon cannot be negative."); + Preconditions.checkArgument(consumeRate >= 0, "consumeRate cannot be negative."); + Preconditions.checkArgument(drainRate >= 0, "drain cannot be negative."); + + this.input = input; + this.output = output; + this.minimumTier = EnumAltarTier.values()[minimumTier]; + this.syphon = syphon; + this.consumeRate = consumeRate; + this.drainRate = drainRate; + } + + @Nonnull + public final Ingredient getInput() { + return input; + } + + @Nonnull + public final ItemStack getOutput() { + return output; + } + + @Nonnull + public EnumAltarTier getMinimumTier() { + return minimumTier; + } + + @Nonnegative + public final int getSyphon() { + return syphon; + } + + @Nonnegative + public final int getConsumeRate() { + return consumeRate; + } + + @Nonnegative + public final int getDrainRate() { + return drainRate; + } +} diff --git a/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeTartaricForge.java b/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeTartaricForge.java new file mode 100644 index 00000000..96021cad --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/api/impl/recipe/RecipeTartaricForge.java @@ -0,0 +1,53 @@ +package WayofTime.bloodmagic.api.impl.recipe; + +import com.google.common.base.Preconditions; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.NonNullList; + +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + +public class RecipeTartaricForge { + + @Nonnull + private final NonNullList input; + @Nonnull + private final ItemStack output; + @Nonnegative + private final double minimumSouls; + @Nonnegative + private final double soulDrain; + + public RecipeTartaricForge(@Nonnull NonNullList input, @Nonnull ItemStack output, @Nonnegative double minimumSouls, @Nonnegative double soulDrain) { + Preconditions.checkNotNull(input, "input cannot be null."); + Preconditions.checkNotNull(output, "output cannot be null."); + Preconditions.checkArgument(minimumSouls >= 0, "minimumSouls cannot be negative."); + Preconditions.checkArgument(soulDrain >= 0, "soulDrain cannot be negative."); + + this.input = input; + this.output = output; + this.minimumSouls = minimumSouls; + this.soulDrain = soulDrain; + } + + @Nonnull + public final NonNullList getInput() { + return input; + } + + @Nonnull + public final ItemStack getOutput() { + return output; + } + + @Nonnegative + public final double getMinimumSouls() { + return minimumSouls; + } + + @Nonnegative + public final double getSoulDrain() { + return soulDrain; + } +}