Merge remote branch 'origin/devel'
Conflicts: docs/config.rst
This commit is contained in:
@@ -70,6 +70,7 @@ feature.
|
|||||||
* Zach McCullough <nosrepa@gmail.com>
|
* Zach McCullough <nosrepa@gmail.com>
|
||||||
* Mike <mike@snowcrash.ca>
|
* Mike <mike@snowcrash.ca>
|
||||||
* Morlok8k <otis.spankmeyer@gmail.com>
|
* Morlok8k <otis.spankmeyer@gmail.com>
|
||||||
|
* Adam Novak <interfect@gmail.com>
|
||||||
* Richard Pastrick <rpastric@contre.us>
|
* Richard Pastrick <rpastric@contre.us>
|
||||||
* Ryan Rector <rmrector@gmail.com>
|
* Ryan Rector <rmrector@gmail.com>
|
||||||
* Jason Scheirer <jason.scheirer@gmail.com>
|
* Jason Scheirer <jason.scheirer@gmail.com>
|
||||||
|
|||||||
@@ -432,7 +432,14 @@ values. The valid configuration keys are listed below.
|
|||||||
|
|
||||||
**Default:** ``#1a1a1a``
|
**Default:** ``#1a1a1a``
|
||||||
|
|
||||||
.. _option_texturepath:
|
``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``
|
``texturepath``
|
||||||
This is a where a specific texture pack can be found to be used during this render.
|
This is a where a specific texture pack can be found to be used during this render.
|
||||||
@@ -624,6 +631,17 @@ Depth
|
|||||||
max
|
max
|
||||||
highest level of blocks to render. Default: 255
|
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
|
||||||
|
|
||||||
|
NoFluids
|
||||||
|
Don't render fluid blocks (water, lava).
|
||||||
|
|
||||||
EdgeLines
|
EdgeLines
|
||||||
Draw edge lines on the back side of blocks, to help distinguish them from
|
Draw edge lines on the back side of blocks, to help distinguish them from
|
||||||
the background.
|
the background.
|
||||||
|
|||||||
@@ -421,7 +421,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
|
# 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
|
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", "overlay"])
|
tileSetOpts = util.dict_subset(render, ["name", "imgformat", "renderchecks", "rerenderprob", "bgcolor", "imgquality", "optimizeimg", "rendermode", "worldname_orig", "title", "dimension", "changelist","showspawn", "overlay","base"])
|
||||||
tileSetOpts.update({"spawn": w.find_true_spawn()}) # TODO find a better way to do this
|
tileSetOpts.update({"spawn": w.find_true_spawn()}) # TODO find a better way to do this
|
||||||
tset = tileset.TileSet(rset, assetMrg, tex, tileSetOpts, tileset_dir)
|
tset = tileset.TileSet(rset, assetMrg, tex, tileSetOpts, tileset_dir)
|
||||||
tilesets.append(tset)
|
tilesets.append(tset)
|
||||||
|
|||||||
@@ -62,6 +62,15 @@ class Depth(RenderPrimitive):
|
|||||||
"min": ("lowest level of blocks to render", 0),
|
"min": ("lowest level of blocks to render", 0),
|
||||||
"max": ("highest level of blocks to render", 255),
|
"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 NoFluids(RenderPrimitive):
|
||||||
|
name = "no-fluids"
|
||||||
|
|
||||||
class EdgeLines(RenderPrimitive):
|
class EdgeLines(RenderPrimitive):
|
||||||
name = "edge-lines"
|
name = "edge-lines"
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ renders = Setting(required=True, default=util.OrderedDict(),
|
|||||||
"markers": Setting(required=False, validator=validateMarkers, default=[]),
|
"markers": Setting(required=False, validator=validateMarkers, default=[]),
|
||||||
"overlay": Setting(required=False, validator=validateOverlays, default=[]),
|
"overlay": Setting(required=False, validator=validateOverlays, default=[]),
|
||||||
"showspawn": Setting(required=False, validator=validateBool, default=True),
|
"showspawn": Setting(required=False, validator=validateBool, default=True),
|
||||||
|
"base": Setting(required=False, validator=validateStr, default=""),
|
||||||
|
|
||||||
# Remove this eventually (once people update their configs)
|
# Remove this eventually (once people update their configs)
|
||||||
"worldname": Setting(required=False, default=None,
|
"worldname": Setting(required=False, default=None,
|
||||||
|
|||||||
@@ -321,71 +321,46 @@ generate_pseudo_data(RenderState *state, unsigned char ancilData) {
|
|||||||
}
|
}
|
||||||
return final_data;
|
return final_data;
|
||||||
|
|
||||||
} else if (state-> block == 54) { /* chests */
|
} else if (state->block == 54) { /* normal chests */
|
||||||
/* the top 2 bits are used to store the type of chest
|
/* Orientation is given by ancilData, pseudo data needed to
|
||||||
* (single or double), the 2 bottom bits are used for
|
* choose from single or double chest and the correct half of
|
||||||
* orientation, look textures.py for more information. */
|
* 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
|
unsigned char chest_data = 0, final_data = 0;
|
||||||
* chest facing west */
|
|
||||||
unsigned char chest_data = 0, air_data = 0, final_data = 0;
|
|
||||||
|
|
||||||
/* search for chests */
|
/* search for chests */
|
||||||
chest_data = check_adjacent_blocks(state, x, y, z, 54);
|
chest_data = check_adjacent_blocks(state, x, y, z, 54);
|
||||||
|
|
||||||
/* search for air */
|
if (chest_data == 1) { /* another chest in the upper-left */
|
||||||
air_data = check_adjacent_blocks(state, x, y, z, 0);
|
final_data = final_data | 0x10 | ancilData;
|
||||||
|
|
||||||
if (chest_data == 1) { /* another chest in the east */
|
} else if (chest_data == 2) { /* in the bottom-left */
|
||||||
final_data = final_data | 0x8; /* only can face to north or south */
|
final_data = final_data | 0x8 | ancilData;
|
||||||
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 north */
|
} else if (chest_data == 4) { /*in the bottom-right */
|
||||||
final_data = final_data | 0x4; /* only can face to east or west */
|
final_data = final_data | 0x8 | ancilData;
|
||||||
if ( !((air_data & 0x4) == 4) ) { /* 0 = west */
|
|
||||||
final_data = final_data | 0x2; /* facing east */
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (chest_data == 4) { /*in the west */
|
} else if (chest_data == 8) { /*in the upper-right */
|
||||||
final_data = final_data | 0x4;
|
final_data = final_data | 0x10 | ancilData;
|
||||||
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 == 0) {
|
} else if (chest_data == 0) {
|
||||||
/* Single chest, determine the orientation */
|
/* Single chest, determine the orientation */
|
||||||
if ( ((air_data & 0x8) == 0) && ((air_data & 0x2) == 2) ) { /* block in +x and no block in -x */
|
final_data = ancilData;
|
||||||
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 */
|
|
||||||
|
|
||||||
} else {
|
} 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 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return final_data;
|
return final_data;
|
||||||
|
|
||||||
} else if ((state->block == 101) || (state->block == 102)) {
|
} else if ((state->block == 101) || (state->block == 102)) {
|
||||||
/* iron bars and glass panes:
|
/* 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! */
|
* not sure yet! Still a TODO! */
|
||||||
/* return check adjacent blocks with air, bit inverted */
|
/* return check adjacent blocks with air, bit inverted */
|
||||||
return check_adjacent_blocks(state, x, y, z, 0) ^ 0x0f;
|
return check_adjacent_blocks(state, x, y, z, 0) ^ 0x0f;
|
||||||
|
|||||||
@@ -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 x = state->x, y = state->y, z = state->z;
|
||||||
|
|
||||||
int increment=0;
|
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;
|
increment=6;
|
||||||
else if ((state->block == 78) || (state->block == 93) || (state->block == 94)) // snow, redstone repeaters (on and off)
|
else if ((state->block == 78) || (state->block == 93) || (state->block == 94)) // snow, redstone repeaters (on and off)
|
||||||
increment=9;
|
increment=9;
|
||||||
|
|||||||
109
overviewer_core/src/primitives/exposed.c
Normal file
109
overviewer_core/src/primitives/exposed.c
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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 validPlusX = 1;
|
||||||
|
int validMinusY = 1;
|
||||||
|
int validPlusY = 1;
|
||||||
|
int validMinusZ = 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 (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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))) ||
|
||||||
|
(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 */
|
||||||
|
/* 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,
|
||||||
|
};
|
||||||
37
overviewer_core/src/primitives/no-fluids.c
Normal file
37
overviewer_core/src/primitives/no-fluids.c
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../overviewer.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
no_fluids_start(void *data, RenderState *state, PyObject *support) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
no_fluids_hidden(void *data, RenderState *state, int x, int y, int z) {
|
||||||
|
return block_has_property(state->block, FLUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderPrimitiveInterface primitive_no_fluids = {
|
||||||
|
"no-fluids", 0,
|
||||||
|
no_fluids_start,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
no_fluids_hidden,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
@@ -131,7 +131,7 @@ class Textures(object):
|
|||||||
|
|
||||||
# a list of subdirectories to search for a given file,
|
# a list of subdirectories to search for a given file,
|
||||||
# after the obvious '.'
|
# 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]
|
search_zip_paths = [filename,] + [d + '/' + filename for d in search_dirs]
|
||||||
def search_dir(base):
|
def search_dir(base):
|
||||||
"""Search the given base dir for filename, in search_dirs."""
|
"""Search the given base dir for filename, in search_dirs."""
|
||||||
@@ -1336,6 +1336,8 @@ block(blockid=41, top_index=23)
|
|||||||
block(blockid=42, top_index=22)
|
block(blockid=42, top_index=22)
|
||||||
|
|
||||||
# double slabs and slabs
|
# 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)
|
@material(blockid=[43, 44], data=range(16), transparent=(44,), solid=True)
|
||||||
def slabs(self, blockid, data):
|
def slabs(self, blockid, data):
|
||||||
texture = data & 7
|
texture = data & 7
|
||||||
@@ -1489,8 +1491,8 @@ def fire(self, blockid, data):
|
|||||||
# monster spawner
|
# monster spawner
|
||||||
block(blockid=52, top_index=34, transparent=True)
|
block(blockid=52, top_index=34, transparent=True)
|
||||||
|
|
||||||
# wooden, cobblestone, red brick, stone brick and netherbrick stairs.
|
# wooden, cobblestone, red brick, stone brick, netherbrick and sandstone stairs.
|
||||||
@material(blockid=[53,67,108,109,114], data=range(8), transparent=True, solid=True, nospawn=True)
|
@material(blockid=[53,67,108,109,114,128], data=range(8), transparent=True, solid=True, nospawn=True)
|
||||||
def stairs(self, blockid, data):
|
def stairs(self, blockid, data):
|
||||||
|
|
||||||
# first, rotations
|
# first, rotations
|
||||||
@@ -1524,7 +1526,9 @@ def stairs(self, blockid, data):
|
|||||||
texture = self.terrain_images[54]
|
texture = self.terrain_images[54]
|
||||||
elif blockid == 114: # netherbrick stairs
|
elif blockid == 114: # netherbrick stairs
|
||||||
texture = self.terrain_images[224]
|
texture = self.terrain_images[224]
|
||||||
|
elif blockid ==128: #sandstone stairs
|
||||||
|
texture = self.terrain_images[192]
|
||||||
|
|
||||||
side = texture.copy()
|
side = texture.copy()
|
||||||
half_block_u = texture.copy() # up, down, left, right
|
half_block_u = texture.copy() # up, down, left, right
|
||||||
half_block_d = texture.copy()
|
half_block_d = texture.copy()
|
||||||
@@ -1608,50 +1612,195 @@ def stairs(self, blockid, data):
|
|||||||
|
|
||||||
return img
|
return img
|
||||||
|
|
||||||
# normal and locked chest (locked was the one used in april fools' day)
|
# normal, locked (used in april's fool day) and ender chests chests
|
||||||
# uses pseudo-ancildata found in iterate.c
|
@material(blockid=[54,95,130], data=range(30), transparent = True)
|
||||||
@material(blockid=[54,95], data=range(12), solid=True)
|
|
||||||
def chests(self, blockid, data):
|
def chests(self, blockid, data):
|
||||||
# First two bits of the pseudo data store if it's a single chest
|
# the first 3 bits are the orientation as stored in minecraft,
|
||||||
# or it's a double chest, first half or second half (left to right).
|
# bits 0x8 and 0x10 indicate which half of the double chest is it.
|
||||||
# The last two bits store the orientation.
|
|
||||||
|
|
||||||
# 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:
|
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
|
return img
|
||||||
|
|
||||||
@@ -3083,8 +3232,11 @@ def enchantment_table(self, blockid, data):
|
|||||||
# TODO this is a place holder, is a 2d image pasted
|
# TODO this is a place holder, is a 2d image pasted
|
||||||
@material(blockid=117, data=range(5), transparent=True)
|
@material(blockid=117, data=range(5), transparent=True)
|
||||||
def brewing_stand(self, blockid, data):
|
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]
|
t = self.terrain_images[157]
|
||||||
img = self.build_billboard(t)
|
stand = self.build_billboard(t)
|
||||||
|
alpha_over(img,stand,(0,-2))
|
||||||
return img
|
return img
|
||||||
|
|
||||||
# cauldron
|
# cauldron
|
||||||
@@ -3169,3 +3321,58 @@ block(blockid=123, top_index=211)
|
|||||||
|
|
||||||
# active redstone lamp
|
# active redstone lamp
|
||||||
block(blockid=124, top_index=212)
|
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
|
||||||
|
|
||||||
|
# emerald ore
|
||||||
|
block(blockid=130, top_index=171)
|
||||||
|
|
||||||
|
# emerald block
|
||||||
|
block(blockid=133, top_index=25)
|
||||||
|
|||||||
@@ -516,7 +516,7 @@ class TileSet(object):
|
|||||||
defaultZoom = 1,
|
defaultZoom = 1,
|
||||||
maxZoom = self.treedepth,
|
maxZoom = self.treedepth,
|
||||||
path = self.options.get('name'),
|
path = self.options.get('name'),
|
||||||
base = '',
|
base = self.options.get('base'),
|
||||||
bgcolor = bgcolorformat(self.options.get('bgcolor')),
|
bgcolor = bgcolorformat(self.options.get('bgcolor')),
|
||||||
world = self.options.get('worldname_orig') +
|
world = self.options.get('worldname_orig') +
|
||||||
(" - " + self.options.get('dimension') if self.options.get('dimension') != 'default' else ''),
|
(" - " + self.options.get('dimension') if self.options.get('dimension') != 'default' else ''),
|
||||||
|
|||||||
Reference in New Issue
Block a user