Creating a usable API (#1713)

* Initial stab at API structuring

* Throwing all the things into the API*
Eliminated all internal imports
Also added some helpful comments
*except for the ritual stuff

* Reducing the API
Threw back the altar/incense/unnecessary items to main
Added in a functional API instance

* API cleanup
Removing all the unnecessities
Smushed and vaporized some redundant recipe stuffs

* Made API dummy instances
Refactor packaging
This commit is contained in:
Arcaratus 2020-11-23 21:03:19 -05:00 committed by GitHub
parent 952b6aeeb0
commit 574d6a8e74
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
144 changed files with 558 additions and 990 deletions

View file

@ -3,6 +3,11 @@ package wayoftime.bloodmagic.api;
import javax.annotation.Nonnull;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.LazyValue;
import org.apache.logging.log4j.LogManager;
import java.util.function.Predicate;
/**
* The main interface between a plugin and Blood Magic's internals.
@ -11,12 +16,22 @@ import net.minecraft.block.BlockState;
* Magic. More advanced integration is out of the scope of this API and are
* considered "addons".
*
* To get an instance of this without actually creating an
* {@link IBloodMagicPlugin}, use {@link BloodMagicPlugin.Inject}.
* Use INSTANCE to get an instance of the API without actually implementing anything
*/
public interface IBloodMagicAPI
{
LazyValue<IBloodMagicAPI> INSTANCE = new LazyValue<>(() ->
{
try
{
return (IBloodMagicAPI) Class.forName("wayoftime.bloodmagic.impl.BloodMagicAPI").getDeclaredField("INSTANCE").get(null);
}
catch (ReflectiveOperationException e)
{
LogManager.getLogger().warn("Unable to find BloodMagicAPI, using a dummy instance instead...");
return new IBloodMagicAPI() {};
}
});
// /**
// * Retrieves the instance of the blacklist.
// *
@ -25,24 +40,19 @@ public interface IBloodMagicAPI
// @Nonnull
// IBloodMagicBlacklist getBlacklist();
/**
* Retrieves the instance of the recipe registrar.
*
* @return the active {@link IBloodMagicRecipeRegistrar} instance
*/
@Nonnull
IBloodMagicRecipeRegistrar getRecipeRegistrar();
/**
* Retrieves the instance of the value manager.
*
* @return the active {@link IBloodMagicValueManager} instance
*/
@Nonnull
IBloodMagicValueManager getValueManager();
default IBloodMagicValueManager getValueManager()
{
return new IBloodMagicValueManager() {};
}
/**
* Registers an {@link IBlockState} as a given component for the Blood Altar.
* Registers a {@link BlockState} as a given component for the Blood Altar.
* <p>
* Valid component types:
* <ul>
@ -57,10 +67,10 @@ public interface IBloodMagicAPI
* @param state The state to register
* @param componentType The type of Blood Altar component to register as.
*/
void registerAltarComponent(@Nonnull BlockState state, @Nonnull String componentType);
default void registerAltarComponent(@Nonnull BlockState state, @Nonnull String componentType) {}
/**
* Removes an {@link IBlockState} from the component mappings
* Removes a {@link BlockState} from the component mappings
* <p>
* Valid component types:
* <ul>
@ -75,6 +85,42 @@ public interface IBloodMagicAPI
* @param state The state to unregister
* @param componentType The type of Blood Altar component to unregister from.
*/
void unregisterAltarComponent(@Nonnull BlockState state, @Nonnull String componentType);
default void unregisterAltarComponent(@Nonnull BlockState state, @Nonnull String componentType) {}
/**
* Registers a {@link Predicate<BlockState>} for tranquility handling
* <p>
* Valid tranquility types:
* <ul>
* <li>PLANT</li>
* <li>CROP</li>
* <li>TREE</li>
* <li>EARTHEN</li>
* <li>WATER</li>
* <li>FIRE</li>
* <li>LAVA</li>
* </ul>
*
* @param predicate Predicate to be used for the handler (goes to ITranquilityHandler)
* @param tranquilityType Tranquility type that the handler holds
* @param value The amount of tranquility that the handler has
*/
default void registerTranquilityHandler(Predicate<BlockState> predicate, String tranquilityType, double value) {}
/**
* Gets the total Will that a Player contains
* <p>
* Valid tranquility types:
* <ul>
* <li>DEFAULT</li>
* <li>CORROSIVE</li>
* <li>DESTRUCTIVE</li>
* <li>VENGEFUL</li>
* <li>STEADFAST</li>
* </ul>
*/
default double getTotalDemonWill(String willType, PlayerEntity player)
{
return 0;
}
}

View file

@ -1,100 +0,0 @@
package wayoftime.bloodmagic.api;
/**
* Allows recipe addition and removal.
*/
public interface IBloodMagicRecipeRegistrar
{
// /**
// * Adds a new recipe to the Blood Altar.
// *
// * @param input An input {@link Ingredient}.
// * @param output An output {@link ItemStack}.
// * @param minimumTier The minimum Blood Altar tier required for this recipe.
// * @param syphon The amount of Life Essence to syphon from the Blood Altar
// * over the course of the craft.
// * @param consumeRate How quickly the Life Essence is syphoned.
// * @param drainRate How quickly progress is lost if the Blood Altar runs out
// * of Life Essence during the craft.
// */
// void addBloodAltar(@Nonnull Ingredient input, @Nonnull ItemStack output, @Nonnegative int minimumTier,
// @Nonnegative int syphon, @Nonnegative int consumeRate, @Nonnegative int drainRate);
//
// /**
// * Removes a Blood Altar recipe based on an input {@link ItemStack}.
// *
// * @param input The input item to remove the recipe of.
// * @return Whether or not a recipe was removed.
// */
// boolean removeBloodAltar(@Nonnull ItemStack input);
//
// /**
// * Adds a new recipe to the Alchemy Table.
// *
// * @param output An output {@link ItemStack}.
// * @param syphon The amount of Life Essence to syphon from the Blood Orb's
// * bound network over the course of the craft.
// * @param ticks The amount of ticks it takes to complete the craft.
// * @param minimumTier The minimum Blood Orb tier required for this recipe.
// * @param input An array of {@link Ingredient}s to accept as inputs.
// */
// void addAlchemyTable(@Nonnull ItemStack output, @Nonnegative int syphon, @Nonnegative int ticks,
// @Nonnegative int minimumTier, @Nonnull Ingredient... input);
//
// /**
// * Removes an Alchemy Table recipe based on an input {@link ItemStack} array.
// *
// * @param input The input items to remove the recipe of.
// * @return Whether or not a recipe was removed.
// */
// boolean removeAlchemyTable(@Nonnull ItemStack... input);
//
// /**
// * Adds a new recipe to the Soul/Tartaric Forge.
// *
// * @param output An output {@link ItemStack}.
// * @param minimumSouls The minimum number of souls that must be contained in the
// * Soul Gem.
// * @param soulDrain The number of souls to drain from the Soul Gem.
// * @param input An array of {@link Ingredient}s to accept as inputs.
// */
// void addTartaricForge(@Nonnull ItemStack output, @Nonnegative double minimumSouls, @Nonnegative double soulDrain,
// @Nonnull Ingredient... input);
//
// /**
// * Removes a Soul/Tartaric Forge recipe based on an input {@link ItemStack}
// * array.
// *
// * @param input The input items to remove the recipe of.
// * @return Whether or not a recipe was removed.
// */
// boolean removeTartaricForge(@Nonnull ItemStack... input);
//
// /**
// * Adds a new recipe to the Alchemy Array.
// *
// * @param input An input {@link Ingredient}. First item put into the
// * Alchemy Array.
// * @param catalyst A catalyst {@link Ingredient}. Second item put into the
// * Alchemy Array.
// * @param output An output {@link ItemStack}.
// * @param circleTexture The texture to render for the Alchemy Array circle.
// */
// void addAlchemyArray(@Nonnull Ingredient input, @Nonnull Ingredient catalyst, @Nonnull ItemStack output,
// @Nullable ResourceLocation circleTexture);
//
// /**
// * Removes an Alchemy Array recipe based on an input {@link ItemStack} and it's
// * catalyst {@link ItemStack}.
// *
// * @param input The input item to remove the recipe of.
// * @param catalyst The catalyst item to remove the recipe of.
// * @return Whether or not a recipe was removed.
// */
// boolean removeAlchemyArray(@Nonnull ItemStack input, @Nonnull ItemStack catalyst);
//
// void addSacrificeCraft(@Nonnull ItemStack output, @Nonnegative double healthRequired, @Nonnull Ingredient... input);
//
// boolean removeSacrificeCraft(@Nonnull ItemStack... input);
}

View file

@ -21,10 +21,10 @@ public interface IBloodMagicValueManager
* @param entityId The registry name of the entity.
* @param value The amount of LP per health point to receive upon sacrifice.
*/
void setSacrificialValue(@Nonnull ResourceLocation entityId, @Nonnegative int value);
default void setSacrificialValue(@Nonnull ResourceLocation entityId, @Nonnegative int value) {}
/**
* Sets the Tranquility value of a given {@link IBlockState}.
* Sets the Tranquility value of a given {@link BlockState}.
* <p>
* Valid tranquility types:
* <ul>
@ -37,9 +37,9 @@ public interface IBloodMagicValueManager
* <li>LAVA</li>
* </ul>
*
* @param state The {@link IBlockState} to set the value of.
* @param state The {@link BlockState} to set the value of.
* @param tranquilityType The type of Tranquility this block should provide.
* @param value The amount of tranquility this block should provide.
*/
void setTranquility(@Nonnull BlockState state, @Nonnull String tranquilityType, double value);
default void setTranquility(@Nonnull BlockState state, @Nonnull String tranquilityType, double value) {}
}

