Ritual reimplementation

Reimplemented the following rituals:
	- Resonance of the Faceted Crystal
	- Crack of the Fractured Crystal
	- Reap of the Harvest Moon
This commit is contained in:
WayofTime 2020-11-26 13:32:56 -05:00
parent 907a0f27e7
commit e312e3d854
13 changed files with 955 additions and 4 deletions

View file

@ -2,6 +2,15 @@
Version 3.0.1
------------------------------------------------------
Reimplemented the following rituals:
- Resonance of the Faceted Crystal
- Crack of the Fractured Crystal
- Reap of the Harvest Moon
------------------------------------------------------
Version 3.0.1
------------------------------------------------------
- Reimplemented the Incense Altar with all appropriate blocks.
- Added guide entries for the Incense Altar and Blood Altar. Other misc entries added, too.
- Fixed a server-related crash on the client on the Sigil of the Green Grove.

View file

@ -55,6 +55,7 @@ import wayoftime.bloodmagic.impl.BloodMagicAPI;
import wayoftime.bloodmagic.impl.BloodMagicCorePlugin;
import wayoftime.bloodmagic.network.BloodMagicPacketHandler;
import wayoftime.bloodmagic.potion.BloodMagicPotions;
import wayoftime.bloodmagic.ritual.ModRituals;
import wayoftime.bloodmagic.ritual.RitualManager;
import wayoftime.bloodmagic.structures.ModDungeons;
import wayoftime.bloodmagic.tile.TileAlchemicalReactionChamber;
@ -163,6 +164,7 @@ public class BloodMagic
OrbRegistry.tierMap.put(BloodMagicItems.ORB_MASTER.get().getTier(), new ItemStack(BloodMagicItems.MASTER_BLOOD_ORB.get()));
BloodMagicCorePlugin.INSTANCE.register(BloodMagicAPI.INSTANCE);
RITUAL_MANAGER.discover();
ModRituals.initHarvestHandlers();
}
public void registerTileEntityTypes(RegistryEvent.Register<TileEntityType<?>> event)

View file

@ -159,6 +159,9 @@ public class GeneratorLanguage extends LanguageProvider
add("ritual.bloodmagic.upgradeRemoveRitual", "Sound of the Cleansing Soul");
add("ritual.bloodmagic.armourEvolveRitual", "Ritual of Living Evolution");
add("ritual.bloodmagic.animalGrowthRitual", "Ritual of the Shepherd");
add("ritual.bloodmagic.crystalHarvestRitual", "Crack of the Fractured Crystal");
add("ritual.bloodmagic.forsakenSoulRitual", "Gathering of the Forsaken Souls");
add("ritual.bloodmagic.crystalSplitRitual", "Resonance of the Faceted Crystal");
add("ritual.bloodmagic.cobblestoneRitual", "Le Vulcanos Frigius");
add("ritual.bloodmagic.placerRitual", "The Filler");

View file

@ -62,7 +62,7 @@ public class ItemSentientScythe extends HoeItem implements IDemonWillWeapon, IMu
{
public static int[] soulBracket = new int[] { 16, 60, 200, 400, 1000 };
public static double[] defaultDamageAdded = new double[] { 0.5, 1, 1.5, 2, 2.5 };
public static double[] destructiveDamageAdded = new double[] { 2, 3, 4, 5, 6 };
public static double[] destructiveDamageAdded = new double[] { 1, 1.5, 2, 2.5, 3 };
public static double[] vengefulDamageAdded = new double[] { 0, 0.5, 1, 1.5, 2 };
public static double[] steadfastDamageAdded = new double[] { 0, 0.5, 1, 1.5, 2 };
public static double[] defaultDigSpeedAdded = new double[] { 1, 1.5, 2, 3, 4 };
@ -296,8 +296,6 @@ public class ItemSentientScythe extends HoeItem implements IDemonWillWeapon, IMu
continue;
}
if (!net.minecraftforge.common.ForgeHooks.onPlayerAttackTarget(attacker, targetEntity))
continue;
if (targetEntity.canBeAttackedWithItem())
{
if (!targetEntity.hitByEntity(attacker))
@ -447,6 +445,8 @@ public class ItemSentientScythe extends HoeItem implements IDemonWillWeapon, IMu
int k = (int) ((double) f5 * 0.5D);
((ServerWorld) attacker.world).spawnParticle(ParticleTypes.DAMAGE_INDICATOR, targetEntity.getPosX(), targetEntity.getPosYHeight(0.5D), targetEntity.getPosZ(), k, 0.1D, 0.0D, 0.1D, 0.2D);
}
applyEffectToEntity(type, willBracket, (LivingEntity) targetEntity, attacker);
}
} else
@ -506,7 +506,7 @@ public class ItemSentientScythe extends HoeItem implements IDemonWillWeapon, IMu
if (!target.isAlive())
{
float absorption = attacker.getAbsorptionAmount();
attacker.addPotionEffect(new EffectInstance(Effects.ABSORPTION, absorptionTime[willBracket], 127));
attacker.addPotionEffect(new EffectInstance(Effects.ABSORPTION, absorptionTime[willBracket], 127, true, false));
attacker.setAbsorptionAmount((float) Math.min(absorption + target.getMaxHealth() * 0.05f, maxAbsorptionHearts));
}
break;

