Attempt to fix 1.16.3 branch's issues on the repository

Added the original 'wayoftime' folder back, so see if that fixed the multiple folder issue.
This commit is contained in:
WayofTime 2020-10-29 15:50:03 -04:00
parent 6b4145a67c
commit 9fa68e86ae
224 changed files with 24047 additions and 0 deletions

View file

@ -0,0 +1,654 @@
package wayoftime.bloodmagic.ritual;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.gen.feature.template.PlacementSettings;
import net.minecraft.world.gen.feature.template.Template;
import wayoftime.bloodmagic.util.Constants;
public abstract class AreaDescriptor implements Iterator<BlockPos>
{
public List<BlockPos> getContainedPositions(BlockPos pos)
{
return new ArrayList<>();
}
public AxisAlignedBB getAABB(BlockPos pos)
{
return null;
}
public abstract void resetCache();
public abstract boolean isWithinArea(BlockPos pos);
public abstract void resetIterator();
public void readFromNBT(CompoundNBT tag)
{
}
public void writeToNBT(CompoundNBT tag)
{
}
public abstract AreaDescriptor copy();
public abstract int getVolumeForOffsets(BlockPos offset1, BlockPos offset2);
public abstract boolean isWithinRange(BlockPos offset1, BlockPos offset2, int verticalLimit, int horizontalLimit);
public abstract int getVolume();
public abstract int getHeight();
public abstract boolean isWithinRange(int verticalLimit, int horizontalLimit);
/**
* This method changes the area descriptor so that its range matches the two
* blocks that are selected. When implementing this method, assume that these
* positions are the blocks that are clicked by the player.
*
* @param pos1
* @param pos2
*/
public abstract void modifyAreaByBlockPositions(BlockPos pos1, BlockPos pos2);
public abstract boolean intersects(AreaDescriptor descriptor);
public abstract AreaDescriptor offset(BlockPos offset);
public abstract AreaDescriptor rotateDescriptor(PlacementSettings settings);
public static class Rectangle extends AreaDescriptor
{
protected BlockPos minimumOffset;
protected BlockPos maximumOffset; // Non-inclusive maximum offset.
private BlockPos currentPosition;
private ArrayList<BlockPos> blockPosCache;
private BlockPos cachedPosition;
private boolean cache = true;
/**
* This constructor takes in the minimum and maximum BlockPos. The maximum
* offset is non-inclusive, meaning if you pass in (0,0,0) and (1,1,1), calling
* getContainedPositions() will only give (0,0,0).
*
* @param minimumOffset -
* @param maximumOffset -
*/
public Rectangle(BlockPos minimumOffset, BlockPos maximumOffset)
{
setOffsets(minimumOffset, maximumOffset);
}
public Rectangle(BlockPos minimumOffset, int sizeX, int sizeY, int sizeZ)
{
this(minimumOffset, minimumOffset.add(sizeX, sizeY, sizeZ));
}
public Rectangle(BlockPos minimumOffset, int size)
{
this(minimumOffset, size, size, size);
}
public Rectangle(AreaDescriptor.Rectangle rectangle)
{
this(rectangle.minimumOffset, rectangle.maximumOffset);
}
public AreaDescriptor.Rectangle copy()
{
return new AreaDescriptor.Rectangle(this);
}
@Override
public List<BlockPos> getContainedPositions(BlockPos pos)
{
if (!cache || !pos.equals(cachedPosition) || blockPosCache.isEmpty())
{
ArrayList<BlockPos> posList = new ArrayList<>();
for (int j = minimumOffset.getY(); j < maximumOffset.getY(); j++)
{
for (int i = minimumOffset.getX(); i < maximumOffset.getX(); i++)
{
for (int k = minimumOffset.getZ(); k < maximumOffset.getZ(); k++)
{
posList.add(pos.add(i, j, k));
}
}
}
blockPosCache = posList;
cachedPosition = pos;
}
return Collections.unmodifiableList(blockPosCache);
}
@Override
public AxisAlignedBB getAABB(BlockPos pos)
{
AxisAlignedBB tempAABB = new AxisAlignedBB(minimumOffset, maximumOffset);
return tempAABB.offset(pos.getX(), pos.getY(), pos.getZ());
}
@Override
public int getHeight()
{
return this.maximumOffset.getY() - this.minimumOffset.getY();
}
public BlockPos getMinimumOffset()
{
return minimumOffset;
}
public BlockPos getMaximumOffset()
{
return maximumOffset;
}
/**
* Sets the offsets of the AreaDescriptor in a safe way that will make
* minimumOffset the lowest corner
*
* @param offset1 -
* @param offset2 -
*/
public void setOffsets(BlockPos offset1, BlockPos offset2)
{
this.minimumOffset = new BlockPos(Math.min(offset1.getX(), offset2.getX()), Math.min(offset1.getY(), offset2.getY()), Math.min(offset1.getZ(), offset2.getZ()));
this.maximumOffset = new BlockPos(Math.max(offset1.getX(), offset2.getX()), Math.max(offset1.getY(), offset2.getY()), Math.max(offset1.getZ(), offset2.getZ()));
blockPosCache = new ArrayList<>();
}
@Override
public void resetCache()
{
this.blockPosCache = new ArrayList<>();
}
@Override
public boolean isWithinArea(BlockPos pos)
{
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
return x >= minimumOffset.getX() && x < maximumOffset.getX() && y >= minimumOffset.getY()
&& y < maximumOffset.getY() && z >= minimumOffset.getZ() && z < maximumOffset.getZ();
}
@Override
public boolean hasNext()
{
return currentPosition == null || !(currentPosition.getX() + 1 == maximumOffset.getX()
&& currentPosition.getY() + 1 == maximumOffset.getY()
&& currentPosition.getZ() + 1 == maximumOffset.getZ());
}
@Override
public BlockPos next()
{
if (currentPosition != null)
{
int nextX = currentPosition.getX() + 1 >= maximumOffset.getX() ? minimumOffset.getX()
: currentPosition.getX() + 1;
int nextZ = nextX != minimumOffset.getX() ? currentPosition.getZ()
: (currentPosition.getZ() + 1 >= maximumOffset.getZ() ? minimumOffset.getZ()
: currentPosition.getZ() + 1);
int nextY = (nextZ != minimumOffset.getZ() || nextX != minimumOffset.getX()) ? currentPosition.getY()
: (currentPosition.getY() + 1);
currentPosition = new BlockPos(nextX, nextY, nextZ);
} else
{
currentPosition = minimumOffset;
}
return currentPosition;
}
@Override
public void remove()
{
}
@Override
public void resetIterator()
{
currentPosition = null;
}
@Override
public void modifyAreaByBlockPositions(BlockPos pos1, BlockPos pos2)
{
setOffsets(pos1, pos2);
maximumOffset = maximumOffset.add(1, 1, 1);
resetIterator();
resetCache();
}
@Override
public void readFromNBT(CompoundNBT tag)
{
minimumOffset = new BlockPos(tag.getInt(Constants.NBT.X_COORD + "min"), tag.getInt(Constants.NBT.Y_COORD + "min"), tag.getInt(Constants.NBT.Z_COORD + "min"));
maximumOffset = new BlockPos(tag.getInt(Constants.NBT.X_COORD + "max"), tag.getInt(Constants.NBT.Y_COORD + "max"), tag.getInt(Constants.NBT.Z_COORD + "max"));
}
@Override
public void writeToNBT(CompoundNBT tag)
{
tag.putInt(Constants.NBT.X_COORD + "min", minimumOffset.getX());
tag.putInt(Constants.NBT.Y_COORD + "min", minimumOffset.getY());
tag.putInt(Constants.NBT.Z_COORD + "min", minimumOffset.getZ());
tag.putInt(Constants.NBT.X_COORD + "max", maximumOffset.getX());
tag.putInt(Constants.NBT.Y_COORD + "max", maximumOffset.getY());
tag.putInt(Constants.NBT.Z_COORD + "max", maximumOffset.getZ());
}
@Override
public int getVolumeForOffsets(BlockPos offset1, BlockPos offset2)
{
BlockPos minPos = new BlockPos(Math.min(offset1.getX(), offset2.getX()), Math.min(offset1.getY(), offset2.getY()), Math.min(offset1.getZ(), offset2.getZ()));
BlockPos maxPos = new BlockPos(Math.max(offset1.getX(), offset2.getX()), Math.max(offset1.getY(), offset2.getY()), Math.max(offset1.getZ(), offset2.getZ()));
maxPos = maxPos.add(1, 1, 1);
return (maxPos.getX() - minPos.getX()) * (maxPos.getY() - minPos.getY()) * (maxPos.getZ() - minPos.getZ());
}
@Override
public boolean isWithinRange(BlockPos offset1, BlockPos offset2, int verticalLimit, int horizontalLimit)
{
BlockPos minPos = new BlockPos(Math.min(offset1.getX(), offset2.getX()), Math.min(offset1.getY(), offset2.getY()), Math.min(offset1.getZ(), offset2.getZ()));
BlockPos maxPos = new BlockPos(Math.max(offset1.getX(), offset2.getX()), Math.max(offset1.getY(), offset2.getY()), Math.max(offset1.getZ(), offset2.getZ()));
return minPos.getY() >= -verticalLimit && maxPos.getY() <= verticalLimit
&& minPos.getX() >= -horizontalLimit && maxPos.getX() <= horizontalLimit
&& minPos.getZ() >= -horizontalLimit && maxPos.getZ() <= horizontalLimit;
}
@Override
public int getVolume()
{
return (maximumOffset.getX() - minimumOffset.getX()) * (maximumOffset.getY() - minimumOffset.getY())
* (maximumOffset.getZ() - minimumOffset.getZ());
}
@Override
public boolean isWithinRange(int verticalLimit, int horizontalLimit)
{
return minimumOffset.getY() >= -verticalLimit && maximumOffset.getY() <= verticalLimit + 1
&& minimumOffset.getX() >= -horizontalLimit && maximumOffset.getX() <= horizontalLimit + 1
&& minimumOffset.getZ() >= -horizontalLimit && maximumOffset.getZ() <= horizontalLimit + 1;
}
@Override
public boolean intersects(AreaDescriptor descriptor)
{
if (descriptor instanceof AreaDescriptor.Rectangle)
{
AreaDescriptor.Rectangle rectangle = (AreaDescriptor.Rectangle) descriptor;
return !(minimumOffset.getX() >= rectangle.maximumOffset.getX()
|| minimumOffset.getY() >= rectangle.maximumOffset.getY()
|| minimumOffset.getZ() >= rectangle.maximumOffset.getZ()
|| rectangle.minimumOffset.getX() >= maximumOffset.getX()
|| rectangle.minimumOffset.getY() >= maximumOffset.getY()
|| rectangle.minimumOffset.getZ() >= maximumOffset.getZ());
}
return false;
}
@Override
public AreaDescriptor offset(BlockPos offset)
{
return new AreaDescriptor.Rectangle(this.minimumOffset.add(offset), this.maximumOffset.add(offset));
}
@Override
public AreaDescriptor rotateDescriptor(PlacementSettings settings)
{
BlockPos rotatePos1 = Template.transformedBlockPos(settings, minimumOffset);
BlockPos rotatePos2 = Template.transformedBlockPos(settings, maximumOffset.add(-1, -1, -1)); // It works,
// shut up!
AreaDescriptor.Rectangle rectangle = new AreaDescriptor.Rectangle(this.minimumOffset, 1);
rectangle.modifyAreaByBlockPositions(rotatePos1, rotatePos2);
return rectangle;
}
}
public static class HemiSphere extends AreaDescriptor
{
private BlockPos minimumOffset;
private int radius;
private ArrayList<BlockPos> blockPosCache;
private BlockPos cachedPosition;
private boolean cache = true;
public HemiSphere(BlockPos minimumOffset, int radius)
{
setRadius(minimumOffset, radius);
}
public HemiSphere(AreaDescriptor.HemiSphere hemiSphere)
{
this(hemiSphere.minimumOffset, hemiSphere.radius);
}
public AreaDescriptor.HemiSphere copy()
{
return new AreaDescriptor.HemiSphere(this);
}
public void setRadius(BlockPos minimumOffset, int radius)
{
this.minimumOffset = new BlockPos(Math.min(minimumOffset.getX(), minimumOffset.getX()), Math.min(minimumOffset.getY(), minimumOffset.getY()), Math.min(minimumOffset.getZ(), minimumOffset.getZ()));
this.radius = radius;
blockPosCache = new ArrayList<>();
}
@Override
public int getHeight()
{
return this.radius * 2;
}
@Override
public List<BlockPos> getContainedPositions(BlockPos pos)
{
if (!cache || !pos.equals(cachedPosition) || blockPosCache.isEmpty())
{
ArrayList<BlockPos> posList = new ArrayList<>();
int i = -radius;
int j = minimumOffset.getY();
int k = -radius;
// TODO For some reason the bottom of the hemisphere is not going up with the
// minOffset
while (i <= radius)
{
while (j <= radius)
{
while (k <= radius)
{
if (i * i + j * j + k * k >= (radius + 0.5F) * (radius + 0.5F))
{
k++;
continue;
}
posList.add(pos.add(i, j, k));
k++;
}
k = -radius;
j++;
}
j = minimumOffset.getY();
i++;
}
blockPosCache = posList;
cachedPosition = pos;
}
return Collections.unmodifiableList(blockPosCache);
}
/**
* Since you can't make a box using a sphere, this returns null
*/
@Override
public AxisAlignedBB getAABB(BlockPos pos)
{
return null;
}
@Override
public void resetCache()
{
this.blockPosCache = new ArrayList<>();
}
@Override
public boolean isWithinArea(BlockPos pos)
{
return blockPosCache.contains(pos);
}
@Override
public boolean hasNext()
{
return false;
}
@Override
public BlockPos next()
{
return null;
}
@Override
public void remove()
{
}
@Override
public void resetIterator()
{
}
@Override
public void modifyAreaByBlockPositions(BlockPos pos1, BlockPos pos2)
{
}
@Override
public int getVolumeForOffsets(BlockPos pos1, BlockPos pos2)
{
return 0;
}
@Override
public boolean isWithinRange(BlockPos offset1, BlockPos offset2, int verticalLimit, int horizontalLimit)
{
return false;
}
@Override
public int getVolume()
{
return 0;
}
@Override
public boolean isWithinRange(int verticalLimit, int horizontalLimit)
{
return false;
}
@Override
public boolean intersects(AreaDescriptor descriptor)
{
return false;
}
@Override
public AreaDescriptor offset(BlockPos offset)
{
return new AreaDescriptor.HemiSphere(minimumOffset.add(offset), radius);
}
@Override
public AreaDescriptor rotateDescriptor(PlacementSettings settings)
{
return this;
}
}
public static class Cross extends AreaDescriptor
{
private ArrayList<BlockPos> blockPosCache;
private BlockPos cachedPosition;
private BlockPos centerPos;
private int size;
private boolean cache = true;
public Cross(BlockPos center, int size)
{
this.centerPos = center;
this.size = size;
this.blockPosCache = new ArrayList<>();
}
public Cross(AreaDescriptor.Cross cross)
{
this(cross.centerPos, cross.size);
}
public AreaDescriptor.Cross copy()
{
return new AreaDescriptor.Cross(this);
}
@Override
public int getHeight()
{
return this.size * 2 + 1;
}
@Override
public List<BlockPos> getContainedPositions(BlockPos pos)
{
if (!cache || !pos.equals(cachedPosition) || blockPosCache.isEmpty())
{
resetCache();
blockPosCache.add(centerPos.add(pos));
for (int i = 1; i <= size; i++)
{
blockPosCache.add(centerPos.add(pos).add(i, 0, 0));
blockPosCache.add(centerPos.add(pos).add(0, 0, i));
blockPosCache.add(centerPos.add(pos).add(-i, 0, 0));
blockPosCache.add(centerPos.add(pos).add(0, 0, -i));
}
}
cachedPosition = pos;
return Collections.unmodifiableList(blockPosCache);
}
@Override
public void resetCache()
{
blockPosCache = new ArrayList<>();
}
@Override
public boolean isWithinArea(BlockPos pos)
{
return blockPosCache.contains(pos);
}
@Override
public boolean hasNext()
{
return false;
}
@Override
public BlockPos next()
{
return null;
}
@Override
public void remove()
{
}
@Override
public void resetIterator()
{
}
@Override
public void modifyAreaByBlockPositions(BlockPos pos1, BlockPos pos2)
{
}
@Override
public int getVolumeForOffsets(BlockPos pos1, BlockPos pos2)
{
return 0;
}
@Override
public boolean isWithinRange(BlockPos offset1, BlockPos offset2, int verticalLimit, int horizontalLimit)
{
return false;
}
@Override
public int getVolume()
{
return 0;
}
@Override
public boolean isWithinRange(int verticalLimit, int horizontalLimit)
{
return false;
}
@Override
public boolean intersects(AreaDescriptor descriptor)
{
return false;
}
@Override
public AreaDescriptor offset(BlockPos offset)
{
return new AreaDescriptor.Cross(centerPos.add(offset), size);
}
@Override
public AreaDescriptor rotateDescriptor(PlacementSettings settings)
{
return this;
}
}
}

