diff --git a/changelog.txt b/changelog.txt index 8118a4c0..1f23e83d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -10,6 +10,7 @@ Version 2.0.0-4 - Animal Growth ritual - Harvest ritual - Magnetism ritual + - Crushing ritual - Added parts for the new Soul System - Added the Monster Soul diff --git a/src/main/java/WayofTime/bloodmagic/registry/ModRituals.java b/src/main/java/WayofTime/bloodmagic/registry/ModRituals.java index fe691de3..b3862dd2 100644 --- a/src/main/java/WayofTime/bloodmagic/registry/ModRituals.java +++ b/src/main/java/WayofTime/bloodmagic/registry/ModRituals.java @@ -25,6 +25,7 @@ public class ModRituals public static Ritual animalGrowthRitual; public static Ritual harvestRitual; public static Ritual magneticRitual; + public static Ritual crushingRitual; public static ImperfectRitual imperfectNight; public static ImperfectRitual imperfectRain; @@ -54,6 +55,8 @@ public class ModRituals initHarvestHandlers(); magneticRitual = new RitualMagnetic(); RitualRegistry.registerRitual(magneticRitual, magneticRitual.getName()); + crushingRitual = new RitualCrushing(); + RitualRegistry.registerRitual(crushingRitual, crushingRitual.getName()); } public static void initImperfectRituals() diff --git a/src/main/java/WayofTime/bloodmagic/ritual/RitualCrushing.java b/src/main/java/WayofTime/bloodmagic/ritual/RitualCrushing.java new file mode 100644 index 00000000..5925556c --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/ritual/RitualCrushing.java @@ -0,0 +1,151 @@ +package WayofTime.bloodmagic.ritual; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import WayofTime.bloodmagic.api.Constants; +import WayofTime.bloodmagic.api.network.SoulNetwork; +import WayofTime.bloodmagic.api.ritual.AreaDescriptor; +import WayofTime.bloodmagic.api.ritual.EnumRuneType; +import WayofTime.bloodmagic.api.ritual.IMasterRitualStone; +import WayofTime.bloodmagic.api.ritual.Ritual; +import WayofTime.bloodmagic.api.ritual.RitualComponent; +import WayofTime.bloodmagic.api.util.helper.NetworkHelper; +import WayofTime.bloodmagic.registry.ModBlocks; +import WayofTime.bloodmagic.util.Utils; + +public class RitualCrushing extends Ritual +{ + public static final String CRUSHING_RANGE = "crushingRange"; + + public RitualCrushing() + { + super("ritualCrushing", 0, 2500, "ritual." + Constants.Mod.MODID + ".crushingRitual"); + addBlockRange(CRUSHING_RANGE, new AreaDescriptor.Rectangle(new BlockPos(-1, -3, -1), 3)); + } + + @Override + public void performRitual(IMasterRitualStone masterRitualStone) + { + World world = masterRitualStone.getWorldObj(); + SoulNetwork network = NetworkHelper.getSoulNetwork(masterRitualStone.getOwner()); + int currentEssence = network.getCurrentEssence(); + + if (currentEssence < getRefreshCost()) + { + network.causeNauseaToPlayer(); + return; + } + + TileEntity tile = world.getTileEntity(masterRitualStone.getBlockPos().up()); + + if (!(tile instanceof IInventory)) + { + return; + } + + IInventory tileEntity; + tileEntity = (IInventory) tile; + + if (tileEntity.getSizeInventory() <= 0) + { + return; + } + + boolean isSilkTouch = false; + int fortune = 0; + + AreaDescriptor crushingRange = getBlockRange(CRUSHING_RANGE); + BlockPos pos = masterRitualStone.getBlockPos(); + + for (BlockPos newPos : crushingRange.getContainedPositions(pos)) + { + if (world.isAirBlock(newPos)) + { + continue; + } + + IBlockState state = world.getBlockState(newPos); + Block block = state.getBlock(); + if (block.equals(ModBlocks.ritualController) || block.equals(ModBlocks.ritualStone)) + { + continue; + } + + if (isSilkTouch && block.canSilkHarvest(world, newPos, state, null)) + { + int meta = block.getMetaFromState(state); + ItemStack item = new ItemStack(block, 1, meta); + ItemStack copyStack = ItemStack.copyItemStack(item); + + Utils.insertStackIntoInventory(copyStack, tileEntity, EnumFacing.DOWN); + + if (copyStack.stackSize > 0) + { + world.spawnEntityInWorld(new EntityItem(world, pos.getX() + 0.5, pos.getY() + 2, pos.getZ() + 0.5, copyStack)); + } + } else + { + List stackList = block.getDrops(world, newPos, state, fortune); + + if (stackList != null && !stackList.isEmpty()) + { + for (ItemStack item : stackList) + { + ItemStack copyStack = ItemStack.copyItemStack(item); + + Utils.insertStackIntoInventory(copyStack, tileEntity, EnumFacing.DOWN); + if (copyStack.stackSize > 0) + { + world.spawnEntityInWorld(new EntityItem(world, pos.getX() + 0.5, pos.getY() + 2, pos.getZ() + 0.5, copyStack)); + } + } + } + } + + world.setBlockToAir(newPos); + } + + network.syphon(getRefreshCost()); + } + + @Override + public int getRefreshTime() + { + return 40; + } + + @Override + public int getRefreshCost() + { + return 7; + } + + @Override + public ArrayList getComponents() + { + ArrayList components = new ArrayList(); + + this.addParallelRunes(ritualComponents, 1, 0, EnumRuneType.EARTH); + this.addParallelRunes(components, 2, 0, EnumRuneType.FIRE); + this.addCornerRunes(components, 2, 0, EnumRuneType.DUSK); + this.addParallelRunes(components, 2, 1, EnumRuneType.AIR); + + return components; + } + + @Override + public Ritual getNewCopy() + { + return new RitualCrushing(); + } +} diff --git a/src/main/java/WayofTime/bloodmagic/ritual/RitualMagnetic.java b/src/main/java/WayofTime/bloodmagic/ritual/RitualMagnetic.java index 4c43829a..bb993062 100644 --- a/src/main/java/WayofTime/bloodmagic/ritual/RitualMagnetic.java +++ b/src/main/java/WayofTime/bloodmagic/ritual/RitualMagnetic.java @@ -36,7 +36,7 @@ public class RitualMagnetic extends Ritual public RitualMagnetic() { - super("ritualMagnetic", 0, 10000, "ritual." + Constants.Mod.MODID + ".magneticRitual"); + super("ritualMagnetic", 0, 5000, "ritual." + Constants.Mod.MODID + ".magneticRitual"); addBlockRange(PLACEMENT_RANGE, new AreaDescriptor.Rectangle(new BlockPos(-1, 1, -1), 3)); } @@ -189,7 +189,7 @@ public class RitualMagnetic extends Ritual @Override public int getRefreshCost() { - return 25; + return 50; } @Override diff --git a/src/main/java/WayofTime/bloodmagic/util/Utils.java b/src/main/java/WayofTime/bloodmagic/util/Utils.java index f2f28c55..fe04da28 100644 --- a/src/main/java/WayofTime/bloodmagic/util/Utils.java +++ b/src/main/java/WayofTime/bloodmagic/util/Utils.java @@ -6,9 +6,12 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; import net.minecraft.item.ItemStack; import net.minecraft.potion.Potion; import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumFacing; import WayofTime.bloodmagic.api.altar.EnumAltarComponent; import WayofTime.bloodmagic.registry.ModBlocks; import WayofTime.bloodmagic.tile.TileInventory; @@ -171,4 +174,301 @@ public class Utils } } } + + /** + * Used to determine if stack1 can be placed into stack2. If stack2 is null + * and stack1 isn't null, returns true. Ignores stack size + * + * @param stack1 + * Stack that is placed into a slot + * @param stack2 + * Slot content that stack1 is placed into + * @return True if they can be combined + */ + public static boolean canCombine(ItemStack stack1, ItemStack stack2) + { + if (stack1 == null) + { + return false; + } + + if (stack2 == null) + { + return true; + } + + if (stack1.isItemStackDamageable() ^ stack2.isItemStackDamageable()) + { + return false; + } + + return stack1.getItem() == stack2.getItem() && stack1.getItemDamage() == stack2.getItemDamage() && ItemStack.areItemStackTagsEqual(stack1, stack2); + } + + /** + * @param stack1 + * Stack that is placed into a slot + * @param stack2 + * Slot content that stack1 is placed into + * @return Stacks after stacking + */ + public static ItemStack[] combineStacks(ItemStack stack1, ItemStack stack2, int transferMax) + { + ItemStack[] returned = new ItemStack[2]; + + if (canCombine(stack1, stack2)) + { + int transferedAmount = Math.min(transferMax, stack2 == null ? stack1.stackSize : Math.min(stack2.getMaxStackSize() - stack2.stackSize, stack1.stackSize)); + if (transferedAmount > 0) + { + ItemStack copyStack = stack1.splitStack(transferedAmount); + if (stack2 == null) + { + stack2 = copyStack; + } else + { + stack2.stackSize += transferedAmount; + } + } + } + + returned[0] = stack1; + returned[1] = stack2; + + return returned; + } + + /** + * @param stack1 + * Stack that is placed into a slot + * @param stack2 + * Slot content that stack1 is placed into + * @return Stacks after stacking + */ + public static ItemStack[] combineStacks(ItemStack stack1, ItemStack stack2) + { + ItemStack[] returned = new ItemStack[2]; + + if (canCombine(stack1, stack2)) + { + int transferedAmount = stack2 == null ? stack1.stackSize : Math.min(stack2.getMaxStackSize() - stack2.stackSize, stack1.stackSize); + if (transferedAmount > 0) + { + ItemStack copyStack = stack1.splitStack(transferedAmount); + if (stack2 == null) + { + stack2 = copyStack; + } else + { + stack2.stackSize += transferedAmount; + } + } + } + + returned[0] = stack1; + returned[1] = stack2; + + return returned; + } + + public static ItemStack insertStackIntoInventory(ItemStack stack, IInventory inventory, EnumFacing dir) + { + if (stack == null) + { + return null; + } + + boolean[] canBeInserted = new boolean[inventory.getSizeInventory()]; + + if (inventory instanceof ISidedInventory) + { + int[] array = ((ISidedInventory) inventory).getSlotsForFace(dir); + for (int in : array) + { + canBeInserted[in] = inventory.isItemValidForSlot(in, stack) && ((ISidedInventory) inventory).canInsertItem(in, stack, dir); + } + } else + { + for (int i = 0; i < canBeInserted.length; i++) + { + canBeInserted[i] = inventory.isItemValidForSlot(i, stack); + } + } + + for (int i = 0; i < inventory.getSizeInventory(); i++) + { + if (!canBeInserted[i]) + { + continue; + } + + ItemStack[] combinedStacks = combineStacks(stack, inventory.getStackInSlot(i)); + stack = combinedStacks[0]; + inventory.setInventorySlotContents(i, combinedStacks[1]); + + if (stack.stackSize <= 0) + { + return stack; + } + } + + return stack; + } + + public static boolean canInsertStackFullyIntoInventory(ItemStack stack, IInventory inventory, EnumFacing dir) + { + return canInsertStackFullyIntoInventory(stack, inventory, dir, false, 0); + } + + public static boolean canInsertStackFullyIntoInventory(ItemStack stack, IInventory inventory, EnumFacing dir, boolean fillToLimit, int limit) + { + if (stack == null) + { + return true; + } + + int itemsLeft = stack.stackSize; + + boolean[] canBeInserted = new boolean[inventory.getSizeInventory()]; + + if (inventory instanceof ISidedInventory) + { + int[] array = ((ISidedInventory) inventory).getSlotsForFace(dir); + for (int in : array) + { + canBeInserted[in] = inventory.isItemValidForSlot(in, stack) && ((ISidedInventory) inventory).canInsertItem(in, stack, dir); + } + } else + { + for (int i = 0; i < canBeInserted.length; i++) + { + canBeInserted[i] = inventory.isItemValidForSlot(i, stack); + } + } + + int numberMatching = 0; + + if (fillToLimit) + { + for (int i = 0; i < inventory.getSizeInventory(); i++) + { + if (!canBeInserted[i]) + { + continue; + } + + ItemStack invStack = inventory.getStackInSlot(i); + + if (invStack != null && canCombine(stack, invStack)) + { + numberMatching += invStack.stackSize; + } + } + } + + if (fillToLimit && limit < stack.stackSize + numberMatching) + { + return false; + } + + for (int i = 0; i < inventory.getSizeInventory(); i++) + { + if (!canBeInserted[i]) + { + continue; + } + + ItemStack invStack = inventory.getStackInSlot(i); + boolean canCombine = canCombine(stack, invStack); + if (canCombine) + { + if (invStack == null) + { + itemsLeft = 0; + } else + { + itemsLeft -= (invStack.getMaxStackSize() - invStack.stackSize); + } + } + + if (itemsLeft <= 0) + { + return true; + } + } + + return false; + } + + public static ItemStack insertStackIntoInventory(ItemStack stack, IInventory inventory, EnumFacing dir, int limit) + { + if (stack == null) + { + return null; + } + + boolean[] canBeInserted = new boolean[inventory.getSizeInventory()]; + + if (inventory instanceof ISidedInventory) + { + int[] array = ((ISidedInventory) inventory).getSlotsForFace(dir); + for (int in : array) + { + canBeInserted[in] = ((ISidedInventory) inventory).canInsertItem(in, stack, dir); + } + } else + { + for (int i = 0; i < canBeInserted.length; i++) + { + canBeInserted[i] = true; + } + } + + int numberMatching = 0; + + for (int i = 0; i < inventory.getSizeInventory(); i++) + { + if (!canBeInserted[i]) + { + continue; + } + + ItemStack invStack = inventory.getStackInSlot(i); + + if (invStack != null && canCombine(stack, invStack)) + { + numberMatching += invStack.stackSize; + } + } + + if (numberMatching >= limit) + { + return stack; + } + + int newLimit = limit - numberMatching; + + for (int i = 0; i < inventory.getSizeInventory(); i++) + { + if (!canBeInserted[i]) + { + continue; + } + + int prevStackSize = stack.stackSize; + + ItemStack[] combinedStacks = combineStacks(stack, inventory.getStackInSlot(i), newLimit); + stack = combinedStacks[0]; + inventory.setInventorySlotContents(i, combinedStacks[1]); + + newLimit -= (prevStackSize - stack.stackSize); + + if (newLimit <= 0 || stack.stackSize <= 0) + { + return stack; + } + } + + return stack; + } }