View file

@ -0,0 +1,26 @@
package wayoftime.bloodmagic.ritual;
import net.minecraft.block.Blocks;
import wayoftime.bloodmagic.ritual.harvest.HarvestHandlerPlantable;
import wayoftime.bloodmagic.ritual.harvest.HarvestHandlerStem;
import wayoftime.bloodmagic.ritual.harvest.HarvestHandlerTall;
import wayoftime.bloodmagic.ritual.harvest.HarvestRegistry;
public class ModRituals
{
public static void initHarvestHandlers()
{
HarvestRegistry.registerRangeAmplifier(Blocks.DIAMOND_BLOCK.getDefaultState(), 15);
HarvestRegistry.registerRangeAmplifier(Blocks.GOLD_BLOCK.getDefaultState(), 10);
HarvestRegistry.registerRangeAmplifier(Blocks.IRON_BLOCK.getDefaultState(), 6);
HarvestRegistry.registerHandler(new HarvestHandlerPlantable());
HarvestRegistry.registerHandler(new HarvestHandlerTall());
HarvestRegistry.registerHandler(new HarvestHandlerStem());
}
//
// public static void initCuttingFluids() {
// CrushingRegistry.registerCuttingFluid(new CrushingHandlerCuttingFluid(ItemCuttingFluid.FluidType.BASIC.getStack(), 250, 0.5));
// CrushingRegistry.registerCuttingFluid(new CrushingHandlerCuttingFluid(ItemCuttingFluid.FluidType.EXPLOSIVE.getStack(), 25, 0.05));
// }
}

View file