View file

@ -0,0 +1,58 @@
package wayoftime.bloodmagic.ritual;
import java.util.concurrent.Callable;
import net.minecraft.nbt.ByteNBT;
import net.minecraft.nbt.INBT;
import net.minecraft.util.Direction;
import net.minecraftforge.common.capabilities.Capability;
public final class CapabilityRuneType
{
public static class RuneTypeStorage implements Capability.IStorage<IRitualStone.Tile>
{
@Override
public INBT writeNBT(Capability<IRitualStone.Tile> capability, IRitualStone.Tile instance, Direction side)
{
return ByteNBT.valueOf((byte) instance.getRuneType().ordinal());
}
@Override
public void readNBT(Capability<IRitualStone.Tile> capability, IRitualStone.Tile instance, Direction side, INBT nbt)
{
instance.setRuneType(EnumRuneType.byMetadata(((ByteNBT) nbt).getByte()));
}
}
public static class RuneTypeWrapper implements IRitualStone.Tile
{
private EnumRuneType type = EnumRuneType.BLANK;
@Override
public boolean isRuneType(EnumRuneType runeType)
{
return type == runeType;
}
@Override
public EnumRuneType getRuneType()
{
return type;
}
public void setRuneType(EnumRuneType runeType)
{
type = runeType;
}
}
public static class Factory implements Callable<IRitualStone.Tile>
{
@Override
public IRitualStone.Tile call()
throws Exception
{
return new RuneTypeWrapper();
}
}
}

View file

@ -0,0 +1,22 @@
package wayoftime.bloodmagic.ritual;
import java.util.Locale;
import net.minecraft.util.IStringSerializable;
public enum EnumReaderBoundaries implements IStringSerializable
{
SUCCESS, VOLUME_TOO_LARGE, NOT_WITHIN_BOUNDARIES;
@Override
public String toString()
{
return name().toLowerCase(Locale.ROOT);
}
@Override
public String getString()
{
return toString();
}
}

View file

@ -0,0 +1,54 @@
package wayoftime.bloodmagic.ritual;
import java.util.Locale;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.text.TextFormatting;
public enum EnumRuneType implements IStringSerializable
{
BLANK(TextFormatting.GRAY),
WATER(TextFormatting.AQUA),
FIRE(TextFormatting.RED),
EARTH(TextFormatting.GREEN),
AIR(TextFormatting.WHITE),
DUSK(TextFormatting.DARK_GRAY),
DAWN(TextFormatting.GOLD);
public final TextFormatting colorCode;
EnumRuneType(TextFormatting colorCode)
{
this.colorCode = colorCode;
}
@Override
public String toString()
{
return name().toLowerCase(Locale.ENGLISH);
}
@Override
public String getString()
{
return this.toString();
}
// @Nonnull
// public ItemStack getStack(int count)
// {
// ItemStack ret = new ItemStack(RegistrarBloodMagicItems.INSCRIPTION_TOOL, count, ordinal());
// CompoundNBT tag = new CompoundNBT();
// tag.putInt(Constants.NBT.USES, 10);
// ret.setTag(tag);
// return ret;
// }
public static EnumRuneType byMetadata(int meta)
{
if (meta < 0 || meta >= values().length)
meta = 0;
return values()[meta];
}
}

View file

