// // 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 coordBuffer = new ArrayList(); 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; } }