@ -0,0 +1,152 @@
package wayoftime.bloodmagic.ritual.harvest;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.CropsBlock;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.loot.LootContext;
import net.minecraft.loot.LootParameters;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.registries.ForgeRegistries;
import wayoftime.bloodmagic.util.BMLog;
/**
* Harvest handler for standard plantable crops such as Wheat, Potatoes, and
* Netherwart. <br>
* Register a new crop for this handler with
* {@link HarvestRegistry#registerStandardCrop(Block, int)}
*/
public class HarvestHandlerPlantable implements IHarvestHandler
{
private static final ItemStack mockHoe = new ItemStack(Items.DIAMOND_HOE, 1);
public HarvestHandlerPlantable()
{
HarvestRegistry.registerStandardCrop(Blocks.CARROTS, 7);
HarvestRegistry.registerStandardCrop(Blocks.WHEAT, 7);
HarvestRegistry.registerStandardCrop(Blocks.POTATOES, 7);
HarvestRegistry.registerStandardCrop(Blocks.BEETROOTS, 3);
HarvestRegistry.registerStandardCrop(Blocks.NETHER_WART, 3);
addThirdPartyCrop("actuallyadditions", "blockFlax", 7);
addThirdPartyCrop("actuallyadditions", "blockCanola", 7);
addThirdPartyCrop("actuallyadditions", "blockRice", 7);
addThirdPartyCrop("extrautils2", "redorchid", 6);
addThirdPartyCrop("extrautils2", "enderlily", 7);
addThirdPartyCrop("roots", "moonglow", 7);
addThirdPartyCrop("roots", "terra_moss", 7);
addThirdPartyCrop("roots", "pereskia", 7);
addThirdPartyCrop("roots", "wildroot", 7);
addThirdPartyCrop("roots", "aubergine", 7);
addThirdPartyCrop("roots", "spirit_herb", 7);
addPamCrops();
}
@Override
public boolean harvest(World world, BlockPos pos, BlockState state, List<ItemStack> drops)
{
// NonNullList<ItemStack> blockDrops = NonNullList.create();
// state.getBlock().getDrops(blockDrops, world, pos, state, 0);
boolean foundSeed = false;
LootContext.Builder lootBuilder = new LootContext.Builder((ServerWorld) world);
Vector3d blockCenter = new Vector3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5);
List<ItemStack> blockDrops = state.getDrops(lootBuilder.withParameter(LootParameters.field_237457_g_, blockCenter).withParameter(LootParameters.TOOL, mockHoe));
// System.out.println("Size of list: " + blockDrops.size());
for (ItemStack stack : blockDrops)
{
if (stack.isEmpty())
continue;
// This hurts my soul.
if (stack.getItem() instanceof BlockItem && ((BlockItem) stack.getItem()).getBlock() == state.getBlock())
{
stack.shrink(1);
foundSeed = true;
break;
}
}
// System.out.println("Found seed: " + foundSeed);
if (foundSeed)
{
world.setBlockState(pos, state.getBlock().getDefaultState());
world.playEvent(2001, pos, Block.getStateId(state));
for (ItemStack stack : blockDrops)
{
if (stack.isEmpty())
continue;
drops.add(stack);
}
return true;
}
return false;
}
@Override
public boolean test(World world, BlockPos pos, BlockState state)
{
// state.hasProperty(null);
return HarvestRegistry.getStandardCrops().containsKey(state.getBlock()) && state.getBlock() instanceof CropsBlock && ((CropsBlock) state.getBlock()).isMaxAge(state);
// return HarvestRegistry.getStandardCrops().containsKey(state.getBlock()) && state.getBlock().getMetaFromState(state) == HarvestRegistry.getStandardCrops().get(state.getBlock());
}
private static void addThirdPartyCrop(String modid, String regName, int matureMeta)
{
if (!ModList.get().isLoaded(modid))
return;
Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(modid, regName));
if (block != null && block != Blocks.AIR)
HarvestRegistry.registerStandardCrop(block, matureMeta);
}
private static void addPamCrops()
{
if (!ModList.get().isLoaded("harvestcraft"))
return;
try
{
Class<?> pamRegistry = Class.forName("com.pam.harvestcraft.blocks.CropRegistry");
Field names = pamRegistry.getDeclaredField("cropNames");
Method getCrop = pamRegistry.getMethod("getCrop", String.class);
for (String name : (String[]) names.get(null))
{
CropsBlock crop = (CropsBlock) getCrop.invoke(null, name);
HarvestRegistry.registerStandardCrop(crop, crop.getMaxAge());
}
} catch (ClassNotFoundException e)
{
BMLog.DEFAULT.error("HarvestCraft integration cancelled; unable to find registry class");
} catch (NoSuchMethodException | NoSuchFieldException e)
{
BMLog.DEFAULT.error("HarvestCraft integration cancelled; unable to find crop name mapper");
} catch (IllegalAccessException | InvocationTargetException e)
{
BMLog.DEFAULT.error("HarvestCraft integration cancelled; crop name lookup broke");
}
}
}

View file

@ -0,0 +1,72 @@
package wayoftime.bloodmagic.ritual.harvest;
import java.util.Collection;
import java.util.List;
import net.minecraft.block.AttachedStemBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.loot.LootContext;
import net.minecraft.loot.LootParameters;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
/**
* Harvest handler for crops with stems such as Pumpkins and Melons. Rotation
* based crop blocks are a good reason to use this (see pumpkins). <br>
* Register a new crop for this handler with
* {@link HarvestRegistry#registerStemCrop(BlockState, BlockState)}
*/
public class HarvestHandlerStem implements IHarvestHandler
{
private static final ItemStack mockHoe = new ItemStack(Items.DIAMOND_HOE, 1);
public HarvestHandlerStem()
{
for (int i = 0; i < 4; i++)
{
Direction facing = Direction.byHorizontalIndex(i);
HarvestRegistry.registerStemCrop(Blocks.PUMPKIN.getDefaultState(), Blocks.ATTACHED_PUMPKIN_STEM.getDefaultState().with(AttachedStemBlock.FACING, facing));
HarvestRegistry.registerStemCrop(Blocks.MELON.getDefaultState(), Blocks.ATTACHED_MELON_STEM.getDefaultState().with(AttachedStemBlock.FACING, facing));
}
}
@Override
public boolean harvest(World world, BlockPos pos, BlockState state, List<ItemStack> drops)
{
Direction cropDir = state.get(AttachedStemBlock.FACING);
if (cropDir != Direction.UP)
{
BlockPos cropPos = pos.offset(cropDir);
BlockState probableCrop = world.getBlockState(cropPos);
Collection<BlockState> registeredCrops = HarvestRegistry.getStemCrops().get(state);
for (BlockState registeredCrop : registeredCrops)
{
if (registeredCrop == probableCrop)
{
LootContext.Builder lootBuilder = new LootContext.Builder((ServerWorld) world);
Vector3d blockCenter = new Vector3d(cropPos.getX() + 0.5, cropPos.getY() + 0.5, cropPos.getZ() + 0.5);
List<ItemStack> blockDrops = registeredCrop.getDrops(lootBuilder.withParameter(LootParameters.field_237457_g_, blockCenter).withParameter(LootParameters.TOOL, mockHoe));
drops.addAll(blockDrops);
world.destroyBlock(cropPos, false);
return true;
}
}
}
return false;
}
@Override
public boolean test(World world, BlockPos pos, BlockState state)
{
return HarvestRegistry.getStemCrops().containsKey(state);
}
}