@ -0,0 +1,81 @@
package wayoftime.bloodmagic.ritual;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import wayoftime.bloodmagic.core.data.SoulNetwork;
import wayoftime.bloodmagic.core.data.SoulTicket;
import wayoftime.bloodmagic.will.EnumDemonWillType;
/**
* This interface is for internal implementation only.
* <p>
* It is provided via the API for easy obtaining of basic data.
*/
public interface IMasterRitualStone
{
UUID getOwner();
SoulNetwork getOwnerNetwork();
boolean activateRitual(ItemStack activationCrystal, PlayerEntity activator, Ritual ritual);
void performRitual(World world, BlockPos pos);
void stopRitual(Ritual.BreakType breakType);
int getCooldown();
void setCooldown(int cooldown);
boolean isActive();
void setActive(boolean active);
Direction getDirection();
boolean areTanksEmpty();
int getRunningTime();
World getWorldObj();
BlockPos getBlockPos();
String getNextBlockRange(String range);
void provideInformationOfRitualToPlayer(PlayerEntity player);
void provideInformationOfRangeToPlayer(PlayerEntity player, String range);
void provideInformationOfWillConfigToPlayer(PlayerEntity player, List<EnumDemonWillType> typeList);
void setActiveWillConfig(PlayerEntity player, List<EnumDemonWillType> typeList);
EnumReaderBoundaries setBlockRangeByBounds(PlayerEntity player, String range, BlockPos offset1, BlockPos offset2);
List<EnumDemonWillType> getActiveWillConfig();
default SoulTicket ticket(int amount)
{
return SoulTicket.block(getWorldObj(), getBlockPos(), amount);
}
AreaDescriptor getBlockRange(String range);
void addBlockRanges(Map<String, AreaDescriptor> blockRanges);
void addBlockRange(String range, AreaDescriptor defaultRange);
void setBlockRanges(Map<String, AreaDescriptor> blockRanges);
void setBlockRange(String range, AreaDescriptor defaultRange);
Ritual getCurrentRitual();
}

View file

@ -0,0 +1,20 @@
package wayoftime.bloodmagic.ritual;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public interface IRitualStone
{
boolean isRuneType(World world, BlockPos pos, EnumRuneType runeType);
void setRuneType(World world, BlockPos pos, EnumRuneType runeType);
interface Tile
{
boolean isRuneType(EnumRuneType runeType);
EnumRuneType getRuneType();
void setRuneType(EnumRuneType runeType);
}
}

View file

@ -0,0 +1,427 @@
package wayoftime.bloodmagic.ritual;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.function.Consumer;
import org.apache.commons.lang3.builder.ToStringBuilder;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
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.demonaura.WorldDemonWillHandler;
import wayoftime.bloodmagic.will.DemonWillHolder;
import wayoftime.bloodmagic.will.EnumDemonWillType;
/**
* Abstract class for creating new rituals. Register your ritual by annotating
* it with {@link RitualRegister}
*/
public abstract class Ritual
{
protected final Map<String, AreaDescriptor> modableRangeMap = new HashMap<>();
protected final Map<String, Integer> volumeRangeMap = new HashMap<>();
protected final Map<String, Integer> horizontalRangeMap = new HashMap<>();
protected final Map<String, Integer> verticalRangeMap = new HashMap<>();
private final String name;
private final int crystalLevel;
private final int activationCost;
private final RitualRenderer renderer;
private final String unlocalizedName;
public Ritual(String name, int crystalLevel, int activationCost, RitualRenderer renderer, String unlocalizedName)
{
this.name = name;
this.crystalLevel = crystalLevel;
this.activationCost = activationCost;
this.renderer = renderer;
this.unlocalizedName = unlocalizedName;
}
/**
* @param name - The name of the ritual
* @param crystalLevel - Required Activation Crystal tier
* @param activationCost - Base LP cost for activating the ritual
*/
public Ritual(String name, int crystalLevel, int activationCost, String unlocalizedName)
{
this(name, crystalLevel, activationCost, null, unlocalizedName);
}
public void readFromNBT(CompoundNBT tag)
{
ListNBT tags = tag.getList("areas", 10);
if (tags.isEmpty())
{
return;
}
for (int i = 0; i < tags.size(); i++)
{
CompoundNBT newTag = tags.getCompound(i);
String rangeKey = newTag.getString("key");
CompoundNBT storedTag = newTag.getCompound("area");
AreaDescriptor desc = this.getBlockRange(rangeKey);
if (desc != null)
{
desc.readFromNBT(storedTag);
}
}
}
public void writeToNBT(CompoundNBT tag)
{
ListNBT tags = new ListNBT();
for (Entry<String, AreaDescriptor> entry : modableRangeMap.entrySet())
{
CompoundNBT newTag = new CompoundNBT();
newTag.putString("key", entry.getKey());
CompoundNBT storedTag = new CompoundNBT();
entry.getValue().writeToNBT(storedTag);
newTag.put("area", storedTag);
tags.add(newTag);
}
tag.put("areas", tags);
}
/**
* Called when the player attempts to activate the ritual.
* <p>
* {@link WayofTime.bloodmagic.tile.TileMasterRitualStone#activateRitual(ItemStack, PlayerEntity, Ritual)}
*
* @param masterRitualStone - The {@link IMasterRitualStone} that the ritual is
* bound to
* @param player - The activating player
* @param owner - Owner of the crystal activating this ritual, or
* the current owner of the ritual if being
* reactivated.
* @return - Whether activation was successful
*/
public boolean activateRitual(IMasterRitualStone masterRitualStone, PlayerEntity player, UUID owner)
{
return true;
}
/**
* Called every {@link #getRefreshTime()} ticks while active.
* <p>
* {@link WayofTime.bloodmagic.tile.TileMasterRitualStone#performRitual(World, BlockPos)}
*
* @param masterRitualStone - The {@link IMasterRitualStone} that the ritual is
* bound to
*/
public abstract void performRitual(IMasterRitualStone masterRitualStone);
/**
* Called when the ritual is stopped for a given {@link Ritual.BreakType}.
* <p>
* {@link WayofTime.bloodmagic.tile.TileMasterRitualStone#stopRitual(Ritual.BreakType)}
*
* @param masterRitualStone - The {@link IMasterRitualStone} that the ritual is
* bound to
* @param breakType - The type of break that caused the stoppage.
*/
public void stopRitual(IMasterRitualStone masterRitualStone, BreakType breakType)
{
}
/**
* Used to set the amount of LP drained every {@link #getRefreshTime()} ticks.
*
* @return - The amount of LP drained per refresh
*/
public abstract int getRefreshCost();
/**
* Used to set the refresh rate of the ritual. (How often
* {@link #performRitual(IMasterRitualStone)} is called.
*
* @return - How often to perform the effect in ticks.
*/
public int getRefreshTime()
{
return 20;
}
public void addBlockRange(String range, AreaDescriptor defaultRange)
{
modableRangeMap.put(range, defaultRange);
}
/**
* Used to grab the range of a ritual for a given effect.
*
* @param range - Range that needs to be pulled.
* @return -
*/
public AreaDescriptor getBlockRange(String range)
{
if (modableRangeMap.containsKey(range))
{
return modableRangeMap.get(range);
}
return null;
}
public List<String> getListOfRanges()
{
return new ArrayList<>(modableRangeMap.keySet());
}
public String getNextBlockRange(String range)
{
List<String> rangeList = getListOfRanges();
if (rangeList.isEmpty())
{
return "";
}
if (!rangeList.contains(range))
{
return rangeList.get(0);
}
boolean hasMatch = false;
for (String rangeCheck : rangeList)
{
if (hasMatch)
{
return rangeCheck;
} else if (rangeCheck.equals(range))
{
hasMatch = true;
}
}
return rangeList.get(0);
}
public EnumReaderBoundaries canBlockRangeBeModified(String range, AreaDescriptor descriptor, IMasterRitualStone master, BlockPos offset1, BlockPos offset2, DemonWillHolder holder)
{
List<EnumDemonWillType> willConfig = master.getActiveWillConfig();
int maxVolume = getMaxVolumeForRange(range, willConfig, holder);
int maxVertical = getMaxVerticalRadiusForRange(range, willConfig, holder);
int maxHorizontal = getMaxHorizontalRadiusForRange(range, willConfig, holder);
return (maxVolume <= 0 || descriptor.getVolumeForOffsets(offset1, offset2) <= maxVolume)
? descriptor.isWithinRange(offset1, offset2, maxVertical, maxHorizontal) ? EnumReaderBoundaries.SUCCESS
: EnumReaderBoundaries.NOT_WITHIN_BOUNDARIES
: EnumReaderBoundaries.VOLUME_TOO_LARGE;
}
protected void setMaximumVolumeAndDistanceOfRange(String range, int volume, int horizontalRadius, int verticalRadius)
{
volumeRangeMap.put(range, volume);
horizontalRangeMap.put(range, horizontalRadius);
verticalRangeMap.put(range, verticalRadius);
}
protected boolean checkDescriptorIsWithinRange(AreaDescriptor descriptor, int maxVolume, int maxHorizontal, int maxVertical)
{
return descriptor.getVolume() <= maxVolume && descriptor.isWithinRange(maxVertical, maxHorizontal);
}
public int getMaxVolumeForRange(String range, List<EnumDemonWillType> activeTypes, DemonWillHolder holder)
{
return volumeRangeMap.get(range);
}
public int getMaxVerticalRadiusForRange(String range, List<EnumDemonWillType> activeTypes, DemonWillHolder holder)
{
return verticalRangeMap.get(range);
}
public int getMaxHorizontalRadiusForRange(String range, List<EnumDemonWillType> activeTypes, DemonWillHolder holder)
{
return horizontalRangeMap.get(range);
}
public ITextComponent getErrorForBlockRangeOnFail(PlayerEntity player, String range, IMasterRitualStone master, BlockPos offset1, BlockPos offset2)
{
AreaDescriptor descriptor = this.getBlockRange(range);
if (descriptor == null)
{
return new TranslationTextComponent("ritual.bloodmagic.blockRange.tooBig", "?");
}
List<EnumDemonWillType> willConfig = master.getActiveWillConfig();
DemonWillHolder holder = WorldDemonWillHandler.getWillHolder(master.getWorldObj(), master.getBlockPos());
int maxVolume = this.getMaxVolumeForRange(range, willConfig, holder);
int maxVertical = this.getMaxVerticalRadiusForRange(range, willConfig, holder);
int maxHorizontal = this.getMaxHorizontalRadiusForRange(range, willConfig, holder);
if (maxVolume > 0 && descriptor.getVolumeForOffsets(offset1, offset2) > maxVolume)
{
return new TranslationTextComponent("ritual.bloodmagic.blockRange.tooBig", maxVolume);
} else
{
return new TranslationTextComponent("ritual.bloodmagic.blockRange.tooFar", maxVertical, maxHorizontal);
}
}
public ITextComponent[] provideInformationOfRitualToPlayer(PlayerEntity player)
{
return new ITextComponent[]
{ new TranslationTextComponent(this.getTranslationKey() + ".info") };
}
public ITextComponent provideInformationOfRangeToPlayer(PlayerEntity player, String range)
{
if (getListOfRanges().contains(range))
{
return new TranslationTextComponent(this.getTranslationKey() + "." + range + ".info");
} else
{
return new TranslationTextComponent("ritual.bloodmagic.blockRange.noRange");
}
}
public abstract void gatherComponents(Consumer<RitualComponent> components);
protected final void addRune(Consumer<RitualComponent> components, int offset1, int y, int offset2, EnumRuneType rune)
{
components.accept(new RitualComponent(new BlockPos(offset1, y, offset2), rune));
}
protected final void addOffsetRunes(Consumer<RitualComponent> components, int offset1, int offset2, int y, EnumRuneType rune)
{
addRune(components, offset1, y, offset2, rune);
addRune(components, offset2, y, offset1, rune);
addRune(components, offset1, y, -offset2, rune);
addRune(components, -offset2, y, offset1, rune);
addRune(components, -offset1, y, offset2, rune);
addRune(components, offset2, y, -offset1, rune);
addRune(components, -offset1, y, -offset2, rune);
addRune(components, -offset2, y, -offset1, rune);
}
protected final void addCornerRunes(Consumer<RitualComponent> components, int offset, int y, EnumRuneType rune)
{
addRune(components, offset, y, offset, rune);
addRune(components, offset, y, -offset, rune);
addRune(components, -offset, y, -offset, rune);
addRune(components, -offset, y, offset, rune);
}
protected final void addParallelRunes(Consumer<RitualComponent> components, int offset, int y, EnumRuneType rune)
{
addRune(components, offset, y, 0, rune);
addRune(components, -offset, y, 0, rune);
addRune(components, 0, y, -offset, rune);
addRune(components, 0, y, offset, rune);
}
public double getWillRespectingConfig(World world, BlockPos pos, EnumDemonWillType type, List<EnumDemonWillType> willConfig)
{
return willConfig.contains(type) ? WorldDemonWillHandler.getCurrentWill(world, pos, type) : 0;
}
public abstract Ritual getNewCopy();
public String getName()
{
return name;
}
public int getCrystalLevel()
{
return crystalLevel;
}
public int getActivationCost()
{
return activationCost;
}
public RitualRenderer getRenderer()
{
return renderer;
}
public String getTranslationKey()
{
return unlocalizedName;
}
public Map<String, AreaDescriptor> getModableRangeMap()
{
return modableRangeMap;
}
public Map<String, Integer> getVolumeRangeMap()
{
return volumeRangeMap;
}
public Map<String, Integer> getHorizontalRangeMap()
{
return horizontalRangeMap;
}
public Map<String, Integer> getVerticalRangeMap()
{
return verticalRangeMap;
}
@Override
public String toString()
{
return new ToStringBuilder(this).append("name", name).append("crystalLevel", crystalLevel).append("activationCost", activationCost).append("renderer", renderer).append("unlocalizedName", unlocalizedName).append("modableRangeMap", modableRangeMap).append("volumeRangeMap", volumeRangeMap).append("horizontalRangeMap", horizontalRangeMap).append("verticalRangeMap", verticalRangeMap).append("refreshTime", getRefreshTime()).append("listOfRanges", getListOfRanges()).toString();
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof Ritual))
return false;
Ritual ritual = (Ritual) o;
if (crystalLevel != ritual.crystalLevel)
return false;
if (activationCost != ritual.activationCost)
return false;
if (name != null ? !name.equals(ritual.name) : ritual.name != null)
return false;
return unlocalizedName != null ? unlocalizedName.equals(ritual.unlocalizedName)
: ritual.unlocalizedName == null;
}
@Override
public int hashCode()
{
int result = name != null ? name.hashCode() : 0;
result = 31 * result + crystalLevel;
result = 31 * result + activationCost;
result = 31 * result + (unlocalizedName != null ? unlocalizedName.hashCode() : 0);
return result;
}
public enum BreakType
{
REDSTONE, BREAK_MRS, BREAK_STONE, ACTIVATE, DEACTIVATE, EXPLOSION,
}
}

