From 4db50a4e6dce7d57bdf095ba2fd650e721be246b Mon Sep 17 00:00:00 2001 From: Cubitect Date: Sat, 10 Mar 2018 21:45:57 +0000 Subject: [PATCH] added 1.13 biome generator --- finders.c | 167 +++++++++++++++++++++++++++++++++++++ generator.c | 197 ++++++++++++++++++++++++++++++------------- generator.h | 33 +++----- layers.c | 235 +++++++++++++++++++++++++++++++++++++++++++--------- layers.h | 34 +++++++- xmapview.c | 8 ++ 6 files changed, 555 insertions(+), 119 deletions(-) diff --git a/finders.c b/finders.c index 17f28b6..6af95cd 100644 --- a/finders.c +++ b/finders.c @@ -426,6 +426,120 @@ Pos getTempleChunkInRegion(long seed, int regionX, int regionZ) } +/* findBiomePosition + * ----------------- + * Finds a suitable pseudo-random location in the specified area. + * Used to determine the positions of spawn and stongholds. + * The return value is non-zero if a valid location was found. + * Warning: accurate, but slow! + * + * TODO: Spawn finding not working in 1.10 + */ +int findBiomePosition(Generator *g, Pos *out, int centerX, int centerZ, int range, const int *biomeList, long *seed) +{ + int x1 = (centerX-range) >> 2; + int z1 = (centerZ-range) >> 2; + int x2 = (centerX+range) >> 2; + int z2 = (centerZ+range) >> 2; + int width = x2 - x1 + 1; + int height = z2 - z1 + 1; + int *map = allocCache(g, width, height); + + genArea(g, map, x1, z1, width, height); + int i, found = 0; + + out->x = 0; + out->z = 0; + + for(i = 0; i < width*height; i++) + { + int biome = map[i]; + + if(biomeList[biome & 0xff] && (found == 0 || nextInt(seed, found + 1) == 0)) + { + out->x = (x1 + i%width) << 2; + out->z = (z1 + i/width) << 2; + ++found; + } + } + + free(map); + return found; +} + + +/*s +Pos getSpawn(long seed) +{ + Generator g = setupGenerator(); + g.topLayerIndex = 43; + applySeed(g, seed); + + Pos spawn; + + setSeed(&seed); + + int found = findBiomePosition(&g, &spawn, 0, 0, 256, biomesToSpawnIn, &seed); + + if(!found) + { + //printf("Unable to find spawn biome"); + } + + int var9 = 0; + + while (!this.provider.canCoordinateBeSpawn(var6, var8)) + { + var6 += var4.nextInt(64) - var4.nextInt(64); + var8 += var4.nextInt(64) - var4.nextInt(64); + ++var9; + + if (var9 == 1000) + { + break; + } + } +} +*/ + + + +/* areBiomesViable + * --------------- + * Determines if the given area contains only biomes specified by 'biomeList'. + * Used to determine the positions of ocean monuments and villages. + * Warning: accurate, but slow! + */ +int areBiomesViable(Generator *g, int posX, int posZ, int radius, const int *biomeList, const int listLen) +{ + int x1 = (posX - radius) >> 2; + int z1 = (posZ - radius) >> 2; + int x2 = (posX + radius) >> 2; + int z2 = (posZ + radius) >> 2; + int width = x2 - x1 + 1; + int height = z2 - z1 + 1; + int i, j; + + int *map = allocCache(g, width, height); + genArea(g, map, x1, z1, width, height); + + for(i = 0; i < width*height; i++) + { + for(j = 0; j < listLen; j++) + { + if(map[i] == biomeList[j]) break; + } + if(j >= listLen) + { + free(map); + return 0; + } + } + + free(map); + return 1; +} + /* filterAllTempCats * ----------------- @@ -677,4 +791,57 @@ long filterAllMajorBiomes(long *seedsIn, long *seedsOut, long seedCnt, +// very slow! +int getAllBiomeRadius(long seed, const int startRadius) +{ + Generator g = setupGenerator(); + int x, z, r, i, bnum; + int *map; + int blist[BIOME_NUM]; + map = allocCache(&g, startRadius*2+1, startRadius*2+1); + + applySeed(&g, seed); + genArea(&g, map, -startRadius, -startRadius, startRadius*2, startRadius*2); + + for(r = startRadius; r > 0; r--) + { + memset(blist, 0, sizeof(int)*BIOME_NUM); + for(z = startRadius-r; z < startRadius+r; z++) + { + for(x = startRadius-r; x < startRadius+r; x++) + { + blist[map[x + z*2*startRadius] & 0x7f] = 1; + } + } + + for(i = 0, bnum = 0; i < BIOME_NUM; i++) if(blist[i]) bnum++; + if(bnum < 36) break; + } + + + free(map); + freeGenerator(&g); + + return r+1; +} + + + + + + + + + + + + + + + + + + + + diff --git a/generator.c b/generator.c index ba73388..bcf8d54 100644 --- a/generator.c +++ b/generator.c @@ -5,14 +5,14 @@ #include #include -const int magscale[] = {1, 4, 16, 64, 256, 256, 1024 }; int *allocCache(Generator *g, int sizeX, int sizeZ) { - int size = calcRequiredBuf(g, sizeX, sizeZ); - if(size < 256) size = 256; + int size = calcRequiredBuf(&g->layers[g->topLayerIndex-1], sizeX, sizeZ); + int *ret = (int*) malloc(sizeof(*ret)*size); memset(ret, 0, sizeof(*ret)*size); + return ret; } @@ -33,6 +33,11 @@ void setupMultiLayer(Layer *l, Layer *p1, Layer *p2, int s, void (*getMap)(Layer } Generator setupGenerator() +{ + return setupGeneratorMC18(); +} + +Generator setupGeneratorMC18() { if(biomes[plains].id == 0) { @@ -42,7 +47,6 @@ Generator setupGenerator() Generator g; g.rawSeed = 0; - g.mag = 1; g.topLayerIndex = 44; g.layerMax = 44; g.layers = (Layer*) malloc(sizeof(Layer)*g.topLayerIndex); @@ -104,74 +108,151 @@ Generator setupGenerator() return g; } -void setGenScale(Generator *g, int magnification) + +Generator setupGeneratorMC113() { - switch(magnification) + if(biomes[plains].id == 0) { - case MAG1: - g->mag = MAG1; - g->topLayerIndex = 44; - break; - case MAG4: - g->mag = MAG4; - g->topLayerIndex = 43; - break; - case MAG16: - g->mag = MAG16; - g->topLayerIndex = 39; - break; - case MAG64: - g->mag = MAG64; - g->topLayerIndex = 26; - break; - case MAG256: - g->mag = MAG256; - g->topLayerIndex = 19; - break; - case MAGSHROOM: - g->mag = MAGSHROOM; - g->topLayerIndex = 17; - break; - case MAG1024: - g->mag = MAG1024; - g->topLayerIndex = 11; - break; + fprintf(stderr, "Warning: The biomes have to be initialised first using initBiomes() before any generator can be used.\n"); + } + + Generator g; + + g.rawSeed = 0; + g.topLayerIndex = 53; + g.layerMax = 53; + g.layers = (Layer*) malloc(sizeof(Layer)*g.topLayerIndex); + + // LAYER PARENT SEED LAYER_FUNCTION + setupLayer(&g.layers[ 0], NULL, 1, mapIsland); + setupLayer(&g.layers[ 1], &g.layers[ 0], 2000, mapZoom); + setupLayer(&g.layers[ 2], &g.layers[ 1], 1, mapAddIsland); + setupLayer(&g.layers[ 3], &g.layers[ 2], 2001, mapZoom); + setupLayer(&g.layers[ 4], &g.layers[ 3], 2, mapAddIsland); + setupLayer(&g.layers[ 5], &g.layers[ 4], 50, mapAddIsland); + setupLayer(&g.layers[ 6], &g.layers[ 5], 70, mapAddIsland); + setupLayer(&g.layers[ 7], &g.layers[ 6], 2, mapRemoveTooMuchOcean); + + setupLayer(&g.layers[ 8], &g.layers[ 7], 2, mapAddSnow); + setupLayer(&g.layers[ 9], &g.layers[ 8], 3, mapAddIsland); + setupLayer(&g.layers[10], &g.layers[ 9], 2, mapCoolWarm); // MAG1024 + setupLayer(&g.layers[11], &g.layers[10], 2, mapHeatIce); + setupLayer(&g.layers[12], &g.layers[11], 3, mapSpecial); + setupLayer(&g.layers[13], &g.layers[12], 2002, mapZoom); + setupLayer(&g.layers[14], &g.layers[13], 2003, mapZoom); + setupLayer(&g.layers[15], &g.layers[14], 4, mapAddIsland); + setupLayer(&g.layers[16], &g.layers[15], 5, mapAddMushroomIsland); // MAGSHROOM + setupLayer(&g.layers[17], &g.layers[16], 4, mapDeepOcean); + // biome layer chain + setupLayer(&g.layers[18], &g.layers[17], 200, mapBiome); // MAG256 + setupLayer(&g.layers[19], &g.layers[18], 1000, mapZoom); + setupLayer(&g.layers[20], &g.layers[19], 1001, mapZoom); + setupLayer(&g.layers[21], &g.layers[20], 1000, mapBiomeEdge); + + // basic river layer chain, used to determine where hills generate + setupLayer(&g.layers[22], &g.layers[17], 100, mapRiverInit); + setupLayer(&g.layers[23], &g.layers[22], 1000, mapZoom); + setupLayer(&g.layers[24], &g.layers[23], 1001, mapZoom); + + setupMultiLayer(&g.layers[25], &g.layers[21], &g.layers[24], 1000, mapHills); // MAG64 + + setupLayer(&g.layers[26], &g.layers[25], 1001, mapRareBiome); + setupLayer(&g.layers[27], &g.layers[26], 1000, mapZoom); + setupLayer(&g.layers[28], &g.layers[27], 3, mapAddIsland); + setupLayer(&g.layers[29], &g.layers[28], 1001, mapZoom); + setupLayer(&g.layers[30], &g.layers[29], 1000, mapShore); + setupLayer(&g.layers[31], &g.layers[30], 1002, mapZoom); + setupLayer(&g.layers[32], &g.layers[31], 1003, mapZoom); + setupLayer(&g.layers[33], &g.layers[32], 1000, mapSmooth); + + // river layer chain + setupLayer(&g.layers[34], &g.layers[22], 1000, mapZoom); + setupLayer(&g.layers[35], &g.layers[34], 1001, mapZoom); + setupLayer(&g.layers[36], &g.layers[35], 1000, mapZoom); + setupLayer(&g.layers[37], &g.layers[36], 1001, mapZoom); + setupLayer(&g.layers[38], &g.layers[37], 1002, mapZoom); // MAG16 + setupLayer(&g.layers[39], &g.layers[38], 1003, mapZoom); + setupLayer(&g.layers[40], &g.layers[39], 1, mapRiver); + setupLayer(&g.layers[41], &g.layers[40], 1000, mapSmooth); + + setupMultiLayer(&g.layers[42], &g.layers[33], &g.layers[41], 100, mapRiverMix); + + // ocean variants + // This branch is connected to layer 7, but makes no use of it (only size). + // I.e this branch is independent of previous layers. + setupLayer(&g.layers[43], &g.layers[ 7], 2, mapOceanTemp); + setupLayer(&g.layers[44], &g.layers[43], 2, mapEdgeOcean); + setupLayer(&g.layers[45], &g.layers[44], 2001, mapZoom); + setupLayer(&g.layers[46], &g.layers[45], 2002, mapZoom); + setupLayer(&g.layers[47], &g.layers[46], 2003, mapZoom); + setupLayer(&g.layers[48], &g.layers[47], 2004, mapZoom); + setupLayer(&g.layers[49], &g.layers[48], 2005, mapZoom); + setupLayer(&g.layers[50], &g.layers[49], 2006, mapZoom); + + setupMultiLayer(&g.layers[51], &g.layers[42], &g.layers[50], 100, mapOceanMix); + + setupLayer(&g.layers[52], &g.layers[51], 10, mapVoronoiZoom); + + return g; +} + + +void setTopLevel(Generator *g, int topLevel) +{ + if(topLevel > g->layerMax) + { + printf("Warning: Top layer index is greater than the number of layers in this generator."); + } + else + { + g->topLayerIndex = topLevel; } } -int calcRequiredBuf(Generator *g, int areaX, int areaZ) + +static void getMaxArea(Layer *layer, int areaX, int areaZ, int *maxX, int *maxZ) { - areaX += 2; - areaZ += 2; - int i, maxX = areaX, maxZ = areaZ; + if(layer == NULL) + return; - for(i = g->topLayerIndex-1; i >= 0; i--) + if(layer->getMap == mapZoom) { - if(g->layers[i].getMap == mapZoom) + areaX = (areaX >> 1) + 2; + areaZ = (areaZ >> 1) + 2; + } + else if(layer->getMap == mapVoronoiZoom) + { + areaX = (areaX >> 2) + 2; + areaZ = (areaZ >> 2) + 2; + } + else + { + if( layer->getMap != mapIsland && + layer->getMap != mapSpecial && + layer->getMap != mapBiome && + layer->getMap != mapRiverInit && + layer->getMap != mapRiverMix ) { - areaX = (areaX >> 1) + 2; areaZ = (areaZ >> 1) + 2; - } - else if(g->layers[i].getMap == mapVoronoiZoom) - { - areaX = (areaX >> 2) + 2; areaZ = (areaZ >> 2) + 2; - } - else - { - if(g->layers[i].getMap == mapIsland) continue; - if(g->layers[i].getMap == mapSpecial) continue; - if(g->layers[i].getMap == mapBiome) continue; - if(g->layers[i].getMap == mapRiverInit) continue; - if(g->layers[i].getMap == mapRiverMix) continue; - areaX += 2; areaZ += 2; } - if(areaX > maxX) maxX = areaX; - if(areaZ > maxZ) maxZ = areaZ; } - return (2*maxX+2) * (2*maxZ+2); + if(areaX > *maxX) *maxX = areaX; + if(areaZ > *maxZ) *maxZ = areaZ; + + getMaxArea(layer->p, areaX, areaZ, maxX, maxZ); + getMaxArea(layer->p2, areaX, areaZ, maxX, maxZ); +} + + +int calcRequiredBuf(Layer *layer, int areaX, int areaZ) +{ + int maxX = areaX, maxZ = areaZ; + getMaxArea(layer, areaX, areaZ, &maxX, &maxZ); + + return maxX * maxZ; } void freeGenerator(Generator *g) @@ -183,7 +264,7 @@ void applySeed(Generator *g, long seed) { g->rawSeed = seed; - // the seed has to be applied recursively, such that the branching layer chains (of parent 2) keep a world seed of zero + // the seed has to be applied recursively setWorldSeed(&g->layers[g->topLayerIndex-1], seed); } diff --git a/generator.h b/generator.h index 247f5ba..1247cfd 100644 --- a/generator.h +++ b/generator.h @@ -3,48 +3,37 @@ #include "layers.h" -/* If speed is more important than accuracy, here are some magnification modes for the generator. - * The map generation is done in stages (layers), some of which zoom into the map, magnifying it. - * These magnification modes control at which stage/magnification the map generation is aborted. - * - * Notes on magnification modes: - * MAG1 - 1 to 1 scale, exact map of the biomes - * MAG4 - 1 to 4 scale, used by some vanilla mc-generation as a faster alternative to the full scale map - * MAG16 - 1 to 16 scale, contains all biomes, except rivers - * MAG64 - 1 to 64 scale, misses oceanic features like beaches, small islands and rare biomes (Sunflower Plains). - * MAG256 - 1 to 256 scale, contains all the basic biomes, no variations (e.g. no hills and no mutations). - * MAGSHROOM, 1 to 256 scale, exploits that Mushroom Islands are determined before most other biomes. - * MAG1024 - 1 to 1024 scale, extreme scale that only contains basic information where biome types generate. - */ -enum Magnification { MAG1, MAG4, MAG16, MAG64, MAG256, MAGSHROOM, MAG1024 }; -extern const int magscale[]; STRUCT(Generator) { Layer *layers; int topLayerIndex; int layerMax; - int mag; long rawSeed; }; // Initialise an instance of a generator Generator setupGenerator(); +Generator setupGeneratorMC18(); +Generator setupGeneratorMC113(); -// Sets the magnification mode of the generator -void setGenScale(Generator *g, int magnification); + +// Sets the top level layer of a generator. +void setTopLevel(Generator *g, int topLevel); // Cleans up and frees the generator layers void freeGenerator(Generator *g); -// Allocates an amount of memory required to generate an area of dimensions 'sizeX' by 'sizeZ' -int *allocCache(Generator *g, int sizeX, int sizeZ); +// Allocates an amount of memory required to generate an area of dimensions +// 'sizeX' by 'sizeZ' for the magnification of the current top layer. +int *allocCache(Generator *layer, int sizeX, int sizeZ); // Set up custom layers void setupLayer(Layer *l, Layer *p, int s, void (*getMap)(Layer *layer, int *out, int x, int z, int w, int h)); void setupMultiLayer(Layer *l, Layer *p1, Layer *p2, int s, void (*getMap)(Layer *layer, int *out, int x, int z, int w, int h)); -// Calculates the minimum size of the buffers required to generate an area of dimensions 'sizeX' by 'sizeZ' -int calcRequiredBuf(Generator *g, int sizeX, int sizeZ); +// Calculates the minimum size of the buffers required to generate an area of dimensions +// 'sizeX' by 'sizeZ' at the scale of the layer. +int calcRequiredBuf(Layer *layer, int sizeX, int sizeZ); // Sets the world seed for the generator void applySeed(Generator *g, long seed); diff --git a/layers.c b/layers.c index 82028fe..de2cf96 100644 --- a/layers.c +++ b/layers.c @@ -70,6 +70,19 @@ void initBiomes() initAddBiome(mesaPlateau_F, Warm, Mesa, 2.0, hHighPlateaus); initAddBiome(mesaPlateau, Warm, Mesa, 2.0, hHighPlateaus); + // TODO: determine the 1.13 biome properties + initAddBiome(skyIslandLow, Lush, Sky, 0, 0); + initAddBiome(skyIslandMedium, Lush, Sky, 0, 0); + initAddBiome(skyIslandHigh, Lush, Sky, 0, 0); + initAddBiome(skyIslandBarren, Lush, Sky, 0, 0); + initAddBiome(warmOcean, Oceanic, Ocean, 0, 0); + initAddBiome(lukewarmOcean, Oceanic, Ocean, 0, 0); + initAddBiome(coldOcean, Oceanic, Ocean, 0, 0); + initAddBiome(warmDeepOcean, Oceanic, Ocean, 0, 0); + initAddBiome(lukewarmDeepOcean, Oceanic, Ocean, 0, 0); + initAddBiome(coldDeepOcean, Oceanic, Ocean, 0, 0); + initAddBiome(frozenDeepOcean, Oceanic, Ocean, 0, 0); + createMutation(plains); createMutation(desert); createMutation(extremeHills); @@ -96,9 +109,11 @@ void initBiomes() void setWorldSeed(Layer *layer, long seed) { - if(layer->getMap == mapRiverMix) setWorldSeed(layer->p2, seed); + if(layer->p2 != NULL && layer->getMap != mapHills) + setWorldSeed(layer->p2, seed); - if(layer->p != NULL) setWorldSeed(layer->p, seed); + if(layer->p != NULL) + setWorldSeed(layer->p, seed); layer->worldSeed = seed; layer->worldSeed *= layer->worldSeed * 6364136223846793005L + 1442695040888963407L; @@ -291,15 +306,15 @@ void mapAddSnow(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWi { int v11 = out[x+1 + (z+1)*pWidth]; - if(v11 == 0) + if(isShallowOcean(v11)) { - out[x + z*areaWidth] = 0; + out[x + z*areaWidth] = v11; } else { setChunkSeed(l, (long)(x + areaX), (long)(z + areaZ)); int r = mcNextInt(l, 6); - char v; + int v; if(r == 0) v = 4; else if(r <= 1) v = 3; @@ -312,6 +327,8 @@ void mapAddSnow(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWi } + + void mapCoolWarm(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight) { int pX = areaX - 1; @@ -454,18 +471,34 @@ void mapDeepOcean(Layer *l, int * __restrict out, int areaX, int areaZ, int area for(x = 0; x < areaWidth; x++) { int v11 = out[(x+1) + (z+1)*pWidth]; - int oceans = 0; - // count adjacent oceans - if(out[(x+1) + (z+0)*pWidth] == 0) oceans++; - if(out[(x+2) + (z+1)*pWidth] == 0) oceans++; - if(out[(x+0) + (z+1)*pWidth] == 0) oceans++; - if(out[(x+1) + (z+2)*pWidth] == 0) oceans++; + if(isShallowOcean(v11)) + { + // count adjacent oceans + int oceans = 0; + if(isShallowOcean(out[(x+1) + (z+0)*pWidth])) oceans++; + if(isShallowOcean(out[(x+2) + (z+1)*pWidth])) oceans++; + if(isShallowOcean(out[(x+0) + (z+1)*pWidth])) oceans++; + if(isShallowOcean(out[(x+1) + (z+2)*pWidth])) oceans++; - if(v11 == 0 && oceans > 3) - out[x + z*areaWidth] = deepOcean; - else - out[x + z*areaWidth] = v11; + if(oceans > 3) + { + if(v11 == warmOcean) + v11 = warmDeepOcean; + else if(v11 == lukewarmOcean) + v11 = lukewarmDeepOcean; + else if(v11 == ocean) + v11 = deepOcean; + else if(v11 == coldOcean) + v11 = coldDeepOcean; + else if(v11 == frozenOcean) + v11 = frozenDeepOcean; + else + v11 = deepOcean; + } + } + + out[x + z*areaWidth] = v11; } } } @@ -855,13 +888,10 @@ void mapRareBiome(Layer *l, int * __restrict out, int areaX, int areaZ, int area setChunkSeed(l, (long)(x + areaX), (long)(z + areaZ)); int v11 = out[x+1 + (z+1)*pWidth]; - if(mcNextInt(l, 57) == 0) + if(mcNextInt(l, 57) == 0 && v11 == plains) { // Flower Forest - if(v11 == plains) - out[x + z*areaWidth] = plains + 128; - else - out[x + z*areaWidth] = v11; + out[x + z*areaWidth] = plains + 128; } else { @@ -987,6 +1017,139 @@ void mapRiverMix(Layer *l, int * __restrict out, int areaX, int areaZ, int areaW exit(1); } + l->p->getMap(l->p, out, areaX, areaZ, areaWidth, areaHeight); // biome chain + memcpy(buf, out, areaWidth*areaHeight*sizeof(int)); + + l->p2->getMap(l->p2, out, areaX, areaZ, areaWidth, areaHeight); // rivers + + for(idx = 0; idx < areaHeight*areaWidth; idx++) + { + if(isOceanic(buf[idx])) + { + out[idx] = buf[idx]; + } + else + { + if(out[idx] == river) + { + if(buf[idx] == icePlains) + out[idx] = frozenRiver; + else if(buf[idx] == mushroomIsland || buf[idx] == mushroomIslandShore) + out[idx] = mushroomIslandShore; + else + out[idx] = out[idx] & 255; + } + else + { + out[idx] = buf[idx]; + } + } + } + + free(buf); +} + + + +void mapOceanTemp(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight) +{ + // The new ocean branch doesn't actually depend on previous layers. + + //int pX = areaX - 1; + //int pZ = areaZ - 1; + //int pWidth = areaWidth + 2; + //int pHeight = areaHeight + 2; + int x, z; + + //l->p->getMap(l->p, out, pX, pZ, pWidth, pHeight); + + for(z = 0; z < areaHeight; z++) + { + for(x = 0; x < areaWidth; x++) + { + setChunkSeed(l, (long)(x + areaX), (long)(z + areaZ)); + + int v11; + + float tmp = (float)mcNextInt(l, 100) / 100.0f; + + if(tmp < 0.05f) + v11 = warmOcean; + else if(tmp < 0.4f) + v11 = lukewarmOcean; + else if(tmp < 0.675f) + v11 = ocean; + else if(tmp < 0.95f) + v11 = coldOcean; + else if(tmp < 1.0f) + v11 = frozenOcean; + else + v11 = ocean; + + out[x + z*areaWidth] = v11; + } + } +} + +void mapEdgeOcean(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight) +{ + int pX = areaX - 1; + int pZ = areaZ - 1; + int pWidth = areaWidth + 2; + int pHeight = areaHeight + 2; + int x, z; + + l->p->getMap(l->p, out, pX, pZ, pWidth, pHeight); + + for(z = 0; z < areaHeight; z++) + { + for(x = 0; x < areaWidth; x++) + { + int v11 = out[x+1 + (z+1)*pWidth]; + + if(v11 == warmOcean) + { + int v10 = out[x+1 + (z+0)*pWidth]; + int v21 = out[x+2 + (z+1)*pWidth]; + int v01 = out[x+0 + (z+1)*pWidth]; + int v12 = out[x+1 + (z+2)*pWidth]; + + if(v10 == frozenOcean || v21 == frozenOcean || v01 == frozenOcean || v12 == frozenOcean) + { + v11 = ocean; + } + } + + if(v11 == frozenOcean) + { + int v10 = out[x+1 + (z+0)*pWidth]; + int v21 = out[x+2 + (z+1)*pWidth]; + int v01 = out[x+0 + (z+1)*pWidth]; + int v12 = out[x+1 + (z+2)*pWidth]; + + if(v10 == warmOcean || v21 == warmOcean || v01 == warmOcean || v12 == warmOcean) + { + v11 = ocean; + } + } + + out[x + z*areaWidth] = v11; + } + } +} + + +void mapOceanMix(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight) +{ + int idx; + int *buf = (int*)malloc(areaWidth*areaHeight*sizeof(int)); + + if(l->p2 == NULL) + { + printf("mapOceanMix() requires two parents! Use setupMultiLayer()\n"); + exit(1); + } + l->p->getMap(l->p, out, areaX, areaZ, areaWidth, areaHeight); memcpy(buf, out, areaWidth*areaHeight*sizeof(int)); @@ -994,32 +1157,30 @@ void mapRiverMix(Layer *l, int * __restrict out, int areaX, int areaZ, int areaW for(idx = 0; idx < areaHeight*areaWidth; idx++) { - if(buf[idx] != ocean && buf[idx] != deepOcean) - { - if (out[idx] == river) - { - if(buf[idx] == icePlains) - out[idx] = frozenRiver; - else if(buf[idx] != mushroomIsland && buf[idx] != mushroomIslandShore) - out[idx] = out[idx] & 255; - else - out[idx] = mushroomIslandShore; - } - else - { - out[idx] = buf[idx]; - } - } - else + if(!isOceanic(buf[idx]) || !isOceanic(out[idx])) { out[idx] = buf[idx]; } + else if(buf[idx] == deepOcean) + { + if(out[idx] == lukewarmOcean) + out[idx] = lukewarmDeepOcean; + else if(out[idx] == ocean) + out[idx] = deepOcean; + else if(out[idx] == coldOcean) + out[idx] = coldDeepOcean; + else if(out[idx] == frozenOcean) + out[idx] = frozenDeepOcean; + } } free(buf); } + + + void mapVoronoiZoom(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight) { areaX -= 2; diff --git a/layers.h b/layers.h index db9a029..81222a5 100644 --- a/layers.h +++ b/layers.h @@ -7,12 +7,16 @@ #define OPT_O2 __attribute__((optimize("O2"))) + enum BiomeID { none = -1, ocean = 0, plains, desert, extremeHills, forest, taiga, swampland, river, hell, sky, // 0-9 frozenOcean, frozenRiver, icePlains, iceMountains, mushroomIsland, mushroomIslandShore, beach, desertHills, forestHills, taigaHills, // 10-19 extremeHillsEdge, jungle, jungleHills, jungleEdge, deepOcean, stoneBeach, coldBeach, birchForest, birchForestHills, roofedForest, // 20-29 coldTaiga, coldTaigaHills, megaTaiga, megaTaigaHills, extremeHillsPlus, savanna, savannaPlateau, mesa, mesaPlateau_F, mesaPlateau, // 30-39 + // 1.13 + skyIslandLow, skyIslandMedium, skyIslandHigh, skyIslandBarren, warmOcean, lukewarmOcean, coldOcean, warmDeepOcean, lukewarmDeepOcean, coldDeepOcean, // 40-49 + frozenDeepOcean, BIOME_NUM }; @@ -91,11 +95,33 @@ static inline int canBeNeighbors(int id1, int id2) return tempCat1 == tempCat2; } +static inline int isShallowOcean(int id) +{ + return id == ocean || id == frozenOcean || + id == warmOcean || id == lukewarmOcean || id == coldOcean; +} + static inline int isOceanic(int id) { - return id == ocean || id == deepOcean || id == frozenOcean; + switch(id) + { + case ocean: + case deepOcean: + case warmOcean: + case warmDeepOcean: + case lukewarmOcean: + case lukewarmDeepOcean: + case coldOcean: + case coldDeepOcean: + case frozenOcean: + case frozenDeepOcean: + return 1; + default: + return 0; + } } + static inline int isBiomeSnowy(int id) { return biomeExists(id) && biomes[id&0xff].temp < 0.1; @@ -195,7 +221,11 @@ void mapSmooth(Layer *l, int * __restrict out, int x, int z, int w, int h); void mapRareBiome(Layer *l, int * __restrict out, int x, int z, int w, int h); void mapShore(Layer *l, int * __restrict out, int x, int z, int w, int h); void mapRiverMix(Layer *l, int * __restrict out, int x, int z, int w, int h); + +void mapOceanTemp(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight); +void mapEdgeOcean(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight); +void mapOceanMix(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight); + void mapVoronoiZoom(Layer *l, int * __restrict out, int x, int z, int w, int h); - #endif /* LAYER_H_ */ diff --git a/xmapview.c b/xmapview.c index ec1b95a..5f12f03 100644 --- a/xmapview.c +++ b/xmapview.c @@ -63,6 +63,14 @@ void initBiomeColours(unsigned char biomeColours[256][3]) setBiomeColour(biomeColours, mesaPlateau_F, 176, 151, 101); setBiomeColour(biomeColours, mesaPlateau, 202, 140, 101); + setBiomeColour(biomeColours, warmOcean, 0, 50, 92); + setBiomeColour(biomeColours, lukewarmOcean, 0, 30, 100); + setBiomeColour(biomeColours, coldOcean, 20, 20, 80); + setBiomeColour(biomeColours, warmDeepOcean, 0, 24, 38); + setBiomeColour(biomeColours, lukewarmDeepOcean, 0, 16, 42); + setBiomeColour(biomeColours, coldDeepOcean, 16, 16, 40); + setBiomeColour(biomeColours, frozenDeepOcean, 100, 100, 112); + setBiomeColour(biomeColours, ocean+128, 0, 0, 112); setBiomeColour(biomeColours, plains+128, 141, 179, 96);