View file

@ -0,0 +1,59 @@
package wayoftime.bloodmagic.ritual.harvest;
import java.util.List;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.CactusBlock;
import net.minecraft.block.SugarCaneBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.loot.LootContext;
import net.minecraft.loot.LootParameters;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
/**
* Harvest handler for crops that grow vertically such as Sugar Cane and Cactus.
* <br>
* Register a new crop for this handler with
* {@link HarvestRegistry#registerTallCrop(BlockState)}
*/
public class HarvestHandlerTall implements IHarvestHandler
{
private static final ItemStack mockHoe = new ItemStack(Items.DIAMOND_HOE, 1);
public HarvestHandlerTall()
{
for (int i = 0; i < 15; i++)
{
HarvestRegistry.registerTallCrop(Blocks.SUGAR_CANE.getDefaultState().with(SugarCaneBlock.AGE, i));
HarvestRegistry.registerTallCrop(Blocks.CACTUS.getDefaultState().with(CactusBlock.AGE, i));
}
}
@Override
public boolean harvest(World world, BlockPos pos, BlockState state, List<ItemStack> drops)
{
BlockState up = world.getBlockState(pos.up());
if (up.getBlock() == state.getBlock())
{
LootContext.Builder lootBuilder = new LootContext.Builder((ServerWorld) world);
Vector3d blockCenter = new Vector3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5);
List<ItemStack> blockDrops = state.getDrops(lootBuilder.withParameter(LootParameters.field_237457_g_, blockCenter).withParameter(LootParameters.TOOL, mockHoe));
drops.addAll(blockDrops);
world.destroyBlock(pos.up(), false);
return true;
}
return false;
}
@Override
public boolean test(World world, BlockPos pos, BlockState state)
{
return HarvestRegistry.getTallCrops().contains(state);
}
}

View file

@ -0,0 +1,125 @@
package wayoftime.bloodmagic.ritual.harvest;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import net.minecraft.block.AttachedStemBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.StemBlock;
public class HarvestRegistry
{
private static final List<IHarvestHandler> HARVEST_HANDLERS = Lists.newArrayList();
private static final Map<Block, Integer> STANDARD_CROPS = Maps.newHashMap();
private static final Set<BlockState> TALL_CROPS = Sets.newHashSet();
private static final Multimap<BlockState, BlockState> STEM_CROPS = ArrayListMultimap.create();
private static final Map<BlockState, Integer> AMPLIFIERS = Maps.newHashMap();
/**
* Registers a handler for the Harvest Ritual to call.
*
* @param handler - The custom handler to register
*/
public static void registerHandler(IHarvestHandler handler)
{
if (!HARVEST_HANDLERS.contains(handler))
HARVEST_HANDLERS.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 (!STANDARD_CROPS.containsKey(crop))
STANDARD_CROPS.put(crop, matureMeta);
}
/**
* Registers a tall crop (Sugar Cane and Cactus) for the
* {@link WayofTime.bloodmagic.ritual.harvest.HarvestHandlerTall} handler to
* handle.
*
* @param crop - The crop block to handle.
*/
public static void registerTallCrop(BlockState crop)
{
if (!TALL_CROPS.contains(crop))
TALL_CROPS.add(crop);
}
/**
* Registers a stem crop (Melon and Pumpkin) for the
* {@link WayofTime.bloodmagic.ritual.harvest.HarvestHandlerStem} handler to
* handle.
* <p>
* Use {@link net.minecraftforge.oredict.OreDictionary#WILDCARD_VALUE} to accept
* any meta for the crop block.
* <p>
* The Stem must be instanceof {@link StemBlock}
*
* @param crop - The crop block to handle.
* @param stem - The stem of the crop
*/
public static void registerStemCrop(BlockState crop, BlockState stem)
{
if (!STEM_CROPS.containsKey(crop) && stem.getBlock() instanceof AttachedStemBlock)
STEM_CROPS.put(stem, crop);
}
/**
* Registers a range amplifier for the Harvest Ritual.
*
* @param block - The block for the amplifier.
* @param range - The range the amplifier provides.
*/
public static void registerRangeAmplifier(BlockState block, int range)
{
if (!AMPLIFIERS.containsKey(block))
AMPLIFIERS.put(block, range);
}
public static List<IHarvestHandler> getHarvestHandlers()
{
return ImmutableList.copyOf(HARVEST_HANDLERS);
}
public static Map<Block, Integer> getStandardCrops()
{
return ImmutableMap.copyOf(STANDARD_CROPS);
}
public static Set<BlockState> getTallCrops()
{
return ImmutableSet.copyOf(TALL_CROPS);
}
public static Multimap<BlockState, BlockState> getStemCrops()
{
return ImmutableMultimap.copyOf(STEM_CROPS);
}
public static Map<BlockState, Integer> getAmplifiers()
{
return ImmutableMap.copyOf(AMPLIFIERS);
}
}