View file

@ -0,0 +1,70 @@
package wayoftime.bloodmagic.ritual;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
/**
* Used to set a {@link EnumRuneType} type to a given {@link BlockPos} for usage
* in Ritual creation.
*/
public class RitualComponent
{
private final BlockPos offset;
private final EnumRuneType runeType;
public RitualComponent(BlockPos offset, EnumRuneType runeType)
{
this.offset = offset;
this.runeType = runeType;
}
public int getX(Direction direction)
{
switch (direction)
{
case EAST:
return -this.getOffset().getZ();
case SOUTH:
return -this.getOffset().getX();
case WEST:
return this.getOffset().getZ();
default:
return this.getOffset().getX();
}
}
public int getY()
{
return this.getOffset().getY();
}
public int getZ(Direction direction)
{
switch (direction)
{
case EAST:
return this.getOffset().getX();
case SOUTH:
return -this.getOffset().getZ();
case WEST:
return -this.getOffset().getX();
default:
return this.getOffset().getZ();
}
}
public BlockPos getOffset(Direction direction)
{
return new BlockPos(getX(direction), offset.getY(), getZ(direction));
}
public BlockPos getOffset()
{
return offset;
}
public EnumRuneType getRuneType()
{
return runeType;
}
}

View file

@ -0,0 +1,177 @@
package wayoftime.bloodmagic.ritual;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.minecraft.block.BlockState;
import net.minecraft.util.DamageSource;
import net.minecraftforge.fml.ModList;
import wayoftime.bloodmagic.ritual.imperfect.ImperfectRitual;
import wayoftime.bloodmagic.util.BMLog;
public class RitualManager
{
public static final DamageSource RITUAL_DAMAGE = new DamageSource("ritual_damage").setDamageBypassesArmor();
private final Map<String, Ritual> rituals;
private final Map<Ritual, String> ritualsReverse;
private final List<Ritual> sortedRituals;
private final Map<String, ImperfectRitual> imperfectRituals;
private final Map<ImperfectRitual, String> imperfectRitualsReverse;
// private final Configuration config;
public RitualManager()
{
this.rituals = Maps.newTreeMap();
this.ritualsReverse = Maps.newHashMap();
this.sortedRituals = Lists.newArrayList();
this.imperfectRituals = Maps.newTreeMap();
this.imperfectRitualsReverse = Maps.newHashMap();
// this.config = config;
}
// public void discover(ASMDataTable dataTable)
public void discover()
{
ModList.get().getAllScanData().forEach(scan -> {
scan.getAnnotations().forEach(a -> {
if (a.getAnnotationType().getClassName().equals(RitualRegister.class.getName()))
{
try
{
Class<?> clazz = Class.forName(a.getClassType().getClassName());
RitualRegister ritualRegister = clazz.getAnnotation(RitualRegister.class);
String id = ritualRegister.value();
if (Ritual.class.isAssignableFrom(clazz))
{
Ritual ritual = (Ritual) clazz.newInstance();
rituals.put(id, ritual);
ritualsReverse.put(ritual, id);
BMLog.DEBUG.info("Registered ritual {}", id);
} else
{
BMLog.DEFAULT.error("Error creating ritual instance for {}.", id);
}
} catch (Exception e)
{
e.printStackTrace();
}
}
});
});
ModList.get().getAllScanData().forEach(scan -> {
scan.getAnnotations().forEach(a -> {
if (a.getAnnotationType().getClassName().equals(RitualRegister.Imperfect.class.getName()))
{
try
{
Class<?> clazz = Class.forName(a.getClassType().getClassName());
RitualRegister.Imperfect ritualRegister = clazz.getAnnotation(RitualRegister.Imperfect.class);
String id = ritualRegister.value();
if (ImperfectRitual.class.isAssignableFrom(clazz))
{
ImperfectRitual ritual = (ImperfectRitual) clazz.newInstance();
imperfectRituals.put(id, ritual);
imperfectRitualsReverse.put(ritual, id);
BMLog.DEBUG.info("Registered imperfect ritual {}", id);
} else
{
BMLog.DEFAULT.error("Error creating imperfect ritual instance for {}.", id);
}
} catch (Exception e)
{
e.printStackTrace();
}
}
});
});
// syncConfig();
// Sort rituals
sortedRituals.addAll(rituals.values());
// Oh dear this is probably so slow
sortedRituals.sort((o1, o2) -> {
Set<RitualComponent> components = Sets.newHashSet();
o1.gatherComponents(components::add);
int initialSize = components.size();
components.clear();
o2.gatherComponents(components::add);
return Integer.compare(initialSize, components.size());
});
}
public Ritual getRitual(String id)
{
return rituals.get(id);
}
public String getId(Ritual ritual)
{
return ritualsReverse.get(ritual);
}
public ImperfectRitual getImperfectRitual(BlockState state)
{
for (ImperfectRitual ritual : imperfectRituals.values()) if (ritual.getBlockRequirement().test(state))
return ritual;
return null;
}
public String getId(ImperfectRitual ritual)
{
return imperfectRitualsReverse.get(ritual);
}
public Collection<Ritual> getRituals()
{
return rituals.values();
}
public Collection<ImperfectRitual> getImperfectRituals()
{
return imperfectRituals.values();
}
public List<Ritual> getSortedRituals()
{
return sortedRituals;
}
// public void syncConfig()
// {
// config.addCustomCategoryComment("rituals", "Toggles for all rituals");
// rituals.forEach((k, v) -> config.getBoolean(k, "rituals", true, "Enable the " + k + " ritual."));
// imperfectRituals.forEach((k, v) -> config.getBoolean(k, "rituals.imperfect", true, "Enable the " + k + " imperfect ritual."));
// config.save();
// }
//
public boolean enabled(String id, boolean imperfect)
{
return id != null;
// return id != null && config.getBoolean(id, "rituals" + (imperfect ? ".imperfect" : ""), true, "");
}
//
// public Configuration getConfig()
// {
// return config;
// }
public static class BadRitualException extends RuntimeException
{
public BadRitualException(String message)
{
super(message);
}
}
}

View file

