Adds spawn output rendering (variant of night which shows dark areas in red) and support for multiple map types with buttons to switch between them.
This commit is contained in:
38
chunk.py
38
chunk.py
@@ -112,6 +112,18 @@ def iterate_chunkblocks(xoff,yoff):
|
||||
transparent_blocks = set([0, 6, 8, 9, 18, 20, 37, 38, 39, 40, 44, 50, 51, 52, 53,
|
||||
59, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 81, 83, 85])
|
||||
|
||||
# This set holds block ids that are solid blocks
|
||||
solid_blocks = set([1, 2, 3, 4, 5, 7, 12, 13, 14, 15, 16, 17, 18, 19, 20, 35,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 53, 54, 56, 57, 58, 60, 61, 62, 64, 65,
|
||||
66, 67, 71, 73, 74, 78, 79, 80, 81, 82, 84, 86, 87, 88, 89, 91])
|
||||
|
||||
# This set holds block ids that are fluid blocks
|
||||
fluid_blocks = set([8,9,10,11])
|
||||
|
||||
# This set holds block ids that are not candidates for spawning mobs on
|
||||
# (glass, half blocks)
|
||||
nospawn_blocks = set([20,44])
|
||||
|
||||
def render_and_save(chunkfile, cachedir, worldobj, cave=False, queue=None):
|
||||
"""Used as the entry point for the multiprocessing workers (since processes
|
||||
can't target bound methods) or to easily render and save one chunk
|
||||
@@ -617,7 +629,14 @@ class ChunkRenderer(object):
|
||||
# block shaded with the current
|
||||
# block's light
|
||||
black_coeff, _ = self.get_lighting_coefficient(x, y, z)
|
||||
composite.alpha_over(img, Image.blend(t[0], black_color, black_coeff), (imgx, imgy), t[1])
|
||||
if self.world.spawn and black_coeff > 0.8 and blockid in solid_blocks and not (
|
||||
blockid in nospawn_blocks or (
|
||||
z != 127 and (blocks[x,y,z+1] in solid_blocks or blocks[x,y,z+1] in fluid_blocks)
|
||||
)
|
||||
):
|
||||
composite.alpha_over(img, Image.blend(t[0], red_color, black_coeff), (imgx, imgy), t[1])
|
||||
else:
|
||||
composite.alpha_over(img, Image.blend(t[0], black_color, black_coeff), (imgx, imgy), t[1])
|
||||
else:
|
||||
# draw each face lit appropriately,
|
||||
# but first just draw the block
|
||||
@@ -625,18 +644,28 @@ class ChunkRenderer(object):
|
||||
|
||||
# top face
|
||||
black_coeff, face_occlude = self.get_lighting_coefficient(x, y, z + 1)
|
||||
# Use red instead of black for spawnable blocks
|
||||
if self.world.spawn and black_coeff > 0.8 and blockid in solid_blocks and not (
|
||||
blockid in nospawn_blocks or (
|
||||
z != 127 and (blocks[x,y,z+1] in solid_blocks or blocks[x,y,z+1] in fluid_blocks)
|
||||
)
|
||||
):
|
||||
over_color = red_color
|
||||
else:
|
||||
over_color = black_color
|
||||
|
||||
if not face_occlude:
|
||||
composite.alpha_over(img, black_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[0]).enhance(black_coeff))
|
||||
composite.alpha_over(img, over_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[0]).enhance(black_coeff))
|
||||
|
||||
# left face
|
||||
black_coeff, face_occlude = self.get_lighting_coefficient(x - 1, y, z)
|
||||
if not face_occlude:
|
||||
composite.alpha_over(img, black_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[1]).enhance(black_coeff))
|
||||
composite.alpha_over(img, over_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[1]).enhance(black_coeff))
|
||||
|
||||
# right face
|
||||
black_coeff, face_occlude = self.get_lighting_coefficient(x, y + 1, z)
|
||||
if not face_occlude:
|
||||
composite.alpha_over(img, black_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[2]).enhance(black_coeff))
|
||||
composite.alpha_over(img, over_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[2]).enhance(black_coeff))
|
||||
|
||||
# Draw edge lines
|
||||
if blockid in (44,): # step block
|
||||
@@ -705,6 +734,7 @@ def generate_facemasks():
|
||||
return (top, left, right)
|
||||
facemasks = generate_facemasks()
|
||||
black_color = Image.new("RGB", (24,24), (0,0,0))
|
||||
red_color = Image.new("RGB", (24,24), (229,36,38))
|
||||
|
||||
# Render 128 different color images for color coded depth blending in cave mode
|
||||
def generate_depthcolors():
|
||||
|
||||
16
config.js
16
config.js
@@ -1,6 +1,5 @@
|
||||
|
||||
var config = {
|
||||
path: 'tiles',
|
||||
fileExt: '{imgformat}',
|
||||
tileSize: 384,
|
||||
defaultZoom: 1,
|
||||
@@ -28,6 +27,21 @@ var signGroups = [
|
||||
{label: "All", match: function(s) {return true}}
|
||||
];
|
||||
|
||||
/* mapTypeData -- a list of alternate map renderings available. At least one rendering must be
|
||||
* listed. When more than one are provided, controls to switch between them are provided, with
|
||||
* the first one being the default.
|
||||
*
|
||||
* Required:
|
||||
* label : string. Displayed on the control.
|
||||
* path : string. Location of the rendered tiles.
|
||||
*/
|
||||
var mapTypeData=[
|
||||
{'label': 'Unlit', 'path': 'tiles'},
|
||||
// {'label': 'Day', 'path': 'lighting/tiles'},
|
||||
// {'label': 'Night', 'path': 'night/tiles'},
|
||||
// {'label': 'Spawn', 'path': 'spawn/tiles'}
|
||||
];
|
||||
|
||||
// Please leave the following variables here:
|
||||
var markerCollection = {}; // holds groups of markers
|
||||
|
||||
|
||||
4
gmap.py
4
gmap.py
@@ -51,6 +51,7 @@ def main():
|
||||
parser.add_option("--chunklist", dest="chunklist", help="A file containing, on each line, a path to a chunkfile to update. Instead of scanning the world directory for chunks, it will just use this list. Normal caching rules still apply.")
|
||||
parser.add_option("--lighting", dest="lighting", help="Renders shadows using light data from each chunk.", action="store_true")
|
||||
parser.add_option("--night", dest="night", help="Renders shadows using light data from each chunk, as if it were night. Implies --lighting.", action="store_true")
|
||||
parser.add_option("--spawn", dest="spawn", help="Renders shadows using light data from each chunk, as if it were night, while also highlighting areas that are dark enough to spawn mobs. Implies --lighting and --night.", action="store_true")
|
||||
parser.add_option("--imgformat", dest="imgformat", help="The image output format to use. Currently supported: png(default), jpg. NOTE: png will always be used as the intermediate image format.")
|
||||
parser.add_option("--optimize-img", dest="optimizeimg", help="If using png, perform image file size optimizations on the output. Specify 1 for pngcrush, 2 for pngcrush+optipng+advdef. This may double (or more) render times, but will produce up to 30% smaller images. NOTE: requires corresponding programs in $PATH or %PATH%")
|
||||
parser.add_option("-q", "--quiet", dest="quiet", action="count", default=0, help="Print less output. You can specify this option multiple times.")
|
||||
@@ -123,7 +124,8 @@ def main():
|
||||
logging.info("Notice: Not using biome data for tinting")
|
||||
|
||||
# First generate the world's chunk images
|
||||
w = world.WorldRenderer(worlddir, cachedir, chunklist=chunklist, lighting=options.lighting, night=options.night, useBiomeData=useBiomeData)
|
||||
w = world.WorldRenderer(worlddir, cachedir, chunklist=chunklist, lighting=options.lighting, night=options.night, spawn=options.spawn, useBiomeData=useBiomeData)
|
||||
|
||||
w.go(options.procs)
|
||||
|
||||
# Now generate the tiles
|
||||
|
||||
@@ -37,6 +37,7 @@ function drawMapControls() {
|
||||
compassImg.src="compass.png";
|
||||
compassDiv.appendChild(compassImg);
|
||||
|
||||
compassDiv.index = 0;
|
||||
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(compassDiv);
|
||||
|
||||
|
||||
@@ -260,16 +261,23 @@ function initialize() {
|
||||
if (argname == "zoom") {zoom = parseInt(value);}
|
||||
}
|
||||
|
||||
var mapTyepControlToggle = false
|
||||
if (mapTypeIds.length > 1) {
|
||||
mapTyepControlToggle = true
|
||||
}
|
||||
var mapOptions = {
|
||||
zoom: zoom,
|
||||
center: new google.maps.LatLng(lat, lng),
|
||||
navigationControl: true,
|
||||
scaleControl: false,
|
||||
mapTypeControl: false,
|
||||
mapTypeControl: mapTyepControlToggle,
|
||||
mapTypeControlOptions: {
|
||||
mapTypeIds: mapTypeIds
|
||||
},
|
||||
mapTypeId: mapTypeIdDefault
|
||||
streetViewControl: false,
|
||||
mapTypeId: 'mcmap'
|
||||
};
|
||||
map = new google.maps.Map(document.getElementById("mcmap"), mapOptions);
|
||||
map = new google.maps.Map(document.getElementById('mcmap'), mapOptions);
|
||||
|
||||
if(config.debug) {
|
||||
map.overlayMapTypes.insertAt(0, new CoordMapType(new google.maps.Size(config.tileSize, config.tileSize)));
|
||||
@@ -287,11 +295,12 @@ function initialize() {
|
||||
}
|
||||
|
||||
// Now attach the coordinate map type to the map's registry
|
||||
map.mapTypes.set('mcmap', MCMapType);
|
||||
for (idx in MCMapType) {
|
||||
map.mapTypes.set('mcmap' + MCMapType[idx].name, MCMapType[idx]);
|
||||
}
|
||||
|
||||
// We can now set the map to use the 'coordinate' map type
|
||||
map.setMapTypeId('mcmap');
|
||||
|
||||
map.setMapTypeId(mapTypeIdDefault);
|
||||
|
||||
// initialize the markers and regions
|
||||
initMarkers();
|
||||
@@ -370,9 +379,9 @@ function initialize() {
|
||||
return new google.maps.LatLng(lat, lng);
|
||||
}
|
||||
|
||||
var MCMapOptions = {
|
||||
getTileUrl: function(tile, zoom) {
|
||||
var url = config.path;
|
||||
function getTileUrlGenerator(path) {
|
||||
return function(tile, zoom) {
|
||||
var url = path;
|
||||
if(tile.x < 0 || tile.x >= Math.pow(2, zoom) || tile.y < 0 || tile.y >= Math.pow(2, zoom)) {
|
||||
url += '/blank';
|
||||
} else if(zoom == 0) {
|
||||
@@ -390,17 +399,33 @@ function initialize() {
|
||||
url += '?c=' + Math.floor(d.getTime() / (1000 * 60 * config.cacheMinutes));
|
||||
}
|
||||
return(url);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var MCMapOptions = new Array;
|
||||
var MCMapType = new Array;
|
||||
var mapTypeIdDefault = null;
|
||||
var mapTypeIds = [];
|
||||
for (idx in mapTypeData) {
|
||||
var view = mapTypeData[idx];
|
||||
|
||||
MCMapOptions[view.label] = {
|
||||
getTileUrl: getTileUrlGenerator(view.path),
|
||||
tileSize: new google.maps.Size(config.tileSize, config.tileSize),
|
||||
maxZoom: config.maxZoom,
|
||||
minZoom: 0,
|
||||
isPng: !(config.fileExt.match(/^png$/i) == null)
|
||||
};
|
||||
|
||||
var MCMapType = new google.maps.ImageMapType(MCMapOptions);
|
||||
MCMapType.name = "MC Map";
|
||||
MCMapType.alt = "Minecraft Map";
|
||||
MCMapType.projection = new MCMapProjection();
|
||||
MCMapType[view.label] = new google.maps.ImageMapType(MCMapOptions[view.label]);
|
||||
MCMapType[view.label].name = view.label;
|
||||
MCMapType[view.label].alt = "Minecraft " + view.label + " Map";
|
||||
MCMapType[view.label].projection = new MCMapProjection();
|
||||
if (mapTypeIdDefault == null) {
|
||||
mapTypeIdDefault = 'mcmap' + view.label;
|
||||
}
|
||||
mapTypeIds.push('mcmap' + view.label);
|
||||
}
|
||||
|
||||
function CoordMapType() {
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ body { height: 100%; margin: 0px; padding: 0px ; background-color: #000; }
|
||||
|
||||
#signControl > div#top {
|
||||
background-color: #fff;
|
||||
border: 1px solid #000;
|
||||
border: 2px solid #000;
|
||||
text-align: center;
|
||||
width: 70px;
|
||||
font-size: 12px;
|
||||
|
||||
7
world.py
7
world.py
@@ -95,11 +95,12 @@ class WorldRenderer(object):
|
||||
files to update. If it includes a trailing newline, it is stripped, so you
|
||||
can pass in file handles just fine.
|
||||
"""
|
||||
def __init__(self, worlddir, cachedir, chunklist=None, lighting=False, night=False, useBiomeData=False):
|
||||
def __init__(self, worlddir, cachedir, chunklist=None, lighting=False, night=False, spawn=False, useBiomeData=False):
|
||||
self.worlddir = worlddir
|
||||
self.caves = False
|
||||
self.lighting = lighting or night
|
||||
self.night = night
|
||||
self.lighting = lighting or night or spawn
|
||||
self.night = night or spawn
|
||||
self.spawn = spawn
|
||||
self.cachedir = cachedir
|
||||
self.useBiomeData = useBiomeData
|
||||
|
||||
|
||||
Reference in New Issue
Block a user