View file

@ -0,0 +1,39 @@
package wayoftime.bloodmagic.ritual.harvest;
import java.util.List;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.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. <br>
* Use this to break the block and plant a new one. <br>
* Add the items to be dropped to the drops list. <br>
*
* @param world - The world
* @param pos - The position of the {@link BlockState} being checked
* @param state - The {@link BlockState} being checked
* @param drops - The items to be dropped
* @return If the block was successfully harvested.
*/
boolean harvest(World world, BlockPos pos, BlockState state, List<ItemStack> drops);
/**
* Tests to see if the block is valid for harvest.
*
* @param world The world
* @param pos The position in the world of the {@link BlockState} being
* checked
* @param state The {@link BlockState} being checked
* @return if this block is valid for harvest.
*/
boolean test(World world, BlockPos pos, BlockState state);
}

View file

@ -0,0 +1,104 @@
package wayoftime.bloodmagic.ritual.types;
import java.util.function.Consumer;
import net.minecraft.block.BlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.ritual.AreaDescriptor;
import wayoftime.bloodmagic.ritual.EnumRuneType;
import wayoftime.bloodmagic.ritual.IMasterRitualStone;
import wayoftime.bloodmagic.ritual.Ritual;
import wayoftime.bloodmagic.ritual.RitualComponent;
import wayoftime.bloodmagic.ritual.RitualRegister;
import wayoftime.bloodmagic.tile.TileDemonCrystal;
@RitualRegister("crystal_harvest")
public class RitualCrystalHarvest extends Ritual
{
public static final String CRYSTAL_RANGE = "crystal";
public RitualCrystalHarvest()
{
super("ritualCrystalHarvest", 0, 40000, "ritual." + BloodMagic.MODID + ".crystalHarvestRitual");
addBlockRange(CRYSTAL_RANGE, new AreaDescriptor.Rectangle(new BlockPos(-3, 2, -3), 7, 5, 7));
setMaximumVolumeAndDistanceOfRange(CRYSTAL_RANGE, 250, 5, 7);
}
@Override
public void performRitual(IMasterRitualStone masterRitualStone)
{
World world = masterRitualStone.getWorldObj();
int currentEssence = masterRitualStone.getOwnerNetwork().getCurrentEssence();
BlockPos pos = masterRitualStone.getBlockPos();
if (currentEssence < getRefreshCost())
{
masterRitualStone.getOwnerNetwork().causeNausea();
return;
}
int maxEffects = 1;
int totalEffects = 0;
AreaDescriptor crystalRange = masterRitualStone.getBlockRange(CRYSTAL_RANGE);
crystalRange.resetIterator();
while (crystalRange.hasNext())
{
BlockPos nextPos = crystalRange.next().add(pos);
TileEntity tile = world.getTileEntity(nextPos);
if (tile instanceof TileDemonCrystal)
{
TileDemonCrystal demonCrystal = (TileDemonCrystal) tile;
if (demonCrystal.dropSingleCrystal())
{
BlockState state = world.getBlockState(nextPos);
world.notifyBlockUpdate(nextPos, state, state, 3);
totalEffects++;
if (totalEffects >= maxEffects)
{
break;
}
}
}
}
masterRitualStone.getOwnerNetwork().syphon(masterRitualStone.ticket(getRefreshCost() * totalEffects));
}
@Override
public int getRefreshTime()
{
return 25;
}
@Override
public int getRefreshCost()
{
return 50;
}
@Override
public void gatherComponents(Consumer<RitualComponent> components)
{
addCornerRunes(components, 1, 0, EnumRuneType.AIR);
addParallelRunes(components, 1, 1, EnumRuneType.DUSK);
addParallelRunes(components, 1, -1, EnumRuneType.FIRE);
addParallelRunes(components, 2, -1, EnumRuneType.FIRE);
addParallelRunes(components, 3, -1, EnumRuneType.FIRE);
addOffsetRunes(components, 3, 1, -1, EnumRuneType.FIRE);
addCornerRunes(components, 3, -1, EnumRuneType.EARTH);
addCornerRunes(components, 3, 0, EnumRuneType.EARTH);
addOffsetRunes(components, 3, 2, 0, EnumRuneType.DUSK);
}
@Override
public Ritual getNewCopy()
{
return new RitualCrystalHarvest();
}
}