@ -0,0 +1,58 @@
package wayoftime.bloodmagic.ritual;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.function.Function;
import wayoftime.bloodmagic.ritual.imperfect.ImperfectRitual;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface RitualRegister
{
String value();
Class<? extends Function<Class<? extends Ritual>, Ritual>> factory() default DefaultRitualFactory.class;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Imperfect
{
String value();
Class<? extends Function<Class<? extends ImperfectRitual>, ImperfectRitual>> factory() default DefaultImperfectRitualFactory.class;
}
class DefaultRitualFactory implements Function<Class<? extends Ritual>, Ritual>
{
@Override
public Ritual apply(Class<? extends Ritual> aClass)
{
try
{
return aClass.newInstance();
} catch (Exception e)
{
return null;
}
}
}
class DefaultImperfectRitualFactory implements Function<Class<? extends ImperfectRitual>, ImperfectRitual>
{
@Override
public ImperfectRitual apply(Class<? extends ImperfectRitual> aClass)
{
try
{
return aClass.newInstance();
} catch (Exception e)
{
return null;
}
}
}
}

View file

@ -0,0 +1,14 @@
package wayoftime.bloodmagic.ritual;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
public abstract class RitualRenderer
{
public abstract void renderAt(IMasterRitualStone masterRitualStone, double x, double y, double z);
protected void bindTexture(ResourceLocation resourceLocation)
{
Minecraft.getInstance().getTextureManager().bindTexture(resourceLocation);
}
}

View file

@ -0,0 +1,20 @@
package wayoftime.bloodmagic.ritual.imperfect;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
/**
* This interface is for internal implementation only.
* <p>
* It is provided via the API for easy obtaining of basic data.
*/
public interface IImperfectRitualStone
{
boolean performRitual(World world, BlockPos pos, ImperfectRitual imperfectRitual, PlayerEntity player);
World getRitualWorld();
BlockPos getRitualPos();
}

View file

@ -0,0 +1,108 @@
package wayoftime.bloodmagic.ritual.imperfect;
import java.util.function.Predicate;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.World;
/**
* Abstract class for creating new imperfect rituals. To register, annotate your
* class with {@link WayofTime.bloodmagic.ritual.RitualRegister.Imperfect}
*/
public abstract class ImperfectRitual
{
private final String name;
private final Predicate<BlockState> blockRequirement;
private final int activationCost;
private final boolean lightShow;
private final String unlocalizedName;
public ImperfectRitual(String name, Predicate<BlockState> blockRequirement, int activationCost, boolean lightShow, String unlocalizedName)
{
this.name = name;
this.blockRequirement = blockRequirement;
this.activationCost = activationCost;
this.lightShow = lightShow;
this.unlocalizedName = unlocalizedName;
}
/**
* @param name The name of the ritual
* @param blockRequirement The block required above the ImperfectRitualStone
* @param activationCost Base LP cost for activating the ritual
*/
public ImperfectRitual(String name, Predicate<BlockState> blockRequirement, int activationCost, String unlocalizedName)
{
this(name, blockRequirement, activationCost, false, unlocalizedName);
}
/**
* Called when the player activates the ritual
* {@link WayofTime.bloodmagic.tile.TileImperfectRitualStone#performRitual(World, net.minecraft.util.math.BlockPos, ImperfectRitual, PlayerEntity)}
*
* @param imperfectRitualStone - The {@link IImperfectRitualStone} that the
* ritual is bound to
* @param player - The player activating the ritual
* @return - Whether activation was successful
*/
public abstract boolean onActivate(IImperfectRitualStone imperfectRitualStone, PlayerEntity player);
public String getName()
{
return name;
}
public Predicate<BlockState> getBlockRequirement()
{
return blockRequirement;
}
public int getActivationCost()
{
return activationCost;
}
public boolean isLightShow()
{
return lightShow;
}
public String getTranslationKey()
{
return unlocalizedName;
}
@Override
public String toString()
{
return getName() + "@" + getActivationCost();
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof ImperfectRitual))
return false;
ImperfectRitual that = (ImperfectRitual) o;
if (activationCost != that.activationCost)
return false;
if (name != null ? !name.equals(that.name) : that.name != null)
return false;
return unlocalizedName != null ? unlocalizedName.equals(that.unlocalizedName) : that.unlocalizedName == null;
}
@Override
public int hashCode()
{
int result = name != null ? name.hashCode() : 0;
result = 31 * result + activationCost;
result = 31 * result + (unlocalizedName != null ? unlocalizedName.hashCode() : 0);
return result;
}
}

View file

@ -0,0 +1,360 @@
package wayoftime.bloodmagic.ritual.types;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import com.mojang.authlib.GameProfile;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.loot.LootContext;
import net.minecraft.loot.LootParameters;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.common.util.FakePlayerFactory;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.common.block.BlockMasterRitualStone;
import wayoftime.bloodmagic.demonaura.WorldDemonWillHandler;
import wayoftime.bloodmagic.ritual.AreaDescriptor;
import wayoftime.bloodmagic.ritual.EnumRuneType;
import wayoftime.bloodmagic.ritual.IMasterRitualStone;
import wayoftime.bloodmagic.ritual.IRitualStone;
import wayoftime.bloodmagic.ritual.Ritual;
import wayoftime.bloodmagic.ritual.RitualComponent;
import wayoftime.bloodmagic.ritual.RitualRegister;
import wayoftime.bloodmagic.util.Utils;
import wayoftime.bloodmagic.will.EnumDemonWillType;
@RitualRegister("crushing")
public class RitualCrushing extends Ritual
{
public static final String CRUSHING_RANGE = "crushingRange";
public static final String CHEST_RANGE = "chest";
public static double rawWillDrain = 0.05;
public static double steadfastWillDrain = 0.2;
public static double destructiveWillDrain = 0.2;
public static double vengefulWillDrain = 0.2;
public static Map<ItemStack, Integer> cuttingFluidLPMap = new HashMap<>();
public static Map<ItemStack, Double> cuttingFluidWillMap = new HashMap<>();
public static int defaultRefreshTime = 40;
private FakePlayer fakePlayer;
public int refreshTime = 40;
private static final ItemStack mockPick = new ItemStack(Items.DIAMOND_PICKAXE, 1);
static
{
mockPick.addEnchantment(Enchantments.SILK_TOUCH, 1);
}
public RitualCrushing()
{
super("ritualCrushing", 0, 5000, "ritual." + BloodMagic.MODID + ".crushingRitual");
addBlockRange(CRUSHING_RANGE, new AreaDescriptor.Rectangle(new BlockPos(-1, -3, -1), 3));
addBlockRange(CHEST_RANGE, new AreaDescriptor.Rectangle(new BlockPos(0, 1, 0), 1));
setMaximumVolumeAndDistanceOfRange(CRUSHING_RANGE, 50, 10, 10);
setMaximumVolumeAndDistanceOfRange(CHEST_RANGE, 1, 3, 3);
}
@Override
public void performRitual(IMasterRitualStone masterRitualStone)
{
World world = masterRitualStone.getWorldObj();
if (world.isRemote)
{
return;
}
int currentEssence = masterRitualStone.getOwnerNetwork().getCurrentEssence();
if (currentEssence < getRefreshCost())
{
masterRitualStone.getOwnerNetwork().causeNausea();
return;
}
BlockPos pos = masterRitualStone.getBlockPos();
AreaDescriptor chestRange = masterRitualStone.getBlockRange(CHEST_RANGE);
TileEntity tile = world.getTileEntity(chestRange.getContainedPositions(pos).get(0));
if (tile != null && Utils.getNumberOfFreeSlots(tile, Direction.DOWN) < 1)
{
return;
}
List<EnumDemonWillType> willConfig = masterRitualStone.getActiveWillConfig();
double rawWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.DEFAULT, willConfig);
double steadfastWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.STEADFAST, willConfig);
double corrosiveWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.CORROSIVE, willConfig);
double destructiveWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.DESTRUCTIVE, willConfig);
double vengefulWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.VENGEFUL, willConfig);
refreshTime = getRefreshTimeForRawWill(rawWill);
boolean consumeRawWill = rawWill >= rawWillDrain && refreshTime != defaultRefreshTime;
boolean isSilkTouch = steadfastWill >= steadfastWillDrain;
boolean useCuttingFluid = corrosiveWill > 0;
int fortune = destructiveWill > 0 ? 3 : 0;
AreaDescriptor crushingRange = masterRitualStone.getBlockRange(CRUSHING_RANGE);
boolean hasOperated = false;
double rawDrain = 0;
for (BlockPos newPos : crushingRange.getContainedPositions(pos))
{
if (world.isAirBlock(newPos))
{
continue;
}
BlockState state = world.getBlockState(newPos);
Block block = state.getBlock();
if (block instanceof BlockMasterRitualStone || block instanceof IRitualStone
|| state.getBlockHardness(world, newPos) == -1.0F || Utils.isBlockLiquid(state))
{
continue;
}
boolean isBlockClaimed = false;
// if (useCuttingFluid)
// {
// ItemStack checkStack = block.getItem(world, newPos, state);
// if (checkStack.isEmpty())
// {
// continue;
// }
//
// ItemStack copyStack = checkStack.copy();
//
// for (ICrushingHandler handler : CrushingRegistry.getCrushingHandlerList())
// {
// int lpDrain = handler.getLpDrain();
// double willDrain = handler.getWillDrain();
//
// if (corrosiveWill < willDrain || currentEssence < lpDrain + getRefreshCost())
// {
// continue;
// }
//
// ItemStack result = handler.getRecipeOutput(copyStack, world, pos);
//
// if (result.isEmpty())
// {
// continue;
// }
//
// if (tile != null)
// {
// result = Utils.insertStackIntoTile(result, tile, Direction.DOWN);
// if (!result.isEmpty())
// {
// Utils.spawnStackAtBlock(world, pos, Direction.UP, result);
// }
// } else
// {
// Utils.spawnStackAtBlock(world, pos, Direction.UP, result);
// }
//
// WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.CORROSIVE, willDrain, true);
// corrosiveWill -= willDrain;
//
// masterRitualStone.getOwnerNetwork().syphon(masterRitualStone.ticket(lpDrain));
// currentEssence -= lpDrain;
//
// isBlockClaimed = true;
// }
//
// }
Blocks d;
if (!isBlockClaimed && isSilkTouch)
{
LootContext.Builder lootBuilder = new LootContext.Builder((ServerWorld) world);
Vector3d blockCenter = new Vector3d(newPos.getX() + 0.5, newPos.getY() + 0.5, newPos.getZ() + 0.5);
List<ItemStack> silkDrops = state.getDrops(lootBuilder.withParameter(LootParameters.field_237457_g_, blockCenter).withParameter(LootParameters.TOOL, mockPick));
for (ItemStack item : silkDrops)
{
ItemStack copyStack = item.copy();
if (tile != null)
{
copyStack = Utils.insertStackIntoTile(copyStack, tile, Direction.DOWN);
} else
{
Utils.spawnStackAtBlock(world, pos, Direction.UP, copyStack);
continue;
}
if (!copyStack.isEmpty())
{
Utils.spawnStackAtBlock(world, pos, Direction.UP, copyStack);
}
}
if (steadfastWill >= steadfastWillDrain)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.STEADFAST, steadfastWillDrain, true);
steadfastWill -= steadfastWillDrain;
} else
{
continue;
}
} else if (!isBlockClaimed)
{
if (fortune > 0 && destructiveWill < destructiveWillDrain)
{
fortune = 0;
}
ItemStack mockFortunePick = new ItemStack(Items.DIAMOND_PICKAXE, 1);
mockFortunePick.addEnchantment(Enchantments.FORTUNE, fortune);
LootContext.Builder lootBuilder = new LootContext.Builder((ServerWorld) world);
Vector3d blockCenter = new Vector3d(newPos.getX() + 0.5, newPos.getY() + 0.5, newPos.getZ() + 0.5);
List<ItemStack> stackList = state.getDrops(lootBuilder.withParameter(LootParameters.field_237457_g_, blockCenter).withParameter(LootParameters.TOOL, mockFortunePick));
// List<ItemStack> stackList = Block.getDrops(state, world, newPos, world.getTileEntity(newPos));
// List<ItemStack> stackList = block.getDrops(world, newPos, state, fortune);
for (ItemStack item : stackList)
{
ItemStack copyStack = item.copy();
if (tile != null)
{
copyStack = Utils.insertStackIntoTile(copyStack, tile, Direction.DOWN);
} else
{
Utils.spawnStackAtBlock(world, pos, Direction.UP, copyStack);
continue;
}
if (!copyStack.isEmpty())
{
Utils.spawnStackAtBlock(world, pos, Direction.UP, copyStack);
}
}
if (fortune > 0)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.DESTRUCTIVE, destructiveWillDrain, true);
destructiveWill -= destructiveWillDrain;
}
}
world.destroyBlock(newPos, false);
masterRitualStone.getOwnerNetwork().syphon(masterRitualStone.ticket(getRefreshCost()));
hasOperated = true;
if (consumeRawWill)
{
rawDrain += rawWillDrain;
rawWill -= rawWillDrain;
}
break;
}
// if (hasOperated && tile != null && vengefulWill >= vengefulWillDrain)
// {
// Pair<ItemStack, Boolean> pair = CompressionRegistry.compressInventory(tile, world);
// if (pair.getRight())
// {
// ItemStack returned = pair.getLeft();
// if (returned != null)
// {
// Utils.spawnStackAtBlock(world, pos, Direction.UP, returned);
// }
//
// WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.VENGEFUL, vengefulWillDrain, true);
// }
// }
if (rawDrain > 0)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.DEFAULT, rawDrain, true);
}
}
public int getRefreshTimeForRawWill(double rawWill)
{
if (rawWill >= rawWillDrain)
{
return Math.max(1, (int) (40 - rawWill / 5));
}
return defaultRefreshTime;
}
@Override
public int getRefreshTime()
{
return refreshTime;
}
@Override
public int getRefreshCost()
{
return 7;
}
@Override
public void gatherComponents(Consumer<RitualComponent> components)
{
addParallelRunes(components, 1, 0, EnumRuneType.EARTH);
addParallelRunes(components, 2, 0, EnumRuneType.FIRE);
addCornerRunes(components, 2, 0, EnumRuneType.DUSK);
addParallelRunes(components, 2, 1, EnumRuneType.AIR);
}
@Override
public ITextComponent[] provideInformationOfRitualToPlayer(PlayerEntity player)
{
return new ITextComponent[]
{ new TranslationTextComponent(this.getTranslationKey() + ".info"),
new TranslationTextComponent(this.getTranslationKey() + ".default.info"),
new TranslationTextComponent(this.getTranslationKey() + ".corrosive.info"),
new TranslationTextComponent(this.getTranslationKey() + ".steadfast.info"),
new TranslationTextComponent(this.getTranslationKey() + ".destructive.info"),
new TranslationTextComponent(this.getTranslationKey() + ".vengeful.info") };
}
@Override
public Ritual getNewCopy()
{
return new RitualCrushing();
}
public static void registerCuttingFluid(ItemStack stack, int lpDrain, double willDrain)
{
cuttingFluidLPMap.put(stack, lpDrain);
cuttingFluidWillMap.put(stack, willDrain);
}
private FakePlayer getFakePlayer(ServerWorld world)
{
return fakePlayer == null
? fakePlayer = FakePlayerFactory.get(world, new GameProfile(null, BloodMagic.MODID + "_ritual_crushing"))
: fakePlayer;
}
}

