Skip to content

Commit b0720c4

Browse files
committed
- 1.2
1 parent 2f3846b commit b0720c4

12 files changed

+816
-121
lines changed

colors.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ void loadColors()
154154
SETCOLORNOISE(120, 89,117,96,255, 6);
155155
SETCOLORNOISE(121, 221,223,165,255, 3);
156156
SETCOLOR(122, 20,18,29,255);
157+
SETCOLORNOISE(123, 70,43,26,255, 2);
158+
SETCOLORNOISE(124, 119,89,55,255, 7);
157159
SETCOLORNOISE(SANDSTEP, 218, 210, 158, 254, 7); // Not fully opaque to prevent culling on this one
158160
SETCOLORNOISE(WOODSTEP, 157,128,79,254, 11); // Not fully opaque to prevent culling on this one
159161
SETCOLORNOISE(COBBLESTEP, 115,115,115,254, 26); // Not fully opaque to prevent culling on this one

extractcolors.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ static const int special_sauce[256][3] = {
139139
{ 14, 9, 10 }, /* 120 */
140140
{ 15, 10, 10 },
141141
{ 5, 2, 10 },
142-
{ -1, -1, 10 },
143-
{ -1, -1, 10 },
142+
{ 3, 13, 10 },
143+
{ 4, 13, 10 },
144144
{ -1, -1, 10 },
145145
{ -1, -1, 10 },
146146
{ -1, -1, 10 },

globals.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
int g_TotalFromChunkX, g_TotalFromChunkZ, g_TotalToChunkX, g_TotalToChunkZ;
44
int g_FromChunkX = UNDEFINED, g_FromChunkZ = UNDEFINED, g_ToChunkX = UNDEFINED, g_ToChunkZ = UNDEFINED;
5-
size_t g_MapsizeZ = 0, g_MapsizeY = 0xfffffff, g_MapminY = 0, g_MapsizeX = 0;
6-
int g_OffsetY = 2;
5+
size_t g_MapsizeZ = 0, g_MapsizeX = 0;
6+
int g_MapminY = 0, g_MapsizeY = 256, g_OffsetY = 2;
77

8-
bool g_RegionFormat = false;
8+
int g_WorldFormat = -1;
99

1010
Orientation g_Orientation = East;
1111
bool g_Nightmode = false;
@@ -29,3 +29,5 @@ int g_MarkerCount = 0;
2929
Marker g_Markers[MAX_MARKERS];
3030

3131
char *g_TilePath = NULL;
32+
33+
int8_t g_SectionMin, g_SectionMax;

globals.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef _GLOBALS_H_
22
#define _GLOBALS_H_
33

4-
#define VERSION "2.2"
4+
#define VERSION "2.3"
55

66
#include <stdint.h>
77
#include <cstdlib>
@@ -26,11 +26,12 @@ extern int g_TotalFromChunkX, g_TotalFromChunkZ, g_TotalToChunkX, g_TotalToChunk
2626
// Current area of world being rendered
2727
extern int g_FromChunkX, g_FromChunkZ, g_ToChunkX, g_ToChunkZ;
2828
// size of that area in blocks (no offset)
29-
extern size_t g_MapsizeY, g_MapminY, g_MapsizeZ, g_MapsizeX;
29+
extern size_t g_MapsizeZ, g_MapsizeX;
30+
extern int g_MapminY, g_MapsizeY;
3031

3132
extern int g_OffsetY; // y pixel offset in the final image for one y step in 3d array (2 or 3)
3233

33-
extern bool g_RegionFormat;
34+
extern int g_WorldFormat;
3435
extern Orientation g_Orientation; // North, West, South, East
3536
extern bool g_Nightmode;
3637
extern bool g_Underground;
@@ -58,4 +59,6 @@ extern uint16_t *g_HeightMap;
5859
// If output is to be split up (for google maps etc) this contains the path to output to, NULL otherwise
5960
extern char *g_TilePath;
6061

62+
extern int8_t g_SectionMin, g_SectionMax;
63+
6164
#endif

helper.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#define CHUNKSIZE_Z 16
66
#define CHUNKSIZE_X 16
77
#define CHUNKSIZE_Y 128
8+
#define SECTION_Y 16
9+
#define SECTION_Y_SHIFT 4
810
// Some macros for easier array access
911
// First: Block array
1012
#define BLOCKAT(x,y,z) g_Terrain[(y) + ((z) + ((x) * g_MapsizeZ)) * g_MapsizeY]
@@ -32,7 +34,8 @@
3234

3335
#define MAX(a,b) ((a) > (b) ? (a) : (b))
3436
#define MIN(a,b) ((a) < (b) ? (a) : (b))
35-
#define RIGHTSTRING(x,y) ((x) + strlen(x) - ((y) > strlen(x) ? strlen(x) : (y)))
37+
//#define RIGHTSTRING(x,y) ((x) + strlen(x) - ((y) > strlen(x) ? strlen(x) : (y)))
38+
#define RIGHTSTRING(x,y) (strlen(x) >= (y) ? (x) + strlen(x) - (y) : (x))
3639

3740
#include <string>
3841

main.cpp

+49-43
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ int main(int argc, char **argv)
305305
return 1;
306306
}
307307
if (!isAlphaWorld(filename)) {
308-
printf("Error: Given path does not contain an alpha/beta world.\n");
308+
printf("Error: Given path does not contain a Minecraft world.\n");
309309
return 1;
310310
}
311311
if (g_Hell) {
@@ -327,19 +327,16 @@ int main(int argc, char **argv)
327327
}
328328
filename = tmp;
329329
}
330-
{ // Figure out whether this is the old save format or McRegion
331-
char tmp[1000];
332-
snprintf(tmp, 1000, "%s/region", filename);
333-
if (dirExists(tmp)) {
334-
printf("McRegion world format detected.\n");
335-
g_RegionFormat = true;
330+
// Figure out whether this is the old save format or McRegion or Anvil
331+
g_WorldFormat = getWorldFormat(filename);
332+
333+
if (g_WorldFormat < 2) {
334+
if (g_MapsizeY > CHUNKSIZE_Y) {
335+
g_MapsizeY = CHUNKSIZE_Y;
336+
}
337+
if (g_MapminY > CHUNKSIZE_Y) {
338+
g_MapminY = CHUNKSIZE_Y;
336339
}
337-
}
338-
if (g_MapsizeY > CHUNKSIZE_Y) {
339-
g_MapsizeY = CHUNKSIZE_Y;
340-
}
341-
if (g_MapminY > CHUNKSIZE_Y) {
342-
g_MapminY = CHUNKSIZE_Y;
343340
}
344341
if (wholeworld && !scanWorldDirectory(filename)) {
345342
printf("Error accessing terrain at '%s'\n", filename);
@@ -353,7 +350,10 @@ int main(int argc, char **argv)
353350
printf("Nothing to render: -min Y has to be < -max/-height Y\n");
354351
return 1;
355352
}
353+
g_SectionMin = g_MapminY >> SECTION_Y_SHIFT;
354+
g_SectionMax = (g_MapsizeY - 1) >> SECTION_Y_SHIFT;
356355
g_MapsizeY -= g_MapminY;
356+
printf("MinY: %d ... MaxY: %d ... MinSecY: %d ... MaxSecY: %d\n", g_MapminY, g_MapsizeY, g_SectionMin, g_SectionMax);
357357
// Whole area to be rendered, in chunks
358358
// If -mem is omitted or high enough, this won't be needed
359359
g_TotalFromChunkX = g_FromChunkX;
@@ -477,6 +477,12 @@ int main(int argc, char **argv)
477477
createImageBuffer(bitmapX, bitmapY, splitImage);
478478
}
479479

480+
// Precompute brightness adjustment factor
481+
float *brightnessLookup = new float[g_MapsizeY];
482+
for (int y = 0; y < g_MapsizeY; ++y) {
483+
brightnessLookup[y] = ((100.0f / (1.0f + exp(- (1.3f * (float(y) * 128.0f / g_MapsizeY) / 16.0f) + 6.0f))) - 91); // thx Donkey Kong
484+
}
485+
480486
// Now here's the loop rendering all the required parts of the image.
481487
// All the vars previously used to define bounds will be set on each loop,
482488
// to create something like a virtual window inside the map.
@@ -580,15 +586,15 @@ int main(int argc, char **argv)
580586
//
581587
const int bmpPosX = int((g_MapsizeZ - z - CHUNKSIZE_Z) * 2 + (x - CHUNKSIZE_X) * 2 + (splitImage ? -2 : bitmapStartX - cropLeft));
582588
int bmpPosY = int(g_MapsizeY * g_OffsetY + z + x - CHUNKSIZE_Z - CHUNKSIZE_X + (splitImage ? 0 : bitmapStartY - cropTop)) + 2 - (HEIGHTAT(x, z) & 0xFF) * g_OffsetY;
583-
const size_t max = (HEIGHTAT(x, z) & 0xFF00) >> 8;
584-
for (size_t y = uint8_t(HEIGHTAT(x, z)); y < max; ++y) {
589+
const int max = (HEIGHTAT(x, z) & 0xFF00) >> 8;
590+
for (int y = uint8_t(HEIGHTAT(x, z)); y < max; ++y) {
585591
bmpPosY -= g_OffsetY;
586592
uint8_t &c = BLOCKAT(x, y, z);
587593
if (c == AIR) {
588594
continue;
589595
}
590596
//float col = float(y) * .78f - 91;
591-
float brightnessAdjustment = (100.0f / (1.0f + exp(- (1.3f * float(y) / 16.0f) + 6.0f))) - 91; // thx Donkey Kong
597+
float brightnessAdjustment = brightnessLookup[y];
592598
if (g_BlendUnderground) {
593599
brightnessAdjustment -= 168;
594600
}
@@ -735,7 +741,7 @@ void optimizeTerrain2(int cropLeft, int cropRight)
735741
for (int z = CHUNKSIZE_Z; z < maxZ; ++z) {
736742
const uint8_t *block = &BLOCKAT(x, 0, z); // Get the lowest block at that point
737743
int highest = 0, lowest = 0xFF; // remember lowest and highest block which are visible to limit the Y-for-loop later
738-
for (size_t y = 0; y < g_MapsizeY; ++y) { // Go up
744+
for (int y = 0; y < g_MapsizeY; ++y) { // Go up
739745
uint8_t &current = blocked[((y+offsetY) % g_MapsizeY) + (offsetZ % modZ)];
740746
if (current) { // Block is hidden, remove
741747
#ifdef _DEBUG
@@ -758,7 +764,7 @@ void optimizeTerrain2(int cropLeft, int cropRight)
758764
blocked[(offsetY % g_MapsizeY) + (offsetZ % modZ)] = 0;
759765
offsetZ += g_MapsizeY;
760766
}
761-
for (size_t y = 0; y < g_MapsizeY; ++y) {
767+
for (int y = 0; y < g_MapsizeY; ++y) {
762768
blocked[y + (offsetGlobal % modZ)] = 0;
763769
}
764770
offsetGlobal += g_MapsizeY;
@@ -780,24 +786,23 @@ void optimizeTerrain3()
780786
gBlocksRemoved = 0;
781787
#endif
782788
printProgress(0, 10);
783-
const int top = (int)g_MapsizeY;
784789
// Helper arrays to remember which block is blocked from being seen. This allows to traverse the array in a slightly more sequential way, which leads to better usage of the CPU cache
785-
uint8_t blocked[CHUNKSIZE_Y*3];
790+
uint8_t *blocked = new uint8_t[g_MapsizeY*3];
786791
const int max = (int)MIN(g_MapsizeX - CHUNKSIZE_X * 2, g_MapsizeZ - CHUNKSIZE_Z * 2);
787792
const int maxX = int(g_MapsizeX - CHUNKSIZE_X - 1);
788793
const int maxZ = int(g_MapsizeZ - CHUNKSIZE_Z - 1);
789794
const size_t maxProgress = size_t(maxX + maxZ);
790795
// The following needs to be done twice, once for the X-Y front plane, once for the Z-Y front plane
791796
for (int x = CHUNKSIZE_X; x <= maxX; ++x) {
792-
memset(blocked, 0, CHUNKSIZE_Y*3); // Nothing is blocked at first
797+
memset(blocked, 0, g_MapsizeY*3); // Nothing is blocked at first
793798
int offset = 0; // The helper array had to be shifted after each run of the inner most loop. As this is expensive, just use an offset that increases instead
794799
const int max2 = MIN(max, x - CHUNKSIZE_X + 1); // Block array will be traversed diagonally, determine how many blocks there are
795800
for (int i = 0; i < max2; ++i) { // This traverses the block array diagonally, which would be upwards in the image
796-
const int blockedOffset = CHUNKSIZE_Y * (i % 3);
801+
const int blockedOffset = g_MapsizeY * (i % 3);
797802
uint8_t *block = &BLOCKAT(x - i, 0, maxZ - i); // Get the lowest block at that point
798803
int highest = 0, lowest = 0xFF;
799-
for (int j = 0; j < top; ++j) { // Go up
800-
if (blocked[blockedOffset + (j+offset) % top]) { // Block is hidden, remove
804+
for (int j = 0; j < g_MapsizeY; ++j) { // Go up
805+
if (blocked[blockedOffset + (j+offset) % g_MapsizeY]) { // Block is hidden, remove
801806
#ifdef _DEBUG
802807
if (*block != AIR) {
803808
++gBlocksRemoved;
@@ -808,31 +813,31 @@ void optimizeTerrain3()
808813
lowest = j;
809814
}
810815
if (colors[*block][PALPHA] == 255) { // Block is not hidden, do not remove, but mark spot as blocked for next iteration
811-
blocked[blockedOffset + (j+offset) % top] = 1;
816+
blocked[blockedOffset + (j+offset) % g_MapsizeY] = 1;
812817
}
813818
if (*block != AIR) highest = j;
814819
}
815820
++block; // Go up
816821
}
817822
HEIGHTAT(x - i, maxZ - i) = (((uint16_t)highest + 1) << 8) | (uint16_t)lowest;
818-
blocked[blockedOffset + ((offset + 1) % top)] = 0; // This will be the array index responsible for the top most block in the next itaration. Set it to 0 as it can't be hidden.
819-
blocked[blockedOffset + (offset % top)] = 0;
823+
blocked[blockedOffset + ((offset + 1) % g_MapsizeY)] = 0; // This will be the array index responsible for the top most block in the next itaration. Set it to 0 as it can't be hidden.
824+
blocked[blockedOffset + (offset % g_MapsizeY)] = 0;
820825
if (i % 3 == 2) {
821826
offset += 2; // Increase offset, as block at height n in current row will hide block at n-1 in next row
822827
}
823828
}
824829
printProgress(size_t(x), maxProgress);
825830
}
826831
for (int z = CHUNKSIZE_Z; z < maxZ; ++z) {
827-
memset(blocked, 0, CHUNKSIZE_Y*3);
832+
memset(blocked, 0, g_MapsizeY*3);
828833
int offset = 0;
829834
const int max2 = MIN(max, z - CHUNKSIZE_Z + 1);
830835
for (int i = 0; i < max2; ++i) {
831-
const int blockedOffset = CHUNKSIZE_Y * (i % 3);
836+
const int blockedOffset = g_MapsizeY * (i % 3);
832837
uint8_t *block = &BLOCKAT(maxX - i, 0, z - i);
833838
int highest = 0, lowest = 0xFF;
834-
for (int j = 0; j < top; ++j) {
835-
if (blocked[blockedOffset + (j+offset) % top]) {
839+
for (int j = 0; j < g_MapsizeY; ++j) {
840+
if (blocked[blockedOffset + (j+offset) % g_MapsizeY]) {
836841
#ifdef _DEBUG
837842
if (*block != AIR) {
838843
++gBlocksRemoved;
@@ -843,21 +848,22 @@ void optimizeTerrain3()
843848
lowest = j;
844849
}
845850
if (colors[*block][PALPHA] == 255) {
846-
blocked[blockedOffset + (j+offset) % top] = 1;
851+
blocked[blockedOffset + (j+offset) % g_MapsizeY] = 1;
847852
}
848853
if (*block != AIR) highest = j;
849854
}
850855
++block;
851856
}
852857
HEIGHTAT(maxX - i, z - i) = (((uint16_t)highest + 1) << 8) | (uint16_t)lowest;
853-
blocked[blockedOffset + ((offset + 1) % top)] = 0;
854-
blocked[blockedOffset + (offset % top)] = 0;
858+
blocked[blockedOffset + ((offset + 1) % g_MapsizeY)] = 0;
859+
blocked[blockedOffset + (offset % g_MapsizeY)] = 0;
855860
if (i % 3 == 2) {
856861
offset += 2;
857862
}
858863
}
859864
printProgress(size_t(z + maxX), maxProgress);
860865
}
866+
delete[] blocked;
861867
printProgress(10, 10);
862868
#ifdef _DEBUG
863869
printf("Removed %lu blocks\n", (unsigned long) gBlocksRemoved);
@@ -875,7 +881,7 @@ void undergroundMode(bool explore)
875881
for (size_t x = CHUNKSIZE_X; x < g_MapsizeX - CHUNKSIZE_X; ++x) {
876882
printProgress(x - CHUNKSIZE_X, g_MapsizeX);
877883
for (size_t z = CHUNKSIZE_Z; z < g_MapsizeZ - CHUNKSIZE_Z; ++z) {
878-
for (size_t y = 0; y < MIN(g_MapsizeY, 64) - 1; y++) {
884+
for (int y = 0; y < MIN(g_MapsizeY, 64) - 1; y++) {
879885
if (BLOCKAT(x, y, z) == TORCH) {
880886
// Torch
881887
BLOCKAT(x, y, z) = AIR;
@@ -915,7 +921,7 @@ void undergroundMode(bool explore)
915921
for (size_t z = 0; z < g_MapsizeZ; ++z) {
916922
size_t ground = 0;
917923
size_t cave = 0;
918-
for (size_t y = g_MapsizeY - 1; y < g_MapsizeY; --y) {
924+
for (int y = g_MapsizeY - 1; y < g_MapsizeY; --y) {
919925
uint8_t &c = BLOCKAT(x, y, z);
920926
if (c != AIR && cave > 0) { // Found a cave, leave floor
921927
if (c == GRASS || c == LEAVES || c == SNOW || GETLIGHTAT(x, y, z) == 0) {
@@ -1019,19 +1025,19 @@ void writeInfoFile(const char* file, int xo, int yo, int bitmapX, int bitmapY)
10191025
char *direction = NULL;
10201026
if (g_Orientation == North) {
10211027
xo += (g_TotalToChunkZ * CHUNKSIZE_Z - g_FromChunkX * CHUNKSIZE_X) * 2 + 4;
1022-
yo -= (g_TotalFromChunkX * CHUNKSIZE_X + g_TotalFromChunkZ * CHUNKSIZE_Z) - CHUNKSIZE_Y * g_OffsetY;
1028+
yo -= (g_TotalFromChunkX * CHUNKSIZE_X + g_TotalFromChunkZ * CHUNKSIZE_Z) - g_MapsizeY * g_OffsetY;
10231029
direction = (char*)"North";
10241030
} else if (g_Orientation == South) {
10251031
xo += (g_TotalToChunkX * CHUNKSIZE_X - g_TotalFromChunkZ * CHUNKSIZE_Z) * 2 + 4;
1026-
yo += ((g_TotalToChunkX) * CHUNKSIZE_X + (g_TotalToChunkZ) * CHUNKSIZE_Z) + CHUNKSIZE_Y * g_OffsetY;
1032+
yo += ((g_TotalToChunkX) * CHUNKSIZE_X + (g_TotalToChunkZ) * CHUNKSIZE_Z) + g_MapsizeY * g_OffsetY;
10271033
direction = (char*)"South";
10281034
} else if (g_Orientation == East) {
10291035
xo -= (g_TotalFromChunkX * CHUNKSIZE_X + g_TotalFromChunkZ * CHUNKSIZE_Z) * g_OffsetY - 6;
1030-
yo += ((g_TotalToChunkX) * CHUNKSIZE_X - g_TotalFromChunkZ * CHUNKSIZE_Z) + CHUNKSIZE_Y * g_OffsetY;
1036+
yo += ((g_TotalToChunkX) * CHUNKSIZE_X - g_TotalFromChunkZ * CHUNKSIZE_Z) + g_MapsizeY * g_OffsetY;
10311037
direction = (char*)"East";
10321038
} else {
10331039
xo += (g_TotalToChunkX * CHUNKSIZE_X + g_TotalToChunkZ * CHUNKSIZE_Z) * g_OffsetY + 2;
1034-
yo += ((g_TotalToChunkZ) * CHUNKSIZE_Z - g_TotalFromChunkX * CHUNKSIZE_X) + CHUNKSIZE_Y * g_OffsetY;
1040+
yo += ((g_TotalToChunkZ) * CHUNKSIZE_Z - g_TotalFromChunkX * CHUNKSIZE_X) + g_MapsizeY * g_OffsetY;
10351041
direction = (char*)"West";
10361042
}
10371043
FILE *fh = fopen(file, "w");
@@ -1106,8 +1112,8 @@ void printHelp(char *binary)
11061112
" -skylight use skylight when rendering map (shadows below trees etc.)\n"
11071113
" hint: using this with -night makes a difference\n"
11081114
" -noise VAL adds some noise to certain blocks, reasonable values are 0-20\n"
1109-
" -height VAL maximum height at which blocks will be rendered (1-%d)\n"
1110-
" -min/max VAL minimum/maximum Y index (height) of blocks to render (0-127)\n"
1115+
" -height VAL maximum height at which blocks will be rendered\n"
1116+
" -min/max VAL minimum/maximum Y index (height) of blocks to render\n"
11111117
" -file NAME sets the output filename to 'NAME'; default is output.png\n"
11121118
" -mem VAL sets the amount of memory (in MiB) used for rendering. mcmap\n"
11131119
" will use incremental rendering or disk caching to stick to\n"
@@ -1146,5 +1152,5 @@ void printHelp(char *binary)
11461152
" - This would render the same world but at night, and only\n"
11471153
" from chunk (-10 -10) to chunk (10 10)\n"
11481154
#endif
1149-
, binary,(int)CHUNKSIZE_Y, binary, binary);
1155+
, binary, binary, binary);
11501156
}

nbt.cpp

+31-1
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,18 @@ NBT_Tag::~NBT_Tag()
352352
}
353353
}
354354

355+
void NBT_Tag::printTags()
356+
{
357+
if (_type != tagCompound) {
358+
printf("Not a tagCompound\n");
359+
return;
360+
}
361+
for (tagmap::iterator it = _elems->begin(); it != _elems->end(); it++) {
362+
printf("Have compound '%s' of type %d\n", it->first.c_str(), (int)it->second->getType());
363+
}
364+
printf("End list.\n");
365+
}
366+
355367

356368
// ----- Data getters -------
357369
// The return value is always a boolean, telling you if the tag was found and the operation
@@ -368,9 +380,27 @@ bool NBT_Tag::getCompound(const string name, NBT_Tag* &compound)
368380
return true;
369381
}
370382

383+
bool NBT_Tag::getList(const string name, list<NBT_Tag *>* &lst)
384+
{
385+
if (_type != tagCompound || _elems->find(name) == _elems->end() || (*_elems)[name]->getType() != tagList) {
386+
return false;
387+
}
388+
lst = (*_elems)[name]->_list;
389+
return true;
390+
}
391+
392+
bool NBT_Tag::getByte(const string name, int8_t &value)
393+
{
394+
if (_type != tagCompound || _elems->find(name) == _elems->end() || (*_elems)[name]->getType() != tagByte) {
395+
return false;
396+
}
397+
value = *(int8_t*)(*_elems)[name]->_data;
398+
return true;
399+
}
400+
371401
bool NBT_Tag::getShort(const string name, int16_t &value)
372402
{
373-
if (_type != tagCompound || _elems->find(name) == _elems->end() || (*_elems)[name]->getType() != tagInt) {
403+
if (_type != tagCompound || _elems->find(name) == _elems->end() || (*_elems)[name]->getType() != tagShort) {
374404
return false;
375405
}
376406
value = _ntohs((*_elems)[name]->_data);

0 commit comments

Comments
 (0)