From 5184c8d3212f7e4850adfb4ab0c784a368f9113a Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Tue, 24 Apr 2012 17:04:51 -0700 Subject: [PATCH 01/14] Added and documented the "exposed" render mode primitive. --- CONTRIBUTORS.rst | 1 + docs/config.rst | 8 +++ overviewer_core/rendermodes.py | 6 ++ overviewer_core/src/primitives/exposed.c | 91 ++++++++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 overviewer_core/src/primitives/exposed.c diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index ff8eb83..6c8da67 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -69,6 +69,7 @@ feature. * Ryan McCue * Zach McCullough * Mike + * Adam Novak * Morlok8k * Richard Pastrick * Ryan Rector diff --git a/docs/config.rst b/docs/config.rst index 042ae0d..ef4dbed 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -611,6 +611,14 @@ Depth max highest level of blocks to render. Default: 255 +Exposed + Only renders blocks that are exposed (adjacent to a transparent block). + + **Options** + + mode + when set to 1, inverts the render mode, only drawing unexposed blocks. Default: 0 + EdgeLines Draw edge lines on the back side of blocks, to help distinguish them from the background. diff --git a/overviewer_core/rendermodes.py b/overviewer_core/rendermodes.py index e1adc9c..2f5d3c8 100644 --- a/overviewer_core/rendermodes.py +++ b/overviewer_core/rendermodes.py @@ -62,6 +62,12 @@ class Depth(RenderPrimitive): "min": ("lowest level of blocks to render", 0), "max": ("highest level of blocks to render", 255), } + +class Exposed(RenderPrimitive): + name = "exposed" + options = { + "mode": ("0 = exposed blocks only, 1 = unexposed blocks only", 0), + } class EdgeLines(RenderPrimitive): name = "edge-lines" diff --git a/overviewer_core/src/primitives/exposed.c b/overviewer_core/src/primitives/exposed.c new file mode 100644 index 0000000..d05ac66 --- /dev/null +++ b/overviewer_core/src/primitives/exposed.c @@ -0,0 +1,91 @@ +/* + * This file is part of the Minecraft Overviewer. + * + * Minecraft Overviewer is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Minecraft Overviewer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the Overviewer. If not, see . + */ + +#include "../overviewer.h" + +typedef struct { + unsigned int mode; /* 0 = exposed only, 1 = unexposed only */ +} PrimitiveExposed; + +static int +exposed_start(void *data, RenderState *state, PyObject *support) { + PrimitiveExposed *self = (PrimitiveExposed *)data; + + if (!render_mode_parse_option(support, "mode", "I", &(self->mode))) + return 1; + + return 0; +} + +static int +exposed_hidden(void *data, RenderState *state, int x, int y, int z) { + PrimitiveExposed *self = (PrimitiveExposed *)data; + + /* Unset these flags if seeming exposure from any of these directions would + * be due to not having data there. + */ + int validMinusX = 1; + int validPlusY = 1; + int validPlusZ = 1; + + /* special handling for section boundaries */ + /* If the neighboring section has no block data, ignore exposure from that + * direction + */ + if (x == 0 && (!(state->chunks[0][1].loaded) || state->chunks[0][1].sections[state->chunky].blocks == NULL)) { + /* No data in -x direction */ + validMinusX = 0; + } + + if (y == 15 && (state->chunky + 1 >= SECTIONS_PER_CHUNK || state->chunks[1][1].sections[state->chunky + 1].blocks == NULL)) { + /* No data in +y direction */ + validPlusY = 0; + } + + if (z == 15 && (!(state->chunks[1][2].loaded) || state->chunks[1][2].sections[state->chunky].blocks == NULL)) { + /* No data in +z direction */ + validPlusZ = 0; + } + + /* If any of the 6 blocks adjacent to us are transparent, we're exposed */ + if( (validMinusX && is_transparent(get_data(state, BLOCKS, x-1, y, z))) || + is_transparent(get_data(state, BLOCKS, x+1, y, z)) || + is_transparent(get_data(state, BLOCKS, x, y-1, z)) || + (validPlusY && is_transparent(get_data(state, BLOCKS, x, y+1, z))) || + is_transparent(get_data(state, BLOCKS, x, y, z-1)) || + (validPlusZ && is_transparent(get_data(state, BLOCKS, x, y, z+1 ))) ) { + + /* Block is exposed */ + /* Returns 1 and hides us if we're rendering unexposed blocks, 0 and + * shows us if we're rendering exposed blocks + */ + return self->mode; + + } + + /* We have no valid evidence that the block is exposed */ + return !(self->mode); /* Hide in normal mode, reveal in inverted mode */ +} + +RenderPrimitiveInterface primitive_exposed = { + "exposed", sizeof(PrimitiveExposed), + exposed_start, + NULL, + NULL, + exposed_hidden, + NULL, +}; From 9df14462769eab275128a82fe30983ee3062e438 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Tue, 24 Apr 2012 20:29:27 -0700 Subject: [PATCH 02/14] Added a NoFluids render mode primitive, and documented it. --- docs/config.rst | 3 ++ overviewer_core/rendermodes.py | 3 ++ overviewer_core/src/primitives/no-fluids.c | 44 ++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 overviewer_core/src/primitives/no-fluids.c diff --git a/docs/config.rst b/docs/config.rst index ef4dbed..9bc38d8 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -618,6 +618,9 @@ Exposed mode when set to 1, inverts the render mode, only drawing unexposed blocks. Default: 0 + +NoFluids + Don't render fluid blocks (water, lava). EdgeLines Draw edge lines on the back side of blocks, to help distinguish them from diff --git a/overviewer_core/rendermodes.py b/overviewer_core/rendermodes.py index 2f5d3c8..a161656 100644 --- a/overviewer_core/rendermodes.py +++ b/overviewer_core/rendermodes.py @@ -68,6 +68,9 @@ class Exposed(RenderPrimitive): options = { "mode": ("0 = exposed blocks only, 1 = unexposed blocks only", 0), } + +class NoFluids(RenderPrimitive): + name = "no-fluids" class EdgeLines(RenderPrimitive): name = "edge-lines" diff --git a/overviewer_core/src/primitives/no-fluids.c b/overviewer_core/src/primitives/no-fluids.c new file mode 100644 index 0000000..1f6cc16 --- /dev/null +++ b/overviewer_core/src/primitives/no-fluids.c @@ -0,0 +1,44 @@ +/* + * This file is part of the Minecraft Overviewer. + * + * Minecraft Overviewer is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Minecraft Overviewer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the Overviewer. If not, see . + */ + +#include "../overviewer.h" + +typedef struct { +} PrimitiveNoFluids; + +static int +no_fluids_start(void *data, RenderState *state, PyObject *support) { + PrimitiveNoFluids *self = (PrimitiveNoFluids *)data; + + return 0; +} + +static int +no_fluids_hidden(void *data, RenderState *state, int x, int y, int z) { + PrimitiveNoFluids *self = (PrimitiveNoFluids *)data; + + return !block_has_property(state->block, FLUID); +} + +RenderPrimitiveInterface primitive_no_fluids = { + "no-fluids", sizeof(PrimitiveNoFluids), + no_fluids_start, + NULL, + NULL, + no_fluids_hidden, + NULL, +}; From b1e4b09ab68bfb31e4cdf790ed9bcc3deffeb3d6 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Tue, 24 Apr 2012 20:35:00 -0700 Subject: [PATCH 03/14] Removing unused struct. --- overviewer_core/src/primitives/no-fluids.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/overviewer_core/src/primitives/no-fluids.c b/overviewer_core/src/primitives/no-fluids.c index 1f6cc16..fe1c704 100644 --- a/overviewer_core/src/primitives/no-fluids.c +++ b/overviewer_core/src/primitives/no-fluids.c @@ -17,25 +17,18 @@ #include "../overviewer.h" -typedef struct { -} PrimitiveNoFluids; - static int no_fluids_start(void *data, RenderState *state, PyObject *support) { - PrimitiveNoFluids *self = (PrimitiveNoFluids *)data; - return 0; } static int no_fluids_hidden(void *data, RenderState *state, int x, int y, int z) { - PrimitiveNoFluids *self = (PrimitiveNoFluids *)data; - return !block_has_property(state->block, FLUID); } RenderPrimitiveInterface primitive_no_fluids = { - "no-fluids", sizeof(PrimitiveNoFluids), + "no-fluids", 0, no_fluids_start, NULL, NULL, From 915aa1a653991f7469a995573a7de5bdc7e4ff47 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Tue, 24 Apr 2012 20:40:39 -0700 Subject: [PATCH 04/14] Inverting sense of no-fluids to be correct. --- overviewer_core/src/primitives/no-fluids.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overviewer_core/src/primitives/no-fluids.c b/overviewer_core/src/primitives/no-fluids.c index fe1c704..cb6428a 100644 --- a/overviewer_core/src/primitives/no-fluids.c +++ b/overviewer_core/src/primitives/no-fluids.c @@ -24,7 +24,7 @@ no_fluids_start(void *data, RenderState *state, PyObject *support) { static int no_fluids_hidden(void *data, RenderState *state, int x, int y, int z) { - return !block_has_property(state->block, FLUID); + return block_has_property(state->block, FLUID); } RenderPrimitiveInterface primitive_no_fluids = { From e0c4137eb49b4bfe3b07801e0a034c9109159a54 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Wed, 25 Apr 2012 00:02:20 -0700 Subject: [PATCH 05/14] Checking for missing data on all sides. --- overviewer_core/src/primitives/exposed.c | 26 ++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/overviewer_core/src/primitives/exposed.c b/overviewer_core/src/primitives/exposed.c index d05ac66..1047beb 100644 --- a/overviewer_core/src/primitives/exposed.c +++ b/overviewer_core/src/primitives/exposed.c @@ -39,7 +39,10 @@ exposed_hidden(void *data, RenderState *state, int x, int y, int z) { * be due to not having data there. */ int validMinusX = 1; + int validPlusX = 1; + int validMinusY = 1; int validPlusY = 1; + int validMinusZ = 1; int validPlusZ = 1; /* special handling for section boundaries */ @@ -50,12 +53,27 @@ exposed_hidden(void *data, RenderState *state, int x, int y, int z) { /* No data in -x direction */ validMinusX = 0; } + + if (x == 15 && (!(state->chunks[2][1].loaded) || state->chunks[2][1].sections[state->chunky].blocks == NULL)) { + /* No data in +x direction */ + validPlusX = 0; + } + + if (y == 0 && (state->chunky - 1 < 0 || state->chunks[1][1].sections[state->chunky - 1].blocks == NULL)) { + /* No data in -y direction */ + validMinusY = 0; + } if (y == 15 && (state->chunky + 1 >= SECTIONS_PER_CHUNK || state->chunks[1][1].sections[state->chunky + 1].blocks == NULL)) { /* No data in +y direction */ validPlusY = 0; } + if (z == 0 && (!(state->chunks[1][0].loaded) || state->chunks[1][0].sections[state->chunky].blocks == NULL)) { + /* No data in -z direction */ + validMinusZ = 0; + } + if (z == 15 && (!(state->chunks[1][2].loaded) || state->chunks[1][2].sections[state->chunky].blocks == NULL)) { /* No data in +z direction */ validPlusZ = 0; @@ -63,10 +81,10 @@ exposed_hidden(void *data, RenderState *state, int x, int y, int z) { /* If any of the 6 blocks adjacent to us are transparent, we're exposed */ if( (validMinusX && is_transparent(get_data(state, BLOCKS, x-1, y, z))) || - is_transparent(get_data(state, BLOCKS, x+1, y, z)) || - is_transparent(get_data(state, BLOCKS, x, y-1, z)) || - (validPlusY && is_transparent(get_data(state, BLOCKS, x, y+1, z))) || - is_transparent(get_data(state, BLOCKS, x, y, z-1)) || + (validPlusX && is_transparent(get_data(state, BLOCKS, x+1, y, z))) || + (validMinusY && is_transparent(get_data(state, BLOCKS, x, y-1, z))) || + (validPlusY && is_transparent(get_data(state, BLOCKS, x, y+1, z))) || + (validMinusZ && is_transparent(get_data(state, BLOCKS, x, y, z-1))) || (validPlusZ && is_transparent(get_data(state, BLOCKS, x, y, z+1 ))) ) { /* Block is exposed */ From 1f29ff5fa18ad2c1910c187259fa94d4c028d9fc Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Wed, 25 Apr 2012 13:04:46 -0700 Subject: [PATCH 06/14] Fixed contributors ordering. --- CONTRIBUTORS.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index 6c8da67..4df9493 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -69,8 +69,8 @@ feature. * Ryan McCue * Zach McCullough * Mike - * Adam Novak * Morlok8k + * Adam Novak * Richard Pastrick * Ryan Rector * Jason Scheirer From 85567cae42854ce6232493fab66c161d313c5d92 Mon Sep 17 00:00:00 2001 From: Fabian Norman Date: Wed, 25 Apr 2012 19:42:18 -0700 Subject: [PATCH 07/14] Initial changes to add the base option to the config file. --- overviewer_core/settingsDefinition.py | 1 + overviewer_core/tileset.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/overviewer_core/settingsDefinition.py b/overviewer_core/settingsDefinition.py index d2e357c..91c2e9b 100644 --- a/overviewer_core/settingsDefinition.py +++ b/overviewer_core/settingsDefinition.py @@ -80,6 +80,7 @@ renders = Setting(required=True, default=util.OrderedDict(), "changelist": Setting(required=False, validator=validateStr, default=None), "markers": Setting(required=False, validator=validateMarkers, default=[]), "showspawn": Setting(required=False, validator=validateBool, default=True), + "base": Setting(required=False, validator=validateStr, default=None), # Remove this eventually (once people update their configs) "worldname": Setting(required=False, default=None, diff --git a/overviewer_core/tileset.py b/overviewer_core/tileset.py index ab25a2a..4fa769f 100644 --- a/overviewer_core/tileset.py +++ b/overviewer_core/tileset.py @@ -513,7 +513,7 @@ class TileSet(object): defaultZoom = 1, maxZoom = self.treedepth, path = self.options.get('name'), - base = '', + base = self.options.get('base'), bgcolor = bgcolorformat(self.options.get('bgcolor')), world = self.options.get('worldname_orig') + (" - " + self.options.get('dimension') if self.options.get('dimension') != 'default' else ''), From d25f5824040c530685db1c33af8edffb3def9ea2 Mon Sep 17 00:00:00 2001 From: Fabian Norman Date: Wed, 25 Apr 2012 19:56:48 -0700 Subject: [PATCH 08/14] Base setting, one more change (last?) --- overviewer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overviewer.py b/overviewer.py index 986d59a..c31b51c 100755 --- a/overviewer.py +++ b/overviewer.py @@ -401,7 +401,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces. # only pass to the TileSet the options it really cares about render['name'] = render_name # perhaps a hack. This is stored here for the asset manager - tileSetOpts = util.dict_subset(render, ["name", "imgformat", "renderchecks", "rerenderprob", "bgcolor", "imgquality", "optimizeimg", "rendermode", "worldname_orig", "title", "dimension", "changelist","showspawn"]) + tileSetOpts = util.dict_subset(render, ["name", "imgformat", "renderchecks", "rerenderprob", "bgcolor", "imgquality", "optimizeimg", "rendermode", "worldname_orig", "title", "dimension", "changelist","showspawn","base"]) tileSetOpts.update({"spawn": w.find_true_spawn()}) # TODO find a better way to do this tset = tileset.TileSet(rset, assetMrg, tex, tileSetOpts, tileset_dir) tilesets.append(tset) From 4fe87de247c5b2af9611f0756851540f078526ef Mon Sep 17 00:00:00 2001 From: Fabian Norman Date: Wed, 25 Apr 2012 23:42:19 -0700 Subject: [PATCH 09/14] Updated docs. --- docs/config.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/config.rst b/docs/config.rst index 042ae0d..fe97059 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -432,6 +432,13 @@ values. The valid configuration keys are listed below. **Default:** ``#1a1a1a`` +``base`` + Allows you to specify a remote location for the tile folder, useful if you + rsync your map's images to a remote server. Leave a trailing slash and point + to the location that contains the tile folders for each render, not the + tiles folder itself. For example, if the tile images start at + http://domain.com/map/world_day/ you want to set this to http://domain.com/map/ + .. _option_texture_pack: ``texturepath`` From e69717f476920a3a38b350c36bdfaaddc1d909c8 Mon Sep 17 00:00:00 2001 From: Fabian Norman Date: Wed, 2 May 2012 00:43:53 -0700 Subject: [PATCH 10/14] Prevent null being set in overviewerConfig.js --- overviewer_core/settingsDefinition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overviewer_core/settingsDefinition.py b/overviewer_core/settingsDefinition.py index 91c2e9b..44af092 100644 --- a/overviewer_core/settingsDefinition.py +++ b/overviewer_core/settingsDefinition.py @@ -80,7 +80,7 @@ renders = Setting(required=True, default=util.OrderedDict(), "changelist": Setting(required=False, validator=validateStr, default=None), "markers": Setting(required=False, validator=validateMarkers, default=[]), "showspawn": Setting(required=False, validator=validateBool, default=True), - "base": Setting(required=False, validator=validateStr, default=None), + "base": Setting(required=False, validator=validateStr, default=""), # Remove this eventually (once people update their configs) "worldname": Setting(required=False, default=None, From b53b20a9a8b6bc54547b89a4e60c70060f336c28 Mon Sep 17 00:00:00 2001 From: Alejandro Aguilera Date: Wed, 16 May 2012 10:01:27 +0200 Subject: [PATCH 11/14] Add the pre-1.3 wooden slabs. --- overviewer_core/src/primitives/edge-lines.c | 2 +- overviewer_core/textures.py | 51 +++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/overviewer_core/src/primitives/edge-lines.c b/overviewer_core/src/primitives/edge-lines.c index 00f12ae..6114309 100644 --- a/overviewer_core/src/primitives/edge-lines.c +++ b/overviewer_core/src/primitives/edge-lines.c @@ -41,7 +41,7 @@ edge_lines_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, P int x = state->x, y = state->y, z = state->z; int increment=0; - if (state->block == 44 && ((state->block_data & 0x8) == 0 )) // half-step BUT no upsidown half-step + if ((state->block == 44 || state->block == 126) && ((state->block_data & 0x8) == 0 )) // half-steps BUT no upsidown half-steps increment=6; else if ((state->block == 78) || (state->block == 93) || (state->block == 94)) // snow, redstone repeaters (on and off) increment=9; diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index ca891de..3b305c1 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -1336,6 +1336,8 @@ block(blockid=41, top_index=23) block(blockid=42, top_index=22) # double slabs and slabs +# these wooden slabs are unobtainable without cheating, they are still +# here because lots of pre-1.3 worlds use this blocks @material(blockid=[43, 44], data=range(16), transparent=(44,), solid=True) def slabs(self, blockid, data): texture = data & 7 @@ -3169,3 +3171,52 @@ block(blockid=123, top_index=211) # active redstone lamp block(blockid=124, top_index=212) + +# wooden double and normal slabs +# these are the new wooden slabs, blockids 43 44 still have wooden +# slabs, but those are unobtainable without cheating +@material(blockid=[125, 126], data=range(16), transparent=(44,), solid=True) +def slabs(self, blockid, data): + texture = data & 7 + if texture== 0: # oak + top = side = self.terrain_images[4] + elif texture== 1: # spruce + top = side = self.terrain_images[198] + elif texture== 2: # birch + top = side = self.terrain_images[214] + elif texture== 3: # jungle + top = side = self.terrain_images[199] + else: + return None + + if blockid == 125: # double slab + return self.build_block(top, side) + + # cut the side texture in half + mask = side.crop((0,8,16,16)) + side = Image.new(side.mode, side.size, self.bgcolor) + alpha_over(side, mask,(0,0,16,8), mask) + + # plain slab + top = self.transform_image_top(top) + side = self.transform_image_side(side) + otherside = side.transpose(Image.FLIP_LEFT_RIGHT) + + sidealpha = side.split()[3] + side = ImageEnhance.Brightness(side).enhance(0.9) + side.putalpha(sidealpha) + othersidealpha = otherside.split()[3] + otherside = ImageEnhance.Brightness(otherside).enhance(0.8) + otherside.putalpha(othersidealpha) + + # upside down slab + delta = 0 + if data & 8 == 8: + delta = 6 + + img = Image.new("RGBA", (24,24), self.bgcolor) + alpha_over(img, side, (0,12 - delta), side) + alpha_over(img, otherside, (12,12 - delta), otherside) + alpha_over(img, top, (0,6 - delta), top) + + return img From b245bbe8b302d3453bbcb73fc6d41a0a73db9b8a Mon Sep 17 00:00:00 2001 From: Alejandro Aguilera Date: Thu, 31 May 2012 12:04:58 +0200 Subject: [PATCH 12/14] Update chests to work with snapshot 12w21b. Add ender chests. Improve some comments. --- overviewer_core/src/iterate.c | 67 ++++------ overviewer_core/textures.py | 227 ++++++++++++++++++++++++++++------ 2 files changed, 207 insertions(+), 87 deletions(-) diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index bbc9446..f4f9a48 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -321,71 +321,46 @@ generate_pseudo_data(RenderState *state, unsigned char ancilData) { } return final_data; - } else if (state-> block == 54) { /* chests */ - /* the top 2 bits are used to store the type of chest - * (single or double), the 2 bottom bits are used for - * orientation, look textures.py for more information. */ + } else if (state->block == 54) { /* normal chests */ + /* Orientation is given by ancilData, pseudo data needed to + * choose from single or double chest and the correct half of + * the chest. */ + + /* Add two bits to ancilData to store single or double chest + * and which half of the chest it is: bit 0x10 = second half + * bit 0x8 = first half */ - /* if placed alone chests always face west, return 0 to make a - * chest facing west */ - unsigned char chest_data = 0, air_data = 0, final_data = 0; + unsigned char chest_data = 0, final_data = 0; /* search for chests */ chest_data = check_adjacent_blocks(state, x, y, z, 54); - /* search for air */ - air_data = check_adjacent_blocks(state, x, y, z, 0); + if (chest_data == 1) { /* another chest in the upper-left */ + final_data = final_data | 0x10 | ancilData; - if (chest_data == 1) { /* another chest in the east */ - final_data = final_data | 0x8; /* only can face to north or south */ - if ( (air_data & 0x2) == 2 ) { - final_data = final_data | 0x1; /* facing north */ - } else { - final_data = final_data | 0x3; /* facing south */ - } + } else if (chest_data == 2) { /* in the bottom-left */ + final_data = final_data | 0x8 | ancilData; - } else if (chest_data == 2) { /* in the north */ - final_data = final_data | 0x4; /* only can face to east or west */ - if ( !((air_data & 0x4) == 4) ) { /* 0 = west */ - final_data = final_data | 0x2; /* facing east */ - } + } else if (chest_data == 4) { /*in the bottom-right */ + final_data = final_data | 0x8 | ancilData; - } else if (chest_data == 4) { /*in the west */ - final_data = final_data | 0x4; - if ( (air_data & 0x2) == 2 ) { - final_data = final_data | 0x1; /* facing north */ - } else { - final_data = final_data | 0x3; /* facing south */ - } - - } else if (chest_data == 8) { /*in the south */ - final_data = final_data | 0x8; - if ( !((air_data & 0x4) == 4) ) { - final_data = final_data | 0x2; /* facing east */ - } + } else if (chest_data == 8) { /*in the upper-right */ + final_data = final_data | 0x10 | ancilData; } else if (chest_data == 0) { /* Single chest, determine the orientation */ - if ( ((air_data & 0x8) == 0) && ((air_data & 0x2) == 2) ) { /* block in +x and no block in -x */ - final_data = final_data | 0x1; /* facing north */ - - } else if ( ((air_data & 0x2) == 0) && ((air_data & 0x8) == 8)) { - final_data = final_data | 0x3; - - } else if ( ((air_data & 0x4) == 0) && ((air_data & 0x1) == 1)) { - final_data = final_data | 0x2; - } /* else, facing west, value = 0 */ + final_data = ancilData; } else { - /* more than one adjacent chests! render as normal chest */ + /* more than one adjacent chests! That shouldn't be + * possible! render as normal chest */ return 0; } - return final_data; } else if ((state->block == 101) || (state->block == 102)) { /* iron bars and glass panes: - * they seem to stick to almost everything but air, but + * they seem to stick to almost everything but air, * not sure yet! Still a TODO! */ /* return check adjacent blocks with air, bit inverted */ return check_adjacent_blocks(state, x, y, z, 0) ^ 0x0f; diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 3b305c1..3c20f94 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -131,7 +131,7 @@ class Textures(object): # a list of subdirectories to search for a given file, # after the obvious '.' - search_dirs = ['anim', 'misc', 'environment'] + search_dirs = ['anim', 'misc', 'environment', 'item'] search_zip_paths = [filename,] + [d + '/' + filename for d in search_dirs] def search_dir(base): """Search the given base dir for filename, in search_dirs.""" @@ -1610,50 +1610,195 @@ def stairs(self, blockid, data): return img -# normal and locked chest (locked was the one used in april fools' day) -# uses pseudo-ancildata found in iterate.c -@material(blockid=[54,95], data=range(12), solid=True) +# normal, locked (used in april's fool day) and ender chests chests +@material(blockid=[54,95,130], data=range(30), transparent = True) def chests(self, blockid, data): - # First two bits of the pseudo data store if it's a single chest - # or it's a double chest, first half or second half (left to right). - # The last two bits store the orientation. + # the first 3 bits are the orientation as stored in minecraft, + # bits 0x8 and 0x10 indicate which half of the double chest is it. - # No need for rotation stuff, uses pseudo data and rotates with the map + # first, do the rotation if needed + orientation_data = data & 7 + if self.rotation == 1: + if orientation_data == 2: data = 5 | (data & 24) + elif orientation_data == 3: data = 4 | (data & 24) + elif orientation_data == 4: data = 2 | (data & 24) + elif orientation_data == 5: data = 3 | (data & 24) + elif self.rotation == 2: + if orientation_data == 2: data = 3 | (data & 24) + elif orientation_data == 3: data = 2 | (data & 24) + elif orientation_data == 4: data = 5 | (data & 24) + elif orientation_data == 5: data = 4 | (data & 24) + elif self.rotation == 3: + if orientation_data == 2: data = 4 | (data & 24) + elif orientation_data == 3: data = 5 | (data & 24) + elif orientation_data == 4: data = 3 | (data & 24) + elif orientation_data == 5: data = 2 | (data & 24) + + if blockid in (95,130) and not data in [2,3,4,5]: return None + # iterate.c will only return the ancil data (without pseudo + # ancil data) for locked and ender chests, so only + # ancilData = 2,3,4,5 are used for this blockids + + if data & 24 == 0: + if blockid == 130: t = self.load_image("enderchest.png") + else: t = self.load_image("chest.png") + t.save("textura.png") + # the textures is no longer in terrain.png, get it from + # item/chest.png and get by cropping all the needed stuff + if t.size != (64,64): t = t.resize((64,64), Image.ANTIALIAS) + # top + top = t.crop((14,0,28,14)) + top.load() # every crop need a load, crop is a lazy operation + # see PIL manual + img = Image.new("RGBA", (16,16), self.bgcolor) + alpha_over(img,top,(1,1)) + top = img + # front + front_top = t.crop((14,14,28,19)) + front_top.load() + front_bottom = t.crop((14,34,28,43)) + front_bottom.load() + front_lock = t.crop((1,0,3,4)) + front_lock.load() + front = Image.new("RGBA", (16,16), self.bgcolor) + alpha_over(front,front_top, (1,1)) + alpha_over(front,front_bottom, (1,6)) + alpha_over(front,front_lock, (7,3)) + # left side + # left side, right side, and back are esentially the same for + # the default texture, we take it anyway just in case other + # textures make use of it. + side_l_top = t.crop((0,14,14,19)) + side_l_top.load() + side_l_bottom = t.crop((0,34,14,43)) + side_l_bottom.load() + side_l = Image.new("RGBA", (16,16), self.bgcolor) + alpha_over(side_l,side_l_top, (1,1)) + alpha_over(side_l,side_l_bottom, (1,6)) + # right side + side_r_top = t.crop((28,14,43,20)) + side_r_top.load() + side_r_bottom = t.crop((28,33,42,43)) + side_r_bottom.load() + side_r = Image.new("RGBA", (16,16), self.bgcolor) + alpha_over(side_r,side_l_top, (1,1)) + alpha_over(side_r,side_l_bottom, (1,6)) + # back + back_top = t.crop((42,14,56,18)) + back_top.load() + back_bottom = t.crop((42,33,56,43)) + back_bottom.load() + back = Image.new("RGBA", (16,16), self.bgcolor) + alpha_over(back,side_l_top, (1,1)) + alpha_over(back,side_l_bottom, (1,6)) - top = self.terrain_images[25] - side = self.terrain_images[26] - - if data & 12 == 0: # single chest - front = self.terrain_images[27] - back = self.terrain_images[26] - - elif data & 12 == 4: # double, first half - front = self.terrain_images[41] - back = self.terrain_images[57] - - elif data & 12 == 8: # double, second half - front = self.terrain_images[42] - back = self.terrain_images[58] - - else: # just in case - front = self.terrain_images[25] - side = self.terrain_images[25] - back = self.terrain_images[25] - - if data & 3 == 0: # facing west - img = self.build_full_block(top, None, None, side, front) - - elif data & 3 == 1: # north - img = self.build_full_block(top, None, None, front, side) - - elif data & 3 == 2: # east - img = self.build_full_block(top, None, None, side, back) - - elif data & 3 == 3: # south - img = self.build_full_block(top, None, None, back, side) - else: - img = self.build_full_block(top, None, None, back, side) + # large chest + # the textures is no longer in terrain.png, get it from + # item/chest.png and get all the needed stuff + t = self.load_image("largechest.png") + if t.size != (128,64): t = t.resize((128,64), Image.ANTIALIAS) + # top + top = t.crop((14,0,44,14)) + top.load() + img = Image.new("RGBA", (32,16), self.bgcolor) + alpha_over(img,top,(1,1)) + top = img + # front + front_top = t.crop((14,14,44,18)) + front_top.load() + front_bottom = t.crop((14,33,44,43)) + front_bottom.load() + front_lock = t.crop((1,0,3,5)) + front_lock.load() + front = Image.new("RGBA", (32,16), self.bgcolor) + alpha_over(front,front_top,(1,1)) + alpha_over(front,front_bottom,(1,5)) + alpha_over(front,front_lock,(15,3)) + # left side + side_l_top = t.crop((0,14,14,18)) + side_l_top.load() + side_l_bottom = t.crop((0,33,14,43)) + side_l_bottom.load() + side_l = Image.new("RGBA", (16,16), self.bgcolor) + alpha_over(side_l,side_l_top, (1,1)) + alpha_over(side_l,side_l_bottom,(1,5)) + # right side + side_r_top = t.crop((44,14,58,18)) + side_r_top.load() + side_r_bottom = t.crop((44,33,58,43)) + side_r_bottom.load() + side_r = Image.new("RGBA", (16,16), self.bgcolor) + alpha_over(side_r,side_r_top, (1,1)) + alpha_over(side_r,side_r_bottom,(1,5)) + # back + back_top = t.crop((58,14,88,18)) + back_top.load() + back_bottom = t.crop((58,33,88,43)) + back_bottom.load() + back = Image.new("RGBA", (32,16), self.bgcolor) + alpha_over(back,back_top,(1,1)) + alpha_over(back,back_bottom,(1,5)) + + + if data & 24 == 8: # double chest, first half + top = top.crop((0,0,16,16)) + top.load() + front = front.crop((0,0,16,16)) + front.load() + back = back.crop((0,0,16,16)) + back.load() + #~ side = side_l + + elif data & 24 == 16: # double, second half + top = top.crop((16,0,32,16)) + top.load() + front = front.crop((16,0,32,16)) + front.load() + back = back.crop((16,0,32,16)) + back.load() + #~ side = side_r + + else: # just in case + return None + + # compose the final block + img = Image.new("RGBA", (24,24), self.bgcolor) + if data & 7 == 2: # north + side = self.transform_image_side(side_r) + alpha_over(img, side, (1,7)) + back = self.transform_image_side(back) + alpha_over(img, back.transpose(Image.FLIP_LEFT_RIGHT), (11,7)) + front = self.transform_image_side(front) + top = self.transform_image_top(top.rotate(180)) + alpha_over(img, top, (0,2)) + + elif data & 7 == 3: # south + side = self.transform_image_side(side_l) + alpha_over(img, side, (1,7)) + front = self.transform_image_side(front).transpose(Image.FLIP_LEFT_RIGHT) + top = self.transform_image_top(top.rotate(180)) + alpha_over(img, top, (0,2)) + alpha_over(img, front,(11,7)) + + elif data & 7 == 4: # west + side = self.transform_image_side(side_r) + alpha_over(img, side.transpose(Image.FLIP_LEFT_RIGHT), (11,7)) + front = self.transform_image_side(front) + alpha_over(img, front,(1,7)) + top = self.transform_image_top(top.rotate(270)) + alpha_over(img, top, (0,2)) + + elif data & 7 == 5: # east + back = self.transform_image_side(back) + side = self.transform_image_side(side_l).transpose(Image.FLIP_LEFT_RIGHT) + alpha_over(img, side, (11,7)) + alpha_over(img, back, (1,7)) + top = self.transform_image_top(top.rotate(270)) + alpha_over(img, top, (0,2)) + + else: # just in case + img = None return img From 86ad4bf611cfe76d78c9efe2d43a6e06b1abd360 Mon Sep 17 00:00:00 2001 From: Alejandro Aguilera Date: Thu, 31 May 2012 13:43:53 +0200 Subject: [PATCH 13/14] Add emerald ore and sandstone stairs. --- overviewer_core/textures.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 3c20f94..9eeb6ae 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -1491,8 +1491,8 @@ def fire(self, blockid, data): # monster spawner block(blockid=52, top_index=34, transparent=True) -# wooden, cobblestone, red brick, stone brick and netherbrick stairs. -@material(blockid=[53,67,108,109,114], data=range(8), transparent=True, solid=True, nospawn=True) +# wooden, cobblestone, red brick, stone brick, netherbrick and sandstone stairs. +@material(blockid=[53,67,108,109,114,128], data=range(8), transparent=True, solid=True, nospawn=True) def stairs(self, blockid, data): # first, rotations @@ -1526,7 +1526,9 @@ def stairs(self, blockid, data): texture = self.terrain_images[54] elif blockid == 114: # netherbrick stairs texture = self.terrain_images[224] - + elif blockid ==128: #sandstone stairs + texture = self.terrain_images[192] + side = texture.copy() half_block_u = texture.copy() # up, down, left, right half_block_d = texture.copy() @@ -3365,3 +3367,6 @@ def slabs(self, blockid, data): alpha_over(img, top, (0,6 - delta), top) return img + +# emerald ore +block(blockid=130, top_index=171) From 85c439b68c4e58a84d289d0a8b225efd40504aa3 Mon Sep 17 00:00:00 2001 From: Alejandro Aguilera Date: Fri, 1 Jun 2012 14:14:40 +0200 Subject: [PATCH 14/14] Add emerald block, improve the looking of the brewing stand. --- overviewer_core/textures.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 9eeb6ae..7758e26 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -3232,8 +3232,11 @@ def enchantment_table(self, blockid, data): # TODO this is a place holder, is a 2d image pasted @material(blockid=117, data=range(5), transparent=True) def brewing_stand(self, blockid, data): + base = self.terrain_images[156] + img = self.build_full_block(None, None, None, None, None, base) t = self.terrain_images[157] - img = self.build_billboard(t) + stand = self.build_billboard(t) + alpha_over(img,stand,(0,-2)) return img # cauldron @@ -3370,3 +3373,6 @@ def slabs(self, blockid, data): # emerald ore block(blockid=130, top_index=171) + +# emerald block +block(blockid=133, top_index=25)