MinecraftGRPF/src/com/mojang/minecraft/level/levelgen/LevelGen.java

260 lines
10 KiB
Java

//
// Decompiled by Procyon v0.5.36
//
package com.mojang.minecraft.level.levelgen;
import java.util.ArrayList;
import com.mojang.minecraft.level.tile.Tile;
import com.mojang.minecraft.level.Level;
import java.util.Random;
import com.mojang.minecraft.level.LevelLoaderListener;
public class LevelGen
{
private LevelLoaderListener levelLoaderListener;
private int width;
private int height;
private int depth;
private Random random;
private byte[] blocks;
private int[] coords;
public LevelGen(final LevelLoaderListener levelLoaderListener) {
this.random = new Random();
this.coords = new int[1048576];
this.levelLoaderListener = levelLoaderListener;
}
public boolean generateLevel(final Level level, final String userName, final int width, final int height, final int depth) {
this.levelLoaderListener.beginLevelLoading("Generating level");
this.width = width;
this.height = height;
this.depth = depth;
this.blocks = new byte[width * height * depth];
this.levelLoaderListener.levelLoadUpdate("Raising..");
final double[] heightMap = this.buildHeightmap(width, height);
this.levelLoaderListener.levelLoadUpdate("Eroding..");
this.buildBlocks(heightMap);
this.levelLoaderListener.levelLoadUpdate("Carving..");
this.carveTunnels();
this.levelLoaderListener.levelLoadUpdate("Watering..");
this.addWater();
this.levelLoaderListener.levelLoadUpdate("Melting..");
this.addLava();
level.setData(width, depth, height, this.blocks);
level.createTime = System.currentTimeMillis();
level.creator = userName;
level.name = "A Nice World";
return true;
}
private void buildBlocks(final double[] heightMap) {
final int w = this.width;
final int h = this.height;
final int d = this.depth;
for (int x = 0; x < w; ++x) {
for (int y = 0; y < d; ++y) {
for (int z = 0; z < h; ++z) {
final int dh = d / 2;
final int rh = d / 3;
final int i = (y * this.height + z) * this.width + x;
int id = 0;
if (y == dh && y >= d / 2 - 1) {
id = Tile.grass.id;
}
else if (y <= dh) {
id = Tile.dirt.id;
}
if (y <= rh) {
id = Tile.rock.id;
}
this.blocks[i] = (byte)id;
}
}
}
}
private double[] buildHeightmap(final int width, final int height) {
final double[] heightmap = new double[width * height];
return heightmap;
}
public void carveTunnels() {
final int w = this.width;
final int h = this.height;
final int d = this.depth;
for (int count = w * h * d / 256 / 64, i = 0; i < count; ++i) {
float x = this.random.nextFloat() * w;
float y = this.random.nextFloat() * d;
float z = this.random.nextFloat() * h;
final int length = (int)(this.random.nextFloat() + this.random.nextFloat() * 150.0f);
float dir1 = (float)(this.random.nextFloat() * 3.141592653589793 * 2.0);
float dira1 = 0.0f;
float dir2 = (float)(this.random.nextFloat() * 3.141592653589793 * 2.0);
float dira2 = 0.0f;
for (int l = 0; l < length; ++l) {
x += (float)(Math.sin(dir1) * Math.cos(dir2));
z += (float)(Math.cos(dir1) * Math.cos(dir2));
y += (float)Math.sin(dir2);
dir1 += dira1 * 0.2f;
dira1 *= 0.9f;
dira1 += this.random.nextFloat() - this.random.nextFloat();
dir2 += dira2 * 0.5f;
dir2 *= 0.5f;
dira2 *= 0.9f;
dira2 += this.random.nextFloat() - this.random.nextFloat();
final float size = (float)(Math.sin(l * 3.141592653589793 / length) * 2.5 + 1.0);
for (int xx = (int)(x - size); xx <= (int)(x + size); ++xx) {
for (int yy = (int)(y - size); yy <= (int)(y + size); ++yy) {
for (int zz = (int)(z - size); zz <= (int)(z + size); ++zz) {
final float xd = xx - x;
final float yd = yy - y;
final float zd = zz - z;
final float dd = xd * xd + yd * yd * 2.0f + zd * zd;
if (dd < size * size && xx >= 1 && yy >= 1 && zz >= 1 && xx < this.width - 1 && yy < this.depth - 1 && zz < this.height - 1) {
final int ii = (yy * this.height + zz) * this.width + xx;
if (this.blocks[ii] == Tile.rock.id) {
this.blocks[ii] = 0;
}
}
}
}
}
}
}
}
public void addWater() {
final long before = System.nanoTime();
long tiles = 0L;
final int source = 0;
final int target = Tile.calmWater.id;
for (int x = 0; x < this.width; ++x) {
tiles += this.floodFillLiquid(x, this.depth / 2 - 1, 0, source, target);
tiles += this.floodFillLiquid(x, this.depth / 2 - 1, this.height - 1, source, target);
}
for (int y = 0; y < this.height; ++y) {
tiles += this.floodFillLiquid(0, this.depth / 2 - 1, y, source, target);
tiles += this.floodFillLiquid(this.width - 1, this.depth / 2 - 1, y, source, target);
}
for (int i = 0; i < this.width * this.height / 5000; ++i) {
final int x2 = this.random.nextInt(this.width);
final int y2 = this.depth / 2 - 1;
final int z = this.random.nextInt(this.height);
if (this.blocks[(y2 * this.height + z) * this.width + x2] == 0) {
tiles += this.floodFillLiquid(x2, y2, z, 0, target);
}
}
final long after = System.nanoTime();
System.out.println("Flood filled " + tiles + " tiles in " + (after - before) / 1000000.0 + " ms");
}
public void addLava() {
int lavaCount = 0;
for (int i = 0; i < this.width * this.height * this.depth / 10000; ++i) {
final int x = this.random.nextInt(this.width);
final int y = this.random.nextInt(this.depth / 2);
final int z = this.random.nextInt(this.height);
if (this.blocks[(y * this.height + z) * this.width + x] == 0) {
++lavaCount;
this.floodFillLiquid(x, y, z, 0, Tile.calmLava.id);
}
}
System.out.println("LavaCount: " + lavaCount);
}
public long floodFillLiquid(final int x, final int y, final int z, final int source, final int tt) {
final byte target = (byte)tt;
final ArrayList<int[]> coordBuffer = new ArrayList<int[]>();
int p = 0;
int wBits = 1;
int hBits = 1;
while (1 << wBits < this.width) {
++wBits;
}
while (1 << hBits < this.height) {
++hBits;
}
final int hMask = this.height - 1;
final int wMask = this.width - 1;
this.coords[p++] = ((y << hBits) + z << wBits) + x;
long tiles = 0L;
final int upStep = this.width * this.height;
while (p > 0) {
int cl = this.coords[--p];
if (p == 0 && coordBuffer.size() > 0) {
System.out.println("IT HAPPENED!");
this.coords = coordBuffer.remove(coordBuffer.size() - 1);
p = this.coords.length;
}
final int z2 = cl >> wBits & hMask;
final int y2 = cl >> wBits + hBits;
int x3;
int x2;
for (x2 = (x3 = (cl & wMask)); x2 > 0; --x2, --cl) {
if (this.blocks[cl - 1] != source) {
break;
}
}
while (x3 < this.width && this.blocks[cl + x3 - x2] == source) {
++x3;
}
final int z3 = cl >> wBits & hMask;
final int y3 = cl >> wBits + hBits;
if (z3 != z2 || y3 != y2) {
System.out.println("hoooly fuck");
}
boolean lastNorth = false;
boolean lastSouth = false;
boolean lastBelow = false;
tiles += x3 - x2;
for (int xx = x2; xx < x3; ++xx) {
this.blocks[cl] = target;
if (z2 > 0) {
final boolean north = this.blocks[cl - this.width] == source;
if (north && !lastNorth) {
if (p == this.coords.length) {
coordBuffer.add(this.coords);
this.coords = new int[1048576];
p = 0;
}
this.coords[p++] = cl - this.width;
}
lastNorth = north;
}
if (z2 < this.height - 1) {
final boolean south = this.blocks[cl + this.width] == source;
if (south && !lastSouth) {
if (p == this.coords.length) {
coordBuffer.add(this.coords);
this.coords = new int[1048576];
p = 0;
}
this.coords[p++] = cl + this.width;
}
lastSouth = south;
}
if (y2 > 0) {
final int belowId = this.blocks[cl - upStep];
if ((target == Tile.lava.id || target == Tile.calmLava.id) && (belowId == Tile.water.id || belowId == Tile.calmWater.id)) {
this.blocks[cl - upStep] = (byte)Tile.rock.id;
}
final boolean below = belowId == source;
if (below && !lastBelow) {
if (p == this.coords.length) {
coordBuffer.add(this.coords);
this.coords = new int[1048576];
p = 0;
}
this.coords[p++] = cl - upStep;
}
lastBelow = below;
}
++cl;
}
}
return tiles;
}
}