Browse Source

Fixed generation bug by writing a better RNG, and separated types into different files

master
Thomas Johnson 2 years ago
parent
commit
5b61f6608e
  1. 1
      src/main/java/t/j/dual/CommandDimension.java
  2. 2
      src/main/java/t/j/dual/Dual.java
  3. 86
      src/main/java/t/j/dual/PointGrid.java
  4. 16
      src/main/java/t/j/dual/PointList.java
  5. 24
      src/main/java/t/j/dual/PointWorld.java
  6. 29
      src/main/java/t/j/dual/RandomPointWorld.java
  7. 73
      src/main/java/t/j/dual/Utilities.java
  8. 179
      src/main/java/t/j/dual/WorldProviderPeace.java

1
src/main/java/t/j/dual/CommandDimension.java

@ -41,6 +41,7 @@ public class CommandDimension extends CommandBase {
throw new CommandException("That dimension isn't registered!");
}
server.getPlayerList().transferPlayerToDimension(player, dimid, itp);
logger.info("Transferred player");
}
}

2
src/main/java/t/j/dual/Dual.java

@ -20,6 +20,7 @@ import org.apache.logging.log4j.Logger;
import t.j.dual.WorldProviderPeace;
import t.j.dual.CommandDimension;
import t.j.dual.Utilities;
@Mod(modid = Dual.MODID, name = Dual.NAME, version = Dual.VERSION)
public class Dual
@ -36,6 +37,7 @@ public class Dual
public void preInit(FMLPreInitializationEvent event)
{
logger = event.getModLog();
Utilities.logger = logger;
}
@EventHandler

86
src/main/java/t/j/dual/PointGrid.java

@ -0,0 +1,86 @@
package t.j.dual;
import java.util.Iterator;
import net.minecraft.util.math.*;
import t.j.dual.PointList;
public class PointGrid implements PointList {
public Vec3d origin;
public Vec3d step;
public Vec3i extent;
public class Iter implements Iterator<Vec3d> {
public PointGrid grid;
int x, y, z;
public Iter(PointGrid grid) {
this.x = 0;
this.y = 0;
this.z = 0;
this.grid = grid;
}
public boolean hasNext() {
return z < grid.extent.getZ();
}
public Vec3d next() {
Vec3d result = new Vec3d(origin.x + x * step.x, origin.y + y * step.y, origin.z + z * step.z);
x += 1;
if (x == grid.extent.getX()) {
x = 0;
y += 1;
if (y == grid.extent.getY()) {
y = 0;
z += 1;
}
}
return result;
}
}
public PointGrid(Vec3d origin, Vec3i extent, Vec3d step) {
this.origin = origin;
this.extent = extent;
this.step = step;
}
public PointGrid(Vec3d origin, Vec3d remote, Vec3i extent) {
this.origin = origin;
this.extent = extent;
Vec3d size = remote.subtract(origin);
Vec3d divisor = new Vec3d(extent.getX() - 1, extent.getY() - 1, extent.getZ() - 1);
this.step = new Vec3d(size.x / divisor.x, size.y / divisor.y, size.z / divisor.z);
}
public int numPoints() {
return extent.getX() * extent.getY() * extent.getZ();
}
public Vec3d nth(int idx) {
int coordX = idx / (extent.getY() * extent.getZ());
int remX = idx % (extent.getY() * extent.getZ());
int coordY = remX / extent.getZ();
int coordZ = remX % extent.getZ();
return new Vec3d(origin.x + coordX * step.x, origin.y + coordY * step.y, origin.z + coordZ * step.z);
}
public Iterator<Vec3d> iterator() {
return new Iter(this);
}
public Vec3d center() {
return new Vec3d(origin.x + (extent.getX() - 1) * step.x / 2.0, origin.y + (extent.getY() - 1) * step.y / 2.0, origin.z + (extent.getZ() - 1) * step.z / 2.0);
}
public Vec3d origin() {
return origin;
}
public Vec3d remote() {
return new Vec3d(origin.x + (extent.getX() - 1) * step.x, origin.y + (extent.getY() - 1) * step.y, origin.z + (extent.getZ() - 1) * step.z);
}
}