View file

@ -1,129 +0,0 @@
package wayoftime.bloodmagic.api;
import javax.annotation.Nonnull;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.JsonToNBT;
import net.minecraft.util.JSONUtils;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.registries.ForgeRegistries;
import wayoftime.bloodmagic.util.Constants;
/**
* Copied liberally from Mekanism. Thanks, pupnewfster!
*
*/
public class SerializerHelper
{
private SerializerHelper()
{
}
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
private static void validateKey(@Nonnull JsonObject json, @Nonnull String key)
{
if (!json.has(key))
{
throw new JsonSyntaxException("Missing '" + key + "', expected to find an object");
}
if (!json.get(key).isJsonObject())
{
throw new JsonSyntaxException("Expected '" + key + "' to be an object");
}
}
public static ItemStack getItemStack(@Nonnull JsonObject json, @Nonnull String key)
{
validateKey(json, key);
return ShapedRecipe.deserializeItem(JSONUtils.getJsonObject(json, key));
}
public static JsonElement serializeItemStack(@Nonnull ItemStack stack)
{
JsonObject json = new JsonObject();
json.addProperty(Constants.JSON.ITEM, stack.getItem().getRegistryName().toString());
if (stack.getCount() > 1)
{
json.addProperty(Constants.JSON.COUNT, stack.getCount());
}
if (stack.hasTag())
{
json.addProperty(Constants.JSON.NBT, stack.getTag().toString());
}
return json;
}
public static FluidStack getFluidStack(@Nonnull JsonObject json, @Nonnull String key)
{
validateKey(json, key);
return deserializeFluid(JSONUtils.getJsonObject(json, key));
}
public static FluidStack deserializeFluid(@Nonnull JsonObject json)
{
if (!json.has(Constants.JSON.AMOUNT))
{
throw new JsonSyntaxException("Expected to receive a amount that is greater than zero");
}
JsonElement count = json.get(Constants.JSON.AMOUNT);
if (!JSONUtils.isNumber(count))
{
throw new JsonSyntaxException("Expected amount to be a number greater than zero.");
}
int amount = count.getAsJsonPrimitive().getAsInt();
if (amount < 1)
{
throw new JsonSyntaxException("Expected amount to be greater than zero.");
}
ResourceLocation resourceLocation = new ResourceLocation(JSONUtils.getString(json, Constants.JSON.FLUID));
Fluid fluid = ForgeRegistries.FLUIDS.getValue(resourceLocation);
if (fluid == null || fluid == Fluids.EMPTY)
{
throw new JsonSyntaxException("Invalid fluid type '" + resourceLocation + "'");
}
CompoundNBT nbt = null;
if (json.has(Constants.JSON.NBT))
{
JsonElement jsonNBT = json.get(Constants.JSON.NBT);
try
{
if (jsonNBT.isJsonObject())
{
nbt = JsonToNBT.getTagFromJson(GSON.toJson(jsonNBT));
} else
{
nbt = JsonToNBT.getTagFromJson(JSONUtils.getString(jsonNBT, Constants.JSON.NBT));
}
} catch (CommandSyntaxException e)
{
throw new JsonSyntaxException("Invalid NBT entry for fluid '" + resourceLocation + "'");
}
}
return new FluidStack(fluid, amount, nbt);
}
public static JsonElement serializeFluidStack(@Nonnull FluidStack stack)
{
JsonObject json = new JsonObject();
json.addProperty(Constants.JSON.FLUID, stack.getFluid().getRegistryName().toString());
json.addProperty(Constants.JSON.AMOUNT, stack.getAmount());
if (stack.hasTag())
{
json.addProperty(Constants.JSON.NBT, stack.getTag().toString());
}
return json;
}
}

