diff --git a/src/main/java/WayofTime/bloodmagic/api/BlockStack.java b/src/main/java/WayofTime/bloodmagic/api/BlockStack.java
index 839b8e06..9a523ed4 100644
--- a/src/main/java/WayofTime/bloodmagic/api/BlockStack.java
+++ b/src/main/java/WayofTime/bloodmagic/api/BlockStack.java
@@ -9,16 +9,18 @@ import net.minecraft.world.World;
import net.minecraftforge.fml.common.registry.GameData;
@Getter
-@EqualsAndHashCode
+@EqualsAndHashCode(exclude = { "state" })
public class BlockStack
{
private final Block block;
private final int meta;
+ private final IBlockState state;
public BlockStack(Block block, int meta)
{
this.block = block;
this.meta = meta;
+ this.state = block.getStateFromMeta(meta);
}
public BlockStack(Block block)
@@ -35,6 +37,6 @@ public class BlockStack
@Override
public String toString()
{
- return GameData.getBlockRegistry().getNameForObject(block) + ":" + meta;
+ return GameData.getBlockRegistry().getNameForObject(getBlock()) + ":" + getMeta();
}
}
diff --git a/src/main/java/WayofTime/bloodmagic/api/iface/IHarvestHandler.java b/src/main/java/WayofTime/bloodmagic/api/iface/IHarvestHandler.java
new file mode 100644
index 00000000..c96e8c7a
--- /dev/null
+++ b/src/main/java/WayofTime/bloodmagic/api/iface/IHarvestHandler.java
@@ -0,0 +1,30 @@
+package WayofTime.bloodmagic.api.iface;
+
+import WayofTime.bloodmagic.api.BlockStack;
+import net.minecraft.util.BlockPos;
+import net.minecraft.world.World;
+
+/**
+ * Used to define a HarvestHandler for the Harvest Ritual.
+ */
+public interface IHarvestHandler
+{
+ /**
+ * Called whenever the Harvest Ritual attempts to harvest a block.
+ *
+ * Use this to break the block, plant a new one, and drop the produced items.
+ *
+ * Make sure to do checks so you are certain the blocks being handled
+ * are the block types you want.
+ *
+ * @param world
+ * - The world the {@link WayofTime.bloodmagic.api.ritual.IMasterRitualStone} is in.
+ * @param pos
+ * - The position of the Block being checked
+ * @param blockStack
+ * - The Block being checked
+ *
+ * @return If the block was successfully harvested.
+ */
+ boolean harvestAndPlant(World world, BlockPos pos, BlockStack blockStack);
+}
diff --git a/src/main/java/WayofTime/bloodmagic/api/registry/HarvestRegistry.java b/src/main/java/WayofTime/bloodmagic/api/registry/HarvestRegistry.java
new file mode 100644
index 00000000..6bdc5a24
--- /dev/null
+++ b/src/main/java/WayofTime/bloodmagic/api/registry/HarvestRegistry.java
@@ -0,0 +1,72 @@
+package WayofTime.bloodmagic.api.registry;
+
+import WayofTime.bloodmagic.api.BlockStack;
+import WayofTime.bloodmagic.api.iface.IHarvestHandler;
+import net.minecraft.block.Block;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class HarvestRegistry
+{
+ private static List handlerList = new ArrayList();
+ private static Map validBlocks = new HashMap();
+ private static Map amplifierMap = new HashMap();
+
+ /**
+ * Registers a handler for the Harvest Ritual to call.
+ *
+ * @param handler
+ * - The custom handler to register
+ */
+ public static void registerHandler(IHarvestHandler handler)
+ {
+ if (!handlerList.contains(handler))
+ handlerList.add(handler);
+ }
+
+ /**
+ * Registers a standard crop (IE: Wheat, Carrots, Potatoes, Netherwart, etc) for
+ * the {@link WayofTime.bloodmagic.ritual.harvest.HarvestHandlerPlantable} handler
+ * to handle.
+ *
+ * @param crop
+ * - The crop block to handle.
+ * @param matureMeta
+ * - The meta value at which the crop is considered mature
+ * and ready to be harvested.
+ */
+ public static void registerStandardCrop(Block crop, int matureMeta)
+ {
+ if (!validBlocks.containsKey(crop))
+ validBlocks.put(crop, matureMeta);
+ }
+
+ /**
+ * Registers a range amplifier for the Harvest Ritual.
+ *
+ * @param blockStack
+ * - The block for the amplifier.
+ * @param range
+ * - The range the amplifier provides.
+ */
+ public static void registerRangeAmplifier(BlockStack blockStack, int range)
+ {
+ if (!amplifierMap.containsKey(blockStack))
+ amplifierMap.put(blockStack, range);
+ }
+
+ public static List getHandlerList() {
+ return handlerList;
+ }
+
+ public static Map getValidBlocks() {
+ return validBlocks;
+ }
+
+ public static Map getAmplifierMap() {
+ return amplifierMap;
+ }
+}
diff --git a/src/main/java/WayofTime/bloodmagic/registry/ModRituals.java b/src/main/java/WayofTime/bloodmagic/registry/ModRituals.java
index 7d168fd4..c907484c 100644
--- a/src/main/java/WayofTime/bloodmagic/registry/ModRituals.java
+++ b/src/main/java/WayofTime/bloodmagic/registry/ModRituals.java
@@ -1,10 +1,12 @@
package WayofTime.bloodmagic.registry;
+import WayofTime.bloodmagic.api.registry.HarvestRegistry;
import WayofTime.bloodmagic.api.registry.ImperfectRitualRegistry;
import WayofTime.bloodmagic.api.registry.RitualRegistry;
import WayofTime.bloodmagic.api.ritual.Ritual;
import WayofTime.bloodmagic.api.ritual.imperfect.ImperfectRitual;
import WayofTime.bloodmagic.ritual.*;
+import WayofTime.bloodmagic.ritual.harvest.HarvestHandlerPlantable;
import WayofTime.bloodmagic.ritual.imperfect.*;
public class ModRituals
@@ -17,6 +19,7 @@ public class ModRituals
public static Ritual featheredKnifeRitual;
public static Ritual regenerationRitual;
public static Ritual animalGrowthRitual;
+ public static Ritual harvestRitual;
public static ImperfectRitual imperfectNight;
public static ImperfectRitual imperfectRain;
@@ -41,6 +44,9 @@ public class ModRituals
RitualRegistry.registerRitual(regenerationRitual, regenerationRitual.getName());
animalGrowthRitual = new RitualAnimalGrowth();
RitualRegistry.registerRitual(animalGrowthRitual, animalGrowthRitual.getName());
+ harvestRitual = new RitualHarvest();
+ RitualRegistry.registerRitual(harvestRitual, harvestRitual.getName());
+ initHarvestHandlers();
}
public static void initImperfectRituals()
@@ -54,4 +60,9 @@ public class ModRituals
imperfectZombie = new ImperfectRitualZombie();
ImperfectRitualRegistry.registerRitual(imperfectZombie);
}
+
+ public static void initHarvestHandlers()
+ {
+ HarvestRegistry.registerHandler(new HarvestHandlerPlantable());
+ }
}
diff --git a/src/main/java/WayofTime/bloodmagic/ritual/RitualHarvest.java b/src/main/java/WayofTime/bloodmagic/ritual/RitualHarvest.java
new file mode 100644
index 00000000..7e37fb2f
--- /dev/null
+++ b/src/main/java/WayofTime/bloodmagic/ritual/RitualHarvest.java
@@ -0,0 +1,119 @@
+package WayofTime.bloodmagic.ritual;
+
+import WayofTime.bloodmagic.api.BlockStack;
+import WayofTime.bloodmagic.api.Constants;
+import WayofTime.bloodmagic.api.iface.IHarvestHandler;
+import WayofTime.bloodmagic.api.network.SoulNetwork;
+import WayofTime.bloodmagic.api.registry.HarvestRegistry;
+import WayofTime.bloodmagic.api.ritual.*;
+import WayofTime.bloodmagic.api.util.helper.NetworkHelper;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.BlockPos;
+import net.minecraft.world.World;
+
+import java.util.ArrayList;
+
+public class RitualHarvest extends Ritual
+{
+ public static final String HARVEST_RANGE = "harvestRange";
+
+ public RitualHarvest()
+ {
+ super("ritualHarvest", 0, 20000, "ritual." + Constants.Mod.MODID + ".harvestRitual");
+
+ HarvestRegistry.registerRangeAmplifier(new BlockStack(Blocks.diamond_block), 15);
+ HarvestRegistry.registerRangeAmplifier(new BlockStack(Blocks.gold_block), 10);
+ HarvestRegistry.registerRangeAmplifier(new BlockStack(Blocks.iron_block), 6);
+ }
+
+ @Override
+ public void performRitual(IMasterRitualStone masterRitualStone)
+ {
+ SoulNetwork network = NetworkHelper.getSoulNetwork(masterRitualStone.getOwner());
+ World world = masterRitualStone.getWorldObj();
+
+ if (network.getCurrentEssence() < getRefreshCost())
+ {
+ network.causeNauseaToPlayer();
+ return;
+ }
+
+ BlockStack amplifierStack = BlockStack.getStackFromPos(world, masterRitualStone.getBlockPos().up());
+
+ int range = 4;
+ if (amplifierStack != null)
+ if (HarvestRegistry.getAmplifierMap().containsKey(amplifierStack))
+ range = HarvestRegistry.getAmplifierMap().get(amplifierStack);
+
+ addBlockRange(HARVEST_RANGE, new AreaDescriptor.Rectangle(new BlockPos(-range, 0, -range), new BlockPos(range + 1, 4, range + 1)));
+
+ int harvested = 0;
+
+ for (BlockPos pos : getBlockRange(HARVEST_RANGE).getContainedPositions(masterRitualStone.getBlockPos().up()))
+ if (harvestBlock(world, pos))
+ harvested++;
+
+ network.syphon(getRefreshCost() * Math.min(100, harvested));
+ }
+
+ @Override
+ public int getRefreshCost()
+ {
+ return 20;
+ }
+
+ @Override
+ public int getRefreshTime()
+ {
+ return 5;
+ }
+
+ @Override
+ public ArrayList getComponents()
+ {
+ ArrayList components = new ArrayList();
+
+ components.add(new RitualComponent(new BlockPos(1, 0, 1), EnumRuneType.DUSK));
+ components.add(new RitualComponent(new BlockPos(1, 0, -1), EnumRuneType.DUSK));
+ components.add(new RitualComponent(new BlockPos(-1, 0, -1), EnumRuneType.DUSK));
+ components.add(new RitualComponent(new BlockPos(-1, 0, 1), EnumRuneType.DUSK));
+ components.add(new RitualComponent(new BlockPos(2, 0, 0), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(-2, 0, 0), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(0, 0, 2), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(0, 0, -2), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(3, 0, 1), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(3, 0, -1), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(-3, 0, 1), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(-3, 0, -1), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(1, 0, 3), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(-1, 0, 3), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(1, 0, -3), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(-1, 0, -3), EnumRuneType.EARTH));
+ components.add(new RitualComponent(new BlockPos(2, 0, 3), EnumRuneType.WATER));
+ components.add(new RitualComponent(new BlockPos(3, 0, 2), EnumRuneType.WATER));
+ components.add(new RitualComponent(new BlockPos(2, 0, -3), EnumRuneType.WATER));
+ components.add(new RitualComponent(new BlockPos(-3, 0, 2), EnumRuneType.WATER));
+ components.add(new RitualComponent(new BlockPos(-2, 0, 3), EnumRuneType.WATER));
+ components.add(new RitualComponent(new BlockPos(3, 0, -2), EnumRuneType.WATER));
+ components.add(new RitualComponent(new BlockPos(-2, 0, -3), EnumRuneType.WATER));
+ components.add(new RitualComponent(new BlockPos(-3, 0, -2), EnumRuneType.WATER));
+
+ return components;
+ }
+
+ @Override
+ public Ritual getNewCopy()
+ {
+ return new RitualHarvest();
+ }
+
+ public static boolean harvestBlock(World world, BlockPos pos) {
+ BlockStack harvestStack = BlockStack.getStackFromPos(world, pos);
+
+ for (IHarvestHandler handler : HarvestRegistry.getHandlerList())
+ if (handler.harvestAndPlant(world, pos, harvestStack))
+ return true;
+
+ return false;
+ }
+}
diff --git a/src/main/java/WayofTime/bloodmagic/ritual/harvest/HarvestHandlerPlantable.java b/src/main/java/WayofTime/bloodmagic/ritual/harvest/HarvestHandlerPlantable.java
new file mode 100644
index 00000000..74d0802b
--- /dev/null
+++ b/src/main/java/WayofTime/bloodmagic/ritual/harvest/HarvestHandlerPlantable.java
@@ -0,0 +1,73 @@
+package WayofTime.bloodmagic.ritual.harvest;
+
+import WayofTime.bloodmagic.api.BlockStack;
+import WayofTime.bloodmagic.api.iface.IHarvestHandler;
+import WayofTime.bloodmagic.api.registry.HarvestRegistry;
+import net.minecraft.block.BlockCrops;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.BlockPos;
+import net.minecraft.world.World;
+import net.minecraftforge.common.IPlantable;
+
+import java.util.List;
+
+public class HarvestHandlerPlantable implements IHarvestHandler
+{
+ public HarvestHandlerPlantable()
+ {
+ HarvestRegistry.registerStandardCrop(Blocks.carrots, 7);
+ HarvestRegistry.registerStandardCrop(Blocks.wheat, 7);
+ HarvestRegistry.registerStandardCrop(Blocks.potatoes, 7);
+ HarvestRegistry.registerStandardCrop(Blocks.nether_wart, 3);
+ }
+
+ @Override
+ public boolean harvestAndPlant(World world, BlockPos pos, BlockStack blockStack)
+ {
+ if (!HarvestRegistry.getValidBlocks().containsKey(blockStack.getBlock()))
+ return false;
+
+ int matureMeta = HarvestRegistry.getValidBlocks().get(blockStack.getBlock());
+
+ if(blockStack.getMeta() < matureMeta)
+ return false;
+
+ List drops = blockStack.getBlock().getDrops(world, pos, blockStack.getState(), 0);
+ boolean foundSeed = false;
+
+ for (ItemStack stack : drops) {
+ if (stack == null)
+ continue;
+
+ if (stack.getItem() instanceof IPlantable)
+ {
+ if (stack.stackSize > 1)
+ stack.stackSize--;
+ else
+ drops.remove(stack);
+
+ foundSeed = true;
+ break;
+ }
+ }
+
+ if (foundSeed)
+ {
+ world.setBlockState(pos, blockStack.getState().withProperty(BlockCrops.AGE, 0));
+ for (ItemStack stack : drops)
+ {
+ if (!world.isRemote)
+ {
+ EntityItem toDrop = new EntityItem(world, pos.getX(), pos.getY() + 0.5, pos.getZ(), stack);
+ world.spawnEntityInWorld(toDrop);
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+}