16
src/main/java/t/j/dual/PointList.java

@ -0,0 +1,16 @@
package t.j.dual;
import java.util.Iterator;
import net.minecraft.util.math.*;
public interface PointList {
int numPoints();
Vec3d nth(int idx);
Vec3d center();
public Iterator<Vec3d> iterator();
// bounding box:
Vec3d origin();
Vec3d remote();
}

24
src/main/java/t/j/dual/PointWorld.java

@ -0,0 +1,24 @@
package t.j.dual;
import java.util.Random;
import java.util.ArrayList;
import net.minecraft.util.math.*;
interface PointWorld {
public Vec3d[] pointsInCell(Vec3i cell);
default public ArrayList<Vec3d> pointsInAABB(Vec3d origin, Vec3d remote) {
ArrayList<Vec3d> points = new ArrayList<Vec3d>();
for (int x = (int) Math.floor(origin.x); x < (int) Math.ceil(remote.x); x++) {
for (int y = (int) Math.floor(origin.y); y < (int) Math.ceil(remote.y); y++) {
for (int z = (int) Math.floor(origin.z); z < (int) Math.ceil(remote.z); z++) {
for (Vec3d point : pointsInCell(new Vec3i(x, y, z))) {
points.add(point);
}
}
}
}
return points;
}
}

29
src/main/java/t/j/dual/RandomPointWorld.java

@ -0,0 +1,29 @@
package t.j.dual;
import net.minecraft.util.math.*;
import java.util.Random;
import java.util.ArrayList;
import t.j.dual.PointWorld;
class RandomPointWorld implements PointWorld {
long seed;
Random random;
public RandomPointWorld(Random random, long seed) {
this.seed = seed;
this.random = random;
}
public Vec3d[] pointsInCell(Vec3i cell) {
random.setSeed(seed ^ cell.getX());
random.setSeed(random.nextLong() ^ cell.getY());
random.setSeed(random.nextLong() ^ cell.getZ());
int nPoints = Utilities.drawPoisson(random, 1.0f);
Vec3d[] points = new Vec3d[nPoints];
for (int i = 0; i < nPoints; i++) {
points[i] = new Vec3d(cell.getX() + random.nextDouble(), cell.getY() + random.nextDouble(), cell.getZ() + random.nextDouble());
}
return points;
}
}

73
src/main/java/t/j/dual/Utilities.java

@ -0,0 +1,73 @@
package t.j.dual;
import java.util.Random;
import net.minecraft.util.math.*;
import org.apache.logging.log4j.Logger;
class Utilities {
public static Logger logger;
public static int drawPoisson(Random random, float mean) {
float target = (float) Math.exp(-mean);
float l = 1.0f;
int result = 0;
while (l > target) {
result += 1;
l *= random.nextFloat();
}
return result - 1;
}
public static boolean inBoundingBox(Vec3d point, Vec3d origin, Vec3d remote) {
return origin.x < point.x && point.x < remote.x &&
origin.y < point.y && point.y < remote.y &&
origin.z < point.z && point.z < remote.z;
}
public static class LFSRRandom extends Random {
private long seed;
public LFSRRandom(long seed) {
this.seed = seed;
}
// One step of a linear feedback shift register using an order-63
// irreducible binary trinomial. Howver, there's a caveat: the stretch of
// 63 zeros is extended to 64 zeroes. This is to (a) prevent degeneraccy
// when the LFSR's seed becomes zero; and (b) balance the number of zeroes
// and ones exactly.
public long shiftAndFeedback(long in) {
if ((in & 0x7fffffff) == 0) {
if (in == 0) {
return 1;
} else {
return 0;
}
} else {
long xor = (in ^ (in >>> 1) ^ (in >>> 63)) & 1;
long rv = (in << 1) | xor;
return rv;
}
}
public void setSeed(long seed) {
this.seed = seed;
}
protected int next(int bits) {
for (int i = 0; i <= bits; i++) {
seed = shiftAndFeedback(seed);
}
int mask;
if (bits == 32) {
mask = -1;
} else {
mask = (1 << bits) - 1;
}
int trimmed = (int) (seed & mask);
return trimmed;
}
}
}

