# 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 . from PIL import Image from . import textures """The contents of this file are imported into the namespace of config files. It also defines the render primitive objects, which are used by the C code. Each render primitive has a corresponding section of C code, so both places must be changed simultaneously if you want to make any changes. """ class RenderPrimitive(object): options = {} name = None def __init__(self, **kwargs): if self.name is None: raise RuntimeError("RenderPrimitive cannot be used directly") self.option_values = {} for key, val in kwargs.items(): if not key in self.options: raise ValueError("primitive `{0}' has no option `{1}'".format(self.name, key)) self.option_values[key] = val # set up defaults for name, (description, default) in self.options.items(): if not name in self.option_values: self.option_values[name] = default class Base(RenderPrimitive): name = "base" options = { "biomes": ("whether or not to use biomes", True), } class NetherOld(RenderPrimitive): name = "netherold" class Nether(RenderPrimitive): name = "nether" class HeightFading(RenderPrimitive): name = "height-fading" options = { # 128 is *WRONG*, it should be 64. but we're grandfathered in for now "sealevel": ("target sea level", 128), } black_color = Image.new("RGB", (24,24), (0,0,0)) white_color = Image.new("RGB", (24,24), (255,255,255)) class Depth(RenderPrimitive): name = "depth" options = { "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 NoFluids(RenderPrimitive): name = "no-fluids" class EdgeLines(RenderPrimitive): name = "edge-lines" options = { "opacity": ("darkness of the edge lines, from 0.0 to 1.0", 0.15), } class Cave(RenderPrimitive): name = "cave" options = { "only_lit": ("only render lit caves", False), } class DepthTinting(RenderPrimitive): name = "depth-tinting" @property def depth_colors(self): depth_colors = getattr(self, "_depth_colors", []) if depth_colors: return depth_colors r = 255 g = 0 b = 0 for z in range(128): depth_colors.append(r) depth_colors.append(g) depth_colors.append(b) if z < 32: g += 7 elif z < 64: r -= 7 elif z < 96: b += 7 else: g -= 7 self._depth_colors = depth_colors return depth_colors class Lighting(RenderPrimitive): name = "lighting" options = { "strength": ("how dark to make the shadows, from 0.0 to 1.0", 1.0), "night": ("whether to use nighttime skylight settings", False), "color": ("whether to use colored light", False), } @property def facemasks(self): facemasks = getattr(self, "_facemasks", None) if facemasks: return facemasks white = Image.new("L", (24,24), 255) top = Image.new("L", (24,24), 0) left = Image.new("L", (24,24), 0) whole = Image.new("L", (24,24), 0) toppart = textures.Textures.transform_image_top(white) leftpart = textures.Textures.transform_image_side(white) # using the real PIL paste here (not alpha_over) because there is # no alpha channel (and it's mode "L") top.paste(toppart, (0,0)) left.paste(leftpart, (0,6)) right = left.transpose(Image.FLIP_LEFT_RIGHT) # Manually touch up 6 pixels that leave a gap, like in # textures._build_block() for x,y in [(13,23), (17,21), (21,19)]: right.putpixel((x,y), 255) for x,y in [(3,4), (7,2), (11,0)]: top.putpixel((x,y), 255) # special fix for chunk boundary stipple for x,y in [(13,11), (17,9), (21,7)]: right.putpixel((x,y), 0) self._facemasks = (top, left, right) return self._facemasks class SmoothLighting(Lighting): name = "smooth-lighting" class ClearBase(RenderPrimitive): name = "clear-base" class Overlay(RenderPrimitive): name = "overlay" options = { 'overlay_color' : ('a tuple of (r, g, b, a) for coloring the overlay', None), } @property def whitecolor(self): whitecolor = getattr(self, "_whitecolor", None) if whitecolor: return whitecolor white = Image.new("RGBA", (24,24), (255, 255, 255, 255)) self._whitecolor = white return white @property def facemask_top(self): facemask_top = getattr(self, "_facemask_top", None) if facemask_top: return facemask_top white = Image.new("L", (24,24), 255) top = Image.new("L", (24,24), 0) toppart = textures.Textures.transform_image_top(white) top.paste(toppart, (0,0)) for x,y in [(3,4), (7,2), (11,0)]: top.putpixel((x,y), 255) self._facemask_top = top return top class SpawnOverlay(Overlay): name = "overlay-spawn" class SlimeOverlay(Overlay): name = "overlay-slime" class StructureOverlay(Overlay): name = "overlay-structure" options = { 'structures': ('a list of ((((relx, rely, relz), blockid), ...), (r, g, b, a)) tuples for coloring minerals', [(((0, 0, 0, 66), (0, -1, 0, 4)), (255, 0, 0, 255)), (((0, 0, 0, 27), (0, -1, 0, 4)), (0, 255, 0, 255)), (((0, 0, 0, 28), (0, -1, 0, 4)), (255, 255, 0, 255)), (((0, 0, 0, 157), (0, -1, 0, 4)), (255, 100, 0, 255)), ]), } class MineralOverlay(Overlay): name = "overlay-mineral" options = { 'minerals' : ('a list of (blockid, (r, g, b)) tuples for coloring minerals', None), } class BiomeOverlay(Overlay): name = "overlay-biomes" options = { 'biomes' : ('a list of (biome, (r, g, b)) tuples for coloring biomes', None), 'alpha' : ('an integer value between 0 (transparent) and 255 (opaque)', None), } class Hide(RenderPrimitive): name = "hide" options = { 'blocks' : ('a list of blockids or (blockid, data) tuples of blocks to hide', []), } # Built-in rendermodes for your convenience! normal = [Base(), EdgeLines()] lighting = [Base(), EdgeLines(), Lighting()] smooth_lighting = [Base(), EdgeLines(), SmoothLighting()] night = [Base(), EdgeLines(), Lighting(night=True)] smooth_night = [Base(), EdgeLines(), SmoothLighting(night=True)] netherold = [Base(), EdgeLines(), NetherOld()] netherold_lighting = [Base(), EdgeLines(), NetherOld(), Lighting()] netherold_smooth_lighting = [Base(), EdgeLines(), NetherOld(), SmoothLighting()] nether = [Base(), EdgeLines(), Nether()] nether_lighting = [Base(), EdgeLines(), Nether(), Lighting()] nether_smooth_lighting = [Base(), EdgeLines(), Nether(), SmoothLighting()] cave = [Base(), EdgeLines(), Cave(), DepthTinting()]