Rift render and right-click improvments

- Highlight rift core when trying to place a door next to a rift, and warn player about instability (place again to confirm placing next to rift)
 - Clean up LSystem class
 - Make rifts jitter less
 - Stop rift particle flicker, lower max age
 - Make rifts grow a bit slower
 - Replace option to use old animation with option to highlight the rift core
 - Make rift render yaw match teleport target yaw
This commit is contained in:
Runemoro 2018-04-04 02:09:05 -04:00
parent ba887a4066
commit 5f8375a693
12 changed files with 161 additions and 240 deletions

View file

@ -6,28 +6,33 @@ import org.poly2tri.geometry.polygon.PolygonPoint;
import org.poly2tri.triangulation.TriangulationPoint;
import org.poly2tri.triangulation.delaunay.DelaunayTriangle;
import java.awt.Point; // TODO: wrong point class!
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.awt.*; // TODO: Wrong point class!
import java.util.*;
import java.util.List;
public final class LSystem { // TODO: Finish cleaning up this class
public static ArrayList<PolygonStorage> curves = new ArrayList<>();
public final class LSystem { // TODO: Rewrite this class
public static ArrayList<PolygonInfo> curves = new ArrayList<>();
/**
* An array containing the args to generate a curve.
* index 0 = rules
* index 1 = angle
* index 2 = start string
*/
// https://en.wikipedia.org/wiki/L-system
//
// System: {rules, angle, start_string}
// Rules: rule1:rule_2:...:rule_n
// Rule: from_substring>to_substring
//
// Each iteration, rules are applied to the string. After, string
// is interpreted as commands for a pencil on a sheet of paper:
// F - move forward by one step
// + - turn clockwise by angle
// - - turn counter-clockwise by angle
// [ - save state (push to stack)
// ] - restore state (pop from stack)
public static final String[] TERDRAGON = {"F>+F----F++++F-", "60", "F"};
public static final String[] DRAGON = {"X>X+YF:Y>FX-Y", "90", "FX"};
public static final String[] TWINDRAGON = {"X>X+YF:Y>FX-Y", "90", "FX--FX"};
public static final String[] VORTEX = {"X>X+YF:Y>FX-Y", "90", "FX---FX"};
static { // Used to be in mod init
// TODO
static {
// TODO: Move to separate class
LSystem.generateLSystem("terdragon", LSystem.TERDRAGON, 4);
LSystem.generateLSystem("terdragon", LSystem.TERDRAGON, 5);
//LSystem.generateLSystem("terdragon", LSystem.TERDRAGON, 6); // degenerate
@ -83,73 +88,23 @@ public final class LSystem { // TODO: Finish cleaning up this class
output = generate(args[2], steps, lSystemsRule);
//get the boundary of the polygon
PolygonStorage polygon = getBoundary(convertToPoints(angle, output, steps));
List<Point> polygon = getBoundary(convertToPoints(angle, output, steps));
//replace the boundary of the polygon with a series of points representing triangles for rendering
polygon.points = tesselate(polygon);
curves.add(polygon);
}
/**
* Naively returns all of the points comprising the fractal
*/
public static PolygonStorage getSpaceFillingCurve(ArrayList<double[]> input) {
// store max x and y values to create bounding box
int maxY = Integer.MIN_VALUE;
int maxX = Integer.MIN_VALUE;
int minY = Integer.MAX_VALUE;
int minX = Integer.MAX_VALUE;
// store confirmed duplicates here
HashSet<Point> duplicates = new HashSet<>();
// store possible singles here
HashSet<Point> singles = new HashSet<>();
// list to store confirmed singles and output in the correct order
ArrayList<Point> output = new ArrayList<>();
// sort into Hashmaps and hashsets to make contains operations possible,
// while testing for duplicates
for (double[] point : input) {
// convert doubles to ints and record min/max values
int xCoord = (int) Math.round(point[0]);
int yCoord = (int) Math.round(point[1]);
if (xCoord > maxX) {
maxX = xCoord;
}
if (xCoord < minX) {
minX = xCoord;
}
if (yCoord > maxY) {
maxY = yCoord;
}
if (yCoord < minY) {
minY = yCoord;
}
output.add(new Point(xCoord, yCoord));
}
return new PolygonStorage(output, maxX, maxY, minX, minY);
curves.add(new PolygonInfo(tesselate(polygon)));
}
/**
* Takes an unordered list of points comprising a fractal curve and builds a
* closed polygon around it
*/
public static PolygonStorage getBoundary(ArrayList<double[]> input) {
public static List<Point> getBoundary(ArrayList<double[]> input) {
// store max x and y values to create bounding box
int maxY = Integer.MIN_VALUE;
int maxX = Integer.MIN_VALUE;
int minY = Integer.MAX_VALUE;
int minX = Integer.MAX_VALUE;
// store confirmed duplicates here
HashSet<Point> duplicates = new HashSet<>();
// store possible singles here
HashSet<Point> singles = new HashSet<>();
@ -159,24 +114,14 @@ public final class LSystem { // TODO: Finish cleaning up this class
// sort into Hashmaps and hashsets to make contains operations possible,
// while testing for duplicates
for (double[] point : input) {
// convert doubles to ints and record min/max values
int xCoord = (int) Math.round(point[0]);
int yCoord = (int) Math.round(point[1]);
if (xCoord > maxX) {
maxX = xCoord;
}
if (xCoord < minX) {
minX = xCoord;
}
if (xCoord > maxX) maxX = xCoord;
if (xCoord < minX) minX = xCoord;
if (yCoord > maxY) maxY = yCoord;
if (yCoord < minY) minY = yCoord;
if (yCoord > maxY) {
maxY = yCoord;
}
if (yCoord < minY) {
minY = yCoord;
}
singles.add(new Point(xCoord, yCoord));
}
@ -235,7 +180,7 @@ public final class LSystem { // TODO: Finish cleaning up this class
}
while (!(output.get(output.size() - 1).equals(firstPoint) && output.size() > 1) && output.size() < singles.size());
return new PolygonStorage(output, maxX, maxY, minX, minY);
return output;
}
/**
@ -341,30 +286,50 @@ public final class LSystem { // TODO: Finish cleaning up this class
}
// a data container class to transmit the important information about the polygon
public static class PolygonStorage {
public PolygonStorage(ArrayList<Point> points, int maxX, int maxY, int minX, int minY) {
this.points = points;
this.maxX = maxX;
this.maxY = maxY;
this.minX = minX;
this.minY = minY;
}
public ArrayList<Point> points;
public static class PolygonInfo {
public final ArrayList<Point> points;
public int maxX;
public int maxY;
public int minX;
public int minY;
public final int maxY;
public final int minX;
public final int minY;
public PolygonInfo(ArrayList<Point> points) {
int minX, minY, maxX, maxY;
minX = minY = maxX = maxY = 0;
// Find bounding box of the polygon
this.points = points;
if (points.size() > 0) {
Point firstPoint = points.get(0);
minX = firstPoint.x;
minY = firstPoint.y;
maxX = firstPoint.x;
maxY = firstPoint.y;
for (Point point : points) {
if (point.x < minX) minX = point.x;
if (point.y < minY) minY = point.y;
if (point.x > maxX) maxX = point.x;
if (point.y > maxY) maxY = point.y;
}
}
this.minX = minX;
this.minY = minY;
this.maxX = maxX;
this.maxY = maxY;
}
}
public static ArrayList<Point> tesselate(PolygonStorage polygon) {
// TODO: Use the GLU tesselator (GPU) instead of poly2tri (CPU): http://wiki.lwjgl.org/wiki/Using_GLU_Tesselator.html
public static ArrayList<Point> tesselate(List<Point> polygon) {
ArrayList<Point> points = new ArrayList<>();
ArrayList<PolygonPoint> polyPoints = new ArrayList<>();
for (int i = 0; i < polygon.points.size(); i++) {
polyPoints.add(new PolygonPoint(polygon.points.get(i).x, polygon.points.get(i).y));
for (Point p : polygon) {
polyPoints.add(new PolygonPoint(p.x, p.y));
}
Polygon poly = new Polygon(polyPoints);
@ -379,88 +344,4 @@ public final class LSystem { // TODO: Finish cleaning up this class
}
return points;
}
// TODO: Figure out what this was meant to be
/*
public static ArrayList<Point> tesselate(Polygon polygon) {
ArrayList<Point> points = new ArrayList<>();
Tessellator tess = new Tessellator();
double[] verticesC1 = new double[polygon.points.size() * 3];
for (int i = 0; i < verticesC1.length; i += 3) {
Point point = polygon.points.get(i / 3);
verticesC1[i] = point.x;
verticesC1[i + 1] = point.y;
verticesC1[i + 2] = 0;
}
tess.glBeginPolygon();
for (int i = 0; i < polygon.points.size(); i++) {
tess.gluTessVertex(verticesC1, i * 3, i);
}
tess.gluEndPolygon();
//Prints out the result of the tessellation.
for (int i = 0; i < tess.primitives.size(); i++) {
System.out.println(tess.primitives.get(i).toString());
}
//To draw the shape it is now a simple matter to put the vertex data you passed in initially into a VBO, and the indices returned
//into an IBO (Index VBO). You have the types of the primitives and the number of indices for each one. Drawing the result should
//be a walk in the park, as long as you have read the appropriate tutorials here or elsewhere.
for (int i = 0; i < tess.primitives.size(); i++) {
Primitives.Primitive prim = tess.primitives.get(i);
ArrayList<Integer> vIndex = prim.vertices;
if (prim.type == GL11.GL_TRIANGLE_STRIP) {
for (int ii = 0; ii < vIndex.size() - 1; ii++) {
points.add(new Point((int) verticesC1[vIndex.get(ii) * 3], (int) verticesC1[vIndex.get(ii) * 3 + 1]));
points.add(new Point((int) verticesC1[vIndex.get(ii + 1) * 3], (int) verticesC1[vIndex.get(ii + 1) * 3 + 1]));
}
}
if (prim.type == GL11.GL_TRIANGLES) {
for (int ii = 0; ii < vIndex.size(); ii++) {
points.add(new Point((int) verticesC1[vIndex.get(ii) * 3], (int) verticesC1[vIndex.get(ii) * 3 + 1]));
}
}
if (prim.type == GL11.GL_TRIANGLE_FAN) {
Integer firstIndex = vIndex.get(0);
// points.add(new Point((int)verticesC1[vIndex.get(firstIndex)],(int) verticesC1[vIndex.get(firstIndex)+1]));
Integer[] vertexList = new Integer[vIndex.size() * 3];
for (Integer ii = 0; ii < vIndex.size() - 2; ii++) {
vertexList[ii * 3] = vIndex.get(0);
vertexList[ii * 3 + 1] = vIndex.get(ii + 1);
vertexList[ii * 3 + 2] = vIndex.get(ii + 2);
}
for (Integer vertex : vertexList) {
if (vertex != null) {
points.add(new Point((int) verticesC1[vertex * 3], (int) verticesC1[vertex * 3 + 1]));
} else {
break;
}
}
System.out.println(vertexList);
}
// points.add(new Point((int)verticesC1[vIndex.get(firstIndex)],(int) verticesC1[vIndex.get(firstIndex)+1]));
// points.add(new Point((int)verticesC1[vIndex.get(ii)*3],(int) verticesC1[vIndex.get(ii)+1]));
// points.add(new Point((int)verticesC1[vIndex.get(ii+1)*3],(int) verticesC1[vIndex.get(ii+1)*3+1]));
// points.add(new Point((int)verticesC1[index],(int)verticesC1[index+1]));
// System.out.println(verticesC1[index]+","+verticesC1[index+1]+","+verticesC1[index+2]);
//System.out.println(tess.primitives.get(i).toString());
}
return points;
}*/
}

View file

@ -1,5 +1,6 @@
package org.dimdev.dimdoors;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.text.TextComponentTranslation;
import org.dimdev.dimdoors.shared.ModConfig;
@ -85,8 +86,9 @@ public class DimDoors {
}
public static void sendTranslatedMessage(Entity entity, String text, Object... translationArgs) {
if (entity instanceof EntityPlayerMP) {
EntityPlayerMP player = (EntityPlayerMP) entity;
// TODO: check if too long and split into several messages?
if (entity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) entity;
player.sendStatusMessage(new TextComponentTranslation(text, translationArgs), ModConfig.general.useStatusBar);
}
}

View file

@ -1,12 +1,12 @@
package org.dimdev.dimdoors.client;
import org.dimdev.dimdoors.shared.world.ModDimensions;
import net.minecraft.client.particle.ParticleSimpleAnimated;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.dimdev.dimdoors.shared.world.ModDimensions;
// This has exactly the same appearence as the 1.6.4 mod.
@SideOnly(Side.CLIENT)
@ -14,35 +14,33 @@ public class ParticleRiftEffect extends ParticleSimpleAnimated { // TODO: colors
private float colorMultiplier;
public ParticleRiftEffect(World world, double x, double y, double z, double motionX, double motionY, double motionZ, float nonPocketColorMultiplier, float pocketColorMultiplier, float scale, int size, int spread) {
public ParticleRiftEffect(World world, double x, double y, double z, double motionX, double motionY, double motionZ, float nonPocketColorMultiplier, float pocketColorMultiplier, float scale, int averageAge, int ageSpread) {
super(world, x, y, z, 160, 8, 0);
this.motionX = motionX;
this.motionY = motionY;
this.motionZ = motionZ;
particleScale *= scale;
particleMaxAge = size - spread / 2 + rand.nextInt(spread);
particleMaxAge = averageAge - ageSpread / 2 + rand.nextInt(ageSpread);
colorMultiplier = ModDimensions.isDimDoorsPocketDimension(world) ? pocketColorMultiplier : nonPocketColorMultiplier;
}
@Override
public void renderParticle(BufferBuilder buffer, Entity entity, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) {
if (particleAge < particleMaxAge / 3 || (particleAge + particleMaxAge) / 3 % 2 == 0) {
float oldRed = particleRed;
float oldGreen = particleGreen;
float oldBlue = particleBlue;
float oldAlpha = particleAlpha;
setRBGColorF(colorMultiplier * particleRed, colorMultiplier * particleGreen, colorMultiplier * particleBlue);
setAlphaF(0.7f);
super.renderParticle(buffer, entity, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ);
setRBGColorF(oldRed, oldGreen, oldBlue);
setAlphaF(oldAlpha);
}
float oldRed = particleRed;
float oldGreen = particleGreen;
float oldBlue = particleBlue;
float oldAlpha = particleAlpha;
setRBGColorF(colorMultiplier * particleRed, colorMultiplier * particleGreen, colorMultiplier * particleBlue);
setAlphaF(1 - (float) particleAge / particleMaxAge);
super.renderParticle(buffer, entity, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ);
setRBGColorF(oldRed, oldGreen, oldBlue);
setAlphaF(oldAlpha);
}
public static class Rift extends ParticleRiftEffect {
public Rift(World world, double x, double y, double z, double motionX, double motionY, double motionZ) {
super(world, x, y, z, motionX, motionY, motionZ, 0.0f, 0.7f, 0.55f, 3800, 1600);
super(world, x, y, z, motionX, motionY, motionZ, 0.0f, 0.7f, 0.55f, 2000, 2000);
}
}

View file

@ -11,7 +11,7 @@ import static org.lwjgl.opengl.GL11.*;
public final class RiftCrackRenderer {
public static void drawCrack(int riftRotation, LSystem.PolygonStorage poly, double size, double xWorld, double yWorld, double zWorld) {
public static void drawCrack(float riftRotation, LSystem.PolygonInfo poly, double size, double xWorld, double yWorld, double zWorld) {
// Calculate the proper size for the rift render
double scale = size / (poly.maxX - poly.minX);
@ -39,11 +39,11 @@ public final class RiftCrackRenderer {
double[] jitters = new double[jCount];
double aggroScaling = size * size * size / 700f;
double jitterScale = size * size * size / 1300f;
// We use random constants here on purpose just to get different wave forms
double xJitter = aggroScaling * Math.sin(1.1f * time*size) * Math.sin(0.8f * time);
double yJitter = aggroScaling * Math.sin(1.2f * time*size) * Math.sin(0.9f * time);
double zJitter = aggroScaling * Math.sin(1.3f * time*size) * Math.sin(0.7f * time);
double xJitter = jitterScale * Math.sin(1.1f * time*size) * Math.sin(0.8f * time);
double yJitter = jitterScale * Math.sin(1.2f * time*size) * Math.sin(0.9f * time);
double zJitter = jitterScale * Math.sin(1.3f * time*size) * Math.sin(0.7f * time);
// generate a series of waveforms
for (int i = 0; i < jCount; i += 1) {

View file

@ -18,17 +18,22 @@ public class TileEntityFloatingRiftRenderer extends TileEntitySpecialRenderer<Ti
private static final ResourceLocation tesseract_path = new ResourceLocation(DimDoors.MODID + ":textures/other/tesseract.png");
private static final Tesseract tesseract = new Tesseract();
public static long showRiftCoreUntil = 0;
@Override
public void render(TileEntityFloatingRift rift, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {
if (ModConfig.graphics.tesseractRifts) {
renderTesseract(rift, x, y, z, partialTicks, destroyStage, alpha);
if (ModConfig.graphics.showRiftCore) {
renderTesseract(rift, x, y, z, partialTicks);
} else {
renderCrack(rift, x, y, z, partialTicks, destroyStage, alpha);
long timeLeft = showRiftCoreUntil - System.currentTimeMillis();
if (timeLeft >= 0/*3000 || timeLeft >= 0 && timeLeft / 500 % 2 == 0*/) {
renderTesseract(rift, x, y, z, partialTicks);
}
}
renderCrack(rift, x, y, z);
}
private void renderCrack(TileEntityFloatingRift rift, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {
private void renderCrack(TileEntityFloatingRift rift, double x, double y, double z) {
GL11.glPushMatrix();
// TODO: Make the sky get dark when a player approaches a rift?
@ -37,11 +42,8 @@ public class TileEntityFloatingRiftRenderer extends TileEntitySpecialRenderer<Ti
GlStateManager.disableCull();
GlStateManager.disableTexture2D();
GlStateManager.enableBlend();
// TODO: This was commented out in the old code, what does it do?
//GlStateManager.colorLogicOp(GlStateManager.LogicOp.INVERT);
//GlStateManager.enableColorLogic();
RiftCrackRenderer.drawCrack(rift.riftRotation, rift.getCurve(), rift.growth / 90, x + 0.5, y + 1.5, z + 0.5);
RiftCrackRenderer.drawCrack(rift.riftYaw, rift.getCurve(), rift.size / 120, x + 0.5, y + 1.5, z + 0.5);
GlStateManager.disableBlend();
GlStateManager.enableTexture2D();
@ -51,7 +53,7 @@ public class TileEntityFloatingRiftRenderer extends TileEntitySpecialRenderer<Ti
GL11.glPopMatrix();
}
private void renderTesseract(TileEntityFloatingRift rift, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {
private void renderTesseract(TileEntityFloatingRift rift, double x, double y, double z, float partialTicks) {
double radian = updateTesseractAngle(rift, partialTicks) * TrigMath.DEG_TO_RAD;
RGBA color = rift.getColor();
if (color == null) color = new RGBA(1, 0.5f, 1, 1);

View file

@ -124,9 +124,14 @@ public final class ModConfig {
}
public static class Graphics {
@Name("tesseractRifts")
@LangKey("dimdoors.graphics.tesseractRifts")
public boolean tesseractRifts = false;
@Name("showRiftCore")
@LangKey("dimdoors.graphics.showRiftCore")
public boolean showRiftCore = false;
@Name("highlightRiftCoreFor")
@LangKey("dimdoors.graphics.highlightRiftCoreFor")
@RangeInt(min = -1)
public int highlightRiftCoreFor = 15000;
}

View file

@ -30,7 +30,6 @@ public class BlockFloatingRift extends BlockSpecialAir implements ITileEntityPro
public static final String ID = "rift";
public BlockFloatingRift() {
// super();
setRegistryName(new ResourceLocation(DimDoors.MODID, ID));
setUnlocalizedName(ID);
setTickRandomly(true);
@ -58,7 +57,6 @@ public class BlockFloatingRift extends BlockSpecialAir implements ITileEntityPro
}
@Override
@SuppressWarnings("deprecation")
public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess world, BlockPos pos) {
if (ModConfig.general.riftBoundingBoxInCreative) {
EntityPlayer player = DimDoors.proxy.getLocalPlayer();
@ -104,6 +102,7 @@ public class BlockFloatingRift extends BlockSpecialAir implements ITileEntityPro
rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D, rand.nextGaussian() * 0.01D));
}
// TODO: depend on size, direction of particles should be rift orientation
FMLClientHandler.instance().getClient().effectRenderer.addEffect(new ParticleRiftEffect.Rift(
world,
pos.getX() + .5, pos.getY() + 1.5, pos.getZ() + .5,

View file

@ -5,6 +5,9 @@ import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.dimdev.dimdoors.DimDoors;
import org.dimdev.dimdoors.client.TileEntityFloatingRiftRenderer;
import org.dimdev.dimdoors.shared.ModConfig;
import org.dimdev.dimdoors.shared.blocks.IRiftProvider;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
@ -21,7 +24,7 @@ import org.dimdev.dimdoors.shared.tileentities.TileEntityFloatingRift;
import java.util.List;
public abstract class ItemDimensionalDoor extends ItemDoor { // TODO: Biomes O' Plenty doors
public abstract class ItemDimensionalDoor extends ItemDoor { // TODO: All wood types, Biome O' Plenty support
public <T extends Block & IRiftProvider<TileEntityEntranceRift>> ItemDimensionalDoor(T block) {
super(block);
@ -29,18 +32,33 @@ public abstract class ItemDimensionalDoor extends ItemDoor { // TODO: Biomes O'
@Override
public EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
BlockPos originalPos = pos; // super.onItemUse needs the actual position
if (!world.getBlockState(pos).getBlock().isReplaceable(world, pos)) pos = pos.offset(facing);
boolean placedOnRift = world.getBlockState(pos).getBlock().equals(ModBlocks.RIFT);
if (!placedOnRift && isRiftNear(world, pos)) {
if (world.isRemote) {
DimDoors.chat(player, "rifts.entrances.rift_too_close"); // TODO: Linebreaks don't work in status message.
TileEntityFloatingRiftRenderer.showRiftCoreUntil = System.currentTimeMillis() + ModConfig.graphics.highlightRiftCoreFor;
}
return EnumActionResult.FAIL;
}
if (world.isRemote) return EnumActionResult.FAIL;
boolean replaceable = world.getBlockState(pos).getBlock().isReplaceable(world, pos);
// Store the rift entity if there's a rift block there that may be broken
TileEntityFloatingRift rift = null;
if (world.getBlockState(replaceable ? pos : pos.offset(facing)).getBlock().equals(ModBlocks.RIFT)) {
rift = (TileEntityFloatingRift) world.getTileEntity(replaceable ? pos : pos.offset(facing));
rift.setUnregisterDisabled(true);
if (placedOnRift) {
if (canBePlacedOnRift()) {
rift = (TileEntityFloatingRift) world.getTileEntity(pos);
rift.setUnregisterDisabled(true);
} else {
DimDoors.sendTranslatedMessage(player, "rifts.entrances.cannot_be_placed_on_rift");
}
}
EnumActionResult result = super.onItemUse(player, world, pos, hand, facing, hitX, hitY, hitZ);
if (!replaceable) pos = pos.offset(facing);
EnumActionResult result = super.onItemUse(player, world, originalPos, hand, facing, hitX, hitY, hitZ);
if (result == EnumActionResult.SUCCESS) {
IBlockState state = world.getBlockState(pos);
if (rift == null) {
@ -66,6 +84,22 @@ public abstract class ItemDimensionalDoor extends ItemDoor { // TODO: Biomes O'
return result;
}
public static boolean isRiftNear(World world, BlockPos pos) {
// TODO: This is called every right click server-side! Is this efficient enough? Maybe use rift registry?
for (int x = pos.getX() - 5; x < pos.getX() + 5; x++) {
for (int y = pos.getY() - 5; y < pos.getY() + 5; y++) {
for (int z = pos.getZ() - 5; z < pos.getZ() + 5; z++) {
BlockPos searchPos = new BlockPos(x, y, z);
if (world.getBlockState(searchPos).getBlock() == ModBlocks.RIFT) {
TileEntityFloatingRift rift = (TileEntityFloatingRift) world.getTileEntity(searchPos);
if (Math.sqrt(pos.distanceSq(searchPos)) < rift.size / 250) return true;
}
}
}
}
return false;
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, World world, List<String> tooltip, ITooltipFlag flag) {

View file

@ -18,7 +18,6 @@ import net.minecraft.world.World;
import org.dimdev.ddutils.RotatedLocation;
import org.dimdev.dimdoors.shared.blocks.ModBlocks;
import org.dimdev.dimdoors.shared.rifts.DestinationMaker;
import org.dimdev.dimdoors.shared.rifts.destinations.GlobalDestination;
import org.dimdev.dimdoors.shared.sound.ModSounds;
import org.dimdev.dimdoors.shared.tileentities.TileEntityFloatingRift;

View file

@ -18,7 +18,6 @@ import org.dimdev.dimdoors.DimDoors;
import org.dimdev.ddutils.RotatedLocation;
import org.dimdev.dimdoors.shared.blocks.ModBlocks;
import org.dimdev.dimdoors.shared.rifts.DestinationMaker;
import org.dimdev.dimdoors.shared.rifts.destinations.GlobalDestination;
import org.dimdev.dimdoors.shared.sound.ModSounds;
import org.dimdev.dimdoors.shared.tileentities.TileEntityFloatingRift;

View file

@ -37,20 +37,20 @@ import java.util.Random;
// TODO: Some of these properties will need to persist when converting to door and then back to rift!
//Need to be saved:
@Saved /*package-private*/ int updateTimer;
@Saved public boolean closing = false; // TODO: maybe we could have a closingSpeed instead?
@Saved public int spawnedEndermenID = 0;
@Saved public float growth = 0;
@Saved protected float teleportTargetYaw;
@Saved protected float teleportTargetPitch;
@Saved public float size = 0; // TODO: store size in blocks
@Saved public float riftYaw = random.nextInt(360);
@Saved protected float teleportTargetPitch; // TODO: also render rift rotated on pitch axis?
@Saved public int curveId = random.nextInt(LSystem.curves.size());
@Saved public int riftRotation = random.nextInt(360);
// Don't need to be saved
@Setter private boolean unregisterDisabled = false;
int updateTimer;
@SideOnly(Side.CLIENT) public double renderAngle; // This is @SideOnly(Side.CLIENT), don't initialize the field ( = 0), or class initialization won't work on the server!
@SideOnly(Side.CLIENT) private int cachedCurveId;
@SideOnly(Side.CLIENT) private LSystem.PolygonStorage curve; // Cache the curve for efficiency
@SideOnly(Side.CLIENT) private LSystem.PolygonInfo curve; // Cache the curve for efficiency
public TileEntityFloatingRift() {
updateTimer = random.nextInt(UPDATE_PERIOD);
@ -67,8 +67,8 @@ import java.util.Random;
// Check if this rift should render white closing particles and
// spread the closing effect to other rifts nearby.
if (closing) {
if (growth > 0) {
growth -= ModConfig.general.riftCloseSpeed;
if (size > 0) {
size -= ModConfig.general.riftCloseSpeed;
} else {
world.setBlockToAir(pos);
}
@ -86,7 +86,7 @@ import java.util.Random;
// Logarithmic growth
for (int n = 0; n < 10; n++) {
// TODO: growthSpeed and growthSize config options
growth += 1F / (growth + 1);
size += 1F / (size + 1);
}
}
@ -164,7 +164,7 @@ import java.util.Random;
}
public void setTeleportTargetRotation(float yaw, float pitch) {
teleportTargetYaw = yaw;
riftYaw = yaw;
teleportTargetPitch = pitch;
markDirty();
}
@ -180,7 +180,7 @@ import java.util.Random;
}
@Override public float getDestinationYaw(float entityYaw) {
return teleportTargetYaw;
return riftYaw;
}
@Override public float getDestinationPitch(float entityPitch) {
@ -188,7 +188,7 @@ import java.util.Random;
}
@SideOnly(Side.CLIENT)
public LSystem.PolygonStorage getCurve() {
public LSystem.PolygonInfo getCurve() {
if (curve != null && curveId == cachedCurveId) {
return curve;
}

View file

@ -118,6 +118,8 @@ rifts.destinations.escape.did_not_use_rift=You didn't use a rift to enter the po
rifts.destinations.escape.rift_has_closed=The rift you used to enter the pocket dimension has closed and you ended up in Limbo!
rifts.destinations.private_pocket_exit.did_not_use_rift=You didn't use a rift to enter the pocket dimension and you ended up in Limbo!
rifts.destinations.private_pocket_exit.rift_has_closed=The rift you used to enter the pocket dimension has closed and you ended up in Limbo!
rifts.entrances.rift_too_close=Placing a door this close to a tear in the world would be dangerous. Either place it on the rift's core (tesseract) or further away. Or use a rift signature to make a rift anyway, at your own risk!
rifts.entrances.cannot_be_placed_on_rift=This type of door can't be placed on a rift.
dimdoors.general=General Options
dimdoors.general.tooltip=General configuration options for the mod