179
src/main/java/t/j/dual/WorldProviderPeace.java

@ -21,6 +21,8 @@ import net.minecraft.block.properties.IProperty;
import net.minecraft.init.Blocks;
import org.apache.logging.log4j.Logger;
import t.j.dual.Utilities;
public class WorldProviderPeace extends WorldProvider {
public static DimensionType dimType;
@ -47,8 +49,8 @@ class BedrockChunkGenerator implements IChunkGenerator {
public BedrockChunkGenerator(World w) {
world = w;
this.pointworld = new PointWorld(world.getSeed());
this.random = new Random();
this.random = new Utilities.LFSRRandom(0);
this.pointworld = new RandomPointWorld(random, world.getSeed());
}
public Chunk generateChunk(int X, int Z) {
@ -59,22 +61,32 @@ class BedrockChunkGenerator implements IChunkGenerator {
primer.setBlockState(x, 0, z, Blocks.BEDROCK.getDefaultState());
}
}
WorldProviderPeace.logger.info("points:" + X + " " + Z);
List<Vec3d> points = pointworld.pointsInAABB(random, new Vec3d(8 * X, 0, 8 * Z), new Vec3d(8 * X + 8, 8 * 16, 8 * Z + 8));
WorldProviderPeace.logger.info("blocks: " + X + " " + Z);
int i = 0;
for (Vec3d point: points) {
i++;
primer.setBlockState((int) (2 * (point.x - 8 * X)), (int) (2 * point.y), (int) (2 * (point.z - 8 * Z)), Blocks.REDSTONE_BLOCK.getDefaultState());
if (((X ^ Z) & 3) >= 0) {
double scale = 8;
double perchunk = 16 / scale;
WorldProviderPeace.logger.info("points:" + X + " " + Z);
List<Vec3d> points = pointworld.pointsInAABB(new Vec3d(perchunk * X, 0, perchunk * Z), new Vec3d(perchunk * X + perchunk, perchunk * 16, perchunk * Z + perchunk));
WorldProviderPeace.logger.info("blocks: " + X + " " + Z);
int i = 0;
int totalz = 0;
for (Vec3d point: points) {
i++;
int x = (int) (scale * (point.x - perchunk * X));
int y = (int) (scale * point.y);
int z = (int) (scale * (point.z - perchunk * Z));
totalz += z;
primer.setBlockState(x, y, z, Blocks.STONE.getDefaultState());
}
WorldProviderPeace.logger.info("(generated " + i + " blocks): " + X + " " + Z);
WorldProviderPeace.logger.info("mean z: " + totalz / (double) i);
}
WorldProviderPeace.logger.info("(generated " + i + " blocks): " + X + " " + Z);
WorldProviderPeace.logger.info("chunk: " + X + " " + Z);
primer.setBlockState(0, 255, 0, Blocks.GOLD_BLOCK.getDefaultState());
primer.setBlockState(15, 255, 0, Blocks.GOLD_BLOCK.getDefaultState());
primer.setBlockState(15, 255, 15, Blocks.GOLD_BLOCK.getDefaultState());
primer.setBlockState(0, 255, 15, Blocks.GOLD_BLOCK.getDefaultState());
Chunk chunk = new Chunk(world, primer, X, Z);
//chunk.generateSkylightMap();
chunk.generateSkylightMap();
WorldProviderPeace.logger.info("done: " + X + " " + Z);
return chunk;
}
@ -107,148 +119,3 @@ class BedrockChunkGenerator implements IChunkGenerator {
}
}
class Utilities {
public static int drawPoisson(Random random, float mean) {
float target = (float) Math.exp(-mean);
float l = 1.0f;
int result = 0;
while (l > target) {
result += 1;
l *= random.nextFloat();
}
return result - 1;
}
public static boolean inBoundingBox(Vec3d point, Vec3d origin, Vec3d remote) {
return origin.x < point.x && point.x < remote.x &&
origin.y < point.y && point.y < remote.y &&
origin.z < point.z && point.z < remote.z;
}
}
interface PointList {
int numPoints();
Vec3d nth(int idx);
Vec3d center();
public Iterator<Vec3d> iterator();
// bounding box:
Vec3d origin();
Vec3d remote();
}
class PointGrid implements PointList {
public Vec3d origin;
public Vec3d step;
public Vec3i extent;
public class Iter implements Iterator<Vec3d> {
public PointGrid grid;
int x, y, z;
public Iter(PointGrid grid) {
this.x = 0;
this.y = 0;
this.z = 0;
this.grid = grid;
}
public boolean hasNext() {
return z < grid.extent.getZ();
}
public Vec3d next() {
Vec3d result = new Vec3d(origin.x + x * step.x, origin.y + y * step.y, origin.z + z * step.z);
x += 1;
if (x == grid.extent.getX()) {
x = 0;
y += 1;
if (y == grid.extent.getY()) {
y = 0;
z += 1;
}
}
return result;
}
}
public PointGrid(Vec3d origin, Vec3i extent, Vec3d step) {
this.origin = origin;
this.extent = extent;
this.step = step;
}
public PointGrid(Vec3d origin, Vec3d remote, Vec3i extent) {
this.origin = origin;
this.extent = extent;
Vec3d size = remote.subtract(origin);
Vec3d divisor = new Vec3d(extent.getX() - 1, extent.getY() - 1, extent.getZ() - 1);
this.step = new Vec3d(size.x / divisor.x, size.y / divisor.y, size.z / divisor.z);
}
public int numPoints() {
return extent.getX() * extent.getY() * extent.getZ();
}
public Vec3d nth(int idx) {
int coordX = idx / (extent.getY() * extent.getZ());
int remX = idx % (extent.getY() * extent.getZ());
int coordY = remX / extent.getZ();
int coordZ = remX % extent.getZ();
return new Vec3d(origin.x + coordX * step.x, origin.y + coordY * step.y, origin.z + coordZ * step.z);
}
public Iterator<Vec3d> iterator() {
return new Iter(this);
}
public Vec3d center() {
return new Vec3d(origin.x + (extent.getX() - 1) * step.x / 2.0, origin.y + (extent.getY() - 1) * step.y / 2.0, origin.z + (extent.getZ() - 1) * step.z / 2.0);
}
public Vec3d origin() {
return origin;
}
public Vec3d remote() {
return new Vec3d(origin.x + (extent.getX() - 1) * step.x, origin.y + (extent.getY() - 1) * step.y, origin.z + (extent.getZ() - 1) * step.z);
}
}
class PointWorld {
long seed;
public PointWorld(long seed) {
this.seed = seed;
}
public Vec3d[] pointsInCell(Random random, Vec3i cell) {
random.setSeed(seed ^ cell.hashCode());
int nPoints = Utilities.drawPoisson(random, 1.0f);
Vec3d[] points = new Vec3d[nPoints];
for (int i = 0; i < nPoints; i++) {
points[i] = new Vec3d(cell.getX() + random.nextDouble(), cell.getY() + random.nextDouble(), cell.getZ() + random.nextDouble());
}
return points;
}
public ArrayList<Vec3d> pointsInAABB(Random random, Vec3d origin, Vec3d remote) {
ArrayList<Vec3d> points = new ArrayList<Vec3d>();
for (int x = (int) Math.floor(origin.x); x <= (int) Math.ceil(remote.x); x++) {
for (int y = (int) Math.floor(origin.y); y <= (int) Math.ceil(remote.y); y++) {
for (int z = (int) Math.floor(origin.z); z <= (int) Math.ceil(remote.z); z++) {
for (Vec3d point : pointsInCell(random, new Vec3i(x, y, z))) {
if (Utilities.inBoundingBox(point, origin, remote)) {
points.add(point);
}
}
}
}
}
return points;
}
public double[][] voronoiNoise(Random random, PointList evalAt) {
return new double[0][0];
}
}
Loading…
Cancel
Save