View file

@ -0,0 +1,255 @@
package wayoftime.bloodmagic.ritual.types;
import java.util.List;
import java.util.function.Consumer;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.potion.EffectInstance;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB;
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.ConfigHandler;
import wayoftime.bloodmagic.altar.IBloodAltar;
import wayoftime.bloodmagic.demonaura.WorldDemonWillHandler;
import wayoftime.bloodmagic.potion.BloodMagicPotions;
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.util.helper.PlayerSacrificeHelper;
import wayoftime.bloodmagic.will.EnumDemonWillType;
@RitualRegister("feathered_knife")
public class RitualFeatheredKnife extends Ritual
{
public static final String ALTAR_RANGE = "altar";
public static final String DAMAGE_RANGE = "damage";
public static double rawWillDrain = 0.05;
public static double destructiveWillDrain = 0.05;
public static double corrosiveWillThreshold = 10;
public static double steadfastWillThreshold = 10;
public static double vengefulWillThreshold = 10;
public static int defaultRefreshTime = 20;
public int refreshTime = 20;
public BlockPos altarOffsetPos = new BlockPos(0, 0, 0); // TODO: Save!
public RitualFeatheredKnife()
{
super("ritualFeatheredKnife", 0, 25000, "ritual." + BloodMagic.MODID + ".featheredKnifeRitual");
addBlockRange(ALTAR_RANGE, new AreaDescriptor.Rectangle(new BlockPos(-5, -10, -5), 11, 21, 11));
addBlockRange(DAMAGE_RANGE, new AreaDescriptor.Rectangle(new BlockPos(-15, -20, -15), 31, 41, 31));
setMaximumVolumeAndDistanceOfRange(ALTAR_RANGE, 0, 10, 15);
setMaximumVolumeAndDistanceOfRange(DAMAGE_RANGE, 0, 25, 15);
}
@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();
List<EnumDemonWillType> willConfig = masterRitualStone.getActiveWillConfig();
double corrosiveWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.CORROSIVE, willConfig);
double destructiveWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.DESTRUCTIVE, willConfig);
double rawWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.DEFAULT, willConfig);
double steadfastWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.STEADFAST, willConfig);
double vengefulWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.VENGEFUL, willConfig);
refreshTime = getRefreshTimeForRawWill(rawWill);
boolean consumeRawWill = rawWill >= rawWillDrain && refreshTime != defaultRefreshTime;
int maxEffects = currentEssence / getRefreshCost();
int totalEffects = 0;
BlockPos altarPos = pos.add(altarOffsetPos);
TileEntity tile = world.getTileEntity(altarPos);
AreaDescriptor altarRange = masterRitualStone.getBlockRange(ALTAR_RANGE);
if (!altarRange.isWithinArea(altarOffsetPos) || !(tile instanceof IBloodAltar))
{
for (BlockPos newPos : altarRange.getContainedPositions(pos))
{
TileEntity nextTile = world.getTileEntity(newPos);
if (nextTile instanceof IBloodAltar)
{
tile = nextTile;
altarOffsetPos = newPos.subtract(pos);
altarRange.resetCache();
break;
}
}
}
boolean useIncense = corrosiveWill >= corrosiveWillThreshold;
if (tile instanceof IBloodAltar)
{
IBloodAltar tileAltar = (IBloodAltar) tile;
AreaDescriptor damageRange = masterRitualStone.getBlockRange(DAMAGE_RANGE);
AxisAlignedBB range = damageRange.getAABB(pos);
double destructiveDrain = 0;
List<PlayerEntity> entities = world.getEntitiesWithinAABB(PlayerEntity.class, range);
for (PlayerEntity player : entities)
{
float healthThreshold = steadfastWill >= steadfastWillThreshold ? 0.7f : 0.3f;
if (vengefulWill >= vengefulWillThreshold
&& !player.getGameProfile().getId().equals(masterRitualStone.getOwner()))
{
healthThreshold = 0.1f;
}
float health = player.getHealth();
float maxHealth = player.getMaxHealth();
float sacrificedHealth = 1;
double lpModifier = 1;
if ((health / player.getMaxHealth() > healthThreshold)
&& (!useIncense || !player.isPotionActive(BloodMagicPotions.SOUL_FRAY)))
{
if (useIncense)
{
double incenseAmount = PlayerSacrificeHelper.getPlayerIncense(player);
sacrificedHealth = health - maxHealth * healthThreshold;
lpModifier *= PlayerSacrificeHelper.getModifier(incenseAmount);
PlayerSacrificeHelper.setPlayerIncense(player, 0);
player.addPotionEffect(new EffectInstance(BloodMagicPotions.SOUL_FRAY, PlayerSacrificeHelper.soulFrayDuration));
}
if (destructiveWill >= destructiveWillDrain * sacrificedHealth)
{
lpModifier *= getLPModifierForWill(destructiveWill);
destructiveWill -= destructiveWillDrain * sacrificedHealth;
destructiveDrain += destructiveWillDrain * sacrificedHealth;
}
// if (LivingArmour.hasFullSet(player))
// {
// ItemStack chestStack = player.getItemStackFromSlot(EquipmentSlotType.CHEST);
// LivingArmour armour = ItemLivingArmour.getLivingArmour(chestStack);
// if (armour != null)
// {
// LivingArmourUpgrade upgrade = ItemLivingArmour.getUpgrade(BloodMagic.MODID + ".upgrade.selfSacrifice", chestStack);
//
// if (upgrade instanceof LivingArmourUpgradeSelfSacrifice)
// {
// double modifier = ((LivingArmourUpgradeSelfSacrifice) upgrade).getSacrificeModifier();
//
// lpModifier *= (1 + modifier);
// }
// }
// }
player.setHealth(health - sacrificedHealth);
tileAltar.sacrificialDaggerCall((int) (ConfigHandler.values.sacrificialDaggerConversion * lpModifier
* sacrificedHealth), false);
totalEffects++;
if (totalEffects >= maxEffects)
{
break;
}
}
}
if (destructiveDrain > 0)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.STEADFAST, destructiveDrain, true);
}
}
masterRitualStone.getOwnerNetwork().syphon(masterRitualStone.ticket(getRefreshCost() * totalEffects));
if (totalEffects > 0 && consumeRawWill)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.DEFAULT, rawWillDrain, true);
}
}
@Override
public int getRefreshTime()
{
return refreshTime;
}
@Override
public int getRefreshCost()
{
return 20;
}
@Override
public void gatherComponents(Consumer<RitualComponent> components)
{
addParallelRunes(components, 1, 0, EnumRuneType.DUSK);
addParallelRunes(components, 2, -1, EnumRuneType.WATER);
addCornerRunes(components, 1, -1, EnumRuneType.AIR);
addOffsetRunes(components, 2, 4, -1, EnumRuneType.FIRE);
addOffsetRunes(components, 2, 4, 0, EnumRuneType.EARTH);
addOffsetRunes(components, 4, 3, 0, EnumRuneType.EARTH);
addCornerRunes(components, 3, 0, EnumRuneType.AIR);
}
@Override
public Ritual getNewCopy()
{
return new RitualFeatheredKnife();
}
@Override
public ITextComponent[] provideInformationOfRitualToPlayer(PlayerEntity player)
{
return new ITextComponent[]
{ new TranslationTextComponent(this.getTranslationKey() + ".info"),
new TranslationTextComponent(this.getTranslationKey() + ".default.info"),
new TranslationTextComponent(this.getTranslationKey() + ".corrosive.info"),
new TranslationTextComponent(this.getTranslationKey() + ".steadfast.info"),
new TranslationTextComponent(this.getTranslationKey() + ".destructive.info"),
new TranslationTextComponent(this.getTranslationKey() + ".vengeful.info") };
}
public double getLPModifierForWill(double destructiveWill)
{
return 1 + destructiveWill * 0.2 / 100;
}
public int getRefreshTimeForRawWill(double rawWill)
{
if (rawWill >= rawWillDrain)
{
return 10;
}
return defaultRefreshTime;
}
}