View file

@ -0,0 +1,46 @@
package wayoftime.bloodmagic.api.compat;
import net.minecraft.util.IStringSerializable;
import java.util.Locale;
public enum EnumDemonWillType implements IStringSerializable
{
DEFAULT("default"),
CORROSIVE("corrosive"),
DESTRUCTIVE("destructive"),
VENGEFUL("vengeful"),
STEADFAST("steadfast");
public final String name;
EnumDemonWillType(String name)
{
this.name = name;
}
@Override
public String toString()
{
return name().toLowerCase(Locale.ENGLISH);
}
@Override
public String getString()
{
return this.toString();
}
public static EnumDemonWillType getType(String type)
{
for (EnumDemonWillType t : values())
{
if (t.name().equalsIgnoreCase(type))
{
return t;
}
}
return null;
}
}

View file

@ -1,4 +1,4 @@
package wayoftime.bloodmagic.api.item;
package wayoftime.bloodmagic.api.compat;
/**
* Any item that implements this interface will not be pulled into the Altar on

View file

@ -1,4 +1,4 @@
package wayoftime.bloodmagic.api.item;
package wayoftime.bloodmagic.api.compat;
import net.minecraft.item.ItemStack;

View file

@ -0,0 +1,47 @@
package wayoftime.bloodmagic.api.compat;
import net.minecraft.item.ItemStack;
/**
* Interface for Items that contain Will
*/
public interface IDemonWill
{
/**
* Obtains the amount of Will an ItemStack contains.
*
* @param willStack - The stack to retrieve the Will from
* @return - The amount of Will an ItemStack contains
*/
double getWill(EnumDemonWillType type, ItemStack willStack);
/**
* Sets the amount of Will in a given ItemStack.
*
* @param willStack - The ItemStack of the Will
* @param will - The amount of will to set the stack to
* @return True if successfully set.
*/
boolean setWill(EnumDemonWillType type, ItemStack willStack, double will);
/**
* Drains the demonic will from the willStack. If all of the will is drained,
* the willStack will be removed.
*
* @param willStack - The ItemStack of the will
* @param drainAmount - The amount of Will to drain
* @return The amount of will drained.
*/
double drainWill(EnumDemonWillType type, ItemStack willStack, double drainAmount);
/**
* Creates a new ItemStack with the specified number of will. Implementation
* should respect the number requested.
*
* @param number - The amount of Will to create the Stack with.
* @return - An ItemStack with the set amount of Will
*/
ItemStack createWill(double number);
EnumDemonWillType getType(ItemStack stack);
}

View file

@ -0,0 +1,19 @@
package wayoftime.bloodmagic.api.compat;
/**
* Implement this interface on a Block that can accept and store Demonic Will.
*/
public interface IDemonWillConduit
{
int getWeight();
double fillDemonWill(EnumDemonWillType type, double amount, boolean doFill);
double drainDemonWill(EnumDemonWillType type, double amount, boolean doDrain);
boolean canFill(EnumDemonWillType type);
boolean canDrain(EnumDemonWillType type);
double getCurrentWill(EnumDemonWillType type);
}

View file

@ -0,0 +1,32 @@
package wayoftime.bloodmagic.api.compat;
import net.minecraft.item.ItemStack;
/**
* Interface for Items that store Will
*/
public interface IDemonWillGem
{
/**
* @param willGemStack - The ItemStack for this demon will gem.
* @param willStack - The ItemStack for the will. Item should extend
* IDemonWill
* @return - The remainder willStack after the will has been absorbed into the
* gem. Return null if there is no will left in the stack.
*/
ItemStack fillDemonWillGem(ItemStack willGemStack, ItemStack willStack);
/**
* Returns the number of souls that are left in the soul gem. Returns a double
* because souls can be fractionally drained.
*/
double getWill(EnumDemonWillType type, ItemStack willGemStack);
void setWill(EnumDemonWillType type, ItemStack willGemStack, double amount);
int getMaxWill(EnumDemonWillType type, ItemStack willGemStack);
double drainWill(EnumDemonWillType type, ItemStack stack, double drainAmount, boolean doDrain);
double fillWill(EnumDemonWillType type, ItemStack stack, double fillAmount, boolean doFill);
}

View file