View file

@ -0,0 +1,215 @@
package wayoftime.bloodmagic.ritual.types;
import java.util.function.Consumer;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.api.compat.EnumDemonWillType;
import wayoftime.bloodmagic.common.block.BloodMagicBlocks;
import wayoftime.bloodmagic.ritual.EnumRuneType;
import wayoftime.bloodmagic.ritual.IMasterRitualStone;
import wayoftime.bloodmagic.ritual.Ritual;
import wayoftime.bloodmagic.ritual.RitualComponent;
import wayoftime.bloodmagic.ritual.RitualRegister;
import wayoftime.bloodmagic.tile.TileDemonCrystal;
@RitualRegister("crystal_split")
public class RitualCrystalSplit extends Ritual
{
public RitualCrystalSplit()
{
super("ritualCrystalSplit", 0, 20000, "ritual." + BloodMagic.MODID + ".crystalSplitRitual");
}
@Override
public void performRitual(IMasterRitualStone masterRitualStone)
{
World world = masterRitualStone.getWorldObj();
int currentEssence = masterRitualStone.getOwnerNetwork().getCurrentEssence();
if (currentEssence < getRefreshCost())
{
masterRitualStone.getOwnerNetwork().causeNausea();
return;
}
BlockPos pos = masterRitualStone.getBlockPos();
Direction direction = masterRitualStone.getDirection();
BlockPos rawPos = pos.up(2);
TileEntity tile = world.getTileEntity(rawPos);
if (!(tile instanceof TileDemonCrystal) || ((TileDemonCrystal) tile).getWillType() != EnumDemonWillType.DEFAULT)
{
return;
}
BlockState rawState = world.getBlockState(rawPos);
TileDemonCrystal rawTile = (TileDemonCrystal) tile;
if (rawTile.getCrystalCount() >= 5)
{
BlockPos vengefulPos = pos.offset(rotateFacing(Direction.NORTH, direction)).up();
BlockPos corrosivePos = pos.offset(rotateFacing(Direction.EAST, direction)).up();
BlockPos steadfastPos = pos.offset(rotateFacing(Direction.SOUTH, direction)).up();
BlockPos destructivePos = pos.offset(rotateFacing(Direction.WEST, direction)).up();
int vengefulCrystals = 0;
int corrosiveCrystals = 0;
int steadfastCrystals = 0;
int destructiveCrystals = 0;
tile = world.getTileEntity(vengefulPos);
if (tile instanceof TileDemonCrystal && ((TileDemonCrystal) tile).getWillType() == EnumDemonWillType.VENGEFUL && ((TileDemonCrystal) tile).getCrystalCount() < 7)
{
vengefulCrystals = ((TileDemonCrystal) tile).getCrystalCount();
} else if (!(tile instanceof TileDemonCrystal) && world.isAirBlock(vengefulPos))
{
// #donothing, no point setting the crystal to 0 again
} else
{
return;
}
tile = world.getTileEntity(corrosivePos);
if (tile instanceof TileDemonCrystal && ((TileDemonCrystal) tile).getWillType() == EnumDemonWillType.CORROSIVE && ((TileDemonCrystal) tile).getCrystalCount() < 7)
{
corrosiveCrystals = ((TileDemonCrystal) tile).getCrystalCount();
} else if (!(tile instanceof TileDemonCrystal) && world.isAirBlock(corrosivePos))
{
} else
{
return;
}
tile = world.getTileEntity(steadfastPos);
if (tile instanceof TileDemonCrystal && ((TileDemonCrystal) tile).getWillType() == EnumDemonWillType.STEADFAST && ((TileDemonCrystal) tile).getCrystalCount() < 7)
{
steadfastCrystals = ((TileDemonCrystal) tile).getCrystalCount();
} else if (!(tile instanceof TileDemonCrystal) && world.isAirBlock(steadfastPos))
{
} else
{
return;
}
tile = world.getTileEntity(destructivePos);
if (tile instanceof TileDemonCrystal && ((TileDemonCrystal) tile).getWillType() == EnumDemonWillType.DESTRUCTIVE && ((TileDemonCrystal) tile).getCrystalCount() < 7)
{
destructiveCrystals = ((TileDemonCrystal) tile).getCrystalCount();
} else if (!(tile instanceof TileDemonCrystal) && world.isAirBlock(destructivePos))
{
} else
{
return;
}
rawTile.setCrystalCount(rawTile.getCrystalCount() - 4);
growCrystal(world, vengefulPos, EnumDemonWillType.VENGEFUL, vengefulCrystals);
growCrystal(world, corrosivePos, EnumDemonWillType.CORROSIVE, corrosiveCrystals);
growCrystal(world, steadfastPos, EnumDemonWillType.STEADFAST, steadfastCrystals);
growCrystal(world, destructivePos, EnumDemonWillType.DESTRUCTIVE, destructiveCrystals);
rawTile.markDirty();
world.notifyBlockUpdate(rawPos, rawState, rawState, 3);
}
}
public Direction rotateFacing(Direction facing, Direction rotation)
{
switch (rotation)
{
case EAST:
return facing.rotateY();
case SOUTH:
return facing.rotateY().rotateY();
case WEST:
return facing.rotateYCCW();
case NORTH:
default:
return facing;
}
}
public void growCrystal(World world, BlockPos pos, EnumDemonWillType type, int currentCrystalCount)
{
if (currentCrystalCount <= 0)
{
BlockState state;
switch (type)
{
case CORROSIVE:
state = BloodMagicBlocks.CORROSIVE_CRYSTAL_BLOCK.get().getDefaultState();
break;
case DEFAULT:
state = BloodMagicBlocks.RAW_CRYSTAL_BLOCK.get().getDefaultState();
break;
case DESTRUCTIVE:
state = BloodMagicBlocks.DESTRUCTIVE_CRYSTAL_BLOCK.get().getDefaultState();
break;
case STEADFAST:
state = BloodMagicBlocks.STEADFAST_CRYSTAL_BLOCK.get().getDefaultState();
break;
case VENGEFUL:
state = BloodMagicBlocks.VENGEFUL_CRYSTAL_BLOCK.get().getDefaultState();
break;
default:
state = BloodMagicBlocks.RAW_CRYSTAL_BLOCK.get().getDefaultState();
}
world.setBlockState(pos, state, 3);
} else
{
TileDemonCrystal tile = (TileDemonCrystal) world.getTileEntity(pos);
tile.setCrystalCount(currentCrystalCount + 1);
tile.markDirty();
BlockState state = world.getBlockState(pos);
world.notifyBlockUpdate(pos, state, state, 3);
}
}
@Override
public int getRefreshTime()
{
return 20;
}
@Override
public int getRefreshCost()
{
return 1000;
}
@Override
public void gatherComponents(Consumer<RitualComponent> components)
{
addRune(components, 0, 0, -1, EnumRuneType.FIRE);
addRune(components, 1, 0, 0, EnumRuneType.EARTH);
addRune(components, 0, 0, 1, EnumRuneType.WATER);
addRune(components, -1, 0, 0, EnumRuneType.AIR);
this.addOffsetRunes(components, 1, 2, -1, EnumRuneType.DUSK);
this.addCornerRunes(components, 1, 0, EnumRuneType.BLANK);
this.addParallelRunes(components, 2, 0, EnumRuneType.DUSK);
}
@Override
public Ritual getNewCopy()
{
return new RitualCrystalSplit();
}
@Override
public ITextComponent[] provideInformationOfRitualToPlayer(PlayerEntity player)
{
return new ITextComponent[] { new TranslationTextComponent(this.getTranslationKey() + ".info") };
}
}