View file

@ -0,0 +1,362 @@
package wayoftime.bloodmagic.ritual.types;
import java.util.List;
import java.util.function.Consumer;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.demonaura.WorldDemonWillHandler;
import wayoftime.bloodmagic.potion.BloodMagicPotions;
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.util.DamageSourceBloodMagic;
import wayoftime.bloodmagic.util.Utils;
import wayoftime.bloodmagic.will.DemonWillHolder;
import wayoftime.bloodmagic.will.EnumDemonWillType;
@RitualRegister("lava")
public class RitualLava extends Ritual
{
public static final String LAVA_RANGE = "lavaRange";
public static final String FIRE_FUSE_RANGE = "fireFuse";
public static final String FIRE_RESIST_RANGE = "fireResist";
public static final String FIRE_DAMAGE_RANGE = "fireDamage";
public static final String LAVA_TANK_RANGE = "lavaTank";
public static final double vengefulWillDrain = 1;
public static final double steadfastWillDrain = 0.5;
public static final double corrosiveWillDrain = 0.2;
public static final int corrosiveRefreshTime = 20;
public int timer = 0;
public RitualLava()
{
super("ritualLava", 0, 10000, "ritual." + BloodMagic.MODID + ".lavaRitual");
addBlockRange(LAVA_RANGE, new AreaDescriptor.Rectangle(new BlockPos(0, 1, 0), 1));
addBlockRange(FIRE_FUSE_RANGE, new AreaDescriptor.Rectangle(new BlockPos(-2, -2, -2), 5));
addBlockRange(FIRE_RESIST_RANGE, new AreaDescriptor.Rectangle(new BlockPos(0, 0, 0), 1));
addBlockRange(FIRE_DAMAGE_RANGE, new AreaDescriptor.Rectangle(new BlockPos(0, 0, 0), 1));
addBlockRange(LAVA_TANK_RANGE, new AreaDescriptor.Rectangle(new BlockPos(0, 1, 0), 1));
setMaximumVolumeAndDistanceOfRange(LAVA_RANGE, 9, 3, 3);
setMaximumVolumeAndDistanceOfRange(FIRE_FUSE_RANGE, 0, 10, 10);
setMaximumVolumeAndDistanceOfRange(FIRE_RESIST_RANGE, 0, 10, 10);
setMaximumVolumeAndDistanceOfRange(FIRE_DAMAGE_RANGE, 0, 10, 10);
setMaximumVolumeAndDistanceOfRange(LAVA_TANK_RANGE, 1, 10, 10);
}
@Override
public void performRitual(IMasterRitualStone masterRitualStone)
{
timer++;
World world = masterRitualStone.getWorldObj();
int currentEssence = masterRitualStone.getOwnerNetwork().getCurrentEssence();
int lpDrain = 0;
if (currentEssence < getRefreshCost())
{
masterRitualStone.getOwnerNetwork().causeNausea();
return;
}
BlockPos pos = masterRitualStone.getBlockPos();
List<EnumDemonWillType> willConfig = masterRitualStone.getActiveWillConfig();
double rawWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.DEFAULT, willConfig);
double rawDrained = 0;
DemonWillHolder holder = WorldDemonWillHandler.getWillHolder(world, pos);
AreaDescriptor lavaRange = masterRitualStone.getBlockRange(LAVA_RANGE);
int maxLavaVolume = getMaxVolumeForRange(LAVA_RANGE, willConfig, holder);
if (!lavaRange.isWithinRange(getMaxVerticalRadiusForRange(LAVA_RANGE, willConfig, holder), getMaxHorizontalRadiusForRange(LAVA_RANGE, willConfig, holder))
|| (maxLavaVolume != 0 && lavaRange.getVolume() > maxLavaVolume))
{
return;
}
for (BlockPos newPos : lavaRange.getContainedPositions(pos))
{
BlockState state = world.getBlockState(newPos);
if (world.isAirBlock(newPos) || Utils.isFlowingLiquid(world, newPos, state))
{
int lpCost = getLPCostForRawWill(rawWill);
if (currentEssence < lpCost)
{
break;
}
world.setBlockState(newPos, Blocks.LAVA.getDefaultState());
currentEssence -= lpCost;
lpDrain += lpCost;
if (rawWill > 0)
{
double drain = getWillCostForRawWill(rawWill);
rawWill -= drain;
rawDrained += drain;
}
}
}
if (rawWill > 0)
{
AreaDescriptor chestRange = masterRitualStone.getBlockRange(LAVA_TANK_RANGE);
TileEntity tile = world.getTileEntity(chestRange.getContainedPositions(pos).get(0));
double drain = getWillCostForRawWill(rawWill);
int lpCost = getLPCostForRawWill(rawWill);
if (rawWill >= drain && currentEssence >= lpCost)
{
if (tile != null)
{
LazyOptional<IFluidHandler> capability = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null);
if (capability.isPresent())
{
IFluidHandler handler = capability.resolve().get();
double filled = handler.fill(new FluidStack(Fluids.LAVA, 1000), FluidAction.EXECUTE);
double ratio = filled / 1000;
rawWill -= drain * ratio;
rawDrained += drain * ratio;
currentEssence -= Math.ceil(lpCost * ratio);
lpDrain += Math.ceil(lpCost * ratio);
}
}
}
}
double vengefulWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.VENGEFUL, willConfig);
double steadfastWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.STEADFAST, willConfig);
double corrosiveWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.CORROSIVE, willConfig);
if (vengefulWill >= vengefulWillDrain)
{
double vengefulDrained = 0;
AreaDescriptor fuseRange = masterRitualStone.getBlockRange(FIRE_FUSE_RANGE);
AxisAlignedBB fuseArea = fuseRange.getAABB(pos);
List<LivingEntity> entities = world.getEntitiesWithinAABB(LivingEntity.class, fuseArea);
for (LivingEntity entity : entities)
{
if (vengefulWill < vengefulWillDrain)
{
break;
}
if (entity instanceof PlayerEntity)
{
continue;
}
if (!entity.isPotionActive(BloodMagicPotions.FIRE_FUSE))
{
entity.addPotionEffect(new EffectInstance(BloodMagicPotions.FIRE_FUSE, 100, 0));
vengefulDrained += vengefulWillDrain;
vengefulWill -= vengefulWillDrain;
}
}
if (vengefulDrained > 0)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.VENGEFUL, vengefulDrained, true);
}
}
if (steadfastWill >= steadfastWillDrain)
{
double steadfastDrained = 0;
AreaDescriptor resistRange = masterRitualStone.getBlockRange(FIRE_RESIST_RANGE);
int duration = getFireResistForWill(steadfastWill);
AxisAlignedBB resistArea = resistRange.getAABB(pos);
List<PlayerEntity> entities = world.getEntitiesWithinAABB(PlayerEntity.class, resistArea);
for (PlayerEntity entity : entities)
{
if (steadfastWill < steadfastWillDrain)
{
break;
}
if (!entity.isPotionActive(Effects.FIRE_RESISTANCE)
|| (entity.getActivePotionEffect(Effects.FIRE_RESISTANCE).getDuration() < 2))
{
entity.addPotionEffect(new EffectInstance(Effects.FIRE_RESISTANCE, 100, 0));
steadfastDrained += steadfastWillDrain;
steadfastWill -= steadfastWillDrain;
}
}
if (steadfastDrained > 0)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.STEADFAST, steadfastDrained, true);
}
}
if (timer % corrosiveRefreshTime == 0 && corrosiveWill >= corrosiveWillDrain)
{
double corrosiveDrained = 0;
AreaDescriptor resistRange = masterRitualStone.getBlockRange(FIRE_DAMAGE_RANGE);
float damage = getCorrosiveDamageForWill(corrosiveWill);
AxisAlignedBB damageArea = resistRange.getAABB(pos);
List<LivingEntity> entities = world.getEntitiesWithinAABB(LivingEntity.class, damageArea);
for (LivingEntity entity : entities)
{
if (corrosiveWill < corrosiveWillDrain)
{
break;
}
if (!entity.isAlive() && entity.hurtTime <= 0 && Utils.isImmuneToFireDamage(entity))
{
if (entity.attackEntityFrom(DamageSourceBloodMagic.INSTANCE, damage))
{
corrosiveDrained += corrosiveWillDrain;
corrosiveWill -= corrosiveWillDrain;
}
}
}
if (corrosiveDrained > 0)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.CORROSIVE, corrosiveDrained, true);
}
}
if (rawDrained > 0)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.DEFAULT, rawDrained, true);
}
masterRitualStone.getOwnerNetwork().syphon(masterRitualStone.ticket(lpDrain));
}
@Override
public int getRefreshTime()
{
return 1;
}
@Override
public int getRefreshCost()
{
return 500;
}
@Override
public ITextComponent[] provideInformationOfRitualToPlayer(PlayerEntity player)
{
return new ITextComponent[]
{ new TranslationTextComponent(this.getTranslationKey() + ".info"),
new TranslationTextComponent(this.getTranslationKey() + ".default.info"),
new TranslationTextComponent(this.getTranslationKey() + ".corrosive.info"),
new TranslationTextComponent(this.getTranslationKey() + ".steadfast.info"),
new TranslationTextComponent(this.getTranslationKey() + ".destructive.info"),
new TranslationTextComponent(this.getTranslationKey() + ".vengeful.info") };
}
@Override
public void gatherComponents(Consumer<RitualComponent> components)
{
addParallelRunes(components, 1, 0, EnumRuneType.FIRE);
}
@Override
public Ritual getNewCopy()
{
return new RitualLava();
}
@Override
public int getMaxVolumeForRange(String range, List<EnumDemonWillType> activeTypes, DemonWillHolder holder)
{
if (LAVA_RANGE.equals(range) && activeTypes.contains(EnumDemonWillType.DESTRUCTIVE))
{
double destructiveWill = holder.getWill(EnumDemonWillType.DESTRUCTIVE);
if (destructiveWill > 0)
{
return 9 + (int) Math.pow(destructiveWill / 10, 1.5);
}
}
return volumeRangeMap.get(range);
}
@Override
public int getMaxVerticalRadiusForRange(String range, List<EnumDemonWillType> activeTypes, DemonWillHolder holder)
{
if (LAVA_RANGE.equals(range) && activeTypes.contains(EnumDemonWillType.DESTRUCTIVE))
{
double destructiveWill = holder.getWill(EnumDemonWillType.DESTRUCTIVE);
if (destructiveWill > 0)
{
return (int) (3 + destructiveWill / 10d);
}
}
return verticalRangeMap.get(range);
}
@Override
public int getMaxHorizontalRadiusForRange(String range, List<EnumDemonWillType> activeTypes, DemonWillHolder holder)
{
if (LAVA_RANGE.equals(range) && activeTypes.contains(EnumDemonWillType.DESTRUCTIVE))
{
double destructiveWill = holder.getWill(EnumDemonWillType.DESTRUCTIVE);
if (destructiveWill > 0)
{
return (int) (3 + destructiveWill / 10d);
}
}
return horizontalRangeMap.get(range);
}
public int getFireResistForWill(double steadfastWill)
{
return (int) (200 + steadfastWill * 3);
}
public float getCorrosiveDamageForWill(double corrosiveWill)
{
return (float) (1 + corrosiveWill * 0.05);
}
public int getLPCostForRawWill(double raw)
{
return Math.max((int) (500 - raw), 0);
}
public double getWillCostForRawWill(double raw)
{
return Math.min(1, raw / 500);
}
}