@ -1,9 +1,12 @@
package wayoftime.bloodmagic.api.item;
package wayoftime.bloodmagic.api.compat;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
/**
* Interface for Items that allow players to see Will inside of chunks
*/
public interface IDemonWillViewer
{
boolean canSeeDemonWillAura(World world, ItemStack stack, PlayerEntity player);

View file

@ -0,0 +1,14 @@
package wayoftime.bloodmagic.api.compat;
import java.util.List;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
/**
* Interface for weapons that drop will when a LivingEntity is killed
*/
public interface IDemonWillWeapon
{
List<ItemStack> getRandomDemonWillDrop(LivingEntity killedEntity, LivingEntity attackingEntity, ItemStack stack, int looting);
}

View file

@ -0,0 +1,44 @@
package wayoftime.bloodmagic.api.compat;
import net.minecraft.item.ItemStack;
/**
* Interface for Items that contain a discrete amount of Will
*/
public interface IDiscreteDemonWill
{
/**
* Obtains the amount of Will an ItemStack contains.
*
* @param soulStack - The stack to retrieve the Will from
* @return - The amount of Will an ItemStack contains
*/
double getWill(ItemStack soulStack);
/**
* Drains the demonic will from the willStack. If all of the will is drained,
* the willStack will be removed. Will only drain in discrete amounts,
* determined by getDiscretization.
*
* @param willStack - The ItemStack of the will
* @param drainAmount - The amount of Will to drain
* @return The amount of will drained.
*/
double drainWill(ItemStack willStack, double drainAmount);
/**
* Gets the discrete number for this demonic will.
*
* @param willStack - The ItemStack of the will
* @return - The discrete number for the given stack.
*/
double getDiscretization(ItemStack willStack);
/**
* Obtains the type of will this is.
*
* @param willStack - The ItemStack of the will
* @return - The type of will this is.
*/
EnumDemonWillType getType(ItemStack willStack);
}

View file

@ -0,0 +1,18 @@
package wayoftime.bloodmagic.api.compat;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
/**
* Any Block that implements this will be considered to be a valid path block for the Incense Altar
*/
public interface IIncensePath
{
/**
* Goes from 0 to however far this path block can be from the altar while still
* functioning. 0 represents a block that can work when it is two blocks
* horizontally away from the altar.
*/
int getLevelOfPath(World world, BlockPos pos, BlockState state);
}

View file

@ -1,8 +1,10 @@
package wayoftime.bloodmagic.api.item;
package wayoftime.bloodmagic.api.compat;
import net.minecraft.item.ItemStack;
import wayoftime.bloodmagic.will.EnumDemonWillType;
/**
* Interface for Items that can contain multiple Will types
*/
public interface IMultiWillTool
{
EnumDemonWillType getCurrentType(ItemStack stack);

View file

@ -1,385 +0,0 @@
package wayoftime.bloodmagic.api.event.recipes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
import net.minecraft.fluid.Fluid;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tags.FluidTags;
import net.minecraft.tags.ITag;
import net.minecraft.tags.TagCollectionManager;
import net.minecraft.util.JSONUtils;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidStack;
import wayoftime.bloodmagic.api.SerializerHelper;
import wayoftime.bloodmagic.util.Constants;
/**
* Created by Thiakil on 12/07/2019.
*/
public abstract class FluidStackIngredient implements InputIngredient<FluidStack>
{
public static FluidStackIngredient from(@Nonnull Fluid instance, int amount)
{
return from(new FluidStack(instance, amount));
}
public static FluidStackIngredient from(@Nonnull FluidStack instance)
{
return new Single(instance);
}
public static FluidStackIngredient from(@Nonnull ITag<Fluid> fluidTag, int minAmount)
{
return new Tagged(fluidTag, minAmount);
}
public static FluidStackIngredient read(PacketBuffer buffer)
{
// TODO: Allow supporting serialization of different types than just the ones we
// implement?
IngredientType type = buffer.readEnumValue(IngredientType.class);
if (type == IngredientType.SINGLE)
{
return Single.read(buffer);
} else if (type == IngredientType.TAGGED)
{
return Tagged.read(buffer);
}
return Multi.read(buffer);
}
public static FluidStackIngredient deserialize(@Nullable JsonElement json)
{
if (json == null || json.isJsonNull())
{
throw new JsonSyntaxException("Ingredient cannot be null");
}
if (json.isJsonArray())
{
JsonArray jsonArray = json.getAsJsonArray();
int size = jsonArray.size();
if (size == 0)
{
throw new JsonSyntaxException("Ingredient array cannot be empty, at least one ingredient must be defined");
} else if (size > 1)
{
FluidStackIngredient[] ingredients = new FluidStackIngredient[size];
for (int i = 0; i < size; i++)
{
// Read all the ingredients
ingredients[i] = deserialize(jsonArray.get(i));
}
return createMulti(ingredients);
}
// If we only have a single element, just set our json as that so that we don't
// have to use Multi for efficiency reasons
json = jsonArray.get(0);
}
if (!json.isJsonObject())
{
throw new JsonSyntaxException("Expected fluid to be object or array of objects");
}
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has(Constants.JSON.FLUID) && jsonObject.has(Constants.JSON.TAG))
{
throw new JsonParseException("An ingredient entry is either a tag or an fluid, not both");
} else if (jsonObject.has(Constants.JSON.FLUID))
{
return from(SerializerHelper.deserializeFluid(jsonObject));
} else if (jsonObject.has(Constants.JSON.TAG))
{
if (!jsonObject.has(Constants.JSON.AMOUNT))
{
throw new JsonSyntaxException("Expected to receive a amount that is greater than zero");
}
JsonElement count = jsonObject.get(Constants.JSON.AMOUNT);
if (!JSONUtils.isNumber(count))
{
throw new JsonSyntaxException("Expected amount to be a number greater than zero.");
}
int amount = count.getAsJsonPrimitive().getAsInt();
if (amount < 1)
{
throw new JsonSyntaxException("Expected amount to be greater than zero.");
}
ResourceLocation resourceLocation = new ResourceLocation(JSONUtils.getString(jsonObject, Constants.JSON.TAG));
ITag<Fluid> tag = TagCollectionManager.getManager().getFluidTags().get(resourceLocation);
if (tag == null)
{
throw new JsonSyntaxException("Unknown fluid tag '" + resourceLocation + "'");
}
return from(tag, amount);
}
throw new JsonSyntaxException("Expected to receive a resource location representing either a tag or a fluid.");
}
public static FluidStackIngredient createMulti(FluidStackIngredient... ingredients)
{
if (ingredients.length == 0)
{
// TODO: Throw error
} else if (ingredients.length == 1)
{
return ingredients[0];
}
List<FluidStackIngredient> cleanedIngredients = new ArrayList<>();
for (FluidStackIngredient ingredient : ingredients)
{
if (ingredient instanceof Multi)
{
// Don't worry about if our inner ingredients are multi as well, as if this is
// the only external method for
// creating a multi ingredient, then we are certified they won't be of a higher
// depth
cleanedIngredients.addAll(Arrays.asList(((Multi) ingredient).ingredients));
} else
{
cleanedIngredients.add(ingredient);
}
}
// There should be more than a single fluid or we would have split out earlier
return new Multi(cleanedIngredients.toArray(new FluidStackIngredient[0]));
}
public static class Single extends FluidStackIngredient
{
@Nonnull
private final FluidStack fluidInstance;
public Single(@Nonnull FluidStack fluidInstance)
{
this.fluidInstance = Objects.requireNonNull(fluidInstance);
}
@Override
public boolean test(@Nonnull FluidStack fluidStack)
{
return testType(fluidStack) && fluidStack.getAmount() >= fluidInstance.getAmount();
}
@Override
public boolean testType(@Nonnull FluidStack fluidStack)
{
return Objects.requireNonNull(fluidStack).isFluidEqual(fluidInstance);
}
@Nonnull
@Override
public FluidStack getMatchingInstance(@Nonnull FluidStack fluidStack)
{
return test(fluidStack) ? fluidInstance : FluidStack.EMPTY;
}
@Nonnull
@Override
public List<FluidStack> getRepresentations()
{
return Collections.singletonList(fluidInstance);
}
@Override
public void write(PacketBuffer buffer)
{
buffer.writeEnumValue(IngredientType.SINGLE);
fluidInstance.writeToPacket(buffer);
}
@Nonnull
@Override
public JsonElement serialize()
{
JsonObject json = new JsonObject();
json.addProperty(Constants.JSON.AMOUNT, fluidInstance.getAmount());
json.addProperty(Constants.JSON.FLUID, fluidInstance.getFluid().getRegistryName().toString());
if (fluidInstance.hasTag())
{
json.addProperty(Constants.JSON.NBT, fluidInstance.getTag().toString());
}
return json;
}
public static Single read(PacketBuffer buffer)
{
return new Single(FluidStack.readFromPacket(buffer));
}
}
public static class Tagged extends FluidStackIngredient
{
@Nonnull
private final ITag<Fluid> tag;
private final int amount;
public Tagged(@Nonnull ITag<Fluid> tag, int amount)
{
this.tag = tag;
this.amount = amount;
}
@Override
public boolean test(@Nonnull FluidStack fluidStack)
{
return testType(fluidStack) && fluidStack.getAmount() >= amount;
}
@Override
public boolean testType(@Nonnull FluidStack fluidStack)
{
return Objects.requireNonNull(fluidStack).getFluid().isIn(tag);
}
@Nonnull
@Override
public FluidStack getMatchingInstance(@Nonnull FluidStack fluidStack)
{
if (test(fluidStack))
{
// Our fluid is in the tag so we make a new stack with the given amount
return new FluidStack(fluidStack, amount);
}
return FluidStack.EMPTY;
}
@Nonnull
@Override
public List<FluidStack> getRepresentations()
{
// TODO: Can this be cached some how
List<FluidStack> representations = new ArrayList<>();
for (Fluid fluid : TagResolverHelper.getRepresentations(tag))
{
representations.add(new FluidStack(fluid, amount));
}
return representations;
}
@Override
public void write(PacketBuffer buffer)
{
buffer.writeEnumValue(IngredientType.TAGGED);
buffer.writeResourceLocation(TagCollectionManager.getManager().getFluidTags().getValidatedIdFromTag(tag));
buffer.writeVarInt(amount);
}
@Nonnull
@Override
public JsonElement serialize()
{
JsonObject json = new JsonObject();
json.addProperty(Constants.JSON.AMOUNT, amount);
json.addProperty(Constants.JSON.TAG, TagCollectionManager.getManager().getFluidTags().getValidatedIdFromTag(tag).toString());
return json;
}
public static Tagged read(PacketBuffer buffer)
{
return new Tagged(FluidTags.makeWrapperTag(buffer.readResourceLocation().toString()), buffer.readVarInt());
}
}
public static class Multi extends FluidStackIngredient
{
private final FluidStackIngredient[] ingredients;
protected Multi(@Nonnull FluidStackIngredient... ingredients)
{
this.ingredients = ingredients;
}
@Override
public boolean test(@Nonnull FluidStack stack)
{
return Arrays.stream(ingredients).anyMatch(ingredient -> ingredient.test(stack));
}
@Override
public boolean testType(@Nonnull FluidStack stack)
{
return Arrays.stream(ingredients).anyMatch(ingredient -> ingredient.testType(stack));
}
@Nonnull
@Override
public FluidStack getMatchingInstance(@Nonnull FluidStack stack)
{
for (FluidStackIngredient ingredient : ingredients)
{
FluidStack matchingInstance = ingredient.getMatchingInstance(stack);
if (!matchingInstance.isEmpty())
{
return matchingInstance;
}
}
return FluidStack.EMPTY;
}
@Nonnull
@Override
public List<FluidStack> getRepresentations()
{
List<FluidStack> representations = new ArrayList<>();
for (FluidStackIngredient ingredient : ingredients)
{
representations.addAll(ingredient.getRepresentations());
}
return representations;
}
@Override
public void write(PacketBuffer buffer)
{
buffer.writeEnumValue(IngredientType.MULTI);
buffer.writeVarInt(ingredients.length);
for (FluidStackIngredient ingredient : ingredients)
{
ingredient.write(buffer);
}
}
@Nonnull
@Override
public JsonElement serialize()
{
JsonArray json = new JsonArray();
for (FluidStackIngredient ingredient : ingredients)
{
json.add(ingredient.serialize());
}
return json;
}
public static FluidStackIngredient read(PacketBuffer buffer)
{
FluidStackIngredient[] ingredients = new FluidStackIngredient[buffer.readVarInt()];
for (int i = 0; i < ingredients.length; i++)
{
ingredients[i] = FluidStackIngredient.read(buffer);
}
return createMulti(ingredients);
}
}
private enum IngredientType
{
SINGLE,
TAGGED,
MULTI
}
}

View file

@ -1,52 +0,0 @@
package wayoftime.bloodmagic.api.event.recipes;
import java.util.List;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import com.google.gson.JsonElement;
import net.minecraft.network.PacketBuffer;
public interface InputIngredient<TYPE> extends Predicate<TYPE>
{
/**
* Evaluates this predicate on the given argument, ignoring any size data.
*
* @param type the input argument
*
* @return {@code true} if the input argument matches the predicate, otherwise
* {@code false}
*/
boolean testType(@Nonnull TYPE type);
TYPE getMatchingInstance(TYPE type);
/**
* Primarily for JEI, a list of valid instances of the type
*
* @return List (empty means no valid registrations found and recipe is to be
* hidden)
*
* @apiNote Do not modify any of the values returned by the representations
*/
@Nonnull
List<TYPE> getRepresentations();
/**
* Writes this ingredient to a PacketBuffer.
*
* @param buffer The buffer to write to.
*/
void write(PacketBuffer buffer);
/**
* Serializes this ingredient to a JsonElement
*
* @return JsonElement representation of this ingredient.
*/
@Nonnull
JsonElement serialize();
}

View file

@ -1,32 +0,0 @@
package wayoftime.bloodmagic.api.event.recipes;
import java.util.Collections;
import java.util.List;
import net.minecraft.tags.ITag;
/**
* Copied from Mekanism, including the author's rant about tags.
*/
public class TagResolverHelper
{
public static <TYPE> List<TYPE> getRepresentations(ITag<TYPE> tag)
{
try
{
return tag.getAllElements();
} catch (IllegalStateException e)
{
// Why do tags have to be such an annoyance in 1.16
// This is needed so that we can ensure we give JEI an empty list of
// representations
// instead of crashing on the first run, as recipes get "initialized" before
// tags are
// done initializing, and we don't want to spam the log with errors. JEI and
// things
// still work fine regardless of this
return Collections.emptyList();
}
}
}

View file

@ -1,67 +0,0 @@
package wayoftime.bloodmagic.api.inventory;
import javax.annotation.Nonnull;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
public final class IgnoredIInventory implements IInventory
{
public static final IgnoredIInventory INSTANCE = new IgnoredIInventory();
private IgnoredIInventory()
{
}
@Override
public int getSizeInventory()
{
return 0;
}
@Override
public boolean isEmpty()
{
return true;
}
@Override
public ItemStack getStackInSlot(int index)
{
return ItemStack.EMPTY;
}
@Override
public ItemStack decrStackSize(int index, int count)
{
return ItemStack.EMPTY;
}
@Override
public ItemStack removeStackFromSlot(int index)
{
return ItemStack.EMPTY;
}
@Override
public void setInventorySlotContents(int index, @Nonnull ItemStack stack)
{
}
@Override
public void markDirty()
{
}
@Override
public boolean isUsableByPlayer(@Nonnull PlayerEntity player)
{
return false;
}
@Override
public void clear()
{
}
}

View file

@ -1,16 +0,0 @@
package wayoftime.bloodmagic.api.item;
import net.minecraft.item.ItemStack;
public interface IARCTool
{
default double getCraftingSpeedMultiplier(ItemStack stack)
{
return 1;
}
default double getAdditionalOutputChanceMultiplier(ItemStack stack)
{
return 1;
}
}

View file

@ -1,32 +0,0 @@
package wayoftime.bloodmagic.api.item;
import javax.annotation.Nonnull;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import wayoftime.bloodmagic.util.Constants;
/**
* Interface for activatable items
*/
public interface IActivatable
{
default boolean getActivated(ItemStack stack)
{
return !stack.isEmpty() && stack.hasTag() && stack.getTag().getBoolean(Constants.NBT.ACTIVATED);
}
@Nonnull
default ItemStack setActivatedState(ItemStack stack, boolean activated)
{
if (!stack.isEmpty())
{
if (!stack.hasTag())
stack.setTag(new CompoundNBT());
stack.getTag().putBoolean(Constants.NBT.ACTIVATED, activated);
}
return stack;
}
}

View file

@ -1,40 +0,0 @@
package wayoftime.bloodmagic.api.item;
import javax.annotation.Nullable;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import wayoftime.bloodmagic.core.data.Binding;
/**
* Implement this interface on any Item that can be bound to a player.
*/
public interface IBindable
{
/**
* Gets an object that stores who this item is bound to.
* <p>
* If the item is not bound, this will be null.
*
* @param stack - The owned ItemStack
* @return - The binding object
*/
@Nullable
default Binding getBinding(ItemStack stack)
{
Binding binding = Binding.fromStack(stack);
return !stack.isEmpty() && binding != null ? binding : null;
}
/**
* Called when the player attempts to bind the item.
*
* @param player - The Player attempting to bind the item
* @param stack - The ItemStack to attempt binding
* @return If binding was successful.
*/
default boolean onBind(PlayerEntity player, ItemStack stack)
{
return true;
}
}

View file

@ -1,32 +0,0 @@
package wayoftime.bloodmagic.api.item;
import javax.annotation.Nonnull;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import wayoftime.bloodmagic.common.item.ItemSigil;
/**
* Used for all {@link ItemSigil} <b>EXCEPT</b> Sigils of Holdings.
*/
public interface ISigil
{
default boolean performArrayEffect(World world, BlockPos pos)
{
return false;
}
default boolean hasArrayEffect()
{
return false;
}
interface Holding
{
@Nonnull
ItemStack getHeldItem(ItemStack holdingStack, PlayerEntity player);
}
}

View file

@ -1,23 +0,0 @@
package wayoftime.bloodmagic.api.providers;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import wayoftime.bloodmagic.api.text.IHasTextComponent;
import wayoftime.bloodmagic.api.text.IHasTranslationKey;
public interface IBaseProvider extends IHasTextComponent, IHasTranslationKey
{
ResourceLocation getRegistryName();
default String getName()
{
return getRegistryName().getPath();
}
@Override
default ITextComponent getTextComponent()
{
return new TranslationTextComponent(getTranslationKey());
}
}

View file

@ -1,32 +0,0 @@
package wayoftime.bloodmagic.api.providers;
import javax.annotation.Nonnull;
import net.minecraft.entity.EntityType;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
public interface IEntityTypeProvider extends IBaseProvider
{
@Nonnull
EntityType<?> getEntityType();
@Override
default ResourceLocation getRegistryName()
{
return getEntityType().getRegistryName();
}
@Override
default ITextComponent getTextComponent()
{
return getEntityType().getName();
}
@Override
default String getTranslationKey()
{
return getEntityType().getTranslationKey();
}
}

View file

@ -1,69 +0,0 @@
package wayoftime.bloodmagic.api.recipe;
import javax.annotation.Nonnull;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import wayoftime.bloodmagic.api.inventory.IgnoredIInventory;
public abstract class BloodMagicRecipe implements IRecipe<IgnoredIInventory>
{
private final ResourceLocation id;
protected BloodMagicRecipe(ResourceLocation id)
{
this.id = id;
}
/**
* Writes this recipe to a PacketBuffer.
*
* @param buffer The buffer to write to.
*/
public abstract void write(PacketBuffer buffer);
@Nonnull
@Override
public ResourceLocation getId()
{
return id;
}
@Override
public boolean matches(@Nonnull IgnoredIInventory inv, @Nonnull World world)
{
return true;
}
@Override
public boolean isDynamic()
{
// Note: If we make this non dynamic, we can make it show in vanilla's crafting
// book and also then obey the recipe locking.
// For now none of that works/makes sense in our concept so don't lock it
return true;
}
@Nonnull
@Override
public ItemStack getCraftingResult(@Nonnull IgnoredIInventory inv)
{
return ItemStack.EMPTY;
}
@Override
public boolean canFit(int width, int height)
{
return true;
}
@Nonnull
@Override
public ItemStack getRecipeOutput()
{
return ItemStack.EMPTY;
}
}

View file

@ -1,166 +0,0 @@
package wayoftime.bloodmagic.api.recipe;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidStack;
import wayoftime.bloodmagic.api.event.recipes.FluidStackIngredient;
public abstract class RecipeARC extends BloodMagicRecipe
{
public static final int MAX_RANDOM_OUTPUTS = 3;
@Nonnull
private final Ingredient input;
@Nonnull
private final Ingredient arc_tool;
private final FluidStackIngredient inputFluid;
@Nonnull
private final ItemStack output;
private final FluidStack outputFluid;
private final boolean consumeIngredient;
private final List<Pair<ItemStack, Double>> addedItems;
protected RecipeARC(ResourceLocation id, Ingredient input, Ingredient arc_tool, FluidStackIngredient inputFluid, ItemStack output, FluidStack outputFluid, boolean consumeIngredient)
{
this(id, input, arc_tool, inputFluid, output, new ArrayList<Pair<ItemStack, Double>>(), outputFluid, consumeIngredient);
}
protected RecipeARC(ResourceLocation id, Ingredient input, Ingredient arc_tool, FluidStackIngredient inputFluid, ItemStack output, List<Pair<ItemStack, Double>> addedItems, FluidStack outputFluid, boolean consumeIngredient)
{
super(id);
this.input = input;
this.arc_tool = arc_tool;
this.inputFluid = inputFluid;
this.output = output;
this.addedItems = addedItems;
this.outputFluid = outputFluid;
this.consumeIngredient = consumeIngredient;
}
public RecipeARC addRandomOutput(ItemStack stack, double chance)
{
if (addedItems.size() >= MAX_RANDOM_OUTPUTS)
{
return this;
}
addedItems.add(Pair.of(stack, chance));
return this;
}
@Nonnull
public final Ingredient getInput()
{
return input;
}
@Nonnull
public final Ingredient getTool()
{
return arc_tool;
}
public final FluidStackIngredient getFluidIngredient()
{
return inputFluid;
}
public final FluidStack getFluidOutput()
{
return outputFluid;
}
@Override
public final NonNullList<Ingredient> getIngredients()
{
NonNullList<Ingredient> list = NonNullList.create();
list.add(getInput());
list.add(getTool());
return list;
}
public List<ItemStack> getAllListedOutputs()
{
List<ItemStack> list = new ArrayList<ItemStack>();
list.add(output.copy());
for (Pair<ItemStack, Double> pair : addedItems)
{
list.add(pair.getLeft().copy());
}
return list;
}
public List<ItemStack> getAllOutputs(Random rand)
{
List<ItemStack> list = new ArrayList<ItemStack>();
list.add(output.copy());
for (Pair<ItemStack, Double> pair : addedItems)
{
if (rand.nextDouble() < pair.getRight())
list.add(pair.getLeft().copy());
}
return list;
}
public double[] getAllOutputChances()
{
int size = addedItems.size();
double[] chanceArray = new double[size];
for (int i = 0; i < size; i++)
{
chanceArray[i] = addedItems.get(i).getRight();
}
return chanceArray;
}
public boolean getConsumeIngredient()
{
return consumeIngredient;
}
@Override
public void write(PacketBuffer buffer)
{
input.write(buffer);
arc_tool.write(buffer);
buffer.writeItemStack(output);
buffer.writeInt(addedItems.size());
for (Pair<ItemStack, Double> pair : addedItems)
{
buffer.writeItemStack(pair.getLeft());
buffer.writeDouble(pair.getValue());
}
buffer.writeBoolean(inputFluid != null);
if (inputFluid != null)
{
inputFluid.write(buffer);
}
buffer.writeBoolean(outputFluid != null);
if (outputFluid != null)
{
outputFluid.writeToPacket(buffer);
}
buffer.writeBoolean(consumeIngredient);
}
}

View file

@ -1,87 +0,0 @@
package wayoftime.bloodmagic.api.recipe;
import javax.annotation.Nonnull;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
public abstract class RecipeAlchemyArray extends BloodMagicRecipe
{
private final ResourceLocation id;
private final ResourceLocation texture;
@Nonnull
private final Ingredient baseInput;
@Nonnull
private final Ingredient addedInput;
@Nonnull
private final ItemStack output;
protected RecipeAlchemyArray(ResourceLocation id, ResourceLocation texture, @Nonnull Ingredient baseIngredient, @Nonnull Ingredient addedIngredient, @Nonnull ItemStack result)
{
super(id);
this.id = id;
this.texture = texture;
this.baseInput = baseIngredient;
this.addedInput = addedIngredient;
this.output = result;
}
@Nonnull
public final ResourceLocation getId()
{
return id;
}
@Nonnull
public final ResourceLocation getTexture()
{
return texture;
}
@Nonnull
public final Ingredient getBaseInput()
{
return baseInput;
}
@Nonnull
public final Ingredient getAddedInput()
{
return addedInput;
}
@Override
public final NonNullList<Ingredient> getIngredients()
{
NonNullList<Ingredient> list = NonNullList.create();
list.add(getBaseInput());
list.add(getAddedInput());
return list;
}
@Nonnull
public final ItemStack getOutput()
{
return output;
}
@Override
public void write(PacketBuffer buffer)
{
if (texture != null)
{
buffer.writeBoolean(true);
buffer.writeResourceLocation(texture);
} else
{
buffer.writeBoolean(false);
}
baseInput.write(buffer);
addedInput.write(buffer);
buffer.writeItemStack(output);
}
}

View file

@ -1,86 +0,0 @@
package wayoftime.bloodmagic.api.recipe;
import java.util.List;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
public abstract class RecipeAlchemyTable extends BloodMagicRecipe
{
@Nonnull
private final List<Ingredient> input;
@Nonnull
private final ItemStack output;
@Nonnegative
private final int syphon;
@Nonnegative
private final int ticks;
@Nonnegative
private final int minimumTier;
public static final int MAX_INPUTS = 6;
public RecipeAlchemyTable(ResourceLocation id, List<Ingredient> input, @Nonnull ItemStack output, int syphon, int ticks, int minimumTier)
{
super(id);
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 List<Ingredient> 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;
}
@Override
public void write(PacketBuffer buffer)
{
buffer.writeInt(input.size());
for (int i = 0; i < input.size(); i++)
{
input.get(i).write(buffer);
}
buffer.writeItemStack(output);
buffer.writeInt(syphon);
buffer.writeInt(ticks);
buffer.writeInt(minimumTier);
}
}

View file

@ -1,103 +0,0 @@
package wayoftime.bloodmagic.api.recipe;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import wayoftime.bloodmagic.altar.AltarTier;
public abstract class RecipeBloodAltar extends BloodMagicRecipe
{
@Nonnull
private final Ingredient input;
@Nonnull
private final ItemStack output;
@Nonnull
private final AltarTier minimumTier;
@Nonnegative
private final int syphon;
@Nonnegative
private final int consumeRate;
@Nonnegative
private final int drainRate;
public RecipeBloodAltar(ResourceLocation id, @Nonnull Ingredient input, @Nonnull ItemStack output, @Nonnegative int minimumTier, @Nonnegative int syphon, @Nonnegative int consumeRate, @Nonnegative int drainRate)
{
super(id);
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 <= AltarTier.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 = AltarTier.values()[minimumTier];
this.syphon = syphon;
this.consumeRate = consumeRate;
this.drainRate = drainRate;
}
@Nonnull
public final Ingredient getInput()
{
return input;
}
@Override
public final NonNullList<Ingredient> getIngredients()
{
NonNullList<Ingredient> list = NonNullList.create();
list.add(getInput());
return list;
}
@Nonnull
public final ItemStack getOutput()
{
return output;
}
@Nonnull
public AltarTier getMinimumTier()
{
return minimumTier;
}
@Nonnegative
public final int getSyphon()
{
return syphon;
}
@Nonnegative
public final int getConsumeRate()
{
return consumeRate;
}
@Nonnegative
public final int getDrainRate()
{
return drainRate;
}
@Override
public void write(PacketBuffer buffer)
{
input.write(buffer);
buffer.writeItemStack(output);
buffer.writeInt(minimumTier.ordinal());
buffer.writeInt(syphon);
buffer.writeInt(consumeRate);
buffer.writeInt(drainRate);
}
}

View file

@ -1,77 +0,0 @@
package wayoftime.bloodmagic.api.recipe;
import java.util.List;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
public abstract class RecipeTartaricForge extends BloodMagicRecipe
{
@Nonnull
private final List<Ingredient> input;
@Nonnull
private final ItemStack output;
@Nonnegative
private final double minimumSouls;
@Nonnegative
private final double soulDrain;
public RecipeTartaricForge(ResourceLocation id, @Nonnull List<Ingredient> input, @Nonnull ItemStack output, @Nonnegative double minimumSouls, @Nonnegative double soulDrain)
{
super(id);
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 List<Ingredient> getInput()
{
return input;
}
@Nonnull
public final ItemStack getOutput()
{
return output;
}
@Nonnegative
public final double getMinimumSouls()
{
return minimumSouls;
}
@Nonnegative
public final double getSoulDrain()
{
return soulDrain;
}
@Override
public void write(PacketBuffer buffer)
{
buffer.writeInt(input.size());
for (int i = 0; i < input.size(); i++)
{
input.get(i).write(buffer);
}
buffer.writeItemStack(output);
buffer.writeDouble(minimumSouls);
buffer.writeDouble(soulDrain);
}
}

View file

@ -1,8 +0,0 @@
package wayoftime.bloodmagic.api.text;
import net.minecraft.util.text.ITextComponent;
public interface IHasTextComponent
{
ITextComponent getTextComponent();
}

View file

@ -1,6 +0,0 @@
package wayoftime.bloodmagic.api.text;
public interface IHasTranslationKey
{
String getTranslationKey();
}

View file

@ -1,14 +0,0 @@
package wayoftime.bloodmagic.api.tile;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import wayoftime.bloodmagic.altar.ComponentType;
public interface IAltarComponent
{
@Nullable
ComponentType getType(World world, BlockState state, BlockPos pos);
}

View file

@ -1,57 +0,0 @@
package wayoftime.bloodmagic.api.tile;
import wayoftime.bloodmagic.altar.AltarTier;
public interface IBloodAltar
{
int getCapacity();
int getCurrentBlood();
AltarTier getTier();
int getProgress();
float getSacrificeMultiplier();
float getSelfSacrificeMultiplier();
float getOrbMultiplier();
float getDislocationMultiplier();
float getConsumptionMultiplier();
float getConsumptionRate();
int getChargingRate();
int getChargingFrequency();
int getTotalCharge();
int getLiquidRequired();
int getBufferCapacity();
void sacrificialDaggerCall(int amount, boolean isSacrifice);
void startCycle();
void checkTier();
boolean isActive();
void setActive();
int fillMainTank(int amount);
/**
* Will set the altar to initiate a cooldown cycle after it crafts before
* starting to craft again, giving the user time to interact with the altar.
* This can only be set while the altar is not active.
*
* @param cooldown - How long the cooldown should last
*/
void requestPauseAfterCrafting(int cooldown);
}

View file

@ -1,16 +0,0 @@
package wayoftime.bloodmagic.api.tile;
import javax.annotation.Nullable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import wayoftime.bloodmagic.block.enums.BloodRuneType;
/**
* Any block that implements this interface wil be considered as Blood Runes for the Blood Altar
*/
public interface IBloodRune
{
@Nullable
BloodRuneType getBloodRune(World world, BlockPos pos);
}