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:
parent
6b4145a67c
commit
9fa68e86ae
224 changed files with 24047 additions and 0 deletions
654
src/main/java/wayoftime/bloodmagic/ritual/AreaDescriptor.java
Normal file
654
src/main/java/wayoftime/bloodmagic/ritual/AreaDescriptor.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
54
src/main/java/wayoftime/bloodmagic/ritual/EnumRuneType.java
Normal file
54
src/main/java/wayoftime/bloodmagic/ritual/EnumRuneType.java
Normal 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];
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
20
src/main/java/wayoftime/bloodmagic/ritual/IRitualStone.java
Normal file
20
src/main/java/wayoftime/bloodmagic/ritual/IRitualStone.java
Normal 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);
|
||||
}
|
||||
}
|
427
src/main/java/wayoftime/bloodmagic/ritual/Ritual.java
Normal file
427
src/main/java/wayoftime/bloodmagic/ritual/Ritual.java
Normal 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,
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
177
src/main/java/wayoftime/bloodmagic/ritual/RitualManager.java
Normal file
177
src/main/java/wayoftime/bloodmagic/ritual/RitualManager.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
362
src/main/java/wayoftime/bloodmagic/ritual/types/RitualLava.java
Normal file
362
src/main/java/wayoftime/bloodmagic/ritual/types/RitualLava.java
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue