Path: blob/main/projects/minecraft-classic/assets/js/RandomLevelWorker.js
1835 views
// World generation as a worker.1function Distort (source, distort) {23this.source = source;4this.distort = distort;56this.getValue = function(x, y) {7return this.source.getValue(x + this.distort.getValue(x, y), y);8}910}1112function ImprovedNoise (random) {1314var fadeCurve = function(d0) {15return d0 * d0 * d0 * (d0 * (d0 * 6.0 - 15.0) + 10.0);16}1718var lerp = function(d0, d1, d2) {19return d1 + d0 * (d2 - d1);20}2122var grad = function(i, d0, d1, d2) {23var d3 = (i &= 15) < 8 ? d0 : d1;24var d4 = i < 4 ? d1 : (i != 12 && i != 14 ? d2 : d0);2526return ((i & 1) == 0 ? d3 : -d3) + ((i & 2) == 0 ? d4 : -d4);27}282930this.p = [];3132for (var i = 0; i < 256; i++) {33this.p[i] = i;34}3536for (var i = 0; i < 256; i++) {37//var j = random.nextInt(256 - i) + i;38//var j = Math.round( Math.random() * 256-i ) + i;39var j = Math.round( random * (256-i) ) + i;4041var tmp = this.p[i];42this.p[i] = this.p[j];43this.p[j] = tmp;4445this.p[i + 256] = this.p[i];46}474849this.getValue = function(d0, d1) {50var d2 = 0.0;51var d3 = d1;52var d4 = d0;53var i = Math.floor(d0) & 255;54var j = Math.floor(d1) & 255;55var k = Math.floor(0.0) & 255;5657d4 -= Math.floor(d4);58d3 -= Math.floor(d3);59d2 = 0.0 - Math.floor(0.0);60var d5 = fadeCurve(d4);61var d6 = fadeCurve(d3);62var d7 = fadeCurve(d2);63var l = this.p[i] + j;64var i1 = this.p[l] + k;6566l = this.p[l + 1] + k;67i = this.p[i + 1] + j;68j = this.p[i] + k;69i = this.p[i + 1] + k;70return lerp(d7, lerp(d6, lerp(d5, grad(this.p[i1], d4, d3, d2), grad(this.p[j], d4 - 1.0, d3, d2)), lerp(d5, grad(this.p[l], d4, d3 - 1.0, d2), grad(this.p[i], d4 - 1.0, d3 - 1.0, d2))), lerp(d6, lerp(d5, grad(this.p[i1 + 1], d4, d3, d2 - 1.0), grad(this.p[j + 1], d4 - 1.0, d3, d2 - 1.0)), lerp(d5, grad(this.p[l + 1], d4, d3 - 1.0, d2 - 1.0), grad(this.p[i + 1], d4 - 1.0, d3 - 1.0, d2 - 1.0))));71}7273}7475function PerlinNoise (random, levels) {7677//var ImprovedNoise = require("./ImprovedNoise.js");7879var noiseLevels = [];80var levels = 8;8182for (var i = 0; i < 8; ++i) {83noiseLevels[i] = new ImprovedNoise(random);84}8586this.getValue = function(x, y) {87var value = 0;88var pow = 1;8990for (var i = 0; i < levels; i++) {91value += noiseLevels[i].getValue(x * pow, y * pow) / pow;92pow /= 2;93}9495return value;96}9798}99100/**101* Creates a pseudo-random value generator. The seed must be an integer.102*103* Uses an optimized version of the Park-Miller PRNG.104* http://www.firstpr.com.au/dsp/rand31/105*/106function Random(seed) {107this._seed = seed % 2147483647;108if (this._seed <= 0) this._seed += 2147483646;109}110111/**112* Returns a pseudo-random value between 1 and 2^32 - 2.113*/114Random.prototype.next = function () {115return this._seed = this._seed * 16807 % 2147483647;116};117118Random.prototype.nextInt = function (max) {119return Math.floor( this.nextFloat()*max );120};121122/**123* Returns a pseudo-random floating point number in range [0, 1).124*/125Random.prototype.nextFloat = function (opt_minOrMax, opt_max) {126// We know that result of next() will be 1 to 2147483646 (inclusive).127return (this.next() - 1) / 2147483646;128};129130131var RandomLevel = function () {132133var progress = {134string: "",135percent: 0,136tiles: null137}138139this.createLevel = function(seed, xSize, zSize, ySize) {140141//this.progressRenderer.progressStart("Generating level");142//return;143var random = new Random(seed);144145146this.xSize = xSize;147this.zSize = zSize;148this.ySize = 64;149this.random = random.nextFloat();150this.tiles = [];//new Array(xSize*zSize*ySize);//[];151this.fillQueue = [];152153//console.log(this.random);154155// grow156this.grow = function(aint) {157var i = this.xSize;158var j = this.zSize;159var k = this.ySize;160var perlinnoise = new PerlinNoise(this.random, 8);161var perlinnoise1 = new PerlinNoise(this.random, 8);162163for (var l = 0; l < i; ++l) {164//this.progress(l * 100 / (this.xSize - 1));165progress.percent = l * 100 / (this.xSize - 1);166self.postMessage(progress);167168for (var i1 = 0; i1 < j; ++i1) {169var flag = perlinnoise.getValue( l, i1) > 8.0;170var flag1 = perlinnoise1.getValue( l, i1) > 12.0;171var j1;172var k1 = parseInt( ((j1 = parseInt(aint[l + i1 * i],10)) * this.zSize + i1) * this.xSize + l, 10);173var l1;174// 7 waterid175//if (((l1 = this.tiles[((j1 + 1) * this.zSize + i1) * this.xSize + l] & 255) == 7) && j1 <= k / 2 - 1 && flag1) {176if (((l1 = parseInt(this.tiles[((j1 + 1) * this.zSize + i1) * this.xSize + l],10) & 255) == 7) && j1 <= k / 2 - 1 && flag1) {177178this.tiles[k1] = 12;//(byte) Tile.gravel.id;179}180181if (l1 == 0) {182var i2 = 1;//Tile.grass.id;183184if (j1 <= k / 2 - 1 && flag) {185i2 = 11;//Tile.sand.id;186}187188this.tiles[k1] = i2;189}190}191}192193}194195// melt196this.melt = function() {197var i = 0;198var j = this.xSize * this.zSize * this.ySize / 10000;199200for (var k = 0; k < j; ++k) {201if (k % 100 == 0) {202// this.progress(k * 100 / (j - 1));203progress.percent = k * 100 / (j - 1);204self.postMessage(progress);205}206207var extray = 16;208209var l = random.nextInt(this.xSize);210var i1 = random.nextInt(this.ySize / 2 - 4) + extray;211var j1 = random.nextInt(this.zSize);212213if (this.tiles[(i1 * this.zSize + j1) * this.xSize + l] == 0) {214++i;215//this.floodFill(l, i1, j1, 0, Tile.calmLava.id);216this.floodFill(l, i1, j1, 0, 17);217218}219}220221//this.progress(100);222//System.out.println("LavaCount: " + i);223//console.log("LavaCount: " + i);224}225226// plant227this.plant = function(aint) {228var i = this.xSize;229var j = this.xSize * this.zSize / 4000;230231for (var k = 0; k < j; ++k) {232//this.progress(k * 100 / (j - 1));233progress.percent = k * 100 / (j - 1);234self.postMessage(progress);235236var l = random.nextInt(this.xSize);237var i1 = random.nextInt(this.zSize);238239for (var j1 = 0; j1 < 20; ++j1) {240var k1 = l;241var l1 = i1;242243for (var i2 = 0; i2 < 20; ++i2) {244k1 += random.nextInt(6) - random.nextInt(6);245l1 += random.nextInt(6) - random.nextInt(6);246if (k1 >= 0 && l1 >= 0 && k1 < this.xSize && l1 < this.zSize) {247var j2 = aint[k1 + l1 * i] + 1;248var k2 = random.nextInt(3) + 4;249var flag = true;250251var l2;252var i3;253var j3;254255for (l2 = j2; l2 <= j2 + 1 + k2; ++l2) {256var b0 = 1;257258if (l2 >= j2 + 1 + k2 - 2) {259b0 = 2;260}261262for (i3 = k1 - b0; i3 <= k1 + b0 && flag; ++i3) {263for (j3 = l1 - b0; j3 <= l1 + b0 && flag; ++j3) {264if (i3 >= 0 && l2 >= 0 && j3 >= 0 && i3 < this.xSize && l2 < this.ySize && j3 < this.zSize) {265if ((this.tiles[(l2 * this.zSize + j3) * this.xSize + i3] & 255) != 0) {266flag = false;267}268} else {269flag = false;270}271}272}273}274275if (flag) {276l2 = (j2 * this.zSize + l1) * this.xSize + k1;277if ((this.tiles[((j2 - 1) * this.zSize + l1) * this.xSize + k1] & 255) == 1 && j2 < this.ySize - k2 - 1) {278this.tiles[l2 - 1 * this.xSize * this.zSize] = 3;//(byte) Tile.dirt.id;279280for (i3 = j2 - 3 + k2; i3 <= j2 + k2; ++i3) {281j3 = i3 - (j2 + k2);282var k3 = parseInt(1 - j3 / 2, 10);283284for (var l3 = k1 - k3; l3 <= k1 + k3; ++l3) {285var i4 = parseInt(l3 - k1, 10);286287for (var j4 = l1 - k3; j4 <= l1 + k3; ++j4) {288var k4 = parseInt(j4 - l1, 10);289290if (Math.abs(i4) != k3 || Math.abs(k4) != k3 || random.nextInt(2) != 0 && j3 != 0) {291this.tiles[(i3 * this.zSize + j4) * this.xSize + l3] = 14;//(byte) Tile.leaves.id;292}293}294}295}296297for (i3 = 0; i3 < k2; ++i3) {298this.tiles[l2 + i3 * this.xSize * this.zSize] = 13;//(byte) Tile.treeTrunk.id;299}300}301}302}303}304}305}306307}308309// place ore310this.placeOre = function(tile, j, k, l) {311l = this.xSize;312var i1 = this.zSize;313var j1 = this.ySize;314var k1 = l * i1 * j1 / 256 / 64 * j / 100;315316for (var l1 = 0; l1 < k1; ++l1) {317//this.progress(l1 * 100 / (k1 - 1) / 4 + k * 100 / 4);318progress.percent = l1 * 100 / (k1 - 1) / 4 + k * 100 / 4;319self.postMessage(progress);320321var f = random.nextFloat() * l;322var f1 = random.nextFloat() * j1;323var f2 = random.nextFloat() * i1;324var i2 = parseInt( ((random.nextFloat() + random.nextFloat()) * 75.0 * j / 100.0) , 10);325var f3 = (random.nextFloat() * 3.141592653589793 * 2.0);326var f4 = 0.0;327var f5 = (random.nextFloat() * 3.141592653589793 * 2.0);328var f6 = 0.0;329330for (var j2 = 0; j2 < i2; ++j2) {331f = ( f + Math.sin(f3) * Math.cos(f5));332f2 = ( f2 + Math.cos(f3) * Math.cos(f5));333f1 = ( f1 + Math.sin(f5));334f3 += f4 * 0.2;335f4 = (f4 *= 0.9) + (random.nextFloat() - random.nextFloat());336f5 = (f5 + f6 * 0.5) * 0.5;337f6 = (f6 *= 0.9) + (random.nextFloat() - random.nextFloat());338var f7 = (Math.sin(j2 * 3.141592653589793 / i2) * j / 100.0 + 1.0);339340for (var k2 = Math.round(f - f7); k2 <= Math.round(f + f7); ++k2) {341for (var l2 = Math.round(f1 - f7); l2 <= Math.round(f1 + f7); ++l2) {342for (var i3 = Math.round(f2 - f7); i3 <= Math.round(f2 + f7); ++i3) {343var f8 = k2 - f;344var f9 = l2 - f1;345var f10 = i3 - f2;346347if (f8 * f8 + f9 * f9 * 2.0 + f10 * f10 < f7 * f7 && k2 >= 1 && l2 >= 1 && i3 >= 1 && k2 < this.xSize - 1 && l2 < this.ySize - 1 && i3 < this.zSize - 1) {348var j3 = parseInt( (l2 * this.zSize + i3) * this.xSize + k2 , 10);349350//if (this.tiles[j3] == Tile.rock.id) {351if (this.tiles[j3] == 2) {352this.tiles[j3] = tile;353}354}355}356}357}358}359}360}361362// floodfill363this.floodFill = function (xc, yc, zc, unused, tile) {364//ArrayList<int[]> fillBuffer = new ArrayList<>();365//console.log(yc)366//yc+=31367368//var fillBuffer = [];369370var wBits = 1;371var hBits = 1;372373while (1 << wBits < xSize)374wBits++;375while (1 << hBits < ySize)376hBits++;377378var zMask = this.zSize - 1;379var xMask = this.xSize - 1;380var count = 1;381382this.fillQueue[0] = ((yc << hBits) + zc << wBits) + xc;383384//console.log(this.fillQueue[0]);385var k2 = 0;386387388var offset = this.xSize * this.zSize;389390while (count > 0) {391--count;392var val = this.fillQueue[count];393//if (count == 0 && fillBuffer.size() > 0) {394/*if (count == 0 && fillBuffer.length > 0) {395//System.out.println("IT HAPPENED!");396console.log("IT HAPPENED!");397//this.fillQueue = fillBuffer.remove(fillBuffer.size() - 1);398this.fillQueue = fillBuffer.slice(fillBuffer.length-1);399400count = this.fillQueue.length;401}*/402403var z = val >> wBits & zMask;404var l2 = val >> wBits + hBits;405406var i3 = 0;407var j3 = 0;408409for (j3 = i3 = val & xMask; i3 > 0 && this.tiles[val - 1] == 0; --val) {410--i3;411}412413while (j3 < this.xSize && this.tiles[val + j3 - i3] == 0) {414++j3;415}416417var k3 = val >> wBits & zMask;418var l3 = val >> wBits + hBits;419420if (k3 != z || l3 != l2) {421//System.out.println("hoooly fuck");422console.log("hoooly fuck")423}424425var flag = false;426var flag1 = false;427var flag2 = false;428429k2 += (j3 - i3);430431//console.log(k2)432433for (i3 = i3; i3 < j3; ++i3) {434//console.log(val)435this.tiles[val] = tile;436var flag3;437438if (z > 0) {439if ((flag3 = this.tiles[val - this.xSize] == 0) && !flag) {440//if (count == this.fillQueue.length) {441//fillBuffer.add(this.fillQueue);442//console.log("111");443//fillBuffer.concat(this.fillQueue);444//this.fillQueue = [];445//count = 0;446//}447448this.fillQueue[count++] = val - this.xSize;449}450451flag = flag3;452}453454if (z < this.zSize - 1) {455if ((flag3 = this.tiles[val + this.xSize] == 0) && !flag1) {456//if (count == this.fillQueue.length) {457//fillBuffer.add(this.fillQueue);458//console.log("222");459//fillBuffer.concat(this.fillQueue);460//this.fillQueue = [];461//count = 0;462//}463464this.fillQueue[count++] = val + this.xSize;465}466467flag1 = flag3;468}469470if (l2 > 0) {471var b2 = this.tiles[val - offset];472473//if (( tile == Tile.lava.id || tile == Tile.calmLava.id) && (b2 == Tile.water.id || b2 == Tile.calmWater.id)) {474if (( tile == 17) && (b2 == 7)) {475this.tiles[val - offset] = 2;//Tile.rock.id;476}477478if ((flag3 = b2 == 0) && !flag2) {479//if (count == this.fillQueue.length) {480//fillBuffer.add(this.fillQueue);481//console.log("333");482//fillBuffer.concat(this.fillQueue);483// this.fillQueue = [];484//count = 0;485//}486487this.fillQueue[count++] = val - offset;488}489490flag2 = flag3;491}492493++val;494}495}496497return k2;498}499500501502503504505progress.string = "Raising..";506//this.progressRenderer.progressStage("Raising..");507var distort = new Distort(new PerlinNoise(this.random, 8), new PerlinNoise(this.random, 8));508var distort1 = new Distort(new PerlinNoise(this.random, 8), new PerlinNoise(this.random, 8));509var perlinnoise = new PerlinNoise(this.random, 8);510var aint = [];511var f = 1.3;512513var l;514var i1;515516for (l = 0; l < xSize; ++l) {517//progress(l * 100 / (xSize - 1));518progress.percent = l * 100 / (xSize - 1);519self.postMessage(progress);520521for (i1 = 0; i1 < zSize; ++i1) {522var d0 = distort.getValue( ( l * f), ( i1 * f)) / 8.0 - 8.0;523var d1 = distort1.getValue( ( l * f), ( i1 * f)) / 6.0 + 6.0;524525if (perlinnoise.getValue( l, i1) / 8.0 > 0.0) {526d1 = d0;527}528529var d2;530531if ((d2 = Math.max(d0, d1) / 2.0) < 0.0) {532d2 *= 0.8;533}534535aint[l + i1 * xSize] = d2;536}537}538539540progress.string = "Eroding..";541//this.progressRenderer.progressStage("Eroding..");542var aint1 = aint;543544distort1 = new Distort(new PerlinNoise(this.random, 8), new PerlinNoise(this.random, 8));545var distort2 = new Distort(new PerlinNoise(this.random, 8), new PerlinNoise(this.random, 8));546547var j1;548var k1;549var l1;550var i2;551552for (j1 = 0; j1 < xSize; ++j1) {553//progress(j1 * 100 / (xSize - 1));554progress.percent = j1 * 100 / (xSize - 1);555self.postMessage(progress);556557for (k1 = 0; k1 < zSize; ++k1) {558var d3 = distort1.getValue( (j1 << 1), (k1 << 1)) / 8.0;559560l1 = distort2.getValue( (j1 << 1), (k1 << 1)) > 0.0 ? 1 : 0;561if (d3 > 2.0) {562i2 = ((aint1[j1 + k1 * xSize] - l1) / 2 << 1) + l1;563aint1[j1 + k1 * xSize] = i2;564}565}566}567568569progress.string = "Soiling..";570//this.progressRenderer.progressStage("Soiling..");571aint1 = aint;572var j2 = this.xSize;573var k2 = this.zSize;574575j1 = this.ySize;576var perlinnoise1 = new PerlinNoise(this.random, 8);577578var l2;579var i3;580581for (l = 0; l < j2; ++l) {582//progress(l * 100 / (xSize - 1));583progress.percent = l * 100 / (xSize - 1);584self.postMessage(progress);585586for (i1 = 0; i1 < k2; ++i1) {587l1 = (perlinnoise1.getValue( l, i1) / 24.0) - 4;588l2 = (i2 = aint1[l + i1 * j2] + j1 / 2) + l1;589aint1[l + i1 * j2] = Math.max(i2, l2);590591for (i3 = 0; i3 < j1; ++i3) {592var j3 = (i3 * zSize + i1) * xSize + l;593var k3 = 0;594595if (i3 <= i2) {596k3 = 3;//Tile.dirt.id;597}598599if (i3 <= l2) {600k3 = 2;//Tile.rock.id;601}602603this.tiles[j3] = k3;604}605}606}607608609progress.string = "Carving..";610//this.progressRenderer.progressStage("Carving..");611612k2 = this.xSize;613j1 = this.zSize;614k1 = this.ySize;615l = k2 * j1 * k1 / 256 / 64;616617for (i1 = 0; i1 < l; ++i1) {618//progress(i1 * 100 / (l - 1) / 4);619progress.percent = i1 * 100 / (l - 1) / 4;620self.postMessage(progress);621622var f1 = random.nextFloat() * k2;623var f2 = random.nextFloat() * k1;624var f3 = random.nextFloat() * j1;625626i3 = ((random.nextFloat() + random.nextFloat()) * 75.0);627var f4 = ( random.nextFloat() * 3.141592653589793 * 2.0);628var f5 = 0.0;629var f6 = ( random.nextFloat() * 3.141592653589793 * 2.0);630var f7 = 0.0;631632for (var l3 = 0; l3 < i3; ++l3) {633f1 = ( f1 + Math.sin(f4) * Math.cos(f6));634f3 = ( f3 + Math.cos(f4) * Math.cos(f6));635f2 = ( f2 + Math.sin(f6));636f4 += f5 * 0.2;637f5 = (f5 *= 0.9) + (random.nextFloat() - random.nextFloat());638f6 = (f6 + f7 * 0.5) * 0.5;639f7 = (f7 *= 0.9) + (random.nextFloat() - random.nextFloat());640if (random.nextFloat() >= 0.3) {641var f8 = f1 + random.nextFloat() * 4.0 - 2.0;642var f9 = f2 + random.nextFloat() * 4.0 - 2.0;643var f10 = f3 + random.nextFloat() * 4.0 - 2.0;644var f11 = (Math.sin( l3 * 3.141592653589793 / i3) * 2.5 + 1.0);645646for (var i4 = parseInt( (f8 - f11), 10); i4 <= parseInt( (f8 + f11), 10); ++i4) {647for (var j4 = parseInt( (f9 - f11), 10); j4 <= parseInt( (f9 + f11), 10); ++j4) {648for (var k4 = (f10 - f11); k4 <= (f10 + f11); ++k4) {649var f12 = i4 - f8;650var f13 = j4 - f9;651var f14 = k4 - f10;652653if (f12 * f12 + f13 * f13 * 2.0 + f14 * f14 < f11 * f11 && i4 >= 1 && j4 >= 1 && k4 >= 1 && i4 < xSize - 1 && j4 < ySize - 1 && k4 < zSize - 1) {654var l4 = parseInt( (j4 * zSize + k4) * xSize + i4 , 10);655656//if (tiles[l4] == Tile.rock.id) {657if (this.tiles[l4] == 2) {658this.tiles[l4] = 0;659}660}661}662}663}664}665}666}667668this.placeOre(20, 90, 1, 4); // coal669this.placeOre(19, 70, 2, 4); // iron670this.placeOre(18, 50, 3, 4); // gold671672progress.string = "Watering..";673//this.progressRenderer.progressStage("Watering..");674//long i5 = System.nanoTime();675var i5 = random.nextFloat();//Math.random();676var j5 = 0;677678l = 7;//Tile.calmWater.id;679//this.progress(0);680681// hack for floodfill to work...682var extray = 64-35;683if(xSize >= 256) extray = 128-36;684if(xSize >= 512) extray = 256-37;685686//console.log(ySize / 2 - 1)687688for (i1 = 0; i1 < xSize; ++i1) {689j5 = j5 + this.floodFill(i1, ySize / 2 - 1 + extray, 0, 0, l) + this.floodFill(i1, ySize / 2 - 1, zSize - 1 + extray, 0, l);690}691692for (i1 = 0; i1 < zSize; ++i1) {693j5 = j5 + this.floodFill(0, ySize / 2 - 1 + extray, i1, 0, l) + this.floodFill(xSize - 1, ySize / 2 - 1 + extray, i1, 0, l);694}695696697i1 = xSize * zSize / 200;698699for (l1 = 0; l1 < i1; ++l1) {700if (l1 % 100 == 0) {701// progress(l1 * 100 / (i1 - 1));702progress.percent = l1 * 100 / (i1 - 1);703self.postMessage(progress);704}705706i2 = random.nextInt(xSize);707l2 = ySize / 2 - 1 - random.nextInt(3) + extray;708i3 = random.nextInt(zSize);709if (this.tiles[(l2 * zSize + i3) * xSize + i2] == 0) {710j5 += this.floodFill(i2, l2, i3, 0, l);711}712}713714progress.percent = 100;715self.postMessage(progress);716717progress.string = "Melting..";718//this.progressRenderer.progressStage("Melting..");719this.melt();720progress.string = "Growing..";721//this.progressRenderer.progressStage("Growing..");722this.grow(aint);723progress.string = "Planting..";724//this.progressRenderer.progressStage("Planting..");725this.plant(aint);726727progress.tiles = this.tiles;728progress.string = "";729self.postMessage(progress);730731}732733734}735736function startGeneration (obj) { //{worldSize: worldSize, seed: props.seed, seedrandom: seedrandom}737var level = new RandomLevel();738//console.log(level)739var width = obj.worldSize;740var depth = obj.worldSize;741var height = 64;742level.createLevel(obj.seed, width, depth, height);743}744745self.addEventListener('message', function(e) {746//console.log("worker get "+e.data);747startGeneration(e.data)748}, false);749750