diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index 29f9d2f..03badca 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -108,11 +108,14 @@ PyObject *init_chunk_render(void) { * If clearexception is true, clears the exception before returning NULL (for * soft failures) */ -PyObject *get_chunk_data(RenderState *state, ChunkNeighborName neighbor, ChunkDataType type, - unsigned char clearexception) { +PyObject *get_chunk_data(RenderState *state, ChunkNeighborName neighbor, ChunkDataType type, unsigned char clearexception) { int x = state->chunkx; + int y = state->chunky; int z = state->chunkz; + int i; PyObject *chunk = NULL; + PyObject *sections = NULL; + PyObject *section = NULL; PyObject *data = NULL; switch (neighbor) { @@ -142,24 +145,57 @@ PyObject *get_chunk_data(RenderState *state, ChunkNeighborName neighbor, ChunkDa return NULL; } + /* now we grab the correct section of the chunk */ + + sections = PyDict_GetItemString(chunk, "Sections"); + if (sections) { + sections = PySequence_Fast(sections, "Sections tag was not a list!"); + } + Py_DECREF(chunk); + if (sections == NULL) { + // exception set, again + if (clearexception) { + PyErr_Clear(); + } + return NULL; + } + + for (i = 0; i < PySequence_Fast_GET_SIZE(sections); i++) { + PyObject *ycoord = NULL; + section = PySequence_Fast_GET_ITEM(sections, i); + ycoord = PyDict_GetItemString(section, "Y"); + if (ycoord && PyInt_AsLong(ycoord) == y) { + Py_INCREF(section); + break; + } + section = NULL; + } + Py_DECREF(sections); + if (section == NULL) { + // exception NOT set this time, but we don't set it because + // missing *sections* are normal operation + // (missing chunks, as above, are NOT.) + return NULL; + } + switch (type) { case BLOCKS: - data = PyDict_GetItemString(chunk, "Blocks"); + data = PyDict_GetItemString(section, "Blocks"); break; case BLOCKDATA: - data = PyDict_GetItemString(chunk, "Data"); + data = PyDict_GetItemString(section, "Data"); break; case SKYLIGHT: - data = PyDict_GetItemString(chunk, "SkyLight"); + data = PyDict_GetItemString(section, "SkyLight"); break; case BLOCKLIGHT: - data = PyDict_GetItemString(chunk, "BlockLight"); + data = PyDict_GetItemString(section, "BlockLight"); break; } - /* fix the borrowed reference */ + /* fix the references */ Py_INCREF(data); - Py_DECREF(chunk); + Py_DECREF(section); return data; } @@ -400,7 +436,6 @@ PyObject* chunk_render(PyObject *self, PyObject *args) { RenderState state; PyObject *regionset; - int chunkx, chunkz; PyObject *modeobj; PyObject *blockmap; @@ -419,7 +454,7 @@ chunk_render(PyObject *self, PyObject *args) { PyObject *t = NULL; - if (!PyArg_ParseTuple(args, "OiiOiiOO", &state.regionset, &state.chunkx, &state.chunkz, &state.img, &xoff, &yoff, &modeobj, &state.textures)) + if (!PyArg_ParseTuple(args, "OiiiOiiOO", &state.regionset, &state.chunkx, &state.chunky, &state.chunkz, &state.img, &xoff, &yoff, &modeobj, &state.textures)) return NULL; /* set up the render mode */ @@ -453,13 +488,15 @@ chunk_render(PyObject *self, PyObject *args) { /* get the block data directly from numpy: */ blocks_py = get_chunk_data(&state, CURRENT, BLOCKS, 0); state.blocks = blocks_py; - if (blocks_py == NULL) { - return NULL; - } - state.blockdatas = get_chunk_data(&state, CURRENT, BLOCKDATA, 1); - if (state.blockdatas == NULL) { - return NULL; + + if (state.blockdatas == NULL || state.blocks == NULL) { + /* only error out completely if there's an exception set this function + will return NULL with no exception IFF the requested section was + missing. */ + if (PyErr_Occurred()) + return NULL; + Py_RETURN_NONE; } left_blocks_py = get_chunk_data(&state, DOWN_LEFT, BLOCKS, 1); @@ -479,20 +516,20 @@ chunk_render(PyObject *self, PyObject *args) { srand(1); for (state.x = 15; state.x > -1; state.x--) { - for (state.y = 0; state.y < 16; state.y++) { + for (state.z = 0; state.z < 16; state.z++) { /* set up the render coordinates */ - state.imgx = xoff + state.x*12 + state.y*12; - /* 128*12 -- offset for z direction, 15*6 -- offset for x */ - state.imgy = yoff - state.x*6 + state.y*6 + 128*12 + 15*6; + state.imgx = xoff + state.x*12 + state.z*12; + /* 16*12 -- offset for y direction, 15*6 -- offset for x */ + state.imgy = yoff - state.x*6 + state.z*6 + 16*12 + 15*6; - for (state.z = 0; state.z < 128; state.z++) { + for (state.y = 0; state.y < 16; state.y++) { unsigned char ancilData; state.imgy -= 12; /* get blockid */ - state.block = getArrayByte3D(blocks_py, state.x, state.y, state.z); + state.block = getArrayShort3D(blocks_py, state.x, state.y, state.z); if (state.block == 0 || render_mode_hidden(rendermode, state.x, state.y, state.z)) { continue; } @@ -590,5 +627,5 @@ chunk_render(PyObject *self, PyObject *args) { Py_XDECREF(up_left_blocks_py); Py_XDECREF(up_right_blocks_py); - return Py_BuildValue("i",2); + Py_RETURN_NONE; } diff --git a/overviewer_core/src/overviewer.h b/overviewer_core/src/overviewer.h index e73fb36..10394dd 100644 --- a/overviewer_core/src/overviewer.h +++ b/overviewer_core/src/overviewer.h @@ -26,15 +26,18 @@ // increment this value if you've made a change to the c extesion // and want to force users to rebuild -#define OVERVIEWER_EXTENSION_VERSION 20 +#define OVERVIEWER_EXTENSION_VERSION 21 /* Python PIL, and numpy headers */ #include #include #include -/* macro for getting a value out of various numpy arrays */ -#define getArrayByte3D(array, x,y,z) (*(unsigned char *)(PyArray_GETPTR3((array), (x), (y), (z)))) +/* macro for getting a value out of various numpy arrays the 3D arrays have + interesting, swizzled coordinates because minecraft (anvil) stores blocks + in y/z/x order */ +#define getArrayByte3D(array, x,y,z) (*(unsigned char *)(PyArray_GETPTR3((array), (y), (z), (x)))) +#define getArrayShort3D(array, x,y,z) (*(unsigned short *)(PyArray_GETPTR3((array), (y), (z), (x)))) #define getArrayShort2D(array, x,y) (*(unsigned short *)(PyArray_GETPTR2((array), (x), (y)))) /* generally useful MAX / MIN macros */ @@ -67,7 +70,7 @@ typedef struct _RenderMode RenderMode; typedef struct { /* the regionset object, and chunk coords */ PyObject *regionset; - int chunkx, chunkz; + int chunkx, chunky, chunkz; /* the tile image and destination */ PyObject *img; @@ -81,7 +84,7 @@ typedef struct { /* the block position and type, and the block array */ int x, y, z; - unsigned char block; + unsigned short block; unsigned char block_data; unsigned char block_pdata; diff --git a/overviewer_core/src/primitives/base.c b/overviewer_core/src/primitives/base.c index 6c8d6b5..80622f0 100644 --- a/overviewer_core/src/primitives/base.c +++ b/overviewer_core/src/primitives/base.c @@ -59,7 +59,7 @@ base_finish(void *data, RenderState *state) { static int base_occluded(void *data, RenderState *state, int x, int y, int z) { - if ( (x != 0) && (y != 15) && (z != 127) && + if ( (x != 0) && (y != 15) && (z != 15) && !render_mode_hidden(state->rendermode, x-1, y, z) && !render_mode_hidden(state->rendermode, x, y, z+1) && !render_mode_hidden(state->rendermode, x, y+1, z) &&