View file

@ -0,0 +1,145 @@
package wayoftime.bloodmagic.ritual.types;
import java.util.List;
import java.util.function.Consumer;
import com.google.common.collect.Lists;
import net.minecraft.block.BlockState;
import net.minecraft.inventory.InventoryHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.ritual.AreaDescriptor;
import wayoftime.bloodmagic.ritual.EnumRuneType;
import wayoftime.bloodmagic.ritual.IMasterRitualStone;
import wayoftime.bloodmagic.ritual.Ritual;
import wayoftime.bloodmagic.ritual.RitualComponent;
import wayoftime.bloodmagic.ritual.RitualRegister;
import wayoftime.bloodmagic.ritual.harvest.HarvestRegistry;
import wayoftime.bloodmagic.ritual.harvest.IHarvestHandler;
/**
* This ritual uses registered {@link IHarvestHandler}'s to harvest blocks.
* <p>
* To register a new Handler for this ritual use
* {@link HarvestRegistry#registerHandler(IHarvestHandler)}
* <p>
* This ritual includes a way to change the range based on what block is above
* the MasterRitualStone. You can use
* {@link HarvestRegistry#registerRangeAmplifier(BlockState, int)} to register a
* new amplifier.
*/
@RitualRegister("harvest")
public class RitualHarvest extends Ritual
{
public static final String HARVEST_RANGE = "harvestRange";
public RitualHarvest()
{
super("ritualHarvest", 0, 20000, "ritual." + BloodMagic.MODID + ".harvestRitual");
addBlockRange(HARVEST_RANGE, new AreaDescriptor.Rectangle(new BlockPos(-4, 1, -4), 9, 5, 9));
setMaximumVolumeAndDistanceOfRange(HARVEST_RANGE, 0, 15, 15);
}
@Override
public void performRitual(IMasterRitualStone masterRitualStone)
{
World world = masterRitualStone.getWorldObj();
BlockPos pos = masterRitualStone.getBlockPos();
if (masterRitualStone.getOwnerNetwork().getCurrentEssence() < getRefreshCost())
{
masterRitualStone.getOwnerNetwork().causeNausea();
return;
}
int harvested = 0;
AreaDescriptor harvestArea = masterRitualStone.getBlockRange(HARVEST_RANGE);
harvestArea.resetIterator();
while (harvestArea.hasNext())
{
BlockPos nextPos = harvestArea.next().add(pos);
if (harvestBlock(world, nextPos, masterRitualStone.getBlockPos()))
{
harvested++;
}
}
masterRitualStone.getOwnerNetwork().syphon(masterRitualStone.ticket(getRefreshCost() * harvested));
}
@Override
public int getRefreshCost()
{
return 20;
}
@Override
public int getRefreshTime()
{
return 5;
}
@Override
public void gatherComponents(Consumer<RitualComponent> components)
{
addCornerRunes(components, 1, 0, EnumRuneType.DUSK);
addParallelRunes(components, 2, 0, EnumRuneType.EARTH);
addOffsetRunes(components, 3, 1, 0, EnumRuneType.EARTH);
addOffsetRunes(components, 3, 2, 0, EnumRuneType.WATER);
}
@Override
public Ritual getNewCopy()
{
return new RitualHarvest();
}
public static boolean harvestBlock(World world, BlockPos cropPos, BlockPos controllerPos)
{
BlockState harvestState = world.getBlockState(cropPos);
TileEntity potentialInventory = world.getTileEntity(controllerPos.up());
IItemHandler itemHandler = null;
if (potentialInventory != null && potentialInventory.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.DOWN).isPresent())
itemHandler = potentialInventory.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.DOWN).resolve().get();
for (IHarvestHandler handler : HarvestRegistry.getHarvestHandlers())
{
if (handler.test(world, cropPos, harvestState))
{
List<ItemStack> drops = Lists.newArrayList();
if (handler.harvest(world, cropPos, harvestState, drops))
{
for (ItemStack stack : drops)
{
if (stack.isEmpty())
continue;
// TODO I wrote this, but didn't actually think about whether it should be a
// thing. Remove the true if we want to keep it
if (itemHandler == null || true)
InventoryHelper.spawnItemStack(world, cropPos.getX(), cropPos.getY(), cropPos.getZ(), stack);
else
{
ItemStack remainder = ItemHandlerHelper.insertItemStacked(itemHandler, stack, false);
if (!remainder.isEmpty())
InventoryHelper.spawnItemStack(world, cropPos.getX(), cropPos.getY(), cropPos.getZ(), remainder);
}
}
return true;
}
}
}
return false;
}
}