From 1f757aee61823d65c2b8dc1d4f0f99f37f676efc Mon Sep 17 00:00:00 2001
From: Speiger
Date: Sat, 17 Jun 2017 14:03:32 +0200
Subject: [PATCH] Final API for 1.10.2 Release
---
.../ic2/api/classic/audio/ISoundModifier.java | 49 +++
.../api/classic/crops/ClassicBaseSeed.java | 29 ++
.../java/ic2/api/classic/crops/ISeedCrop.java | 32 ++
.../ic2/api/classic/item/ICropAnalyzer.java | 8 +
.../java/ic2/api/classic/item/IEUReader.java | 8 +
.../classic/item/ISortedTerraformerBP.java | 16 +
.../ic2/api/classic/item/IThermometer.java | 8 +
.../network/adv/IBitLevelOverride.java | 10 +
.../api/classic/network/adv/IInputBuffer.java | 49 +++
.../classic/network/adv/IOutputBuffer.java | 45 +++
.../api/classic/network/adv/NetworkField.java | 81 +++++
.../recipe/machine/ISawmillOutput.java | 6 +
.../ic2/api/classic/tile/IFakeMachine.java | 15 +
.../java/ic2/api/classic/tile/ISawMill.java | 6 +
src/main/java/ic2/api/crops/CropSoilType.java | 42 +++
.../java/ic2/api/crops/ExampleCropCard.java | 53 +++
.../api/energy/IEnergyNetEventReceiver.java | 20 +
.../ic2/api/event/TeBlockFinalCallEvent.java | 20 +
src/main/java/ic2/api/info/ITeBlock.java | 344 ++++++++++++++++++
src/main/java/ic2/api/item/HudMode.java | 37 ++
.../java/ic2/api/item/IItemHudProvider.java | 46 +++
.../ic2/api/item/ITeBlockSpecialItem.java | 35 ++
.../ic2/api/recipe/IRecipeInputFactory.java | 17 +
.../ic2/api/upgrade/IAugmentationUpgrade.java | 20 +
.../api/upgrade/IEnergyStorageUpgrade.java | 30 ++
.../api/upgrade/IFluidConsumingUpgrade.java | 10 +
.../api/upgrade/IFluidProducingUpgrade.java | 10 +
.../java/ic2/api/upgrade/IFullUpgrade.java | 12 +
.../api/upgrade/IItemConsumingUpgrade.java | 10 +
.../api/upgrade/IItemProducingUpgrade.java | 10 +
.../ic2/api/upgrade/IProcessingUpgrade.java | 50 +++
.../upgrade/IRedstoneSensitiveUpgrade.java | 31 ++
.../ic2/api/upgrade/ITransformerUpgrade.java | 20 +
.../ic2/api/upgrade/IUpgradableBlock.java | 29 ++
.../java/ic2/api/upgrade/IUpgradeItem.java | 43 +++
.../ic2/api/upgrade/UpgradableProperty.java | 45 +++
.../java/ic2/api/upgrade/UpgradeRegistry.java | 38 ++
37 files changed, 1334 insertions(+)
create mode 100644 src/main/java/ic2/api/classic/audio/ISoundModifier.java
create mode 100644 src/main/java/ic2/api/classic/crops/ClassicBaseSeed.java
create mode 100644 src/main/java/ic2/api/classic/crops/ISeedCrop.java
create mode 100644 src/main/java/ic2/api/classic/item/ICropAnalyzer.java
create mode 100644 src/main/java/ic2/api/classic/item/IEUReader.java
create mode 100644 src/main/java/ic2/api/classic/item/ISortedTerraformerBP.java
create mode 100644 src/main/java/ic2/api/classic/item/IThermometer.java
create mode 100644 src/main/java/ic2/api/classic/network/adv/IBitLevelOverride.java
create mode 100644 src/main/java/ic2/api/classic/network/adv/IInputBuffer.java
create mode 100644 src/main/java/ic2/api/classic/network/adv/IOutputBuffer.java
create mode 100644 src/main/java/ic2/api/classic/network/adv/NetworkField.java
create mode 100644 src/main/java/ic2/api/classic/recipe/machine/ISawmillOutput.java
create mode 100644 src/main/java/ic2/api/classic/tile/IFakeMachine.java
create mode 100644 src/main/java/ic2/api/classic/tile/ISawMill.java
create mode 100644 src/main/java/ic2/api/crops/CropSoilType.java
create mode 100644 src/main/java/ic2/api/crops/ExampleCropCard.java
create mode 100644 src/main/java/ic2/api/energy/IEnergyNetEventReceiver.java
create mode 100644 src/main/java/ic2/api/event/TeBlockFinalCallEvent.java
create mode 100644 src/main/java/ic2/api/info/ITeBlock.java
create mode 100644 src/main/java/ic2/api/item/HudMode.java
create mode 100644 src/main/java/ic2/api/item/IItemHudProvider.java
create mode 100644 src/main/java/ic2/api/item/ITeBlockSpecialItem.java
create mode 100644 src/main/java/ic2/api/recipe/IRecipeInputFactory.java
create mode 100644 src/main/java/ic2/api/upgrade/IAugmentationUpgrade.java
create mode 100644 src/main/java/ic2/api/upgrade/IEnergyStorageUpgrade.java
create mode 100644 src/main/java/ic2/api/upgrade/IFluidConsumingUpgrade.java
create mode 100644 src/main/java/ic2/api/upgrade/IFluidProducingUpgrade.java
create mode 100644 src/main/java/ic2/api/upgrade/IFullUpgrade.java
create mode 100644 src/main/java/ic2/api/upgrade/IItemConsumingUpgrade.java
create mode 100644 src/main/java/ic2/api/upgrade/IItemProducingUpgrade.java
create mode 100644 src/main/java/ic2/api/upgrade/IProcessingUpgrade.java
create mode 100644 src/main/java/ic2/api/upgrade/IRedstoneSensitiveUpgrade.java
create mode 100644 src/main/java/ic2/api/upgrade/ITransformerUpgrade.java
create mode 100644 src/main/java/ic2/api/upgrade/IUpgradableBlock.java
create mode 100644 src/main/java/ic2/api/upgrade/IUpgradeItem.java
create mode 100644 src/main/java/ic2/api/upgrade/UpgradableProperty.java
create mode 100644 src/main/java/ic2/api/upgrade/UpgradeRegistry.java
diff --git a/src/main/java/ic2/api/classic/audio/ISoundModifier.java b/src/main/java/ic2/api/classic/audio/ISoundModifier.java
new file mode 100644
index 0000000..03e1b96
--- /dev/null
+++ b/src/main/java/ic2/api/classic/audio/ISoundModifier.java
@@ -0,0 +1,49 @@
+package ic2.api.classic.audio;
+
+import net.minecraft.world.World;
+
+public interface ISoundModifier
+{
+ /**
+ * Validates that the modifier is in the right world.
+ * And if it is valid for being used.
+ * @param world The world that the player is in
+ * @return if it is valid.
+ */
+ public boolean isModifierValid(World world);
+
+ /**
+ * Client tick if that is needed. Could be that you need that.
+ * @param world The player is in
+ */
+ public void onAudioTick(World world);
+
+ /**
+ * Function for checking if it has a effect for that type.
+ * If not its getting skipped.
+ * @param type The sound type it checks.
+ * @return if it has a effect
+ */
+ public boolean hasEffect(PositionSpec type);
+
+ /**
+ * the modifier that the SoundModifier has.
+ * @param type the Type of sound it checks for.
+ * @return the Modifier of the sound
+ */
+ public float getAudioEffect(PositionSpec type);
+
+ /**
+ * The Range of the modifier. only for is in range check
+ * @param type The type it is in
+ * @return the max radius into each direction
+ */
+ public int getEffectRange(PositionSpec type);
+
+ /**
+ * Position where the modifier is.
+ * Get requested every tick
+ * @return the position
+ */
+ public IAudioPosition getPosition();
+}
diff --git a/src/main/java/ic2/api/classic/crops/ClassicBaseSeed.java b/src/main/java/ic2/api/classic/crops/ClassicBaseSeed.java
new file mode 100644
index 0000000..2b9cb12
--- /dev/null
+++ b/src/main/java/ic2/api/classic/crops/ClassicBaseSeed.java
@@ -0,0 +1,29 @@
+package ic2.api.classic.crops;
+
+import ic2.api.crops.BaseSeed;
+import ic2.api.crops.CropCard;
+
+public class ClassicBaseSeed extends BaseSeed
+{
+ public final int stackSize;
+
+ public ClassicBaseSeed(BaseSeed seed)
+ {
+ this(seed.crop, seed.size, seed.statGrowth, seed.statGain, seed.statResistance, 1);
+ }
+
+ public ClassicBaseSeed(CropCard crop, int size, int statGrowth, int statGain, int statResistance)
+ {
+ this(crop, size, statGrowth, statGain, statResistance, 1);
+ }
+
+ public ClassicBaseSeed(CropCard crop, int size, int statGrowth, int statGain, int statResistance, int stackSize)
+ {
+ super(crop, size, statGrowth, statGain, statResistance);
+ this.stackSize = stackSize;
+ }
+
+
+
+
+}
diff --git a/src/main/java/ic2/api/classic/crops/ISeedCrop.java b/src/main/java/ic2/api/classic/crops/ISeedCrop.java
new file mode 100644
index 0000000..80c00fc
--- /dev/null
+++ b/src/main/java/ic2/api/classic/crops/ISeedCrop.java
@@ -0,0 +1,32 @@
+package ic2.api.classic.crops;
+
+import ic2.api.crops.ICropTile;
+import net.minecraft.item.ItemStack;
+
+/**
+ *
+ * @author Speiger
+ *
+ * Support for the feature that Crops can drop Seeds
+ * optionally when you rightclick it with the hoe
+ * to toggle its mode. Its not the best item to use for but i had no
+ * better idea.
+ * This does not mean IC2 Seeds i mean the original crop seeds.
+ */
+public interface ISeedCrop
+{
+ /**
+ * If the Crop drops seeds instead of
+ * @param tile the Crop it is planted on.
+ * @return if it should drop seeds instead of the usual Gain
+ */
+ public boolean doDropSeeds(ICropTile tile);
+
+ /**
+ * Function to gain the CropSeeds.
+ * Note this is not about IC2Seeds this is about the base crop seeds.
+ * @param tile the Crop it is planted on.
+ * @return the Seed that it should drop
+ */
+ public ItemStack getSeed(ICropTile tile);
+}
diff --git a/src/main/java/ic2/api/classic/item/ICropAnalyzer.java b/src/main/java/ic2/api/classic/item/ICropAnalyzer.java
new file mode 100644
index 0000000..fbeec20
--- /dev/null
+++ b/src/main/java/ic2/api/classic/item/ICropAnalyzer.java
@@ -0,0 +1,8 @@
+package ic2.api.classic.item;
+
+import net.minecraft.item.ItemStack;
+
+public interface ICropAnalyzer
+{
+ public boolean isCropAnalyzer(ItemStack stack);
+}
diff --git a/src/main/java/ic2/api/classic/item/IEUReader.java b/src/main/java/ic2/api/classic/item/IEUReader.java
new file mode 100644
index 0000000..0959cb7
--- /dev/null
+++ b/src/main/java/ic2/api/classic/item/IEUReader.java
@@ -0,0 +1,8 @@
+package ic2.api.classic.item;
+
+import net.minecraft.item.ItemStack;
+
+public interface IEUReader
+{
+ public boolean isEUReader(ItemStack stack);
+}
diff --git a/src/main/java/ic2/api/classic/item/ISortedTerraformerBP.java b/src/main/java/ic2/api/classic/item/ISortedTerraformerBP.java
new file mode 100644
index 0000000..4e7f69d
--- /dev/null
+++ b/src/main/java/ic2/api/classic/item/ISortedTerraformerBP.java
@@ -0,0 +1,16 @@
+package ic2.api.classic.item;
+
+import ic2.api.item.ITerraformingBP;
+import net.minecraft.item.ItemStack;
+
+public interface ISortedTerraformerBP extends ITerraformingBP
+{
+ /**
+ * This function determens if the logic from the Terraformer
+ * should be random or a Final List that actually can end.
+ * The Biome BluePrints from classic need only to run once thats why it exists.
+ * @param stack yourBluePrint
+ * @return true = SortedLogic, false = defaultLogic
+ */
+ public boolean needsSortedLogic(ItemStack stack);
+}
diff --git a/src/main/java/ic2/api/classic/item/IThermometer.java b/src/main/java/ic2/api/classic/item/IThermometer.java
new file mode 100644
index 0000000..b26b41b
--- /dev/null
+++ b/src/main/java/ic2/api/classic/item/IThermometer.java
@@ -0,0 +1,8 @@
+package ic2.api.classic.item;
+
+import net.minecraft.item.ItemStack;
+
+public interface IThermometer
+{
+ public boolean isThermometer(ItemStack stack);
+}
diff --git a/src/main/java/ic2/api/classic/network/adv/IBitLevelOverride.java b/src/main/java/ic2/api/classic/network/adv/IBitLevelOverride.java
new file mode 100644
index 0000000..b3f09f9
--- /dev/null
+++ b/src/main/java/ic2/api/classic/network/adv/IBitLevelOverride.java
@@ -0,0 +1,10 @@
+package ic2.api.classic.network.adv;
+
+import ic2.api.classic.network.adv.NetworkField.BitLevel;
+
+public interface IBitLevelOverride
+{
+ public BitLevel getOverride(int fieldID, String fieldName);
+
+ public boolean hasOverride(int fieldID, String fieldName);
+}
diff --git a/src/main/java/ic2/api/classic/network/adv/IInputBuffer.java b/src/main/java/ic2/api/classic/network/adv/IInputBuffer.java
new file mode 100644
index 0000000..bd472b6
--- /dev/null
+++ b/src/main/java/ic2/api/classic/network/adv/IInputBuffer.java
@@ -0,0 +1,49 @@
+package ic2.api.classic.network.adv;
+
+import java.util.UUID;
+
+import ic2.api.classic.network.adv.NetworkField.BitLevel;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.fml.common.registry.IForgeRegistry;
+import net.minecraftforge.fml.common.registry.IForgeRegistryEntry;
+
+
+public interface IInputBuffer
+{
+
+ public boolean readBoolean();
+
+ public byte readByte();
+
+ public short readShort();
+
+ public int readMedium();
+
+ public int readInt();
+
+ public float readFloat();
+
+ public double readDouble();
+
+ public long readLong();
+
+ public long readData(BitLevel length);
+
+ public char readChar();
+
+ public byte[] readBytes();
+
+ public byte[] readBytes(BitLevel length);
+
+ public String readString();
+
+ public String readString(BitLevel length);
+
+ public NBTTagCompound readNBTData();
+
+ public T readForgeRegistryEntry(IForgeRegistry registry);
+
+ public UUID readUUID();
+
+
+}
diff --git a/src/main/java/ic2/api/classic/network/adv/IOutputBuffer.java b/src/main/java/ic2/api/classic/network/adv/IOutputBuffer.java
new file mode 100644
index 0000000..3804345
--- /dev/null
+++ b/src/main/java/ic2/api/classic/network/adv/IOutputBuffer.java
@@ -0,0 +1,45 @@
+package ic2.api.classic.network.adv;
+
+import java.util.UUID;
+
+import ic2.api.classic.network.adv.NetworkField.BitLevel;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.fml.common.registry.IForgeRegistryEntry;
+
+public interface IOutputBuffer
+{
+ public void writeBoolean(boolean value);
+
+ public void writeByte(byte value);
+
+ public void writeShort(short value);
+
+ public void writeMedium(int value);
+
+ public void writeInt(int value);
+
+ public void writeFloat(float value);
+
+ public void writeDouble(double value);
+
+ public void writeLong(long value);
+
+ public void writeData(long value, BitLevel type);
+
+ public void writeChar(char value);
+
+ public void writeString(String value);
+
+ public void writeString(String value, BitLevel length);
+
+ public void writeBytes(byte[] value);
+
+ public void writeBytes(byte[] value, BitLevel length);
+
+ public void writeNBTData(NBTTagCompound value);
+
+ public void writeForgeEntry(IForgeRegistryEntry value);
+
+ public void writeUUID(UUID value);
+
+}
diff --git a/src/main/java/ic2/api/classic/network/adv/NetworkField.java b/src/main/java/ic2/api/classic/network/adv/NetworkField.java
new file mode 100644
index 0000000..570c1a7
--- /dev/null
+++ b/src/main/java/ic2/api/classic/network/adv/NetworkField.java
@@ -0,0 +1,81 @@
+package ic2.api.classic.network.adv;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(CLASS)
+@Target(FIELD)
+public @interface NetworkField
+{
+ public int index();
+
+ public BitLevel compression() default BitLevel.Bit0;
+
+ public boolean override() default false;
+
+ public static enum BitLevel
+ {
+ Bit0(0), //IgnoreCase
+ Bit8(1), //Byte
+ Bit16(2), //Short
+ Bit24(3), //Medium
+ Bit32(4), //Integer
+ Bit40(5), //Integer + Byte
+ Bit48(6), //Integer + Short
+ Bit56(7), //Integer + Medium
+ Bit64(8); //long
+
+ final int index;
+ final long maxNumber;
+ public static BitLevel[] levels;
+
+ private BitLevel(int lvl)
+ {
+ index = lvl;
+ maxNumber = (1L << (lvl * 8));
+ }
+
+ public int getIndex()
+ {
+ return index;
+ }
+
+ public boolean isSkip()
+ {
+ return index == 0;
+ }
+
+ public boolean isValid(BitLevel limit)
+ {
+ if(index == 0) return false;
+ else return index < limit.index;
+ }
+
+ public long limitNumber(long input)
+ {
+ if(index == 0) return 0;
+ if(input >= maxNumber) return maxNumber - 1;
+ return input;
+ }
+
+ public static BitLevel getLevel(int index)
+ {
+ if(index < 0 || index > 8)
+ {
+ return BitLevel.Bit32;
+ }
+ return levels[index];
+ }
+ static
+ {
+ levels = new BitLevel[values().length];
+ for(BitLevel level : values())
+ {
+ levels[level.getIndex()] = level;
+ }
+ }
+ }
+}
diff --git a/src/main/java/ic2/api/classic/recipe/machine/ISawmillOutput.java b/src/main/java/ic2/api/classic/recipe/machine/ISawmillOutput.java
new file mode 100644
index 0000000..f0c7bfd
--- /dev/null
+++ b/src/main/java/ic2/api/classic/recipe/machine/ISawmillOutput.java
@@ -0,0 +1,6 @@
+package ic2.api.classic.recipe.machine;
+
+public interface ISawmillOutput
+{
+ public boolean increaseResuls(int amount);
+}
diff --git a/src/main/java/ic2/api/classic/tile/IFakeMachine.java b/src/main/java/ic2/api/classic/tile/IFakeMachine.java
new file mode 100644
index 0000000..bd6dcf9
--- /dev/null
+++ b/src/main/java/ic2/api/classic/tile/IFakeMachine.java
@@ -0,0 +1,15 @@
+package ic2.api.classic.tile;
+
+/**
+ *
+ * @author Speiger
+ *
+ * Class to get upgrade information out of a Upgrade
+ * If you implement that class then it means you
+ * only want to read data for ReadOnly purpose.
+ * Not to use it on machines
+ */
+public interface IFakeMachine extends IMachine
+{
+
+}
diff --git a/src/main/java/ic2/api/classic/tile/ISawMill.java b/src/main/java/ic2/api/classic/tile/ISawMill.java
new file mode 100644
index 0000000..e090311
--- /dev/null
+++ b/src/main/java/ic2/api/classic/tile/ISawMill.java
@@ -0,0 +1,6 @@
+package ic2.api.classic.tile;
+
+public interface ISawMill extends IMachine
+{
+
+}
diff --git a/src/main/java/ic2/api/crops/CropSoilType.java b/src/main/java/ic2/api/crops/CropSoilType.java
new file mode 100644
index 0000000..1a8dddf
--- /dev/null
+++ b/src/main/java/ic2/api/crops/CropSoilType.java
@@ -0,0 +1,42 @@
+package ic2.api.crops;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+
+/**
+ * List of possible blocks to be used as soil for a crop.
+ * @author estebes
+ */
+public enum CropSoilType {
+ //DIRT(Blocks.DIRT),
+ FARMLAND(Blocks.FARMLAND),
+ MYCELIUM(Blocks.MYCELIUM),
+ SAND(Blocks.SAND),
+ SOULSAND(Blocks.SOUL_SAND);
+
+ private CropSoilType(@Nonnull Block block) {
+ this.block = block;
+ }
+
+ public Block getBlock() {
+ return this.block;
+ }
+
+ /**
+ * Check if a block can be used as soil.
+ * @param block the block
+ * @return true if the block is a possible crop soil
+ */
+ public static boolean contais(Block block) {
+ for (CropSoilType aux : CropSoilType.values()) {
+ if (aux.getBlock() == block) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private final Block block;
+}
diff --git a/src/main/java/ic2/api/crops/ExampleCropCard.java b/src/main/java/ic2/api/crops/ExampleCropCard.java
new file mode 100644
index 0000000..2fc5220
--- /dev/null
+++ b/src/main/java/ic2/api/crops/ExampleCropCard.java
@@ -0,0 +1,53 @@
+package ic2.api.crops;
+
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ResourceLocation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * CropCard example
+ * @author estebes
+ */
+public class ExampleCropCard extends CropCard {
+ @Override
+ public String getId() {
+ return "example";
+ }
+
+ @Override
+ public String getOwner() {
+ return "myaddon";
+ }
+
+ /**
+ * See {@link CropProperties} for more info.
+ */
+ @Override
+ public CropProperties getProperties() {
+ return new CropProperties(1, 0, 4, 0, 0, 2);
+ }
+
+ @Override
+ public int getMaxSize() {
+ return 5;
+ }
+
+ @Override
+ public ItemStack getGain(ICropTile crop) {
+ return new ItemStack(Items.DIAMOND, 1);
+ }
+
+ @Override
+ public List getTexturesLocation() {
+ List ret = new ArrayList(getMaxSize());
+
+ for (int size = 1; size <= getMaxSize(); size++) {
+ ret.add(new ResourceLocation("myaddon", "blocks/crop/" + getId() + "_" + size));
+ }
+
+ return ret;
+ }
+}
diff --git a/src/main/java/ic2/api/energy/IEnergyNetEventReceiver.java b/src/main/java/ic2/api/energy/IEnergyNetEventReceiver.java
new file mode 100644
index 0000000..420eb10
--- /dev/null
+++ b/src/main/java/ic2/api/energy/IEnergyNetEventReceiver.java
@@ -0,0 +1,20 @@
+package ic2.api.energy;
+
+import ic2.api.energy.tile.IEnergyTile;
+
+/**
+ * Interface for handlers being invoked after energy net changes.
+ *
+ * Normally it's enough to listen for the neighbor update, which also happens, but using this
+ * mechanism allows listening to events that are not adjacent. Mechanisms that inject energy over
+ * a distance or provide compatibility with 3rd party energy may benefit from it.
+ *
+ *
The events will be fired after validation and only for successful changes.
+ *
+ *
WARNING: The events may (and will) be invoked from arbitrary threads. It's up to the
+ * implementation of IEnergyNetEventReceiver to properly synchronize them.
+ */
+public interface IEnergyNetEventReceiver {
+ void onAdd(IEnergyTile tile);
+ void onRemove(IEnergyTile tile);
+}
diff --git a/src/main/java/ic2/api/event/TeBlockFinalCallEvent.java b/src/main/java/ic2/api/event/TeBlockFinalCallEvent.java
new file mode 100644
index 0000000..3b1958d
--- /dev/null
+++ b/src/main/java/ic2/api/event/TeBlockFinalCallEvent.java
@@ -0,0 +1,20 @@
+package ic2.api.event;
+
+import net.minecraftforge.fml.common.eventhandler.Event;
+
+import ic2.api.info.ITeBlock;
+
+/** This event is a notification for an internal event you might will to subscribe to if you're using ITeBlock, hence it is empty.
+ *
+ * For more information such as why this event exists, when it's posted, and how to react to it properly, see {@link ITeBlock}.
+ *
+ *
+ * @see ITeBlock
+ *
+ * @since IC2 2.6.67
+ * @version 1.0
+ *
+ * @author Chocohead
+ */
+public final class TeBlockFinalCallEvent extends Event {
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/info/ITeBlock.java b/src/main/java/ic2/api/info/ITeBlock.java
new file mode 100644
index 0000000..fe44aa7
--- /dev/null
+++ b/src/main/java/ic2/api/info/ITeBlock.java
@@ -0,0 +1,344 @@
+package ic2.api.info;
+
+import java.util.Set;
+
+import net.minecraft.block.material.Material;
+import net.minecraft.util.ResourceLocation;
+
+import net.minecraftforge.common.MinecraftForge;
+
+import ic2.api.event.TeBlockFinalCallEvent;
+import ic2.api.item.ITeBlockSpecialItem;
+import ic2.api.tile.IWrenchable;
+
+/** First of all, yes this class is empty. It's public documentation for the actual internal interface ITeBlock. Use the internal one not this!
+ *
+ * You may be asking, why would an internal interface need documenting? Well, the answer is so people can use TileEntityBlock
.
+ * That class is the base for all IC2 tile entities, so by being able to use that you're level to IC2.
+ * Many methods are protected in there too, as they're only designed to be called by BlockTileEntity
(which is the block all IC2 tile entities will be on),
+ * by being able to extend it means all those methods you can now extend and be confident they will be called correctly.
+ *
+ *
+ * The more observant might have noticed there was an event that allowed you to do basically the same thing called TeBlockBakeEvent
.
+ * Whilst that event used to add your own class onto TeBlock
(that wasn't ideal as you could end up using the same ID as another addon which would cause a crash),
+ * this allows you to completely implement your own version of TeBlock
, then let IC2 take it and build the necessary structures around it.
+ * Both mean you no longer have to use EnumHelper
and lots of reflection to mess about with TeBlock
,
+ * just to be left with either a crash from doing it too late/wrong, or lots of code bound to IC2 (such as language keys and blockstate jsons being in IC2's assets).
+ *
+ *
+ * Unlike TeBlockBakeEvent
, this gives you near total control of your tile entities:
+ *
+ * You can pick whether each of your tile entity items show up in creative, and the order in which they do.
+ * You can choose whether you use an enum
or class
for your implementation.
+ * We use (and I personally recommend) using an enum
, as the values should never change, but in the end the choice is yours.
+ * There is a proper separation between each registered ITeBlock
by resource location, rather than everything being inserted into a single enum
.
+ * You also receive your own instance of BlockTileEntity
and ItemBlockTileEntity
rather than having to use IC2's own one.
+ * All the language keys and blockstate file are in your own assets (which you can, and in fact have to, pick).
+ *
+ * It is a vast improvement over TeBlockBakeEvent
, which is probably important as it's gone now ;)
+ *
+ *
+ * The event allows you to properly register your own version of TeBlock
in a way that will be as fully supported as is physically possible.
+ * It's not in the actual API itself as it's heavily dependent on internal classes, so you have this instead.
+ * This is also probably the most documented thing in the entire IC2 API. I'm too kind really. ;)
+ *
+ *
+ *
+ * So that's all well and good, but what you really want is an example of how to do it properly. Good idea, let's go.
+ *
+ *import net.minecraftforge.common.MinecraftForge;
+ *import net.minecraftforge.fml.common.Mod;
+ *import net.minecraftforge.fml.common.Mod.EventHandler;
+ *import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
+ *import net.minecraftforge.fml.common.event.FMLInitializationEvent;
+ *
+ *{@literal @}Mod(modId="ExampleIC2Addon")
+ *public class ExampleIC2Addon {
+ * public ExampleIC2Addon() {
+ * //You have to register before IC2 reaches Pre-Initialization, which unless you specifically load before it is unlikely you'll achieve.
+ * //Especially if you're an addon, you'll want to be loading after IC2 not before!
+ * //But, your mod's constructor will definitely be called before then. The issue is it's called more than once.
+ * //If you try registering the same tile entity ID twice it will crash (more on that later), so you'll have to use a singleton instance.
+ * //An enum works well for this, but anything will work as long as it's registered to the event bus once, and only once.
+ * MinecraftForge.EVENT_BUS.register(TileEntityRegisterer.INSTANCE);
+ * }
+ *
+ * {@literal @}EventHandler
+ * public void preInit(FMLPreInitializationEvent event) {
+ * MyTeBlock.registerTileEntities();
+ * }
+ *
+ * {@literal @}EventHandler
+ * public void preInit(FMLInitializationEvent event) {
+ * MyTeBlock.buildDummies();
+ * }
+ *}
+ *
+ *import ic2.api.event.TeBlockFinalCallEvent;
+ *import ic2.core.block.TeBlockRegistry;
+ *import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+ *
+ *public enum TileEntityRegisterer {
+ * INSTANCE;
+ *
+ * {@literal @}SubscribeEvent
+ * public void register(TeBlockFinalCallEvent event) {
+ * TeBlockRegistry.addAll(MyTeBlock.class, MyTeBlock.IDENTITY);
+ * }
+ *}
+ *
+ *import ic2.core.block.BlockTileEntity;
+ *import ic2.core.block.ITeBlock;
+ *import ic2.core.block.TileEntityBlock;
+ *import ic2.core.item.block.ItemBlockTileEntity;
+ *import ic2.core.ref.TeBlock.DefaultDrop;
+ *import ic2.core.ref.TeBlock.HarvestTool;
+ *import ic2.core.ref.TeBlock.ITePlaceHandler;
+ *import ic2.core.util.Util;
+ *import net.minecraft.block.material.Material;
+ *import net.minecraft.creativetab.CreativeTabs;
+ *import net.minecraft.item.EnumRarity;
+ *import net.minecraft.item.ItemStack;
+ *import net.minecraft.tileentity.TileEntity;
+ *import net.minecraft.util.EnumFacing;
+ *import net.minecraft.util.ResourceLocation;
+ *
+ *public enum MyTeBlock implements ITeBlock {
+ * my_machine_name(MyMachineTileEntity.class, 0, false, Util.noFacings, false, HarvestTool.Pickaxe, DefaultDrop.Machine, 5, 10, EnumRarity.UNCOMMON, Material.IRON);
+ *
+ * private MyTeBlock(Class extends TileEntityBlock> teClass, int ID,
+ * boolean hasActive, Set{@literal <}EnumFacing{@literal >} possibleFacings, boolean canBeWrenched,
+ * HarvestTool tool, DefaultDrop drop,
+ * float hardness, float explosionResistance, EnumRarity rarity, Material material) {
+ * this.teClass = teClass;
+ * this.ID = ID;
+ * this.hasActive = hasActive;
+ * this.possibleFacings = possibleFacings;
+ * this.canBeWrenched = canBeWrenched;
+ * this.tool = tool;
+ * this.drop = drop;
+ * this.hardness = hardness;
+ * this.explosionResistance = explosionResistance;
+ * this.rarity = rarity;
+ * this.material = material;
+ * }
+ *
+ * {@literal @}Override
+ * public boolean hasItem() {
+ * return teClass != null && itemMeta != -1;
+ * }
+ *
+ * {@literal @}Override
+ * public String getName() {
+ * return name();
+ * }
+ *
+ * {@literal @}Override
+ * public ResourceLocation getIdentifier() {
+ * return IDENTITY;
+ * }
+ *
+ * {@literal @}Override
+ * public Class extends TileEntityBlock> getTeClass() {
+ * return teClass;
+ * }
+ *
+ * {@literal @}Override
+ * public boolean hasActive() {
+ * return hasActive;
+ * }
+ *
+ * {@literal @}Override
+ * public int getId() {
+ * return ID;
+ * }
+ *
+ * {@literal @}Override
+ * public float getHardness() {
+ * return hardness;
+ * }
+ *
+ * {@literal @}Override
+ * public HarvestTool getHarvestTool() {
+ * return tool;
+ * }
+ *
+ * {@literal @}Override
+ * public DefaultDrop getDefaultDrop() {
+ * return drop;
+ * }
+ *
+ * {@literal @}Override
+ * public float getExplosionResistance() {
+ * return explosionResistance;
+ * }
+ *
+ * {@literal @}Override
+ * public boolean allowWrenchRotating() {
+ * return canBeWrenched;
+ * }
+ *
+ * {@literal @}Override
+ * public Set{@literal <}EnumFacing{@literal >} getSupportedFacings() {
+ * return possibleFacings;
+ * }
+ *
+ * {@literal @}Override
+ * public EnumRarity getRarity() {
+ * return rarity;
+ * }
+ *
+ * {@literal @}Override
+ * public Material getMaterial() {
+ * return material;
+ * }
+ *
+ * {@literal @}Override
+ * public void addSubBlocks(List{@literal <}ItemStack{@literal >} list, BlockTileEntity block, ItemBlockTileEntity item, CreativeTabs tab) {
+ * for (MyTeBlock block : values()) {
+ * if (type.hasItem()) {
+ * list.add(block.getItemStack(type));
+ * }
+ * }
+ * }
+ *
+ * {@literal @}Override
+ * public void setPlaceHandler(ITePlaceHandler handler) {
+ * this.placeHandler = handler;
+ * }
+ *
+ * {@literal @}Override
+ * public ITePlaceHandler getPlaceHandler() {
+ * return placeHandler;
+ * }
+ *
+ * public static void registerTileEntities() {
+ * for (MyTeBlock block : values()) {
+ * if (block.teClass != null) TileEntity.addMapping(block.teClass, IDENTITY.getResourceDomain() + ':' + block.getName());
+ * }
+ * }
+ *
+ * public static void buildDummies() {
+ * for (MyTeBlock block : values()) {
+ * //System.out.printf("Registering %s (with teClass %s)%n", block.getName(), block.teClass);
+ * if (block.teClass != null) {
+ * try {
+ * block.dummyTe = block.teClass.newInstance();
+ * } catch (Exception e) {
+ * e.printStackTrace();
+ * }
+ * }
+ * }
+ * }
+ *
+ * {@literal @}Override
+ * public TileEntityBlock getDummyTe() {
+ * return dummyTe;
+ * }
+ *
+ * private final Class extends TileEntityBlock> teClass;
+ * private final int ID;
+ * private final boolean hasActive;
+ * private final Set{@literal <}EnumFacing{@literal >} possibleFacings;
+ * private final boolean canBeWrenched;
+ * private final HarvestTool tool;
+ * private final DefaultDrop drop;
+ * private final float hardness;
+ * private final float explosionResistance;
+ * private final EnumRarity rarity;
+ * private final Material material;
+ * private TileEntityBlock dummyTe;
+ * private ITePlaceHandler placeHandler;
+ *
+ * public static final ResourceLocation IDENTITY = new ResourceLocation("ExampleIC2Addon", "machines");
+ *}
+ *
+ * And that's it, you now have my_machine_name
registered with the MyMachineTileEntity
tile entity class,
+ * the language key to translate it's name being ExampleIC2Addon.machines.my_machine_name and
+ * the blockstate being in machines.json
file in your mod's assets.
+ *
+ *
+ *
+ * But hang on, what are all the parameters of our new enum
and what does ITeBlock
do with them? What are dummy tile entities for?
+ * Don't worry, it's quite simple (once you know it at least).
+ *
+ *
+ * First we'll start on what {@link TeBlockFinalCallEvent} is. It's posted on the {@link MinecraftForge#EVENT_BUS} just before the blocks are built,
+ * after which point any further attempts to register ITeBlock
s will fail, as we can't inject them late due to the model generating.
+ * It is best to hook into this to register your ITeBlock
s, as it will be guaranteed to be posted at the right time.
+ *
+ * In terms of ITeBlock
, there's quite a bit of information it needs in order to function. We'll go through each parameter (or getter method most cases too) in turn:
+ *
+ * - name: The name the new tile entity. This is important as the localisation and resource names depend on it, as well as some network syncing code.
+ * - teClass: The class of your tile entity, it must extend
TileEntityBlock
otherwise it would miss critical methods to work.
+ * If extending that is a problem then using ITeBlock
isn't what you should be doing.
+ * - itemMeta: The ID of the new instance. This is utterly critical, as it's the thing used to detect which
ITeBlock
an item is.
+ * That's very important as the tile entity class is worked out by the ID when a block's being placed in ItemBlockTileEntity
.
+ * Changing this will cause everyone's items to change and there is no stopping that if you do.
+ * The ID you pick should start at 0, and go up to Short.MAX_VALUE.
+ * Use -1 if the tile entity doesn't have an item form (or is placed using an item other than ItemBlockTileEntity
).
+ * - identifier: The resource location associated with the
ITeBlock
.
+ * The language keys, translations and internal mappings all use this, so it's best to store it as a static final variable and use that.
+ * - hasActive: If the tile entity has an active state too, which is based off whether
TileEntityBlock#getActive()
returns true
or not.
+ * The models for that will be at name_active, you can check te.json
for an example if you wish.
+ * - supportedFacings: A set of
EnumFacing
s that the block can face, used for rotating by the wrench for example.
+ * IC2 has some useful constants relating to that in Util
(allFacings, horizontalFacings, downSideFacings and noFacings).
+ * - allowWrenchRotating: Whether the tile entity can be rotated with a wrench (for {@link IWrenchable}).
+ * - harvestTool: The tool used to harvest the tile entity, currently only None, Pickaxe, Shovel and Axe.
+ * More can be added on request, but support has to be specifically added, so there's no nice way via
EnumHelper
unfortunately.
+ * - defaultDrop: The item(s) that will drop when the block is broken using the correct tool. Currently only Self, None, Generator, Machine, and AdvMachine.
+ * Like
harvestTool
, more can be added upon request.
+ * - hardness: The hardness the block should have with the tile entity, IC2 normally uses 5.
+ * - explosionResistance: The explosionResistance the block should have with the tile entity, IC2 normally uses 10.
+ * - rarity: The
EnumRarity
that the item will have for the tile entity.
+ * - material: The {@link Material} that the block representing the tile entity should have. Maximum of 16 different ones per ITeBlock registration.
+ * - placeHandler: Custom placement logic, used for things like Reactor Chambers within IC2 itself.
+ * Returning null for this uses the default logic (placing like a normal block).
+ * - dummyTe: An instance of the tile entity never registered to the world (don't try doing that) used for getting additional information about the Tile Entity.
+ * Mostly an internal thing, only exposed in case your Tile Entity uses a special constructor.
+ *
+ * - addSubBlocks: Called by
BlockTileEntity
to add all the ITeBlock
s you want to the creative menu.
+ * {@link BlockTileEntity#getItemStack(ITeBlock)} will be a useful method to get the item stack, a block instance is passed for that reason.
+ * This is only called once on a random ITeBlock
for the resource location, because they are internally stored in a {@link Set} so has no order.
+ * Will probably be changed to a static method if/when the move is made to only Java 8 support.
+ *
+ * IMPORTANT THINGS TO NOTE
+ *
+ * - Getting your instance of
BlockTileEntity
and ItemBlockTileEntity
+ * - For
BlockTileEntity
, use {@link TeBlockRegistry#get(ResourceLocation)}.
+ * For ItemBlockTileEntity
, use {@link BlockTileEntity#getItem()}.
+ * - Using a custom item model for your
ITeBlock
+ * - Implement
ITeBlockSpecialItem
along with ITeBlock
, then the item model will be what's provided rather than the block model.
+ *
+ * More will be added to this list if questions keep re-occurring, or are about a suitably important topic.
+ *
+ *
+ *
+ * There, that should be everything you need to utilise ITeBlock
to add your own tile entities using IC2's very flexible framework.
+ * I'll be happy to answer any questions you have on it, your best bet is to ask me (Chocohead) on the IC2 forums,
+ * although if you post in the support section other people might be able to help before I see your post.
+ * I'll certainly take suggestions too, this is a first version of ITeBlock
, so I'm sure there could be improvements made.
+ *
+ * Goodness I spent too long on this again...
+ *
+ *
+ *
+ * @see {@link TeBlockFinalCallEvent} for the event you'll need to subscribe to.
+ * @see {@link ic2.core.ref.TeBlock} for how all the IC2 implements {@link ITeBlock}.
+ * @see {@link ic2.core.ref.TeBlock.HarvestTool} for the currently available tools (you'll need this for adding new tile entities).
+ * @see {@link ic2.core.ref.TeBlock.DefaultDrop} for the currently available drops (you'll need this for adding new tile entities too).
+ * @see {@link ic2.core.ref.TeBlock.ITePlaceHandler} for making your own block placement handler (example in {@link ic2.core.item.ItemHandlers#reactorChamberPlace}).
+ * @see {@link ic2.core.util.Util} for the useful facings you might want for supportedFacings
.
+ * @see {@link ic2.core.block.TileEntityBlock} for the base tile entity.
+ * @see {@link ic2.core.block.BlockTileEntity} for the base block (you'll never need to construct this yourself).
+ * @see {@link ic2.core.item.block.ItemBlockTileEntity} for the base item (you'll never need to construct this yourself either).
+ * @see {@link ITeBlockSpecialItem} for the interface used to have a custom item location.
+ *
+ *
+ * @since IC2 2.6.114
+ * @version 1.2
+ *
+ * @author Chocohead
+ */
+public interface ITeBlock {
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/item/HudMode.java b/src/main/java/ic2/api/item/HudMode.java
new file mode 100644
index 0000000..d78c602
--- /dev/null
+++ b/src/main/java/ic2/api/item/HudMode.java
@@ -0,0 +1,37 @@
+package ic2.api.item;
+
+public enum HudMode {
+ DISABLED("ic2.hud.disabled"), BASIC("ic2.hud.basic"), EXTENDED("ic2.hud.extended"), ADVANCED("ic2.hud.advanced");
+
+ private HudMode(String key) {
+ translationKey = key;
+ }
+
+ private final String translationKey;
+
+ public boolean shouldDisplay() {
+ return this != DISABLED;
+ }
+
+ public boolean hasTooltip() {
+ return this == EXTENDED || this == ADVANCED;
+ }
+
+ public String getTranslationKey() {
+ return translationKey;
+ }
+
+ public int getID() {
+ return ordinal();
+ }
+
+ public static HudMode getFromID(int ID) {
+ return VALUES[ID % VALUES.length];
+ }
+
+ public static int getMaxMode() {
+ return VALUES.length - 1;
+ }
+
+ private static final HudMode[] VALUES = values();
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/item/IItemHudProvider.java b/src/main/java/ic2/api/item/IItemHudProvider.java
new file mode 100644
index 0000000..47639b3
--- /dev/null
+++ b/src/main/java/ic2/api/item/IItemHudProvider.java
@@ -0,0 +1,46 @@
+package ic2.api.item;
+
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+
+/**
+ * An interface to show that an {@link Item} can display the HUD overlay if worn.
+ *
+ * @author Chocohead
+ */
+public interface IItemHudProvider extends IElectricItem {
+ /**
+ * Whether the given stack should display the HUD overlay.
+ *
+ * @param stack The stack currently being worn
+ * @return Whether the HUD overlay should be drawn
+ */
+ boolean doesProvideHUD(ItemStack stack);
+
+ /**
+ * Gets the current {@link HudMode} of the worn stack (probably stored as NBT)
+ *
+ * @param stack The stack currently being worn
+ * @return The HUD overlay mode
+ */
+ HudMode getHudMode(ItemStack stack);
+
+ /**
+ * Override the percent shown by the HUD overlay for the applied item.
+ *
+ * By default, {@link IElectricItem}s have the percentage charged shown,
+ * damageable items have their {@link Item#getDurabilityForDisplay(ItemStack)} values shown
+ * and items that don't apply to either aren't shown at all.
+ *
+ * @author Chocohead
+ */
+ public static interface IItemHudBarProvider {
+ /**
+ * Get the percent to show in the overlay HUD for the given stack.
+ *
+ * @param stack The stack to get the percent for.
+ * @return A number between 0 and 100, less than 0 will not render the item at all.
+ */
+ int getBarPercent(ItemStack stack);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/item/ITeBlockSpecialItem.java b/src/main/java/ic2/api/item/ITeBlockSpecialItem.java
new file mode 100644
index 0000000..7d9ca63
--- /dev/null
+++ b/src/main/java/ic2/api/item/ITeBlockSpecialItem.java
@@ -0,0 +1,35 @@
+package ic2.api.item;
+
+import net.minecraft.client.renderer.block.model.ModelResourceLocation;
+import net.minecraft.item.ItemStack;
+
+import ic2.api.info.ITeBlock;
+
+/**
+ * Change the default icon for an {@link ITeBlock} by implementing this.
+ *
+ * @since IC2 2.6.85
+ * @version 1.0
+ *
+ * @see {@link ITeBlock} for more information
+ *
+ * @author Chocohead
+ */
+public interface ITeBlockSpecialItem {
+ /**
+ * Should the model be delegated to the {@link ITeBlock} or the default used?
+ *
+ * @param stack The itemstack being rendered
+ * @return Whether the {@link ITeBlock} will return an {@link ModelResourceLocation}
+ */
+ boolean doesOverrideDefault(ItemStack stack);
+
+ /**
+ * The {@link ModelResourceLocation} for the given stack.
+ * Will still use the default even if {@link #doesOverrideDefault(ItemStack)} returns true if this returns null.
+ *
+ * @param stack The itemstack being rendered
+ * @return The model location to be used
+ */
+ ModelResourceLocation getModelLocation(ItemStack stack);
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/recipe/IRecipeInputFactory.java b/src/main/java/ic2/api/recipe/IRecipeInputFactory.java
new file mode 100644
index 0000000..f802ebb
--- /dev/null
+++ b/src/main/java/ic2/api/recipe/IRecipeInputFactory.java
@@ -0,0 +1,17 @@
+package ic2.api.recipe;
+
+import net.minecraft.item.ItemStack;
+
+import net.minecraftforge.fluids.Fluid;
+
+public interface IRecipeInputFactory {
+ IRecipeInput forStack(ItemStack stack);
+ IRecipeInput forStack(ItemStack stack, int amount);
+ IRecipeInput forOreDict(String name);
+ IRecipeInput forOreDict(String name, int amount);
+ IRecipeInput forOreDict(String name, int amount, int metaOverride);
+ IRecipeInput forFluidContainer(Fluid fluid);
+ IRecipeInput forFluidContainer(Fluid fluid, int amount);
+ IRecipeInput forAny(IRecipeInput... options);
+ IRecipeInput forAny(Iterable options);
+}
diff --git a/src/main/java/ic2/api/upgrade/IAugmentationUpgrade.java b/src/main/java/ic2/api/upgrade/IAugmentationUpgrade.java
new file mode 100644
index 0000000..4a0ff0a
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/IAugmentationUpgrade.java
@@ -0,0 +1,20 @@
+package ic2.api.upgrade;
+
+import net.minecraft.item.ItemStack;
+
+/**
+ * An interface to mark an item as an {@link UpgradableProperty#Augmentable} type upgrade
+ *
+ * @author Player, Chocohead
+ */
+public interface IAugmentationUpgrade extends IUpgradeItem {
+ /**
+ * Gets the augmentation of the upgrade on the given {@link IUpgradableBlock}
+ *
+ * @param stack The upgrade stack
+ * @param parent The block being augmented
+ *
+ * @return The augmentation applied
+ */
+ int getAugmentation(ItemStack stack, IUpgradableBlock parent);
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/IEnergyStorageUpgrade.java b/src/main/java/ic2/api/upgrade/IEnergyStorageUpgrade.java
new file mode 100644
index 0000000..9c9a9e6
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/IEnergyStorageUpgrade.java
@@ -0,0 +1,30 @@
+package ic2.api.upgrade;
+
+import net.minecraft.item.ItemStack;
+
+/**
+ * An interface to mark an item as an {@link UpgradableProperty#EnergyStorage} type upgrade
+ *
+ * @author Player, Chocohead
+ */
+public interface IEnergyStorageUpgrade extends IUpgradeItem {
+ /**
+ * A raw value that is added to the {@link IUpgradableBlock}'s energy storage
+ *
+ * @param stack The upgrade stack
+ * @param parent The block storing energy
+ *
+ * @return The raw change in energy storage to be applied
+ */
+ int getExtraEnergyStorage(ItemStack stack, IUpgradableBlock parent);
+
+ /**
+ * A multiplier value that the {@link IUpgradableBlock}'s energy storage is affected by
+ *
+ * @param stack The upgrade stack
+ * @param parent The block storing energy
+ *
+ * @return The multiplier to be applied to be energy storage
+ */
+ double getEnergyStorageMultiplier(ItemStack stack, IUpgradableBlock parent);
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/IFluidConsumingUpgrade.java b/src/main/java/ic2/api/upgrade/IFluidConsumingUpgrade.java
new file mode 100644
index 0000000..f798452
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/IFluidConsumingUpgrade.java
@@ -0,0 +1,10 @@
+package ic2.api.upgrade;
+
+/**
+ * An interface to mark an item as an {@link UpgradableProperty#FluidConsuming} type upgrade
+ *
+ * @author Player, Chocohead
+ */
+public interface IFluidConsumingUpgrade extends IUpgradeItem {
+
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/IFluidProducingUpgrade.java b/src/main/java/ic2/api/upgrade/IFluidProducingUpgrade.java
new file mode 100644
index 0000000..f310a90
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/IFluidProducingUpgrade.java
@@ -0,0 +1,10 @@
+package ic2.api.upgrade;
+
+/**
+ * An interface to mark an item as an {@link UpgradableProperty#FluidProducing} type upgrade
+ *
+ * @author Player, Chocohead
+ */
+public interface IFluidProducingUpgrade extends IUpgradeItem {
+
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/IFullUpgrade.java b/src/main/java/ic2/api/upgrade/IFullUpgrade.java
new file mode 100644
index 0000000..2077862
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/IFullUpgrade.java
@@ -0,0 +1,12 @@
+package ic2.api.upgrade;
+
+/**
+ * An interface to mark an item supporting all {@link UpgradableProperty} type upgrades
+ *
+ * @author Player, Chocohead
+ */
+public interface IFullUpgrade extends IAugmentationUpgrade, IEnergyStorageUpgrade, IFluidConsumingUpgrade,
+ IFluidProducingUpgrade, IItemConsumingUpgrade, IItemProducingUpgrade, IProcessingUpgrade,
+ IRedstoneSensitiveUpgrade, ITransformerUpgrade {
+
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/IItemConsumingUpgrade.java b/src/main/java/ic2/api/upgrade/IItemConsumingUpgrade.java
new file mode 100644
index 0000000..0a7216b
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/IItemConsumingUpgrade.java
@@ -0,0 +1,10 @@
+package ic2.api.upgrade;
+
+/**
+ * An interface to mark an item as an {@link UpgradableProperty#ItemConsuming} type upgrade
+ *
+ * @author Player, Chocohead
+ */
+public interface IItemConsumingUpgrade extends IUpgradeItem {
+
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/IItemProducingUpgrade.java b/src/main/java/ic2/api/upgrade/IItemProducingUpgrade.java
new file mode 100644
index 0000000..85a3b99
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/IItemProducingUpgrade.java
@@ -0,0 +1,10 @@
+package ic2.api.upgrade;
+
+/**
+ * An interface to mark an item as an {@link UpgradableProperty#ItemProducing} type upgrade
+ *
+ * @author Player, Chocohead
+ */
+public interface IItemProducingUpgrade extends IUpgradeItem {
+
+}
diff --git a/src/main/java/ic2/api/upgrade/IProcessingUpgrade.java b/src/main/java/ic2/api/upgrade/IProcessingUpgrade.java
new file mode 100644
index 0000000..694b468
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/IProcessingUpgrade.java
@@ -0,0 +1,50 @@
+package ic2.api.upgrade;
+
+import net.minecraft.item.ItemStack;
+
+/**
+ * An interface to mark an item as an {@link UpgradableProperty#Processing} type upgrade
+ *
+ * @author Player, Chocohead
+ */
+public interface IProcessingUpgrade extends IUpgradeItem {
+ /**
+ * A raw value that the process time is affected by (in ticks)
+ *
+ * @param stack The upgrade stack
+ * @param parent The {@link IUpgradableBlock} receiving the change
+ *
+ * @return The raw change in process to be applied
+ */
+ int getExtraProcessTime(ItemStack stack, IUpgradableBlock parent);
+
+ /**
+ * A multiplier value that the process time is affected by
+ *
+ * @param stack The upgrade stack
+ * @param parent The {@link IUpgradableBlock} receiving the change
+ *
+ * @return The multiplier to be applied to be progress
+ */
+ double getProcessTimeMultiplier(ItemStack stack, IUpgradableBlock parent);
+
+ /**
+ * A raw value that is added to the {@link IUpgradableBlock}'s energy demand
+ *
+ * @param stack The upgrade stack
+ * @param parent The block consuming energy
+ *
+ * @return The raw change in energy demand to be applied
+ */
+ int getExtraEnergyDemand(ItemStack stack, IUpgradableBlock parent);
+
+ /**
+ * A multiplier value that the {@link IUpgradableBlock}'s energy demand is affected by
+ *
+ * @param stack The upgrade stack
+ * @param parent The block consuming energy
+ *
+ * @return The multiplier to be applied to be energy demand
+ */
+ double getEnergyDemandMultiplier(ItemStack stack, IUpgradableBlock parent);
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/IRedstoneSensitiveUpgrade.java b/src/main/java/ic2/api/upgrade/IRedstoneSensitiveUpgrade.java
new file mode 100644
index 0000000..7c06a5a
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/IRedstoneSensitiveUpgrade.java
@@ -0,0 +1,31 @@
+package ic2.api.upgrade;
+
+import net.minecraft.item.ItemStack;
+
+/**
+ * An interface to mark an item as an {@link UpgradableProperty#RedstoneSensitive} type upgrade
+ *
+ * @author Player, Chocohead
+ */
+public interface IRedstoneSensitiveUpgrade extends IUpgradeItem {
+ /**
+ * Whether the upgrade modifies the given {@link IUpgradableBlock}'s redstone input
+ *
+ * @param stack The upgrade stack
+ * @param parent The block being modified
+ *
+ * @return Whether the redstone input should be changed (and thus {@link #getRedstoneInput(ItemStack, IUpgradableBlock, int)} be called)
+ */
+ boolean modifiesRedstoneInput(ItemStack stack, IUpgradableBlock parent);
+
+ /**
+ * Change the redstone input given the {@link IUpgradableBlock}'s initial input value
+ *
+ * @param stack The upgrade stack
+ * @param parent The block receiving the redstone signal
+ * @param externalInput The initial redstone signal
+ *
+ * @return The new redstone signal
+ */
+ int getRedstoneInput(ItemStack stack, IUpgradableBlock parent, int externalInput);
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/ITransformerUpgrade.java b/src/main/java/ic2/api/upgrade/ITransformerUpgrade.java
new file mode 100644
index 0000000..e6e2146
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/ITransformerUpgrade.java
@@ -0,0 +1,20 @@
+package ic2.api.upgrade;
+
+import net.minecraft.item.ItemStack;
+
+/**
+ * An interface to mark an item as an {@link UpgradableProperty#Transformer} type upgrade
+ *
+ * @author Player, Chocohead
+ */
+public interface ITransformerUpgrade extends IUpgradeItem {
+ /**
+ * Gets the additional tier that the given {@link IUpgradableBlock} can take
+ *
+ * @param stack The upgrade stack
+ * @param parent The block receiving energy
+ *
+ * @return The value to tier the tier by
+ */
+ int getExtraTier(ItemStack stack, IUpgradableBlock parent);
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/IUpgradableBlock.java b/src/main/java/ic2/api/upgrade/IUpgradableBlock.java
new file mode 100644
index 0000000..7667618
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/IUpgradableBlock.java
@@ -0,0 +1,29 @@
+package ic2.api.upgrade;
+
+import java.util.Set;
+
+/**
+ * An interface to mark a block as supporting {@link IUpgradeItem}s
+ *
+ * @author Player
+ */
+public interface IUpgradableBlock {
+ /**
+ * @return The energy the block current has
+ */
+ double getEnergy();
+
+ /**
+ * Attempt to use the given amount of energy
+ *
+ * @param amount The amount of energy to be used
+ *
+ * @return Whether the energy was successfully used
+ */
+ boolean useEnergy(double amount);
+
+ /**
+ * @return The set of {@link UpgradableProperty}s that the block supports
+ */
+ Set getUpgradableProperties();
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/IUpgradeItem.java b/src/main/java/ic2/api/upgrade/IUpgradeItem.java
new file mode 100644
index 0000000..3a26e23
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/IUpgradeItem.java
@@ -0,0 +1,43 @@
+package ic2.api.upgrade;
+
+import java.util.List;
+import java.util.Set;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+
+/**
+ * An interface to mark an item as an upgrade for {@link IUpgradableBlock}s
+ *
+ * @author Player, Chocohead
+ */
+public interface IUpgradeItem {
+ /**
+ * Checks if the upgrade is valid for the given {@link UpgradableProperty} types
+ *
+ * @param stack The upgrade stack being checked
+ * @param types The list of types being tested
+ *
+ * @return Whether the upgrade is valid
+ */
+ boolean isSuitableFor(ItemStack stack, Set types);
+
+ /**
+ * Called every time the given {@link IUpgradableBlock} ticks
+ *
+ * @param stack The upgrade stack being ticked
+ * @param parent The parent block being ticked
+ *
+ * @return Whether to call {@link TileEntity#markDirty()} due to a stack changing
+ */
+ boolean onTick(ItemStack stack, IUpgradableBlock parent);
+
+ /**
+ * Called when the given {@link IUpgradableBlock} finishes processing
+ *
+ * @param stack The upgrade stack
+ * @param parent The parent finishing processing
+ * @param output The list of output products from the process
+ */
+ void onProcessEnd(ItemStack stack, IUpgradableBlock parent, List output);
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/UpgradableProperty.java b/src/main/java/ic2/api/upgrade/UpgradableProperty.java
new file mode 100644
index 0000000..17c575c
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/UpgradableProperty.java
@@ -0,0 +1,45 @@
+package ic2.api.upgrade;
+
+/**
+ * The possible properties an {@link IUpgradableBlock} can support
+ *
+ * @author Player
+ */
+public enum UpgradableProperty {
+ /**
+ * A block that processes something, taking upgrade process time + energy demand into account
+ */
+ Processing,
+ /**
+ * A simple count based upgrade property, e.g. extra range
+ */
+ Augmentable,
+ /**
+ * A block that is sensitive to redstone state/changes
+ */
+ RedstoneSensitive,
+ /**
+ * A block that can have it's tier changed
+ */
+ Transformer,
+ /**
+ * A block that can have the amount of energy it stores changed
+ */
+ EnergyStorage,
+ /**
+ * A block that consumes items
+ */
+ ItemConsuming,
+ /**
+ * A block that produces items
+ */
+ ItemProducing,
+ /**
+ * A block that consumes fluids
+ */
+ FluidConsuming,
+ /**
+ * A block that produces fluids
+ */
+ FluidProducing,
+}
\ No newline at end of file
diff --git a/src/main/java/ic2/api/upgrade/UpgradeRegistry.java b/src/main/java/ic2/api/upgrade/UpgradeRegistry.java
new file mode 100644
index 0000000..8f6bed6
--- /dev/null
+++ b/src/main/java/ic2/api/upgrade/UpgradeRegistry.java
@@ -0,0 +1,38 @@
+package ic2.api.upgrade;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+
+/**
+ * The registry that contains all known {@link IUpgradeItem}s
+ *
+ * @author Player
+ */
+public class UpgradeRegistry {
+ /**
+ * Register an upgrade itemstack to the registry
+ *
+ * @param stack The upgrade to register
+ *
+ * @return The stack that has been registered
+ */
+ public static ItemStack register(ItemStack stack) {
+ if (!(stack.getItem() instanceof IUpgradeItem)) throw new IllegalArgumentException("The stack must represent an IUpgradeItem.");
+
+ upgrades.add(stack);
+
+ return stack;
+ }
+
+ /**
+ * @return An unmodifiable list of registered upgrades
+ */
+ public static Iterable getUpgrades() {
+ return Collections.unmodifiableCollection(upgrades);
+ }
+
+ private static final List upgrades = new ArrayList();
+}