View file

@ -0,0 +1,202 @@
package wayoftime.bloodmagic.ritual.types;
import java.util.function.Consumer;
import com.mojang.authlib.GameProfile;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack;
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.common.Tags;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.common.util.FakePlayerFactory;
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.util.Utils;
@RitualRegister("magnetism")
public class RitualMagnetic extends Ritual
{
public static final String PLACEMENT_RANGE = "placementRange";
// public static final String SEARCH_RANGE = "searchRange";
public BlockPos lastPos; // An offset
private FakePlayer fakePlayer;
public RitualMagnetic()
{
super("ritualMagnetic", 0, 5000, "ritual." + BloodMagic.MODID + ".magneticRitual");
addBlockRange(PLACEMENT_RANGE, new AreaDescriptor.Rectangle(new BlockPos(-1, 1, -1), 3));
setMaximumVolumeAndDistanceOfRange(PLACEMENT_RANGE, 50, 4, 4);
}
@Override
public void performRitual(IMasterRitualStone masterRitualStone)
{
World world = masterRitualStone.getWorldObj();
Vector3d MRSpos = new Vector3d(masterRitualStone.getBlockPos().getX(), masterRitualStone.getBlockPos().getY(), masterRitualStone.getBlockPos().getZ());
int currentEssence = masterRitualStone.getOwnerNetwork().getCurrentEssence();
if (currentEssence < getRefreshCost())
{
masterRitualStone.getOwnerNetwork().causeNausea();
return;
}
BlockPos pos = masterRitualStone.getBlockPos();
AreaDescriptor placementRange = masterRitualStone.getBlockRange(PLACEMENT_RANGE);
BlockPos replacement = pos;
boolean replace = false;
for (BlockPos offset : placementRange.getContainedPositions(pos))
{
if (world.isAirBlock(offset))
{
replacement = offset;
replace = true;
break;
}
}
BlockState downState = world.getBlockState(pos.down());
int radius = getRadius(downState.getBlock());
if (replace)
{
int j = -1;
int i = -radius;
int k = -radius;
if (lastPos != null)
{
j = lastPos.getY();
i = Math.min(radius, Math.max(-radius, lastPos.getX()));
k = Math.min(radius, Math.max(-radius, lastPos.getZ()));
}
if (j + pos.getY() >= 0)
{
while (i <= radius)
{
while (k <= radius)
{
BlockPos newPos = pos.add(i, j, k);
Vector3d newPosVector = new Vector3d(newPos.getX(), newPos.getY(), newPos.getZ());
BlockState state = world.getBlockState(newPos);
// RayTraceResult fakeRayTrace = world.rayTraceBlocks(MRSpos, newPosVector, false);
// ItemStack checkStack = state.getBlock().getPickBlock(state, fakeRayTrace, world, newPos, getFakePlayer((ServerWorld) world));
ItemStack checkStack = new ItemStack(state.getBlock());
if (isBlockOre(checkStack))
{
Utils.swapLocations(world, newPos, world, replacement);
masterRitualStone.getOwnerNetwork().syphon(masterRitualStone.ticket(getRefreshCost()));
k++;
this.lastPos = new BlockPos(i, j, k);
return;
} else
{
k++;
}
}
i++;
k = -radius;
}
j--;
i = -radius;
this.lastPos = new BlockPos(i, j, k);
return;
}
j = -1;
this.lastPos = new BlockPos(i, j, k);
}
}
public int getRadius(Block block)
{
if (block == Blocks.IRON_BLOCK)
{
return 7;
}
if (block == Blocks.GOLD_BLOCK)
{
return 15;
}
if (block == Blocks.DIAMOND_BLOCK)
{
return 31;
}
return 3;
}
@Override
public int getRefreshTime()
{
return 40;
}
@Override
public int getRefreshCost()
{
return 50;
}
@Override
public void gatherComponents(Consumer<RitualComponent> components)
{
addCornerRunes(components, 1, 0, EnumRuneType.EARTH);
addParallelRunes(components, 2, 1, EnumRuneType.EARTH);
addCornerRunes(components, 2, 1, EnumRuneType.AIR);
addParallelRunes(components, 2, 2, EnumRuneType.FIRE);
}
@Override
public Ritual getNewCopy()
{
return new RitualMagnetic();
}
private FakePlayer getFakePlayer(ServerWorld world)
{
return fakePlayer == null
? fakePlayer = FakePlayerFactory.get(world, new GameProfile(null, BloodMagic.MODID + "_ritual_magnetic"))
: fakePlayer;
}
public static boolean isBlockOre(ItemStack stack)
{
if (stack.isEmpty())
return false;
return stack.getItem().isIn(Tags.Items.ORES);
// for(ResourceLocation rl : stack.getItem().getTags())
// {
// rl.getPath()
// }
// for (int id : OreDictionary.getOreIDs(stack))
// {
// String oreName = OreDictionary.getOreName(id);
// if (oreName.contains("ore"))
// return true;
// }
// return false;
}
}

View file

@ -0,0 +1,85 @@
package wayoftime.bloodmagic.ritual.types;
import java.util.function.Consumer;
import net.minecraft.block.Blocks;
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;
@RitualRegister("water")
public class RitualWater extends Ritual
{
public static final String WATER_RANGE = "waterRange";
public RitualWater()
{
super("ritualWater", 0, 500, "ritual." + BloodMagic.MODID + ".waterRitual");
addBlockRange(WATER_RANGE, new AreaDescriptor.Rectangle(new BlockPos(0, 1, 0), 1));
setMaximumVolumeAndDistanceOfRange(WATER_RANGE, 9, 3, 3);
}
@Override
public void performRitual(IMasterRitualStone masterRitualStone)
{
World world = masterRitualStone.getWorldObj();
int currentEssence = masterRitualStone.getOwnerNetwork().getCurrentEssence();
if (currentEssence < getRefreshCost())
{
masterRitualStone.getOwnerNetwork().causeNausea();
return;
}
int maxEffects = currentEssence / getRefreshCost();
int totalEffects = 0;
AreaDescriptor waterRange = masterRitualStone.getBlockRange(WATER_RANGE);
for (BlockPos newPos : waterRange.getContainedPositions(masterRitualStone.getBlockPos()))
{
if (world.isAirBlock(newPos))
{
world.setBlockState(newPos, Blocks.WATER.getDefaultState());
totalEffects++;
}
if (totalEffects >= maxEffects)
{
break;
}
}
masterRitualStone.getOwnerNetwork().syphon(masterRitualStone.ticket(getRefreshCost() * totalEffects));
}
@Override
public int getRefreshTime()
{
return 1;
}
@Override
public int getRefreshCost()
{
return 25;
}
@Override
public void gatherComponents(Consumer<RitualComponent> components)
{
addCornerRunes(components, 1, 0, EnumRuneType.WATER);
}
@Override
public Ritual getNewCopy()
{
return new RitualWater();
}
}